spartan2.c 12.2 KB
Newer Older
wdenk's avatar
wdenk committed
1 2 3 4
/*
 * (C) Copyright 2002
 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
 *
5
 * SPDX-License-Identifier:	GPL-2.0+
wdenk's avatar
wdenk committed
6 7 8 9 10 11 12 13 14 15 16 17
 */

#include <common.h>		/* core U-Boot definitions */
#include <spartan2.h>		/* Spartan-II device family */

/* Define FPGA_DEBUG to get debug printf's */
#ifdef	FPGA_DEBUG
#define PRINTF(fmt,args...)	printf (fmt ,##args)
#else
#define PRINTF(fmt,args...)
#endif

18 19
#undef CONFIG_SYS_FPGA_CHECK_BUSY
#undef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk's avatar
wdenk committed
20 21 22 23 24 25 26 27 28 29

/* Note: The assumption is that we cannot possibly run fast enough to
 * overrun the device (the Slave Parallel mode can free run at 50MHz).
 * If there is a need to operate slower, define CONFIG_FPGA_DELAY in
 * the board config file to slow things down.
 */
#ifndef CONFIG_FPGA_DELAY
#define CONFIG_FPGA_DELAY()
#endif

30 31
#ifndef CONFIG_SYS_FPGA_WAIT
#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100	/* 10 ms */
wdenk's avatar
wdenk committed
32 33
#endif

34 35 36
static int Spartan2_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize);
static int Spartan2_sp_dump(Xilinx_desc *desc, const void *buf, size_t bsize);
/* static int Spartan2_sp_info(Xilinx_desc *desc ); */
wdenk's avatar
wdenk committed
37

38 39 40
static int Spartan2_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize);
static int Spartan2_ss_dump(Xilinx_desc *desc, const void *buf, size_t bsize);
/* static int Spartan2_ss_info(Xilinx_desc *desc ); */
wdenk's avatar
wdenk committed
41 42 43

/* ------------------------------------------------------------------------- */
/* Spartan-II Generic Implementation */
44
int Spartan2_load(Xilinx_desc *desc, const void *buf, size_t bsize)
wdenk's avatar
wdenk committed
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
{
	int ret_val = FPGA_FAIL;

	switch (desc->iface) {
	case slave_serial:
		PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
		ret_val = Spartan2_ss_load (desc, buf, bsize);
		break;

	case slave_parallel:
		PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
		ret_val = Spartan2_sp_load (desc, buf, bsize);
		break;

	default:
		printf ("%s: Unsupported interface type, %d\n",
				__FUNCTION__, desc->iface);
	}

	return ret_val;
}

67
int Spartan2_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
wdenk's avatar
wdenk committed
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
{
	int ret_val = FPGA_FAIL;

	switch (desc->iface) {
	case slave_serial:
		PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
		ret_val = Spartan2_ss_dump (desc, buf, bsize);
		break;

	case slave_parallel:
		PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
		ret_val = Spartan2_sp_dump (desc, buf, bsize);
		break;

	default:
		printf ("%s: Unsupported interface type, %d\n",
				__FUNCTION__, desc->iface);
	}

	return ret_val;
}

int Spartan2_info( Xilinx_desc *desc )
{
	return FPGA_SUCCESS;
}


/* ------------------------------------------------------------------------- */
/* Spartan-II Slave Parallel Generic Implementation */

