1008 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * altera-jtag.c4 *5 * altera FPGA driver6 *7 * Copyright (C) Altera Corporation 1998-20018 * 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 after26 * a single TCK clock cycle with TMS high or TMS low, respectively. This27 * 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 on55 * 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 state57 * is used as the intermediate state, look up the TMS value in the58 * 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, 0x7FFD65};66 67/* Flag bits for alt_jtag_io() function */68#define TMS_HIGH 169#define TMS_LOW 070#define TDI_HIGH 171#define TDI_LOW 072#define READ_TDO 173#define IGNORE_TDO 074 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(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 else130 js->dr_pre = count;131 } else132 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 else145 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(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 else168 js->ir_pre = count;169 170 } else171 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 else183 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(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 else207 js->dr_post = count;208 209 } else210 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 else223 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(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 else246 js->ir_post = count;247 248 } else249 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 else263 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 else324 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, wait_state);348 349 if (status == 0) {350 /*351 * Set TMS high to loop in RESET state352 * Set TMS low to loop in any other stable state353 */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 stable368 * state for the specified duration of real time. If369 * no JTAG operations have been performed yet, then only370 * a delay is performed. This permits the WAIT USECS371 * statement to be used in VECTOR programs without causing372 * 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, 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 data400 * 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 else409 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 else419 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 else429 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 else484 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 else547 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 out565 * 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 else578 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, start_state);634 635 if (status == 0) {636 if (shift_count > js->ir_length) {637 alloc_chars = (shift_count + 7) >> 3;638 kfree(js->ir_buffer);639 js->ir_buffer = (u8 *)alt_malloc(alloc_chars);640 if (js->ir_buffer == NULL)641 status = -ENOMEM;642 else643 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 buffer652 */653 altera_concatenate_data(js->ir_buffer,654 js->ir_pre_data,655 js->ir_pre,656 tdi_data,657 start_index,658 count,659 js->ir_post_data,660 js->ir_post);661 /* Do the IRSCAN */662 alt_jtag_irscan(astate,663 start_code,664 shift_count,665 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, 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, start_state);733 734 if (status == 0) {735 if (shift_count > js->ir_length) {736 alloc_chars = (shift_count + 7) >> 3;737 kfree(js->ir_buffer);738 js->ir_buffer = (u8 *)alt_malloc(alloc_chars);739 if (js->ir_buffer == NULL)740 status = -ENOMEM;741 else742 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 buffer751 */752 altera_concatenate_data(js->ir_buffer,753 js->ir_pre_data,754 js->ir_pre,755 in_data,756 in_index,757 count,758 js->ir_post_data,759 js->ir_post);760 761 /* Do the IRSCAN */762 alt_jtag_irscan(astate,763 start_code,764 shift_count,765 js->ir_buffer,766 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, js->irstop_state);775 776 777 if (status == 0)778 /* Now extract the returned data from the buffer */779 altera_extract_target_data(js->ir_buffer,780 out_data, out_index,781 js->ir_pre, 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, start_state);837 838 if (status == 0) {839 if (shift_count > js->dr_length) {840 alloc_chars = (shift_count + 7) >> 3;841 kfree(js->dr_buffer);842 js->dr_buffer = (u8 *)alt_malloc(alloc_chars);843 if (js->dr_buffer == NULL)844 status = -ENOMEM;845 else846 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 buffer855 */856 altera_concatenate_data(js->dr_buffer,857 js->dr_pre_data,858 js->dr_pre,859 tdi_data,860 start_index,861 count,862 js->dr_post_data,863 js->dr_post);864 /* Do the DRSCAN */865 alt_jtag_drscan(astate, start_code, shift_count,866 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, 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, start_state);928 929 if (status == 0) {930 if (shift_count > js->dr_length) {931 alloc_chars = (shift_count + 7) >> 3;932 kfree(js->dr_buffer);933 js->dr_buffer = (u8 *)alt_malloc(alloc_chars);934 935 if (js->dr_buffer == NULL)936 status = -ENOMEM;937 else938 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 buffer947 */948 altera_concatenate_data(js->dr_buffer,949 js->dr_pre_data,950 js->dr_pre,951 in_data,952 in_index,953 count,954 js->dr_post_data,955 js->dr_post);956 957 /* Do the DRSCAN */958 alt_jtag_drscan(astate,959 start_code,960 shift_count,961 js->dr_buffer,962 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, js->drstop_state);971 972 if (status == 0)973 /* Now extract the returned data from the buffer */974 altera_extract_target_data(js->dr_buffer,975 out_data,976 out_index,977 js->dr_pre,978 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(js->dr_pre_data);991 js->dr_pre_data = NULL;992 993 kfree(js->dr_post_data);994 js->dr_post_data = NULL;995 996 kfree(js->dr_buffer);997 js->dr_buffer = NULL;998 999 kfree(js->ir_pre_data);1000 js->ir_pre_data = NULL;1001 1002 kfree(js->ir_post_data);1003 js->ir_post_data = NULL;1004 1005 kfree(js->ir_buffer);1006 js->ir_buffer = NULL;1007}1008