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