99
static int Spartan2_sp_load(Xilinx_desc *desc, const void *buf, size_t bsize)
wdenk's avatar
wdenk committed
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
{
	int ret_val = FPGA_FAIL;	/* assume the worst */
	Xilinx_Spartan2_Slave_Parallel_fns *fn = desc->iface_fns;

	PRINTF ("%s: start with interface functions @ 0x%p\n",
			__FUNCTION__, fn);

	if (fn) {
		size_t bytecount = 0;
		unsigned char *data = (unsigned char *) buf;
		int cookie = desc->cookie;	/* make a local copy */
		unsigned long ts;		/* timestamp */

		PRINTF ("%s: Function Table:\n"
				"ptr:\t0x%p\n"
				"struct: 0x%p\n"
				"pre: 0x%p\n"
				"pgm:\t0x%p\n"
				"init:\t0x%p\n"
				"err:\t0x%p\n"
				"clk:\t0x%p\n"
				"cs:\t0x%p\n"
				"wr:\t0x%p\n"
				"read data:\t0x%p\n"
				"write data:\t0x%p\n"
				"busy:\t0x%p\n"
				"abort:\t0x%p\n",
				"post:\t0x%p\n\n",
				__FUNCTION__, &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
				fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
				fn->abort, fn->post);

		/*
		 * This code is designed to emulate the "Express Style"
		 * Continuous Data Loading in Slave Parallel Mode for
		 * the Spartan-II Family.
		 */
137
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk's avatar
wdenk committed
138 139 140 141 142 143 144 145 146 147
		printf ("Loading FPGA Device %d...\n", cookie);
#endif
		/*
		 * Run the pre configuration function if there is one.
		 */
		if (*fn->pre) {
			(*fn->pre) (cookie);
		}

		/* Establish the initial state */
York Sun's avatar
York Sun committed
148
		(*fn->pgm) (true, true, cookie);	/* Assert the program, commit */
wdenk's avatar
wdenk committed
149 150 151

		/* Get ready for the burn */
		CONFIG_FPGA_DELAY ();
York Sun's avatar
York Sun committed
152
		(*fn->pgm) (false, true, cookie);	/* Deassert the program, commit */
wdenk's avatar
wdenk committed
153 154 155 156 157

		ts = get_timer (0);		/* get current time */
		/* Now wait for INIT and BUSY to go high */
		do {
			CONFIG_FPGA_DELAY ();
158
			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
wdenk's avatar
wdenk committed
159 160 161 162 163 164
				puts ("** Timeout waiting for INIT to clear.\n");
				(*fn->abort) (cookie);	/* abort the burn */
				return FPGA_FAIL;
			}
		} while ((*fn->init) (cookie) && (*fn->busy) (cookie));

York Sun's avatar
York Sun committed
165 166 167
		(*fn->wr) (true, true, cookie); /* Assert write, commit */
		(*fn->cs) (true, true, cookie); /* Assert chip select, commit */
		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
wdenk's avatar
wdenk committed
168 169 170 171 172 173

		/* Load the data */
		while (bytecount < bsize) {
			/* XXX - do we check for an Ctrl-C press in here ??? */
			/* XXX - Check the error bit? */

York Sun's avatar
York Sun committed
174
			(*fn->wdata) (data[bytecount++], true, cookie); /* write the data */
wdenk's avatar
wdenk committed
175
			CONFIG_FPGA_DELAY ();
York Sun's avatar
York Sun committed
176
			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
wdenk's avatar
wdenk committed
177
			CONFIG_FPGA_DELAY ();
York Sun's avatar
York Sun committed
178
			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
wdenk's avatar
wdenk committed
179

180
#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
wdenk's avatar
wdenk committed
181 182 183 184 185 186
			ts = get_timer (0);	/* get current time */
			while ((*fn->busy) (cookie)) {
				/* XXX - we should have a check in here somewhere to
				 * make sure we aren't busy forever... */

				CONFIG_FPGA_DELAY ();
York Sun's avatar
York Sun committed
187
				(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
wdenk's avatar
wdenk committed
188
				CONFIG_FPGA_DELAY ();
York Sun's avatar
York Sun committed
189
				(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
wdenk's avatar
wdenk committed
190

191
				if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
wdenk's avatar
wdenk committed
192 193 194 195 196 197 198
					puts ("** Timeout waiting for BUSY to clear.\n");
					(*fn->abort) (cookie);	/* abort the burn */
					return FPGA_FAIL;
				}
			}
#endif

199
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk's avatar
wdenk committed
200 201 202 203 204 205
			if (bytecount % (bsize / 40) == 0)
				putc ('.');		/* let them know we are alive */
#endif
		}

		CONFIG_FPGA_DELAY ();
York Sun's avatar
York Sun committed
206 207
		(*fn->cs) (false, true, cookie);	/* Deassert the chip select */
		(*fn->wr) (false, true, cookie);	/* Deassert the write pin */
wdenk's avatar
wdenk committed
208

209
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk's avatar
wdenk committed
210 211 212 213 214 215 216 217 218
		putc ('\n');			/* terminate the dotted line */
#endif

		/* now check for done signal */
		ts = get_timer (0);		/* get current time */
		ret_val = FPGA_SUCCESS;
		while ((*fn->done) (cookie) == FPGA_FAIL) {

			CONFIG_FPGA_DELAY ();
York Sun's avatar
York Sun committed
219
			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
wdenk's avatar
wdenk committed
220
			CONFIG_FPGA_DELAY ();
York Sun's avatar
York Sun committed
221
			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
wdenk's avatar
wdenk committed
222

223
			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
wdenk's avatar
wdenk committed
224 225 226 227 228 229 230 231 232 233
				puts ("** Timeout waiting for DONE to clear.\n");
				(*fn->abort) (cookie);	/* abort the burn */
				ret_val = FPGA_FAIL;
				break;
			}
		}

		/*
		 * Run the post configuration function if there is one.
		 */
234
		if (*fn->post)
wdenk's avatar
wdenk committed
235 236
			(*fn->post) (cookie);

237
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
238 239 240
		if (ret_val == FPGA_SUCCESS)
			puts ("Done.\n");
		else
wdenk's avatar
wdenk committed
241 242 243 244 245 246 247 248 249 250
			puts ("Fail.\n");
#endif

	} else {
		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
	}

	return ret_val;
}

