brintos

brintos / linux-shallow public Read only

0
0
Text · 20.9 KiB · 27e8e0c Raw
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