linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] mtd: spi-nor: Add VIA/WonderMedia serial flash controller driver
@ 2025-05-10 19:42 Alexey Charkov
  2025-05-10 19:42 ` [PATCH 1/3] dt-bindings: spi: Add VIA/WonderMedia serial flash controller Alexey Charkov
                   ` (2 more replies)
  0 siblings, 3 replies; 16+ messages in thread
From: Alexey Charkov @ 2025-05-10 19:42 UTC (permalink / raw)
  To: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Tudor Ambarus, Pratyush Yadav, Michael Walle, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Krzysztof Kozlowski
  Cc: linux-spi, devicetree, linux-kernel, linux-mtd, linux-arm-kernel,
	Alexey Charkov

Add a driver for the self-contained SPI NOR flash controller found on
VIA/WonderMedia SoCs, along with the respective DT binding and DTS.

The driver is a clean reimplementation based on the Linux SPI NOR
framework, although only chip probing routines are SPI NOR specific.
The rest of the controller operation is abstracted away behind a small
set of MMIO registers and a physical memory mapping for chip contents.
In fact, the vendor's implementation open-coded all driver operations
on top of the MTD framework directly, but had to rely on a static table
of supported flash chips indexed by ID due to the lack of auto-probing.

Signed-off-by: Alexey Charkov <alchark@gmail.com>
---
Alexey Charkov (3):
      dt-bindings: spi: Add VIA/WonderMedia serial flash controller
      mtd: spi-nor: Add a driver for the VIA/WonderMedia serial flash controller
      ARM: dts: vt8500: Add serial flash controller and its clock

 .../devicetree/bindings/spi/via,vt8500-sflash.yaml | 122 +++++
 MAINTAINERS                                        |   2 +
 arch/arm/boot/dts/vt8500/vt8500-bv07.dts           |  37 ++
 arch/arm/boot/dts/vt8500/vt8500.dtsi               |  34 ++
 arch/arm/boot/dts/vt8500/wm8505-ref.dts            |  37 ++
 arch/arm/boot/dts/vt8500/wm8505.dtsi               |  21 +
 arch/arm/boot/dts/vt8500/wm8650-mid.dts            |  37 ++
 arch/arm/boot/dts/vt8500/wm8650.dtsi               |  21 +
 arch/arm/boot/dts/vt8500/wm8750-apc8750.dts        |  37 ++
 arch/arm/boot/dts/vt8500/wm8750.dtsi               |  21 +
 arch/arm/boot/dts/vt8500/wm8850-w70v2.dts          |  37 ++
 arch/arm/boot/dts/vt8500/wm8850.dtsi               |  21 +
 arch/arm/boot/dts/vt8500/wm8950-apc-rock.dts       |  37 ++
 drivers/mtd/spi-nor/controllers/Kconfig            |  14 +
 drivers/mtd/spi-nor/controllers/Makefile           |   1 +
 drivers/mtd/spi-nor/controllers/wmt-sflash.c       | 525 +++++++++++++++++++++
 16 files changed, 1004 insertions(+)
---
base-commit: ed61cb3d78d585209ec775933078e268544fe9a4
change-id: 20250510-wmt-sflash-b0ba35f1a3ae

Best regards,
-- 
Alexey Charkov <alchark@gmail.com>



^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/3] dt-bindings: spi: Add VIA/WonderMedia serial flash controller
  2025-05-10 19:42 [PATCH 0/3] mtd: spi-nor: Add VIA/WonderMedia serial flash controller driver Alexey Charkov
@ 2025-05-10 19:42 ` Alexey Charkov
  2025-05-14 20:41   ` Rob Herring
  2025-05-10 19:42 ` [PATCH 2/3] mtd: spi-nor: Add a driver for the " Alexey Charkov
  2025-05-10 19:42 ` [PATCH 3/3] ARM: dts: vt8500: Add serial flash controller and its clock Alexey Charkov
  2 siblings, 1 reply; 16+ messages in thread
From: Alexey Charkov @ 2025-05-10 19:42 UTC (permalink / raw)
  To: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Tudor Ambarus, Pratyush Yadav, Michael Walle, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Krzysztof Kozlowski
  Cc: linux-spi, devicetree, linux-kernel, linux-mtd, linux-arm-kernel,
	Alexey Charkov

Add a binding for the serial flash controller found on VIA/WonderMedia
SoCs, which provides semi-transparent access to SPI NOR chips by
mapping their contents to the physical CPU address space.

Signed-off-by: Alexey Charkov <alchark@gmail.com>
---
 .../devicetree/bindings/spi/via,vt8500-sflash.yaml | 122 +++++++++++++++++++++
 MAINTAINERS                                        |   1 +
 2 files changed, 123 insertions(+)

diff --git a/Documentation/devicetree/bindings/spi/via,vt8500-sflash.yaml b/Documentation/devicetree/bindings/spi/via,vt8500-sflash.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d2ea0dacdd56118c0cb5a1cb510ceb7591e1e5ca
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/via,vt8500-sflash.yaml
@@ -0,0 +1,122 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/via,vt8500-sflash.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: VIA/WonderMedia serial flash controller
+
+description:
+  This controller is used on VIA/WonderMedia SoCs such as VIA VT8500,
+  WonderMedia WM8850 and similar. It provides a semi-transparent interface
+  for reading and writing SPI NOR chip contents via a physical memory map,
+  abstracting away all SPI communication, while also providing a direct
+  mechanism for issuing "programmable commands" to the underlying SPI chip
+
+maintainers:
+  - Alexey Charkov <alchark@gmail.com>
+
+properties:
+  compatible:
+    enum:
+      - via,vt8500-sflash
+      - wm,wm8505-sflash
+      - wm,wm8650-sflash
+      - wm,wm8750-sflash
+      - wm,wm8850-sflash
+
+  reg:
+    items:
+      - description: MMIO registers region of the controller
+      - description:
+          Physical memory region within which the controller will map the
+          flash contents of chip 0 for reading and writing. If the flash
+          size is smaller than this region, it will be mapped at its end.
+          Note that if this chip is used as the boot device (as is most
+          often the case), the boot ROM maps it at the very end of the
+          CPU address space (i.e. ending at 0xffffffff)
+      - description:
+          Physical memory region within which the controller will map the
+          flash contents of chip 1 for reading and writing. If the flash
+          size is smaller than this region, it will be mapped at its end
+
+  reg-names:
+    items:
+      - const: io
+      - const: chip0-mmap
+      - const: chip1-mmap
+
+  clocks:
+    maxItems: 1
+
+  "#address-cells":
+    const: 1
+
+  "#size-cells":
+    const: 0
+
+patternProperties:
+  "^flash@[0-1]$":
+    type: object
+    additionalProperties: true
+
+    properties:
+      reg:
+        minimum: 0
+        maximum: 1
+
+required:
+  - compatible
+  - reg
+  - reg-names
+  - clocks
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    sflash: spi-nor-controller@d8002000 {
+        compatible = "wm,wm8850-sflash";
+        reg = <0xd8002000 0x400>,
+              <0xff800000 0x800000>,
+              <0xef800000 0x800000>;
+        reg-names = "io", "chip0-mmap", "chip1-mmap";
+        clocks = <&clksf>;
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        flash@0 {
+            compatible = "jedec,spi-nor";
+            reg = <0>;
+
+            partitions {
+                compatible = "fixed-partitions";
+                #address-cells = <1>;
+                #size-cells = <1>;
+
+                partition@0 {
+                    label = "U-boot";
+                    reg = <0 0x50000>;
+                    read-only;
+                };
+
+                partition@1 {
+                    label = "U-boot environment 1";
+                    reg = <0x50000 0x10000>;
+                };
+
+                partition@2 {
+                    label = "U-boot environment 2";
+                    reg = <0x60000 0x10000>;
+                };
+
+                partition@3 {
+                    label = "W-load";
+                    reg = <0x70000 0x10000>;
+                    read-only;
+                };
+            };
+        };
+    };
+
+...
diff --git a/MAINTAINERS b/MAINTAINERS
index 6dbdf02d6b0c9357ad1da520a0f6c16b7f38f879..f09c457bbfc5ef71a3f8379c111bac52b767cbbc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3475,6 +3475,7 @@ F:	Documentation/devicetree/bindings/hwinfo/via,vt8500-scc-id.yaml
 F:	Documentation/devicetree/bindings/i2c/wm,wm8505-i2c.yaml
 F:	Documentation/devicetree/bindings/interrupt-controller/via,vt8500-intc.yaml
 F:	Documentation/devicetree/bindings/pwm/via,vt8500-pwm.yaml
+F:	Documentation/devicetree/bindings/spi/via,vt8500-sflash.yaml
 F:	arch/arm/boot/dts/vt8500/
 F:	arch/arm/mach-vt8500/
 F:	drivers/clocksource/timer-vt8500.c

