]> git.ipfire.org Git - people/ms/u-boot.git/blame - common/virtex2.c
rename CFG_ macros to CONFIG_SYS
[people/ms/u-boot.git] / common / virtex2.c
CommitLineData
5d3207da
WD
1/*
2 * (C) Copyright 2002
3 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
4 * Keith Outwater, keith_outwater@mvis.com
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 *
24 */
25
26/*
27 * Configuration support for Xilinx Virtex2 devices. Based
28 * on spartan2.c (Rich Ireland, rireland@enterasys.com).
29 */
30
31#include <common.h>
32#include <virtex2.h>
33
9a9200b4
WD
34#if 0
35#define FPGA_DEBUG
265817c7 36#endif
9a9200b4 37
5d3207da
WD
38#ifdef FPGA_DEBUG
39#define PRINTF(fmt,args...) printf (fmt ,##args)
40#else
41#define PRINTF(fmt,args...)
42#endif
43
44/*
45 * If the SelectMap interface can be overrun by the processor, define
6d0f6bcf 46 * CONFIG_SYS_FPGA_CHECK_BUSY and/or CONFIG_FPGA_DELAY in the board configuration
5d3207da
WD
47 * file and add board-specific support for checking BUSY status. By default,
48 * assume that the SelectMap interface cannot be overrun.
49 */
6d0f6bcf
JCPV
50#ifndef CONFIG_SYS_FPGA_CHECK_BUSY
51#undef CONFIG_SYS_FPGA_CHECK_BUSY
5d3207da
WD
52#endif
53
54#ifndef CONFIG_FPGA_DELAY
55#define CONFIG_FPGA_DELAY()
56#endif
57
6d0f6bcf
JCPV
58#ifndef CONFIG_SYS_FPGA_PROG_FEEDBACK
59#define CONFIG_SYS_FPGA_PROG_FEEDBACK
5d3207da
WD
60#endif
61
62/*
63 * Don't allow config cycle to be interrupted
64 */
6d0f6bcf
JCPV
65#ifndef CONFIG_SYS_FPGA_CHECK_CTRLC
66#undef CONFIG_SYS_FPGA_CHECK_CTRLC
5d3207da
WD
67#endif
68
69/*
70 * Check for errors during configuration by default
71 */
6d0f6bcf
JCPV
72#ifndef CONFIG_SYS_FPGA_CHECK_ERROR
73#define CONFIG_SYS_FPGA_CHECK_ERROR
5d3207da
WD
74#endif
75
76/*
77 * The default timeout in mS for INIT_B to deassert after PROG_B has
78 * been deasserted. Per the latest Virtex II Handbook (page 347), the
79 * max time from PORG_B deassertion to INIT_B deassertion is 4uS per
80 * data frame for the XC2V8000. The XC2V8000 has 2860 data frames
81 * which yields 11.44 mS. So let's make it bigger in order to handle
82 * an XC2V1000, if anyone can ever get ahold of one.
83 */
6d0f6bcf
JCPV
84#ifndef CONFIG_SYS_FPGA_WAIT_INIT
85#define CONFIG_SYS_FPGA_WAIT_INIT CONFIG_SYS_HZ/2 /* 500 ms */
5d3207da
WD
86#endif
87
88/*
89 * The default timeout for waiting for BUSY to deassert during configuration.
90 * This is normally not necessary since for most reasonable configuration
91 * clock frequencies (i.e. 66 MHz or less), BUSY monitoring is unnecessary.
92 */
6d0f6bcf
JCPV
93#ifndef CONFIG_SYS_FPGA_WAIT_BUSY
94#define CONFIG_SYS_FPGA_WAIT_BUSY CONFIG_SYS_HZ/200 /* 5 ms*/
5d3207da
WD
95#endif
96
97/* Default timeout for waiting for FPGA to enter operational mode after
98 * configuration data has been written.
99 */
6d0f6bcf
JCPV
100#ifndef CONFIG_SYS_FPGA_WAIT_CONFIG
101#define CONFIG_SYS_FPGA_WAIT_CONFIG CONFIG_SYS_HZ/5 /* 200 ms */
5d3207da
WD
102#endif
103
104static int Virtex2_ssm_load (Xilinx_desc * desc, void *buf, size_t bsize);
105static int Virtex2_ssm_dump (Xilinx_desc * desc, void *buf, size_t bsize);
106static int Virtex2_ssm_reloc (Xilinx_desc * desc, ulong reloc_offset);
107
108static int Virtex2_ss_load (Xilinx_desc * desc, void *buf, size_t bsize);
109static int Virtex2_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize);
110static int Virtex2_ss_reloc (Xilinx_desc * desc, ulong reloc_offset);
111
112int Virtex2_load (Xilinx_desc * desc, void *buf, size_t bsize)
113{
114 int ret_val = FPGA_FAIL;
115
116 switch (desc->iface) {
117 case slave_serial:
118 PRINTF ("%s: Launching Slave Serial Load\n", __FUNCTION__);
119 ret_val = Virtex2_ss_load (desc, buf, bsize);
120 break;
121
122 case slave_selectmap:
123 PRINTF ("%s: Launching Slave Parallel Load\n", __FUNCTION__);
124 ret_val = Virtex2_ssm_load (desc, buf, bsize);
125 break;
126
127 default:
128 printf ("%s: Unsupported interface type, %d\n",
129 __FUNCTION__, desc->iface);
130 }
131 return ret_val;
132}
133
134int Virtex2_dump (Xilinx_desc * desc, void *buf, size_t bsize)
135{
136 int ret_val = FPGA_FAIL;
137
138 switch (desc->iface) {
139 case slave_serial:
140 PRINTF ("%s: Launching Slave Serial Dump\n", __FUNCTION__);
141 ret_val = Virtex2_ss_dump (desc, buf, bsize);
142 break;
143
144 case slave_parallel:
145 PRINTF ("%s: Launching Slave Parallel Dump\n", __FUNCTION__);
146 ret_val = Virtex2_ssm_dump (desc, buf, bsize);
147 break;
148
149 default:
150 printf ("%s: Unsupported interface type, %d\n",
151 __FUNCTION__, desc->iface);
152 }
153 return ret_val;
154}
155
156int Virtex2_info (Xilinx_desc * desc)
157{
158 return FPGA_SUCCESS;
159}
160
161int Virtex2_reloc (Xilinx_desc * desc, ulong reloc_offset)
162{
163 int ret_val = FPGA_FAIL;
164
165 if (desc->family != Xilinx_Virtex2) {
166 printf ("%s: Unsupported family type, %d\n",
167 __FUNCTION__, desc->family);
168 return FPGA_FAIL;
169 } else
170 switch (desc->iface) {
171 case slave_serial:
172 ret_val = Virtex2_ss_reloc (desc, reloc_offset);
173 break;
174
175 case slave_selectmap:
176 ret_val = Virtex2_ssm_reloc (desc, reloc_offset);
177 break;
178
179 default:
180 printf ("%s: Unsupported interface type, %d\n",
181 __FUNCTION__, desc->iface);
182 }
183 return ret_val;
184}
185
186/*
187 * Virtex-II Slave SelectMap configuration loader. Configuration via
188 * SelectMap is as follows:
189 * 1. Set the FPGA's PROG_B line low.
190 * 2. Set the FPGA's PROG_B line high. Wait for INIT_B to go high.
191 * 3. Write data to the SelectMap port. If INIT_B goes low at any time
192 * this process, a configuration error (most likely CRC failure) has
193 * ocurred. At this point a status word may be read from the
194 * SelectMap interface to determine the source of the problem (You
9a9200b4 195 * could, for instance, put this in your 'abort' function handler).
5d3207da
WD
196 * 4. After all data has been written, test the state of the FPGA
197 * INIT_B and DONE lines. If both are high, configuration has
198 * succeeded. Congratulations!
199 */
200static int Virtex2_ssm_load (Xilinx_desc * desc, void *buf, size_t bsize)
201{
202 int ret_val = FPGA_FAIL;
203 Xilinx_Virtex2_Slave_SelectMap_fns *fn = desc->iface_fns;
204
205 PRINTF ("%s:%d: Start with interface functions @ 0x%p\n",
206 __FUNCTION__, __LINE__, fn);
207
208 if (fn) {
209 size_t bytecount = 0;
210 unsigned char *data = (unsigned char *) buf;
211 int cookie = desc->cookie;
212 unsigned long ts;
213
214 /* Gotta split this one up (so the stack won't blow??) */
215 PRINTF ("%s:%d: Function Table:\n"
216 " base 0x%p\n"
217 " struct 0x%p\n"
218 " pre 0x%p\n"
219 " prog 0x%p\n"
220 " init 0x%p\n"
221 " error 0x%p\n",
222 __FUNCTION__, __LINE__,
223 &fn, fn, fn->pre, fn->pgm, fn->init, fn->err);
224 PRINTF (" clock 0x%p\n"
225 " cs 0x%p\n"
226 " write 0x%p\n"
227 " rdata 0x%p\n"
228 " wdata 0x%p\n"
229 " busy 0x%p\n"
230 " abort 0x%p\n"
231 " post 0x%p\n\n",
232 fn->clk, fn->cs, fn->wr, fn->rdata, fn->wdata,
233 fn->busy, fn->abort, fn->post);
234
6d0f6bcf 235#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
5d3207da
WD
236 printf ("Initializing FPGA Device %d...\n", cookie);
237#endif
238 /*
239 * Run the pre configuration function if there is one.
240 */
241 if (*fn->pre) {
242 (*fn->pre) (cookie);
243 }
244
245 /*
246 * Assert the program line. The minimum pulse width for
247 * Virtex II devices is 300 nS (Tprogram parameter in datasheet).
248 * There is no maximum value for the pulse width. Check to make
249 * sure that INIT_B goes low after assertion of PROG_B
250 */
251 (*fn->pgm) (TRUE, TRUE, cookie);
252 udelay (10);
253 ts = get_timer (0);
254 do {
6d0f6bcf 255 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_INIT) {
9a9200b4 256 printf ("%s:%d: ** Timeout after %d ticks waiting for INIT"
5d3207da 257 " to assert.\n", __FUNCTION__, __LINE__,
6d0f6bcf 258 CONFIG_SYS_FPGA_WAIT_INIT);
5d3207da
WD
259 (*fn->abort) (cookie);
260 return FPGA_FAIL;
261 }
262 } while (!(*fn->init) (cookie));
263
264 (*fn->pgm) (FALSE, TRUE, cookie);
265 CONFIG_FPGA_DELAY ();
266 (*fn->clk) (TRUE, TRUE, cookie);
267
268 /*
269 * Start a timer and wait for INIT_B to go high
270 */
271 ts = get_timer (0);
272 do {
273 CONFIG_FPGA_DELAY ();
6d0f6bcf 274 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_INIT) {
9a9200b4 275 printf ("%s:%d: ** Timeout after %d ticks waiting for INIT"
5d3207da 276 " to deassert.\n", __FUNCTION__, __LINE__,
6d0f6bcf 277 CONFIG_SYS_FPGA_WAIT_INIT);
5d3207da
WD
278 (*fn->abort) (cookie);
279 return FPGA_FAIL;
280 }
281 } while ((*fn->init) (cookie) && (*fn->busy) (cookie));
282
283 (*fn->wr) (TRUE, TRUE, cookie);
284 (*fn->cs) (TRUE, TRUE, cookie);
285
286 udelay (10000);
287
288 /*
289 * Load the data byte by byte
290 */
291 while (bytecount < bsize) {
6d0f6bcf 292#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
5d3207da
WD
293 if (ctrlc ()) {
294 (*fn->abort) (cookie);
295 return FPGA_FAIL;
296 }
297#endif
9a9200b4
WD
298
299 if ((*fn->done) (cookie) == FPGA_SUCCESS) {
300 PRINTF ("%s:%d:done went active early, bytecount = %d\n",
301 __FUNCTION__, __LINE__, bytecount);
302 break;
303 }
304
6d0f6bcf 305#ifdef CONFIG_SYS_FPGA_CHECK_ERROR
5d3207da 306 if ((*fn->init) (cookie)) {
9a9200b4 307 printf ("\n%s:%d: ** Error: INIT asserted during"
5d3207da 308 " configuration\n", __FUNCTION__, __LINE__);
9a9200b4
WD
309 printf ("%d = buffer offset, %d = buffer size\n",
310 bytecount, bsize);
5d3207da
WD
311 (*fn->abort) (cookie);
312 return FPGA_FAIL;
313 }
314#endif
9a9200b4 315
5d3207da
WD
316 (*fn->wdata) (data[bytecount++], TRUE, cookie);
317 CONFIG_FPGA_DELAY ();
318
319 /*
320 * Cycle the clock pin
321 */
322 (*fn->clk) (FALSE, TRUE, cookie);
323 CONFIG_FPGA_DELAY ();
324 (*fn->clk) (TRUE, TRUE, cookie);
325
6d0f6bcf 326#ifdef CONFIG_SYS_FPGA_CHECK_BUSY
5d3207da
WD
327 ts = get_timer (0);
328 while ((*fn->busy) (cookie)) {
6d0f6bcf 329 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_BUSY) {
9a9200b4 330 printf ("%s:%d: ** Timeout after %d ticks waiting for"
5d3207da 331 " BUSY to deassert\n",
6d0f6bcf 332 __FUNCTION__, __LINE__, CONFIG_SYS_FPGA_WAIT_BUSY);
5d3207da
WD
333 (*fn->abort) (cookie);
334 return FPGA_FAIL;
335 }
336 }
337#endif
338
6d0f6bcf 339#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
5d3207da
WD
340 if (bytecount % (bsize / 40) == 0)
341 putc ('.');
342#endif
343 }
344
345 /*
346 * Finished writing the data; deassert FPGA CS_B and WRITE_B signals.
347 */
348 CONFIG_FPGA_DELAY ();
349 (*fn->cs) (FALSE, TRUE, cookie);
350 (*fn->wr) (FALSE, TRUE, cookie);
351
6d0f6bcf 352#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
5d3207da
WD
353 putc ('\n');
354#endif
355
356 /*
357 * Check for successful configuration. FPGA INIT_B and DONE should
358 * both be high upon successful configuration.
359 */
360 ts = get_timer (0);
361 ret_val = FPGA_SUCCESS;
362 while (((*fn->done) (cookie) == FPGA_FAIL) || (*fn->init) (cookie)) {
6d0f6bcf 363 if (get_timer (ts) > CONFIG_SYS_FPGA_WAIT_CONFIG) {
9a9200b4 364 printf ("%s:%d: ** Timeout after %d ticks waiting for DONE to"
5d3207da 365 "assert and INIT to deassert\n",
6d0f6bcf 366 __FUNCTION__, __LINE__, CONFIG_SYS_FPGA_WAIT_CONFIG);
5d3207da
WD
367 (*fn->abort) (cookie);
368 ret_val = FPGA_FAIL;
369 break;
370 }
371 }
372
373 if (ret_val == FPGA_SUCCESS) {
6d0f6bcf 374#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
5d3207da
WD
375 printf ("Initialization of FPGA device %d complete\n", cookie);
376#endif
377 /*
378 * Run the post configuration function if there is one.
379 */
380 if (*fn->post) {
381 (*fn->post) (cookie);
382 }
383 } else {
6d0f6bcf 384#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
5d3207da
WD
385 printf ("** Initialization of FPGA device %d FAILED\n",
386 cookie);
387#endif
388 }
389 } else {
390 printf ("%s:%d: NULL Interface function table!\n",
391 __FUNCTION__, __LINE__);
392 }
393 return ret_val;
394}
395
396/*
397 * Read the FPGA configuration data
398 */
399static int Virtex2_ssm_dump (Xilinx_desc * desc, void *buf, size_t bsize)
400{
401 int ret_val = FPGA_FAIL;
402 Xilinx_Virtex2_Slave_SelectMap_fns *fn = desc->iface_fns;
403
404 if (fn) {
405 unsigned char *data = (unsigned char *) buf;
406 size_t bytecount = 0;
407 int cookie = desc->cookie;
408
409 printf ("Starting Dump of FPGA Device %d...\n", cookie);
410
411 (*fn->cs) (TRUE, TRUE, cookie);
412 (*fn->clk) (TRUE, TRUE, cookie);
413
414 while (bytecount < bsize) {
6d0f6bcf 415#ifdef CONFIG_SYS_FPGA_CHECK_CTRLC
5d3207da
WD
416 if (ctrlc ()) {
417 (*fn->abort) (cookie);
418 return FPGA_FAIL;
419 }
420#endif
421 /*
422 * Cycle the clock and read the data
423 */
424 (*fn->clk) (FALSE, TRUE, cookie);
425 (*fn->clk) (TRUE, TRUE, cookie);
426 (*fn->rdata) (&(data[bytecount++]), cookie);
6d0f6bcf 427#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
5d3207da
WD
428 if (bytecount % (bsize / 40) == 0)
429 putc ('.');
430#endif
431 }
432
433 /*
434 * Deassert CS_B and cycle the clock to deselect the device.
435 */
436 (*fn->cs) (FALSE, FALSE, cookie);
437 (*fn->clk) (FALSE, TRUE, cookie);
438 (*fn->clk) (TRUE, TRUE, cookie);
439
6d0f6bcf 440#ifdef CONFIG_SYS_FPGA_PROG_FEEDBACK
5d3207da
WD
441 putc ('\n');
442#endif
443 puts ("Done.\n");
444 } else {
445 printf ("%s:%d: NULL Interface function table!\n",
446 __FUNCTION__, __LINE__);
447 }
448 return ret_val;
449}
450
451/*
452 * Relocate the addresses in the function table from FLASH (or ROM,
453 * or whatever) to RAM.
454 */
455static int Virtex2_ssm_reloc (Xilinx_desc * desc, ulong reloc_offset)
456{
457 ulong addr;
458 int ret_val = FPGA_FAIL;
459 Xilinx_Virtex2_Slave_SelectMap_fns *fn_r, *fn =
460 (Xilinx_Virtex2_Slave_SelectMap_fns *) (desc->iface_fns);
461
462 if (fn) {
463 /*
464 * Get the relocated table address
465 */
466 addr = (ulong) fn + reloc_offset;
467 fn_r = (Xilinx_Virtex2_Slave_SelectMap_fns *) addr;
468
469 /*
470 * Check to see if the table has already been relocated. If not, do
471 * a sanity check to make sure there is a faithful copy of the
472 * FLASH based function table in RAM, then adjust the table.
473 */
474 if (!fn_r->relocated) {
475 if (memcmp
476 (fn_r, fn, sizeof (Xilinx_Virtex2_Slave_SelectMap_fns))
477 == 0) {
478 desc->iface_fns = fn_r;
479 } else {
480 PRINTF ("%s:%d: Invalid function table at 0x%p\n",
481 __FUNCTION__, __LINE__, fn_r);
482 return FPGA_FAIL;
483 }
484
485 PRINTF ("%s:%d: Relocating descriptor at 0x%p\n",
486 __FUNCTION__, __LINE__, desc);
487
488 addr = (ulong) (fn->pre) + reloc_offset;
489 fn_r->pre = (Xilinx_pre_fn) addr;
490 addr = (ulong) (fn->pgm) + reloc_offset;
491 fn_r->pgm = (Xilinx_pgm_fn) addr;
492 addr = (ulong) (fn->init) + reloc_offset;
493 fn_r->init = (Xilinx_init_fn) addr;
494 addr = (ulong) (fn->done) + reloc_offset;
495 fn_r->done = (Xilinx_done_fn) addr;
496 addr = (ulong) (fn->err) + reloc_offset;
497 fn_r->err = (Xilinx_err_fn) addr;
498 addr = (ulong) (fn->clk) + reloc_offset;
499 fn_r->clk = (Xilinx_clk_fn) addr;
500 addr = (ulong) (fn->cs) + reloc_offset;
501 fn_r->cs = (Xilinx_cs_fn) addr;
502 addr = (ulong) (fn->wr) + reloc_offset;
503 fn_r->wr = (Xilinx_wr_fn) addr;
504 addr = (ulong) (fn->rdata) + reloc_offset;
505 fn_r->rdata = (Xilinx_rdata_fn) addr;
506 addr = (ulong) (fn->wdata) + reloc_offset;
507 fn_r->wdata = (Xilinx_wdata_fn) addr;
508 addr = (ulong) (fn->busy) + reloc_offset;
509 fn_r->busy = (Xilinx_busy_fn) addr;
510 addr = (ulong) (fn->abort) + reloc_offset;
511 fn_r->abort = (Xilinx_abort_fn) addr;
512 addr = (ulong) (fn->post) + reloc_offset;
513 fn_r->post = (Xilinx_post_fn) addr;
514 fn_r->relocated = TRUE;
515 } else {
516 printf ("%s:%d: Function table @0x%p has already been relocated\n", __FUNCTION__, __LINE__, fn_r);
517 desc->iface_fns = fn_r;
518 }
519 ret_val = FPGA_SUCCESS;
520 } else {
521 printf ("%s: NULL Interface function table!\n", __FUNCTION__);
522 }
523 return ret_val;
524}
525
526static int Virtex2_ss_load (Xilinx_desc * desc, void *buf, size_t bsize)
527{
528 printf ("%s: Slave Serial Loading is unsupported\n", __FUNCTION__);
529 return FPGA_FAIL;
530}
531
532static int Virtex2_ss_dump (Xilinx_desc * desc, void *buf, size_t bsize)
533{
534 printf ("%s: Slave Serial Dumping is unsupported\n", __FUNCTION__);
535 return FPGA_FAIL;
536}
537
538static int Virtex2_ss_reloc (Xilinx_desc * desc, ulong reloc_offset)
539{
540 int ret_val = FPGA_FAIL;
541 Xilinx_Virtex2_Slave_Serial_fns *fn =
542 (Xilinx_Virtex2_Slave_Serial_fns *) (desc->iface_fns);
543
544 if (fn) {
545 printf ("%s:%d: Slave Serial Loading is unsupported\n",
546 __FUNCTION__, __LINE__);
547 } else {
548 printf ("%s:%d: NULL Interface function table!\n",
549 __FUNCTION__, __LINE__);
550 }
551 return ret_val;
552}
5d3207da
WD
553
554/* vim: set ts=4 tw=78: */