blob: b7a063a95fc83477f4d468692005e1312667c33e [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Wolfgang Denkc38e70c2005-09-25 16:44:21 +02002/*
3 * (C) Copyright 2002
4 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
Wolfgang Denkc38e70c2005-09-25 16:44:21 +02005 */
6
7/*
8 * Configuration support for Xilinx Spartan3 devices. Based
9 * on spartan2.c (Rich Ireland, rireland@enterasys.com).
10 */
Wolfgang Denk34ca9d32005-09-25 18:49:35 +020011
Alexander Dahla151d232022-10-07 14:20:02 +020012#define LOG_CATEGORY UCLASS_FPGA
13
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020014#include <common.h> /* core U-Boot definitions */
Alexander Dahla151d232022-10-07 14:20:02 +020015#include <log.h>
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020016#include <spartan3.h> /* Spartan-II device family */
17
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020018#undef CONFIG_SYS_FPGA_CHECK_BUSY
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020019
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
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020029#ifndef CONFIG_SYS_FPGA_WAIT
30#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100 /* 10 ms */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020031#endif
32
Michal Simek25e1e2e2014-03-13 12:49:21 +010033static int spartan3_sp_load(xilinx_desc *desc, const void *buf, size_t bsize);
34static int spartan3_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize);
35/* static int spartan3_sp_info(xilinx_desc *desc ); */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020036
Michal Simek25e1e2e2014-03-13 12:49:21 +010037static int spartan3_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
38static int spartan3_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
39/* static int spartan3_ss_info(xilinx_desc *desc); */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020040
41/* ------------------------------------------------------------------------- */
42/* Spartan-II Generic Implementation */
Michal Simek14663652014-05-02 14:09:30 +020043static int spartan3_load(xilinx_desc *desc, const void *buf, size_t bsize,
Oleksandr Suvorovc0806cc2022-07-22 17:16:10 +030044 bitstream_type bstype, int flags)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020045{
46 int ret_val = FPGA_FAIL;
47
48 switch (desc->iface) {
49 case slave_serial:
Alexander Dahla151d232022-10-07 14:20:02 +020050 log_debug("Launching Slave Serial Load\n");
Michal Simek2091a0c2014-03-13 11:28:42 +010051 ret_val = spartan3_ss_load(desc, buf, bsize);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020052 break;
53
54 case slave_parallel:
Alexander Dahla151d232022-10-07 14:20:02 +020055 log_debug("Launching Slave Parallel Load\n");
Michal Simek2091a0c2014-03-13 11:28:42 +010056 ret_val = spartan3_sp_load(desc, buf, bsize);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020057 break;
58
59 default:
60 printf ("%s: Unsupported interface type, %d\n",
61 __FUNCTION__, desc->iface);
62 }
63
64 return ret_val;
65}
66
Michal Simek75fafac2014-03-13 13:07:57 +010067static int spartan3_dump(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020068{
69 int ret_val = FPGA_FAIL;
70
71 switch (desc->iface) {
72 case slave_serial:
Alexander Dahla151d232022-10-07 14:20:02 +020073 log_debug("Launching Slave Serial Dump\n");
Michal Simek2091a0c2014-03-13 11:28:42 +010074 ret_val = spartan3_ss_dump(desc, buf, bsize);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020075 break;
76
77 case slave_parallel:
Alexander Dahla151d232022-10-07 14:20:02 +020078 log_debug("Launching Slave Parallel Dump\n");
Michal Simek2091a0c2014-03-13 11:28:42 +010079 ret_val = spartan3_sp_dump(desc, buf, bsize);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020080 break;
81
82 default:
83 printf ("%s: Unsupported interface type, %d\n",
84 __FUNCTION__, desc->iface);
85 }
86
87 return ret_val;
88}
89
Michal Simek75fafac2014-03-13 13:07:57 +010090static int spartan3_info(xilinx_desc *desc)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020091{
92 return FPGA_SUCCESS;
93}
94
95
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020096/* ------------------------------------------------------------------------- */
97/* Spartan-II Slave Parallel Generic Implementation */
98
Michal Simek25e1e2e2014-03-13 12:49:21 +010099static int spartan3_sp_load(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200100{
101 int ret_val = FPGA_FAIL; /* assume the worst */
Michal Simek2091a0c2014-03-13 11:28:42 +0100102 xilinx_spartan3_slave_parallel_fns *fn = desc->iface_fns;
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200103
Alexander Dahla151d232022-10-07 14:20:02 +0200104 log_debug("start with interface functions @ 0x%p\n", fn);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200105
106 if (fn) {
107 size_t bytecount = 0;
108 unsigned char *data = (unsigned char *) buf;
109 int cookie = desc->cookie; /* make a local copy */
110 unsigned long ts; /* timestamp */
111
Alexander Dahla151d232022-10-07 14:20:02 +0200112 log_debug("Function Table:\n"
113 "ptr:\t0x%p\n"
114 "struct: 0x%p\n"
115 "pre: 0x%p\n"
116 "pgm:\t0x%p\n"
117 "init:\t0x%p\n"
118 "err:\t0x%p\n"
119 "clk:\t0x%p\n"
120 "cs:\t0x%p\n"
121 "wr:\t0x%p\n"
122 "read data:\t0x%p\n"
123 "write data:\t0x%p\n"
124 "busy:\t0x%p\n"
125 "abort:\t0x%p\n"
126 "post:\t0x%p\n\n",
127 &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
128 fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
129 fn->abort, fn->post);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200130
131 /*
132 * This code is designed to emulate the "Express Style"
133 * Continuous Data Loading in Slave Parallel Mode for
134 * the Spartan-II Family.
135 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200136#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200137 printf ("Loading FPGA Device %d...\n", cookie);
138#endif
139 /*
140 * Run the pre configuration function if there is one.
141 */
142 if (*fn->pre) {
143 (*fn->pre) (cookie);
144 }
145
146 /* Establish the initial state */
York Sun4a598092013-04-01 11:29:11 -0700147 (*fn->pgm) (true, true, cookie); /* Assert the program, commit */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200148
149 /* Get ready for the burn */
150 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700151 (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200152
153 ts = get_timer (0); /* get current time */
154 /* Now wait for INIT and BUSY to go high */
155 do {
156 CONFIG_FPGA_DELAY ();
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200157 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200158 puts ("** Timeout waiting for INIT to clear.\n");
159 (*fn->abort) (cookie); /* abort the burn */
160 return FPGA_FAIL;
161 }
162 } while ((*fn->init) (cookie) && (*fn->busy) (cookie));
163
York Sun4a598092013-04-01 11:29:11 -0700164 (*fn->wr) (true, true, cookie); /* Assert write, commit */
165 (*fn->cs) (true, true, cookie); /* Assert chip select, commit */
166 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200167
168 /* Load the data */
169 while (bytecount < bsize) {
170 /* XXX - do we check for an Ctrl-C press in here ??? */
171 /* XXX - Check the error bit? */
172
York Sun4a598092013-04-01 11:29:11 -0700173 (*fn->wdata) (data[bytecount++], true, cookie); /* write the data */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200174 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700175 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200176 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700177 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200178
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200179#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200180 ts = get_timer (0); /* get current time */
181 while ((*fn->busy) (cookie)) {
182 /* XXX - we should have a check in here somewhere to
183 * make sure we aren't busy forever... */
184
185 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700186 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200187 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700188 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200189
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200190 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200191 puts ("** Timeout waiting for BUSY to clear.\n");
192 (*fn->abort) (cookie); /* abort the burn */
193 return FPGA_FAIL;
194 }
195 }
196#endif
197
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200198#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200199 if (bytecount % (bsize / 40) == 0)
200 putc ('.'); /* let them know we are alive */
201#endif
202 }
203
204 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700205 (*fn->cs) (false, true, cookie); /* Deassert the chip select */
206 (*fn->wr) (false, true, cookie); /* Deassert the write pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200207
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200208#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200209 putc ('\n'); /* terminate the dotted line */
210#endif
211
212 /* now check for done signal */
213 ts = get_timer (0); /* get current time */
214 ret_val = FPGA_SUCCESS;
215 while ((*fn->done) (cookie) == FPGA_FAIL) {
216 /* XXX - we should have a check in here somewhere to
217 * make sure we aren't busy forever... */
218
219 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700220 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200221 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700222 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200223
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200224 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200225 puts ("** Timeout waiting for DONE to clear.\n");
226 (*fn->abort) (cookie); /* abort the burn */
227 ret_val = FPGA_FAIL;
228 break;
229 }
230 }
231
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200232 /*
233 * Run the post configuration function if there is one.
234 */
Matthias Fuchs93081662009-02-15 22:29:15 +0100235 if (*fn->post)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200236 (*fn->post) (cookie);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200237
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200238#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Matthias Fuchs93081662009-02-15 22:29:15 +0100239 if (ret_val == FPGA_SUCCESS)
240 puts ("Done.\n");
241 else
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200242 puts ("Fail.\n");
243#endif
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200244
245 } else {
246 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
247 }
248
249 return ret_val;
250}
251
Michal Simek25e1e2e2014-03-13 12:49:21 +0100252static int spartan3_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200253{
254 int ret_val = FPGA_FAIL; /* assume the worst */
Michal Simek2091a0c2014-03-13 11:28:42 +0100255 xilinx_spartan3_slave_parallel_fns *fn = desc->iface_fns;
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200256
257 if (fn) {
258 unsigned char *data = (unsigned char *) buf;
259 size_t bytecount = 0;
260 int cookie = desc->cookie; /* make a local copy */
261
262 printf ("Starting Dump of FPGA Device %d...\n", cookie);
263
York Sun4a598092013-04-01 11:29:11 -0700264 (*fn->cs) (true, true, cookie); /* Assert chip select, commit */
265 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200266
267 /* dump the data */
268 while (bytecount < bsize) {
269 /* XXX - do we check for an Ctrl-C press in here ??? */
270
York Sun4a598092013-04-01 11:29:11 -0700271 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
272 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200273 (*fn->rdata) (&(data[bytecount++]), cookie); /* read the data */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200274#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200275 if (bytecount % (bsize / 40) == 0)
276 putc ('.'); /* let them know we are alive */
277#endif
278 }
279
York Sun4a598092013-04-01 11:29:11 -0700280 (*fn->cs) (false, false, cookie); /* Deassert the chip select */
281 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
282 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200283
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200284#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200285 putc ('\n'); /* terminate the dotted line */
286#endif
287 puts ("Done.\n");
288
289 /* XXX - checksum the data? */
290 } else {
291 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
292 }
293
294 return ret_val;
295}
296
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200297
298/* ------------------------------------------------------------------------- */
299
Michal Simek25e1e2e2014-03-13 12:49:21 +0100300static int spartan3_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200301{
302 int ret_val = FPGA_FAIL; /* assume the worst */
Michal Simek2091a0c2014-03-13 11:28:42 +0100303 xilinx_spartan3_slave_serial_fns *fn = desc->iface_fns;
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200304 int i;
Matthias Fuchsb845b1e2007-12-27 17:13:05 +0100305 unsigned char val;
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200306
Alexander Dahla151d232022-10-07 14:20:02 +0200307 log_debug("start with interface functions @ 0x%p\n", fn);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200308
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
Alexander Dahla151d232022-10-07 14:20:02 +0200315 log_debug("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 &fn, fn, fn->pgm, fn->init,
324 fn->clk, fn->wr, fn->done);
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200325#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200326 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 */
York Sun4a598092013-04-01 11:29:11 -0700337 (*fn->pgm) (true, true, cookie); /* Assert the program, commit */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200338
339 /* Wait for INIT state (init low) */
340 ts = get_timer (0); /* get current time */
341 do {
342 CONFIG_FPGA_DELAY ();
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200343 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200344 puts ("** Timeout waiting for INIT to start.\n");
Wolfgang Wegner015db1f2010-04-23 11:08:05 +0200345 if (*fn->abort)
346 (*fn->abort) (cookie);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200347 return FPGA_FAIL;
348 }
349 } while (!(*fn->init) (cookie));
350
351 /* Get ready for the burn */
352 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700353 (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200354
355 ts = get_timer (0); /* get current time */
356 /* Now wait for INIT to go high */
357 do {
358 CONFIG_FPGA_DELAY ();
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200359 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200360 puts ("** Timeout waiting for INIT to clear.\n");
Wolfgang Wegner015db1f2010-04-23 11:08:05 +0200361 if (*fn->abort)
362 (*fn->abort) (cookie);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200363 return FPGA_FAIL;
364 }
365 } while ((*fn->init) (cookie));
366
367 /* Load the data */
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100368 if(*fn->bwr)
York Sun4a598092013-04-01 11:29:11 -0700369 (*fn->bwr) (data, bsize, true, cookie);
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100370 else {
371 while (bytecount < bsize) {
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200372
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100373 /* Xilinx detects an error if INIT goes low (active)
374 while DONE is low (inactive) */
375 if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
376 puts ("** CRC error during FPGA load.\n");
Wolfgang Wegner015db1f2010-04-23 11:08:05 +0200377 if (*fn->abort)
378 (*fn->abort) (cookie);
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100379 return (FPGA_FAIL);
380 }
381 val = data [bytecount ++];
382 i = 8;
383 do {
384 /* Deassert the clock */
York Sun4a598092013-04-01 11:29:11 -0700385 (*fn->clk) (false, true, cookie);
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100386 CONFIG_FPGA_DELAY ();
387 /* Write data */
York Sun4a598092013-04-01 11:29:11 -0700388 (*fn->wr) ((val & 0x80), true, cookie);
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100389 CONFIG_FPGA_DELAY ();
390 /* Assert the clock */
York Sun4a598092013-04-01 11:29:11 -0700391 (*fn->clk) (true, true, cookie);
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100392 CONFIG_FPGA_DELAY ();
393 val <<= 1;
394 i --;
395 } while (i > 0);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200396
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200397#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100398 if (bytecount % (bsize / 40) == 0)
399 putc ('.'); /* let them know we are alive */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200400#endif
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100401 }
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200402 }
403
404 CONFIG_FPGA_DELAY ();
405
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200406#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200407 putc ('\n'); /* terminate the dotted line */
408#endif
409
410 /* now check for done signal */
411 ts = get_timer (0); /* get current time */
412 ret_val = FPGA_SUCCESS;
York Sun4a598092013-04-01 11:29:11 -0700413 (*fn->wr) (true, true, cookie);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200414
415 while (! (*fn->done) (cookie)) {
416 /* XXX - we should have a check in here somewhere to
417 * make sure we aren't busy forever... */
418
419 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700420 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200421 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700422 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200423
424 putc ('*');
425
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200426 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200427 puts ("** Timeout waiting for DONE to clear.\n");
428 ret_val = FPGA_FAIL;
429 break;
430 }
431 }
432 putc ('\n'); /* terminate the dotted line */
433
Matthias Fuchs518e2e142007-12-27 17:12:43 +0100434 /*
435 * Run the post configuration function if there is one.
436 */
Matthias Fuchs93081662009-02-15 22:29:15 +0100437 if (*fn->post)
Matthias Fuchs518e2e142007-12-27 17:12:43 +0100438 (*fn->post) (cookie);
Matthias Fuchs518e2e142007-12-27 17:12:43 +0100439
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200440#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Matthias Fuchs93081662009-02-15 22:29:15 +0100441 if (ret_val == FPGA_SUCCESS)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200442 puts ("Done.\n");
Matthias Fuchs93081662009-02-15 22:29:15 +0100443 else
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200444 puts ("Fail.\n");
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200445#endif
446
447 } else {
448 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
449 }
450
451 return ret_val;
452}
453
Michal Simek25e1e2e2014-03-13 12:49:21 +0100454static int spartan3_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200455{
456 /* Readback is only available through the Slave Parallel and */
457 /* boundary-scan interfaces. */
458 printf ("%s: Slave Serial Dumping is unavailable\n",
459 __FUNCTION__);
460 return FPGA_FAIL;
461}
Michal Simek75fafac2014-03-13 13:07:57 +0100462
463struct xilinx_fpga_op spartan3_op = {
464 .load = spartan3_load,
465 .dump = spartan3_dump,
466 .info = spartan3_info,
467};