Accessing SPI NOR Flash as Block Device

Fabian Herb fabian at herb-clan.de
Sat Jan 18 12:55:25 CET 2025


Hi everyone!

I’m trying to access a SquashFS image in serial SPI flash. A block device layer was added to MTD devices last August, but it was only activated for NAND flash (commit d12689a). So, without really knowing what I was doing, I patched NOR flash code in the same way [1], and sure enough, the block device is showing up in "lsblk“ and "dm tree“:

=> dm tree 
 Class     Seq    Probed  Driver                Name
-----------------------------------------------------------
 root          0  [ + ]   root_driver           root_driver
 simple_bus    0  [ + ]   simple_bus            |-- soc
 spi           0  [ + ]   sun4i_spi             |   |-- spi at 1c05000
 spi_flash     0  [ + ]   jedec_spi_nor         |   |   `-- w25q128 at 0
 blk           0  [   ]   mtd_blk               |   |       `-- w25q128 at 0.blk <mailto:w25q128 at 0.blk>

But "sqfsls“ still doesn’t work on the block device. The problem seems to be that blk_get_devnum_by_uclass_idname() (in drivers/block/blk-uclass.c) expects the parent device of the block device to be UCLASS_MTD, but it is UCLASS_SPI_FLASH instead. This matches with the output of "dm tree“.

I don’t know how to go from here. Is this an easy fix? Or a greater architectural endeavour?

Thanks and regards,
Fabian

—

[1]

diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 7100b64bf22..582c7a0eae3 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -18,6 +18,10 @@
 
 #include "sf_internal.h"
 
+struct spi_nor_plat {
+	struct mtd_info *mtd;
+};
+
 static int spi_nor_create_read_dirmap(struct spi_nor *nor)
 {
 	struct spi_mem_dirmap_info info = {
@@ -208,14 +212,25 @@ static int spi_flash_std_get_sw_write_prot(struct udevice *dev)
 	return spi_flash_cmd_get_sw_write_prot(flash);
 }
 
+static int spi_flash_std_bind(struct udevice *dev)
+{
+	struct spi_nor_plat *plat = dev_get_plat(dev);
+
+	return mtd_bind(dev, &plat->mtd);
+}
+
 int spi_flash_std_probe(struct udevice *dev)
 {
 	struct spi_slave *slave = dev_get_parent_priv(dev);
 	struct spi_flash *flash;
+	struct mtd_info *mtd = dev_get_uclass_priv(dev);
+	struct spi_nor_plat *plat = dev_get_plat(dev);
 
 	flash = dev_get_uclass_priv(dev);
 	flash->dev = dev;
 	flash->spi = slave;
+	plat->mtd = mtd;
+
 	return spi_flash_probe_slave(flash);
 }
 
@@ -260,6 +275,8 @@ U_BOOT_DRIVER(jedec_spi_nor) = {
 	.priv_auto	= sizeof(struct spi_nor),
 	.ops		= &spi_flash_std_ops,
 	.flags		= DM_FLAG_OS_PREPARE,
+	.bind = spi_flash_std_bind,
+	.plat_auto = sizeof(struct spi_nor_plat),
 };
 
 DM_DRIVER_ALIAS(jedec_spi_nor, spansion_m25p16)



More information about the U-Boot mailing list