]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/siemens/common/fpga.c
Initial revision
[karo-tx-uboot.git] / board / siemens / common / fpga.c
1 /*
2  * (C) Copyright 2002
3  * Wolfgang Grandegger, DENX Software Engineering, wg@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24
25 #include <common.h>
26 #include <command.h>
27 #include <linux/ctype.h>
28 #include <common.h>
29 #include <cmd_boot.h>
30 #include <cmd_bsp.h>
31
32 #include "fpga.h"
33
34 int  power_on_reset(void);
35
36 /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
37
38
39 static int fpga_get_version(fpga_t* fpga, char* name)
40 {
41     char vname[12];
42     /*
43      * Net-list string format:
44      *     "vvvvvvvvddddddddn...".
45      *     Version Date    Name
46      *     "0000000322042002PUMA" = PUMA version 3 from 22.04.2002.
47      */
48     if (strlen(name) < (16 + strlen(fpga->name)))
49         goto failure;
50     /* Check FPGA name */
51     if (strcmp(&name[16], fpga->name) != 0)
52         goto failure;
53     /* Get version number */
54     memcpy(vname, name, 8);
55     vname[8] = '\0';
56     return simple_strtoul(vname, NULL, 16);
57
58  failure:
59     printf("Image name %s is invalid\n", name);
60     return -1;
61 }
62
63 /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
64
65 static fpga_t* fpga_get(char* fpga_name)
66 {
67     char name[FPGA_NAME_LEN];
68     int i;
69
70     if (strlen(fpga_name) >= FPGA_NAME_LEN)
71         goto failure;
72     for (i = 0; i < strlen(fpga_name); i++)
73         name[i] = toupper(fpga_name[i]);
74     name[i] = '\0';
75     for (i = 0; i < fpga_count; i++) {
76         if (strcmp(name, fpga_list[i].name) == 0)
77             return &fpga_list[i];
78     }
79  failure:
80     printf("FPGA: name %s is invalid\n", fpga_name);
81     return NULL;
82 }
83
84 /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
85
86 static void fpga_status (fpga_t* fpga)
87 {
88     /* Check state */
89     if (fpga_control(fpga, FPGA_DONE_IS_HIGH))
90         printf ("%s is loaded (%08lx)\n",
91                 fpga->name, fpga_control(fpga, FPGA_GET_ID));
92     else
93         printf ("%s is NOT loaded\n", fpga->name);
94 }
95
96 /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
97
98 #define FPGA_RESET_TIMEOUT 100 /* = 10 ms */
99
100 static int fpga_reset (fpga_t* fpga)
101 {
102     int i;
103
104     /* Set PROG to low and wait til INIT goes low */
105     fpga_control(fpga, FPGA_PROG_SET_LOW);
106     for (i = 0; i < FPGA_RESET_TIMEOUT; i++) {
107         udelay (100);
108         if (!fpga_control(fpga, FPGA_INIT_IS_HIGH))
109             break;
110     }
111     if (i == FPGA_RESET_TIMEOUT)
112         goto failure;
113
114     /* Set PROG to high and wait til INIT goes high */
115     fpga_control(fpga, FPGA_PROG_SET_HIGH);
116     for (i = 0; i < FPGA_RESET_TIMEOUT; i++) {
117         udelay (100);
118         if (fpga_control(fpga, FPGA_INIT_IS_HIGH))
119             break;
120     }
121     if (i == FPGA_RESET_TIMEOUT)
122         goto failure;
123
124     return 0;
125  failure:
126     return 1;
127 }
128
129 /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
130
131 #define FPGA_LOAD_TIMEOUT 100 /* = 10 ms */
132
133 static int fpga_load (fpga_t* fpga, ulong addr, int checkall)
134 {
135     volatile uchar *fpga_addr = (volatile uchar *)fpga->conf_base;
136     image_header_t hdr;
137     ulong len, checksum;
138     uchar *data = (uchar *)&hdr;
139     char *s, msg[32];
140     int verify, i;
141
142     /*
143      * Check the image header and data of the net-list
144      */
145     memcpy (&hdr, (char *)addr, sizeof(image_header_t));
146
147     if (hdr.ih_magic != IH_MAGIC) {
148         strcpy (msg, "Bad Image Magic Number");
149         goto failure;
150     }
151
152     len  = sizeof(image_header_t);
153
154     checksum = hdr.ih_hcrc;
155     hdr.ih_hcrc = 0;
156
157     if (crc32 (0, data, len) != checksum) {
158         strcpy (msg, "Bad Image Header CRC");
159         goto failure;
160     }
161
162     data = (uchar*)(addr + sizeof(image_header_t));
163     len  = hdr.ih_size;
164
165     s = getenv ("verify");
166     verify = (s && (*s == 'n')) ? 0 : 1;
167     if (verify) {
168         if (crc32 (0, data, len) != hdr.ih_dcrc) {
169             strcpy (msg, "Bad Image Data CRC");
170             goto failure;
171         }
172     }
173
174     if (checkall && fpga_get_version(fpga, hdr.ih_name) < 0)
175         return 1;
176
177     /* align length */
178     if (len & 1)
179         ++len;
180
181     /*
182      * Reset FPGA and wait for completion
183      */
184     if (fpga_reset(fpga)) {
185         strcpy (msg, "Reset Timeout");
186         goto failure;
187     }
188
189     printf ("(%s)... ", hdr.ih_name);
190     /*
191      * Copy data to FPGA
192      */
193     fpga_control (fpga, FPGA_LOAD_MODE);
194     while (len--) {
195         *fpga_addr = *data++;
196     }
197     fpga_control (fpga, FPGA_READ_MODE);
198
199     /*
200      * Wait for completion and check error status if timeout
201      */
202     for (i = 0; i < FPGA_LOAD_TIMEOUT; i++) {
203         udelay (100);
204         if (fpga_control (fpga, FPGA_DONE_IS_HIGH))
205             break;
206     }
207     if (i == FPGA_LOAD_TIMEOUT) {
208         if (fpga_control(fpga, FPGA_INIT_IS_HIGH))
209             strcpy(msg, "Invalid Size");
210         else
211             strcpy(msg, "CRC Error");
212         goto failure;
213     }
214
215     printf("done\n");
216     return 0;
217
218  failure:
219
220     printf("ERROR: %s\n", msg);
221     return 1;
222 }
223
224 #if (CONFIG_COMMANDS & CFG_CMD_BSP)
225
226 /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
227
228 int do_fpga (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
229 {
230     ulong addr = 0;
231     int i;
232     fpga_t* fpga;
233
234     if (argc < 2)
235         goto failure;
236
237     if (strncmp(argv[1], "stat", 4) == 0) {             /* status */
238         if (argc == 2) {
239             for (i = 0; i < fpga_count; i++) {
240                 fpga_status (&fpga_list[i]);
241             }
242         }
243         else if (argc == 3) {
244             if ((fpga = fpga_get(argv[2])) == 0)
245                 goto failure;
246             fpga_status (fpga);
247         }
248         else
249             goto failure;
250     }
251     else if (strcmp(argv[1],"load") == 0) {             /* load */
252         if (argc == 3 && fpga_count == 1) {
253             fpga = &fpga_list[0];
254         }
255         else if (argc == 4) {
256             if ((fpga = fpga_get(argv[2])) == 0)
257                 goto failure;
258         }
259         else
260             goto failure;
261
262         addr = simple_strtoul(argv[argc-1], NULL, 16);
263
264         printf ("FPGA load %s: addr %08lx: ",
265                 fpga->name, addr);
266         fpga_load (fpga, addr, 1);
267
268     }
269     else if (strncmp(argv[1], "rese", 4) == 0) {        /* reset */
270         if (argc == 2 && fpga_count == 1) {
271             fpga = &fpga_list[0];
272         }
273         else if (argc == 3) {
274             if ((fpga = fpga_get(argv[2])) == 0)
275                 goto failure;
276         }
277         else
278             goto failure;
279
280         printf ("FPGA reset %s: ", fpga->name);
281         if (fpga_reset(fpga))
282             printf ("ERROR: Timeout\n");
283         else
284             printf ("done\n");
285     }
286     else
287         goto failure;
288
289     return 0;
290
291  failure:
292     printf ("Usage:\n%s\n", cmdtp->usage);
293     return 1;
294 }
295
296 #endif  /* CONFIG_COMMANDS & CFG_CMD_BSP */
297
298 /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
299
300 int fpga_init (void)
301 {
302     ulong addr;
303     ulong new_id, old_id = 0;
304     image_header_t *hdr;
305     fpga_t* fpga;
306     int do_load, i, j;
307     char name[16], *s;
308
309     /*
310      *  Port setup for FPGA control
311      */
312     for (i = 0; i < fpga_count; i++) {
313         fpga_control(&fpga_list[i], FPGA_INIT_PORTS);
314     }
315
316     /*
317      * Load FPGA(s): a new net-list is loaded if the FPGA is
318      * empty, Power-on-Reset or the old one is not up-to-date
319      */
320     for (i = 0; i < fpga_count; i++) {
321         fpga = &fpga_list[i];
322         printf ("%s:  ", fpga->name);
323
324         for (j = 0; j < strlen(fpga->name); j++)
325             name[j] = tolower(fpga->name[j]);
326         name[j] = '\0';
327         sprintf(name, "%s_addr", name);
328         addr = 0;
329         if ((s = getenv(name)) != NULL)
330             addr = simple_strtoul(s, NULL, 16);
331
332         if (!addr) {
333             printf ("env. variable %s undefined\n", name);
334             return 1;
335         }
336
337         hdr = (image_header_t *)addr;
338         if ((new_id = fpga_get_version(fpga, hdr->ih_name)) == -1)
339             return 1;
340
341         do_load = 1;
342
343         if (!power_on_reset() && fpga_control(fpga, FPGA_DONE_IS_HIGH)) {
344             old_id = fpga_control(fpga, FPGA_GET_ID);
345             if (new_id == old_id)
346                 do_load = 0;
347         }
348
349         if (do_load) {
350             printf ("loading ");
351             fpga_load (fpga, addr, 0);
352         } else {
353             printf ("loaded (%08lx)\n", old_id);
354         }
355     }
356
357     return 0;
358 }