251
static int Spartan2_sp_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
wdenk's avatar
wdenk committed
252 253 254 255 256 257 258 259 260 261 262
{
	int ret_val = FPGA_FAIL;	/* assume the worst */
	Xilinx_Spartan2_Slave_Parallel_fns *fn = desc->iface_fns;

	if (fn) {
		unsigned char *data = (unsigned char *) buf;
		size_t bytecount = 0;
		int cookie = desc->cookie;	/* make a local copy */

		printf ("Starting Dump of FPGA Device %d...\n", cookie);

York Sun's avatar
York Sun committed
263 264
		(*fn->cs) (true, true, cookie); /* Assert chip select, commit */
		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
wdenk's avatar
wdenk committed
265 266 267 268 269

		/* dump the data */
		while (bytecount < bsize) {
			/* XXX - do we check for an Ctrl-C press in here ??? */

York Sun's avatar
York Sun committed
270 271
			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
wdenk's avatar
wdenk committed
272
			(*fn->rdata) (&(data[bytecount++]), cookie);	/* read the data */
273
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk's avatar
wdenk committed
274 275 276 277 278
			if (bytecount % (bsize / 40) == 0)
				putc ('.');		/* let them know we are alive */
#endif
		}

York Sun's avatar
York Sun committed
279 280 281
		(*fn->cs) (false, false, cookie);	/* Deassert the chip select */
		(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
wdenk's avatar
wdenk committed
282

283
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk's avatar
wdenk committed
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
		putc ('\n');			/* terminate the dotted line */
#endif
		puts ("Done.\n");

		/* XXX - checksum the data? */
	} else {
		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
	}

	return ret_val;
}


/* ------------------------------------------------------------------------- */

299
static int Spartan2_ss_load(Xilinx_desc *desc, const void *buf, size_t bsize)
wdenk's avatar
wdenk committed
300
{
wdenk's avatar
wdenk committed
301
	int ret_val = FPGA_FAIL;	/* assume the worst */
wdenk's avatar
wdenk committed
302
	Xilinx_Spartan2_Slave_Serial_fns *fn = desc->iface_fns;
wdenk's avatar
wdenk committed
303
	int i;
304
	unsigned char val;
wdenk's avatar
wdenk committed
305

wdenk's avatar
wdenk committed
306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
	PRINTF ("%s: start with interface functions @ 0x%p\n",
			__FUNCTION__, fn);

	if (fn) {
		size_t bytecount = 0;
		unsigned char *data = (unsigned char *) buf;
		int cookie = desc->cookie;	/* make a local copy */
		unsigned long ts;		/* timestamp */

		PRINTF ("%s: Function Table:\n"
				"ptr:\t0x%p\n"
				"struct: 0x%p\n"
				"pgm:\t0x%p\n"
				"init:\t0x%p\n"
				"clk:\t0x%p\n"
				"wr:\t0x%p\n"
				"done:\t0x%p\n\n",
wdenk's avatar
wdenk committed
323 324
				__FUNCTION__, &fn, fn, fn->pgm, fn->init,
				fn->clk, fn->wr, fn->done);
325
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk's avatar
wdenk committed
326 327 328 329 330 331 332 333 334 335 336
		printf ("Loading FPGA Device %d...\n", cookie);
#endif

		/*
		 * Run the pre configuration function if there is one.
		 */
		if (*fn->pre) {
			(*fn->pre) (cookie);
		}

		/* Establish the initial state */
York Sun's avatar
York Sun committed
337
		(*fn->pgm) (true, true, cookie);	/* Assert the program, commit */
wdenk's avatar
wdenk committed
338

wdenk's avatar
wdenk committed
339
		/* Wait for INIT state (init low)                            */
wdenk's avatar
wdenk committed
340 341 342
		ts = get_timer (0);		/* get current time */
		do {
			CONFIG_FPGA_DELAY ();
343
			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
wdenk's avatar
wdenk committed
344 345 346 347
				puts ("** Timeout waiting for INIT to start.\n");
				return FPGA_FAIL;
			}
		} while (!(*fn->init) (cookie));
wdenk's avatar
wdenk committed
348

wdenk's avatar
wdenk committed
349 350
		/* Get ready for the burn */
		CONFIG_FPGA_DELAY ();
York Sun's avatar
York Sun committed
351
		(*fn->pgm) (false, true, cookie);	/* Deassert the program, commit */
wdenk's avatar
wdenk committed
352 353 354 355 356

		ts = get_timer (0);		/* get current time */
		/* Now wait for INIT to go high */
		do {
			CONFIG_FPGA_DELAY ();
357
			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
wdenk's avatar
wdenk committed
358 359 360 361 362 363 364
				puts ("** Timeout waiting for INIT to clear.\n");
				return FPGA_FAIL;
			}
		} while ((*fn->init) (cookie));

		/* Load the data */
		while (bytecount < bsize) {
wdenk's avatar
wdenk committed
365 366 367 368 369 370 371 372 373 374 375

			/* Xilinx detects an error if INIT goes low (active)
			   while DONE is low (inactive) */
			if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
				puts ("** CRC error during FPGA load.\n");
				return (FPGA_FAIL);
			}
			val = data [bytecount ++];
			i = 8;
			do {
				/* Deassert the clock */
York Sun's avatar
York Sun committed
376
				(*fn->clk) (false, true, cookie);
wdenk's avatar
wdenk committed
377 378
				CONFIG_FPGA_DELAY ();
				/* Write data */
York Sun's avatar
York Sun committed
379
				(*fn->wr) ((val & 0x80), true, cookie);
wdenk's avatar
wdenk committed
380 381
				CONFIG_FPGA_DELAY ();
				/* Assert the clock */
York Sun's avatar
York Sun committed
382
				(*fn->clk) (true, true, cookie);
wdenk's avatar
wdenk committed
383 384 385 386 387
				CONFIG_FPGA_DELAY ();
				val <<= 1;
				i --;
			} while (i > 0);

388
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk's avatar
wdenk committed
389 390 391 392 393 394 395
			if (bytecount % (bsize / 40) == 0)
				putc ('.');		/* let them know we are alive */
#endif
		}

		CONFIG_FPGA_DELAY ();

