ULINK driver: Implement variable TCK frequency in OpenULINK firmware
[openocd.git] / src / jtag / drivers / OpenULINK / src / jtag.c
1 /***************************************************************************
2 * Copyright (C) 2011 by Martin Schmoelzer *
3 * <martin.schmoelzer@student.tuwien.ac.at> *
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
21 #include "jtag.h"
22
23 #include "io.h"
24 #include "msgtypes.h"
25 #include "common.h"
26
27 #include <stdbool.h>
28
29 /** Delay value for SCAN_IN operations with less than maximum TCK frequency */
30 u8 delay_scan_in = 0;
31
32 /** Delay value for SCAN_OUT operations with less than maximum TCK frequency */
33 u8 delay_scan_out = 0;
34
35 /** Delay value for SCAN_IO operations with less than maximum TCK frequency */
36 u8 delay_scan_io = 0;
37
38 /** Delay value for CLOCK_TCK operations with less than maximum frequency */
39 u8 delay_tck = 0;
40
41 /** Delay value for CLOCK_TMS operations with less than maximum frequency */
42 u8 delay_tms = 0;
43
44 /**
45 * Perform JTAG SCAN-IN operation at maximum TCK frequency.
46 *
47 * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
48 * stored in the EP2 IN buffer.
49 *
50 * Maximum achievable TCK frequency is 182 kHz for ULINK clocked at 24 MHz.
51 *
52 * @param out_offset offset in OUT2BUF where payload data starts
53 */
54 void jtag_scan_in(u8 out_offset, u8 in_offset)
55 {
56 u8 scan_size_bytes, bits_last_byte;
57 u8 tms_count_start, tms_count_end;
58 u8 tms_sequence_start, tms_sequence_end;
59 u8 tdo_data, i, j;
60
61 u8 outb_buffer;
62
63 /* Get parameters from OUT2BUF */
64 scan_size_bytes = OUT2BUF[out_offset];
65 bits_last_byte = OUT2BUF[out_offset + 1];
66 tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
67 tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
68 tms_sequence_start = OUT2BUF[out_offset + 3];
69 tms_sequence_end = OUT2BUF[out_offset + 4];
70
71 if (tms_count_start > 0) {
72 jtag_clock_tms(tms_count_start, tms_sequence_start);
73 }
74
75 outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS);
76
77 /* Shift all bytes except the last byte */
78 for (i = 0; i < scan_size_bytes - 1; i++) {
79 tdo_data = 0;
80
81 for (j = 0; j < 8; j++) {
82 OUTB = outb_buffer; /* TCK changes here */
83 tdo_data = tdo_data >> 1;
84 OUTB = (outb_buffer | PIN_TCK);
85
86 if (GET_TDO()) {
87 tdo_data |= 0x80;
88 }
89 }
90
91 /* Copy TDO data to IN2BUF */
92 IN2BUF[i + in_offset] = tdo_data;
93 }
94
95 tdo_data = 0;
96
97 /* Shift the last byte */
98 for (j = 0; j < bits_last_byte; j++) {
99 /* Assert TMS signal if requested and this is the last bit */
100 if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
101 outb_buffer |= PIN_TMS;
102 tms_count_end--;
103 tms_sequence_end = tms_sequence_end >> 1;
104 }
105
106 OUTB = outb_buffer; /* TCK change here */
107 tdo_data = tdo_data >> 1;
108 OUTB = (outb_buffer | PIN_TCK);
109
110 if (GET_TDO()) {
111 tdo_data |= 0x80;
112 }
113 }
114 tdo_data = tdo_data >> (8 - bits_last_byte);
115
116 /* Copy TDO data to IN2BUF */
117 IN2BUF[i + in_offset] = tdo_data;
118
119 /* Move to correct end state */
120 if (tms_count_end > 0) {
121 jtag_clock_tms(tms_count_end, tms_sequence_end);
122 }
123 }
124
125 /**
126 * Perform JTAG SCAN-IN operation at variable TCK frequency.
127 *
128 * Dummy data is shifted into the JTAG chain via TDI, TDO data is sampled and
129 * stored in the EP2 IN buffer.
130 *
131 * Maximum achievable TCK frequency is 113 kHz for ULINK clocked at 24 MHz.
132 *
133 * @param out_offset offset in OUT2BUF where payload data starts
134 */
135 void jtag_slow_scan_in(u8 out_offset, u8 in_offset)
136 {
137 u8 scan_size_bytes, bits_last_byte;
138 u8 tms_count_start, tms_count_end;
139 u8 tms_sequence_start, tms_sequence_end;
140 u8 tdo_data, i, j, k;
141
142 u8 outb_buffer;
143
144 /* Get parameters from OUT2BUF */
145 scan_size_bytes = OUT2BUF[out_offset];
146 bits_last_byte = OUT2BUF[out_offset + 1];
147 tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
148 tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
149 tms_sequence_start = OUT2BUF[out_offset + 3];
150 tms_sequence_end = OUT2BUF[out_offset + 4];
151
152 if (tms_count_start > 0) {
153 jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
154 }
155
156 outb_buffer = OUTB & ~(PIN_TDI | PIN_TCK | PIN_TMS);
157
158 /* Shift all bytes except the last byte */
159 for (i = 0; i < scan_size_bytes - 1; i++) {
160 tdo_data = 0;
161
162 for (j = 0; j < 8; j++) {
163 OUTB = outb_buffer; /* TCK changes here */
164 for (k = 0; k < delay_scan_in; k++);
165 tdo_data = tdo_data >> 1;
166
167 OUTB = (outb_buffer | PIN_TCK);
168 for (k = 0; k < delay_scan_in; k++);
169
170 if (GET_TDO()) {
171 tdo_data |= 0x80;
172 }
173 }
174
175 /* Copy TDO data to IN2BUF */
176 IN2BUF[i + in_offset] = tdo_data;
177 }
178
179 tdo_data = 0;
180
181 /* Shift the last byte */
182 for (j = 0; j < bits_last_byte; j++) {
183 /* Assert TMS signal if requested and this is the last bit */
184 if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
185 outb_buffer |= PIN_TMS;
186 tms_count_end--;
187 tms_sequence_end = tms_sequence_end >> 1;
188 }
189
190 OUTB = outb_buffer; /* TCK change here */
191 for (k = 0; k < delay_scan_in; k++);
192 tdo_data = tdo_data >> 1;
193
194 OUTB = (outb_buffer | PIN_TCK);
195 for (k = 0; k < delay_scan_in; k++);
196
197 if (GET_TDO()) {
198 tdo_data |= 0x80;
199 }
200 }
201 tdo_data = tdo_data >> (8 - bits_last_byte);
202
203 /* Copy TDO data to IN2BUF */
204 IN2BUF[i + in_offset] = tdo_data;
205
206 /* Move to correct end state */
207 if (tms_count_end > 0) {
208 jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
209 }
210 }
211
212 /**
213 * Perform JTAG SCAN-OUT operation at maximum TCK frequency.
214 *
215 * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
216 * data is not sampled.
217 * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
218 *
219 * Maximum achievable TCK frequency is 142 kHz for ULINK clocked at 24 MHz.
220 *
221 * @param out_offset offset in OUT2BUF where payload data starts
222 */
223 void jtag_scan_out(u8 out_offset)
224 {
225 u8 scan_size_bytes, bits_last_byte;
226 u8 tms_count_start, tms_count_end;
227 u8 tms_sequence_start, tms_sequence_end;
228 u8 tdi_data, i, j;
229
230 u8 outb_buffer;
231
232 /* Get parameters from OUT2BUF */
233 scan_size_bytes = OUT2BUF[out_offset];
234 bits_last_byte = OUT2BUF[out_offset + 1];
235 tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
236 tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
237 tms_sequence_start = OUT2BUF[out_offset + 3];
238 tms_sequence_end = OUT2BUF[out_offset + 4];
239
240 if (tms_count_start > 0) {
241 jtag_clock_tms(tms_count_start, tms_sequence_start);
242 }
243
244 outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
245
246 /* Shift all bytes except the last byte */
247 for (i = 0; i < scan_size_bytes - 1; i++) {
248 tdi_data = OUT2BUF[i + out_offset + 5];
249
250 for (j = 0; j < 8; j++) {
251 if (tdi_data & 0x01) {
252 outb_buffer |= PIN_TDI;
253 }
254 else {
255 outb_buffer &= ~PIN_TDI;
256 }
257
258 OUTB = outb_buffer; /* TDI and TCK change here */
259 tdi_data = tdi_data >> 1;
260 OUTB = (outb_buffer | PIN_TCK);
261 }
262 }
263
264 tdi_data = OUT2BUF[i + out_offset + 5];
265
266 /* Shift the last byte */
267 for (j = 0; j < bits_last_byte; j++) {
268 if (tdi_data & 0x01) {
269 outb_buffer |= PIN_TDI;
270 }
271 else {
272 outb_buffer &= ~PIN_TDI;
273 }
274
275 /* Assert TMS signal if requested and this is the last bit */
276 if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
277 outb_buffer |= PIN_TMS;
278 tms_count_end--;
279 tms_sequence_end = tms_sequence_end >> 1;
280 }
281
282 OUTB = outb_buffer; /* TDI and TCK change here */
283 tdi_data = tdi_data >> 1;
284 OUTB = (outb_buffer | PIN_TCK);
285 }
286
287 /* Move to correct end state */
288 if (tms_count_end > 0) {
289 jtag_clock_tms(tms_count_end, tms_sequence_end);
290 }
291 }
292
293 /**
294 * Perform JTAG SCAN-OUT operation at maximum TCK frequency.
295 *
296 * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
297 * data is not sampled.
298 * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
299 *
300 * Maximum achievable TCK frequency is 97 kHz for ULINK clocked at 24 MHz.
301 *
302 * @param out_offset offset in OUT2BUF where payload data starts
303 */
304 void jtag_slow_scan_out(u8 out_offset)
305 {
306 u8 scan_size_bytes, bits_last_byte;
307 u8 tms_count_start, tms_count_end;
308 u8 tms_sequence_start, tms_sequence_end;
309 u8 tdi_data, i, j, k;
310
311 u8 outb_buffer;
312
313 /* Get parameters from OUT2BUF */
314 scan_size_bytes = OUT2BUF[out_offset];
315 bits_last_byte = OUT2BUF[out_offset + 1];
316 tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
317 tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
318 tms_sequence_start = OUT2BUF[out_offset + 3];
319 tms_sequence_end = OUT2BUF[out_offset + 4];
320
321 if (tms_count_start > 0) {
322 jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
323 }
324
325 outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
326
327 /* Shift all bytes except the last byte */
328 for (i = 0; i < scan_size_bytes - 1; i++) {
329 tdi_data = OUT2BUF[i + out_offset + 5];
330
331 for (j = 0; j < 8; j++) {
332 if (tdi_data & 0x01) {
333 outb_buffer |= PIN_TDI;
334 }
335 else {
336 outb_buffer &= ~PIN_TDI;
337 }
338
339 OUTB = outb_buffer; /* TDI and TCK change here */
340 for (k = 0; k < delay_scan_out; k++);
341 tdi_data = tdi_data >> 1;
342
343 OUTB = (outb_buffer | PIN_TCK);
344 for (k = 0; k < delay_scan_out; k++);
345 }
346 }
347
348 tdi_data = OUT2BUF[i + out_offset + 5];
349
350 /* Shift the last byte */
351 for (j = 0; j < bits_last_byte; j++) {
352 if (tdi_data & 0x01) {
353 outb_buffer |= PIN_TDI;
354 }
355 else {
356 outb_buffer &= ~PIN_TDI;
357 }
358
359 /* Assert TMS signal if requested and this is the last bit */
360 if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
361 outb_buffer |= PIN_TMS;
362 tms_count_end--;
363 tms_sequence_end = tms_sequence_end >> 1;
364 }
365
366 OUTB = outb_buffer; /* TDI and TCK change here */
367 for (k = 0; k < delay_scan_out; k++);
368 tdi_data = tdi_data >> 1;
369
370 OUTB = (outb_buffer | PIN_TCK);
371 for (k = 0; k < delay_scan_out; k++);
372 }
373
374 /* Move to correct end state */
375 if (tms_count_end > 0) {
376 jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
377 }
378 }
379
380 /**
381 * Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
382 *
383 * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
384 * data is sampled and stored in the EP2 IN buffer.
385 * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
386 *
387 * Maximum achievable TCK frequency is 100 kHz for ULINK clocked at 24 MHz.
388 *
389 * @param out_offset offset in OUT2BUF where payload data starts
390 */
391 void jtag_scan_io(u8 out_offset, u8 in_offset)
392 {
393 u8 scan_size_bytes, bits_last_byte;
394 u8 tms_count_start, tms_count_end;
395 u8 tms_sequence_start, tms_sequence_end;
396 u8 tdi_data, tdo_data, i, j;
397
398 u8 outb_buffer;
399
400 /* Get parameters from OUT2BUF */
401 scan_size_bytes = OUT2BUF[out_offset];
402 bits_last_byte = OUT2BUF[out_offset + 1];
403 tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
404 tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
405 tms_sequence_start = OUT2BUF[out_offset + 3];
406 tms_sequence_end = OUT2BUF[out_offset + 4];
407
408 if (tms_count_start > 0) {
409 jtag_clock_tms(tms_count_start, tms_sequence_start);
410 }
411
412 outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
413
414 /* Shift all bytes except the last byte */
415 for (i = 0; i < scan_size_bytes - 1; i++) {
416 tdi_data = OUT2BUF[i + out_offset + 5];
417 tdo_data = 0;
418
419 for (j = 0; j < 8; j++) {
420 if (tdi_data & 0x01) {
421 outb_buffer |= PIN_TDI;
422 }
423 else {
424 outb_buffer &= ~PIN_TDI;
425 }
426
427 OUTB = outb_buffer; /* TDI and TCK change here */
428 tdi_data = tdi_data >> 1;
429 OUTB = (outb_buffer | PIN_TCK);
430 tdo_data = tdo_data >> 1;
431
432 if (GET_TDO()) {
433 tdo_data |= 0x80;
434 }
435 }
436
437 /* Copy TDO data to IN2BUF */
438 IN2BUF[i + in_offset] = tdo_data;
439 }
440
441 tdi_data = OUT2BUF[i + out_offset + 5];
442 tdo_data = 0;
443
444 /* Shift the last byte */
445 for (j = 0; j < bits_last_byte; j++) {
446 if (tdi_data & 0x01) {
447 outb_buffer |= PIN_TDI;
448 }
449 else {
450 outb_buffer &= ~PIN_TDI;
451 }
452
453 /* Assert TMS signal if requested and this is the last bit */
454 if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
455 outb_buffer |= PIN_TMS;
456 tms_count_end--;
457 tms_sequence_end = tms_sequence_end >> 1;
458 }
459
460 OUTB = outb_buffer; /* TDI and TCK change here */
461 tdi_data = tdi_data >> 1;
462 OUTB = (outb_buffer | PIN_TCK);
463 tdo_data = tdo_data >> 1;
464
465 if (GET_TDO()) {
466 tdo_data |= 0x80;
467 }
468 }
469 tdo_data = tdo_data >> (8 - bits_last_byte);
470
471 /* Copy TDO data to IN2BUF */
472 IN2BUF[i + in_offset] = tdo_data;
473
474 /* Move to correct end state */
475 if (tms_count_end > 0) {
476 jtag_clock_tms(tms_count_end, tms_sequence_end);
477 }
478 }
479
480 /**
481 * Perform bidirectional JTAG SCAN operation at maximum TCK frequency.
482 *
483 * Data stored in EP2 OUT buffer is shifted into the JTAG chain via TDI, TDO
484 * data is sampled and stored in the EP2 IN buffer.
485 * The TAP-FSM state is alyways left in the PAUSE-DR/PAUSE-IR state.
486 *
487 * Maximum achievable TCK frequency is 78 kHz for ULINK clocked at 24 MHz.
488 *
489 * @param out_offset offset in OUT2BUF where payload data starts
490 */
491 void jtag_slow_scan_io(u8 out_offset, u8 in_offset)
492 {
493 u8 scan_size_bytes, bits_last_byte;
494 u8 tms_count_start, tms_count_end;
495 u8 tms_sequence_start, tms_sequence_end;
496 u8 tdi_data, tdo_data, i, j, k;
497
498 u8 outb_buffer;
499
500 /* Get parameters from OUT2BUF */
501 scan_size_bytes = OUT2BUF[out_offset];
502 bits_last_byte = OUT2BUF[out_offset + 1];
503 tms_count_start = (OUT2BUF[out_offset + 2] >> 4) & 0x0F;
504 tms_count_end = OUT2BUF[out_offset + 2] & 0x0F;
505 tms_sequence_start = OUT2BUF[out_offset + 3];
506 tms_sequence_end = OUT2BUF[out_offset + 4];
507
508 if (tms_count_start > 0) {
509 jtag_slow_clock_tms(tms_count_start, tms_sequence_start);
510 }
511
512 outb_buffer = OUTB & ~(PIN_TCK | PIN_TMS);
513
514 /* Shift all bytes except the last byte */
515 for (i = 0; i < scan_size_bytes - 1; i++) {
516 tdi_data = OUT2BUF[i + out_offset + 5];
517 tdo_data = 0;
518
519 for (j = 0; j < 8; j++) {
520 if (tdi_data & 0x01) {
521 outb_buffer |= PIN_TDI;
522 }
523 else {
524 outb_buffer &= ~PIN_TDI;
525 }
526
527 OUTB = outb_buffer; /* TDI and TCK change here */
528 for (k = 0; k < delay_scan_io; k++);
529 tdi_data = tdi_data >> 1;
530
531 OUTB = (outb_buffer | PIN_TCK);
532 for (k = 0; k < delay_scan_io; k++);
533 tdo_data = tdo_data >> 1;
534
535 if (GET_TDO()) {
536 tdo_data |= 0x80;
537 }
538 }
539
540 /* Copy TDO data to IN2BUF */
541 IN2BUF[i + in_offset] = tdo_data;
542 }
543
544 tdi_data = OUT2BUF[i + out_offset + 5];
545 tdo_data = 0;
546
547 /* Shift the last byte */
548 for (j = 0; j < bits_last_byte; j++) {
549 if (tdi_data & 0x01) {
550 outb_buffer |= PIN_TDI;
551 }
552 else {
553 outb_buffer &= ~PIN_TDI;
554 }
555
556 /* Assert TMS signal if requested and this is the last bit */
557 if ((j == bits_last_byte - 1) && (tms_count_end > 0)) {
558 outb_buffer |= PIN_TMS;
559 tms_count_end--;
560 tms_sequence_end = tms_sequence_end >> 1;
561 }
562
563 OUTB = outb_buffer; /* TDI and TCK change here */
564 for (k = 0; k < delay_scan_io; k++);
565 tdi_data = tdi_data >> 1;
566
567 OUTB = (outb_buffer | PIN_TCK);
568 for (k = 0; k < delay_scan_io; k++);
569 tdo_data = tdo_data >> 1;
570
571 if (GET_TDO()) {
572 tdo_data |= 0x80;
573 }
574 }
575 tdo_data = tdo_data >> (8 - bits_last_byte);
576
577 /* Copy TDO data to IN2BUF */
578 IN2BUF[i + in_offset] = tdo_data;
579
580 /* Move to correct end state */
581 if (tms_count_end > 0) {
582 jtag_slow_clock_tms(tms_count_end, tms_sequence_end);
583 }
584 }
585
586 /**
587 * Generate TCK clock cycles.
588 *
589 * Maximum achievable TCK frequency is 375 kHz for ULINK clocked at 24 MHz.
590 *
591 * @param count number of TCK clock cyclces to generate.
592 */
593 void jtag_clock_tck(u16 count)
594 {
595 u16 i;
596 u8 outb_buffer = OUTB & ~(PIN_TCK);
597
598 for ( i = 0; i < count; i++ ) {
599 OUTB = outb_buffer;
600 OUTB = outb_buffer | PIN_TCK;
601 }
602 }
603
604 /**
605 * Generate TCK clock cycles at variable frequency.
606 *
607 * Maximum achieveable TCK frequency is 166.6 kHz for ULINK clocked at 24 MHz.
608 *
609 * @param count number of TCK clock cyclces to generate.
610 */
611 void jtag_slow_clock_tck(u16 count)
612 {
613 u16 i;
614 u8 j;
615 u8 outb_buffer = OUTB & ~(PIN_TCK);
616
617 for ( i = 0; i < count; i++ ) {
618 OUTB = outb_buffer;
619 for (j = 0; j < delay_tck; j++);
620 OUTB = outb_buffer | PIN_TCK;
621 for (j = 0; j < delay_tck; j++);
622 }
623 }
624
625 /**
626 * Perform TAP FSM state transitions at maximum TCK frequency.
627 *
628 * Maximum achievable TCK frequency is 176 kHz for ULINK clocked at 24 MHz.
629 *
630 * @param count the number of state transitions to perform.
631 * @param sequence the TMS pin levels for each state transition, starting with
632 * the least-significant bit.
633 */
634 void jtag_clock_tms(u8 count, u8 sequence)
635 {
636 u8 outb_buffer = OUTB & ~(PIN_TCK);
637 u8 i;
638
639 for ( i = 0; i < count; i++ ) {
640 /* Set TMS pin according to sequence parameter */
641 if ( sequence & 0x1 ) {
642 outb_buffer |= PIN_TMS;
643 }
644 else {
645 outb_buffer &= ~PIN_TMS;
646 }
647
648 OUTB = outb_buffer;
649 sequence = sequence >> 1;
650 OUTB = outb_buffer | PIN_TCK;
651 }
652 }
653
654 /**
655 * Perform TAP-FSM state transitions at less than maximum TCK frequency.
656 *
657 * Maximum achievable TCK frequency is 117 kHz for ULINK clocked at 24 MHz.
658 *
659 * @param count the number of state transitions to perform.
660 * @param sequence the TMS pin levels for each state transition, starting with
661 * the least-significant bit.
662 */
663 void jtag_slow_clock_tms(u8 count, u8 sequence)
664 {
665 u8 outb_buffer = OUTB & ~(PIN_TCK);
666 u8 i, j;
667
668 for (i = 0; i < count; i++) {
669 /* Set TMS pin according to sequence parameter */
670 if ( sequence & 0x1 ) {
671 outb_buffer |= PIN_TMS;
672 }
673 else {
674 outb_buffer &= ~PIN_TMS;
675 }
676
677 OUTB = outb_buffer;
678 for (j = 0; j < delay_tms; j++);
679 sequence = sequence >> 1;
680 OUTB = outb_buffer | PIN_TCK;
681 for (j = 0; j < delay_tms; j++);
682 }
683 }
684
685 /**
686 * Get current JTAG signal states.
687 *
688 * @return a 16-bit integer where the most-significant byte contains the state
689 * of the JTAG input signals and the least-significant byte cotains the state
690 * of the JTAG output signals.
691 */
692 u16 jtag_get_signals(void)
693 {
694 u8 input_signal_state, output_signal_state;
695
696 input_signal_state = 0;
697 output_signal_state = 0;
698
699 /* Get states of input pins */
700 if (GET_TDO()) {
701 input_signal_state |= SIGNAL_TDO;
702 }
703 if (GET_BRKOUT()) {
704 input_signal_state |= SIGNAL_BRKOUT;
705 }
706 if (GET_TRAP()) {
707 input_signal_state |= SIGNAL_TRAP;
708 }
709 if (GET_RTCK()) {
710 /* Using RTCK this way would be extremely slow,
711 * implemented only for the sake of completeness */
712 input_signal_state |= SIGNAL_RTCK;
713 }
714
715 /* Get states of output pins */
716 output_signal_state = PINSB & MASK_PORTB_DIRECTION_OUT;
717
718 return ((u16)input_signal_state << 8) | ((u16)output_signal_state);
719 }
720
721 /**
722 * Set state of JTAG output signals.
723 *
724 * @param low signals which should be de-asserted.
725 * @param high signals which should be asserted.
726 */
727 void jtag_set_signals(u8 low, u8 high)
728 {
729 OUTB &= ~(low & MASK_PORTB_DIRECTION_OUT);
730 OUTB |= (high & MASK_PORTB_DIRECTION_OUT);
731 }
732
733 /**
734 * Configure TCK delay parameters.
735 *
736 * @param scan_in number of delay cycles in scan_in operations.
737 * @param scan_out number of delay cycles in scan_out operations.
738 * @param scan_io number of delay cycles in scan_io operations.
739 * @param tck number of delay cycles in clock_tck operations.
740 * @param tms number of delay cycles in clock_tms operations.
741 */
742 void jtag_configure_tck_delay(u8 scan_in, u8 scan_out, u8 scan_io, u8 tck,
743 u8 tms)
744 {
745 delay_scan_in = scan_in;
746 delay_scan_out = scan_out;
747 delay_scan_io = scan_io;
748 delay_tck = tck;
749 delay_tms = tms;
750 }