Merge tag 'v3.3.7' into 3.3/master
[zen-stable.git] / drivers / misc / altera-stapl / altera-jtag.c
blobf4bf20096972f4b5804f6c643448c3ca609c79ff
1 /*
2 * altera-jtag.c
4 * altera FPGA driver
6 * Copyright (C) Altera Corporation 1998-2001
7 * Copyright (C) 2010 NetUP Inc.
8 * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include <linux/delay.h>
27 #include <linux/firmware.h>
28 #include <linux/slab.h>
29 #include <misc/altera.h>
30 #include "altera-exprt.h"
31 #include "altera-jtag.h"
33 #define alt_jtag_io(a, b, c)\
34 astate->config->jtag_io(astate->config->dev, a, b, c);
36 #define alt_malloc(a) kzalloc(a, GFP_KERNEL);
39 * This structure shows, for each JTAG state, which state is reached after
40 * a single TCK clock cycle with TMS high or TMS low, respectively. This
41 * describes all possible state transitions in the JTAG state machine.
43 struct altera_jtag_machine {
44 enum altera_jtag_state tms_high;
45 enum altera_jtag_state tms_low;
48 static const struct altera_jtag_machine altera_transitions[] = {
49 /* RESET */ { RESET, IDLE },
50 /* IDLE */ { DRSELECT, IDLE },
51 /* DRSELECT */ { IRSELECT, DRCAPTURE },
52 /* DRCAPTURE */ { DREXIT1, DRSHIFT },
53 /* DRSHIFT */ { DREXIT1, DRSHIFT },
54 /* DREXIT1 */ { DRUPDATE, DRPAUSE },
55 /* DRPAUSE */ { DREXIT2, DRPAUSE },
56 /* DREXIT2 */ { DRUPDATE, DRSHIFT },
57 /* DRUPDATE */ { DRSELECT, IDLE },
58 /* IRSELECT */ { RESET, IRCAPTURE },
59 /* IRCAPTURE */ { IREXIT1, IRSHIFT },
60 /* IRSHIFT */ { IREXIT1, IRSHIFT },
61 /* IREXIT1 */ { IRUPDATE, IRPAUSE },
62 /* IRPAUSE */ { IREXIT2, IRPAUSE },
63 /* IREXIT2 */ { IRUPDATE, IRSHIFT },
64 /* IRUPDATE */ { DRSELECT, IDLE }
68 * This table contains the TMS value to be used to take the NEXT STEP on
69 * the path to the desired state. The array index is the current state,
70 * and the bit position is the desired endstate. To find out which state
71 * is used as the intermediate state, look up the TMS value in the
72 * altera_transitions[] table.
74 static const u16 altera_jtag_path_map[16] = {
75 /* RST RTI SDRS CDR SDR E1DR PDR E2DR */
76 0x0001, 0xFFFD, 0xFE01, 0xFFE7, 0xFFEF, 0xFF0F, 0xFFBF, 0xFFFF,
77 /* UDR SIRS CIR SIR E1IR PIR E2IR UIR */
78 0xFEFD, 0x0001, 0xF3FF, 0xF7FF, 0x87FF, 0xDFFF, 0xFFFF, 0x7FFD
81 /* Flag bits for alt_jtag_io() function */
82 #define TMS_HIGH 1
83 #define TMS_LOW 0
84 #define TDI_HIGH 1
85 #define TDI_LOW 0
86 #define READ_TDO 1
87 #define IGNORE_TDO 0
89 int altera_jinit(struct altera_state *astate)
91 struct altera_jtag *js = &astate->js;
93 /* initial JTAG state is unknown */
94 js->jtag_state = ILLEGAL_JTAG_STATE;
96 /* initialize to default state */
97 js->drstop_state = IDLE;
98 js->irstop_state = IDLE;
99 js->dr_pre = 0;
100 js->dr_post = 0;
101 js->ir_pre = 0;
102 js->ir_post = 0;
103 js->dr_length = 0;
104 js->ir_length = 0;
106 js->dr_pre_data = NULL;
107 js->dr_post_data = NULL;
108 js->ir_pre_data = NULL;
109 js->ir_post_data = NULL;
110 js->dr_buffer = NULL;
111 js->ir_buffer = NULL;
113 return 0;
116 int altera_set_drstop(struct altera_jtag *js, enum altera_jtag_state state)
118 js->drstop_state = state;
120 return 0;
123 int altera_set_irstop(struct altera_jtag *js, enum altera_jtag_state state)
125 js->irstop_state = state;
127 return 0;
130 int altera_set_dr_pre(struct altera_jtag *js,
131 u32 count, u32 start_index,
132 u8 *preamble_data)
134 int status = 0;
135 u32 i;
136 u32 j;
138 if (count > js->dr_pre) {
139 kfree(js->dr_pre_data);
140 js->dr_pre_data = (u8 *)alt_malloc((count + 7) >> 3);
141 if (js->dr_pre_data == NULL)
142 status = -ENOMEM;
143 else
144 js->dr_pre = count;
145 } else
146 js->dr_pre = count;
148 if (status == 0) {
149 for (i = 0; i < count; ++i) {
150 j = i + start_index;
152 if (preamble_data == NULL)
153 js->dr_pre_data[i >> 3] |= (1 << (i & 7));
154 else {
155 if (preamble_data[j >> 3] & (1 << (j & 7)))
156 js->dr_pre_data[i >> 3] |=
157 (1 << (i & 7));
158 else
159 js->dr_pre_data[i >> 3] &=
160 ~(u32)(1 << (i & 7));
166 return status;
169 int altera_set_ir_pre(struct altera_jtag *js, u32 count, u32 start_index,
170 u8 *preamble_data)
172 int status = 0;
173 u32 i;
174 u32 j;
176 if (count > js->ir_pre) {
177 kfree(js->ir_pre_data);
178 js->ir_pre_data = (u8 *)alt_malloc((count + 7) >> 3);
179 if (js->ir_pre_data == NULL)
180 status = -ENOMEM;
181 else
182 js->ir_pre = count;
184 } else
185 js->ir_pre = count;
187 if (status == 0) {
188 for (i = 0; i < count; ++i) {
189 j = i + start_index;
190 if (preamble_data == NULL)
191 js->ir_pre_data[i >> 3] |= (1 << (i & 7));
192 else {
193 if (preamble_data[j >> 3] & (1 << (j & 7)))
194 js->ir_pre_data[i >> 3] |=
195 (1 << (i & 7));
196 else
197 js->ir_pre_data[i >> 3] &=
198 ~(u32)(1 << (i & 7));
204 return status;
207 int altera_set_dr_post(struct altera_jtag *js, u32 count, u32 start_index,
208 u8 *postamble_data)
210 int status = 0;
211 u32 i;
212 u32 j;
214 if (count > js->dr_post) {
215 kfree(js->dr_post_data);
216 js->dr_post_data = (u8 *)alt_malloc((count + 7) >> 3);
218 if (js->dr_post_data == NULL)
219 status = -ENOMEM;
220 else
221 js->dr_post = count;
223 } else
224 js->dr_post = count;
226 if (status == 0) {
227 for (i = 0; i < count; ++i) {
228 j = i + start_index;
230 if (postamble_data == NULL)
231 js->dr_post_data[i >> 3] |= (1 << (i & 7));
232 else {
233 if (postamble_data[j >> 3] & (1 << (j & 7)))
234 js->dr_post_data[i >> 3] |=
235 (1 << (i & 7));
236 else
237 js->dr_post_data[i >> 3] &=
238 ~(u32)(1 << (i & 7));
244 return status;
247 int altera_set_ir_post(struct altera_jtag *js, u32 count, u32 start_index,
248 u8 *postamble_data)
250 int status = 0;
251 u32 i;
252 u32 j;
254 if (count > js->ir_post) {
255 kfree(js->ir_post_data);
256 js->ir_post_data = (u8 *)alt_malloc((count + 7) >> 3);
257 if (js->ir_post_data == NULL)
258 status = -ENOMEM;
259 else
260 js->ir_post = count;
262 } else
263 js->ir_post = count;
265 if (status != 0)
266 return status;
268 for (i = 0; i < count; ++i) {
269 j = i + start_index;
271 if (postamble_data == NULL)
272 js->ir_post_data[i >> 3] |= (1 << (i & 7));
273 else {
274 if (postamble_data[j >> 3] & (1 << (j & 7)))
275 js->ir_post_data[i >> 3] |= (1 << (i & 7));
276 else
277 js->ir_post_data[i >> 3] &=
278 ~(u32)(1 << (i & 7));
283 return status;
286 static void altera_jreset_idle(struct altera_state *astate)
288 struct altera_jtag *js = &astate->js;
289 int i;
290 /* Go to Test Logic Reset (no matter what the starting state may be) */
291 for (i = 0; i < 5; ++i)
292 alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO);
294 /* Now step to Run Test / Idle */
295 alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO);
296 js->jtag_state = IDLE;
299 int altera_goto_jstate(struct altera_state *astate,
300 enum altera_jtag_state state)
302 struct altera_jtag *js = &astate->js;
303 int tms;
304 int count = 0;
305 int status = 0;
307 if (js->jtag_state == ILLEGAL_JTAG_STATE)
308 /* initialize JTAG chain to known state */
309 altera_jreset_idle(astate);
311 if (js->jtag_state == state) {
313 * We are already in the desired state.
314 * If it is a stable state, loop here.
315 * Otherwise do nothing (no clock cycles).
317 if ((state == IDLE) || (state == DRSHIFT) ||
318 (state == DRPAUSE) || (state == IRSHIFT) ||
319 (state == IRPAUSE)) {
320 alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO);
321 } else if (state == RESET)
322 alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO);
324 } else {
325 while ((js->jtag_state != state) && (count < 9)) {
326 /* Get TMS value to take a step toward desired state */
327 tms = (altera_jtag_path_map[js->jtag_state] &
328 (1 << state))
329 ? TMS_HIGH : TMS_LOW;
331 /* Take a step */
332 alt_jtag_io(tms, TDI_LOW, IGNORE_TDO);
334 if (tms)
335 js->jtag_state =
336 altera_transitions[js->jtag_state].tms_high;
337 else
338 js->jtag_state =
339 altera_transitions[js->jtag_state].tms_low;
341 ++count;
345 if (js->jtag_state != state)
346 status = -EREMOTEIO;
348 return status;
351 int altera_wait_cycles(struct altera_state *astate,
352 s32 cycles,
353 enum altera_jtag_state wait_state)
355 struct altera_jtag *js = &astate->js;
356 int tms;
357 s32 count;
358 int status = 0;
360 if (js->jtag_state != wait_state)
361 status = altera_goto_jstate(astate, wait_state);
363 if (status == 0) {
365 * Set TMS high to loop in RESET state
366 * Set TMS low to loop in any other stable state
368 tms = (wait_state == RESET) ? TMS_HIGH : TMS_LOW;
370 for (count = 0L; count < cycles; count++)
371 alt_jtag_io(tms, TDI_LOW, IGNORE_TDO);
375 return status;
378 int altera_wait_msecs(struct altera_state *astate,
379 s32 microseconds, enum altera_jtag_state wait_state)
381 * Causes JTAG hardware to sit in the specified stable
382 * state for the specified duration of real time. If
383 * no JTAG operations have been performed yet, then only
384 * a delay is performed. This permits the WAIT USECS
385 * statement to be used in VECTOR programs without causing
386 * any JTAG operations.
387 * Returns 0 for success, else appropriate error code.
390 struct altera_jtag *js = &astate->js;
391 int status = 0;
393 if ((js->jtag_state != ILLEGAL_JTAG_STATE) &&
394 (js->jtag_state != wait_state))
395 status = altera_goto_jstate(astate, wait_state);
397 if (status == 0)
398 /* Wait for specified time interval */
399 udelay(microseconds);
401 return status;
404 static void altera_concatenate_data(u8 *buffer,
405 u8 *preamble_data,
406 u32 preamble_count,
407 u8 *target_data,
408 u32 start_index,
409 u32 target_count,
410 u8 *postamble_data,
411 u32 postamble_count)
413 * Copies preamble data, target data, and postamble data
414 * into one buffer for IR or DR scans.
417 u32 i, j, k;
419 for (i = 0L; i < preamble_count; ++i) {
420 if (preamble_data[i >> 3L] & (1L << (i & 7L)))
421 buffer[i >> 3L] |= (1L << (i & 7L));
422 else
423 buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
427 j = start_index;
428 k = preamble_count + target_count;
429 for (; i < k; ++i, ++j) {
430 if (target_data[j >> 3L] & (1L << (j & 7L)))
431 buffer[i >> 3L] |= (1L << (i & 7L));
432 else
433 buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
437 j = 0L;
438 k = preamble_count + target_count + postamble_count;
439 for (; i < k; ++i, ++j) {
440 if (postamble_data[j >> 3L] & (1L << (j & 7L)))
441 buffer[i >> 3L] |= (1L << (i & 7L));
442 else
443 buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
448 static int alt_jtag_drscan(struct altera_state *astate,
449 int start_state,
450 int count,
451 u8 *tdi,
452 u8 *tdo)
454 int i = 0;
455 int tdo_bit = 0;
456 int status = 1;
458 /* First go to DRSHIFT state */
459 switch (start_state) {
460 case 0: /* IDLE */
461 alt_jtag_io(1, 0, 0); /* DRSELECT */
462 alt_jtag_io(0, 0, 0); /* DRCAPTURE */
463 alt_jtag_io(0, 0, 0); /* DRSHIFT */
464 break;
466 case 1: /* DRPAUSE */
467 alt_jtag_io(1, 0, 0); /* DREXIT2 */
468 alt_jtag_io(1, 0, 0); /* DRUPDATE */
469 alt_jtag_io(1, 0, 0); /* DRSELECT */
470 alt_jtag_io(0, 0, 0); /* DRCAPTURE */
471 alt_jtag_io(0, 0, 0); /* DRSHIFT */
472 break;
474 case 2: /* IRPAUSE */
475 alt_jtag_io(1, 0, 0); /* IREXIT2 */
476 alt_jtag_io(1, 0, 0); /* IRUPDATE */
477 alt_jtag_io(1, 0, 0); /* DRSELECT */
478 alt_jtag_io(0, 0, 0); /* DRCAPTURE */
479 alt_jtag_io(0, 0, 0); /* DRSHIFT */
480 break;
482 default:
483 status = 0;
486 if (status) {
487 /* loop in the SHIFT-DR state */
488 for (i = 0; i < count; i++) {
489 tdo_bit = alt_jtag_io(
490 (i == count - 1),
491 tdi[i >> 3] & (1 << (i & 7)),
492 (tdo != NULL));
494 if (tdo != NULL) {
495 if (tdo_bit)
496 tdo[i >> 3] |= (1 << (i & 7));
497 else
498 tdo[i >> 3] &= ~(u32)(1 << (i & 7));
503 alt_jtag_io(0, 0, 0); /* DRPAUSE */
506 return status;
509 static int alt_jtag_irscan(struct altera_state *astate,
510 int start_state,
511 int count,
512 u8 *tdi,
513 u8 *tdo)
515 int i = 0;
516 int tdo_bit = 0;
517 int status = 1;
519 /* First go to IRSHIFT state */
520 switch (start_state) {
521 case 0: /* IDLE */
522 alt_jtag_io(1, 0, 0); /* DRSELECT */
523 alt_jtag_io(1, 0, 0); /* IRSELECT */
524 alt_jtag_io(0, 0, 0); /* IRCAPTURE */
525 alt_jtag_io(0, 0, 0); /* IRSHIFT */
526 break;
528 case 1: /* DRPAUSE */
529 alt_jtag_io(1, 0, 0); /* DREXIT2 */
530 alt_jtag_io(1, 0, 0); /* DRUPDATE */
531 alt_jtag_io(1, 0, 0); /* DRSELECT */
532 alt_jtag_io(1, 0, 0); /* IRSELECT */
533 alt_jtag_io(0, 0, 0); /* IRCAPTURE */
534 alt_jtag_io(0, 0, 0); /* IRSHIFT */
535 break;
537 case 2: /* IRPAUSE */
538 alt_jtag_io(1, 0, 0); /* IREXIT2 */
539 alt_jtag_io(1, 0, 0); /* IRUPDATE */
540 alt_jtag_io(1, 0, 0); /* DRSELECT */
541 alt_jtag_io(1, 0, 0); /* IRSELECT */
542 alt_jtag_io(0, 0, 0); /* IRCAPTURE */
543 alt_jtag_io(0, 0, 0); /* IRSHIFT */
544 break;
546 default:
547 status = 0;
550 if (status) {
551 /* loop in the SHIFT-IR state */
552 for (i = 0; i < count; i++) {
553 tdo_bit = alt_jtag_io(
554 (i == count - 1),
555 tdi[i >> 3] & (1 << (i & 7)),
556 (tdo != NULL));
557 if (tdo != NULL) {
558 if (tdo_bit)
559 tdo[i >> 3] |= (1 << (i & 7));
560 else
561 tdo[i >> 3] &= ~(u32)(1 << (i & 7));
566 alt_jtag_io(0, 0, 0); /* IRPAUSE */
569 return status;
572 static void altera_extract_target_data(u8 *buffer,
573 u8 *target_data,
574 u32 start_index,
575 u32 preamble_count,
576 u32 target_count)
578 * Copies target data from scan buffer, filtering out
579 * preamble and postamble data.
582 u32 i;
583 u32 j;
584 u32 k;
586 j = preamble_count;
587 k = start_index + target_count;
588 for (i = start_index; i < k; ++i, ++j) {
589 if (buffer[j >> 3] & (1 << (j & 7)))
590 target_data[i >> 3] |= (1 << (i & 7));
591 else
592 target_data[i >> 3] &= ~(u32)(1 << (i & 7));
597 int altera_irscan(struct altera_state *astate,
598 u32 count,
599 u8 *tdi_data,
600 u32 start_index)
601 /* Shifts data into instruction register */
603 struct altera_jtag *js = &astate->js;
604 int start_code = 0;
605 u32 alloc_chars = 0;
606 u32 shift_count = js->ir_pre + count + js->ir_post;
607 int status = 0;
608 enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
610 switch (js->jtag_state) {
611 case ILLEGAL_JTAG_STATE:
612 case RESET:
613 case IDLE:
614 start_code = 0;
615 start_state = IDLE;
616 break;
618 case DRSELECT:
619 case DRCAPTURE:
620 case DRSHIFT:
621 case DREXIT1:
622 case DRPAUSE:
623 case DREXIT2:
624 case DRUPDATE:
625 start_code = 1;
626 start_state = DRPAUSE;
627 break;
629 case IRSELECT:
630 case IRCAPTURE:
631 case IRSHIFT:
632 case IREXIT1:
633 case IRPAUSE:
634 case IREXIT2:
635 case IRUPDATE:
636 start_code = 2;
637 start_state = IRPAUSE;
638 break;
640 default:
641 status = -EREMOTEIO;
642 break;
645 if (status == 0)
646 if (js->jtag_state != start_state)
647 status = altera_goto_jstate(astate, start_state);
649 if (status == 0) {
650 if (shift_count > js->ir_length) {
651 alloc_chars = (shift_count + 7) >> 3;
652 kfree(js->ir_buffer);
653 js->ir_buffer = (u8 *)alt_malloc(alloc_chars);
654 if (js->ir_buffer == NULL)
655 status = -ENOMEM;
656 else
657 js->ir_length = alloc_chars * 8;
662 if (status == 0) {
664 * Copy preamble data, IR data,
665 * and postamble data into a buffer
667 altera_concatenate_data(js->ir_buffer,
668 js->ir_pre_data,
669 js->ir_pre,
670 tdi_data,
671 start_index,
672 count,
673 js->ir_post_data,
674 js->ir_post);
675 /* Do the IRSCAN */
676 alt_jtag_irscan(astate,
677 start_code,
678 shift_count,
679 js->ir_buffer,
680 NULL);
682 /* alt_jtag_irscan() always ends in IRPAUSE state */
683 js->jtag_state = IRPAUSE;
686 if (status == 0)
687 if (js->irstop_state != IRPAUSE)
688 status = altera_goto_jstate(astate, js->irstop_state);
691 return status;
694 int altera_swap_ir(struct altera_state *astate,
695 u32 count,
696 u8 *in_data,
697 u32 in_index,
698 u8 *out_data,
699 u32 out_index)
700 /* Shifts data into instruction register, capturing output data */
702 struct altera_jtag *js = &astate->js;
703 int start_code = 0;
704 u32 alloc_chars = 0;
705 u32 shift_count = js->ir_pre + count + js->ir_post;
706 int status = 0;
707 enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
709 switch (js->jtag_state) {
710 case ILLEGAL_JTAG_STATE:
711 case RESET:
712 case IDLE:
713 start_code = 0;
714 start_state = IDLE;
715 break;
717 case DRSELECT:
718 case DRCAPTURE:
719 case DRSHIFT:
720 case DREXIT1:
721 case DRPAUSE:
722 case DREXIT2:
723 case DRUPDATE:
724 start_code = 1;
725 start_state = DRPAUSE;
726 break;
728 case IRSELECT:
729 case IRCAPTURE:
730 case IRSHIFT:
731 case IREXIT1:
732 case IRPAUSE:
733 case IREXIT2:
734 case IRUPDATE:
735 start_code = 2;
736 start_state = IRPAUSE;
737 break;
739 default:
740 status = -EREMOTEIO;
741 break;
744 if (status == 0)
745 if (js->jtag_state != start_state)
746 status = altera_goto_jstate(astate, start_state);
748 if (status == 0) {
749 if (shift_count > js->ir_length) {
750 alloc_chars = (shift_count + 7) >> 3;
751 kfree(js->ir_buffer);
752 js->ir_buffer = (u8 *)alt_malloc(alloc_chars);
753 if (js->ir_buffer == NULL)
754 status = -ENOMEM;
755 else
756 js->ir_length = alloc_chars * 8;
761 if (status == 0) {
763 * Copy preamble data, IR data,
764 * and postamble data into a buffer
766 altera_concatenate_data(js->ir_buffer,
767 js->ir_pre_data,
768 js->ir_pre,
769 in_data,
770 in_index,
771 count,
772 js->ir_post_data,
773 js->ir_post);
775 /* Do the IRSCAN */
776 alt_jtag_irscan(astate,
777 start_code,
778 shift_count,
779 js->ir_buffer,
780 js->ir_buffer);
782 /* alt_jtag_irscan() always ends in IRPAUSE state */
783 js->jtag_state = IRPAUSE;
786 if (status == 0)
787 if (js->irstop_state != IRPAUSE)
788 status = altera_goto_jstate(astate, js->irstop_state);
791 if (status == 0)
792 /* Now extract the returned data from the buffer */
793 altera_extract_target_data(js->ir_buffer,
794 out_data, out_index,
795 js->ir_pre, count);
797 return status;
800 int altera_drscan(struct altera_state *astate,
801 u32 count,
802 u8 *tdi_data,
803 u32 start_index)
804 /* Shifts data into data register (ignoring output data) */
806 struct altera_jtag *js = &astate->js;
807 int start_code = 0;
808 u32 alloc_chars = 0;
809 u32 shift_count = js->dr_pre + count + js->dr_post;
810 int status = 0;
811 enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
813 switch (js->jtag_state) {
814 case ILLEGAL_JTAG_STATE:
815 case RESET:
816 case IDLE:
817 start_code = 0;
818 start_state = IDLE;
819 break;
821 case DRSELECT:
822 case DRCAPTURE:
823 case DRSHIFT:
824 case DREXIT1:
825 case DRPAUSE:
826 case DREXIT2:
827 case DRUPDATE:
828 start_code = 1;
829 start_state = DRPAUSE;
830 break;
832 case IRSELECT:
833 case IRCAPTURE:
834 case IRSHIFT:
835 case IREXIT1:
836 case IRPAUSE:
837 case IREXIT2:
838 case IRUPDATE:
839 start_code = 2;
840 start_state = IRPAUSE;
841 break;
843 default:
844 status = -EREMOTEIO;
845 break;
848 if (status == 0)
849 if (js->jtag_state != start_state)
850 status = altera_goto_jstate(astate, start_state);
852 if (status == 0) {
853 if (shift_count > js->dr_length) {
854 alloc_chars = (shift_count + 7) >> 3;
855 kfree(js->dr_buffer);
856 js->dr_buffer = (u8 *)alt_malloc(alloc_chars);
857 if (js->dr_buffer == NULL)
858 status = -ENOMEM;
859 else
860 js->dr_length = alloc_chars * 8;
865 if (status == 0) {
867 * Copy preamble data, DR data,
868 * and postamble data into a buffer
870 altera_concatenate_data(js->dr_buffer,
871 js->dr_pre_data,
872 js->dr_pre,
873 tdi_data,
874 start_index,
875 count,
876 js->dr_post_data,
877 js->dr_post);
878 /* Do the DRSCAN */
879 alt_jtag_drscan(astate, start_code, shift_count,
880 js->dr_buffer, NULL);
881 /* alt_jtag_drscan() always ends in DRPAUSE state */
882 js->jtag_state = DRPAUSE;
885 if (status == 0)
886 if (js->drstop_state != DRPAUSE)
887 status = altera_goto_jstate(astate, js->drstop_state);
889 return status;
892 int altera_swap_dr(struct altera_state *astate, u32 count,
893 u8 *in_data, u32 in_index,
894 u8 *out_data, u32 out_index)
895 /* Shifts data into data register, capturing output data */
897 struct altera_jtag *js = &astate->js;
898 int start_code = 0;
899 u32 alloc_chars = 0;
900 u32 shift_count = js->dr_pre + count + js->dr_post;
901 int status = 0;
902 enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
904 switch (js->jtag_state) {
905 case ILLEGAL_JTAG_STATE:
906 case RESET:
907 case IDLE:
908 start_code = 0;
909 start_state = IDLE;
910 break;
912 case DRSELECT:
913 case DRCAPTURE:
914 case DRSHIFT:
915 case DREXIT1:
916 case DRPAUSE:
917 case DREXIT2:
918 case DRUPDATE:
919 start_code = 1;
920 start_state = DRPAUSE;
921 break;
923 case IRSELECT:
924 case IRCAPTURE:
925 case IRSHIFT:
926 case IREXIT1:
927 case IRPAUSE:
928 case IREXIT2:
929 case IRUPDATE:
930 start_code = 2;
931 start_state = IRPAUSE;
932 break;
934 default:
935 status = -EREMOTEIO;
936 break;
939 if (status == 0)
940 if (js->jtag_state != start_state)
941 status = altera_goto_jstate(astate, start_state);
943 if (status == 0) {
944 if (shift_count > js->dr_length) {
945 alloc_chars = (shift_count + 7) >> 3;
946 kfree(js->dr_buffer);
947 js->dr_buffer = (u8 *)alt_malloc(alloc_chars);
949 if (js->dr_buffer == NULL)
950 status = -ENOMEM;
951 else
952 js->dr_length = alloc_chars * 8;
957 if (status == 0) {
959 * Copy preamble data, DR data,
960 * and postamble data into a buffer
962 altera_concatenate_data(js->dr_buffer,
963 js->dr_pre_data,
964 js->dr_pre,
965 in_data,
966 in_index,
967 count,
968 js->dr_post_data,
969 js->dr_post);
971 /* Do the DRSCAN */
972 alt_jtag_drscan(astate,
973 start_code,
974 shift_count,
975 js->dr_buffer,
976 js->dr_buffer);
978 /* alt_jtag_drscan() always ends in DRPAUSE state */
979 js->jtag_state = DRPAUSE;
982 if (status == 0)
983 if (js->drstop_state != DRPAUSE)
984 status = altera_goto_jstate(astate, js->drstop_state);
986 if (status == 0)
987 /* Now extract the returned data from the buffer */
988 altera_extract_target_data(js->dr_buffer,
989 out_data,
990 out_index,
991 js->dr_pre,
992 count);
994 return status;
997 void altera_free_buffers(struct altera_state *astate)
999 struct altera_jtag *js = &astate->js;
1000 /* If the JTAG interface was used, reset it to TLR */
1001 if (js->jtag_state != ILLEGAL_JTAG_STATE)
1002 altera_jreset_idle(astate);
1004 kfree(js->dr_pre_data);
1005 js->dr_pre_data = NULL;
1007 kfree(js->dr_post_data);
1008 js->dr_post_data = NULL;
1010 kfree(js->dr_buffer);
1011 js->dr_buffer = NULL;
1013 kfree(js->ir_pre_data);
1014 js->ir_pre_data = NULL;
1016 kfree(js->ir_post_data);
1017 js->ir_post_data = NULL;
1019 kfree(js->ir_buffer);
1020 js->ir_buffer = NULL;