jtag: getting the JTAG speed can fail
[openocd.git] / src / jtag / drivers / amt_jtagaccel.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <jtag/interface.h>
25
26 #if PARPORT_USE_PPDEV == 1
27 #include <linux/parport.h>
28 #include <linux/ppdev.h>
29 #include <sys/ioctl.h>
30 #else /* not PARPORT_USE_PPDEV */
31 #ifndef _WIN32
32 #include <sys/io.h>
33 #endif
34 #endif
35
36 #if PARPORT_USE_GIVEIO == 1
37 #if IS_CYGWIN == 1
38 #include <windows.h>
39 #endif
40 #endif
41
42 /**
43 * @file
44 * Support the Amontec Chameleon POD with JTAG Accelerator support.
45 * This is a parallel port JTAG adapter with a CPLD between the
46 * parallel port and the JTAG connection. VHDL code running in the
47 * CPLD significantly accelerates JTAG operations compared to the
48 * bitbanging "Wiggler" style of most parallel port adapters.
49 */
50
51 /* configuration */
52 static uint16_t amt_jtagaccel_port;
53
54 /* interface variables
55 */
56 static uint8_t aw_control_rst = 0x00;
57 static uint8_t aw_control_fsm = 0x10;
58 static uint8_t aw_control_baudrate = 0x20;
59
60 static int rtck_enabled = 0;
61
62 #if PARPORT_USE_PPDEV == 1
63 static int device_handle;
64
65 static const int addr_mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
66
67 /* FIXME do something sane when these ioctl/read/write calls fail. */
68
69 #define AMT_AW(val) \
70 do { \
71 int __retval; \
72 \
73 __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
74 __retval = write(device_handle, &val, 1); \
75 } while (0)
76 #define AMT_AR(val) \
77 do { \
78 int __retval; \
79 \
80 __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
81 __retval = read(device_handle, &val, 1); \
82 } while (0)
83
84 static const int data_mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
85
86 #define AMT_DW(val) \
87 do { \
88 int __retval; \
89 \
90 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
91 __retval = write(device_handle, &val, 1); \
92 } while (0)
93 #define AMT_DR(val) \
94 do { \
95 int __retval; \
96 \
97 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
98 __retval = read(device_handle, &val, 1); \
99 } while (0)
100
101 #else
102
103 #define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0)
104 #define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0)
105 #define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0)
106 #define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0)
107
108 #endif // PARPORT_USE_PPDEV
109
110 /* tap_move[i][j]: tap movement command to go from state i to state j
111 * 0: Test-Logic-Reset
112 * 1: Run-Test/Idle
113 * 2: Shift-DR
114 * 3: Pause-DR
115 * 4: Shift-IR
116 * 5: Pause-IR
117 */
118 static uint8_t amt_jtagaccel_tap_move[6][6][2] =
119 {
120 /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */
121 {{0x1f, 0x00}, {0x0f, 0x00}, {0x05, 0x00}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00}}, /* RESET */
122 {{0x1f, 0x00}, {0x00, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x0b, 0x00}}, /* IDLE */
123 {{0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* DRSHIFT */
124 {{0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* DRPAUSE */
125 {{0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00}}, /* IRSHIFT */
126 {{0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00}}, /* IRPAUSE */
127 };
128
129
130 static void amt_jtagaccel_reset(int trst, int srst)
131 {
132 if (trst == 1)
133 aw_control_rst |= 0x4;
134 else if (trst == 0)
135 aw_control_rst &= ~0x4;
136
137 if (srst == 1)
138 aw_control_rst |= 0x1;
139 else if (srst == 0)
140 aw_control_rst &= ~0x1;
141
142 AMT_AW(aw_control_rst);
143 }
144
145 static int amt_jtagaccel_speed(int speed)
146 {
147 aw_control_baudrate &= 0xf0;
148 aw_control_baudrate |= speed & 0x0f;
149 AMT_AW(aw_control_baudrate);
150
151 return ERROR_OK;
152 }
153
154 static void amt_jtagaccel_end_state(tap_state_t state)
155 {
156 if (tap_is_state_stable(state))
157 tap_set_end_state(state);
158 else
159 {
160 LOG_ERROR("BUG: %i is not a valid end state", state);
161 exit(-1);
162 }
163 }
164
165 static void amt_wait_scan_busy(void)
166 {
167 int timeout = 4096;
168 uint8_t ar_status;
169
170 AMT_AR(ar_status);
171 while (((ar_status) & 0x80) && (timeout-- > 0))
172 AMT_AR(ar_status);
173
174 if (ar_status & 0x80)
175 {
176 LOG_ERROR("amt_jtagaccel timed out while waiting for end of scan, rtck was %s, last AR_STATUS: 0x%2.2x", (rtck_enabled) ? "enabled" : "disabled", ar_status);
177 exit(-1);
178 }
179 }
180
181 static void amt_jtagaccel_state_move(void)
182 {
183 uint8_t aw_scan_tms_5;
184 uint8_t tms_scan[2];
185
186 tap_state_t cur_state = tap_get_state();
187 tap_state_t end_state = tap_get_end_state();
188
189 tms_scan[0] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][0];
190 tms_scan[1] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][1];
191
192 aw_scan_tms_5 = 0x40 | (tms_scan[0] & 0x1f);
193 AMT_AW(aw_scan_tms_5);
194 int retval = jtag_get_speed(&jtag_speed);
195 assert(retval == ERROR_OK);
196 if (jtag_speed > 3 || rtck_enabled)
197 amt_wait_scan_busy();
198
199 if (tms_scan[0] & 0x80)
200 {
201 aw_scan_tms_5 = 0x40 | (tms_scan[1] & 0x1f);
202 AMT_AW(aw_scan_tms_5);
203 if (jtag_speed > 3 || rtck_enabled)
204 amt_wait_scan_busy();
205 }
206
207 tap_set_state(end_state);
208 }
209
210 static void amt_jtagaccel_runtest(int num_cycles)
211 {
212 int i = 0;
213 uint8_t aw_scan_tms_5;
214 uint8_t aw_scan_tms_1to4;
215
216 tap_state_t saved_end_state = tap_get_end_state();
217
218 /* only do a state_move when we're not already in IDLE */
219 if (tap_get_state() != TAP_IDLE)
220 {
221 amt_jtagaccel_end_state(TAP_IDLE);
222 amt_jtagaccel_state_move();
223 }
224
225 while (num_cycles - i >= 5)
226 {
227 aw_scan_tms_5 = 0x40;
228 AMT_AW(aw_scan_tms_5);
229 i += 5;
230 }
231
232 if (num_cycles - i > 0)
233 {
234 aw_scan_tms_1to4 = 0x80 | ((num_cycles - i - 1) & 0x3) << 4;
235 AMT_AW(aw_scan_tms_1to4);
236 }
237
238 amt_jtagaccel_end_state(saved_end_state);
239 if (tap_get_state() != tap_get_end_state())
240 amt_jtagaccel_state_move();
241 }
242
243 static void amt_jtagaccel_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
244 {
245 int bits_left = scan_size;
246 int bit_count = 0;
247 tap_state_t saved_end_state = tap_get_end_state();
248 uint8_t aw_tdi_option;
249 uint8_t dw_tdi_scan;
250 uint8_t dr_tdo;
251 uint8_t aw_tms_scan;
252 uint8_t tms_scan[2];
253 int jtag_speed_var;
254 int retval = jtag_get_speed(&jtag_speed_var);
255 assert(retval == ERROR_OK);
256
257 if (ir_scan)
258 amt_jtagaccel_end_state(TAP_IRSHIFT);
259 else
260 amt_jtagaccel_end_state(TAP_DRSHIFT);
261
262 amt_jtagaccel_state_move();
263 amt_jtagaccel_end_state(saved_end_state);
264
265 /* handle unaligned bits at the beginning */
266 if ((scan_size - 1) % 8)
267 {
268 aw_tdi_option = 0x30 | (((scan_size - 1) % 8) - 1);
269 AMT_AW(aw_tdi_option);
270
271 dw_tdi_scan = buf_get_u32(buffer, bit_count, (scan_size - 1) % 8) & 0xff;
272 AMT_DW(dw_tdi_scan);
273 if (jtag_speed_var > 3 || rtck_enabled)
274 amt_wait_scan_busy();
275
276 if ((type == SCAN_IN) || (type == SCAN_IO))
277 {
278 AMT_DR(dr_tdo);
279 dr_tdo = dr_tdo >> (8 - ((scan_size - 1) % 8));
280 buf_set_u32(buffer, bit_count, (scan_size - 1) % 8, dr_tdo);
281 }
282
283 bit_count += (scan_size - 1) % 8;
284 bits_left -= (scan_size - 1) % 8;
285 }
286
287 while (bits_left - 1 >= 8)
288 {
289 dw_tdi_scan = buf_get_u32(buffer, bit_count, 8) & 0xff;
290 AMT_DW(dw_tdi_scan);
291 if (jtag_speed_var > 3 || rtck_enabled)
292 amt_wait_scan_busy();
293
294 if ((type == SCAN_IN) || (type == SCAN_IO))
295 {
296 AMT_DR(dr_tdo);
297 buf_set_u32(buffer, bit_count, 8, dr_tdo);
298 }
299
300 bit_count += 8;
301 bits_left -= 8;
302 }
303
304 tms_scan[0] = amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0];
305 tms_scan[1] = amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][1];
306 aw_tms_scan = 0x40 | (tms_scan[0] & 0x1f) | (buf_get_u32(buffer, bit_count, 1) << 5);
307 AMT_AW(aw_tms_scan);
308 if (jtag_speed_var > 3 || rtck_enabled)
309 amt_wait_scan_busy();
310
311 if ((type == SCAN_IN) || (type == SCAN_IO))
312 {
313 AMT_DR(dr_tdo);
314 dr_tdo = dr_tdo >> 7;
315 buf_set_u32(buffer, bit_count, 1, dr_tdo);
316 }
317
318 if (tms_scan[0] & 0x80)
319 {
320 aw_tms_scan = 0x40 | (tms_scan[1] & 0x1f);
321 AMT_AW(aw_tms_scan);
322 if (jtag_speed_var > 3 || rtck_enabled)
323 amt_wait_scan_busy();
324 }
325 tap_set_state(tap_get_end_state());
326 }
327
328 static int amt_jtagaccel_execute_queue(void)
329 {
330 struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
331 int scan_size;
332 enum scan_type type;
333 uint8_t *buffer;
334 int retval;
335
336 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
337 * that wasn't handled by a caller-provided error handler
338 */
339 retval = ERROR_OK;
340
341 while (cmd)
342 {
343 switch (cmd->type)
344 {
345 case JTAG_RESET:
346 #ifdef _DEBUG_JTAG_IO_
347 LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
348 #endif
349 if (cmd->cmd.reset->trst == 1)
350 {
351 tap_set_state(TAP_RESET);
352 }
353 amt_jtagaccel_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
354 break;
355 case JTAG_RUNTEST:
356 #ifdef _DEBUG_JTAG_IO_
357 LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
358 #endif
359 amt_jtagaccel_end_state(cmd->cmd.runtest->end_state);
360 amt_jtagaccel_runtest(cmd->cmd.runtest->num_cycles);
361 break;
362 case JTAG_TLR_RESET:
363 #ifdef _DEBUG_JTAG_IO_
364 LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
365 #endif
366 amt_jtagaccel_end_state(cmd->cmd.statemove->end_state);
367 amt_jtagaccel_state_move();
368 break;
369 case JTAG_SCAN:
370 #ifdef _DEBUG_JTAG_IO_
371 LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state);
372 #endif
373 amt_jtagaccel_end_state(cmd->cmd.scan->end_state);
374 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
375 type = jtag_scan_type(cmd->cmd.scan);
376 amt_jtagaccel_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
377 if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
378 retval = ERROR_JTAG_QUEUE_FAILED;
379 if (buffer)
380 free(buffer);
381 break;
382 case JTAG_SLEEP:
383 #ifdef _DEBUG_JTAG_IO_
384 LOG_DEBUG("sleep %" PRIi32, cmd->cmd.sleep->us);
385 #endif
386 jtag_sleep(cmd->cmd.sleep->us);
387 break;
388 default:
389 LOG_ERROR("BUG: unknown JTAG command type encountered");
390 exit(-1);
391 }
392 cmd = cmd->next;
393 }
394
395 return retval;
396 }
397
398 #if PARPORT_USE_GIVEIO == 1
399 int amt_jtagaccel_get_giveio_access(void)
400 {
401 HANDLE h;
402 OSVERSIONINFO version;
403
404 version.dwOSVersionInfoSize = sizeof version;
405 if (!GetVersionEx(&version)) {
406 errno = EINVAL;
407 return -1;
408 }
409 if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
410 return 0;
411
412 h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
413 if (h == INVALID_HANDLE_VALUE) {
414 errno = ENODEV;
415 return -1;
416 }
417
418 CloseHandle(h);
419
420 return 0;
421 }
422 #endif
423
424 static int amt_jtagaccel_init(void)
425 {
426 #if PARPORT_USE_PPDEV == 1
427 char buffer[256];
428 int i = 0;
429 uint8_t control_port;
430 #else
431 uint8_t status_port;
432 #endif
433 uint8_t ar_status;
434
435 #if PARPORT_USE_PPDEV == 1
436 if (device_handle > 0)
437 {
438 LOG_ERROR("device is already opened");
439 return ERROR_JTAG_INIT_FAILED;
440 }
441
442 snprintf(buffer, 256, "/dev/parport%d", amt_jtagaccel_port);
443 device_handle = open(buffer, O_RDWR);
444
445 if (device_handle < 0)
446 {
447 LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
448 return ERROR_JTAG_INIT_FAILED;
449 }
450
451 i = ioctl(device_handle, PPCLAIM);
452 if (i < 0)
453 {
454 LOG_ERROR("cannot claim device");
455 return ERROR_JTAG_INIT_FAILED;
456 }
457
458 i = IEEE1284_MODE_EPP;
459 i = ioctl(device_handle, PPSETMODE, & i);
460 if (i < 0)
461 {
462 LOG_ERROR(" cannot set compatible mode to device");
463 return ERROR_JTAG_INIT_FAILED;
464 }
465
466 control_port = 0x00;
467 i = ioctl(device_handle, PPWCONTROL, &control_port);
468
469 control_port = 0x04;
470 i = ioctl(device_handle, PPWCONTROL, &control_port);
471
472 #else
473 if (amt_jtagaccel_port == 0)
474 {
475 amt_jtagaccel_port = 0x378;
476 LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
477 }
478
479 #if PARPORT_USE_GIVEIO == 1
480 if (amt_jtagaccel_get_giveio_access() != 0) {
481 #else /* PARPORT_USE_GIVEIO */
482 if (ioperm(amt_jtagaccel_port, 5, 1) != 0) {
483 #endif /* PARPORT_USE_GIVEIO */
484 LOG_ERROR("missing privileges for direct i/o");
485 return ERROR_JTAG_INIT_FAILED;
486 }
487
488 /* prepare epp port */
489 /* clear timeout */
490 status_port = inb(amt_jtagaccel_port + 1);
491 outb(status_port | 0x1, amt_jtagaccel_port + 1);
492
493 /* reset epp port */
494 outb(0x00, amt_jtagaccel_port + 2);
495 outb(0x04, amt_jtagaccel_port + 2);
496 #endif
497
498 if (rtck_enabled)
499 {
500 /* set RTCK enable bit */
501 aw_control_fsm |= 0x02;
502 }
503
504 /* enable JTAG port */
505 aw_control_fsm |= 0x04;
506 AMT_AW(aw_control_fsm);
507
508 int jtag_speed_var;
509 int retval = jtag_get_speed(&jtag_speed_var);
510 amt_jtagaccel_speed(jtag_speed_var);
511
512 enum reset_types jtag_reset_config = jtag_get_reset_config();
513 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
514 aw_control_rst &= ~0x8;
515 else
516 aw_control_rst |= 0x8;
517
518 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
519 aw_control_rst &= ~0x2;
520 else
521 aw_control_rst |= 0x2;
522
523 amt_jtagaccel_reset(0, 0);
524
525 /* read status register */
526 AMT_AR(ar_status);
527 LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status);
528
529 return ERROR_OK;
530 }
531
532 static int amt_jtagaccel_quit(void)
533 {
534
535 return ERROR_OK;
536 }
537
538 COMMAND_HANDLER(amt_jtagaccel_handle_parport_port_command)
539 {
540 if (CMD_ARGC == 1)
541 {
542 /* only if the port wasn't overwritten by cmdline */
543 if (amt_jtagaccel_port == 0)
544 {
545 uint16_t port;
546 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
547 amt_jtagaccel_port = port;
548 }
549 else
550 {
551 LOG_ERROR("The parport port was already configured!");
552 return ERROR_FAIL;
553 }
554 }
555
556 command_print(CMD_CTX, "parport port = %u", amt_jtagaccel_port);
557
558 return ERROR_OK;
559 }
560
561 COMMAND_HANDLER(amt_jtagaccel_handle_rtck_command)
562 {
563 if (CMD_ARGC == 0)
564 {
565 command_print(CMD_CTX, "amt_jtagaccel RTCK feature %s", (rtck_enabled) ? "enabled" : "disabled");
566 return ERROR_OK;
567 }
568 else
569 {
570 if (strcmp(CMD_ARGV[0], "enabled") == 0)
571 {
572 rtck_enabled = 1;
573 }
574 else
575 {
576 rtck_enabled = 0;
577 }
578 }
579
580 return ERROR_OK;
581 }
582
583 static const struct command_registration amtjtagaccel_command_handlers[] = {
584 {
585 .name = "parport_port",
586 .handler = &amt_jtagaccel_handle_parport_port_command,
587 .mode = COMMAND_CONFIG,
588 .help = "configure or display the parallel port to use",
589 .usage = "[port_num]",
590 },
591 {
592 /**
593 * @todo Remove this "rtck" command; just use the standard
594 * mechanism to enable/disable adaptive clocking. First
595 * implement the standard mechanism and deprecate "rtck";
596 * after a year or so, it'll be safe to remove this.
597 */
598 .name = "rtck",
599 .handler = &amt_jtagaccel_handle_rtck_command,
600 .mode = COMMAND_CONFIG,
601 .help = "configure or display RTCK support",
602 .usage = "[enable|disable]",
603 },
604 COMMAND_REGISTRATION_DONE
605 };
606
607 struct jtag_interface amt_jtagaccel_interface = {
608 .name = "amt_jtagaccel",
609 .commands = amtjtagaccel_command_handlers,
610
611 .init = amt_jtagaccel_init,
612 .quit = amt_jtagaccel_quit,
613 .speed = amt_jtagaccel_speed,
614 .execute_queue = amt_jtagaccel_execute_queue,
615 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)