-- 
2.49.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 2/3] mtd: spi-nor: Add a driver for the VIA/WonderMedia serial flash controller
  2025-05-10 19:42 [PATCH 0/3] mtd: spi-nor: Add VIA/WonderMedia serial flash controller driver Alexey Charkov
  2025-05-10 19:42 ` [PATCH 1/3] dt-bindings: spi: Add VIA/WonderMedia serial flash controller Alexey Charkov
@ 2025-05-10 19:42 ` Alexey Charkov
  2025-05-11 11:13   ` kernel test robot
                     ` (2 more replies)
  2025-05-10 19:42 ` [PATCH 3/3] ARM: dts: vt8500: Add serial flash controller and its clock Alexey Charkov
  2 siblings, 3 replies; 16+ messages in thread
From: Alexey Charkov @ 2025-05-10 19:42 UTC (permalink / raw)
  To: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Tudor Ambarus, Pratyush Yadav, Michael Walle, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Krzysztof Kozlowski
  Cc: linux-spi, devicetree, linux-kernel, linux-mtd, linux-arm-kernel,
	Alexey Charkov

The controller is tailored to SPI NOR flash memory and abstracts away all
SPI communications behind a small set of MMIO registers and a physical
memory mapping of the actual chip contents.

It doesn't expose chip probing functions beyond reading the ID though, so
use lower level chip opcodes via the "programmable command mode" of the
controller and the kernel's SPI NOR framework to avoid hard-coding chip
parameters for each ID the way the vendor kernel does it.

Currently tested on a WonderMedia WM8950 SoC with a Macronix MX25L4005A
flash chip (APC Rock board), but should work on all VIA/WonderMedia SoCs

Signed-off-by: Alexey Charkov <alchark@gmail.com>
---
 MAINTAINERS                                  |   1 +
 drivers/mtd/spi-nor/controllers/Kconfig      |  14 +
 drivers/mtd/spi-nor/controllers/Makefile     |   1 +
 drivers/mtd/spi-nor/controllers/wmt-sflash.c | 525 +++++++++++++++++++++++++++
 4 files changed, 541 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index f09c457bbfc5ef71a3f8379c111bac52b767cbbc..ff849c03a3b79a0487d3ab7e704ed11ffdb58f41 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3481,6 +3481,7 @@ F:	arch/arm/mach-vt8500/
 F:	drivers/clocksource/timer-vt8500.c
 F:	drivers/i2c/busses/i2c-viai2c-wmt.c
 F:	drivers/mmc/host/wmt-sdmmc.c
+F:	drivers/mtd/spi-nor/controllers/wmt-sflash.c
 F:	drivers/pwm/pwm-vt8500.c
 F:	drivers/rtc/rtc-vt8500.c
 F:	drivers/soc/vt8500/
diff --git a/drivers/mtd/spi-nor/controllers/Kconfig b/drivers/mtd/spi-nor/controllers/Kconfig
index ca45dcd3ffe81f87dbf9ddc2a1535244ea92be20..aa8400b9aeaaec3b8b3f8996d501f5ac77a488ea 100644
--- a/drivers/mtd/spi-nor/controllers/Kconfig
+++ b/drivers/mtd/spi-nor/controllers/Kconfig
@@ -16,3 +16,17 @@ config SPI_NXP_SPIFI
 	  SPIFI is a specialized controller for connecting serial SPI
 	  Flash. Enable this option if you have a device with a SPIFI
 	  controller and want to access the Flash as a mtd device.
+
+config SPI_WMT_SFLASH
+	tristate "VIA/WonderMedia serial flash controller"
+	depends on ARCH_VT8500 || COMPILE_TEST
+	depends on OF
+	depends on HAS_IOMEM
+	help
+	  Enable support for the VIA/WonderMedia serial flash controller.
+
+	  This is the specialized controller driving SPI NOR flash chips
+	  inside VIA/WonderMedia SoCs. Most if not all VIA/WonderMedia
+	  based devices use SPI NOR flash as their boot storage, so select
+	  this if you need to access the primary or secondary bootloader
+	  and their environment partitions.
diff --git a/drivers/mtd/spi-nor/controllers/Makefile b/drivers/mtd/spi-nor/controllers/Makefile
index 0b8e1d5309138619bbfdf3e27639b6be2935e65e..9c0365354a37986755f3c067ba2f1f5708fd20ad 100644
--- a/drivers/mtd/spi-nor/controllers/Makefile
+++ b/drivers/mtd/spi-nor/controllers/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_SPI_HISI_SFC)	+= hisi-sfc.o
 obj-$(CONFIG_SPI_NXP_SPIFI)	+= nxp-spifi.o
+obj-$(CONFIG_SPI_WMT_SFLASH)	+= wmt-sflash.o
diff --git a/drivers/mtd/spi-nor/controllers/wmt-sflash.c b/drivers/mtd/spi-nor/controllers/wmt-sflash.c
new file mode 100644
index 0000000000000000000000000000000000000000..d63c3402345a9dac7e8a0591bb032481ad3b02f7
--- /dev/null
+++ b/drivers/mtd/spi-nor/controllers/wmt-sflash.c
@@ -0,0 +1,525 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * VIA/WonderMedia SPI NOR flash controller driver
+ *
+ * Copyright (c) 2025 Alexey Charkov <alchark@gmail.com>
+ */
+#include <linux/clk.h>
+#include <linux/bitops.h>
+#include <linux/errno.h>
+#include <linux/iopoll.h>
+#include <linux/log2.h>
+#include <linux/minmax.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/spi-nor.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#define SF_CHIP_SEL_0_CFG	0x000		/* chip select 0 config */
+#define SF_CHIP_SEL_1_CFG	0x008		/* chip select 0 config */
+#define SF_CHIP_SEL_CFG(x)	(8 * (x))
+#define SF_CHIP_SEL_ADDR	GENMASK(31, 16) /* 64kb aligned address */
+#define SF_CHIP_SEL_SIZE	GENMASK(11, 8)	/* log2(size/32kb) */
+
+#define SF_SPI_INTF_CFG		0x040	/* SPI interface config */
+#define SF_ADDR_WIDTH_32	BIT(0)	/* 0: 24 bit, 1: 32 bit addr */
+#define SF_USR_RD_CMD_MOD	BIT(4)	/* 0: normal, 1: user cmd read */
+#define SF_USR_WR_CMD_MOD	BIT(5)	/* 0: normal, 1: user cmd write */
+#define SF_PROG_CMD_MOD		BIT(6)	/* 0: normal, 1: prog cmd */
+#define SF_CS_DELAY		GENMASK(18, 16)	/* chip select delay */
+#define SF_RES_DELAY		GENMASK(27, 24) /* reset delay */
+#define SF_PDWN_DELAY		GENMASK(31, 28) /* power down delay */
+
+#define SF_SPI_RD_WR_CTR	0x050	/* read/write control */
+#define SF_RD_FAST		BIT(0)	/* 0: normal read, 1: fast read */
+#define SF_RD_ID		BIT(4)	/* 0: read status, 1: read ID */
+
+#define SF_SPI_WR_EN_CTR	0x060	/* write enable control */
+#define SF_CS0_WR_EN		BIT(0)
+#define SF_CS1_WR_EN		BIT(1)
+#define SF_CS_WR_EN(x)		BIT(x)
+
+#define SF_SPI_ER_CTR		0x070	/* erase control */
+#define SF_CHIP_ERASE		BIT(0)	/* full chip erase */
+#define SF_SEC_ERASE		BIT(15)	/* sector erase */
+
+#define SF_SPI_ER_START_ADDR	0x074	/* erase start address */
+#define SF_CHIP_ER_CS0		BIT(0)	/* erase chip 0 */
+#define SF_CHIP_ER_CS1		BIT(1)	/* erase chip 1 */
+#define SF_CHIP_ER_CS(x)	BIT(x)
+#define SF_ER_START_ADDR	GENMASK(31, 16)
+
+#define SF_SPI_ERROR_STATUS	0x080
+#define SF_MASLOCK_ERR		BIT(0)	/* master lock */
+#define SF_PCMD_ACC_ERR		BIT(1)	/* programmable cmd access */
+#define SF_PCMD_OP_ERR		BIT(2)	/* programmable cmd opcode */
+#define SF_PWR_DWN_ACC_ERR	BIT(3)	/* power down access */
+#define SF_MEM_REGION_ERR	BIT(4)	/* memory region */
+#define SF_WR_PROT_ERR		BIT(5)	/* write protection */
+#define SF_SPI_ERROR_CLEARALL	(SF_MASLOCK_ERR | \
+				 SF_PCMD_ACC_ERR | \
+				 SF_PCMD_OP_ERR | \
+				 SF_PWR_DWN_ACC_ERR | \
+				 SF_MEM_REGION_ERR | \
+				 SF_WR_PROT_ERR)
+
+#define SF_SPI_MEM_0_SR_ACC	0x100	/* status read from chip 0 */
+#define SF_SPI_MEM_1_SR_ACC	0x110	/* status read from chip 1 */
+#define SF_SPI_MEM_SR_ACC(x)	(0x100 + 0x10 * (x))
+
+#define SF_SPI_PDWN_CTR_0	0x180	/* power down chip 0 */
+#define SF_SPI_PDWN_CTR_1	0x190	/* power down chip 1 */
+#define SF_SPI_PDWN_CTR_(x)	(0x180 + 0x10 * (x))
+#define SF_PWR_DOWN		BIT(0)
+
+#define SF_SPI_PROG_CMD_CTR	0x200	/* programmable cmd control */
+#define SF_PROG_CMD_EN		BIT(0)	/* enable programmable cmd */
+#define SF_PROG_CMD_CS		GENMASK(1, 1)	/* chip select for cmd */
+#define SF_RX_DATA_SIZE		GENMASK(22, 16)	/* receive data size */
+#define SF_TX_DATA_SIZE		GENMASK(30, 24)	/* transmit data size */
+
+#define SF_SPI_USER_CMD_VAL	0x210
+#define SF_USR_RD_CMD		GENMASK(7, 0)	/* user read command */
+#define SF_USR_WR_CMD		GENMASK(23, 16)	/* user write command */
+
+#define SF_SPI_PROG_CMD_WBF	0x300	/* 64 bytes pcmd write buffer */
+#define SF_SPI_PROG_CMD_RBF	0x380	/* 64 bytes pcmd read buffer */
+
+#define SF_WAIT_TIMEOUT		1000000
+
+struct wmt_sflash_priv {
+	size_t			cs;
+	struct wmt_sflash_host	*host;
+	void __iomem		*mmap_base;
+	resource_size_t		mmap_phys;
+};
+
+#define SF_MAX_CHIP_NUM		2
+struct wmt_sflash_host {
+	struct device		*dev;
+	struct clk		*clk;
+
+	void __iomem		*regbase;
+	struct resource		*mmap_res[SF_MAX_CHIP_NUM];
+
+	struct spi_nor		*nor[SF_MAX_CHIP_NUM];
+	size_t			num_chips;
+};
+
+static int wmt_sflash_prep(struct spi_nor *nor)
+{
+	struct wmt_sflash_priv *priv = nor->priv;
+	struct wmt_sflash_host *host = priv->host;
+
+	return clk_prepare_enable(host->clk);
+}
+
+static void wmt_sflash_unprep(struct spi_nor *nor)
+{
+	struct wmt_sflash_priv *priv = nor->priv;
+	struct wmt_sflash_host *host = priv->host;
+
+	clk_disable_unprepare(host->clk);
+}
+
+static void wmt_sflash_pcmd_mode(struct wmt_sflash_host *host, bool enable)
+{
+	u32 reg = readl(host->regbase + SF_SPI_INTF_CFG);
+
+	reg &= ~SF_PROG_CMD_MOD;
+	reg |= FIELD_PREP(SF_PROG_CMD_MOD, enable);
+	writel(reg, host->regbase + SF_SPI_INTF_CFG);
+}
+
+static inline int wmt_sflash_wait_pcmd(struct wmt_sflash_host *host)
+{
+	u32 reg;
+
+	return readl_poll_timeout(host->regbase + SF_SPI_PROG_CMD_CTR, reg,
+		!(reg & SF_PROG_CMD_EN), 1, SF_WAIT_TIMEOUT);
+}
+
+static int wmt_sflash_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
+			       size_t len)
+{
+	struct wmt_sflash_priv *priv = nor->priv;
+	struct wmt_sflash_host *host = priv->host;
+	int ret;
+	u32 reg;
+
+	if (len > 64) {
+		dev_err(host->dev,
+		"Cannot read %d bytes from registers\n", len);
+		return -EINVAL;
+	}
+
+	wmt_sflash_pcmd_mode(host, true);
+	writeb(opcode, host->regbase + SF_SPI_PROG_CMD_WBF);
+
+	reg = SF_PROG_CMD_EN |
+	      FIELD_PREP(SF_PROG_CMD_CS, priv->cs) |
+	      FIELD_PREP(SF_TX_DATA_SIZE, 1) |
+	      FIELD_PREP(SF_RX_DATA_SIZE, len);
+	writel(reg, host->regbase + SF_SPI_PROG_CMD_CTR);
+
+	ret = wmt_sflash_wait_pcmd(host);
+
+	if (len)
+		memcpy_fromio(buf, host->regbase + SF_SPI_PROG_CMD_RBF, len);
+
+	wmt_sflash_pcmd_mode(host, false);
+
+	return ret;
+}
+
+static int wmt_sflash_write_reg(struct spi_nor *nor, u8 opcode, const u8 *buf,
+				size_t len)
+{
+	struct wmt_sflash_priv *priv = nor->priv;
+	struct wmt_sflash_host *host = priv->host;
+	int ret;
+	u32 reg;
+
+	if (len > 63) {
+		dev_err(host->dev,
+		"Cannot write %d bytes to registers\n", len);
+		return -EINVAL;
+	}
+
+	wmt_sflash_pcmd_mode(host, true);
+	writeb(opcode, host->regbase + SF_SPI_PROG_CMD_WBF);
+
+	if (len)
+		memcpy_toio(host->regbase + SF_SPI_PROG_CMD_WBF + 1, buf, len);
+
+	reg = SF_PROG_CMD_EN |
+	      FIELD_PREP(SF_PROG_CMD_CS, priv->cs) |
+	      FIELD_PREP(SF_TX_DATA_SIZE, len + 1);
+	writel(reg, host->regbase + SF_SPI_PROG_CMD_CTR);
+
+	ret = wmt_sflash_wait_pcmd(host);
+	wmt_sflash_pcmd_mode(host, false);
+
+	return ret;
+}
+
+static int wmt_sflash_wait_spi(struct wmt_sflash_priv *priv)
+{
+	struct wmt_sflash_host *host = priv->host;
+	int timeout = SF_WAIT_TIMEOUT;
+	u32 error;
+
+	while (timeout--) {
+		if (!(readl(host->regbase +
+			    SF_SPI_MEM_SR_ACC(priv->cs)) & 1))
+			return 0;
+
+		error = readl(host->regbase + SF_SPI_ERROR_STATUS);
+		if (error & SF_MASLOCK_ERR) {
+			dev_err(host->dev,
+				"Master lock error\n");
+			goto err;
+		}
+		if (error & SF_PCMD_ACC_ERR) {
+			dev_err(host->dev,
+				"Programmable command access error\n");
+			goto err;
+		}
+		if (error & SF_PCMD_OP_ERR) {
+			dev_err(host->dev,
+				"Programmable command opcode error\n");
+			goto err;
+		}
+		if (error & SF_PWR_DWN_ACC_ERR) {
+			dev_err(host->dev,
+				"Power down access error\n");
+			goto err;
+		}
+		if (error & SF_MEM_REGION_ERR) {
+			dev_err(host->dev,
+				"Memory region error\n");
+			goto err;
+		}
+		if (error & SF_WR_PROT_ERR) {
+			dev_err(host->dev,
+				"Write protection error\n");
+			goto err;
+		}
+	}
+	return 0;
+
+err:
+	writel(SF_SPI_ERROR_CLEARALL, host->regbase + SF_SPI_ERROR_STATUS);
+	return -EBUSY;
+}
+
+static ssize_t wmt_sflash_read(struct spi_nor *nor, loff_t from, size_t len,
+			       u_char *read_buf)
+{
+	struct wmt_sflash_priv *priv = nor->priv;
+	struct wmt_sflash_host *host = priv->host;
+	u32 reg = nor->read_opcode == SPINOR_OP_READ_FAST ? SF_RD_FAST : 0;
+
+	writel(reg, host->regbase + SF_SPI_RD_WR_CTR);
+
+	if (wmt_sflash_wait_spi(priv))
+		return 0;
+
+	memcpy_fromio(read_buf, priv->mmap_base + from, len);
+	return len;
+}
+
+static ssize_t wmt_sflash_write(struct spi_nor *nor, loff_t to, size_t len,
+				const u_char *write_buf)
+{
+	struct wmt_sflash_priv *priv = nor->priv;
+	struct wmt_sflash_host *host = priv->host;
+	size_t burst, offset = 0;
+
+	writel(SF_CS_WR_EN(priv->cs),
+	       host->regbase + SF_SPI_WR_EN_CTR);
+
+	while (offset < len) {
+		/* select 8 / 4 / 2 / 1 byte write length */
+		burst = 1 << min(3, ilog2(len - offset));
+		memcpy_toio(priv->mmap_base + to + offset,
+			    write_buf + offset, burst);
+
+		if (wmt_sflash_wait_spi(priv))
+			return offset;
+
+		offset += burst;
+	}
+
+	writel(0, host->regbase + SF_SPI_WR_EN_CTR);
+
+	return offset;
+}
+
+static int wmt_sflash_erase(struct spi_nor *nor, loff_t offs)
+{
+	struct wmt_sflash_priv *priv = nor->priv;
+	struct wmt_sflash_host *host = priv->host;
+	int ret = 0;
+	u32 reg;
+
+	if (offs & (SZ_64K - 1)) {
+		dev_err(host->dev,
+			"Erase offset 0x%llx not on 64k boundary\n", offs);
+		return -EINVAL;
+	}
+
+	writel(SF_CS_WR_EN(priv->cs),
+	       host->regbase + SF_SPI_WR_EN_CTR);
+
+	reg = SF_CHIP_ER_CS(priv->cs) |
+	      FIELD_PREP(SF_ER_START_ADDR, (priv->mmap_phys + offs) >> 16);
+	writel(reg, host->regbase + SF_SPI_ER_START_ADDR);
+
+	writel(SF_SEC_ERASE, host->regbase + SF_SPI_ER_CTR);
+
+	ret = wmt_sflash_wait_spi(priv);
+	writel(0, host->regbase + SF_SPI_WR_EN_CTR);
+
+	return ret;
+}
+
+static const struct spi_nor_controller_ops wmt_sflash_controller_ops = {
+	.prepare	= wmt_sflash_prep,
+	.unprepare	= wmt_sflash_unprep,
+	.read_reg	= wmt_sflash_read_reg,
+	.write_reg	= wmt_sflash_write_reg,
+	.read		= wmt_sflash_read,
+	.write		= wmt_sflash_write,
+	.erase		= wmt_sflash_erase,
+};
+
+static int wmt_sflash_register(struct device_node *np,
+				   struct wmt_sflash_host *host)
+{
+	const struct spi_nor_hwcaps hwcaps = {
+		.mask = SNOR_HWCAPS_READ |
+			SNOR_HWCAPS_READ_FAST |
+			SNOR_HWCAPS_PP,
+	};
+	struct device *dev = host->dev;
+	struct wmt_sflash_priv *priv;
+	struct mtd_info *mtd;
+	struct spi_nor *nor;
+	int ret;
+	u32 reg;
+
+	nor = devm_kzalloc(dev, sizeof(*nor), GFP_KERNEL);
+	if (!nor)
+		return -ENOMEM;
+
+	nor->dev = dev;
+	spi_nor_set_flash_node(nor, np);
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	ret = of_property_read_u32(np, "reg", &priv->cs);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "There's no reg property for %pOF\n",
+				     np);
+
+	if (priv->cs >= SF_MAX_CHIP_NUM)
+		return dev_err_probe(dev, -ENXIO,
+				     "Chip select %d is out of bounds\n",
+				     priv->cs);
+
+	priv->host = host;
+	nor->priv = priv;
+	nor->controller_ops = &wmt_sflash_controller_ops;
+
+	ret = spi_nor_scan(nor, NULL, &hwcaps);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "Failed to scan SPI NOR chip\n");
+
+	mtd = &nor->mtd;
+	mtd->name = np->name;
+
+	priv->mmap_phys = host->mmap_res[priv->cs]->end - mtd->size + 1;
+	priv->mmap_phys &= -SZ_64K;
+
+	priv->mmap_base = devm_ioremap(dev, priv->mmap_phys, mtd->size);
+	if (IS_ERR(priv->mmap_base))
+		return dev_err_probe(dev, PTR_ERR(priv->mmap_base),
+			"Failed to map chip %d at address 0x%x size 0x%llx\n",
+			priv->cs, priv->mmap_phys, mtd->size);
+
+	reg = FIELD_PREP(SF_CHIP_SEL_ADDR, priv->mmap_phys >> 16) |
+	      FIELD_PREP(SF_CHIP_SEL_SIZE, order_base_2(mtd->size) - 15);
+	writel(reg, host->regbase + SF_CHIP_SEL_CFG(priv->cs));
+
+	reg = FIELD_PREP(SF_CS_DELAY, 3);
+	writel(reg, host->regbase + SF_SPI_INTF_CFG);
+
+	/* the controller only handles 64k aligned addresses */
+	mtd->erasesize = max(mtd->erasesize, SZ_64K);
+
+	ret = mtd_device_register(mtd, NULL, 0);
+	if (ret)
+		return dev_err_probe(dev, ret,
+				     "Failed to register MTD device\n");
+
+	host->nor[host->num_chips] = nor;
+	host->num_chips++;
+	return 0;
+}
+
+static void wmt_sflash_unregister_all(struct wmt_sflash_host *host)
+{
+	int i;
+
+	for (i = 0; i < host->num_chips; i++)
+		mtd_device_unregister(&host->nor[i]->mtd);
+}
+
+static int wmt_sflash_register_all(struct wmt_sflash_host *host)
+{
+	struct device *dev = host->dev;
+	struct device_node *np;
+	int ret;
+
+	for_each_available_child_of_node(dev->of_node, np) {
+		ret = wmt_sflash_register(np, host);
+		if (ret) {
+			of_node_put(np);
+			goto fail;
+		}
+
+		if (host->num_chips == SF_MAX_CHIP_NUM) {
+			dev_warn(dev, "Flash count exceeds the maximum chipselect number\n");
+			of_node_put(np);
+			break;
+		}
+	}
+	return 0;
+
+fail:
+	wmt_sflash_unregister_all(host);
+	return ret;
+}
+
+static int wmt_sflash_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct wmt_sflash_host *host;
+	char mmap_str[32];
+	int ret, i;
+
+	host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return dev_err_probe(dev, -ENOMEM,
+			"Failed to allocate controller private data\n");
+
+	platform_set_drvdata(pdev, host);
+	host->dev = dev;
+
+	host->regbase = devm_platform_ioremap_resource_byname(pdev, "io");
+	if (IS_ERR(host->regbase))
+		return dev_err_probe(dev, PTR_ERR(host->regbase),
+			"Failed to remap controller MMIO registers\n");
+
+	for (i = 0; i < SF_MAX_CHIP_NUM; i++) {
+		snprintf(mmap_str, sizeof(mmap_str), "chip%d-mmap", i);
+
+		host->mmap_res[i] = platform_get_resource_byname(pdev,
+						IORESOURCE_MEM, mmap_str);
+		if (!host->mmap_res[i])
+			return dev_err_probe(dev, -ENXIO,
+				"Memory map region not found for chip %d\n",
+				i);
+	}
+
+	host->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(host->clk))
+		return dev_err_probe(dev, PTR_ERR(host->clk),
+			"Failed to get clock\n");
+
+	ret = clk_prepare_enable(host->clk);
+	if (ret)
+		return dev_err_probe(dev, ret, "Failed to enable clock\n");
+
+	ret = wmt_sflash_register_all(host);
+
+	clk_disable_unprepare(host->clk);
+	return ret;
+}
+
+static void wmt_sflash_remove(struct platform_device *pdev)
+{
+	struct wmt_sflash_host *host = platform_get_drvdata(pdev);
+
+	wmt_sflash_unregister_all(host);
+}
+
+static const struct of_device_id wmt_sflash_dt_ids[] = {
+	{ .compatible = "via,vt8500-sflash"},
+	{ .compatible = "wm,wm8505-sflash"},
+	{ .compatible = "wm,wm8650-sflash"},
+	{ .compatible = "wm,wm8750-sflash"},
+	{ .compatible = "wm,wm8850-sflash"},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, wmt_sflash_dt_ids);
+
+static struct platform_driver wmt_sflash_driver = {
+	.driver = {
+		.name	= "wmt-sflash",
+		.of_match_table = wmt_sflash_dt_ids,
+	},
+	.probe	= wmt_sflash_probe,
+	.remove = wmt_sflash_remove,
+};
+module_platform_driver(wmt_sflash_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("VIA/WonderMedia SPI NOR flash controller driver");

-- 
2.49.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 3/3] ARM: dts: vt8500: Add serial flash controller and its clock
  2025-05-10 19:42 [PATCH 0/3] mtd: spi-nor: Add VIA/WonderMedia serial flash controller driver Alexey Charkov
  2025-05-10 19:42 ` [PATCH 1/3] dt-bindings: spi: Add VIA/WonderMedia serial flash controller Alexey Charkov
  2025-05-10 19:42 ` [PATCH 2/3] mtd: spi-nor: Add a driver for the " Alexey Charkov
@ 2025-05-10 19:42 ` Alexey Charkov
  2 siblings, 0 replies; 16+ messages in thread
