Blame view

common/cmd_fpga.c 9.44 KB
4a9cbbe83   wdenk   Initial revision
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  /*
   * (C) Copyright 2000, 2001
   * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
   *
   * See file CREDITS for list of people who contributed to this
   * project.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License as
   * published by the Free Software Foundation; either version 2 of
   * the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
   * MA 02111-1307 USA
   *
   */
  
  /*
   *  FPGA support
   */
  #include <common.h>
  #include <command.h>
baa26db41   Jon Loeliger   common/cmd_[af]*:...
30
  #if defined(CONFIG_CMD_NET)
4a9cbbe83   wdenk   Initial revision
31
32
  #include <net.h>
  #endif
8bde7f776   wdenk   * Code cleanup:
33
  #include <fpga.h>
c3d2b4b48   wdenk   Code cleanup.
34
  #include <malloc.h>
4a9cbbe83   wdenk   Initial revision
35

4a9cbbe83   wdenk   Initial revision
36
  /* Local functions */
d4ca31c40   wdenk   * Cleanup lowboot...
37
  static int fpga_get_op (char *opstr);
4a9cbbe83   wdenk   Initial revision
38
39
40
41
42
  
  /* Local defines */
  #define FPGA_NONE   -1
  #define FPGA_INFO   0
  #define FPGA_LOAD   1
30ce5ab04   wdenk   * Patch by Gleb N...
43
  #define FPGA_LOADB  2
4a9cbbe83   wdenk   Initial revision
44
  #define FPGA_DUMP   3
f0ff4692f   Stefan Roese   Add FPGA Altera C...
45
  #define FPGA_LOADMK 4
4a9cbbe83   wdenk   Initial revision
46

