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