1 // SPDX-License-Identifier: GPL-2.0+
4 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
7 #define LOG_CATEGORY UCLASS_FPGA
9 #include <common.h> /* core U-Boot definitions */
11 #include <spartan2.h> /* Spartan-II device family */
13 /* 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).
15 * If there is a need to operate slower, define CFG_FPGA_DELAY in
16 * the board config file to slow things down.
18 #ifndef CFG_FPGA_DELAY
19 #define CFG_FPGA_DELAY()
22 #ifndef CFG_SYS_FPGA_WAIT
23 #define CFG_SYS_FPGA_WAIT CONFIG_SYS_HZ/100 /* 10 ms */
26 static int spartan2_sp_load(xilinx_desc *desc, const void *buf, size_t bsize);
27 static int spartan2_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize);
28 /* static int spartan2_sp_info(xilinx_desc *desc ); */
30 static int spartan2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
31 static int spartan2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
32 /* static int spartan2_ss_info(xilinx_desc *desc ); */
34 /* ------------------------------------------------------------------------- */
35 /* Spartan-II Generic Implementation */
36 static int spartan2_load(xilinx_desc *desc, const void *buf, size_t bsize,
37 bitstream_type bstype, int flags)
39 int ret_val = FPGA_FAIL;
41 switch (desc->iface) {
43 log_debug("Launching Slave Serial Load\n");
44 ret_val = spartan2_ss_load(desc, buf, bsize);
48 log_debug("Launching Slave Parallel Load\n");
49 ret_val = spartan2_sp_load(desc, buf, bsize);
53 printf ("%s: Unsupported interface type, %d\n",
54 __FUNCTION__, desc->iface);
60 static int spartan2_dump(xilinx_desc *desc, const void *buf, size_t bsize)
62 int ret_val = FPGA_FAIL;
64 switch (desc->iface) {
66 log_debug("Launching Slave Serial Dump\n");
67 ret_val = spartan2_ss_dump(desc, buf, bsize);
71 log_debug("Launching Slave Parallel Dump\n");
72 ret_val = spartan2_sp_dump(desc, buf, bsize);
76 printf ("%s: Unsupported interface type, %d\n",
77 __FUNCTION__, desc->iface);
83 static int spartan2_info(xilinx_desc *desc)
89 /* ------------------------------------------------------------------------- */
90 /* Spartan-II Slave Parallel Generic Implementation */
92 static int spartan2_sp_load(xilinx_desc *desc, const void *buf, size_t bsize)
94 int ret_val = FPGA_FAIL; /* assume the worst */
95 xilinx_spartan2_slave_parallel_fns *fn = desc->iface_fns;
97 log_debug("start with interface functions @ 0x%p\n", 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 */
105 log_debug("Function Table:\n"
116 "write data:\t0x%p\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);
125 * This code is designed to emulate the "Express Style"
126 * Continuous Data Loading in Slave Parallel Mode for
127 * the Spartan-II Family.
129 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
130 printf ("Loading FPGA Device %d...\n", cookie);
133 * Run the pre configuration function if there is one.
139 /* Establish the initial state */
140 (*fn->pgm) (true, true, cookie); /* Assert the program, commit */
142 /* Get ready for the burn */
144 (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */
146 ts = get_timer (0); /* get current time */
147 /* Now wait for INIT and BUSY to go high */
150 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
151 puts ("** Timeout waiting for INIT to clear.\n");
152 (*fn->abort) (cookie); /* abort the burn */
155 } while ((*fn->init) (cookie) && (*fn->busy) (cookie));
157 (*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 */
162 while (bytecount < bsize) {
163 /* XXX - do we check for an Ctrl-C press in here ??? */
164 /* XXX - Check the error bit? */
166 (*fn->wdata) (data[bytecount++], true, cookie); /* write the data */
168 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
170 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
172 #ifdef CONFIG_SYS_FPGA_CHECK_BUSY
173 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... */
179 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
181 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
183 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
184 puts ("** Timeout waiting for BUSY to clear.\n");
185 (*fn->abort) (cookie); /* abort the burn */
191 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
192 if (bytecount % (bsize / 40) == 0)
193 putc ('.'); /* let them know we are alive */
198 (*fn->cs) (false, true, cookie); /* Deassert the chip select */
199 (*fn->wr) (false, true, cookie); /* Deassert the write pin */
201 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
202 putc ('\n'); /* terminate the dotted line */
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) {
211 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
213 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
215 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
216 puts ("** Timeout waiting for DONE to clear.\n");
217 (*fn->abort) (cookie); /* abort the burn */
224 * Run the post configuration function if there is one.
227 (*fn->post) (cookie);
229 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
230 if (ret_val == FPGA_SUCCESS)
237 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
243 static int spartan2_sp_dump(xilinx_desc *desc, const void *buf, size_t bsize)
245 int ret_val = FPGA_FAIL; /* assume the worst */
246 xilinx_spartan2_slave_parallel_fns *fn = desc->iface_fns;
249 unsigned char *data = (unsigned char *) buf;
250 size_t bytecount = 0;
251 int cookie = desc->cookie; /* make a local copy */
253 printf ("Starting Dump of FPGA Device %d...\n", cookie);
255 (*fn->cs) (true, true, cookie); /* Assert chip select, commit */
256 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
259 while (bytecount < bsize) {
260 /* XXX - do we check for an Ctrl-C press in here ??? */
262 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
263 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
264 (*fn->rdata) (&(data[bytecount++]), cookie); /* read the data */
265 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
266 if (bytecount % (bsize / 40) == 0)
267 putc ('.'); /* let them know we are alive */
271 (*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 */
275 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
276 putc ('\n'); /* terminate the dotted line */
280 /* XXX - checksum the data? */
282 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
289 /* ------------------------------------------------------------------------- */
291 static int spartan2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
293 int ret_val = FPGA_FAIL; /* assume the worst */
294 xilinx_spartan2_slave_serial_fns *fn = desc->iface_fns;
298 log_debug("start with interface functions @ 0x%p\n", 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 */
306 log_debug("Function Table:\n"
314 &fn, fn, fn->pgm, fn->init,
315 fn->clk, fn->wr, fn->done);
316 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
317 printf ("Loading FPGA Device %d...\n", cookie);
321 * Run the pre configuration function if there is one.
327 /* Establish the initial state */
328 (*fn->pgm) (true, true, cookie); /* Assert the program, commit */
330 /* Wait for INIT state (init low) */
331 ts = get_timer (0); /* get current time */
334 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
335 puts ("** Timeout waiting for INIT to start.\n");
338 } while (!(*fn->init) (cookie));
340 /* Get ready for the burn */
342 (*fn->pgm) (false, true, cookie); /* Deassert the program, commit */
344 ts = get_timer (0); /* get current time */
345 /* Now wait for INIT to go high */
348 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
349 puts ("** Timeout waiting for INIT to clear.\n");
352 } while ((*fn->init) (cookie));
355 while (bytecount < bsize) {
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");
363 val = data [bytecount ++];
366 /* Deassert the clock */
367 (*fn->clk) (false, true, cookie);
370 (*fn->wr) ((val & 0x80), true, cookie);
372 /* Assert the clock */
373 (*fn->clk) (true, true, cookie);
379 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
380 if (bytecount % (bsize / 40) == 0)
381 putc ('.'); /* let them know we are alive */
387 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
388 putc ('\n'); /* terminate the dotted line */
391 /* now check for done signal */
392 ts = get_timer (0); /* get current time */
393 ret_val = FPGA_SUCCESS;
394 (*fn->wr) (true, true, cookie);
396 while (! (*fn->done) (cookie)) {
399 (*fn->clk) (false, true, cookie); /* Deassert the clock pin */
401 (*fn->clk) (true, true, cookie); /* Assert the clock pin */
405 if (get_timer (ts) > CFG_SYS_FPGA_WAIT) { /* check the time */
406 puts ("** Timeout waiting for DONE to clear.\n");
411 putc ('\n'); /* terminate the dotted line */
414 * Run the post configuration function if there is one.
417 (*fn->post) (cookie);
419 #ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
420 if (ret_val == FPGA_SUCCESS)
427 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
433 static int spartan2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
435 /* Readback is only available through the Slave Parallel and */
436 /* boundary-scan interfaces. */
437 printf ("%s: Slave Serial Dumping is unavailable\n",
442 struct xilinx_fpga_op spartan2_op = {
443 .load = spartan2_load,
444 .dump = spartan2_dump,
445 .info = spartan2_info,