1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021 |
- /*
- * altera-jtag.c
- *
- * altera FPGA driver
- *
- * Copyright (C) Altera Corporation 1998-2001
- * Copyright (C) 2010 NetUP Inc.
- * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- *
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #include <linux/delay.h>
- #include <linux/firmware.h>
- #include <linux/slab.h>
- #include <misc/altera.h>
- #include "altera-exprt.h"
- #include "altera-jtag.h"
- #define alt_jtag_io(a, b, c)\
- astate->config->jtag_io(astate->config->dev, a, b, c);
- #define alt_malloc(a) kzalloc(a, GFP_KERNEL);
- /*
- * This structure shows, for each JTAG state, which state is reached after
- * a single TCK clock cycle with TMS high or TMS low, respectively. This
- * describes all possible state transitions in the JTAG state machine.
- */
- struct altera_jtag_machine {
- enum altera_jtag_state tms_high;
- enum altera_jtag_state tms_low;
- };
- static const struct altera_jtag_machine altera_transitions[] = {
- /* RESET */ { RESET, IDLE },
- /* IDLE */ { DRSELECT, IDLE },
- /* DRSELECT */ { IRSELECT, DRCAPTURE },
- /* DRCAPTURE */ { DREXIT1, DRSHIFT },
- /* DRSHIFT */ { DREXIT1, DRSHIFT },
- /* DREXIT1 */ { DRUPDATE, DRPAUSE },
- /* DRPAUSE */ { DREXIT2, DRPAUSE },
- /* DREXIT2 */ { DRUPDATE, DRSHIFT },
- /* DRUPDATE */ { DRSELECT, IDLE },
- /* IRSELECT */ { RESET, IRCAPTURE },
- /* IRCAPTURE */ { IREXIT1, IRSHIFT },
- /* IRSHIFT */ { IREXIT1, IRSHIFT },
- /* IREXIT1 */ { IRUPDATE, IRPAUSE },
- /* IRPAUSE */ { IREXIT2, IRPAUSE },
- /* IREXIT2 */ { IRUPDATE, IRSHIFT },
- /* IRUPDATE */ { DRSELECT, IDLE }
- };
- /*
- * This table contains the TMS value to be used to take the NEXT STEP on
- * the path to the desired state. The array index is the current state,
- * and the bit position is the desired endstate. To find out which state
- * is used as the intermediate state, look up the TMS value in the
- * altera_transitions[] table.
- */
- static const u16 altera_jtag_path_map[16] = {
- /* RST RTI SDRS CDR SDR E1DR PDR E2DR */
- 0x0001, 0xFFFD, 0xFE01, 0xFFE7, 0xFFEF, 0xFF0F, 0xFFBF, 0xFFFF,
- /* UDR SIRS CIR SIR E1IR PIR E2IR UIR */
- 0xFEFD, 0x0001, 0xF3FF, 0xF7FF, 0x87FF, 0xDFFF, 0xFFFF, 0x7FFD
- };
- /* Flag bits for alt_jtag_io() function */
- #define TMS_HIGH 1
- #define TMS_LOW 0
- #define TDI_HIGH 1
- #define TDI_LOW 0
- #define READ_TDO 1
- #define IGNORE_TDO 0
- int altera_jinit(struct altera_state *astate)
- {
- struct altera_jtag *js = &astate->js;
- /* initial JTAG state is unknown */
- js->jtag_state = ILLEGAL_JTAG_STATE;
- /* initialize to default state */
- js->drstop_state = IDLE;
- js->irstop_state = IDLE;
- js->dr_pre = 0;
- js->dr_post = 0;
- js->ir_pre = 0;
- js->ir_post = 0;
- js->dr_length = 0;
- js->ir_length = 0;
- js->dr_pre_data = NULL;
- js->dr_post_data = NULL;
- js->ir_pre_data = NULL;
- js->ir_post_data = NULL;
- js->dr_buffer = NULL;
- js->ir_buffer = NULL;
- return 0;
- }
- int altera_set_drstop(struct altera_jtag *js, enum altera_jtag_state state)
- {
- js->drstop_state = state;
- return 0;
- }
- int altera_set_irstop(struct altera_jtag *js, enum altera_jtag_state state)
- {
- js->irstop_state = state;
- return 0;
- }
- int altera_set_dr_pre(struct altera_jtag *js,
- u32 count, u32 start_index,
- u8 *preamble_data)
- {
- int status = 0;
- u32 i;
- u32 j;
- if (count > js->dr_pre) {
- kfree(js->dr_pre_data);
- js->dr_pre_data = (u8 *)alt_malloc((count + 7) >> 3);
- if (js->dr_pre_data == NULL)
- status = -ENOMEM;
- else
- js->dr_pre = count;
- } else
- js->dr_pre = count;
- if (status == 0) {
- for (i = 0; i < count; ++i) {
- j = i + start_index;
- if (preamble_data == NULL)
- js->dr_pre_data[i >> 3] |= (1 << (i & 7));
- else {
- if (preamble_data[j >> 3] & (1 << (j & 7)))
- js->dr_pre_data[i >> 3] |=
- (1 << (i & 7));
- else
- js->dr_pre_data[i >> 3] &=
- ~(u32)(1 << (i & 7));
- }
- }
- }
- return status;
- }
- int altera_set_ir_pre(struct altera_jtag *js, u32 count, u32 start_index,
- u8 *preamble_data)
- {
- int status = 0;
- u32 i;
- u32 j;
- if (count > js->ir_pre) {
- kfree(js->ir_pre_data);
- js->ir_pre_data = (u8 *)alt_malloc((count + 7) >> 3);
- if (js->ir_pre_data == NULL)
- status = -ENOMEM;
- else
- js->ir_pre = count;
- } else
- js->ir_pre = count;
- if (status == 0) {
- for (i = 0; i < count; ++i) {
- j = i + start_index;
- if (preamble_data == NULL)
- js->ir_pre_data[i >> 3] |= (1 << (i & 7));
- else {
- if (preamble_data[j >> 3] & (1 << (j & 7)))
- js->ir_pre_data[i >> 3] |=
- (1 << (i & 7));
- else
- js->ir_pre_data[i >> 3] &=
- ~(u32)(1 << (i & 7));
- }
- }
- }
- return status;
- }
- int altera_set_dr_post(struct altera_jtag *js, u32 count, u32 start_index,
- u8 *postamble_data)
- {
- int status = 0;
- u32 i;
- u32 j;
- if (count > js->dr_post) {
- kfree(js->dr_post_data);
- js->dr_post_data = (u8 *)alt_malloc((count + 7) >> 3);
- if (js->dr_post_data == NULL)
- status = -ENOMEM;
- else
- js->dr_post = count;
- } else
- js->dr_post = count;
- if (status == 0) {
- for (i = 0; i < count; ++i) {
- j = i + start_index;
- if (postamble_data == NULL)
- js->dr_post_data[i >> 3] |= (1 << (i & 7));
- else {
- if (postamble_data[j >> 3] & (1 << (j & 7)))
- js->dr_post_data[i >> 3] |=
- (1 << (i & 7));
- else
- js->dr_post_data[i >> 3] &=
- ~(u32)(1 << (i & 7));
- }
- }
- }
- return status;
- }
- int altera_set_ir_post(struct altera_jtag *js, u32 count, u32 start_index,
- u8 *postamble_data)
- {
- int status = 0;
- u32 i;
- u32 j;
- if (count > js->ir_post) {
- kfree(js->ir_post_data);
- js->ir_post_data = (u8 *)alt_malloc((count + 7) >> 3);
- if (js->ir_post_data == NULL)
- status = -ENOMEM;
- else
- js->ir_post = count;
- } else
- js->ir_post = count;
- if (status != 0)
- return status;
- for (i = 0; i < count; ++i) {
- j = i + start_index;
- if (postamble_data == NULL)
- js->ir_post_data[i >> 3] |= (1 << (i & 7));
- else {
- if (postamble_data[j >> 3] & (1 << (j & 7)))
- js->ir_post_data[i >> 3] |= (1 << (i & 7));
- else
- js->ir_post_data[i >> 3] &=
- ~(u32)(1 << (i & 7));
- }
- }
- return status;
- }
- static void altera_jreset_idle(struct altera_state *astate)
- {
- struct altera_jtag *js = &astate->js;
- int i;
- /* Go to Test Logic Reset (no matter what the starting state may be) */
- for (i = 0; i < 5; ++i)
- alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO);
- /* Now step to Run Test / Idle */
- alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO);
- js->jtag_state = IDLE;
- }
- int altera_goto_jstate(struct altera_state *astate,
- enum altera_jtag_state state)
- {
- struct altera_jtag *js = &astate->js;
- int tms;
- int count = 0;
- int status = 0;
- if (js->jtag_state == ILLEGAL_JTAG_STATE)
- /* initialize JTAG chain to known state */
- altera_jreset_idle(astate);
- if (js->jtag_state == state) {
- /*
- * We are already in the desired state.
- * If it is a stable state, loop here.
- * Otherwise do nothing (no clock cycles).
- */
- if ((state == IDLE) || (state == DRSHIFT) ||
- (state == DRPAUSE) || (state == IRSHIFT) ||
- (state == IRPAUSE)) {
- alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO);
- } else if (state == RESET)
- alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO);
- } else {
- while ((js->jtag_state != state) && (count < 9)) {
- /* Get TMS value to take a step toward desired state */
- tms = (altera_jtag_path_map[js->jtag_state] &
- (1 << state))
- ? TMS_HIGH : TMS_LOW;
- /* Take a step */
- alt_jtag_io(tms, TDI_LOW, IGNORE_TDO);
- if (tms)
- js->jtag_state =
- altera_transitions[js->jtag_state].tms_high;
- else
- js->jtag_state =
- altera_transitions[js->jtag_state].tms_low;
- ++count;
- }
- }
- if (js->jtag_state != state)
- status = -EREMOTEIO;
- return status;
- }
- int altera_wait_cycles(struct altera_state *astate,
- s32 cycles,
- enum altera_jtag_state wait_state)
- {
- struct altera_jtag *js = &astate->js;
- int tms;
- s32 count;
- int status = 0;
- if (js->jtag_state != wait_state)
- status = altera_goto_jstate(astate, wait_state);
- if (status == 0) {
- /*
- * Set TMS high to loop in RESET state
- * Set TMS low to loop in any other stable state
- */
- tms = (wait_state == RESET) ? TMS_HIGH : TMS_LOW;
- for (count = 0L; count < cycles; count++)
- alt_jtag_io(tms, TDI_LOW, IGNORE_TDO);
- }
- return status;
- }
- int altera_wait_msecs(struct altera_state *astate,
- s32 microseconds, enum altera_jtag_state wait_state)
- /*
- * Causes JTAG hardware to sit in the specified stable
- * state for the specified duration of real time. If
- * no JTAG operations have been performed yet, then only
- * a delay is performed. This permits the WAIT USECS
- * statement to be used in VECTOR programs without causing
- * any JTAG operations.
- * Returns 0 for success, else appropriate error code.
- */
- {
- struct altera_jtag *js = &astate->js;
- int status = 0;
- if ((js->jtag_state != ILLEGAL_JTAG_STATE) &&
- (js->jtag_state != wait_state))
- status = altera_goto_jstate(astate, wait_state);
- if (status == 0)
- /* Wait for specified time interval */
- udelay(microseconds);
- return status;
- }
- static void altera_concatenate_data(u8 *buffer,
- u8 *preamble_data,
- u32 preamble_count,
- u8 *target_data,
- u32 start_index,
- u32 target_count,
- u8 *postamble_data,
- u32 postamble_count)
- /*
- * Copies preamble data, target data, and postamble data
- * into one buffer for IR or DR scans.
- */
- {
- u32 i, j, k;
- for (i = 0L; i < preamble_count; ++i) {
- if (preamble_data[i >> 3L] & (1L << (i & 7L)))
- buffer[i >> 3L] |= (1L << (i & 7L));
- else
- buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
- }
- j = start_index;
- k = preamble_count + target_count;
- for (; i < k; ++i, ++j) {
- if (target_data[j >> 3L] & (1L << (j & 7L)))
- buffer[i >> 3L] |= (1L << (i & 7L));
- else
- buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
- }
- j = 0L;
- k = preamble_count + target_count + postamble_count;
- for (; i < k; ++i, ++j) {
- if (postamble_data[j >> 3L] & (1L << (j & 7L)))
- buffer[i >> 3L] |= (1L << (i & 7L));
- else
- buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
- }
- }
- static int alt_jtag_drscan(struct altera_state *astate,
- int start_state,
- int count,
- u8 *tdi,
- u8 *tdo)
- {
- int i = 0;
- int tdo_bit = 0;
- int status = 1;
- /* First go to DRSHIFT state */
- switch (start_state) {
- case 0: /* IDLE */
- alt_jtag_io(1, 0, 0); /* DRSELECT */
- alt_jtag_io(0, 0, 0); /* DRCAPTURE */
- alt_jtag_io(0, 0, 0); /* DRSHIFT */
- break;
- case 1: /* DRPAUSE */
- alt_jtag_io(1, 0, 0); /* DREXIT2 */
- alt_jtag_io(1, 0, 0); /* DRUPDATE */
- alt_jtag_io(1, 0, 0); /* DRSELECT */
- alt_jtag_io(0, 0, 0); /* DRCAPTURE */
- alt_jtag_io(0, 0, 0); /* DRSHIFT */
- break;
- case 2: /* IRPAUSE */
- alt_jtag_io(1, 0, 0); /* IREXIT2 */
- alt_jtag_io(1, 0, 0); /* IRUPDATE */
- alt_jtag_io(1, 0, 0); /* DRSELECT */
- alt_jtag_io(0, 0, 0); /* DRCAPTURE */
- alt_jtag_io(0, 0, 0); /* DRSHIFT */
- break;
- default:
- status = 0;
- }
- if (status) {
- /* loop in the SHIFT-DR state */
- for (i = 0; i < count; i++) {
- tdo_bit = alt_jtag_io(
- (i == count - 1),
- tdi[i >> 3] & (1 << (i & 7)),
- (tdo != NULL));
- if (tdo != NULL) {
- if (tdo_bit)
- tdo[i >> 3] |= (1 << (i & 7));
- else
- tdo[i >> 3] &= ~(u32)(1 << (i & 7));
- }
- }
- alt_jtag_io(0, 0, 0); /* DRPAUSE */
- }
- return status;
- }
- static int alt_jtag_irscan(struct altera_state *astate,
- int start_state,
- int count,
- u8 *tdi,
- u8 *tdo)
- {
- int i = 0;
- int tdo_bit = 0;
- int status = 1;
- /* First go to IRSHIFT state */
- switch (start_state) {
- case 0: /* IDLE */
- alt_jtag_io(1, 0, 0); /* DRSELECT */
- alt_jtag_io(1, 0, 0); /* IRSELECT */
- alt_jtag_io(0, 0, 0); /* IRCAPTURE */
- alt_jtag_io(0, 0, 0); /* IRSHIFT */
- break;
- case 1: /* DRPAUSE */
- alt_jtag_io(1, 0, 0); /* DREXIT2 */
- alt_jtag_io(1, 0, 0); /* DRUPDATE */
- alt_jtag_io(1, 0, 0); /* DRSELECT */
- alt_jtag_io(1, 0, 0); /* IRSELECT */
- alt_jtag_io(0, 0, 0); /* IRCAPTURE */
- alt_jtag_io(0, 0, 0); /* IRSHIFT */
- break;
- case 2: /* IRPAUSE */
- alt_jtag_io(1, 0, 0); /* IREXIT2 */
- alt_jtag_io(1, 0, 0); /* IRUPDATE */
- alt_jtag_io(1, 0, 0); /* DRSELECT */
- alt_jtag_io(1, 0, 0); /* IRSELECT */
- alt_jtag_io(0, 0, 0); /* IRCAPTURE */
- alt_jtag_io(0, 0, 0); /* IRSHIFT */
- break;
- default:
- status = 0;
- }
- if (status) {
- /* loop in the SHIFT-IR state */
- for (i = 0; i < count; i++) {
- tdo_bit = alt_jtag_io(
- (i == count - 1),
- tdi[i >> 3] & (1 << (i & 7)),
- (tdo != NULL));
- if (tdo != NULL) {
- if (tdo_bit)
- tdo[i >> 3] |= (1 << (i & 7));
- else
- tdo[i >> 3] &= ~(u32)(1 << (i & 7));
- }
- }
- alt_jtag_io(0, 0, 0); /* IRPAUSE */
- }
- return status;
- }
- static void altera_extract_target_data(u8 *buffer,
- u8 *target_data,
- u32 start_index,
- u32 preamble_count,
- u32 target_count)
- /*
- * Copies target data from scan buffer, filtering out
- * preamble and postamble data.
- */
- {
- u32 i;
- u32 j;
- u32 k;
- j = preamble_count;
- k = start_index + target_count;
- for (i = start_index; i < k; ++i, ++j) {
- if (buffer[j >> 3] & (1 << (j & 7)))
- target_data[i >> 3] |= (1 << (i & 7));
- else
- target_data[i >> 3] &= ~(u32)(1 << (i & 7));
- }
- }
- int altera_irscan(struct altera_state *astate,
- u32 count,
- u8 *tdi_data,
- u32 start_index)
- /* Shifts data into instruction register */
- {
- struct altera_jtag *js = &astate->js;
- int start_code = 0;
- u32 alloc_chars = 0;
- u32 shift_count = js->ir_pre + count + js->ir_post;
- int status = 0;
- enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
- switch (js->jtag_state) {
- case ILLEGAL_JTAG_STATE:
- case RESET:
- case IDLE:
- start_code = 0;
- start_state = IDLE;
- break;
- case DRSELECT:
- case DRCAPTURE:
- case DRSHIFT:
- case DREXIT1:
- case DRPAUSE:
- case DREXIT2:
- case DRUPDATE:
- start_code = 1;
- start_state = DRPAUSE;
- break;
- case IRSELECT:
- case IRCAPTURE:
- case IRSHIFT:
- case IREXIT1:
- case IRPAUSE:
- case IREXIT2:
- case IRUPDATE:
- start_code = 2;
- start_state = IRPAUSE;
- break;
- default:
- status = -EREMOTEIO;
- break;
- }
- if (status == 0)
- if (js->jtag_state != start_state)
- status = altera_goto_jstate(astate, start_state);
- if (status == 0) {
- if (shift_count > js->ir_length) {
- alloc_chars = (shift_count + 7) >> 3;
- kfree(js->ir_buffer);
- js->ir_buffer = (u8 *)alt_malloc(alloc_chars);
- if (js->ir_buffer == NULL)
- status = -ENOMEM;
- else
- js->ir_length = alloc_chars * 8;
- }
- }
- if (status == 0) {
- /*
- * Copy preamble data, IR data,
- * and postamble data into a buffer
- */
- altera_concatenate_data(js->ir_buffer,
- js->ir_pre_data,
- js->ir_pre,
- tdi_data,
- start_index,
- count,
- js->ir_post_data,
- js->ir_post);
- /* Do the IRSCAN */
- alt_jtag_irscan(astate,
- start_code,
- shift_count,
- js->ir_buffer,
- NULL);
- /* alt_jtag_irscan() always ends in IRPAUSE state */
- js->jtag_state = IRPAUSE;
- }
- if (status == 0)
- if (js->irstop_state != IRPAUSE)
- status = altera_goto_jstate(astate, js->irstop_state);
- return status;
- }
- int altera_swap_ir(struct altera_state *astate,
- u32 count,
- u8 *in_data,
- u32 in_index,
- u8 *out_data,
- u32 out_index)
- /* Shifts data into instruction register, capturing output data */
- {
- struct altera_jtag *js = &astate->js;
- int start_code = 0;
- u32 alloc_chars = 0;
- u32 shift_count = js->ir_pre + count + js->ir_post;
- int status = 0;
- enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
- switch (js->jtag_state) {
- case ILLEGAL_JTAG_STATE:
- case RESET:
- case IDLE:
- start_code = 0;
- start_state = IDLE;
- break;
- case DRSELECT:
- case DRCAPTURE:
- case DRSHIFT:
- case DREXIT1:
- case DRPAUSE:
- case DREXIT2:
- case DRUPDATE:
- start_code = 1;
- start_state = DRPAUSE;
- break;
- case IRSELECT:
- case IRCAPTURE:
- case IRSHIFT:
- case IREXIT1:
- case IRPAUSE:
- case IREXIT2:
- case IRUPDATE:
- start_code = 2;
- start_state = IRPAUSE;
- break;
- default:
- status = -EREMOTEIO;
- break;
- }
- if (status == 0)
- if (js->jtag_state != start_state)
- status = altera_goto_jstate(astate, start_state);
- if (status == 0) {
- if (shift_count > js->ir_length) {
- alloc_chars = (shift_count + 7) >> 3;
- kfree(js->ir_buffer);
- js->ir_buffer = (u8 *)alt_malloc(alloc_chars);
- if (js->ir_buffer == NULL)
- status = -ENOMEM;
- else
- js->ir_length = alloc_chars * 8;
- }
- }
- if (status == 0) {
- /*
- * Copy preamble data, IR data,
- * and postamble data into a buffer
- */
- altera_concatenate_data(js->ir_buffer,
- js->ir_pre_data,
- js->ir_pre,
- in_data,
- in_index,
- count,
- js->ir_post_data,
- js->ir_post);
- /* Do the IRSCAN */
- alt_jtag_irscan(astate,
- start_code,
- shift_count,
- js->ir_buffer,
- js->ir_buffer);
- /* alt_jtag_irscan() always ends in IRPAUSE state */
- js->jtag_state = IRPAUSE;
- }
- if (status == 0)
- if (js->irstop_state != IRPAUSE)
- status = altera_goto_jstate(astate, js->irstop_state);
- if (status == 0)
- /* Now extract the returned data from the buffer */
- altera_extract_target_data(js->ir_buffer,
- out_data, out_index,
- js->ir_pre, count);
- return status;
- }
- int altera_drscan(struct altera_state *astate,
- u32 count,
- u8 *tdi_data,
- u32 start_index)
- /* Shifts data into data register (ignoring output data) */
- {
- struct altera_jtag *js = &astate->js;
- int start_code = 0;
- u32 alloc_chars = 0;
- u32 shift_count = js->dr_pre + count + js->dr_post;
- int status = 0;
- enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
- switch (js->jtag_state) {
- case ILLEGAL_JTAG_STATE:
- case RESET:
- case IDLE:
- start_code = 0;
- start_state = IDLE;
- break;
- case DRSELECT:
- case DRCAPTURE:
- case DRSHIFT:
- case DREXIT1:
- case DRPAUSE:
- case DREXIT2:
- case DRUPDATE:
- start_code = 1;
- start_state = DRPAUSE;
- break;
- case IRSELECT:
- case IRCAPTURE:
- case IRSHIFT:
- case IREXIT1:
- case IRPAUSE:
- case IREXIT2:
- case IRUPDATE:
- start_code = 2;
- start_state = IRPAUSE;
- break;
- default:
- status = -EREMOTEIO;
- break;
- }
- if (status == 0)
- if (js->jtag_state != start_state)
- status = altera_goto_jstate(astate, start_state);
- if (status == 0) {
- if (shift_count > js->dr_length) {
- alloc_chars = (shift_count + 7) >> 3;
- kfree(js->dr_buffer);
- js->dr_buffer = (u8 *)alt_malloc(alloc_chars);
- if (js->dr_buffer == NULL)
- status = -ENOMEM;
- else
- js->dr_length = alloc_chars * 8;
- }
- }
- if (status == 0) {
- /*
- * Copy preamble data, DR data,
- * and postamble data into a buffer
- */
- altera_concatenate_data(js->dr_buffer,
- js->dr_pre_data,
- js->dr_pre,
- tdi_data,
- start_index,
- count,
- js->dr_post_data,
- js->dr_post);
- /* Do the DRSCAN */
- alt_jtag_drscan(astate, start_code, shift_count,
- js->dr_buffer, NULL);
- /* alt_jtag_drscan() always ends in DRPAUSE state */
- js->jtag_state = DRPAUSE;
- }
- if (status == 0)
- if (js->drstop_state != DRPAUSE)
- status = altera_goto_jstate(astate, js->drstop_state);
- return status;
- }
- int altera_swap_dr(struct altera_state *astate, u32 count,
- u8 *in_data, u32 in_index,
- u8 *out_data, u32 out_index)
- /* Shifts data into data register, capturing output data */
- {
- struct altera_jtag *js = &astate->js;
- int start_code = 0;
- u32 alloc_chars = 0;
- u32 shift_count = js->dr_pre + count + js->dr_post;
- int status = 0;
- enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
- switch (js->jtag_state) {
- case ILLEGAL_JTAG_STATE:
- case RESET:
- case IDLE:
- start_code = 0;
- start_state = IDLE;
- break;
- case DRSELECT:
- case DRCAPTURE:
- case DRSHIFT:
- case DREXIT1:
- case DRPAUSE:
- case DREXIT2:
- case DRUPDATE:
- start_code = 1;
- start_state = DRPAUSE;
- break;
- case IRSELECT:
- case IRCAPTURE:
- case IRSHIFT:
- case IREXIT1:
- case IRPAUSE:
- case IREXIT2:
- case IRUPDATE:
- start_code = 2;
- start_state = IRPAUSE;
- break;
- default:
- status = -EREMOTEIO;
- break;
- }
- if (status == 0)
- if (js->jtag_state != start_state)
- status = altera_goto_jstate(astate, start_state);
- if (status == 0) {
- if (shift_count > js->dr_length) {
- alloc_chars = (shift_count + 7) >> 3;
- kfree(js->dr_buffer);
- js->dr_buffer = (u8 *)alt_malloc(alloc_chars);
- if (js->dr_buffer == NULL)
- status = -ENOMEM;
- else
- js->dr_length = alloc_chars * 8;
- }
- }
- if (status == 0) {
- /*
- * Copy preamble data, DR data,
- * and postamble data into a buffer
- */
- altera_concatenate_data(js->dr_buffer,
- js->dr_pre_data,
- js->dr_pre,
- in_data,
- in_index,
- count,
- js->dr_post_data,
- js->dr_post);
- /* Do the DRSCAN */
- alt_jtag_drscan(astate,
- start_code,
- shift_count,
- js->dr_buffer,
- js->dr_buffer);
- /* alt_jtag_drscan() always ends in DRPAUSE state */
- js->jtag_state = DRPAUSE;
- }
- if (status == 0)
- if (js->drstop_state != DRPAUSE)
- status = altera_goto_jstate(astate, js->drstop_state);
- if (status == 0)
- /* Now extract the returned data from the buffer */
- altera_extract_target_data(js->dr_buffer,
- out_data,
- out_index,
- js->dr_pre,
- count);
- return status;
- }
- void altera_free_buffers(struct altera_state *astate)
- {
- struct altera_jtag *js = &astate->js;
- /* If the JTAG interface was used, reset it to TLR */
- if (js->jtag_state != ILLEGAL_JTAG_STATE)
- altera_jreset_idle(astate);
- kfree(js->dr_pre_data);
- js->dr_pre_data = NULL;
- kfree(js->dr_post_data);
- js->dr_post_data = NULL;
- kfree(js->dr_buffer);
- js->dr_buffer = NULL;
- kfree(js->ir_pre_data);
- js->ir_pre_data = NULL;
- kfree(js->ir_post_data);
- js->ir_post_data = NULL;
- kfree(js->ir_buffer);
- js->ir_buffer = NULL;
- }
|