devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support
@ 2025-10-10  8:40 Richard Genoud
  2025-10-10  8:40 ` [PATCH 01/15] mtd: rawnand: sunxi: Remove superfluous register readings Richard Genoud
                   ` (14 more replies)
  0 siblings, 15 replies; 33+ messages in thread
From: Richard Genoud @ 2025-10-10  8:40 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

Hi everyone,

This patch series introduce H6/H616 NAND controller support (but not yet
the DMA/MDMA part).

All the work was done on a H616 board with a Kioxia TC58NVG1S3HTA00 NAND
chip.
ECC is supported, as well as scrambling.

H6 SoC has not been tested, but it shares all registers with H616, plus
some registers dedicated to Embedded Crypto Engine that H616 lacks.

This IP has quite some register fields modified from the A10/A23, but in
the end, it works more or less the same.
Main differences with A10/A23 are:
- The need for 2 more clocks (for ECC and MBUS)
- The use of a new USER_DATA_LEN register
- More ECC strengths (44, 52, 68, 72, 76 and 80 bits / 1KB)
- MDMA based on chained buffers
- some registers layouts have changed (mainly due do the stronger ECC)

Patch 1 removes a superfluous call, and is independent from the others.

Patch 2 introduces allwinner,sun50i-h616-nand-controller compatible
in order to differentiate from the A10 and A23.

Patch 3 adds the NAND controller node to sun50i-h616.dtsi

Patches 4-14 are paving the way to the introduction of H616 NAND
controller support.
They are small, without functional change and easier to review than a
big patch.
They move a fixed value (register offset, field mask, SRAM size) into
the struct sunxi_nfc_caps when those values are different on H6/H616.

Patch 15 introduce the support for H6/H616 NAND controller.

Regards,
Richard

Richard Genoud (15):
  mtd: rawnand: sunxi: Remove superfluous register readings
  dt-bindings: mtd: sunxi: Add new compatible
  arm64: dts: allwinner: h616: add NAND controller
  mtd: nand: sunxi: move ecc strenghts in sunxi_nfc_caps
  mtd: nand: sunxi: introduce reg_ecc_err_cnt in sunxi_nfc_caps
  mtd: nand: sunxi: introduce reg_user_data in sunxi_nfc_caps
  mtd: nand: sunxi: rework pattern found registers
  mtd: nand: sunxi: add has_ecc_block_512 capability
  mtd: nand: sunxi: introduce ecc_mode_mask in sunxi_nfc_caps
  mtd: nand: sunxi: introduce random en/dir in sunxi_nfc_caps
  mtd: nand: sunxi: introduce reg_pat_id in sunxi_nfc_caps
  mtd: nand: sunxi: introduce reg_spare_area in sunxi_nfc_caps
  mtd: nand: sunxi: introduce ecc_err_mask in sunxi_nfc_caps
  mtd: nand: sunxi: introduce sram_size in sunxi_nfc_caps
  mtd: rawnand: sunxi: Add support for H616 nand controller

 .../mtd/allwinner,sun4i-a10-nand.yaml         |  56 ++-
 .../arm64/boot/dts/allwinner/sun50i-h616.dtsi |  50 +++
 drivers/mtd/nand/raw/sunxi_nand.c             | 342 +++++++++++++++---
 3 files changed, 390 insertions(+), 58 deletions(-)

-- 
2.47.3


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

