source: SVN/rincon/u-boot/board/w7o/fpga.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: 10.5 KB
Line 
1/*
2 * (C) Copyright 2001
3 * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
4 *  and
5 * Bill Hunter, Wave 7 Optics, william.hunter@mediaone.net
6 *
7 * See file CREDITS for list of people who contributed to this
8 * project.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 */
25#include <config.h>
26#include <common.h>
27#include "w7o.h"
28#include <asm/processor.h>
29#include "errors.h"
30
31static void
32fpga_img_write(unsigned long *src, unsigned long len, unsigned short *daddr)
33{
34    unsigned long i;
35    volatile unsigned long val;
36    volatile unsigned short *dest = daddr;      /* volatile-bypass optimizer */
37
38    for (i = 0; i < len; i++, src++) {
39        val = *src;
40        *dest = (unsigned short)((val & 0xff000000L) >> 16);
41        *dest = (unsigned short)((val & 0x00ff0000L) >> 8);
42        *dest = (unsigned short)(val & 0x0000ff00L);
43        *dest = (unsigned short)((val & 0x000000ffL) << 8);
44    }
45
46    /* Terminate programming with 4 C clocks */
47    dest = daddr;
48    val = *(unsigned short *)dest;
49    val = *(unsigned short *)dest;
50    val = *(unsigned short *)dest;
51    val = *(unsigned short *)dest;
52
53}
54
55
56int
57fpgaDownload(unsigned char *saddr,
58             unsigned long size,
59             unsigned short *daddr)
60{
61    int i;                                      /* index, intr disable flag */
62    int start;                                  /* timer */
63    unsigned long greg, grego;                  /* GPIO & output register */
64    unsigned long length;                       /* image size in words */
65    unsigned long *source;                      /* image source addr */
66    unsigned short *dest;                       /* destination FPGA addr */
67    volatile unsigned short *ndest;             /* temp dest FPGA addr */
68    volatile unsigned short val;                /* temp val */
69    unsigned long cnfg = GPIO_XCV_CNFG;         /* FPGA CNFG */
70    unsigned long eirq = GPIO_XCV_IRQ;
71    int retval = -1;                            /* Function return value */
72
73    /* Setup some basic values */
74    length = (size / 4) + 1;                    /* size in words, rounding UP
75                                                    is OK */
76    source = (unsigned long *)saddr;
77    dest = (unsigned short *)daddr;
78
79    /* Get DCR output register */
80    grego = in32(PPC405GP_GPIO0_OR);
81
82    /* Reset FPGA */
83    grego &= ~GPIO_XCV_PROG;                    /* PROG line low */
84    out32(PPC405GP_GPIO0_OR, grego);
85
86    /* Setup timeout timer */
87    start = get_timer(0);
88
89    /* Wait for FPGA init line */
90    while(in32(PPC405GP_GPIO0_IR) & GPIO_XCV_INIT) { /* Wait INIT line low */
91        /* Check for timeout - 100us max, so use 3ms */
92        if (get_timer(start) > 3) {
93            printf("     failed to start init.\n");
94            log_warn(ERR_XINIT0);               /* Don't halt */
95
96            /* Reset line stays low */
97            goto done;                          /* I like gotos... */
98        }
99    }
100
101    /* Unreset FPGA */
102    grego |= GPIO_XCV_PROG;                     /* PROG line high */
103    out32(PPC405GP_GPIO0_OR, grego);
104
105    /* Wait for FPGA end of init period .  */
106    while(!(in32(PPC405GP_GPIO0_IR) & GPIO_XCV_INIT)) { /* Wait for INIT hi */
107
108        /* Check for timeout */
109        if (get_timer(start) > 3) {
110            printf("     failed to exit init.\n");
111            log_warn(ERR_XINIT1);
112
113            /* Reset FPGA */
114            grego &= ~GPIO_XCV_PROG;            /* PROG line low */
115            out32(PPC405GP_GPIO0_OR, grego);
116
117            goto done;
118        }
119    }
120
121    /* Now program FPGA ... */
122    ndest = dest;
123    for (i = 0; i < CONFIG_NUM_FPGAS; i++) {
124        /* Toggle IRQ/GPIO */
125        greg = mfdcr(CPC0_CR0);                 /* get chip ctrl register */
126        greg |= eirq;                           /* toggle irq/gpio */
127        mtdcr(CPC0_CR0, greg);                  /*  ... just do it */
128
129        /* turn on open drain for CNFG */
130        greg = in32(PPC405GP_GPIO0_ODR);        /* get open drain register */
131        greg |= cnfg;                           /* CNFG open drain */
132        out32(PPC405GP_GPIO0_ODR, greg);        /*  .. just do it */
133
134        /* Turn output enable on for CNFG */
135        greg = in32(PPC405GP_GPIO0_TCR);        /* get tristate register */
136        greg |= cnfg;                           /* CNFG tristate inactive */
137        out32(PPC405GP_GPIO0_TCR, greg);        /*  ... just do it */
138
139        /* Setup FPGA for programming */
140        grego &= ~cnfg;                         /* CONFIG line low */
141        out32(PPC405GP_GPIO0_OR, grego);
142
143        /*
144         * Program the FPGA
145         */
146        printf("\n       destination: 0x%lx ", (unsigned long)ndest);
147
148        fpga_img_write(source,  length,  (unsigned short *)ndest);
149
150        /* Done programming */
151        grego |= cnfg;                          /* CONFIG line high */
152        out32(PPC405GP_GPIO0_OR, grego);
153
154        /* Turn output enable OFF for CNFG */
155        greg = in32(PPC405GP_GPIO0_TCR);        /* get tristate register */
156        greg &= ~cnfg;                          /* CNFG tristate inactive */
157        out32(PPC405GP_GPIO0_TCR, greg);        /*  ... just do it */
158
159        /* Toggle IRQ/GPIO */
160        greg = mfdcr(CPC0_CR0);                 /* get chip ctrl register */
161        greg &= ~eirq;                          /* toggle irq/gpio */
162        mtdcr(CPC0_CR0, greg);                  /*  ... just do it */
163
164        ndest = (unsigned short *)((char *)ndest + 0x00100000L); /* XXX - Next FPGA addr */
165        cnfg >>= 1;                             /* XXX - Next  */
166        eirq >>= 1;
167    }
168
169    /* Terminate programming with 4 C clocks */
170    ndest = dest;
171    for (i = 0; i < CONFIG_NUM_FPGAS; i++) {
172        val = *ndest;
173        val = *ndest;
174        val = *ndest;
175        val = *ndest;
176        ndest = (unsigned short *)((char *)ndest + 0x00100000L);
177    }
178
179    /* Setup timer */
180    start = get_timer(0);
181
182    /* Wait for FPGA end of programming period .  */
183    while(!(in32(PPC405GP_GPIO0_IR) & GPIO_XCV_DONE)) { /* Test DONE low */
184
185        /* Check for timeout */
186        if (get_timer(start) > 3) {
187            printf("     done failed to come high.\n");
188            log_warn(ERR_XDONE1);
189
190            /* Reset FPGA */
191            grego &= ~GPIO_XCV_PROG;            /* PROG line low */
192            out32(PPC405GP_GPIO0_OR, grego);
193
194            goto done;
195        }
196    }
197
198    printf("\n       FPGA load succeeded\n");
199    retval = 0;                                 /* Program OK */
200
201done:
202    return retval;
203}
204
205/* FPGA image is stored in flash */
206extern flash_info_t    flash_info[];
207
208int init_fpga(void)
209{
210    unsigned int i,j,ptr;                       /* General purpose */
211    unsigned char bufchar;                      /* General purpose character */
212    unsigned char *buf;                         /* Start of image pointer */
213    unsigned long len;                          /* Length of image */
214    unsigned char *fn_buf;                      /* Start of filename string */
215    unsigned int fn_len;                        /* Length of filename string */
216    unsigned char *xcv_buf;                     /* Pointer to start of image */
217    unsigned long xcv_len;                      /* Length of image */
218    unsigned long crc;                          /* 30bit crc in image */
219    unsigned long calc_crc;                     /* Calc'd 30bit crc */
220    int retval = -1;
221
222    /* Tell the world what we are doing */
223    printf("FPGA:  ");
224
225    /*
226     * Get address of first sector where the FPGA
227     * image is stored.
228     */
229    buf = (unsigned char *)flash_info[1].start[0];
230
231    /*
232     * Get the stored image's CRC & length.
233     */
234    crc = *(unsigned long *)(buf+4);            /* CRC is first long word */
235    len = *(unsigned long *)(buf+8);            /* Image len is next long */
236
237    /* Pedantic */
238    if ((len < 0x133A4) || (len > 0x80000))
239        goto bad_image;
240
241    /*
242     * Get the file name pointer and length.
243     */
244    fn_len = (*(unsigned short *)(buf+12) & 0xff); /* filename length
245                                                      is next short */
246    fn_buf = buf + 14;
247
248    /*
249     * Get the FPGA image pointer and length length.
250     */
251    xcv_buf = fn_buf + fn_len;                  /* pointer to fpga image */
252    xcv_len = len - 14 - fn_len;                /* fpga image length */
253
254    /* Check for uninitialized FLASH */
255    if ((strncmp((char *)buf, "w7o", 3)!=0) || (len > 0x0007ffffL) || (len == 0))
256        goto bad_image;
257
258    /*
259     * Calculate and Check the image's CRC.
260     */
261    calc_crc = crc32(0, xcv_buf, xcv_len);
262    if (crc != calc_crc) {
263        printf("\nfailed - bad CRC\n");
264        goto done;
265    }
266
267    /* Output the file name */
268    printf("file name  : ");
269    for (i=0;i<fn_len;i++) {
270        bufchar = fn_buf[+i];
271        if (bufchar<' ' || bufchar>'~') bufchar = '.';
272        putc(bufchar);
273    }
274
275    /*
276     * find rest of display data
277     */
278    ptr = 15;                                   /* Offset to ncd filename
279                                                   length in fpga image */
280    j = xcv_buf[ptr];                           /* Get len of ncd filename */
281    if (j > 32) goto bad_image;
282    ptr = ptr + j + 3;                          /* skip ncd filename string +
283                                                   3 bytes more bytes */
284
285    /*
286     * output target device string
287     */
288    j = xcv_buf[ptr++] - 1;                     /* len of targ str less term */
289    if (j > 32) goto bad_image;
290    printf("\n       target     : ");
291    for (i = 0; i < j; i++) {
292        bufchar = (xcv_buf[ptr++]);
293        if (bufchar<' ' || bufchar>'~') bufchar = '.';
294        putc(bufchar);
295    }
296
297    /*
298     * output compilation date string and time string
299     */
300    ptr += 3;                                   /* skip 2 bytes */
301    printf("\n       synth time : ");
302    j = (xcv_buf[ptr++] - 1);                   /* len of date str less term */
303    if (j > 32) goto bad_image;
304    for (i = 0; i < j; i++) {
305        bufchar = (xcv_buf[ptr++]);
306        if (bufchar<' ' || bufchar>'~') bufchar = '.';
307        putc(bufchar);
308    }
309
310    ptr += 3;                                   /* Skip 2 bytes */
311    printf(" - ");
312    j = (xcv_buf[ptr++] - 1);                   /* slen = targ dev str len */
313    if (j > 32) goto bad_image;
314    for (i = 0; i < j; i++) {
315        bufchar = (xcv_buf[ptr++]);
316        if (bufchar<' ' || bufchar>'~') bufchar = '.';
317        putc(bufchar);
318    }
319
320    /*
321     * output crc and length strings
322     */
323    printf("\n       len & crc  : 0x%lx  0x%lx", len, crc);
324
325    /*
326     * Program the FPGA.
327     */
328    retval = fpgaDownload((unsigned char*)xcv_buf, xcv_len,
329                          (unsigned short *)0xfd000000L);
330    return retval;
331
332bad_image:
333    printf("\n       BAD FPGA image format @ %lx\n", flash_info[1].start[0]);
334    log_warn(ERR_XIMAGE);
335done:
336    return retval;
337}
338
339void test_fpga(unsigned short *daddr)
340{
341    int i;
342    volatile unsigned short *ndest = daddr;
343
344    for (i = 0; i < CONFIG_NUM_FPGAS; i++) {
345#if defined(CONFIG_W7OLMG)
346        ndest[0x7e] = 0x55aa;
347        if (ndest[0x7e] != 0x55aa)
348            log_warn(ERR_XRW1 + i);
349        ndest[0x7e] = 0xaa55;
350        if (ndest[0x7e] != 0xaa55)
351            log_warn(ERR_XRW1 + i);
352        ndest[0x7e] = 0xc318;
353        if (ndest[0x7e] != 0xc318)
354            log_warn(ERR_XRW1 + i);
355
356#elif defined(CONFIG_W7OLMC)
357        ndest[0x800] = 0x55aa;
358        ndest[0x801] = 0xaa55;
359        ndest[0x802] = 0xc318;
360        ndest[0x4800] = 0x55aa;
361        ndest[0x4801] = 0xaa55;
362        ndest[0x4802] = 0xc318;
363        if ((ndest[0x800] != 0x55aa) ||
364            (ndest[0x801] != 0xaa55) ||
365            (ndest[0x802] != 0xc318))
366            log_warn(ERR_XRW1 + (2 * i));       /* Auto gen error code */
367        if ((ndest[0x4800] != 0x55aa) ||
368            (ndest[0x4801] != 0xaa55) ||
369            (ndest[0x4802] != 0xc318))
370            log_warn(ERR_XRW2 + (2 * i));       /* Auto gen error code */
371
372#else
373# error "Unknown W7O board configuration"
374#endif
375    }
376
377    printf("       FPGA ready\n");
378    return;
379}
Note: See TracBrowser for help on using the repository browser.