blob: e892fa571f196f42e3467017617090d60b0f3ff9 [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 Riniabb9a042024-05-18 20:20:43 -060014#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
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020018/* Note: The assumption is that we cannot possibly run fast enough to
19 * overrun the device (the Slave Parallel mode can free run at 50MHz).
Tom Rini88d86ec2022-12-04 10:03:57 -050020 * If there is a need to operate slower, define CFG_FPGA_DELAY in
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020021 * the board config file to slow things down.
22 */
Tom Rini88d86ec2022-12-04 10:03:57 -050023#ifndef CFG_FPGA_DELAY
24#define CFG_FPGA_DELAY()
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020025#endif
26
Tom Rini6a5dccc2022-11-16 13:10:41 -050027#ifndef CFG_SYS_FPGA_WAIT
28#define CFG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100 /* 10 ms */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020029#endif
30
Michal Simek25e1e2e2014-03-13 12:49:21 +010031static int spartan3_sp_load(xilinx_desc *desc, const void *buf, size_t bsize);
32static int spartan3_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize);
33/* static int spartan3_sp_info(xilinx_desc *desc ); */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020034
Michal Simek25e1e2e2014-03-13 12:49:21 +010035static int spartan3_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
36static int spartan3_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
37/* static int spartan3_ss_info(xilinx_desc *desc); */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020038
39/* ------------------------------------------------------------------------- */
40/* Spartan-II Generic Implementation */
Michal Simek14663652014-05-02 14:09:30 +020041static int spartan3_load(xilinx_desc *desc, const void *buf, size_t bsize,
Oleksandr Suvorovc0806cc2022-07-22 17:16:10 +030042 bitstream_type bstype, int flags)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020043{
44 int ret_val = FPGA_FAIL;
45
46 switch (desc->iface) {
47 case slave_serial:
Alexander Dahla151d232022-10-07 14:20:02 +020048 log_debug("Launching Slave Serial Load\n");
Michal Simek2091a0c2014-03-13 11:28:42 +010049 ret_val = spartan3_ss_load(desc, buf, bsize);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020050 break;
51
52 case slave_parallel:
Alexander Dahla151d232022-10-07 14:20:02 +020053 log_debug("Launching Slave Parallel Load\n");
Michal Simek2091a0c2014-03-13 11:28:42 +010054 ret_val = spartan3_sp_load(desc, buf, bsize);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020055 break;
56
57 default:
58 printf ("%s: Unsupported interface type, %d\n",
59 __FUNCTION__, desc->iface);
60 }
61
62 return ret_val;
63}
64
Michal Simek75fafac2014-03-13 13:07:57 +010065static int spartan3_dump(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020066{
67 int ret_val = FPGA_FAIL;
68
69 switch (desc->iface) {
70 case slave_serial:
Alexander Dahla151d232022-10-07 14:20:02 +020071 log_debug("Launching Slave Serial Dump\n");
Michal Simek2091a0c2014-03-13 11:28:42 +010072 ret_val = spartan3_ss_dump(desc, buf, bsize);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020073 break;
74
75 case slave_parallel:
Alexander Dahla151d232022-10-07 14:20:02 +020076 log_debug("Launching Slave Parallel Dump\n");
Michal Simek2091a0c2014-03-13 11:28:42 +010077 ret_val = spartan3_sp_dump(desc, buf, bsize);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020078 break;
79
80 default:
81 printf ("%s: Unsupported interface type, %d\n",
82 __FUNCTION__, desc->iface);
83 }
84
85 return ret_val;
86}
87
Michal Simek75fafac2014-03-13 13:07:57 +010088static int spartan3_info(xilinx_desc *desc)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020089{
90 return FPGA_SUCCESS;
91}
92
93
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020094/* ------------------------------------------------------------------------- */
95/* Spartan-II Slave Parallel Generic Implementation */
96
Michal Simek25e1e2e2014-03-13 12:49:21 +010097static int spartan3_sp_load(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +020098{
99 int ret_val = FPGA_FAIL; /* assume the worst */
Michal Simek2091a0c2014-03-13 11:28:42 +0100100 xilinx_spartan3_slave_parallel_fns *fn = desc->iface_fns;
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200101
Alexander Dahla151d232022-10-07 14:20:02 +0200102 log_debug("start with interface functions @ 0x%p\n", fn);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200103
104 if (fn) {
105 size_t bytecount = 0;
106 unsigned char *data = (unsigned char *) buf;
107 int cookie = desc->cookie; /* make a local copy */
108 unsigned long ts; /* timestamp */
109
Alexander Dahla151d232022-10-07 14:20:02 +0200110 log_debug("Function Table:\n"
111 "ptr:\t0x%p\n"
112 "struct: 0x%p\n"
113 "pre: 0x%p\n"
114 "pgm:\t0x%p\n"
115 "init:\t0x%p\n"
116 "err:\t0x%p\n"
117 "clk:\t0x%p\n"
118 "cs:\t0x%p\n"
119 "wr:\t0x%p\n"
120 "read data:\t0x%p\n"
121 "write data:\t0x%p\n"
122 "busy:\t0x%p\n"
123 "abort:\t0x%p\n"
124 "post:\t0x%p\n\n",
125 &fn, fn, fn->pre, fn->pgm, fn->init, fn->err,
126 fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata, fn->busy,
127 fn->abort, fn->post);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200128
129 /*
130 * This code is designed to emulate the "Express Style"
131 * Continuous Data Loading in Slave Parallel Mode for
132 * the Spartan-II Family.
133 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200134#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200135 printf ("Loading FPGA Device %d...\n", cookie);
136#endif
137 /*
138 * Run the pre configuration function if there is one.
139 */
140 if (*fn->pre) {
141 (*fn->pre) (cookie);
142 }
143
144 /* Establish the initial state */
York Sun4a598092013-04-01 11:29:11 -0700145 (*fn->pgm) (true, true, cookie); /* Assert the program, commit */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200146
147 /* Get ready for the burn */
Tom Rini88d86ec2022-12-04 10:03:57 -0500148 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700149 (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200150
151 ts = get_timer (0); /* get current time */
152 /* Now wait for INIT and BUSY to go high */
153 do {
Tom Rini88d86ec2022-12-04 10:03:57 -0500154 CFG_FPGA_DELAY ();
Tom Rini6a5dccc2022-11-16 13:10:41 -0500155 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200156 puts ("** Timeout waiting for INIT to clear.\n");
157 (*fn->abort) (cookie); /* abort the burn */
158 return FPGA_FAIL;
159 }
160 } while ((*fn->init) (cookie) && (*fn->busy) (cookie));
161
York Sun4a598092013-04-01 11:29:11 -0700162 (*fn->wr) (true, true, cookie); /* Assert write, commit */
163 (*fn->cs) (true, true, cookie); /* Assert chip select, commit */
164 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200165
166 /* Load the data */
167 while (bytecount < bsize) {
168 /* XXX - do we check for an Ctrl-C press in here ??? */
169 /* XXX - Check the error bit? */
170
York Sun4a598092013-04-01 11:29:11 -0700171 (*fn->wdata) (data[bytecount++], true, cookie); /* write the data */
Tom Rini88d86ec2022-12-04 10:03:57 -0500172 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700173 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Tom Rini88d86ec2022-12-04 10:03:57 -0500174 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700175 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200176
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200177#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200178 ts = get_timer (0); /* get current time */
179 while ((*fn->busy) (cookie)) {
180 /* XXX - we should have a check in here somewhere to
181 * make sure we aren't busy forever... */
182
Tom Rini88d86ec2022-12-04 10:03:57 -0500183 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700184 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Tom Rini88d86ec2022-12-04 10:03:57 -0500185 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700186 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200187
Tom Rini6a5dccc2022-11-16 13:10:41 -0500188 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200189 puts ("** Timeout waiting for BUSY to clear.\n");
190 (*fn->abort) (cookie); /* abort the burn */
191 return FPGA_FAIL;
192 }
193 }
194#endif
195
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200196#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200197 if (bytecount % (bsize / 40) == 0)
198 putc ('.'); /* let them know we are alive */
199#endif
200 }
201
Tom Rini88d86ec2022-12-04 10:03:57 -0500202 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700203 (*fn->cs) (false, true, cookie); /* Deassert the chip select */
204 (*fn->wr) (false, true, cookie); /* Deassert the write pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200205
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200206#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200207 putc ('\n'); /* terminate the dotted line */
208#endif
209
210 /* now check for done signal */
211 ts = get_timer (0); /* get current time */
212 ret_val = FPGA_SUCCESS;
213 while ((*fn->done) (cookie) == FPGA_FAIL) {
214 /* XXX - we should have a check in here somewhere to
215 * make sure we aren't busy forever... */
216
Tom Rini88d86ec2022-12-04 10:03:57 -0500217 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700218 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Tom Rini88d86ec2022-12-04 10:03:57 -0500219 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700220 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200221
Tom Rini6a5dccc2022-11-16 13:10:41 -0500222 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200223 puts ("** Timeout waiting for DONE to clear.\n");
224 (*fn->abort) (cookie); /* abort the burn */
225 ret_val = FPGA_FAIL;
226 break;
227 }
228 }
229
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200230 /*
231 * Run the post configuration function if there is one.
232 */
Matthias Fuchs93081662009-02-15 22:29:15 +0100233 if (*fn->post)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200234 (*fn->post) (cookie);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200235
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200236#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Matthias Fuchs93081662009-02-15 22:29:15 +0100237 if (ret_val == FPGA_SUCCESS)
238 puts ("Done.\n");
239 else
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200240 puts ("Fail.\n");
241#endif
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200242
243 } else {
244 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
245 }
246
247 return ret_val;
248}
249
Michal Simek25e1e2e2014-03-13 12:49:21 +0100250static int spartan3_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200251{
252 int ret_val = FPGA_FAIL; /* assume the worst */
Michal Simek2091a0c2014-03-13 11:28:42 +0100253 xilinx_spartan3_slave_parallel_fns *fn = desc->iface_fns;
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200254
255 if (fn) {
256 unsigned char *data = (unsigned char *) buf;
257 size_t bytecount = 0;
258 int cookie = desc->cookie; /* make a local copy */
259
260 printf ("Starting Dump of FPGA Device %d...\n", cookie);
261
York Sun4a598092013-04-01 11:29:11 -0700262 (*fn->cs) (true, true, cookie); /* Assert chip select, commit */
263 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200264
265 /* dump the data */
266 while (bytecount < bsize) {
267 /* XXX - do we check for an Ctrl-C press in here ??? */
268
York Sun4a598092013-04-01 11:29:11 -0700269 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
270 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200271 (*fn->rdata) (&(data[bytecount++]), cookie); /* read the data */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200272#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200273 if (bytecount % (bsize / 40) == 0)
274 putc ('.'); /* let them know we are alive */
275#endif
276 }
277
York Sun4a598092013-04-01 11:29:11 -0700278 (*fn->cs) (false, false, cookie); /* Deassert the chip select */
279 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
280 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200281
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200282#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200283 putc ('\n'); /* terminate the dotted line */
284#endif
285 puts ("Done.\n");
286
287 /* XXX - checksum the data? */
288 } else {
289 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
290 }
291
292 return ret_val;
293}
294
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200295
296/* ------------------------------------------------------------------------- */
297
Michal Simek25e1e2e2014-03-13 12:49:21 +0100298static int spartan3_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200299{
300 int ret_val = FPGA_FAIL; /* assume the worst */
Michal Simek2091a0c2014-03-13 11:28:42 +0100301 xilinx_spartan3_slave_serial_fns *fn = desc->iface_fns;
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200302 int i;
Matthias Fuchsb845b1e2007-12-27 17:13:05 +0100303 unsigned char val;
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200304
Alexander Dahla151d232022-10-07 14:20:02 +0200305 log_debug("start with interface functions @ 0x%p\n", fn);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200306
307 if (fn) {
308 size_t bytecount = 0;
309 unsigned char *data = (unsigned char *) buf;
310 int cookie = desc->cookie; /* make a local copy */
311 unsigned long ts; /* timestamp */
312
Alexander Dahla151d232022-10-07 14:20:02 +0200313 log_debug("Function Table:\n"
314 "ptr:\t0x%p\n"
315 "struct: 0x%p\n"
316 "pgm:\t0x%p\n"
317 "init:\t0x%p\n"
318 "clk:\t0x%p\n"
319 "wr:\t0x%p\n"
320 "done:\t0x%p\n\n",
321 &fn, fn, fn->pgm, fn->init,
322 fn->clk, fn->wr, fn->done);
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200323#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200324 printf ("Loading FPGA Device %d...\n", cookie);
325#endif
326
327 /*
328 * Run the pre configuration function if there is one.
329 */
330 if (*fn->pre) {
331 (*fn->pre) (cookie);
332 }
333
334 /* Establish the initial state */
York Sun4a598092013-04-01 11:29:11 -0700335 (*fn->pgm) (true, true, cookie); /* Assert the program, commit */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200336
337 /* Wait for INIT state (init low) */
338 ts = get_timer (0); /* get current time */
339 do {
Tom Rini88d86ec2022-12-04 10:03:57 -0500340 CFG_FPGA_DELAY ();
Tom Rini6a5dccc2022-11-16 13:10:41 -0500341 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200342 puts ("** Timeout waiting for INIT to start.\n");
Wolfgang Wegner015db1f2010-04-23 11:08:05 +0200343 if (*fn->abort)
344 (*fn->abort) (cookie);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200345 return FPGA_FAIL;
346 }
347 } while (!(*fn->init) (cookie));
348
349 /* Get ready for the burn */
Tom Rini88d86ec2022-12-04 10:03:57 -0500350 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700351 (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200352
353 ts = get_timer (0); /* get current time */
354 /* Now wait for INIT to go high */
355 do {
Tom Rini88d86ec2022-12-04 10:03:57 -0500356 CFG_FPGA_DELAY ();
Tom Rini6a5dccc2022-11-16 13:10:41 -0500357 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200358 puts ("** Timeout waiting for INIT to clear.\n");
Wolfgang Wegner015db1f2010-04-23 11:08:05 +0200359 if (*fn->abort)
360 (*fn->abort) (cookie);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200361 return FPGA_FAIL;
362 }
363 } while ((*fn->init) (cookie));
364
365 /* Load the data */
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100366 if(*fn->bwr)
York Sun4a598092013-04-01 11:29:11 -0700367 (*fn->bwr) (data, bsize, true, cookie);
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100368 else {
369 while (bytecount < bsize) {
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200370
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100371 /* Xilinx detects an error if INIT goes low (active)
372 while DONE is low (inactive) */
373 if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
374 puts ("** CRC error during FPGA load.\n");
Wolfgang Wegner015db1f2010-04-23 11:08:05 +0200375 if (*fn->abort)
376 (*fn->abort) (cookie);
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100377 return (FPGA_FAIL);
378 }
379 val = data [bytecount ++];
380 i = 8;
381 do {
382 /* Deassert the clock */
York Sun4a598092013-04-01 11:29:11 -0700383 (*fn->clk) (false, true, cookie);
Tom Rini88d86ec2022-12-04 10:03:57 -0500384 CFG_FPGA_DELAY ();
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100385 /* Write data */
York Sun4a598092013-04-01 11:29:11 -0700386 (*fn->wr) ((val & 0x80), true, cookie);
Tom Rini88d86ec2022-12-04 10:03:57 -0500387 CFG_FPGA_DELAY ();
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100388 /* Assert the clock */
York Sun4a598092013-04-01 11:29:11 -0700389 (*fn->clk) (true, true, cookie);
Tom Rini88d86ec2022-12-04 10:03:57 -0500390 CFG_FPGA_DELAY ();
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100391 val <<= 1;
392 i --;
393 } while (i > 0);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200394
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200395#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100396 if (bytecount % (bsize / 40) == 0)
397 putc ('.'); /* let them know we are alive */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200398#endif
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100399 }
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200400 }
401
Tom Rini88d86ec2022-12-04 10:03:57 -0500402 CFG_FPGA_DELAY ();
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200403
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200404#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200405 putc ('\n'); /* terminate the dotted line */
406#endif
407
408 /* now check for done signal */
409 ts = get_timer (0); /* get current time */
410 ret_val = FPGA_SUCCESS;
York Sun4a598092013-04-01 11:29:11 -0700411 (*fn->wr) (true, true, cookie);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200412
413 while (! (*fn->done) (cookie)) {
414 /* XXX - we should have a check in here somewhere to
415 * make sure we aren't busy forever... */
416
Tom Rini88d86ec2022-12-04 10:03:57 -0500417 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700418 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Tom Rini88d86ec2022-12-04 10:03:57 -0500419 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700420 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200421
422 putc ('*');
423
Tom Rini6a5dccc2022-11-16 13:10:41 -0500424 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200425 puts ("** Timeout waiting for DONE to clear.\n");
426 ret_val = FPGA_FAIL;
427 break;
428 }
429 }
430 putc ('\n'); /* terminate the dotted line */
431
Matthias Fuchs518e2e142007-12-27 17:12:43 +0100432 /*
433 * Run the post configuration function if there is one.
434 */
Matthias Fuchs93081662009-02-15 22:29:15 +0100435 if (*fn->post)
Matthias Fuchs518e2e142007-12-27 17:12:43 +0100436 (*fn->post) (cookie);
Matthias Fuchs518e2e142007-12-27 17:12:43 +0100437
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200438#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Matthias Fuchs93081662009-02-15 22:29:15 +0100439 if (ret_val == FPGA_SUCCESS)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200440 puts ("Done.\n");
Matthias Fuchs93081662009-02-15 22:29:15 +0100441 else
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200442 puts ("Fail.\n");
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200443#endif
444
445 } else {
446 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
447 }
448
449 return ret_val;
450}
451
Michal Simek25e1e2e2014-03-13 12:49:21 +0100452static int spartan3_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200453{
454 /* Readback is only available through the Slave Parallel and */
455 /* boundary-scan interfaces. */
456 printf ("%s: Slave Serial Dumping is unavailable\n",
457 __FUNCTION__);
458 return FPGA_FAIL;
459}
Michal Simek75fafac2014-03-13 13:07:57 +0100460
461struct xilinx_fpga_op spartan3_op = {
462 .load = spartan3_load,
463 .dump = spartan3_dump,
464 .info = spartan3_info,
465};