* [PATCH 01/15] mtd: rawnand: sunxi: Remove superfluous register readings
  2025-10-10  8:40 [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
@ 2025-10-10  8:40 ` Richard Genoud
  2025-10-11 10:15   ` Jernej Škrabec
  2025-10-10  8:40 ` [PATCH 02/15] dt-bindings: mtd: sunxi: Add new compatible Richard Genoud
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 33+ messages in thread
From: Richard Genoud @ 2025-10-10  8:40 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

The register NFC_REG_ECC_CTL was read twice and the result was not used,
then a third time with a mask applied.
Removing those calls didn't change the behavior.

Tested on H616 SoC, scrambling enabled.

Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
 drivers/mtd/nand/raw/sunxi_nand.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 162cd5f4f234..10a48e0d361f 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -623,13 +623,12 @@ static void sunxi_nfc_randomizer_config(struct nand_chip *nand, int page,
 					bool ecc)
 {
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
-	u32 ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
+	u32 ecc_ctl;
 	u16 state;
 
 	if (!(nand->options & NAND_NEED_SCRAMBLING))
 		return;
 
-	ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
 	state = sunxi_nfc_randomizer_state(nand, page, ecc);
 	ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_SEED_MSK;
 	writel(ecc_ctl | NFC_RANDOM_SEED(state), nfc->regs + NFC_REG_ECC_CTL);
-- 
2.47.3


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

* [PATCH 02/15] dt-bindings: mtd: sunxi: Add new compatible
  2025-10-10  8:40 [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
  2025-10-10  8:40 ` [PATCH 01/15] mtd: rawnand: sunxi: Remove superfluous register readings Richard Genoud
@ 2025-10-10  8:40 ` Richard Genoud
  2025-10-10  8:45   ` Krzysztof Kozlowski
  2025-10-10  8:49   ` Krzysztof Kozlowski
  2025-10-10  8:40 ` [PATCH 03/15] arm64: dts: allwinner: h616: add NAND controller Richard Genoud
                   ` (12 subsequent siblings)
  14 siblings, 2 replies; 33+ messages in thread
From: Richard Genoud @ 2025-10-10  8:40 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

The H616 NAND controller is quite different from the A10 and A23 ones,
some registers offset changed, and some new one are introduced.
Also, the DMA handling is different (it uses chained descriptors)

So, introduce a new compatible to represent this version of the IP.

Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
 .../mtd/allwinner,sun4i-a10-nand.yaml         | 56 ++++++++++++++-----
 1 file changed, 43 insertions(+), 13 deletions(-)

diff --git a/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml b/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
index 054b6b8bf9b9..cc63091fe936 100644
--- a/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
+++ b/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
@@ -6,34 +6,64 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 
 title: Allwinner A10 NAND Controller
 
-allOf:
-  - $ref: nand-controller.yaml
-
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
   - Maxime Ripard <mripard@kernel.org>
 
+allOf:
+  - $ref: nand-controller.yaml
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - allwinner,sun4i-a10-nand
+              - allwinner,sun8i-a23-nand-controller
+    then:
+      properties:
+        clocks:
+          items:
+            - description: Bus Clock
+            - description: Module Clock
+        clock-names:
+          items:
+            - const: ahb
+            - const: mod
+
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - allwinner,sun50i-h616-nand-controller
+    then:
+      properties:
+        clocks:
+          items:
+            - description: Bus Clock
+            - description: Module Clock
+            - description: ECC Clock
+            - description: MBus Clock
+        clock-names:
+          items:
+            - const: ahb
+            - const: mod
+            - const: ecc
+            - const: mbus
+
 properties:
   compatible:
     enum:
       - allwinner,sun4i-a10-nand
       - allwinner,sun8i-a23-nand-controller
+      - allwinner,sun50i-h616-nand-controller
   reg:
     maxItems: 1
 
   interrupts:
     maxItems: 1
 
-  clocks:
-    items:
-      - description: Bus Clock
-      - description: Module Clock
-
-  clock-names:
-    items:
-      - const: ahb
-      - const: mod
-
   resets:
     maxItems: 1
 
-- 
2.47.3


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

* [PATCH 03/15] arm64: dts: allwinner: h616: add NAND controller
  2025-10-10  8:40 [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
  2025-10-10  8:40 ` [PATCH 01/15] mtd: rawnand: sunxi: Remove superfluous register readings Richard Genoud
  2025-10-10  8:40 ` [PATCH 02/15] dt-bindings: mtd: sunxi: Add new compatible Richard Genoud
@ 2025-10-10  8:40 ` Richard Genoud
  2025-10-10  8:47   ` Krzysztof Kozlowski
  2025-10-11 10:33   ` Jernej Škrabec
  2025-10-10  8:40 ` [PATCH 04/15] mtd: nand: sunxi: move ecc strenghts in sunxi_nfc_caps Richard Genoud
                   ` (11 subsequent siblings)
  14 siblings, 2 replies; 33+ messages in thread
From: Richard Genoud @ 2025-10-10  8:40 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

The H616 has a NAND controller quite similar to the A10/A23 ones, but
with some register differences, more clocks (for ECC and MBUS), more ECC
strengths, so this requires a new compatible string.

This patch adds the NAND controller node and pins in the device tree.

Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
 .../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 50 +++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
index ceedae9e399b..60626eba7f7c 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
@@ -278,6 +278,37 @@ ir_rx_pin: ir-rx-pin {
 				function = "ir_rx";
 			};
 
+			nand_pins: nand-pins {
+				pins = "PC0", "PC1", "PC2", "PC5", "PC8", "PC9",
+				       "PC10", "PC11", "PC12", "PC13", "PC14",
+				       "PC15", "PC16";
+				function = "nand0";
+			};
+
+			nand_cs0_pin: nand-cs0-pin {
+				pins = "PC4";
+				function = "nand0";
+				bias-pull-up;
+			};
+
+			nand_cs1_pin: nand-cs1-pin {
+				pins = "PC3";
+				function = "nand0";
+				bias-pull-up;
+			};
+
+			nand_rb0_pin: nand-rb0-pin {
+				pins = "PC6";
+				function = "nand0";
+				bias-pull-up;
+			};
+
+			nand_rb1_pin: nand-rb1-pin {
+				pins = "PC7";
+				function = "nand0";
+				bias-pull-up;
+			};
+
 			mmc0_pins: mmc0-pins {
 				pins = "PF0", "PF1", "PF2", "PF3",
 				       "PF4", "PF5";
@@ -440,6 +471,25 @@ mmc2: mmc@4022000 {
 			#size-cells = <0>;
 		};
 
+		nfc: nand-controller@4011000 {
+			compatible = "allwinner,sun50i-h616-nand-controller";
+			reg = <0x04011000 0x1000>;
+			interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+			clocks = <&ccu CLK_BUS_NAND>, <&ccu CLK_NAND0>,
+				<&ccu CLK_NAND1>, <&ccu CLK_MBUS_NAND>;
+			clock-names = "ahb", "mod", "ecc", "mbus";
+			resets = <&ccu RST_BUS_NAND>;
+			reset-names = "ahb";
+			dmas = <&dma 10>;
+			dma-names = "rxtx";
+			pinctrl-names = "default";
+			pinctrl-0 = <&nand_pins>, <&nand_cs0_pin>,
+				<&nand_cs1_pin>, <&nand_rb0_pin>,
+				<&nand_rb1_pin>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+		};
+
 		uart0: serial@5000000 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0x05000000 0x400>;
-- 
2.47.3


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

* [PATCH 04/15] mtd: nand: sunxi: move ecc strenghts in sunxi_nfc_caps
  2025-10-10  8:40 [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
                   ` (2 preceding siblings ...)
  2025-10-10  8:40 ` [PATCH 03/15] arm64: dts: allwinner: h616: add NAND controller Richard Genoud
@ 2025-10-10  8:40 ` Richard Genoud
  2025-10-11 10:41   ` Jernej Škrabec
  2025-10-10  8:40 ` [PATCH 05/15] mtd: nand: sunxi: introduce reg_ecc_err_cnt " Richard Genoud
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 33+ messages in thread
From: Richard Genoud @ 2025-10-10  8:40 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

H6/H616 has more ecc strenghts.
This commit prepares the change.
No functional change.

Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
 drivers/mtd/nand/raw/sunxi_nand.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 10a48e0d361f..198dd40f9220 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -213,11 +213,15 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
  *			through MBUS on A23/A33 needs extra configuration.
  * @reg_io_data:	I/O data register
  * @dma_maxburst:	DMA maxburst
+ * @ecc_strengths:	Available ECC strengths array
+ * @nstrengths:		Size of @ecc_strengths
  */
 struct sunxi_nfc_caps {
 	bool has_mdma;
 	unsigned int reg_io_data;
 	unsigned int dma_maxburst;
+	const u8 *ecc_strengths;
+	unsigned int nstrengths;
 };
 
 /**
@@ -1619,9 +1623,9 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
 				       struct nand_ecc_ctrl *ecc,
 				       struct device_node *np)
 {
-	static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
 	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
+	const u8 *strengths = nfc->caps->ecc_strengths;
 	struct mtd_info *mtd = nand_to_mtd(nand);
 	struct nand_device *nanddev = mtd_to_nanddev(mtd);
 	int nsectors;
@@ -1645,7 +1649,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
 
 		ecc->strength = bytes * 8 / fls(8 * ecc->size);
 
-		for (i = 0; i < ARRAY_SIZE(strengths); i++) {
+		for (i = 0; i < nfc->caps->nstrengths; i++) {
 			if (strengths[i] > ecc->strength)
 				break;
 		}
@@ -1666,7 +1670,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
 	}
 
 	/* Add ECC info retrieval from DT */
-	for (i = 0; i < ARRAY_SIZE(strengths); i++) {
+	for (i = 0; i < nfc->caps->nstrengths; i++) {
 		if (ecc->strength <= strengths[i]) {
 			/*
 			 * Update ecc->strength value with the actual strength
@@ -1677,7 +1681,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
 		}
 	}
 
-	if (i >= ARRAY_SIZE(strengths)) {
+	if (i >= nfc->caps->nstrengths) {
 		dev_err(nfc->dev, "unsupported strength\n");
 		return -ENOTSUPP;
 	}
@@ -2167,15 +2171,23 @@ static void sunxi_nfc_remove(struct platform_device *pdev)
 		dma_release_channel(nfc->dmac);
 }
 
+static const u8 sunxi_ecc_strengths_a10[] = {
+	16, 24, 28, 32, 40, 48, 56, 60, 64
+};
+
 static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
 	.reg_io_data = NFC_REG_A10_IO_DATA,
 	.dma_maxburst = 4,
+	.ecc_strengths = sunxi_ecc_strengths_a10,
+	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
 };
 
 static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
 	.has_mdma = true,
 	.reg_io_data = NFC_REG_A23_IO_DATA,
 	.dma_maxburst = 8,
+	.ecc_strengths = sunxi_ecc_strengths_a10,
+	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
 };
 
 static const struct of_device_id sunxi_nfc_ids[] = {
-- 
2.47.3


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

* [PATCH 05/15] mtd: nand: sunxi: introduce reg_ecc_err_cnt in sunxi_nfc_caps
  2025-10-10  8:40 [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
                   ` (3 preceding siblings ...)
  2025-10-10  8:40 ` [PATCH 04/15] mtd: nand: sunxi: move ecc strenghts in sunxi_nfc_caps Richard Genoud
@ 2025-10-10  8:40 ` Richard Genoud
  2025-10-10  8:40 ` [PATCH 06/15] mtd: nand: sunxi: introduce reg_user_data " Richard Genoud
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 33+ messages in thread
From: Richard Genoud @ 2025-10-10  8:40 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

The H6/H616 ECC_ERR_CNT register is not at the same offset as the
A10/A23 one, so move its offset into sunxi_nfc_caps

No functional change.

Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
 drivers/mtd/nand/raw/sunxi_nand.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 198dd40f9220..faaac71e7be3 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -46,7 +46,8 @@
 #define NFC_REG_ECC_CTL		0x0034
 #define NFC_REG_ECC_ST		0x0038
 #define NFC_REG_DEBUG		0x003C
-#define NFC_REG_ECC_ERR_CNT(x)	((0x0040 + (x)) & ~0x3)
+#define NFC_REG_A10_ECC_ERR_CNT	0x0040
+#define NFC_REG_ECC_ERR_CNT(nfc, x)	((nfc->caps->reg_ecc_err_cnt + (x)) & ~0x3)
 #define NFC_REG_USER_DATA(x)	(0x0050 + ((x) * 4))
 #define NFC_REG_SPARE_AREA	0x00A0
 #define NFC_REG_PAT_ID		0x00A4
@@ -212,6 +213,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
  * @has_mdma:		Use mbus dma mode, otherwise general dma
  *			through MBUS on A23/A33 needs extra configuration.
  * @reg_io_data:	I/O data register
+ * @reg_ecc_err_cnt:	ECC error counter register
  * @dma_maxburst:	DMA maxburst
  * @ecc_strengths:	Available ECC strengths array
  * @nstrengths:		Size of @ecc_strengths
@@ -219,6 +221,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
 struct sunxi_nfc_caps {
 	bool has_mdma;
 	unsigned int reg_io_data;
+	unsigned int reg_ecc_err_cnt;
 	unsigned int dma_maxburst;
 	const u8 *ecc_strengths;
 	unsigned int nstrengths;
@@ -790,7 +793,7 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob,
 		return 0;
 	}
 
-	tmp = readl(nfc->regs + NFC_REG_ECC_ERR_CNT(step));
+	tmp = readl(nfc->regs + NFC_REG_ECC_ERR_CNT(nfc, step));
 
 	return NFC_ECC_ERR_CNT(step, tmp);
 }
@@ -2177,6 +2180,7 @@ static const u8 sunxi_ecc_strengths_a10[] = {
 
 static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
 	.reg_io_data = NFC_REG_A10_IO_DATA,
+	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
 	.dma_maxburst = 4,
 	.ecc_strengths = sunxi_ecc_strengths_a10,
 	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
@@ -2185,6 +2189,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
 static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
 	.has_mdma = true,
 	.reg_io_data = NFC_REG_A23_IO_DATA,
+	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
 	.dma_maxburst = 8,
 	.ecc_strengths = sunxi_ecc_strengths_a10,
 	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
-- 
2.47.3


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

* [PATCH 06/15] mtd: nand: sunxi: introduce reg_user_data in sunxi_nfc_caps
  2025-10-10  8:40 [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
                   ` (4 preceding siblings ...)
  2025-10-10  8:40 ` [PATCH 05/15] mtd: nand: sunxi: introduce reg_ecc_err_cnt " Richard Genoud
@ 2025-10-10  8:40 ` Richard Genoud
  2025-10-10  8:40 ` [PATCH 07/15] mtd: nand: sunxi: rework pattern found registers Richard Genoud
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 33+ messages in thread
From: Richard Genoud @ 2025-10-10  8:40 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

The H6/H616 USER_DATA register is not at the same offset as the
A10/A23 one, so move its offset into sunxi_nfc_caps

No functional change.

Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
 drivers/mtd/nand/raw/sunxi_nand.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index faaac71e7be3..6c78370a6095 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -48,7 +48,8 @@
 #define NFC_REG_DEBUG		0x003C
 #define NFC_REG_A10_ECC_ERR_CNT	0x0040
 #define NFC_REG_ECC_ERR_CNT(nfc, x)	((nfc->caps->reg_ecc_err_cnt + (x)) & ~0x3)
-#define NFC_REG_USER_DATA(x)	(0x0050 + ((x) * 4))
+#define NFC_REG_A10_USER_DATA	0x0050
+#define NFC_REG_USER_DATA(nfc, x)	(nfc->caps->reg_user_data + ((x) * 4))
 #define NFC_REG_SPARE_AREA	0x00A0
 #define NFC_REG_PAT_ID		0x00A4
 #define NFC_REG_MDMA_ADDR	0x00C0
@@ -214,6 +215,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
  *			through MBUS on A23/A33 needs extra configuration.
  * @reg_io_data:	I/O data register
  * @reg_ecc_err_cnt:	ECC error counter register
+ * @reg_user_data:	User data register
  * @dma_maxburst:	DMA maxburst
  * @ecc_strengths:	Available ECC strengths array
  * @nstrengths:		Size of @ecc_strengths
@@ -222,6 +224,7 @@ struct sunxi_nfc_caps {
 	bool has_mdma;
 	unsigned int reg_io_data;
 	unsigned int reg_ecc_err_cnt;
+	unsigned int reg_user_data;
 	unsigned int dma_maxburst;
 	const u8 *ecc_strengths;
 	unsigned int nstrengths;
@@ -723,8 +726,8 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob,
 {
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 
-	sunxi_nfc_user_data_to_buf(readl(nfc->regs + NFC_REG_USER_DATA(step)),
-				   oob);
+	sunxi_nfc_user_data_to_buf(readl(nfc->regs +
+					 NFC_REG_USER_DATA(nfc, step)), oob);
 
 	/* De-randomize the Bad Block Marker. */
 	if (bbm && (nand->options & NAND_NEED_SCRAMBLING))
@@ -746,7 +749,7 @@ static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand,
 	}
 
 	writel(sunxi_nfc_buf_to_user_data(oob),
-	       nfc->regs + NFC_REG_USER_DATA(step));
+	       nfc->regs + NFC_REG_USER_DATA(nfc, step));
 }
 
 static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand,
@@ -2181,6 +2184,7 @@ static const u8 sunxi_ecc_strengths_a10[] = {
 static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
 	.reg_io_data = NFC_REG_A10_IO_DATA,
 	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
+	.reg_user_data = NFC_REG_A10_USER_DATA,
 	.dma_maxburst = 4,
 	.ecc_strengths = sunxi_ecc_strengths_a10,
 	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
@@ -2190,6 +2194,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
 	.has_mdma = true,
 	.reg_io_data = NFC_REG_A23_IO_DATA,
 	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
+	.reg_user_data = NFC_REG_A10_USER_DATA,
 	.dma_maxburst = 8,
 	.ecc_strengths = sunxi_ecc_strengths_a10,
 	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
-- 
2.47.3


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

* [PATCH 07/15] mtd: nand: sunxi: rework pattern found registers
  2025-10-10  8:40 [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
                   ` (5 preceding siblings ...)
  2025-10-10  8:40 ` [PATCH 06/15] mtd: nand: sunxi: introduce reg_user_data " Richard Genoud
@ 2025-10-10  8:40 ` Richard Genoud
  2025-10-10  8:40 ` [PATCH 08/15] mtd: nand: sunxi: add has_ecc_block_512 capability Richard Genoud
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 33+ messages in thread
From: Richard Genoud @ 2025-10-10  8:40 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

On H6/H616, the register ECC_PAT_FOUND is at its own address, and not
part of ECC status register.
So, we introduce the pattern found register offset in sunxi_nfc_caps,
along with its mask.

Also, introduce a non compile-time field_get() because FIELD_GET() and
u32_get_bits() don't work with non compile-time constant.
https://lore.kernel.org/lkml/cover.1739540679.git.geert+renesas@glider.be/

No functional change.

Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
 drivers/mtd/nand/raw/sunxi_nand.c | 36 ++++++++++++++++++++++++++-----
 1 file changed, 31 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 6c78370a6095..8c0430fbbb38 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -29,6 +29,9 @@
 #include <linux/iopoll.h>
 #include <linux/reset.h>
 
+/* non compile-time field get */
+#define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
+
 #define NFC_REG_CTL		0x0000
 #define NFC_REG_ST		0x0004
 #define NFC_REG_INT		0x0008
@@ -150,7 +153,13 @@
 /* define bit use in NFC_ECC_ST */
 #define NFC_ECC_ERR(x)		BIT(x)
 #define NFC_ECC_ERR_MSK		GENMASK(15, 0)
-#define NFC_ECC_PAT_FOUND(x)	BIT(x + 16)
+
+/*
+ * define bit use in NFC_REG_PAT_FOUND
+ * For A10/A23, NFC_REG_PAT_FOUND == NFC_ECC_ST register
+ */
+#define NFC_ECC_PAT_FOUND_MSK(nfc) (nfc->caps->pat_found_mask)
+
 #define NFC_ECC_ERR_CNT(b, x)	(((x) >> (((b) % 4) * 8)) & 0xff)
 
 #define NFC_DEFAULT_TIMEOUT_MS	1000
@@ -216,6 +225,8 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
  * @reg_io_data:	I/O data register
  * @reg_ecc_err_cnt:	ECC error counter register
  * @reg_user_data:	User data register
+ * @reg_pat_found:	Data Pattern Status Register
+ * @pat_found_mask:	ECC_PAT_FOUND mask in NFC_REG_PAT_FOUND register
  * @dma_maxburst:	DMA maxburst
  * @ecc_strengths:	Available ECC strengths array
  * @nstrengths:		Size of @ecc_strengths
@@ -225,6 +236,8 @@ struct sunxi_nfc_caps {
 	unsigned int reg_io_data;
 	unsigned int reg_ecc_err_cnt;
 	unsigned int reg_user_data;
+	unsigned int reg_pat_found;
+	unsigned int pat_found_mask;
 	unsigned int dma_maxburst;
 	const u8 *ecc_strengths;
 	unsigned int nstrengths;
@@ -766,7 +779,8 @@ static void sunxi_nfc_hw_ecc_update_stats(struct nand_chip *nand,
 }
 
 static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob,
-				    int step, u32 status, bool *erased)
+				    int step, u32 status, u32 pattern_found,
+				    bool *erased)
 {
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 	struct nand_ecc_ctrl *ecc = &nand->ecc;
@@ -777,7 +791,7 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob,
 	if (status & NFC_ECC_ERR(step))
 		return -EBADMSG;
 
-	if (status & NFC_ECC_PAT_FOUND(step)) {
+	if (pattern_found & BIT(step)) {
 		u8 pattern;
 
 		if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1))) {
@@ -811,6 +825,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand,
 	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
 	struct nand_ecc_ctrl *ecc = &nand->ecc;
 	int raw_mode = 0;
+	u32 pattern_found;
 	bool erased;
 	int ret;
 
@@ -838,8 +853,12 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand,
 
 	*cur_off = oob_off + ecc->bytes + 4;
 
+	pattern_found = readl(nfc->regs + nfc->caps->reg_pat_found);
+	pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found);
+
 	ret = sunxi_nfc_hw_ecc_correct(nand, data, oob_required ? oob : NULL, 0,
 				       readl(nfc->regs + NFC_REG_ECC_ST),
+				       pattern_found,
 				       &erased);
 	if (erased)
 		return 1;
@@ -920,7 +939,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf
 	unsigned int max_bitflips = 0;
 	int ret, i, raw_mode = 0;
 	struct scatterlist sg;
-	u32 status, wait;
+	u32 status, pattern_found, wait;
 
 	ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
 	if (ret)
@@ -961,6 +980,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf
 		return ret;
 
 	status = readl(nfc->regs + NFC_REG_ECC_ST);
+	pattern_found = readl(nfc->regs + nfc->caps->reg_pat_found);
+	pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found);
 
 	for (i = 0; i < nchunks; i++) {
 		int data_off = i * ecc->size;
@@ -971,7 +992,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf
 
 		ret = sunxi_nfc_hw_ecc_correct(nand, randomized ? data : NULL,
 					       oob_required ? oob : NULL,
-					       i, status, &erased);
+					       i, status, pattern_found,
+					       &erased);
 
 		/* ECC errors are handled in the second loop. */
 		if (ret < 0)
@@ -2185,6 +2207,8 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
 	.reg_io_data = NFC_REG_A10_IO_DATA,
 	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
 	.reg_user_data = NFC_REG_A10_USER_DATA,
+	.reg_pat_found = NFC_REG_ECC_ST,
+	.pat_found_mask = GENMASK(31, 16),
 	.dma_maxburst = 4,
 	.ecc_strengths = sunxi_ecc_strengths_a10,
 	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
@@ -2195,6 +2219,8 @@ static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
 	.reg_io_data = NFC_REG_A23_IO_DATA,
 	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
 	.reg_user_data = NFC_REG_A10_USER_DATA,
+	.reg_pat_found = NFC_REG_ECC_ST,
+	.pat_found_mask = GENMASK(31, 16),
 	.dma_maxburst = 8,
 	.ecc_strengths = sunxi_ecc_strengths_a10,
 	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
-- 
2.47.3


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

* [PATCH 08/15] mtd: nand: sunxi: add has_ecc_block_512 capability
  2025-10-10  8:40 [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
                   ` (6 preceding siblings ...)
  2025-10-10  8:40 ` [PATCH 07/15] mtd: nand: sunxi: rework pattern found registers Richard Genoud
@ 2025-10-10  8:40 ` Richard Genoud
  2025-10-10  8:40 ` [PATCH 09/15] mtd: nand: sunxi: introduce ecc_mode_mask in sunxi_nfc_caps Richard Genoud
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 33+ messages in thread
From: Richard Genoud @ 2025-10-10  8:40 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

The H6/H616 controller can't handle 512 bytes ecc block size.
Let it be a capability.

No functional change.

Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
 drivers/mtd/nand/raw/sunxi_nand.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 8c0430fbbb38..672e934444ca 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -222,6 +222,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
  *
  * @has_mdma:		Use mbus dma mode, otherwise general dma
  *			through MBUS on A23/A33 needs extra configuration.
+ * @has_ecc_block_512:	If the ECC can handle 512B or only 1024B chuncks
  * @reg_io_data:	I/O data register
  * @reg_ecc_err_cnt:	ECC error counter register
  * @reg_user_data:	User data register
@@ -233,6 +234,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
  */
 struct sunxi_nfc_caps {
 	bool has_mdma;
+	bool has_ecc_block_512;
 	unsigned int reg_io_data;
 	unsigned int reg_ecc_err_cnt;
 	unsigned int reg_user_data;
@@ -1748,8 +1750,14 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
 	sunxi_nand->ecc.ecc_ctl = NFC_ECC_MODE(i) | NFC_ECC_EXCEPTION |
 				  NFC_ECC_PIPELINE | NFC_ECC_EN;
 
-	if (ecc->size == 512)
-		sunxi_nand->ecc.ecc_ctl |= NFC_ECC_BLOCK_512;
+	if (ecc->size == 512) {
+		if (nfc->caps->has_ecc_block_512) {
+			sunxi_nand->ecc.ecc_ctl |= NFC_ECC_BLOCK_512;
+		} else {
+			dev_err(nfc->dev, "512B ECC block not supported\n");
+			return -EOPNOTSUPP;
+		}
+	}
 
 	return 0;
 }
@@ -2204,6 +2212,7 @@ static const u8 sunxi_ecc_strengths_a10[] = {
 };
 
 static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
+	.has_ecc_block_512 = true,
 	.reg_io_data = NFC_REG_A10_IO_DATA,
 	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
 	.reg_user_data = NFC_REG_A10_USER_DATA,
@@ -2216,6 +2225,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
 
 static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
 	.has_mdma = true,
+	.has_ecc_block_512 = true,
 	.reg_io_data = NFC_REG_A23_IO_DATA,
 	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
 	.reg_user_data = NFC_REG_A10_USER_DATA,
-- 
2.47.3


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

* [PATCH 09/15] mtd: nand: sunxi: introduce ecc_mode_mask in sunxi_nfc_caps
  2025-10-10  8:40 [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
                   ` (7 preceding siblings ...)
  2025-10-10  8:40 ` [PATCH 08/15] mtd: nand: sunxi: add has_ecc_block_512 capability Richard Genoud
@ 2025-10-10  8:40 ` Richard Genoud
  2025-10-10  8:40 ` [PATCH 10/15] mtd: nand: sunxi: introduce random en/dir " Richard Genoud
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 33+ messages in thread
From: Richard Genoud @ 2025-10-10  8:40 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

The H6/H616 ECC_MODE field is not at the same offset, and has not the
same size.
So move the mask into sunxi_nfc_caps.

No functional change.

Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
 drivers/mtd/nand/raw/sunxi_nand.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 672e934444ca..3c21f54e8e3f 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -29,8 +29,9 @@
 #include <linux/iopoll.h>
 #include <linux/reset.h>
 
-/* non compile-time field get */
+/* non compile-time field get/prep */
 #define field_get(_mask, _reg) (((_reg) & (_mask)) >> (ffs(_mask) - 1))
+#define field_prep(_mask, _val) (((_val) << (ffs(_mask) - 1)) & (_mask))
 
 #define NFC_REG_CTL		0x0000
 #define NFC_REG_ST		0x0004
@@ -145,8 +146,8 @@
 #define NFC_ECC_BLOCK_512	BIT(5)
 #define NFC_RANDOM_EN		BIT(9)
 #define NFC_RANDOM_DIRECTION	BIT(10)
-#define NFC_ECC_MODE_MSK	GENMASK(15, 12)
-#define NFC_ECC_MODE(x)		((x) << 12)
+#define NFC_ECC_MODE_MSK(nfc)	(nfc->caps->ecc_mode_mask)
+#define NFC_ECC_MODE(nfc, x)	field_prep(NFC_ECC_MODE_MSK(nfc), (x))
 #define NFC_RANDOM_SEED_MSK	GENMASK(30, 16)
 #define NFC_RANDOM_SEED(x)	((x) << 16)
 
@@ -227,6 +228,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
  * @reg_ecc_err_cnt:	ECC error counter register
  * @reg_user_data:	User data register
  * @reg_pat_found:	Data Pattern Status Register
+ * @ecc_mode_mask:	ECC_MODE mask in NFC_ECC_CTL register
  * @pat_found_mask:	ECC_PAT_FOUND mask in NFC_REG_PAT_FOUND register
  * @dma_maxburst:	DMA maxburst
  * @ecc_strengths:	Available ECC strengths array
@@ -239,6 +241,7 @@ struct sunxi_nfc_caps {
 	unsigned int reg_ecc_err_cnt;
 	unsigned int reg_user_data;
 	unsigned int reg_pat_found;
+	unsigned int ecc_mode_mask;
 	unsigned int pat_found_mask;
 	unsigned int dma_maxburst;
 	const u8 *ecc_strengths;
@@ -1747,7 +1750,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
 	ecc->read_oob_raw = nand_read_oob_std;
 	ecc->write_oob_raw = nand_write_oob_std;
 
-	sunxi_nand->ecc.ecc_ctl = NFC_ECC_MODE(i) | NFC_ECC_EXCEPTION |
+	sunxi_nand->ecc.ecc_ctl = NFC_ECC_MODE(nfc, i) | NFC_ECC_EXCEPTION |
 				  NFC_ECC_PIPELINE | NFC_ECC_EN;
 
 	if (ecc->size == 512) {
@@ -2217,6 +2220,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
 	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
 	.reg_user_data = NFC_REG_A10_USER_DATA,
 	.reg_pat_found = NFC_REG_ECC_ST,
+	.ecc_mode_mask = GENMASK(15, 12),
 	.pat_found_mask = GENMASK(31, 16),
 	.dma_maxburst = 4,
 	.ecc_strengths = sunxi_ecc_strengths_a10,
@@ -2230,6 +2234,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
 	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
 	.reg_user_data = NFC_REG_A10_USER_DATA,
 	.reg_pat_found = NFC_REG_ECC_ST,
+	.ecc_mode_mask = GENMASK(15, 12),
 	.pat_found_mask = GENMASK(31, 16),
 	.dma_maxburst = 8,
 	.ecc_strengths = sunxi_ecc_strengths_a10,
-- 
2.47.3


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

* [PATCH 10/15] mtd: nand: sunxi: introduce random en/dir in sunxi_nfc_caps
  2025-10-10  8:40 [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
                   ` (8 preceding siblings ...)
  2025-10-10  8:40 ` [PATCH 09/15] mtd: nand: sunxi: introduce ecc_mode_mask in sunxi_nfc_caps Richard Genoud
@ 2025-10-10  8:40 ` Richard Genoud
  2025-10-10  8:40 ` [PATCH 11/15] mtd: nand: sunxi: introduce reg_pat_id " Richard Genoud
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 33+ messages in thread
From: Richard Genoud @ 2025-10-10  8:40 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

The H6/H616 RANDOM EN/DIRECTION masks are different from A10/A23.
So move the masks into sunxi_nfc_caps.

No functional change.

Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
 drivers/mtd/nand/raw/sunxi_nand.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 3c21f54e8e3f..5161dfff46ed 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -144,8 +144,8 @@
 #define NFC_ECC_EXCEPTION	BIT(4)
 #define NFC_ECC_BLOCK_SIZE_MSK	BIT(5)
 #define NFC_ECC_BLOCK_512	BIT(5)
-#define NFC_RANDOM_EN		BIT(9)
-#define NFC_RANDOM_DIRECTION	BIT(10)
+#define NFC_RANDOM_EN(nfc)	(nfc->caps->random_en_mask)
+#define NFC_RANDOM_DIRECTION(nfc) (nfc->caps->random_dir_mask)
 #define NFC_ECC_MODE_MSK(nfc)	(nfc->caps->ecc_mode_mask)
 #define NFC_ECC_MODE(nfc, x)	field_prep(NFC_ECC_MODE_MSK(nfc), (x))
 #define NFC_RANDOM_SEED_MSK	GENMASK(30, 16)
@@ -228,6 +228,8 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
  * @reg_ecc_err_cnt:	ECC error counter register
  * @reg_user_data:	User data register
  * @reg_pat_found:	Data Pattern Status Register
+ * @random_en_mask:	RANDOM_EN mask in NFC_ECC_CTL register
+ * @random_dir_mask:	RANDOM_DIRECTION mask in NFC_ECC_CTL register
  * @ecc_mode_mask:	ECC_MODE mask in NFC_ECC_CTL register
  * @pat_found_mask:	ECC_PAT_FOUND mask in NFC_REG_PAT_FOUND register
  * @dma_maxburst:	DMA maxburst
@@ -241,6 +243,8 @@ struct sunxi_nfc_caps {
 	unsigned int reg_ecc_err_cnt;
 	unsigned int reg_user_data;
 	unsigned int reg_pat_found;
+	unsigned int random_en_mask;
+	unsigned int random_dir_mask;
 	unsigned int ecc_mode_mask;
 	unsigned int pat_found_mask;
 	unsigned int dma_maxburst;
@@ -669,7 +673,7 @@ static void sunxi_nfc_randomizer_enable(struct nand_chip *nand)
 	if (!(nand->options & NAND_NEED_SCRAMBLING))
 		return;
 
-	writel(readl(nfc->regs + NFC_REG_ECC_CTL) | NFC_RANDOM_EN,
+	writel(readl(nfc->regs + NFC_REG_ECC_CTL) | NFC_RANDOM_EN(nfc),
 	       nfc->regs + NFC_REG_ECC_CTL);
 }
 
@@ -680,7 +684,7 @@ static void sunxi_nfc_randomizer_disable(struct nand_chip *nand)
 	if (!(nand->options & NAND_NEED_SCRAMBLING))
 		return;
 
-	writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_EN,
+	writel(readl(nfc->regs + NFC_REG_ECC_CTL) & ~NFC_RANDOM_EN(nfc),
 	       nfc->regs + NFC_REG_ECC_CTL);
 }
 
@@ -2220,6 +2224,8 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
 	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
 	.reg_user_data = NFC_REG_A10_USER_DATA,
 	.reg_pat_found = NFC_REG_ECC_ST,
+	.random_en_mask = BIT(9),
+	.random_dir_mask = BIT(10),
 	.ecc_mode_mask = GENMASK(15, 12),
 	.pat_found_mask = GENMASK(31, 16),
 	.dma_maxburst = 4,
@@ -2234,6 +2240,8 @@ static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
 	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
 	.reg_user_data = NFC_REG_A10_USER_DATA,
 	.reg_pat_found = NFC_REG_ECC_ST,
+	.random_en_mask = BIT(9),
+	.random_dir_mask = BIT(10),
 	.ecc_mode_mask = GENMASK(15, 12),
 	.pat_found_mask = GENMASK(31, 16),
 	.dma_maxburst = 8,
-- 
2.47.3


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

* [PATCH 11/15] mtd: nand: sunxi: introduce reg_pat_id in sunxi_nfc_caps
  2025-10-10  8:40 [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
                   ` (9 preceding siblings ...)
  2025-10-10  8:40 ` [PATCH 10/15] mtd: nand: sunxi: introduce random en/dir " Richard Genoud
@ 2025-10-10  8:40 ` Richard Genoud
  2025-10-10  8:40 ` [PATCH 12/15] mtd: nand: sunxi: introduce reg_spare_area " Richard Genoud
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 33+ messages in thread
From: Richard Genoud @ 2025-10-10  8:40 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

The H6/H616 pattern ID register is not at the same offset as the
A10/A23 one, so move its offset into sunxi_nfc_caps.

No functional change.

Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
 drivers/mtd/nand/raw/sunxi_nand.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 5161dfff46ed..8921e66e0c6d 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -55,7 +55,8 @@
 #define NFC_REG_A10_USER_DATA	0x0050
 #define NFC_REG_USER_DATA(nfc, x)	(nfc->caps->reg_user_data + ((x) * 4))
 #define NFC_REG_SPARE_AREA	0x00A0
-#define NFC_REG_PAT_ID		0x00A4
+#define NFC_REG_PAT_ID(nfc) (nfc->caps->reg_pat_id)
+#define NFC_REG_A10_PAT_ID	0x00A4
 #define NFC_REG_MDMA_ADDR	0x00C0
 #define NFC_REG_MDMA_CNT	0x00C4
 #define NFC_RAM0_BASE		0x0400
@@ -227,6 +228,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
  * @reg_io_data:	I/O data register
  * @reg_ecc_err_cnt:	ECC error counter register
  * @reg_user_data:	User data register
+ * @reg_pat_id:		Pattern ID Register
  * @reg_pat_found:	Data Pattern Status Register
  * @random_en_mask:	RANDOM_EN mask in NFC_ECC_CTL register
  * @random_dir_mask:	RANDOM_DIRECTION mask in NFC_ECC_CTL register
@@ -242,6 +244,7 @@ struct sunxi_nfc_caps {
 	unsigned int reg_io_data;
 	unsigned int reg_ecc_err_cnt;
 	unsigned int reg_user_data;
+	unsigned int reg_pat_id;
 	unsigned int reg_pat_found;
 	unsigned int random_en_mask;
 	unsigned int random_dir_mask;
@@ -803,7 +806,7 @@ static int sunxi_nfc_hw_ecc_correct(struct nand_chip *nand, u8 *data, u8 *oob,
 	if (pattern_found & BIT(step)) {
 		u8 pattern;
 
-		if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1))) {
+		if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & 0x1))) {
 			pattern = 0x0;
 		} else {
 			pattern = 0xff;
@@ -2223,6 +2226,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
 	.reg_io_data = NFC_REG_A10_IO_DATA,
 	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
 	.reg_user_data = NFC_REG_A10_USER_DATA,
+	.reg_pat_id = NFC_REG_A10_PAT_ID,
 	.reg_pat_found = NFC_REG_ECC_ST,
 	.random_en_mask = BIT(9),
 	.random_dir_mask = BIT(10),
@@ -2239,6 +2243,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
 	.reg_io_data = NFC_REG_A23_IO_DATA,
 	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
 	.reg_user_data = NFC_REG_A10_USER_DATA,
+	.reg_pat_id = NFC_REG_A10_PAT_ID,
 	.reg_pat_found = NFC_REG_ECC_ST,
 	.random_en_mask = BIT(9),
 	.random_dir_mask = BIT(10),
-- 
2.47.3


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

* [PATCH 12/15] mtd: nand: sunxi: introduce reg_spare_area in sunxi_nfc_caps
  2025-10-10  8:40 [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
                   ` (10 preceding siblings ...)
  2025-10-10  8:40 ` [PATCH 11/15] mtd: nand: sunxi: introduce reg_pat_id " Richard Genoud
@ 2025-10-10  8:40 ` Richard Genoud
  2025-10-10  8:40 ` [PATCH 13/15] mtd: nand: sunxi: introduce ecc_err_mask " Richard Genoud
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 33+ messages in thread
From: Richard Genoud @ 2025-10-10  8:40 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

The H6/H616 spare area register is not at the same offset as the
A10/A23 one, so move its offset into sunxi_nfc_caps.

No functional change.

Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
 drivers/mtd/nand/raw/sunxi_nand.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 8921e66e0c6d..80aafa4e1844 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -54,7 +54,8 @@
 #define NFC_REG_ECC_ERR_CNT(nfc, x)	((nfc->caps->reg_ecc_err_cnt + (x)) & ~0x3)
 #define NFC_REG_A10_USER_DATA	0x0050
 #define NFC_REG_USER_DATA(nfc, x)	(nfc->caps->reg_user_data + ((x) * 4))
-#define NFC_REG_SPARE_AREA	0x00A0
+#define NFC_REG_SPARE_AREA(nfc) (nfc->caps->reg_spare_area)
+#define NFC_REG_A10_SPARE_AREA	0x00A0
 #define NFC_REG_PAT_ID(nfc) (nfc->caps->reg_pat_id)
 #define NFC_REG_A10_PAT_ID	0x00A4
 #define NFC_REG_MDMA_ADDR	0x00C0
@@ -228,6 +229,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
  * @reg_io_data:	I/O data register
  * @reg_ecc_err_cnt:	ECC error counter register
  * @reg_user_data:	User data register
+ * @reg_spare_area:	Spare Area Register
  * @reg_pat_id:		Pattern ID Register
  * @reg_pat_found:	Data Pattern Status Register
  * @random_en_mask:	RANDOM_EN mask in NFC_ECC_CTL register
@@ -244,6 +246,7 @@ struct sunxi_nfc_caps {
 	unsigned int reg_io_data;
 	unsigned int reg_ecc_err_cnt;
 	unsigned int reg_user_data;
+	unsigned int reg_spare_area;
 	unsigned int reg_pat_id;
 	unsigned int reg_pat_found;
 	unsigned int random_en_mask;
@@ -466,7 +469,7 @@ static void sunxi_nfc_select_chip(struct nand_chip *nand, unsigned int cs)
 	if (sel->rb >= 0)
 		ctl |= NFC_RB_SEL(sel->rb);
 
-	writel(mtd->writesize, nfc->regs + NFC_REG_SPARE_AREA);
+	writel(mtd->writesize, nfc->regs + NFC_REG_SPARE_AREA(nfc));
 
 	if (nfc->clk_rate != sunxi_nand->clk_rate) {
 		clk_set_rate(nfc->mod_clk, sunxi_nand->clk_rate);
@@ -2226,6 +2229,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
 	.reg_io_data = NFC_REG_A10_IO_DATA,
 	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
 	.reg_user_data = NFC_REG_A10_USER_DATA,
+	.reg_spare_area = NFC_REG_A10_SPARE_AREA,
 	.reg_pat_id = NFC_REG_A10_PAT_ID,
 	.reg_pat_found = NFC_REG_ECC_ST,
 	.random_en_mask = BIT(9),
@@ -2243,6 +2247,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
 	.reg_io_data = NFC_REG_A23_IO_DATA,
 	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
 	.reg_user_data = NFC_REG_A10_USER_DATA,
+	.reg_spare_area = NFC_REG_A10_SPARE_AREA,
 	.reg_pat_id = NFC_REG_A10_PAT_ID,
 	.reg_pat_found = NFC_REG_ECC_ST,
 	.random_en_mask = BIT(9),
-- 
2.47.3


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

* [PATCH 13/15] mtd: nand: sunxi: introduce ecc_err_mask in sunxi_nfc_caps
  2025-10-10  8:40 [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
                   ` (11 preceding siblings ...)
  2025-10-10  8:40 ` [PATCH 12/15] mtd: nand: sunxi: introduce reg_spare_area " Richard Genoud
@ 2025-10-10  8:40 ` Richard Genoud
  2025-10-10  8:40 ` [PATCH 14/15] mtd: nand: sunxi: introduce sram_size " Richard Genoud
  2025-10-10  8:40 ` [PATCH 15/15] mtd: rawnand: sunxi: Add support for H616 nand controller Richard Genoud
  14 siblings, 0 replies; 33+ messages in thread
From: Richard Genoud @ 2025-10-10  8:40 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

The H6/H616 error mask register is bigger than the A10/A23 one, so move
its mask into sunxi_nfc_caps.

No functional change

Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
 drivers/mtd/nand/raw/sunxi_nand.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 80aafa4e1844..3912878e7645 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -155,7 +155,7 @@
 
 /* define bit use in NFC_ECC_ST */
 #define NFC_ECC_ERR(x)		BIT(x)
-#define NFC_ECC_ERR_MSK		GENMASK(15, 0)
+#define NFC_ECC_ERR_MSK(nfc)	(nfc->caps->ecc_err_mask)
 
 /*
  * define bit use in NFC_REG_PAT_FOUND
@@ -235,6 +235,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
  * @random_en_mask:	RANDOM_EN mask in NFC_ECC_CTL register
  * @random_dir_mask:	RANDOM_DIRECTION mask in NFC_ECC_CTL register
  * @ecc_mode_mask:	ECC_MODE mask in NFC_ECC_CTL register
+ * @ecc_err_mask:	NFC_ECC_ERR mask in NFC_ECC_ST register
  * @pat_found_mask:	ECC_PAT_FOUND mask in NFC_REG_PAT_FOUND register
  * @dma_maxburst:	DMA maxburst
  * @ecc_strengths:	Available ECC strengths array
@@ -252,6 +253,7 @@ struct sunxi_nfc_caps {
 	unsigned int random_en_mask;
 	unsigned int random_dir_mask;
 	unsigned int ecc_mode_mask;
+	unsigned int ecc_err_mask;
 	unsigned int pat_found_mask;
 	unsigned int dma_maxburst;
 	const u8 *ecc_strengths;
@@ -1030,7 +1032,7 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf
 		sunxi_nfc_hw_ecc_update_stats(nand, &max_bitflips, ret);
 	}
 
-	if (status & NFC_ECC_ERR_MSK) {
+	if (status & NFC_ECC_ERR_MSK(nfc)) {
 		for (i = 0; i < nchunks; i++) {
 			int data_off = i * ecc->size;
 			int oob_off = i * (ecc->bytes + 4);
@@ -2235,6 +2237,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
 	.random_en_mask = BIT(9),
 	.random_dir_mask = BIT(10),
 	.ecc_mode_mask = GENMASK(15, 12),
+	.ecc_err_mask = GENMASK(15, 0),
 	.pat_found_mask = GENMASK(31, 16),
 	.dma_maxburst = 4,
 	.ecc_strengths = sunxi_ecc_strengths_a10,
@@ -2253,6 +2256,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
 	.random_en_mask = BIT(9),
 	.random_dir_mask = BIT(10),
 	.ecc_mode_mask = GENMASK(15, 12),
+	.ecc_err_mask = GENMASK(15, 0),
 	.pat_found_mask = GENMASK(31, 16),
 	.dma_maxburst = 8,
 	.ecc_strengths = sunxi_ecc_strengths_a10,
-- 
2.47.3


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

* [PATCH 14/15] mtd: nand: sunxi: introduce sram_size in sunxi_nfc_caps
  2025-10-10  8:40 [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
                   ` (12 preceding siblings ...)
  2025-10-10  8:40 ` [PATCH 13/15] mtd: nand: sunxi: introduce ecc_err_mask " Richard Genoud
@ 2025-10-10  8:40 ` Richard Genoud
  2025-10-10  8:40 ` [PATCH 15/15] mtd: rawnand: sunxi: Add support for H616 nand controller Richard Genoud
  14 siblings, 0 replies; 33+ messages in thread
From: Richard Genoud @ 2025-10-10  8:40 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

The H6/H616 the SRAM is bigger than the A10/A23 one, so move its size
into sunxi_nfc_caps.

No functional change

Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
 drivers/mtd/nand/raw/sunxi_nand.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 3912878e7645..e81d74c6633a 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -167,8 +167,6 @@
 
 #define NFC_DEFAULT_TIMEOUT_MS	1000
 
-#define NFC_SRAM_SIZE		1024
-
 #define NFC_MAX_CS		7
 
 /**
@@ -240,6 +238,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
  * @dma_maxburst:	DMA maxburst
  * @ecc_strengths:	Available ECC strengths array
  * @nstrengths:		Size of @ecc_strengths
+ * @sram_size:		Size of the NAND controller SRAM
  */
 struct sunxi_nfc_caps {
 	bool has_mdma;
@@ -258,6 +257,7 @@ struct sunxi_nfc_caps {
 	unsigned int dma_maxburst;
 	const u8 *ecc_strengths;
 	unsigned int nstrengths;
+	int sram_size;
 };
 
 /**
@@ -495,7 +495,7 @@ static void sunxi_nfc_read_buf(struct nand_chip *nand, uint8_t *buf, int len)
 	while (len > offs) {
 		bool poll = false;
 
-		cnt = min(len - offs, NFC_SRAM_SIZE);
+		cnt = min(len - offs, nfc->caps->sram_size);
 
 		ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
 		if (ret)
@@ -533,7 +533,7 @@ static void sunxi_nfc_write_buf(struct nand_chip *nand, const uint8_t *buf,
 	while (len > offs) {
 		bool poll = false;
 
-		cnt = min(len - offs, NFC_SRAM_SIZE);
+		cnt = min(len - offs, nfc->caps->sram_size);
 
 		ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);
 		if (ret)
@@ -1861,7 +1861,7 @@ static int sunxi_nfc_exec_subop(struct nand_chip *nand,
 		case NAND_OP_DATA_OUT_INSTR:
 			start = nand_subop_get_data_start_off(subop, i);
 			remaining = nand_subop_get_data_len(subop, i);
-			cnt = min_t(u32, remaining, NFC_SRAM_SIZE);
+			cnt = min_t(u32, remaining, nfc->caps->sram_size);
 			cmd |= NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD;
 
 			if (instr->type == NAND_OP_DATA_OUT_INSTR) {
@@ -2242,6 +2242,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
 	.dma_maxburst = 4,
 	.ecc_strengths = sunxi_ecc_strengths_a10,
 	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
+	.sram_size = 1024,
 };
 
 static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
@@ -2261,6 +2262,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
 	.dma_maxburst = 8,
 	.ecc_strengths = sunxi_ecc_strengths_a10,
 	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
+	.sram_size = 1024,
 };
 
 static const struct of_device_id sunxi_nfc_ids[] = {
-- 
2.47.3


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

* [PATCH 15/15] mtd: rawnand: sunxi: Add support for H616 nand controller
  2025-10-10  8:40 [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
                   ` (13 preceding siblings ...)
  2025-10-10  8:40 ` [PATCH 14/15] mtd: nand: sunxi: introduce sram_size " Richard Genoud
@ 2025-10-10  8:40 ` Richard Genoud
  2025-10-11  1:00   ` kernel test robot
  2025-10-11 10:48   ` Jernej Škrabec
  14 siblings, 2 replies; 33+ messages in thread
From: Richard Genoud @ 2025-10-10  8:40 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

The H616 nand controller has the same base as A10/A23, with some
differences:
- mdma is based on chained buffers
- its ECC supports up to 80bit per 1024bytes
- some registers layouts are a bit different, mainly due do the stronger
  ECC.
- it uses USER_DATA_LEN registers along USER_DATA registers.
- it needs a specific clock for ECC and MBUS.

This patch introduce the basic support, without DMA/MDMA.

Tested on Whatsminer H616 board (with and without scrambling, ECC)

Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
 drivers/mtd/nand/raw/sunxi_nand.c | 182 ++++++++++++++++++++++++++++--
 1 file changed, 174 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index e81d74c6633a..1e1185f8d980 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -49,17 +49,40 @@
 #define NFC_REG_A23_IO_DATA	0x0300
 #define NFC_REG_ECC_CTL		0x0034
 #define NFC_REG_ECC_ST		0x0038
-#define NFC_REG_DEBUG		0x003C
+#define NFC_REG_H6_PAT_FOUND	0x003C
 #define NFC_REG_A10_ECC_ERR_CNT	0x0040
+#define NFC_REG_H6_ECC_ERR_CNT	0x0050
 #define NFC_REG_ECC_ERR_CNT(nfc, x)	((nfc->caps->reg_ecc_err_cnt + (x)) & ~0x3)
+#define NFC_REG_H6_RDATA_CTL	0x0044
+#define NFC_REG_H6_RDATA_0	0x0048
+#define NFC_REG_H6_RDATA_1	0x004C
 #define NFC_REG_A10_USER_DATA	0x0050
+#define NFC_REG_H6_USER_DATA	0x0080
 #define NFC_REG_USER_DATA(nfc, x)	(nfc->caps->reg_user_data + ((x) * 4))
+#define NFC_REG_H6_USER_DATA_LEN 0x0070
+/* A USER_DATA_LEN register can hold the length of 8 USER_DATA registers */
+#define NFC_REG_USER_DATA_LEN_CAPACITY 8
+#define NFC_REG_USER_DATA_LEN(nfc, step) \
+	 (nfc->caps->reg_user_data_len + \
+	 ((step) / NFC_REG_USER_DATA_LEN_CAPACITY) * 4)
 #define NFC_REG_SPARE_AREA(nfc) (nfc->caps->reg_spare_area)
 #define NFC_REG_A10_SPARE_AREA	0x00A0
 #define NFC_REG_PAT_ID(nfc) (nfc->caps->reg_pat_id)
 #define NFC_REG_A10_PAT_ID	0x00A4
 #define NFC_REG_MDMA_ADDR	0x00C0
 #define NFC_REG_MDMA_CNT	0x00C4
+#define NFC_REG_H6_EFNAND_STATUS 0x0110
+#define NFC_REG_H6_SPARE_AREA	0x0114
+#define NFC_REG_H6_PAT_ID	0x0118
+#define NFC_REG_H6_DDR2_SPEC_CTL 0x011C
+#define NFC_REG_H6_NDMA_MODE_CTL 0x0120
+#define NFC_REG_H6_MDMA_DLBA_REG 0x0200
+#define NFC_REG_H6_MDMA_STA	0x0204
+#define NFC_REG_H6_MDMA_INT_MAS	0x0208
+#define NFC_REG_H6_MDMA_DESC_ADDR 0x020C
+#define NFC_REG_H6_MDMA_BUF_ADDR 0x0210
+#define NFC_REG_H6_MDMA_CNT	0x0214
+
 #define NFC_RAM0_BASE		0x0400
 #define NFC_RAM1_BASE		0x0800
 
@@ -71,6 +94,7 @@
 #define NFC_BUS_WIDTH_16	(1 << 2)
 #define NFC_RB_SEL_MSK		BIT(3)
 #define NFC_RB_SEL(x)		((x) << 3)
+/* CE_SEL BIT 27 is meant to be used for GPIO chipselect */
 #define NFC_CE_SEL_MSK		GENMASK(26, 24)
 #define NFC_CE_SEL(x)		((x) << 24)
 #define NFC_CE_CTL		BIT(6)
@@ -89,6 +113,9 @@
 #define NFC_STA			BIT(4)
 #define NFC_NATCH_INT_FLAG	BIT(5)
 #define NFC_RB_STATE(x)		BIT(x + 8)
+#define NFC_RB_STATE_MSK	GENMASK(11, 8)
+#define NDFC_RDATA_STA_1	BIT(12)
+#define NDFC_RDATA_STA_0	BIT(13)
 
 /* define bit use in NFC_INT */
 #define NFC_B2R_INT_ENABLE	BIT(0)
@@ -100,6 +127,7 @@
 
 /* define bit use in NFC_TIMING_CTL */
 #define NFC_TIMING_CTL_EDO	BIT(8)
+#define NFC_TIMING_CTL_E_EDO	BIT(9)
 
 /* define NFC_TIMING_CFG register layout */
 #define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD)		\
@@ -107,9 +135,15 @@
 	(((tWHR) & 0x3) << 4) | (((tRHW) & 0x3) << 6) |		\
 	(((tCAD) & 0x7) << 8))
 
+#define NFC_TIMING_CFG2(tCDQSS, tSC, tCLHZ, tCSS, tWC)		\
+	((((tCDQSS) & 0x1) << 11) | (((tSC) & 0x3) << 12) |	\
+	 (((tCLHZ) & 0x3) << 14) | (((tCSS) & 0x3) << 16) |	\
+	 (((tWC) & 0x3) << 18))
+
 /* define bit use in NFC_CMD */
 #define NFC_CMD_LOW_BYTE_MSK	GENMASK(7, 0)
-#define NFC_CMD_HIGH_BYTE_MSK	GENMASK(15, 8)
+#define NFC_CMD_HIGH_BYTE_MSK	GENMASK(15, 8)  // 15-10 reserved on H6
+#define NFC_CMD_ADR_NUM_MSK	GENMASK(9, 8)
 #define NFC_CMD(x)		(x)
 #define NFC_ADR_NUM_MSK		GENMASK(18, 16)
 #define NFC_ADR_NUM(x)		(((x) - 1) << 16)
@@ -122,6 +156,7 @@
 #define NFC_SEQ			BIT(25)
 #define NFC_DATA_SWAP_METHOD	BIT(26)
 #define NFC_ROW_AUTO_INC	BIT(27)
+#define NFC_H6_SEND_RND_CMD2	BIT(27)
 #define NFC_SEND_CMD3		BIT(28)
 #define NFC_SEND_CMD4		BIT(29)
 #define NFC_CMD_TYPE_MSK	GENMASK(31, 30)
@@ -133,6 +168,7 @@
 #define NFC_READ_CMD_MSK	GENMASK(7, 0)
 #define NFC_RND_READ_CMD0_MSK	GENMASK(15, 8)
 #define NFC_RND_READ_CMD1_MSK	GENMASK(23, 16)
+#define NFC_RND_READ_CMD2_MSK	GENMASK(31, 24)
 
 /* define bit use in NFC_WCMD_SET */
 #define NFC_PROGRAM_CMD_MSK	GENMASK(7, 0)
@@ -150,6 +186,9 @@
 #define NFC_RANDOM_DIRECTION(nfc) (nfc->caps->random_dir_mask)
 #define NFC_ECC_MODE_MSK(nfc)	(nfc->caps->ecc_mode_mask)
 #define NFC_ECC_MODE(nfc, x)	field_prep(NFC_ECC_MODE_MSK(nfc), (x))
+/* RANDOM_PAGE_SIZE: 0: ECC block size  1: page size */
+#define NFC_A23_RANDOM_PAGE_SIZE	BIT(11)
+#define NFC_H6_RANDOM_PAGE_SIZE	BIT(7)
 #define NFC_RANDOM_SEED_MSK	GENMASK(30, 16)
 #define NFC_RANDOM_SEED(x)	((x) << 16)
 
@@ -165,6 +204,9 @@
 
 #define NFC_ECC_ERR_CNT(b, x)	(((x) >> (((b) % 4) * 8)) & 0xff)
 
+#define NFC_USER_DATA_LEN_MSK(step) \
+	(0xf << (((step) % NFC_REG_USER_DATA_LEN_CAPACITY) * 4))
+
 #define NFC_DEFAULT_TIMEOUT_MS	1000
 
 #define NFC_MAX_CS		7
@@ -224,9 +266,11 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
  * @has_mdma:		Use mbus dma mode, otherwise general dma
  *			through MBUS on A23/A33 needs extra configuration.
  * @has_ecc_block_512:	If the ECC can handle 512B or only 1024B chuncks
+ * @has_mbus_clk:	If the controller needs a mbus clock.
  * @reg_io_data:	I/O data register
  * @reg_ecc_err_cnt:	ECC error counter register
  * @reg_user_data:	User data register
+ * @reg_user_data_len:	User data length register
  * @reg_spare_area:	Spare Area Register
  * @reg_pat_id:		Pattern ID Register
  * @reg_pat_found:	Data Pattern Status Register
@@ -238,14 +282,23 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
  * @dma_maxburst:	DMA maxburst
  * @ecc_strengths:	Available ECC strengths array
  * @nstrengths:		Size of @ecc_strengths
+ * @max_ecc_steps:	Maximum supported steps for ECC, this is also the
+ *			number of user data registers
+ * @user_data_len_tab:  Table of lenghts supported by USER_DATA_LEN register
+ *			The table index is the value to set in NFC_USER_DATA_LEN
+ *			registers, and the corresponding value is the number of
+ *			bytes to write
+ * @nuser_data_tab:	Size of @user_data_len_tab
  * @sram_size:		Size of the NAND controller SRAM
  */
 struct sunxi_nfc_caps {
 	bool has_mdma;
 	bool has_ecc_block_512;
+	bool has_mbus_clk;
 	unsigned int reg_io_data;
 	unsigned int reg_ecc_err_cnt;
 	unsigned int reg_user_data;
+	unsigned int reg_user_data_len;
 	unsigned int reg_spare_area;
 	unsigned int reg_pat_id;
 	unsigned int reg_pat_found;
@@ -257,6 +310,9 @@ struct sunxi_nfc_caps {
 	unsigned int dma_maxburst;
 	const u8 *ecc_strengths;
 	unsigned int nstrengths;
+	const u8 *user_data_len_tab;
+	unsigned int nuser_data_tab;
+	unsigned int max_ecc_steps;
 	int sram_size;
 };
 
@@ -268,6 +324,7 @@ struct sunxi_nfc_caps {
  * @regs: NAND controller registers
  * @ahb_clk: NAND controller AHB clock
  * @mod_clk: NAND controller mod clock
+ * @ecc_clk: NAND controller ECC clock
  * @reset: NAND controller reset line
  * @assigned_cs: bitmask describing already assigned CS lines
  * @clk_rate: NAND controller current clock rate
@@ -282,7 +339,9 @@ struct sunxi_nfc {
 	struct device *dev;
 	void __iomem *regs;
 	struct clk *ahb_clk;
+	struct clk *mbus_clk;
 	struct clk *mod_clk;
+	struct clk *ecc_clk;
 	struct reset_control *reset;
 	unsigned long assigned_cs;
 	unsigned long clk_rate;
@@ -764,6 +823,53 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob,
 		sunxi_nfc_randomize_bbm(nand, page, oob);
 }
 
+/*
+ * On H6/H6 the user_data length has to be set in specific registers
+ * before writing.
+ */
+static void sunxi_nfc_reset_user_data_len(struct sunxi_nfc *nfc)
+{
+	int loop_step = NFC_REG_USER_DATA_LEN_CAPACITY;
+
+	/* not all SoCs have this register */
+	if (!nfc->caps->reg_user_data_len)
+		return;
+
+	for (int i = 0; i < nfc->caps->max_ecc_steps; i += loop_step)
+		writel(0, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, i));
+}
+
+static void sunxi_nfc_set_user_data_len(struct sunxi_nfc *nfc,
+					int len, int step)
+{
+	bool found = false;
+	u32 val;
+	int i;
+
+	/* not all SoCs have this register */
+	if (!nfc->caps->reg_user_data_len)
+		return;
+
+	for (i = 0; i < nfc->caps->nuser_data_tab; i++) {
+		if (len == nfc->caps->user_data_len_tab[i]) {
+			found = true;
+			break;
+		}
+	}
+
+	if (!found) {
+		dev_warn(nfc->dev,
+			 "Unsupported length for user data reg: %d\n", len);
+		return;
+	}
+
+	val = readl(nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step));
+
+	val &= ~NFC_USER_DATA_LEN_MSK(step);
+	val |= field_prep(NFC_USER_DATA_LEN_MSK(step), i);
+	writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step));
+}
+
 static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand,
 						const u8 *oob, int step,
 						bool bbm, int page)
