]> git.sur5r.net Git - u-boot/blob - common/cmd_fpga.c
* Patch by Yusdi Santoso, 22 Oct 2004:
[u-boot] / 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
59 /* Convert bitstream data and load into the fpga */
60 int fpga_loadbitstream(unsigned long dev, char* fpgadata, size_t size)
61 {
62         int length;
63         char* swapdata;
64         int swapsize;
65         char buffer[80];
66         char *ptr;
67         char *dataptr;
68         int data;
69         int i;
70         int rc;
71
72         dataptr = fpgadata;
73
74 #if CFG_FPGA_XILINX
75         /* skip the first 13 bytes of the bitsteam, their meaning is unknown */
76         dataptr+=13;
77
78         /* get design name (identifier, length, string) */
79         if (*dataptr++ != 0x61) {
80                 PRINTF("fpga_loadbitstream: Design name identifier not recognized in bitstream.\n");
81                 return FPGA_FAIL;
82         }
83
84         length = (*dataptr << 8) + *(dataptr+1);
85         dataptr+=2;
86         for(i=0;i<length;i++)
87                 buffer[i]=*dataptr++;
88
89         buffer[length-5]='\0'; /* remove filename extension */
90         PRINTF("fpga_loadbitstream: design name = \"%s\".\n",buffer);
91
92         /* get part number (identifier, length, string) */
93         if (*dataptr++ != 0x62) {
94                 printf("fpga_loadbitstream: Part number identifier not recognized in bitstream.\n");
95                 return FPGA_FAIL;
96         }
97
98         length = (*dataptr << 8) + *(dataptr+1); dataptr+=2;
99         for(i=0;i<length;i++)
100                 buffer[i]=*dataptr++;
101         PRINTF("fpga_loadbitstream: part number = \"%s\".\n",buffer);
102
103         /* get date (identifier, length, string) */
104         if (*dataptr++ != 0x63) {
105                 printf("fpga_loadbitstream: Date identifier not recognized in bitstream.\n");
106                 return FPGA_FAIL;
107         }
108
109         length = (*dataptr << 8) + *(dataptr+1); dataptr+=2;
110         for(i=0;i<length;i++)
111                 buffer[i]=*dataptr++;
112         PRINTF("fpga_loadbitstream: date = \"%s\".\n",buffer);
113
114         /* get time (identifier, length, string) */
115         if (*dataptr++ != 0x64) {
116                 printf("fpga_loadbitstream: Time identifier not recognized in bitstream.\n");
117                 return FPGA_FAIL;
118         }
119
120         length = (*dataptr << 8) + *(dataptr+1); dataptr+=2;
121         for(i=0;i<length;i++)
122                 buffer[i]=*dataptr++;
123         PRINTF("fpga_loadbitstream: time = \"%s\".\n",buffer);
124
125         /* get fpga data length (identifier, length) */
126         if (*dataptr++ != 0x65) {
127                 printf("fpga_loadbitstream: Data length identifier not recognized in bitstream.\n");
128                 return FPGA_FAIL;
129         }
130         swapsize = ((long)*dataptr<<24) + ((long)*(dataptr+1)<<16) + ((long)*(dataptr+2)<<8) + (long)*(dataptr+3);
131         dataptr+=4;
132         PRINTF("fpga_loadbitstream: bytes in bitstream = %d.\n",swapsize);
133
134         /* check consistency of length obtained */
135         if (swapsize >= size) {
136                 printf("fpga_loadbitstream: Could not find right length of data in bitstream.\n");
137                 return FPGA_FAIL;
138         }
139
140         /* allocate memory */
141         swapdata = (char *)malloc(swapsize);
142         if (swapdata == NULL) {
143                 printf("fpga_loadbitstream: Could not allocate %d bytes memory !\n",swapsize);
144                 return FPGA_FAIL;
145         }
146
147         /* read data into memory and swap bits */
148         ptr = swapdata;
149         for (i = 0; i < swapsize; i++) {
150                 data = 0x00;
151                 data |= (*dataptr & 0x01) << 7;
152                 data |= (*dataptr & 0x02) << 5;
153                 data |= (*dataptr & 0x04) << 3;
154                 data |= (*dataptr & 0x08) << 1;
155                 data |= (*dataptr & 0x10) >> 1;
156                 data |= (*dataptr & 0x20) >> 3;
157                 data |= (*dataptr & 0x40) >> 5;
158                 data |= (*dataptr & 0x80) >> 7;
159                 *ptr++ = data;
160                 dataptr++;
161         }
162
163         rc = fpga_load(dev, swapdata, swapsize);
164         free(swapdata);
165         return rc;
166 #else
167         printf("Bitstream support only for Xilinx devices.\n");
168         return FPGA_FAIL;
169 #endif
170 }
171
172 /* ------------------------------------------------------------------------- */
173 /* command form:
174  *   fpga <op> <device number> <data addr> <datasize>
175  * where op is 'load', 'dump', or 'info'
176  * If there is no device number field, the fpga environment variable is used.
177  * If there is no data addr field, the fpgadata environment variable is used.
178  * The info command requires no data address field.
179  */
180 int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
181 {
182         int op, dev = FPGA_INVALID_DEVICE;
183         size_t data_size = 0;
184         void *fpga_data = NULL;
185         char *devstr = getenv ("fpga");
186         char *datastr = getenv ("fpgadata");
187         int rc = FPGA_FAIL;
188
189         if (devstr)
190                 dev = (int) simple_strtoul (devstr, NULL, 16);
191         if (datastr)
192                 fpga_data = (void *) simple_strtoul (datastr, NULL, 16);
193
194         switch (argc) {
195         case 5:         /* fpga <op> <dev> <data> <datasize> */
196                 data_size = simple_strtoul (argv[4], NULL, 16);
197         case 4:         /* fpga <op> <dev> <data> */
198                 fpga_data = (void *) simple_strtoul (argv[3], NULL, 16);
199                 PRINTF ("do_fpga: fpga_data = 0x%x\n",
200                         (uint) fpga_data);
201         case 3:         /* fpga <op> <dev | data addr> */
202                 dev = (int) simple_strtoul (argv[2], NULL, 16);
203                 PRINTF ("do_fpga: device = %d\n", dev);
204                 /* FIXME - this is a really weak test */
205                 if ((argc == 3) && (dev > fpga_count ())) {     /* must be buffer ptr */
206                         PRINTF ("do_fpga: Assuming buffer pointer in arg 3\n");
207                         fpga_data = (void *) dev;
208                         PRINTF ("do_fpga: 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 ("do_fpga: 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 */