From: Alexey Charkov @ 2025-05-10 19:42 UTC (permalink / raw)
  To: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Tudor Ambarus, Pratyush Yadav, Michael Walle, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Krzysztof Kozlowski
  Cc: linux-spi, devicetree, linux-kernel, linux-mtd, linux-arm-kernel,
	Alexey Charkov

The serial flash controller resides at the same MMIO address in all known
VIA/WonderMedia SoCs, and its clock uses the same enable bit and divisor
reg on all SoCs, feeding off PLL B.

Add respective DT nodes using SoC specific compatibles for the controller
to make it future proof in case any differences in behavior are discovered
later on.

All known boards boot from SPI NOR flash, so their flash chips are at CS0
and mapped by the boot ROM at the end of their CPU address space. Add
respective DT nodes in board-specific dts files too.

Signed-off-by: Alexey Charkov <alchark@gmail.com>
---
 arch/arm/boot/dts/vt8500/vt8500-bv07.dts     | 37 ++++++++++++++++++++++++++++
 arch/arm/boot/dts/vt8500/vt8500.dtsi         | 34 +++++++++++++++++++++++++
 arch/arm/boot/dts/vt8500/wm8505-ref.dts      | 37 ++++++++++++++++++++++++++++
 arch/arm/boot/dts/vt8500/wm8505.dtsi         | 21 ++++++++++++++++
 arch/arm/boot/dts/vt8500/wm8650-mid.dts      | 37 ++++++++++++++++++++++++++++
 arch/arm/boot/dts/vt8500/wm8650.dtsi         | 21 ++++++++++++++++
 arch/arm/boot/dts/vt8500/wm8750-apc8750.dts  | 37 ++++++++++++++++++++++++++++
 arch/arm/boot/dts/vt8500/wm8750.dtsi         | 21 ++++++++++++++++
 arch/arm/boot/dts/vt8500/wm8850-w70v2.dts    | 37 ++++++++++++++++++++++++++++
 arch/arm/boot/dts/vt8500/wm8850.dtsi         | 21 ++++++++++++++++
 arch/arm/boot/dts/vt8500/wm8950-apc-rock.dts | 37 ++++++++++++++++++++++++++++
 11 files changed, 340 insertions(+)

diff --git a/arch/arm/boot/dts/vt8500/vt8500-bv07.dts b/arch/arm/boot/dts/vt8500/vt8500-bv07.dts
index 38a2da5e2c5d64477f04e1da9d98cb97be0d95e4..c3c5ba3ac014cc49bee8c2b9e6c7b25225d4d5fe 100644
--- a/arch/arm/boot/dts/vt8500/vt8500-bv07.dts
+++ b/arch/arm/boot/dts/vt8500/vt8500-bv07.dts
@@ -30,6 +30,43 @@ timing0: timing-800x480 {
 	};
 };
 
+&sflash {
+	status = "okay";
+
+	flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "U-boot";
+				reg = <0 0x50000>;
+				read-only;
+			};
+
+			partition@1 {
+				label = "U-boot environment 1";
+				reg = <0x50000 0x10000>;
+			};
+
+			partition@2 {
+				label = "U-boot environment 2";
+				reg = <0x60000 0x10000>;
+			};
+
+			partition@3 {
+				label = "W-load";
+				reg = <0x70000 0x10000>;
+				read-only;
+			};
+		};
+	};
+};
+
 &uart0 {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/vt8500/vt8500.dtsi b/arch/arm/boot/dts/vt8500/vt8500.dtsi
index 2ba021585d4889f29777a12473964c29f999f3a0..7ea115576c69b517cb2a08206638062f22c976a0 100644
--- a/arch/arm/boot/dts/vt8500/vt8500.dtsi
+++ b/arch/arm/boot/dts/vt8500/vt8500.dtsi
@@ -74,6 +74,19 @@ ref24: ref24M {
 					clock-frequency = <24000000>;
 				};
 
+				ref25: clock-25000000 {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+					clock-frequency = <25000000>;
+				};
+
+				pllb: clock@204 {
+					#clock-cells = <0>;
+					compatible = "via,vt8500-pll-clock";
+					clocks = <&ref25>;
+					reg = <0x204>;
+				};
+
 				clkuart0: uart0 {
 					#clock-cells = <0>;
 					compatible = "via,vt8500-device-clock";
@@ -105,6 +118,15 @@ clkuart3: uart3 {
 					enable-reg = <0x250>;
 					enable-bit = <4>;
 				};
+
+				clksf: clock {
+					#clock-cells = <0>;
+					compatible = "via,vt8500-device-clock";
+					clocks = <&pllb>;
+					divisor-reg = <0x314>;
+					enable-reg = <0x254>;
+					enable-bit = <23>;
+				};
 			};
 		};
 
