From 256f19fa66c04f703559762d841bf4421125452c Mon Sep 17 00:00:00 2001 From: Siva Durga Prasad Paladugu Date: Fri, 14 Mar 2014 16:35:37 +0530 Subject: [PATCH] fpga: zynq: Added support to load bit stream from SD/MMC Added support to load a bitstream image in chunks by reading it in chunks from SD/MMC. Command format: loadfs [dev] [address] [image size] [blocksize] [] Example: fpga loadfs 0 1000000 3dbafc 4000 mmc 0 fpga.bin Signed-off-by: Siva Durga Prasad Paladugu Signed-off-by: Michal Simek --- common/cmd_fpga.c | 49 +++++++++++++++++++++++-- drivers/fpga/fpga.c | 28 +++++++++++++++ drivers/fpga/xilinx.c | 31 ++++++++++++++++ drivers/fpga/zynqpl.c | 84 +++++++++++++++++++++++++++++++++++++++++++ include/fpga.h | 13 +++++++ include/xilinx.h | 4 +++ include/zynqpl.h | 4 +++ 7 files changed, 210 insertions(+), 3 deletions(-) diff --git a/common/cmd_fpga.c b/common/cmd_fpga.c index 010cd24e63d..4d5caa041e7 100644 --- a/common/cmd_fpga.c +++ b/common/cmd_fpga.c @@ -12,6 +12,9 @@ #include #include #include +#ifdef CONFIG_FPGA_LOADFS +#include +#endif /* Local functions */ static int fpga_get_op(char *opstr); @@ -23,6 +26,7 @@ static int fpga_get_op(char *opstr); #define FPGA_LOADB 2 #define FPGA_DUMP 3 #define FPGA_LOADMK 4 +#define FPGA_LOADFS 5 /* ------------------------------------------------------------------------- */ /* command form: @@ -45,6 +49,11 @@ int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) const char *fit_uname = NULL; ulong fit_addr; #endif +#ifdef CONFIG_FPGA_LOADFS + fpga_fs_info fpga_fsinfo; + + fpga_fsinfo.fstype = FS_TYPE_ANY; +#endif if (devstr) dev = (int) simple_strtoul(devstr, NULL, 16); @@ -52,6 +61,17 @@ int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) fpga_data = (void *)simple_strtoul(datastr, NULL, 16); switch (argc) { +#ifdef CONFIG_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]; + + if (fpga_fsinfo.fstype == FS_TYPE_ANY) + fpga_fsinfo.fstype = FS_TYPE_FAT; +#endif case 5: /* fpga */ data_size = simple_strtoul(argv[4], NULL, 16); @@ -120,6 +140,13 @@ int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) case FPGA_NONE: case FPGA_INFO: break; +#ifdef CONFIG_FPGA_LOADFS + case FPGA_LOADFS: + /* Blocksize can be zero */ + if (!fpga_fsinfo.interface || !fpga_fsinfo.dev_part || + !fpga_fsinfo.filename || fpga_fsinfo.fstype == FS_TYPE_ANY) + wrong_parms = 1; +#endif case FPGA_LOAD: case FPGA_LOADB: case FPGA_DUMP: @@ -152,7 +179,11 @@ int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) case FPGA_LOADB: rc = fpga_loadbitstream(dev, fpga_data, data_size); break; - +#ifdef CONFIG_FPGA_LOADFS + case FPGA_LOADFS: + rc = fpga_fsload(dev, fpga_data, data_size, &fpga_fsinfo); + break; +#endif case FPGA_LOADMK: switch (genimg_get_format(fpga_data)) { case IMAGE_FORMAT_LEGACY: @@ -257,6 +288,10 @@ static int fpga_get_op(char *opstr) op = FPGA_LOADB; else if (!strcmp("load", opstr)) op = FPGA_LOAD; +#ifdef CONFIG_FPGA_LOADFS + else if (!strcmp("loadfs", opstr)) + op = FPGA_LOADFS; +#endif else if (!strcmp("loadmk", opstr)) op = FPGA_LOADMK; else if (!strcmp("dump", opstr)) @@ -267,8 +302,11 @@ static int fpga_get_op(char *opstr) return op; } - +#ifdef CONFIG_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" @@ -281,6 +319,11 @@ U_BOOT_CMD(fpga, 6, 1, do_fpga, #if defined(CONFIG_FIT) "\n" "\tFor loadmk operating on FIT format uImage address must include\n" - "\tsubimage unit name in the form of addr:" + "\tsubimage unit name in the form of addr:\n" +#endif +#ifdef CONFIG_FPGA_LOADFS + "Load device from filesystem (FAT by default) (Xilinx only)\n" + " loadfs [dev] [address] [image size] [blocksize] \n" + " [] \n" #endif ); diff --git a/drivers/fpga/fpga.c b/drivers/fpga/fpga.c index 2ed2f959a1e..1f61e7d10dc 100644 --- a/drivers/fpga/fpga.c +++ b/drivers/fpga/fpga.c @@ -179,6 +179,34 @@ int __weak fpga_loadbitstream(int devnum, char *fpgadata, size_t size) return FPGA_FAIL; } +#ifdef CONFIG_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_fsload(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 2e0db535d47..8e9b1a2324d 100644 --- a/drivers/fpga/xilinx.c +++ b/drivers/fpga/xilinx.c @@ -141,6 +141,37 @@ int fpga_loadbitstream(int devnum, char *fpgadata, size_t size) return fpga_load(devnum, dataptr, swapsize); } +#ifdef CONFIG_FPGA_LOADFS +int xilinx_fsload(Xilinx_desc *desc, const void *buf, size_t bsize, + fpga_fs_info *fpga_fsinfo) +{ + int ret_val = FPGA_FAIL; /* assume a failure */ + + if (!xilinx_validate(desc, (char *)__func__)) { + printf("%s: Invalid device descriptor\n", __func__); + } else { + switch (desc->family) { + case xilinx_zynq: +#if defined(CONFIG_FPGA_ZYNQPL) + PRINTF("%s: Launching the Zynq PL Loader...\n", + __func__); + ret_val = zynq_fsload(desc, buf, bsize, + fpga_fsinfo); +#else + printf("%s: No support for Zynq devices.\n", + __func__); +#endif + break; + + default: + printf("%s: Unsupported family type, %d\n", + __func__, desc->family); + } + } + return ret_val; +} +#endif + int xilinx_load(Xilinx_desc *desc, const void *buf, size_t bsize) { int ret_val = FPGA_FAIL; /* assume a failure */ diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c index e53ab7641c0..3572bc9c1fa 100644 --- a/drivers/fpga/zynqpl.c +++ b/drivers/fpga/zynqpl.c @@ -13,6 +13,9 @@ #include #include #include +#if defined(CONFIG_FPGA_LOADFS) && !defined(CONFIG_SPL_BUILD) +#include +#endif #define DEVCFG_CTRL_PCFG_PROG_B 0x40000000 #define DEVCFG_CTRL_PCAP_RATE_EN_MASK 0x02000000 @@ -358,6 +361,87 @@ static int zynq_validate_bitstream(Xilinx_desc *desc, const void *buf, return 0; } +#if defined(CONFIG_FPGA_LOADFS) && !defined(CONFIG_SPL_BUILD) +int zynq_fsload(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, FS_TYPE_FAT)) + 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 + int zynq_load(Xilinx_desc *desc, const void *buf, size_t bsize) { unsigned long ts; /* Timestamp */ diff --git a/include/fpga.h b/include/fpga.h index acc9efc883b..615d453963e 100644 --- a/include/fpga.h +++ b/include/fpga.h @@ -35,6 +35,15 @@ typedef struct { /* typedef fpga_desc */ void *devdesc; /* real device descriptor */ } fpga_desc; /* end, typedef fpga_desc */ +#ifdef CONFIG_FPGA_LOADFS +typedef struct { /* typedef fpga_desc */ + unsigned int blocksize; + char *interface; + char *dev_part; + char *filename; + int fstype; +} fpga_fs_info; +#endif /* root function definitions */ extern void fpga_init(void); @@ -42,6 +51,10 @@ extern int fpga_add(fpga_type devtype, void *desc); extern int fpga_count(void); extern const fpga_desc *const fpga_get_desc(int devnum); extern int fpga_load(int devnum, const void *buf, size_t bsize); +#ifdef CONFIG_FPGA_LOADFS +extern int fpga_fsload(int devnum, const void *buf, size_t size, + fpga_fs_info *fpga_fsinfo); +#endif extern int fpga_loadbitstream(int devnum, char *fpgadata, size_t size); extern int fpga_dump(int devnum, const void *buf, size_t bsize); extern int fpga_info(int devnum); diff --git a/include/xilinx.h b/include/xilinx.h index 00a585e5fc3..2d8f0e225c8 100644 --- a/include/xilinx.h +++ b/include/xilinx.h @@ -46,6 +46,10 @@ typedef struct { /* typedef Xilinx_desc */ /* Generic Xilinx Functions *********************************************************************/ extern int xilinx_load(Xilinx_desc *desc, const void *image, size_t size); +#ifdef CONFIG_FPGA_LOADFS +extern int xilinx_fsload(Xilinx_desc *desc, const void *buf, size_t bsize, + fpga_fs_info *fpga_fsinfo); +#endif extern int xilinx_dump(Xilinx_desc *desc, const void *buf, size_t bsize); extern int xilinx_info(Xilinx_desc *desc); diff --git a/include/zynqpl.h b/include/zynqpl.h index 11806fdc39e..224c841b550 100644 --- a/include/zynqpl.h +++ b/include/zynqpl.h @@ -13,6 +13,10 @@ #include extern int zynq_load(Xilinx_desc *desc, const void *image, size_t size); +#ifdef CONFIG_FPGA_LOADFS +extern int zynq_fsload(Xilinx_desc *desc, const void *buf, size_t bsize, + fpga_fs_info *fsinfo); +#endif extern int zynq_dump(Xilinx_desc *desc, const void *buf, size_t bsize); extern int zynq_info(Xilinx_desc *desc); #ifdef CONFIG_CMD_ZYNQ_AES -- 2.47.3