Merge remote-tracking branches 'spi/fix/gqspi', 'spi/fix/imx', 'spi/fix/mg-spfi'...
[linux-2.6-block.git] / drivers / misc / altera-stapl / altera-jtag.c
CommitLineData
fa766c9b
IL
1/*
2 * altera-jtag.c
3 *
4 * altera FPGA driver
5 *
6 * Copyright (C) Altera Corporation 1998-2001
7 * Copyright (C) 2010 NetUP Inc.
8 * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru>
9 *
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.
14 *
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
18 *
19 * GNU General Public License for more details.
20 *
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.
24 */
25
92ce5269 26#include <linux/delay.h>
fa766c9b
IL
27#include <linux/firmware.h>
28#include <linux/slab.h>
cff4fa84 29#include <misc/altera.h>
fa766c9b
IL
30#include "altera-exprt.h"
31#include "altera-jtag.h"
32
33#define alt_jtag_io(a, b, c)\
34 astate->config->jtag_io(astate->config->dev, a, b, c);
35
36#define alt_malloc(a) kzalloc(a, GFP_KERNEL);
37
38/*
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.
42 */
43struct altera_jtag_machine {
44 enum altera_jtag_state tms_high;
45 enum altera_jtag_state tms_low;
46};
47
48static 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 }
65};
66
67/*
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.
73 */
74static 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
79};
80
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
88
89int altera_jinit(struct altera_state *astate)
90{
91 struct altera_jtag *js = &astate->js;
92
93 /* initial JTAG state is unknown */
94 js->jtag_state = ILLEGAL_JTAG_STATE;
95
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;
105
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;
112
113 return 0;
114}
115
116int altera_set_drstop(struct altera_jtag *js, enum altera_jtag_state state)
117{
118 js->drstop_state = state;
119
120 return 0;
121}
122
123int altera_set_irstop(struct altera_jtag *js, enum altera_jtag_state state)
124{
125 js->irstop_state = state;
126
127 return 0;
128}
129
130int altera_set_dr_pre(struct altera_jtag *js,
131 u32 count, u32 start_index,
132 u8 *preamble_data)
133{
134 int status = 0;
135 u32 i;
136 u32 j;
137
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;
147
148 if (status == 0) {
149 for (i = 0; i < count; ++i) {
150 j = i + start_index;
151
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));
161
162 }
163 }
164 }
165
166 return status;
167}
168
169int altera_set_ir_pre(struct altera_jtag *js, u32 count, u32 start_index,
170 u8 *preamble_data)
171{
172 int status = 0;
173 u32 i;
174 u32 j;
175
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;
183
184 } else
185 js->ir_pre = count;
186
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));
199
200 }
201 }
202 }
203
204 return status;
205}
206
207int altera_set_dr_post(struct altera_jtag *js, u32 count, u32 start_index,
208 u8 *postamble_data)
209{
210 int status = 0;
211 u32 i;
212 u32 j;
213
214 if (count > js->dr_post) {
215 kfree(js->dr_post_data);
216 js->dr_post_data = (u8 *)alt_malloc((count + 7) >> 3);
217
218 if (js->dr_post_data == NULL)
219 status = -ENOMEM;
220 else
221 js->dr_post = count;
222
223 } else
224 js->dr_post = count;
225
226 if (status == 0) {
227 for (i = 0; i < count; ++i) {
228 j = i + start_index;
229
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));
239
240 }
241 }
242 }
243
244 return status;
245}
246
247int altera_set_ir_post(struct altera_jtag *js, u32 count, u32 start_index,
248 u8 *postamble_data)
249{
250 int status = 0;
251 u32 i;
252 u32 j;
253
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;
261
262 } else
263 js->ir_post = count;
264
265 if (status != 0)
266 return status;
267
268 for (i = 0; i < count; ++i) {
269 j = i + start_index;
270
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));
279
280 }
281 }
282
283 return status;
284}
285
286static void altera_jreset_idle(struct altera_state *astate)
287{
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);
293
294 /* Now step to Run Test / Idle */
295 alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO);
296 js->jtag_state = IDLE;
297}
298
299int altera_goto_jstate(struct altera_state *astate,
300 enum altera_jtag_state state)
301{
302 struct altera_jtag *js = &astate->js;
303 int tms;
304 int count = 0;
305 int status = 0;
306
307 if (js->jtag_state == ILLEGAL_JTAG_STATE)
308 /* initialize JTAG chain to known state */
309 altera_jreset_idle(astate);
310
311 if (js->jtag_state == state) {
312 /*
313 * We are already in the desired state.
314 * If it is a stable state, loop here.
315 * Otherwise do nothing (no clock cycles).
316 */
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);
323
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;
330
331 /* Take a step */
332 alt_jtag_io(tms, TDI_LOW, IGNORE_TDO);
333
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;
340
341 ++count;
342 }
343 }
344
345 if (js->jtag_state != state)
346 status = -EREMOTEIO;
347
348 return status;
349}
350
351int altera_wait_cycles(struct altera_state *astate,
352 s32 cycles,
353 enum altera_jtag_state wait_state)
354{
355 struct altera_jtag *js = &astate->js;
356 int tms;
357 s32 count;
358 int status = 0;
359
360 if (js->jtag_state != wait_state)
361 status = altera_goto_jstate(astate, wait_state);
362
363 if (status == 0) {
364 /*
365 * Set TMS high to loop in RESET state
366 * Set TMS low to loop in any other stable state
367 */
368 tms = (wait_state == RESET) ? TMS_HIGH : TMS_LOW;
369
370 for (count = 0L; count < cycles; count++)
371 alt_jtag_io(tms, TDI_LOW, IGNORE_TDO);
372
373 }
374
375 return status;
376}
377
378int altera_wait_msecs(struct altera_state *astate,
379 s32 microseconds, enum altera_jtag_state wait_state)
380/*
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.
388 */
389{
390 struct altera_jtag *js = &astate->js;
391 int status = 0;
392
393 if ((js->jtag_state != ILLEGAL_JTAG_STATE) &&
394 (js->jtag_state != wait_state))
395 status = altera_goto_jstate(astate, wait_state);
396
397 if (status == 0)
398 /* Wait for specified time interval */
399 udelay(microseconds);
400
401 return status;
402}
403
404static 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)
412/*
413 * Copies preamble data, target data, and postamble data
414 * into one buffer for IR or DR scans.
415 */
416{
417 u32 i, j, k;
418
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));
424
425 }
426
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));
434
435 }
436
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));
444
445 }
446}
447
448static int alt_jtag_drscan(struct altera_state *astate,
449 int start_state,
450 int count,
451 u8 *tdi,
452 u8 *tdo)
453{
454 int i = 0;
455 int tdo_bit = 0;
456 int status = 1;
457
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;
465
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;
473
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;
481
482 default:
483 status = 0;
484 }
485
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));
493
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));
499
500 }
501 }
502
503 alt_jtag_io(0, 0, 0); /* DRPAUSE */
504 }
505
506 return status;
507}
508
509static int alt_jtag_irscan(struct altera_state *astate,
510 int start_state,
511 int count,
512 u8 *tdi,
513 u8 *tdo)
514{
515 int i = 0;
516 int tdo_bit = 0;
517 int status = 1;
518
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;
527
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;
536
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;
545
546 default:
547 status = 0;
548 }
549
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));
562
563 }
564 }
565
566 alt_jtag_io(0, 0, 0); /* IRPAUSE */
567 }
568
569 return status;
570}
571
572static void altera_extract_target_data(u8 *buffer,
573 u8 *target_data,
574 u32 start_index,
575 u32 preamble_count,
576 u32 target_count)
577/*
578 * Copies target data from scan buffer, filtering out
579 * preamble and postamble data.
580 */
581{
582 u32 i;
583 u32 j;
584 u32 k;
585
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));
593
594 }
595}
596
597int altera_irscan(struct altera_state *astate,
598 u32 count,
599 u8 *tdi_data,
600 u32 start_index)
601/* Shifts data into instruction register */
602{
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;
609
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;
617
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;
628
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;
639
640 default:
641 status = -EREMOTEIO;
642 break;
643 }
644
645 if (status == 0)
646 if (js->jtag_state != start_state)
647 status = altera_goto_jstate(astate, start_state);
648
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;
658
659 }
660 }
661
662 if (status == 0) {
663 /*
664 * Copy preamble data, IR data,
665 * and postamble data into a buffer
666 */
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);
681
682 /* alt_jtag_irscan() always ends in IRPAUSE state */
683 js->jtag_state = IRPAUSE;
684 }
685
686 if (status == 0)
687 if (js->irstop_state != IRPAUSE)
688 status = altera_goto_jstate(astate, js->irstop_state);
689
690
691 return status;
692}
693
694int 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 */
701{
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;
708
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;
716
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;
727
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;
738
739 default:
740 status = -EREMOTEIO;
741 break;
742 }
743
744 if (status == 0)
745 if (js->jtag_state != start_state)
746 status = altera_goto_jstate(astate, start_state);
747
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;
757
758 }
759 }
760
761 if (status == 0) {
762 /*
763 * Copy preamble data, IR data,
764 * and postamble data into a buffer
765 */
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);
774
775 /* Do the IRSCAN */
776 alt_jtag_irscan(astate,
777 start_code,
778 shift_count,
779 js->ir_buffer,
780 js->ir_buffer);
781
782 /* alt_jtag_irscan() always ends in IRPAUSE state */
783 js->jtag_state = IRPAUSE;
784 }
785
786 if (status == 0)
787 if (js->irstop_state != IRPAUSE)
788 status = altera_goto_jstate(astate, js->irstop_state);
789
790
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);
796
797 return status;
798}
799
800int 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) */
805{
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;
812
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;
820
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;
831
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;
842
843 default:
844 status = -EREMOTEIO;
845 break;
846 }
847
848 if (status == 0)
849 if (js->jtag_state != start_state)
850 status = altera_goto_jstate(astate, start_state);
851
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;
861
862 }
863 }
864
865 if (status == 0) {
866 /*
867 * Copy preamble data, DR data,
868 * and postamble data into a buffer
869 */
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;
883 }
884
885 if (status == 0)
886 if (js->drstop_state != DRPAUSE)
887 status = altera_goto_jstate(astate, js->drstop_state);
888
889 return status;
890}
891
892int 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 */
896{
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;
903
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;
911
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;
922
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;
933
934 default:
935 status = -EREMOTEIO;
936 break;
937 }
938
939 if (status == 0)
940 if (js->jtag_state != start_state)
941 status = altera_goto_jstate(astate, start_state);
942
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);
948
949 if (js->dr_buffer == NULL)
950 status = -ENOMEM;
951 else
952 js->dr_length = alloc_chars * 8;
953
954 }
955 }
956
957 if (status == 0) {
958 /*
959 * Copy preamble data, DR data,
960 * and postamble data into a buffer
961 */
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);
970
971 /* Do the DRSCAN */
972 alt_jtag_drscan(astate,
973 start_code,
974 shift_count,
975 js->dr_buffer,
976 js->dr_buffer);
977
978 /* alt_jtag_drscan() always ends in DRPAUSE state */
979 js->jtag_state = DRPAUSE;
980 }
981
982 if (status == 0)
983 if (js->drstop_state != DRPAUSE)
984 status = altera_goto_jstate(astate, js->drstop_state);
985
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);
993
994 return status;
995}
996
997void altera_free_buffers(struct altera_state *astate)
998{
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);
1003
1004 kfree(js->dr_pre_data);
1005 js->dr_pre_data = NULL;
1006
1007 kfree(js->dr_post_data);
1008 js->dr_post_data = NULL;
1009
1010 kfree(js->dr_buffer);
1011 js->dr_buffer = NULL;
1012
1013 kfree(js->ir_pre_data);
1014 js->ir_pre_data = NULL;
1015
1016 kfree(js->ir_post_data);
1017 js->ir_post_data = NULL;
1018
1019 kfree(js->ir_buffer);
1020 js->ir_buffer = NULL;
1021}