42f8bc36168a5b2458dc1c9be91189945cc5350f
[openocd.git] / src / jtag / 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 #include "config.h"
21 #include "log.h"
22 #include "jtag.h"
23
24 /* system includes */
25 #include <sys/io.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 #include <sys/time.h>
30 #include <time.h>
31
32 #if PARPORT_USE_PPDEV == 1
33 #include <linux/parport.h>
34 #include <linux/ppdev.h>
35 #include <fcntl.h>
36 #include <sys/ioctl.h>
37 #include <unistd.h>
38 #endif
39
40 /* configuration */
41 unsigned long amt_jtagaccel_port;
42
43 /* interface variables
44 */
45 static u8 aw_control_rst = 0x00;
46 static u8 aw_control_fsm = 0x10;
47 static u8 aw_control_baudrate = 0x20;
48
49 static int rtck_enabled = 0;
50
51 #if PARPORT_USE_PPDEV == 1
52 static int device_handle;
53 int addr_mode = IEEE1284_MODE_EPP | IEEE1284_ADDR ;
54 int data_mode = IEEE1284_MODE_EPP | IEEE1284_DATA ;
55 #define AMT_AW(val) do { ioctl(device_handle, PPSETMODE, &addr_mode); write(device_handle, &val, 1); } while (0)
56 #define AMT_AR(val) do { ioctl(device_handle, PPSETMODE, &addr_mode); read(device_handle, &val, 1); } while (0)
57 #define AMT_DW(val) do { ioctl(device_handle, PPSETMODE, &data_mode); write(device_handle, &val, 1); } while (0)
58 #define AMT_DR(val) do { ioctl(device_handle, PPSETMODE, &data_mode); read(device_handle, &val, 1); } while (0)
59 #else
60 #define AMT_AW(val) do { outb(val, amt_jtagaccel_port + 3); } while (0)
61 #define AMT_AR(val) do { val = inb(amt_jtagaccel_port + 3); } while (0)
62 #define AMT_DW(val) do { outb(val, amt_jtagaccel_port + 4); } while (0)
63 #define AMT_DR(val) do { val = inb(amt_jtagaccel_port + 4); } while (0)
64 #endif
65
66 int amt_jtagaccel_execute_queue(void);
67 int amt_jtagaccel_register_commands(struct command_context_s *cmd_ctx);
68 int amt_jtagaccel_speed(int speed);
69 int amt_jtagaccel_init(void);
70 int amt_jtagaccel_quit(void);
71
72 int amt_jtagaccel_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
73 int amt_jtagaccel_handle_rtck_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
74
75 /* tap_move[i][j]: tap movement command to go from state i to state j
76 * 0: Test-Logic-Reset
77 * 1: Run-Test/Idle
78 * 2: Shift-DR
79 * 3: Pause-DR
80 * 4: Shift-IR
81 * 5: Pause-IR
82 */
83 u8 amt_jtagaccel_tap_move[6][6][2] =
84 {
85 /* TLR RTI SD PD SI PI */
86 {{0x1f, 0x00}, {0x0f, 0x00}, {0x8a, 0x04}, {0x0a, 0x00}, {0x06, 0x00}, {0x96, 0x00}}, /* TLR */
87 {{0x1f, 0x00}, {0x00, 0x00}, {0x85, 0x08}, {0x05, 0x00}, {0x8b, 0x08}, {0x0b, 0x00}}, /* RTI */
88 {{0x1f, 0x00}, {0x0d, 0x00}, {0x00, 0x00}, {0x01, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* SD */
89 {{0x1f, 0x00}, {0x0c, 0x00}, {0x08, 0x00}, {0x00, 0x00}, {0x8f, 0x09}, {0x8f, 0x01}}, /* PD */
90 {{0x1f, 0x00}, {0x0d, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x00, 0x00}, {0x01, 0x00}}, /* SI */
91 {{0x1f, 0x00}, {0x0c, 0x00}, {0x07, 0x00}, {0x97, 0x00}, {0x08, 0x00}, {0x00, 0x00}}, /* PI */
92 };
93
94 jtag_interface_t amt_jtagaccel_interface =
95 {
96 .name = "amt_jtagaccel",
97
98 .execute_queue = amt_jtagaccel_execute_queue,
99
100 .support_statemove = 0,
101
102 .speed = amt_jtagaccel_speed,
103 .register_commands = amt_jtagaccel_register_commands,
104 .init = amt_jtagaccel_init,
105 .quit = amt_jtagaccel_quit,
106 };
107
108 int amt_jtagaccel_register_commands(struct command_context_s *cmd_ctx)
109 {
110 register_command(cmd_ctx, NULL, "parport_port", amt_jtagaccel_handle_parport_port_command,
111 COMMAND_CONFIG, NULL);
112 register_command(cmd_ctx, NULL, "rtck", amt_jtagaccel_handle_rtck_command,
113 COMMAND_CONFIG, NULL);
114
115 return ERROR_OK;
116 }
117
118 void amt_jtagaccel_reset(int trst, int srst)
119 {
120 if (trst == 1)
121 aw_control_rst |= 0x4;
122 else if (trst == 0)
123 aw_control_rst &= ~0x4;
124
125 if (srst == 1)
126 aw_control_rst |= 0x1;
127 else if (srst == 0)
128 aw_control_rst &= ~0x1;
129
130 AMT_AW(aw_control_rst);
131 }
132
133 int amt_jtagaccel_speed(int speed)
134 {
135 aw_control_baudrate &= 0xf0;
136 aw_control_baudrate |= speed & 0x0f;
137 AMT_AW(aw_control_baudrate);
138
139 return ERROR_OK;
140 }
141
142 void amt_jtagaccel_end_state(state)
143 {
144 if (tap_move_map[state] != -1)
145 end_state = state;
146 else
147 {
148 ERROR("BUG: %i is not a valid end state", state);
149 exit(-1);
150 }
151 }
152
153 void amt_wait_scan_busy()
154 {
155 int timeout = 4096;
156 u8 ar_status;
157
158 AMT_AR(ar_status);
159 while (((ar_status) & 0x80) && (timeout-- > 0))
160 AMT_AR(ar_status);
161
162 if (ar_status & 0x80)
163 {
164 ERROR("amt_jtagaccel timed out while waiting for end of scan, rtck was %s", (rtck_enabled) ? "enabled" : "disabled");
165 exit(-1);
166 }
167 }
168
169 void amt_jtagaccel_state_move(void)
170 {
171 u8 aw_scan_tms_5;
172 u8 tms_scan[2];
173
174 tms_scan[0] = amt_jtagaccel_tap_move[tap_move_map[cur_state]][tap_move_map[end_state]][0];
175 tms_scan[1] = amt_jtagaccel_tap_move[tap_move_map[cur_state]][tap_move_map[end_state]][1];
176
177 aw_scan_tms_5 = 0x40 | (tms_scan[0] & 0x1f);
178 AMT_AW(aw_scan_tms_5);
179 if (jtag_speed > 3 || rtck_enabled)
180 amt_wait_scan_busy();
181
182 if (tms_scan[0] & 0x80)
183 {
184 aw_scan_tms_5 = 0x40 | (tms_scan[1] & 0x1f);
185 AMT_AW(aw_scan_tms_5);
186 if (jtag_speed > 3 || rtck_enabled)
187 amt_wait_scan_busy();
188 }
189
190 cur_state = end_state;
191 }
192
193 void amt_jtagaccel_runtest(int num_cycles)
194 {
195 int i = 0;
196 u8 aw_scan_tms_5;
197 u8 aw_scan_tms_1to4;
198
199 enum tap_state saved_end_state = end_state;
200
201 /* only do a state_move when we're not already in RTI */
202 if (cur_state != TAP_RTI)
203 {
204 amt_jtagaccel_end_state(TAP_RTI);
205 amt_jtagaccel_state_move();
206 }
207
208 while (num_cycles - i >= 5)
209 {
210 aw_scan_tms_5 = 0x40;
211 AMT_AW(aw_scan_tms_5);
212 i += 5;
213 }
214
215 if (num_cycles - i > 0)
216 {
217 aw_scan_tms_1to4 = 0x80 | ((num_cycles - i - 1) & 0x3) << 4;
218 AMT_AW(aw_scan_tms_1to4);
219 }
220
221 amt_jtagaccel_end_state(saved_end_state);
222 if (cur_state != end_state)
223 amt_jtagaccel_state_move();
224 }
225
226 void amt_jtagaccel_scan(int ir_scan, enum scan_type type, u8 *buffer, int scan_size)
227 {
228 int bits_left = scan_size;
229 int bit_count = 0;
230 enum tap_state saved_end_state = end_state;
231 u8 aw_tdi_option;
232 u8 dw_tdi_scan;
233 u8 dr_tdo;
234 u8 aw_tms_scan;
235 u8 tms_scan[2];
236
237 if (ir_scan)
238 amt_jtagaccel_end_state(TAP_SI);
239 else
240 amt_jtagaccel_end_state(TAP_SD);
241
242 amt_jtagaccel_state_move();
243 amt_jtagaccel_end_state(saved_end_state);
244
245 /* handle unaligned bits at the beginning */
246 if ((scan_size - 1) % 8)
247 {
248 aw_tdi_option = 0x30 | (((scan_size - 1) % 8) - 1);
249 AMT_AW(aw_tdi_option);
250
251 dw_tdi_scan = buf_get_u32(buffer, bit_count, (scan_size - 1) % 8) & 0xff;
252 AMT_DW(dw_tdi_scan);
253 if (jtag_speed > 3 || rtck_enabled)
254 amt_wait_scan_busy();
255
256 if ((type == SCAN_IN) || (type == SCAN_IO))
257 {
258 AMT_DR(dr_tdo);
259 dr_tdo = dr_tdo >> (8 - ((scan_size - 1) % 8));
260 buf_set_u32(buffer, bit_count, (scan_size - 1) % 8, dr_tdo);
261 }
262
263 bit_count += (scan_size - 1) % 8;
264 bits_left -= (scan_size - 1) % 8;
265 }
266
267 while (bits_left - 1 >= 8)
268 {
269 dw_tdi_scan = buf_get_u32(buffer, bit_count, 8) & 0xff;
270 AMT_DW(dw_tdi_scan);
271 if (jtag_speed > 3 || rtck_enabled)
272 amt_wait_scan_busy();
273
274 if ((type == SCAN_IN) || (type == SCAN_IO))
275 {
276 AMT_DR(dr_tdo);
277 buf_set_u32(buffer, bit_count, 8, dr_tdo);
278 }
279
280 bit_count += 8;
281 bits_left -= 8;
282 }
283
284 tms_scan[0] = amt_jtagaccel_tap_move[tap_move_map[cur_state]][tap_move_map[end_state]][0];
285 tms_scan[1] = amt_jtagaccel_tap_move[tap_move_map[cur_state]][tap_move_map[end_state]][1];
286 aw_tms_scan = 0x40 | (tms_scan[0] & 0x1f) | (buf_get_u32(buffer, bit_count, 1) << 5);
287 AMT_AW(aw_tms_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 dr_tdo = dr_tdo >> 7;
295 buf_set_u32(buffer, bit_count, 1, dr_tdo);
296 }
297
298 if (tms_scan[0] & 0x80)
299 {
300 aw_tms_scan = 0x40 | (tms_scan[1] & 0x1f);
301 AMT_AW(aw_tms_scan);
302 if (jtag_speed > 3 || rtck_enabled)
303 amt_wait_scan_busy();
304 }
305 cur_state = end_state;
306 }
307
308 int amt_jtagaccel_execute_queue(void)
309 {
310 jtag_command_t *cmd = jtag_command_queue; /* currently processed command */
311 int scan_size;
312 enum scan_type type;
313 u8 *buffer;
314
315 while (cmd)
316 {
317 switch (cmd->type)
318 {
319 case JTAG_END_STATE:
320 #ifdef _DEBUG_JTAG_IO_
321 DEBUG("end_state: %i", cmd->cmd.end_state->end_state);
322 #endif
323 if (cmd->cmd.end_state->end_state != -1)
324 amt_jtagaccel_end_state(cmd->cmd.end_state->end_state);
325 break;
326 case JTAG_RESET:
327 #ifdef _DEBUG_JTAG_IO_
328 DEBUG("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
329 #endif
330 if (cmd->cmd.reset->trst == 1)
331 {
332 cur_state = TAP_TLR;
333 }
334 amt_jtagaccel_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
335 break;
336 case JTAG_RUNTEST:
337 #ifdef _DEBUG_JTAG_IO_
338 DEBUG("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
339 #endif
340 if (cmd->cmd.runtest->end_state != -1)
341 amt_jtagaccel_end_state(cmd->cmd.runtest->end_state);
342 amt_jtagaccel_runtest(cmd->cmd.runtest->num_cycles);
343 break;
344 case JTAG_STATEMOVE:
345 #ifdef _DEBUG_JTAG_IO_
346 DEBUG("statemove end in %i", cmd->cmd.statemove->end_state);
347 #endif
348 if (cmd->cmd.statemove->end_state != -1)
349 amt_jtagaccel_end_state(cmd->cmd.statemove->end_state);
350 amt_jtagaccel_state_move();
351 break;
352 case JTAG_SCAN:
353 #ifdef _DEBUG_JTAG_IO_
354 DEBUG("scan end in %i", cmd->cmd.scan->end_state);
355 #endif
356 if (cmd->cmd.scan->end_state != -1)
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 return ERROR_JTAG_QUEUE_FAILED;
363 if (buffer)
364 free(buffer);
365 break;
366 case JTAG_SLEEP:
367 #ifdef _DEBUG_JTAG_IO_
368 DEBUG("sleep", cmd->cmd.sleep->us);
369 #endif
370 jtag_sleep(cmd->cmd.sleep->us);
371 break;
372 default:
373 ERROR("BUG: unknown JTAG command type encountered");
374 exit(-1);
375 }
376 cmd = cmd->next;
377 }
378
379 return ERROR_OK;
380 }
381
382 int amt_jtagaccel_init(void)
383 {
384 #if PARPORT_USE_PPDEV == 1
385 char buffer[256];
386 int i = 0;
387 u8 control_port;
388 #else
389 u8 status_port;
390 #endif
391
392 #if PARPORT_USE_PPDEV == 1
393 if (device_handle > 0)
394 {
395 ERROR("device is already opened");
396 return ERROR_JTAG_INIT_FAILED;
397 }
398
399 snprintf(buffer, 256, "/dev/parport%d", amt_jtagaccel_port);
400 device_handle = open(buffer, O_RDWR);
401
402 if (device_handle < 0)
403 {
404 ERROR("cannot open device. check it exists and that user read and write rights are set");
405 return ERROR_JTAG_INIT_FAILED;
406 }
407
408 i = ioctl(device_handle, PPCLAIM);
409 if (i < 0)
410 {
411 ERROR("cannot claim device");
412 return ERROR_JTAG_INIT_FAILED;
413 }
414
415 i = IEEE1284_MODE_EPP;
416 i = ioctl(device_handle, PPSETMODE, & i);
417 if (i < 0)
418 {
419 ERROR(" cannot set compatible mode to device");
420 return ERROR_JTAG_INIT_FAILED;
421 }
422
423 control_port = 0x00;
424 i = ioctl(device_handle, PPWCONTROL, &control_port);
425
426 control_port = 0x04;
427 i = ioctl(device_handle, PPWCONTROL, &control_port);
428
429 #else
430 if (amt_jtagaccel_port == 0)
431 {
432 amt_jtagaccel_port = 0x378;
433 WARNING("No parport port specified, using default '0x378' (LPT1)");
434 }
435
436 if (ioperm(amt_jtagaccel_port, 5, 1) != 0) {
437 ERROR("missing privileges for direct i/o");
438 return ERROR_JTAG_INIT_FAILED;
439 }
440
441 /* prepare epp port */
442 /* clear timeout */
443 status_port = inb(amt_jtagaccel_port + 1);
444 outb(status_port | 0x1, amt_jtagaccel_port + 1);
445
446 /* reset epp port */
447 outb(0x00, amt_jtagaccel_port + 2);
448 outb(0x04, amt_jtagaccel_port + 2);
449 #endif
450
451 /* enable JTAG port */
452 aw_control_fsm |= 0x04;
453 AMT_AW(aw_control_fsm);
454
455 amt_jtagaccel_speed(jtag_speed);
456
457 if (jtag_reset_config & RESET_TRST_OPEN_DRAIN)
458 aw_control_rst &= ~0x8;
459 else
460 aw_control_rst |= 0x8;
461
462 if (jtag_reset_config & RESET_SRST_PUSH_PULL)
463 aw_control_rst &= ~0x2;
464 else
465 aw_control_rst |= 0x2;
466
467 amt_jtagaccel_reset(0, 0);
468
469 return ERROR_OK;
470 }
471
472 int amt_jtagaccel_quit(void)
473 {
474
475 return ERROR_OK;
476 }
477
478 int amt_jtagaccel_handle_parport_port_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
479 {
480 if (argc == 0)
481 return ERROR_OK;
482
483 /* only if the port wasn't overwritten by cmdline */
484 if (amt_jtagaccel_port == 0)
485 amt_jtagaccel_port = strtoul(args[0], NULL, 0);
486
487 return ERROR_OK;
488 }
489
490 int amt_jtagaccel_handle_rtck_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
491 {
492 if (argc == 0)
493 {
494 command_print(cmd_ctx, "amt_jtagaccel RTCK feature %s", (rtck_enabled) ? "enabled" : "disabled");
495 return ERROR_OK;
496 }
497 else
498 {
499 if (strcmp(args[0], "enabled") == 0)
500 {
501 rtck_enabled = 1;
502
503 /* set RTCK enable bit */
504 aw_control_fsm |= 0x02;
505 AMT_AW(aw_control_fsm);
506 }
507 }
508
509 return ERROR_OK;
510 }

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)