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