source: SVN/rincon/u-boot/common/virtex2.c @ 55

Last change on this file since 55 was 55, checked in by Tim Harvey, 2 years ago

rincon: added latest u-boot source

restored form server backup

Signed-off-by: Tim Harvey <tharvey@…>

File size: 14.8 KB
Line 
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
34#if 0
35#define FPGA_DEBUG
36#endif
37
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
46 * CFG_FPGA_CHECK_BUSY and/or CONFIG_FPGA_DELAY in the board configuration
47 * file and add board-specific support for checking BUSY status. By default,
48 * assume that the SelectMap interface cannot be overrun.
49 */
50#ifndef CFG_FPGA_CHECK_BUSY
51#undef CFG_FPGA_CHECK_BUSY
52#endif
53
54#ifndef CONFIG_FPGA_DELAY
55#define CONFIG_FPGA_DELAY()
56#endif
57
58#ifndef CFG_FPGA_PROG_FEEDBACK
59#define CFG_FPGA_PROG_FEEDBACK
60#endif
61
62/*
63 * Don't allow config cycle to be interrupted
64 */
65#ifndef CFG_FPGA_CHECK_CTRLC
66#undef CFG_FPGA_CHECK_CTRLC
67#endif
68
69/*
70 * Check for errors during configuration by default
71 */
72#ifndef CFG_FPGA_CHECK_ERROR
73#define CFG_FPGA_CHECK_ERROR
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 */
84#ifndef CFG_FPGA_WAIT_INIT
85#define CFG_FPGA_WAIT_INIT      CFG_HZ/2        /* 500 ms */
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 */
93#ifndef CFG_FPGA_WAIT_BUSY
94#define CFG_FPGA_WAIT_BUSY      CFG_HZ/200      /* 5 ms*/
95#endif
96
97/* Default timeout for waiting for FPGA to enter operational mode after
98 * configuration data has been written.
99 */
100#ifndef CFG_FPGA_WAIT_CONFIG
101#define CFG_FPGA_WAIT_CONFIG    CFG_HZ/5        /* 200 ms */
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
195 *    could, for instance, put this in your 'abort' function handler).
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
235#ifdef CFG_FPGA_PROG_FEEDBACK
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 {
255                        if (get_timer (ts) > CFG_FPGA_WAIT_INIT) {
256                                printf ("%s:%d: ** Timeout after %d ticks waiting for INIT"
257                                                " to assert.\n", __FUNCTION__, __LINE__,
258                                                CFG_FPGA_WAIT_INIT);
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 ();
274                        if (get_timer (ts) > CFG_FPGA_WAIT_INIT) {
275                                printf ("%s:%d: ** Timeout after %d ticks waiting for INIT"
276                                                " to deassert.\n", __FUNCTION__, __LINE__,
277                                                CFG_FPGA_WAIT_INIT);
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) {
292#ifdef CFG_FPGA_CHECK_CTRLC
293                        if (ctrlc ()) {
294                                (*fn->abort) (cookie);
295                                return FPGA_FAIL;
296                        }
297#endif
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
305#ifdef CFG_FPGA_CHECK_ERROR
306                        if ((*fn->init) (cookie)) {
307                                printf ("\n%s:%d:  ** Error: INIT asserted during"
308                                                " configuration\n", __FUNCTION__, __LINE__);
309                                printf ("%d = buffer offset, %d = buffer size\n",
310                                        bytecount, bsize);
311                                (*fn->abort) (cookie);
312                                return FPGA_FAIL;
313                        }
314#endif
315
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
326#ifdef CFG_FPGA_CHECK_BUSY
327                        ts = get_timer (0);
328                        while ((*fn->busy) (cookie)) {
329                                if (get_timer (ts) > CFG_FPGA_WAIT_BUSY) {
330                                        printf ("%s:%d: ** Timeout after %d ticks waiting for"
331                                                        " BUSY to deassert\n",
332                                                        __FUNCTION__, __LINE__, CFG_FPGA_WAIT_BUSY);
333                                        (*fn->abort) (cookie);
334                                        return FPGA_FAIL;
335                                }
336                        }
337#endif
338
339#ifdef CFG_FPGA_PROG_FEEDBACK
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
352#ifdef CFG_FPGA_PROG_FEEDBACK
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)) {
363                        if (get_timer (ts) > CFG_FPGA_WAIT_CONFIG) {
364                                printf ("%s:%d: ** Timeout after %d ticks waiting for DONE to"
365                                                "assert and INIT to deassert\n",
366                                                __FUNCTION__, __LINE__, CFG_FPGA_WAIT_CONFIG);
367                                (*fn->abort) (cookie);
368                                ret_val = FPGA_FAIL;
369                                break;
370                        }
371                }
372
373                if (ret_val == FPGA_SUCCESS) {
374#ifdef CFG_FPGA_PROG_FEEDBACK
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 {
384#ifdef CFG_FPGA_PROG_FEEDBACK
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) {
415#ifdef CFG_FPGA_CHECK_CTRLC
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);
427#ifdef CFG_FPGA_PROG_FEEDBACK
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
440#ifdef CFG_FPGA_PROG_FEEDBACK
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}
553
554/* vim: set ts=4 tw=78: */
Note: See TracBrowser for help on using the repository browser.