blob: b4d87d47d9332388bb2c1709b3c5553b9aefdfa7 [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
Tom Rinidec7ea02024-05-20 13:35:03 -060014#include <config.h> /* core U-Boot definitions */
Alexander Dahla151d232022-10-07 14:20:02 +020015#include <log.h>
Tom Rinidec7ea02024-05-20 13:35:03 -060016#include <time.h>
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020017#include <spartan3.h> /* Spartan-II device family */
18
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020019/* Note: The assumption is that we cannot possibly run fast enough to
20 * overrun the device (the Slave Parallel mode can free run at 50MHz).
Tom Rini88d86ec2022-12-04 10:03:57 -050021 * If there is a need to operate slower, define CFG_FPGA_DELAY in
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020022 * the board config file to slow things down.
23 */
Tom Rini88d86ec2022-12-04 10:03:57 -050024#ifndef CFG_FPGA_DELAY
25#define CFG_FPGA_DELAY()
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020026#endif
27
Tom Rini6a5dccc2022-11-16 13:10:41 -050028#ifndef CFG_SYS_FPGA_WAIT
29#define CFG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100 /* 10 ms */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020030#endif
31
Michal Simek25e1e2e2014-03-13 12:49:21 +010032static int spartan3_sp_load(xilinx_desc *desc, const void *buf, size_t bsize);
33static int spartan3_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize);
34/* static int spartan3_sp_info(xilinx_desc *desc ); */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020035
Michal Simek25e1e2e2014-03-13 12:49:21 +010036static int spartan3_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
37static int spartan3_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
38/* static int spartan3_ss_info(xilinx_desc *desc); */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020039
40/* ------------------------------------------------------------------------- */
41/* Spartan-II Generic Implementation */
Michal Simek14663652014-05-02 14:09:30 +020042static int spartan3_load(xilinx_desc *desc, const void *buf, size_t bsize,
Oleksandr Suvorovc0806cc2022-07-22 17:16:10 +030043 bitstream_type bstype, int flags)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020044{
45 int ret_val = FPGA_FAIL;
46
47 switch (desc->iface) {
48 case slave_serial:
Alexander Dahla151d232022-10-07 14:20:02 +020049 log_debug("Launching Slave Serial Load\n");
Michal Simek2091a0c2014-03-13 11:28:42 +010050 ret_val = spartan3_ss_load(desc, buf, bsize);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020051 break;
52
53 case slave_parallel:
Alexander Dahla151d232022-10-07 14:20:02 +020054 log_debug("Launching Slave Parallel Load\n");
Michal Simek2091a0c2014-03-13 11:28:42 +010055 ret_val = spartan3_sp_load(desc, buf, bsize);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020056 break;
57
58 default:
59 printf ("%s: Unsupported interface type, %d\n",
60 __FUNCTION__, desc->iface);
61 }
62
63 return ret_val;
64}
65
Michal Simek75fafac2014-03-13 13:07:57 +010066static int spartan3_dump(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020067{
68 int ret_val = FPGA_FAIL;
69
70 switch (desc->iface) {
71 case slave_serial:
Alexander Dahla151d232022-10-07 14:20:02 +020072 log_debug("Launching Slave Serial Dump\n");
Michal Simek2091a0c2014-03-13 11:28:42 +010073 ret_val = spartan3_ss_dump(desc, buf, bsize);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020074 break;
75
76 case slave_parallel:
Alexander Dahla151d232022-10-07 14:20:02 +020077 log_debug("Launching Slave Parallel Dump\n");
Michal Simek2091a0c2014-03-13 11:28:42 +010078 ret_val = spartan3_sp_dump(desc, buf, bsize);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020079 break;
80
81 default:
82 printf ("%s: Unsupported interface type, %d\n",
83 __FUNCTION__, desc->iface);
84 }
85
86 return ret_val;
87}
88
Michal Simek75fafac2014-03-13 13:07:57 +010089static int spartan3_info(xilinx_desc *desc)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020090{
91 return FPGA_SUCCESS;
92}
93
94
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020095/* ------------------------------------------------------------------------- */
96/* Spartan-II Slave Parallel Generic Implementation */
97
Michal Simek25e1e2e2014-03-13 12:49:21 +010098static int spartan3_sp_load(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020099{
100 int ret_val = FPGA_FAIL; /* assume the worst */
Michal Simek2091a0c2014-03-13 11:28:42 +0100101 xilinx_spartan3_slave_parallel_fns *fn = desc->iface_fns;
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200102
Alexander Dahla151d232022-10-07 14:20:02 +0200103 log_debug("start with interface functions @ 0x%p\n", fn);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200104
105 if (fn) {
106 size_t bytecount = 0;
107 unsigned char *data = (unsigned char *) buf;
108 int cookie = desc->cookie; /* make a local copy */
109 unsigned long ts; /* timestamp */
110
Alexander Dahla151d232022-10-07 14:20:02 +0200111 log_debug("Function Table:\n"
112 "ptr:\t0x%p\n"
113 "struct: 0x%p\n"
114 "pre: 0x%p\n"
115 "pgm:\t0x%p\n"
116 "init:\t0x%p\n"
117 "err:\t0x%p\n"
118 "clk:\t0x%p\n"
119 "cs:\t0x%p\n"
120 "wr:\t0x%p\n"
121 "read data:\t0x%p\n"
122 "write data:\t0x%p\n"
123 "busy:\t0x%p\n"
124 "abort:\t0x%p\n"
125 "post:\t0x%p\n\n",
126 &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
127 fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
128 fn->abort, fn->post);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200129
130 /*
131 * This code is designed to emulate the "Express Style"
132 * Continuous Data Loading in Slave Parallel Mode for
133 * the Spartan-II Family.
134 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200135#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200136 printf ("Loading FPGA Device %d...\n", cookie);
137#endif
138 /*
139 * Run the pre configuration function if there is one.
140 */
141 if (*fn->pre) {
142 (*fn->pre) (cookie);
143 }
144
145 /* Establish the initial state */
York Sun4a598092013-04-01 11:29:11 -0700146 (*fn->pgm) (true, true, cookie); /* Assert the program, commit */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200147
148 /* Get ready for the burn */
Tom Rini88d86ec2022-12-04 10:03:57 -0500149 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700150 (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200151
152 ts = get_timer (0); /* get current time */
153 /* Now wait for INIT and BUSY to go high */
154 do {
Tom Rini88d86ec2022-12-04 10:03:57 -0500155 CFG_FPGA_DELAY ();
Tom Rini6a5dccc2022-11-16 13:10:41 -0500156 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200157 puts ("** Timeout waiting for INIT to clear.\n");
158 (*fn->abort) (cookie); /* abort the burn */
159 return FPGA_FAIL;
160 }
161 } while ((*fn->init) (cookie) && (*fn->busy) (cookie));
162
York Sun4a598092013-04-01 11:29:11 -0700163 (*fn->wr) (true, true, cookie); /* Assert write, commit */
164 (*fn->cs) (true, true, cookie); /* Assert chip select, commit */
165 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200166
167 /* Load the data */
168 while (bytecount < bsize) {
169 /* XXX - do we check for an Ctrl-C press in here ??? */
170 /* XXX - Check the error bit? */
171
York Sun4a598092013-04-01 11:29:11 -0700172 (*fn->wdata) (data[bytecount++], true, cookie); /* write the data */
Tom Rini88d86ec2022-12-04 10:03:57 -0500173 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700174 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Tom Rini88d86ec2022-12-04 10:03:57 -0500175 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700176 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200177
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200178#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200179 ts = get_timer (0); /* get current time */
180 while ((*fn->busy) (cookie)) {
181 /* XXX - we should have a check in here somewhere to
182 * make sure we aren't busy forever... */
183
Tom Rini88d86ec2022-12-04 10:03:57 -0500184 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700185 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Tom Rini88d86ec2022-12-04 10:03:57 -0500186 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700187 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200188
Tom Rini6a5dccc2022-11-16 13:10:41 -0500189 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200190 puts ("** Timeout waiting for BUSY to clear.\n");
191 (*fn->abort) (cookie); /* abort the burn */
192 return FPGA_FAIL;
193 }
194 }
195#endif
196
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200197#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200198 if (bytecount % (bsize / 40) == 0)
199 putc ('.'); /* let them know we are alive */
200#endif
201 }
202
Tom Rini88d86ec2022-12-04 10:03:57 -0500203 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700204 (*fn->cs) (false, true, cookie); /* Deassert the chip select */
205 (*fn->wr) (false, true, cookie); /* Deassert the write pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200206
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200207#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200208 putc ('\n'); /* terminate the dotted line */
209#endif
210
211 /* now check for done signal */
212 ts = get_timer (0); /* get current time */
213 ret_val = FPGA_SUCCESS;
214 while ((*fn->done) (cookie) == FPGA_FAIL) {
215 /* XXX - we should have a check in here somewhere to
216 * make sure we aren't busy forever... */
217
Tom Rini88d86ec2022-12-04 10:03:57 -0500218 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700219 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Tom Rini88d86ec2022-12-04 10:03:57 -0500220 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700221 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200222
Tom Rini6a5dccc2022-11-16 13:10:41 -0500223 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200224 puts ("** Timeout waiting for DONE to clear.\n");
225 (*fn->abort) (cookie); /* abort the burn */
226 ret_val = FPGA_FAIL;
227 break;
228 }
229 }
230
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200231 /*
232 * Run the post configuration function if there is one.
233 */
Matthias Fuchs93081662009-02-15 22:29:15 +0100234 if (*fn->post)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200235 (*fn->post) (cookie);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200236
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200237#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Matthias Fuchs93081662009-02-15 22:29:15 +0100238 if (ret_val == FPGA_SUCCESS)
239 puts ("Done.\n");
240 else
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200241 puts ("Fail.\n");
242#endif
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200243
244 } else {
245 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
246 }
247
248 return ret_val;
249}
250
Michal Simek25e1e2e2014-03-13 12:49:21 +0100251static int spartan3_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200252{
253 int ret_val = FPGA_FAIL; /* assume the worst */
Michal Simek2091a0c2014-03-13 11:28:42 +0100254 xilinx_spartan3_slave_parallel_fns *fn = desc->iface_fns;
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200255
256 if (fn) {
257 unsigned char *data = (unsigned char *) buf;
258 size_t bytecount = 0;
259 int cookie = desc->cookie; /* make a local copy */
260
261 printf ("Starting Dump of FPGA Device %d...\n", cookie);
262
York Sun4a598092013-04-01 11:29:11 -0700263 (*fn->cs) (true, true, cookie); /* Assert chip select, commit */
264 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200265
266 /* dump the data */
267 while (bytecount < bsize) {
268 /* XXX - do we check for an Ctrl-C press in here ??? */
269
York Sun4a598092013-04-01 11:29:11 -0700270 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
271 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200272 (*fn->rdata) (&(data[bytecount++]), cookie); /* read the data */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200273#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200274 if (bytecount % (bsize / 40) == 0)
275 putc ('.'); /* let them know we are alive */
276#endif
277 }
278
York Sun4a598092013-04-01 11:29:11 -0700279 (*fn->cs) (false, false, cookie); /* Deassert the chip select */
280 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
281 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200282
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200283#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200284 putc ('\n'); /* terminate the dotted line */
285#endif
286 puts ("Done.\n");
287
288 /* XXX - checksum the data? */
289 } else {
290 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
291 }
292
293 return ret_val;
294}
295
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200296
297/* ------------------------------------------------------------------------- */
298
Michal Simek25e1e2e2014-03-13 12:49:21 +0100299static int spartan3_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200300{
301 int ret_val = FPGA_FAIL; /* assume the worst */
Michal Simek2091a0c2014-03-13 11:28:42 +0100302 xilinx_spartan3_slave_serial_fns *fn = desc->iface_fns;
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200303 int i;
Matthias Fuchsb845b1e2007-12-27 17:13:05 +0100304 unsigned char val;
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200305
Alexander Dahla151d232022-10-07 14:20:02 +0200306 log_debug("start with interface functions @ 0x%p\n", fn);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200307
308 if (fn) {
309 size_t bytecount = 0;
310 unsigned char *data = (unsigned char *) buf;
311 int cookie = desc->cookie; /* make a local copy */
312 unsigned long ts; /* timestamp */
313
Alexander Dahla151d232022-10-07 14:20:02 +0200314 log_debug("Function Table:\n"
315 "ptr:\t0x%p\n"
316 "struct: 0x%p\n"
317 "pgm:\t0x%p\n"
318 "init:\t0x%p\n"
319 "clk:\t0x%p\n"
320 "wr:\t0x%p\n"
321 "done:\t0x%p\n\n",
322 &fn, fn, fn->pgm, fn->init,
323 fn->clk, fn->wr, fn->done);
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200324#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200325 printf ("Loading FPGA Device %d...\n", cookie);
326#endif
327
328 /*
329 * Run the pre configuration function if there is one.
330 */
331 if (*fn->pre) {
332 (*fn->pre) (cookie);
333 }
334
335 /* Establish the initial state */
York Sun4a598092013-04-01 11:29:11 -0700336 (*fn->pgm) (true, true, cookie); /* Assert the program, commit */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200337
338 /* Wait for INIT state (init low) */
339 ts = get_timer (0); /* get current time */
340 do {
Tom Rini88d86ec2022-12-04 10:03:57 -0500341 CFG_FPGA_DELAY ();
Tom Rini6a5dccc2022-11-16 13:10:41 -0500342 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200343 puts ("** Timeout waiting for INIT to start.\n");
Wolfgang Wegner015db1f2010-04-23 11:08:05 +0200344 if (*fn->abort)
345 (*fn->abort) (cookie);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200346 return FPGA_FAIL;
347 }
348 } while (!(*fn->init) (cookie));
349
350 /* Get ready for the burn */
Tom Rini88d86ec2022-12-04 10:03:57 -0500351 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700352 (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200353
354 ts = get_timer (0); /* get current time */
355 /* Now wait for INIT to go high */
356 do {
Tom Rini88d86ec2022-12-04 10:03:57 -0500357 CFG_FPGA_DELAY ();
Tom Rini6a5dccc2022-11-16 13:10:41 -0500358 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200359 puts ("** Timeout waiting for INIT to clear.\n");
Wolfgang Wegner015db1f2010-04-23 11:08:05 +0200360 if (*fn->abort)
361 (*fn->abort) (cookie);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200362 return FPGA_FAIL;
363 }
364 } while ((*fn->init) (cookie));
365
366 /* Load the data */
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100367 if(*fn->bwr)
York Sun4a598092013-04-01 11:29:11 -0700368 (*fn->bwr) (data, bsize, true, cookie);
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100369 else {
370 while (bytecount < bsize) {
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200371
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100372 /* Xilinx detects an error if INIT goes low (active)
373 while DONE is low (inactive) */
374 if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
375 puts ("** CRC error during FPGA load.\n");
Wolfgang Wegner015db1f2010-04-23 11:08:05 +0200376 if (*fn->abort)
377 (*fn->abort) (cookie);
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100378 return (FPGA_FAIL);
379 }
380 val = data [bytecount ++];
381 i = 8;
382 do {
383 /* Deassert the clock */
York Sun4a598092013-04-01 11:29:11 -0700384 (*fn->clk) (false, true, cookie);
Tom Rini88d86ec2022-12-04 10:03:57 -0500385 CFG_FPGA_DELAY ();
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100386 /* Write data */
York Sun4a598092013-04-01 11:29:11 -0700387 (*fn->wr) ((val & 0x80), true, cookie);
Tom Rini88d86ec2022-12-04 10:03:57 -0500388 CFG_FPGA_DELAY ();
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100389 /* Assert the clock */
York Sun4a598092013-04-01 11:29:11 -0700390 (*fn->clk) (true, true, cookie);
Tom Rini88d86ec2022-12-04 10:03:57 -0500391 CFG_FPGA_DELAY ();
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100392 val <<= 1;
393 i --;
394 } while (i > 0);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200395
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200396#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100397 if (bytecount % (bsize / 40) == 0)
398 putc ('.'); /* let them know we are alive */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200399#endif
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100400 }
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200401 }
402
Tom Rini88d86ec2022-12-04 10:03:57 -0500403 CFG_FPGA_DELAY ();
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200404
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200405#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200406 putc ('\n'); /* terminate the dotted line */
407#endif
408
409 /* now check for done signal */
410 ts = get_timer (0); /* get current time */
411 ret_val = FPGA_SUCCESS;
York Sun4a598092013-04-01 11:29:11 -0700412 (*fn->wr) (true, true, cookie);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200413
414 while (! (*fn->done) (cookie)) {
415 /* XXX - we should have a check in here somewhere to
416 * make sure we aren't busy forever... */
417
Tom Rini88d86ec2022-12-04 10:03:57 -0500418 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700419 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Tom Rini88d86ec2022-12-04 10:03:57 -0500420 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700421 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200422
423 putc ('*');
424
Tom Rini6a5dccc2022-11-16 13:10:41 -0500425 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200426 puts ("** Timeout waiting for DONE to clear.\n");
427 ret_val = FPGA_FAIL;
428 break;
429 }
430 }
431 putc ('\n'); /* terminate the dotted line */
432
Matthias Fuchs518e2e142007-12-27 17:12:43 +0100433 /*
434 * Run the post configuration function if there is one.
435 */
Matthias Fuchs93081662009-02-15 22:29:15 +0100436 if (*fn->post)
Matthias Fuchs518e2e142007-12-27 17:12:43 +0100437 (*fn->post) (cookie);
Matthias Fuchs518e2e142007-12-27 17:12:43 +0100438
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200439#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Matthias Fuchs93081662009-02-15 22:29:15 +0100440 if (ret_val == FPGA_SUCCESS)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200441 puts ("Done.\n");
Matthias Fuchs93081662009-02-15 22:29:15 +0100442 else
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200443 puts ("Fail.\n");
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200444#endif
445
446 } else {
447 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
448 }
449
450 return ret_val;
451}
452
Michal Simek25e1e2e2014-03-13 12:49:21 +0100453static int spartan3_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200454{
455 /* Readback is only available through the Slave Parallel and */
456 /* boundary-scan interfaces. */
457 printf ("%s: Slave Serial Dumping is unavailable\n",
458 __FUNCTION__);
459 return FPGA_FAIL;
460}
Michal Simek75fafac2014-03-13 13:07:57 +0100461
462struct xilinx_fpga_op spartan3_op = {
463 .load = spartan3_load,
464 .dump = spartan3_dump,
465 .info = spartan3_info,
466};