1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * (C) Copyright 2002
4 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
5 */
6
7/*
8 * Configuration support for Xilinx Spartan3 devices.  Based
9 * on spartan2.c (Rich Ireland, rireland@enterasys.com).
10 */
11
12#define LOG_CATEGORY UCLASS_FPGA
13
14#include <config.h>		/* core U-Boot definitions */
15#include <log.h>
16#include <time.h>
17#include <spartan3.h>		/* Spartan-II device family */
18
19/* Note: The assumption is that we cannot possibly run fast enough to
20 * overrun the device (the Slave Parallel mode can free run at 50MHz).
21 * If there is a need to operate slower, define CFG_FPGA_DELAY in
22 * the board config file to slow things down.
23 */
24#ifndef CFG_FPGA_DELAY
25#define CFG_FPGA_DELAY()
26#endif
27
28#ifndef CFG_SYS_FPGA_WAIT
29#define CFG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100	/* 10 ms */
30#endif
31
32static int spartan3_sp_load(xilinx_desc *desc, const void *buf, size_t bsize);
33static int spartan3_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize);
34/* static int spartan3_sp_info(xilinx_desc *desc ); */
35
36static int spartan3_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
37static int spartan3_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
38/* static int spartan3_ss_info(xilinx_desc *desc); */
39
40/* ------------------------------------------------------------------------- */
41/* Spartan-II Generic Implementation */
42static int spartan3_load(xilinx_desc *desc, const void *buf, size_t bsize,
43			 bitstream_type bstype, int flags)
44{
45	int ret_val = FPGA_FAIL;
46
47	switch (desc->iface) {
48	case slave_serial:
49		log_debug("Launching Slave Serial Load\n");
50		ret_val = spartan3_ss_load(desc, buf, bsize);
51		break;
52
53	case slave_parallel:
54		log_debug("Launching Slave Parallel Load\n");
55		ret_val = spartan3_sp_load(desc, buf, bsize);
56		break;
57
58	default:
59		printf ("%s: Unsupported interface type, %d\n",
60				__FUNCTION__, desc->iface);
61	}
62
63	return ret_val;
64}
65
66static int spartan3_dump(xilinx_desc *desc, const void *buf, size_t bsize)
67{
68	int ret_val = FPGA_FAIL;
69
70	switch (desc->iface) {
71	case slave_serial:
72		log_debug("Launching Slave Serial Dump\n");
73		ret_val = spartan3_ss_dump(desc, buf, bsize);
74		break;
75
76	case slave_parallel:
77		log_debug("Launching Slave Parallel Dump\n");
78		ret_val = spartan3_sp_dump(desc, buf, bsize);
79		break;
80
81	default:
82		printf ("%s: Unsupported interface type, %d\n",
83				__FUNCTION__, desc->iface);
84	}
85
86	return ret_val;
87}
88
89static int spartan3_info(xilinx_desc *desc)
90{
91	return FPGA_SUCCESS;
92}
93
94
95/* ------------------------------------------------------------------------- */
96/* Spartan-II Slave Parallel Generic Implementation */
97
98static int spartan3_sp_load(xilinx_desc *desc, const void *buf, size_t bsize)
99{
100	int ret_val = FPGA_FAIL;	/* assume the worst */
101	xilinx_spartan3_slave_parallel_fns *fn = desc->iface_fns;
102
103	log_debug("start with interface functions @ 0x%p\n", fn);
104
105	if (fn) {
106		size_t bytecount = 0;
107		unsigned char *data = (unsigned char *) buf;
108		int cookie = desc->cookie;	/* make a local copy */
109		unsigned long ts;		/* timestamp */
110
111		log_debug("Function Table:\n"
112			  "ptr:\t0x%p\n"
113			  "struct: 0x%p\n"
114			  "pre: 0x%p\n"
115			  "pgm:\t0x%p\n"
116			  "init:\t0x%p\n"
117			  "err:\t0x%p\n"
118			  "clk:\t0x%p\n"
119			  "cs:\t0x%p\n"
120			  "wr:\t0x%p\n"
121			  "read data:\t0x%p\n"
122			  "write data:\t0x%p\n"
123			  "busy:\t0x%p\n"
124			  "abort:\t0x%p\n"
125			  "post:\t0x%p\n\n",
126			  &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
127			  fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
128			  fn->abort, fn->post);
129
130		/*
131		 * This code is designed to emulate the "Express Style"
132		 * Continuous Data Loading in Slave Parallel Mode for
133		 * the Spartan-II Family.
134		 */
135#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
136		printf ("Loading FPGA Device %d...\n", cookie);
137#endif
138		/*
139		 * Run the pre configuration function if there is one.
140		 */
141		if (*fn->pre) {
142			(*fn->pre) (cookie);
143		}
144
145		/* Establish the initial state */
146		(*fn->pgm) (true, true, cookie);	/* Assert the program, commit */
147
148		/* Get ready for the burn */
149		CFG_FPGA_DELAY ();
150		(*fn->pgm) (false, true, cookie);	/* Deassert the program, commit */
151
152		ts = get_timer (0);		/* get current time */
153		/* Now wait for INIT and BUSY to go high */
154		do {
155			CFG_FPGA_DELAY ();
156			if (get_timer (ts) > CFG_SYS_FPGA_WAIT) {	/* check the time */
157				puts ("** Timeout waiting for INIT to clear.\n");
158				(*fn->abort) (cookie);	/* abort the burn */
159				return FPGA_FAIL;
160			}
161		} while ((*fn->init) (cookie) && (*fn->busy) (cookie));
162
163		(*fn->wr) (true, true, cookie); /* Assert write, commit */
164		(*fn->cs) (true, true, cookie); /* Assert chip select, commit */
165		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
166
167		/* Load the data */
168		while (bytecount < bsize) {
169			/* XXX - do we check for an Ctrl-C press in here ??? */
170			/* XXX - Check the error bit? */
171
172			(*fn->wdata) (data[bytecount++], true, cookie); /* write the data */
173			CFG_FPGA_DELAY ();
174			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
175			CFG_FPGA_DELAY ();
176			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
177
178#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
179			ts = get_timer (0);	/* get current time */
180			while ((*fn->busy) (cookie)) {
181				/* XXX - we should have a check in here somewhere to
182				 * make sure we aren't busy forever... */
183
184				CFG_FPGA_DELAY ();
185				(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
186				CFG_FPGA_DELAY ();
187				(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
188
189				if (get_timer (ts) > CFG_SYS_FPGA_WAIT) {	/* check the time */
190					puts ("** Timeout waiting for BUSY to clear.\n");
191					(*fn->abort) (cookie);	/* abort the burn */
192					return FPGA_FAIL;
193				}
194			}
195#endif
196
197#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
198			if (bytecount % (bsize / 40) == 0)
199				putc ('.');		/* let them know we are alive */
200#endif
201		}
202
203		CFG_FPGA_DELAY ();
204		(*fn->cs) (false, true, cookie);	/* Deassert the chip select */
205		(*fn->wr) (false, true, cookie);	/* Deassert the write pin */
206
207#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
208		putc ('\n');			/* terminate the dotted line */
209#endif
210
211		/* now check for done signal */
212		ts = get_timer (0);		/* get current time */
213		ret_val = FPGA_SUCCESS;
214		while ((*fn->done) (cookie) == FPGA_FAIL) {
215			/* XXX - we should have a check in here somewhere to
216			 * make sure we aren't busy forever... */
217
218			CFG_FPGA_DELAY ();
219			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
220			CFG_FPGA_DELAY ();
221			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
222
223			if (get_timer (ts) > CFG_SYS_FPGA_WAIT) {	/* check the time */
224				puts ("** Timeout waiting for DONE to clear.\n");
225				(*fn->abort) (cookie);	/* abort the burn */
226				ret_val = FPGA_FAIL;
227				break;
228			}
229		}
230
231		/*
232		 * Run the post configuration function if there is one.
233		 */
234		if (*fn->post)
235			(*fn->post) (cookie);
236
237#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
238		if (ret_val == FPGA_SUCCESS)
239			puts ("Done.\n");
240		else
241			puts ("Fail.\n");
242#endif
243
244	} else {
245		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
246	}
247
248	return ret_val;
249}
250
251static int spartan3_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize)
252{
253	int ret_val = FPGA_FAIL;	/* assume the worst */
254	xilinx_spartan3_slave_parallel_fns *fn = desc->iface_fns;
255
256	if (fn) {
257		unsigned char *data = (unsigned char *) buf;
258		size_t bytecount = 0;
259		int cookie = desc->cookie;	/* make a local copy */
260
261		printf ("Starting Dump of FPGA Device %d...\n", cookie);
262
263		(*fn->cs) (true, true, cookie); /* Assert chip select, commit */
264		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
265
266		/* dump the data */
267		while (bytecount < bsize) {
268			/* XXX - do we check for an Ctrl-C press in here ??? */
269
270			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
271			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
272			(*fn->rdata) (&(data[bytecount++]), cookie);	/* read the data */
273#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
274			if (bytecount % (bsize / 40) == 0)
275				putc ('.');		/* let them know we are alive */
276#endif
277		}
278
279		(*fn->cs) (false, false, cookie);	/* Deassert the chip select */
280		(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
281		(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
282
283#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
284		putc ('\n');			/* terminate the dotted line */
285#endif
286		puts ("Done.\n");
287
288		/* XXX - checksum the data? */
289	} else {
290		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
291	}
292
293	return ret_val;
294}
295
296
297/* ------------------------------------------------------------------------- */
298
299static int spartan3_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
300{
301	int ret_val = FPGA_FAIL;	/* assume the worst */
302	xilinx_spartan3_slave_serial_fns *fn = desc->iface_fns;
303	int i;
304	unsigned char val;
305
306	log_debug("start with interface functions @ 0x%p\n", fn);
307
308	if (fn) {
309		size_t bytecount = 0;
310		unsigned char *data = (unsigned char *) buf;
311		int cookie = desc->cookie;	/* make a local copy */
312		unsigned long ts;		/* timestamp */
313
314		log_debug("Function Table:\n"
315			  "ptr:\t0x%p\n"
316			  "struct: 0x%p\n"
317			  "pgm:\t0x%p\n"
318			  "init:\t0x%p\n"
319			  "clk:\t0x%p\n"
320			  "wr:\t0x%p\n"
321			  "done:\t0x%p\n\n",
322			  &fn, fn, fn->pgm, fn->init,
323			  fn->clk, fn->wr, fn->done);
324#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
325		printf ("Loading FPGA Device %d...\n", cookie);
326#endif
327
328		/*
329		 * Run the pre configuration function if there is one.
330		 */
331		if (*fn->pre) {
332			(*fn->pre) (cookie);
333		}
334
335		/* Establish the initial state */
336		(*fn->pgm) (true, true, cookie);	/* Assert the program, commit */
337
338		/* Wait for INIT state (init low)                            */
339		ts = get_timer (0);		/* get current time */
340		do {
341			CFG_FPGA_DELAY ();
342			if (get_timer (ts) > CFG_SYS_FPGA_WAIT) {	/* check the time */
343				puts ("** Timeout waiting for INIT to start.\n");
344				if (*fn->abort)
345					(*fn->abort) (cookie);
346				return FPGA_FAIL;
347			}
348		} while (!(*fn->init) (cookie));
349
350		/* Get ready for the burn */
351		CFG_FPGA_DELAY ();
352		(*fn->pgm) (false, true, cookie);	/* Deassert the program, commit */
353
354		ts = get_timer (0);		/* get current time */
355		/* Now wait for INIT to go high */
356		do {
357			CFG_FPGA_DELAY ();
358			if (get_timer (ts) > CFG_SYS_FPGA_WAIT) {	/* check the time */
359				puts ("** Timeout waiting for INIT to clear.\n");
360				if (*fn->abort)
361					(*fn->abort) (cookie);
362				return FPGA_FAIL;
363			}
364		} while ((*fn->init) (cookie));
365
366		/* Load the data */
367		if(*fn->bwr)
368			(*fn->bwr) (data, bsize, true, cookie);
369		else {
370			while (bytecount < bsize) {
371
372				/* Xilinx detects an error if INIT goes low (active)
373				   while DONE is low (inactive) */
374				if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
375					puts ("** CRC error during FPGA load.\n");
376					if (*fn->abort)
377						(*fn->abort) (cookie);
378					return (FPGA_FAIL);
379				}
380				val = data [bytecount ++];
381				i = 8;
382				do {
383					/* Deassert the clock */
384					(*fn->clk) (false, true, cookie);
385					CFG_FPGA_DELAY ();
386					/* Write data */
387					(*fn->wr) ((val & 0x80), true, cookie);
388					CFG_FPGA_DELAY ();
389					/* Assert the clock */
390					(*fn->clk) (true, true, cookie);
391					CFG_FPGA_DELAY ();
392					val <<= 1;
393					i --;
394				} while (i > 0);
395
396#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
397				if (bytecount % (bsize / 40) == 0)
398					putc ('.');		/* let them know we are alive */
399#endif
400			}
401		}
402
403		CFG_FPGA_DELAY ();
404
405#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
406		putc ('\n');			/* terminate the dotted line */
407#endif
408
409		/* now check for done signal */
410		ts = get_timer (0);		/* get current time */
411		ret_val = FPGA_SUCCESS;
412		(*fn->wr) (true, true, cookie);
413
414		while (! (*fn->done) (cookie)) {
415			/* XXX - we should have a check in here somewhere to
416			 * make sure we aren't busy forever... */
417
418			CFG_FPGA_DELAY ();
419			(*fn->clk) (false, true, cookie);	/* Deassert the clock pin */
420			CFG_FPGA_DELAY ();
421			(*fn->clk) (true, true, cookie);	/* Assert the clock pin */
422
423			putc ('*');
424
425			if (get_timer (ts) > CFG_SYS_FPGA_WAIT) {	/* check the time */
426				puts ("** Timeout waiting for DONE to clear.\n");
427				ret_val = FPGA_FAIL;
428				break;
429			}
430		}
431		putc ('\n');			/* terminate the dotted line */
432
433		/*
434		 * Run the post configuration function if there is one.
435		 */
436		if (*fn->post)
437			(*fn->post) (cookie);
438
439#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
440		if (ret_val == FPGA_SUCCESS)
441			puts ("Done.\n");
442		else
443			puts ("Fail.\n");
444#endif
445
446	} else {
447		printf ("%s: NULL Interface function table!\n", __FUNCTION__);
448	}
449
450	return ret_val;
451}
452
453static int spartan3_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
454{
455	/* Readback is only available through the Slave Parallel and         */
456	/* boundary-scan interfaces.                                         */
457	printf ("%s: Slave Serial Dumping is unavailable\n",
458			__FUNCTION__);
459	return FPGA_FAIL;
460}
461
462struct xilinx_fpga_op spartan3_op = {
463	.load = spartan3_load,
464	.dump = spartan3_dump,
465	.info = spartan3_info,
466};
467