]> git.ipfire.org Git - thirdparty/u-boot.git/blame - cmd/fpga.c
mmc: zynqmp: Add HS200 modes support for ZynqMP
[thirdparty/u-boot.git] / cmd / fpga.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
4a9cbbe8
WD
2/*
3 * (C) Copyright 2000, 2001
4 * Rich Ireland, Enterasys Networks, rireland@enterasys.com.
4a9cbbe8
WD
5 */
6
7/*
8 * FPGA support
9 */
10#include <common.h>
11#include <command.h>
8bde7f77 12#include <fpga.h>
1a897668 13#include <fs.h>
c3d2b4b4 14#include <malloc.h>
4a9cbbe8 15
4a9cbbe8 16/* Local functions */
fc598412 17static int fpga_get_op(char *opstr);
4a9cbbe8
WD
18
19/* Local defines */
5cf22289
MS
20enum {
21 FPGA_NONE = -1,
22 FPGA_INFO,
23 FPGA_LOAD,
24 FPGA_LOADB,
25 FPGA_DUMP,
26 FPGA_LOADMK,
27 FPGA_LOADP,
28 FPGA_LOADBP,
29 FPGA_LOADFS,
30};
4a9cbbe8
WD
31
32/* ------------------------------------------------------------------------- */
33/* command form:
34 * fpga <op> <device number> <data addr> <datasize>
35 * where op is 'load', 'dump', or 'info'
36 * If there is no device number field, the fpga environment variable is used.
37 * If there is no data addr field, the fpgadata environment variable is used.
38 * The info command requires no data address field.
39 */
fc598412 40int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
4a9cbbe8 41{
d4ca31c4
WD
42 int op, dev = FPGA_INVALID_DEVICE;
43 size_t data_size = 0;
44 void *fpga_data = NULL;
00caae6d
SG
45 char *devstr = env_get("fpga");
46 char *datastr = env_get("fpgadata");
d4ca31c4 47 int rc = FPGA_FAIL;
a790b5b2 48 int wrong_parms = 0;
fc598412 49#if defined(CONFIG_FIT)
c28c4d19
MB
50 const char *fit_uname = NULL;
51 ulong fit_addr;
52#endif
1a897668
SDPP
53#if defined(CONFIG_CMD_FPGA_LOADFS)
54 fpga_fs_info fpga_fsinfo;
55 fpga_fsinfo.fstype = FS_TYPE_ANY;
56#endif
d4ca31c4
WD
57
58 if (devstr)
fc598412 59 dev = (int) simple_strtoul(devstr, NULL, 16);
d4ca31c4 60 if (datastr)
fc598412 61 fpga_data = (void *)simple_strtoul(datastr, NULL, 16);
d4ca31c4
WD
62
63 switch (argc) {
1a897668
SDPP
64#if defined(CONFIG_CMD_FPGA_LOADFS)
65 case 9:
66 fpga_fsinfo.blocksize = (unsigned int)
67 simple_strtoul(argv[5], NULL, 16);
68 fpga_fsinfo.interface = argv[6];
69 fpga_fsinfo.dev_part = argv[7];
70 fpga_fsinfo.filename = argv[8];
71#endif
d4ca31c4 72 case 5: /* fpga <op> <dev> <data> <datasize> */
fc598412 73 data_size = simple_strtoul(argv[4], NULL, 16);
c28c4d19 74
d4ca31c4 75 case 4: /* fpga <op> <dev> <data> */
c28c4d19 76#if defined(CONFIG_FIT)
fc598412
MS
77 if (fit_parse_subimage(argv[3], (ulong)fpga_data,
78 &fit_addr, &fit_uname)) {
c28c4d19 79 fpga_data = (void *)fit_addr;
fc598412
MS
80 debug("* fpga: subimage '%s' from FIT image ",
81 fit_uname);
82 debug("at 0x%08lx\n", fit_addr);
c28c4d19
MB
83 } else
84#endif
85 {
fc598412 86 fpga_data = (void *)simple_strtoul(argv[3], NULL, 16);
06297db0 87 debug("* fpga: cmdline image address = 0x%08lx\n",
fc598412 88 (ulong)fpga_data);
c28c4d19 89 }
455ad585 90 debug("%s: fpga_data = 0x%lx\n", __func__, (ulong)fpga_data);
c28c4d19 91
d4ca31c4 92 case 3: /* fpga <op> <dev | data addr> */
fc598412 93 dev = (int)simple_strtoul(argv[2], NULL, 16);
06297db0 94 debug("%s: device = %d\n", __func__, dev);
d4ca31c4 95 /* FIXME - this is a really weak test */
fc598412
MS
96 if ((argc == 3) && (dev > fpga_count())) {
97 /* must be buffer ptr */
06297db0 98 debug("%s: Assuming buffer pointer in arg 3\n",
fc598412 99 __func__);
c28c4d19
MB
100
101#if defined(CONFIG_FIT)
fc598412
MS
102 if (fit_parse_subimage(argv[2], (ulong)fpga_data,
103 &fit_addr, &fit_uname)) {
c28c4d19 104 fpga_data = (void *)fit_addr;
fc598412
MS
105 debug("* fpga: subimage '%s' from FIT image ",
106 fit_uname);
107 debug("at 0x%08lx\n", fit_addr);
c28c4d19
MB
108 } else
109#endif
110 {
455ad585 111 fpga_data = (void *)(uintptr_t)dev;
fc598412
MS
112 debug("* fpga: cmdline image addr = 0x%08lx\n",
113 (ulong)fpga_data);
c28c4d19
MB
114 }
115
455ad585
MS
116 debug("%s: fpga_data = 0x%lx\n",
117 __func__, (ulong)fpga_data);
d4ca31c4
WD
118 dev = FPGA_INVALID_DEVICE; /* reset device num */
119 }
c28c4d19 120
d4ca31c4 121 case 2: /* fpga <op> */
fc598412 122 op = (int)fpga_get_op(argv[1]);
d4ca31c4 123 break;
c28c4d19 124
d4ca31c4 125 default:
fc598412 126 debug("%s: Too many or too few args (%d)\n", __func__, argc);
d4ca31c4
WD
127 op = FPGA_NONE; /* force usage display */
128 break;
129 }
130
a790b5b2
SB
131 if (dev == FPGA_INVALID_DEVICE) {
132 puts("FPGA device not specified\n");
133 op = FPGA_NONE;
134 }
135
136 switch (op) {
137 case FPGA_NONE:
138 case FPGA_INFO:
139 break;
1a897668
SDPP
140#if defined(CONFIG_CMD_FPGA_LOADFS)
141 case FPGA_LOADFS:
142 /* Blocksize can be zero */
143 if (!fpga_fsinfo.interface || !fpga_fsinfo.dev_part ||
144 !fpga_fsinfo.filename)
145 wrong_parms = 1;
146#endif
a790b5b2 147 case FPGA_LOAD:
67193864 148 case FPGA_LOADP:
a790b5b2 149 case FPGA_LOADB:
67193864 150 case FPGA_LOADBP:
a790b5b2
SB
151 case FPGA_DUMP:
152 if (!fpga_data || !data_size)
153 wrong_parms = 1;
154 break;
64e809af 155#if defined(CONFIG_CMD_FPGA_LOADMK)
a790b5b2
SB
156 case FPGA_LOADMK:
157 if (!fpga_data)
158 wrong_parms = 1;
159 break;
64e809af 160#endif
a790b5b2
SB
161 }
162
163 if (wrong_parms) {
164 puts("Wrong parameters for FPGA request\n");
165 op = FPGA_NONE;
166 }
167
d4ca31c4
WD
168 switch (op) {
169 case FPGA_NONE:
4c12eeb8 170 return CMD_RET_USAGE;
d4ca31c4
WD
171
172 case FPGA_INFO:
fc598412 173 rc = fpga_info(dev);
d4ca31c4
WD
174 break;
175
176 case FPGA_LOAD:
7a78bd26 177 rc = fpga_load(dev, fpga_data, data_size, BIT_FULL);
d4ca31c4
WD
178 break;
179
67193864
MS
180#if defined(CONFIG_CMD_FPGA_LOADP)
181 case FPGA_LOADP:
182 rc = fpga_load(dev, fpga_data, data_size, BIT_PARTIAL);
183 break;
184#endif
185
30ce5ab0 186 case FPGA_LOADB:
7a78bd26 187 rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_FULL);
30ce5ab0
WD
188 break;
189
67193864
MS
190#if defined(CONFIG_CMD_FPGA_LOADBP)
191 case FPGA_LOADBP:
192 rc = fpga_loadbitstream(dev, fpga_data, data_size, BIT_PARTIAL);
193 break;
194#endif
195
1a897668
SDPP
196#if defined(CONFIG_CMD_FPGA_LOADFS)
197 case FPGA_LOADFS:
198 rc = fpga_fsload(dev, fpga_data, data_size, &fpga_fsinfo);
199 break;
200#endif
201
64e809af 202#if defined(CONFIG_CMD_FPGA_LOADMK)
f0ff4692 203 case FPGA_LOADMK:
fc598412 204 switch (genimg_get_format(fpga_data)) {
21d29f7f 205#if defined(CONFIG_IMAGE_FORMAT_LEGACY)
d5934ad7
MB
206 case IMAGE_FORMAT_LEGACY:
207 {
fc598412
MS
208 image_header_t *hdr =
209 (image_header_t *)fpga_data;
210 ulong data;
32d7cdd3
MS
211 uint8_t comp;
212
213 comp = image_get_comp(hdr);
214 if (comp == IH_COMP_GZIP) {
1b63aaa5 215#if defined(CONFIG_GZIP)
32d7cdd3
MS
216 ulong image_buf = image_get_data(hdr);
217 data = image_get_load(hdr);
218 ulong image_size = ~0UL;
219
220 if (gunzip((void *)data, ~0UL,
221 (void *)image_buf,
222 &image_size) != 0) {
223 puts("GUNZIP: error\n");
224 return 1;
225 }
226 data_size = image_size;
1b63aaa5
MS
227#else
228 puts("Gunzip image is not supported\n");
229 return 1;
230#endif
32d7cdd3
MS
231 } else {
232 data = (ulong)image_get_data(hdr);
233 data_size = image_get_data_size(hdr);
234 }
7a78bd26
MS
235 rc = fpga_load(dev, (void *)data, data_size,
236 BIT_FULL);
f0ff4692 237 }
d5934ad7 238 break;
21d29f7f 239#endif
d5934ad7
MB
240#if defined(CONFIG_FIT)
241 case IMAGE_FORMAT_FIT:
c28c4d19
MB
242 {
243 const void *fit_hdr = (const void *)fpga_data;
244 int noffset;
e6a857da 245 const void *fit_data;
c28c4d19
MB
246
247 if (fit_uname == NULL) {
fc598412 248 puts("No FIT subimage unit name\n");
c28c4d19
MB
249 return 1;
250 }
251
fc598412
MS
252 if (!fit_check_format(fit_hdr)) {
253 puts("Bad FIT image format\n");
c28c4d19
MB
254 return 1;
255 }
256
257 /* get fpga component image node offset */
fc598412
MS
258 noffset = fit_image_get_node(fit_hdr,
259 fit_uname);
c28c4d19 260 if (noffset < 0) {
fc598412
MS
261 printf("Can't find '%s' FIT subimage\n",
262 fit_uname);
c28c4d19
MB
263 return 1;
264 }
265
266 /* verify integrity */
b8da8366 267 if (!fit_image_verify(fit_hdr, noffset)) {
c28c4d19
MB
268 puts ("Bad Data Hash\n");
269 return 1;
270 }
271
272 /* get fpga subimage data address and length */
fc598412
MS
273 if (fit_image_get_data(fit_hdr, noffset,
274 &fit_data, &data_size)) {
275 puts("Fpga subimage data not found\n");
c28c4d19
MB
276 return 1;
277 }
278
7a78bd26
MS
279 rc = fpga_load(dev, fit_data, data_size,
280 BIT_FULL);
c28c4d19 281 }
d5934ad7
MB
282 break;
283#endif
284 default:
fc598412 285 puts("** Unknown image type\n");
d5934ad7
MB
286 rc = FPGA_FAIL;
287 break;
f0ff4692
SR
288 }
289 break;
64e809af 290#endif
f0ff4692 291
d4ca31c4 292 case FPGA_DUMP:
fc598412 293 rc = fpga_dump(dev, fpga_data, data_size);
d4ca31c4
WD
294 break;
295
296 default:
fc598412 297 printf("Unknown operation\n");
4c12eeb8 298 return CMD_RET_USAGE;
d4ca31c4 299 }
fc598412 300 return rc;
4a9cbbe8
WD
301}
302
4a9cbbe8
WD
303/*
304 * Map op to supported operations. We don't use a table since we
305 * would just have to relocate it from flash anyway.
306 */
fc598412 307static int fpga_get_op(char *opstr)
4a9cbbe8
WD
308{
309 int op = FPGA_NONE;
310
fc598412 311 if (!strcmp("info", opstr))
4a9cbbe8 312 op = FPGA_INFO;
fc598412 313 else if (!strcmp("loadb", opstr))
30ce5ab0 314 op = FPGA_LOADB;
fc598412 315 else if (!strcmp("load", opstr))
4a9cbbe8 316 op = FPGA_LOAD;
67193864
MS
317#if defined(CONFIG_CMD_FPGA_LOADP)
318 else if (!strcmp("loadp", opstr))
319 op = FPGA_LOADP;
320#endif
321#if defined(CONFIG_CMD_FPGA_LOADBP)
322 else if (!strcmp("loadbp", opstr))
323 op = FPGA_LOADBP;
324#endif
1a897668
SDPP
325#if defined(CONFIG_CMD_FPGA_LOADFS)
326 else if (!strcmp("loadfs", opstr))
327 op = FPGA_LOADFS;
328#endif
64e809af 329#if defined(CONFIG_CMD_FPGA_LOADMK)
fc598412 330 else if (!strcmp("loadmk", opstr))
f0ff4692 331 op = FPGA_LOADMK;
64e809af 332#endif
fc598412 333 else if (!strcmp("dump", opstr))
4a9cbbe8 334 op = FPGA_DUMP;
4a9cbbe8 335
fc598412
MS
336 if (op == FPGA_NONE)
337 printf("Unknown fpga operation \"%s\"\n", opstr);
338
4a9cbbe8
WD
339 return op;
340}
341
1a897668
SDPP
342#if defined(CONFIG_CMD_FPGA_LOADFS)
343U_BOOT_CMD(fpga, 9, 1, do_fpga,
344#else
fc598412 345U_BOOT_CMD(fpga, 6, 1, do_fpga,
1a897668 346#endif
fc598412
MS
347 "loadable FPGA image support",
348 "[operation type] [device number] [image address] [image size]\n"
349 "fpga operations:\n"
2d73f0d6 350 " dump\t[dev] [address] [size]\tLoad device to memory buffer\n"
fc598412
MS
351 " info\t[dev]\t\t\tlist known device information\n"
352 " load\t[dev] [address] [size]\tLoad device from memory buffer\n"
67193864
MS
353#if defined(CONFIG_CMD_FPGA_LOADP)
354 " loadp\t[dev] [address] [size]\t"
355 "Load device from memory buffer with partial bitstream\n"
356#endif
fc598412
MS
357 " loadb\t[dev] [address] [size]\t"
358 "Load device from bitstream buffer (Xilinx only)\n"
67193864
MS
359#if defined(CONFIG_CMD_FPGA_LOADBP)
360 " loadbp\t[dev] [address] [size]\t"
361 "Load device from bitstream buffer with partial bitstream"
362 "(Xilinx only)\n"
363#endif
1a897668
SDPP
364#if defined(CONFIG_CMD_FPGA_LOADFS)
365 "Load device from filesystem (FAT by default) (Xilinx only)\n"
366 " loadfs [dev] [address] [image size] [blocksize] <interface>\n"
367 " [<dev[:part]>] <filename>\n"
368#endif
64e809af 369#if defined(CONFIG_CMD_FPGA_LOADMK)
fc598412 370 " loadmk [dev] [address]\tLoad device generated with mkimage"
c28c4d19 371#if defined(CONFIG_FIT)
fc598412
MS
372 "\n"
373 "\tFor loadmk operating on FIT format uImage address must include\n"
374 "\tsubimage unit name in the form of addr:<subimg_uname>"
c28c4d19 375#endif
64e809af 376#endif
c28c4d19 377);