1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * altera-jtag.c
4 *
5 * altera FPGA driver
6 *
7 * Copyright (C) Altera Corporation 1998-2001
8 * Copyright (C) 2010 NetUP Inc.
9 * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru>
10 */
11
12#include <linux/delay.h>
13#include <linux/firmware.h>
14#include <linux/slab.h>
15#include <misc/altera.h>
16#include "altera-exprt.h"
17#include "altera-jtag.h"
18
19#define alt_jtag_io(a, b, c)\
20 astate->config->jtag_io(astate->config->dev, a, b, c);
21
22#define alt_malloc(a) kzalloc(a, GFP_KERNEL);
23
24/*
25 * This structure shows, for each JTAG state, which state is reached after
26 * a single TCK clock cycle with TMS high or TMS low, respectively. This
27 * describes all possible state transitions in the JTAG state machine.
28 */
29struct altera_jtag_machine {
30 enum altera_jtag_state tms_high;
31 enum altera_jtag_state tms_low;
32};
33
34static const struct altera_jtag_machine altera_transitions[] = {
35 /* RESET */ { RESET, IDLE },
36 /* IDLE */ { DRSELECT, IDLE },
37 /* DRSELECT */ { IRSELECT, DRCAPTURE },
38 /* DRCAPTURE */ { DREXIT1, DRSHIFT },
39 /* DRSHIFT */ { DREXIT1, DRSHIFT },
40 /* DREXIT1 */ { DRUPDATE, DRPAUSE },
41 /* DRPAUSE */ { DREXIT2, DRPAUSE },
42 /* DREXIT2 */ { DRUPDATE, DRSHIFT },
43 /* DRUPDATE */ { DRSELECT, IDLE },
44 /* IRSELECT */ { RESET, IRCAPTURE },
45 /* IRCAPTURE */ { IREXIT1, IRSHIFT },
46 /* IRSHIFT */ { IREXIT1, IRSHIFT },
47 /* IREXIT1 */ { IRUPDATE, IRPAUSE },
48 /* IRPAUSE */ { IREXIT2, IRPAUSE },
49 /* IREXIT2 */ { IRUPDATE, IRSHIFT },
50 /* IRUPDATE */ { DRSELECT, IDLE }
51};
52
53/*
54 * This table contains the TMS value to be used to take the NEXT STEP on
55 * the path to the desired state. The array index is the current state,
56 * and the bit position is the desired endstate. To find out which state
57 * is used as the intermediate state, look up the TMS value in the
58 * altera_transitions[] table.
59 */
60static const u16 altera_jtag_path_map[16] = {
61 /* RST RTI SDRS CDR SDR E1DR PDR E2DR */
62 0x0001, 0xFFFD, 0xFE01, 0xFFE7, 0xFFEF, 0xFF0F, 0xFFBF, 0xFFFF,
63 /* UDR SIRS CIR SIR E1IR PIR E2IR UIR */
64 0xFEFD, 0x0001, 0xF3FF, 0xF7FF, 0x87FF, 0xDFFF, 0xFFFF, 0x7FFD
65};
66
67/* Flag bits for alt_jtag_io() function */
68#define TMS_HIGH 1
69#define TMS_LOW 0
70#define TDI_HIGH 1
71#define TDI_LOW 0
72#define READ_TDO 1
73#define IGNORE_TDO 0
74
75int altera_jinit(struct altera_state *astate)
76{
77 struct altera_jtag *js = &astate->js;
78
79 /* initial JTAG state is unknown */
80 js->jtag_state = ILLEGAL_JTAG_STATE;
81
82 /* initialize to default state */
83 js->drstop_state = IDLE;
84 js->irstop_state = IDLE;
85 js->dr_pre = 0;
86 js->dr_post = 0;
87 js->ir_pre = 0;
88 js->ir_post = 0;
89 js->dr_length = 0;
90 js->ir_length = 0;
91
92 js->dr_pre_data = NULL;
93 js->dr_post_data = NULL;
94 js->ir_pre_data = NULL;
95 js->ir_post_data = NULL;
96 js->dr_buffer = NULL;
97 js->ir_buffer = NULL;
98
99 return 0;
100}
101
102int altera_set_drstop(struct altera_jtag *js, enum altera_jtag_state state)
103{
104 js->drstop_state = state;
105
106 return 0;
107}
108
109int altera_set_irstop(struct altera_jtag *js, enum altera_jtag_state state)
110{
111 js->irstop_state = state;
112
113 return 0;
114}
115
116int altera_set_dr_pre(struct altera_jtag *js,
117 u32 count, u32 start_index,
118 u8 *preamble_data)
119{
120 int status = 0;
121 u32 i;
122 u32 j;
123
124 if (count > js->dr_pre) {
125 kfree(objp: js->dr_pre_data);
126 js->dr_pre_data = (u8 *)alt_malloc((count + 7) >> 3);
127 if (js->dr_pre_data == NULL)
128 status = -ENOMEM;
129 else
130 js->dr_pre = count;
131 } else
132 js->dr_pre = count;
133
134 if (status == 0) {
135 for (i = 0; i < count; ++i) {
136 j = i + start_index;
137
138 if (preamble_data == NULL)
139 js->dr_pre_data[i >> 3] |= (1 << (i & 7));
140 else {
141 if (preamble_data[j >> 3] & (1 << (j & 7)))
142 js->dr_pre_data[i >> 3] |=
143 (1 << (i & 7));
144 else
145 js->dr_pre_data[i >> 3] &=
146 ~(u32)(1 << (i & 7));
147
148 }
149 }
150 }
151
152 return status;
153}
154
155int altera_set_ir_pre(struct altera_jtag *js, u32 count, u32 start_index,
156 u8 *preamble_data)
157{
158 int status = 0;
159 u32 i;
160 u32 j;
161
162 if (count > js->ir_pre) {
163 kfree(objp: js->ir_pre_data);
164 js->ir_pre_data = (u8 *)alt_malloc((count + 7) >> 3);
165 if (js->ir_pre_data == NULL)
166 status = -ENOMEM;
167 else
168 js->ir_pre = count;
169
170 } else
171 js->ir_pre = count;
172
173 if (status == 0) {
174 for (i = 0; i < count; ++i) {
175 j = i + start_index;
176 if (preamble_data == NULL)
177 js->ir_pre_data[i >> 3] |= (1 << (i & 7));
178 else {
179 if (preamble_data[j >> 3] & (1 << (j & 7)))
180 js->ir_pre_data[i >> 3] |=
181 (1 << (i & 7));
182 else
183 js->ir_pre_data[i >> 3] &=
184 ~(u32)(1 << (i & 7));
185
186 }
187 }
188 }
189
190 return status;
191}
192
193int altera_set_dr_post(struct altera_jtag *js, u32 count, u32 start_index,
194 u8 *postamble_data)
195{
196 int status = 0;
197 u32 i;
198 u32 j;
199
200 if (count > js->dr_post) {
201 kfree(objp: js->dr_post_data);
202 js->dr_post_data = (u8 *)alt_malloc((count + 7) >> 3);
203
204 if (js->dr_post_data == NULL)
205 status = -ENOMEM;
206 else
207 js->dr_post = count;
208
209 } else
210 js->dr_post = count;
211
212 if (status == 0) {
213 for (i = 0; i < count; ++i) {
214 j = i + start_index;
215
216 if (postamble_data == NULL)
217 js->dr_post_data[i >> 3] |= (1 << (i & 7));
218 else {
219 if (postamble_data[j >> 3] & (1 << (j & 7)))
220 js->dr_post_data[i >> 3] |=
221 (1 << (i & 7));
222 else
223 js->dr_post_data[i >> 3] &=
224 ~(u32)(1 << (i & 7));
225
226 }
227 }
228 }
229
230 return status;
231}
232
233int altera_set_ir_post(struct altera_jtag *js, u32 count, u32 start_index,
234 u8 *postamble_data)
235{
236 int status = 0;
237 u32 i;
238 u32 j;
239
240 if (count > js->ir_post) {
241 kfree(objp: js->ir_post_data);
242 js->ir_post_data = (u8 *)alt_malloc((count + 7) >> 3);
243 if (js->ir_post_data == NULL)
244 status = -ENOMEM;
245 else
246 js->ir_post = count;
247
248 } else
249 js->ir_post = count;
250
251 if (status != 0)
252 return status;
253
254 for (i = 0; i < count; ++i) {
255 j = i + start_index;
256
257 if (postamble_data == NULL)
258 js->ir_post_data[i >> 3] |= (1 << (i & 7));
259 else {
260 if (postamble_data[j >> 3] & (1 << (j & 7)))
261 js->ir_post_data[i >> 3] |= (1 << (i & 7));
262 else
263 js->ir_post_data[i >> 3] &=
264 ~(u32)(1 << (i & 7));
265
266 }
267 }
268
269 return status;
270}
271
272static void altera_jreset_idle(struct altera_state *astate)
273{
274 struct altera_jtag *js = &astate->js;
275 int i;
276 /* Go to Test Logic Reset (no matter what the starting state may be) */
277 for (i = 0; i < 5; ++i)
278 alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO);
279
280 /* Now step to Run Test / Idle */
281 alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO);
282 js->jtag_state = IDLE;
283}
284
285int altera_goto_jstate(struct altera_state *astate,
286 enum altera_jtag_state state)
287{
288 struct altera_jtag *js = &astate->js;
289 int tms;
290 int count = 0;
291 int status = 0;
292
293 if (js->jtag_state == ILLEGAL_JTAG_STATE)
294 /* initialize JTAG chain to known state */
295 altera_jreset_idle(astate);
296
297 if (js->jtag_state == state) {
298 /*
299 * We are already in the desired state.
300 * If it is a stable state, loop here.
301 * Otherwise do nothing (no clock cycles).
302 */
303 if ((state == IDLE) || (state == DRSHIFT) ||
304 (state == DRPAUSE) || (state == IRSHIFT) ||
305 (state == IRPAUSE)) {
306 alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO);
307 } else if (state == RESET)
308 alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO);
309
310 } else {
311 while ((js->jtag_state != state) && (count < 9)) {
312 /* Get TMS value to take a step toward desired state */
313 tms = (altera_jtag_path_map[js->jtag_state] &
314 (1 << state))
315 ? TMS_HIGH : TMS_LOW;
316
317 /* Take a step */
318 alt_jtag_io(tms, TDI_LOW, IGNORE_TDO);
319
320 if (tms)
321 js->jtag_state =
322 altera_transitions[js->jtag_state].tms_high;
323 else
324 js->jtag_state =
325 altera_transitions[js->jtag_state].tms_low;
326
327 ++count;
328 }
329 }
330
331 if (js->jtag_state != state)
332 status = -EREMOTEIO;
333
334 return status;
335}
336
337int altera_wait_cycles(struct altera_state *astate,
338 s32 cycles,
339 enum altera_jtag_state wait_state)
340{
341 struct altera_jtag *js = &astate->js;
342 int tms;
343 s32 count;
344 int status = 0;
345
346 if (js->jtag_state != wait_state)
347 status = altera_goto_jstate(astate, state: wait_state);
348
349 if (status == 0) {
350 /*
351 * Set TMS high to loop in RESET state
352 * Set TMS low to loop in any other stable state
353 */
354 tms = (wait_state == RESET) ? TMS_HIGH : TMS_LOW;
355
356 for (count = 0L; count < cycles; count++)
357 alt_jtag_io(tms, TDI_LOW, IGNORE_TDO);
358
359 }
360
361 return status;
362}
363
364int altera_wait_msecs(struct altera_state *astate,
365 s32 microseconds, enum altera_jtag_state wait_state)
366/*
367 * Causes JTAG hardware to sit in the specified stable
368 * state for the specified duration of real time. If
369 * no JTAG operations have been performed yet, then only
370 * a delay is performed. This permits the WAIT USECS
371 * statement to be used in VECTOR programs without causing
372 * any JTAG operations.
373 * Returns 0 for success, else appropriate error code.
374 */
375{
376 struct altera_jtag *js = &astate->js;
377 int status = 0;
378
379 if ((js->jtag_state != ILLEGAL_JTAG_STATE) &&
380 (js->jtag_state != wait_state))
381 status = altera_goto_jstate(astate, state: wait_state);
382
383 if (status == 0)
384 /* Wait for specified time interval */
385 udelay(microseconds);
386
387 return status;
388}
389
390static void altera_concatenate_data(u8 *buffer,
391 u8 *preamble_data,
392 u32 preamble_count,
393 u8 *target_data,
394 u32 start_index,
395 u32 target_count,
396 u8 *postamble_data,
397 u32 postamble_count)
398/*
399 * Copies preamble data, target data, and postamble data
400 * into one buffer for IR or DR scans.
401 */
402{
403 u32 i, j, k;
404
405 for (i = 0L; i < preamble_count; ++i) {
406 if (preamble_data[i >> 3L] & (1L << (i & 7L)))
407 buffer[i >> 3L] |= (1L << (i & 7L));
408 else
409 buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
410
411 }
412
413 j = start_index;
414 k = preamble_count + target_count;
415 for (; i < k; ++i, ++j) {
416 if (target_data[j >> 3L] & (1L << (j & 7L)))
417 buffer[i >> 3L] |= (1L << (i & 7L));
418 else
419 buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
420
421 }
422
423 j = 0L;
424 k = preamble_count + target_count + postamble_count;
425 for (; i < k; ++i, ++j) {
426 if (postamble_data[j >> 3L] & (1L << (j & 7L)))
427 buffer[i >> 3L] |= (1L << (i & 7L));
428 else
429 buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
430
431 }
432}
433
434static int alt_jtag_drscan(struct altera_state *astate,
435 int start_state,
436 int count,
437 u8 *tdi,
438 u8 *tdo)
439{
440 int i = 0;
441 int tdo_bit = 0;
442 int status = 1;
443
444 /* First go to DRSHIFT state */
445 switch (start_state) {
446 case 0: /* IDLE */
447 alt_jtag_io(1, 0, 0); /* DRSELECT */
448 alt_jtag_io(0, 0, 0); /* DRCAPTURE */
449 alt_jtag_io(0, 0, 0); /* DRSHIFT */
450 break;
451
452 case 1: /* DRPAUSE */
453 alt_jtag_io(1, 0, 0); /* DREXIT2 */
454 alt_jtag_io(1, 0, 0); /* DRUPDATE */
455 alt_jtag_io(1, 0, 0); /* DRSELECT */
456 alt_jtag_io(0, 0, 0); /* DRCAPTURE */
457 alt_jtag_io(0, 0, 0); /* DRSHIFT */
458 break;
459
460 case 2: /* IRPAUSE */
461 alt_jtag_io(1, 0, 0); /* IREXIT2 */
462 alt_jtag_io(1, 0, 0); /* IRUPDATE */
463 alt_jtag_io(1, 0, 0); /* DRSELECT */
464 alt_jtag_io(0, 0, 0); /* DRCAPTURE */
465 alt_jtag_io(0, 0, 0); /* DRSHIFT */
466 break;
467
468 default:
469 status = 0;
470 }
471
472 if (status) {
473 /* loop in the SHIFT-DR state */
474 for (i = 0; i < count; i++) {
475 tdo_bit = alt_jtag_io(
476 (i == count - 1),
477 tdi[i >> 3] & (1 << (i & 7)),
478 (tdo != NULL));
479
480 if (tdo != NULL) {
481 if (tdo_bit)
482 tdo[i >> 3] |= (1 << (i & 7));
483 else
484 tdo[i >> 3] &= ~(u32)(1 << (i & 7));
485
486 }
487 }
488
489 alt_jtag_io(0, 0, 0); /* DRPAUSE */
490 }
491
492 return status;
493}
494
495static int alt_jtag_irscan(struct altera_state *astate,
496 int start_state,
497 int count,
498 u8 *tdi,
499 u8 *tdo)
500{
501 int i = 0;
502 int tdo_bit = 0;
503 int status = 1;
504
505 /* First go to IRSHIFT state */
506 switch (start_state) {
507 case 0: /* IDLE */
508 alt_jtag_io(1, 0, 0); /* DRSELECT */
509 alt_jtag_io(1, 0, 0); /* IRSELECT */
510 alt_jtag_io(0, 0, 0); /* IRCAPTURE */
511 alt_jtag_io(0, 0, 0); /* IRSHIFT */
512 break;
513
514 case 1: /* DRPAUSE */
515 alt_jtag_io(1, 0, 0); /* DREXIT2 */
516 alt_jtag_io(1, 0, 0); /* DRUPDATE */
517 alt_jtag_io(1, 0, 0); /* DRSELECT */
518 alt_jtag_io(1, 0, 0); /* IRSELECT */
519 alt_jtag_io(0, 0, 0); /* IRCAPTURE */
520 alt_jtag_io(0, 0, 0); /* IRSHIFT */
521 break;
522
523 case 2: /* IRPAUSE */
524 alt_jtag_io(1, 0, 0); /* IREXIT2 */
525 alt_jtag_io(1, 0, 0); /* IRUPDATE */
526 alt_jtag_io(1, 0, 0); /* DRSELECT */
527 alt_jtag_io(1, 0, 0); /* IRSELECT */
528 alt_jtag_io(0, 0, 0); /* IRCAPTURE */
529 alt_jtag_io(0, 0, 0); /* IRSHIFT */
530 break;
531
532 default:
533 status = 0;
534 }
535
536 if (status) {
537 /* loop in the SHIFT-IR state */
538 for (i = 0; i < count; i++) {
539 tdo_bit = alt_jtag_io(
540 (i == count - 1),
541 tdi[i >> 3] & (1 << (i & 7)),
542 (tdo != NULL));
543 if (tdo != NULL) {
544 if (tdo_bit)
545 tdo[i >> 3] |= (1 << (i & 7));
546 else
547 tdo[i >> 3] &= ~(u32)(1 << (i & 7));
548
549 }
550 }
551
552 alt_jtag_io(0, 0, 0); /* IRPAUSE */
553 }
554
555 return status;
556}
557
558static void altera_extract_target_data(u8 *buffer,
559 u8 *target_data,
560 u32 start_index,
561 u32 preamble_count,
562 u32 target_count)
563/*
564 * Copies target data from scan buffer, filtering out
565 * preamble and postamble data.
566 */
567{
568 u32 i;
569 u32 j;
570 u32 k;
571
572 j = preamble_count;
573 k = start_index + target_count;
574 for (i = start_index; i < k; ++i, ++j) {
575 if (buffer[j >> 3] & (1 << (j & 7)))
576 target_data[i >> 3] |= (1 << (i & 7));
577 else
578 target_data[i >> 3] &= ~(u32)(1 << (i & 7));
579
580 }
581}
582
583int altera_irscan(struct altera_state *astate,
584 u32 count,
585 u8 *tdi_data,
586 u32 start_index)
587/* Shifts data into instruction register */
588{
589 struct altera_jtag *js = &astate->js;
590 int start_code = 0;
591 u32 alloc_chars = 0;
592 u32 shift_count = js->ir_pre + count + js->ir_post;
593 int status = 0;
594 enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
595
596 switch (js->jtag_state) {
597 case ILLEGAL_JTAG_STATE:
598 case RESET:
599 case IDLE:
600 start_code = 0;
601 start_state = IDLE;
602 break;
603
604 case DRSELECT:
605 case DRCAPTURE:
606 case DRSHIFT:
607 case DREXIT1:
608 case DRPAUSE:
609 case DREXIT2:
610 case DRUPDATE:
611 start_code = 1;
612 start_state = DRPAUSE;
613 break;
614
615 case IRSELECT:
616 case IRCAPTURE:
617 case IRSHIFT:
618 case IREXIT1:
619 case IRPAUSE:
620 case IREXIT2:
621 case IRUPDATE:
622 start_code = 2;
623 start_state = IRPAUSE;
624 break;
625
626 default:
627 status = -EREMOTEIO;
628 break;
629 }
630
631 if (status == 0)
632 if (js->jtag_state != start_state)
633 status = altera_goto_jstate(astate, state: start_state);
634
635 if (status == 0) {
636 if (shift_count > js->ir_length) {
637 alloc_chars = (shift_count + 7) >> 3;
638 kfree(objp: js->ir_buffer);
639 js->ir_buffer = (u8 *)alt_malloc(alloc_chars);
640 if (js->ir_buffer == NULL)
641 status = -ENOMEM;
642 else
643 js->ir_length = alloc_chars * 8;
644
645 }
646 }
647
648 if (status == 0) {
649 /*
650 * Copy preamble data, IR data,
651 * and postamble data into a buffer
652 */
653 altera_concatenate_data(buffer: js->ir_buffer,
654 preamble_data: js->ir_pre_data,
655 preamble_count: js->ir_pre,
656 target_data: tdi_data,
657 start_index,
658 target_count: count,
659 postamble_data: js->ir_post_data,
660 postamble_count: js->ir_post);
661 /* Do the IRSCAN */
662 alt_jtag_irscan(astate,
663 start_state: start_code,
664 count: shift_count,
665 tdi: js->ir_buffer,
666 NULL);
667
668 /* alt_jtag_irscan() always ends in IRPAUSE state */
669 js->jtag_state = IRPAUSE;
670 }
671
672 if (status == 0)
673 if (js->irstop_state != IRPAUSE)
674 status = altera_goto_jstate(astate, state: js->irstop_state);
675
676
677 return status;
678}
679
680int altera_swap_ir(struct altera_state *astate,
681 u32 count,
682 u8 *in_data,
683 u32 in_index,
684 u8 *out_data,
685 u32 out_index)
686/* Shifts data into instruction register, capturing output data */
687{
688 struct altera_jtag *js = &astate->js;
689 int start_code = 0;
690 u32 alloc_chars = 0;
691 u32 shift_count = js->ir_pre + count + js->ir_post;
692 int status = 0;
693 enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
694
695 switch (js->jtag_state) {
696 case ILLEGAL_JTAG_STATE:
697 case RESET:
698 case IDLE:
699 start_code = 0;
700 start_state = IDLE;
701 break;
702
703 case DRSELECT:
704 case DRCAPTURE:
705 case DRSHIFT:
706 case DREXIT1:
707 case DRPAUSE:
708 case DREXIT2:
709 case DRUPDATE:
710 start_code = 1;
711 start_state = DRPAUSE;
712 break;
713
714 case IRSELECT:
715 case IRCAPTURE:
716 case IRSHIFT:
717 case IREXIT1:
718 case IRPAUSE:
719 case IREXIT2:
720 case IRUPDATE:
721 start_code = 2;
722 start_state = IRPAUSE;
723 break;
724
725 default:
726 status = -EREMOTEIO;
727 break;
728 }
729
730 if (status == 0)
731 if (js->jtag_state != start_state)
732 status = altera_goto_jstate(astate, state: start_state);
733
734 if (status == 0) {
735 if (shift_count > js->ir_length) {
736 alloc_chars = (shift_count + 7) >> 3;
737 kfree(objp: js->ir_buffer);
738 js->ir_buffer = (u8 *)alt_malloc(alloc_chars);
739 if (js->ir_buffer == NULL)
740 status = -ENOMEM;
741 else
742 js->ir_length = alloc_chars * 8;
743
744 }
745 }
746
747 if (status == 0) {
748 /*
749 * Copy preamble data, IR data,
750 * and postamble data into a buffer
751 */
752 altera_concatenate_data(buffer: js->ir_buffer,
753 preamble_data: js->ir_pre_data,
754 preamble_count: js->ir_pre,
755 target_data: in_data,
756 start_index: in_index,
757 target_count: count,
758 postamble_data: js->ir_post_data,
759 postamble_count: js->ir_post);
760
761 /* Do the IRSCAN */
762 alt_jtag_irscan(astate,
763 start_state: start_code,
764 count: shift_count,
765 tdi: js->ir_buffer,
766 tdo: js->ir_buffer);
767
768 /* alt_jtag_irscan() always ends in IRPAUSE state */
769 js->jtag_state = IRPAUSE;
770 }
771
772 if (status == 0)
773 if (js->irstop_state != IRPAUSE)
774 status = altera_goto_jstate(astate, state: js->irstop_state);
775
776
777 if (status == 0)
778 /* Now extract the returned data from the buffer */
779 altera_extract_target_data(buffer: js->ir_buffer,
780 target_data: out_data, start_index: out_index,
781 preamble_count: js->ir_pre, target_count: count);
782
783 return status;
784}
785
786int altera_drscan(struct altera_state *astate,
787 u32 count,
788 u8 *tdi_data,
789 u32 start_index)
790/* Shifts data into data register (ignoring output data) */
791{
792 struct altera_jtag *js = &astate->js;
793 int start_code = 0;
794 u32 alloc_chars = 0;
795 u32 shift_count = js->dr_pre + count + js->dr_post;
796 int status = 0;
797 enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
798
799 switch (js->jtag_state) {
800 case ILLEGAL_JTAG_STATE:
801 case RESET:
802 case IDLE:
803 start_code = 0;
804 start_state = IDLE;
805 break;
806
807 case DRSELECT:
808 case DRCAPTURE:
809 case DRSHIFT:
810 case DREXIT1:
811 case DRPAUSE:
812 case DREXIT2:
813 case DRUPDATE:
814 start_code = 1;
815 start_state = DRPAUSE;
816 break;
817
818 case IRSELECT:
819 case IRCAPTURE:
820 case IRSHIFT:
821 case IREXIT1:
822 case IRPAUSE:
823 case IREXIT2:
824 case IRUPDATE:
825 start_code = 2;
826 start_state = IRPAUSE;
827 break;
828
829 default:
830 status = -EREMOTEIO;
831 break;
832 }
833
834 if (status == 0)
835 if (js->jtag_state != start_state)
836 status = altera_goto_jstate(astate, state: start_state);
837
838 if (status == 0) {
839 if (shift_count > js->dr_length) {
840 alloc_chars = (shift_count + 7) >> 3;
841 kfree(objp: js->dr_buffer);
842 js->dr_buffer = (u8 *)alt_malloc(alloc_chars);
843 if (js->dr_buffer == NULL)
844 status = -ENOMEM;
845 else
846 js->dr_length = alloc_chars * 8;
847
848 }
849 }
850
851 if (status == 0) {
852 /*
853 * Copy preamble data, DR data,
854 * and postamble data into a buffer
855 */
856 altera_concatenate_data(buffer: js->dr_buffer,
857 preamble_data: js->dr_pre_data,
858 preamble_count: js->dr_pre,
859 target_data: tdi_data,
860 start_index,
861 target_count: count,
862 postamble_data: js->dr_post_data,
863 postamble_count: js->dr_post);
864 /* Do the DRSCAN */
865 alt_jtag_drscan(astate, start_state: start_code, count: shift_count,
866 tdi: js->dr_buffer, NULL);
867 /* alt_jtag_drscan() always ends in DRPAUSE state */
868 js->jtag_state = DRPAUSE;
869 }
870
871 if (status == 0)
872 if (js->drstop_state != DRPAUSE)
873 status = altera_goto_jstate(astate, state: js->drstop_state);
874
875 return status;
876}
877
878int altera_swap_dr(struct altera_state *astate, u32 count,
879 u8 *in_data, u32 in_index,
880 u8 *out_data, u32 out_index)
881/* Shifts data into data register, capturing output data */
882{
883 struct altera_jtag *js = &astate->js;
884 int start_code = 0;
885 u32 alloc_chars = 0;
886 u32 shift_count = js->dr_pre + count + js->dr_post;
887 int status = 0;
888 enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
889
890 switch (js->jtag_state) {
891 case ILLEGAL_JTAG_STATE:
892 case RESET:
893 case IDLE:
894 start_code = 0;
895 start_state = IDLE;
896 break;
897
898 case DRSELECT:
899 case DRCAPTURE:
900 case DRSHIFT:
901 case DREXIT1:
902 case DRPAUSE:
903 case DREXIT2:
904 case DRUPDATE:
905 start_code = 1;
906 start_state = DRPAUSE;
907 break;
908
909 case IRSELECT:
910 case IRCAPTURE:
911 case IRSHIFT:
912 case IREXIT1:
913 case IRPAUSE:
914 case IREXIT2:
915 case IRUPDATE:
916 start_code = 2;
917 start_state = IRPAUSE;
918 break;
919
920 default:
921 status = -EREMOTEIO;
922 break;
923 }
924
925 if (status == 0)
926 if (js->jtag_state != start_state)
927 status = altera_goto_jstate(astate, state: start_state);
928
929 if (status == 0) {
930 if (shift_count > js->dr_length) {
931 alloc_chars = (shift_count + 7) >> 3;
932 kfree(objp: js->dr_buffer);
933 js->dr_buffer = (u8 *)alt_malloc(alloc_chars);
934
935 if (js->dr_buffer == NULL)
936 status = -ENOMEM;
937 else
938 js->dr_length = alloc_chars * 8;
939
940 }
941 }
942
943 if (status == 0) {
944 /*
945 * Copy preamble data, DR data,
946 * and postamble data into a buffer
947 */
948 altera_concatenate_data(buffer: js->dr_buffer,
949 preamble_data: js->dr_pre_data,
950 preamble_count: js->dr_pre,
951 target_data: in_data,
952 start_index: in_index,
953 target_count: count,
954 postamble_data: js->dr_post_data,
955 postamble_count: js->dr_post);
956
957 /* Do the DRSCAN */
958 alt_jtag_drscan(astate,
959 start_state: start_code,
960 count: shift_count,
961 tdi: js->dr_buffer,
962 tdo: js->dr_buffer);
963
964 /* alt_jtag_drscan() always ends in DRPAUSE state */
965 js->jtag_state = DRPAUSE;
966 }
967
968 if (status == 0)
969 if (js->drstop_state != DRPAUSE)
970 status = altera_goto_jstate(astate, state: js->drstop_state);
971
972 if (status == 0)
973 /* Now extract the returned data from the buffer */
974 altera_extract_target_data(buffer: js->dr_buffer,
975 target_data: out_data,
976 start_index: out_index,
977 preamble_count: js->dr_pre,
978 target_count: count);
979
980 return status;
981}
982
983void altera_free_buffers(struct altera_state *astate)
984{
985 struct altera_jtag *js = &astate->js;
986 /* If the JTAG interface was used, reset it to TLR */
987 if (js->jtag_state != ILLEGAL_JTAG_STATE)
988 altera_jreset_idle(astate);
989
990 kfree(objp: js->dr_pre_data);
991 js->dr_pre_data = NULL;
992
993 kfree(objp: js->dr_post_data);
994 js->dr_post_data = NULL;
995
996 kfree(objp: js->dr_buffer);
997 js->dr_buffer = NULL;
998
999 kfree(objp: js->ir_pre_data);
1000 js->ir_pre_data = NULL;
1001
1002 kfree(objp: js->ir_post_data);
1003 js->ir_post_data = NULL;
1004
1005 kfree(objp: js->ir_buffer);
1006 js->ir_buffer = NULL;
1007}
1008

source code of linux/drivers/misc/altera-stapl/altera-jtag.c