Commit 875c78934ee252744be1e5b2a9ad7ec5df239239
1 parent
db421e6451
Exists in
master
and in
54 other branches
Add Xilinx Spartan3 family FPGA support
Patch by Kurt Stremerch, 14 February 2005
Showing 6 changed files with 809 additions and 1 deletions Side-by-side Diff
CHANGELOG
... | ... | @@ -2,6 +2,9 @@ |
2 | 2 | Changes for U-Boot 1.1.4: |
3 | 3 | ====================================================================== |
4 | 4 | |
5 | +* Add Xilinx Spartan3 family FPGA support | |
6 | + Patch by Kurt Stremerch, 14 February 2005 | |
7 | + | |
5 | 8 | * Fix drivers/cfi_flash.c: use info->reset_cmd instead of FLASH_CMD_RESET |
6 | 9 | Patch by Zachary Landau, 11 Feb 2005 |
7 | 10 |
common/Makefile
... | ... | @@ -49,7 +49,7 @@ |
49 | 49 | flash.o fpga.o \ |
50 | 50 | hush.o kgdb.o lcd.o lists.o lynxkdi.o \ |
51 | 51 | memsize.o miiphybb.o miiphyutil.o \ |
52 | - s_record.o serial.o soft_i2c.o soft_spi.o spartan2.o \ | |
52 | + s_record.o serial.o soft_i2c.o soft_spi.o spartan2.o spartan3.o \ | |
53 | 53 | usb.o usb_kbd.o usb_storage.o \ |
54 | 54 | virtex2.o xilinx.o |
55 | 55 |
common/spartan3.c
1 | +/* | |
2 | + * (C) Copyright 2002 | |
3 | + * Rich Ireland, Enterasys Networks, rireland@enterasys.com. | |
4 | + * | |
5 | + * See file CREDITS for list of people who contributed to this | |
6 | + * project. | |
7 | + * | |
8 | + * This program is free software; you can redistribute it and/or | |
9 | + * modify it under the terms of the GNU General Public License as | |
10 | + * published by the Free Software Foundation; either version 2 of | |
11 | + * the License, or (at your option) any later version. | |
12 | + * | |
13 | + * This program is distributed in the hope that it will be useful, | |
14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | + * GNU General Public License for more details. | |
17 | + * | |
18 | + * You should have received a copy of the GNU General Public License | |
19 | + * along with this program; if not, write to the Free Software | |
20 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | + * MA 02111-1307 USA | |
22 | + * | |
23 | + */ | |
24 | + | |
25 | +/* | |
26 | + * Configuration support for Xilinx Spartan3 devices. Based | |
27 | + * on spartan2.c (Rich Ireland, rireland@enterasys.com). | |
28 | + */ | |
29 | + | |
30 | +#include <common.h> /* core U-Boot definitions */ | |
31 | +#include <spartan3.h> /* Spartan-II device family */ | |
32 | + | |
33 | +#if (CONFIG_FPGA & (CFG_XILINX | CFG_SPARTAN3)) | |
34 | + | |
35 | +/* Define FPGA_DEBUG to get debug printf's */ | |
36 | +#ifdef FPGA_DEBUG | |
37 | +#define PRINTF(fmt,args...) printf (fmt ,##args) | |
38 | +#else | |
39 | +#define PRINTF(fmt,args...) | |
40 | +#endif | |
41 | + | |
42 | +#undef CFG_FPGA_CHECK_BUSY | |
43 | +#undef CFG_FPGA_PROG_FEEDBACK | |
44 | + | |
45 | +/* Note: The assumption is that we cannot possibly run fast enough to | |
46 | + * overrun the device (the Slave Parallel mode can free run at 50MHz). | |
47 | + * If there is a need to operate slower, define CONFIG_FPGA_DELAY in | |
48 | + * the board config file to slow things down. | |
49 | + */ | |
50 | +#ifndef CONFIG_FPGA_DELAY | |
51 | +#define CONFIG_FPGA_DELAY() | |
52 | +#endif | |
53 | + | |
54 | +#ifndef CFG_FPGA_WAIT | |
55 | +#define CFG_FPGA_WAIT CFG_HZ/100 /* 10 ms */ | |
56 | +#endif | |
57 | + | |
58 | +static int Spartan3_sp_load( Xilinx_desc *desc, void *buf, size_t bsize ); | |
59 | +static int Spartan3_sp_dump( Xilinx_desc *desc, void *buf, size_t bsize ); | |
60 | +/* static int Spartan3_sp_info( Xilinx_desc *desc ); */ | |
61 | +static int Spartan3_sp_reloc( Xilinx_desc *desc, ulong reloc_offset ); | |
62 | + | |
63 | +static int Spartan3_ss_load( Xilinx_desc *desc, void *buf, size_t bsize ); | |
64 | +static int Spartan3_ss_dump( Xilinx_desc *desc, void *buf, size_t bsize ); | |
65 | +/* static int Spartan3_ss_info( Xilinx_desc *desc ); */ | |
66 | +static int Spartan3_ss_reloc( Xilinx_desc *desc, ulong reloc_offset ); | |
67 | + | |
68 | +/* ------------------------------------------------------------------------- */ | |
69 | +/* Spartan-II Generic Implementation */ | |
70 | +int Spartan3_load (Xilinx_desc * desc, void *buf, size_t bsize) | |
71 | +{ | |
72 | + int ret_val = FPGA_FAIL; | |
73 | + | |
74 | + switch (desc->iface) { | |
75 | + case slave_serial: | |
76 | + PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__); | |
77 | + ret_val = Spartan3_ss_load (desc, buf, bsize); | |
78 | + break; | |
79 | + | |
80 | + case slave_parallel: | |
81 | + PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__); | |
82 | + ret_val = Spartan3_sp_load (desc, buf, bsize); | |
83 | + break; | |
84 | + | |
85 | + default: | |
86 | + printf ("%s: Unsupported interface type, %d\n", | |
87 | + __FUNCTION__, desc->iface); | |
88 | + } | |
89 | + | |
90 | + return ret_val; | |
91 | +} | |
92 | + | |
93 | +int Spartan3_dump (Xilinx_desc * desc, void *buf, size_t bsize) | |
94 | +{ | |
95 | + int ret_val = FPGA_FAIL; | |
96 | + | |
97 | + switch (desc->iface) { | |
98 | + case slave_serial: | |
99 | + PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__); | |
100 | + ret_val = Spartan3_ss_dump (desc, buf, bsize); | |
101 | + break; | |
102 | + | |
103 | + case slave_parallel: | |
104 | + PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__); | |
105 | + ret_val = Spartan3_sp_dump (desc, buf, bsize); | |
106 | + break; | |
107 | + | |
108 | + default: | |
109 | + printf ("%s: Unsupported interface type, %d\n", | |
110 | + __FUNCTION__, desc->iface); | |
111 | + } | |
112 | + | |
113 | + return ret_val; | |
114 | +} | |
115 | + | |
116 | +int Spartan3_info( Xilinx_desc *desc ) | |
117 | +{ | |
118 | + return FPGA_SUCCESS; | |
119 | +} | |
120 | + | |
121 | + | |
122 | +int Spartan3_reloc (Xilinx_desc * desc, ulong reloc_offset) | |
123 | +{ | |
124 | + int ret_val = FPGA_FAIL; /* assume a failure */ | |
125 | + | |
126 | + if (desc->family != Xilinx_Spartan3) { | |
127 | + printf ("%s: Unsupported family type, %d\n", | |
128 | + __FUNCTION__, desc->family); | |
129 | + return FPGA_FAIL; | |
130 | + } else | |
131 | + switch (desc->iface) { | |
132 | + case slave_serial: | |
133 | + ret_val = Spartan3_ss_reloc (desc, reloc_offset); | |
134 | + break; | |
135 | + | |
136 | + case slave_parallel: | |
137 | + ret_val = Spartan3_sp_reloc (desc, reloc_offset); | |
138 | + break; | |
139 | + | |
140 | + default: | |
141 | + printf ("%s: Unsupported interface type, %d\n", | |
142 | + __FUNCTION__, desc->iface); | |
143 | + } | |
144 | + | |
145 | + return ret_val; | |
146 | +} | |
147 | + | |
148 | + | |
149 | +/* ------------------------------------------------------------------------- */ | |
150 | +/* Spartan-II Slave Parallel Generic Implementation */ | |
151 | + | |
152 | +static int Spartan3_sp_load (Xilinx_desc * desc, void *buf, size_t bsize) | |
153 | +{ | |
154 | + int ret_val = FPGA_FAIL; /* assume the worst */ | |
155 | + Xilinx_Spartan3_Slave_Parallel_fns *fn = desc->iface_fns; | |
156 | + | |
157 | + PRINTF ("%s: start with interface functions @ 0x%p\n", | |
158 | + __FUNCTION__, fn); | |
159 | + | |
160 | + if (fn) { | |
161 | + size_t bytecount = 0; | |
162 | + unsigned char *data = (unsigned char *) buf; | |
163 | + int cookie = desc->cookie; /* make a local copy */ | |
164 | + unsigned long ts; /* timestamp */ | |
165 | + | |
166 | + PRINTF ("%s: Function Table:\n" | |
167 | + "ptr:\t0x%p\n" | |
168 | + "struct: 0x%p\n" | |
169 | + "pre: 0x%p\n" | |
170 | + "pgm:\t0x%p\n" | |
171 | + "init:\t0x%p\n" | |
172 | + "err:\t0x%p\n" | |
173 | + "clk:\t0x%p\n" | |
174 | + "cs:\t0x%p\n" | |
175 | + "wr:\t0x%p\n" | |
176 | + "read data:\t0x%p\n" | |
177 | + "write data:\t0x%p\n" | |
178 | + "busy:\t0x%p\n" | |
179 | + "abort:\t0x%p\n", | |
180 | + "post:\t0x%p\n\n", | |
181 | + __FUNCTION__, &fn, fn, fn->pre, fn->pgm, fn->init, fn->err, | |
182 | + fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy, | |
183 | + fn->abort, fn->post); | |
184 | + | |
185 | + /* | |
186 | + * This code is designed to emulate the "Express Style" | |
187 | + * Continuous Data Loading in Slave Parallel Mode for | |
188 | + * the Spartan-II Family. | |
189 | + */ | |
190 | +#ifdef CFG_FPGA_PROG_FEEDBACK | |
191 | + printf ("Loading FPGA Device %d...\n", cookie); | |
192 | +#endif | |
193 | + /* | |
194 | + * Run the pre configuration function if there is one. | |
195 | + */ | |
196 | + if (*fn->pre) { | |
197 | + (*fn->pre) (cookie); | |
198 | + } | |
199 | + | |
200 | + /* Establish the initial state */ | |
201 | + (*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */ | |
202 | + | |
203 | + /* Get ready for the burn */ | |
204 | + CONFIG_FPGA_DELAY (); | |
205 | + (*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */ | |
206 | + | |
207 | + ts = get_timer (0); /* get current time */ | |
208 | + /* Now wait for INIT and BUSY to go high */ | |
209 | + do { | |
210 | + CONFIG_FPGA_DELAY (); | |
211 | + if (get_timer (ts) > CFG_FPGA_WAIT) { /* check the time */ | |
212 | + puts ("** Timeout waiting for INIT to clear.\n"); | |
213 | + (*fn->abort) (cookie); /* abort the burn */ | |
214 | + return FPGA_FAIL; | |
215 | + } | |
216 | + } while ((*fn->init) (cookie) && (*fn->busy) (cookie)); | |
217 | + | |
218 | + (*fn->wr) (TRUE, TRUE, cookie); /* Assert write, commit */ | |
219 | + (*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */ | |
220 | + (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ | |
221 | + | |
222 | + /* Load the data */ | |
223 | + while (bytecount < bsize) { | |
224 | + /* XXX - do we check for an Ctrl-C press in here ??? */ | |
225 | + /* XXX - Check the error bit? */ | |
226 | + | |
227 | + (*fn->wdata) (data[bytecount++], TRUE, cookie); /* write the data */ | |
228 | + CONFIG_FPGA_DELAY (); | |
229 | + (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ | |
230 | + CONFIG_FPGA_DELAY (); | |
231 | + (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ | |
232 | + | |
233 | +#ifdef CFG_FPGA_CHECK_BUSY | |
234 | + ts = get_timer (0); /* get current time */ | |
235 | + while ((*fn->busy) (cookie)) { | |
236 | + /* XXX - we should have a check in here somewhere to | |
237 | + * make sure we aren't busy forever... */ | |
238 | + | |
239 | + CONFIG_FPGA_DELAY (); | |
240 | + (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ | |
241 | + CONFIG_FPGA_DELAY (); | |
242 | + (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ | |
243 | + | |
244 | + if (get_timer (ts) > CFG_FPGA_WAIT) { /* check the time */ | |
245 | + puts ("** Timeout waiting for BUSY to clear.\n"); | |
246 | + (*fn->abort) (cookie); /* abort the burn */ | |
247 | + return FPGA_FAIL; | |
248 | + } | |
249 | + } | |
250 | +#endif | |
251 | + | |
252 | +#ifdef CFG_FPGA_PROG_FEEDBACK | |
253 | + if (bytecount % (bsize / 40) == 0) | |
254 | + putc ('.'); /* let them know we are alive */ | |
255 | +#endif | |
256 | + } | |
257 | + | |
258 | + CONFIG_FPGA_DELAY (); | |
259 | + (*fn->cs) (FALSE, TRUE, cookie); /* Deassert the chip select */ | |
260 | + (*fn->wr) (FALSE, TRUE, cookie); /* Deassert the write pin */ | |
261 | + | |
262 | +#ifdef CFG_FPGA_PROG_FEEDBACK | |
263 | + putc ('\n'); /* terminate the dotted line */ | |
264 | +#endif | |
265 | + | |
266 | + /* now check for done signal */ | |
267 | + ts = get_timer (0); /* get current time */ | |
268 | + ret_val = FPGA_SUCCESS; | |
269 | + while ((*fn->done) (cookie) == FPGA_FAIL) { | |
270 | + /* XXX - we should have a check in here somewhere to | |
271 | + * make sure we aren't busy forever... */ | |
272 | + | |
273 | + CONFIG_FPGA_DELAY (); | |
274 | + (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ | |
275 | + CONFIG_FPGA_DELAY (); | |
276 | + (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ | |
277 | + | |
278 | + if (get_timer (ts) > CFG_FPGA_WAIT) { /* check the time */ | |
279 | + puts ("** Timeout waiting for DONE to clear.\n"); | |
280 | + (*fn->abort) (cookie); /* abort the burn */ | |
281 | + ret_val = FPGA_FAIL; | |
282 | + break; | |
283 | + } | |
284 | + } | |
285 | + | |
286 | + if (ret_val == FPGA_SUCCESS) { | |
287 | +#ifdef CFG_FPGA_PROG_FEEDBACK | |
288 | + puts ("Done.\n"); | |
289 | +#endif | |
290 | + } | |
291 | + /* | |
292 | + * Run the post configuration function if there is one. | |
293 | + */ | |
294 | + if (*fn->post) { | |
295 | + (*fn->post) (cookie); | |
296 | + } | |
297 | + | |
298 | + else { | |
299 | +#ifdef CFG_FPGA_PROG_FEEDBACK | |
300 | + puts ("Fail.\n"); | |
301 | +#endif | |
302 | + } | |
303 | + | |
304 | + } else { | |
305 | + printf ("%s: NULL Interface function table!\n", __FUNCTION__); | |
306 | + } | |
307 | + | |
308 | + return ret_val; | |
309 | +} | |
310 | + | |
311 | +static int Spartan3_sp_dump (Xilinx_desc * desc, void *buf, size_t bsize) | |
312 | +{ | |
313 | + int ret_val = FPGA_FAIL; /* assume the worst */ | |
314 | + Xilinx_Spartan3_Slave_Parallel_fns *fn = desc->iface_fns; | |
315 | + | |
316 | + if (fn) { | |
317 | + unsigned char *data = (unsigned char *) buf; | |
318 | + size_t bytecount = 0; | |
319 | + int cookie = desc->cookie; /* make a local copy */ | |
320 | + | |
321 | + printf ("Starting Dump of FPGA Device %d...\n", cookie); | |
322 | + | |
323 | + (*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */ | |
324 | + (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ | |
325 | + | |
326 | + /* dump the data */ | |
327 | + while (bytecount < bsize) { | |
328 | + /* XXX - do we check for an Ctrl-C press in here ??? */ | |
329 | + | |
330 | + (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ | |
331 | + (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ | |
332 | + (*fn->rdata) (&(data[bytecount++]), cookie); /* read the data */ | |
333 | +#ifdef CFG_FPGA_PROG_FEEDBACK | |
334 | + if (bytecount % (bsize / 40) == 0) | |
335 | + putc ('.'); /* let them know we are alive */ | |
336 | +#endif | |
337 | + } | |
338 | + | |
339 | + (*fn->cs) (FALSE, FALSE, cookie); /* Deassert the chip select */ | |
340 | + (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ | |
341 | + (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ | |
342 | + | |
343 | +#ifdef CFG_FPGA_PROG_FEEDBACK | |
344 | + putc ('\n'); /* terminate the dotted line */ | |
345 | +#endif | |
346 | + puts ("Done.\n"); | |
347 | + | |
348 | + /* XXX - checksum the data? */ | |
349 | + } else { | |
350 | + printf ("%s: NULL Interface function table!\n", __FUNCTION__); | |
351 | + } | |
352 | + | |
353 | + return ret_val; | |
354 | +} | |
355 | + | |
356 | + | |
357 | +static int Spartan3_sp_reloc (Xilinx_desc * desc, ulong reloc_offset) | |
358 | +{ | |
359 | + int ret_val = FPGA_FAIL; /* assume the worst */ | |
360 | + Xilinx_Spartan3_Slave_Parallel_fns *fn_r, *fn = | |
361 | + (Xilinx_Spartan3_Slave_Parallel_fns *) (desc->iface_fns); | |
362 | + | |
363 | + if (fn) { | |
364 | + ulong addr; | |
365 | + | |
366 | + /* Get the relocated table address */ | |
367 | + addr = (ulong) fn + reloc_offset; | |
368 | + fn_r = (Xilinx_Spartan3_Slave_Parallel_fns *) addr; | |
369 | + | |
370 | + if (!fn_r->relocated) { | |
371 | + | |
372 | + if (memcmp (fn_r, fn, | |
373 | + sizeof (Xilinx_Spartan3_Slave_Parallel_fns)) | |
374 | + == 0) { | |
375 | + /* good copy of the table, fix the descriptor pointer */ | |
376 | + desc->iface_fns = fn_r; | |
377 | + } else { | |
378 | + PRINTF ("%s: Invalid function table at 0x%p\n", | |
379 | + __FUNCTION__, fn_r); | |
380 | + return FPGA_FAIL; | |
381 | + } | |
382 | + | |
383 | + PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__, | |
384 | + desc); | |
385 | + | |
386 | + addr = (ulong) (fn->pre) + reloc_offset; | |
387 | + fn_r->pre = (Xilinx_pre_fn) addr; | |
388 | + | |
389 | + addr = (ulong) (fn->pgm) + reloc_offset; | |
390 | + fn_r->pgm = (Xilinx_pgm_fn) addr; | |
391 | + | |
392 | + addr = (ulong) (fn->init) + reloc_offset; | |
393 | + fn_r->init = (Xilinx_init_fn) addr; | |
394 | + | |
395 | + addr = (ulong) (fn->done) + reloc_offset; | |
396 | + fn_r->done = (Xilinx_done_fn) addr; | |
397 | + | |
398 | + addr = (ulong) (fn->clk) + reloc_offset; | |
399 | + fn_r->clk = (Xilinx_clk_fn) addr; | |
400 | + | |
401 | + addr = (ulong) (fn->err) + reloc_offset; | |
402 | + fn_r->err = (Xilinx_err_fn) addr; | |
403 | + | |
404 | + addr = (ulong) (fn->cs) + reloc_offset; | |
405 | + fn_r->cs = (Xilinx_cs_fn) addr; | |
406 | + | |
407 | + addr = (ulong) (fn->wr) + reloc_offset; | |
408 | + fn_r->wr = (Xilinx_wr_fn) addr; | |
409 | + | |
410 | + addr = (ulong) (fn->rdata) + reloc_offset; | |
411 | + fn_r->rdata = (Xilinx_rdata_fn) addr; | |
412 | + | |
413 | + addr = (ulong) (fn->wdata) + reloc_offset; | |
414 | + fn_r->wdata = (Xilinx_wdata_fn) addr; | |
415 | + | |
416 | + addr = (ulong) (fn->busy) + reloc_offset; | |
417 | + fn_r->busy = (Xilinx_busy_fn) addr; | |
418 | + | |
419 | + addr = (ulong) (fn->abort) + reloc_offset; | |
420 | + fn_r->abort = (Xilinx_abort_fn) addr; | |
421 | + | |
422 | + addr = (ulong) (fn->post) + reloc_offset; | |
423 | + fn_r->post = (Xilinx_post_fn) addr; | |
424 | + | |
425 | + fn_r->relocated = TRUE; | |
426 | + | |
427 | + } else { | |
428 | + /* this table has already been moved */ | |
429 | + /* XXX - should check to see if the descriptor is correct */ | |
430 | + desc->iface_fns = fn_r; | |
431 | + } | |
432 | + | |
433 | + ret_val = FPGA_SUCCESS; | |
434 | + } else { | |
435 | + printf ("%s: NULL Interface function table!\n", __FUNCTION__); | |
436 | + } | |
437 | + | |
438 | + return ret_val; | |
439 | + | |
440 | +} | |
441 | + | |
442 | +/* ------------------------------------------------------------------------- */ | |
443 | + | |
444 | +static int Spartan3_ss_load (Xilinx_desc * desc, void *buf, size_t bsize) | |
445 | +{ | |
446 | + int ret_val = FPGA_FAIL; /* assume the worst */ | |
447 | + Xilinx_Spartan3_Slave_Serial_fns *fn = desc->iface_fns; | |
448 | + int i; | |
449 | + char val; | |
450 | + | |
451 | + PRINTF ("%s: start with interface functions @ 0x%p\n", | |
452 | + __FUNCTION__, fn); | |
453 | + | |
454 | + if (fn) { | |
455 | + size_t bytecount = 0; | |
456 | + unsigned char *data = (unsigned char *) buf; | |
457 | + int cookie = desc->cookie; /* make a local copy */ | |
458 | + unsigned long ts; /* timestamp */ | |
459 | + | |
460 | + PRINTF ("%s: Function Table:\n" | |
461 | + "ptr:\t0x%p\n" | |
462 | + "struct: 0x%p\n" | |
463 | + "pgm:\t0x%p\n" | |
464 | + "init:\t0x%p\n" | |
465 | + "clk:\t0x%p\n" | |
466 | + "wr:\t0x%p\n" | |
467 | + "done:\t0x%p\n\n", | |
468 | + __FUNCTION__, &fn, fn, fn->pgm, fn->init, | |
469 | + fn->clk, fn->wr, fn->done); | |
470 | +#ifdef CFG_FPGA_PROG_FEEDBACK | |
471 | + printf ("Loading FPGA Device %d...\n", cookie); | |
472 | +#endif | |
473 | + | |
474 | + /* | |
475 | + * Run the pre configuration function if there is one. | |
476 | + */ | |
477 | + if (*fn->pre) { | |
478 | + (*fn->pre) (cookie); | |
479 | + } | |
480 | + | |
481 | + /* Establish the initial state */ | |
482 | + (*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */ | |
483 | + | |
484 | + /* Wait for INIT state (init low) */ | |
485 | + ts = get_timer (0); /* get current time */ | |
486 | + do { | |
487 | + CONFIG_FPGA_DELAY (); | |
488 | + if (get_timer (ts) > CFG_FPGA_WAIT) { /* check the time */ | |
489 | + puts ("** Timeout waiting for INIT to start.\n"); | |
490 | + return FPGA_FAIL; | |
491 | + } | |
492 | + } while (!(*fn->init) (cookie)); | |
493 | + | |
494 | + /* Get ready for the burn */ | |
495 | + CONFIG_FPGA_DELAY (); | |
496 | + (*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */ | |
497 | + | |
498 | + ts = get_timer (0); /* get current time */ | |
499 | + /* Now wait for INIT to go high */ | |
500 | + do { | |
501 | + CONFIG_FPGA_DELAY (); | |
502 | + if (get_timer (ts) > CFG_FPGA_WAIT) { /* check the time */ | |
503 | + puts ("** Timeout waiting for INIT to clear.\n"); | |
504 | + return FPGA_FAIL; | |
505 | + } | |
506 | + } while ((*fn->init) (cookie)); | |
507 | + | |
508 | + /* Load the data */ | |
509 | + while (bytecount < bsize) { | |
510 | + | |
511 | + /* Xilinx detects an error if INIT goes low (active) | |
512 | + while DONE is low (inactive) */ | |
513 | + if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) { | |
514 | + puts ("** CRC error during FPGA load.\n"); | |
515 | + return (FPGA_FAIL); | |
516 | + } | |
517 | + val = data [bytecount ++]; | |
518 | + i = 8; | |
519 | + do { | |
520 | + /* Deassert the clock */ | |
521 | + (*fn->clk) (FALSE, TRUE, cookie); | |
522 | + CONFIG_FPGA_DELAY (); | |
523 | + /* Write data */ | |
524 | + (*fn->wr) ((val < 0), TRUE, cookie); | |
525 | + CONFIG_FPGA_DELAY (); | |
526 | + /* Assert the clock */ | |
527 | + (*fn->clk) (TRUE, TRUE, cookie); | |
528 | + CONFIG_FPGA_DELAY (); | |
529 | + val <<= 1; | |
530 | + i --; | |
531 | + } while (i > 0); | |
532 | + | |
533 | +#ifdef CFG_FPGA_PROG_FEEDBACK | |
534 | + if (bytecount % (bsize / 40) == 0) | |
535 | + putc ('.'); /* let them know we are alive */ | |
536 | +#endif | |
537 | + } | |
538 | + | |
539 | + CONFIG_FPGA_DELAY (); | |
540 | + | |
541 | +#ifdef CFG_FPGA_PROG_FEEDBACK | |
542 | + putc ('\n'); /* terminate the dotted line */ | |
543 | +#endif | |
544 | + | |
545 | + /* now check for done signal */ | |
546 | + ts = get_timer (0); /* get current time */ | |
547 | + ret_val = FPGA_SUCCESS; | |
548 | + (*fn->wr) (TRUE, TRUE, cookie); | |
549 | + | |
550 | + while (! (*fn->done) (cookie)) { | |
551 | + /* XXX - we should have a check in here somewhere to | |
552 | + * make sure we aren't busy forever... */ | |
553 | + | |
554 | + CONFIG_FPGA_DELAY (); | |
555 | + (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */ | |
556 | + CONFIG_FPGA_DELAY (); | |
557 | + (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */ | |
558 | + | |
559 | + putc ('*'); | |
560 | + | |
561 | + if (get_timer (ts) > CFG_FPGA_WAIT) { /* check the time */ | |
562 | + puts ("** Timeout waiting for DONE to clear.\n"); | |
563 | + ret_val = FPGA_FAIL; | |
564 | + break; | |
565 | + } | |
566 | + } | |
567 | + putc ('\n'); /* terminate the dotted line */ | |
568 | + | |
569 | +#ifdef CFG_FPGA_PROG_FEEDBACK | |
570 | + if (ret_val == FPGA_SUCCESS) { | |
571 | + puts ("Done.\n"); | |
572 | + } | |
573 | + else { | |
574 | + puts ("Fail.\n"); | |
575 | + } | |
576 | +#endif | |
577 | + | |
578 | + } else { | |
579 | + printf ("%s: NULL Interface function table!\n", __FUNCTION__); | |
580 | + } | |
581 | + | |
582 | + return ret_val; | |
583 | +} | |
584 | + | |
585 | +static int Spartan3_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize) | |
586 | +{ | |
587 | + /* Readback is only available through the Slave Parallel and */ | |
588 | + /* boundary-scan interfaces. */ | |
589 | + printf ("%s: Slave Serial Dumping is unavailable\n", | |
590 | + __FUNCTION__); | |
591 | + return FPGA_FAIL; | |
592 | +} | |
593 | + | |
594 | +static int Spartan3_ss_reloc (Xilinx_desc * desc, ulong reloc_offset) | |
595 | +{ | |
596 | + int ret_val = FPGA_FAIL; /* assume the worst */ | |
597 | + Xilinx_Spartan3_Slave_Serial_fns *fn_r, *fn = | |
598 | + (Xilinx_Spartan3_Slave_Serial_fns *) (desc->iface_fns); | |
599 | + | |
600 | + if (fn) { | |
601 | + ulong addr; | |
602 | + | |
603 | + /* Get the relocated table address */ | |
604 | + addr = (ulong) fn + reloc_offset; | |
605 | + fn_r = (Xilinx_Spartan3_Slave_Serial_fns *) addr; | |
606 | + | |
607 | + if (!fn_r->relocated) { | |
608 | + | |
609 | + if (memcmp (fn_r, fn, | |
610 | + sizeof (Xilinx_Spartan3_Slave_Serial_fns)) | |
611 | + == 0) { | |
612 | + /* good copy of the table, fix the descriptor pointer */ | |
613 | + desc->iface_fns = fn_r; | |
614 | + } else { | |
615 | + PRINTF ("%s: Invalid function table at 0x%p\n", | |
616 | + __FUNCTION__, fn_r); | |
617 | + return FPGA_FAIL; | |
618 | + } | |
619 | + | |
620 | + PRINTF ("%s: Relocating descriptor at 0x%p\n", __FUNCTION__, | |
621 | + desc); | |
622 | + | |
623 | + addr = (ulong) (fn->pre) + reloc_offset; | |
624 | + fn_r->pre = (Xilinx_pre_fn) addr; | |
625 | + | |
626 | + addr = (ulong) (fn->pgm) + reloc_offset; | |
627 | + fn_r->pgm = (Xilinx_pgm_fn) addr; | |
628 | + | |
629 | + addr = (ulong) (fn->init) + reloc_offset; | |
630 | + fn_r->init = (Xilinx_init_fn) addr; | |
631 | + | |
632 | + addr = (ulong) (fn->done) + reloc_offset; | |
633 | + fn_r->done = (Xilinx_done_fn) addr; | |
634 | + | |
635 | + addr = (ulong) (fn->clk) + reloc_offset; | |
636 | + fn_r->clk = (Xilinx_clk_fn) addr; | |
637 | + | |
638 | + addr = (ulong) (fn->wr) + reloc_offset; | |
639 | + fn_r->wr = (Xilinx_wr_fn) addr; | |
640 | + | |
641 | + fn_r->relocated = TRUE; | |
642 | + | |
643 | + } else { | |
644 | + /* this table has already been moved */ | |
645 | + /* XXX - should check to see if the descriptor is correct */ | |
646 | + desc->iface_fns = fn_r; | |
647 | + } | |
648 | + | |
649 | + ret_val = FPGA_SUCCESS; | |
650 | + } else { | |
651 | + printf ("%s: NULL Interface function table!\n", __FUNCTION__); | |
652 | + } | |
653 | + | |
654 | + return ret_val; | |
655 | + | |
656 | +} | |
657 | + | |
658 | +#endif |
common/xilinx.c
... | ... | @@ -30,6 +30,7 @@ |
30 | 30 | #include <common.h> |
31 | 31 | #include <virtex2.h> |
32 | 32 | #include <spartan2.h> |
33 | +#include <spartan3.h> | |
33 | 34 | |
34 | 35 | #if (CONFIG_FPGA & CFG_FPGA_XILINX) |
35 | 36 | |
... | ... | @@ -67,6 +68,16 @@ |
67 | 68 | __FUNCTION__); |
68 | 69 | #endif |
69 | 70 | break; |
71 | + case Xilinx_Spartan3: | |
72 | +#if (CONFIG_FPGA & CFG_SPARTAN3) | |
73 | + PRINTF ("%s: Launching the Spartan-III Loader...\n", | |
74 | + __FUNCTION__); | |
75 | + ret_val = Spartan3_load (desc, buf, bsize); | |
76 | +#else | |
77 | + printf ("%s: No support for Spartan-III devices.\n", | |
78 | + __FUNCTION__); | |
79 | +#endif | |
80 | + break; | |
70 | 81 | case Xilinx_Virtex2: |
71 | 82 | #if (CONFIG_FPGA & CFG_VIRTEX2) |
72 | 83 | PRINTF ("%s: Launching the Virtex-II Loader...\n", |
... | ... | @@ -104,6 +115,16 @@ |
104 | 115 | __FUNCTION__); |
105 | 116 | #endif |
106 | 117 | break; |
118 | + case Xilinx_Spartan3: | |
119 | +#if (CONFIG_FPGA & CFG_SPARTAN3) | |
120 | + PRINTF ("%s: Launching the Spartan-III Reader...\n", | |
121 | + __FUNCTION__); | |
122 | + ret_val = Spartan3_dump (desc, buf, bsize); | |
123 | +#else | |
124 | + printf ("%s: No support for Spartan-III devices.\n", | |
125 | + __FUNCTION__); | |
126 | +#endif | |
127 | + break; | |
107 | 128 | case Xilinx_Virtex2: |
108 | 129 | #if (CONFIG_FPGA & CFG_VIRTEX2) |
109 | 130 | PRINTF ("%s: Launching the Virtex-II Reader...\n", |
... | ... | @@ -133,6 +154,9 @@ |
133 | 154 | case Xilinx_Spartan2: |
134 | 155 | printf ("Spartan-II\n"); |
135 | 156 | break; |
157 | + case Xilinx_Spartan3: | |
158 | + printf ("Spartan-III\n"); | |
159 | + break; | |
136 | 160 | case Xilinx_Virtex2: |
137 | 161 | printf ("Virtex-II\n"); |
138 | 162 | break; |
... | ... | @@ -182,6 +206,15 @@ |
182 | 206 | __FUNCTION__); |
183 | 207 | #endif |
184 | 208 | break; |
209 | + case Xilinx_Spartan3: | |
210 | +#if (CONFIG_FPGA & CFG_SPARTAN3) | |
211 | + Spartan3_info (desc); | |
212 | +#else | |
213 | + /* just in case */ | |
214 | + printf ("%s: No support for Spartan-III devices.\n", | |
215 | + __FUNCTION__); | |
216 | +#endif | |
217 | + break; | |
185 | 218 | case Xilinx_Virtex2: |
186 | 219 | #if (CONFIG_FPGA & CFG_VIRTEX2) |
187 | 220 | Virtex2_info (desc); |
... | ... | @@ -220,6 +253,14 @@ |
220 | 253 | ret_val = Spartan2_reloc (desc, reloc_offset); |
221 | 254 | #else |
222 | 255 | printf ("%s: No support for Spartan-II devices.\n", |
256 | + __FUNCTION__); | |
257 | +#endif | |
258 | + break; | |
259 | + case Xilinx_Spartan3: | |
260 | +#if (CONFIG_FPGA & CFG_SPARTAN3) | |
261 | + ret_val = Spartan3_reloc (desc, reloc_offset); | |
262 | +#else | |
263 | + printf ("%s: No support for Spartan-III devices.\n", | |
223 | 264 | __FUNCTION__); |
224 | 265 | #endif |
225 | 266 | break; |
include/spartan3.h
1 | +/* | |
2 | + * (C) Copyright 2002 | |
3 | + * Rich Ireland, Enterasys Networks, rireland@enterasys.com. | |
4 | + * | |
5 | + * See file CREDITS for list of people who contributed to this | |
6 | + * project. | |
7 | + * | |
8 | + * This program is free software; you can redistribute it and/or | |
9 | + * modify it under the terms of the GNU General Public License as | |
10 | + * published by the Free Software Foundation; either version 2 of | |
11 | + * the License, or (at your option) any later version. | |
12 | + * | |
13 | + * This program is distributed in the hope that it will be useful, | |
14 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | + * GNU General Public License for more details. | |
17 | + * | |
18 | + * You should have received a copy of the GNU General Public License | |
19 | + * along with this program; if not, write to the Free Software | |
20 | + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | + * MA 02111-1307 USA | |
22 | + * | |
23 | + */ | |
24 | + | |
25 | +#ifndef _SPARTAN3_H_ | |
26 | +#define _SPARTAN3_H_ | |
27 | + | |
28 | +#include <xilinx.h> | |
29 | + | |
30 | +extern int Spartan3_load( Xilinx_desc *desc, void *image, size_t size ); | |
31 | +extern int Spartan3_dump( Xilinx_desc *desc, void *buf, size_t bsize ); | |
32 | +extern int Spartan3_info( Xilinx_desc *desc ); | |
33 | +extern int Spartan3_reloc( Xilinx_desc *desc, ulong reloc_off ); | |
34 | + | |
35 | +/* Slave Parallel Implementation function table */ | |
36 | +typedef struct { | |
37 | + Xilinx_pre_fn pre; | |
38 | + Xilinx_pgm_fn pgm; | |
39 | + Xilinx_init_fn init; | |
40 | + Xilinx_err_fn err; | |
41 | + Xilinx_done_fn done; | |
42 | + Xilinx_clk_fn clk; | |
43 | + Xilinx_cs_fn cs; | |
44 | + Xilinx_wr_fn wr; | |
45 | + Xilinx_rdata_fn rdata; | |
46 | + Xilinx_wdata_fn wdata; | |
47 | + Xilinx_busy_fn busy; | |
48 | + Xilinx_abort_fn abort; | |
49 | + Xilinx_post_fn post; | |
50 | + int relocated; | |
51 | +} Xilinx_Spartan3_Slave_Parallel_fns; | |
52 | + | |
53 | +/* Slave Serial Implementation function table */ | |
54 | +typedef struct { | |
55 | + Xilinx_pre_fn pre; | |
56 | + Xilinx_pgm_fn pgm; | |
57 | + Xilinx_clk_fn clk; | |
58 | + Xilinx_init_fn init; | |
59 | + Xilinx_done_fn done; | |
60 | + Xilinx_wr_fn wr; | |
61 | + int relocated; | |
62 | +} Xilinx_Spartan3_Slave_Serial_fns; | |
63 | + | |
64 | +/* Device Image Sizes | |
65 | + *********************************************************************/ | |
66 | +/* Spartan-III (1.2V) */ | |
67 | +#define XILINX_XC3S50_SIZE 439264/8 | |
68 | +#define XILINX_XC3S200_SIZE 1047616/8 | |
69 | +#define XILINX_XC3S400_SIZE 1699136/8 | |
70 | +#define XILINX_XC3S1000_SIZE 3223488/8 | |
71 | +#define XILINX_XC3S1500_SIZE 5214784/8 | |
72 | +#define XILINX_XC3S2000_SIZE 7673024/8 | |
73 | +#define XILINX_XC3S4000_SIZE 11316864/8 | |
74 | +#define XILINX_XC3S5000_SIZE 13271936/8 | |
75 | + | |
76 | +/* Descriptor Macros | |
77 | + *********************************************************************/ | |
78 | +/* Spartan-II devices */ | |
79 | +#define XILINX_XC3S50_DESC(iface, fn_table, cookie) \ | |
80 | +{ Xilinx_Spartan3, iface, XILINX_XC3S50_SIZE, fn_table, cookie } | |
81 | + | |
82 | +#define XILINX_XC3S200_DESC(iface, fn_table, cookie) \ | |
83 | +{ Xilinx_Spartan3, iface, XILINX_XC3S200_SIZE, fn_table, cookie } | |
84 | + | |
85 | +#define XILINX_XC3S400_DESC(iface, fn_table, cookie) \ | |
86 | +{ Xilinx_Spartan3, iface, XILINX_XC3S400_SIZE, fn_table, cookie } | |
87 | + | |
88 | +#define XILINX_XC3S1000_DESC(iface, fn_table, cookie) \ | |
89 | +{ Xilinx_Spartan3, iface, XILINX_XC3S1000_SIZE, fn_table, cookie } | |
90 | + | |
91 | +#define XILINX_XC3S1500_DESC(iface, fn_table, cookie) \ | |
92 | +{ Xilinx_Spartan3, iface, XILINX_XC3S1500_SIZE, fn_table, cookie } | |
93 | + | |
94 | +#define XILINX_XC3S2000_DESC(iface, fn_table, cookie) \ | |
95 | +{ Xilinx_Spartan3, iface, XILINX_XC3S2000E_SIZE, fn_table, cookie } | |
96 | + | |
97 | +#define XILINX_XC3S4000_DESC(iface, fn_table, cookie) \ | |
98 | +{ Xilinx_Spartan3, iface, XILINX_XC3S4000E_SIZE, fn_table, cookie } | |
99 | + | |
100 | +#define XILINX_XC3S5000_DESC(iface, fn_table, cookie) \ | |
101 | +{ Xilinx_Spartan3, iface, XILINX_XC3S5000E_SIZE, fn_table, cookie } | |
102 | + | |
103 | +#endif /* _SPARTAN3_H_ */ |
include/xilinx.h
... | ... | @@ -32,9 +32,11 @@ |
32 | 32 | #define CFG_SPARTAN2 CFG_FPGA_DEV( 0x1 ) |
33 | 33 | #define CFG_VIRTEX_E CFG_FPGA_DEV( 0x2 ) |
34 | 34 | #define CFG_VIRTEX2 CFG_FPGA_DEV( 0x4 ) |
35 | +#define CFG_SPARTAN3 CFG_FPGA_DEV( 0x8 ) | |
35 | 36 | #define CFG_XILINX_SPARTAN2 (CFG_FPGA_XILINX | CFG_SPARTAN2) |
36 | 37 | #define CFG_XILINX_VIRTEX_E (CFG_FPGA_XILINX | CFG_VIRTEX_E) |
37 | 38 | #define CFG_XILINX_VIRTEX2 (CFG_FPGA_XILINX | CFG_VIRTEX2) |
39 | +#define CFG_XILINX_SPARTAN3 (CFG_FPGA_XILINX | CFG_SPARTAN3) | |
38 | 40 | /* XXX - Add new models here */ |
39 | 41 | |
40 | 42 | |
... | ... | @@ -65,6 +67,7 @@ |
65 | 67 | Xilinx_Spartan2, /* Spartan-II Family */ |
66 | 68 | Xilinx_VirtexE, /* Virtex-E Family */ |
67 | 69 | Xilinx_Virtex2, /* Virtex2 Family */ |
70 | + Xilinx_Spartan3, /* Spartan-III Family */ | |
68 | 71 | max_xilinx_type /* insert all new types before this */ |
69 | 72 | } Xilinx_Family; /* end, typedef Xilinx_Family */ |
70 | 73 |