Bind the SPI-NOR jedec_spi_nor device into the MTD block subsystem
from a new jedec_spi_nor_bind() .bind() hook, matching the
spinand_bind()/mmc_bind() precedent of creating blk children once at
bind time rather than on every probe. Set the block descriptor's
logical block size, log2blksz, and lba from a new
CONFIG_MTD_BLOCK_SIZE Kconfig value (default 4 KB) instead of a DT
property, matching the sector size GPT images are generated with.

No changes to mtd_bind()'s signature or behavior for existing
callers.

.bind() runs exactly once per device lifetime, so the mtdblock child
is created unconditionally there. Probe-time only looks the child up
via blk_find_from_parent() to refresh the mtd_info pointer and block
geometry (blksz, log2blksz, lba, part_type), which must still happen
on every probe since flash->mtd is only valid after spi_nor_scan()
succeeds. If the lookup fails, that is a real error (the child
failed to bind), reported via dev_err() and unwound through the
existing err_read_id path, which is a generic post-spi_claim_bus()
cleanup and not specific to ID-read failures.

Wrap the block in a preprocessor '#if CONFIG_IS_ENABLED(MTD_BLOCK)'
guard instead of a runtime check, since CONFIG_MTD_BLOCK_SIZE is only
emitted to autoconf.h when MTD_BLOCK is enabled; referencing it
unconditionally fails to build with MTD_BLOCK disabled.

Signed-off-by: Vandhiadevan Karunamoorthy 
<[email protected]>
---
 drivers/mtd/Kconfig        |  9 +++++++++
 drivers/mtd/spi/sf_probe.c | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 21b8b21f6b2..41a4ee9aeea 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -39,6 +39,15 @@ config MTD_BLOCK
          Enable support for block device access to MTD devices
          using blk_ops abstraction.
 
+config MTD_BLOCK_SIZE
+       hex "MTD logical block size"
+       depends on MTD_BLOCK
+       default 0x1000
+       help
+         Logical block size exposed by mtdblock/ubiblock devices to the
+         block layer. This is the sector size used for GPT partitioning,
+         not the underlying flash erase size.
+
 config SYS_MTDPARTS_RUNTIME
        bool "Allow MTDPARTS to be configured at runtime"
        depends on !COMPILE_TEST
diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 7100b64bf22..8143f53c3ae 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -9,12 +9,15 @@
 
 #include <dm.h>
 #include <errno.h>
+#include <linux/mtd/mtd.h>
 #include <linux/mtd/spi-nor.h>
 #include <log.h>
 #include <malloc.h>
+#include <part.h>
 #include <spi.h>
 #include <spi_flash.h>
 #include <spi-mem.h>
+#include <dm/device_compat.h>
 
 #include "sf_internal.h"
 
@@ -100,6 +103,28 @@ static int spi_flash_probe_slave(struct spi_flash *flash)
        if (ret)
                goto err_read_id;
 
+#if CONFIG_IS_ENABLED(MTD_BLOCK)
+       if (CONFIG_IS_ENABLED(DM_SPI_FLASH)) {
+               struct mtd_info **plat = dev_get_plat(flash->dev);
+               struct udevice *bdev;
+               struct blk_desc *bdesc;
+
+               /* The mtdblock child is created by jedec_spi_nor_bind(). */
+               ret = blk_find_from_parent(flash->dev, &bdev);
+               if (ret) {
+                       dev_err(flash->dev, "mtdblock child not found: %d\n", 
ret);
+                       goto err_read_id;
+               }
+
+               bdesc = dev_get_uclass_plat(bdev);
+               *plat = &flash->mtd;
+               bdesc->blksz = CONFIG_MTD_BLOCK_SIZE;
+               bdesc->log2blksz = LOG2(bdesc->blksz);
+               bdesc->lba = lldiv(flash->mtd.size, bdesc->blksz);
+               bdesc->part_type = PART_TYPE_UNKNOWN;
+       }
+#endif
+
        if (CONFIG_IS_ENABLED(SPI_DIRMAP)) {
                ret = spi_nor_create_read_dirmap(flash);
                if (ret)
@@ -251,13 +276,23 @@ static const struct udevice_id spi_flash_std_ids[] = {
        { }
 };
 
+static int jedec_spi_nor_bind(struct udevice *dev)
+{
+       if (!CONFIG_IS_ENABLED(MTD_BLOCK))
+               return 0;
+
+       return mtd_bind(dev, dev_get_plat(dev));
+}
+
 U_BOOT_DRIVER(jedec_spi_nor) = {
        .name           = "jedec_spi_nor",
        .id             = UCLASS_SPI_FLASH,
        .of_match       = spi_flash_std_ids,
+       .bind           = jedec_spi_nor_bind,
        .probe          = spi_flash_std_probe,
        .remove         = spi_flash_std_remove,
        .priv_auto      = sizeof(struct spi_nor),
+       .plat_auto      = sizeof(struct mtd_info *),
        .ops            = &spi_flash_std_ops,
        .flags          = DM_FLAG_OS_PREPARE,
 };

-- 
2.34.1

Reply via email to