1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2005 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
6 ***************************************************************************/
12 #include <jtag/adapter.h>
13 #include <jtag/interface.h>
15 #if PARPORT_USE_PPDEV == 1
16 #include <linux/parport.h>
17 #include <linux/ppdev.h>
18 #include <sys/ioctl.h>
19 #else /* not PARPORT_USE_PPDEV */
25 #if PARPORT_USE_GIVEIO == 1
33 * Support the Amontec Chameleon POD with JTAG Accelerator support.
34 * This is a parallel port JTAG adapter with a CPLD between the
35 * parallel port and the JTAG connection. VHDL code running in the
36 * CPLD significantly accelerates JTAG operations compared to the
37 * bitbanging "Wiggler" style of most parallel port adapters.
41 static uint16_t amt_jtagaccel_port
;
43 /* interface variables
45 static uint8_t aw_control_rst
;
46 static uint8_t aw_control_fsm
= 0x10;
47 static uint8_t aw_control_baudrate
= 0x20;
49 static int rtck_enabled
;
51 #if PARPORT_USE_PPDEV == 1
52 static int device_handle
;
54 static const int addr_mode
= IEEE1284_MODE_EPP
| IEEE1284_ADDR
;
56 /* FIXME do something sane when these ioctl/read/write calls fail. */
62 __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
63 assert(__retval >= 0); \
64 __retval = write(device_handle, &val, 1); \
65 assert(__retval >= 0); \
71 __retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
72 assert(__retval >= 0); \
73 __retval = read(device_handle, &val, 1); \
74 assert(__retval >= 0); \
77 static const int data_mode
= IEEE1284_MODE_EPP
| IEEE1284_DATA
;
83 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
84 assert(__retval >= 0); \
85 __retval = write(device_handle, &val, 1); \
86 assert(__retval >= 0); \
92 __retval = ioctl(device_handle, PPSETMODE, &data_mode); \
93 assert(__retval >= 0); \
94 __retval = read(device_handle, &val, 1); \
95 assert(__retval >= 0); \
100 #define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0)
101 #define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0)
102 #define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0)
103 #define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0)
105 #endif /* PARPORT_USE_PPDEV */
107 /* tap_move[i][j]: tap movement command to go from state i to state j
108 * 0: Test-Logic-Reset
115 static const uint8_t amt_jtagaccel_tap_move
[6][6][2] = {
116 /* RESET IDLE DRSHIFT DRPAUSE IRSHIFT IRPAUSE */
117 { {0x1f, 0x00}, {0x0f, 0x00}, {0x05, 0x00}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00} }, /* RESET */
118 { {0x1f, 0x00}, {0x00, 0x00}, {0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x0b, 0x00} }, /* IDLE */
119 { {0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01} }, /* DRSHIFT */
120 { {0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01} }, /* DRPAUSE */
121 { {0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00} }, /* IRSHIFT */
122 { {0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00} }, /* IRPAUSE */
125 static void amt_jtagaccel_reset(int trst
, int srst
)
128 aw_control_rst
|= 0x4;
130 aw_control_rst
&= ~0x4;
133 aw_control_rst
|= 0x1;
135 aw_control_rst
&= ~0x1;
137 AMT_AW(aw_control_rst
);
140 static int amt_jtagaccel_speed(int speed
)
142 aw_control_baudrate
&= 0xf0;
143 aw_control_baudrate
|= speed
& 0x0f;
144 AMT_AW(aw_control_baudrate
);
149 static void amt_jtagaccel_end_state(tap_state_t state
)
151 if (tap_is_state_stable(state
))
152 tap_set_end_state(state
);
154 LOG_ERROR("BUG: %i is not a valid end state", state
);
159 static void amt_wait_scan_busy(void)
165 while (((ar_status
) & 0x80) && (timeout
-- > 0))
168 if (ar_status
& 0x80) {
170 "amt_jtagaccel timed out while waiting for end of scan, rtck was %s, last AR_STATUS: 0x%2.2x",
171 (rtck_enabled
) ? "enabled" : "disabled",
177 static void amt_jtagaccel_state_move(void)
179 uint8_t aw_scan_tms_5
;
182 tap_state_t cur_state
= tap_get_state();
183 tap_state_t end_state
= tap_get_end_state();
185 tms_scan
[0] = amt_jtagaccel_tap_move
[tap_move_ndx(cur_state
)][tap_move_ndx(end_state
)][0];
186 tms_scan
[1] = amt_jtagaccel_tap_move
[tap_move_ndx(cur_state
)][tap_move_ndx(end_state
)][1];
188 aw_scan_tms_5
= 0x40 | (tms_scan
[0] & 0x1f);
189 AMT_AW(aw_scan_tms_5
);
191 int retval
= adapter_get_speed(&jtag_speed
);
192 assert(retval
== ERROR_OK
);
193 if (jtag_speed
> 3 || rtck_enabled
)
194 amt_wait_scan_busy();
196 if (tms_scan
[0] & 0x80) {
197 aw_scan_tms_5
= 0x40 | (tms_scan
[1] & 0x1f);
198 AMT_AW(aw_scan_tms_5
);
199 if (jtag_speed
> 3 || rtck_enabled
)
200 amt_wait_scan_busy();
203 tap_set_state(end_state
);
206 static void amt_jtagaccel_runtest(int num_cycles
)
209 uint8_t aw_scan_tms_5
;
210 uint8_t aw_scan_tms_1to4
;
212 tap_state_t saved_end_state
= tap_get_end_state();
214 /* only do a state_move when we're not already in IDLE */
215 if (tap_get_state() != TAP_IDLE
) {
216 amt_jtagaccel_end_state(TAP_IDLE
);
217 amt_jtagaccel_state_move();
220 while (num_cycles
- i
>= 5) {
221 aw_scan_tms_5
= 0x40;
222 AMT_AW(aw_scan_tms_5
);
226 if (num_cycles
- i
> 0) {
227 aw_scan_tms_1to4
= 0x80 | ((num_cycles
- i
- 1) & 0x3) << 4;
228 AMT_AW(aw_scan_tms_1to4
);
231 amt_jtagaccel_end_state(saved_end_state
);
232 if (tap_get_state() != tap_get_end_state())
233 amt_jtagaccel_state_move();
236 static void amt_jtagaccel_scan(bool ir_scan
, enum scan_type type
, uint8_t *buffer
, int scan_size
)
238 int bits_left
= scan_size
;
240 tap_state_t saved_end_state
= tap_get_end_state();
241 uint8_t aw_tdi_option
;
247 int retval
= adapter_get_speed(&jtag_speed_var
);
248 assert(retval
== ERROR_OK
);
251 amt_jtagaccel_end_state(TAP_IRSHIFT
);
253 amt_jtagaccel_end_state(TAP_DRSHIFT
);
255 /* Only move if we're not already there */
256 if (tap_get_state() != tap_get_end_state())
257 amt_jtagaccel_state_move();
259 amt_jtagaccel_end_state(saved_end_state
);
261 /* handle unaligned bits at the beginning */
262 if ((scan_size
- 1) % 8) {
263 aw_tdi_option
= 0x30 | (((scan_size
- 1) % 8) - 1);
264 AMT_AW(aw_tdi_option
);
266 dw_tdi_scan
= buf_get_u32(buffer
, bit_count
, (scan_size
- 1) % 8) & 0xff;
268 if (jtag_speed_var
> 3 || rtck_enabled
)
269 amt_wait_scan_busy();
271 if ((type
== SCAN_IN
) || (type
== SCAN_IO
)) {
273 dr_tdo
= dr_tdo
>> (8 - ((scan_size
- 1) % 8));
274 buf_set_u32(buffer
, bit_count
, (scan_size
- 1) % 8, dr_tdo
);
277 bit_count
+= (scan_size
- 1) % 8;
278 bits_left
-= (scan_size
- 1) % 8;
281 while (bits_left
- 1 >= 8) {
282 dw_tdi_scan
= buf_get_u32(buffer
, bit_count
, 8) & 0xff;
284 if (jtag_speed_var
> 3 || rtck_enabled
)
285 amt_wait_scan_busy();
287 if ((type
== SCAN_IN
) || (type
== SCAN_IO
)) {
289 buf_set_u32(buffer
, bit_count
, 8, dr_tdo
);
297 amt_jtagaccel_tap_move
[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][0];
299 amt_jtagaccel_tap_move
[tap_move_ndx(tap_get_state())][tap_move_ndx(tap_get_end_state())][1];
300 aw_tms_scan
= 0x40 | (tms_scan
[0] & 0x1f) | (buf_get_u32(buffer
, bit_count
, 1) << 5);
302 if (jtag_speed_var
> 3 || rtck_enabled
)
303 amt_wait_scan_busy();
305 if ((type
== SCAN_IN
) || (type
== SCAN_IO
)) {
307 dr_tdo
= dr_tdo
>> 7;
308 buf_set_u32(buffer
, bit_count
, 1, dr_tdo
);
311 if (tms_scan
[0] & 0x80) {
312 aw_tms_scan
= 0x40 | (tms_scan
[1] & 0x1f);
314 if (jtag_speed_var
> 3 || rtck_enabled
)
315 amt_wait_scan_busy();
317 tap_set_state(tap_get_end_state());
320 static int amt_jtagaccel_execute_queue(void)
322 struct jtag_command
*cmd
= jtag_command_queue
; /* currently processed command */
328 /* return ERROR_OK, unless a jtag_read_buffer returns a failed check
329 * that wasn't handled by a caller-provided error handler
336 LOG_DEBUG_IO("reset trst: %i srst %i",
337 cmd
->cmd
.reset
->trst
,
338 cmd
->cmd
.reset
->srst
);
339 if (cmd
->cmd
.reset
->trst
== 1)
340 tap_set_state(TAP_RESET
);
341 amt_jtagaccel_reset(cmd
->cmd
.reset
->trst
, cmd
->cmd
.reset
->srst
);
344 LOG_DEBUG_IO("runtest %i cycles, end in %i",
345 cmd
->cmd
.runtest
->num_cycles
,
346 cmd
->cmd
.runtest
->end_state
);
347 amt_jtagaccel_end_state(cmd
->cmd
.runtest
->end_state
);
348 amt_jtagaccel_runtest(cmd
->cmd
.runtest
->num_cycles
);
351 LOG_DEBUG_IO("statemove end in %i", cmd
->cmd
.statemove
->end_state
);
352 amt_jtagaccel_end_state(cmd
->cmd
.statemove
->end_state
);
353 amt_jtagaccel_state_move();
356 LOG_DEBUG_IO("scan end in %i", cmd
->cmd
.scan
->end_state
);
357 amt_jtagaccel_end_state(cmd
->cmd
.scan
->end_state
);
358 scan_size
= jtag_build_buffer(cmd
->cmd
.scan
, &buffer
);
359 type
= jtag_scan_type(cmd
->cmd
.scan
);
360 amt_jtagaccel_scan(cmd
->cmd
.scan
->ir_scan
, type
, buffer
, scan_size
);
361 if (jtag_read_buffer(buffer
, cmd
->cmd
.scan
) != ERROR_OK
)
362 retval
= ERROR_JTAG_QUEUE_FAILED
;
366 LOG_DEBUG_IO("sleep %" PRIu32
, cmd
->cmd
.sleep
->us
);
367 jtag_sleep(cmd
->cmd
.sleep
->us
);
370 LOG_ERROR("BUG: unknown JTAG command type encountered");
379 #if PARPORT_USE_GIVEIO == 1
380 int amt_jtagaccel_get_giveio_access(void)
383 OSVERSIONINFO version
;
385 version
.dwOSVersionInfoSize
= sizeof(version
);
386 if (!GetVersionEx(&version
)) {
390 if (version
.dwPlatformId
!= VER_PLATFORM_WIN32_NT
)
393 h
= CreateFile("\\\\.\\giveio",
398 FILE_ATTRIBUTE_NORMAL
,
400 if (h
== INVALID_HANDLE_VALUE
) {
411 static int amt_jtagaccel_init(void)
413 #if PARPORT_USE_PPDEV == 1
416 uint8_t control_port
;
422 #if PARPORT_USE_PPDEV == 1
423 if (device_handle
> 0) {
424 LOG_ERROR("device is already opened");
425 return ERROR_JTAG_INIT_FAILED
;
428 snprintf(buffer
, 256, "/dev/parport%d", amt_jtagaccel_port
);
429 device_handle
= open(buffer
, O_RDWR
);
431 if (device_handle
< 0) {
433 "cannot open device. check it exists and that user read and write rights are set");
434 return ERROR_JTAG_INIT_FAILED
;
437 i
= ioctl(device_handle
, PPCLAIM
);
439 LOG_ERROR("cannot claim device");
440 return ERROR_JTAG_INIT_FAILED
;
443 i
= IEEE1284_MODE_EPP
;
444 i
= ioctl(device_handle
, PPSETMODE
, &i
);
446 LOG_ERROR(" cannot set compatible mode to device");
447 return ERROR_JTAG_INIT_FAILED
;
451 i
= ioctl(device_handle
, PPWCONTROL
, &control_port
);
454 i
= ioctl(device_handle
, PPWCONTROL
, &control_port
);
457 if (amt_jtagaccel_port
== 0) {
458 amt_jtagaccel_port
= 0x378;
459 LOG_WARNING("No parport port specified, using default '0x378' (LPT1)");
462 #if PARPORT_USE_GIVEIO == 1
463 if (amt_jtagaccel_get_giveio_access() != 0) {
464 #else /* PARPORT_USE_GIVEIO */
465 if (ioperm(amt_jtagaccel_port
, 5, 1) != 0) {
466 #endif /* PARPORT_USE_GIVEIO */
467 LOG_ERROR("missing privileges for direct i/o");
468 return ERROR_JTAG_INIT_FAILED
;
473 status_port
= inb(amt_jtagaccel_port
+ 1);
474 outb(status_port
| 0x1, amt_jtagaccel_port
+ 1);
477 outb(0x00, amt_jtagaccel_port
+ 2);
478 outb(0x04, amt_jtagaccel_port
+ 2);
482 /* set RTCK enable bit */
483 aw_control_fsm
|= 0x02;
486 /* enable JTAG port */
487 aw_control_fsm
|= 0x04;
488 AMT_AW(aw_control_fsm
);
490 enum reset_types jtag_reset_config
= jtag_get_reset_config();
491 if (jtag_reset_config
& RESET_TRST_OPEN_DRAIN
)
492 aw_control_rst
&= ~0x8;
494 aw_control_rst
|= 0x8;
496 if (jtag_reset_config
& RESET_SRST_PUSH_PULL
)
497 aw_control_rst
&= ~0x2;
499 aw_control_rst
|= 0x2;
501 amt_jtagaccel_reset(0, 0);
503 /* read status register */
505 LOG_DEBUG("AR_STATUS: 0x%2.2x", ar_status
);
510 static int amt_jtagaccel_quit(void)
516 COMMAND_HANDLER(amt_jtagaccel_handle_parport_port_command
)
519 /* only if the port wasn't overwritten by cmdline */
520 if (amt_jtagaccel_port
== 0) {
522 COMMAND_PARSE_NUMBER(u16
, CMD_ARGV
[0], port
);
523 amt_jtagaccel_port
= port
;
525 LOG_ERROR("The parport port was already configured!");
530 command_print(CMD
, "parport port = %u", amt_jtagaccel_port
);
535 COMMAND_HANDLER(amt_jtagaccel_handle_rtck_command
)
539 "amt_jtagaccel RTCK feature %s",
540 (rtck_enabled
) ? "enabled" : "disabled");
543 if (strcmp(CMD_ARGV
[0], "enabled") == 0)
552 static const struct command_registration amtjtagaccel_command_handlers
[] = {
554 .name
= "parport_port",
555 .handler
= &amt_jtagaccel_handle_parport_port_command
,
556 .mode
= COMMAND_CONFIG
,
557 .help
= "configure or display the parallel port to use",
558 .usage
= "[port_num]",
562 * @todo Remove this "rtck" command; just use the standard
563 * mechanism to enable/disable adaptive clocking. First
564 * implement the standard mechanism and deprecate "rtck";
565 * after a year or so, it'll be safe to remove this.
568 .handler
= &amt_jtagaccel_handle_rtck_command
,
569 .mode
= COMMAND_CONFIG
,
570 .help
= "configure or display RTCK support",
571 .usage
= "[enable|disable]",
573 COMMAND_REGISTRATION_DONE
576 static struct jtag_interface amt_jtagaccel_interface
= {
577 .execute_queue
= amt_jtagaccel_execute_queue
,
580 struct adapter_driver amt_jtagaccel_adapter_driver
= {
581 .name
= "amt_jtagaccel",
582 .transports
= jtag_only
,
583 .commands
= amtjtagaccel_command_handlers
,
585 .init
= amt_jtagaccel_init
,
586 .quit
= amt_jtagaccel_quit
,
587 .speed
= amt_jtagaccel_speed
,
589 .jtag_ops
= &amt_jtagaccel_interface
,
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)