]> git.sur5r.net Git - u-boot/blob - board/w7o/fpga.c
powerpc/83xx/km: make local functions and structs static
[u-boot] / board / w7o / fpga.c
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 <linux/compiler.h>
30 #include "errors.h"
31
32 static void
33 fpga_img_write(unsigned long *src, unsigned long len, unsigned short *daddr)
34 {
35         unsigned long i;
36         volatile unsigned long val;
37         volatile unsigned short *dest = daddr;  /* volatile-bypass optimizer */
38
39         for (i = 0; i < len; i++, src++) {
40                 val = *src;
41                 *dest = (unsigned short) ((val & 0xff000000L) >> 16);
42                 *dest = (unsigned short) ((val & 0x00ff0000L) >> 8);
43                 *dest = (unsigned short) (val & 0x0000ff00L);
44                 *dest = (unsigned short) ((val & 0x000000ffL) << 8);
45         }
46
47         /* Terminate programming with 4 C clocks */
48         dest = daddr;
49         val = *(unsigned short *) dest;
50         val = *(unsigned short *) dest;
51         val = *(unsigned short *) dest;
52         val = *(unsigned short *) dest;
53
54 }
55
56
57 int
58 fpgaDownload(unsigned char *saddr, unsigned long size, unsigned short *daddr)
59 {
60         int i;                  /* index, intr disable flag */
61         int start;              /* timer */
62         unsigned long greg, grego;      /* GPIO & output register */
63         unsigned long length;   /* image size in words */
64         unsigned long *source;  /* image source addr */
65         unsigned short *dest;   /* destination FPGA addr */
66         volatile unsigned short *ndest; /* temp dest FPGA addr */
67         unsigned long cnfg = GPIO_XCV_CNFG;     /* FPGA CNFG */
68         unsigned long eirq = GPIO_XCV_IRQ;
69         int retval = -1;        /* Function return value */
70         __maybe_unused volatile unsigned short val;     /* temp val */
71
72         /* Setup some basic values */
73         length = (size / 4) + 1;        /* size in words, rounding UP
74                                            is OK */
75         source = (unsigned long *) saddr;
76         dest = (unsigned short *) daddr;
77
78         /* Get DCR output register */
79         grego = in32(PPC405GP_GPIO0_OR);
80
81         /* Reset FPGA */
82         grego &= ~GPIO_XCV_PROG;        /* PROG line low */
83         out32(PPC405GP_GPIO0_OR, grego);
84
85         /* Setup timeout timer */
86         start = get_timer(0);
87
88         /* Wait for FPGA init line to go low */
89         while (in32(PPC405GP_GPIO0_IR) & GPIO_XCV_INIT) {
90                 /* Check for timeout - 100us max, so use 3ms */
91                 if (get_timer(start) > 3) {
92                         printf("     failed to start init.\n");
93                         log_warn(ERR_XINIT0);   /* Don't halt */
94
95                         /* Reset line stays low */
96                         goto done;      /* I like gotos... */
97                 }
98         }
99
100         /* Unreset FPGA */
101         grego |= GPIO_XCV_PROG; /* PROG line high */
102         out32(PPC405GP_GPIO0_OR, grego);
103
104         /* Wait for FPGA end of init period = init line go hi  */
105         while (!(in32(PPC405GP_GPIO0_IR) & GPIO_XCV_INIT)) {
106
107                 /* Check for timeout */
108                 if (get_timer(start) > 3) {
109                         printf("     failed to exit init.\n");
110                         log_warn(ERR_XINIT1);
111
112                         /* Reset FPGA */
113                         grego &= ~GPIO_XCV_PROG;        /* PROG line low */
114                         out32(PPC405GP_GPIO0_OR, grego);
115
116                         goto done;
117                 }
118         }
119
120         /* Now program FPGA ... */
121         ndest = dest;
122         for (i = 0; i < CONFIG_NUM_FPGAS; i++) {
123                 /* Toggle IRQ/GPIO */
124                 greg = mfdcr(CPC0_CR0); /* get chip ctrl register */
125                 greg |= eirq;   /* toggle irq/gpio */
126                 mtdcr(CPC0_CR0, greg);  /*  ... just do it */
127
128                 /* turn on open drain for CNFG */
129                 greg = in32(PPC405GP_GPIO0_ODR); /* get open drain register */
130                 greg |= cnfg;   /* CNFG open drain */
131                 out32(PPC405GP_GPIO0_ODR, greg); /*  .. just do it */
132
133                 /* Turn output enable on for CNFG */
134                 greg = in32(PPC405GP_GPIO0_TCR); /* get tristate register */
135                 greg |= cnfg;   /* CNFG tristate inactive */
136                 out32(PPC405GP_GPIO0_TCR, greg); /*  ... just do it */
137
138                 /* Setup FPGA for programming */
139                 grego &= ~cnfg; /* CONFIG line low */
140                 out32(PPC405GP_GPIO0_OR, grego);
141
142                 /*
143                  * Program the FPGA
144                  */
145                 printf("\n       destination: 0x%lx ", (unsigned long) ndest);
146
147                 fpga_img_write(source, length, (unsigned short *) ndest);
148
149                 /* Done programming */
150                 grego |= cnfg;  /* CONFIG line high */
151                 out32(PPC405GP_GPIO0_OR, grego);
152
153                 /* Turn output enable OFF for CNFG */
154                 greg = in32(PPC405GP_GPIO0_TCR); /* get tristate register */
155                 greg &= ~cnfg;  /* CNFG tristate inactive */
156                 out32(PPC405GP_GPIO0_TCR, greg); /*  ... just do it */
157
158                 /* Toggle IRQ/GPIO */
159                 greg = mfdcr(CPC0_CR0); /* get chip ctrl register */
160                 greg &= ~eirq;  /* toggle irq/gpio */
161                 mtdcr(CPC0_CR0, greg);  /*  ... just do it */
162
163                 /* XXX - Next FPGA addr */
164                 ndest = (unsigned short *) ((char *) ndest + 0x00100000L);
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 = Test DONE low  */
183         while (!(in32(PPC405GP_GPIO0_IR) & GPIO_XCV_DONE)) {
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
201 done:
202         return retval;
203 }
204
205 /* FPGA image is stored in flash */
206 extern flash_info_t flash_info[];
207
208 int 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          * filename length is next short
244          */
245         fn_len = (*(unsigned short *) (buf + 12) & 0xff);
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)
256             || (len == 0))
257                 goto bad_image;
258
259         /*
260          * Calculate and Check the image's CRC.
261          */
262         calc_crc = crc32(0, xcv_buf, xcv_len);
263         if (crc != calc_crc) {
264                 printf("\nfailed - bad CRC\n");
265                 goto done;
266         }
267
268         /* Output the file name */
269         printf("file name  : ");
270         for (i = 0; i < fn_len; i++) {
271                 bufchar = fn_buf[+i];
272                 if (bufchar < ' ' || bufchar > '~')
273                         bufchar = '.';
274                 putc(bufchar);
275         }
276
277         /*
278          * find rest of display data
279          */
280         ptr = 15;               /* Offset to ncd filename
281                                    length in fpga image */
282         j = xcv_buf[ptr];       /* Get len of ncd filename */
283         if (j > 32)
284                 goto bad_image;
285         ptr = ptr + j + 3;      /* skip ncd filename string +
286                                    3 bytes more bytes */
287
288         /*
289          * output target device string
290          */
291         j = xcv_buf[ptr++] - 1; /* len of targ str less term */
292         if (j > 32)
293                 goto bad_image;
294         printf("\n       target     : ");
295         for (i = 0; i < j; i++) {
296                 bufchar = (xcv_buf[ptr++]);
297                 if (bufchar < ' ' || bufchar > '~')
298                         bufchar = '.';
299                 putc(bufchar);
300         }
301
302         /*
303          * output compilation date string and time string
304          */
305         ptr += 3;               /* skip 2 bytes */
306         printf("\n       synth time : ");
307         j = (xcv_buf[ptr++] - 1);       /* len of date str less term */
308         if (j > 32)
309                 goto bad_image;
310         for (i = 0; i < j; i++) {
311                 bufchar = (xcv_buf[ptr++]);
312                 if (bufchar < ' ' || bufchar > '~')
313                         bufchar = '.';
314                 putc(bufchar);
315         }
316
317         ptr += 3;               /* Skip 2 bytes */
318         printf(" - ");
319         j = (xcv_buf[ptr++] - 1);       /* slen = targ dev str len */
320         if (j > 32)
321                 goto bad_image;
322         for (i = 0; i < j; i++) {
323                 bufchar = (xcv_buf[ptr++]);
324                 if (bufchar < ' ' || bufchar > '~')
325                         bufchar = '.';
326                 putc(bufchar);
327         }
328
329         /*
330          * output crc and length strings
331          */
332         printf("\n       len & crc  : 0x%lx  0x%lx", len, crc);
333
334         /*
335          * Program the FPGA.
336          */
337         retval = fpgaDownload((unsigned char *) xcv_buf, xcv_len,
338                               (unsigned short *) 0xfd000000L);
339         return retval;
340
341 bad_image:
342         printf("\n       BAD FPGA image format @ %lx\n",
343                flash_info[1].start[0]);
344         log_warn(ERR_XIMAGE);
345 done:
346         return retval;
347 }
348
349 void test_fpga(unsigned short *daddr)
350 {
351         int i;
352         volatile unsigned short *ndest = daddr;
353
354         for (i = 0; i < CONFIG_NUM_FPGAS; i++) {
355 #if defined(CONFIG_W7OLMG)
356                 ndest[0x7e] = 0x55aa;
357                 if (ndest[0x7e] != 0x55aa)
358                         log_warn(ERR_XRW1 + i);
359                 ndest[0x7e] = 0xaa55;
360                 if (ndest[0x7e] != 0xaa55)
361                         log_warn(ERR_XRW1 + i);
362                 ndest[0x7e] = 0xc318;
363                 if (ndest[0x7e] != 0xc318)
364                         log_warn(ERR_XRW1 + i);
365
366 #elif defined(CONFIG_W7OLMC)
367                 ndest[0x800] = 0x55aa;
368                 ndest[0x801] = 0xaa55;
369                 ndest[0x802] = 0xc318;
370                 ndest[0x4800] = 0x55aa;
371                 ndest[0x4801] = 0xaa55;
372                 ndest[0x4802] = 0xc318;
373                 if ((ndest[0x800] != 0x55aa) ||
374                     (ndest[0x801] != 0xaa55) || (ndest[0x802] != 0xc318))
375                         log_warn(ERR_XRW1 + (2 * i)); /* Auto gen error code */
376                 if ((ndest[0x4800] != 0x55aa) ||
377                     (ndest[0x4801] != 0xaa55) || (ndest[0x4802] != 0xc318))
378                         log_warn(ERR_XRW2 + (2 * i)); /* Auto gen error code */
379
380 #else
381 #error "Unknown W7O board configuration"
382 #endif
383         }
384
385         printf("       FPGA ready\n");
386         return;
387 }