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