jtag: linuxgpiod: drop extra parenthesis
[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, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <jtag/adapter.h>
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;
57 static uint8_t aw_control_fsm = 0x10;
58 static uint8_t aw_control_baudrate = 0x20;
59
60 static int rtck_enabled;
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 assert(__retval >= 0); \
75 __retval = write(device_handle, &val, 1); \
76 assert(__retval >= 0); \
77 } while (0)
78 #define AMT_AR(val) \
79 do { \
80 int __retval; \
81 \
82 __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
83 assert(__retval >= 0); \
84 __retval = read(device_handle, &val, 1); \
85 assert(__retval >= 0); \
86 } while (0)
87
88 static const int data_mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
89
90 #define AMT_DW(val) \
91 do { \
92 int __retval; \
93 \
94 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
95 assert(__retval >= 0); \
96 __retval = write(device_handle, &val, 1); \
97 assert(__retval >= 0); \
98 } while (0)
99 #define AMT_DR(val) \
100 do { \
101 int __retval; \
102 \
103 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
104 assert(__retval >= 0); \
105 __retval = read(device_handle, &val, 1); \
106 assert(__retval >= 0); \
107 } while (0)
108
109 #else
110
111 #define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0)
112 #define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0)
113 #define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0)
114 #define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0)
115
116 #endif /* PARPORT_USE_PPDEV */
117
118 /* tap_move[i][j]: tap movement command to go from state i to state j
119 * 0: Test-Logic-Reset
120 * 1: Run-Test/Idle
121 * 2: Shift-DR
122 * 3: Pause-DR
123 * 4: Shift-IR
124 * 5: Pause-IR
125 */
126 static const uint8_t amt_jtagaccel_tap_move[6][6][2] = {
127 /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */
128 { {0x1f, 0x00}, {0x0f, 0x00}, {0x05, 0x00}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00} }, /* RESET */
129 { {0x1f, 0x00}, {0x00, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x0b, 0x00} }, /* IDLE */
130 { {0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01} }, /* DRSHIFT */
131 { {0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01} }, /* DRPAUSE */
132 { {0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00} }, /* IRSHIFT */
133 { {0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00} }, /* IRPAUSE */
134 };
135
136 static void amt_jtagaccel_reset(int trst, int srst)
137 {
138 if (trst == 1)
139 aw_control_rst |= 0x4;
140 else if (trst == 0)
141 aw_control_rst &= ~0x4;
142
143 if (srst == 1)
144 aw_control_rst |= 0x1;
145 else if (srst == 0)
146 aw_control_rst &= ~0x1;
147
148 AMT_AW(aw_control_rst);
149 }
150
151 static int amt_jtagaccel_speed(int speed)
152 {
153 aw_control_baudrate &= 0xf0;
154 aw_control_baudrate |= speed & 0x0f;
155 AMT_AW(aw_control_baudrate);
156
157 return ERROR_OK;
158 }
159
160 static void amt_jtagaccel_end_state(tap_state_t state)
161 {
162 if (tap_is_state_stable(state))
163 tap_set_end_state(state);
164 else {
165 LOG_ERROR("BUG: %i is not a valid end state", state);
166 exit(-1);
167 }
168 }
169
170 static void amt_wait_scan_busy(void)
171 {
172 int timeout = 4096;
173 uint8_t ar_status;
174
175 AMT_AR(ar_status);
176 while (((ar_status) & 0x80) && (timeout-- > 0))
177 AMT_AR(ar_status);
178
179 if (ar_status & 0x80) {
180 LOG_ERROR(
181 "amt_jtagaccel timed out while waiting for end of scan, rtck was %s, last AR_STATUS: 0x%2.2x",
182 (rtck_enabled) ? "enabled" : "disabled",
183 ar_status);
184 exit(-1);
185 }
186 }
187
188 static void amt_jtagaccel_state_move(void)
189 {
190 uint8_t aw_scan_tms_5;
191 uint8_t tms_scan[2];
192
193 tap_state_t cur_state = tap_get_state();
194 tap_state_t end_state = tap_get_end_state();
195
196 tms_scan[0] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][0];
197 tms_scan[1] = amt_jtagaccel_tap_move[tap_move_ndx(cur_state)][tap_move_ndx(end_state)][1];
198
199 aw_scan_tms_5 = 0x40 | (tms_scan[0] & 0x1f);
200 AMT_AW(aw_scan_tms_5);
201 int jtag_speed = 0;
202 int retval = adapter_get_speed(&jtag_speed);
203 assert(retval == ERROR_OK);
204 if (jtag_speed > 3 || rtck_enabled)
205 amt_wait_scan_busy();
206
207 if (tms_scan[0] & 0x80) {
208 aw_scan_tms_5 = 0x40 | (tms_scan[1] & 0x1f);
209 AMT_AW(aw_scan_tms_5);
210 if (jtag_speed > 3 || rtck_enabled)
211 amt_wait_scan_busy();
212 }
213
214 tap_set_state(end_state);
215 }
216
217 static void amt_jtagaccel_runtest(int num_cycles)
218 {
219 int i = 0;
220 uint8_t aw_scan_tms_5;
221 uint8_t aw_scan_tms_1to4;
222
223 tap_state_t saved_end_state = tap_get_end_state();
224
225 /* only do a state_move when we're not already in IDLE */
226 if (tap_get_state() != TAP_IDLE) {
227 amt_jtagaccel_end_state(TAP_IDLE);
228 amt_jtagaccel_state_move();
229 }
230
231 while (num_cycles - i >= 5) {
232 aw_scan_tms_5 = 0x40;
233 AMT_AW(aw_scan_tms_5);
234 i += 5;
235 }
236
237 if (num_cycles - i > 0) {
238 aw_scan_tms_1to4 = 0x80 | ((num_cycles - i - 1) & 0x3) << 4;
239 AMT_AW(aw_scan_tms_1to4);
240 }
241
242 amt_jtagaccel_end_state(saved_end_state);
243 if (tap_get_state() != tap_get_end_state())
244 amt_jtagaccel_state_move();
245 }
246
247 static void amt_jtagaccel_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size)
248 {
249 int bits_left = scan_size;
250 int bit_count = 0;
251 tap_state_t saved_end_state = tap_get_end_state();
252 uint8_t aw_tdi_option;
253 uint8_t dw_tdi_scan;
254 uint8_t dr_tdo;
255 uint8_t aw_tms_scan;
256 uint8_t tms_scan[2];
257 int jtag_speed_var;
258 int retval = adapter_get_speed(&jtag_speed_var);
259 assert(retval == ERROR_OK);
260
261 if (ir_scan)
262 amt_jtagaccel_end_state(TAP_IRSHIFT);
263 else
264 amt_jtagaccel_end_state(TAP_DRSHIFT);
265
266 /* Only move if we're not already there */
267 if (tap_get_state() != tap_get_end_state())
268 amt_jtagaccel_state_move();
269
270 amt_jtagaccel_end_state(saved_end_state);
271
272 /* handle unaligned bits at the beginning */
273 if ((scan_size - 1) % 8) {
274 aw_tdi_option = 0x30 | (((scan_size - 1) % 8) - 1);
275 AMT_AW(aw_tdi_option);
276
277 dw_tdi_scan = buf_get_u32(buffer, bit_count, (scan_size - 1) % 8) & 0xff;
278 AMT_DW(dw_tdi_scan);
279 if (jtag_speed_var > 3 || rtck_enabled)
280 amt_wait_scan_busy();
281
282 if ((type == SCAN_IN) || (type == SCAN_IO)) {
283 AMT_DR(dr_tdo);
284 dr_tdo = dr_tdo >> (8 - ((scan_size - 1) % 8));
285 buf_set_u32(buffer, bit_count, (scan_size - 1) % 8, dr_tdo);
286 }
287
288 bit_count += (scan_size - 1) % 8;
289 bits_left -= (scan_size - 1) % 8;
290 }
291
292 while (bits_left - 1 >= 8) {
293 dw_tdi_scan = buf_get_u32(buffer, bit_count, 8) & 0xff;
294 AMT_DW(dw_tdi_scan);
295 if (jtag_speed_var > 3 || rtck_enabled)
296 amt_wait_scan_busy();
297
298 if ((type == SCAN_IN) || (type == SCAN_IO)) {
299 AMT_DR(dr_tdo);
300 buf_set_u32(buffer, bit_count, 8, dr_tdo);
301 }
302
303 bit_count += 8;
304 bits_left -= 8;
305 }
306
307 tms_scan[0] =
308 amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0];
309 tms_scan[1] =
310 amt_jtagaccel_tap_move[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][1];
311 aw_tms_scan = 0x40 | (tms_scan[0] & 0x1f) | (buf_get_u32(buffer, bit_count, 1) << 5);
312 AMT_AW(aw_tms_scan);
313 if (jtag_speed_var > 3 || rtck_enabled)
314 amt_wait_scan_busy();
315
316 if ((type == SCAN_IN) || (type == SCAN_IO)) {
317 AMT_DR(dr_tdo);
318 dr_tdo = dr_tdo >> 7;
319 buf_set_u32(buffer, bit_count, 1, dr_tdo);
320 }
321
322 if (tms_scan[0] & 0x80) {
323 aw_tms_scan = 0x40 | (tms_scan[1] & 0x1f);
324 AMT_AW(aw_tms_scan);
325 if (jtag_speed_var > 3 || rtck_enabled)
326 amt_wait_scan_busy();
327 }
328 tap_set_state(tap_get_end_state());
329 }
330
331 static int amt_jtagaccel_execute_queue(void)
332 {
333 struct jtag_command *cmd = jtag_command_queue; /* currently processed command */
334 int scan_size;
335 enum scan_type type;
336 uint8_t *buffer;
337 int retval;
338
339 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
340 * that wasn't handled by a caller-provided error handler
341 */
342 retval = ERROR_OK;
343
344 while (cmd) {
345 switch (cmd->type) {
346 case JTAG_RESET:
347 LOG_DEBUG_IO("reset trst: %i srst %i",
348 cmd->cmd.reset->trst,
349 cmd->cmd.reset->srst);
350 if (cmd->cmd.reset->trst == 1)
351 tap_set_state(TAP_RESET);
352 amt_jtagaccel_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
353 break;
354 case JTAG_RUNTEST:
355 LOG_DEBUG_IO("runtest %i cycles, end in %i",
356 cmd->cmd.runtest->num_cycles,
357 cmd->cmd.runtest->end_state);
358 amt_jtagaccel_end_state(cmd->cmd.runtest->end_state);
359 amt_jtagaccel_runtest(cmd->cmd.runtest->num_cycles);
360 break;
361 case JTAG_TLR_RESET:
362 LOG_DEBUG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
363 amt_jtagaccel_end_state(cmd->cmd.statemove->end_state);
364 amt_jtagaccel_state_move();
365 break;
366 case JTAG_SCAN:
367 LOG_DEBUG_IO("scan end in %i", cmd->cmd.scan->end_state);
368 amt_jtagaccel_end_state(cmd->cmd.scan->end_state);
369 scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer);
370 type = jtag_scan_type(cmd->cmd.scan);
371 amt_jtagaccel_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size);
372 if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK)
373 retval = ERROR_JTAG_QUEUE_FAILED;
374 free(buffer);
375 break;
376 case JTAG_SLEEP:
377 LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
378 jtag_sleep(cmd->cmd.sleep->us);
379 break;
380 default:
381 LOG_ERROR("BUG: unknown JTAG command type encountered");
382 exit(-1);
383 }
384 cmd = cmd->next;
385 }
386
387 return retval;
388 }
389
390 #if PARPORT_USE_GIVEIO == 1
391 int amt_jtagaccel_get_giveio_access(void)
392 {
393 HANDLE h;
394 OSVERSIONINFO version;
395
396 version.dwOSVersionInfoSize = sizeof(version);
397 if (!GetVersionEx(&version)) {
398 errno = EINVAL;
399 return -1;
400 }
401 if (version.dwPlatformId != VER_PLATFORM_WIN32_NT)
402 return 0;
403
404 h = CreateFile("\\\\.\\giveio",
405 GENERIC_READ,
406 0,
407 NULL,
408 OPEN_EXISTING,
409 FILE_ATTRIBUTE_NORMAL,
410 NULL);
411 if (h == INVALID_HANDLE_VALUE) {
412 errno = ENODEV;
413 return -1;
414 }
415
416 CloseHandle(h);
417
418 return 0;
419 }
420 #endif
421
422 static int amt_jtagaccel_init(void)
423 {
424 #if PARPORT_USE_PPDEV == 1
425 char buffer[256];
426 int i = 0;
427 uint8_t control_port;
428 #else
429 uint8_t status_port;
430 #endif
431 uint8_t ar_status;
432
433 #if PARPORT_USE_PPDEV == 1
434 if (device_handle > 0) {
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 LOG_ERROR(
444 "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 LOG_ERROR("cannot claim device");
451 return ERROR_JTAG_INIT_FAILED;
452 }
453
454 i = IEEE1284_MODE_EPP;
455 i = ioctl(device_handle, PPSETMODE, &i);
456 if (i < 0) {
457 LOG_ERROR(" cannot set compatible mode to device");
458 return ERROR_JTAG_INIT_FAILED;
459 }
460
461 control_port = 0x00;
462 i = ioctl(device_handle, PPWCONTROL, &control_port);
463
464 control_port = 0x04;
465 i = ioctl(device_handle, PPWCONTROL, &control_port);
466
467 #else
468 if (amt_jtagaccel_port == 0) {
469 amt_jtagaccel_port = 0x378;
470 LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
471 }
472
473 #if PARPORT_USE_GIVEIO == 1
474 if (amt_jtagaccel_get_giveio_access() != 0) {
475 #else /* PARPORT_USE_GIVEIO */
476 if (ioperm(amt_jtagaccel_port, 5, 1) != 0) {
477 #endif /* PARPORT_USE_GIVEIO */
478 LOG_ERROR("missing privileges for direct i/o");
479 return ERROR_JTAG_INIT_FAILED;
480 }
481
482 /* prepare epp port
483 * clear timeout */
484 status_port = inb(amt_jtagaccel_port + 1);
485 outb(status_port | 0x1, amt_jtagaccel_port + 1);
486
487 /* reset epp port */
488 outb(0x00, amt_jtagaccel_port + 2);
489 outb(0x04, amt_jtagaccel_port + 2);
490 #endif
491
492 if (rtck_enabled) {
493 /* set RTCK enable bit */
494 aw_control_fsm |= 0x02;
495 }
496
497 /* enable JTAG port */
498 aw_control_fsm |= 0x04;
499 AMT_AW(aw_control_fsm);
500
501 enum reset_types jtag_reset_config = jtag_get_reset_config();
502 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
503 aw_control_rst &= ~0x8;
504 else
505 aw_control_rst |= 0x8;
506
507 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
508 aw_control_rst &= ~0x2;
509 else
510 aw_control_rst |= 0x2;
511
512 amt_jtagaccel_reset(0, 0);
513
514 /* read status register */
515 AMT_AR(ar_status);
516 LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status);
517
518 return ERROR_OK;
519 }
520
521 static int amt_jtagaccel_quit(void)
522 {
523
524 return ERROR_OK;
525 }
526
527 COMMAND_HANDLER(amt_jtagaccel_handle_parport_port_command)
528 {
529 if (CMD_ARGC == 1) {
530 /* only if the port wasn't overwritten by cmdline */
531 if (amt_jtagaccel_port == 0) {
532 uint16_t port;
533 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], port);
534 amt_jtagaccel_port = port;
535 } else {
536 LOG_ERROR("The parport port was already configured!");
537 return ERROR_FAIL;
538 }
539 }
540
541 command_print(CMD, "parport port = %u", amt_jtagaccel_port);
542
543 return ERROR_OK;
544 }
545
546 COMMAND_HANDLER(amt_jtagaccel_handle_rtck_command)
547 {
548 if (CMD_ARGC == 0) {
549 command_print(CMD,
550 "amt_jtagaccel RTCK feature %s",
551 (rtck_enabled) ? "enabled" : "disabled");
552 return ERROR_OK;
553 } else {
554 if (strcmp(CMD_ARGV[0], "enabled") == 0)
555 rtck_enabled = 1;
556 else
557 rtck_enabled = 0;
558 }
559
560 return ERROR_OK;
561 }
562
563 static const struct command_registration amtjtagaccel_command_handlers[] = {
564 {
565 .name = "parport_port",
566 .handler = &amt_jtagaccel_handle_parport_port_command,
567 .mode = COMMAND_CONFIG,
568 .help = "configure or display the parallel port to use",
569 .usage = "[port_num]",
570 },
571 {
572 /**
573 * @todo Remove this "rtck" command; just use the standard
574 * mechanism to enable/disable adaptive clocking. First
575 * implement the standard mechanism and deprecate "rtck";
576 * after a year or so, it'll be safe to remove this.
577 */
578 .name = "rtck",
579 .handler = &amt_jtagaccel_handle_rtck_command,
580 .mode = COMMAND_CONFIG,
581 .help = "configure or display RTCK support",
582 .usage = "[enable|disable]",
583 },
584 COMMAND_REGISTRATION_DONE
585 };
586
587 static struct jtag_interface amt_jtagaccel_interface = {
588 .execute_queue = amt_jtagaccel_execute_queue,
589 };
590
591 struct adapter_driver amt_jtagaccel_adapter_driver = {
592 .name = "amt_jtagaccel",
593 .transports = jtag_only,
594 .commands = amtjtagaccel_command_handlers,
595
596 .init = amt_jtagaccel_init,
597 .quit = amt_jtagaccel_quit,
598 .speed = amt_jtagaccel_speed,
599
600 .jtag_ops = &amt_jtagaccel_interface,
601 };

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)