blob: 0d2d9a4693264684bbeb5167790057c0ae07b732 [file] [log] [blame]
wdenk5d3207d2002-08-21 22:08:56 +00001/*
2 * (C) Copyright 2002
3 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
4 * Keith Outwater, keith_outwater@mvis.com
5 *
Wolfgang Denkd79de1d2013-07-08 09:37:19 +02006 * SPDX-License-Identifier: GPL-2.0+
wdenk5d3207d2002-08-21 22:08:56 +00007 */
8
9/*
10 * Configuration support for Xilinx Virtex2 devices. Based
11 * on spartan2.c (Rich Ireland, rireland@enterasys.com).
12 */
13
14#include <common.h>
15#include <virtex2.h>
16
Wolfgang Denkffb77562005-09-24 23:41:00 +020017#if 0
18#define FPGA_DEBUG
Wolfgang Denk0cbaf642005-09-25 00:53:22 +020019#endif
Wolfgang Denkffb77562005-09-24 23:41:00 +020020
wdenk5d3207d2002-08-21 22:08:56 +000021#ifdef FPGA_DEBUG
22#define PRINTF(fmt,args...) printf (fmt ,##args)
23#else
24#define PRINTF(fmt,args...)
25#endif
26
27/*
28 * If the SelectMap interface can be overrun by the processor, define
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020029 * CONFIG_SYS_FPGA_CHECK_BUSY and/or CONFIG_FPGA_DELAY in the board configuration
wdenk5d3207d2002-08-21 22:08:56 +000030 * file and add board-specific support for checking BUSY status. By default,
31 * assume that the SelectMap interface cannot be overrun.
32 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020033#ifndef CONFIG_SYS_FPGA_CHECK_BUSY
34#undef CONFIG_SYS_FPGA_CHECK_BUSY
wdenk5d3207d2002-08-21 22:08:56 +000035#endif
36
37#ifndef CONFIG_FPGA_DELAY
38#define CONFIG_FPGA_DELAY()
39#endif
40
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020041#ifndef CONFIG_SYS_FPGA_PROG_FEEDBACK
42#define CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk5d3207d2002-08-21 22:08:56 +000043#endif
44
45/*
46 * Don't allow config cycle to be interrupted
47 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020048#ifndef CONFIG_SYS_FPGA_CHECK_CTRLC
49#undef CONFIG_SYS_FPGA_CHECK_CTRLC
wdenk5d3207d2002-08-21 22:08:56 +000050#endif
51
52/*
53 * Check for errors during configuration by default
54 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020055#ifndef CONFIG_SYS_FPGA_CHECK_ERROR
56#define CONFIG_SYS_FPGA_CHECK_ERROR
wdenk5d3207d2002-08-21 22:08:56 +000057#endif
58
59/*
60 * The default timeout in mS for INIT_B to deassert after PROG_B has
61 * been deasserted. Per the latest Virtex II Handbook (page 347), the
62 * max time from PORG_B deassertion to INIT_B deassertion is 4uS per
63 * data frame for the XC2V8000. The XC2V8000 has 2860 data frames
64 * which yields 11.44 mS. So let's make it bigger in order to handle
65 * an XC2V1000, if anyone can ever get ahold of one.
66 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020067#ifndef CONFIG_SYS_FPGA_WAIT_INIT
68#define CONFIG_SYS_FPGA_WAIT_INIT CONFIG_SYS_HZ/2 /* 500 ms */
wdenk5d3207d2002-08-21 22:08:56 +000069#endif
70
71/*
72 * The default timeout for waiting for BUSY to deassert during configuration.
73 * This is normally not necessary since for most reasonable configuration
74 * clock frequencies (i.e. 66 MHz or less), BUSY monitoring is unnecessary.
75 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020076#ifndef CONFIG_SYS_FPGA_WAIT_BUSY
77#define CONFIG_SYS_FPGA_WAIT_BUSY CONFIG_SYS_HZ/200 /* 5 ms*/
wdenk5d3207d2002-08-21 22:08:56 +000078#endif
79
80/* Default timeout for waiting for FPGA to enter operational mode after
81 * configuration data has been written.
82 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020083#ifndef CONFIG_SYS_FPGA_WAIT_CONFIG
84#define CONFIG_SYS_FPGA_WAIT_CONFIG CONFIG_SYS_HZ/5 /* 200 ms */
wdenk5d3207d2002-08-21 22:08:56 +000085#endif
86
Michal Simek25e1e2e2014-03-13 12:49:21 +010087static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize);
88static int virtex2_ssm_dump(xilinx_desc *desc, const void *buf, size_t bsize);
wdenk5d3207d2002-08-21 22:08:56 +000089
Michal Simek25e1e2e2014-03-13 12:49:21 +010090static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize);
91static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize);
wdenk5d3207d2002-08-21 22:08:56 +000092
Michal Simek14663652014-05-02 14:09:30 +020093static int virtex2_load(xilinx_desc *desc, const void *buf, size_t bsize,
94 bitstream_type bstype)
wdenk5d3207d2002-08-21 22:08:56 +000095{
96 int ret_val = FPGA_FAIL;
97
98 switch (desc->iface) {
99 case slave_serial:
100 PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
Michal Simek90258882014-03-13 11:33:36 +0100101 ret_val = virtex2_ss_load(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000102 break;
103
104 case slave_selectmap:
105 PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
Michal Simek90258882014-03-13 11:33:36 +0100106 ret_val = virtex2_ssm_load(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000107 break;
108
109 default:
110 printf ("%s: Unsupported interface type, %d\n",
111 __FUNCTION__, desc->iface);
112 }
113 return ret_val;
114}
115
Michal Simek75fafac2014-03-13 13:07:57 +0100116static int virtex2_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000117{
118 int ret_val = FPGA_FAIL;
119
120 switch (desc->iface) {
121 case slave_serial:
122 PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
Michal Simek90258882014-03-13 11:33:36 +0100123 ret_val = virtex2_ss_dump(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000124 break;
125
126 case slave_parallel:
127 PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
Michal Simek90258882014-03-13 11:33:36 +0100128 ret_val = virtex2_ssm_dump(desc, buf, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000129 break;
130
131 default:
132 printf ("%s: Unsupported interface type, %d\n",
133 __FUNCTION__, desc->iface);
134 }
135 return ret_val;
136}
137
Michal Simek75fafac2014-03-13 13:07:57 +0100138static int virtex2_info(xilinx_desc *desc)
wdenk5d3207d2002-08-21 22:08:56 +0000139{
140 return FPGA_SUCCESS;
141}
142
wdenk5d3207d2002-08-21 22:08:56 +0000143/*
144 * Virtex-II Slave SelectMap configuration loader. Configuration via
145 * SelectMap is as follows:
146 * 1. Set the FPGA's PROG_B line low.
147 * 2. Set the FPGA's PROG_B line high. Wait for INIT_B to go high.
148 * 3. Write data to the SelectMap port. If INIT_B goes low at any time
149 * this process, a configuration error (most likely CRC failure) has
150 * ocurred. At this point a status word may be read from the
151 * SelectMap interface to determine the source of the problem (You
Wolfgang Denkffb77562005-09-24 23:41:00 +0200152 * could, for instance, put this in your 'abort' function handler).
wdenk5d3207d2002-08-21 22:08:56 +0000153 * 4. After all data has been written, test the state of the FPGA
154 * INIT_B and DONE lines. If both are high, configuration has
155 * succeeded. Congratulations!
156 */
Michal Simek25e1e2e2014-03-13 12:49:21 +0100157static int virtex2_ssm_load(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000158{
159 int ret_val = FPGA_FAIL;
Michal Simek90258882014-03-13 11:33:36 +0100160 xilinx_virtex2_slave_selectmap_fns *fn = desc->iface_fns;
wdenk5d3207d2002-08-21 22:08:56 +0000161
162 PRINTF ("%s:%d: Start with interface functions @ 0x%p\n",
163 __FUNCTION__, __LINE__, fn);
164
165 if (fn) {
166 size_t bytecount = 0;
167 unsigned char *data = (unsigned char *) buf;
168 int cookie = desc->cookie;
169 unsigned long ts;
170
171 /* Gotta split this one up (so the stack won't blow??) */
172 PRINTF ("%s:%d: Function Table:\n"
173 " base 0x%p\n"
174 " struct 0x%p\n"
175 " pre 0x%p\n"
176 " prog 0x%p\n"
177 " init 0x%p\n"
178 " error 0x%p\n",
179 __FUNCTION__, __LINE__,
180 &fn, fn, fn->pre, fn->pgm, fn->init, fn->err);
181 PRINTF (" clock 0x%p\n"
182 " cs 0x%p\n"
183 " write 0x%p\n"
184 " rdata 0x%p\n"
185 " wdata 0x%p\n"
186 " busy 0x%p\n"
187 " abort 0x%p\n"
188 " post 0x%p\n\n",
189 fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata,
190 fn->busy, fn->abort, fn->post);
191
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200192#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk5d3207d2002-08-21 22:08:56 +0000193 printf ("Initializing FPGA Device %d...\n", cookie);
194#endif
195 /*
196 * Run the pre configuration function if there is one.
197 */
198 if (*fn->pre) {
199 (*fn->pre) (cookie);
200 }
201
202 /*
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 */
York Sun4a598092013-04-01 11:29:11 -0700208 (*fn->pgm) (true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000209 udelay (10);
210 ts = get_timer (0);
211 do {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200212 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_INIT) {
Wolfgang Denkffb77562005-09-24 23:41:00 +0200213 printf ("%s:%d: ** Timeout after %d ticks waiting for INIT"
wdenk5d3207d2002-08-21 22:08:56 +0000214 " to assert.\n", __FUNCTION__, __LINE__,
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200215 CONFIG_SYS_FPGA_WAIT_INIT);
wdenk5d3207d2002-08-21 22:08:56 +0000216 (*fn->abort) (cookie);
217 return FPGA_FAIL;
218 }
219 } while (!(*fn->init) (cookie));
220
York Sun4a598092013-04-01 11:29:11 -0700221 (*fn->pgm) (false, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000222 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700223 (*fn->clk) (true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000224
225 /*
226 * Start a timer and wait for INIT_B to go high
227 */
228 ts = get_timer (0);
229 do {
230 CONFIG_FPGA_DELAY ();
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200231 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_INIT) {
Wolfgang Denkffb77562005-09-24 23:41:00 +0200232 printf ("%s:%d: ** Timeout after %d ticks waiting for INIT"
wdenk5d3207d2002-08-21 22:08:56 +0000233 " to deassert.\n", __FUNCTION__, __LINE__,
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200234 CONFIG_SYS_FPGA_WAIT_INIT);
wdenk5d3207d2002-08-21 22:08:56 +0000235 (*fn->abort) (cookie);
236 return FPGA_FAIL;
237 }
238 } while ((*fn->init) (cookie) && (*fn->busy) (cookie));
239
York Sun4a598092013-04-01 11:29:11 -0700240 (*fn->wr) (true, true, cookie);
241 (*fn->cs) (true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000242
243 udelay (10000);
244
245 /*
246 * Load the data byte by byte
247 */
248 while (bytecount < bsize) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200249#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
wdenk5d3207d2002-08-21 22:08:56 +0000250 if (ctrlc ()) {
251 (*fn->abort) (cookie);
252 return FPGA_FAIL;
253 }
254#endif
Wolfgang Denkffb77562005-09-24 23:41:00 +0200255
256 if ((*fn->done) (cookie) == FPGA_SUCCESS) {
257 PRINTF ("%s:%d:done went active early, bytecount = %d\n",
258 __FUNCTION__, __LINE__, bytecount);
259 break;
260 }
261
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200262#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
wdenk5d3207d2002-08-21 22:08:56 +0000263 if ((*fn->init) (cookie)) {
Wolfgang Denkffb77562005-09-24 23:41:00 +0200264 printf ("\n%s:%d: ** Error: INIT asserted during"
wdenk5d3207d2002-08-21 22:08:56 +0000265 " configuration\n", __FUNCTION__, __LINE__);
Wolfgang Denkffb77562005-09-24 23:41:00 +0200266 printf ("%d = buffer offset, %d = buffer size\n",
267 bytecount, bsize);
wdenk5d3207d2002-08-21 22:08:56 +0000268 (*fn->abort) (cookie);
269 return FPGA_FAIL;
270 }
271#endif
Wolfgang Denkffb77562005-09-24 23:41:00 +0200272
York Sun4a598092013-04-01 11:29:11 -0700273 (*fn->wdata) (data[bytecount++], true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000274 CONFIG_FPGA_DELAY ();
275
276 /*
277 * Cycle the clock pin
278 */
York Sun4a598092013-04-01 11:29:11 -0700279 (*fn->clk) (false, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000280 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700281 (*fn->clk) (true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000282
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200283#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
wdenk5d3207d2002-08-21 22:08:56 +0000284 ts = get_timer (0);
285 while ((*fn->busy) (cookie)) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200286 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_BUSY) {
Wolfgang Denkffb77562005-09-24 23:41:00 +0200287 printf ("%s:%d: ** Timeout after %d ticks waiting for"
wdenk5d3207d2002-08-21 22:08:56 +0000288 " BUSY to deassert\n",
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200289 __FUNCTION__, __LINE__, CONFIG_SYS_FPGA_WAIT_BUSY);
wdenk5d3207d2002-08-21 22:08:56 +0000290 (*fn->abort) (cookie);
291 return FPGA_FAIL;
292 }
293 }
294#endif
295
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200296#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk5d3207d2002-08-21 22:08:56 +0000297 if (bytecount % (bsize / 40) == 0)
298 putc ('.');
299#endif
300 }
301
302 /*
303 * Finished writing the data; deassert FPGA CS_B and WRITE_B signals.
304 */
305 CONFIG_FPGA_DELAY ();
York Sun4a598092013-04-01 11:29:11 -0700306 (*fn->cs) (false, true, cookie);
307 (*fn->wr) (false, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000308
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200309#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk5d3207d2002-08-21 22:08:56 +0000310 putc ('\n');
311#endif
312
313 /*
314 * Check for successful configuration. FPGA INIT_B and DONE should
315 * both be high upon successful configuration.
316 */
317 ts = get_timer (0);
318 ret_val = FPGA_SUCCESS;
319 while (((*fn->done) (cookie) == FPGA_FAIL) || (*fn->init) (cookie)) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200320 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_CONFIG) {
Wolfgang Denkffb77562005-09-24 23:41:00 +0200321 printf ("%s:%d: ** Timeout after %d ticks waiting for DONE to"
wdenk5d3207d2002-08-21 22:08:56 +0000322 "assert and INIT to deassert\n",
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200323 __FUNCTION__, __LINE__, CONFIG_SYS_FPGA_WAIT_CONFIG);
wdenk5d3207d2002-08-21 22:08:56 +0000324 (*fn->abort) (cookie);
325 ret_val = FPGA_FAIL;
326 break;
327 }
328 }
329
330 if (ret_val == FPGA_SUCCESS) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200331#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk5d3207d2002-08-21 22:08:56 +0000332 printf ("Initialization of FPGA device %d complete\n", cookie);
333#endif
334 /*
335 * Run the post configuration function if there is one.
336 */
337 if (*fn->post) {
338 (*fn->post) (cookie);
339 }
340 } else {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200341#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk5d3207d2002-08-21 22:08:56 +0000342 printf ("** Initialization of FPGA device %d FAILED\n",
343 cookie);
344#endif
345 }
346 } else {
347 printf ("%s:%d: NULL Interface function table!\n",
348 __FUNCTION__, __LINE__);
349 }
350 return ret_val;
351}
352
353/*
354 * Read the FPGA configuration data
355 */
Michal Simek25e1e2e2014-03-13 12:49:21 +0100356static int virtex2_ssm_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000357{
358 int ret_val = FPGA_FAIL;
Michal Simek90258882014-03-13 11:33:36 +0100359 xilinx_virtex2_slave_selectmap_fns *fn = desc->iface_fns;
wdenk5d3207d2002-08-21 22:08:56 +0000360
361 if (fn) {
362 unsigned char *data = (unsigned char *) buf;
363 size_t bytecount = 0;
364 int cookie = desc->cookie;
365
366 printf ("Starting Dump of FPGA Device %d...\n", cookie);
367
York Sun4a598092013-04-01 11:29:11 -0700368 (*fn->cs) (true, true, cookie);
369 (*fn->clk) (true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000370
371 while (bytecount < bsize) {
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200372#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
wdenk5d3207d2002-08-21 22:08:56 +0000373 if (ctrlc ()) {
374 (*fn->abort) (cookie);
375 return FPGA_FAIL;
376 }
377#endif
378 /*
379 * Cycle the clock and read the data
380 */
York Sun4a598092013-04-01 11:29:11 -0700381 (*fn->clk) (false, true, cookie);
382 (*fn->clk) (true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000383 (*fn->rdata) (&(data[bytecount++]), cookie);
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200384#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk5d3207d2002-08-21 22:08:56 +0000385 if (bytecount % (bsize / 40) == 0)
386 putc ('.');
387#endif
388 }
389
390 /*
391 * Deassert CS_B and cycle the clock to deselect the device.
392 */
York Sun4a598092013-04-01 11:29:11 -0700393 (*fn->cs) (false, false, cookie);
394 (*fn->clk) (false, true, cookie);
395 (*fn->clk) (true, true, cookie);
wdenk5d3207d2002-08-21 22:08:56 +0000396
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200397#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
wdenk5d3207d2002-08-21 22:08:56 +0000398 putc ('\n');
399#endif
400 puts ("Done.\n");
401 } else {
402 printf ("%s:%d: NULL Interface function table!\n",
403 __FUNCTION__, __LINE__);
404 }
405 return ret_val;
406}
407
Michal Simek25e1e2e2014-03-13 12:49:21 +0100408static int virtex2_ss_load(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000409{
410 printf ("%s: Slave Serial Loading is unsupported\n", __FUNCTION__);
411 return FPGA_FAIL;
412}
413
Michal Simek25e1e2e2014-03-13 12:49:21 +0100414static int virtex2_ss_dump(xilinx_desc *desc, const void *buf, size_t bsize)
wdenk5d3207d2002-08-21 22:08:56 +0000415{
416 printf ("%s: Slave Serial Dumping is unsupported\n", __FUNCTION__);
417 return FPGA_FAIL;
418}
419
wdenk5d3207d2002-08-21 22:08:56 +0000420/* vim: set ts=4 tw=78: */
Michal Simek75fafac2014-03-13 13:07:57 +0100421
422struct xilinx_fpga_op virtex2_op = {
423 .load = virtex2_load,
424 .dump = virtex2_dump,
425 .info = virtex2_info,
426};