[new uImage] Add dual format uImage support framework
[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
168         if (devstr)
169                 dev = (int) simple_strtoul (devstr, NULL, 16);
170         if (datastr)
171                 fpga_data = (void *) simple_strtoul (datastr, NULL, 16);
172
173         switch (argc) {
174         case 5:         /* fpga <op> <dev> <data> <datasize> */
175                 data_size = simple_strtoul (argv[4], NULL, 16);
176         case 4:         /* fpga <op> <dev> <data> */
177                 fpga_data = (void *) simple_strtoul (argv[3], NULL, 16);
178                 PRINTF ("%s: fpga_data = 0x%x\n", __FUNCTION__, (uint) fpga_data);
179         case 3:         /* fpga <op> <dev | data addr> */
180                 dev = (int) simple_strtoul (argv[2], NULL, 16);
181                 PRINTF ("%s: device = %d\n", __FUNCTION__, dev);
182                 /* FIXME - this is a really weak test */
183                 if ((argc == 3) && (dev > fpga_count ())) {     /* must be buffer ptr */
184                         PRINTF ("%s: Assuming buffer pointer in arg 3\n",
185                                 __FUNCTION__);
186                         fpga_data = (void *) dev;
187                         PRINTF ("%s: fpga_data = 0x%x\n",
188                                 __FUNCTION__, (uint) fpga_data);
189                         dev = FPGA_INVALID_DEVICE;      /* reset device num */
190                 }
191         case 2:         /* fpga <op> */
192                 op = (int) fpga_get_op (argv[1]);
193                 break;
194         default:
195                 PRINTF ("%s: Too many or too few args (%d)\n",
196                         __FUNCTION__, argc);
197                 op = FPGA_NONE; /* force usage display */
198                 break;
199         }
200
201         switch (op) {
202         case FPGA_NONE:
203                 fpga_usage (cmdtp);
204                 break;
205
206         case FPGA_INFO:
207                 rc = fpga_info (dev);
208                 break;
209
210         case FPGA_LOAD:
211                 rc = fpga_load (dev, fpga_data, data_size);
212                 break;
213
214         case FPGA_LOADB:
215                 rc = fpga_loadbitstream(dev, fpga_data, data_size);
216                 break;
217
218         case FPGA_LOADMK:
219                 switch (gen_image_get_format (fpga_data)) {
220                 case IMAGE_FORMAT_LEGACY:
221                         {
222                                 image_header_t *hdr = (image_header_t *)fpga_data;
223                                 ulong   data;
224
225                                 if (!image_check_magic (hdr)) {
226                                         puts ("Bad Magic Number\n");
227                                         return 1;
228                                 }
229                                 data = (ulong)image_get_data (hdr);
230                                 data_size = image_get_data_size (hdr);
231                                 rc = fpga_load (dev, (void *)data, data_size);
232                         }
233                         break;
234 #if defined(CONFIG_FIT)
235                 case IMAGE_FORMAT_FIT:
236                         fit_unsupported ("fpga");
237                         rc = FPGA_FAIL;
238                         break;
239 #endif
240                 default:
241                         puts ("** Unknown image type\n");
242                         rc = FPGA_FAIL;
243                         break;
244                 }
245                 break;
246
247         case FPGA_DUMP:
248                 rc = fpga_dump (dev, fpga_data, data_size);
249                 break;
250
251         default:
252                 printf ("Unknown operation\n");
253                 fpga_usage (cmdtp);
254                 break;
255         }
256         return (rc);
257 }
258
259 static void fpga_usage (cmd_tbl_t * cmdtp)
260 {
261         printf ("Usage:\n%s\n", cmdtp->usage);
262 }
263
264 /*
265  * Map op to supported operations.  We don't use a table since we
266  * would just have to relocate it from flash anyway.
267  */
268 static int fpga_get_op (char *opstr)
269 {
270         int op = FPGA_NONE;
271
272         if (!strcmp ("info", opstr)) {
273                 op = FPGA_INFO;
274         } else if (!strcmp ("loadb", opstr)) {
275                 op = FPGA_LOADB;
276         } else if (!strcmp ("load", opstr)) {
277                 op = FPGA_LOAD;
278         } else if (!strcmp ("loadmk", opstr)) {
279                 op = FPGA_LOADMK;
280         } else if (!strcmp ("dump", opstr)) {
281                 op = FPGA_DUMP;
282         }
283
284         if (op == FPGA_NONE) {
285                 printf ("Unknown fpga operation \"%s\"\n", opstr);
286         }
287         return op;
288 }
289
290 U_BOOT_CMD (fpga, 6, 1, do_fpga,
291             "fpga    - loadable FPGA image support\n",
292             "fpga [operation type] [device number] [image address] [image size]\n"
293             "fpga operations:\n"
294             "\tinfo\tlist known device information\n"
295             "\tload\tLoad device from memory buffer\n"
296             "\tloadb\tLoad device from bitstream buffer (Xilinx devices only)\n"
297             "\tloadmk\tLoad device generated with mkimage\n"
298             "\tdump\tLoad device to memory buffer\n");