Hi Fabio, On 2/8/2026 10:26 PM, Fabio Estevam wrote: > From: Fabio Estevam <[email protected]> > > Add support for booting U-Boot SPL from SPI NAND devices > using the MTD subsystem. > > - Introduce CONFIG_SPL_SPI_NAND_LOAD to enable SPL loading > from SPI NAND flash. > - Implement spl_spi_nand.c as a dedicated SPL loader that > reads the FIT image from SPI NAND via MTD. > - Update common/spl/Kconfig and Makefiles to include the > new loader in SPL builds. > - Adjust drivers/mtd/Makefile and drivers/mtd/nand/Makefile > to build the necessary SPI NAND MTD objects only when > CONFIG_SPL_SPI_NAND_LOAD is enabled, avoiding size impact > on other boards. > > This allows boards like the Omega4 RV1103 to boot SPL directly > from SPI NAND, keeping the SPL small and avoiding unnecessary > inclusion of SPI NOR code.
The content in this patch seem very generic and could possible be sent as a separate series that adds a generic SPL MTD loader. There also seem to be another SPL NAND loader part of the series at [1] that may be related. [1] https://lore.kernel.org/all/[email protected]/ > > Signed-off-by: Fabio Estevam <[email protected]> > --- > Changes since v1: > - None. > > common/spl/Kconfig | 10 ++++- > common/spl/Makefile | 1 + > common/spl/spl_spi_nand.c | 82 +++++++++++++++++++++++++++++++++++++++ > drivers/mtd/Makefile | 1 + > drivers/mtd/nand/Makefile | 13 ++++++- > 5 files changed, 105 insertions(+), 2 deletions(-) > create mode 100644 common/spl/spl_spi_nand.c > > diff --git a/common/spl/Kconfig b/common/spl/Kconfig > index 2998b7acb75f..126855b804ce 100644 > --- a/common/spl/Kconfig > +++ b/common/spl/Kconfig > @@ -1576,13 +1576,21 @@ config SPL_SPI_LOAD > Enable support for loading next stage, U-Boot or otherwise, from > SPI NOR in U-Boot SPL. > > +config SPL_SPI_NAND_LOAD > + bool "Support loading from SPI NAND flash" > + depends on SPL > + depends on MTD && DM_MTD > + help > + Enable support for loading next stage, U-Boot or otherwise, from > + SPI NAND in U-Boot SPL. > + > endif # SPL_SPI_FLASH_SUPPORT > > config SYS_SPI_U_BOOT_OFFS > hex "address of u-boot payload in SPI flash" > default 0x8000 if ARCH_SUNXI > default 0x0 > - depends on SPL_SPI_LOAD || SPL_SPI_SUNXI > + depends on SPL_SPI_LOAD || SPL_SPI_NAND_LOAD || SPL_SPI_SUNXI > help > Address within SPI-Flash from where the u-boot payload is fetched > from. > diff --git a/common/spl/Makefile b/common/spl/Makefile > index 4c9482bd3096..4628902e7e31 100644 > --- a/common/spl/Makefile > +++ b/common/spl/Makefile > @@ -35,6 +35,7 @@ obj-$(CONFIG_$(PHASE_)NVME) += spl_nvme.o > obj-$(CONFIG_$(PHASE_)SEMIHOSTING) += spl_semihosting.o > obj-$(CONFIG_$(PHASE_)DFU) += spl_dfu.o > obj-$(CONFIG_$(PHASE_)SPI_LOAD) += spl_spi.o > +obj-$(CONFIG_$(PHASE_)SPI_NAND_LOAD) += spl_spi_nand.o > obj-$(CONFIG_$(PHASE_)RAM_SUPPORT) += spl_ram.o > obj-$(CONFIG_$(PHASE_)USB_SDP_SUPPORT) += spl_sdp.o > endif > diff --git a/common/spl/spl_spi_nand.c b/common/spl/spl_spi_nand.c > new file mode 100644 > index 000000000000..20b877f75a05 > --- /dev/null > +++ b/common/spl/spl_spi_nand.c > @@ -0,0 +1,82 @@ > +// SPDX-License-Identifier: GPL-2.0+ > + > +/* > + * SPL loader for SPI NAND devices using the MTD subsystem. > + * > + * Based on spl_spi.c, which is: > + * > + * Copyright (C) 2011 OMICRON electronics GmbH > + * > + * based on drivers/mtd/nand/raw/nand_spl_load.c > + * > + * Copyright (C) 2011 > + * Heiko Schocher, DENX Software Engineering, [email protected]. > + */ > + > +#include <config.h> > +#include <image.h> > +#include <log.h> > +#include <errno.h> > +#include <spl.h> > +#include <spl_load.h> > +#include <asm/io.h> > +#include <dm/device_compat.h> > +#include <dm/ofnode.h> > +#include <dm/uclass.h> > +#include <mtd.h> > + > +static struct mtd_info *spl_spi_nand_get_mtd(void) > +{ > + struct udevice *dev; > + int ret; > + > + for (ret = uclass_first_device_err(UCLASS_MTD, &dev); > + dev; > + ret = uclass_next_device_err(&dev)) { > + if (ret) > + continue; > + if (device_is_compatible(dev, "spi-nand")) > + return dev_get_uclass_priv(dev); Is there a reason why you limit this to only spi-nand? I think it would be better to pivot this into a more generic SPL MTD loader. > + } > + > + return NULL; > +} > + > +static ulong spl_spinand_fit_read(struct spl_load_info *load, ulong offs, > + ulong size, void *buf) The _fit_ part can probably be dropped. > +{ > + struct mtd_info *mtd = load->priv; > + size_t retlen = 0; > + int ret; > + > + ret = mtd_read(mtd, offs, size, &retlen, buf); > + if (ret && ret != -EUCLEAN) { Maybe use mtd_is_bitflip(ret) > + printf("SPI NAND read failed offs=0x%lx size=0x%lx ret=%d\n", > + offs, size, ret); > + return 0; > + } > + if (retlen != size) Why do we need an error message above and not here? > + return 0; > + > + return retlen; > +} > + > +static int spl_spinand_load_image(struct spl_image_info *spl_image, > + struct spl_boot_device *bootdev) > +{ > + struct spl_load_info load; > + struct mtd_info *mtd; > + > + mtd = spl_spi_nand_get_mtd(); > + if (!mtd) { > + puts("SPI NAND probe failed.\n"); > + return -ENODEV; > + } > + > + spl_load_init(&load, spl_spinand_fit_read, mtd, 1); Should probably use mtd->writesize as bl_len. spl_load_init(&load, spl_mtd_read, mtd, mtd->writesize); > + > + return spl_load(spl_image, bootdev, &load, 0, > CONFIG_SYS_SPI_U_BOOT_OFFS); Suggest you could use something like following to closer match SPL flash. offset = CONFIG_SYS_SPI_U_BOOT_OFFS; if (CONFIG_IS_ENABLED(OF_REAL)) offset = ofnode_conf_read_int("u-boot,spl-payload-offset", offset); return spl_load(spl_image, bootdev, &load, 0, offset); > +} > + > +/* Use priority 1 so that boards can override this */ > +SPL_LOAD_IMAGE_METHOD("SPI NAND", 1, BOOT_DEVICE_SPI, > spl_spinand_load_image); > diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile > index ce05e206073d..a12d880a9e90 100644 > --- a/drivers/mtd/Makefile > +++ b/drivers/mtd/Makefile > @@ -34,6 +34,7 @@ else > ifneq ($(mtd-y),) > obj-$(CONFIG_SPL_MTD) += mtd.o > endif > +obj-$(CONFIG_SPL_SPI_NAND_LOAD) += nand/ > obj-$(CONFIG_$(PHASE_)NAND_SUPPORT) += nand/ > obj-$(CONFIG_SPL_ONENAND_SUPPORT) += onenand/ > obj-$(CONFIG_$(PHASE_)SPI_FLASH_SUPPORT) += spi/ > diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile > index c8169cf73902..7cd2a5f1af9b 100644 > --- a/drivers/mtd/nand/Makefile > +++ b/drivers/mtd/nand/Makefile > @@ -1,10 +1,21 @@ > # SPDX-License-Identifier: GPL-2.0+ > > -ifeq ($(CONFIG_XPL_BUILD)$(CONFIG_TPL_BUILD),) > nandcore-objs := core.o bbt.o > + > +ifeq ($(CONFIG_XPL_BUILD)$(CONFIG_TPL_BUILD),) Having both XPL and TPL is redundant and could be cleaned up to just have ($(CONFIG_XPL_BUILD),). Regards, Jonas > + > +# U-Boot proper > obj-$(CONFIG_MTD_NAND_CORE) += nandcore.o > obj-$(CONFIG_MTD_RAW_NAND) += raw/ > obj-$(CONFIG_MTD_SPI_NAND) += spi/ > + > else > + > +# SPL / XPL / TPL > +# SPL has no MTD_NAND_CORE symbol, so we must key off SPI NAND usage > +obj-$(CONFIG_SPL_SPI_NAND_LOAD) += nandcore.o > +obj-$(CONFIG_SPL_SPI_NAND_LOAD) += spi/ > + > +# raw NAND still follows the normal SPL rule > obj-$(CONFIG_$(PHASE_)NAND_SUPPORT) += raw/ > endif

