[PATCH] misc: fs_loader: Add QSPI RAW partition loading support

From: Tien Fong Chee tien.fong.chee@intel.com
Enhanced the generic firmware loader to support QSPI RAW partition loading. This would enable FPGA configuration bitstream loading from QSPI RAW partition to program FPGA.
Signed-off-by: Tien Fong Chee tien.fong.chee@intel.com Signed-off-by: Jit Loon Lim jit.loon.lim@intel.com --- drivers/misc/fs_loader.c | 92 ++++++++++++++++++++++++++++++++-------- include/fs_loader.h | 35 +++++++++++++++ 2 files changed, 109 insertions(+), 18 deletions(-)
diff --git a/drivers/misc/fs_loader.c b/drivers/misc/fs_loader.c index 5b4d03639c..d57d717ed3 100644 --- a/drivers/misc/fs_loader.c +++ b/drivers/misc/fs_loader.c @@ -19,6 +19,7 @@ #include <mapmem.h> #include <malloc.h> #include <spl.h> +#include <spi_flash.h>
#ifdef CONFIG_CMD_UBIFS #include <ubi_uboot.h> @@ -69,17 +70,18 @@ static int mount_ubifs(char *mtdpart, char *ubivol) } #endif
+__weak struct blk_desc *blk_get_by_device(struct udevice *dev) +{ + return NULL; +} + static int select_fs_dev(struct device_plat *plat) { int ret; - if (plat->phandlepart.phandle) { ofnode node; - node = ofnode_get_by_phandle(plat->phandlepart.phandle); - struct udevice *dev; - ret = device_get_global_by_ofnode(node, &dev); if (!ret) { struct blk_desc *desc = blk_get_by_device(dev); @@ -95,16 +97,13 @@ static int select_fs_dev(struct device_plat *plat) ret = mount_ubifs(plat->mtdpart, plat->ubivol); if (ret) return ret; - ret = fs_set_blk_dev("ubi", NULL, FS_TYPE_UBIFS); } else { debug("Error: unsupported storage device.\n"); return -ENODEV; } - if (ret) debug("Error: could not access storage.\n"); - return ret; }
@@ -123,16 +122,26 @@ static int _request_firmware_prepare(struct udevice *dev, const char *name, void *dbuf, size_t size, u32 offset) { - if (!name || name[0] == '\0') - return -EINVAL; - struct firmware *firmwarep = dev_get_priv(dev); + struct device_plat *plat = dev_get_plat(dev); + char *endptr; + u32 fw_offset;
if (!firmwarep) return -ENOMEM;
firmwarep->name = name; - firmwarep->offset = offset; + + if (plat->data_type == DATA_RAW) { + fw_offset = simple_strtoul(firmwarep->name, &endptr, 16); + if (firmwarep->name == endptr || *endptr != '\0') + return -EINVAL; + + firmwarep->offset = fw_offset + offset; + } else { + firmwarep->offset = offset; + } + firmwarep->data = dbuf; firmwarep->size = size;
@@ -149,7 +158,8 @@ static int fw_get_filesystem_firmware(struct udevice *dev) { loff_t actread; char *storage_interface, *dev_part, *ubi_mtdpart, *ubi_volume; - int ret; + int ret = 0; + struct device_plat *plat = dev_get_plat(dev);
storage_interface = env_get("storage_interface"); dev_part = env_get("fw_dev_part"); @@ -169,7 +179,8 @@ static int fw_get_filesystem_firmware(struct udevice *dev) else ret = -ENODEV; } else { - ret = select_fs_dev(dev_get_plat(dev)); + if (plat->data_type == DATA_FS) + ret = select_fs_dev(dev_get_plat(dev)); }
if (ret) @@ -180,8 +191,18 @@ static int fw_get_filesystem_firmware(struct udevice *dev) if (!firmwarep) return -ENOMEM;
- ret = fs_read(firmwarep->name, (ulong)map_to_sysmem(firmwarep->data), - firmwarep->offset, firmwarep->size, &actread); + if (plat->data_type == DATA_FS) + ret = fs_read(firmwarep->name, + (ulong)map_to_sysmem(firmwarep->data), + firmwarep->offset, firmwarep->size, &actread); + else if (plat->data_type == DATA_RAW) { +#ifdef CONFIG_SPI_FLASH + ret = spi_flash_read_dm(plat->flash, firmwarep->offset, + firmwarep->size, + (void *)map_to_sysmem(firmwarep->data)); + actread = firmwarep->size; +#endif + }
if (ret) { debug("Error: %d Failed to read %s from flash %lld != %zu.\n", @@ -230,6 +251,7 @@ int request_firmware_into_buf(struct udevice *dev, static int fs_loader_of_to_plat(struct udevice *dev) { u32 phandlepart[2]; + u32 sfconfig[4];
ofnode fs_loader_node = dev_ofnode(dev);
@@ -249,6 +271,17 @@ static int fs_loader_of_to_plat(struct udevice *dev)
plat->ubivol = (char *)ofnode_read_string( fs_loader_node, "ubivol"); + + if (!ofnode_read_u32_array(fs_loader_node, "sfconfig", sfconfig, + 4)) { + plat->data_type = DATA_RAW; + plat->sfconfig.bus = sfconfig[0]; + plat->sfconfig.cs = sfconfig[1]; + plat->sfconfig.speed = sfconfig[2]; + plat->sfconfig.mode = sfconfig[3]; + } else { + plat->data_type = DATA_FS; + } }
return 0; @@ -256,10 +289,33 @@ static int fs_loader_of_to_plat(struct udevice *dev)
static int fs_loader_probe(struct udevice *dev) { -#if CONFIG_IS_ENABLED(DM) && CONFIG_IS_ENABLED(BLK) - int ret; + int ret = 0; struct device_plat *plat = dev_get_plat(dev);
+#ifdef CONFIG_SPI_FLASH + if (!plat->flash) { + debug("bus = %d\ncs = %d\nspeed= %d\nmode = %d\n", + plat->sfconfig.bus, plat->sfconfig.cs, + plat->sfconfig.speed, plat->sfconfig.mode); + + ret = spi_flash_probe_bus_cs(plat->sfconfig.bus, + plat->sfconfig.cs, + plat->sfconfig.speed, + plat->sfconfig.mode, + &plat->flash); + if (ret) { + debug("fs_loader: Failed to initialize SPI flash at "); + debug("%u:%u (error %d)\n", plat->sfconfig.bus, + plat->sfconfig.cs, ret); + return -ENODEV; + } + + if (!plat->flash) + return -EINVAL; + } +#endif + +#if CONFIG_IS_ENABLED(DM) && CONFIG_IS_ENABLED(BLK) if (plat->phandlepart.phandle) { ofnode node = ofnode_get_by_phandle(plat->phandlepart.phandle); struct udevice *parent_dev = NULL; @@ -279,7 +335,7 @@ static int fs_loader_probe(struct udevice *dev) } #endif
- return 0; + return ret; };
static const struct udevice_id fs_loader_ids[] = { diff --git a/include/fs_loader.h b/include/fs_loader.h index 8de7cb18dc..6b6450ac03 100644 --- a/include/fs_loader.h +++ b/include/fs_loader.h @@ -22,6 +22,35 @@ struct phandle_part { u32 partition; };
+/** + * struct sf_config - A place for storing serial flash configuration + * + * This holds information about bus, chip-select, and speed and mode of a serial + * flash configuration. + * + * @bus: SPI bus number. + * @cs: SPI chip selection. + * @speed: Speed selection. + * @mode: SPI mode. + */ +struct sf_config { + u32 bus; + u32 cs; + u32 speed; + u32 mode; +}; + +/** + * enum data_flags - Flag to indicate data as RAW or as filesystem + * + * DATA_RAW: Data stored as RAW. + * DATA_FS: DATA stored as filesystem. + */ +enum data_flags { + DATA_RAW, /* Stored in raw */ + DATA_FS, /* Stored within a file system */ +}; + /** * struct phandle_part - A place for storing all supported storage devices * @@ -30,11 +59,17 @@ struct phandle_part { * @phandlepart: Attribute data for block device. * @mtdpart: MTD partition for ubi partition. * @ubivol: UBI volume-name for ubifsmount. + * @enum data_flags: Data type (RAW or filesystem). + * @struct sf_config: Serial flash configuration. + * @struct spi_flash: Information about a SPI flash. */ struct device_plat { struct phandle_part phandlepart; char *mtdpart; char *ubivol; + enum data_flags data_type; + struct sf_config sfconfig; + struct udevice *flash; };
/**
participants (1)
-
Jit Loon Lim