What I'm trying to accomplish is to be able to read the kernel directly from a squashfs partition in SPI NOR flash.

This should have been simple, as SPI-NOR is an MTD device, and MTD_BLOCK translates that to a block device, and squashfs needs a block device.

The issue is that MTD_BLOCK adds some hooks, in particular "mtd_bind()" but the only point where that ever gets called is from drivers/mtd/nand/spi/core.c

So even though one activates CONFIG_MTD_BLOCK, no mtd device or partition ever gets registered as a block device (unless you happen to have a spi-nand controller, which, contrary to spi-nor, would be unsuitable for a squashfs filesystem...)

I tried doing the obvious, that is, copy and adapt the spi-nand code into the spi-nor driver, see attached patch, but that doesn't have any effect whatsoever.

I tried similar things a few months ago, and also had a discussion here on the list, but that sort of faded out without any further results...

Example session:

zynq-uboot> mtd list
SF: Detected n25q256ax1 with page size 256 Bytes, erase size 64 KiB, total 32 MiB
0x000000000000-0x000000100000 : "qspi-boot-bin"
0x000000100000-0x000002000000 : "qspi-rootfs"
List of MTD devices:
* nor0
  - device: flash@0
  - parent: spi@e000d000
  - driver: jedec_spi_nor
  - path: /axi/spi@e000d000/flash@0
  - type: NOR flash
  - block size: 0x10000 bytes
  - min I/O: 0x1 bytes
  - 0x000000000000-0x000002000000 : "nor0"
          - 0x000000000000-0x000000100000 : "qspi-boot-bin"
          - 0x000000100000-0x000002000000 : "qspi-rootfs"
zynq-uboot> lsblk
Block Driver          Devices
-----------------------------
mmc_blk             : mmc 0
mtd_blk             : <none>
ubi_blk             : <none>
usb_storage_blk     : <none>
zynq-uboot> dm tree
 Class     Seq    Probed  Driver                Name
-----------------------------------------------------------
 root          0  [ + ]   root_driver           root_driver
 simple_bus    0  [ + ]   simple_bus            |-- axi
 gpio          0  [   ]   gpio_zynq             |   |-- gpio@e000a000
 i2c           0  [   ]   i2c_cdns              |   |-- i2c@e0004000
 i2c           1  [   ]   i2c_cdns              |   |-- i2c@e0005000
 gpio          1  [   ]   pca953x               |   |   `-- gpio@41
 serial        0  [ + ]   serial_zynq           |   |-- serial@e0000000
 spi           0  [ + ]   zynq_qspi             |   |-- spi@e000d000
 spi_flash     0  [ + ]   jedec_spi_nor         |   |   `-- flash@0
 mmc           0  [ + ]   arasan_sdhci          |   |-- mmc@e0100000
 blk           0  [   ]   mmc_blk               |   |   |-- [email protected]  bootdev       0  [   ]   mmc_bootdev           |   |   `-- [email protected]
 simple_bus    1  [ + ]   simple_bus            |   |-- slcr@f8000000
 clk           0  [ + ]   zynq_clk              |   |   `-- clkc@100
 timer         0  [ + ]   arm_twd_timer         |   |-- timer@f8f00600
 usb           0  [   ]   ehci_zynq             |   `-- usb@e0002000
 bootstd       0  [   ]   bootstd_drv           `-- bootstd
 bootmeth      0  [   ]   bootmeth_extlinux         `-- extlinux


--
Mike Looijmans
System Expert

TOPIC Embedded Products B.V.
Materiaalweg 4, 5681 RJ Best
The Netherlands

T: +31 (0) 499 33 69 69
E: [email protected]
W: www.topic.nl


From fdad3abf136a0d4f05f73506671580784297f32e Mon Sep 17 00:00:00 2001
From: Mike Looijmans <[email protected]>
Date: Tue, 25 Mar 2025 16:03:03 +0100
Subject: [PATCH] spi/sf_probe.c: Register stuff at ubi/mtd in bind

Doesn't work, see mail list
Creates block devices, but they don't work
Have to set CONFIG_SYS_MALLOC_F_LEN=0x900 to prevent allocation error
---
 drivers/mtd/spi/sf_probe.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c
index 7100b64bf22..6c7799fddb2 100644
--- a/drivers/mtd/spi/sf_probe.c
+++ b/drivers/mtd/spi/sf_probe.c
@@ -7,17 +7,24 @@
  * Copyright (C) 2013 Jagannadha Sutradharudu Teki, Xilinx Inc.
  */
 
+#include <blk.h>
 #include <dm.h>
 #include <errno.h>
+#include <linux/mtd/mtd.h>
 #include <linux/mtd/spi-nor.h>
 #include <log.h>
 #include <malloc.h>
 #include <spi.h>
 #include <spi_flash.h>
 #include <spi-mem.h>
+#include <ubi_uboot.h>
 
 #include "sf_internal.h"
 
+struct spinor_plat {
+	struct mtd_info *mtd;
+};
+
 static int spi_nor_create_read_dirmap(struct spi_nor *nor)
 {
 	struct spi_mem_dirmap_info info = {
@@ -211,14 +218,39 @@ static int spi_flash_std_get_sw_write_prot(struct udevice *dev)
 int spi_flash_std_probe(struct udevice *dev)
 {
 	struct spi_slave *slave = dev_get_parent_priv(dev);
+	struct spinor_plat *plat = dev_get_plat(dev);
 	struct spi_flash *flash;
 
 	flash = dev_get_uclass_priv(dev);
 	flash->dev = dev;
 	flash->spi = slave;
+	plat->mtd = &flash->mtd;
 	return spi_flash_probe_slave(flash);
 }
 
+int spi_flash_std_bind(struct udevice *dev)
+{
+#ifndef CONFIG_XPL_BUILD
+	struct spinor_plat *plat = dev_get_plat(dev);
+	int ret;
+
+	if (blk_enabled()) {
+		if (CONFIG_IS_ENABLED(MTD_BLOCK)) {
+			ret = mtd_bind(dev, &plat->mtd);
+			if (ret) {
+				pr_err("mtd_bind failed: %d\n", ret);
+				return ret;
+			}
+		}
+
+		if (CONFIG_IS_ENABLED(UBI_BLOCK))
+			return ubi_bind(dev);
+	}
+#endif
+
+	return 0;
+}
+
 static int spi_flash_std_remove(struct udevice *dev)
 {
 	struct spi_flash *flash = dev_get_uclass_priv(dev);
@@ -256,6 +288,7 @@ U_BOOT_DRIVER(jedec_spi_nor) = {
 	.id		= UCLASS_SPI_FLASH,
 	.of_match	= spi_flash_std_ids,
 	.probe		= spi_flash_std_probe,
+	.bind		= spi_flash_std_bind,
 	.remove		= spi_flash_std_remove,
 	.priv_auto	= sizeof(struct spi_nor),
 	.ops		= &spi_flash_std_ops,
-- 
2.43.0

Reply via email to