blob: 8871deaea6f6031c4366e6313859b2537730cce3 [file] [log] [blame]
Tom Rini83d290c2018-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 Hancock175dccd2019-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
Alexander Dahl63c46e02022-10-07 14:20:03 +020015#define LOG_CATEGORY UCLASS_FPGA
16
wdenk5d3207d2002-08-21 22:08:56 +000017#include <common.h>
Simon Glass24b852a2015-11-08 23:47:45 -070018#include <console.h>
Alexander Dahl63c46e02022-10-07 14:20:03 +020019#include <log.h>
wdenk5d3207d2002-08-21 22:08:56 +000020#include <virtex2.h>
Simon Glassc05ed002020-05-10 11:40:11 -060021#include <linux/delay.h>
wdenk5d3207d2002-08-21 22:08:56 +000022
wdenk5d3207d2002-08-21 22:08:56 +000023/*
24 * If the SelectMap interface can be overrun by the processor, define
Robert Hancockfa57af02019-06-18 09:47:12 -060025 * CONFIG_SYS_FPGA_CHECK_BUSY and/or CONFIG_FPGA_DELAY in the board
26 * configuration file and add board-specific support for checking BUSY status.
27 * By default, assume that the SelectMap interface cannot be overrun.
wdenk5d3207d2002-08-21 22:08:56 +000028 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020029#ifndef CONFIG_SYS_FPGA_CHECK_BUSY
30#undef CONFIG_SYS_FPGA_CHECK_BUSY
wdenk5d3207d2002-08-21 22:08:56 +000031#endif
32
33#ifndef CONFIG_FPGA_DELAY
34#define CONFIG_FPGA_DELAY()
35#endif
36
wdenk5d3207d2002-08-21 22:08:56 +000037/*
wdenk5d3207d2002-08-21 22:08:56 +000038 * Check for errors during configuration by default
39 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020040#ifndef CONFIG_SYS_FPGA_CHECK_ERROR
41#define CONFIG_SYS_FPGA_CHECK_ERROR
wdenk5d3207d2002-08-21 22:08:56 +000042#endif
43
44/*
45 * The default timeout in mS for INIT_B to deassert after PROG_B has
46 * been deasserted. Per the latest Virtex II Handbook (page 347), the
47 * max time from PORG_B deassertion to INIT_B deassertion is 4uS per
48 * data frame for the XC2V8000. The XC2V8000 has 2860 data frames
49 * which yields 11.44 mS. So let's make it bigger in order to handle
50 * an XC2V1000, if anyone can ever get ahold of one.
51 */
Tom Rini65cc0e22022-11-16 13:10:41 -050052#ifndef CFG_SYS_FPGA_WAIT_INIT
53#define CFG_SYS_FPGA_WAIT_INIT CONFIG_SYS_HZ / 2 /* 500 ms */
wdenk5d3207d2002-08-21 22:08:56 +000054#endif
55
56/*
57 * The default timeout for waiting for BUSY to deassert during configuration.
58 * This is normally not necessary since for most reasonable configuration
59 * clock frequencies (i.e. 66 MHz or less), BUSY monitoring is unnecessary.
60 */
Tom Rini65cc0e22022-11-16 13:10:41 -050061#ifndef CFG_SYS_FPGA_WAIT_BUSY
62#define CFG_SYS_FPGA_WAIT_BUSY CONFIG_SYS_HZ / 200 /* 5 ms*/
wdenk5d3207d2002-08-21 22:08:56 +000063#endif
64
65/* Default timeout for waiting for FPGA to enter operational mode after
66 * configuration data has been written.
67 */
Tom Rini65cc0e22022-11-16 13:10:41 -050068#ifndef CFG_SYS_FPGA_WAIT_CONFIG
69#define CFG_SYS_FPGA_WAIT_CONFIG CONFIG_SYS_HZ / 5 /* 200 ms */
wdenk5d3207d2002-08-21 22:08:56 +000070#endif
71
Michal Simekf8c1be92014-03-13 12:49:21 +010072static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize);
73static int virtex2_ssm_dump(xilinx_desc *desc, const void *buf, size_t bsize);
wdenk5d3207d2002-08-21 22:08:56 +000074
Michal Simekf8c1be92014-03-13 12:49:21 +010075static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
76static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
wdenk5d3207d2002-08-21 22:08:56 +000077
Michal Simek7a78bd22014-05-02 14:09:30 +020078static int virtex2_load(xilinx_desc *desc, const void *buf, size_t bsize,
Oleksandr Suvorov3e784812022-07-22 17:16:10 +030079 bitstream_type bstype, int flags)
wdenk5d3207d2002-08-21 22:08:56 +000080{
81 int ret_val = FPGA_FAIL;
82
83 switch (desc->iface) {
84 case slave_serial:
Alexander Dahl63c46e02022-10-07 14:20:03 +020085 log_debug("Launching Slave Serial Load\n");
Michal Simekd9071ce2014-03-13 11:33:36 +010086 ret_val = virtex2_ss_load(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +000087 break;
88
89 case slave_selectmap:
Alexander Dahl63c46e02022-10-07 14:20:03 +020090 log_debug("Launching Slave Parallel Load\n");
Michal Simekd9071ce2014-03-13 11:33:36 +010091 ret_val = virtex2_ssm_load(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +000092 break;
93
94 default:
Robert Hancockfa57af02019-06-18 09:47:12 -060095 printf("%s: Unsupported interface type, %d\n",
96 __func__, desc->iface);
wdenk5d3207d2002-08-21 22:08:56 +000097 }
98 return ret_val;
99}
100
Michal Simek14cfc4f2014-03-13 13:07:57 +0100101static int virtex2_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000102{
103 int ret_val = FPGA_FAIL;
104
105 switch (desc->iface) {
106 case slave_serial:
Alexander Dahl63c46e02022-10-07 14:20:03 +0200107 log_debug("Launching Slave Serial Dump\n");
Michal Simekd9071ce2014-03-13 11:33:36 +0100108 ret_val = virtex2_ss_dump(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000109 break;
110
111 case slave_parallel:
Alexander Dahl63c46e02022-10-07 14:20:03 +0200112 log_debug("Launching Slave Parallel Dump\n");
Michal Simekd9071ce2014-03-13 11:33:36 +0100113 ret_val = virtex2_ssm_dump(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000114 break;
115
116 default:
Robert Hancockfa57af02019-06-18 09:47:12 -0600117 printf("%s: Unsupported interface type, %d\n",
118 __func__, desc->iface);
wdenk5d3207d2002-08-21 22:08:56 +0000119 }
120 return ret_val;
121}
122
Michal Simek14cfc4f2014-03-13 13:07:57 +0100123static int virtex2_info(xilinx_desc *desc)
wdenk5d3207d2002-08-21 22:08:56 +0000124{
125 return FPGA_SUCCESS;
126}
127
wdenk5d3207d2002-08-21 22:08:56 +0000128/*
Robert Hancock175dccd2019-06-18 09:47:16 -0600129 * Virtex-II Slave SelectMap or Serial configuration loader. Configuration
130 * is as follows:
wdenk5d3207d2002-08-21 22:08:56 +0000131 * 1. Set the FPGA's PROG_B line low.
132 * 2. Set the FPGA's PROG_B line high. Wait for INIT_B to go high.
133 * 3. Write data to the SelectMap port. If INIT_B goes low at any time
134 * this process, a configuration error (most likely CRC failure) has
135 * ocurred. At this point a status word may be read from the
136 * SelectMap interface to determine the source of the problem (You
Wolfgang Denk9a9200b2005-09-24 23:41:00 +0200137 * could, for instance, put this in your 'abort' function handler).
wdenk5d3207d2002-08-21 22:08:56 +0000138 * 4. After all data has been written, test the state of the FPGA
139 * INIT_B and DONE lines. If both are high, configuration has
140 * succeeded. Congratulations!
141 */
Robert Hancock175dccd2019-06-18 09:47:16 -0600142static int virtex2_slave_pre(xilinx_virtex2_slave_fns *fn, int cookie)
wdenk5d3207d2002-08-21 22:08:56 +0000143{
Robert Hancock33720812019-06-18 09:47:14 -0600144 unsigned long ts;
wdenk5d3207d2002-08-21 22:08:56 +0000145
Alexander Dahl63c46e02022-10-07 14:20:03 +0200146 log_debug("Start with interface functions @ 0x%p\n", fn);
wdenk5d3207d2002-08-21 22:08:56 +0000147
Robert Hancock33720812019-06-18 09:47:14 -0600148 if (!fn) {
149 printf("%s:%d: NULL Interface function table!\n",
150 __func__, __LINE__);
151 return FPGA_FAIL;
152 }
wdenk5d3207d2002-08-21 22:08:56 +0000153
Robert Hancock33720812019-06-18 09:47:14 -0600154 /* Gotta split this one up (so the stack won't blow??) */
Alexander Dahl63c46e02022-10-07 14:20:03 +0200155 log_debug("Function Table:\n"
156 " base 0x%p\n"
157 " struct 0x%p\n"
158 " pre 0x%p\n"
159 " prog 0x%p\n"
160 " init 0x%p\n"
161 " error 0x%p\n",
162 &fn, fn, fn->pre, fn->pgm, fn->init, fn->err);
163 log_debug(" clock 0x%p\n"
164 " cs 0x%p\n"
165 " write 0x%p\n"
166 " rdata 0x%p\n"
167 " wdata 0x%p\n"
168 " busy 0x%p\n"
169 " abort 0x%p\n"
170 " post 0x%p\n\n",
171 fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata,
172 fn->busy, fn->abort, fn->post);
wdenk5d3207d2002-08-21 22:08:56 +0000173
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200174#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock33720812019-06-18 09:47:14 -0600175 printf("Initializing FPGA Device %d...\n", cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000176#endif
Robert Hancock33720812019-06-18 09:47:14 -0600177 /*
178 * Run the pre configuration function if there is one.
179 */
180 if (*fn->pre)
181 (*fn->pre)(cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000182
Robert Hancock33720812019-06-18 09:47:14 -0600183 /*
184 * Assert the program line. The minimum pulse width for
185 * Virtex II devices is 300 nS (Tprogram parameter in datasheet).
186 * There is no maximum value for the pulse width. Check to make
187 * sure that INIT_B goes low after assertion of PROG_B
188 */
189 (*fn->pgm)(true, true, cookie);
190 udelay(10);
191 ts = get_timer(0);
192 do {
Tom Rini65cc0e22022-11-16 13:10:41 -0500193 if (get_timer(ts) > CFG_SYS_FPGA_WAIT_INIT) {
Robert Hancock33720812019-06-18 09:47:14 -0600194 printf("%s:%d: ** Timeout after %d ticks waiting for INIT to assert.\n",
Tom Rini65cc0e22022-11-16 13:10:41 -0500195 __func__, __LINE__, CFG_SYS_FPGA_WAIT_INIT);
Robert Hancock33720812019-06-18 09:47:14 -0600196 (*fn->abort)(cookie);
197 return FPGA_FAIL;
198 }
199 } while (!(*fn->init)(cookie));
wdenk5d3207d2002-08-21 22:08:56 +0000200
Robert Hancock33720812019-06-18 09:47:14 -0600201 (*fn->pgm)(false, true, cookie);
202 CONFIG_FPGA_DELAY();
203 if (fn->clk)
Robert Hancockfa57af02019-06-18 09:47:12 -0600204 (*fn->clk)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000205
Robert Hancock33720812019-06-18 09:47:14 -0600206 /*
207 * Start a timer and wait for INIT_B to go high
208 */
209 ts = get_timer(0);
210 do {
211 CONFIG_FPGA_DELAY();
Tom Rini65cc0e22022-11-16 13:10:41 -0500212 if (get_timer(ts) > CFG_SYS_FPGA_WAIT_INIT) {
Robert Hancock33720812019-06-18 09:47:14 -0600213 printf("%s:%d: ** Timeout after %d ticks waiting for INIT to deassert.\n",
Tom Rini65cc0e22022-11-16 13:10:41 -0500214 __func__, __LINE__, CFG_SYS_FPGA_WAIT_INIT);
Robert Hancock33720812019-06-18 09:47:14 -0600215 (*fn->abort)(cookie);
216 return FPGA_FAIL;
217 }
218 } while ((*fn->init)(cookie) && (*fn->busy)(cookie));
wdenk5d3207d2002-08-21 22:08:56 +0000219
Robert Hancock33720812019-06-18 09:47:14 -0600220 if (fn->wr)
Robert Hancockfa57af02019-06-18 09:47:12 -0600221 (*fn->wr)(true, true, cookie);
Robert Hancock33720812019-06-18 09:47:14 -0600222 if (fn->cs)
Robert Hancockfa57af02019-06-18 09:47:12 -0600223 (*fn->cs)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000224
Robert Hancock33720812019-06-18 09:47:14 -0600225 mdelay(10);
226 return FPGA_SUCCESS;
227}
wdenk5d3207d2002-08-21 22:08:56 +0000228
Robert Hancock175dccd2019-06-18 09:47:16 -0600229static int virtex2_slave_post(xilinx_virtex2_slave_fns *fn,
Robert Hancock33720812019-06-18 09:47:14 -0600230 int cookie)
231{
232 int ret_val = FPGA_SUCCESS;
Robert Hancocka0549f72019-06-18 09:47:15 -0600233 int num_done = 0;
Robert Hancock33720812019-06-18 09:47:14 -0600234 unsigned long ts;
Wolfgang Denk9a9200b2005-09-24 23:41:00 +0200235
Robert Hancock33720812019-06-18 09:47:14 -0600236 /*
237 * Finished writing the data; deassert FPGA CS_B and WRITE_B signals.
238 */
239 CONFIG_FPGA_DELAY();
240 if (fn->cs)
Robert Hancockfa57af02019-06-18 09:47:12 -0600241 (*fn->cs)(false, true, cookie);
Robert Hancock33720812019-06-18 09:47:14 -0600242 if (fn->wr)
Robert Hancockfa57af02019-06-18 09:47:12 -0600243 (*fn->wr)(false, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000244
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200245#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock33720812019-06-18 09:47:14 -0600246 putc('\n');
wdenk5d3207d2002-08-21 22:08:56 +0000247#endif
248
Robert Hancock33720812019-06-18 09:47:14 -0600249 /*
250 * Check for successful configuration. FPGA INIT_B and DONE
Robert Hancocka0549f72019-06-18 09:47:15 -0600251 * should both be high upon successful configuration. Continue pulsing
252 * clock with data set to all ones until DONE is asserted and for 8
253 * clock cycles afterwards.
Robert Hancock33720812019-06-18 09:47:14 -0600254 */
255 ts = get_timer(0);
Robert Hancocka0549f72019-06-18 09:47:15 -0600256 while (true) {
257 if ((*fn->done)(cookie) == FPGA_SUCCESS &&
258 !((*fn->init)(cookie))) {
259 if (num_done++ >= 8)
260 break;
261 }
262
Tom Rini65cc0e22022-11-16 13:10:41 -0500263 if (get_timer(ts) > CFG_SYS_FPGA_WAIT_CONFIG) {
Robert Hancock33720812019-06-18 09:47:14 -0600264 printf("%s:%d: ** Timeout after %d ticks waiting for DONE to assert and INIT to deassert\n",
Tom Rini65cc0e22022-11-16 13:10:41 -0500265 __func__, __LINE__, CFG_SYS_FPGA_WAIT_CONFIG);
Robert Hancock33720812019-06-18 09:47:14 -0600266 (*fn->abort)(cookie);
267 ret_val = FPGA_FAIL;
268 break;
269 }
Robert Hancock175dccd2019-06-18 09:47:16 -0600270 if (fn->wbulkdata) {
271 unsigned char dummy = 0xff;
272 (*fn->wbulkdata)(&dummy, 1, true, cookie);
273 } else {
274 (*fn->wdata)(0xff, true, cookie);
275 CONFIG_FPGA_DELAY();
276 (*fn->clk)(false, true, cookie);
277 CONFIG_FPGA_DELAY();
278 (*fn->clk)(true, true, cookie);
279 }
Robert Hancock33720812019-06-18 09:47:14 -0600280 }
281
282 if (ret_val == FPGA_SUCCESS) {
283#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
284 printf("Initialization of FPGA device %d complete\n", cookie);
285#endif
wdenk5d3207d2002-08-21 22:08:56 +0000286 /*
Robert Hancock33720812019-06-18 09:47:14 -0600287 * Run the post configuration function if there is one.
wdenk5d3207d2002-08-21 22:08:56 +0000288 */
Robert Hancock33720812019-06-18 09:47:14 -0600289 if (*fn->post)
290 (*fn->post)(cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000291 } else {
Robert Hancock33720812019-06-18 09:47:14 -0600292#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
293 printf("** Initialization of FPGA device %d FAILED\n",
294 cookie);
295#endif
wdenk5d3207d2002-08-21 22:08:56 +0000296 }
297 return ret_val;
298}
299
Robert Hancock33720812019-06-18 09:47:14 -0600300static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize)
301{
302 int ret_val = FPGA_FAIL;
Robert Hancock175dccd2019-06-18 09:47:16 -0600303 xilinx_virtex2_slave_fns *fn = desc->iface_fns;
Robert Hancock33720812019-06-18 09:47:14 -0600304 size_t bytecount = 0;
305 unsigned char *data = (unsigned char *)buf;
306 int cookie = desc->cookie;
307
308 ret_val = virtex2_slave_pre(fn, cookie);
309 if (ret_val != FPGA_SUCCESS)
310 return ret_val;
311
312 /*
313 * Load the data byte by byte
314 */
315 while (bytecount < bsize) {
316#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
317 if (ctrlc()) {
318 (*fn->abort)(cookie);
319 return FPGA_FAIL;
320 }
321#endif
322
323 if ((*fn->done)(cookie) == FPGA_SUCCESS) {
Alexander Dahl63c46e02022-10-07 14:20:03 +0200324 log_debug("done went active early, bytecount = %zu\n",
325 bytecount);
Robert Hancock33720812019-06-18 09:47:14 -0600326 break;
327 }
328
329#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
330 if ((*fn->init)(cookie)) {
331 printf("\n%s:%d: ** Error: INIT asserted during configuration\n",
332 __func__, __LINE__);
333 printf("%zu = buffer offset, %zu = buffer size\n",
334 bytecount, bsize);
335 (*fn->abort)(cookie);
336 return FPGA_FAIL;
337 }
338#endif
339
340 (*fn->wdata)(data[bytecount++], true, cookie);
341 CONFIG_FPGA_DELAY();
342
343 /*
344 * Cycle the clock pin
345 */
346 (*fn->clk)(false, true, cookie);
347 CONFIG_FPGA_DELAY();
348 (*fn->clk)(true, true, cookie);
349
350#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
351 ts = get_timer(0);
352 while ((*fn->busy)(cookie)) {
Tom Rini65cc0e22022-11-16 13:10:41 -0500353 if (get_timer(ts) > CFG_SYS_FPGA_WAIT_BUSY) {
Robert Hancock33720812019-06-18 09:47:14 -0600354 printf("%s:%d: ** Timeout after %d ticks waiting for BUSY to deassert\n",
355 __func__, __LINE__,
Tom Rini65cc0e22022-11-16 13:10:41 -0500356 CFG_SYS_FPGA_WAIT_BUSY);
Robert Hancock33720812019-06-18 09:47:14 -0600357 (*fn->abort)(cookie);
358 return FPGA_FAIL;
359 }
360 }
361#endif
362
363#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
364 if (bytecount % (bsize / 40) == 0)
365 putc('.');
366#endif
367 }
368
369 return virtex2_slave_post(fn, cookie);
370}
371
wdenk5d3207d2002-08-21 22:08:56 +0000372/*
373 * Read the FPGA configuration data
374 */
Michal Simekf8c1be92014-03-13 12:49:21 +0100375static int virtex2_ssm_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000376{
377 int ret_val = FPGA_FAIL;
Robert Hancock175dccd2019-06-18 09:47:16 -0600378 xilinx_virtex2_slave_fns *fn = desc->iface_fns;
wdenk5d3207d2002-08-21 22:08:56 +0000379
380 if (fn) {
Robert Hancockfa57af02019-06-18 09:47:12 -0600381 unsigned char *data = (unsigned char *)buf;
wdenk5d3207d2002-08-21 22:08:56 +0000382 size_t bytecount = 0;
383 int cookie = desc->cookie;
384
Robert Hancockfa57af02019-06-18 09:47:12 -0600385 printf("Starting Dump of FPGA Device %d...\n", cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000386
Robert Hancockfa57af02019-06-18 09:47:12 -0600387 (*fn->cs)(true, true, cookie);
388 (*fn->clk)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000389
390 while (bytecount < bsize) {
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200391#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
Robert Hancockfa57af02019-06-18 09:47:12 -0600392 if (ctrlc()) {
393 (*fn->abort)(cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000394 return FPGA_FAIL;
395 }
396#endif
397 /*
398 * Cycle the clock and read the data
399 */
Robert Hancockfa57af02019-06-18 09:47:12 -0600400 (*fn->clk)(false, true, cookie);
401 (*fn->clk)(true, true, cookie);
402 (*fn->rdata)(&data[bytecount++], cookie);
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200403#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk5d3207d2002-08-21 22:08:56 +0000404 if (bytecount % (bsize / 40) == 0)
Robert Hancockfa57af02019-06-18 09:47:12 -0600405 putc('.');
wdenk5d3207d2002-08-21 22:08:56 +0000406#endif
407 }
408
409 /*
410 * Deassert CS_B and cycle the clock to deselect the device.
411 */
Robert Hancockfa57af02019-06-18 09:47:12 -0600412 (*fn->cs)(false, false, cookie);
413 (*fn->clk)(false, true, cookie);
414 (*fn->clk)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000415
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200416#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancockfa57af02019-06-18 09:47:12 -0600417 putc('\n');
wdenk5d3207d2002-08-21 22:08:56 +0000418#endif
Robert Hancockfa57af02019-06-18 09:47:12 -0600419 puts("Done.\n");
wdenk5d3207d2002-08-21 22:08:56 +0000420 } else {
Robert Hancockfa57af02019-06-18 09:47:12 -0600421 printf("%s:%d: NULL Interface function table!\n",
422 __func__, __LINE__);
wdenk5d3207d2002-08-21 22:08:56 +0000423 }
424 return ret_val;
425}
426
Michal Simekf8c1be92014-03-13 12:49:21 +0100427static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000428{
Robert Hancock175dccd2019-06-18 09:47:16 -0600429 int ret_val = FPGA_FAIL;
430 xilinx_virtex2_slave_fns *fn = desc->iface_fns;
431 unsigned char *data = (unsigned char *)buf;
432 int cookie = desc->cookie;
433
434 ret_val = virtex2_slave_pre(fn, cookie);
435 if (ret_val != FPGA_SUCCESS)
436 return ret_val;
437
438 if (fn->wbulkdata) {
439 /* Load the data in a single chunk */
440 (*fn->wbulkdata)(data, bsize, true, cookie);
441 } else {
442 size_t bytecount = 0;
443
444 /*
445 * Load the data bit by bit
446 */
447 while (bytecount < bsize) {
448 unsigned char curr_data = data[bytecount++];
449 int bit;
450
451#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
452 if (ctrlc()) {
453 (*fn->abort) (cookie);
454 return FPGA_FAIL;
455 }
456#endif
457
458 if ((*fn->done)(cookie) == FPGA_SUCCESS) {
Alexander Dahl63c46e02022-10-07 14:20:03 +0200459 log_debug("done went active early, bytecount = %zu\n",
460 bytecount);
Robert Hancock175dccd2019-06-18 09:47:16 -0600461 break;
462 }
463
464#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
465 if ((*fn->init)(cookie)) {
466 printf("\n%s:%d: ** Error: INIT asserted during configuration\n",
467 __func__, __LINE__);
468 printf("%zu = buffer offset, %zu = buffer size\n",
469 bytecount, bsize);
470 (*fn->abort)(cookie);
471 return FPGA_FAIL;
472 }
473#endif
474
475 for (bit = 7; bit >= 0; --bit) {
476 unsigned char curr_bit = (curr_data >> bit) & 1;
477 (*fn->wdata)(curr_bit, true, cookie);
478 CONFIG_FPGA_DELAY();
479 (*fn->clk)(false, true, cookie);
480 CONFIG_FPGA_DELAY();
481 (*fn->clk)(true, true, cookie);
482 }
483
484 /* Slave serial never uses a busy pin */
485
486#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
487 if (bytecount % (bsize / 40) == 0)
488 putc('.');
489#endif
490 }
491 }
492
493 return virtex2_slave_post(fn, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000494}
495
Michal Simekf8c1be92014-03-13 12:49:21 +0100496static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000497{
Robert Hancockfa57af02019-06-18 09:47:12 -0600498 printf("%s: Slave Serial Dumping is unsupported\n", __func__);
wdenk5d3207d2002-08-21 22:08:56 +0000499 return FPGA_FAIL;
500}
501
wdenk5d3207d2002-08-21 22:08:56 +0000502/* vim: set ts=4 tw=78: */
Michal Simek14cfc4f2014-03-13 13:07:57 +0100503
504struct xilinx_fpga_op virtex2_op = {
505 .load = virtex2_load,
506 .dump = virtex2_dump,
507 .info = virtex2_info,
508};