@@ -858,6 +964,8 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand,
 	if (ret)
 		return ret;
 
+	sunxi_nfc_reset_user_data_len(nfc);
+	sunxi_nfc_set_user_data_len(nfc, 4, 0);
 	sunxi_nfc_randomizer_config(nand, page, false);
 	sunxi_nfc_randomizer_enable(nand);
 	writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
@@ -968,6 +1076,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf
 		return ret;
 
 	sunxi_nfc_hw_ecc_enable(nand);
+	sunxi_nfc_reset_user_data_len(nfc);
+	sunxi_nfc_set_user_data_len(nfc, 4, 0);
 	sunxi_nfc_randomizer_config(nand, page, false);
 	sunxi_nfc_randomizer_enable(nand);
 
@@ -1100,6 +1210,8 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand,
 
 	sunxi_nfc_randomizer_config(nand, page, false);
 	sunxi_nfc_randomizer_enable(nand);
+	sunxi_nfc_reset_user_data_len(nfc);
+	sunxi_nfc_set_user_data_len(nfc, 4, 0);
 	sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, 0, bbm, page);
 
 	writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
@@ -1344,10 +1456,12 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand,
 	if (ret)
 		goto pio_fallback;
 
+	sunxi_nfc_reset_user_data_len(nfc);
 	for (i = 0; i < ecc->steps; i++) {
 		const u8 *oob = nand->oob_poi + (i * (ecc->bytes + 4));
 
 		sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page);
