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