diff --git a/common/cmd_fpga.c b/common/cmd_fpga.c index 802f3ecfff..bda5c8f798 100644 --- a/common/cmd_fpga.c +++ b/common/cmd_fpga.c @@ -11,6 +11,7 @@ #include #include #include +#include #include /* Local functions */ @@ -25,6 +26,7 @@ static int fpga_get_op(char *opstr); #define FPGA_LOADMK 4 #define FPGA_LOADP 5 #define FPGA_LOADBP 6 +#define FPGA_LOADFS 7 /* ------------------------------------------------------------------------- */ /* command form: @@ -47,6 +49,10 @@ int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) const char *fit_uname = NULL; ulong fit_addr; #endif +#if defined(CONFIG_CMD_FPGA_LOADFS) + fpga_fs_info fpga_fsinfo; + fpga_fsinfo.fstype = FS_TYPE_ANY; +#endif if (devstr) dev = (int) simple_strtoul(devstr, NULL, 16); @@ -54,6 +60,14 @@ int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) fpga_data = (void *)simple_strtoul(datastr, NULL, 16); switch (argc) { +#if defined(CONFIG_CMD_FPGA_LOADFS) + case 9: + fpga_fsinfo.blocksize = (unsigned int) + simple_strtoul(argv[5], NULL, 16); + fpga_fsinfo.interface = argv[6]; + fpga_fsinfo.dev_part = argv[7]; + fpga_fsinfo.filename = argv[8]; +#endif case 5: /* fpga */ data_size = simple_strtoul(argv[4], NULL, 16); @@ -122,6 +136,13 @@ int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) case FPGA_NONE: case FPGA_INFO: break; +#if defined(CONFIG_CMD_FPGA_LOADFS) + case FPGA_LOADFS: + /* Blocksize can be zero */ + if (!fpga_fsinfo.interface || !fpga_fsinfo.dev_part || + !fpga_fsinfo.filename) + wrong_parms = 1; +#endif case FPGA_LOAD: case FPGA_LOADP: case FPGA_LOADB: @@ -171,6 +192,12 @@ int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) break; #endif +#if defined(CONFIG_CMD_FPGA_LOADFS) + case FPGA_LOADFS: + rc = fpga_fsload(dev, fpga_data, data_size, &fpga_fsinfo); + break; +#endif + #if defined(CONFIG_CMD_FPGA_LOADMK) case FPGA_LOADMK: switch (genimg_get_format(fpga_data)) { @@ -287,6 +314,10 @@ static int fpga_get_op(char *opstr) else if (!strcmp("loadbp", opstr)) op = FPGA_LOADBP; #endif +#if defined(CONFIG_CMD_FPGA_LOADFS) + else if (!strcmp("loadfs", opstr)) + op = FPGA_LOADFS; +#endif #if defined(CONFIG_CMD_FPGA_LOADMK) else if (!strcmp("loadmk", opstr)) op = FPGA_LOADMK; @@ -300,7 +331,11 @@ static int fpga_get_op(char *opstr) return op; } +#if defined(CONFIG_CMD_FPGA_LOADFS) +U_BOOT_CMD(fpga, 9, 1, do_fpga, +#else U_BOOT_CMD(fpga, 6, 1, do_fpga, +#endif "loadable FPGA image support", "[operation type] [device number] [image address] [image size]\n" "fpga operations:\n" @@ -318,6 +353,11 @@ U_BOOT_CMD(fpga, 6, 1, do_fpga, "Load device from bitstream buffer with partial bitstream" "(Xilinx only)\n" #endif +#if defined(CONFIG_CMD_FPGA_LOADFS) + "Load device from filesystem (FAT by default) (Xilinx only)\n" + " loadfs [dev] [address] [image size] [blocksize] \n" + " [] \n" +#endif #if defined(CONFIG_CMD_FPGA_LOADMK) " loadmk [dev] [address]\tLoad device generated with mkimage" #if defined(CONFIG_FIT) diff --git a/drivers/fpga/fpga.c b/drivers/fpga/fpga.c index e770950909..37946d5e18 100644 --- a/drivers/fpga/fpga.c +++ b/drivers/fpga/fpga.c @@ -180,6 +180,34 @@ int __weak fpga_loadbitstream(int devnum, char *fpgadata, size_t size, return FPGA_FAIL; } +#if defined(CONFIG_CMD_FPGA_LOADFS) +int fpga_fsload(int devnum, const void *buf, size_t size, + fpga_fs_info *fpga_fsinfo) +{ + int ret_val = FPGA_FAIL; /* assume failure */ + const fpga_desc *desc = fpga_validate(devnum, buf, size, + (char *)__func__); + + if (desc) { + switch (desc->devtype) { + case fpga_xilinx: +#if defined(CONFIG_FPGA_XILINX) + ret_val = xilinx_loadfs(desc->devdesc, buf, size, + fpga_fsinfo); +#else + fpga_no_sup((char *)__func__, "Xilinx devices"); +#endif + break; + default: + printf("%s: Invalid or unsupported device type %d\n", + __func__, desc->devtype); + } + } + + return ret_val; +} +#endif + /* * Generic multiplexing code */ diff --git a/drivers/fpga/xilinx.c b/drivers/fpga/xilinx.c index ab9f51733e..3795c1aff6 100644 --- a/drivers/fpga/xilinx.c +++ b/drivers/fpga/xilinx.c @@ -142,6 +142,22 @@ int xilinx_load(xilinx_desc *desc, const void *buf, size_t bsize, return desc->operations->load(desc, buf, bsize, bstype); } +#if defined(CONFIG_CMD_FPGA_LOADFS) +int xilinx_loadfs(xilinx_desc *desc, const void *buf, size_t bsize, + fpga_fs_info *fpga_fsinfo) +{ + if (!xilinx_validate(desc, (char *)__func__)) { + printf("%s: Invalid device descriptor\n", __func__); + return FPGA_FAIL; + } + + if (!desc->operations->loadfs) + return FPGA_FAIL; + + return desc->operations->loadfs(desc, buf, bsize, fpga_fsinfo); +} +#endif + int xilinx_dump(xilinx_desc *desc, const void *buf, size_t bsize) { if (!xilinx_validate (desc, (char *)__FUNCTION__)) { diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c index 915f07735a..68fe0f3b03 100644 --- a/drivers/fpga/zynqpl.c +++ b/drivers/fpga/zynqpl.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -398,6 +399,87 @@ static int zynq_load(xilinx_desc *desc, const void *buf, size_t bsize, return FPGA_SUCCESS; } +#if defined(CONFIG_CMD_FPGA_LOADFS) +static int zynq_loadfs(xilinx_desc *desc, const void *buf, size_t bsize, + fpga_fs_info *fsinfo) +{ + unsigned long ts; /* Timestamp */ + u32 isr_status, swap; + u32 partialbit = 0; + u32 blocksize; + u32 pos = 0; + int fstype; + char *interface, *dev_part, *filename; + + blocksize = fsinfo->blocksize; + interface = fsinfo->interface; + dev_part = fsinfo->dev_part; + filename = fsinfo->filename; + fstype = fsinfo->fstype; + + if (fs_set_blk_dev(interface, dev_part, fstype)) + return FPGA_FAIL; + + if (fs_read(filename, (u32) buf, pos, blocksize) < 0) + return FPGA_FAIL; + + if (zynq_validate_bitstream(desc, buf, bsize, blocksize, &swap, + &partialbit)) + return FPGA_FAIL; + + dcache_disable(); + + do { + buf = zynq_align_dma_buffer((u32 *)buf, blocksize, swap); + + if (zynq_dma_transfer((u32)buf | 1, blocksize >> 2, + 0xffffffff, 0)) + return FPGA_FAIL; + + bsize -= blocksize; + pos += blocksize; + + if (fs_set_blk_dev(interface, dev_part, fstype)) + return FPGA_FAIL; + + if (bsize > blocksize) { + if (fs_read(filename, (u32) buf, pos, blocksize) < 0) + return FPGA_FAIL; + } else { + if (fs_read(filename, (u32) buf, pos, bsize) < 0) + return FPGA_FAIL; + } + } while (bsize > blocksize); + + buf = zynq_align_dma_buffer((u32 *)buf, blocksize, swap); + + if (zynq_dma_transfer((u32)buf | 1, bsize >> 2, 0xffffffff, 0)) + return FPGA_FAIL; + + dcache_enable(); + + isr_status = readl(&devcfg_base->int_sts); + + /* Check FPGA configuration completion */ + ts = get_timer(0); + while (!(isr_status & DEVCFG_ISR_PCFG_DONE)) { + if (get_timer(ts) > CONFIG_SYS_FPGA_WAIT) { + printf("%s: Timeout wait for FPGA to config\n", + __func__); + return FPGA_FAIL; + } + isr_status = readl(&devcfg_base->int_sts); + } + + debug("%s: FPGA config done\n", __func__); + + if (!partialbit) + zynq_slcr_devcfg_enable(); + + return FPGA_SUCCESS; +} +#endif + static int zynq_dump(xilinx_desc *desc, const void *buf, size_t bsize) { return FPGA_FAIL; @@ -405,6 +487,9 @@ static int zynq_dump(xilinx_desc *desc, const void *buf, size_t bsize) struct xilinx_fpga_op zynq_op = { .load = zynq_load, +#if defined(CONFIG_CMD_FPGA_LOADFS) + .loadfs = zynq_loadfs, +#endif .dump = zynq_dump, .info = zynq_info, }; diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h index fb600b8605..97632452f8 100644 --- a/include/configs/zynq-common.h +++ b/include/configs/zynq-common.h @@ -194,6 +194,7 @@ #define CONFIG_CMD_FPGA_LOADMK #define CONFIG_CMD_FPGA_LOADP #define CONFIG_CMD_FPGA_LOADBP +#define CONFIG_CMD_FPGA_LOADFS /* Open Firmware flat tree */ #define CONFIG_OF_LIBFDT diff --git a/include/fpga.h b/include/fpga.h index 49efd375f7..914024c17c 100644 --- a/include/fpga.h +++ b/include/fpga.h @@ -35,6 +35,13 @@ typedef struct { /* typedef fpga_desc */ void *devdesc; /* real device descriptor */ } fpga_desc; /* end, typedef fpga_desc */ +typedef struct { /* typedef fpga_desc */ + unsigned int blocksize; + char *interface; + char *dev_part; + char *filename; + int fstype; +} fpga_fs_info; typedef enum { BIT_FULL = 0, @@ -47,6 +54,8 @@ extern int fpga_add(fpga_type devtype, void *desc); extern int fpga_count(void); extern int fpga_load(int devnum, const void *buf, size_t bsize, bitstream_type bstype); +extern int fpga_fsload(int devnum, const void *buf, size_t size, + fpga_fs_info *fpga_fsinfo); extern int fpga_loadbitstream(int devnum, char *fpgadata, size_t size, bitstream_type bstype); extern int fpga_dump(int devnum, const void *buf, size_t bsize); diff --git a/include/xilinx.h b/include/xilinx.h index 7d83ba2095..aebcb3bfdf 100644 --- a/include/xilinx.h +++ b/include/xilinx.h @@ -46,6 +46,7 @@ typedef struct { /* typedef xilinx_desc */ struct xilinx_fpga_op { int (*load)(xilinx_desc *, const void *, size_t, bitstream_type); + int (*loadfs)(xilinx_desc *, const void *, size_t, fpga_fs_info *); int (*dump)(xilinx_desc *, const void *, size_t); int (*info)(xilinx_desc *); }; @@ -56,6 +57,8 @@ int xilinx_load(xilinx_desc *desc, const void *image, size_t size, bitstream_type bstype); int xilinx_dump(xilinx_desc *desc, const void *buf, size_t bsize); int xilinx_info(xilinx_desc *desc); +int xilinx_loadfs(xilinx_desc *desc, const void *buf, size_t bsize, + fpga_fs_info *fpga_fsinfo); /* Board specific implementation specific function types *********************************************************************/