@@ -114,6 +136,18 @@ timer@d8130100 {
 			interrupts = <36>;
 		};
 
+		sflash: spi-nor-controller@d8002000 {
+			compatible = "via,vt8500-sflash";
+			reg = <0xd8002000 0x400>,
+			      <0xff800000 0x800000>,
+			      <0xef800000 0x800000>;
+			reg-names = "io", "chip0-mmap", "chip1-mmap";
+			clocks = <&clksf>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		usb@d8007900 {
 			compatible = "via,vt8500-ehci";
 			reg = <0xd8007900 0x200>;
diff --git a/arch/arm/boot/dts/vt8500/wm8505-ref.dts b/arch/arm/boot/dts/vt8500/wm8505-ref.dts
index 8ce9e2ef0a81097e7143a5392ee5b42bf8028ec1..b037f9d919fb51a527f35276e2b8601f3f3d8505 100644
--- a/arch/arm/boot/dts/vt8500/wm8505-ref.dts
+++ b/arch/arm/boot/dts/vt8500/wm8505-ref.dts
@@ -30,6 +30,43 @@ timing0: timing-800x480 {
 	};
 };
 
+&sflash {
+	status = "okay";
+
+	flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "U-boot";
+				reg = <0 0x50000>;
+				read-only;
+			};
+
+			partition@1 {
+				label = "U-boot environment 1";
+				reg = <0x50000 0x10000>;
+			};
+
+			partition@2 {
+				label = "U-boot environment 2";
+				reg = <0x60000 0x10000>;
+			};
+
+			partition@3 {
+				label = "W-load";
+				reg = <0x70000 0x10000>;
+				read-only;
+			};
+		};
+	};
+};
+
 &uart0 {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/vt8500/wm8505.dtsi b/arch/arm/boot/dts/vt8500/wm8505.dtsi
index 99c064c916b2279797f71261ca9306e9dcd4bbd8..bf9ba4e99f86d1bf41c4e4bfe8b4f71ad162be4f 100644
--- a/arch/arm/boot/dts/vt8500/wm8505.dtsi
+++ b/arch/arm/boot/dts/vt8500/wm8505.dtsi
@@ -203,6 +203,15 @@ clksdhc: sdhc {
 					enable-reg = <0x254>;
 					enable-bit = <18>;
 				};
+
+				clksf: clock {
+					#clock-cells = <0>;
+					compatible = "via,vt8500-device-clock";
+					clocks = <&pllb>;
+					divisor-reg = <0x314>;
+					enable-reg = <0x254>;
+					enable-bit = <23>;
+				};
 			};
 		};
 
@@ -212,6 +221,18 @@ timer@d8130100 {
 			interrupts = <36>;
 		};
 
+		sflash: spi-nor-controller@d8002000 {
+			compatible = "wm,wm8505-sflash";
+			reg = <0xd8002000 0x400>,
+			      <0xff800000 0x800000>,
+			      <0xef800000 0x800000>;
+			reg-names = "io", "chip0-mmap", "chip1-mmap";
+			clocks = <&clksf>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		usb@d8007100 {
 			compatible = "via,vt8500-ehci";
 			reg = <0xd8007100 0x200>;
diff --git a/arch/arm/boot/dts/vt8500/wm8650-mid.dts b/arch/arm/boot/dts/vt8500/wm8650-mid.dts
index 7977b6c1e8ebf215df210dee703e470b9159d329..d3c8b7b99706603bab5aa8dad1165edb3763c2f6 100644
--- a/arch/arm/boot/dts/vt8500/wm8650-mid.dts
+++ b/arch/arm/boot/dts/vt8500/wm8650-mid.dts
@@ -31,6 +31,43 @@ timing0: timing-800x480 {
 	};
 };
 
+&sflash {
+	status = "okay";
+
+	flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "U-boot";
+				reg = <0 0x50000>;
+				read-only;
+			};
+
+			partition@1 {
+				label = "U-boot environment 1";
+				reg = <0x50000 0x10000>;
+			};
+
+			partition@2 {
+				label = "U-boot environment 2";
+				reg = <0x60000 0x10000>;
+			};
+
+			partition@3 {
+				label = "W-load";
+				reg = <0x70000 0x10000>;
+				read-only;
+			};
+		};
+	};
+};
+
 &uart0 {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/vt8500/wm8650.dtsi b/arch/arm/boot/dts/vt8500/wm8650.dtsi
index 0d6c7bd87f7dcce0eef056d04c38ab1de5d52639..972b61d2437b1da9ce765b65f844872e8df4da1d 100644
--- a/arch/arm/boot/dts/vt8500/wm8650.dtsi
+++ b/arch/arm/boot/dts/vt8500/wm8650.dtsi
@@ -175,6 +175,15 @@ clksdhc: sdhc {
 					enable-reg = <0x254>;
 					enable-bit = <18>;
 				};
+
+				clksf: clock {
+					#clock-cells = <0>;
+					compatible = "via,vt8500-device-clock";
+					clocks = <&pllb>;
+					divisor-reg = <0x314>;
+					enable-reg = <0x254>;
+					enable-bit = <23>;
+				};
 			};
 		};
 
@@ -184,6 +193,18 @@ timer@d8130100 {
 			interrupts = <36>;
 		};
 
+		sflash: spi-nor-controller@d8002000 {
+			compatible = "wm,wm8650-sflash";
+			reg = <0xd8002000 0x400>,
+			      <0xff800000 0x800000>,
+			      <0xef800000 0x800000>;
+			reg-names = "io", "chip0-mmap", "chip1-mmap";
+			clocks = <&clksf>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		usb@d8007900 {
 			compatible = "via,vt8500-ehci";
 			reg = <0xd8007900 0x200>;
diff --git a/arch/arm/boot/dts/vt8500/wm8750-apc8750.dts b/arch/arm/boot/dts/vt8500/wm8750-apc8750.dts
index 136e812bc1e498d48c7fc61154bc66a48888b117..4465946cfe44e82db1cad14c1f81237e1ccc0e67 100644
--- a/arch/arm/boot/dts/vt8500/wm8750-apc8750.dts
+++ b/arch/arm/boot/dts/vt8500/wm8750-apc8750.dts
@@ -24,6 +24,43 @@ i2c: i2c {
 	};
 };
 
+&sflash {
+	status = "okay";
+
+	flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "U-boot";
+				reg = <0 0x50000>;
+				read-only;
+			};
+
+			partition@1 {
+				label = "U-boot environment 1";
+				reg = <0x50000 0x10000>;
+			};
+
+			partition@2 {
+				label = "U-boot environment 2";
+				reg = <0x60000 0x10000>;
+			};
+
+			partition@3 {
+				label = "W-load";
+				reg = <0x70000 0x10000>;
+				read-only;
+			};
+		};
+	};
+};
+
 &uart0 {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/vt8500/wm8750.dtsi b/arch/arm/boot/dts/vt8500/wm8750.dtsi
index 0158c0ba5dd110957eac38775d3bf3ebd2ab4154..d6b4e4463fae1e8a0a3cf0feecce7125b4a67f5c 100644
--- a/arch/arm/boot/dts/vt8500/wm8750.dtsi
+++ b/arch/arm/boot/dts/vt8500/wm8750.dtsi
@@ -240,6 +240,15 @@ clki2c1: i2c1clk {
 					enable-reg = <0x250>;
 					enable-bit = <9>;
 				};
+
+				clksf: clock {
+					#clock-cells = <0>;
+					compatible = "via,vt8500-device-clock";
+					clocks = <&pllb>;
+					divisor-reg = <0x314>;
+					enable-reg = <0x254>;
+					enable-bit = <23>;
+				};
 			};
 		};
 
@@ -256,6 +265,18 @@ timer@d8130100 {
 			interrupts = <36>;
 		};
 
+		sflash: spi-nor-controller@d8002000 {
+			compatible = "wm,wm8750-sflash";
+			reg = <0xd8002000 0x400>,
+			      <0xff800000 0x800000>,
+			      <0xef800000 0x800000>;
+			reg-names = "io", "chip0-mmap", "chip1-mmap";
+			clocks = <&clksf>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		usb@d8007900 {
 			compatible = "via,vt8500-ehci";
 			reg = <0xd8007900 0x200>;
diff --git a/arch/arm/boot/dts/vt8500/wm8850-w70v2.dts b/arch/arm/boot/dts/vt8500/wm8850-w70v2.dts
index 5d409323b10cb94a5694722de1e31cff5be390ce..d2638a204579d3dff477bb7f458438037e08019b 100644
--- a/arch/arm/boot/dts/vt8500/wm8850-w70v2.dts
+++ b/arch/arm/boot/dts/vt8500/wm8850-w70v2.dts
@@ -42,6 +42,43 @@ timing0: timing-800x480 {
 	};
 };
 
+&sflash {
+	status = "okay";
+
+	flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "U-boot";
+				reg = <0 0x50000>;
+				read-only;
+			};
+
+			partition@1 {
+				label = "U-boot environment 1";
+				reg = <0x50000 0x10000>;
+			};
+
+			partition@2 {
+				label = "U-boot environment 2";
+				reg = <0x60000 0x10000>;
+			};
+
+			partition@3 {
+				label = "W-load";
+				reg = <0x70000 0x10000>;
+				read-only;
+			};
+		};
+	};
+};
+
 &uart0 {
 	status = "okay";
 };
diff --git a/arch/arm/boot/dts/vt8500/wm8850.dtsi b/arch/arm/boot/dts/vt8500/wm8850.dtsi
index c4bfb4d30aad0358b39cbf30edf0c63e32167bbd..6837198de2508536eef52537a7f451679d36c38b 100644
--- a/arch/arm/boot/dts/vt8500/wm8850.dtsi
+++ b/arch/arm/boot/dts/vt8500/wm8850.dtsi
@@ -217,6 +217,15 @@ clksdhc: sdhc {
 					enable-reg = <0x250>;
 					enable-bit = <0>;
 				};
+
+				clksf: clock {
+					#clock-cells = <0>;
+					compatible = "via,vt8500-device-clock";
+					clocks = <&pllb>;
+					divisor-reg = <0x314>;
+					enable-reg = <0x254>;
+					enable-bit = <23>;
+				};
 			};
 		};
 
@@ -243,6 +252,18 @@ timer@d8130100 {
 			interrupts = <36>;
 		};
 
+		sflash: spi-nor-controller@d8002000 {
+			compatible = "wm,wm8850-sflash";
+			reg = <0xd8002000 0x400>,
+			      <0xff800000 0x800000>,
+			      <0xef800000 0x800000>;
+			reg-names = "io", "chip0-mmap", "chip1-mmap";
+			clocks = <&clksf>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			status = "disabled";
+		};
+
 		usb@d8007900 {
 			compatible = "via,vt8500-ehci";
 			reg = <0xd8007900 0x200>;
diff --git a/arch/arm/boot/dts/vt8500/wm8950-apc-rock.dts b/arch/arm/boot/dts/vt8500/wm8950-apc-rock.dts
index 58b3c8deb4f20ae072bf1381f1dfa5e5adeb414a..647fdcccdbbd680276af1fa30363e09bbeb5ad16 100644
--- a/arch/arm/boot/dts/vt8500/wm8950-apc-rock.dts
+++ b/arch/arm/boot/dts/vt8500/wm8950-apc-rock.dts
@@ -16,6 +16,43 @@ memory@0 {
 	};
 };
 
+&sflash {
+	status = "okay";
+
+	flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+
+		partitions {
+			compatible = "fixed-partitions";
+			#address-cells = <1>;
+			#size-cells = <1>;
+
+			partition@0 {
+				label = "U-boot";
+				reg = <0 0x50000>;
+				read-only;
+			};
+
+			partition@1 {
+				label = "U-boot environment 1";
+				reg = <0x50000 0x10000>;
+			};
+
+			partition@2 {
+				label = "U-boot environment 2";
+				reg = <0x60000 0x10000>;
+			};
+
+			partition@3 {
+				label = "W-load";
+				reg = <0x70000 0x10000>;
+				read-only;
+			};
+		};
+	};
+};
+
 &uart0 {
 	status = "okay";
 };

-- 
2.49.0



