blob: 51b8d3120567925f6b163ace0b2ee29501806e76 [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
wdenk5d3207d2002-08-21 22:08:56 +000044/*
wdenk5d3207d2002-08-21 22:08:56 +000045 * Check for errors during configuration by default
46 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020047#ifndef CONFIG_SYS_FPGA_CHECK_ERROR
48#define CONFIG_SYS_FPGA_CHECK_ERROR
wdenk5d3207d2002-08-21 22:08:56 +000049#endif
50
51/*
52 * The default timeout in mS for INIT_B to deassert after PROG_B has
53 * been deasserted. Per the latest Virtex II Handbook (page 347), the
54 * max time from PORG_B deassertion to INIT_B deassertion is 4uS per
55 * data frame for the XC2V8000. The XC2V8000 has 2860 data frames
56 * which yields 11.44 mS. So let's make it bigger in order to handle
57 * an XC2V1000, if anyone can ever get ahold of one.
58 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020059#ifndef CONFIG_SYS_FPGA_WAIT_INIT
Robert Hancock19b55dc2019-06-18 09:47:12 -060060#define CONFIG_SYS_FPGA_WAIT_INIT CONFIG_SYS_HZ / 2 /* 500 ms */
wdenk5d3207d2002-08-21 22:08:56 +000061#endif
62
63/*
64 * The default timeout for waiting for BUSY to deassert during configuration.
65 * This is normally not necessary since for most reasonable configuration
66 * clock frequencies (i.e. 66 MHz or less), BUSY monitoring is unnecessary.
67 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020068#ifndef CONFIG_SYS_FPGA_WAIT_BUSY
Robert Hancock19b55dc2019-06-18 09:47:12 -060069#define CONFIG_SYS_FPGA_WAIT_BUSY CONFIG_SYS_HZ / 200 /* 5 ms*/
wdenk5d3207d2002-08-21 22:08:56 +000070#endif
71
72/* Default timeout for waiting for FPGA to enter operational mode after
73 * configuration data has been written.
74 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020075#ifndef CONFIG_SYS_FPGA_WAIT_CONFIG
Robert Hancock19b55dc2019-06-18 09:47:12 -060076#define CONFIG_SYS_FPGA_WAIT_CONFIG CONFIG_SYS_HZ / 5 /* 200 ms */
wdenk5d3207d2002-08-21 22:08:56 +000077#endif
78
Michal Simek25e1e2e2014-03-13 12:49:21 +010079static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize);
80static int virtex2_ssm_dump(xilinx_desc *desc, const void *buf, size_t bsize);
wdenk5d3207d2002-08-21 22:08:56 +000081
Michal Simek25e1e2e2014-03-13 12:49:21 +010082static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
83static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
wdenk5d3207d2002-08-21 22:08:56 +000084
Michal Simek14663652014-05-02 14:09:30 +020085static int virtex2_load(xilinx_desc *desc, const void *buf, size_t bsize,
Oleksandr Suvorovc0806cc2022-07-22 17:16:10 +030086 bitstream_type bstype, int flags)
wdenk5d3207d2002-08-21 22:08:56 +000087{
88 int ret_val = FPGA_FAIL;
89
90 switch (desc->iface) {
91 case slave_serial:
Robert Hancock19b55dc2019-06-18 09:47:12 -060092 PRINTF("%s: Launching Slave Serial Load\n", __func__);
Michal Simek90258882014-03-13 11:33:36 +010093 ret_val = virtex2_ss_load(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +000094 break;
95
96 case slave_selectmap:
Robert Hancock19b55dc2019-06-18 09:47:12 -060097 PRINTF("%s: Launching Slave Parallel Load\n", __func__);
Michal Simek90258882014-03-13 11:33:36 +010098 ret_val = virtex2_ssm_load(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +000099 break;
100
101 default:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600102 printf("%s: Unsupported interface type, %d\n",
103 __func__, desc->iface);
wdenk5d3207d2002-08-21 22:08:56 +0000104 }
105 return ret_val;
106}
107
Michal Simek75fafac2014-03-13 13:07:57 +0100108static int virtex2_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000109{
110 int ret_val = FPGA_FAIL;
111
112 switch (desc->iface) {
113 case slave_serial:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600114 PRINTF("%s: Launching Slave Serial Dump\n", __func__);
Michal Simek90258882014-03-13 11:33:36 +0100115 ret_val = virtex2_ss_dump(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000116 break;
117
118 case slave_parallel:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600119 PRINTF("%s: Launching Slave Parallel Dump\n", __func__);
Michal Simek90258882014-03-13 11:33:36 +0100120 ret_val = virtex2_ssm_dump(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000121 break;
122
123 default:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600124 printf("%s: Unsupported interface type, %d\n",
125 __func__, desc->iface);
wdenk5d3207d2002-08-21 22:08:56 +0000126 }
127 return ret_val;
128}
129
Michal Simek75fafac2014-03-13 13:07:57 +0100130static int virtex2_info(xilinx_desc *desc)
wdenk5d3207d2002-08-21 22:08:56 +0000131{
132 return FPGA_SUCCESS;
133}
134
wdenk5d3207d2002-08-21 22:08:56 +0000135/*
Robert Hancock0b888342019-06-18 09:47:16 -0600136 * Virtex-II Slave SelectMap or Serial configuration loader. Configuration
137 * is as follows:
wdenk5d3207d2002-08-21 22:08:56 +0000138 * 1. Set the FPGA's PROG_B line low.
139 * 2. Set the FPGA's PROG_B line high. Wait for INIT_B to go high.
140 * 3. Write data to the SelectMap port. If INIT_B goes low at any time
141 * this process, a configuration error (most likely CRC failure) has
142 * ocurred. At this point a status word may be read from the
143 * SelectMap interface to determine the source of the problem (You
Wolfgang Denkffb77562005-09-24 23:41:00 +0200144 * could, for instance, put this in your 'abort' function handler).
wdenk5d3207d2002-08-21 22:08:56 +0000145 * 4. After all data has been written, test the state of the FPGA
146 * INIT_B and DONE lines. If both are high, configuration has
147 * succeeded. Congratulations!
148 */
Robert Hancock0b888342019-06-18 09:47:16 -0600149static int virtex2_slave_pre(xilinx_virtex2_slave_fns *fn, int cookie)
wdenk5d3207d2002-08-21 22:08:56 +0000150{
Robert Hancock8a7d6632019-06-18 09:47:14 -0600151 unsigned long ts;
wdenk5d3207d2002-08-21 22:08:56 +0000152
Robert Hancock19b55dc2019-06-18 09:47:12 -0600153 PRINTF("%s:%d: Start with interface functions @ 0x%p\n",
154 __func__, __LINE__, fn);
wdenk5d3207d2002-08-21 22:08:56 +0000155
Robert Hancock8a7d6632019-06-18 09:47:14 -0600156 if (!fn) {
157 printf("%s:%d: NULL Interface function table!\n",
158 __func__, __LINE__);
159 return FPGA_FAIL;
160 }
wdenk5d3207d2002-08-21 22:08:56 +0000161
Robert Hancock8a7d6632019-06-18 09:47:14 -0600162 /* Gotta split this one up (so the stack won't blow??) */
163 PRINTF("%s:%d: Function Table:\n"
164 " base 0x%p\n"
165 " struct 0x%p\n"
166 " pre 0x%p\n"
167 " prog 0x%p\n"
168 " init 0x%p\n"
169 " error 0x%p\n",
170 __func__, __LINE__,
171 &fn, fn, fn->pre, fn->pgm, fn->init, fn->err);
172 PRINTF(" clock 0x%p\n"
173 " cs 0x%p\n"
174 " write 0x%p\n"
175 " rdata 0x%p\n"
176 " wdata 0x%p\n"
177 " busy 0x%p\n"
178 " abort 0x%p\n"
179 " post 0x%p\n\n",
180 fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata,
181 fn->busy, fn->abort, fn->post);
wdenk5d3207d2002-08-21 22:08:56 +0000182
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200183#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock8a7d6632019-06-18 09:47:14 -0600184 printf("Initializing FPGA Device %d...\n", cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000185#endif
Robert Hancock8a7d6632019-06-18 09:47:14 -0600186 /*
187 * Run the pre configuration function if there is one.
188 */
189 if (*fn->pre)
190 (*fn->pre)(cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000191
Robert Hancock8a7d6632019-06-18 09:47:14 -0600192 /*
193 * Assert the program line. The minimum pulse width for
194 * Virtex II devices is 300 nS (Tprogram parameter in datasheet).
195 * There is no maximum value for the pulse width. Check to make
196 * sure that INIT_B goes low after assertion of PROG_B
197 */
198 (*fn->pgm)(true, true, cookie);
199 udelay(10);
200 ts = get_timer(0);
201 do {
202 if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT_INIT) {
203 printf("%s:%d: ** Timeout after %d ticks waiting for INIT to assert.\n",
204 __func__, __LINE__, CONFIG_SYS_FPGA_WAIT_INIT);
205 (*fn->abort)(cookie);
206 return FPGA_FAIL;
207 }
208 } while (!(*fn->init)(cookie));
wdenk5d3207d2002-08-21 22:08:56 +0000209
Robert Hancock8a7d6632019-06-18 09:47:14 -0600210 (*fn->pgm)(false, true, cookie);
211 CONFIG_FPGA_DELAY();
212 if (fn->clk)
Robert Hancock19b55dc2019-06-18 09:47:12 -0600213 (*fn->clk)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000214
Robert Hancock8a7d6632019-06-18 09:47:14 -0600215 /*
216 * Start a timer and wait for INIT_B to go high
217 */
218 ts = get_timer(0);
219 do {
220 CONFIG_FPGA_DELAY();
221 if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT_INIT) {
222 printf("%s:%d: ** Timeout after %d ticks waiting for INIT to deassert.\n",
223 __func__, __LINE__, CONFIG_SYS_FPGA_WAIT_INIT);
224 (*fn->abort)(cookie);
225 return FPGA_FAIL;
226 }
227 } while ((*fn->init)(cookie) && (*fn->busy)(cookie));
wdenk5d3207d2002-08-21 22:08:56 +0000228
Robert Hancock8a7d6632019-06-18 09:47:14 -0600229 if (fn->wr)
Robert Hancock19b55dc2019-06-18 09:47:12 -0600230 (*fn->wr)(true, true, cookie);
Robert Hancock8a7d6632019-06-18 09:47:14 -0600231 if (fn->cs)
Robert Hancock19b55dc2019-06-18 09:47:12 -0600232 (*fn->cs)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000233
Robert Hancock8a7d6632019-06-18 09:47:14 -0600234 mdelay(10);
235 return FPGA_SUCCESS;
236}
wdenk5d3207d2002-08-21 22:08:56 +0000237
Robert Hancock0b888342019-06-18 09:47:16 -0600238static int virtex2_slave_post(xilinx_virtex2_slave_fns *fn,
Robert Hancock8a7d6632019-06-18 09:47:14 -0600239 int cookie)
240{
241 int ret_val = FPGA_SUCCESS;
Robert Hancock7b5140c2019-06-18 09:47:15 -0600242 int num_done = 0;
Robert Hancock8a7d6632019-06-18 09:47:14 -0600243 unsigned long ts;
Wolfgang Denkffb77562005-09-24 23:41:00 +0200244
Robert Hancock8a7d6632019-06-18 09:47:14 -0600245 /*
246 * Finished writing the data; deassert FPGA CS_B and WRITE_B signals.
247 */
248 CONFIG_FPGA_DELAY();
249 if (fn->cs)
250 (*fn->cs)(false, true, cookie);
251 if (fn->wr)
252 (*fn->wr)(false, true, cookie);
Wolfgang Denkffb77562005-09-24 23:41:00 +0200253
Robert Hancock8a7d6632019-06-18 09:47:14 -0600254#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
255 putc('\n');
wdenk5d3207d2002-08-21 22:08:56 +0000256#endif
Wolfgang Denkffb77562005-09-24 23:41:00 +0200257
Robert Hancock8a7d6632019-06-18 09:47:14 -0600258 /*
259 * Check for successful configuration. FPGA INIT_B and DONE
Robert Hancock7b5140c2019-06-18 09:47:15 -0600260 * should both be high upon successful configuration. Continue pulsing
261 * clock with data set to all ones until DONE is asserted and for 8
262 * clock cycles afterwards.
Robert Hancock8a7d6632019-06-18 09:47:14 -0600263 */
264 ts = get_timer(0);
Robert Hancock7b5140c2019-06-18 09:47:15 -0600265 while (true) {
266 if ((*fn->done)(cookie) == FPGA_SUCCESS &&
267 !((*fn->init)(cookie))) {
268 if (num_done++ >= 8)
269 break;
270 }
271
Robert Hancock8a7d6632019-06-18 09:47:14 -0600272 if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT_CONFIG) {
273 printf("%s:%d: ** Timeout after %d ticks waiting for DONE to assert and INIT to deassert\n",
274 __func__, __LINE__, CONFIG_SYS_FPGA_WAIT_CONFIG);
275 (*fn->abort)(cookie);
276 ret_val = FPGA_FAIL;
277 break;
278 }
Robert Hancock0b888342019-06-18 09:47:16 -0600279 if (fn->wbulkdata) {
280 unsigned char dummy = 0xff;
281 (*fn->wbulkdata)(&dummy, 1, true, cookie);
282 } else {
283 (*fn->wdata)(0xff, true, cookie);
284 CONFIG_FPGA_DELAY();
285 (*fn->clk)(false, true, cookie);
286 CONFIG_FPGA_DELAY();
287 (*fn->clk)(true, true, cookie);
288 }
Robert Hancock8a7d6632019-06-18 09:47:14 -0600289 }
wdenk5d3207d2002-08-21 22:08:56 +0000290
Robert Hancock8a7d6632019-06-18 09:47:14 -0600291 if (ret_val == FPGA_SUCCESS) {
292#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
293 printf("Initialization of FPGA device %d complete\n", cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000294#endif
Robert Hancock8a7d6632019-06-18 09:47:14 -0600295 /*
296 * Run the post configuration function if there is one.
297 */
298 if (*fn->post)
299 (*fn->post)(cookie);
300 } else {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200301#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock8a7d6632019-06-18 09:47:14 -0600302 printf("** Initialization of FPGA device %d FAILED\n",
303 cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000304#endif
Robert Hancock8a7d6632019-06-18 09:47:14 -0600305 }
306 return ret_val;
307}
308
309static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize)
310{
311 int ret_val = FPGA_FAIL;
Robert Hancock0b888342019-06-18 09:47:16 -0600312 xilinx_virtex2_slave_fns *fn = desc->iface_fns;
Robert Hancock8a7d6632019-06-18 09:47:14 -0600313 size_t bytecount = 0;
314 unsigned char *data = (unsigned char *)buf;
315 int cookie = desc->cookie;
316
317 ret_val = virtex2_slave_pre(fn, cookie);
318 if (ret_val != FPGA_SUCCESS)
319 return ret_val;
320
321 /*
322 * Load the data byte by byte
323 */
324 while (bytecount < bsize) {
325#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
326 if (ctrlc()) {
327 (*fn->abort)(cookie);
328 return FPGA_FAIL;
wdenk5d3207d2002-08-21 22:08:56 +0000329 }
Robert Hancock8a7d6632019-06-18 09:47:14 -0600330#endif
wdenk5d3207d2002-08-21 22:08:56 +0000331
Robert Hancock8a7d6632019-06-18 09:47:14 -0600332 if ((*fn->done)(cookie) == FPGA_SUCCESS) {
333 PRINTF("%s:%d:done went active early, bytecount = %d\n",
334 __func__, __LINE__, bytecount);
335 break;
336 }
wdenk5d3207d2002-08-21 22:08:56 +0000337
Robert Hancock8a7d6632019-06-18 09:47:14 -0600338#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
339 if ((*fn->init)(cookie)) {
340 printf("\n%s:%d: ** Error: INIT asserted during configuration\n",
341 __func__, __LINE__);
342 printf("%zu = buffer offset, %zu = buffer size\n",
343 bytecount, bsize);
344 (*fn->abort)(cookie);
345 return FPGA_FAIL;
346 }
wdenk5d3207d2002-08-21 22:08:56 +0000347#endif
348
Robert Hancock8a7d6632019-06-18 09:47:14 -0600349 (*fn->wdata)(data[bytecount++], true, cookie);
350 CONFIG_FPGA_DELAY();
351
wdenk5d3207d2002-08-21 22:08:56 +0000352 /*
Robert Hancock8a7d6632019-06-18 09:47:14 -0600353 * Cycle the clock pin
wdenk5d3207d2002-08-21 22:08:56 +0000354 */
Robert Hancock8a7d6632019-06-18 09:47:14 -0600355 (*fn->clk)(false, true, cookie);
356 CONFIG_FPGA_DELAY();
357 (*fn->clk)(true, true, cookie);
358
359#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
Robert Hancock19b55dc2019-06-18 09:47:12 -0600360 ts = get_timer(0);
Robert Hancock8a7d6632019-06-18 09:47:14 -0600361 while ((*fn->busy)(cookie)) {
362 if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT_BUSY) {
363 printf("%s:%d: ** Timeout after %d ticks waiting for BUSY to deassert\n",
Robert Hancock19b55dc2019-06-18 09:47:12 -0600364 __func__, __LINE__,
Robert Hancock8a7d6632019-06-18 09:47:14 -0600365 CONFIG_SYS_FPGA_WAIT_BUSY);
Robert Hancock19b55dc2019-06-18 09:47:12 -0600366 (*fn->abort)(cookie);
Robert Hancock8a7d6632019-06-18 09:47:14 -0600367 return FPGA_FAIL;
wdenk5d3207d2002-08-21 22:08:56 +0000368 }
369 }
wdenk5d3207d2002-08-21 22:08:56 +0000370#endif
Robert Hancock8a7d6632019-06-18 09:47:14 -0600371
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200372#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock8a7d6632019-06-18 09:47:14 -0600373 if (bytecount % (bsize / 40) == 0)
374 putc('.');
wdenk5d3207d2002-08-21 22:08:56 +0000375#endif
wdenk5d3207d2002-08-21 22:08:56 +0000376 }
Robert Hancock8a7d6632019-06-18 09:47:14 -0600377
378 return virtex2_slave_post(fn, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000379}
380
381/*
382 * Read the FPGA configuration data
383 */
Michal Simek25e1e2e2014-03-13 12:49:21 +0100384static int virtex2_ssm_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000385{
386 int ret_val = FPGA_FAIL;
Robert Hancock0b888342019-06-18 09:47:16 -0600387 xilinx_virtex2_slave_fns *fn = desc->iface_fns;
wdenk5d3207d2002-08-21 22:08:56 +0000388
389 if (fn) {
Robert Hancock19b55dc2019-06-18 09:47:12 -0600390 unsigned char *data = (unsigned char *)buf;
wdenk5d3207d2002-08-21 22:08:56 +0000391 size_t bytecount = 0;
392 int cookie = desc->cookie;
393
Robert Hancock19b55dc2019-06-18 09:47:12 -0600394 printf("Starting Dump of FPGA Device %d...\n", cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000395
Robert Hancock19b55dc2019-06-18 09:47:12 -0600396 (*fn->cs)(true, true, cookie);
397 (*fn->clk)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000398
399 while (bytecount < bsize) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200400#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
Robert Hancock19b55dc2019-06-18 09:47:12 -0600401 if (ctrlc()) {
402 (*fn->abort)(cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000403 return FPGA_FAIL;
404 }
405#endif
406 /*
407 * Cycle the clock and read the data
408 */
Robert Hancock19b55dc2019-06-18 09:47:12 -0600409 (*fn->clk)(false, true, cookie);
410 (*fn->clk)(true, true, cookie);
411 (*fn->rdata)(&data[bytecount++], cookie);
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200412#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk5d3207d2002-08-21 22:08:56 +0000413 if (bytecount % (bsize / 40) == 0)
Robert Hancock19b55dc2019-06-18 09:47:12 -0600414 putc('.');
wdenk5d3207d2002-08-21 22:08:56 +0000415#endif
416 }
417
418 /*
419 * Deassert CS_B and cycle the clock to deselect the device.
420 */
Robert Hancock19b55dc2019-06-18 09:47:12 -0600421 (*fn->cs)(false, false, cookie);
422 (*fn->clk)(false, true, cookie);
423 (*fn->clk)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000424
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200425#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock19b55dc2019-06-18 09:47:12 -0600426 putc('\n');
wdenk5d3207d2002-08-21 22:08:56 +0000427#endif
Robert Hancock19b55dc2019-06-18 09:47:12 -0600428 puts("Done.\n");
wdenk5d3207d2002-08-21 22:08:56 +0000429 } else {
Robert Hancock19b55dc2019-06-18 09:47:12 -0600430 printf("%s:%d: NULL Interface function table!\n",
431 __func__, __LINE__);
wdenk5d3207d2002-08-21 22:08:56 +0000432 }
433 return ret_val;
434}
435
Michal Simek25e1e2e2014-03-13 12:49:21 +0100436static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000437{
Robert Hancock0b888342019-06-18 09:47:16 -0600438 int ret_val = FPGA_FAIL;
439 xilinx_virtex2_slave_fns *fn = desc->iface_fns;
440 unsigned char *data = (unsigned char *)buf;
441 int cookie = desc->cookie;
442
443 ret_val = virtex2_slave_pre(fn, cookie);
444 if (ret_val != FPGA_SUCCESS)
445 return ret_val;
446
447 if (fn->wbulkdata) {
448 /* Load the data in a single chunk */
449 (*fn->wbulkdata)(data, bsize, true, cookie);
450 } else {
451 size_t bytecount = 0;
452
453 /*
454 * Load the data bit by bit
455 */
456 while (bytecount < bsize) {
457 unsigned char curr_data = data[bytecount++];
458 int bit;
459
460#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
461 if (ctrlc()) {
462 (*fn->abort) (cookie);
463 return FPGA_FAIL;
464 }
465#endif
466
467 if ((*fn->done)(cookie) == FPGA_SUCCESS) {
468 PRINTF("%s:%d:done went active early, bytecount = %d\n",
469 __func__, __LINE__, bytecount);
470 break;
471 }
472
473#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
474 if ((*fn->init)(cookie)) {
475 printf("\n%s:%d: ** Error: INIT asserted during configuration\n",
476 __func__, __LINE__);
477 printf("%zu = buffer offset, %zu = buffer size\n",
478 bytecount, bsize);
479 (*fn->abort)(cookie);
480 return FPGA_FAIL;
481 }
482#endif
483
484 for (bit = 7; bit >= 0; --bit) {
485 unsigned char curr_bit = (curr_data >> bit) & 1;
486 (*fn->wdata)(curr_bit, true, cookie);
487 CONFIG_FPGA_DELAY();
488 (*fn->clk)(false, true, cookie);
489 CONFIG_FPGA_DELAY();
490 (*fn->clk)(true, true, cookie);
491 }
492
493 /* Slave serial never uses a busy pin */
494
495#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
496 if (bytecount % (bsize / 40) == 0)
497 putc('.');
498#endif
499 }
500 }
501
502 return virtex2_slave_post(fn, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000503}
504
Michal Simek25e1e2e2014-03-13 12:49:21 +0100505static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000506{
Robert Hancock19b55dc2019-06-18 09:47:12 -0600507 printf("%s: Slave Serial Dumping is unsupported\n", __func__);
wdenk5d3207d2002-08-21 22:08:56 +0000508 return FPGA_FAIL;
509}
510
wdenk5d3207d2002-08-21 22:08:56 +0000511/* vim: set ts=4 tw=78: */
Michal Simek75fafac2014-03-13 13:07:57 +0100512
513struct xilinx_fpga_op virtex2_op = {
514 .load = virtex2_load,
515 .dump = virtex2_dump,
516 .info = virtex2_info,
517};