30ce5ab04   wdenk   * Patch by Gleb N...
47
48
49
  /* Convert bitstream data and load into the fpga */
  int fpga_loadbitstream(unsigned long dev, char* fpgadata, size_t size)
  {
0133502e3   Matthias Fuchs   Improve configura...
50
  #if defined(CONFIG_FPGA_XILINX)
8b019da65   Wolfgang Denk   Fix sign extensio...
51
  	unsigned int length;
8b019da65   Wolfgang Denk   Fix sign extensio...
52
  	unsigned int swapsize;
30ce5ab04   wdenk   * Patch by Gleb N...
53
  	char buffer[80];
8b019da65   Wolfgang Denk   Fix sign extensio...
54
  	unsigned char *dataptr;
8b019da65   Wolfgang Denk   Fix sign extensio...
55
  	unsigned int i;
30ce5ab04   wdenk   * Patch by Gleb N...
56
  	int rc;
77ddac948   Wolfgang Denk   Cleanup for GCC-4.x
57
  	dataptr = (unsigned char *)fpgadata;
30ce5ab04   wdenk   * Patch by Gleb N...
58

8b019da65   Wolfgang Denk   Fix sign extensio...
59
60
61
62
  	/* skip the first bytes of the bitsteam, their meaning is unknown */
  	length = (*dataptr << 8) + *(dataptr+1);
  	dataptr+=2;
  	dataptr+=length;
30ce5ab04   wdenk   * Patch by Gleb N...
63
64
  
  	/* get design name (identifier, length, string) */
8b019da65   Wolfgang Denk   Fix sign extensio...
65
66
  	length = (*dataptr << 8) + *(dataptr+1);
  	dataptr+=2;
30ce5ab04   wdenk   * Patch by Gleb N...
67
  	if (*dataptr++ != 0x61) {
06297db06   Stefano Babic   FPGA: use debug()...
68
69
70
71
  		debug("%s: Design name identifier not recognized "
  			"in bitstream
  ",
  			__func__);
30ce5ab04   wdenk   * Patch by Gleb N...
72
73
  		return FPGA_FAIL;
  	}
a562e1bd9   wdenk   Patch by Florian ...
74
  	length = (*dataptr << 8) + *(dataptr+1);
30ce5ab04   wdenk   * Patch by Gleb N...
75
76
  	dataptr+=2;
  	for(i=0;i<length;i++)
d0ff51ba5   Wolfgang Denk   Code cleanup: fix...
77
  		buffer[i] = *dataptr++;
a562e1bd9   wdenk   Patch by Florian ...
78

8b019da65   Wolfgang Denk   Fix sign extensio...
79
80
  	printf("  design filename = \"%s\"
  ", buffer);
30ce5ab04   wdenk   * Patch by Gleb N...
81
82
83
  
  	/* get part number (identifier, length, string) */
  	if (*dataptr++ != 0x62) {
06297db06   Stefano Babic   FPGA: use debug()...
84
85
86
87
  		printf("%s: Part number identifier not recognized "
  			"in bitstream
  ",
  			__func__);
30ce5ab04   wdenk   * Patch by Gleb N...
88
89
  		return FPGA_FAIL;
  	}
a562e1bd9   wdenk   Patch by Florian ...
90

8b019da65   Wolfgang Denk   Fix sign extensio...
91
92
  	length = (*dataptr << 8) + *(dataptr+1);
  	dataptr+=2;
a562e1bd9   wdenk   Patch by Florian ...
93
  	for(i=0;i<length;i++)
d0ff51ba5   Wolfgang Denk   Code cleanup: fix...
94
  		buffer[i] = *dataptr++;
8b019da65   Wolfgang Denk   Fix sign extensio...
95
96
  	printf("  part number = \"%s\"
  ", buffer);
a562e1bd9   wdenk   Patch by Florian ...
97

30ce5ab04   wdenk   * Patch by Gleb N...
98
99
  	/* get date (identifier, length, string) */
  	if (*dataptr++ != 0x63) {
8b019da65   Wolfgang Denk   Fix sign extensio...
100
101
  		printf("%s: Date identifier not recognized in bitstream
  ",
06297db06   Stefano Babic   FPGA: use debug()...
102
  		       __func__);
30ce5ab04   wdenk   * Patch by Gleb N...
103
104
  		return FPGA_FAIL;
  	}
a562e1bd9   wdenk   Patch by Florian ...
105

8b019da65   Wolfgang Denk   Fix sign extensio...
106
107
  	length = (*dataptr << 8) + *(dataptr+1);
  	dataptr+=2;
30ce5ab04   wdenk   * Patch by Gleb N...
108
  	for(i=0;i<length;i++)
d0ff51ba5   Wolfgang Denk   Code cleanup: fix...
109
  		buffer[i] = *dataptr++;
8b019da65   Wolfgang Denk   Fix sign extensio...
110
111
  	printf("  date = \"%s\"
  ", buffer);
30ce5ab04   wdenk   * Patch by Gleb N...
112
113
114
  
  	/* get time (identifier, length, string) */
  	if (*dataptr++ != 0x64) {
06297db06   Stefano Babic   FPGA: use debug()...
115
116
117
  		printf("%s: Time identifier not recognized in bitstream
  ",
  			__func__);
30ce5ab04   wdenk   * Patch by Gleb N...
118
119
  		return FPGA_FAIL;
  	}
a562e1bd9   wdenk   Patch by Florian ...
120

8b019da65   Wolfgang Denk   Fix sign extensio...
121
122
  	length = (*dataptr << 8) + *(dataptr+1);
  	dataptr+=2;
30ce5ab04   wdenk   * Patch by Gleb N...
123
  	for(i=0;i<length;i++)
d0ff51ba5   Wolfgang Denk   Code cleanup: fix...
124
  		buffer[i] = *dataptr++;
8b019da65   Wolfgang Denk   Fix sign extensio...
125
126
  	printf("  time = \"%s\"
  ", buffer);
a562e1bd9   wdenk   Patch by Florian ...
127

30ce5ab04   wdenk   * Patch by Gleb N...
128
129
  	/* get fpga data length (identifier, length) */
  	if (*dataptr++ != 0x65) {
8b019da65   Wolfgang Denk   Fix sign extensio...
130
131
  		printf("%s: Data length identifier not recognized in bitstream
  ",
06297db06   Stefano Babic   FPGA: use debug()...
132
  			__func__);
30ce5ab04   wdenk   * Patch by Gleb N...
133
134
  		return FPGA_FAIL;
  	}
8f79e4c2d   Wolfgang Denk   Add configuration...
135
136
137
  	swapsize = ((unsigned int) *dataptr     <<24) +
  	           ((unsigned int) *(dataptr+1) <<16) +
  	           ((unsigned int) *(dataptr+2) <<8 ) +
8b019da65   Wolfgang Denk   Fix sign extensio...
138
  	           ((unsigned int) *(dataptr+3)     ) ;
30ce5ab04   wdenk   * Patch by Gleb N...
139
  	dataptr+=4;
8b019da65   Wolfgang Denk   Fix sign extensio...
140
141
  	printf("  bytes in bitstream = %d
  ", swapsize);
a562e1bd9   wdenk   Patch by Florian ...
142

c26acc1a4   Matthias Fuchs   Remove bit swappi...
143
  	rc = fpga_load(dev, dataptr, swapsize);
30ce5ab04   wdenk   * Patch by Gleb N...
144
145
  	return rc;
  #else
8b019da65   Wolfgang Denk   Fix sign extensio...
146
147
  	printf("Bitstream support only for Xilinx devices
  ");
30ce5ab04   wdenk   * Patch by Gleb N...
148
149
150
  	return FPGA_FAIL;
  #endif
  }
4a9cbbe83   wdenk   Initial revision
151
152
153
154
155
156
157
158
  /* ------------------------------------------------------------------------- */
  /* command form:
   *   fpga <op> <device number> <data addr> <datasize>
   * where op is 'load', 'dump', or 'info'
   * If there is no device number field, the fpga environment variable is used.
   * If there is no data addr field, the fpgadata environment variable is used.
   * The info command requires no data address field.
   */
54841ab50   Wolfgang Denk   Make sure that ar...
159
  int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
4a9cbbe83   wdenk   Initial revision
160
  {
d4ca31c40   wdenk   * Cleanup lowboot...
161
162
163
164
165
166
  	int op, dev = FPGA_INVALID_DEVICE;
  	size_t data_size = 0;
  	void *fpga_data = NULL;
  	char *devstr = getenv ("fpga");
  	char *datastr = getenv ("fpgadata");
  	int rc = FPGA_FAIL;
a790b5b23   Stefano Babic   cmd_fpga: cleanup...
167
  	int wrong_parms = 0;
c28c4d193   Marian Balakowicz   [new uImage] Add ...
168
169
170
171
  #if defined (CONFIG_FIT)
  	const char *fit_uname = NULL;
  	ulong fit_addr;
  #endif
d4ca31c40   wdenk   * Cleanup lowboot...
172
173
174
175
176
177
178
179
180
  
  	if (devstr)
  		dev = (int) simple_strtoul (devstr, NULL, 16);
  	if (datastr)
  		fpga_data = (void *) simple_strtoul (datastr, NULL, 16);
  
  	switch (argc) {
  	case 5:		/* fpga <op> <dev> <data> <datasize> */
  		data_size = simple_strtoul (argv[4], NULL, 16);
c28c4d193   Marian Balakowicz   [new uImage] Add ...
181

d4ca31c40   wdenk   * Cleanup lowboot...
182
  	case 4:		/* fpga <op> <dev> <data> */
c28c4d193   Marian Balakowicz   [new uImage] Add ...
183
184
185
186
  #if defined(CONFIG_FIT)
  		if (fit_parse_subimage (argv[3], (ulong)fpga_data,
  					&fit_addr, &fit_uname)) {
  			fpga_data = (void *)fit_addr;
06297db06   Stefano Babic   FPGA: use debug()...
187
188
189
190
  			debug("*  fpga: subimage '%s' from FIT image "
  				"at 0x%08lx
  ",
  				fit_uname, fit_addr);
c28c4d193   Marian Balakowicz   [new uImage] Add ...
191
192
193
194
  		} else
  #endif
  		{
  			fpga_data = (void *) simple_strtoul (argv[3], NULL, 16);
06297db06   Stefano Babic   FPGA: use debug()...
195
196
197
  			debug("*  fpga: cmdline image address = 0x%08lx
  ",
  				(ulong)fpga_data);
c28c4d193   Marian Balakowicz   [new uImage] Add ...
198
  		}
06297db06   Stefano Babic   FPGA: use debug()...
199
200
  		debug("%s: fpga_data = 0x%x
  ", __func__, (uint) fpga_data);
c28c4d193   Marian Balakowicz   [new uImage] Add ...
201

d4ca31c40   wdenk   * Cleanup lowboot...
202
203
  	case 3:		/* fpga <op> <dev | data addr> */
  		dev = (int) simple_strtoul (argv[2], NULL, 16);
06297db06   Stefano Babic   FPGA: use debug()...
204
205
  		debug("%s: device = %d
  ", __func__, dev);
d4ca31c40   wdenk   * Cleanup lowboot...
206
207
  		/* FIXME - this is a really weak test */
  		if ((argc == 3) && (dev > fpga_count ())) {	/* must be buffer ptr */
06297db06   Stefano Babic   FPGA: use debug()...
208
209
210
  			debug("%s: Assuming buffer pointer in arg 3
  ",
  				__func__);
c28c4d193   Marian Balakowicz   [new uImage] Add ...
211
212
213
214
215
  
  #if defined(CONFIG_FIT)
  			if (fit_parse_subimage (argv[2], (ulong)fpga_data,
  						&fit_addr, &fit_uname)) {
  				fpga_data = (void *)fit_addr;
06297db06   Stefano Babic   FPGA: use debug()...
216
217
218
219
  				debug("*  fpga: subimage '%s' from FIT image "
  					"at 0x%08lx
  ",
  					fit_uname, fit_addr);
c28c4d193   Marian Balakowicz   [new uImage] Add ...
220
221
222
223
  			} else
  #endif
  			{
  				fpga_data = (void *) dev;
06297db06   Stefano Babic   FPGA: use debug()...
224
225
226
  				debug("*  fpga: cmdline image address = "
  					"0x%08lx
  ", (ulong)fpga_data);
c28c4d193   Marian Balakowicz   [new uImage] Add ...
227
  			}
06297db06   Stefano Babic   FPGA: use debug()...
228
229
230
  			debug("%s: fpga_data = 0x%x
  ",
  				__func__, (uint) fpga_data);
d4ca31c40   wdenk   * Cleanup lowboot...
231
232
  			dev = FPGA_INVALID_DEVICE;	/* reset device num */
  		}
c28c4d193   Marian Balakowicz   [new uImage] Add ...
233

d4ca31c40   wdenk   * Cleanup lowboot...
234
235
236
  	case 2:		/* fpga <op> */
  		op = (int) fpga_get_op (argv[1]);
  		break;
c28c4d193   Marian Balakowicz   [new uImage] Add ...
237

d4ca31c40   wdenk   * Cleanup lowboot...
238
  	default:
06297db06   Stefano Babic   FPGA: use debug()...
239
240
241
  		debug("%s: Too many or too few args (%d)
  ",
  			__func__, argc);
d4ca31c40   wdenk   * Cleanup lowboot...
242
243
244
  		op = FPGA_NONE;	/* force usage display */
  		break;
  	}
a790b5b23   Stefano Babic   cmd_fpga: cleanup...
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
  	if (dev == FPGA_INVALID_DEVICE) {
  		puts("FPGA device not specified
  ");
  		op = FPGA_NONE;
  	}
  
  	switch (op) {
  	case FPGA_NONE:
  	case FPGA_INFO:
  		break;
  	case FPGA_LOAD:
  	case FPGA_LOADB:
  	case FPGA_DUMP:
  		if (!fpga_data || !data_size)
  			wrong_parms = 1;
  		break;
  	case FPGA_LOADMK:
  		if (!fpga_data)
  			wrong_parms = 1;
  		break;
  	}
  
  	if (wrong_parms) {
  		puts("Wrong parameters for FPGA request
  ");
  		op = FPGA_NONE;
  	}
d4ca31c40   wdenk   * Cleanup lowboot...
272
273
  	switch (op) {
  	case FPGA_NONE:
4c12eeb8b   Simon Glass   Convert cmd_usage...
274
  		return CMD_RET_USAGE;
d4ca31c40   wdenk   * Cleanup lowboot...
275
276
277
278
279
280
281
282
  
  	case FPGA_INFO:
  		rc = fpga_info (dev);
  		break;
  
  	case FPGA_LOAD:
  		rc = fpga_load (dev, fpga_data, data_size);
  		break;
30ce5ab04   wdenk   * Patch by Gleb N...
283
284
285
  	case FPGA_LOADB:
  		rc = fpga_loadbitstream(dev, fpga_data, data_size);
  		break;
f0ff4692f   Stefan Roese   Add FPGA Altera C...
286
  	case FPGA_LOADMK:
9a4daad0a   Marian Balakowicz   [new uImage] Upda...
287
  		switch (genimg_get_format (fpga_data)) {
d5934ad77   Marian Balakowicz   [new uImage] Add ...
288
289
290
291
  		case IMAGE_FORMAT_LEGACY:
  			{
  				image_header_t *hdr = (image_header_t *)fpga_data;
  				ulong	data;
d5934ad77   Marian Balakowicz   [new uImage] Add ...
292
293
294
  				data = (ulong)image_get_data (hdr);
  				data_size = image_get_data_size (hdr);
  				rc = fpga_load (dev, (void *)data, data_size);
f0ff4692f   Stefan Roese   Add FPGA Altera C...
295
  			}
d5934ad77   Marian Balakowicz   [new uImage] Add ...
296
297
298
  			break;
  #if defined(CONFIG_FIT)
  		case IMAGE_FORMAT_FIT:
c28c4d193   Marian Balakowicz   [new uImage] Add ...
299
300
301
  			{
  				const void *fit_hdr = (const void *)fpga_data;
  				int noffset;
e6a857da7   Wolfgang Denk   fpga: constify to...
302
  				const void *fit_data;
c28c4d193   Marian Balakowicz   [new uImage] Add ...
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
  
  				if (fit_uname == NULL) {
  					puts ("No FIT subimage unit name
  ");
  					return 1;
  				}
  
  				if (!fit_check_format (fit_hdr)) {
  					puts ("Bad FIT image format
  ");
  					return 1;
  				}
  
  				/* get fpga component image node offset */
  				noffset = fit_image_get_node (fit_hdr, fit_uname);
  				if (noffset < 0) {
  					printf ("Can't find '%s' FIT subimage
  ", fit_uname);
  					return 1;
  				}
  
  				/* verify integrity */
  				if (!fit_image_check_hashes (fit_hdr, noffset)) {
  					puts ("Bad Data Hash
  ");
  					return 1;
  				}
  
  				/* get fpga subimage data address and length */
  				if (fit_image_get_data (fit_hdr, noffset, &fit_data, &data_size)) {
  					puts ("Could not find fpga subimage data
  ");
  					return 1;
  				}
  
  				rc = fpga_load (dev, fit_data, data_size);
  			}
d5934ad77   Marian Balakowicz   [new uImage] Add ...
340
341
342
343
344
345
346
  			break;
  #endif
  		default:
  			puts ("** Unknown image type
  ");
  			rc = FPGA_FAIL;
  			break;
f0ff4692f   Stefan Roese   Add FPGA Altera C...
347
348
  		}
  		break;
d4ca31c40   wdenk   * Cleanup lowboot...
349
350
351
352
353
  	case FPGA_DUMP:
  		rc = fpga_dump (dev, fpga_data, data_size);
  		break;
  
  	default:
8b019da65   Wolfgang Denk   Fix sign extensio...
354
355
  		printf ("Unknown operation
  ");
4c12eeb8b   Simon Glass   Convert cmd_usage...
356
  		return CMD_RET_USAGE;
d4ca31c40   wdenk   * Cleanup lowboot...
357
358
  	}
  	return (rc);
4a9cbbe83   wdenk   Initial revision
359
  }
4a9cbbe83   wdenk   Initial revision
360
361
362
363
  /*
   * Map op to supported operations.  We don't use a table since we
   * would just have to relocate it from flash anyway.
   */
d4ca31c40   wdenk   * Cleanup lowboot...
364
  static int fpga_get_op (char *opstr)
4a9cbbe83   wdenk   Initial revision
365
366
367
368
369
  {
  	int op = FPGA_NONE;
  
  	if (!strcmp ("info", opstr)) {
  		op = FPGA_INFO;
30ce5ab04   wdenk   * Patch by Gleb N...
370
371
  	} else if (!strcmp ("loadb", opstr)) {
  		op = FPGA_LOADB;
d4ca31c40   wdenk   * Cleanup lowboot...
372
  	} else if (!strcmp ("load", opstr)) {
4a9cbbe83   wdenk   Initial revision
373
  		op = FPGA_LOAD;
f0ff4692f   Stefan Roese   Add FPGA Altera C...
374
375
  	} else if (!strcmp ("loadmk", opstr)) {
  		op = FPGA_LOADMK;
d4ca31c40   wdenk   * Cleanup lowboot...
376
  	} else if (!strcmp ("dump", opstr)) {
4a9cbbe83   wdenk   Initial revision
377
378
  		op = FPGA_DUMP;
  	}
d4ca31c40   wdenk   * Cleanup lowboot...
379
  	if (op == FPGA_NONE) {
4a9cbbe83   wdenk   Initial revision
380
381
382
383
384
  		printf ("Unknown fpga operation \"%s\"
  ", opstr);
  	}
  	return op;
  }
d4ca31c40   wdenk   * Cleanup lowboot...
385
  U_BOOT_CMD (fpga, 6, 1, do_fpga,
a790b5b23   Stefano Babic   cmd_fpga: cleanup...
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
  	"loadable FPGA image support",
  	"[operation type] [device number] [image address] [image size]
  "
  	"fpga operations:
  "
  	"  dump\t[dev]\t\t\tLoad device to memory buffer
  "
  	"  info\t[dev]\t\t\tlist known device information
  "
  	"  load\t[dev] [address] [size]\tLoad device from memory buffer
  "
  	"  loadb\t[dev] [address] [size]\t"
  	"Load device from bitstream buffer (Xilinx only)
  "
  	"  loadmk [dev] [address]\tLoad device generated with mkimage"
c28c4d193   Marian Balakowicz   [new uImage] Add ...
401
  #if defined(CONFIG_FIT)
a790b5b23   Stefano Babic   cmd_fpga: cleanup...
402
403
404
405
406
  	"
  "
  	"\tFor loadmk operating on FIT format uImage address must include
  "
  	"\tsubimage unit name in the form of addr:<subimg_uname>"
c28c4d193   Marian Balakowicz   [new uImage] Add ...
407
408
  #endif
  );