^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/3] mtd: spi-nor: Add a driver for the VIA/WonderMedia serial flash controller
  2025-05-10 19:42 ` [PATCH 2/3] mtd: spi-nor: Add a driver for the " Alexey Charkov
@ 2025-05-11 11:13   ` kernel test robot
  2025-05-11 12:16   ` kernel test robot
  2025-05-12  9:20   ` Pratyush Yadav
  2 siblings, 0 replies; 16+ messages in thread
From: kernel test robot @ 2025-05-11 11:13 UTC (permalink / raw)
  To: Alexey Charkov, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Tudor Ambarus, Pratyush Yadav, Michael Walle,
	Miquel Raynal, Richard Weinberger, Vignesh Raghavendra
  Cc: oe-kbuild-all, linux-spi, devicetree, linux-kernel, linux-mtd,
	linux-arm-kernel, Alexey Charkov

Hi Alexey,

kernel test robot noticed the following build errors:

[auto build test ERROR on ed61cb3d78d585209ec775933078e268544fe9a4]

url:    https://github.com/intel-lab-lkp/linux/commits/Alexey-Charkov/dt-bindings-spi-Add-VIA-WonderMedia-serial-flash-controller/20250511-034459
base:   ed61cb3d78d585209ec775933078e268544fe9a4
patch link:    https://lore.kernel.org/r/20250510-wmt-sflash-v1-2-02a1ac6adf12%40gmail.com
patch subject: [PATCH 2/3] mtd: spi-nor: Add a driver for the VIA/WonderMedia serial flash controller
config: sh-allmodconfig (https://download.01.org/0day-ci/archive/20250511/202505111905.tlinDurh-lkp@intel.com/config)
compiler: sh4-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250511/202505111905.tlinDurh-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202505111905.tlinDurh-lkp@intel.com/

All errors (new ones prefixed by >>):

   drivers/mtd/spi-nor/controllers/wmt-sflash.c: In function 'wmt_sflash_pcmd_mode':
>> drivers/mtd/spi-nor/controllers/wmt-sflash.c:132:16: error: implicit declaration of function 'FIELD_PREP' [-Wimplicit-function-declaration]
     132 |         reg |= FIELD_PREP(SF_PROG_CMD_MOD, enable);
         |                ^~~~~~~~~~


vim +/FIELD_PREP +132 drivers/mtd/spi-nor/controllers/wmt-sflash.c

   126	
   127	static void wmt_sflash_pcmd_mode(struct wmt_sflash_host *host, bool enable)
   128	{
   129		u32 reg = readl(host->regbase + SF_SPI_INTF_CFG);
   130	
   131		reg &= ~SF_PROG_CMD_MOD;
 > 132		reg |= FIELD_PREP(SF_PROG_CMD_MOD, enable);
   133		writel(reg, host->regbase + SF_SPI_INTF_CFG);
   134	}
   135	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/3] mtd: spi-nor: Add a driver for the VIA/WonderMedia serial flash controller
  2025-05-10 19:42 ` [PATCH 2/3] mtd: spi-nor: Add a driver for the " Alexey Charkov
  2025-05-11 11:13   ` kernel test robot
@ 2025-05-11 12:16   ` kernel test robot
  2025-05-12  9:20   ` Pratyush Yadav
  2 siblings, 0 replies; 16+ messages in thread
From: kernel test robot @ 2025-05-11 12:16 UTC (permalink / raw)
  To: Alexey Charkov, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Tudor Ambarus, Pratyush Yadav, Michael Walle,
	Miquel Raynal, Richard Weinberger, Vignesh Raghavendra
  Cc: oe-kbuild-all, linux-spi, devicetree, linux-kernel, linux-mtd,
	linux-arm-kernel, Alexey Charkov

Hi Alexey,

kernel test robot noticed the following build warnings:

[auto build test WARNING on ed61cb3d78d585209ec775933078e268544fe9a4]

url:    https://github.com/intel-lab-lkp/linux/commits/Alexey-Charkov/dt-bindings-spi-Add-VIA-WonderMedia-serial-flash-controller/20250511-034459
base:   ed61cb3d78d585209ec775933078e268544fe9a4
patch link:    https://lore.kernel.org/r/20250510-wmt-sflash-v1-2-02a1ac6adf12%40gmail.com
patch subject: [PATCH 2/3] mtd: spi-nor: Add a driver for the VIA/WonderMedia serial flash controller
config: s390-allyesconfig (https://download.01.org/0day-ci/archive/20250511/202505112028.FOL7oTti-lkp@intel.com/config)
compiler: s390-linux-gcc (GCC) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250511/202505112028.FOL7oTti-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202505112028.FOL7oTti-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from include/linux/device.h:15,
                    from include/linux/mtd/mtd.h:13,
                    from drivers/mtd/spi-nor/controllers/wmt-sflash.c:14:
   drivers/mtd/spi-nor/controllers/wmt-sflash.c: In function 'wmt_sflash_read_reg':
>> drivers/mtd/spi-nor/controllers/wmt-sflash.c:154:17: warning: format '%d' expects argument of type 'int', but argument 3 has type 'size_t' {aka 'long unsigned int'} [-Wformat=]
     154 |                 "Cannot read %d bytes from registers\n", len);
         |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/dev_printk.h:110:30: note: in definition of macro 'dev_printk_index_wrap'
     110 |                 _p_func(dev, fmt, ##__VA_ARGS__);                       \
         |                              ^~~
   include/linux/dev_printk.h:154:56: note: in expansion of macro 'dev_fmt'
     154 |         dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                                        ^~~~~~~
   drivers/mtd/spi-nor/controllers/wmt-sflash.c:153:17: note: in expansion of macro 'dev_err'
     153 |                 dev_err(host->dev,
         |                 ^~~~~~~
   drivers/mtd/spi-nor/controllers/wmt-sflash.c:154:31: note: format string is defined here
     154 |                 "Cannot read %d bytes from registers\n", len);
         |                              ~^
         |                               |
         |                               int
         |                              %ld
   drivers/mtd/spi-nor/controllers/wmt-sflash.c: In function 'wmt_sflash_write_reg':
   drivers/mtd/spi-nor/controllers/wmt-sflash.c:187:17: warning: format '%d' expects argument of type 'int', but argument 3 has type 'size_t' {aka 'long unsigned int'} [-Wformat=]
     187 |                 "Cannot write %d bytes to registers\n", len);
         |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/dev_printk.h:110:30: note: in definition of macro 'dev_printk_index_wrap'
     110 |                 _p_func(dev, fmt, ##__VA_ARGS__);                       \
         |                              ^~~
   include/linux/dev_printk.h:154:56: note: in expansion of macro 'dev_fmt'
     154 |         dev_printk_index_wrap(_dev_err, KERN_ERR, dev, dev_fmt(fmt), ##__VA_ARGS__)
         |                                                        ^~~~~~~
   drivers/mtd/spi-nor/controllers/wmt-sflash.c:186:17: note: in expansion of macro 'dev_err'
     186 |                 dev_err(host->dev,
         |                 ^~~~~~~
   drivers/mtd/spi-nor/controllers/wmt-sflash.c:187:32: note: format string is defined here
     187 |                 "Cannot write %d bytes to registers\n", len);
         |                               ~^
         |                                |
         |                                int
         |                               %ld
   drivers/mtd/spi-nor/controllers/wmt-sflash.c: In function 'wmt_sflash_register':
   drivers/mtd/spi-nor/controllers/wmt-sflash.c:365:47: error: passing argument 3 of 'of_property_read_u32' from incompatible pointer type [-Wincompatible-pointer-types]
     365 |         ret = of_property_read_u32(np, "reg", &priv->cs);
         |                                               ^~~~~~~~~
         |                                               |
         |                                               size_t * {aka long unsigned int *}
   In file included from include/linux/mtd/mtd.h:14:
   include/linux/of.h:1419:45: note: expected 'u32 *' {aka 'unsigned int *'} but argument is of type 'size_t *' {aka 'long unsigned int *'}
    1419 |                                        u32 *out_value)
         |                                        ~~~~~^~~~~~~~~
   drivers/mtd/spi-nor/controllers/wmt-sflash.c:373:52: warning: format '%d' expects argument of type 'int', but argument 4 has type 'size_t' {aka 'long unsigned int'} [-Wformat=]
     373 |                                      "Chip select %d is out of bounds\n",
         |                                                   ~^
         |                                                    |
         |                                                    int
         |                                                   %ld
     374 |                                      priv->cs);
         |                                      ~~~~~~~~       
         |                                          |
         |                                          size_t {aka long unsigned int}
   drivers/mtd/spi-nor/controllers/wmt-sflash.c:394:46: warning: format '%d' expects argument of type 'int', but argument 4 has type 'size_t' {aka 'long unsigned int'} [-Wformat=]
     394 |                         "Failed to map chip %d at address 0x%x size 0x%llx\n",
         |                                             ~^
         |                                              |
         |                                              int
         |                                             %ld
     395 |                         priv->cs, priv->mmap_phys, mtd->size);
         |                         ~~~~~~~~              
         |                             |
         |                             size_t {aka long unsigned int}
>> drivers/mtd/spi-nor/controllers/wmt-sflash.c:394:62: warning: format '%x' expects argument of type 'unsigned int', but argument 5 has type 'resource_size_t' {aka 'long long unsigned int'} [-Wformat=]
     394 |                         "Failed to map chip %d at address 0x%x size 0x%llx\n",
         |                                                             ~^
         |                                                              |
         |                                                              unsigned int
         |                                                             %llx
     395 |                         priv->cs, priv->mmap_phys, mtd->size);
         |                                   ~~~~~~~~~~~~~~~             
         |                                       |
         |                                       resource_size_t {aka long long unsigned int}


