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