Merge branch 'master' of ssh://gemini/home/wd/git/u-boot/master
[platform/kernel/u-boot.git] / common / cmd_fpga.c
1 /*
2  * (C) Copyright 2000, 2001
3  * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
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 /*
26  *  FPGA support
27  */
28 #include <common.h>
29 #include <command.h>
30 #if defined(CONFIG_CMD_NET)
31 #include <net.h>
32 #endif
33 #include <fpga.h>
34 #include <malloc.h>
35
36 #if 0
37 #define FPGA_DEBUG
38 #endif
39
40 #ifdef  FPGA_DEBUG
41 #define PRINTF(fmt,args...)     printf (fmt ,##args)
42 #else
43 #define PRINTF(fmt,args...)
44 #endif
45
46 /* Local functions */
47 static void fpga_usage (cmd_tbl_t * cmdtp);
48 static int fpga_get_op (char *opstr);
49
50 /* Local defines */
51 #define FPGA_NONE   -1
52 #define FPGA_INFO   0
53 #define FPGA_LOAD   1
54 #define FPGA_LOADB  2
55 #define FPGA_DUMP   3
56 #define FPGA_LOADMK 4
57
58 /* Convert bitstream data and load into the fpga */
59 int fpga_loadbitstream(unsigned long dev, char* fpgadata, size_t size)
60 {
61 #if defined(CONFIG_FPGA_XILINX)
62         unsigned int length;
63         unsigned int swapsize;
64         char buffer[80];
65         unsigned char *dataptr;
66         unsigned int i;
67         int rc;
68
69         dataptr = (unsigned char *)fpgadata;
70
71         /* skip the first bytes of the bitsteam, their meaning is unknown */
72         length = (*dataptr << 8) + *(dataptr+1);
73         dataptr+=2;
74         dataptr+=length;
75
76         /* get design name (identifier, length, string) */
77         length = (*dataptr << 8) + *(dataptr+1);
78         dataptr+=2;
79         if (*dataptr++ != 0x61) {
80                 PRINTF ("%s: Design name identifier not recognized in bitstream\n",
81                         __FUNCTION__ );
82                 return FPGA_FAIL;
83         }
84
85         length = (*dataptr << 8) + *(dataptr+1);
86         dataptr+=2;
87         for(i=0;i<length;i++)
88                 buffer[i] = *dataptr++;
89
90         printf("  design filename = \"%s\"\n", buffer);
91
92         /* get part number (identifier, length, string) */
93         if (*dataptr++ != 0x62) {
94                 printf("%s: Part number identifier not recognized in bitstream\n",
95                         __FUNCTION__ );
96                 return FPGA_FAIL;
97         }
98
99         length = (*dataptr << 8) + *(dataptr+1);
100         dataptr+=2;
101         for(i=0;i<length;i++)
102                 buffer[i] = *dataptr++;
103         printf("  part number = \"%s\"\n", buffer);
104
105         /* get date (identifier, length, string) */
106         if (*dataptr++ != 0x63) {
107                 printf("%s: Date identifier not recognized in bitstream\n",
108                        __FUNCTION__);
109                 return FPGA_FAIL;
110         }
111
112         length = (*dataptr << 8) + *(dataptr+1);
113         dataptr+=2;
114         for(i=0;i<length;i++)
115                 buffer[i] = *dataptr++;
116         printf("  date = \"%s\"\n", buffer);
117
118         /* get time (identifier, length, string) */
119         if (*dataptr++ != 0x64) {
120                 printf("%s: Time identifier not recognized in bitstream\n",__FUNCTION__);
121                 return FPGA_FAIL;
122         }
123
124         length = (*dataptr << 8) + *(dataptr+1);
125         dataptr+=2;
126         for(i=0;i<length;i++)
127                 buffer[i] = *dataptr++;
128         printf("  time = \"%s\"\n", buffer);
129
130         /* get fpga data length (identifier, length) */
131         if (*dataptr++ != 0x65) {
132                 printf("%s: Data length identifier not recognized in bitstream\n",
133                         __FUNCTION__);
134                 return FPGA_FAIL;
135         }
136         swapsize = ((unsigned int) *dataptr     <<24) +
137                    ((unsigned int) *(dataptr+1) <<16) +
138                    ((unsigned int) *(dataptr+2) <<8 ) +
139                    ((unsigned int) *(dataptr+3)     ) ;
140         dataptr+=4;
141         printf("  bytes in bitstream = %d\n", swapsize);
142
143         rc = fpga_load(dev, dataptr, swapsize);
144         return rc;
145 #else
146         printf("Bitstream support only for Xilinx devices\n");
147         return FPGA_FAIL;
148 #endif
149 }
150
151 /* ------------------------------------------------------------------------- */
152 /* command form:
153  *   fpga <op> <device number> <data addr> <datasize>
154  * where op is 'load', 'dump', or 'info'
155  * If there is no device number field, the fpga environment variable is used.
156  * If there is no data addr field, the fpgadata environment variable is used.
157  * The info command requires no data address field.
158  */
159 int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
160 {
161         int op, dev = FPGA_INVALID_DEVICE;
162         size_t data_size = 0;
163         void *fpga_data = NULL;
164         char *devstr = getenv ("fpga");
165         char *datastr = getenv ("fpgadata");
166         int rc = FPGA_FAIL;
167 #if defined (CONFIG_FIT)
168         const char *fit_uname = NULL;
169         ulong fit_addr;
170 #endif
171
172         if (devstr)
173                 dev = (int) simple_strtoul (devstr, NULL, 16);
174         if (datastr)
175                 fpga_data = (void *) simple_strtoul (datastr, NULL, 16);
176
177         switch (argc) {
178         case 5:         /* fpga <op> <dev> <data> <datasize> */
179                 data_size = simple_strtoul (argv[4], NULL, 16);
180
181         case 4:         /* fpga <op> <dev> <data> */
182 #if defined(CONFIG_FIT)
183                 if (fit_parse_subimage (argv[3], (ulong)fpga_data,
184                                         &fit_addr, &fit_uname)) {
185                         fpga_data = (void *)fit_addr;
186                         debug ("*  fpga: subimage '%s' from FIT image at 0x%08lx\n",
187                                         fit_uname, fit_addr);
188                 } else
189 #endif
190                 {
191                         fpga_data = (void *) simple_strtoul (argv[3], NULL, 16);
192                         debug ("*  fpga: cmdline image address = 0x%08lx\n", (ulong)fpga_data);
193                 }
194                 PRINTF ("%s: fpga_data = 0x%x\n", __FUNCTION__, (uint) fpga_data);
195
196         case 3:         /* fpga <op> <dev | data addr> */
197                 dev = (int) simple_strtoul (argv[2], NULL, 16);
198                 PRINTF ("%s: device = %d\n", __FUNCTION__, dev);
199                 /* FIXME - this is a really weak test */
200                 if ((argc == 3) && (dev > fpga_count ())) {     /* must be buffer ptr */
201                         PRINTF ("%s: Assuming buffer pointer in arg 3\n",
202                                 __FUNCTION__);
203
204 #if defined(CONFIG_FIT)
205                         if (fit_parse_subimage (argv[2], (ulong)fpga_data,
206                                                 &fit_addr, &fit_uname)) {
207                                 fpga_data = (void *)fit_addr;
208                                 debug ("*  fpga: subimage '%s' from FIT image at 0x%08lx\n",
209                                                 fit_uname, fit_addr);
210                         } else
211 #endif
212                         {
213                                 fpga_data = (void *) dev;
214                                 debug ("*  fpga: cmdline image address = 0x%08lx\n", (ulong)fpga_data);
215                         }
216
217                         PRINTF ("%s: fpga_data = 0x%x\n",
218                                 __FUNCTION__, (uint) fpga_data);
219                         dev = FPGA_INVALID_DEVICE;      /* reset device num */
220                 }
221
222         case 2:         /* fpga <op> */
223                 op = (int) fpga_get_op (argv[1]);
224                 break;
225
226         default:
227                 PRINTF ("%s: Too many or too few args (%d)\n",
228                         __FUNCTION__, argc);
229                 op = FPGA_NONE; /* force usage display */
230                 break;
231         }
232
233         switch (op) {
234         case FPGA_NONE:
235                 fpga_usage (cmdtp);
236                 break;
237
238         case FPGA_INFO:
239                 rc = fpga_info (dev);
240                 break;
241
242         case FPGA_LOAD:
243                 rc = fpga_load (dev, fpga_data, data_size);
244                 break;
245
246         case FPGA_LOADB:
247                 rc = fpga_loadbitstream(dev, fpga_data, data_size);
248                 break;
249
250         case FPGA_LOADMK:
251                 switch (genimg_get_format (fpga_data)) {
252                 case IMAGE_FORMAT_LEGACY:
253                         {
254                                 image_header_t *hdr = (image_header_t *)fpga_data;
255                                 ulong   data;
256
257                                 data = (ulong)image_get_data (hdr);
258                                 data_size = image_get_data_size (hdr);
259                                 rc = fpga_load (dev, (void *)data, data_size);
260                         }
261                         break;
262 #if defined(CONFIG_FIT)
263                 case IMAGE_FORMAT_FIT:
264                         {
265                                 const void *fit_hdr = (const void *)fpga_data;
266                                 int noffset;
267                                 void *fit_data;
268
269                                 if (fit_uname == NULL) {
270                                         puts ("No FIT subimage unit name\n");
271                                         return 1;
272                                 }
273
274                                 if (!fit_check_format (fit_hdr)) {
275                                         puts ("Bad FIT image format\n");
276                                         return 1;
277                                 }
278
279                                 /* get fpga component image node offset */
280                                 noffset = fit_image_get_node (fit_hdr, fit_uname);
281                                 if (noffset < 0) {
282                                         printf ("Can't find '%s' FIT subimage\n", fit_uname);
283                                         return 1;
284                                 }
285
286                                 /* verify integrity */
287                                 if (!fit_image_check_hashes (fit_hdr, noffset)) {
288                                         puts ("Bad Data Hash\n");
289                                         return 1;
290                                 }
291
292                                 /* get fpga subimage data address and length */
293                                 if (fit_image_get_data (fit_hdr, noffset, &fit_data, &data_size)) {
294                                         puts ("Could not find fpga subimage data\n");
295                                         return 1;
296                                 }
297
298                                 rc = fpga_load (dev, fit_data, data_size);
299                         }
300                         break;
301 #endif
302                 default:
303                         puts ("** Unknown image type\n");
304                         rc = FPGA_FAIL;
305                         break;
306                 }
307                 break;
308
309         case FPGA_DUMP:
310                 rc = fpga_dump (dev, fpga_data, data_size);
311                 break;
312
313         default:
314                 printf ("Unknown operation\n");
315                 fpga_usage (cmdtp);
316                 break;
317         }
318         return (rc);
319 }
320
321 static void fpga_usage (cmd_tbl_t * cmdtp)
322 {
323         cmd_usage(cmdtp);
324 }
325
326 /*
327  * Map op to supported operations.  We don't use a table since we
328  * would just have to relocate it from flash anyway.
329  */
330 static int fpga_get_op (char *opstr)
331 {
332         int op = FPGA_NONE;
333
334         if (!strcmp ("info", opstr)) {
335                 op = FPGA_INFO;
336         } else if (!strcmp ("loadb", opstr)) {
337                 op = FPGA_LOADB;
338         } else if (!strcmp ("load", opstr)) {
339                 op = FPGA_LOAD;
340         } else if (!strcmp ("loadmk", opstr)) {
341                 op = FPGA_LOADMK;
342         } else if (!strcmp ("dump", opstr)) {
343                 op = FPGA_DUMP;
344         }
345
346         if (op == FPGA_NONE) {
347                 printf ("Unknown fpga operation \"%s\"\n", opstr);
348         }
349         return op;
350 }
351
352 U_BOOT_CMD (fpga, 6, 1, do_fpga,
353             "loadable FPGA image support",
354             "fpga [operation type] [device number] [image address] [image size]\n"
355             "fpga operations:\n"
356             "\tinfo\tlist known device information\n"
357             "\tload\tLoad device from memory buffer\n"
358             "\tloadb\tLoad device from bitstream buffer (Xilinx devices only)\n"
359             "\tloadmk\tLoad device generated with mkimage\n"
360             "\tdump\tLoad device to memory buffer\n"
361 #if defined(CONFIG_FIT)
362             "\tFor loadmk operating on FIT format uImage address must include\n"
363             "\tsubimage unit name in the form of addr:<subimg_uname>\n"
364 #endif
365 );