vim +154 drivers/mtd/spi-nor/controllers/wmt-sflash.c

  > 14	#include <linux/mtd/mtd.h>
    15	#include <linux/mtd/spi-nor.h>
    16	#include <linux/of.h>
    17	#include <linux/platform_device.h>
    18	#include <linux/slab.h>
    19	
    20	#define SF_CHIP_SEL_0_CFG	0x000		/* chip select 0 config */
    21	#define SF_CHIP_SEL_1_CFG	0x008		/* chip select 0 config */
    22	#define SF_CHIP_SEL_CFG(x)	(8 * (x))
    23	#define SF_CHIP_SEL_ADDR	GENMASK(31, 16) /* 64kb aligned address */
    24	#define SF_CHIP_SEL_SIZE	GENMASK(11, 8)	/* log2(size/32kb) */
    25	
    26	#define SF_SPI_INTF_CFG		0x040	/* SPI interface config */
    27	#define SF_ADDR_WIDTH_32	BIT(0)	/* 0: 24 bit, 1: 32 bit addr */
    28	#define SF_USR_RD_CMD_MOD	BIT(4)	/* 0: normal, 1: user cmd read */
    29	#define SF_USR_WR_CMD_MOD	BIT(5)	/* 0: normal, 1: user cmd write */
    30	#define SF_PROG_CMD_MOD		BIT(6)	/* 0: normal, 1: prog cmd */
    31	#define SF_CS_DELAY		GENMASK(18, 16)	/* chip select delay */
    32	#define SF_RES_DELAY		GENMASK(27, 24) /* reset delay */
    33	#define SF_PDWN_DELAY		GENMASK(31, 28) /* power down delay */
    34	
    35	#define SF_SPI_RD_WR_CTR	0x050	/* read/write control */
    36	#define SF_RD_FAST		BIT(0)	/* 0: normal read, 1: fast read */
    37	#define SF_RD_ID		BIT(4)	/* 0: read status, 1: read ID */
    38	
    39	#define SF_SPI_WR_EN_CTR	0x060	/* write enable control */
    40	#define SF_CS0_WR_EN		BIT(0)
    41	#define SF_CS1_WR_EN		BIT(1)
    42	#define SF_CS_WR_EN(x)		BIT(x)
    43	
    44	#define SF_SPI_ER_CTR		0x070	/* erase control */
    45	#define SF_CHIP_ERASE		BIT(0)	/* full chip erase */
    46	#define SF_SEC_ERASE		BIT(15)	/* sector erase */
    47	
    48	#define SF_SPI_ER_START_ADDR	0x074	/* erase start address */
    49	#define SF_CHIP_ER_CS0		BIT(0)	/* erase chip 0 */
    50	#define SF_CHIP_ER_CS1		BIT(1)	/* erase chip 1 */
    51	#define SF_CHIP_ER_CS(x)	BIT(x)
    52	#define SF_ER_START_ADDR	GENMASK(31, 16)
    53	
    54	#define SF_SPI_ERROR_STATUS	0x080
    55	#define SF_MASLOCK_ERR		BIT(0)	/* master lock */
    56	#define SF_PCMD_ACC_ERR		BIT(1)	/* programmable cmd access */
    57	#define SF_PCMD_OP_ERR		BIT(2)	/* programmable cmd opcode */
    58	#define SF_PWR_DWN_ACC_ERR	BIT(3)	/* power down access */
    59	#define SF_MEM_REGION_ERR	BIT(4)	/* memory region */
    60	#define SF_WR_PROT_ERR		BIT(5)	/* write protection */
    61	#define SF_SPI_ERROR_CLEARALL	(SF_MASLOCK_ERR | \
    62					 SF_PCMD_ACC_ERR | \
    63					 SF_PCMD_OP_ERR | \
    64					 SF_PWR_DWN_ACC_ERR | \
    65					 SF_MEM_REGION_ERR | \
    66					 SF_WR_PROT_ERR)
    67	
    68	#define SF_SPI_MEM_0_SR_ACC	0x100	/* status read from chip 0 */
    69	#define SF_SPI_MEM_1_SR_ACC	0x110	/* status read from chip 1 */
    70	#define SF_SPI_MEM_SR_ACC(x)	(0x100 + 0x10 * (x))
    71	
    72	#define SF_SPI_PDWN_CTR_0	0x180	/* power down chip 0 */
    73	#define SF_SPI_PDWN_CTR_1	0x190	/* power down chip 1 */
    74	#define SF_SPI_PDWN_CTR_(x)	(0x180 + 0x10 * (x))
    75	#define SF_PWR_DOWN		BIT(0)
    76	
    77	#define SF_SPI_PROG_CMD_CTR	0x200	/* programmable cmd control */
    78	#define SF_PROG_CMD_EN		BIT(0)	/* enable programmable cmd */
    79	#define SF_PROG_CMD_CS		GENMASK(1, 1)	/* chip select for cmd */
    80	#define SF_RX_DATA_SIZE		GENMASK(22, 16)	/* receive data size */
    81	#define SF_TX_DATA_SIZE		GENMASK(30, 24)	/* transmit data size */
    82	
    83	#define SF_SPI_USER_CMD_VAL	0x210
    84	#define SF_USR_RD_CMD		GENMASK(7, 0)	/* user read command */
    85	#define SF_USR_WR_CMD		GENMASK(23, 16)	/* user write command */
    86	
    87	#define SF_SPI_PROG_CMD_WBF	0x300	/* 64 bytes pcmd write buffer */
    88	#define SF_SPI_PROG_CMD_RBF	0x380	/* 64 bytes pcmd read buffer */
    89	
    90	#define SF_WAIT_TIMEOUT		1000000
    91	
    92	struct wmt_sflash_priv {
    93		size_t			cs;
    94		struct wmt_sflash_host	*host;
    95		void __iomem		*mmap_base;
    96		resource_size_t		mmap_phys;
    97	};
    98	
    99	#define SF_MAX_CHIP_NUM		2
   100	struct wmt_sflash_host {
   101		struct device		*dev;
   102		struct clk		*clk;
   103	
   104		void __iomem		*regbase;
   105		struct resource		*mmap_res[SF_MAX_CHIP_NUM];
   106	
   107		struct spi_nor		*nor[SF_MAX_CHIP_NUM];
   108		size_t			num_chips;
   109	};
   110	
   111	static int wmt_sflash_prep(struct spi_nor *nor)
   112	{
   113		struct wmt_sflash_priv *priv = nor->priv;
   114		struct wmt_sflash_host *host = priv->host;
   115	
   116		return clk_prepare_enable(host->clk);
   117	}
   118	
   119	static void wmt_sflash_unprep(struct spi_nor *nor)
   120	{
   121		struct wmt_sflash_priv *priv = nor->priv;
   122		struct wmt_sflash_host *host = priv->host;
   123	
   124		clk_disable_unprepare(host->clk);
   125	}
   126	
   127	static void wmt_sflash_pcmd_mode(struct wmt_sflash_host *host, bool enable)
   128	{
   129		u32 reg = readl(host->regbase + SF_SPI_INTF_CFG);
   130	
   131		reg &= ~SF_PROG_CMD_MOD;
   132		reg |= FIELD_PREP(SF_PROG_CMD_MOD, enable);
   133		writel(reg, host->regbase + SF_SPI_INTF_CFG);
   134	}
   135	
   136	static inline int wmt_sflash_wait_pcmd(struct wmt_sflash_host *host)
   137	{
   138		u32 reg;
   139	
   140		return readl_poll_timeout(host->regbase + SF_SPI_PROG_CMD_CTR, reg,
   141			!(reg & SF_PROG_CMD_EN), 1, SF_WAIT_TIMEOUT);
   142	}
   143	
   144	static int wmt_sflash_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf,
   145				       size_t len)
   146	{
   147		struct wmt_sflash_priv *priv = nor->priv;
   148		struct wmt_sflash_host *host = priv->host;
   149		int ret;
   150		u32 reg;
   151	
   152		if (len > 64) {
   153			dev_err(host->dev,
 > 154			"Cannot read %d bytes from registers\n", len);
   155			return -EINVAL;
   156		}
   157	
   158		wmt_sflash_pcmd_mode(host, true);
   159		writeb(opcode, host->regbase + SF_SPI_PROG_CMD_WBF);
   160	
   161		reg = SF_PROG_CMD_EN |
   162		      FIELD_PREP(SF_PROG_CMD_CS, priv->cs) |
   163		      FIELD_PREP(SF_TX_DATA_SIZE, 1) |
   164		      FIELD_PREP(SF_RX_DATA_SIZE, len);
   165		writel(reg, host->regbase + SF_SPI_PROG_CMD_CTR);
   166	
   167		ret = wmt_sflash_wait_pcmd(host);
   168	
   169		if (len)
   170			memcpy_fromio(buf, host->regbase + SF_SPI_PROG_CMD_RBF, len);
   171	
   172		wmt_sflash_pcmd_mode(host, false);
   173	
   174		return ret;
   175	}
   176	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/3] mtd: spi-nor: Add a driver for the VIA/WonderMedia serial flash controller
  2025-05-10 19:42 ` [PATCH 2/3] mtd: spi-nor: Add a driver for the " Alexey Charkov
  2025-05-11 11:13   ` kernel test robot
  2025-05-11 12:16   ` kernel test robot
@ 2025-05-12  9:20   ` Pratyush Yadav
  2025-05-12 17:50     ` Alexey Charkov
  2 siblings, 1 reply; 16+ messages in thread
From: Pratyush Yadav @ 2025-05-12  9:20 UTC (permalink / raw)
  To: Alexey Charkov
  Cc: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Tudor Ambarus, Pratyush Yadav, Michael Walle, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Krzysztof Kozlowski,
	linux-spi, devicetree, linux-kernel, linux-mtd, linux-arm-kernel

Hi Alexey,

On Sat, May 10 2025, Alexey Charkov wrote:

> The controller is tailored to SPI NOR flash memory and abstracts away all
> SPI communications behind a small set of MMIO registers and a physical
> memory mapping of the actual chip contents.
>
> It doesn't expose chip probing functions beyond reading the ID though, so
> use lower level chip opcodes via the "programmable command mode" of the
> controller and the kernel's SPI NOR framework to avoid hard-coding chip
> parameters for each ID the way the vendor kernel does it.
>
> Currently tested on a WonderMedia WM8950 SoC with a Macronix MX25L4005A
> flash chip (APC Rock board), but should work on all VIA/WonderMedia SoCs
>
> Signed-off-by: Alexey Charkov <alchark@gmail.com>
> ---
>  MAINTAINERS                                  |   1 +
>  drivers/mtd/spi-nor/controllers/Kconfig      |  14 +
>  drivers/mtd/spi-nor/controllers/Makefile     |   1 +
>  drivers/mtd/spi-nor/controllers/wmt-sflash.c | 525 +++++++++++++++++++++++++++

Drivers in drivers/mtd/spi-nor/controllers/ are deprecated, and we want
to eventually get rid of the API. The expected way is for drivers to use
SPI MEM (drivers/spi/spi-mem.c). SPI MEM drivers are usually more
general and not tailored specifically to SPI NOR flashes, so it might be
a bit tricky to write drivers for specialized hardware with it. But I
think the drivers/spi/spi-intel.c driver is written for similar kind of
hardware so it should be possible.
>
[...]

-- 
Regards,
Pratyush Yadav


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/3] mtd: spi-nor: Add a driver for the VIA/WonderMedia serial flash controller
  2025-05-12  9:20   ` Pratyush Yadav
@ 2025-05-12 17:50     ` Alexey Charkov
  2025-07-24 13:51       ` Pratyush Yadav
  0 siblings, 1 reply; 16+ messages in thread
From: Alexey Charkov @ 2025-05-12 17:50 UTC (permalink / raw)
  To: Pratyush Yadav
  Cc: Mark Brown, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Tudor Ambarus, Michael Walle, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Krzysztof Kozlowski, linux-spi, devicetree,
	linux-kernel, linux-mtd, linux-arm-kernel

Hi Pratyush,

On Mon, May 12, 2025 at 1:20 PM Pratyush Yadav <pratyush@kernel.org> wrote:
>
> Hi Alexey,
>
> On Sat, May 10 2025, Alexey Charkov wrote:
>
> > The controller is tailored to SPI NOR flash memory and abstracts away all
> > SPI communications behind a small set of MMIO registers and a physical
> > memory mapping of the actual chip contents.
> >
> > It doesn't expose chip probing functions beyond reading the ID though, so
> > use lower level chip opcodes via the "programmable command mode" of the
> > controller and the kernel's SPI NOR framework to avoid hard-coding chip
> > parameters for each ID the way the vendor kernel does it.
> >
> > Currently tested on a WonderMedia WM8950 SoC with a Macronix MX25L4005A
> > flash chip (APC Rock board), but should work on all VIA/WonderMedia SoCs
> >
> > Signed-off-by: Alexey Charkov <alchark@gmail.com>
> > ---
> >  MAINTAINERS                                  |   1 +
> >  drivers/mtd/spi-nor/controllers/Kconfig      |  14 +
> >  drivers/mtd/spi-nor/controllers/Makefile     |   1 +
> >  drivers/mtd/spi-nor/controllers/wmt-sflash.c | 525 +++++++++++++++++++++++++++
>
> Drivers in drivers/mtd/spi-nor/controllers/ are deprecated, and we want
> to eventually get rid of the API. The expected way is for drivers to use
> SPI MEM (drivers/spi/spi-mem.c). SPI MEM drivers are usually more
> general and not tailored specifically to SPI NOR flashes, so it might be
> a bit tricky to write drivers for specialized hardware with it. But I
> think the drivers/spi/spi-intel.c driver is written for similar kind of
> hardware so it should be possible.

Oops. I've had a look at spi-mem, and it seems like it's not a
particularly fitting abstraction for this controller.

From what I understood, spi-mem primarily expects to be talking SPI
opcodes to the controller, and for the controller/driver to bring
their own chip probing routines. This controller on the other hand
abstracts the opcodes away, and wants someone to tell it what its
flash chip can do (the controller itself can only get a chip ID in
"normal" mode, and it needs to somehow know the chip size and
standard/fast read capability of the chip). So pretty much the
opposite, huh.

In the end, I only need something like spi_nor_detect() and can do the
rest directly on top of the MTD framework without touching any SPI
opcodes after the detection is done. Is there any other non-deprecated
framework that can provide something like this? Maybe physmap? It
looks even older than SPI NOR though :)

