[PATCH 04/11] mtd: spi-nor: cadence: add a PBL driver
Michael Tretter
m.tretter at pengutronix.de
Wed Oct 7 03:55:49 PDT 2026
Integrate the Cadence QSPI driver with read-only support into the PBL
with a pbl_bio abstraction. This allows to load additional binaries and
firmware from the flash while still in the PBL without requiring a full
barebox proper.
Signed-off-by: Michael Tretter <m.tretter at pengutronix.de>
---
drivers/mtd/spi-nor/Kconfig | 3 +
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/cadence-quadspi-pbl.c | 104 ++++++++++++++++++++++++++++++
include/pbl/mtd.h | 26 ++++++++
4 files changed, 134 insertions(+)
diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index b34c69203ec2..e703ce707c5b 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -26,6 +26,9 @@ config SPI_CADENCE_QUADSPI
help
This enables support for the Cadence Quad SPI controller and NOR flash.
+config SPI_CADENCE_QUADSPI_PBL
+ bool
+
config SPI_SYNOPSYS_OCTALSPI_NOR
tristate "Synopsys DesignWare Octal SPI controller"
help
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index ed73a95ec6b9..9e229a37ddfb 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-pbl-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
obj-$(CONFIG_SPI_CADENCE_QUADSPI) += cadence-quadspi.o cadence-quadspi-common.o
+pbl-$(CONFIG_SPI_CADENCE_QUADSPI_PBL) += cadence-quadspi-pbl.o cadence-quadspi-common.o
obj-$(CONFIG_SPI_SYNOPSYS_OCTALSPI_NOR) += dw-ospi-nor.o
diff --git a/drivers/mtd/spi-nor/cadence-quadspi-pbl.c b/drivers/mtd/spi-nor/cadence-quadspi-pbl.c
new file mode 100644
index 000000000000..b2bb00d15dc7
--- /dev/null
+++ b/drivers/mtd/spi-nor/cadence-quadspi-pbl.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <io.h>
+#include <linux/array_size.h>
+#include <linux/mtd/spi-nor.h>
+#include <linux/printk.h>
+#include <linux/time.h>
+#include <pbl/bio.h>
+#include <pbl/mtd.h>
+
+#include "cadence-quadspi.h"
+
+static void cqspi_write(struct spi_nor *nor, loff_t to,
+ size_t len, size_t *retlen, const u_char *buf)
+{
+}
+
+static int cqspi_get_flash_pdata(struct cqspi_st *cqspi,
+ struct cqspi_flash_pdata *f_pdata)
+{
+ void __iomem *reg_base = cqspi->iobase;
+
+ f_pdata->block_size = (readl(reg_base + CQSPI_REG_SIZE) >>
+ CQSPI_REG_SIZE_BLOCK_LSB) &
+ CQSPI_REG_SIZE_BLOCK_MASK;
+ cqspi->no_reconfig = true;
+
+ return 0;
+}
+
+static int cqspi_setup_flash(struct cqspi_st *cqspi,
+ struct cqspi_flash_pdata *f_pdata)
+{
+ const struct spi_nor_hwcaps hwcaps = {
+ .mask = SNOR_HWCAPS_READ |
+ SNOR_HWCAPS_READ_FAST |
+ SNOR_HWCAPS_READ_1_1_2 |
+ SNOR_HWCAPS_READ_1_1_4 |
+ SNOR_HWCAPS_PP,
+ };
+ struct spi_nor *nor;
+ struct mtd_info *mtd;
+ int ret;
+
+ ret = cqspi_get_flash_pdata(cqspi, f_pdata);
+ if (ret)
+ return ret;
+
+ nor = &f_pdata->nor;
+ mtd = &f_pdata->mtd;
+
+ nor->mtd = mtd;
+
+ nor->priv = cqspi;
+ nor->read_reg = cqspi_read_reg;
+ nor->write_reg = cqspi_write_reg;
+ nor->read = cqspi_read;
+ nor->write = cqspi_write;
+
+ return spi_nor_scan(nor, NULL, &hwcaps, false);
+}
+
+static int cqspi_bio_read(struct pbl_bio *bio, off_t start,
+ void *buf, unsigned int nblocks)
+{
+ struct cqspi_st *cqspi = bio->priv;
+ struct spi_nor *nor = &cqspi->f_pdata[0].nor;
+ int ret;
+ size_t count = 0;
+
+ ret = nor->read(nor, start, nblocks, &count, buf);
+ if (ret)
+ return ret;
+
+ return count;
+}
+
+static struct cqspi_st cqspi;
+
+int cqspi_bio_init(struct pbl_bio *bio,
+ void __iomem *iobase, void __iomem *ahb_base,
+ unsigned int master_ref_clk,
+ struct cadence_qspi_platform_data *qspi_pdata)
+{
+ cqspi.master_ref_clk_hz = master_ref_clk;
+ cqspi.iobase = iobase;
+ cqspi.ahb_base = ahb_base;
+
+ cqspi_wait_idle(&cqspi);
+ cqspi_controller_init(&cqspi);
+
+ cqspi.current_cs = -1;
+ cqspi.sclk = 0;
+
+ cqspi.is_decoded_cs = qspi_pdata->is_decoded_cs;
+ cqspi.fifo_depth = qspi_pdata->fifo_depth;
+
+ cqspi_setup_flash(&cqspi, &cqspi.f_pdata[0]);
+
+ bio->priv = &cqspi;
+ bio->read = cqspi_bio_read;
+
+ return 0;
+}
diff --git a/include/pbl/mtd.h b/include/pbl/mtd.h
new file mode 100644
index 000000000000..f58b61d29997
--- /dev/null
+++ b/include/pbl/mtd.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __PBL_MTD_H__
+#define __PBL_MTD_H__
+
+#include <linux/types.h>
+
+struct pbl_bio;
+
+#include <platform_data/cadence_qspi.h>
+
+#ifdef CONFIG_SPI_CADENCE_QUADSPI_PBL
+int cqspi_bio_init(struct pbl_bio *bio,
+ void __iomem *iobase, void __iomem *ahb_base,
+ unsigned int master_ref_clk,
+ struct cadence_qspi_platform_data *qspi_pdata);
+#else
+static inline int cqspi_bio_init(struct pbl_bio *bio,
+ void __iomem *iobase, void __iomem *ahb_base,
+ unsigned int master_ref_clk,
+ struct cadence_qspi_platform_data *qspi_pdata)
+{
+ return -ENOSYS;
+}
+#endif
+
+#endif /* __PBL_MTD_H__ */
--
2.47.3
More information about the barebox
mailing list