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

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)