Best regards,
Alexey


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/3] dt-bindings: spi: Add VIA/WonderMedia serial flash controller
  2025-05-10 19:42 ` [PATCH 1/3] dt-bindings: spi: Add VIA/WonderMedia serial flash controller Alexey Charkov
@ 2025-05-14 20:41   ` Rob Herring
  2025-05-15 19:50     ` Alexey Charkov
  0 siblings, 1 reply; 16+ messages in thread
From: Rob Herring @ 2025-05-14 20:41 UTC (permalink / raw)
  To: Alexey Charkov
  Cc: Mark Brown, Krzysztof Kozlowski, Conor Dooley, Tudor Ambarus,
	Pratyush Yadav, Michael Walle, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Krzysztof Kozlowski, linux-spi, devicetree,
	linux-kernel, linux-mtd, linux-arm-kernel

On Sat, May 10, 2025 at 11:42:21PM +0400, Alexey Charkov wrote:
> Add a binding for the serial flash controller found on VIA/WonderMedia
> SoCs, which provides semi-transparent access to SPI NOR chips by
> mapping their contents to the physical CPU address space.
> 
> Signed-off-by: Alexey Charkov <alchark@gmail.com>
> ---
>  .../devicetree/bindings/spi/via,vt8500-sflash.yaml | 122 +++++++++++++++++++++
>  MAINTAINERS                                        |   1 +
>  2 files changed, 123 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/spi/via,vt8500-sflash.yaml b/Documentation/devicetree/bindings/spi/via,vt8500-sflash.yaml
> new file mode 100644
> index 0000000000000000000000000000000000000000..d2ea0dacdd56118c0cb5a1cb510ceb7591e1e5ca
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/spi/via,vt8500-sflash.yaml
> @@ -0,0 +1,122 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/spi/via,vt8500-sflash.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: VIA/WonderMedia serial flash controller
> +
> +description:
> +  This controller is used on VIA/WonderMedia SoCs such as VIA VT8500,
> +  WonderMedia WM8850 and similar. It provides a semi-transparent interface
> +  for reading and writing SPI NOR chip contents via a physical memory map,
> +  abstracting away all SPI communication, while also providing a direct
> +  mechanism for issuing "programmable commands" to the underlying SPI chip
> +
> +maintainers:
> +  - Alexey Charkov <alchark@gmail.com>
> +
> +properties:
> +  compatible:
> +    enum:
> +      - via,vt8500-sflash
> +      - wm,wm8505-sflash
> +      - wm,wm8650-sflash
> +      - wm,wm8750-sflash
> +      - wm,wm8850-sflash
> +
> +  reg:
> +    items:
> +      - description: MMIO registers region of the controller
> +      - description:
> +          Physical memory region within which the controller will map the
> +          flash contents of chip 0 for reading and writing. If the flash
> +          size is smaller than this region, it will be mapped at its end.
> +          Note that if this chip is used as the boot device (as is most
> +          often the case), the boot ROM maps it at the very end of the
> +          CPU address space (i.e. ending at 0xffffffff)

Period needed on the end.

> +      - description:
> +          Physical memory region within which the controller will map the
> +          flash contents of chip 1 for reading and writing. If the flash
> +          size is smaller than this region, it will be mapped at its end

Period needed on the end.

> +
> +  reg-names:
> +    items:
> +      - const: io
> +      - const: chip0-mmap
> +      - const: chip1-mmap
> +
> +  clocks:
> +    maxItems: 1
> +
> +  "#address-cells":
> +    const: 1
> +
> +  "#size-cells":
> +    const: 0

This follows the SPI binding, right? Drop these 2 and add a $ref to 
spi-controller.yaml.

> +
> +patternProperties:
> +  "^flash@[0-1]$":
> +    type: object
> +    additionalProperties: true
> +
> +    properties:
> +      reg:
> +        minimum: 0
> +        maximum: 1
> +
> +required:
> +  - compatible
> +  - reg
> +  - reg-names
> +  - clocks
> +
> +unevaluatedProperties: false
> +
> +examples:
> +  - |
> +    sflash: spi-nor-controller@d8002000 {

spi@...

> +        compatible = "wm,wm8850-sflash";
> +        reg = <0xd8002000 0x400>,
> +              <0xff800000 0x800000>,
> +              <0xef800000 0x800000>;
> +        reg-names = "io", "chip0-mmap", "chip1-mmap";
> +        clocks = <&clksf>;
> +        #address-cells = <1>;
> +        #size-cells = <0>;
> +
> +        flash@0 {
> +            compatible = "jedec,spi-nor";
> +            reg = <0>;
> +
> +            partitions {
> +                compatible = "fixed-partitions";
> +                #address-cells = <1>;
> +                #size-cells = <1>;
> +
> +                partition@0 {
> +                    label = "U-boot";

The somewhat standard value here is 'u-boot'.

> +                    reg = <0 0x50000>;
> +                    read-only;
> +                };
> +
> +                partition@1 {
> +                    label = "U-boot environment 1";

u-boot-env

> +                    reg = <0x50000 0x10000>;
> +                };
> +
> +                partition@2 {
> +                    label = "U-boot environment 2";

alt-u-boot-env or u-boot-env-backup?

> +                    reg = <0x60000 0x10000>;
> +                };
> +
> +                partition@3 {
> +                    label = "W-load";
> +                    reg = <0x70000 0x10000>;
> +                    read-only;
> +                };
> +            };
> +        };
> +    };
> +
> +...
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 6dbdf02d6b0c9357ad1da520a0f6c16b7f38f879..f09c457bbfc5ef71a3f8379c111bac52b767cbbc 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -3475,6 +3475,7 @@ F:	Documentation/devicetree/bindings/hwinfo/via,vt8500-scc-id.yaml
>  F:	Documentation/devicetree/bindings/i2c/wm,wm8505-i2c.yaml
>  F:	Documentation/devicetree/bindings/interrupt-controller/via,vt8500-intc.yaml
>  F:	Documentation/devicetree/bindings/pwm/via,vt8500-pwm.yaml
> +F:	Documentation/devicetree/bindings/spi/via,vt8500-sflash.yaml
>  F:	arch/arm/boot/dts/vt8500/
>  F:	arch/arm/mach-vt8500/
>  F:	drivers/clocksource/timer-vt8500.c
> 
> -- 
> 2.49.0
> 


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/3] dt-bindings: spi: Add VIA/WonderMedia serial flash controller
  2025-05-14 20:41   ` Rob Herring
@ 2025-05-15 19:50     ` Alexey Charkov
  2025-06-06  8:29       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 16+ messages in thread
From: Alexey Charkov @ 2025-05-15 19:50 UTC (permalink / raw)
  To: Rob Herring
  Cc: Mark Brown, Krzysztof Kozlowski, Conor Dooley, Tudor Ambarus,
	Pratyush Yadav, Michael Walle, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Krzysztof Kozlowski, linux-spi, devicetree,
	linux-kernel, linux-mtd, linux-arm-kernel

On Wed, May 14, 2025 at 11:42 PM Rob Herring <robh@kernel.org> wrote:
>
> On Sat, May 10, 2025 at 11:42:21PM +0400, Alexey Charkov wrote:
> > Add a binding for the serial flash controller found on VIA/WonderMedia
> > SoCs, which provides semi-transparent access to SPI NOR chips by
> > mapping their contents to the physical CPU address space.
> >
> > Signed-off-by: Alexey Charkov <alchark@gmail.com>
> > ---
> >  .../devicetree/bindings/spi/via,vt8500-sflash.yaml | 122 +++++++++++++++++++++
> >  MAINTAINERS                                        |   1 +
> >  2 files changed, 123 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/spi/via,vt8500-sflash.yaml b/Documentation/devicetree/bindings/spi/via,vt8500-sflash.yaml
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..d2ea0dacdd56118c0cb5a1cb510ceb7591e1e5ca
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/spi/via,vt8500-sflash.yaml
> > @@ -0,0 +1,122 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/spi/via,vt8500-sflash.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: VIA/WonderMedia serial flash controller
> > +
> > +description:
> > +  This controller is used on VIA/WonderMedia SoCs such as VIA VT8500,
> > +  WonderMedia WM8850 and similar. It provides a semi-transparent interface
> > +  for reading and writing SPI NOR chip contents via a physical memory map,
> > +  abstracting away all SPI communication, while also providing a direct
> > +  mechanism for issuing "programmable commands" to the underlying SPI chip
> > +
> > +maintainers:
> > +  - Alexey Charkov <alchark@gmail.com>
> > +
> > +properties:
> > +  compatible:
> > +    enum:
> > +      - via,vt8500-sflash
> > +      - wm,wm8505-sflash
> > +      - wm,wm8650-sflash
> > +      - wm,wm8750-sflash
> > +      - wm,wm8850-sflash
> > +
> > +  reg:
> > +    items:
> > +      - description: MMIO registers region of the controller
> > +      - description:
> > +          Physical memory region within which the controller will map the
> > +          flash contents of chip 0 for reading and writing. If the flash
> > +          size is smaller than this region, it will be mapped at its end.
> > +          Note that if this chip is used as the boot device (as is most
> > +          often the case), the boot ROM maps it at the very end of the
> > +          CPU address space (i.e. ending at 0xffffffff)
>
> Period needed on the end.

Noted, thank you! Will adjust in the next version.

> > +      - description:
> > +          Physical memory region within which the controller will map the
> > +          flash contents of chip 1 for reading and writing. If the flash
> > +          size is smaller than this region, it will be mapped at its end
>
> Period needed on the end.

Ditto.

> > +
> > +  reg-names:
> > +    items:
> > +      - const: io
> > +      - const: chip0-mmap
> > +      - const: chip1-mmap
> > +
> > +  clocks:
> > +    maxItems: 1
> > +
> > +  "#address-cells":
> > +    const: 1
> > +
> > +  "#size-cells":
> > +    const: 0
>
> This follows the SPI binding, right? Drop these 2 and add a $ref to
> spi-controller.yaml.

Need some advice here. While this controller speaks SPI protocol to
its connected flash chips, it's a special-purpose thing that doesn't
expose much SPI functionality to the outside world, nor can it drive
any SPI devices other than SPI NOR flash. Does that still qualify as
an SPI controller as far as the bindings are concerned?

Happy to reference the spi-controller.yaml binding if so.

> > +patternProperties:
> > +  "^flash@[0-1]$":
> > +    type: object
> > +    additionalProperties: true
> > +
> > +    properties:
> > +      reg:
> > +        minimum: 0
> > +        maximum: 1
> > +
> > +required:
> > +  - compatible
> > +  - reg
> > +  - reg-names
> > +  - clocks
> > +
> > +unevaluatedProperties: false
> > +
> > +examples:
> > +  - |
> > +    sflash: spi-nor-controller@d8002000 {
>
> spi@...

Related to the question above... Happy to call it spi@ if appropriate
in this case.

> > +        compatible = "wm,wm8850-sflash";
> > +        reg = <0xd8002000 0x400>,
> > +              <0xff800000 0x800000>,
> > +              <0xef800000 0x800000>;
> > +        reg-names = "io", "chip0-mmap", "chip1-mmap";
> > +        clocks = <&clksf>;
> > +        #address-cells = <1>;
> > +        #size-cells = <0>;
> > +
> > +        flash@0 {
> > +            compatible = "jedec,spi-nor";
> > +            reg = <0>;
> > +
> > +            partitions {
> > +                compatible = "fixed-partitions";
> > +                #address-cells = <1>;
> > +                #size-cells = <1>;
> > +
> > +                partition@0 {
> > +                    label = "U-boot";
>
> The somewhat standard value here is 'u-boot'.

Noted, thanks - will adjust in the next version.

> > +                    reg = <0 0x50000>;
> > +                    read-only;
> > +                };
> > +
> > +                partition@1 {
> > +                    label = "U-boot environment 1";
>
> u-boot-env

Ditto.

> > +                    reg = <0x50000 0x10000>;
> > +                };
> > +
> > +                partition@2 {
> > +                    label = "U-boot environment 2";
>
> alt-u-boot-env or u-boot-env-backup?

Ditto.

Thanks for your review and comments Rob!

Best regards,
Alexey


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/3] dt-bindings: spi: Add VIA/WonderMedia serial flash controller
  2025-05-15 19:50     ` Alexey Charkov
@ 2025-06-06  8:29       ` Krzysztof Kozlowski
  2025-06-06  9:06         ` Alexey Charkov
  0 siblings, 1 reply; 16+ messages in thread
From: Krzysztof Kozlowski @ 2025-06-06  8:29 UTC (permalink / raw)
  To: Alexey Charkov, Rob Herring
  Cc: Mark Brown, Krzysztof Kozlowski, Conor Dooley, Tudor Ambarus,
	Pratyush Yadav, Michael Walle, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, linux-spi, devicetree, linux-kernel,
	linux-mtd, linux-arm-kernel

On 15/05/2025 21:50, Alexey Charkov wrote:
>>> +
>>> +  "#address-cells":
>>> +    const: 1
>>> +
>>> +  "#size-cells":
>>> +    const: 0
>>
>> This follows the SPI binding, right? Drop these 2 and add a $ref to
>> spi-controller.yaml.
> 
> Need some advice here. While this controller speaks SPI protocol to
> its connected flash chips, it's a special-purpose thing that doesn't
> expose much SPI functionality to the outside world, nor can it drive
> any SPI devices other than SPI NOR flash. Does that still qualify as
> an SPI controller as far as the bindings are concerned?
> 
> Happy to reference the spi-controller.yaml binding if so.

SPI NOR flashes are still child devices of an SPI controller. You can
look at other examples - aren't they all using spi-controller? Why this
would be different? Unless you found some cases that are different, but
then which ones?



