[new uImage] Define a API for image handling operations
[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                 {
220                         image_header_t header;
221                         image_header_t *hdr = &header;
222                         ulong   data;
223
224                         memmove (&header, (char *)fpga_data, image_get_header_size ());
225                         if (!image_check_magic (hdr)) {
226                                 puts ("Bad Magic Number\n");
227                                 return 1;
228                         }
229                         data = ((ulong)fpga_data + image_get_header_size ());
230                         data_size = image_get_data_size (hdr);
231                         rc = fpga_load (dev, (void *)data, data_size);
232                 }
233                 break;
234
235         case FPGA_DUMP:
236                 rc = fpga_dump (dev, fpga_data, data_size);
237                 break;
238
239         default:
240                 printf ("Unknown operation\n");
241                 fpga_usage (cmdtp);
242                 break;
243         }
244         return (rc);
245 }
246
247 static void fpga_usage (cmd_tbl_t * cmdtp)
248 {
249         printf ("Usage:\n%s\n", cmdtp->usage);
250 }
251
252 /*
253  * Map op to supported operations.  We don't use a table since we
254  * would just have to relocate it from flash anyway.
255  */
256 static int fpga_get_op (char *opstr)
257 {
258         int op = FPGA_NONE;
259
260         if (!strcmp ("info", opstr)) {
261                 op = FPGA_INFO;
262         } else if (!strcmp ("loadb", opstr)) {
263                 op = FPGA_LOADB;
264         } else if (!strcmp ("load", opstr)) {
265                 op = FPGA_LOAD;
266         } else if (!strcmp ("loadmk", opstr)) {
267                 op = FPGA_LOADMK;
268         } else if (!strcmp ("dump", opstr)) {
269                 op = FPGA_DUMP;
270         }
271
272         if (op == FPGA_NONE) {
273                 printf ("Unknown fpga operation \"%s\"\n", opstr);
274         }
275         return op;
276 }
277
278 U_BOOT_CMD (fpga, 6, 1, do_fpga,
279             "fpga    - loadable FPGA image support\n",
280             "fpga [operation type] [device number] [image address] [image size]\n"
281             "fpga operations:\n"
282             "\tinfo\tlist known device information\n"
283             "\tload\tLoad device from memory buffer\n"
284             "\tloadb\tLoad device from bitstream buffer (Xilinx devices only)\n"
285             "\tloadmk\tLoad device generated with mkimage\n"
286             "\tdump\tLoad device to memory buffer\n");