[U-Boot] [RFC PATCH] fpga: Added support to load bit stream from SD/MMC

Michal Simek michal.simek at xilinx.com
Fri May 2 16:10:03 CEST 2014


From: Siva Durga Prasad Paladugu <siva.durga.paladugu at xilinx.com>

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] <interface>
       [<dev[:part]>] <filename>
Example: fpga loadfs 0 1000000 3dbafc 4000 mmc 0 fpga.bin

Signed-off-by: Siva Durga Prasad Paladugu <sivadur at xilinx.com>
Signed-off-by: Michal Simek <michal.simek at xilinx.com>
---

We have tested just FAT case but I am sending this as RFC
to give some inputs from you.
The reason for this command is that when u-boot running
from OCM on zynq there is just 192kB for u-boot itself
and there must be an option to load bitstream to PL
because there full DDR controller.
Bitstreams are bigger and bigger and reading it with chunks
is only one way how to do it.
This is also necessary to do it for u-boot SPL when
we add fpga support there.

The question is if this is the way how to extend fpga command
because loadfs should be fpga subcommand.

This patch is based on this branch.
http://git.denx.de/?p=u-boot/u-boot-microblaze.git;a=shortlog;h=refs/heads/xnext/zynq

Thanks for your comments,
Michal

---
 common/cmd_fpga.c             | 41 +++++++++++++++++++++
 drivers/fpga/fpga.c           | 28 ++++++++++++++
 drivers/fpga/xilinx.c         | 16 ++++++++
 drivers/fpga/zynqpl.c         | 85 +++++++++++++++++++++++++++++++++++++++++++
 include/configs/zynq-common.h |  1 +
 include/fpga.h                |  9 +++++
 include/xilinx.h              |  3 ++
 7 files changed, 183 insertions(+)

diff --git a/common/cmd_fpga.c b/common/cmd_fpga.c
index 802f3ec..3add0c3 100644
--- a/common/cmd_fpga.c
+++ b/common/cmd_fpga.c
@@ -11,6 +11,7 @@
 #include <common.h>
 #include <command.h>
 #include <fpga.h>
+#include <fs.h>
 #include <malloc.h>

 /* 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,11 @@ 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_FAT;
+#endif

 	if (devstr)
 		dev = (int) simple_strtoul(devstr, NULL, 16);
@@ -54,6 +61,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 <op> <dev> <data> <datasize> */
 		data_size = simple_strtoul(argv[4], NULL, 16);

@@ -122,6 +137,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 || fpga_fsinfo.fstype == FS_TYPE_ANY)
+			wrong_parms = 1;
+#endif
 	case FPGA_LOAD:
 	case FPGA_LOADP:
 	case FPGA_LOADB:
@@ -171,6 +193,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 +315,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 +332,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 +354,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] <interface>\n"
+	   "        [<dev[:part]>] <filename>\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 e770950..37946d5 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 ab9f517..3795c1a 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 915f077..7834e2f 100644
--- a/drivers/fpga/zynqpl.c
+++ b/drivers/fpga/zynqpl.c
@@ -9,6 +9,7 @@

 #include <common.h>
 #include <asm/io.h>
+#include <fs.h>
 #include <zynqpl.h>
 #include <linux/sizes.h>
 #include <asm/arch/hardware.h>
@@ -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, 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
+
 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 af420d1..8e0f935 100644
--- a/include/configs/zynq-common.h
+++ b/include/configs/zynq-common.h
@@ -217,6 +217,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 49efd37..914024c 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 9600432..774487e 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
  *********************************************************************/
--
1.8.2.3

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140502/b5d1fcc7/attachment.pgp>


More information about the U-Boot mailing list