+		sunxi_nfc_set_user_data_len(nfc, 4, i);
 	}
 
 	nand_prog_page_begin_op(nand, page, 0, NULL, 0);
@@ -2148,18 +2262,36 @@ static int sunxi_nfc_probe(struct platform_device *pdev)
 	if (irq < 0)
 		return irq;
 
+	nfc->caps = of_device_get_match_data(dev);
+	if (!nfc->caps)
+		return -EINVAL;
+
 	nfc->ahb_clk = devm_clk_get_enabled(dev, "ahb");
 	if (IS_ERR(nfc->ahb_clk)) {
 		dev_err(dev, "failed to retrieve ahb clk\n");
 		return PTR_ERR(nfc->ahb_clk);
 	}
 
+	if (nfc->caps->has_mbus_clk) {
+		nfc->mbus_clk = devm_clk_get_enabled(dev, "mbus");
+		if (IS_ERR(nfc->mbus_clk)) {
+			dev_err(dev, "No mbus clock specified\n");
+			return PTR_ERR(nfc->mbus_clk);
+		}
+	}
+
 	nfc->mod_clk = devm_clk_get_enabled(dev, "mod");
 	if (IS_ERR(nfc->mod_clk)) {
 		dev_err(dev, "failed to retrieve mod clk\n");
 		return PTR_ERR(nfc->mod_clk);
 	}
 
+	nfc->ecc_clk = devm_clk_get_optional_enabled(dev, "ecc");
+	if (IS_ERR(nfc->ecc_clk)) {
+		dev_err(dev, "failed to retrieve ecc clk\n");
+		return PTR_ERR(nfc->ecc_clk);
+	}
+
 	nfc->reset = devm_reset_control_get_optional_exclusive(dev, "ahb");
 	if (IS_ERR(nfc->reset))
 		return PTR_ERR(nfc->reset);
@@ -2170,12 +2302,6 @@ static int sunxi_nfc_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	nfc->caps = of_device_get_match_data(&pdev->dev);
-	if (!nfc->caps) {
-		ret = -EINVAL;
-		goto out_ahb_reset_reassert;
-	}
-
 	ret = sunxi_nfc_rst(nfc);
 	if (ret)
 		goto out_ahb_reset_reassert;
@@ -2226,8 +2352,17 @@ static const u8 sunxi_ecc_strengths_a10[] = {
 	16, 24, 28, 32, 40, 48, 56, 60, 64
 };
 
+static const u8 sunxi_ecc_strengths_h6[] = {
+	16, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80
+};
+
+static const u8 sunxi_user_data_len_h6[] = {
+	0, 4, 8, 12, 16, 20, 24, 28, 32
+};
+
 static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
 	.has_ecc_block_512 = true,
+	.has_mbus_clk = false,
 	.reg_io_data = NFC_REG_A10_IO_DATA,
 	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
 	.reg_user_data = NFC_REG_A10_USER_DATA,
@@ -2242,11 +2377,13 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
 	.dma_maxburst = 4,
 	.ecc_strengths = sunxi_ecc_strengths_a10,
 	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
+	.max_ecc_steps = 16,
 	.sram_size = 1024,
 };
 
 static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
 	.has_mdma = true,
+	.has_mbus_clk = false,
 	.has_ecc_block_512 = true,
 	.reg_io_data = NFC_REG_A23_IO_DATA,
 	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
@@ -2262,9 +2399,34 @@ static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
 	.dma_maxburst = 8,
 	.ecc_strengths = sunxi_ecc_strengths_a10,
 	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
+	.max_ecc_steps = 16,
 	.sram_size = 1024,
 };
 
