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