From: Tien Fong Chee <[email protected]> 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 <[email protected]> Signed-off-by: Chen Huei Lok <[email protected]> --- doc/device-tree-bindings/misc/fs_loader.txt | 8 ++ drivers/misc/fs_loader.c | 94 +++++++++++++++++---- include/fs_loader.h | 31 +++++++ 3 files changed, 117 insertions(+), 16 deletions(-) diff --git a/doc/device-tree-bindings/misc/fs_loader.txt b/doc/device-tree-bindings/misc/fs_loader.txt index 542be4b25a0..8ee59db24d5 100644 --- a/doc/device-tree-bindings/misc/fs_loader.txt +++ b/doc/device-tree-bindings/misc/fs_loader.txt @@ -12,6 +12,7 @@ Required properties: required for ubi and mounting. - ubivol: which volume of ubi the image loading from, this property is required for ubi and mounting. +- sfconfig: should only contain "bus number" and "chip selection". Example of storage device and partition search set for mmc, usb, sata and ubi in device tree source as shown in below: @@ -46,3 +47,10 @@ ubi in device tree source as shown in below: mtdpart = "UBI", ubivol = "ubi0"; }; + + Example for qspi: + fs_loader4: fs-loader@4 { + bootph-all; + compatible = "u-boot,fs-loader"; + sfconfig = <0 0>; + }; diff --git a/drivers/misc/fs_loader.c b/drivers/misc/fs_loader.c index 6af4c7f15e7..03fed40fed6 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> @@ -121,16 +122,31 @@ 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; + if (plat->data_type == DATA_RAW) { + if (!name) + return -EINVAL; + + fw_offset = simple_strtoul(name, &endptr, 16); + if (name == endptr || *endptr != '\0') + return -EINVAL; + + firmwarep->offset = fw_offset + offset; + } else { + if (!name || name[0] == '\0') + return -EINVAL; + + firmwarep->offset = offset; + } + firmwarep->name = name; - firmwarep->offset = offset; firmwarep->data = dbuf; firmwarep->size = size; @@ -146,13 +162,17 @@ static int _request_firmware_prepare(struct udevice *dev, static int fw_get_filesystem_firmware(struct udevice *dev) { loff_t actread = 0; - char *storage_interface, *dev_part, *ubi_mtdpart, *ubi_volume; - int ret; + char *storage_interface = NULL, *dev_part = NULL; + char *ubi_mtdpart = NULL, *ubi_volume = NULL; + int ret = 0; + struct device_plat *plat = dev_get_plat(dev); - storage_interface = env_get("storage_interface"); - dev_part = env_get("fw_dev_part"); - ubi_mtdpart = env_get("fw_ubi_mtdpart"); - ubi_volume = env_get("fw_ubi_volume"); + if (CONFIG_IS_ENABLED(ENV_SUPPORT)) { + storage_interface = env_get("storage_interface"); + dev_part = env_get("fw_dev_part"); + ubi_mtdpart = env_get("fw_ubi_mtdpart"); + ubi_volume = env_get("fw_ubi_volume"); + } if (storage_interface && dev_part) { ret = fs_set_blk_dev(storage_interface, dev_part, FS_TYPE_ANY); @@ -167,7 +187,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) @@ -178,8 +199,20 @@ 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) { + if (IS_ENABLED(CONFIG_SPI_FLASH)) { + ret = spi_flash_read_dm(plat->flash, firmwarep->offset, + firmwarep->size, + (void *)firmwarep->data); + actread = firmwarep->size; + } else { + ret = -ENOSYS; + } + } if (ret) { debug("Error: %d Failed to read %s from flash %lld != %zu.\n", @@ -228,6 +261,7 @@ int request_firmware_into_buf(struct udevice *dev, static int fs_loader_of_to_plat(struct udevice *dev) { u32 phandlepart[2]; + u32 sfconfig[2]; ofnode fs_loader_node = dev_ofnode(dev); @@ -247,6 +281,15 @@ 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, + 2)) { + plat->data_type = DATA_RAW; + plat->sfconfig.bus = sfconfig[0]; + plat->sfconfig.cs = sfconfig[1]; + } else { + plat->data_type = DATA_FS; + } } return 0; @@ -254,10 +297,29 @@ 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); + if (IS_ENABLED(CONFIG_SPI_FLASH) && + plat->data_type == DATA_RAW && !plat->flash) { + debug("bus = %d\ncs = %d\n", + plat->sfconfig.bus, plat->sfconfig.cs); + + ret = spi_flash_probe_bus_cs(plat->sfconfig.bus, + plat->sfconfig.cs, + &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; + } + +#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; @@ -277,7 +339,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 7e16e0f7030..8f868f031f1 100644 --- a/include/fs_loader.h +++ b/include/fs_loader.h @@ -22,6 +22,31 @@ struct phandle_part { u32 partition; }; +/** + * struct sf_config - A place for storing serial flash configuration + * + * This holds information about bus and chip-select of a serial flash + * configuration. + * + * @bus: SPI bus number. + * @cs: SPI chip selection. + */ +struct sf_config { + u32 bus; + u32 cs; +}; + +/** + * 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 +55,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; }; /** -- 2.43.7