+static const struct sunxi_nfc_caps sunxi_nfc_h616_caps = {
+	.has_mdma = false, // H6 supports only chained descriptors
+	.has_mbus_clk = true,
+	.reg_io_data = NFC_REG_A23_IO_DATA,
+	.reg_ecc_err_cnt = NFC_REG_H6_ECC_ERR_CNT,
+	.reg_user_data = NFC_REG_H6_USER_DATA,
+	.reg_user_data_len = NFC_REG_H6_USER_DATA_LEN,
+	.reg_spare_area = NFC_REG_H6_SPARE_AREA,
+	.reg_pat_id = NFC_REG_H6_PAT_ID,
+	.reg_pat_found = NFC_REG_H6_PAT_FOUND,
+	.random_en_mask = BIT(5),
+	.random_dir_mask = BIT(6),
+	.ecc_mode_mask = GENMASK(15, 8),
+	.ecc_err_mask = GENMASK(31, 0),
+	.pat_found_mask = GENMASK(31, 0),
+	.dma_maxburst = 8,
+	.ecc_strengths = sunxi_ecc_strengths_h6,
+	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_h6),
+	.user_data_len_tab = sunxi_user_data_len_h6,
+	.nuser_data_tab = ARRAY_SIZE(sunxi_user_data_len_h6),
+	.max_ecc_steps = 32,
+	.sram_size = 8192,
+};
+
 static const struct of_device_id sunxi_nfc_ids[] = {
 	{
 		.compatible = "allwinner,sun4i-a10-nand",
@@ -2274,6 +2436,10 @@ static const struct of_device_id sunxi_nfc_ids[] = {
 		.compatible = "allwinner,sun8i-a23-nand-controller",
 		.data = &sunxi_nfc_a23_caps,
 	},
+	{
+		.compatible = "allwinner,sun50i-h616-nand-controller",
+		.data = &sunxi_nfc_h616_caps,
+	},
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sunxi_nfc_ids);
-- 
2.47.3


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

* Re: [PATCH 02/15] dt-bindings: mtd: sunxi: Add new compatible
  2025-10-10  8:40 ` [PATCH 02/15] dt-bindings: mtd: sunxi: Add new compatible Richard Genoud
@ 2025-10-10  8:45   ` Krzysztof Kozlowski
  2025-10-10 10:16     ` Richard GENOUD
  2025-10-10  8:49   ` Krzysztof Kozlowski
  1 sibling, 1 reply; 33+ messages in thread
From: Krzysztof Kozlowski @ 2025-10-10  8:45 UTC (permalink / raw)
  To: Richard Genoud, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel

On 10/10/2025 10:40, Richard Genoud wrote:
> The H616 NAND controller is quite different from the A10 and A23 ones,
> some registers offset changed, and some new one are introduced.
> Also, the DMA handling is different (it uses chained descriptors)
> 


Subject: not new compatible, but "H616" or whatever device is called.
Otherwise every commit would be called like that making git log
--oneline useless.

> So, introduce a new compatible to represent this version of the IP.
> 
> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
> ---
>  .../mtd/allwinner,sun4i-a10-nand.yaml         | 56 ++++++++++++++-----
>  1 file changed, 43 insertions(+), 13 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml b/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
> index 054b6b8bf9b9..cc63091fe936 100644
> --- a/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
> +++ b/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
> @@ -6,34 +6,64 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
>  
>  title: Allwinner A10 NAND Controller
>  
> -allOf:
> -  - $ref: nand-controller.yaml
> -
>  maintainers:
>    - Chen-Yu Tsai <wens@csie.org>
>    - Maxime Ripard <mripard@kernel.org>
>  
> +allOf:
> +  - $ref: nand-controller.yaml


If moving it, can you place it like in example-schema, so at the bottom,
above unevaluatedProps?

> +
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            enum:
> +              - allwinner,sun4i-a10-nand
> +              - allwinner,sun8i-a23-nand-controller
> +    then:
> +      properties:
> +        clocks:
> +          items:
> +            - description: Bus Clock
> +            - description: Module Clock
> +        clock-names:
> +          items:
> +            - const: ahb
> +            - const: mod
> +
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            enum:
> +              - allwinner,sun50i-h616-nand-controller
> +    then:
> +      properties:
> +        clocks:
> +          items:
> +            - description: Bus Clock
> +            - description: Module Clock
> +            - description: ECC Clock
> +            - description: MBus Clock
> +        clock-names:
> +          items:
> +            - const: ahb
> +            - const: mod
> +            - const: ecc
> +            - const: mbus
> +
>  properties:
>    compatible:
>      enum:
>        - allwinner,sun4i-a10-nand
>        - allwinner,sun8i-a23-nand-controller
> +      - allwinner,sun50i-h616-nand-controller
>    reg:
>      maxItems: 1
>  
>    interrupts:
>      maxItems: 1
>  
> -  clocks:
> -    items:
> -      - description: Bus Clock
> -      - description: Module Clock
> -
> -  clock-names:
> -    items:
> -      - const: ahb
> -      - const: mod


You cannot remove it. Broadest constraints, see writing schema.

or my standard reference example:
https://elixir.bootlin.com/linux/v6.11-rc6/source/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml#L127


Best regards,
Krzysztof

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

* Re: [PATCH 03/15] arm64: dts: allwinner: h616: add NAND controller
  2025-10-10  8:40 ` [PATCH 03/15] arm64: dts: allwinner: h616: add NAND controller Richard Genoud
@ 2025-10-10  8:47   ` Krzysztof Kozlowski
  2025-10-10 10:22     ` Richard GENOUD
  2025-10-11 10:33   ` Jernej Škrabec
  1 sibling, 1 reply; 33+ messages in thread
From: Krzysztof Kozlowski @ 2025-10-10  8:47 UTC (permalink / raw)
  To: Richard Genoud, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel

On 10/10/2025 10:40, Richard Genoud wrote:
> The H616 has a NAND controller quite similar to the A10/A23 ones, but
> with some register differences, more clocks (for ECC and MBUS), more ECC
> strengths, so this requires a new compatible string.
> 
> This patch adds the NAND controller node and pins in the device tree.


Please do not use "This commit/patch/change", but imperative mood. See
longer explanation here:
https://elixir.bootlin.com/linux/v6.16/source/Documentation/process/submitting-patches.rst#L94

> 
> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
> ---

Confusing order of patches. Driver code cannot depend on DTS.

See submitting patches in DT. It is VERY explicit about it. Please also
read maintainer soc profile.

Best regards,
Krzysztof

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

* Re: [PATCH 02/15] dt-bindings: mtd: sunxi: Add new compatible
  2025-10-10  8:40 ` [PATCH 02/15] dt-bindings: mtd: sunxi: Add new compatible Richard Genoud
  2025-10-10  8:45   ` Krzysztof Kozlowski
@ 2025-10-10  8:49   ` Krzysztof Kozlowski
  2025-10-10 10:18     ` Richard GENOUD
  1 sibling, 1 reply; 33+ messages in thread
From: Krzysztof Kozlowski @ 2025-10-10  8:49 UTC (permalink / raw)
  To: Richard Genoud, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel

On 10/10/2025 10:40, Richard Genoud wrote:
> +
>  properties:
>    compatible:
>      enum:
>        - allwinner,sun4i-a10-nand
>        - allwinner,sun8i-a23-nand-controller
> +      - allwinner,sun50i-h616-nand-controller


Also:
1. missing new line - why did you remove it?
2. Keep existing sunxi preferred order of entries. In other platforms it
is alphanumerical, not natural. In case sunxi uses something else, just
be sure you use sunxi order.

Best regards,
Krzysztof

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

* Re: [PATCH 02/15] dt-bindings: mtd: sunxi: Add new compatible
  2025-10-10  8:45   ` Krzysztof Kozlowski
@ 2025-10-10 10:16     ` Richard GENOUD
  0 siblings, 0 replies; 33+ messages in thread
From: Richard GENOUD @ 2025-10-10 10:16 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel

Hi Krzysztof,

Le 10/10/2025 à 10:45, Krzysztof Kozlowski a écrit :
> On 10/10/2025 10:40, Richard Genoud wrote:
>> The H616 NAND controller is quite different from the A10 and A23 ones,
>> some registers offset changed, and some new one are introduced.
>> Also, the DMA handling is different (it uses chained descriptors)
>>
> 
> 
> Subject: not new compatible, but "H616" or whatever device is called.
> Otherwise every commit would be called like that making git log
> --oneline useless.
Indeed.

> 
>> So, introduce a new compatible to represent this version of the IP.
>>
>> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
>> ---
>>   .../mtd/allwinner,sun4i-a10-nand.yaml         | 56 ++++++++++++++-----
>>   1 file changed, 43 insertions(+), 13 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml b/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
>> index 054b6b8bf9b9..cc63091fe936 100644
>> --- a/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
>> +++ b/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
>> @@ -6,34 +6,64 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
>>   
>>   title: Allwinner A10 NAND Controller
>>   
>> -allOf:
>> -  - $ref: nand-controller.yaml
>> -
>>   maintainers:
>>     - Chen-Yu Tsai <wens@csie.org>
>>     - Maxime Ripard <mripard@kernel.org>
>>   
>> +allOf:
>> +  - $ref: nand-controller.yaml
> 
> 
> If moving it, can you place it like in example-schema, so at the bottom,
> above unevaluatedProps?
Yes, absolutely.

> 
>> +
>> +  - if:
>> +      properties:
>> +        compatible:
>> +          contains:
>> +            enum:
>> +              - allwinner,sun4i-a10-nand
>> +              - allwinner,sun8i-a23-nand-controller
>> +    then:
>> +      properties:
>> +        clocks:
>> +          items:
>> +            - description: Bus Clock
>> +            - description: Module Clock
>> +        clock-names:
>> +          items:
>> +            - const: ahb
>> +            - const: mod
>> +
>> +  - if:
>> +      properties:
>> +        compatible:
>> +          contains:
>> +            enum:
>> +              - allwinner,sun50i-h616-nand-controller
>> +    then:
>> +      properties:
>> +        clocks:
>> +          items:
>> +            - description: Bus Clock
>> +            - description: Module Clock
>> +            - description: ECC Clock
>> +            - description: MBus Clock
>> +        clock-names:
>> +          items:
>> +            - const: ahb
>> +            - const: mod
>> +            - const: ecc
>> +            - const: mbus
>> +
>>   properties:
>>     compatible:
>>       enum:
>>         - allwinner,sun4i-a10-nand
>>         - allwinner,sun8i-a23-nand-controller
>> +      - allwinner,sun50i-h616-nand-controller
>>     reg:
>>       maxItems: 1
>>   
>>     interrupts:
>>       maxItems: 1
>>   
>> -  clocks:
>> -    items:
>> -      - description: Bus Clock
>> -      - description: Module Clock
>> -
>> -  clock-names:
>> -    items:
>> -      - const: ahb
>> -      - const: mod
> 
> 
> You cannot remove it. Broadest constraints, see writing schema.
> 
> or my standard reference example:
> https://elixir.bootlin.com/linux/v6.11-rc6/source/Documentation/devicetree/bindings/ufs/qcom,ufs.yaml#L127
Ok

Thanks!

> 
> 
> Best regards,
> Krzysztof


-- 
Richard Genoud, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

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

* Re: [PATCH 02/15] dt-bindings: mtd: sunxi: Add new compatible
  2025-10-10  8:49   ` Krzysztof Kozlowski
@ 2025-10-10 10:18     ` Richard GENOUD
  2025-10-11 10:27       ` Jernej Škrabec
  0 siblings, 1 reply; 33+ messages in thread
From: Richard GENOUD @ 2025-10-10 10:18 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel

Le 10/10/2025 à 10:49, Krzysztof Kozlowski a écrit :
> On 10/10/2025 10:40, Richard Genoud wrote:
>> +
>>   properties:
>>     compatible:
>>       enum:
>>         - allwinner,sun4i-a10-nand
>>         - allwinner,sun8i-a23-nand-controller
>> +      - allwinner,sun50i-h616-nand-controller
> 
> 
> Also:
> 1. missing new line - why did you remove it?
> 2. Keep existing sunxi preferred order of entries. In other platforms it
> is alphanumerical, not natural. In case sunxi uses something else, just
> be sure you use sunxi order.
ok, make sens

Thanks!

> 
> Best regards,
> Krzysztof


-- 
Richard Genoud, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

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

* Re: [PATCH 03/15] arm64: dts: allwinner: h616: add NAND controller
  2025-10-10  8:47   ` Krzysztof Kozlowski
@ 2025-10-10 10:22     ` Richard GENOUD
  2025-10-10 10:24       ` Krzysztof Kozlowski
  0 siblings, 1 reply; 33+ messages in thread
From: Richard GENOUD @ 2025-10-10 10:22 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel

Le 10/10/2025 à 10:47, Krzysztof Kozlowski a écrit :
> On 10/10/2025 10:40, Richard Genoud wrote:
>> The H616 has a NAND controller quite similar to the A10/A23 ones, but
>> with some register differences, more clocks (for ECC and MBUS), more ECC
>> strengths, so this requires a new compatible string.
>>
>> This patch adds the NAND controller node and pins in the device tree.
> 
> 
> Please do not use "This commit/patch/change", but imperative mood. See
> longer explanation here:
> https://elixir.bootlin.com/linux/v6.16/source/Documentation/process/submitting-patches.rst#L94
You're right, I'll reformulate that.


> 
>>
>> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
>> ---
> 
> Confusing order of patches. Driver code cannot depend on DTS.
> 
> See submitting patches in DT. It is VERY explicit about it. Please also
> read maintainer soc profile.
Indeed, it's quite explicit in
Documentation/devicetree/bindings/submitting-patches.rst
Sorry for that.

But I don't know what you are referring to as "maintainer soc profile"
I guess soc here doesn't stand for system on chip :)

Thanks!

> 
> Best regards,
> Krzysztof


-- 
Richard Genoud, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

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

* Re: [PATCH 03/15] arm64: dts: allwinner: h616: add NAND controller
  2025-10-10 10:22     ` Richard GENOUD
@ 2025-10-10 10:24       ` Krzysztof Kozlowski
  0 siblings, 0 replies; 33+ messages in thread
From: Krzysztof Kozlowski @ 2025-10-10 10:24 UTC (permalink / raw)
  To: Richard GENOUD, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel

On 10/10/2025 12:22, Richard GENOUD wrote:
>>> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
>>> ---
>>
>> Confusing order of patches. Driver code cannot depend on DTS.
>>
>> See submitting patches in DT. It is VERY explicit about it. Please also
>> read maintainer soc profile.
> Indeed, it's quite explicit in
> Documentation/devicetree/bindings/submitting-patches.rst
> Sorry for that.
> 
> But I don't know what you are referring to as "maintainer soc profile"
> I guess soc here doesn't stand for system on chip :)

Here:

Documentation/process/maintainer-soc.rst

Best regards,
Krzysztof

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

* Re: [PATCH 15/15] mtd: rawnand: sunxi: Add support for H616 nand controller
  2025-10-10  8:40 ` [PATCH 15/15] mtd: rawnand: sunxi: Add support for H616 nand controller Richard Genoud
@ 2025-10-11  1:00   ` kernel test robot
  2025-10-11 10:48   ` Jernej Škrabec
  1 sibling, 0 replies; 33+ messages in thread
From: kernel test robot @ 2025-10-11  1:00 UTC (permalink / raw)
  To: Richard Genoud, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Jernej Skrabec, Samuel Holland
  Cc: llvm, oe-kbuild-all, Wentao Liang, Uwe Kleine-König,
	Maxime Ripard, Thomas Petazzoni, linux-mtd, devicetree,
	linux-arm-kernel, linux-sunxi, linux-kernel, Richard Genoud

Hi Richard,

kernel test robot noticed the following build warnings:

[auto build test WARNING on mtd/nand/next]
[also build test WARNING on mtd/mtd/next mtd/mtd/fixes sunxi/sunxi/for-next robh/for-next linus/master v6.17 next-20251010]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Richard-Genoud/mtd-rawnand-sunxi-Remove-superfluous-register-readings/20251010-164637
base:   https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git nand/next
patch link:    https://lore.kernel.org/r/20251010084042.341224-16-richard.genoud%40bootlin.com
patch subject: [PATCH 15/15] mtd: rawnand: sunxi: Add support for H616 nand controller
config: riscv-randconfig-002-20251011 (https://download.01.org/0day-ci/archive/20251011/202510110828.Xb6hqQvx-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 39f292ffa13d7ca0d1edff27ac8fd55024bb4d19)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251011/202510110828.Xb6hqQvx-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/202510110828.Xb6hqQvx-lkp@intel.com/

All warnings (new ones prefixed by >>):

>> Warning: drivers/mtd/nand/raw/sunxi_nand.c:351 struct member 'mbus_clk' not described in 'sunxi_nfc'

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

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

* Re: [PATCH 01/15] mtd: rawnand: sunxi: Remove superfluous register readings
  2025-10-10  8:40 ` [PATCH 01/15] mtd: rawnand: sunxi: Remove superfluous register readings Richard Genoud
@ 2025-10-11 10:15   ` Jernej Škrabec
  0 siblings, 0 replies; 33+ messages in thread
From: Jernej Škrabec @ 2025-10-11 10:15 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Samuel Holland, Richard Genoud
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

Dne petek, 10. oktober 2025 ob 10:40:28 Srednjeevropski poletni čas je Richard Genoud napisal(a):
> The register NFC_REG_ECC_CTL was read twice and the result was not used,
> then a third time with a mask applied.
> Removing those calls didn't change the behavior.
> 
> Tested on H616 SoC, scrambling enabled.
> 
> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>

Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>

Best regards,
Jernej



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

* Re: [PATCH 02/15] dt-bindings: mtd: sunxi: Add new compatible
  2025-10-10 10:18     ` Richard GENOUD
@ 2025-10-11 10:27       ` Jernej Škrabec
  2025-10-13 11:56         ` Richard GENOUD
  0 siblings, 1 reply; 33+ messages in thread
From: Jernej Škrabec @ 2025-10-11 10:27 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Samuel Holland, Richard GENOUD
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel

Hi,

Dne petek, 10. oktober 2025 ob 12:18:56 Srednjeevropski poletni čas je Richard GENOUD napisal(a):
> Le 10/10/2025 à 10:49, Krzysztof Kozlowski a écrit :
> > On 10/10/2025 10:40, Richard Genoud wrote:
> >> +
> >>   properties:
> >>     compatible:
> >>       enum:
> >>         - allwinner,sun4i-a10-nand
> >>         - allwinner,sun8i-a23-nand-controller
> >> +      - allwinner,sun50i-h616-nand-controller
> > 
> > 
> > Also:
> > 1. missing new line - why did you remove it?
> > 2. Keep existing sunxi preferred order of entries. In other platforms it
> > is alphanumerical, not natural. In case sunxi uses something else, just
> > be sure you use sunxi order.

Sunxi order is from oldest generation to newest and then alphabetically
by soc name.

This is already correctly ordered.

Best regards,
Jernej

> ok, make sens
> 
> Thanks!
> 
> > 
> > Best regards,
> > Krzysztof
> 
> 
> 





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

* Re: [PATCH 03/15] arm64: dts: allwinner: h616: add NAND controller
  2025-10-10  8:40 ` [PATCH 03/15] arm64: dts: allwinner: h616: add NAND controller Richard Genoud
  2025-10-10  8:47   ` Krzysztof Kozlowski
@ 2025-10-11 10:33   ` Jernej Škrabec
  2025-10-13 11:59     ` Richard GENOUD
  1 sibling, 1 reply; 33+ messages in thread
From: Jernej Škrabec @ 2025-10-11 10:33 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Samuel Holland, Richard Genoud
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

Dne petek, 10. oktober 2025 ob 10:40:30 Srednjeevropski poletni čas je Richard Genoud napisal(a):
> The H616 has a NAND controller quite similar to the A10/A23 ones, but
> with some register differences, more clocks (for ECC and MBUS), more ECC
> strengths, so this requires a new compatible string.
> 
> This patch adds the NAND controller node and pins in the device tree.
> 
> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
> ---
>  .../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 50 +++++++++++++++++++
>  1 file changed, 50 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
> index ceedae9e399b..60626eba7f7c 100644
> --- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
> +++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
> @@ -278,6 +278,37 @@ ir_rx_pin: ir-rx-pin {
>  				function = "ir_rx";
>  			};
>  
> +			nand_pins: nand-pins {
> +				pins = "PC0", "PC1", "PC2", "PC5", "PC8", "PC9",
> +				       "PC10", "PC11", "PC12", "PC13", "PC14",
> +				       "PC15", "PC16";
> +				function = "nand0";
> +			};
> +
> +			nand_cs0_pin: nand-cs0-pin {
> +				pins = "PC4";
> +				function = "nand0";
> +				bias-pull-up;
> +			};
> +
> +			nand_cs1_pin: nand-cs1-pin {
> +				pins = "PC3";
> +				function = "nand0";
> +				bias-pull-up;
> +			};
> +
> +			nand_rb0_pin: nand-rb0-pin {
> +				pins = "PC6";
> +				function = "nand0";
> +				bias-pull-up;
> +			};
> +
> +			nand_rb1_pin: nand-rb1-pin {
> +				pins = "PC7";
> +				function = "nand0";
> +				bias-pull-up;
> +			};
> +
>  			mmc0_pins: mmc0-pins {
>  				pins = "PF0", "PF1", "PF2", "PF3",
>  				       "PF4", "PF5";
> @@ -440,6 +471,25 @@ mmc2: mmc@4022000 {
>  			#size-cells = <0>;
>  		};
>  
> +		nfc: nand-controller@4011000 {

Nodes are sorted by memory address. So this one should be moved before
mmc2 and possibly others.

> +			compatible = "allwinner,sun50i-h616-nand-controller";
> +			reg = <0x04011000 0x1000>;
> +			interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
> +			clocks = <&ccu CLK_BUS_NAND>, <&ccu CLK_NAND0>,
> +				<&ccu CLK_NAND1>, <&ccu CLK_MBUS_NAND>;
> +			clock-names = "ahb", "mod", "ecc", "mbus";
> +			resets = <&ccu RST_BUS_NAND>;
> +			reset-names = "ahb";
> +			dmas = <&dma 10>;
> +			dma-names = "rxtx";
> +			pinctrl-names = "default";
> +			pinctrl-0 = <&nand_pins>, <&nand_cs0_pin>,
> +				<&nand_cs1_pin>, <&nand_rb0_pin>,
> +				<&nand_rb1_pin>;

Are you sure that each nand device will use exactly this pin configuration?
IIUC, not all chips will have two CS and two RB pins. If so, pinctrl nodes
should be moved to device DT and pins subnodes should be marked with
/omit-if-no-ref/.

Best regards,
Jernej

> +			#address-cells = <1>;
> +			#size-cells = <0>;
> +		};
> +
>  		uart0: serial@5000000 {
>  			compatible = "snps,dw-apb-uart";
>  			reg = <0x05000000 0x400>;
> 





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

* Re: [PATCH 04/15] mtd: nand: sunxi: move ecc strenghts in sunxi_nfc_caps
  2025-10-10  8:40 ` [PATCH 04/15] mtd: nand: sunxi: move ecc strenghts in sunxi_nfc_caps Richard Genoud
@ 2025-10-11 10:41   ` Jernej Škrabec
  2025-10-13 12:00     ` Richard GENOUD
  0 siblings, 1 reply; 33+ messages in thread
From: Jernej Škrabec @ 2025-10-11 10:41 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Samuel Holland, Richard Genoud
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

Hi!

Dne petek, 10. oktober 2025 ob 10:40:31 Srednjeevropski poletni čas je Richard Genoud napisal(a):
> H6/H616 has more ecc strenghts.
> This commit prepares the change.
> No functional change.

Format looks weird. Reword message to something like moving ecc to caps which
will allow expand support for newer cores.

Also, there should be empty line before "No functional change."

Best regards,
Jernej

> 
> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
> ---
>  drivers/mtd/nand/raw/sunxi_nand.c | 20 ++++++++++++++++----
>  1 file changed, 16 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
> index 10a48e0d361f..198dd40f9220 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
> @@ -213,11 +213,15 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
>   *			through MBUS on A23/A33 needs extra configuration.
>   * @reg_io_data:	I/O data register
>   * @dma_maxburst:	DMA maxburst
> + * @ecc_strengths:	Available ECC strengths array
> + * @nstrengths:		Size of @ecc_strengths
>   */
>  struct sunxi_nfc_caps {
>  	bool has_mdma;
>  	unsigned int reg_io_data;
>  	unsigned int dma_maxburst;
> +	const u8 *ecc_strengths;
> +	unsigned int nstrengths;
>  };
>  
>  /**
> @@ -1619,9 +1623,9 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
>  				       struct nand_ecc_ctrl *ecc,
>  				       struct device_node *np)
>  {
> -	static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
>  	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
>  	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
> +	const u8 *strengths = nfc->caps->ecc_strengths;
>  	struct mtd_info *mtd = nand_to_mtd(nand);
>  	struct nand_device *nanddev = mtd_to_nanddev(mtd);
>  	int nsectors;
> @@ -1645,7 +1649,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
>  
>  		ecc->strength = bytes * 8 / fls(8 * ecc->size);
>  
> -		for (i = 0; i < ARRAY_SIZE(strengths); i++) {
> +		for (i = 0; i < nfc->caps->nstrengths; i++) {
>  			if (strengths[i] > ecc->strength)
>  				break;
>  		}
> @@ -1666,7 +1670,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
>  	}
>  
>  	/* Add ECC info retrieval from DT */
> -	for (i = 0; i < ARRAY_SIZE(strengths); i++) {
> +	for (i = 0; i < nfc->caps->nstrengths; i++) {
>  		if (ecc->strength <= strengths[i]) {
>  			/*
>  			 * Update ecc->strength value with the actual strength
> @@ -1677,7 +1681,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
>  		}
>  	}
>  
> -	if (i >= ARRAY_SIZE(strengths)) {
> +	if (i >= nfc->caps->nstrengths) {
>  		dev_err(nfc->dev, "unsupported strength\n");
>  		return -ENOTSUPP;
>  	}
> @@ -2167,15 +2171,23 @@ static void sunxi_nfc_remove(struct platform_device *pdev)
>  		dma_release_channel(nfc->dmac);
>  }
>  
> +static const u8 sunxi_ecc_strengths_a10[] = {
> +	16, 24, 28, 32, 40, 48, 56, 60, 64
> +};
> +
>  static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
>  	.reg_io_data = NFC_REG_A10_IO_DATA,
>  	.dma_maxburst = 4,
> +	.ecc_strengths = sunxi_ecc_strengths_a10,
> +	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
>  };
>  
>  static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
>  	.has_mdma = true,
>  	.reg_io_data = NFC_REG_A23_IO_DATA,
>  	.dma_maxburst = 8,
> +	.ecc_strengths = sunxi_ecc_strengths_a10,
> +	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
>  };
>  
>  static const struct of_device_id sunxi_nfc_ids[] = {
> 





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

* Re: [PATCH 15/15] mtd: rawnand: sunxi: Add support for H616 nand controller
  2025-10-10  8:40 ` [PATCH 15/15] mtd: rawnand: sunxi: Add support for H616 nand controller Richard Genoud
  2025-10-11  1:00   ` kernel test robot
@ 2025-10-11 10:48   ` Jernej Škrabec
  2025-10-13 12:01     ` Richard GENOUD
  1 sibling, 1 reply; 33+ messages in thread
From: Jernej Škrabec @ 2025-10-11 10:48 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
	Samuel Holland, Richard Genoud
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel, Richard Genoud

Dne petek, 10. oktober 2025 ob 10:40:42 Srednjeevropski poletni čas je Richard Genoud napisal(a):
> The H616 nand controller has the same base as A10/A23, with some
> differences:
> - mdma is based on chained buffers
> - its ECC supports up to 80bit per 1024bytes
> - some registers layouts are a bit different, mainly due do the stronger
>   ECC.
> - it uses USER_DATA_LEN registers along USER_DATA registers.
> - it needs a specific clock for ECC and MBUS.
> 
> This patch introduce the basic support, without DMA/MDMA.
> 
> Tested on Whatsminer H616 board (with and without scrambling, ECC)
> 
> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
> ---
>  drivers/mtd/nand/raw/sunxi_nand.c | 182 ++++++++++++++++++++++++++++--
>  1 file changed, 174 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
> index e81d74c6633a..1e1185f8d980 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
> @@ -49,17 +49,40 @@
>  #define NFC_REG_A23_IO_DATA	0x0300
>  #define NFC_REG_ECC_CTL		0x0034
>  #define NFC_REG_ECC_ST		0x0038
> -#define NFC_REG_DEBUG		0x003C
> +#define NFC_REG_H6_PAT_FOUND	0x003C
>  #define NFC_REG_A10_ECC_ERR_CNT	0x0040
> +#define NFC_REG_H6_ECC_ERR_CNT	0x0050
>  #define NFC_REG_ECC_ERR_CNT(nfc, x)	((nfc->caps->reg_ecc_err_cnt + (x)) & ~0x3)
> +#define NFC_REG_H6_RDATA_CTL	0x0044
> +#define NFC_REG_H6_RDATA_0	0x0048
> +#define NFC_REG_H6_RDATA_1	0x004C
>  #define NFC_REG_A10_USER_DATA	0x0050
> +#define NFC_REG_H6_USER_DATA	0x0080
>  #define NFC_REG_USER_DATA(nfc, x)	(nfc->caps->reg_user_data + ((x) * 4))
> +#define NFC_REG_H6_USER_DATA_LEN 0x0070
> +/* A USER_DATA_LEN register can hold the length of 8 USER_DATA registers */
> +#define NFC_REG_USER_DATA_LEN_CAPACITY 8
> +#define NFC_REG_USER_DATA_LEN(nfc, step) \
> +	 (nfc->caps->reg_user_data_len + \
> +	 ((step) / NFC_REG_USER_DATA_LEN_CAPACITY) * 4)
>  #define NFC_REG_SPARE_AREA(nfc) (nfc->caps->reg_spare_area)
>  #define NFC_REG_A10_SPARE_AREA	0x00A0
>  #define NFC_REG_PAT_ID(nfc) (nfc->caps->reg_pat_id)
>  #define NFC_REG_A10_PAT_ID	0x00A4
>  #define NFC_REG_MDMA_ADDR	0x00C0
>  #define NFC_REG_MDMA_CNT	0x00C4
> +#define NFC_REG_H6_EFNAND_STATUS 0x0110
> +#define NFC_REG_H6_SPARE_AREA	0x0114
> +#define NFC_REG_H6_PAT_ID	0x0118
> +#define NFC_REG_H6_DDR2_SPEC_CTL 0x011C
> +#define NFC_REG_H6_NDMA_MODE_CTL 0x0120
> +#define NFC_REG_H6_MDMA_DLBA_REG 0x0200
> +#define NFC_REG_H6_MDMA_STA	0x0204
> +#define NFC_REG_H6_MDMA_INT_MAS	0x0208
> +#define NFC_REG_H6_MDMA_DESC_ADDR 0x020C
> +#define NFC_REG_H6_MDMA_BUF_ADDR 0x0210
> +#define NFC_REG_H6_MDMA_CNT	0x0214
> +
>  #define NFC_RAM0_BASE		0x0400
>  #define NFC_RAM1_BASE		0x0800
>  
> @@ -71,6 +94,7 @@
>  #define NFC_BUS_WIDTH_16	(1 << 2)
>  #define NFC_RB_SEL_MSK		BIT(3)
>  #define NFC_RB_SEL(x)		((x) << 3)
> +/* CE_SEL BIT 27 is meant to be used for GPIO chipselect */
>  #define NFC_CE_SEL_MSK		GENMASK(26, 24)
>  #define NFC_CE_SEL(x)		((x) << 24)
>  #define NFC_CE_CTL		BIT(6)
> @@ -89,6 +113,9 @@
>  #define NFC_STA			BIT(4)
>  #define NFC_NATCH_INT_FLAG	BIT(5)
>  #define NFC_RB_STATE(x)		BIT(x + 8)
> +#define NFC_RB_STATE_MSK	GENMASK(11, 8)
> +#define NDFC_RDATA_STA_1	BIT(12)
> +#define NDFC_RDATA_STA_0	BIT(13)
>  
>  /* define bit use in NFC_INT */
>  #define NFC_B2R_INT_ENABLE	BIT(0)
> @@ -100,6 +127,7 @@
>  
>  /* define bit use in NFC_TIMING_CTL */
>  #define NFC_TIMING_CTL_EDO	BIT(8)
> +#define NFC_TIMING_CTL_E_EDO	BIT(9)
>  
>  /* define NFC_TIMING_CFG register layout */
>  #define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD)		\
> @@ -107,9 +135,15 @@
>  	(((tWHR) & 0x3) << 4) | (((tRHW) & 0x3) << 6) |		\
>  	(((tCAD) & 0x7) << 8))
>  
> +#define NFC_TIMING_CFG2(tCDQSS, tSC, tCLHZ, tCSS, tWC)		\
> +	((((tCDQSS) & 0x1) << 11) | (((tSC) & 0x3) << 12) |	\
> +	 (((tCLHZ) & 0x3) << 14) | (((tCSS) & 0x3) << 16) |	\
> +	 (((tWC) & 0x3) << 18))
> +
>  /* define bit use in NFC_CMD */
>  #define NFC_CMD_LOW_BYTE_MSK	GENMASK(7, 0)
> -#define NFC_CMD_HIGH_BYTE_MSK	GENMASK(15, 8)
> +#define NFC_CMD_HIGH_BYTE_MSK	GENMASK(15, 8)  // 15-10 reserved on H6
> +#define NFC_CMD_ADR_NUM_MSK	GENMASK(9, 8)
>  #define NFC_CMD(x)		(x)
>  #define NFC_ADR_NUM_MSK		GENMASK(18, 16)
>  #define NFC_ADR_NUM(x)		(((x) - 1) << 16)
> @@ -122,6 +156,7 @@
>  #define NFC_SEQ			BIT(25)
>  #define NFC_DATA_SWAP_METHOD	BIT(26)
>  #define NFC_ROW_AUTO_INC	BIT(27)
> +#define NFC_H6_SEND_RND_CMD2	BIT(27)
>  #define NFC_SEND_CMD3		BIT(28)
>  #define NFC_SEND_CMD4		BIT(29)
>  #define NFC_CMD_TYPE_MSK	GENMASK(31, 30)
> @@ -133,6 +168,7 @@
>  #define NFC_READ_CMD_MSK	GENMASK(7, 0)
>  #define NFC_RND_READ_CMD0_MSK	GENMASK(15, 8)
>  #define NFC_RND_READ_CMD1_MSK	GENMASK(23, 16)
> +#define NFC_RND_READ_CMD2_MSK	GENMASK(31, 24)
>  
>  /* define bit use in NFC_WCMD_SET */
>  #define NFC_PROGRAM_CMD_MSK	GENMASK(7, 0)
> @@ -150,6 +186,9 @@
>  #define NFC_RANDOM_DIRECTION(nfc) (nfc->caps->random_dir_mask)
>  #define NFC_ECC_MODE_MSK(nfc)	(nfc->caps->ecc_mode_mask)
>  #define NFC_ECC_MODE(nfc, x)	field_prep(NFC_ECC_MODE_MSK(nfc), (x))
> +/* RANDOM_PAGE_SIZE: 0: ECC block size  1: page size */
> +#define NFC_A23_RANDOM_PAGE_SIZE	BIT(11)
> +#define NFC_H6_RANDOM_PAGE_SIZE	BIT(7)
>  #define NFC_RANDOM_SEED_MSK	GENMASK(30, 16)
>  #define NFC_RANDOM_SEED(x)	((x) << 16)
>  
> @@ -165,6 +204,9 @@
>  
>  #define NFC_ECC_ERR_CNT(b, x)	(((x) >> (((b) % 4) * 8)) & 0xff)
>  
> +#define NFC_USER_DATA_LEN_MSK(step) \
> +	(0xf << (((step) % NFC_REG_USER_DATA_LEN_CAPACITY) * 4))
> +
>  #define NFC_DEFAULT_TIMEOUT_MS	1000
>  
>  #define NFC_MAX_CS		7
> @@ -224,9 +266,11 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
>   * @has_mdma:		Use mbus dma mode, otherwise general dma
>   *			through MBUS on A23/A33 needs extra configuration.
>   * @has_ecc_block_512:	If the ECC can handle 512B or only 1024B chuncks
> + * @has_mbus_clk:	If the controller needs a mbus clock.
>   * @reg_io_data:	I/O data register
>   * @reg_ecc_err_cnt:	ECC error counter register
>   * @reg_user_data:	User data register
> + * @reg_user_data_len:	User data length register
>   * @reg_spare_area:	Spare Area Register
>   * @reg_pat_id:		Pattern ID Register
>   * @reg_pat_found:	Data Pattern Status Register
> @@ -238,14 +282,23 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
>   * @dma_maxburst:	DMA maxburst
>   * @ecc_strengths:	Available ECC strengths array
>   * @nstrengths:		Size of @ecc_strengths
> + * @max_ecc_steps:	Maximum supported steps for ECC, this is also the
> + *			number of user data registers
> + * @user_data_len_tab:  Table of lenghts supported by USER_DATA_LEN register
> + *			The table index is the value to set in NFC_USER_DATA_LEN
> + *			registers, and the corresponding value is the number of
> + *			bytes to write
> + * @nuser_data_tab:	Size of @user_data_len_tab
>   * @sram_size:		Size of the NAND controller SRAM
>   */
>  struct sunxi_nfc_caps {
>  	bool has_mdma;
>  	bool has_ecc_block_512;
> +	bool has_mbus_clk;
>  	unsigned int reg_io_data;
>  	unsigned int reg_ecc_err_cnt;
>  	unsigned int reg_user_data;
> +	unsigned int reg_user_data_len;
>  	unsigned int reg_spare_area;
>  	unsigned int reg_pat_id;
>  	unsigned int reg_pat_found;
> @@ -257,6 +310,9 @@ struct sunxi_nfc_caps {
>  	unsigned int dma_maxburst;
>  	const u8 *ecc_strengths;
>  	unsigned int nstrengths;
> +	const u8 *user_data_len_tab;
> +	unsigned int nuser_data_tab;
> +	unsigned int max_ecc_steps;
>  	int sram_size;
>  };
>  
> @@ -268,6 +324,7 @@ struct sunxi_nfc_caps {
>   * @regs: NAND controller registers
>   * @ahb_clk: NAND controller AHB clock
>   * @mod_clk: NAND controller mod clock
> + * @ecc_clk: NAND controller ECC clock
>   * @reset: NAND controller reset line
>   * @assigned_cs: bitmask describing already assigned CS lines
>   * @clk_rate: NAND controller current clock rate
> @@ -282,7 +339,9 @@ struct sunxi_nfc {
>  	struct device *dev;
>  	void __iomem *regs;
>  	struct clk *ahb_clk;
> +	struct clk *mbus_clk;
>  	struct clk *mod_clk;
> +	struct clk *ecc_clk;
>  	struct reset_control *reset;
>  	unsigned long assigned_cs;
>  	unsigned long clk_rate;
> @@ -764,6 +823,53 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob,
>  		sunxi_nfc_randomize_bbm(nand, page, oob);
>  }
>  
> +/*
> + * On H6/H6 the user_data length has to be set in specific registers
> + * before writing.
> + */
> +static void sunxi_nfc_reset_user_data_len(struct sunxi_nfc *nfc)
> +{
> +	int loop_step = NFC_REG_USER_DATA_LEN_CAPACITY;
> +
> +	/* not all SoCs have this register */
> +	if (!nfc->caps->reg_user_data_len)
> +		return;
> +
> +	for (int i = 0; i < nfc->caps->max_ecc_steps; i += loop_step)
> +		writel(0, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, i));
> +}
> +
> +static void sunxi_nfc_set_user_data_len(struct sunxi_nfc *nfc,
> +					int len, int step)
> +{
> +	bool found = false;
> +	u32 val;
> +	int i;
> +
> +	/* not all SoCs have this register */
> +	if (!nfc->caps->reg_user_data_len)
> +		return;
> +
> +	for (i = 0; i < nfc->caps->nuser_data_tab; i++) {
> +		if (len == nfc->caps->user_data_len_tab[i]) {
> +			found = true;
> +			break;
> +		}
> +	}
> +
> +	if (!found) {
> +		dev_warn(nfc->dev,
> +			 "Unsupported length for user data reg: %d\n", len);
> +		return;
> +	}
> +
> +	val = readl(nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step));
> +
> +	val &= ~NFC_USER_DATA_LEN_MSK(step);
> +	val |= field_prep(NFC_USER_DATA_LEN_MSK(step), i);
> +	writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step));
> +}
> +
>  static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand,
>  						const u8 *oob, int step,
>  						bool bbm, int page)
> @@ -858,6 +964,8 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand,
>  	if (ret)
>  		return ret;
>  
> +	sunxi_nfc_reset_user_data_len(nfc);
> +	sunxi_nfc_set_user_data_len(nfc, 4, 0);
>  	sunxi_nfc_randomizer_config(nand, page, false);
>  	sunxi_nfc_randomizer_enable(nand);
>  	writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
> @@ -968,6 +1076,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf
>  		return ret;
>  
>  	sunxi_nfc_hw_ecc_enable(nand);
> +	sunxi_nfc_reset_user_data_len(nfc);
> +	sunxi_nfc_set_user_data_len(nfc, 4, 0);
>  	sunxi_nfc_randomizer_config(nand, page, false);
>  	sunxi_nfc_randomizer_enable(nand);
>  
> @@ -1100,6 +1210,8 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand,
>  
>  	sunxi_nfc_randomizer_config(nand, page, false);
>  	sunxi_nfc_randomizer_enable(nand);
> +	sunxi_nfc_reset_user_data_len(nfc);
> +	sunxi_nfc_set_user_data_len(nfc, 4, 0);
>  	sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, 0, bbm, page);
>  
>  	writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
> @@ -1344,10 +1456,12 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand,
>  	if (ret)
>  		goto pio_fallback;
>  
> +	sunxi_nfc_reset_user_data_len(nfc);
>  	for (i = 0; i < ecc->steps; i++) {
>  		const u8 *oob = nand->oob_poi + (i * (ecc->bytes + 4));
>  
>  		sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page);
> +		sunxi_nfc_set_user_data_len(nfc, 4, i);
>  	}
>  
>  	nand_prog_page_begin_op(nand, page, 0, NULL, 0);
> @@ -2148,18 +2262,36 @@ static int sunxi_nfc_probe(struct platform_device *pdev)
>  	if (irq < 0)
>  		return irq;
>  
> +	nfc->caps = of_device_get_match_data(dev);
> +	if (!nfc->caps)
> +		return -EINVAL;
> +
>  	nfc->ahb_clk = devm_clk_get_enabled(dev, "ahb");
>  	if (IS_ERR(nfc->ahb_clk)) {
>  		dev_err(dev, "failed to retrieve ahb clk\n");
>  		return PTR_ERR(nfc->ahb_clk);
>  	}
>  
> +	if (nfc->caps->has_mbus_clk) {
> +		nfc->mbus_clk = devm_clk_get_enabled(dev, "mbus");
> +		if (IS_ERR(nfc->mbus_clk)) {
> +			dev_err(dev, "No mbus clock specified\n");
> +			return PTR_ERR(nfc->mbus_clk);
> +		}
> +	}
> +
>  	nfc->mod_clk = devm_clk_get_enabled(dev, "mod");
>  	if (IS_ERR(nfc->mod_clk)) {
>  		dev_err(dev, "failed to retrieve mod clk\n");
>  		return PTR_ERR(nfc->mod_clk);
>  	}
>  
> +	nfc->ecc_clk = devm_clk_get_optional_enabled(dev, "ecc");
> +	if (IS_ERR(nfc->ecc_clk)) {
> +		dev_err(dev, "failed to retrieve ecc clk\n");
> +		return PTR_ERR(nfc->ecc_clk);
> +	}
> +
>  	nfc->reset = devm_reset_control_get_optional_exclusive(dev, "ahb");
>  	if (IS_ERR(nfc->reset))
>  		return PTR_ERR(nfc->reset);
> @@ -2170,12 +2302,6 @@ static int sunxi_nfc_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>  
> -	nfc->caps = of_device_get_match_data(&pdev->dev);
> -	if (!nfc->caps) {
> -		ret = -EINVAL;
> -		goto out_ahb_reset_reassert;
> -	}
> -
>  	ret = sunxi_nfc_rst(nfc);
>  	if (ret)
>  		goto out_ahb_reset_reassert;
> @@ -2226,8 +2352,17 @@ static const u8 sunxi_ecc_strengths_a10[] = {
>  	16, 24, 28, 32, 40, 48, 56, 60, 64
>  };
>  
> +static const u8 sunxi_ecc_strengths_h6[] = {
> +	16, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80
> +};
> +
> +static const u8 sunxi_user_data_len_h6[] = {
> +	0, 4, 8, 12, 16, 20, 24, 28, 32
> +};
> +
>  static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
>  	.has_ecc_block_512 = true,
> +	.has_mbus_clk = false,
>  	.reg_io_data = NFC_REG_A10_IO_DATA,
>  	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
>  	.reg_user_data = NFC_REG_A10_USER_DATA,
> @@ -2242,11 +2377,13 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
>  	.dma_maxburst = 4,
>  	.ecc_strengths = sunxi_ecc_strengths_a10,
>  	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
> +	.max_ecc_steps = 16,
>  	.sram_size = 1024,
>  };
>  
>  static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
>  	.has_mdma = true,
> +	.has_mbus_clk = false,
>  	.has_ecc_block_512 = true,
>  	.reg_io_data = NFC_REG_A23_IO_DATA,
>  	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
> @@ -2262,9 +2399,34 @@ static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
>  	.dma_maxburst = 8,
>  	.ecc_strengths = sunxi_ecc_strengths_a10,
>  	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
> +	.max_ecc_steps = 16,
>  	.sram_size = 1024,
>  };
>  
> +static const struct sunxi_nfc_caps sunxi_nfc_h616_caps = {
> +	.has_mdma = false, // H6 supports only chained descriptors

H6 or H616?

Fix the comment.

Best regards,
Jernej

> +	.has_mbus_clk = true,
> +	.reg_io_data = NFC_REG_A23_IO_DATA,
> +	.reg_ecc_err_cnt = NFC_REG_H6_ECC_ERR_CNT,
> +	.reg_user_data = NFC_REG_H6_USER_DATA,
> +	.reg_user_data_len = NFC_REG_H6_USER_DATA_LEN,
> +	.reg_spare_area = NFC_REG_H6_SPARE_AREA,
> +	.reg_pat_id = NFC_REG_H6_PAT_ID,
> +	.reg_pat_found = NFC_REG_H6_PAT_FOUND,
> +	.random_en_mask = BIT(5),
> +	.random_dir_mask = BIT(6),
> +	.ecc_mode_mask = GENMASK(15, 8),
> +	.ecc_err_mask = GENMASK(31, 0),
> +	.pat_found_mask = GENMASK(31, 0),
> +	.dma_maxburst = 8,
> +	.ecc_strengths = sunxi_ecc_strengths_h6,
> +	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_h6),
> +	.user_data_len_tab = sunxi_user_data_len_h6,
> +	.nuser_data_tab = ARRAY_SIZE(sunxi_user_data_len_h6),
> +	.max_ecc_steps = 32,
> +	.sram_size = 8192,
> +};
> +
>  static const struct of_device_id sunxi_nfc_ids[] = {
>  	{
>  		.compatible = "allwinner,sun4i-a10-nand",
> @@ -2274,6 +2436,10 @@ static const struct of_device_id sunxi_nfc_ids[] = {
>  		.compatible = "allwinner,sun8i-a23-nand-controller",
>  		.data = &sunxi_nfc_a23_caps,
>  	},
> +	{
> +		.compatible = "allwinner,sun50i-h616-nand-controller",
> +		.data = &sunxi_nfc_h616_caps,
> +	},
>  	{ /* sentinel */ }
>  };
>  MODULE_DEVICE_TABLE(of, sunxi_nfc_ids);
> 





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

* Re: [PATCH 02/15] dt-bindings: mtd: sunxi: Add new compatible
  2025-10-11 10:27       ` Jernej Škrabec
@ 2025-10-13 11:56         ` Richard GENOUD
  0 siblings, 0 replies; 33+ messages in thread
From: Richard GENOUD @ 2025-10-13 11:56 UTC (permalink / raw)
  To: Jernej Škrabec, Krzysztof Kozlowski, Miquel Raynal,
	Richard Weinberger, Vignesh Raghavendra, Rob Herring,
	Krzysztof Kozlowski, Conor Dooley, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel

Le 11/10/2025 à 12:27, Jernej Škrabec a écrit :
> Hi,
> 
> Dne petek, 10. oktober 2025 ob 12:18:56 Srednjeevropski poletni čas je Richard GENOUD napisal(a):
>> Le 10/10/2025 à 10:49, Krzysztof Kozlowski a écrit :
>>> On 10/10/2025 10:40, Richard Genoud wrote:
>>>> +
>>>>    properties:
>>>>      compatible:
>>>>        enum:
>>>>          - allwinner,sun4i-a10-nand
>>>>          - allwinner,sun8i-a23-nand-controller
>>>> +      - allwinner,sun50i-h616-nand-controller
>>>
>>>
>>> Also:
>>> 1. missing new line - why did you remove it?
>>> 2. Keep existing sunxi preferred order of entries. In other platforms it
>>> is alphanumerical, not natural. In case sunxi uses something else, just
>>> be sure you use sunxi order.
> 
> Sunxi order is from oldest generation to newest and then alphabetically
> by soc name.
> 
> This is already correctly ordered.
Ok.

Thanks!

> 
> Best regards,
> Jernej
> 
>> ok, make sens
>>
>> Thanks!
>>
>>>
>>> Best regards,
>>> Krzysztof
>>

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

* Re: [PATCH 03/15] arm64: dts: allwinner: h616: add NAND controller
  2025-10-11 10:33   ` Jernej Škrabec
@ 2025-10-13 11:59     ` Richard GENOUD
  0 siblings, 0 replies; 33+ messages in thread
From: Richard GENOUD @ 2025-10-13 11:59 UTC (permalink / raw)
  To: Jernej Škrabec, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel

Le 11/10/2025 à 12:33, Jernej Škrabec a écrit :
> Dne petek, 10. oktober 2025 ob 10:40:30 Srednjeevropski poletni čas je Richard Genoud napisal(a):
>> The H616 has a NAND controller quite similar to the A10/A23 ones, but
>> with some register differences, more clocks (for ECC and MBUS), more ECC
>> strengths, so this requires a new compatible string.
>>
>> This patch adds the NAND controller node and pins in the device tree.
>>
>> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
>> ---
>>   .../arm64/boot/dts/allwinner/sun50i-h616.dtsi | 50 +++++++++++++++++++
>>   1 file changed, 50 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
>> index ceedae9e399b..60626eba7f7c 100644
>> --- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
>> +++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
>> @@ -278,6 +278,37 @@ ir_rx_pin: ir-rx-pin {
>>   				function = "ir_rx";
>>   			};
>>   
>> +			nand_pins: nand-pins {
>> +				pins = "PC0", "PC1", "PC2", "PC5", "PC8", "PC9",
>> +				       "PC10", "PC11", "PC12", "PC13", "PC14",
>> +				       "PC15", "PC16";
>> +				function = "nand0";
>> +			};
>> +
>> +			nand_cs0_pin: nand-cs0-pin {
>> +				pins = "PC4";
>> +				function = "nand0";
>> +				bias-pull-up;
>> +			};
>> +
>> +			nand_cs1_pin: nand-cs1-pin {
>> +				pins = "PC3";
>> +				function = "nand0";
>> +				bias-pull-up;
>> +			};
>> +
>> +			nand_rb0_pin: nand-rb0-pin {
>> +				pins = "PC6";
>> +				function = "nand0";
>> +				bias-pull-up;
>> +			};
>> +
>> +			nand_rb1_pin: nand-rb1-pin {
>> +				pins = "PC7";
>> +				function = "nand0";
>> +				bias-pull-up;
>> +			};
>> +
>>   			mmc0_pins: mmc0-pins {
>>   				pins = "PF0", "PF1", "PF2", "PF3",
>>   				       "PF4", "PF5";
>> @@ -440,6 +471,25 @@ mmc2: mmc@4022000 {
>>   			#size-cells = <0>;
>>   		};
>>   
>> +		nfc: nand-controller@4011000 {
> 
> Nodes are sorted by memory address. So this one should be moved before
> mmc2 and possibly others.
Indeed.
I'll fix that.

> 
>> +			compatible = "allwinner,sun50i-h616-nand-controller";
>> +			reg = <0x04011000 0x1000>;
>> +			interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
>> +			clocks = <&ccu CLK_BUS_NAND>, <&ccu CLK_NAND0>,
>> +				<&ccu CLK_NAND1>, <&ccu CLK_MBUS_NAND>;
>> +			clock-names = "ahb", "mod", "ecc", "mbus";
>> +			resets = <&ccu RST_BUS_NAND>;
>> +			reset-names = "ahb";
>> +			dmas = <&dma 10>;
>> +			dma-names = "rxtx";
>> +			pinctrl-names = "default";
>> +			pinctrl-0 = <&nand_pins>, <&nand_cs0_pin>,
>> +				<&nand_cs1_pin>, <&nand_rb0_pin>,
>> +				<&nand_rb1_pin>;
> 
> Are you sure that each nand device will use exactly this pin configuration?
> IIUC, not all chips will have two CS and two RB pins. If so, pinctrl nodes
> should be moved to device DT and pins subnodes should be marked with
> /omit-if-no-ref/.

You're right, all pins may not be used.

Thanks!

> 
> Best regards,
> Jernej
> 
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>> +		};
>> +
>>   		uart0: serial@5000000 {
>>   			compatible = "snps,dw-apb-uart";
>>   			reg = <0x05000000 0x400>;
>>

-- 
Richard Genoud, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

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

* Re: [PATCH 04/15] mtd: nand: sunxi: move ecc strenghts in sunxi_nfc_caps
  2025-10-11 10:41   ` Jernej Škrabec
@ 2025-10-13 12:00     ` Richard GENOUD
  0 siblings, 0 replies; 33+ messages in thread
From: Richard GENOUD @ 2025-10-13 12:00 UTC (permalink / raw)
  To: Jernej Škrabec, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Chen-Yu Tsai, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel

Le 11/10/2025 à 12:41, Jernej Škrabec a écrit :
> Hi!
> 
> Dne petek, 10. oktober 2025 ob 10:40:31 Srednjeevropski poletni čas je Richard Genoud napisal(a):
>> H6/H616 has more ecc strenghts.
>> This commit prepares the change.
>> No functional change.
> 
> Format looks weird. Reword message to something like moving ecc to caps which
> will allow expand support for newer cores.
> 
> Also, there should be empty line before "No functional change."

I'll reword that

Thanks!

> 
> Best regards,
> Jernej
> 
>>
>> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
>> ---
>>   drivers/mtd/nand/raw/sunxi_nand.c | 20 ++++++++++++++++----
>>   1 file changed, 16 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
>> index 10a48e0d361f..198dd40f9220 100644
>> --- a/drivers/mtd/nand/raw/sunxi_nand.c
>> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
>> @@ -213,11 +213,15 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
>>    *			through MBUS on A23/A33 needs extra configuration.
>>    * @reg_io_data:	I/O data register
>>    * @dma_maxburst:	DMA maxburst
>> + * @ecc_strengths:	Available ECC strengths array
>> + * @nstrengths:		Size of @ecc_strengths
>>    */
>>   struct sunxi_nfc_caps {
>>   	bool has_mdma;
>>   	unsigned int reg_io_data;
>>   	unsigned int dma_maxburst;
>> +	const u8 *ecc_strengths;
>> +	unsigned int nstrengths;
>>   };
>>   
>>   /**
>> @@ -1619,9 +1623,9 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
>>   				       struct nand_ecc_ctrl *ecc,
>>   				       struct device_node *np)
>>   {
>> -	static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
>>   	struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
>>   	struct sunxi_nfc *nfc = to_sunxi_nfc(nand->controller);
>> +	const u8 *strengths = nfc->caps->ecc_strengths;
>>   	struct mtd_info *mtd = nand_to_mtd(nand);
>>   	struct nand_device *nanddev = mtd_to_nanddev(mtd);
>>   	int nsectors;
>> @@ -1645,7 +1649,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
>>   
>>   		ecc->strength = bytes * 8 / fls(8 * ecc->size);
>>   
>> -		for (i = 0; i < ARRAY_SIZE(strengths); i++) {
>> +		for (i = 0; i < nfc->caps->nstrengths; i++) {
>>   			if (strengths[i] > ecc->strength)
>>   				break;
>>   		}
>> @@ -1666,7 +1670,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
>>   	}
>>   
>>   	/* Add ECC info retrieval from DT */
>> -	for (i = 0; i < ARRAY_SIZE(strengths); i++) {
>> +	for (i = 0; i < nfc->caps->nstrengths; i++) {
>>   		if (ecc->strength <= strengths[i]) {
>>   			/*
>>   			 * Update ecc->strength value with the actual strength
>> @@ -1677,7 +1681,7 @@ static int sunxi_nand_hw_ecc_ctrl_init(struct nand_chip *nand,
>>   		}
>>   	}
>>   
>> -	if (i >= ARRAY_SIZE(strengths)) {
>> +	if (i >= nfc->caps->nstrengths) {
>>   		dev_err(nfc->dev, "unsupported strength\n");
>>   		return -ENOTSUPP;
>>   	}
>> @@ -2167,15 +2171,23 @@ static void sunxi_nfc_remove(struct platform_device *pdev)
>>   		dma_release_channel(nfc->dmac);
>>   }
>>   
>> +static const u8 sunxi_ecc_strengths_a10[] = {
>> +	16, 24, 28, 32, 40, 48, 56, 60, 64
>> +};
>> +
>>   static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
>>   	.reg_io_data = NFC_REG_A10_IO_DATA,
>>   	.dma_maxburst = 4,
>> +	.ecc_strengths = sunxi_ecc_strengths_a10,
>> +	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
>>   };
>>   
>>   static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
>>   	.has_mdma = true,
>>   	.reg_io_data = NFC_REG_A23_IO_DATA,
>>   	.dma_maxburst = 8,
>> +	.ecc_strengths = sunxi_ecc_strengths_a10,
>> +	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
>>   };
>>   
>>   static const struct of_device_id sunxi_nfc_ids[] = {
>>
> 
> 
> 
> 


-- 
Richard Genoud, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

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

* Re: [PATCH 15/15] mtd: rawnand: sunxi: Add support for H616 nand controller
  2025-10-11 10:48   ` Jernej Škrabec
@ 2025-10-13 12:01     ` Richard GENOUD
  0 siblings, 0 replies; 33+ messages in thread
From: Richard GENOUD @ 2025-10-13 12:01 UTC (permalink / raw)
  To: Jernej Škrabec, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Samuel Holland
  Cc: Wentao Liang, Uwe Kleine-König, Maxime Ripard,
	Thomas Petazzoni, linux-mtd, devicetree, linux-arm-kernel,
	linux-sunxi, linux-kernel

Le 11/10/2025 à 12:48, Jernej Škrabec a écrit :
> Dne petek, 10. oktober 2025 ob 10:40:42 Srednjeevropski poletni čas je Richard Genoud napisal(a):
>> The H616 nand controller has the same base as A10/A23, with some
>> differences:
>> - mdma is based on chained buffers
>> - its ECC supports up to 80bit per 1024bytes
>> - some registers layouts are a bit different, mainly due do the stronger
>>    ECC.
>> - it uses USER_DATA_LEN registers along USER_DATA registers.
>> - it needs a specific clock for ECC and MBUS.
>>
>> This patch introduce the basic support, without DMA/MDMA.
>>
>> Tested on Whatsminer H616 board (with and without scrambling, ECC)
>>
>> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
>> ---
>>   drivers/mtd/nand/raw/sunxi_nand.c | 182 ++++++++++++++++++++++++++++--
>>   1 file changed, 174 insertions(+), 8 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
>> index e81d74c6633a..1e1185f8d980 100644
>> --- a/drivers/mtd/nand/raw/sunxi_nand.c
>> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
>> @@ -49,17 +49,40 @@
>>   #define NFC_REG_A23_IO_DATA	0x0300
>>   #define NFC_REG_ECC_CTL		0x0034
>>   #define NFC_REG_ECC_ST		0x0038
>> -#define NFC_REG_DEBUG		0x003C
>> +#define NFC_REG_H6_PAT_FOUND	0x003C
>>   #define NFC_REG_A10_ECC_ERR_CNT	0x0040
>> +#define NFC_REG_H6_ECC_ERR_CNT	0x0050
>>   #define NFC_REG_ECC_ERR_CNT(nfc, x)	((nfc->caps->reg_ecc_err_cnt + (x)) & ~0x3)
>> +#define NFC_REG_H6_RDATA_CTL	0x0044
>> +#define NFC_REG_H6_RDATA_0	0x0048
>> +#define NFC_REG_H6_RDATA_1	0x004C
>>   #define NFC_REG_A10_USER_DATA	0x0050
>> +#define NFC_REG_H6_USER_DATA	0x0080
>>   #define NFC_REG_USER_DATA(nfc, x)	(nfc->caps->reg_user_data + ((x) * 4))
>> +#define NFC_REG_H6_USER_DATA_LEN 0x0070
>> +/* A USER_DATA_LEN register can hold the length of 8 USER_DATA registers */
>> +#define NFC_REG_USER_DATA_LEN_CAPACITY 8
>> +#define NFC_REG_USER_DATA_LEN(nfc, step) \
>> +	 (nfc->caps->reg_user_data_len + \
>> +	 ((step) / NFC_REG_USER_DATA_LEN_CAPACITY) * 4)
>>   #define NFC_REG_SPARE_AREA(nfc) (nfc->caps->reg_spare_area)
>>   #define NFC_REG_A10_SPARE_AREA	0x00A0
>>   #define NFC_REG_PAT_ID(nfc) (nfc->caps->reg_pat_id)
>>   #define NFC_REG_A10_PAT_ID	0x00A4
>>   #define NFC_REG_MDMA_ADDR	0x00C0
>>   #define NFC_REG_MDMA_CNT	0x00C4
>> +#define NFC_REG_H6_EFNAND_STATUS 0x0110
>> +#define NFC_REG_H6_SPARE_AREA	0x0114
>> +#define NFC_REG_H6_PAT_ID	0x0118
>> +#define NFC_REG_H6_DDR2_SPEC_CTL 0x011C
>> +#define NFC_REG_H6_NDMA_MODE_CTL 0x0120
>> +#define NFC_REG_H6_MDMA_DLBA_REG 0x0200
>> +#define NFC_REG_H6_MDMA_STA	0x0204
>> +#define NFC_REG_H6_MDMA_INT_MAS	0x0208
>> +#define NFC_REG_H6_MDMA_DESC_ADDR 0x020C
>> +#define NFC_REG_H6_MDMA_BUF_ADDR 0x0210
>> +#define NFC_REG_H6_MDMA_CNT	0x0214
>> +
>>   #define NFC_RAM0_BASE		0x0400
>>   #define NFC_RAM1_BASE		0x0800
>>   
>> @@ -71,6 +94,7 @@
>>   #define NFC_BUS_WIDTH_16	(1 << 2)
>>   #define NFC_RB_SEL_MSK		BIT(3)
>>   #define NFC_RB_SEL(x)		((x) << 3)
>> +/* CE_SEL BIT 27 is meant to be used for GPIO chipselect */
>>   #define NFC_CE_SEL_MSK		GENMASK(26, 24)
>>   #define NFC_CE_SEL(x)		((x) << 24)
>>   #define NFC_CE_CTL		BIT(6)
>> @@ -89,6 +113,9 @@
>>   #define NFC_STA			BIT(4)
>>   #define NFC_NATCH_INT_FLAG	BIT(5)
>>   #define NFC_RB_STATE(x)		BIT(x + 8)
>> +#define NFC_RB_STATE_MSK	GENMASK(11, 8)
>> +#define NDFC_RDATA_STA_1	BIT(12)
>> +#define NDFC_RDATA_STA_0	BIT(13)
>>   
>>   /* define bit use in NFC_INT */
>>   #define NFC_B2R_INT_ENABLE	BIT(0)
>> @@ -100,6 +127,7 @@
>>   
>>   /* define bit use in NFC_TIMING_CTL */
>>   #define NFC_TIMING_CTL_EDO	BIT(8)
>> +#define NFC_TIMING_CTL_E_EDO	BIT(9)
>>   
>>   /* define NFC_TIMING_CFG register layout */
>>   #define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD)		\
>> @@ -107,9 +135,15 @@
>>   	(((tWHR) & 0x3) << 4) | (((tRHW) & 0x3) << 6) |		\
>>   	(((tCAD) & 0x7) << 8))
>>   
>> +#define NFC_TIMING_CFG2(tCDQSS, tSC, tCLHZ, tCSS, tWC)		\
>> +	((((tCDQSS) & 0x1) << 11) | (((tSC) & 0x3) << 12) |	\
>> +	 (((tCLHZ) & 0x3) << 14) | (((tCSS) & 0x3) << 16) |	\
>> +	 (((tWC) & 0x3) << 18))
>> +
>>   /* define bit use in NFC_CMD */
>>   #define NFC_CMD_LOW_BYTE_MSK	GENMASK(7, 0)
>> -#define NFC_CMD_HIGH_BYTE_MSK	GENMASK(15, 8)
>> +#define NFC_CMD_HIGH_BYTE_MSK	GENMASK(15, 8)  // 15-10 reserved on H6
>> +#define NFC_CMD_ADR_NUM_MSK	GENMASK(9, 8)
>>   #define NFC_CMD(x)		(x)
>>   #define NFC_ADR_NUM_MSK		GENMASK(18, 16)
>>   #define NFC_ADR_NUM(x)		(((x) - 1) << 16)
>> @@ -122,6 +156,7 @@
>>   #define NFC_SEQ			BIT(25)
>>   #define NFC_DATA_SWAP_METHOD	BIT(26)
>>   #define NFC_ROW_AUTO_INC	BIT(27)
>> +#define NFC_H6_SEND_RND_CMD2	BIT(27)
>>   #define NFC_SEND_CMD3		BIT(28)
>>   #define NFC_SEND_CMD4		BIT(29)
>>   #define NFC_CMD_TYPE_MSK	GENMASK(31, 30)
>> @@ -133,6 +168,7 @@
>>   #define NFC_READ_CMD_MSK	GENMASK(7, 0)
>>   #define NFC_RND_READ_CMD0_MSK	GENMASK(15, 8)
>>   #define NFC_RND_READ_CMD1_MSK	GENMASK(23, 16)
>> +#define NFC_RND_READ_CMD2_MSK	GENMASK(31, 24)
>>   
>>   /* define bit use in NFC_WCMD_SET */
>>   #define NFC_PROGRAM_CMD_MSK	GENMASK(7, 0)
>> @@ -150,6 +186,9 @@
>>   #define NFC_RANDOM_DIRECTION(nfc) (nfc->caps->random_dir_mask)
>>   #define NFC_ECC_MODE_MSK(nfc)	(nfc->caps->ecc_mode_mask)
>>   #define NFC_ECC_MODE(nfc, x)	field_prep(NFC_ECC_MODE_MSK(nfc), (x))
>> +/* RANDOM_PAGE_SIZE: 0: ECC block size  1: page size */
>> +#define NFC_A23_RANDOM_PAGE_SIZE	BIT(11)
>> +#define NFC_H6_RANDOM_PAGE_SIZE	BIT(7)
>>   #define NFC_RANDOM_SEED_MSK	GENMASK(30, 16)
>>   #define NFC_RANDOM_SEED(x)	((x) << 16)
>>   
>> @@ -165,6 +204,9 @@
>>   
>>   #define NFC_ECC_ERR_CNT(b, x)	(((x) >> (((b) % 4) * 8)) & 0xff)
>>   
>> +#define NFC_USER_DATA_LEN_MSK(step) \
>> +	(0xf << (((step) % NFC_REG_USER_DATA_LEN_CAPACITY) * 4))
>> +
>>   #define NFC_DEFAULT_TIMEOUT_MS	1000
>>   
>>   #define NFC_MAX_CS		7
>> @@ -224,9 +266,11 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
>>    * @has_mdma:		Use mbus dma mode, otherwise general dma
>>    *			through MBUS on A23/A33 needs extra configuration.
>>    * @has_ecc_block_512:	If the ECC can handle 512B or only 1024B chuncks
>> + * @has_mbus_clk:	If the controller needs a mbus clock.
>>    * @reg_io_data:	I/O data register
>>    * @reg_ecc_err_cnt:	ECC error counter register
>>    * @reg_user_data:	User data register
>> + * @reg_user_data_len:	User data length register
>>    * @reg_spare_area:	Spare Area Register
>>    * @reg_pat_id:		Pattern ID Register
>>    * @reg_pat_found:	Data Pattern Status Register
>> @@ -238,14 +282,23 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
>>    * @dma_maxburst:	DMA maxburst
>>    * @ecc_strengths:	Available ECC strengths array
>>    * @nstrengths:		Size of @ecc_strengths
>> + * @max_ecc_steps:	Maximum supported steps for ECC, this is also the
>> + *			number of user data registers
>> + * @user_data_len_tab:  Table of lenghts supported by USER_DATA_LEN register
>> + *			The table index is the value to set in NFC_USER_DATA_LEN
>> + *			registers, and the corresponding value is the number of
>> + *			bytes to write
>> + * @nuser_data_tab:	Size of @user_data_len_tab
>>    * @sram_size:		Size of the NAND controller SRAM
>>    */
>>   struct sunxi_nfc_caps {
>>   	bool has_mdma;
>>   	bool has_ecc_block_512;
>> +	bool has_mbus_clk;
>>   	unsigned int reg_io_data;
>>   	unsigned int reg_ecc_err_cnt;
>>   	unsigned int reg_user_data;
>> +	unsigned int reg_user_data_len;
>>   	unsigned int reg_spare_area;
>>   	unsigned int reg_pat_id;
>>   	unsigned int reg_pat_found;
>> @@ -257,6 +310,9 @@ struct sunxi_nfc_caps {
>>   	unsigned int dma_maxburst;
>>   	const u8 *ecc_strengths;
>>   	unsigned int nstrengths;
>> +	const u8 *user_data_len_tab;
>> +	unsigned int nuser_data_tab;
>> +	unsigned int max_ecc_steps;
>>   	int sram_size;
>>   };
>>   
>> @@ -268,6 +324,7 @@ struct sunxi_nfc_caps {
>>    * @regs: NAND controller registers
>>    * @ahb_clk: NAND controller AHB clock
>>    * @mod_clk: NAND controller mod clock
>> + * @ecc_clk: NAND controller ECC clock
>>    * @reset: NAND controller reset line
>>    * @assigned_cs: bitmask describing already assigned CS lines
>>    * @clk_rate: NAND controller current clock rate
>> @@ -282,7 +339,9 @@ struct sunxi_nfc {
>>   	struct device *dev;
>>   	void __iomem *regs;
>>   	struct clk *ahb_clk;
>> +	struct clk *mbus_clk;
>>   	struct clk *mod_clk;
>> +	struct clk *ecc_clk;
>>   	struct reset_control *reset;
>>   	unsigned long assigned_cs;
>>   	unsigned long clk_rate;
>> @@ -764,6 +823,53 @@ static void sunxi_nfc_hw_ecc_get_prot_oob_bytes(struct nand_chip *nand, u8 *oob,
>>   		sunxi_nfc_randomize_bbm(nand, page, oob);
>>   }
>>   
>> +/*
>> + * On H6/H6 the user_data length has to be set in specific registers
>> + * before writing.
>> + */
>> +static void sunxi_nfc_reset_user_data_len(struct sunxi_nfc *nfc)
>> +{
>> +	int loop_step = NFC_REG_USER_DATA_LEN_CAPACITY;
>> +
>> +	/* not all SoCs have this register */
>> +	if (!nfc->caps->reg_user_data_len)
>> +		return;
>> +
>> +	for (int i = 0; i < nfc->caps->max_ecc_steps; i += loop_step)
>> +		writel(0, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, i));
>> +}
>> +
>> +static void sunxi_nfc_set_user_data_len(struct sunxi_nfc *nfc,
>> +					int len, int step)
>> +{
>> +	bool found = false;
>> +	u32 val;
>> +	int i;
>> +
>> +	/* not all SoCs have this register */
>> +	if (!nfc->caps->reg_user_data_len)
>> +		return;
>> +
>> +	for (i = 0; i < nfc->caps->nuser_data_tab; i++) {
>> +		if (len == nfc->caps->user_data_len_tab[i]) {
>> +			found = true;
>> +			break;
>> +		}
>> +	}
>> +
>> +	if (!found) {
>> +		dev_warn(nfc->dev,
>> +			 "Unsupported length for user data reg: %d\n", len);
>> +		return;
>> +	}
>> +
>> +	val = readl(nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step));
>> +
>> +	val &= ~NFC_USER_DATA_LEN_MSK(step);
>> +	val |= field_prep(NFC_USER_DATA_LEN_MSK(step), i);
>> +	writel(val, nfc->regs + NFC_REG_USER_DATA_LEN(nfc, step));
>> +}
>> +
>>   static void sunxi_nfc_hw_ecc_set_prot_oob_bytes(struct nand_chip *nand,
>>   						const u8 *oob, int step,
>>   						bool bbm, int page)
>> @@ -858,6 +964,8 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct nand_chip *nand,
>>   	if (ret)
>>   		return ret;
>>   
>> +	sunxi_nfc_reset_user_data_len(nfc);
>> +	sunxi_nfc_set_user_data_len(nfc, 4, 0);
>>   	sunxi_nfc_randomizer_config(nand, page, false);
>>   	sunxi_nfc_randomizer_enable(nand);
>>   	writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
>> @@ -968,6 +1076,8 @@ static int sunxi_nfc_hw_ecc_read_chunks_dma(struct nand_chip *nand, uint8_t *buf
>>   		return ret;
>>   
>>   	sunxi_nfc_hw_ecc_enable(nand);
>> +	sunxi_nfc_reset_user_data_len(nfc);
>> +	sunxi_nfc_set_user_data_len(nfc, 4, 0);
>>   	sunxi_nfc_randomizer_config(nand, page, false);
>>   	sunxi_nfc_randomizer_enable(nand);
>>   
>> @@ -1100,6 +1210,8 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct nand_chip *nand,
>>   
>>   	sunxi_nfc_randomizer_config(nand, page, false);
>>   	sunxi_nfc_randomizer_enable(nand);
>> +	sunxi_nfc_reset_user_data_len(nfc);
>> +	sunxi_nfc_set_user_data_len(nfc, 4, 0);
>>   	sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, 0, bbm, page);
>>   
>>   	writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
>> @@ -1344,10 +1456,12 @@ static int sunxi_nfc_hw_ecc_write_page_dma(struct nand_chip *nand,
>>   	if (ret)
>>   		goto pio_fallback;
>>   
>> +	sunxi_nfc_reset_user_data_len(nfc);
>>   	for (i = 0; i < ecc->steps; i++) {
>>   		const u8 *oob = nand->oob_poi + (i * (ecc->bytes + 4));
>>   
>>   		sunxi_nfc_hw_ecc_set_prot_oob_bytes(nand, oob, i, !i, page);
>> +		sunxi_nfc_set_user_data_len(nfc, 4, i);
>>   	}
>>   
>>   	nand_prog_page_begin_op(nand, page, 0, NULL, 0);
>> @@ -2148,18 +2262,36 @@ static int sunxi_nfc_probe(struct platform_device *pdev)
>>   	if (irq < 0)
>>   		return irq;
>>   
>> +	nfc->caps = of_device_get_match_data(dev);
>> +	if (!nfc->caps)
>> +		return -EINVAL;
>> +
>>   	nfc->ahb_clk = devm_clk_get_enabled(dev, "ahb");
>>   	if (IS_ERR(nfc->ahb_clk)) {
>>   		dev_err(dev, "failed to retrieve ahb clk\n");
>>   		return PTR_ERR(nfc->ahb_clk);
>>   	}
>>   
>> +	if (nfc->caps->has_mbus_clk) {
>> +		nfc->mbus_clk = devm_clk_get_enabled(dev, "mbus");
>> +		if (IS_ERR(nfc->mbus_clk)) {
>> +			dev_err(dev, "No mbus clock specified\n");
>> +			return PTR_ERR(nfc->mbus_clk);
>> +		}
>> +	}
>> +
>>   	nfc->mod_clk = devm_clk_get_enabled(dev, "mod");
>>   	if (IS_ERR(nfc->mod_clk)) {
>>   		dev_err(dev, "failed to retrieve mod clk\n");
>>   		return PTR_ERR(nfc->mod_clk);
>>   	}
>>   
>> +	nfc->ecc_clk = devm_clk_get_optional_enabled(dev, "ecc");
>> +	if (IS_ERR(nfc->ecc_clk)) {
>> +		dev_err(dev, "failed to retrieve ecc clk\n");
>> +		return PTR_ERR(nfc->ecc_clk);
>> +	}
>> +
>>   	nfc->reset = devm_reset_control_get_optional_exclusive(dev, "ahb");
>>   	if (IS_ERR(nfc->reset))
>>   		return PTR_ERR(nfc->reset);
>> @@ -2170,12 +2302,6 @@ static int sunxi_nfc_probe(struct platform_device *pdev)
>>   		return ret;
>>   	}
>>   
>> -	nfc->caps = of_device_get_match_data(&pdev->dev);
>> -	if (!nfc->caps) {
>> -		ret = -EINVAL;
>> -		goto out_ahb_reset_reassert;
>> -	}
>> -
>>   	ret = sunxi_nfc_rst(nfc);
>>   	if (ret)
>>   		goto out_ahb_reset_reassert;
>> @@ -2226,8 +2352,17 @@ static const u8 sunxi_ecc_strengths_a10[] = {
>>   	16, 24, 28, 32, 40, 48, 56, 60, 64
>>   };
>>   
>> +static const u8 sunxi_ecc_strengths_h6[] = {
>> +	16, 24, 28, 32, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80
>> +};
>> +
>> +static const u8 sunxi_user_data_len_h6[] = {
>> +	0, 4, 8, 12, 16, 20, 24, 28, 32
>> +};
>> +
>>   static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
>>   	.has_ecc_block_512 = true,
>> +	.has_mbus_clk = false,
>>   	.reg_io_data = NFC_REG_A10_IO_DATA,
>>   	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
>>   	.reg_user_data = NFC_REG_A10_USER_DATA,
>> @@ -2242,11 +2377,13 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
>>   	.dma_maxburst = 4,
>>   	.ecc_strengths = sunxi_ecc_strengths_a10,
>>   	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
>> +	.max_ecc_steps = 16,
>>   	.sram_size = 1024,
>>   };
>>   
>>   static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
>>   	.has_mdma = true,
>> +	.has_mbus_clk = false,
>>   	.has_ecc_block_512 = true,
>>   	.reg_io_data = NFC_REG_A23_IO_DATA,
>>   	.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
>> @@ -2262,9 +2399,34 @@ static const struct sunxi_nfc_caps sunxi_nfc_a23_caps = {
>>   	.dma_maxburst = 8,
>>   	.ecc_strengths = sunxi_ecc_strengths_a10,
>>   	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
>> +	.max_ecc_steps = 16,
>>   	.sram_size = 1024,
>>   };
>>   
>> +static const struct sunxi_nfc_caps sunxi_nfc_h616_caps = {
>> +	.has_mdma = false, // H6 supports only chained descriptors
> 
> H6 or H616?
Yes, it should be H616. I'll change that.

Thanks!

> 
> Fix the comment.
> 
> Best regards,
> Jernej
> 
>> +	.has_mbus_clk = true,
>> +	.reg_io_data = NFC_REG_A23_IO_DATA,
>> +	.reg_ecc_err_cnt = NFC_REG_H6_ECC_ERR_CNT,
>> +	.reg_user_data = NFC_REG_H6_USER_DATA,
>> +	.reg_user_data_len = NFC_REG_H6_USER_DATA_LEN,
>> +	.reg_spare_area = NFC_REG_H6_SPARE_AREA,
>> +	.reg_pat_id = NFC_REG_H6_PAT_ID,
>> +	.reg_pat_found = NFC_REG_H6_PAT_FOUND,
>> +	.random_en_mask = BIT(5),
>> +	.random_dir_mask = BIT(6),
>> +	.ecc_mode_mask = GENMASK(15, 8),
>> +	.ecc_err_mask = GENMASK(31, 0),
>> +	.pat_found_mask = GENMASK(31, 0),
>> +	.dma_maxburst = 8,
>> +	.ecc_strengths = sunxi_ecc_strengths_h6,
>> +	.nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_h6),
>> +	.user_data_len_tab = sunxi_user_data_len_h6,
>> +	.nuser_data_tab = ARRAY_SIZE(sunxi_user_data_len_h6),
>> +	.max_ecc_steps = 32,
>> +	.sram_size = 8192,
>> +};
>> +
>>   static const struct of_device_id sunxi_nfc_ids[] = {
>>   	{
>>   		.compatible = "allwinner,sun4i-a10-nand",
>> @@ -2274,6 +2436,10 @@ static const struct of_device_id sunxi_nfc_ids[] = {
>>   		.compatible = "allwinner,sun8i-a23-nand-controller",
>>   		.data = &sunxi_nfc_a23_caps,
>>   	},
>> +	{
>> +		.compatible = "allwinner,sun50i-h616-nand-controller",
>> +		.data = &sunxi_nfc_h616_caps,
>> +	},
>>   	{ /* sentinel */ }
>>   };
>>   MODULE_DEVICE_TABLE(of, sunxi_nfc_ids);
>>
> 
> 
> 
> 


-- 
Richard Genoud, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com

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

end of thread, other threads:[~2025-10-13 12:01 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-10  8:40 [PATCH 00/15] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
2025-10-10  8:40 ` [PATCH 01/15] mtd: rawnand: sunxi: Remove superfluous register readings Richard Genoud
2025-10-11 10:15   ` Jernej Škrabec
2025-10-10  8:40 ` [PATCH 02/15] dt-bindings: mtd: sunxi: Add new compatible Richard Genoud
2025-10-10  8:45   ` Krzysztof Kozlowski
2025-10-10 10:16     ` Richard GENOUD
2025-10-10  8:49   ` Krzysztof Kozlowski
2025-10-10 10:18     ` Richard GENOUD
2025-10-11 10:27       ` Jernej Škrabec
2025-10-13 11:56         ` Richard GENOUD
2025-10-10  8:40 ` [PATCH 03/15] arm64: dts: allwinner: h616: add NAND controller Richard Genoud
2025-10-10  8:47   ` Krzysztof Kozlowski
2025-10-10 10:22     ` Richard GENOUD
2025-10-10 10:24       ` Krzysztof Kozlowski
2025-10-11 10:33   ` Jernej Škrabec
2025-10-13 11:59     ` Richard GENOUD
2025-10-10  8:40 ` [PATCH 04/15] mtd: nand: sunxi: move ecc strenghts in sunxi_nfc_caps Richard Genoud
2025-10-11 10:41   ` Jernej Škrabec
2025-10-13 12:00     ` Richard GENOUD
2025-10-10  8:40 ` [PATCH 05/15] mtd: nand: sunxi: introduce reg_ecc_err_cnt " Richard Genoud
2025-10-10  8:40 ` [PATCH 06/15] mtd: nand: sunxi: introduce reg_user_data " Richard Genoud
2025-10-10  8:40 ` [PATCH 07/15] mtd: nand: sunxi: rework pattern found registers Richard Genoud
2025-10-10  8:40 ` [PATCH 08/15] mtd: nand: sunxi: add has_ecc_block_512 capability Richard Genoud
2025-10-10  8:40 ` [PATCH 09/15] mtd: nand: sunxi: introduce ecc_mode_mask in sunxi_nfc_caps Richard Genoud
2025-10-10  8:40 ` [PATCH 10/15] mtd: nand: sunxi: introduce random en/dir " Richard Genoud
2025-10-10  8:40 ` [PATCH 11/15] mtd: nand: sunxi: introduce reg_pat_id " Richard Genoud
2025-10-10  8:40 ` [PATCH 12/15] mtd: nand: sunxi: introduce reg_spare_area " Richard Genoud
2025-10-10  8:40 ` [PATCH 13/15] mtd: nand: sunxi: introduce ecc_err_mask " Richard Genoud
2025-10-10  8:40 ` [PATCH 14/15] mtd: nand: sunxi: introduce sram_size " Richard Genoud
2025-10-10  8:40 ` [PATCH 15/15] mtd: rawnand: sunxi: Add support for H616 nand controller Richard Genoud
2025-10-11  1:00   ` kernel test robot
2025-10-11 10:48   ` Jernej Škrabec
2025-10-13 12:01     ` Richard GENOUD

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).