blob: 98405589134317b697be5d543c6b9651098e6a46 [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
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
Michal Simek25e1e2e2014-03-13 12:49:21 +0100297static int spartan3_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200298{
299 int ret_val = FPGA_FAIL; /* assume the worst */
Michal Simek2091a0c2014-03-13 11:28:42 +0100300 xilinx_spartan3_slave_serial_fns *fn = desc->iface_fns;
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200301 int i;
Matthias Fuchsb845b1e2007-12-27 17:13:05 +0100302 unsigned char val;
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200303
Alexander Dahla151d232022-10-07 14:20:02 +0200304 log_debug("start with interface functions @ 0x%p\n", fn);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200305
306 if (fn) {
307 size_t bytecount = 0;
308 unsigned char *data = (unsigned char *) buf;
309 int cookie = desc->cookie; /* make a local copy */
310 unsigned long ts; /* timestamp */
311
Alexander Dahla151d232022-10-07 14:20:02 +0200312 log_debug("Function Table:\n"
313 "ptr:\t0x%p\n"
314 "struct: 0x%p\n"
315 "pgm:\t0x%p\n"
316 "init:\t0x%p\n"
317 "clk:\t0x%p\n"
318 "wr:\t0x%p\n"
319 "done:\t0x%p\n\n",
320 &fn, fn, fn->pgm, fn->init,
321 fn->clk, fn->wr, fn->done);
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200322#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200323 printf ("Loading FPGA Device %d...\n", cookie);
324#endif
325
326 /*
327 * Run the pre configuration function if there is one.
328 */
329 if (*fn->pre) {
330 (*fn->pre) (cookie);
331 }
332
333 /* Establish the initial state */
York Sun4a598092013-04-01 11:29:11 -0700334 (*fn->pgm) (true, true, cookie); /* Assert the program, commit */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200335
336 /* Wait for INIT state (init low) */
337 ts = get_timer (0); /* get current time */
338 do {
Tom Rini88d86ec2022-12-04 10:03:57 -0500339 CFG_FPGA_DELAY ();
Tom Rini6a5dccc2022-11-16 13:10:41 -0500340 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200341 puts ("** Timeout waiting for INIT to start.\n");
Wolfgang Wegner015db1f2010-04-23 11:08:05 +0200342 if (*fn->abort)
343 (*fn->abort) (cookie);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200344 return FPGA_FAIL;
345 }
346 } while (!(*fn->init) (cookie));
347
348 /* Get ready for the burn */
Tom Rini88d86ec2022-12-04 10:03:57 -0500349 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700350 (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200351
352 ts = get_timer (0); /* get current time */
353 /* Now wait for INIT to go high */
354 do {
Tom Rini88d86ec2022-12-04 10:03:57 -0500355 CFG_FPGA_DELAY ();
Tom Rini6a5dccc2022-11-16 13:10:41 -0500356 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200357 puts ("** Timeout waiting for INIT to clear.\n");
Wolfgang Wegner015db1f2010-04-23 11:08:05 +0200358 if (*fn->abort)
359 (*fn->abort) (cookie);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200360 return FPGA_FAIL;
361 }
362 } while ((*fn->init) (cookie));
363
364 /* Load the data */
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100365 if(*fn->bwr)
York Sun4a598092013-04-01 11:29:11 -0700366 (*fn->bwr) (data, bsize, true, cookie);
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100367 else {
368 while (bytecount < bsize) {
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200369
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100370 /* Xilinx detects an error if INIT goes low (active)
371 while DONE is low (inactive) */
372 if ((*fn->done) (cookie) == 0 && (*fn->init) (cookie)) {
373 puts ("** CRC error during FPGA load.\n");
Wolfgang Wegner015db1f2010-04-23 11:08:05 +0200374 if (*fn->abort)
375 (*fn->abort) (cookie);
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100376 return (FPGA_FAIL);
377 }
378 val = data [bytecount ++];
379 i = 8;
380 do {
381 /* Deassert the clock */
York Sun4a598092013-04-01 11:29:11 -0700382 (*fn->clk) (false, true, cookie);
Tom Rini88d86ec2022-12-04 10:03:57 -0500383 CFG_FPGA_DELAY ();
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100384 /* Write data */
York Sun4a598092013-04-01 11:29:11 -0700385 (*fn->wr) ((val & 0x80), true, cookie);
Tom Rini88d86ec2022-12-04 10:03:57 -0500386 CFG_FPGA_DELAY ();
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100387 /* Assert the clock */
York Sun4a598092013-04-01 11:29:11 -0700388 (*fn->clk) (true, true, cookie);
Tom Rini88d86ec2022-12-04 10:03:57 -0500389 CFG_FPGA_DELAY ();
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100390 val <<= 1;
391 i --;
392 } while (i > 0);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200393
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200394#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100395 if (bytecount % (bsize / 40) == 0)
396 putc ('.'); /* let them know we are alive */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200397#endif
Wolfgang Wegnerd37e5552009-10-30 16:55:02 +0100398 }
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200399 }
400
Tom Rini88d86ec2022-12-04 10:03:57 -0500401 CFG_FPGA_DELAY ();
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200402
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200403#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200404 putc ('\n'); /* terminate the dotted line */
405#endif
406
407 /* now check for done signal */
408 ts = get_timer (0); /* get current time */
409 ret_val = FPGA_SUCCESS;
York Sun4a598092013-04-01 11:29:11 -0700410 (*fn->wr) (true, true, cookie);
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200411
412 while (! (*fn->done) (cookie)) {
413 /* XXX - we should have a check in here somewhere to
414 * make sure we aren't busy forever... */
415
Tom Rini88d86ec2022-12-04 10:03:57 -0500416 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700417 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
Tom Rini88d86ec2022-12-04 10:03:57 -0500418 CFG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700419 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200420
421 putc ('*');
422
Tom Rini6a5dccc2022-11-16 13:10:41 -0500423 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200424 puts ("** Timeout waiting for DONE to clear.\n");
425 ret_val = FPGA_FAIL;
426 break;
427 }
428 }
429 putc ('\n'); /* terminate the dotted line */
430
Matthias Fuchs518e2e142007-12-27 17:12:43 +0100431 /*
432 * Run the post configuration function if there is one.
433 */
Matthias Fuchs93081662009-02-15 22:29:15 +0100434 if (*fn->post)
Matthias Fuchs518e2e142007-12-27 17:12:43 +0100435 (*fn->post) (cookie);
Matthias Fuchs518e2e142007-12-27 17:12:43 +0100436
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200437#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Matthias Fuchs93081662009-02-15 22:29:15 +0100438 if (ret_val == FPGA_SUCCESS)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200439 puts ("Done.\n");
Matthias Fuchs93081662009-02-15 22:29:15 +0100440 else
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200441 puts ("Fail.\n");
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200442#endif
443
444 } else {
445 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
446 }
447
448 return ret_val;
449}
450
Michal Simek25e1e2e2014-03-13 12:49:21 +0100451static int spartan3_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
Wolfgang Denkc38e70c2005-09-25 16:44:21 +0200452{
453 /* Readback is only available through the Slave Parallel and */
454 /* boundary-scan interfaces. */
455 printf ("%s: Slave Serial Dumping is unavailable\n",
456 __FUNCTION__);
457 return FPGA_FAIL;
458}
Michal Simek75fafac2014-03-13 13:07:57 +0100459
460struct xilinx_fpga_op spartan3_op = {
461 .load = spartan3_load,
462 .dump = spartan3_dump,
463 .info = spartan3_info,
464};