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