From: "Chee, Tien Fong" <tien.fong.chee@altera.com>
To: Chen Huei Lok <chen.huei.lok@altera.com>, u-boot@lists.denx.de
Cc: Tom Rini <trini@konsulko.com>, Marek Vasut <marex@denx.de>,
Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>,
Alif Zakuan Yuslaimi <alif.zakuan.yuslaimi@altera.com>,
Boon Khai Ng <boon.khai.ng@altera.com>,
Kok Kiang Hea <kok.kiang.hea@altera.com>
Subject: Re: [PATCH v4 01/15] misc: fs_loader: Add QSPI RAW offset loading support
Date: Wed, 21 Oct 2026 09:55:08 +0800 [thread overview]
Message-ID: <67fb0209-2ca4-42ec-8416-9ad76fc97b2d@altera.com> (raw)
In-Reply-To: <20261016044047.21496-2-chen.huei.lok@altera.com>
On 16/10/2026 12:40 pm, Chen Huei Lok wrote:
> From: Tien Fong Chee <tien.fong.chee@altera.com>
>
> Add support for loading data from a QSPI RAW flash offset through the
> generic firmware loader. Consumers include the DDR calibration backup
> restore path, and optionally FPGA bitstream loading from QSPI.
>
> Signed-off-by: Tien Fong Chee <tien.fong.chee@altera.com>
> Signed-off-by: Chen Huei Lok <chen.huei.lok@altera.com>
> ---
> doc/device-tree-bindings/misc/fs_loader.txt | 8 ++
> drivers/misc/fs_loader.c | 99 +++++++++++++++++----
> include/fs_loader.h | 33 ++++++-
> 3 files changed, 120 insertions(+), 20 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..293db94dd29 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,11 +297,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);
>
> - if (plat->phandlepart.phandle) {
> + 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) &&
> + plat->phandlepart.phandle) {
> ofnode node = ofnode_get_by_phandle(plat->phandlepart.phandle);
> struct udevice *parent_dev = NULL;
>
> @@ -269,15 +331,14 @@ static int fs_loader_probe(struct udevice *dev)
> ret = blk_get_from_parent(parent_dev, &dev);
> if (ret) {
> debug("fs_loader: No block device: %d\n",
> - ret);
> + ret);
>
> return ret;
> }
> }
> }
> -#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..f9c073fee6e 100644
> --- a/include/fs_loader.h
> +++ b/include/fs_loader.h
> @@ -23,18 +23,49 @@ struct phandle_part {
> };
>
> /**
> - * struct phandle_part - A place for storing all supported storage devices
> + * 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 device_plat - A place for storing all supported storage devices
> *
> * This holds information about all supported storage devices for driver use.
> *
> * @phandlepart: Attribute data for block device.
> * @mtdpart: MTD partition for ubi partition.
> * @ubivol: UBI volume-name for ubifsmount.
> + * @data_type: Data type (RAW or filesystem).
> + * @sfconfig: Serial flash configuration.
> + * @flash: SPI flash device used for RAW offset reads.
> */
> struct device_plat {
> struct phandle_part phandlepart;
> char *mtdpart;
> char *ubivol;
> + enum data_flags data_type;
> + struct sf_config sfconfig;
> + struct udevice *flash;
> };
>
> /**
Reviewed-by: Tien Fong Chee <tien.fong.chee@altera.com>
Best regards,
Tien Fong
next parent reply other threads:[~2026-10-21 1:55 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20261016044047.21496-1-chen.huei.lok@altera.com>
[not found] ` <20261016044047.21496-2-chen.huei.lok@altera.com>
2026-10-21 1:55 ` Chee, Tien Fong [this message]
[not found] ` <20261016044047.21496-3-chen.huei.lok@altera.com>
2026-10-21 2:07 ` [PATCH v4 02/15] arm: dts: socfpga: n5x: add DDR retention calibration backup nodes Chee, Tien Fong
[not found] ` <20261016044047.21496-4-chen.huei.lok@altera.com>
2026-10-21 2:09 ` [PATCH v4 03/15] arm: socfpga: n5x: enable QSPI mailbox before DDR init Chee, Tien Fong
[not found] ` <20261016044047.21496-5-chen.huei.lok@altera.com>
2026-10-21 2:14 ` [PATCH v4 04/15] ddr: altera: n5x: Add self-refresh support in DDR4 Chee, Tien Fong
[not found] ` <20261016044047.21496-6-chen.huei.lok@altera.com>
2026-10-21 2:16 ` [PATCH v4 05/15] configs: socfpga: n5x: enable required configs for DDR retention Chee, Tien Fong
[not found] ` <20261016044047.21496-7-chen.huei.lok@altera.com>
2026-10-21 2:18 ` [PATCH v4 06/15] ddr: altera: n5x: set DDR init progress bit for watchdog recovery Chee, Tien Fong
[not found] ` <20261016044047.21496-8-chen.huei.lok@altera.com>
2026-10-21 2:20 ` [PATCH v4 07/15] ddr: altera: n5x: re-init DDR when double-bit ECC error is detected Chee, Tien Fong
[not found] ` <20261016044047.21496-9-chen.huei.lok@altera.com>
2026-10-21 2:21 ` [PATCH v4 08/15] ddr: altera: n5x: re-init DDR after watchdog reset from init hang Chee, Tien Fong
[not found] ` <20261016044047.21496-10-chen.huei.lok@altera.com>
2026-10-21 2:22 ` [PATCH v4 09/15] ddr: altera: n5x: return error on invalid DDR controller type Chee, Tien Fong
[not found] ` <20261016044047.21496-11-chen.huei.lok@altera.com>
2026-10-21 2:24 ` [PATCH v4 10/15] ddr: altera: n5x: use correct cast for reset status register read Chee, Tien Fong
[not found] ` <20261016044047.21496-12-chen.huei.lok@altera.com>
2026-10-21 2:25 ` [PATCH v4 11/15] ddr: altera: n5x: fix debug log typo Chee, Tien Fong
[not found] ` <20261016044047.21496-13-chen.huei.lok@altera.com>
2026-10-21 2:27 ` [PATCH v4 12/15] ddr: altera: n5x: rename is_ddr_init_skipped() and quieten reset log Chee, Tien Fong
[not found] ` <20261016044047.21496-14-chen.huei.lok@altera.com>
2026-10-21 2:29 ` [PATCH v4 13/15] ddr: altera: n5x: drop always-false unsigned less-than-zero checks Chee, Tien Fong
[not found] ` <20261016044047.21496-15-chen.huei.lok@altera.com>
2026-10-21 2:30 ` [PATCH v4 14/15] ddr: altera: n5x: reconfigure DDR when mem-clk handoff changes Chee, Tien Fong
[not found] ` <20261016044047.21496-16-chen.huei.lok@altera.com>
2026-10-21 2:31 ` [PATCH v4 15/15] ddr: altera: n5x: Replay PIE handoff on DDR retention restore Chee, Tien Fong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=67fb0209-2ca4-42ec-8416-9ad76fc97b2d@altera.com \
--to=tien.fong.chee@altera.com \
--cc=alif.zakuan.yuslaimi@altera.com \
--cc=boon.khai.ng@altera.com \
--cc=chen.huei.lok@altera.com \
--cc=kok.kiang.hea@altera.com \
--cc=marex@denx.de \
--cc=simon.k.r.goldschmidt@gmail.com \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.