JTAG/Drivers: Amontec JTAG accelerator fixes
[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 jtag_speed = jtag_get_speed();
195 if (jtag_speed > 3 || rtck_enabled)
196 amt_wait_scan_busy();
197
198 if (tms_scan[0] & 0x80)
199 {
200 aw_scan_tms_5 = 0x40 | (tms_scan[1] & 0x1f);
201 AMT_AW(aw_scan_tms_5);
202 if (jtag_speed > 3 || rtck_enabled)
203 amt_wait_scan_busy();
204 }
205
206 tap_set_state(end_state);
207 }
208
209 static void amt_jtagaccel_runtest(int num_cycles)
210 {
211 int i = 0;
212 uint8_t aw_scan_tms_5;
213 uint8_t aw_scan_tms_1to4;
214
215 tap_state_t saved_end_state = tap_get_end_state();
216
217 /* only do a state_move when we're not already in IDLE */
218 if (tap_get_state() != TAP_IDLE)
219 {
220 amt_jtagaccel_end_state(TAP_IDLE);
221 amt_jtagaccel_state_move();
222 }
223
224 while (num_cycles - i >= 5)
225 {
226 aw_scan_tms_5 = 0x40;
227 AMT_AW(aw_scan_tms_5);
228 i += 5;
229 }
230
231 if (num_cycles - i > 0)
232 {
233 aw_scan_tms_1to4 = 0x80 | ((num_cycles - i - 1) & 0x3) << 4;
234 AMT_AW(aw_scan_tms_1to4);
235 }
236
237 amt_jtagaccel_end_state(saved_end_state);
238 if (tap_get_state() != tap_get_end_state())
239 amt_jtagaccel_state_move();
240 }
241
242 static void amt_jtagaccel_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
243 {
244 int bits_left = scan_size;
245 int bit_count = 0;
246 tap_state_t saved_end_state = tap_get_end_state();
247 uint8_t aw_tdi_option;
248 uint8_t dw_tdi_scan;
249 uint8_t dr_tdo;
250 uint8_t aw_tms_scan;
251 uint8_t tms_scan[2];
252 int jtag_speed = jtag_get_speed();
253
254 if (ir_scan)
255 amt_jtagaccel_end_state(TAP_IRSHIFT);
256 else
257 amt_jtagaccel_end_state(TAP_DRSHIFT);
258
259 amt_jtagaccel_state_move();
260 amt_jtagaccel_end_state(saved_end_state);
261
262 /* handle unaligned bits at the beginning */
263 if ((scan_size - 1) % 8)
264 {
265 aw_tdi_option = 0x30 | (((scan_size - 1) % 8) - 1);
266 AMT_AW(aw_tdi_option);
267
268 dw_tdi_scan = buf_get_u32(buffer, bit_count, (scan_size - 1) % 8) & 0xff;
269 AMT_DW(dw_tdi_scan);
270 if (jtag_speed > 3 || rtck_enabled)
271 amt_wait_scan_busy();
272
273 if ((type == SCAN_IN) || (type == SCAN_IO))
274 {
275 AMT_DR(dr_tdo);
276 dr_tdo = dr_tdo >> (8 - ((scan_size - 1) % 8));
277 buf_set_u32(buffer, bit_count, (scan_size - 1) % 8, dr_tdo);
278 }
279
280 bit_count += (scan_size - 1) % 8;
281 bits_left -= (scan_size - 1) % 8;
282 }
283
284 while (bits_left - 1 >= 8)
285 {
286 dw_tdi_scan = buf_get_u32(buffer, bit_count, 8) & 0xff;
287 AMT_DW(dw_tdi_scan);
288 if (jtag_speed > 3 || rtck_enabled)
289 amt_wait_scan_busy();
290
291 if ((type == SCAN_IN) || (type == SCAN_IO))
292 {
293 AMT_DR(dr_tdo);
294 buf_set_u32(buffer, bit_count, 8, dr_tdo);
295 }
296
297 bit_count += 8;
298 bits_left -= 8;
299 }
300
301 tms_scan[0] = amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0];
302 tms_scan[1] = amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][1];
303 aw_tms_scan = 0x40 | (tms_scan[0] & 0x1f) | (buf_get_u32(buffer, bit_count, 1) << 5);
304 AMT_AW(aw_tms_scan);
305 if (jtag_speed > 3 || rtck_enabled)
306 amt_wait_scan_busy();
307
308 if ((type == SCAN_IN) || (type == SCAN_IO))
309 {
310 AMT_DR(dr_tdo);
311 dr_tdo = dr_tdo >> 7;
312 buf_set_u32(buffer, bit_count, 1, dr_tdo);
313 }
314
315 if (tms_scan[0] & 0x80)
316 {
317 aw_tms_scan = 0x40 | (tms_scan[1] & 0x1f);
318 AMT_AW(aw_tms_scan);
319 if (jtag_speed > 3 || rtck_enabled)
320 amt_wait_scan_busy();
321 }
322 tap_set_state(tap_get_end_state());
323 }
324
325 static int amt_jtagaccel_execute_queue(void)
326 {
327 struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
328 int scan_size;
329 enum scan_type type;
330 uint8_t *buffer;
331 int retval;
332
333 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
334 * that wasn't handled by a caller-provided error handler
335 */
336 retval = ERROR_OK;
337
338 while (cmd)
339 {
340 switch (cmd->type)
341 {
342 case JTAG_RESET:
343 #ifdef _DEBUG_JTAG_IO_
344 LOG_DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
345 #endif
346 if (cmd->cmd.reset->trst == 1)
347 {
348 tap_set_state(TAP_RESET);
349 }
350 amt_jtagaccel_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
351 break;
352 case JTAG_RUNTEST:
353 #ifdef _DEBUG_JTAG_IO_
354 LOG_DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
355 #endif
356 amt_jtagaccel_end_state(cmd->cmd.runtest->end_state);
357 amt_jtagaccel_runtest(cmd->cmd.runtest->num_cycles);
358 break;
359 case JTAG_STATEMOVE:
360 #ifdef _DEBUG_JTAG_IO_
361 LOG_DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
362 #endif
363 amt_jtagaccel_end_state(cmd->cmd.statemove->end_state);
364 amt_jtagaccel_state_move();
365 break;
366 case JTAG_SCAN:
367 #ifdef _DEBUG_JTAG_IO_
368 LOG_DEBUG("scan end in %i", cmd->cmd.scan->end_state);
369 #endif
370 amt_jtagaccel_end_state(cmd->cmd.scan->end_state);
371 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
372 type = jtag_scan_type(cmd->cmd.scan);
373 amt_jtagaccel_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
374 if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
375 retval = ERROR_JTAG_QUEUE_FAILED;
376 if (buffer)
377 free(buffer);
378 break;
379 case JTAG_SLEEP:
380 #ifdef _DEBUG_JTAG_IO_
381 LOG_DEBUG("sleep %" PRIi32, cmd->cmd.sleep->us);
382 #endif
383 jtag_sleep(cmd->cmd.sleep->us);
384 break;
385 default:
386 LOG_ERROR("BUG: unknown JTAG command type encountered");
387 exit(-1);
388 }
389 cmd = cmd->next;
390 }
391
392 return retval;
393 }
394
395 #if PARPORT_USE_GIVEIO == 1
396 int amt_jtagaccel_get_giveio_access(void)
397 {
398 HANDLE h;
399 OSVERSIONINFO version;
400
401 version.dwOSVersionInfoSize = sizeof version;
402 if (!GetVersionEx(&version)) {
403 errno = EINVAL;
404 return -1;
405 }
406 if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
407 return 0;
408
409 h = CreateFile("\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
410 if (h == INVALID_HANDLE_VALUE) {
411 errno = ENODEV;
412 return -1;
413 }
414
415 CloseHandle(h);
416
417 return 0;
418 }
419 #endif
420
421 static int amt_jtagaccel_init(void)
422 {
423 #if PARPORT_USE_PPDEV == 1
424 char buffer[256];
425 int i = 0;
426 uint8_t control_port;
427 #else
428 uint8_t status_port;
429 #endif
430 uint8_t ar_status;
431
432 #if PARPORT_USE_PPDEV == 1
433 if (device_handle > 0)
434 {
435 LOG_ERROR("device is already opened");
436 return ERROR_JTAG_INIT_FAILED;
437 }
438
439 snprintf(buffer, 256, "/dev/parport%d", amt_jtagaccel_port);
440 device_handle = open(buffer, O_RDWR);
441
442 if (device_handle < 0)
443 {
444 LOG_ERROR("cannot open device. check it exists and that user read and write rights are set");
445 return ERROR_JTAG_INIT_FAILED;
446 }
447
448 i = ioctl(device_handle, PPCLAIM);
449 if (i < 0)
450 {
451 LOG_ERROR("cannot claim device");
452 return ERROR_JTAG_INIT_FAILED;
453 }
454
455 i = IEEE1284_MODE_EPP;
456 i = ioctl(device_handle, PPSETMODE, & i);
457 if (i < 0)
458 {
459 LOG_ERROR(" cannot set compatible mode to device");
460 return ERROR_JTAG_INIT_FAILED;
461 }
462
463 control_port = 0x00;
464 i = ioctl(device_handle, PPWCONTROL, &control_port);
465
466 control_port = 0x04;
467 i = ioctl(device_handle, PPWCONTROL, &control_port);
468
469 #else
470 if (amt_jtagaccel_port == 0)
471 {
472 amt_jtagaccel_port = 0x378;
473 LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
474 }
475
476 #if PARPORT_USE_GIVEIO == 1
477 if (amt_jtagaccel_get_giveio_access() != 0) {
478 #else /* PARPORT_USE_GIVEIO */
479 if (ioperm(amt_jtagaccel_port, 5, 1) != 0) {
480 #endif /* PARPORT_USE_GIVEIO */
481 LOG_ERROR("missing privileges for direct i/o");
482 return ERROR_JTAG_INIT_FAILED;
483 }
484
485 /* prepare epp port */
486 /* clear timeout */
487 status_port = inb(amt_jtagaccel_port + 1);
488 outb(status_port | 0x1, amt_jtagaccel_port + 1);
489
490 /* reset epp port */
491 outb(0x00, amt_jtagaccel_port + 2);
492 outb(0x04, amt_jtagaccel_port + 2);
493 #endif
494
495 if (rtck_enabled)
496 {
497 /* set RTCK enable bit */
498 aw_control_fsm |= 0x02;
499 }
500
501 /* enable JTAG port */
502 aw_control_fsm |= 0x04;
503 AMT_AW(aw_control_fsm);
504
505 amt_jtagaccel_speed(jtag_get_speed());
506
507 enum reset_types jtag_reset_config = jtag_get_reset_config();
508 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
509 aw_control_rst &= ~0x8;
510 else
511 aw_control_rst |= 0x8;
512
513 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
514 aw_control_rst &= ~0x2;
515 else
516 aw_control_rst |= 0x2;
517
518 amt_jtagaccel_reset(0, 0);
519
520 /* read status register */
521 AMT_AR(ar_status);
522 LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status);
523
524 return ERROR_OK;
525 }
526
527 static int amt_jtagaccel_quit(void)
528 {
529
530 return ERROR_OK;
531 }
532
533 COMMAND_HANDLER(amt_jtagaccel_handle_parport_port_command)
534 {
535 if (CMD_ARGC == 1)
536 {
537 /* only if the port wasn't overwritten by cmdline */
538 if (amt_jtagaccel_port == 0)
539 {
540 uint16_t port;
541 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
542 amt_jtagaccel_port = port;
543 }
544 else
545 {
546 LOG_ERROR("The parport port was already configured!");
547 return ERROR_FAIL;
548 }
549 }
550
551 command_print(CMD_CTX, "parport port = %u", amt_jtagaccel_port);
552
553 return ERROR_OK;
554 }
555
556 COMMAND_HANDLER(amt_jtagaccel_handle_rtck_command)
557 {
558 if (CMD_ARGC == 0)
559 {
560 command_print(CMD_CTX, "amt_jtagaccel RTCK feature %s", (rtck_enabled) ? "enabled" : "disabled");
561 return ERROR_OK;
562 }
563 else
564 {
565 if (strcmp(CMD_ARGV[0], "enabled") == 0)
566 {
567 rtck_enabled = 1;
568 }
569 else
570 {
571 rtck_enabled = 0;
572 }
573 }
574
575 return ERROR_OK;
576 }
577
578 static const struct command_registration amtjtagaccel_command_handlers[] = {
579 {
580 .name = "parport_port",
581 .handler = &amt_jtagaccel_handle_parport_port_command,
582 .mode = COMMAND_CONFIG,
583 .help = "configure or display the parallel port to use",
584 .usage = "[port_num]",
585 },
586 {
587 /**
588 * @todo Remove this "rtck" command; just use the standard
589 * mechanism to enable/disable adaptive clocking. First
590 * implement the standard mechanism and deprecate "rtck";
591 * after a year or so, it'll be safe to remove this.
592 */
593 .name = "rtck",
594 .handler = &amt_jtagaccel_handle_rtck_command,
595 .mode = COMMAND_CONFIG,
596 .help = "configure or display RTCK support",
597 .usage = "[enable|disable]",
598 },
599 COMMAND_REGISTRATION_DONE
600 };
601
602 struct jtag_interface amt_jtagaccel_interface = {
603 .name = "amt_jtagaccel",
604 .commands = amtjtagaccel_command_handlers,
605
606 .init = amt_jtagaccel_init,
607 .quit = amt_jtagaccel_quit,
608 .speed = amt_jtagaccel_speed,
609 .execute_queue = amt_jtagaccel_execute_queue,
610 };

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)