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 | 79 ++++++++++++++++++--- include/fs_loader.h | 31 ++++++++ 3 files changed, 107 insertions(+), 11 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..d4804d649e6 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> @@ -67,6 +68,11 @@ 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; @@ -121,16 +127,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; @@ -147,7 +163,8 @@ static int fw_get_filesystem_firmware(struct udevice *dev) { loff_t actread = 0; 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"); @@ -167,7 +184,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 +196,17 @@ 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 *)firmwarep->data); + actread = firmwarep->size; +#endif + } if (ret) { debug("Error: %d Failed to read %s from flash %lld != %zu.\n", @@ -228,6 +255,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 +275,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 +291,30 @@ 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\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; + } +#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; @@ -277,7 +334,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

