blob: 8e2c12bb58b1271efea0e3d3a31084eafc49cfdb [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
Alexander Dahl4b842e12022-10-07 14:20:03 +020015#define LOG_CATEGORY UCLASS_FPGA
16
Tom Rinidec7ea02024-05-20 13:35:03 -060017#include <config.h>
Simon Glassa73bda42015-11-08 23:47:45 -070018#include <console.h>
Alexander Dahl4b842e12022-10-07 14:20:03 +020019#include <log.h>
wdenk5d3207d2002-08-21 22:08:56 +000020#include <virtex2.h>
Simon Glassdbd79542020-05-10 11:40:11 -060021#include <linux/delay.h>
wdenk5d3207d2002-08-21 22:08:56 +000022
wdenk5d3207d2002-08-21 22:08:56 +000023/*
Tom Rinife8f39a2022-12-04 10:03:29 -050024 * If the SelectMap interface can be overrun by the processor, enable
Tom Rini88d86ec2022-12-04 10:03:57 -050025 * CONFIG_SYS_FPGA_CHECK_BUSY and/or define CFG_FPGA_DELAY in the board
Robert Hancock19b55dc2019-06-18 09:47:12 -060026 * 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 */
wdenk5d3207d2002-08-21 22:08:56 +000029
Tom Rini88d86ec2022-12-04 10:03:57 -050030#ifndef CFG_FPGA_DELAY
31#define CFG_FPGA_DELAY()
wdenk5d3207d2002-08-21 22:08:56 +000032#endif
33
wdenk5d3207d2002-08-21 22:08:56 +000034/*
wdenk5d3207d2002-08-21 22:08:56 +000035 * Check for errors during configuration by default
36 */
Tom Rini364d0022023-01-10 11:19:45 -050037#ifndef CFG_SYS_FPGA_CHECK_ERROR
38#define CFG_SYS_FPGA_CHECK_ERROR
wdenk5d3207d2002-08-21 22:08:56 +000039#endif
40
41/*
42 * The default timeout in mS for INIT_B to deassert after PROG_B has
43 * been deasserted. Per the latest Virtex II Handbook (page 347), the
44 * max time from PORG_B deassertion to INIT_B deassertion is 4uS per
45 * data frame for the XC2V8000. The XC2V8000 has 2860 data frames
46 * which yields 11.44 mS. So let's make it bigger in order to handle
47 * an XC2V1000, if anyone can ever get ahold of one.
48 */
Tom Rini6a5dccc2022-11-16 13:10:41 -050049#ifndef CFG_SYS_FPGA_WAIT_INIT
50#define CFG_SYS_FPGA_WAIT_INIT CONFIG_SYS_HZ / 2 /* 500 ms */
wdenk5d3207d2002-08-21 22:08:56 +000051#endif
52
53/*
54 * The default timeout for waiting for BUSY to deassert during configuration.
55 * This is normally not necessary since for most reasonable configuration
56 * clock frequencies (i.e. 66 MHz or less), BUSY monitoring is unnecessary.
57 */
Tom Rini6a5dccc2022-11-16 13:10:41 -050058#ifndef CFG_SYS_FPGA_WAIT_BUSY
59#define CFG_SYS_FPGA_WAIT_BUSY CONFIG_SYS_HZ / 200 /* 5 ms*/
wdenk5d3207d2002-08-21 22:08:56 +000060#endif
61
62/* Default timeout for waiting for FPGA to enter operational mode after
63 * configuration data has been written.
64 */
Tom Rini6a5dccc2022-11-16 13:10:41 -050065#ifndef CFG_SYS_FPGA_WAIT_CONFIG
66#define CFG_SYS_FPGA_WAIT_CONFIG CONFIG_SYS_HZ / 5 /* 200 ms */
wdenk5d3207d2002-08-21 22:08:56 +000067#endif
68
Michal Simek25e1e2e2014-03-13 12:49:21 +010069static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize);
70static int virtex2_ssm_dump(xilinx_desc *desc, const void *buf, size_t bsize);
wdenk5d3207d2002-08-21 22:08:56 +000071
Michal Simek25e1e2e2014-03-13 12:49:21 +010072static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
73static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
wdenk5d3207d2002-08-21 22:08:56 +000074
Michal Simek14663652014-05-02 14:09:30 +020075static int virtex2_load(xilinx_desc *desc, const void *buf, size_t bsize,
Oleksandr Suvorovc0806cc2022-07-22 17:16:10 +030076 bitstream_type bstype, int flags)
wdenk5d3207d2002-08-21 22:08:56 +000077{
78 int ret_val = FPGA_FAIL;
79
80 switch (desc->iface) {
81 case slave_serial:
Alexander Dahl4b842e12022-10-07 14:20:03 +020082 log_debug("Launching Slave Serial Load\n");
Michal Simek90258882014-03-13 11:33:36 +010083 ret_val = virtex2_ss_load(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +000084 break;
85
86 case slave_selectmap:
Alexander Dahl4b842e12022-10-07 14:20:03 +020087 log_debug("Launching Slave Parallel Load\n");
Michal Simek90258882014-03-13 11:33:36 +010088 ret_val = virtex2_ssm_load(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +000089 break;
90
91 default:
Robert Hancock19b55dc2019-06-18 09:47:12 -060092 printf("%s: Unsupported interface type, %d\n",
93 __func__, desc->iface);
wdenk5d3207d2002-08-21 22:08:56 +000094 }
95 return ret_val;
96}
97
Michal Simek75fafac2014-03-13 13:07:57 +010098static int virtex2_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +000099{
100 int ret_val = FPGA_FAIL;
101
102 switch (desc->iface) {
103 case slave_serial:
Alexander Dahl4b842e12022-10-07 14:20:03 +0200104 log_debug("Launching Slave Serial Dump\n");
Michal Simek90258882014-03-13 11:33:36 +0100105 ret_val = virtex2_ss_dump(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000106 break;
107
108 case slave_parallel:
Alexander Dahl4b842e12022-10-07 14:20:03 +0200109 log_debug("Launching Slave Parallel Dump\n");
Michal Simek90258882014-03-13 11:33:36 +0100110 ret_val = virtex2_ssm_dump(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000111 break;
112
113 default:
Robert Hancock19b55dc2019-06-18 09:47:12 -0600114 printf("%s: Unsupported interface type, %d\n",
115 __func__, desc->iface);
wdenk5d3207d2002-08-21 22:08:56 +0000116 }
117 return ret_val;
118}
119
Michal Simek75fafac2014-03-13 13:07:57 +0100120static int virtex2_info(xilinx_desc *desc)
wdenk5d3207d2002-08-21 22:08:56 +0000121{
122 return FPGA_SUCCESS;
123}
124
wdenk5d3207d2002-08-21 22:08:56 +0000125/*
Robert Hancock0b888342019-06-18 09:47:16 -0600126 * Virtex-II Slave SelectMap or Serial configuration loader. Configuration
127 * is as follows:
wdenk5d3207d2002-08-21 22:08:56 +0000128 * 1. Set the FPGA's PROG_B line low.
129 * 2. Set the FPGA's PROG_B line high. Wait for INIT_B to go high.
130 * 3. Write data to the SelectMap port. If INIT_B goes low at any time
131 * this process, a configuration error (most likely CRC failure) has
132 * ocurred. At this point a status word may be read from the
133 * SelectMap interface to determine the source of the problem (You
Wolfgang Denkffb77562005-09-24 23:41:00 +0200134 * could, for instance, put this in your 'abort' function handler).
wdenk5d3207d2002-08-21 22:08:56 +0000135 * 4. After all data has been written, test the state of the FPGA
136 * INIT_B and DONE lines. If both are high, configuration has
137 * succeeded. Congratulations!
138 */
Robert Hancock0b888342019-06-18 09:47:16 -0600139static int virtex2_slave_pre(xilinx_virtex2_slave_fns *fn, int cookie)
wdenk5d3207d2002-08-21 22:08:56 +0000140{
Robert Hancock8a7d6632019-06-18 09:47:14 -0600141 unsigned long ts;
wdenk5d3207d2002-08-21 22:08:56 +0000142
Alexander Dahl4b842e12022-10-07 14:20:03 +0200143 log_debug("Start with interface functions @ 0x%p\n", fn);
wdenk5d3207d2002-08-21 22:08:56 +0000144
Robert Hancock8a7d6632019-06-18 09:47:14 -0600145 if (!fn) {
146 printf("%s:%d: NULL Interface function table!\n",
147 __func__, __LINE__);
148 return FPGA_FAIL;
149 }
wdenk5d3207d2002-08-21 22:08:56 +0000150
Robert Hancock8a7d6632019-06-18 09:47:14 -0600151 /* Gotta split this one up (so the stack won't blow??) */
Alexander Dahl4b842e12022-10-07 14:20:03 +0200152 log_debug("Function Table:\n"
153 " base 0x%p\n"
154 " struct 0x%p\n"
155 " pre 0x%p\n"
156 " prog 0x%p\n"
157 " init 0x%p\n"
158 " error 0x%p\n",
159 &fn, fn, fn->pre, fn->pgm, fn->init, fn->err);
160 log_debug(" clock 0x%p\n"
161 " cs 0x%p\n"
162 " write 0x%p\n"
163 " rdata 0x%p\n"
164 " wdata 0x%p\n"
165 " busy 0x%p\n"
166 " abort 0x%p\n"
167 " post 0x%p\n\n",
168 fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata,
169 fn->busy, fn->abort, fn->post);
wdenk5d3207d2002-08-21 22:08:56 +0000170
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200171#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock8a7d6632019-06-18 09:47:14 -0600172 printf("Initializing FPGA Device %d...\n", cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000173#endif
Robert Hancock8a7d6632019-06-18 09:47:14 -0600174 /*
175 * Run the pre configuration function if there is one.
176 */
177 if (*fn->pre)
178 (*fn->pre)(cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000179
Robert Hancock8a7d6632019-06-18 09:47:14 -0600180 /*
181 * Assert the program line. The minimum pulse width for
182 * Virtex II devices is 300 nS (Tprogram parameter in datasheet).
183 * There is no maximum value for the pulse width. Check to make
184 * sure that INIT_B goes low after assertion of PROG_B
185 */
186 (*fn->pgm)(true, true, cookie);
187 udelay(10);
188 ts = get_timer(0);
189 do {
Tom Rini6a5dccc2022-11-16 13:10:41 -0500190 if (get_timer(ts) > CFG_SYS_FPGA_WAIT_INIT) {
Robert Hancock8a7d6632019-06-18 09:47:14 -0600191 printf("%s:%d: ** Timeout after %d ticks waiting for INIT to assert.\n",
Tom Rini6a5dccc2022-11-16 13:10:41 -0500192 __func__, __LINE__, CFG_SYS_FPGA_WAIT_INIT);
Robert Hancock8a7d6632019-06-18 09:47:14 -0600193 (*fn->abort)(cookie);
194 return FPGA_FAIL;
195 }
196 } while (!(*fn->init)(cookie));
wdenk5d3207d2002-08-21 22:08:56 +0000197
Robert Hancock8a7d6632019-06-18 09:47:14 -0600198 (*fn->pgm)(false, true, cookie);
Tom Rini88d86ec2022-12-04 10:03:57 -0500199 CFG_FPGA_DELAY();
Robert Hancock8a7d6632019-06-18 09:47:14 -0600200 if (fn->clk)
Robert Hancock19b55dc2019-06-18 09:47:12 -0600201 (*fn->clk)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000202
Robert Hancock8a7d6632019-06-18 09:47:14 -0600203 /*
204 * Start a timer and wait for INIT_B to go high
205 */
206 ts = get_timer(0);
207 do {
Tom Rini88d86ec2022-12-04 10:03:57 -0500208 CFG_FPGA_DELAY();
Tom Rini6a5dccc2022-11-16 13:10:41 -0500209 if (get_timer(ts) > CFG_SYS_FPGA_WAIT_INIT) {
Robert Hancock8a7d6632019-06-18 09:47:14 -0600210 printf("%s:%d: ** Timeout after %d ticks waiting for INIT to deassert.\n",
Tom Rini6a5dccc2022-11-16 13:10:41 -0500211 __func__, __LINE__, CFG_SYS_FPGA_WAIT_INIT);
Robert Hancock8a7d6632019-06-18 09:47:14 -0600212 (*fn->abort)(cookie);
213 return FPGA_FAIL;
214 }
215 } while ((*fn->init)(cookie) && (*fn->busy)(cookie));
wdenk5d3207d2002-08-21 22:08:56 +0000216
Robert Hancock8a7d6632019-06-18 09:47:14 -0600217 if (fn->wr)
Robert Hancock19b55dc2019-06-18 09:47:12 -0600218 (*fn->wr)(true, true, cookie);
Robert Hancock8a7d6632019-06-18 09:47:14 -0600219 if (fn->cs)
Robert Hancock19b55dc2019-06-18 09:47:12 -0600220 (*fn->cs)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000221
Robert Hancock8a7d6632019-06-18 09:47:14 -0600222 mdelay(10);
223 return FPGA_SUCCESS;
224}
wdenk5d3207d2002-08-21 22:08:56 +0000225
Robert Hancock0b888342019-06-18 09:47:16 -0600226static int virtex2_slave_post(xilinx_virtex2_slave_fns *fn,
Robert Hancock8a7d6632019-06-18 09:47:14 -0600227 int cookie)
228{
229 int ret_val = FPGA_SUCCESS;
Robert Hancock7b5140c2019-06-18 09:47:15 -0600230 int num_done = 0;
Robert Hancock8a7d6632019-06-18 09:47:14 -0600231 unsigned long ts;
Wolfgang Denkffb77562005-09-24 23:41:00 +0200232
Robert Hancock8a7d6632019-06-18 09:47:14 -0600233 /*
234 * Finished writing the data; deassert FPGA CS_B and WRITE_B signals.
235 */
Tom Rini88d86ec2022-12-04 10:03:57 -0500236 CFG_FPGA_DELAY();
Robert Hancock8a7d6632019-06-18 09:47:14 -0600237 if (fn->cs)
238 (*fn->cs)(false, true, cookie);
239 if (fn->wr)
240 (*fn->wr)(false, true, cookie);
Wolfgang Denkffb77562005-09-24 23:41:00 +0200241
Robert Hancock8a7d6632019-06-18 09:47:14 -0600242#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
243 putc('\n');
wdenk5d3207d2002-08-21 22:08:56 +0000244#endif
Wolfgang Denkffb77562005-09-24 23:41:00 +0200245
Robert Hancock8a7d6632019-06-18 09:47:14 -0600246 /*
247 * Check for successful configuration. FPGA INIT_B and DONE
Robert Hancock7b5140c2019-06-18 09:47:15 -0600248 * should both be high upon successful configuration. Continue pulsing
249 * clock with data set to all ones until DONE is asserted and for 8
250 * clock cycles afterwards.
Robert Hancock8a7d6632019-06-18 09:47:14 -0600251 */
252 ts = get_timer(0);
Robert Hancock7b5140c2019-06-18 09:47:15 -0600253 while (true) {
254 if ((*fn->done)(cookie) == FPGA_SUCCESS &&
255 !((*fn->init)(cookie))) {
256 if (num_done++ >= 8)
257 break;
258 }
259
Tom Rini6a5dccc2022-11-16 13:10:41 -0500260 if (get_timer(ts) > CFG_SYS_FPGA_WAIT_CONFIG) {
Robert Hancock8a7d6632019-06-18 09:47:14 -0600261 printf("%s:%d: ** Timeout after %d ticks waiting for DONE to assert and INIT to deassert\n",
Tom Rini6a5dccc2022-11-16 13:10:41 -0500262 __func__, __LINE__, CFG_SYS_FPGA_WAIT_CONFIG);
Robert Hancock8a7d6632019-06-18 09:47:14 -0600263 (*fn->abort)(cookie);
264 ret_val = FPGA_FAIL;
265 break;
266 }
Robert Hancock0b888342019-06-18 09:47:16 -0600267 if (fn->wbulkdata) {
268 unsigned char dummy = 0xff;
269 (*fn->wbulkdata)(&dummy, 1, true, cookie);
270 } else {
271 (*fn->wdata)(0xff, true, cookie);
Tom Rini88d86ec2022-12-04 10:03:57 -0500272 CFG_FPGA_DELAY();
Robert Hancock0b888342019-06-18 09:47:16 -0600273 (*fn->clk)(false, true, cookie);
Tom Rini88d86ec2022-12-04 10:03:57 -0500274 CFG_FPGA_DELAY();
Robert Hancock0b888342019-06-18 09:47:16 -0600275 (*fn->clk)(true, true, cookie);
276 }
Robert Hancock8a7d6632019-06-18 09:47:14 -0600277 }
wdenk5d3207d2002-08-21 22:08:56 +0000278
Robert Hancock8a7d6632019-06-18 09:47:14 -0600279 if (ret_val == FPGA_SUCCESS) {
280#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
281 printf("Initialization of FPGA device %d complete\n", cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000282#endif
Robert Hancock8a7d6632019-06-18 09:47:14 -0600283 /*
284 * Run the post configuration function if there is one.
285 */
286 if (*fn->post)
287 (*fn->post)(cookie);
288 } else {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200289#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock8a7d6632019-06-18 09:47:14 -0600290 printf("** Initialization of FPGA device %d FAILED\n",
291 cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000292#endif
Robert Hancock8a7d6632019-06-18 09:47:14 -0600293 }
294 return ret_val;
295}
296
297static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize)
298{
299 int ret_val = FPGA_FAIL;
Robert Hancock0b888342019-06-18 09:47:16 -0600300 xilinx_virtex2_slave_fns *fn = desc->iface_fns;
Robert Hancock8a7d6632019-06-18 09:47:14 -0600301 size_t bytecount = 0;
302 unsigned char *data = (unsigned char *)buf;
303 int cookie = desc->cookie;
304
305 ret_val = virtex2_slave_pre(fn, cookie);
306 if (ret_val != FPGA_SUCCESS)
307 return ret_val;
308
309 /*
310 * Load the data byte by byte
311 */
312 while (bytecount < bsize) {
313#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
314 if (ctrlc()) {
315 (*fn->abort)(cookie);
316 return FPGA_FAIL;
wdenk5d3207d2002-08-21 22:08:56 +0000317 }
Robert Hancock8a7d6632019-06-18 09:47:14 -0600318#endif
wdenk5d3207d2002-08-21 22:08:56 +0000319
Robert Hancock8a7d6632019-06-18 09:47:14 -0600320 if ((*fn->done)(cookie) == FPGA_SUCCESS) {
Alexander Dahl4b842e12022-10-07 14:20:03 +0200321 log_debug("done went active early, bytecount = %zu\n",
322 bytecount);
Robert Hancock8a7d6632019-06-18 09:47:14 -0600323 break;
324 }
wdenk5d3207d2002-08-21 22:08:56 +0000325
Tom Rini364d0022023-01-10 11:19:45 -0500326#ifdef CFG_SYS_FPGA_CHECK_ERROR
Robert Hancock8a7d6632019-06-18 09:47:14 -0600327 if ((*fn->init)(cookie)) {
328 printf("\n%s:%d: ** Error: INIT asserted during configuration\n",
329 __func__, __LINE__);
330 printf("%zu = buffer offset, %zu = buffer size\n",
331 bytecount, bsize);
332 (*fn->abort)(cookie);
333 return FPGA_FAIL;
334 }
wdenk5d3207d2002-08-21 22:08:56 +0000335#endif
336
Robert Hancock8a7d6632019-06-18 09:47:14 -0600337 (*fn->wdata)(data[bytecount++], true, cookie);
Tom Rini88d86ec2022-12-04 10:03:57 -0500338 CFG_FPGA_DELAY();
Robert Hancock8a7d6632019-06-18 09:47:14 -0600339
wdenk5d3207d2002-08-21 22:08:56 +0000340 /*
Robert Hancock8a7d6632019-06-18 09:47:14 -0600341 * Cycle the clock pin
wdenk5d3207d2002-08-21 22:08:56 +0000342 */
Robert Hancock8a7d6632019-06-18 09:47:14 -0600343 (*fn->clk)(false, true, cookie);
Tom Rini88d86ec2022-12-04 10:03:57 -0500344 CFG_FPGA_DELAY();
Robert Hancock8a7d6632019-06-18 09:47:14 -0600345 (*fn->clk)(true, true, cookie);
346
347#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
Robert Hancock19b55dc2019-06-18 09:47:12 -0600348 ts = get_timer(0);
Robert Hancock8a7d6632019-06-18 09:47:14 -0600349 while ((*fn->busy)(cookie)) {
Tom Rini6a5dccc2022-11-16 13:10:41 -0500350 if (get_timer(ts) > CFG_SYS_FPGA_WAIT_BUSY) {
Robert Hancock8a7d6632019-06-18 09:47:14 -0600351 printf("%s:%d: ** Timeout after %d ticks waiting for BUSY to deassert\n",
Robert Hancock19b55dc2019-06-18 09:47:12 -0600352 __func__, __LINE__,
Tom Rini6a5dccc2022-11-16 13:10:41 -0500353 CFG_SYS_FPGA_WAIT_BUSY);
Robert Hancock19b55dc2019-06-18 09:47:12 -0600354 (*fn->abort)(cookie);
Robert Hancock8a7d6632019-06-18 09:47:14 -0600355 return FPGA_FAIL;
wdenk5d3207d2002-08-21 22:08:56 +0000356 }
357 }
wdenk5d3207d2002-08-21 22:08:56 +0000358#endif
Robert Hancock8a7d6632019-06-18 09:47:14 -0600359
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200360#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock8a7d6632019-06-18 09:47:14 -0600361 if (bytecount % (bsize / 40) == 0)
362 putc('.');
wdenk5d3207d2002-08-21 22:08:56 +0000363#endif
wdenk5d3207d2002-08-21 22:08:56 +0000364 }
Robert Hancock8a7d6632019-06-18 09:47:14 -0600365
366 return virtex2_slave_post(fn, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000367}
368
369/*
370 * Read the FPGA configuration data
371 */
Michal Simek25e1e2e2014-03-13 12:49:21 +0100372static int virtex2_ssm_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000373{
374 int ret_val = FPGA_FAIL;
Robert Hancock0b888342019-06-18 09:47:16 -0600375 xilinx_virtex2_slave_fns *fn = desc->iface_fns;
wdenk5d3207d2002-08-21 22:08:56 +0000376
377 if (fn) {
Robert Hancock19b55dc2019-06-18 09:47:12 -0600378 unsigned char *data = (unsigned char *)buf;
wdenk5d3207d2002-08-21 22:08:56 +0000379 size_t bytecount = 0;
380 int cookie = desc->cookie;
381
Robert Hancock19b55dc2019-06-18 09:47:12 -0600382 printf("Starting Dump of FPGA Device %d...\n", cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000383
Robert Hancock19b55dc2019-06-18 09:47:12 -0600384 (*fn->cs)(true, true, cookie);
385 (*fn->clk)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000386
387 while (bytecount < bsize) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200388#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
Robert Hancock19b55dc2019-06-18 09:47:12 -0600389 if (ctrlc()) {
390 (*fn->abort)(cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000391 return FPGA_FAIL;
392 }
393#endif
394 /*
395 * Cycle the clock and read the data
396 */
Robert Hancock19b55dc2019-06-18 09:47:12 -0600397 (*fn->clk)(false, true, cookie);
398 (*fn->clk)(true, true, cookie);
399 (*fn->rdata)(&data[bytecount++], cookie);
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200400#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk5d3207d2002-08-21 22:08:56 +0000401 if (bytecount % (bsize / 40) == 0)
Robert Hancock19b55dc2019-06-18 09:47:12 -0600402 putc('.');
wdenk5d3207d2002-08-21 22:08:56 +0000403#endif
404 }
405
406 /*
407 * Deassert CS_B and cycle the clock to deselect the device.
408 */
Robert Hancock19b55dc2019-06-18 09:47:12 -0600409 (*fn->cs)(false, false, cookie);
410 (*fn->clk)(false, true, cookie);
411 (*fn->clk)(true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000412
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200413#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
Robert Hancock19b55dc2019-06-18 09:47:12 -0600414 putc('\n');
wdenk5d3207d2002-08-21 22:08:56 +0000415#endif
Robert Hancock19b55dc2019-06-18 09:47:12 -0600416 puts("Done.\n");
wdenk5d3207d2002-08-21 22:08:56 +0000417 } else {
Robert Hancock19b55dc2019-06-18 09:47:12 -0600418 printf("%s:%d: NULL Interface function table!\n",
419 __func__, __LINE__);
wdenk5d3207d2002-08-21 22:08:56 +0000420 }
421 return ret_val;
422}
423
Michal Simek25e1e2e2014-03-13 12:49:21 +0100424static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000425{
Robert Hancock0b888342019-06-18 09:47:16 -0600426 int ret_val = FPGA_FAIL;
427 xilinx_virtex2_slave_fns *fn = desc->iface_fns;
428 unsigned char *data = (unsigned char *)buf;
429 int cookie = desc->cookie;
430
431 ret_val = virtex2_slave_pre(fn, cookie);
432 if (ret_val != FPGA_SUCCESS)
433 return ret_val;
434
435 if (fn->wbulkdata) {
436 /* Load the data in a single chunk */
437 (*fn->wbulkdata)(data, bsize, true, cookie);
438 } else {
439 size_t bytecount = 0;
440
441 /*
442 * Load the data bit by bit
443 */
444 while (bytecount < bsize) {
445 unsigned char curr_data = data[bytecount++];
446 int bit;
447
448#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
449 if (ctrlc()) {
450 (*fn->abort) (cookie);
451 return FPGA_FAIL;
452 }
453#endif
454
455 if ((*fn->done)(cookie) == FPGA_SUCCESS) {
Alexander Dahl4b842e12022-10-07 14:20:03 +0200456 log_debug("done went active early, bytecount = %zu\n",
457 bytecount);
Robert Hancock0b888342019-06-18 09:47:16 -0600458 break;
459 }
460
Tom Rini364d0022023-01-10 11:19:45 -0500461#ifdef CFG_SYS_FPGA_CHECK_ERROR
Robert Hancock0b888342019-06-18 09:47:16 -0600462 if ((*fn->init)(cookie)) {
463 printf("\n%s:%d: ** Error: INIT asserted during configuration\n",
464 __func__, __LINE__);
465 printf("%zu = buffer offset, %zu = buffer size\n",
466 bytecount, bsize);
467 (*fn->abort)(cookie);
468 return FPGA_FAIL;
469 }
470#endif
471
472 for (bit = 7; bit >= 0; --bit) {
473 unsigned char curr_bit = (curr_data >> bit) & 1;
474 (*fn->wdata)(curr_bit, true, cookie);
Tom Rini88d86ec2022-12-04 10:03:57 -0500475 CFG_FPGA_DELAY();
Robert Hancock0b888342019-06-18 09:47:16 -0600476 (*fn->clk)(false, true, cookie);
Tom Rini88d86ec2022-12-04 10:03:57 -0500477 CFG_FPGA_DELAY();
Robert Hancock0b888342019-06-18 09:47:16 -0600478 (*fn->clk)(true, true, cookie);
479 }
480
481 /* Slave serial never uses a busy pin */
482
483#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
484 if (bytecount % (bsize / 40) == 0)
485 putc('.');
486#endif
487 }
488 }
489
490 return virtex2_slave_post(fn, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000491}
492
Michal Simek25e1e2e2014-03-13 12:49:21 +0100493static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000494{
Robert Hancock19b55dc2019-06-18 09:47:12 -0600495 printf("%s: Slave Serial Dumping is unsupported\n", __func__);
wdenk5d3207d2002-08-21 22:08:56 +0000496 return FPGA_FAIL;
497}
498
wdenk5d3207d2002-08-21 22:08:56 +0000499/* vim: set ts=4 tw=78: */
Michal Simek75fafac2014-03-13 13:07:57 +0100500
501struct xilinx_fpga_op virtex2_op = {
502 .load = virtex2_load,
503 .dump = virtex2_dump,
504 .info = virtex2_info,
505};