cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

altera-jtag.c (21450B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * altera-jtag.c
      4 *
      5 * altera FPGA driver
      6 *
      7 * Copyright (C) Altera Corporation 1998-2001
      8 * Copyright (C) 2010 NetUP Inc.
      9 * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru>
     10 */
     11
     12#include <linux/delay.h>
     13#include <linux/firmware.h>
     14#include <linux/slab.h>
     15#include <misc/altera.h>
     16#include "altera-exprt.h"
     17#include "altera-jtag.h"
     18
     19#define	alt_jtag_io(a, b, c)\
     20		astate->config->jtag_io(astate->config->dev, a, b, c);
     21
     22#define	alt_malloc(a)	kzalloc(a, GFP_KERNEL);
     23
     24/*
     25 * This structure shows, for each JTAG state, which state is reached after
     26 * a single TCK clock cycle with TMS high or TMS low, respectively.  This
     27 * describes all possible state transitions in the JTAG state machine.
     28 */
     29struct altera_jtag_machine {
     30	enum altera_jtag_state tms_high;
     31	enum altera_jtag_state tms_low;
     32};
     33
     34static const struct altera_jtag_machine altera_transitions[] = {
     35	/* RESET     */	{ RESET,	IDLE },
     36	/* IDLE      */	{ DRSELECT,	IDLE },
     37	/* DRSELECT  */	{ IRSELECT,	DRCAPTURE },
     38	/* DRCAPTURE */	{ DREXIT1,	DRSHIFT },
     39	/* DRSHIFT   */	{ DREXIT1,	DRSHIFT },
     40	/* DREXIT1   */	{ DRUPDATE,	DRPAUSE },
     41	/* DRPAUSE   */	{ DREXIT2,	DRPAUSE },
     42	/* DREXIT2   */	{ DRUPDATE,	DRSHIFT },
     43	/* DRUPDATE  */	{ DRSELECT,	IDLE },
     44	/* IRSELECT  */	{ RESET,	IRCAPTURE },
     45	/* IRCAPTURE */	{ IREXIT1,	IRSHIFT },
     46	/* IRSHIFT   */	{ IREXIT1,	IRSHIFT },
     47	/* IREXIT1   */	{ IRUPDATE,	IRPAUSE },
     48	/* IRPAUSE   */	{ IREXIT2,	IRPAUSE },
     49	/* IREXIT2   */	{ IRUPDATE,	IRSHIFT },
     50	/* IRUPDATE  */	{ DRSELECT,	IDLE }
     51};
     52
     53/*
     54 * This table contains the TMS value to be used to take the NEXT STEP on
     55 * the path to the desired state.  The array index is the current state,
     56 * and the bit position is the desired endstate.  To find out which state
     57 * is used as the intermediate state, look up the TMS value in the
     58 * altera_transitions[] table.
     59 */
     60static const u16 altera_jtag_path_map[16] = {
     61	/* RST	RTI	SDRS	CDR	SDR	E1DR	PDR	E2DR */
     62	0x0001,	0xFFFD,	0xFE01,	0xFFE7,	0xFFEF,	0xFF0F,	0xFFBF,	0xFFFF,
     63	/* UDR	SIRS	CIR	SIR	E1IR	PIR	E2IR	UIR */
     64	0xFEFD,	0x0001,	0xF3FF,	0xF7FF,	0x87FF,	0xDFFF,	0xFFFF,	0x7FFD
     65};
     66
     67/* Flag bits for alt_jtag_io() function */
     68#define TMS_HIGH   1
     69#define TMS_LOW    0
     70#define TDI_HIGH   1
     71#define TDI_LOW    0
     72#define READ_TDO   1
     73#define IGNORE_TDO 0
     74
     75int altera_jinit(struct altera_state *astate)
     76{
     77	struct altera_jtag *js = &astate->js;
     78
     79	/* initial JTAG state is unknown */
     80	js->jtag_state = ILLEGAL_JTAG_STATE;
     81
     82	/* initialize to default state */
     83	js->drstop_state = IDLE;
     84	js->irstop_state = IDLE;
     85	js->dr_pre  = 0;
     86	js->dr_post = 0;
     87	js->ir_pre  = 0;
     88	js->ir_post = 0;
     89	js->dr_length    = 0;
     90	js->ir_length    = 0;
     91
     92	js->dr_pre_data  = NULL;
     93	js->dr_post_data = NULL;
     94	js->ir_pre_data  = NULL;
     95	js->ir_post_data = NULL;
     96	js->dr_buffer	 = NULL;
     97	js->ir_buffer	 = NULL;
     98
     99	return 0;
    100}
    101
    102int altera_set_drstop(struct altera_jtag *js, enum altera_jtag_state state)
    103{
    104	js->drstop_state = state;
    105
    106	return 0;
    107}
    108
    109int altera_set_irstop(struct altera_jtag *js, enum altera_jtag_state state)
    110{
    111	js->irstop_state = state;
    112
    113	return 0;
    114}
    115
    116int altera_set_dr_pre(struct altera_jtag *js,
    117				u32 count, u32 start_index,
    118				u8 *preamble_data)
    119{
    120	int status = 0;
    121	u32 i;
    122	u32 j;
    123
    124	if (count > js->dr_pre) {
    125		kfree(js->dr_pre_data);
    126		js->dr_pre_data = (u8 *)alt_malloc((count + 7) >> 3);
    127		if (js->dr_pre_data == NULL)
    128			status = -ENOMEM;
    129		else
    130			js->dr_pre = count;
    131	} else
    132		js->dr_pre = count;
    133
    134	if (status == 0) {
    135		for (i = 0; i < count; ++i) {
    136			j = i + start_index;
    137
    138			if (preamble_data == NULL)
    139				js->dr_pre_data[i >> 3] |= (1 << (i & 7));
    140			else {
    141				if (preamble_data[j >> 3] & (1 << (j & 7)))
    142					js->dr_pre_data[i >> 3] |=
    143							(1 << (i & 7));
    144				else
    145					js->dr_pre_data[i >> 3] &=
    146							~(u32)(1 << (i & 7));
    147
    148			}
    149		}
    150	}
    151
    152	return status;
    153}
    154
    155int altera_set_ir_pre(struct altera_jtag *js, u32 count, u32 start_index,
    156							u8 *preamble_data)
    157{
    158	int status = 0;
    159	u32 i;
    160	u32 j;
    161
    162	if (count > js->ir_pre) {
    163		kfree(js->ir_pre_data);
    164		js->ir_pre_data = (u8 *)alt_malloc((count + 7) >> 3);
    165		if (js->ir_pre_data == NULL)
    166			status = -ENOMEM;
    167		else
    168			js->ir_pre = count;
    169
    170	} else
    171		js->ir_pre = count;
    172
    173	if (status == 0) {
    174		for (i = 0; i < count; ++i) {
    175			j = i + start_index;
    176			if (preamble_data == NULL)
    177				js->ir_pre_data[i >> 3] |= (1 << (i & 7));
    178			else {
    179				if (preamble_data[j >> 3] & (1 << (j & 7)))
    180					js->ir_pre_data[i >> 3] |=
    181							(1 << (i & 7));
    182				else
    183					js->ir_pre_data[i >> 3] &=
    184							~(u32)(1 << (i & 7));
    185
    186			}
    187		}
    188	}
    189
    190	return status;
    191}
    192
    193int altera_set_dr_post(struct altera_jtag *js, u32 count, u32 start_index,
    194						u8 *postamble_data)
    195{
    196	int status = 0;
    197	u32 i;
    198	u32 j;
    199
    200	if (count > js->dr_post) {
    201		kfree(js->dr_post_data);
    202		js->dr_post_data = (u8 *)alt_malloc((count + 7) >> 3);
    203
    204		if (js->dr_post_data == NULL)
    205			status = -ENOMEM;
    206		else
    207			js->dr_post = count;
    208
    209	} else
    210		js->dr_post = count;
    211
    212	if (status == 0) {
    213		for (i = 0; i < count; ++i) {
    214			j = i + start_index;
    215
    216			if (postamble_data == NULL)
    217				js->dr_post_data[i >> 3] |= (1 << (i & 7));
    218			else {
    219				if (postamble_data[j >> 3] & (1 << (j & 7)))
    220					js->dr_post_data[i >> 3] |=
    221								(1 << (i & 7));
    222				else
    223					js->dr_post_data[i >> 3] &=
    224					    ~(u32)(1 << (i & 7));
    225
    226			}
    227		}
    228	}
    229
    230	return status;
    231}
    232
    233int altera_set_ir_post(struct altera_jtag *js, u32 count, u32 start_index,
    234						u8 *postamble_data)
    235{
    236	int status = 0;
    237	u32 i;
    238	u32 j;
    239
    240	if (count > js->ir_post) {
    241		kfree(js->ir_post_data);
    242		js->ir_post_data = (u8 *)alt_malloc((count + 7) >> 3);
    243		if (js->ir_post_data == NULL)
    244			status = -ENOMEM;
    245		else
    246			js->ir_post = count;
    247
    248	} else
    249		js->ir_post = count;
    250
    251	if (status != 0)
    252		return status;
    253
    254	for (i = 0; i < count; ++i) {
    255		j = i + start_index;
    256
    257		if (postamble_data == NULL)
    258			js->ir_post_data[i >> 3] |= (1 << (i & 7));
    259		else {
    260			if (postamble_data[j >> 3] & (1 << (j & 7)))
    261				js->ir_post_data[i >> 3] |= (1 << (i & 7));
    262			else
    263				js->ir_post_data[i >> 3] &=
    264				    ~(u32)(1 << (i & 7));
    265
    266		}
    267	}
    268
    269	return status;
    270}
    271
    272static void altera_jreset_idle(struct altera_state *astate)
    273{
    274	struct altera_jtag *js = &astate->js;
    275	int i;
    276	/* Go to Test Logic Reset (no matter what the starting state may be) */
    277	for (i = 0; i < 5; ++i)
    278		alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO);
    279
    280	/* Now step to Run Test / Idle */
    281	alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO);
    282	js->jtag_state = IDLE;
    283}
    284
    285int altera_goto_jstate(struct altera_state *astate,
    286					enum altera_jtag_state state)
    287{
    288	struct altera_jtag *js = &astate->js;
    289	int tms;
    290	int count = 0;
    291	int status = 0;
    292
    293	if (js->jtag_state == ILLEGAL_JTAG_STATE)
    294		/* initialize JTAG chain to known state */
    295		altera_jreset_idle(astate);
    296
    297	if (js->jtag_state == state) {
    298		/*
    299		 * We are already in the desired state.
    300		 * If it is a stable state, loop here.
    301		 * Otherwise do nothing (no clock cycles).
    302		 */
    303		if ((state == IDLE) || (state == DRSHIFT) ||
    304			(state == DRPAUSE) || (state == IRSHIFT) ||
    305				(state == IRPAUSE)) {
    306			alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO);
    307		} else if (state == RESET)
    308			alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO);
    309
    310	} else {
    311		while ((js->jtag_state != state) && (count < 9)) {
    312			/* Get TMS value to take a step toward desired state */
    313			tms = (altera_jtag_path_map[js->jtag_state] &
    314							(1 << state))
    315							? TMS_HIGH : TMS_LOW;
    316
    317			/* Take a step */
    318			alt_jtag_io(tms, TDI_LOW, IGNORE_TDO);
    319
    320			if (tms)
    321				js->jtag_state =
    322					altera_transitions[js->jtag_state].tms_high;
    323			else
    324				js->jtag_state =
    325					altera_transitions[js->jtag_state].tms_low;
    326
    327			++count;
    328		}
    329	}
    330
    331	if (js->jtag_state != state)
    332		status = -EREMOTEIO;
    333
    334	return status;
    335}
    336
    337int altera_wait_cycles(struct altera_state *astate,
    338					s32 cycles,
    339					enum altera_jtag_state wait_state)
    340{
    341	struct altera_jtag *js = &astate->js;
    342	int tms;
    343	s32 count;
    344	int status = 0;
    345
    346	if (js->jtag_state != wait_state)
    347		status = altera_goto_jstate(astate, wait_state);
    348
    349	if (status == 0) {
    350		/*
    351		 * Set TMS high to loop in RESET state
    352		 * Set TMS low to loop in any other stable state
    353		 */
    354		tms = (wait_state == RESET) ? TMS_HIGH : TMS_LOW;
    355
    356		for (count = 0L; count < cycles; count++)
    357			alt_jtag_io(tms, TDI_LOW, IGNORE_TDO);
    358
    359	}
    360
    361	return status;
    362}
    363
    364int altera_wait_msecs(struct altera_state *astate,
    365			s32 microseconds, enum altera_jtag_state wait_state)
    366/*
    367 * Causes JTAG hardware to sit in the specified stable
    368 * state for the specified duration of real time.  If
    369 * no JTAG operations have been performed yet, then only
    370 * a delay is performed.  This permits the WAIT USECS
    371 * statement to be used in VECTOR programs without causing
    372 * any JTAG operations.
    373 * Returns 0 for success, else appropriate error code.
    374 */
    375{
    376	struct altera_jtag *js = &astate->js;
    377	int status = 0;
    378
    379	if ((js->jtag_state != ILLEGAL_JTAG_STATE) &&
    380	    (js->jtag_state != wait_state))
    381		status = altera_goto_jstate(astate, wait_state);
    382
    383	if (status == 0)
    384		/* Wait for specified time interval */
    385		udelay(microseconds);
    386
    387	return status;
    388}
    389
    390static void altera_concatenate_data(u8 *buffer,
    391				u8 *preamble_data,
    392				u32 preamble_count,
    393				u8 *target_data,
    394				u32 start_index,
    395				u32 target_count,
    396				u8 *postamble_data,
    397				u32 postamble_count)
    398/*
    399 * Copies preamble data, target data, and postamble data
    400 * into one buffer for IR or DR scans.
    401 */
    402{
    403	u32 i, j, k;
    404
    405	for (i = 0L; i < preamble_count; ++i) {
    406		if (preamble_data[i >> 3L] & (1L << (i & 7L)))
    407			buffer[i >> 3L] |= (1L << (i & 7L));
    408		else
    409			buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
    410
    411	}
    412
    413	j = start_index;
    414	k = preamble_count + target_count;
    415	for (; i < k; ++i, ++j) {
    416		if (target_data[j >> 3L] & (1L << (j & 7L)))
    417			buffer[i >> 3L] |= (1L << (i & 7L));
    418		else
    419			buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
    420
    421	}
    422
    423	j = 0L;
    424	k = preamble_count + target_count + postamble_count;
    425	for (; i < k; ++i, ++j) {
    426		if (postamble_data[j >> 3L] & (1L << (j & 7L)))
    427			buffer[i >> 3L] |= (1L << (i & 7L));
    428		else
    429			buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
    430
    431	}
    432}
    433
    434static int alt_jtag_drscan(struct altera_state *astate,
    435			int start_state,
    436			int count,
    437			u8 *tdi,
    438			u8 *tdo)
    439{
    440	int i = 0;
    441	int tdo_bit = 0;
    442	int status = 1;
    443
    444	/* First go to DRSHIFT state */
    445	switch (start_state) {
    446	case 0:						/* IDLE */
    447		alt_jtag_io(1, 0, 0);	/* DRSELECT */
    448		alt_jtag_io(0, 0, 0);	/* DRCAPTURE */
    449		alt_jtag_io(0, 0, 0);	/* DRSHIFT */
    450		break;
    451
    452	case 1:						/* DRPAUSE */
    453		alt_jtag_io(1, 0, 0);	/* DREXIT2 */
    454		alt_jtag_io(1, 0, 0);	/* DRUPDATE */
    455		alt_jtag_io(1, 0, 0);	/* DRSELECT */
    456		alt_jtag_io(0, 0, 0);	/* DRCAPTURE */
    457		alt_jtag_io(0, 0, 0);	/* DRSHIFT */
    458		break;
    459
    460	case 2:						/* IRPAUSE */
    461		alt_jtag_io(1, 0, 0);	/* IREXIT2 */
    462		alt_jtag_io(1, 0, 0);	/* IRUPDATE */
    463		alt_jtag_io(1, 0, 0);	/* DRSELECT */
    464		alt_jtag_io(0, 0, 0);	/* DRCAPTURE */
    465		alt_jtag_io(0, 0, 0);	/* DRSHIFT */
    466		break;
    467
    468	default:
    469		status = 0;
    470	}
    471
    472	if (status) {
    473		/* loop in the SHIFT-DR state */
    474		for (i = 0; i < count; i++) {
    475			tdo_bit = alt_jtag_io(
    476					(i == count - 1),
    477					tdi[i >> 3] & (1 << (i & 7)),
    478					(tdo != NULL));
    479
    480			if (tdo != NULL) {
    481				if (tdo_bit)
    482					tdo[i >> 3] |= (1 << (i & 7));
    483				else
    484					tdo[i >> 3] &= ~(u32)(1 << (i & 7));
    485
    486			}
    487		}
    488
    489		alt_jtag_io(0, 0, 0);	/* DRPAUSE */
    490	}
    491
    492	return status;
    493}
    494
    495static int alt_jtag_irscan(struct altera_state *astate,
    496		    int start_state,
    497		    int count,
    498		    u8 *tdi,
    499		    u8 *tdo)
    500{
    501	int i = 0;
    502	int tdo_bit = 0;
    503	int status = 1;
    504
    505	/* First go to IRSHIFT state */
    506	switch (start_state) {
    507	case 0:						/* IDLE */
    508		alt_jtag_io(1, 0, 0);	/* DRSELECT */
    509		alt_jtag_io(1, 0, 0);	/* IRSELECT */
    510		alt_jtag_io(0, 0, 0);	/* IRCAPTURE */
    511		alt_jtag_io(0, 0, 0);	/* IRSHIFT */
    512		break;
    513
    514	case 1:						/* DRPAUSE */
    515		alt_jtag_io(1, 0, 0);	/* DREXIT2 */
    516		alt_jtag_io(1, 0, 0);	/* DRUPDATE */
    517		alt_jtag_io(1, 0, 0);	/* DRSELECT */
    518		alt_jtag_io(1, 0, 0);	/* IRSELECT */
    519		alt_jtag_io(0, 0, 0);	/* IRCAPTURE */
    520		alt_jtag_io(0, 0, 0);	/* IRSHIFT */
    521		break;
    522
    523	case 2:						/* IRPAUSE */
    524		alt_jtag_io(1, 0, 0);	/* IREXIT2 */
    525		alt_jtag_io(1, 0, 0);	/* IRUPDATE */
    526		alt_jtag_io(1, 0, 0);	/* DRSELECT */
    527		alt_jtag_io(1, 0, 0);	/* IRSELECT */
    528		alt_jtag_io(0, 0, 0);	/* IRCAPTURE */
    529		alt_jtag_io(0, 0, 0);	/* IRSHIFT */
    530		break;
    531
    532	default:
    533		status = 0;
    534	}
    535
    536	if (status) {
    537		/* loop in the SHIFT-IR state */
    538		for (i = 0; i < count; i++) {
    539			tdo_bit = alt_jtag_io(
    540				      (i == count - 1),
    541				      tdi[i >> 3] & (1 << (i & 7)),
    542				      (tdo != NULL));
    543			if (tdo != NULL) {
    544				if (tdo_bit)
    545					tdo[i >> 3] |= (1 << (i & 7));
    546				else
    547					tdo[i >> 3] &= ~(u32)(1 << (i & 7));
    548
    549			}
    550		}
    551
    552		alt_jtag_io(0, 0, 0);	/* IRPAUSE */
    553	}
    554
    555	return status;
    556}
    557
    558static void altera_extract_target_data(u8 *buffer,
    559				u8 *target_data,
    560				u32 start_index,
    561				u32 preamble_count,
    562				u32 target_count)
    563/*
    564 * Copies target data from scan buffer, filtering out
    565 * preamble and postamble data.
    566 */
    567{
    568	u32 i;
    569	u32 j;
    570	u32 k;
    571
    572	j = preamble_count;
    573	k = start_index + target_count;
    574	for (i = start_index; i < k; ++i, ++j) {
    575		if (buffer[j >> 3] & (1 << (j & 7)))
    576			target_data[i >> 3] |= (1 << (i & 7));
    577		else
    578			target_data[i >> 3] &= ~(u32)(1 << (i & 7));
    579
    580	}
    581}
    582
    583int altera_irscan(struct altera_state *astate,
    584				u32 count,
    585				u8 *tdi_data,
    586				u32 start_index)
    587/* Shifts data into instruction register */
    588{
    589	struct altera_jtag *js = &astate->js;
    590	int start_code = 0;
    591	u32 alloc_chars = 0;
    592	u32 shift_count = js->ir_pre + count + js->ir_post;
    593	int status = 0;
    594	enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
    595
    596	switch (js->jtag_state) {
    597	case ILLEGAL_JTAG_STATE:
    598	case RESET:
    599	case IDLE:
    600		start_code = 0;
    601		start_state = IDLE;
    602		break;
    603
    604	case DRSELECT:
    605	case DRCAPTURE:
    606	case DRSHIFT:
    607	case DREXIT1:
    608	case DRPAUSE:
    609	case DREXIT2:
    610	case DRUPDATE:
    611		start_code = 1;
    612		start_state = DRPAUSE;
    613		break;
    614
    615	case IRSELECT:
    616	case IRCAPTURE:
    617	case IRSHIFT:
    618	case IREXIT1:
    619	case IRPAUSE:
    620	case IREXIT2:
    621	case IRUPDATE:
    622		start_code = 2;
    623		start_state = IRPAUSE;
    624		break;
    625
    626	default:
    627		status = -EREMOTEIO;
    628		break;
    629	}
    630
    631	if (status == 0)
    632		if (js->jtag_state != start_state)
    633			status = altera_goto_jstate(astate, 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			else
    643				js->ir_length = alloc_chars * 8;
    644
    645		}
    646	}
    647
    648	if (status == 0) {
    649		/*
    650		 * Copy preamble data, IR data,
    651		 * and postamble data into a buffer
    652		 */
    653		altera_concatenate_data(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			else
    742				js->ir_length = alloc_chars * 8;
    743
    744		}
    745	}
    746
    747	if (status == 0) {
    748		/*
    749		 * Copy preamble data, IR data,
    750		 * and postamble data into a buffer
    751		 */
    752		altera_concatenate_data(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			else
    846				js->dr_length = alloc_chars * 8;
    847
    848		}
    849	}
    850
    851	if (status == 0) {
    852		/*
    853		 * Copy preamble data, DR data,
    854		 * and postamble data into a buffer
    855		 */
    856		altera_concatenate_data(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			else
    938				js->dr_length = alloc_chars * 8;
    939
    940		}
    941	}
    942
    943	if (status == 0) {
    944		/*
    945		 * Copy preamble data, DR data,
    946		 * and postamble data into a buffer
    947		 */
    948		altera_concatenate_data(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}