Best regards,
Krzysztof


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/3] dt-bindings: spi: Add VIA/WonderMedia serial flash controller
  2025-06-06  8:29       ` Krzysztof Kozlowski
@ 2025-06-06  9:06         ` Alexey Charkov
  2025-06-09  9:07           ` Miquel Raynal
  0 siblings, 1 reply; 16+ messages in thread
From: Alexey Charkov @ 2025-06-06  9:06 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Rob Herring, Mark Brown, Krzysztof Kozlowski, Conor Dooley,
	Tudor Ambarus, Pratyush Yadav, Michael Walle, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, linux-spi, devicetree,
	linux-kernel, linux-mtd, linux-arm-kernel

On Fri, Jun 6, 2025 at 12:29 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On 15/05/2025 21:50, Alexey Charkov wrote:
> >>> +
> >>> +  "#address-cells":
> >>> +    const: 1
> >>> +
> >>> +  "#size-cells":
> >>> +    const: 0
> >>
> >> This follows the SPI binding, right? Drop these 2 and add a $ref to
> >> spi-controller.yaml.
> >
> > Need some advice here. While this controller speaks SPI protocol to
> > its connected flash chips, it's a special-purpose thing that doesn't
> > expose much SPI functionality to the outside world, nor can it drive
> > any SPI devices other than SPI NOR flash. Does that still qualify as
> > an SPI controller as far as the bindings are concerned?
> >
> > Happy to reference the spi-controller.yaml binding if so.
>
> SPI NOR flashes are still child devices of an SPI controller. You can
> look at other examples - aren't they all using spi-controller? Why this
> would be different? Unless you found some cases that are different, but
> then which ones?

No strong opinions here, and no expectation of any special treatment
:) Just wanted to consult on what's most appropriate.

My (subjective and perhaps unfounded) expectation when seeing
something advertise itself as an SPI controller was that it would be a
general purpose SPI master, to which one can e.g. connect an SPI
driven LCD screen and get it to work with generic Linux SPI
infrastructure - which would not be possible with this single-purpose
NOR-only flash controller. Given that I don't know how flexible or
restrictive other examples are in terms of driving arbitrary SPI
devices, I thought it's better to just ask.

What I'm getting from this exchange here is that I'd better use the
spi-controller binding and respective node names regardless of the
fact that this controller cannot drive arbitrary SPI devices beyond
NOR flash (which, as I'm getting, is irrelevant after all).

Best regards,
Alexey


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/3] dt-bindings: spi: Add VIA/WonderMedia serial flash controller
  2025-06-06  9:06         ` Alexey Charkov
@ 2025-06-09  9:07           ` Miquel Raynal
  2025-06-09  9:15             ` Alexey Charkov
  0 siblings, 1 reply; 16+ messages in thread
From: Miquel Raynal @ 2025-06-09  9:07 UTC (permalink / raw)
  To: Alexey Charkov
  Cc: Krzysztof Kozlowski, Rob Herring, Mark Brown, Krzysztof Kozlowski,
	Conor Dooley, Tudor Ambarus, Pratyush Yadav, Michael Walle,
	Richard Weinberger, Vignesh Raghavendra, linux-spi, devicetree,
	linux-kernel, linux-mtd, linux-arm-kernel

Hi Alexey,

>> > Happy to reference the spi-controller.yaml binding if so.
>>
>> SPI NOR flashes are still child devices of an SPI controller. You can
>> look at other examples - aren't they all using spi-controller? Why this
>> would be different? Unless you found some cases that are different, but
>> then which ones?
>
> No strong opinions here, and no expectation of any special treatment
> :) Just wanted to consult on what's most appropriate.
>
> My (subjective and perhaps unfounded) expectation when seeing
> something advertise itself as an SPI controller was that it would be a
> general purpose SPI master, to which one can e.g. connect an SPI
> driven LCD screen and get it to work with generic Linux SPI
> infrastructure - which would not be possible with this single-purpose
> NOR-only flash controller. Given that I don't know how flexible or
> restrictive other examples are in terms of driving arbitrary SPI
> devices, I thought it's better to just ask.
>
> What I'm getting from this exchange here is that I'd better use the
> spi-controller binding and respective node names regardless of the
> fact that this controller cannot drive arbitrary SPI devices beyond
> NOR flash (which, as I'm getting, is irrelevant after all).

Just for information, there are several SPI controllers which are
optimized for flash handling (not only NOR, though) and for that we have
a spi-mem layer which allows to reference a set of SPI memory "only"
callbacks. On the description side though, these controllers are like
all other SPI controllers, so the same controller bindings may apply.

Thanks,
Miquèl


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 1/3] dt-bindings: spi: Add VIA/WonderMedia serial flash controller
  2025-06-09  9:07           ` Miquel Raynal
@ 2025-06-09  9:15             ` Alexey Charkov
  0 siblings, 0 replies; 16+ messages in thread
From: Alexey Charkov @ 2025-06-09  9:15 UTC (permalink / raw)
  To: Miquel Raynal
  Cc: Krzysztof Kozlowski, Rob Herring, Mark Brown, Krzysztof Kozlowski,
	Conor Dooley, Tudor Ambarus, Pratyush Yadav, Michael Walle,
	Richard Weinberger, Vignesh Raghavendra, linux-spi, devicetree,
	linux-kernel, linux-mtd, linux-arm-kernel

On Mon, Jun 9, 2025 at 1:07 PM Miquel Raynal <miquel.raynal@bootlin.com> wrote:
>
> Hi Alexey,
>
> >> > Happy to reference the spi-controller.yaml binding if so.
> >>
> >> SPI NOR flashes are still child devices of an SPI controller. You can
> >> look at other examples - aren't they all using spi-controller? Why this
> >> would be different? Unless you found some cases that are different, but
> >> then which ones?
> >
> > No strong opinions here, and no expectation of any special treatment
> > :) Just wanted to consult on what's most appropriate.
> >
> > My (subjective and perhaps unfounded) expectation when seeing
> > something advertise itself as an SPI controller was that it would be a
> > general purpose SPI master, to which one can e.g. connect an SPI
> > driven LCD screen and get it to work with generic Linux SPI
> > infrastructure - which would not be possible with this single-purpose
> > NOR-only flash controller. Given that I don't know how flexible or
> > restrictive other examples are in terms of driving arbitrary SPI
> > devices, I thought it's better to just ask.
> >
> > What I'm getting from this exchange here is that I'd better use the
> > spi-controller binding and respective node names regardless of the
> > fact that this controller cannot drive arbitrary SPI devices beyond
> > NOR flash (which, as I'm getting, is irrelevant after all).
>
> Just for information, there are several SPI controllers which are
> optimized for flash handling (not only NOR, though) and for that we have
> a spi-mem layer which allows to reference a set of SPI memory "only"
> callbacks. On the description side though, these controllers are like
> all other SPI controllers, so the same controller bindings may apply.

Noted, thank you Miquèl!

Best regards,
Alexey


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/3] mtd: spi-nor: Add a driver for the VIA/WonderMedia serial flash controller
  2025-05-12 17:50     ` Alexey Charkov
@ 2025-07-24 13:51       ` Pratyush Yadav
  2025-07-28  7:09         ` Mika Westerberg
  0 siblings, 1 reply; 16+ messages in thread
From: Pratyush Yadav @ 2025-07-24 13:51 UTC (permalink / raw)
  To: Alexey Charkov
  Cc: Pratyush Yadav, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Tudor Ambarus, Michael Walle, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Krzysztof Kozlowski,
	linux-spi, devicetree, linux-kernel, linux-mtd, linux-arm-kernel,
	Mika Westerberg

Hi Alexey,

This email got buried in my inbox somewhere...

On Mon, May 12 2025, Alexey Charkov wrote:

> Hi Pratyush,
>
> On Mon, May 12, 2025 at 1:20 PM Pratyush Yadav <pratyush@kernel.org> wrote:
>>
>> Hi Alexey,
>>
>> On Sat, May 10 2025, Alexey Charkov wrote:
>>
>> > The controller is tailored to SPI NOR flash memory and abstracts away all
>> > SPI communications behind a small set of MMIO registers and a physical
>> > memory mapping of the actual chip contents.
>> >
>> > It doesn't expose chip probing functions beyond reading the ID though, so
>> > use lower level chip opcodes via the "programmable command mode" of the
>> > controller and the kernel's SPI NOR framework to avoid hard-coding chip
>> > parameters for each ID the way the vendor kernel does it.
>> >
>> > Currently tested on a WonderMedia WM8950 SoC with a Macronix MX25L4005A
>> > flash chip (APC Rock board), but should work on all VIA/WonderMedia SoCs
>> >
>> > Signed-off-by: Alexey Charkov <alchark@gmail.com>
>> > ---
>> >  MAINTAINERS                                  |   1 +
>> >  drivers/mtd/spi-nor/controllers/Kconfig      |  14 +
>> >  drivers/mtd/spi-nor/controllers/Makefile     |   1 +
>> >  drivers/mtd/spi-nor/controllers/wmt-sflash.c | 525 +++++++++++++++++++++++++++
>>
>> Drivers in drivers/mtd/spi-nor/controllers/ are deprecated, and we want
>> to eventually get rid of the API. The expected way is for drivers to use
>> SPI MEM (drivers/spi/spi-mem.c). SPI MEM drivers are usually more
>> general and not tailored specifically to SPI NOR flashes, so it might be
>> a bit tricky to write drivers for specialized hardware with it. But I
>> think the drivers/spi/spi-intel.c driver is written for similar kind of
>> hardware so it should be possible.
>
> Oops. I've had a look at spi-mem, and it seems like it's not a
> particularly fitting abstraction for this controller.
>
> From what I understood, spi-mem primarily expects to be talking SPI
> opcodes to the controller, and for the controller/driver to bring
> their own chip probing routines. This controller on the other hand
> abstracts the opcodes away, and wants someone to tell it what its
> flash chip can do (the controller itself can only get a chip ID in
> "normal" mode, and it needs to somehow know the chip size and
> standard/fast read capability of the chip). So pretty much the
> opposite, huh.

Does it use SFDP to figure out which opcodes to use? Then it feels very
similar to intel-spi. See [0] for example. I know this is fitting a
square peg in a round hole, but if it isn't too painful then it would
make maintenance on SPI NOR end a bit easier.

Mika (+Cc), you did the conversion of intel-spi to SPI MEM. Maybe you
can share how painful/easy the conversion was, and if it ended up being
maintainable?

>
> In the end, I only need something like spi_nor_detect() and can do the
> rest directly on top of the MTD framework without touching any SPI
> opcodes after the detection is done. Is there any other non-deprecated
> framework that can provide something like this? Maybe physmap? It
> looks even older than SPI NOR though :)

[0] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/spi/spi-intel.c#n905

-- 
Regards,
Pratyush Yadav


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 2/3] mtd: spi-nor: Add a driver for the VIA/WonderMedia serial flash controller
  2025-07-24 13:51       ` Pratyush Yadav
@ 2025-07-28  7:09         ` Mika Westerberg
  0 siblings, 0 replies; 16+ messages in thread
From: Mika Westerberg @ 2025-07-28  7:09 UTC (permalink / raw)
  To: Pratyush Yadav
  Cc: Alexey Charkov, Mark Brown, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Tudor Ambarus, Michael Walle, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Krzysztof Kozlowski,
	linux-spi, devicetree, linux-kernel, linux-mtd, linux-arm-kernel

Hi,

On Thu, Jul 24, 2025 at 03:51:08PM +0200, Pratyush Yadav wrote:
> > From what I understood, spi-mem primarily expects to be talking SPI
> > opcodes to the controller, and for the controller/driver to bring
> > their own chip probing routines. This controller on the other hand
> > abstracts the opcodes away, and wants someone to tell it what its
> > flash chip can do (the controller itself can only get a chip ID in
> > "normal" mode, and it needs to somehow know the chip size and
> > standard/fast read capability of the chip). So pretty much the
> > opposite, huh.
> 
> Does it use SFDP to figure out which opcodes to use? Then it feels very
> similar to intel-spi. See [0] for example. I know this is fitting a
> square peg in a round hole, but if it isn't too painful then it would
> make maintenance on SPI NOR end a bit easier.
> 
> Mika (+Cc), you did the conversion of intel-spi to SPI MEM. Maybe you
> can share how painful/easy the conversion was, and if it ended up being
> maintainable?

Well it is kind of "maintainable" but the driver needs to do whole lot of
translation to get the SPI opcodes translated into the commands the
controller can actually execute. This means that if we get new opcodes for
new chips the driver needs to be updated too. I feel the SPI MEM is not
really good fit for "higher level" controllers like this.


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2025-07-28  7:30 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-10 19:42 [PATCH 0/3] mtd: spi-nor: Add VIA/WonderMedia serial flash controller driver Alexey Charkov
2025-05-10 19:42 ` [PATCH 1/3] dt-bindings: spi: Add VIA/WonderMedia serial flash controller Alexey Charkov
2025-05-14 20:41   ` Rob Herring
2025-05-15 19:50     ` Alexey Charkov
2025-06-06  8:29       ` Krzysztof Kozlowski
2025-06-06  9:06         ` Alexey Charkov
2025-06-09  9:07           ` Miquel Raynal
2025-06-09  9:15             ` Alexey Charkov
2025-05-10 19:42 ` [PATCH 2/3] mtd: spi-nor: Add a driver for the " Alexey Charkov
2025-05-11 11:13   ` kernel test robot
2025-05-11 12:16   ` kernel test robot
2025-05-12  9:20   ` Pratyush Yadav
2025-05-12 17:50     ` Alexey Charkov
2025-07-24 13:51       ` Pratyush Yadav
2025-07-28  7:09         ` Mika Westerberg
2025-05-10 19:42 ` [PATCH 3/3] ARM: dts: vt8500: Add serial flash controller and its clock Alexey Charkov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).