blob: 395736875f60106506033d65dc7f1768137964d8 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
wdenk5d3207d2002-08-21 22:08:56 +00002/*
3 * (C) Copyright 2002
4 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
5 * Keith Outwater, keith_outwater@mvis.com
Robert Hancock0b888342019-06-18 09:47:16 -06006 *
7 * Copyright (c) 2019 SED Systems, a division of Calian Ltd.
wdenk5d3207d2002-08-21 22:08:56 +00008 */
9
10/*
11 * Configuration support for Xilinx Virtex2 devices. Based
12 * on spartan2.c (Rich Ireland, rireland@enterasys.com).
13 */
14
15#include <common.h>
Simon Glassa73bda42015-11-08 23:47:45 -070016#include <console.h>
wdenk5d3207d2002-08-21 22:08:56 +000017#include <virtex2.h>
18
Wolfgang Denkffb77562005-09-24 23:41:00 +020019#if 0
20#define FPGA_DEBUG
Wolfgang Denk0cbaf642005-09-25 00:53:22 +020021#endif
Wolfgang Denkffb77562005-09-24 23:41:00 +020022
wdenk5d3207d2002-08-21 22:08:56 +000023#ifdef FPGA_DEBUG
Robert Hancock19b55dc2019-06-18 09:47:12 -060024#define PRINTF(fmt, args...) printf(fmt, ##args)
wdenk5d3207d2002-08-21 22:08:56 +000025#else
Robert Hancock19b55dc2019-06-18 09:47:12 -060026#define PRINTF(fmt, args...)
wdenk5d3207d2002-08-21 22:08:56 +000027#endif
28
29/*
30 * If the SelectMap interface can be overrun by the processor, define
Robert Hancock19b55dc2019-06-18 09:47:12 -060031 * CONFIG_SYS_FPGA_CHECK_BUSY and/or CONFIG_FPGA_DELAY in the board
32 * configuration file and add board-specific support for checking BUSY status.
33 * By default, assume that the SelectMap interface cannot be overrun.
wdenk5d3207d2002-08-21 22:08:56 +000034 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020035#ifndef CONFIG_SYS_FPGA_CHECK_BUSY
36#undef CONFIG_SYS_FPGA_CHECK_BUSY
wdenk5d3207d2002-08-21 22:08:56 +000037#endif
38
39#ifndef CONFIG_FPGA_DELAY
40#define CONFIG_FPGA_DELAY()
41#endif
42
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020043#ifndef CONFIG_SYS_FPGA_PROG_FEEDBACK
44#define CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk5d3207d2002-08-21 22:08:56 +000045#endif
46
47/*
48 * Don't allow config cycle to be interrupted
49 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020050#ifndef CONFIG_SYS_FPGA_CHECK_CTRLC
51#undef CONFIG_SYS_FPGA_CHECK_CTRLC
wdenk5d3207d2002-08-21 22:08:56 +000052#endif
53
54/*
55 * Check for errors during configuration by default
56 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020057#ifndef CONFIG_SYS_FPGA_CHECK_ERROR
58#define CONFIG_SYS_FPGA_CHECK_ERROR
wdenk5d3207d2002-08-21 22:08:56 +000059#endif
60
61/*
62 * The default timeout in mS for INIT_B to deassert after PROG_B has
63 * been deasserted. Per the latest Virtex II Handbook (page 347), the
64 * max time from PORG_B deassertion to INIT_B deassertion is 4uS per
65 * data frame for the XC2V8000. The XC2V8000 has 2860 data frames
66 * which yields 11.44 mS. So let's make it bigger in order to handle
67 * an XC2V1000, if anyone can ever get ahold of one.
68 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020069#ifndef CONFIG_SYS_FPGA_WAIT_INIT
Robert Hancock19b55dc2019-06-18 09:47:12 -060070#define CONFIG_SYS_FPGA_WAIT_INIT CONFIG_SYS_HZ / 2 /* 500 ms */
wdenk5d3207d2002-08-21 22:08:56 +000071#endif
72
73/*
74 * The default timeout for waiting for BUSY to deassert during configuration.
75 * This is normally not necessary since for most reasonable configuration
76 * clock frequencies (i.e. 66 MHz or less), BUSY monitoring is unnecessary.
77 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020078#ifndef CONFIG_SYS_FPGA_WAIT_BUSY
Robert Hancock19b55dc2019-06-18 09:47:12 -060079#define CONFIG_SYS_FPGA_WAIT_BUSY CONFIG_SYS_HZ / 200 /* 5 ms*/
wdenk5d3207d2002-08-21 22:08:56 +000080#endif
81
82/* Default timeout for waiting for FPGA to enter operational mode after
83 * configuration data has been written.
84 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020085#ifndef CONFIG_SYS_FPGA_WAIT_CONFIG
Robert Hancock19b55dc2019-06-18 09:47:12 -060086#define CONFIG_SYS_FPGA_WAIT_CONFIG CONFIG_SYS_HZ / 5 /* 200 ms */
wdenk5d3207d2002-08-21 22:08:56 +000087#endif
88
Michal Simek25e1e2e2014-03-13 12:49:21 +010089static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize);
90static int virtex2_ssm_dump(xilinx_desc *desc, const void *buf, size_t bsize);
wdenk5d3207d2002-08-21 22:08:56 +000091
Michal Simek25e1e2e2014-03-13 12:49:21 +010092static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
93static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
wdenk5d3207d2002-08-21 22:08:56 +000094
Michal Simek14663652014-05-02 14:09:30 +020095static int virtex2_load(xilinx_desc *desc, const void *buf, size_t bsize,
96 bitstream_type bstype)
wdenk5d3207d2002-08-21 22:08:56 +000097{
98 int ret_val = FPGA_FAIL;
99
100 switch (desc->iface) {
101 case slave_serial:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600102 PRINTF("%s: Launching Slave Serial Load\n", __func__);
Michal Simek90258882014-03-13 11:33:36 +0100103 ret_val = virtex2_ss_load(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000104 break;
105
106 case slave_selectmap:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600107 PRINTF("%s: Launching Slave Parallel Load\n", __func__);
Michal Simek90258882014-03-13 11:33:36 +0100108 ret_val = virtex2_ssm_load(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000109 break;
110
111 default:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600112 printf("%s: Unsupported interface type, %d\n",
113 __func__, desc->iface);
wdenk5d3207d2002-08-21 22:08:56 +0000114 }
115 return ret_val;
116}
117
Michal Simek75fafac2014-03-13 13:07:57 +0100118static int virtex2_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000119{
120 int ret_val = FPGA_FAIL;
121
122 switch (desc->iface) {
123 case slave_serial:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600124 PRINTF("%s: Launching Slave Serial Dump\n", __func__);
Michal Simek90258882014-03-13 11:33:36 +0100125 ret_val = virtex2_ss_dump(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000126 break;
127
128 case slave_parallel:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600129 PRINTF("%s: Launching Slave Parallel Dump\n", __func__);
Michal Simek90258882014-03-13 11:33:36 +0100130 ret_val = virtex2_ssm_dump(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000131 break;
132
133 default:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600134 printf("%s: Unsupported interface type, %d\n",
135 __func__, desc->iface);
wdenk5d3207d2002-08-21 22:08:56 +0000136 }
137 return ret_val;
138}
139
Michal Simek75fafac2014-03-13 13:07:57 +0100140static int virtex2_info(xilinx_desc *desc)
wdenk5d3207d2002-08-21 22:08:56 +0000141{
142 return FPGA_SUCCESS;
143}
144
wdenk5d3207d2002-08-21 22:08:56 +0000145/*
Robert Hancock0b888342019-06-18 09:47:16 -0600146 * Virtex-II Slave SelectMap or Serial configuration loader. Configuration
147 * is as follows:
wdenk5d3207d2002-08-21 22:08:56 +0000148 * 1. Set the FPGA's PROG_B line low.
149 * 2. Set the FPGA's PROG_B line high. Wait for INIT_B to go high.
150 * 3. Write data to the SelectMap port. If INIT_B goes low at any time
151 * this process, a configuration error (most likely CRC failure) has
152 * ocurred. At this point a status word may be read from the
153 * SelectMap interface to determine the source of the problem (You
Wolfgang Denkffb77562005-09-24 23:41:00 +0200154 * could, for instance, put this in your 'abort' function handler).
wdenk5d3207d2002-08-21 22:08:56 +0000155 * 4. After all data has been written, test the state of the FPGA
156 * INIT_B and DONE lines. If both are high, configuration has
157 * succeeded. Congratulations!
158 */
Robert Hancock0b888342019-06-18 09:47:16 -0600159static int virtex2_slave_pre(xilinx_virtex2_slave_fns *fn, int cookie)
wdenk5d3207d2002-08-21 22:08:56 +0000160{
Robert Hancock8a7d6632019-06-18 09:47:14 -0600161 unsigned long ts;
wdenk5d3207d2002-08-21 22:08:56 +0000162
Robert Hancock19b55dc2019-06-18 09:47:12 -0600163 PRINTF("%s:%d: Start with interface functions @ 0x%p\n",
164 __func__, __LINE__, fn);
wdenk5d3207d2002-08-21 22:08:56 +0000165
Robert Hancock8a7d6632019-06-18 09:47:14 -0600166 if (!fn) {
167 printf("%s:%d: NULL Interface function table!\n",
168 __func__, __LINE__);
169 return FPGA_FAIL;
170 }
wdenk5d3207d2002-08-21 22:08:56 +0000171
Robert Hancock8a7d6632019-06-18 09:47:14 -0600172 /* Gotta split this one up (so the stack won't blow??) */
173 PRINTF("%s:%d: Function Table:\n"
174 " base 0x%p\n"
175 " struct 0x%p\n"
176 " pre 0x%p\n"
177 " prog 0x%p\n"
178 " init 0x%p\n"
179 " error 0x%p\n",
180 __func__, __LINE__,
181 &fn, fn, fn->pre, fn->pgm, fn->init, fn->err);
182 PRINTF(" clock 0x%p\n"
183 " cs 0x%p\n"
184 " write 0x%p\n"
185 " rdata 0x%p\n"
186 " wdata 0x%p\n"
187 " busy 0x%p\n"
188 " abort 0x%p\n"
189 " post 0x%p\n\n",
190 fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata,
191 fn->busy, fn->abort, fn->post);
wdenk5d3207d2002-08-21 22:08:56 +0000192
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200193#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock8a7d6632019-06-18 09:47:14 -0600194 printf("Initializing FPGA Device %d...\n", cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000195#endif
Robert Hancock8a7d6632019-06-18 09:47:14 -0600196 /*
197 * Run the pre configuration function if there is one.
198 */
199 if (*fn->pre)
200 (*fn->pre)(cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000201
Robert Hancock8a7d6632019-06-18 09:47:14 -0600202 /*
203 * Assert the program line. The minimum pulse width for
204 * Virtex II devices is 300 nS (Tprogram parameter in datasheet).
205 * There is no maximum value for the pulse width. Check to make
206 * sure that INIT_B goes low after assertion of PROG_B
207 */
208 (*fn->pgm)(true, true, cookie);
209 udelay(10);
210 ts = get_timer(0);
211 do {
212 if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT_INIT) {
213 printf("%s:%d: ** Timeout after %d ticks waiting for INIT to assert.\n",
214 __func__, __LINE__, CONFIG_SYS_FPGA_WAIT_INIT);
215 (*fn->abort)(cookie);
216 return FPGA_FAIL;
217 }
218 } while (!(*fn->init)(cookie));
wdenk5d3207d2002-08-21 22:08:56 +0000219
Robert Hancock8a7d6632019-06-18 09:47:14 -0600220 (*fn->pgm)(false, true, cookie);
221 CONFIG_FPGA_DELAY();
222 if (fn->clk)
Robert Hancock19b55dc2019-06-18 09:47:12 -0600223 (*fn->clk)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000224
Robert Hancock8a7d6632019-06-18 09:47:14 -0600225 /*
226 * Start a timer and wait for INIT_B to go high
227 */
228 ts = get_timer(0);
229 do {
230 CONFIG_FPGA_DELAY();
231 if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT_INIT) {
232 printf("%s:%d: ** Timeout after %d ticks waiting for INIT to deassert.\n",
233 __func__, __LINE__, CONFIG_SYS_FPGA_WAIT_INIT);
234 (*fn->abort)(cookie);
235 return FPGA_FAIL;
236 }
237 } while ((*fn->init)(cookie) && (*fn->busy)(cookie));
wdenk5d3207d2002-08-21 22:08:56 +0000238
Robert Hancock8a7d6632019-06-18 09:47:14 -0600239 if (fn->wr)
Robert Hancock19b55dc2019-06-18 09:47:12 -0600240 (*fn->wr)(true, true, cookie);
Robert Hancock8a7d6632019-06-18 09:47:14 -0600241 if (fn->cs)
Robert Hancock19b55dc2019-06-18 09:47:12 -0600242 (*fn->cs)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000243
Robert Hancock8a7d6632019-06-18 09:47:14 -0600244 mdelay(10);
245 return FPGA_SUCCESS;
246}
wdenk5d3207d2002-08-21 22:08:56 +0000247
Robert Hancock0b888342019-06-18 09:47:16 -0600248static int virtex2_slave_post(xilinx_virtex2_slave_fns *fn,
Robert Hancock8a7d6632019-06-18 09:47:14 -0600249 int cookie)
250{
251 int ret_val = FPGA_SUCCESS;
Robert Hancock7b5140c2019-06-18 09:47:15 -0600252 int num_done = 0;
Robert Hancock8a7d6632019-06-18 09:47:14 -0600253 unsigned long ts;
Wolfgang Denkffb77562005-09-24 23:41:00 +0200254
Robert Hancock8a7d6632019-06-18 09:47:14 -0600255 /*
256 * Finished writing the data; deassert FPGA CS_B and WRITE_B signals.
257 */
258 CONFIG_FPGA_DELAY();
259 if (fn->cs)
260 (*fn->cs)(false, true, cookie);
261 if (fn->wr)
262 (*fn->wr)(false, true, cookie);
Wolfgang Denkffb77562005-09-24 23:41:00 +0200263
Robert Hancock8a7d6632019-06-18 09:47:14 -0600264#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
265 putc('\n');
wdenk5d3207d2002-08-21 22:08:56 +0000266#endif
Wolfgang Denkffb77562005-09-24 23:41:00 +0200267
Robert Hancock8a7d6632019-06-18 09:47:14 -0600268 /*
269 * Check for successful configuration. FPGA INIT_B and DONE
Robert Hancock7b5140c2019-06-18 09:47:15 -0600270 * should both be high upon successful configuration. Continue pulsing
271 * clock with data set to all ones until DONE is asserted and for 8
272 * clock cycles afterwards.
Robert Hancock8a7d6632019-06-18 09:47:14 -0600273 */
274 ts = get_timer(0);
Robert Hancock7b5140c2019-06-18 09:47:15 -0600275 while (true) {
276 if ((*fn->done)(cookie) == FPGA_SUCCESS &&
277 !((*fn->init)(cookie))) {
278 if (num_done++ >= 8)
279 break;
280 }
281
Robert Hancock8a7d6632019-06-18 09:47:14 -0600282 if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT_CONFIG) {
283 printf("%s:%d: ** Timeout after %d ticks waiting for DONE to assert and INIT to deassert\n",
284 __func__, __LINE__, CONFIG_SYS_FPGA_WAIT_CONFIG);
285 (*fn->abort)(cookie);
286 ret_val = FPGA_FAIL;
287 break;
288 }
Robert Hancock0b888342019-06-18 09:47:16 -0600289 if (fn->wbulkdata) {
290 unsigned char dummy = 0xff;
291 (*fn->wbulkdata)(&dummy, 1, true, cookie);
292 } else {
293 (*fn->wdata)(0xff, true, cookie);
294 CONFIG_FPGA_DELAY();
295 (*fn->clk)(false, true, cookie);
296 CONFIG_FPGA_DELAY();
297 (*fn->clk)(true, true, cookie);
298 }
Robert Hancock8a7d6632019-06-18 09:47:14 -0600299 }
wdenk5d3207d2002-08-21 22:08:56 +0000300
Robert Hancock8a7d6632019-06-18 09:47:14 -0600301 if (ret_val == FPGA_SUCCESS) {
302#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
303 printf("Initialization of FPGA device %d complete\n", cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000304#endif
Robert Hancock8a7d6632019-06-18 09:47:14 -0600305 /*
306 * Run the post configuration function if there is one.
307 */
308 if (*fn->post)
309 (*fn->post)(cookie);
310 } else {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200311#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock8a7d6632019-06-18 09:47:14 -0600312 printf("** Initialization of FPGA device %d FAILED\n",
313 cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000314#endif
Robert Hancock8a7d6632019-06-18 09:47:14 -0600315 }
316 return ret_val;
317}
318
319static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize)
320{
321 int ret_val = FPGA_FAIL;
Robert Hancock0b888342019-06-18 09:47:16 -0600322 xilinx_virtex2_slave_fns *fn = desc->iface_fns;
Robert Hancock8a7d6632019-06-18 09:47:14 -0600323 size_t bytecount = 0;
324 unsigned char *data = (unsigned char *)buf;
325 int cookie = desc->cookie;
326
327 ret_val = virtex2_slave_pre(fn, cookie);
328 if (ret_val != FPGA_SUCCESS)
329 return ret_val;
330
331 /*
332 * Load the data byte by byte
333 */
334 while (bytecount < bsize) {
335#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
336 if (ctrlc()) {
337 (*fn->abort)(cookie);
338 return FPGA_FAIL;
wdenk5d3207d2002-08-21 22:08:56 +0000339 }
Robert Hancock8a7d6632019-06-18 09:47:14 -0600340#endif
wdenk5d3207d2002-08-21 22:08:56 +0000341
Robert Hancock8a7d6632019-06-18 09:47:14 -0600342 if ((*fn->done)(cookie) == FPGA_SUCCESS) {
343 PRINTF("%s:%d:done went active early, bytecount = %d\n",
344 __func__, __LINE__, bytecount);
345 break;
346 }
wdenk5d3207d2002-08-21 22:08:56 +0000347
Robert Hancock8a7d6632019-06-18 09:47:14 -0600348#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
349 if ((*fn->init)(cookie)) {
350 printf("\n%s:%d: ** Error: INIT asserted during configuration\n",
351 __func__, __LINE__);
352 printf("%zu = buffer offset, %zu = buffer size\n",
353 bytecount, bsize);
354 (*fn->abort)(cookie);
355 return FPGA_FAIL;
356 }
wdenk5d3207d2002-08-21 22:08:56 +0000357#endif
358
Robert Hancock8a7d6632019-06-18 09:47:14 -0600359 (*fn->wdata)(data[bytecount++], true, cookie);
360 CONFIG_FPGA_DELAY();
361
wdenk5d3207d2002-08-21 22:08:56 +0000362 /*
Robert Hancock8a7d6632019-06-18 09:47:14 -0600363 * Cycle the clock pin
wdenk5d3207d2002-08-21 22:08:56 +0000364 */
Robert Hancock8a7d6632019-06-18 09:47:14 -0600365 (*fn->clk)(false, true, cookie);
366 CONFIG_FPGA_DELAY();
367 (*fn->clk)(true, true, cookie);
368
369#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
Robert Hancock19b55dc2019-06-18 09:47:12 -0600370 ts = get_timer(0);
Robert Hancock8a7d6632019-06-18 09:47:14 -0600371 while ((*fn->busy)(cookie)) {
372 if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT_BUSY) {
373 printf("%s:%d: ** Timeout after %d ticks waiting for BUSY to deassert\n",
Robert Hancock19b55dc2019-06-18 09:47:12 -0600374 __func__, __LINE__,
Robert Hancock8a7d6632019-06-18 09:47:14 -0600375 CONFIG_SYS_FPGA_WAIT_BUSY);
Robert Hancock19b55dc2019-06-18 09:47:12 -0600376 (*fn->abort)(cookie);
Robert Hancock8a7d6632019-06-18 09:47:14 -0600377 return FPGA_FAIL;
wdenk5d3207d2002-08-21 22:08:56 +0000378 }
379 }
wdenk5d3207d2002-08-21 22:08:56 +0000380#endif
Robert Hancock8a7d6632019-06-18 09:47:14 -0600381
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200382#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock8a7d6632019-06-18 09:47:14 -0600383 if (bytecount % (bsize / 40) == 0)
384 putc('.');
wdenk5d3207d2002-08-21 22:08:56 +0000385#endif
wdenk5d3207d2002-08-21 22:08:56 +0000386 }
Robert Hancock8a7d6632019-06-18 09:47:14 -0600387
388 return virtex2_slave_post(fn, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000389}
390
391/*
392 * Read the FPGA configuration data
393 */
Michal Simek25e1e2e2014-03-13 12:49:21 +0100394static int virtex2_ssm_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000395{
396 int ret_val = FPGA_FAIL;
Robert Hancock0b888342019-06-18 09:47:16 -0600397 xilinx_virtex2_slave_fns *fn = desc->iface_fns;
wdenk5d3207d2002-08-21 22:08:56 +0000398
399 if (fn) {
Robert Hancock19b55dc2019-06-18 09:47:12 -0600400 unsigned char *data = (unsigned char *)buf;
wdenk5d3207d2002-08-21 22:08:56 +0000401 size_t bytecount = 0;
402 int cookie = desc->cookie;
403
Robert Hancock19b55dc2019-06-18 09:47:12 -0600404 printf("Starting Dump of FPGA Device %d...\n", cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000405
Robert Hancock19b55dc2019-06-18 09:47:12 -0600406 (*fn->cs)(true, true, cookie);
407 (*fn->clk)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000408
409 while (bytecount < bsize) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200410#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
Robert Hancock19b55dc2019-06-18 09:47:12 -0600411 if (ctrlc()) {
412 (*fn->abort)(cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000413 return FPGA_FAIL;
414 }
415#endif
416 /*
417 * Cycle the clock and read the data
418 */
Robert Hancock19b55dc2019-06-18 09:47:12 -0600419 (*fn->clk)(false, true, cookie);
420 (*fn->clk)(true, true, cookie);
421 (*fn->rdata)(&data[bytecount++], cookie);
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200422#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk5d3207d2002-08-21 22:08:56 +0000423 if (bytecount % (bsize / 40) == 0)
Robert Hancock19b55dc2019-06-18 09:47:12 -0600424 putc('.');
wdenk5d3207d2002-08-21 22:08:56 +0000425#endif
426 }
427
428 /*
429 * Deassert CS_B and cycle the clock to deselect the device.
430 */
Robert Hancock19b55dc2019-06-18 09:47:12 -0600431 (*fn->cs)(false, false, cookie);
432 (*fn->clk)(false, true, cookie);
433 (*fn->clk)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000434
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200435#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock19b55dc2019-06-18 09:47:12 -0600436 putc('\n');
wdenk5d3207d2002-08-21 22:08:56 +0000437#endif
Robert Hancock19b55dc2019-06-18 09:47:12 -0600438 puts("Done.\n");
wdenk5d3207d2002-08-21 22:08:56 +0000439 } else {
Robert Hancock19b55dc2019-06-18 09:47:12 -0600440 printf("%s:%d: NULL Interface function table!\n",
441 __func__, __LINE__);
wdenk5d3207d2002-08-21 22:08:56 +0000442 }
443 return ret_val;
444}
445
Michal Simek25e1e2e2014-03-13 12:49:21 +0100446static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000447{
Robert Hancock0b888342019-06-18 09:47:16 -0600448 int ret_val = FPGA_FAIL;
449 xilinx_virtex2_slave_fns *fn = desc->iface_fns;
450 unsigned char *data = (unsigned char *)buf;
451 int cookie = desc->cookie;
452
453 ret_val = virtex2_slave_pre(fn, cookie);
454 if (ret_val != FPGA_SUCCESS)
455 return ret_val;
456
457 if (fn->wbulkdata) {
458 /* Load the data in a single chunk */
459 (*fn->wbulkdata)(data, bsize, true, cookie);
460 } else {
461 size_t bytecount = 0;
462
463 /*
464 * Load the data bit by bit
465 */
466 while (bytecount < bsize) {
467 unsigned char curr_data = data[bytecount++];
468 int bit;
469
470#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
471 if (ctrlc()) {
472 (*fn->abort) (cookie);
473 return FPGA_FAIL;
474 }
475#endif
476
477 if ((*fn->done)(cookie) == FPGA_SUCCESS) {
478 PRINTF("%s:%d:done went active early, bytecount = %d\n",
479 __func__, __LINE__, bytecount);
480 break;
481 }
482
483#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
484 if ((*fn->init)(cookie)) {
485 printf("\n%s:%d: ** Error: INIT asserted during configuration\n",
486 __func__, __LINE__);
487 printf("%zu = buffer offset, %zu = buffer size\n",
488 bytecount, bsize);
489 (*fn->abort)(cookie);
490 return FPGA_FAIL;
491 }
492#endif
493
494 for (bit = 7; bit >= 0; --bit) {
495 unsigned char curr_bit = (curr_data >> bit) & 1;
496 (*fn->wdata)(curr_bit, true, cookie);
497 CONFIG_FPGA_DELAY();
498 (*fn->clk)(false, true, cookie);
499 CONFIG_FPGA_DELAY();
500 (*fn->clk)(true, true, cookie);
501 }
502
503 /* Slave serial never uses a busy pin */
504
505#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
506 if (bytecount % (bsize / 40) == 0)
507 putc('.');
508#endif
509 }
510 }
511
512 return virtex2_slave_post(fn, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000513}
514
Michal Simek25e1e2e2014-03-13 12:49:21 +0100515static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000516{
Robert Hancock19b55dc2019-06-18 09:47:12 -0600517 printf("%s: Slave Serial Dumping is unsupported\n", __func__);
wdenk5d3207d2002-08-21 22:08:56 +0000518 return FPGA_FAIL;
519}
520
wdenk5d3207d2002-08-21 22:08:56 +0000521/* vim: set ts=4 tw=78: */
Michal Simek75fafac2014-03-13 13:07:57 +0100522
523struct xilinx_fpga_op virtex2_op = {
524 .load = virtex2_load,
525 .dump = virtex2_dump,
526 .info = virtex2_info,
527};