blob: f72dfdec94ead6cadedb8c592d4f684037d089c1 [file] [log] [blame]
Tom Rini10e47792018-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 Dahlcb9c1f92022-10-07 14:20:01 +02007#define LOG_CATEGORY UCLASS_FPGA
8
wdenke2211742002-11-02 23:30:20 +00009#include <common.h> /* core U-Boot definitions */
Alexander Dahlcb9c1f92022-10-07 14:20:01 +020010#include <log.h>
wdenke2211742002-11-02 23:30:20 +000011#include <spartan2.h> /* Spartan-II device family */
12
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020013#undef CONFIG_SYS_FPGA_CHECK_BUSY
wdenke2211742002-11-02 23:30:20 +000014
15/* Note: The assumption is that we cannot possibly run fast enough to
16 * overrun the device (the Slave Parallel mode can free run at 50MHz).
17 * If there is a need to operate slower, define CONFIG_FPGA_DELAY in
18 * the board config file to slow things down.
19 */
20#ifndef CONFIG_FPGA_DELAY
21#define CONFIG_FPGA_DELAY()
22#endif
23
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020024#ifndef CONFIG_SYS_FPGA_WAIT
25#define CONFIG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100 /* 10 ms */
wdenke2211742002-11-02 23:30:20 +000026#endif
27
Michal Simek25e1e2e2014-03-13 12:49:21 +010028static int spartan2_sp_load(xilinx_desc *desc, const void *buf, size_t bsize);
29static int spartan2_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize);
30/* static int spartan2_sp_info(xilinx_desc *desc ); */
wdenke2211742002-11-02 23:30:20 +000031
Michal Simek25e1e2e2014-03-13 12:49:21 +010032static int spartan2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
33static int spartan2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
34/* static int spartan2_ss_info(xilinx_desc *desc ); */
wdenke2211742002-11-02 23:30:20 +000035
36/* ------------------------------------------------------------------------- */
37/* Spartan-II Generic Implementation */
Michal Simek14663652014-05-02 14:09:30 +020038static int spartan2_load(xilinx_desc *desc, const void *buf, size_t bsize,
Oleksandr Suvorovc0806cc2022-07-22 17:16:10 +030039 bitstream_type bstype, int flags)
wdenke2211742002-11-02 23:30:20 +000040{
41 int ret_val = FPGA_FAIL;
42
43 switch (desc->iface) {
44 case slave_serial:
Alexander Dahlcb9c1f92022-10-07 14:20:01 +020045 log_debug("Launching Slave Serial Load\n");
Michal Simek5206cca2014-03-13 11:23:43 +010046 ret_val = spartan2_ss_load(desc, buf, bsize);
wdenke2211742002-11-02 23:30:20 +000047 break;
48
49 case slave_parallel:
Alexander Dahlcb9c1f92022-10-07 14:20:01 +020050 log_debug("Launching Slave Parallel Load\n");
Michal Simek5206cca2014-03-13 11:23:43 +010051 ret_val = spartan2_sp_load(desc, buf, bsize);
wdenke2211742002-11-02 23:30:20 +000052 break;
53
54 default:
55 printf ("%s: Unsupported interface type, %d\n",
56 __FUNCTION__, desc->iface);
57 }
58
59 return ret_val;
60}
61
Michal Simek75fafac2014-03-13 13:07:57 +010062static int spartan2_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenke2211742002-11-02 23:30:20 +000063{
64 int ret_val = FPGA_FAIL;
65
66 switch (desc->iface) {
67 case slave_serial:
Alexander Dahlcb9c1f92022-10-07 14:20:01 +020068 log_debug("Launching Slave Serial Dump\n");
Michal Simek5206cca2014-03-13 11:23:43 +010069 ret_val = spartan2_ss_dump(desc, buf, bsize);
wdenke2211742002-11-02 23:30:20 +000070 break;
71
72 case slave_parallel:
Alexander Dahlcb9c1f92022-10-07 14:20:01 +020073 log_debug("Launching Slave Parallel Dump\n");
Michal Simek5206cca2014-03-13 11:23:43 +010074 ret_val = spartan2_sp_dump(desc, buf, bsize);
wdenke2211742002-11-02 23:30:20 +000075 break;
76
77 default:
78 printf ("%s: Unsupported interface type, %d\n",
79 __FUNCTION__, desc->iface);
80 }
81
82 return ret_val;
83}
84
Michal Simek75fafac2014-03-13 13:07:57 +010085static int spartan2_info(xilinx_desc *desc)
wdenke2211742002-11-02 23:30:20 +000086{
87 return FPGA_SUCCESS;
88}
89
90
wdenke2211742002-11-02 23:30:20 +000091/* ------------------------------------------------------------------------- */
92/* Spartan-II Slave Parallel Generic Implementation */
93
Michal Simek25e1e2e2014-03-13 12:49:21 +010094static int spartan2_sp_load(xilinx_desc *desc, const void *buf, size_t bsize)
wdenke2211742002-11-02 23:30:20 +000095{
96 int ret_val = FPGA_FAIL; /* assume the worst */
Michal Simek5206cca2014-03-13 11:23:43 +010097 xilinx_spartan2_slave_parallel_fns *fn = desc->iface_fns;
wdenke2211742002-11-02 23:30:20 +000098
Alexander Dahlcb9c1f92022-10-07 14:20:01 +020099 log_debug("start with interface functions @ 0x%p\n", fn);
wdenke2211742002-11-02 23:30:20 +0000100
101 if (fn) {
102 size_t bytecount = 0;
103 unsigned char *data = (unsigned char *) buf;
104 int cookie = desc->cookie; /* make a local copy */
105 unsigned long ts; /* timestamp */
106
Alexander Dahlcb9c1f92022-10-07 14:20:01 +0200107 log_debug("Function Table:\n"
108 "ptr:\t0x%p\n"
109 "struct: 0x%p\n"
110 "pre: 0x%p\n"
111 "pgm:\t0x%p\n"
112 "init:\t0x%p\n"
113 "err:\t0x%p\n"
114 "clk:\t0x%p\n"
115 "cs:\t0x%p\n"
116 "wr:\t0x%p\n"
117 "read data:\t0x%p\n"
118 "write data:\t0x%p\n"
119 "busy:\t0x%p\n"
120 "abort:\t0x%p\n"
121 "post:\t0x%p\n\n",
122 &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
123 fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
124 fn->abort, fn->post);
wdenke2211742002-11-02 23:30:20 +0000125
126 /*
127 * This code is designed to emulate the "Express Style"
128 * Continuous Data Loading in Slave Parallel Mode for
129 * the Spartan-II Family.
130 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200131#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenke2211742002-11-02 23:30:20 +0000132 printf ("Loading FPGA Device %d...\n", cookie);
133#endif
134 /*
135 * Run the pre configuration function if there is one.
136 */
137 if (*fn->pre) {
138 (*fn->pre) (cookie);
139 }
140
141 /* Establish the initial state */
York Sun4a598092013-04-01 11:29:11 -0700142 (*fn->pgm) (true, true, cookie); /* Assert the program, commit */
wdenke2211742002-11-02 23:30:20 +0000143
144 /* Get ready for the burn */
145 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700146 (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */
wdenke2211742002-11-02 23:30:20 +0000147
148 ts = get_timer (0); /* get current time */
149 /* Now wait for INIT and BUSY to go high */
150 do {
151 CONFIG_FPGA_DELAY ();
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200152 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
wdenke2211742002-11-02 23:30:20 +0000153 puts ("** Timeout waiting for INIT to clear.\n");
154 (*fn->abort) (cookie); /* abort the burn */
155 return FPGA_FAIL;
156 }
157 } while ((*fn->init) (cookie) && (*fn->busy) (cookie));
158
York Sun4a598092013-04-01 11:29:11 -0700159 (*fn->wr) (true, true, cookie); /* Assert write, commit */
160 (*fn->cs) (true, true, cookie); /* Assert chip select, commit */
161 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
wdenke2211742002-11-02 23:30:20 +0000162
163 /* Load the data */
164 while (bytecount < bsize) {
165 /* XXX - do we check for an Ctrl-C press in here ??? */
166 /* XXX - Check the error bit? */
167
York Sun4a598092013-04-01 11:29:11 -0700168 (*fn->wdata) (data[bytecount++], true, cookie); /* write the data */
wdenke2211742002-11-02 23:30:20 +0000169 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700170 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
wdenke2211742002-11-02 23:30:20 +0000171 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700172 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
wdenke2211742002-11-02 23:30:20 +0000173
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200174#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
wdenke2211742002-11-02 23:30:20 +0000175 ts = get_timer (0); /* get current time */
176 while ((*fn->busy) (cookie)) {
177 /* XXX - we should have a check in here somewhere to
178 * make sure we aren't busy forever... */
179
180 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700181 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
wdenke2211742002-11-02 23:30:20 +0000182 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700183 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
wdenke2211742002-11-02 23:30:20 +0000184
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200185 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
wdenke2211742002-11-02 23:30:20 +0000186 puts ("** Timeout waiting for BUSY to clear.\n");
187 (*fn->abort) (cookie); /* abort the burn */
188 return FPGA_FAIL;
189 }
190 }
191#endif
192
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200193#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenke2211742002-11-02 23:30:20 +0000194 if (bytecount % (bsize / 40) == 0)
195 putc ('.'); /* let them know we are alive */
196#endif
197 }
198
199 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700200 (*fn->cs) (false, true, cookie); /* Deassert the chip select */
201 (*fn->wr) (false, true, cookie); /* Deassert the write pin */
wdenke2211742002-11-02 23:30:20 +0000202
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200203#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenke2211742002-11-02 23:30:20 +0000204 putc ('\n'); /* terminate the dotted line */
205#endif
206
207 /* now check for done signal */
208 ts = get_timer (0); /* get current time */
209 ret_val = FPGA_SUCCESS;
210 while ((*fn->done) (cookie) == FPGA_FAIL) {
wdenke2211742002-11-02 23:30:20 +0000211
212 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700213 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
wdenke2211742002-11-02 23:30:20 +0000214 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700215 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
wdenke2211742002-11-02 23:30:20 +0000216
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200217 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
wdenke2211742002-11-02 23:30:20 +0000218 puts ("** Timeout waiting for DONE to clear.\n");
219 (*fn->abort) (cookie); /* abort the burn */
220 ret_val = FPGA_FAIL;
221 break;
222 }
223 }
224
wdenke2211742002-11-02 23:30:20 +0000225 /*
226 * Run the post configuration function if there is one.
227 */
Matthias Fuchsf73e0ed2009-02-15 22:28:36 +0100228 if (*fn->post)
wdenke2211742002-11-02 23:30:20 +0000229 (*fn->post) (cookie);
wdenke2211742002-11-02 23:30:20 +0000230
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200231#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Matthias Fuchsf73e0ed2009-02-15 22:28:36 +0100232 if (ret_val == FPGA_SUCCESS)
233 puts ("Done.\n");
234 else
wdenke2211742002-11-02 23:30:20 +0000235 puts ("Fail.\n");
236#endif
wdenke2211742002-11-02 23:30:20 +0000237
238 } else {
239 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
240 }
241
242 return ret_val;
243}
244
Michal Simek25e1e2e2014-03-13 12:49:21 +0100245static int spartan2_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenke2211742002-11-02 23:30:20 +0000246{
247 int ret_val = FPGA_FAIL; /* assume the worst */
Michal Simek5206cca2014-03-13 11:23:43 +0100248 xilinx_spartan2_slave_parallel_fns *fn = desc->iface_fns;
wdenke2211742002-11-02 23:30:20 +0000249
250 if (fn) {
251 unsigned char *data = (unsigned char *) buf;
252 size_t bytecount = 0;
253 int cookie = desc->cookie; /* make a local copy */
254
255 printf ("Starting Dump of FPGA Device %d...\n", cookie);
256
York Sun4a598092013-04-01 11:29:11 -0700257 (*fn->cs) (true, true, cookie); /* Assert chip select, commit */
258 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
wdenke2211742002-11-02 23:30:20 +0000259
260 /* dump the data */
261 while (bytecount < bsize) {
262 /* XXX - do we check for an Ctrl-C press in here ??? */
263
York Sun4a598092013-04-01 11:29:11 -0700264 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
265 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
wdenke2211742002-11-02 23:30:20 +0000266 (*fn->rdata) (&(data[bytecount++]), cookie); /* read the data */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200267#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenke2211742002-11-02 23:30:20 +0000268 if (bytecount % (bsize / 40) == 0)
269 putc ('.'); /* let them know we are alive */
270#endif
271 }
272
York Sun4a598092013-04-01 11:29:11 -0700273 (*fn->cs) (false, false, cookie); /* Deassert the chip select */
274 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
275 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
wdenke2211742002-11-02 23:30:20 +0000276
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200277#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenke2211742002-11-02 23:30:20 +0000278 putc ('\n'); /* terminate the dotted line */
279#endif
280 puts ("Done.\n");
281
282 /* XXX - checksum the data? */
283 } else {
284 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
285 }
286
287 return ret_val;
288}
289
wdenke2211742002-11-02 23:30:20 +0000290
291/* ------------------------------------------------------------------------- */
292
Michal Simek25e1e2e2014-03-13 12:49:21 +0100293static int spartan2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
wdenke2211742002-11-02 23:30:20 +0000294{
wdenk57b2d802003-06-27 21:31:46 +0000295 int ret_val = FPGA_FAIL; /* assume the worst */
Michal Simek5206cca2014-03-13 11:23:43 +0100296 xilinx_spartan2_slave_serial_fns *fn = desc->iface_fns;
wdenk57b2d802003-06-27 21:31:46 +0000297 int i;
Matthias Fuchsb845b1e2007-12-27 17:13:05 +0100298 unsigned char val;
wdenk57b2d802003-06-27 21:31:46 +0000299
Alexander Dahlcb9c1f92022-10-07 14:20:01 +0200300 log_debug("start with interface functions @ 0x%p\n", fn);
wdenk1272e232002-11-10 22:06:23 +0000301
302 if (fn) {
303 size_t bytecount = 0;
304 unsigned char *data = (unsigned char *) buf;
305 int cookie = desc->cookie; /* make a local copy */
306 unsigned long ts; /* timestamp */
307
Alexander Dahlcb9c1f92022-10-07 14:20:01 +0200308 log_debug("Function Table:\n"
309 "ptr:\t0x%p\n"
310 "struct: 0x%p\n"
311 "pgm:\t0x%p\n"
312 "init:\t0x%p\n"
313 "clk:\t0x%p\n"
314 "wr:\t0x%p\n"
315 "done:\t0x%p\n\n",
316 &fn, fn, fn->pgm, fn->init,
317 fn->clk, fn->wr, fn->done);
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200318#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk1272e232002-11-10 22:06:23 +0000319 printf ("Loading FPGA Device %d...\n", cookie);
320#endif
321
322 /*
323 * Run the pre configuration function if there is one.
324 */
325 if (*fn->pre) {
326 (*fn->pre) (cookie);
327 }
328
329 /* Establish the initial state */
York Sun4a598092013-04-01 11:29:11 -0700330 (*fn->pgm) (true, true, cookie); /* Assert the program, commit */
wdenk1272e232002-11-10 22:06:23 +0000331
wdenk57b2d802003-06-27 21:31:46 +0000332 /* Wait for INIT state (init low) */
wdenk1272e232002-11-10 22:06:23 +0000333 ts = get_timer (0); /* get current time */
334 do {
335 CONFIG_FPGA_DELAY ();
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200336 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
wdenk1272e232002-11-10 22:06:23 +0000337 puts ("** Timeout waiting for INIT to start.\n");
338 return FPGA_FAIL;
339 }
340 } while (!(*fn->init) (cookie));
wdenk57b2d802003-06-27 21:31:46 +0000341
wdenk1272e232002-11-10 22:06:23 +0000342 /* Get ready for the burn */
343 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700344 (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */
wdenk1272e232002-11-10 22:06:23 +0000345
346 ts = get_timer (0); /* get current time */
347 /* Now wait for INIT to go high */
348 do {
349 CONFIG_FPGA_DELAY ();
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200350 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
wdenk1272e232002-11-10 22:06:23 +0000351 puts ("** Timeout waiting for INIT to clear.\n");
352 return FPGA_FAIL;
353 }
354 } while ((*fn->init) (cookie));
355
356 /* Load the data */
357 while (bytecount < bsize) {
wdenk57b2d802003-06-27 21:31:46 +0000358
359 /* Xilinx detects an error if INIT goes low (active)
360 while DONE is low (inactive) */
361 if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
362 puts ("** CRC error during FPGA load.\n");
363 return (FPGA_FAIL);
364 }
365 val = data [bytecount ++];
366 i = 8;
367 do {
368 /* Deassert the clock */
York Sun4a598092013-04-01 11:29:11 -0700369 (*fn->clk) (false, true, cookie);
wdenk57b2d802003-06-27 21:31:46 +0000370 CONFIG_FPGA_DELAY ();
371 /* Write data */
York Sun4a598092013-04-01 11:29:11 -0700372 (*fn->wr) ((val & 0x80), true, cookie);
wdenk57b2d802003-06-27 21:31:46 +0000373 CONFIG_FPGA_DELAY ();
374 /* Assert the clock */
York Sun4a598092013-04-01 11:29:11 -0700375 (*fn->clk) (true, true, cookie);
wdenk57b2d802003-06-27 21:31:46 +0000376 CONFIG_FPGA_DELAY ();
377 val <<= 1;
378 i --;
379 } while (i > 0);
380
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200381#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk1272e232002-11-10 22:06:23 +0000382 if (bytecount % (bsize / 40) == 0)
383 putc ('.'); /* let them know we are alive */
384#endif
385 }
386
387 CONFIG_FPGA_DELAY ();
388
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200389#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk1272e232002-11-10 22:06:23 +0000390 putc ('\n'); /* terminate the dotted line */
391#endif
392
393 /* now check for done signal */
394 ts = get_timer (0); /* get current time */
395 ret_val = FPGA_SUCCESS;
York Sun4a598092013-04-01 11:29:11 -0700396 (*fn->wr) (true, true, cookie);
wdenk1272e232002-11-10 22:06:23 +0000397
398 while (! (*fn->done) (cookie)) {
wdenk1272e232002-11-10 22:06:23 +0000399
400 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700401 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
wdenk1272e232002-11-10 22:06:23 +0000402 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700403 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
wdenk1272e232002-11-10 22:06:23 +0000404
wdenk57b2d802003-06-27 21:31:46 +0000405 putc ('*');
406
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200407 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT) { /* check the time */
wdenk1272e232002-11-10 22:06:23 +0000408 puts ("** Timeout waiting for DONE to clear.\n");
409 ret_val = FPGA_FAIL;
410 break;
411 }
412 }
413 putc ('\n'); /* terminate the dotted line */
414
Matthias Fuchs518e2e142007-12-27 17:12:43 +0100415 /*
416 * Run the post configuration function if there is one.
417 */
Matthias Fuchsf73e0ed2009-02-15 22:28:36 +0100418 if (*fn->post)
Matthias Fuchs518e2e142007-12-27 17:12:43 +0100419 (*fn->post) (cookie);
Matthias Fuchs518e2e142007-12-27 17:12:43 +0100420
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200421#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Matthias Fuchsf73e0ed2009-02-15 22:28:36 +0100422 if (ret_val == FPGA_SUCCESS)
wdenk1272e232002-11-10 22:06:23 +0000423 puts ("Done.\n");
Matthias Fuchsf73e0ed2009-02-15 22:28:36 +0100424 else
wdenk1272e232002-11-10 22:06:23 +0000425 puts ("Fail.\n");
wdenk1272e232002-11-10 22:06:23 +0000426#endif
427
428 } else {
429 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
430 }
431
432 return ret_val;
wdenke2211742002-11-02 23:30:20 +0000433}
434
Michal Simek25e1e2e2014-03-13 12:49:21 +0100435static int spartan2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenke2211742002-11-02 23:30:20 +0000436{
wdenk57b2d802003-06-27 21:31:46 +0000437 /* Readback is only available through the Slave Parallel and */
438 /* boundary-scan interfaces. */
wdenk1272e232002-11-10 22:06:23 +0000439 printf ("%s: Slave Serial Dumping is unavailable\n",
wdenke2211742002-11-02 23:30:20 +0000440 __FUNCTION__);
441 return FPGA_FAIL;
442}
Michal Simek75fafac2014-03-13 13:07:57 +0100443
444struct xilinx_fpga_op spartan2_op = {
445 .load = spartan2_load,
446 .dump = spartan2_dump,
447 .info = spartan2_info,
448};