Merge with git://www.denx.de/git/u-boot.git
[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 (CONFIG_COMMANDS & CFG_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 #if defined (CONFIG_FPGA) && ( CONFIG_COMMANDS & CFG_CMD_FPGA )
47
48 /* Local functions */
49 static void fpga_usage (cmd_tbl_t * cmdtp);
50 static int fpga_get_op (char *opstr);
51
52 /* Local defines */
53 #define FPGA_NONE   -1
54 #define FPGA_INFO   0
55 #define FPGA_LOAD   1
56 #define FPGA_LOADB  2
57 #define FPGA_DUMP   3
58 #define FPGA_LOADMK 4
59
60 /* Convert bitstream data and load into the fpga */
61 int fpga_loadbitstream(unsigned long dev, char* fpgadata, size_t size)
62 {
63         unsigned int length;
64         unsigned char* swapdata;
65         unsigned int swapsize;
66         char buffer[80];
67         unsigned char *ptr;
68         unsigned char *dataptr;
69         unsigned char data;
70         unsigned int i;
71         int rc;
72
73         dataptr = (unsigned char *)fpgadata;
74
75 #if CFG_FPGA_XILINX
76         /* skip the first bytes of the bitsteam, their meaning is unknown */
77         length = (*dataptr << 8) + *(dataptr+1);
78         dataptr+=2;
79         dataptr+=length;
80
81         /* get design name (identifier, length, string) */
82         length = (*dataptr << 8) + *(dataptr+1);
83         dataptr+=2;
84         if (*dataptr++ != 0x61) {
85                 PRINTF ("%s: Design name identifier not recognized in bitstream\n",
86                         __FUNCTION__ );
87                 return FPGA_FAIL;
88         }
89
90         length = (*dataptr << 8) + *(dataptr+1);
91         dataptr+=2;
92         for(i=0;i<length;i++)
93                 buffer[i]=*dataptr++;
94
95         printf("  design filename = \"%s\"\n", buffer);
96
97         /* get part number (identifier, length, string) */
98         if (*dataptr++ != 0x62) {
99                 printf("%s: Part number identifier not recognized in bitstream\n",
100                         __FUNCTION__ );
101                 return FPGA_FAIL;
102         }
103
104         length = (*dataptr << 8) + *(dataptr+1);
105         dataptr+=2;
106         for(i=0;i<length;i++)
107                 buffer[i]=*dataptr++;
108         printf("  part number = \"%s\"\n", buffer);
109
110         /* get date (identifier, length, string) */
111         if (*dataptr++ != 0x63) {
112                 printf("%s: Date identifier not recognized in bitstream\n",
113                        __FUNCTION__);
114                 return FPGA_FAIL;
115         }
116
117         length = (*dataptr << 8) + *(dataptr+1);
118         dataptr+=2;
119         for(i=0;i<length;i++)
120                 buffer[i]=*dataptr++;
121         printf("  date = \"%s\"\n", buffer);
122
123         /* get time (identifier, length, string) */
124         if (*dataptr++ != 0x64) {
125                 printf("%s: Time identifier not recognized in bitstream\n",__FUNCTION__);
126                 return FPGA_FAIL;
127         }
128
129         length = (*dataptr << 8) + *(dataptr+1);
130         dataptr+=2;
131         for(i=0;i<length;i++)
132                 buffer[i]=*dataptr++;
133         printf("  time = \"%s\"\n", buffer);
134
135         /* get fpga data length (identifier, length) */
136         if (*dataptr++ != 0x65) {
137                 printf("%s: Data length identifier not recognized in bitstream\n",
138                         __FUNCTION__);
139                 return FPGA_FAIL;
140         }
141         swapsize = ((unsigned int) *dataptr     <<24) +
142                    ((unsigned int) *(dataptr+1) <<16) +
143                    ((unsigned int) *(dataptr+2) <<8 ) +
144                    ((unsigned int) *(dataptr+3)     ) ;
145         dataptr+=4;
146         printf("  bytes in bitstream = %d\n", swapsize);
147
148         /* check consistency of length obtained */
149         if (swapsize >= size) {
150                 printf("%s: Could not find right length of data in bitstream\n",
151                         __FUNCTION__);
152                 return FPGA_FAIL;
153         }
154
155         /* allocate memory */
156         swapdata = (unsigned char *)malloc(swapsize);
157         if (swapdata == NULL) {
158                 printf("%s: Could not allocate %d bytes memory !\n",
159                         __FUNCTION__, swapsize);
160                 return FPGA_FAIL;
161         }
162
163         /* read data into memory and swap bits */
164         ptr = swapdata;
165         for (i = 0; i < swapsize; i++) {
166                 data = 0x00;
167                 data |= (*dataptr & 0x01) << 7;
168                 data |= (*dataptr & 0x02) << 5;
169                 data |= (*dataptr & 0x04) << 3;
170                 data |= (*dataptr & 0x08) << 1;
171                 data |= (*dataptr & 0x10) >> 1;
172                 data |= (*dataptr & 0x20) >> 3;
173                 data |= (*dataptr & 0x40) >> 5;
174                 data |= (*dataptr & 0x80) >> 7;
175                 *ptr++ = data;
176                 dataptr++;
177         }
178
179         rc = fpga_load(dev, swapdata, swapsize);
180         free(swapdata);
181         return rc;
182 #else
183         printf("Bitstream support only for Xilinx devices\n");
184         return FPGA_FAIL;
185 #endif
186 }
187
188 /* ------------------------------------------------------------------------- */
189 /* command form:
190  *   fpga <op> <device number> <data addr> <datasize>
191  * where op is 'load', 'dump', or 'info'
192  * If there is no device number field, the fpga environment variable is used.
193  * If there is no data addr field, the fpgadata environment variable is used.
194  * The info command requires no data address field.
195  */
196 int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
197 {
198         int op, dev = FPGA_INVALID_DEVICE;
199         size_t data_size = 0;
200         void *fpga_data = NULL;
201         char *devstr = getenv ("fpga");
202         char *datastr = getenv ("fpgadata");
203         int rc = FPGA_FAIL;
204
205         if (devstr)
206                 dev = (int) simple_strtoul (devstr, NULL, 16);
207         if (datastr)
208                 fpga_data = (void *) simple_strtoul (datastr, NULL, 16);
209
210         switch (argc) {
211         case 5:         /* fpga <op> <dev> <data> <datasize> */
212                 data_size = simple_strtoul (argv[4], NULL, 16);
213         case 4:         /* fpga <op> <dev> <data> */
214                 fpga_data = (void *) simple_strtoul (argv[3], NULL, 16);
215                 PRINTF ("%s: fpga_data = 0x%x\n", __FUNCTION__, (uint) fpga_data);
216         case 3:         /* fpga <op> <dev | data addr> */
217                 dev = (int) simple_strtoul (argv[2], NULL, 16);
218                 PRINTF ("%s: device = %d\n", __FUNCTION__, dev);
219                 /* FIXME - this is a really weak test */
220                 if ((argc == 3) && (dev > fpga_count ())) {     /* must be buffer ptr */
221                         PRINTF ("%s: Assuming buffer pointer in arg 3\n",
222                                 __FUNCTION__);
223                         fpga_data = (void *) dev;
224                         PRINTF ("%s: fpga_data = 0x%x\n",
225                                 __FUNCTION__, (uint) fpga_data);
226                         dev = FPGA_INVALID_DEVICE;      /* reset device num */
227                 }
228         case 2:         /* fpga <op> */
229                 op = (int) fpga_get_op (argv[1]);
230                 break;
231         default:
232                 PRINTF ("%s: Too many or too few args (%d)\n",
233                         __FUNCTION__, argc);
234                 op = FPGA_NONE; /* force usage display */
235                 break;
236         }
237
238         switch (op) {
239         case FPGA_NONE:
240                 fpga_usage (cmdtp);
241                 break;
242
243         case FPGA_INFO:
244                 rc = fpga_info (dev);
245                 break;
246
247         case FPGA_LOAD:
248                 rc = fpga_load (dev, fpga_data, data_size);
249                 break;
250
251         case FPGA_LOADB:
252                 rc = fpga_loadbitstream(dev, fpga_data, data_size);
253                 break;
254
255         case FPGA_LOADMK:
256                 {
257                         image_header_t header;
258                         image_header_t *hdr = &header;
259                         ulong   data;
260
261                         memmove (&header, (char *)fpga_data, sizeof(image_header_t));
262                         if (ntohl(hdr->ih_magic) != IH_MAGIC) {
263                                 puts ("Bad Magic Number\n");
264                                 return 1;
265                         }
266                         data = ((ulong)fpga_data + sizeof(image_header_t));
267                         data_size  = ntohl(hdr->ih_size);
268                         rc = fpga_load (dev, (void *)data, data_size);
269                 }
270                 break;
271
272         case FPGA_DUMP:
273                 rc = fpga_dump (dev, fpga_data, data_size);
274                 break;
275
276         default:
277                 printf ("Unknown operation\n");
278                 fpga_usage (cmdtp);
279                 break;
280         }
281         return (rc);
282 }
283
284 static void fpga_usage (cmd_tbl_t * cmdtp)
285 {
286         printf ("Usage:\n%s\n", cmdtp->usage);
287 }
288
289 /*
290  * Map op to supported operations.  We don't use a table since we
291  * would just have to relocate it from flash anyway.
292  */
293 static int fpga_get_op (char *opstr)
294 {
295         int op = FPGA_NONE;
296
297         if (!strcmp ("info", opstr)) {
298                 op = FPGA_INFO;
299         } else if (!strcmp ("loadb", opstr)) {
300                 op = FPGA_LOADB;
301         } else if (!strcmp ("load", opstr)) {
302                 op = FPGA_LOAD;
303         } else if (!strcmp ("loadmk", opstr)) {
304                 op = FPGA_LOADMK;
305         } else if (!strcmp ("dump", opstr)) {
306                 op = FPGA_DUMP;
307         }
308
309         if (op == FPGA_NONE) {
310                 printf ("Unknown fpga operation \"%s\"\n", opstr);
311         }
312         return op;
313 }
314
315 U_BOOT_CMD (fpga, 6, 1, do_fpga,
316             "fpga    - loadable FPGA image support\n",
317             "fpga [operation type] [device number] [image address] [image size]\n"
318             "fpga operations:\n"
319             "\tinfo\tlist known device information\n"
320             "\tload\tLoad device from memory buffer\n"
321             "\tloadb\tLoad device from bitstream buffer (Xilinx devices only)\n"
322             "\tloadmk\tLoad device generated with mkimage\n"
323             "\tdump\tLoad device to memory buffer\n");
324 #endif /* CONFIG_FPGA && CONFIG_COMMANDS & CFG_CMD_FPGA */