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