blob: b3e0537bab07d08363a023a486f60250b59340a4 [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>
Simon Glassdbd79542020-05-10 11:40:11 -060018#include <linux/delay.h>
wdenk5d3207d2002-08-21 22:08:56 +000019
Wolfgang Denkffb77562005-09-24 23:41:00 +020020#if 0
21#define FPGA_DEBUG
Wolfgang Denk0cbaf642005-09-25 00:53:22 +020022#endif
Wolfgang Denkffb77562005-09-24 23:41:00 +020023
wdenk5d3207d2002-08-21 22:08:56 +000024#ifdef FPGA_DEBUG
Robert Hancock19b55dc2019-06-18 09:47:12 -060025#define PRINTF(fmt, args...) printf(fmt, ##args)
wdenk5d3207d2002-08-21 22:08:56 +000026#else
Robert Hancock19b55dc2019-06-18 09:47:12 -060027#define PRINTF(fmt, args...)
wdenk5d3207d2002-08-21 22:08:56 +000028#endif
29
30/*
31 * If the SelectMap interface can be overrun by the processor, define
Robert Hancock19b55dc2019-06-18 09:47:12 -060032 * CONFIG_SYS_FPGA_CHECK_BUSY and/or CONFIG_FPGA_DELAY in the board
33 * configuration file and add board-specific support for checking BUSY status.
34 * By default, assume that the SelectMap interface cannot be overrun.
wdenk5d3207d2002-08-21 22:08:56 +000035 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020036#ifndef CONFIG_SYS_FPGA_CHECK_BUSY
37#undef CONFIG_SYS_FPGA_CHECK_BUSY
wdenk5d3207d2002-08-21 22:08:56 +000038#endif
39
40#ifndef CONFIG_FPGA_DELAY
41#define CONFIG_FPGA_DELAY()
42#endif
43
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020044#ifndef CONFIG_SYS_FPGA_PROG_FEEDBACK
45#define CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk5d3207d2002-08-21 22:08:56 +000046#endif
47
48/*
49 * Don't allow config cycle to be interrupted
50 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020051#ifndef CONFIG_SYS_FPGA_CHECK_CTRLC
52#undef CONFIG_SYS_FPGA_CHECK_CTRLC
wdenk5d3207d2002-08-21 22:08:56 +000053#endif
54
55/*
56 * Check for errors during configuration by default
57 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020058#ifndef CONFIG_SYS_FPGA_CHECK_ERROR
59#define CONFIG_SYS_FPGA_CHECK_ERROR
wdenk5d3207d2002-08-21 22:08:56 +000060#endif
61
62/*
63 * The default timeout in mS for INIT_B to deassert after PROG_B has
64 * been deasserted. Per the latest Virtex II Handbook (page 347), the
65 * max time from PORG_B deassertion to INIT_B deassertion is 4uS per
66 * data frame for the XC2V8000. The XC2V8000 has 2860 data frames
67 * which yields 11.44 mS. So let's make it bigger in order to handle
68 * an XC2V1000, if anyone can ever get ahold of one.
69 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020070#ifndef CONFIG_SYS_FPGA_WAIT_INIT
Robert Hancock19b55dc2019-06-18 09:47:12 -060071#define CONFIG_SYS_FPGA_WAIT_INIT CONFIG_SYS_HZ / 2 /* 500 ms */
wdenk5d3207d2002-08-21 22:08:56 +000072#endif
73
74/*
75 * The default timeout for waiting for BUSY to deassert during configuration.
76 * This is normally not necessary since for most reasonable configuration
77 * clock frequencies (i.e. 66 MHz or less), BUSY monitoring is unnecessary.
78 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020079#ifndef CONFIG_SYS_FPGA_WAIT_BUSY
Robert Hancock19b55dc2019-06-18 09:47:12 -060080#define CONFIG_SYS_FPGA_WAIT_BUSY CONFIG_SYS_HZ / 200 /* 5 ms*/
wdenk5d3207d2002-08-21 22:08:56 +000081#endif
82
83/* Default timeout for waiting for FPGA to enter operational mode after
84 * configuration data has been written.
85 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020086#ifndef CONFIG_SYS_FPGA_WAIT_CONFIG
Robert Hancock19b55dc2019-06-18 09:47:12 -060087#define CONFIG_SYS_FPGA_WAIT_CONFIG CONFIG_SYS_HZ / 5 /* 200 ms */
wdenk5d3207d2002-08-21 22:08:56 +000088#endif
89
Michal Simek25e1e2e2014-03-13 12:49:21 +010090static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize);
91static int virtex2_ssm_dump(xilinx_desc *desc, const void *buf, size_t bsize);
wdenk5d3207d2002-08-21 22:08:56 +000092
Michal Simek25e1e2e2014-03-13 12:49:21 +010093static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
94static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
wdenk5d3207d2002-08-21 22:08:56 +000095
Michal Simek14663652014-05-02 14:09:30 +020096static int virtex2_load(xilinx_desc *desc, const void *buf, size_t bsize,
97 bitstream_type bstype)
wdenk5d3207d2002-08-21 22:08:56 +000098{
99 int ret_val = FPGA_FAIL;
100
101 switch (desc->iface) {
102 case slave_serial:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600103 PRINTF("%s: Launching Slave Serial Load\n", __func__);
Michal Simek90258882014-03-13 11:33:36 +0100104 ret_val = virtex2_ss_load(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000105 break;
106
107 case slave_selectmap:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600108 PRINTF("%s: Launching Slave Parallel Load\n", __func__);
Michal Simek90258882014-03-13 11:33:36 +0100109 ret_val = virtex2_ssm_load(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000110 break;
111
112 default:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600113 printf("%s: Unsupported interface type, %d\n",
114 __func__, desc->iface);
wdenk5d3207d2002-08-21 22:08:56 +0000115 }
116 return ret_val;
117}
118
Michal Simek75fafac2014-03-13 13:07:57 +0100119static int virtex2_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000120{
121 int ret_val = FPGA_FAIL;
122
123 switch (desc->iface) {
124 case slave_serial:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600125 PRINTF("%s: Launching Slave Serial Dump\n", __func__);
Michal Simek90258882014-03-13 11:33:36 +0100126 ret_val = virtex2_ss_dump(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000127 break;
128
129 case slave_parallel:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600130 PRINTF("%s: Launching Slave Parallel Dump\n", __func__);
Michal Simek90258882014-03-13 11:33:36 +0100131 ret_val = virtex2_ssm_dump(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000132 break;
133
134 default:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600135 printf("%s: Unsupported interface type, %d\n",
136 __func__, desc->iface);
wdenk5d3207d2002-08-21 22:08:56 +0000137 }
138 return ret_val;
139}
140
Michal Simek75fafac2014-03-13 13:07:57 +0100141static int virtex2_info(xilinx_desc *desc)
wdenk5d3207d2002-08-21 22:08:56 +0000142{
143 return FPGA_SUCCESS;
144}
145
wdenk5d3207d2002-08-21 22:08:56 +0000146/*
Robert Hancock0b888342019-06-18 09:47:16 -0600147 * Virtex-II Slave SelectMap or Serial configuration loader. Configuration
148 * is as follows:
wdenk5d3207d2002-08-21 22:08:56 +0000149 * 1. Set the FPGA's PROG_B line low.
150 * 2. Set the FPGA's PROG_B line high. Wait for INIT_B to go high.
151 * 3. Write data to the SelectMap port. If INIT_B goes low at any time
152 * this process, a configuration error (most likely CRC failure) has
153 * ocurred. At this point a status word may be read from the
154 * SelectMap interface to determine the source of the problem (You
Wolfgang Denkffb77562005-09-24 23:41:00 +0200155 * could, for instance, put this in your 'abort' function handler).
wdenk5d3207d2002-08-21 22:08:56 +0000156 * 4. After all data has been written, test the state of the FPGA
157 * INIT_B and DONE lines. If both are high, configuration has
158 * succeeded. Congratulations!
159 */
Robert Hancock0b888342019-06-18 09:47:16 -0600160static int virtex2_slave_pre(xilinx_virtex2_slave_fns *fn, int cookie)
wdenk5d3207d2002-08-21 22:08:56 +0000161{
Robert Hancock8a7d6632019-06-18 09:47:14 -0600162 unsigned long ts;
wdenk5d3207d2002-08-21 22:08:56 +0000163
Robert Hancock19b55dc2019-06-18 09:47:12 -0600164 PRINTF("%s:%d: Start with interface functions @ 0x%p\n",
165 __func__, __LINE__, fn);
wdenk5d3207d2002-08-21 22:08:56 +0000166
Robert Hancock8a7d6632019-06-18 09:47:14 -0600167 if (!fn) {
168 printf("%s:%d: NULL Interface function table!\n",
169 __func__, __LINE__);
170 return FPGA_FAIL;
171 }
wdenk5d3207d2002-08-21 22:08:56 +0000172
Robert Hancock8a7d6632019-06-18 09:47:14 -0600173 /* Gotta split this one up (so the stack won't blow??) */
174 PRINTF("%s:%d: Function Table:\n"
175 " base 0x%p\n"
176 " struct 0x%p\n"
177 " pre 0x%p\n"
178 " prog 0x%p\n"
179 " init 0x%p\n"
180 " error 0x%p\n",
181 __func__, __LINE__,
182 &fn, fn, fn->pre, fn->pgm, fn->init, fn->err);
183 PRINTF(" clock 0x%p\n"
184 " cs 0x%p\n"
185 " write 0x%p\n"
186 " rdata 0x%p\n"
187 " wdata 0x%p\n"
188 " busy 0x%p\n"
189 " abort 0x%p\n"
190 " post 0x%p\n\n",
191 fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata,
192 fn->busy, fn->abort, fn->post);
wdenk5d3207d2002-08-21 22:08:56 +0000193
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200194#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock8a7d6632019-06-18 09:47:14 -0600195 printf("Initializing FPGA Device %d...\n", cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000196#endif
Robert Hancock8a7d6632019-06-18 09:47:14 -0600197 /*
198 * Run the pre configuration function if there is one.
199 */
200 if (*fn->pre)
201 (*fn->pre)(cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000202
Robert Hancock8a7d6632019-06-18 09:47:14 -0600203 /*
204 * Assert the program line. The minimum pulse width for
205 * Virtex II devices is 300 nS (Tprogram parameter in datasheet).
206 * There is no maximum value for the pulse width. Check to make
207 * sure that INIT_B goes low after assertion of PROG_B
208 */
209 (*fn->pgm)(true, true, cookie);
210 udelay(10);
211 ts = get_timer(0);
212 do {
213 if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT_INIT) {
214 printf("%s:%d: ** Timeout after %d ticks waiting for INIT to assert.\n",
215 __func__, __LINE__, CONFIG_SYS_FPGA_WAIT_INIT);
216 (*fn->abort)(cookie);
217 return FPGA_FAIL;
218 }
219 } while (!(*fn->init)(cookie));
wdenk5d3207d2002-08-21 22:08:56 +0000220
Robert Hancock8a7d6632019-06-18 09:47:14 -0600221 (*fn->pgm)(false, true, cookie);
222 CONFIG_FPGA_DELAY();
223 if (fn->clk)
Robert Hancock19b55dc2019-06-18 09:47:12 -0600224 (*fn->clk)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000225
Robert Hancock8a7d6632019-06-18 09:47:14 -0600226 /*
227 * Start a timer and wait for INIT_B to go high
228 */
229 ts = get_timer(0);
230 do {
231 CONFIG_FPGA_DELAY();
232 if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT_INIT) {
233 printf("%s:%d: ** Timeout after %d ticks waiting for INIT to deassert.\n",
234 __func__, __LINE__, CONFIG_SYS_FPGA_WAIT_INIT);
235 (*fn->abort)(cookie);
236 return FPGA_FAIL;
237 }
238 } while ((*fn->init)(cookie) && (*fn->busy)(cookie));
wdenk5d3207d2002-08-21 22:08:56 +0000239
Robert Hancock8a7d6632019-06-18 09:47:14 -0600240 if (fn->wr)
Robert Hancock19b55dc2019-06-18 09:47:12 -0600241 (*fn->wr)(true, true, cookie);
Robert Hancock8a7d6632019-06-18 09:47:14 -0600242 if (fn->cs)
Robert Hancock19b55dc2019-06-18 09:47:12 -0600243 (*fn->cs)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000244
Robert Hancock8a7d6632019-06-18 09:47:14 -0600245 mdelay(10);
246 return FPGA_SUCCESS;
247}
wdenk5d3207d2002-08-21 22:08:56 +0000248
Robert Hancock0b888342019-06-18 09:47:16 -0600249static int virtex2_slave_post(xilinx_virtex2_slave_fns *fn,
Robert Hancock8a7d6632019-06-18 09:47:14 -0600250 int cookie)
251{
252 int ret_val = FPGA_SUCCESS;
Robert Hancock7b5140c2019-06-18 09:47:15 -0600253 int num_done = 0;
Robert Hancock8a7d6632019-06-18 09:47:14 -0600254 unsigned long ts;
Wolfgang Denkffb77562005-09-24 23:41:00 +0200255
Robert Hancock8a7d6632019-06-18 09:47:14 -0600256 /*
257 * Finished writing the data; deassert FPGA CS_B and WRITE_B signals.
258 */
259 CONFIG_FPGA_DELAY();
260 if (fn->cs)
261 (*fn->cs)(false, true, cookie);
262 if (fn->wr)
263 (*fn->wr)(false, true, cookie);
Wolfgang Denkffb77562005-09-24 23:41:00 +0200264
Robert Hancock8a7d6632019-06-18 09:47:14 -0600265#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
266 putc('\n');
wdenk5d3207d2002-08-21 22:08:56 +0000267#endif
Wolfgang Denkffb77562005-09-24 23:41:00 +0200268
Robert Hancock8a7d6632019-06-18 09:47:14 -0600269 /*
270 * Check for successful configuration. FPGA INIT_B and DONE
Robert Hancock7b5140c2019-06-18 09:47:15 -0600271 * should both be high upon successful configuration. Continue pulsing
272 * clock with data set to all ones until DONE is asserted and for 8
273 * clock cycles afterwards.
Robert Hancock8a7d6632019-06-18 09:47:14 -0600274 */
275 ts = get_timer(0);
Robert Hancock7b5140c2019-06-18 09:47:15 -0600276 while (true) {
277 if ((*fn->done)(cookie) == FPGA_SUCCESS &&
278 !((*fn->init)(cookie))) {
279 if (num_done++ >= 8)
280 break;
281 }
282
Robert Hancock8a7d6632019-06-18 09:47:14 -0600283 if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT_CONFIG) {
284 printf("%s:%d: ** Timeout after %d ticks waiting for DONE to assert and INIT to deassert\n",
285 __func__, __LINE__, CONFIG_SYS_FPGA_WAIT_CONFIG);
286 (*fn->abort)(cookie);
287 ret_val = FPGA_FAIL;
288 break;
289 }
Robert Hancock0b888342019-06-18 09:47:16 -0600290 if (fn->wbulkdata) {
291 unsigned char dummy = 0xff;
292 (*fn->wbulkdata)(&dummy, 1, true, cookie);
293 } else {
294 (*fn->wdata)(0xff, true, cookie);
295 CONFIG_FPGA_DELAY();
296 (*fn->clk)(false, true, cookie);
297 CONFIG_FPGA_DELAY();
298 (*fn->clk)(true, true, cookie);
299 }
Robert Hancock8a7d6632019-06-18 09:47:14 -0600300 }
wdenk5d3207d2002-08-21 22:08:56 +0000301
Robert Hancock8a7d6632019-06-18 09:47:14 -0600302 if (ret_val == FPGA_SUCCESS) {
303#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
304 printf("Initialization of FPGA device %d complete\n", cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000305#endif
Robert Hancock8a7d6632019-06-18 09:47:14 -0600306 /*
307 * Run the post configuration function if there is one.
308 */
309 if (*fn->post)
310 (*fn->post)(cookie);
311 } else {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200312#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock8a7d6632019-06-18 09:47:14 -0600313 printf("** Initialization of FPGA device %d FAILED\n",
314 cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000315#endif
Robert Hancock8a7d6632019-06-18 09:47:14 -0600316 }
317 return ret_val;
318}
319
320static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize)
321{
322 int ret_val = FPGA_FAIL;
Robert Hancock0b888342019-06-18 09:47:16 -0600323 xilinx_virtex2_slave_fns *fn = desc->iface_fns;
Robert Hancock8a7d6632019-06-18 09:47:14 -0600324 size_t bytecount = 0;
325 unsigned char *data = (unsigned char *)buf;
326 int cookie = desc->cookie;
327
328 ret_val = virtex2_slave_pre(fn, cookie);
329 if (ret_val != FPGA_SUCCESS)
330 return ret_val;
331
332 /*
333 * Load the data byte by byte
334 */
335 while (bytecount < bsize) {
336#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
337 if (ctrlc()) {
338 (*fn->abort)(cookie);
339 return FPGA_FAIL;
wdenk5d3207d2002-08-21 22:08:56 +0000340 }
Robert Hancock8a7d6632019-06-18 09:47:14 -0600341#endif
wdenk5d3207d2002-08-21 22:08:56 +0000342
Robert Hancock8a7d6632019-06-18 09:47:14 -0600343 if ((*fn->done)(cookie) == FPGA_SUCCESS) {
344 PRINTF("%s:%d:done went active early, bytecount = %d\n",
345 __func__, __LINE__, bytecount);
346 break;
347 }
wdenk5d3207d2002-08-21 22:08:56 +0000348
Robert Hancock8a7d6632019-06-18 09:47:14 -0600349#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
350 if ((*fn->init)(cookie)) {
351 printf("\n%s:%d: ** Error: INIT asserted during configuration\n",
352 __func__, __LINE__);
353 printf("%zu = buffer offset, %zu = buffer size\n",
354 bytecount, bsize);
355 (*fn->abort)(cookie);
356 return FPGA_FAIL;
357 }
wdenk5d3207d2002-08-21 22:08:56 +0000358#endif
359
Robert Hancock8a7d6632019-06-18 09:47:14 -0600360 (*fn->wdata)(data[bytecount++], true, cookie);
361 CONFIG_FPGA_DELAY();
362
wdenk5d3207d2002-08-21 22:08:56 +0000363 /*
Robert Hancock8a7d6632019-06-18 09:47:14 -0600364 * Cycle the clock pin
wdenk5d3207d2002-08-21 22:08:56 +0000365 */
Robert Hancock8a7d6632019-06-18 09:47:14 -0600366 (*fn->clk)(false, true, cookie);
367 CONFIG_FPGA_DELAY();
368 (*fn->clk)(true, true, cookie);
369
370#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
Robert Hancock19b55dc2019-06-18 09:47:12 -0600371 ts = get_timer(0);
Robert Hancock8a7d6632019-06-18 09:47:14 -0600372 while ((*fn->busy)(cookie)) {
373 if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT_BUSY) {
374 printf("%s:%d: ** Timeout after %d ticks waiting for BUSY to deassert\n",
Robert Hancock19b55dc2019-06-18 09:47:12 -0600375 __func__, __LINE__,
Robert Hancock8a7d6632019-06-18 09:47:14 -0600376 CONFIG_SYS_FPGA_WAIT_BUSY);
Robert Hancock19b55dc2019-06-18 09:47:12 -0600377 (*fn->abort)(cookie);
Robert Hancock8a7d6632019-06-18 09:47:14 -0600378 return FPGA_FAIL;
wdenk5d3207d2002-08-21 22:08:56 +0000379 }
380 }
wdenk5d3207d2002-08-21 22:08:56 +0000381#endif
Robert Hancock8a7d6632019-06-18 09:47:14 -0600382
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200383#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock8a7d6632019-06-18 09:47:14 -0600384 if (bytecount % (bsize / 40) == 0)
385 putc('.');
wdenk5d3207d2002-08-21 22:08:56 +0000386#endif
wdenk5d3207d2002-08-21 22:08:56 +0000387 }
Robert Hancock8a7d6632019-06-18 09:47:14 -0600388
389 return virtex2_slave_post(fn, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000390}
391
392/*
393 * Read the FPGA configuration data
394 */
Michal Simek25e1e2e2014-03-13 12:49:21 +0100395static int virtex2_ssm_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000396{
397 int ret_val = FPGA_FAIL;
Robert Hancock0b888342019-06-18 09:47:16 -0600398 xilinx_virtex2_slave_fns *fn = desc->iface_fns;
wdenk5d3207d2002-08-21 22:08:56 +0000399
400 if (fn) {
Robert Hancock19b55dc2019-06-18 09:47:12 -0600401 unsigned char *data = (unsigned char *)buf;
wdenk5d3207d2002-08-21 22:08:56 +0000402 size_t bytecount = 0;
403 int cookie = desc->cookie;
404
Robert Hancock19b55dc2019-06-18 09:47:12 -0600405 printf("Starting Dump of FPGA Device %d...\n", cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000406
Robert Hancock19b55dc2019-06-18 09:47:12 -0600407 (*fn->cs)(true, true, cookie);
408 (*fn->clk)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000409
410 while (bytecount < bsize) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200411#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
Robert Hancock19b55dc2019-06-18 09:47:12 -0600412 if (ctrlc()) {
413 (*fn->abort)(cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000414 return FPGA_FAIL;
415 }
416#endif
417 /*
418 * Cycle the clock and read the data
419 */
Robert Hancock19b55dc2019-06-18 09:47:12 -0600420 (*fn->clk)(false, true, cookie);
421 (*fn->clk)(true, true, cookie);
422 (*fn->rdata)(&data[bytecount++], cookie);
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200423#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk5d3207d2002-08-21 22:08:56 +0000424 if (bytecount % (bsize / 40) == 0)
Robert Hancock19b55dc2019-06-18 09:47:12 -0600425 putc('.');
wdenk5d3207d2002-08-21 22:08:56 +0000426#endif
427 }
428
429 /*
430 * Deassert CS_B and cycle the clock to deselect the device.
431 */
Robert Hancock19b55dc2019-06-18 09:47:12 -0600432 (*fn->cs)(false, false, cookie);
433 (*fn->clk)(false, true, cookie);
434 (*fn->clk)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000435
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200436#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock19b55dc2019-06-18 09:47:12 -0600437 putc('\n');
wdenk5d3207d2002-08-21 22:08:56 +0000438#endif
Robert Hancock19b55dc2019-06-18 09:47:12 -0600439 puts("Done.\n");
wdenk5d3207d2002-08-21 22:08:56 +0000440 } else {
Robert Hancock19b55dc2019-06-18 09:47:12 -0600441 printf("%s:%d: NULL Interface function table!\n",
442 __func__, __LINE__);
wdenk5d3207d2002-08-21 22:08:56 +0000443 }
444 return ret_val;
445}
446
Michal Simek25e1e2e2014-03-13 12:49:21 +0100447static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000448{
Robert Hancock0b888342019-06-18 09:47:16 -0600449 int ret_val = FPGA_FAIL;
450 xilinx_virtex2_slave_fns *fn = desc->iface_fns;
451 unsigned char *data = (unsigned char *)buf;
452 int cookie = desc->cookie;
453
454 ret_val = virtex2_slave_pre(fn, cookie);
455 if (ret_val != FPGA_SUCCESS)
456 return ret_val;
457
458 if (fn->wbulkdata) {
459 /* Load the data in a single chunk */
460 (*fn->wbulkdata)(data, bsize, true, cookie);
461 } else {
462 size_t bytecount = 0;
463
464 /*
465 * Load the data bit by bit
466 */
467 while (bytecount < bsize) {
468 unsigned char curr_data = data[bytecount++];
469 int bit;
470
471#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
472 if (ctrlc()) {
473 (*fn->abort) (cookie);
474 return FPGA_FAIL;
475 }
476#endif
477
478 if ((*fn->done)(cookie) == FPGA_SUCCESS) {
479 PRINTF("%s:%d:done went active early, bytecount = %d\n",
480 __func__, __LINE__, bytecount);
481 break;
482 }
483
484#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
485 if ((*fn->init)(cookie)) {
486 printf("\n%s:%d: ** Error: INIT asserted during configuration\n",
487 __func__, __LINE__);
488 printf("%zu = buffer offset, %zu = buffer size\n",
489 bytecount, bsize);
490 (*fn->abort)(cookie);
491 return FPGA_FAIL;
492 }
493#endif
494
495 for (bit = 7; bit >= 0; --bit) {
496 unsigned char curr_bit = (curr_data >> bit) & 1;
497 (*fn->wdata)(curr_bit, true, cookie);
498 CONFIG_FPGA_DELAY();
499 (*fn->clk)(false, true, cookie);
500 CONFIG_FPGA_DELAY();
501 (*fn->clk)(true, true, cookie);
502 }
503
504 /* Slave serial never uses a busy pin */
505
506#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
507 if (bytecount % (bsize / 40) == 0)
508 putc('.');
509#endif
510 }
511 }
512
513 return virtex2_slave_post(fn, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000514}
515
Michal Simek25e1e2e2014-03-13 12:49:21 +0100516static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000517{
Robert Hancock19b55dc2019-06-18 09:47:12 -0600518 printf("%s: Slave Serial Dumping is unsupported\n", __func__);
wdenk5d3207d2002-08-21 22:08:56 +0000519 return FPGA_FAIL;
520}
521
wdenk5d3207d2002-08-21 22:08:56 +0000522/* vim: set ts=4 tw=78: */
Michal Simek75fafac2014-03-13 13:07:57 +0100523
524struct xilinx_fpga_op virtex2_op = {
525 .load = virtex2_load,
526 .dump = virtex2_dump,
527 .info = virtex2_info,
528};