blob: cd16a9c44c29046571c527d6118b208c194a58c0 [file] [log] [blame]
wdenke2211742002-11-02 23:30:20 +00001/*
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#include <common.h> /* core U-Boot definitions */
26#include <spartan2.h> /* Spartan-II device family */
27
wdenke2211742002-11-02 23:30:20 +000028/* Define FPGA_DEBUG to get debug printf's */
29#ifdef FPGA_DEBUG
30#define PRINTF(fmt,args...) printf (fmt ,##args)
31#else
32#define PRINTF(fmt,args...)
33#endif
34
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020035#undef CONFIG_SYS_FPGA_CHECK_BUSY
36#undef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenke2211742002-11-02 23:30:20 +000037
38/* Note: The assumption is that we cannot possibly run fast enough to
39 * overrun the device (the Slave Parallel mode can free run at 50MHz).
40 * If there is a need to operate slower, define CONFIG_FPGA_DELAY in
41 * the board config file to slow things down.
42 */
43#ifndef CONFIG_FPGA_DELAY
44#define CONFIG_FPGA_DELAY()
45#endif
46
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020047#ifndef CONFIG_SYS_FPGA_WAIT
48#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100 /* 10 ms */
wdenke2211742002-11-02 23:30:20 +000049#endif
50
51static int Spartan2_sp_load( Xilinx_desc *desc, void *buf, size_t bsize );
52static int Spartan2_sp_dump( Xilinx_desc *desc, void *buf, size_t bsize );
53/* static int Spartan2_sp_info( Xilinx_desc *desc ); */
wdenke2211742002-11-02 23:30:20 +000054
55static int Spartan2_ss_load( Xilinx_desc *desc, void *buf, size_t bsize );
56static int Spartan2_ss_dump( Xilinx_desc *desc, void *buf, size_t bsize );
57/* static int Spartan2_ss_info( Xilinx_desc *desc ); */
wdenke2211742002-11-02 23:30:20 +000058
59/* ------------------------------------------------------------------------- */
60/* Spartan-II Generic Implementation */
61int Spartan2_load (Xilinx_desc * desc, void *buf, size_t bsize)
62{
63 int ret_val = FPGA_FAIL;
64
65 switch (desc->iface) {
66 case slave_serial:
67 PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
68 ret_val = Spartan2_ss_load (desc, buf, bsize);
69 break;
70
71 case slave_parallel:
72 PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
73 ret_val = Spartan2_sp_load (desc, buf, bsize);
74 break;
75
76 default:
77 printf ("%s: Unsupported interface type, %d\n",
78 __FUNCTION__, desc->iface);
79 }
80
81 return ret_val;
82}
83
84int Spartan2_dump (Xilinx_desc * desc, void *buf, size_t bsize)
85{
86 int ret_val = FPGA_FAIL;
87
88 switch (desc->iface) {
89 case slave_serial:
90 PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
91 ret_val = Spartan2_ss_dump (desc, buf, bsize);
92 break;
93
94 case slave_parallel:
95 PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
96 ret_val = Spartan2_sp_dump (desc, buf, bsize);
97 break;
98
99 default:
100 printf ("%s: Unsupported interface type, %d\n",
101 __FUNCTION__, desc->iface);
102 }
103
104 return ret_val;
105}
106
107int Spartan2_info( Xilinx_desc *desc )
108{
109 return FPGA_SUCCESS;
110}
111
112
wdenke2211742002-11-02 23:30:20 +0000113/* ------------------------------------------------------------------------- */
114/* Spartan-II Slave Parallel Generic Implementation */
115
116static int Spartan2_sp_load (Xilinx_desc * desc, void *buf, size_t bsize)
117{
118 int ret_val = FPGA_FAIL; /* assume the worst */
119 Xilinx_Spartan2_Slave_Parallel_fns *fn = desc->iface_fns;
120
121 PRINTF ("%s: start with interface functions @ 0x%p\n",
122 __FUNCTION__, fn);
123
124 if (fn) {
125 size_t bytecount = 0;
126 unsigned char *data = (unsigned char *) buf;
127 int cookie = desc->cookie; /* make a local copy */
128 unsigned long ts; /* timestamp */
129
130 PRINTF ("%s: Function Table:\n"
131 "ptr:\t0x%p\n"
132 "struct: 0x%p\n"
133 "pre: 0x%p\n"
134 "pgm:\t0x%p\n"
135 "init:\t0x%p\n"
136 "err:\t0x%p\n"
137 "clk:\t0x%p\n"
138 "cs:\t0x%p\n"
139 "wr:\t0x%p\n"
140 "read data:\t0x%p\n"
141 "write data:\t0x%p\n"
142 "busy:\t0x%p\n"
143 "abort:\t0x%p\n",
144 "post:\t0x%p\n\n",
145 __FUNCTION__, &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
146 fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
147 fn->abort, fn->post);
148
149 /*
150 * This code is designed to emulate the "Express Style"
151 * Continuous Data Loading in Slave Parallel Mode for
152 * the Spartan-II Family.
153 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200154#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenke2211742002-11-02 23:30:20 +0000155 printf ("Loading FPGA Device %d...\n", cookie);
156#endif
157 /*
158 * Run the pre configuration function if there is one.
159 */
160 if (*fn->pre) {
161 (*fn->pre) (cookie);
162 }
163
164 /* Establish the initial state */
165 (*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */
166
167 /* Get ready for the burn */
168 CONFIG_FPGA_DELAY ();
169 (*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */
170
171 ts = get_timer (0); /* get current time */
172 /* Now wait for INIT and BUSY to go high */
173 do {
174 CONFIG_FPGA_DELAY ();
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200175 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
wdenke2211742002-11-02 23:30:20 +0000176 puts ("** Timeout waiting for INIT to clear.\n");
177 (*fn->abort) (cookie); /* abort the burn */
178 return FPGA_FAIL;
179 }
180 } while ((*fn->init) (cookie) && (*fn->busy) (cookie));
181
182 (*fn->wr) (TRUE, TRUE, cookie); /* Assert write, commit */
183 (*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */
184 (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
185
186 /* Load the data */
187 while (bytecount < bsize) {
188 /* XXX - do we check for an Ctrl-C press in here ??? */
189 /* XXX - Check the error bit? */
190
191 (*fn->wdata) (data[bytecount++], TRUE, cookie); /* write the data */
192 CONFIG_FPGA_DELAY ();
193 (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
194 CONFIG_FPGA_DELAY ();
195 (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
196
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200197#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
wdenke2211742002-11-02 23:30:20 +0000198 ts = get_timer (0); /* get current time */
199 while ((*fn->busy) (cookie)) {
200 /* XXX - we should have a check in here somewhere to
201 * make sure we aren't busy forever... */
202
203 CONFIG_FPGA_DELAY ();
204 (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
205 CONFIG_FPGA_DELAY ();
206 (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
207
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200208 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
wdenke2211742002-11-02 23:30:20 +0000209 puts ("** Timeout waiting for BUSY to clear.\n");
210 (*fn->abort) (cookie); /* abort the burn */
211 return FPGA_FAIL;
212 }
213 }
214#endif
215
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200216#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenke2211742002-11-02 23:30:20 +0000217 if (bytecount % (bsize / 40) == 0)
218 putc ('.'); /* let them know we are alive */
219#endif
220 }
221
222 CONFIG_FPGA_DELAY ();
223 (*fn->cs) (FALSE, TRUE, cookie); /* Deassert the chip select */
224 (*fn->wr) (FALSE, TRUE, cookie); /* Deassert the write pin */
225
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200226#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenke2211742002-11-02 23:30:20 +0000227 putc ('\n'); /* terminate the dotted line */
228#endif
229
230 /* now check for done signal */
231 ts = get_timer (0); /* get current time */
232 ret_val = FPGA_SUCCESS;
233 while ((*fn->done) (cookie) == FPGA_FAIL) {
wdenke2211742002-11-02 23:30:20 +0000234
235 CONFIG_FPGA_DELAY ();
236 (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
237 CONFIG_FPGA_DELAY ();
238 (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
239
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200240 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
wdenke2211742002-11-02 23:30:20 +0000241 puts ("** Timeout waiting for DONE to clear.\n");
242 (*fn->abort) (cookie); /* abort the burn */
243 ret_val = FPGA_FAIL;
244 break;
245 }
246 }
247
wdenke2211742002-11-02 23:30:20 +0000248 /*
249 * Run the post configuration function if there is one.
250 */
Matthias Fuchs3818b672009-02-15 22:28:36 +0100251 if (*fn->post)
wdenke2211742002-11-02 23:30:20 +0000252 (*fn->post) (cookie);
wdenke2211742002-11-02 23:30:20 +0000253
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200254#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Matthias Fuchs3818b672009-02-15 22:28:36 +0100255 if (ret_val == FPGA_SUCCESS)
256 puts ("Done.\n");
257 else
wdenke2211742002-11-02 23:30:20 +0000258 puts ("Fail.\n");
259#endif
wdenke2211742002-11-02 23:30:20 +0000260
261 } else {
262 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
263 }
264
265 return ret_val;
266}
267
268static int Spartan2_sp_dump (Xilinx_desc * desc, void *buf, size_t bsize)
269{
270 int ret_val = FPGA_FAIL; /* assume the worst */
271 Xilinx_Spartan2_Slave_Parallel_fns *fn = desc->iface_fns;
272
273 if (fn) {
274 unsigned char *data = (unsigned char *) buf;
275 size_t bytecount = 0;
276 int cookie = desc->cookie; /* make a local copy */
277
278 printf ("Starting Dump of FPGA Device %d...\n", cookie);
279
280 (*fn->cs) (TRUE, TRUE, cookie); /* Assert chip select, commit */
281 (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
282
283 /* dump the data */
284 while (bytecount < bsize) {
285 /* XXX - do we check for an Ctrl-C press in here ??? */
286
287 (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
288 (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
289 (*fn->rdata) (&(data[bytecount++]), cookie); /* read the data */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200290#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenke2211742002-11-02 23:30:20 +0000291 if (bytecount % (bsize / 40) == 0)
292 putc ('.'); /* let them know we are alive */
293#endif
294 }
295
296 (*fn->cs) (FALSE, FALSE, cookie); /* Deassert the chip select */
297 (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
298 (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
299
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200300#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenke2211742002-11-02 23:30:20 +0000301 putc ('\n'); /* terminate the dotted line */
302#endif
303 puts ("Done.\n");
304
305 /* XXX - checksum the data? */
306 } else {
307 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
308 }
309
310 return ret_val;
311}
312
313
wdenke2211742002-11-02 23:30:20 +0000314/* ------------------------------------------------------------------------- */
315
316static int Spartan2_ss_load (Xilinx_desc * desc, void *buf, size_t bsize)
317{
wdenk8bde7f72003-06-27 21:31:46 +0000318 int ret_val = FPGA_FAIL; /* assume the worst */
wdenk7f6c2cb2002-11-10 22:06:23 +0000319 Xilinx_Spartan2_Slave_Serial_fns *fn = desc->iface_fns;
wdenk8bde7f72003-06-27 21:31:46 +0000320 int i;
Matthias Fuchs437fc732007-12-27 17:13:05 +0100321 unsigned char val;
wdenk8bde7f72003-06-27 21:31:46 +0000322
wdenk7f6c2cb2002-11-10 22:06:23 +0000323 PRINTF ("%s: start with interface functions @ 0x%p\n",
324 __FUNCTION__, fn);
325
326 if (fn) {
327 size_t bytecount = 0;
328 unsigned char *data = (unsigned char *) buf;
329 int cookie = desc->cookie; /* make a local copy */
330 unsigned long ts; /* timestamp */
331
332 PRINTF ("%s: Function Table:\n"
333 "ptr:\t0x%p\n"
334 "struct: 0x%p\n"
335 "pgm:\t0x%p\n"
336 "init:\t0x%p\n"
337 "clk:\t0x%p\n"
338 "wr:\t0x%p\n"
339 "done:\t0x%p\n\n",
wdenk8bde7f72003-06-27 21:31:46 +0000340 __FUNCTION__, &fn, fn, fn->pgm, fn->init,
341 fn->clk, fn->wr, fn->done);
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200342#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk7f6c2cb2002-11-10 22:06:23 +0000343 printf ("Loading FPGA Device %d...\n", cookie);
344#endif
345
346 /*
347 * Run the pre configuration function if there is one.
348 */
349 if (*fn->pre) {
350 (*fn->pre) (cookie);
351 }
352
353 /* Establish the initial state */
354 (*fn->pgm) (TRUE, TRUE, cookie); /* Assert the program, commit */
355
wdenk8bde7f72003-06-27 21:31:46 +0000356 /* Wait for INIT state (init low) */
wdenk7f6c2cb2002-11-10 22:06:23 +0000357 ts = get_timer (0); /* get current time */
358 do {
359 CONFIG_FPGA_DELAY ();
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200360 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
wdenk7f6c2cb2002-11-10 22:06:23 +0000361 puts ("** Timeout waiting for INIT to start.\n");
362 return FPGA_FAIL;
363 }
364 } while (!(*fn->init) (cookie));
wdenk8bde7f72003-06-27 21:31:46 +0000365
wdenk7f6c2cb2002-11-10 22:06:23 +0000366 /* Get ready for the burn */
367 CONFIG_FPGA_DELAY ();
368 (*fn->pgm) (FALSE, TRUE, cookie); /* Deassert the program, commit */
369
370 ts = get_timer (0); /* get current time */
371 /* Now wait for INIT to go high */
372 do {
373 CONFIG_FPGA_DELAY ();
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200374 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
wdenk7f6c2cb2002-11-10 22:06:23 +0000375 puts ("** Timeout waiting for INIT to clear.\n");
376 return FPGA_FAIL;
377 }
378 } while ((*fn->init) (cookie));
379
380 /* Load the data */
381 while (bytecount < bsize) {
wdenk8bde7f72003-06-27 21:31:46 +0000382
383 /* Xilinx detects an error if INIT goes low (active)
384 while DONE is low (inactive) */
385 if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
386 puts ("** CRC error during FPGA load.\n");
387 return (FPGA_FAIL);
388 }
389 val = data [bytecount ++];
390 i = 8;
391 do {
392 /* Deassert the clock */
393 (*fn->clk) (FALSE, TRUE, cookie);
394 CONFIG_FPGA_DELAY ();
395 /* Write data */
Wolfgang Denk6ecbb7a2007-11-17 01:30:40 +0100396 (*fn->wr) ((val & 0x80), TRUE, cookie);
wdenk8bde7f72003-06-27 21:31:46 +0000397 CONFIG_FPGA_DELAY ();
398 /* Assert the clock */
399 (*fn->clk) (TRUE, TRUE, cookie);
400 CONFIG_FPGA_DELAY ();
401 val <<= 1;
402 i --;
403 } while (i > 0);
404
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200405#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk7f6c2cb2002-11-10 22:06:23 +0000406 if (bytecount % (bsize / 40) == 0)
407 putc ('.'); /* let them know we are alive */
408#endif
409 }
410
411 CONFIG_FPGA_DELAY ();
412
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200413#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk7f6c2cb2002-11-10 22:06:23 +0000414 putc ('\n'); /* terminate the dotted line */
415#endif
416
417 /* now check for done signal */
418 ts = get_timer (0); /* get current time */
419 ret_val = FPGA_SUCCESS;
wdenk8bde7f72003-06-27 21:31:46 +0000420 (*fn->wr) (TRUE, TRUE, cookie);
wdenk7f6c2cb2002-11-10 22:06:23 +0000421
422 while (! (*fn->done) (cookie)) {
wdenk7f6c2cb2002-11-10 22:06:23 +0000423
424 CONFIG_FPGA_DELAY ();
425 (*fn->clk) (FALSE, TRUE, cookie); /* Deassert the clock pin */
426 CONFIG_FPGA_DELAY ();
427 (*fn->clk) (TRUE, TRUE, cookie); /* Assert the clock pin */
428
wdenk8bde7f72003-06-27 21:31:46 +0000429 putc ('*');
430
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200431 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
wdenk7f6c2cb2002-11-10 22:06:23 +0000432 puts ("** Timeout waiting for DONE to clear.\n");
433 ret_val = FPGA_FAIL;
434 break;
435 }
436 }
437 putc ('\n'); /* terminate the dotted line */
438
Matthias Fuchs21d39d52007-12-27 17:12:43 +0100439 /*
440 * Run the post configuration function if there is one.
441 */
Matthias Fuchs3818b672009-02-15 22:28:36 +0100442 if (*fn->post)
Matthias Fuchs21d39d52007-12-27 17:12:43 +0100443 (*fn->post) (cookie);
Matthias Fuchs21d39d52007-12-27 17:12:43 +0100444
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200445#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Matthias Fuchs3818b672009-02-15 22:28:36 +0100446 if (ret_val == FPGA_SUCCESS)
wdenk7f6c2cb2002-11-10 22:06:23 +0000447 puts ("Done.\n");
Matthias Fuchs3818b672009-02-15 22:28:36 +0100448 else
wdenk7f6c2cb2002-11-10 22:06:23 +0000449 puts ("Fail.\n");
wdenk7f6c2cb2002-11-10 22:06:23 +0000450#endif
451
452 } else {
453 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
454 }
455
456 return ret_val;
wdenke2211742002-11-02 23:30:20 +0000457}
458
459static int Spartan2_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize)
460{
wdenk8bde7f72003-06-27 21:31:46 +0000461 /* Readback is only available through the Slave Parallel and */
462 /* boundary-scan interfaces. */
wdenk7f6c2cb2002-11-10 22:06:23 +0000463 printf ("%s: Slave Serial Dumping is unavailable\n",
wdenke2211742002-11-02 23:30:20 +0000464 __FUNCTION__);
465 return FPGA_FAIL;
466}