blob: 6eef87b78e16d41cf8635a8930f6642e33c5ae48 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenke2211742002-11-02 23:30:20 +00002/*
3 * (C) Copyright 2002
4 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
wdenke2211742002-11-02 23:30:20 +00005 */
6
Alexander Dahlbc33b692022-10-07 14:20:01 +02007#define LOG_CATEGORY UCLASS_FPGA
wdenke2211742002-11-02 23:30:20 +00008
Alexander Dahlbc33b692022-10-07 14:20:01 +02009#include <common.h> /* core U-Boot definitions */
10#include <log.h>
11#include <spartan2.h> /* Spartan-II device family */
wdenke2211742002-11-02 23:30:20 +000012
wdenke2211742002-11-02 23:30:20 +000013/* 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).
Tom Rini72fc2642022-12-04 10:03:57 -050015 * If there is a need to operate slower, define CFG_FPGA_DELAY in
wdenke2211742002-11-02 23:30:20 +000016 * the board config file to slow things down.
17 */
Tom Rini72fc2642022-12-04 10:03:57 -050018#ifndef CFG_FPGA_DELAY
19#define CFG_FPGA_DELAY()
wdenke2211742002-11-02 23:30:20 +000020#endif
21
Tom Rini65cc0e22022-11-16 13:10:41 -050022#ifndef CFG_SYS_FPGA_WAIT
23#define CFG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100 /* 10 ms */
wdenke2211742002-11-02 23:30:20 +000024#endif
25
Michal Simekf8c1be92014-03-13 12:49:21 +010026static int spartan2_sp_load(xilinx_desc *desc, const void *buf, size_t bsize);
27static int spartan2_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize);
28/* static int spartan2_sp_info(xilinx_desc *desc ); */
wdenke2211742002-11-02 23:30:20 +000029
Michal Simekf8c1be92014-03-13 12:49:21 +010030static int spartan2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
31static int spartan2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
32/* static int spartan2_ss_info(xilinx_desc *desc ); */
wdenke2211742002-11-02 23:30:20 +000033
34/* ------------------------------------------------------------------------- */
35/* Spartan-II Generic Implementation */
Michal Simek7a78bd22014-05-02 14:09:30 +020036static int spartan2_load(xilinx_desc *desc, const void *buf, size_t bsize,
Oleksandr Suvorov3e784812022-07-22 17:16:10 +030037 bitstream_type bstype, int flags)
wdenke2211742002-11-02 23:30:20 +000038{
39 int ret_val = FPGA_FAIL;
40
41 switch (desc->iface) {
42 case slave_serial:
Alexander Dahlbc33b692022-10-07 14:20:01 +020043 log_debug("Launching Slave Serial Load\n");
Michal Simekb625b9a2014-03-13 11:23:43 +010044 ret_val = spartan2_ss_load(desc, buf, bsize);
wdenke2211742002-11-02 23:30:20 +000045 break;
46
47 case slave_parallel:
Alexander Dahlbc33b692022-10-07 14:20:01 +020048 log_debug("Launching Slave Parallel Load\n");
Michal Simekb625b9a2014-03-13 11:23:43 +010049 ret_val = spartan2_sp_load(desc, buf, bsize);
wdenke2211742002-11-02 23:30:20 +000050 break;
51
52 default:
53 printf ("%s: Unsupported interface type, %d\n",
54 __FUNCTION__, desc->iface);
55 }
56
57 return ret_val;
58}
59
Michal Simek14cfc4f2014-03-13 13:07:57 +010060static int spartan2_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenke2211742002-11-02 23:30:20 +000061{
62 int ret_val = FPGA_FAIL;
63
64 switch (desc->iface) {
65 case slave_serial:
Alexander Dahlbc33b692022-10-07 14:20:01 +020066 log_debug("Launching Slave Serial Dump\n");
Michal Simekb625b9a2014-03-13 11:23:43 +010067 ret_val = spartan2_ss_dump(desc, buf, bsize);
wdenke2211742002-11-02 23:30:20 +000068 break;
69
70 case slave_parallel:
Alexander Dahlbc33b692022-10-07 14:20:01 +020071 log_debug("Launching Slave Parallel Dump\n");
Michal Simekb625b9a2014-03-13 11:23:43 +010072 ret_val = spartan2_sp_dump(desc, buf, bsize);
wdenke2211742002-11-02 23:30:20 +000073 break;
74
75 default:
76 printf ("%s: Unsupported interface type, %d\n",
77 __FUNCTION__, desc->iface);
78 }
79
80 return ret_val;
81}
82
Michal Simek14cfc4f2014-03-13 13:07:57 +010083static int spartan2_info(xilinx_desc *desc)
wdenke2211742002-11-02 23:30:20 +000084{
85 return FPGA_SUCCESS;
86}
87
88
wdenke2211742002-11-02 23:30:20 +000089/* ------------------------------------------------------------------------- */
90/* Spartan-II Slave Parallel Generic Implementation */
91
Michal Simekf8c1be92014-03-13 12:49:21 +010092static int spartan2_sp_load(xilinx_desc *desc, const void *buf, size_t bsize)
wdenke2211742002-11-02 23:30:20 +000093{
94 int ret_val = FPGA_FAIL; /* assume the worst */
Michal Simekb625b9a2014-03-13 11:23:43 +010095 xilinx_spartan2_slave_parallel_fns *fn = desc->iface_fns;
wdenke2211742002-11-02 23:30:20 +000096
Alexander Dahlbc33b692022-10-07 14:20:01 +020097 log_debug("start with interface functions @ 0x%p\n", fn);
wdenke2211742002-11-02 23:30:20 +000098
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
Alexander Dahlbc33b692022-10-07 14:20:01 +0200105 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);
wdenke2211742002-11-02 23:30:20 +0000123
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 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200129#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenke2211742002-11-02 23:30:20 +0000130 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 */
York Sun472d5462013-04-01 11:29:11 -0700140 (*fn->pgm) (true, true, cookie); /* Assert the program, commit */
wdenke2211742002-11-02 23:30:20 +0000141
142 /* Get ready for the burn */
Tom Rini72fc2642022-12-04 10:03:57 -0500143 CFG_FPGA_DELAY ();
York Sun472d5462013-04-01 11:29:11 -0700144 (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */
wdenke2211742002-11-02 23:30:20 +0000145
146 ts = get_timer (0); /* get current time */
147 /* Now wait for INIT and BUSY to go high */
148 do {
Tom Rini72fc2642022-12-04 10:03:57 -0500149 CFG_FPGA_DELAY ();
Tom Rini65cc0e22022-11-16 13:10:41 -0500150 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
wdenke2211742002-11-02 23:30:20 +0000151 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
York Sun472d5462013-04-01 11:29:11 -0700157 (*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 */
wdenke2211742002-11-02 23:30:20 +0000160
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
York Sun472d5462013-04-01 11:29:11 -0700166 (*fn->wdata) (data[bytecount++], true, cookie); /* write the data */
Tom Rini72fc2642022-12-04 10:03:57 -0500167 CFG_FPGA_DELAY ();
York Sun472d5462013-04-01 11:29:11 -0700168 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Tom Rini72fc2642022-12-04 10:03:57 -0500169 CFG_FPGA_DELAY ();
York Sun472d5462013-04-01 11:29:11 -0700170 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
wdenke2211742002-11-02 23:30:20 +0000171
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200172#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
wdenke2211742002-11-02 23:30:20 +0000173 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
Tom Rini72fc2642022-12-04 10:03:57 -0500178 CFG_FPGA_DELAY ();
York Sun472d5462013-04-01 11:29:11 -0700179 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Tom Rini72fc2642022-12-04 10:03:57 -0500180 CFG_FPGA_DELAY ();
York Sun472d5462013-04-01 11:29:11 -0700181 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
wdenke2211742002-11-02 23:30:20 +0000182
Tom Rini65cc0e22022-11-16 13:10:41 -0500183 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
wdenke2211742002-11-02 23:30:20 +0000184 puts ("** Timeout waiting for BUSY to clear.\n");
185 (*fn->abort) (cookie); /* abort the burn */
186 return FPGA_FAIL;
187 }
188 }
189#endif
190
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200191#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenke2211742002-11-02 23:30:20 +0000192 if (bytecount % (bsize / 40) == 0)
193 putc ('.'); /* let them know we are alive */
194#endif
195 }
196
Tom Rini72fc2642022-12-04 10:03:57 -0500197 CFG_FPGA_DELAY ();
York Sun472d5462013-04-01 11:29:11 -0700198 (*fn->cs) (false, true, cookie); /* Deassert the chip select */
199 (*fn->wr) (false, true, cookie); /* Deassert the write pin */
wdenke2211742002-11-02 23:30:20 +0000200
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200201#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenke2211742002-11-02 23:30:20 +0000202 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) {
wdenke2211742002-11-02 23:30:20 +0000209
Tom Rini72fc2642022-12-04 10:03:57 -0500210 CFG_FPGA_DELAY ();
York Sun472d5462013-04-01 11:29:11 -0700211 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Tom Rini72fc2642022-12-04 10:03:57 -0500212 CFG_FPGA_DELAY ();
York Sun472d5462013-04-01 11:29:11 -0700213 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
wdenke2211742002-11-02 23:30:20 +0000214
Tom Rini65cc0e22022-11-16 13:10:41 -0500215 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
wdenke2211742002-11-02 23:30:20 +0000216 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
wdenke2211742002-11-02 23:30:20 +0000223 /*
224 * Run the post configuration function if there is one.
225 */
Matthias Fuchs3818b672009-02-15 22:28:36 +0100226 if (*fn->post)
wdenke2211742002-11-02 23:30:20 +0000227 (*fn->post) (cookie);
wdenke2211742002-11-02 23:30:20 +0000228
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200229#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Matthias Fuchs3818b672009-02-15 22:28:36 +0100230 if (ret_val == FPGA_SUCCESS)
231 puts ("Done.\n");
232 else
wdenke2211742002-11-02 23:30:20 +0000233 puts ("Fail.\n");
234#endif
wdenke2211742002-11-02 23:30:20 +0000235
236 } else {
237 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
238 }
239
240 return ret_val;
241}
242
Michal Simekf8c1be92014-03-13 12:49:21 +0100243static int spartan2_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenke2211742002-11-02 23:30:20 +0000244{
245 int ret_val = FPGA_FAIL; /* assume the worst */
Michal Simekb625b9a2014-03-13 11:23:43 +0100246 xilinx_spartan2_slave_parallel_fns *fn = desc->iface_fns;
wdenke2211742002-11-02 23:30:20 +0000247
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
York Sun472d5462013-04-01 11:29:11 -0700255 (*fn->cs) (true, true, cookie); /* Assert chip select, commit */
256 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
wdenke2211742002-11-02 23:30:20 +0000257
258 /* dump the data */
259 while (bytecount < bsize) {
260 /* XXX - do we check for an Ctrl-C press in here ??? */
261
York Sun472d5462013-04-01 11:29:11 -0700262 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
263 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
wdenke2211742002-11-02 23:30:20 +0000264 (*fn->rdata) (&(data[bytecount++]), cookie); /* read the data */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200265#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenke2211742002-11-02 23:30:20 +0000266 if (bytecount % (bsize / 40) == 0)
267 putc ('.'); /* let them know we are alive */
268#endif
269 }
270
York Sun472d5462013-04-01 11:29:11 -0700271 (*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 */
wdenke2211742002-11-02 23:30:20 +0000274
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200275#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenke2211742002-11-02 23:30:20 +0000276 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
wdenke2211742002-11-02 23:30:20 +0000289/* ------------------------------------------------------------------------- */
290
Michal Simekf8c1be92014-03-13 12:49:21 +0100291static int spartan2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
wdenke2211742002-11-02 23:30:20 +0000292{
wdenk8bde7f72003-06-27 21:31:46 +0000293 int ret_val = FPGA_FAIL; /* assume the worst */
Michal Simekb625b9a2014-03-13 11:23:43 +0100294 xilinx_spartan2_slave_serial_fns *fn = desc->iface_fns;
wdenk8bde7f72003-06-27 21:31:46 +0000295 int i;
Matthias Fuchs437fc732007-12-27 17:13:05 +0100296 unsigned char val;
wdenk8bde7f72003-06-27 21:31:46 +0000297
Alexander Dahlbc33b692022-10-07 14:20:01 +0200298 log_debug("start with interface functions @ 0x%p\n", fn);
wdenk7f6c2cb2002-11-10 22:06:23 +0000299
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
Alexander Dahlbc33b692022-10-07 14:20:01 +0200306 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);
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200316#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk7f6c2cb2002-11-10 22:06:23 +0000317 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 */
York Sun472d5462013-04-01 11:29:11 -0700328 (*fn->pgm) (true, true, cookie); /* Assert the program, commit */
wdenk7f6c2cb2002-11-10 22:06:23 +0000329
wdenk8bde7f72003-06-27 21:31:46 +0000330 /* Wait for INIT state (init low) */
wdenk7f6c2cb2002-11-10 22:06:23 +0000331 ts = get_timer (0); /* get current time */
332 do {
Tom Rini72fc2642022-12-04 10:03:57 -0500333 CFG_FPGA_DELAY ();
Tom Rini65cc0e22022-11-16 13:10:41 -0500334 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
wdenk7f6c2cb2002-11-10 22:06:23 +0000335 puts ("** Timeout waiting for INIT to start.\n");
336 return FPGA_FAIL;
337 }
338 } while (!(*fn->init) (cookie));
wdenk8bde7f72003-06-27 21:31:46 +0000339
wdenk7f6c2cb2002-11-10 22:06:23 +0000340 /* Get ready for the burn */
Tom Rini72fc2642022-12-04 10:03:57 -0500341 CFG_FPGA_DELAY ();
York Sun472d5462013-04-01 11:29:11 -0700342 (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */
wdenk7f6c2cb2002-11-10 22:06:23 +0000343
344 ts = get_timer (0); /* get current time */
345 /* Now wait for INIT to go high */
346 do {
Tom Rini72fc2642022-12-04 10:03:57 -0500347 CFG_FPGA_DELAY ();
Tom Rini65cc0e22022-11-16 13:10:41 -0500348 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
wdenk7f6c2cb2002-11-10 22:06:23 +0000349 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) {
wdenk8bde7f72003-06-27 21:31:46 +0000356
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 */
York Sun472d5462013-04-01 11:29:11 -0700367 (*fn->clk) (false, true, cookie);
Tom Rini72fc2642022-12-04 10:03:57 -0500368 CFG_FPGA_DELAY ();
wdenk8bde7f72003-06-27 21:31:46 +0000369 /* Write data */
York Sun472d5462013-04-01 11:29:11 -0700370 (*fn->wr) ((val & 0x80), true, cookie);
Tom Rini72fc2642022-12-04 10:03:57 -0500371 CFG_FPGA_DELAY ();
wdenk8bde7f72003-06-27 21:31:46 +0000372 /* Assert the clock */
York Sun472d5462013-04-01 11:29:11 -0700373 (*fn->clk) (true, true, cookie);
Tom Rini72fc2642022-12-04 10:03:57 -0500374 CFG_FPGA_DELAY ();
wdenk8bde7f72003-06-27 21:31:46 +0000375 val <<= 1;
376 i --;
377 } while (i > 0);
378
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200379#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk7f6c2cb2002-11-10 22:06:23 +0000380 if (bytecount % (bsize / 40) == 0)
381 putc ('.'); /* let them know we are alive */
382#endif
383 }
384
Tom Rini72fc2642022-12-04 10:03:57 -0500385 CFG_FPGA_DELAY ();
wdenk7f6c2cb2002-11-10 22:06:23 +0000386
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200387#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk7f6c2cb2002-11-10 22:06:23 +0000388 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;
York Sun472d5462013-04-01 11:29:11 -0700394 (*fn->wr) (true, true, cookie);
wdenk7f6c2cb2002-11-10 22:06:23 +0000395
396 while (! (*fn->done) (cookie)) {
wdenk7f6c2cb2002-11-10 22:06:23 +0000397
Tom Rini72fc2642022-12-04 10:03:57 -0500398 CFG_FPGA_DELAY ();
York Sun472d5462013-04-01 11:29:11 -0700399 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Tom Rini72fc2642022-12-04 10:03:57 -0500400 CFG_FPGA_DELAY ();
York Sun472d5462013-04-01 11:29:11 -0700401 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
wdenk7f6c2cb2002-11-10 22:06:23 +0000402
wdenk8bde7f72003-06-27 21:31:46 +0000403 putc ('*');
404
Tom Rini65cc0e22022-11-16 13:10:41 -0500405 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
wdenk7f6c2cb2002-11-10 22:06:23 +0000406 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
Matthias Fuchs21d39d52007-12-27 17:12:43 +0100413 /*
414 * Run the post configuration function if there is one.
415 */
Matthias Fuchs3818b672009-02-15 22:28:36 +0100416 if (*fn->post)
Matthias Fuchs21d39d52007-12-27 17:12:43 +0100417 (*fn->post) (cookie);
Matthias Fuchs21d39d52007-12-27 17:12:43 +0100418
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200419#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Matthias Fuchs3818b672009-02-15 22:28:36 +0100420 if (ret_val == FPGA_SUCCESS)
wdenk7f6c2cb2002-11-10 22:06:23 +0000421 puts ("Done.\n");
Matthias Fuchs3818b672009-02-15 22:28:36 +0100422 else
wdenk7f6c2cb2002-11-10 22:06:23 +0000423 puts ("Fail.\n");
wdenk7f6c2cb2002-11-10 22:06:23 +0000424#endif
425
426 } else {
427 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
428 }
429
430 return ret_val;
wdenke2211742002-11-02 23:30:20 +0000431}
432
Michal Simekf8c1be92014-03-13 12:49:21 +0100433static int spartan2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenke2211742002-11-02 23:30:20 +0000434{
wdenk8bde7f72003-06-27 21:31:46 +0000435 /* Readback is only available through the Slave Parallel and */
436 /* boundary-scan interfaces. */
wdenk7f6c2cb2002-11-10 22:06:23 +0000437 printf ("%s: Slave Serial Dumping is unavailable\n",
wdenke2211742002-11-02 23:30:20 +0000438 __FUNCTION__);
439 return FPGA_FAIL;
440}
Michal Simek14cfc4f2014-03-13 13:07:57 +0100441
442struct xilinx_fpga_op spartan2_op = {
443 .load = spartan2_load,
444 .dump = spartan2_dump,
445 .info = spartan2_info,
446};