396
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk's avatar
wdenk committed
397 398 399 400 401 402
		putc ('\n');			/* terminate the dotted line */
#endif

		/* now check for done signal */
		ts = get_timer (0);		/* get current time */
		ret_val = FPGA_SUCCESS;
York Sun's avatar
York Sun committed
403
		(*fn->wr) (true, true, cookie);
wdenk's avatar
wdenk committed
404 405 406 407

		while (! (*fn->done) (cookie)) {

			CONFIG_FPGA_DELAY ();
York Sun's avatar
York Sun committed
408
			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
wdenk's avatar
wdenk committed
409
			CONFIG_FPGA_DELAY ();
York Sun's avatar
York Sun committed
410
			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
wdenk's avatar
wdenk committed
411

wdenk's avatar
wdenk committed
412 413
			putc ('*');

414
			if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) {	/* check the time */
wdenk's avatar
wdenk committed
415 416 417 418 419 420 421
				puts ("** Timeout waiting for DONE to clear.\n");
				ret_val = FPGA_FAIL;
				break;
			}
		}
		putc ('\n');			/* terminate the dotted line */

422 423 424
		/*
		 * Run the post configuration function if there is one.
		 */
425
		if (*fn->post)
426 427
			(*fn->post) (cookie);

428
#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
429
		if (ret_val == FPGA_SUCCESS)
wdenk's avatar
wdenk committed
430
			puts ("Done.\n");
431
		else
wdenk's avatar
wdenk committed
432 433 434 435 436 437 438 439
			puts ("Fail.\n");
#endif

	} else {
		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
	}

	return ret_val;
wdenk's avatar
wdenk committed
440 441
}

442
static int Spartan2_ss_dump(Xilinx_desc *desc, const void *buf, size_t bsize)
wdenk's avatar
wdenk committed
443
{
wdenk's avatar
wdenk committed
444 445
	/* Readback is only available through the Slave Parallel and         */
	/* boundary-scan interfaces.                                         */
wdenk's avatar
wdenk committed
446
	printf ("%s: Slave Serial Dumping is unavailable\n",
wdenk's avatar
wdenk committed
447 448 449
			__FUNCTION__);
	return FPGA_FAIL;
}