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.c...@altera.com> Signed-off-by: Naresh Kumar Ravulapalli <nareshkumar.ravulapa...@altera.com> --- drivers/misc/fs_loader.c | 86 +++++++++++++++++++++++++++++++++------- include/fs_loader.h | 36 ++++++++++++++++- 2 files changed, 106 insertions(+), 16 deletions(-) diff --git a/drivers/misc/fs_loader.c b/drivers/misc/fs_loader.c index 66803f4b997..931443048e5 100644 --- a/drivers/misc/fs_loader.c +++ b/drivers/misc/fs_loader.c @@ -1,7 +1,7 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2018-2019 Intel Corporation <www.intel.com> - * + * Copyright (C) 2025 Altera Corporation <www.altera.com> */ #define LOG_CATEGORY UCLASS_FS_FIRMWARE_LOADER @@ -20,6 +20,7 @@ #include <mapmem.h> #include <malloc.h> #include <spl.h> +#include <spi_flash.h> #ifdef CONFIG_CMD_UBIFS #include <ubi_uboot.h> @@ -70,6 +71,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; @@ -124,16 +130,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; @@ -148,9 +164,10 @@ static int _request_firmware_prepare(struct udevice *dev, */ static int fw_get_filesystem_firmware(struct udevice *dev) { - loff_t actread; + 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"); @@ -170,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) @@ -181,8 +199,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", @@ -231,6 +259,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); @@ -250,6 +279,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; @@ -257,10 +295,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, + 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; @@ -280,7 +338,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 5eb5b7ab4a1..1b36f05415a 100644 --- a/include/fs_loader.h +++ b/include/fs_loader.h @@ -1,8 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2018 Intel Corporation <www.intel.com> - * - * SPDX-License-Identifier: GPL-2.0 + * Copyright (C) 2025 Altera Corporation <www.altera.com> */ + #ifndef _FS_LOADER_H_ #define _FS_LOADER_H_ @@ -22,6 +23,31 @@ 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. + */ +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 +56,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.35.3