* [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support
@ 2025-10-16 14:27 Richard Genoud
2025-10-16 14:27 ` [PATCH 01/24] mtd: rawnand: sunxi: cosmetic: remove needless comment Richard Genoud
` (23 more replies)
0 siblings, 24 replies; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
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.
Support for booting from NAND is not part of this series, but it's almost
ready. (It needs quite some modifications in sunxi-spl-image-builder.c
and sunxi_toc0.c)
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)
Patches 1 and 2 are small fixes
Patches 3-6 harmonize the registers definitions between U-Boot and SPL,
and ultimately merge those definitions in an include file, without
functional change.
Patches 7-19 are paving the way to the introduction of H6/H616 NAND
controller by adding per SoC capabilities for both drivers. They are
small for an easier review, without functional change.
Patches 20-21 are adding missing NAND related clocks definitions for
H6/H616
Patch 22 adds the support for H6/H616 NAND controller in U-Boot.
Patch 23 adds the support for H6/H616 NAND controller in SPL.
Patch 24 fixes warnings in sunxi_nand_spl.c
A similar series for this NAND controller support in Linux has been sent
and being reviewed.
Richard Genoud (24):
mtd: rawnand: sunxi: cosmetic: remove needless comment
mtd: rawnand: sunxi_spl: fix pointer from integer without a cast
mtd: rawnand: sunxi_spl: cosmetic: harmonize register defines with non
spl file
mtd: rawnand: sunxi_spl: cosmetic: use definitions from
linux/mtd/rawnand.h
mtd: rawnand: sunxi_spl: cosmetic: replace AHB_DIV_1 by
CCM_NAND_CTRL_M/N
mtd: rawnand: sunxi: cosmetic: merge register definitions for
sunxi_nand{,_spl}.c
mtd: rawnand: sunxi: cosmetic: add per SoC capabilities
mtd: rawnand: sunxi: cosmetic: move ECC_ERR_CNT register offset in SoC
caps
mtd: rawnand: sunxi: cosmetic: move USER_DATA register offset in SoC
caps
mtd: rawnand: sunxi: cosmetic: move ECC_PAT_FOUND register in SoC caps
mtd: rawnand: sunxi: cosmetic: add has_ecc_block_512 capability
mtd: rawnand: sunxi: cosmetic: move NFC_ECC_MODE offset in SoC caps
mtd: rawnand: sunxi: cosmetic: introduce reg_pat_id in sunxi_nfc_caps
mtd: rawnand: sunxi_spl: cosmetic: add per SoC capabilities
mtd: rawnand: sunxi: cosmetic: move NFC_RANDOM_EN register offset in
SoC caps
mtd: rawnand: sunxi: cosmetic: introduce reg_spare_area in
sunxi_nfc_caps
mtd: rawnand: sunxi_spl: use NFC_ECC_ERR_MSK and NFC_ECC_PAT_FOUND
mtd: rawnand: sunxi_spl: increase max_oobsize for 2KiB pages
mtd: rawnand: sunxi_spl: cosmetic: use NFC_ECC_MODE and
NFC_RANDOM_SEED macros
sunxi: clock: H6: add NAND controller clock registers
clk: sunxi: Add MBUS Master Clock Gating Register
mtd: rawnand: sunxi: add support for H6/H616 nand controller
mtd: rawnand: sunxi_spl: add support for H6/H616 nand controller
mtd: rawnand: sunxi_spl: Fix cast to pointer from integer warnings
.../include/asm/arch-sunxi/clock_sun50i_h6.h | 24 ++
board/sunxi/board.c | 17 +-
drivers/clk/sunxi/clk_h6.c | 2 +
drivers/clk/sunxi/clk_h616.c | 2 +
drivers/mtd/nand/raw/Kconfig | 3 +-
drivers/mtd/nand/raw/sunxi_nand.c | 301 ++++++++---------
drivers/mtd/nand/raw/sunxi_nand.h | 229 +++++++++++++
drivers/mtd/nand/raw/sunxi_nand_spl.c | 305 +++++++++++-------
8 files changed, 616 insertions(+), 267 deletions(-)
create mode 100644 drivers/mtd/nand/raw/sunxi_nand.h
base-commit: 2ba64e303b2706e5c42a6bf982326d632342ca66
^ permalink raw reply [flat|nested] 43+ messages in thread
* [PATCH 01/24] mtd: rawnand: sunxi: cosmetic: remove needless comment
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-17 7:56 ` Andre Przywara
2025-10-16 14:27 ` [PATCH 02/24] mtd: rawnand: sunxi_spl: fix pointer from integer without a cast Richard Genoud
` (22 subsequent siblings)
23 siblings, 1 reply; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Remove 'complete' member from struct sunxi_nfc
The 'complete' member isn't part of the structure, let's remove it.
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 1ce09b56b804..c6b9b2a4ebac 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -270,8 +270,6 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
* @clk_rate: NAND controller current clock rate
* @chips: a list containing all the NAND chips attached to
* this NAND controller
- * @complete: a completion object used to wait for NAND
- * controller events
*/
struct sunxi_nfc {
struct nand_hw_control controller;
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 02/24] mtd: rawnand: sunxi_spl: fix pointer from integer without a cast
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
2025-10-16 14:27 ` [PATCH 01/24] mtd: rawnand: sunxi: cosmetic: remove needless comment Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-17 7:57 ` Andre Przywara
2025-10-16 14:27 ` [PATCH 03/24] mtd: rawnand: sunxi_spl: cosmetic: harmonize register defines with non spl file Richard Genoud
` (21 subsequent siblings)
23 siblings, 1 reply; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Fix pointer from interget warning when compiling for ARM64
When compiling for arm64, we get this error:
error: passing argument 2 of ‘__memcpy_fromio’ makes pointer from
integer without a cast [-Wint-conversion]
Fix that with a cast to (void *)(uintptr_t)
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand_spl.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
index 4f1e2d9a5775..19091ece632b 100644
--- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
@@ -310,7 +310,8 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
return 1;
/* Retrieve the data from SRAM */
- memcpy_fromio(data, SUNXI_NFC_BASE + NFC_RAM0_BASE,
+ memcpy_fromio(data,
+ (void *)(uintptr_t)SUNXI_NFC_BASE + NFC_RAM0_BASE,
conf->ecc_size);
/* Stop the ECC engine */
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 03/24] mtd: rawnand: sunxi_spl: cosmetic: harmonize register defines with non spl file
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
2025-10-16 14:27 ` [PATCH 01/24] mtd: rawnand: sunxi: cosmetic: remove needless comment Richard Genoud
2025-10-16 14:27 ` [PATCH 02/24] mtd: rawnand: sunxi_spl: fix pointer from integer without a cast Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-17 7:57 ` Andre Przywara
2025-10-16 14:27 ` [PATCH 04/24] mtd: rawnand: sunxi_spl: cosmetic: use definitions from linux/mtd/rawnand.h Richard Genoud
` (20 subsequent siblings)
23 siblings, 1 reply; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Harmonize registers definition in sunxi_nand{,_spl}.c files
This is a first step to then include the same file from both
sunxi_nand{,_spl}.c files
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand_spl.c | 148 ++++++++++++--------------
1 file changed, 66 insertions(+), 82 deletions(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
index 19091ece632b..3ccf716b99ac 100644
--- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
@@ -14,48 +14,32 @@
#include <linux/mtd/rawnand.h>
/* registers */
-#define NFC_CTL 0x00000000
-#define NFC_ST 0x00000004
-#define NFC_INT 0x00000008
-#define NFC_TIMING_CTL 0x0000000C
-#define NFC_TIMING_CFG 0x00000010
-#define NFC_ADDR_LOW 0x00000014
-#define NFC_ADDR_HIGH 0x00000018
-#define NFC_SECTOR_NUM 0x0000001C
-#define NFC_CNT 0x00000020
-#define NFC_CMD 0x00000024
-#define NFC_RCMD_SET 0x00000028
-#define NFC_WCMD_SET 0x0000002C
-#define NFC_IO_DATA 0x00000030
-#define NFC_ECC_CTL 0x00000034
-#define NFC_ECC_ST 0x00000038
-#define NFC_DEBUG 0x0000003C
-#define NFC_ECC_CNT0 0x00000040
-#define NFC_ECC_CNT1 0x00000044
-#define NFC_ECC_CNT2 0x00000048
-#define NFC_ECC_CNT3 0x0000004C
-#define NFC_USER_DATA_BASE 0x00000050
-#define NFC_EFNAND_STATUS 0x00000090
-#define NFC_SPARE_AREA 0x000000A0
-#define NFC_PATTERN_ID 0x000000A4
+#define NFC_REG_CTL 0x00000000
+#define NFC_REG_ST 0x00000004
+#define NFC_REG_ADDR_LOW 0x00000014
+#define NFC_REG_ADDR_HIGH 0x00000018
+#define NFC_REG_CNT 0x00000020
+#define NFC_REG_CMD 0x00000024
+#define NFC_REG_RCMD_SET 0x00000028
+#define NFC_REG_ECC_CTL 0x00000034
+#define NFC_REG_ECC_ST 0x00000038
+#define NFC_REG_SPARE_AREA 0x000000A0
#define NFC_RAM0_BASE 0x00000400
#define NFC_RAM1_BASE 0x00000800
-#define NFC_CTL_EN (1 << 0)
-#define NFC_CTL_RESET (1 << 1)
-#define NFC_CTL_RAM_METHOD (1 << 14)
-#define NFC_CTL_PAGE_SIZE_MASK (0xf << 8)
-#define NFC_CTL_PAGE_SIZE(a) ((fls(a) - 11) << 8)
+#define NFC_EN (1 << 0)
+#define NFC_RESET (1 << 1)
+#define NFC_PAGE_SHIFT_MSK (0xf << 8)
+#define NFC_PAGE_SIZE(a) ((fls(a) - 11) << 8)
#define NFC_ECC_EN (1 << 0)
-#define NFC_ECC_PIPELINE (1 << 3)
#define NFC_ECC_EXCEPTION (1 << 4)
-#define NFC_ECC_BLOCK_SIZE (1 << 5)
-#define NFC_ECC_RANDOM_EN (1 << 9)
-#define NFC_ECC_RANDOM_DIRECTION (1 << 10)
+#define NFC_ECC_BLOCK_512 (1 << 5)
+#define NFC_RANDOM_EN (1 << 9)
+#define NFC_RANDOM_DIRECTION (1 << 10)
-#define NFC_ADDR_NUM_OFFSET 16
-#define NFC_SEND_ADDR (1 << 19)
+#define NFC_ADR_NUM_OFFSET 16
+#define NFC_SEND_ADR (1 << 19)
#define NFC_ACCESS_DIR (1 << 20)
#define NFC_DATA_TRANS (1 << 21)
#define NFC_SEND_CMD1 (1 << 22)
@@ -66,17 +50,17 @@
#define NFC_ROW_AUTO_INC (1 << 27)
#define NFC_SEND_CMD3 (1 << 28)
#define NFC_SEND_CMD4 (1 << 29)
-#define NFC_RAW_CMD (0 << 30)
-#define NFC_ECC_CMD (1 << 30)
-#define NFC_PAGE_CMD (2 << 30)
+#define NFC_NORMAL_OP (0 << 30)
+#define NFC_ECC_OP (1 << 30)
+#define NFC_PAGE_OP (2 << 30)
-#define NFC_ST_CMD_INT_FLAG (1 << 1)
-#define NFC_ST_DMA_INT_FLAG (1 << 2)
-#define NFC_ST_CMD_FIFO_STAT (1 << 3)
+#define NFC_CMD_INT_FLAG (1 << 1)
+#define NFC_DMA_INT_FLAG (1 << 2)
+#define NFC_CMD_FIFO_STATUS (1 << 3)
#define NFC_READ_CMD_OFFSET 0
-#define NFC_RANDOM_READ_CMD0_OFFSET 8
-#define NFC_RANDOM_READ_CMD1_OFFSET 16
+#define NFC_RND_READ_CMD0_OFFSET 8
+#define NFC_RND_READ_CMD1_OFFSET 16
#define NFC_CMD_RNDOUTSTART 0xE0
#define NFC_CMD_RNDOUT 0x05
@@ -143,8 +127,8 @@ static inline int check_value_negated(int offset, int unexpected_bits,
static int nand_wait_cmd_fifo_empty(void)
{
- if (!check_value_negated(SUNXI_NFC_BASE + NFC_ST, NFC_ST_CMD_FIFO_STAT,
- DEFAULT_TIMEOUT_US)) {
+ if (!check_value_negated(SUNXI_NFC_BASE + NFC_REG_ST,
+ NFC_CMD_FIFO_STATUS, DEFAULT_TIMEOUT_US)) {
printf("nand: timeout waiting for empty cmd FIFO\n");
return -ETIMEDOUT;
}
@@ -154,7 +138,7 @@ static int nand_wait_cmd_fifo_empty(void)
static int nand_wait_int(void)
{
- if (!check_value(SUNXI_NFC_BASE + NFC_ST, NFC_ST_CMD_INT_FLAG,
+ if (!check_value(SUNXI_NFC_BASE + NFC_REG_ST, NFC_CMD_INT_FLAG,
DEFAULT_TIMEOUT_US)) {
printf("nand: timeout waiting for interruption\n");
return -ETIMEDOUT;
@@ -171,8 +155,8 @@ static int nand_exec_cmd(u32 cmd)
if (ret)
return ret;
- writel(NFC_ST_CMD_INT_FLAG, SUNXI_NFC_BASE + NFC_ST);
- writel(cmd, SUNXI_NFC_BASE + NFC_CMD);
+ writel(NFC_CMD_INT_FLAG, SUNXI_NFC_BASE + NFC_REG_ST);
+ writel(cmd, SUNXI_NFC_BASE + NFC_REG_CMD);
return nand_wait_int();
}
@@ -183,13 +167,13 @@ void nand_init(void)
board_nand_init();
- val = readl(SUNXI_NFC_BASE + NFC_CTL);
+ val = readl(SUNXI_NFC_BASE + NFC_REG_CTL);
/* enable and reset CTL */
- writel(val | NFC_CTL_EN | NFC_CTL_RESET,
- SUNXI_NFC_BASE + NFC_CTL);
+ writel(val | NFC_EN | NFC_RESET,
+ SUNXI_NFC_BASE + NFC_REG_CTL);
- if (!check_value_negated(SUNXI_NFC_BASE + NFC_CTL,
- NFC_CTL_RESET, DEFAULT_TIMEOUT_US)) {
+ if (!check_value_negated(SUNXI_NFC_BASE + NFC_REG_CTL,
+ NFC_RESET, DEFAULT_TIMEOUT_US)) {
printf("Couldn't initialize nand\n");
}
@@ -203,42 +187,42 @@ static void nand_apply_config(const struct nfc_config *conf)
nand_wait_cmd_fifo_empty();
- val = readl(SUNXI_NFC_BASE + NFC_CTL);
- val &= ~NFC_CTL_PAGE_SIZE_MASK;
- writel(val | NFC_CTL_PAGE_SIZE(conf->page_size),
- SUNXI_NFC_BASE + NFC_CTL);
- writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_CNT);
- writel(conf->page_size, SUNXI_NFC_BASE + NFC_SPARE_AREA);
+ val = readl(SUNXI_NFC_BASE + NFC_REG_CTL);
+ val &= ~NFC_PAGE_SHIFT_MSK;
+ writel(val | NFC_PAGE_SIZE(conf->page_size),
+ SUNXI_NFC_BASE + NFC_REG_CTL);
+ writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_REG_CNT);
+ writel(conf->page_size, SUNXI_NFC_BASE + NFC_REG_SPARE_AREA);
}
static int nand_load_page(const struct nfc_config *conf, u32 offs)
{
int page = offs / conf->page_size;
- writel((NFC_CMD_RNDOUTSTART << NFC_RANDOM_READ_CMD1_OFFSET) |
- (NFC_CMD_RNDOUT << NFC_RANDOM_READ_CMD0_OFFSET) |
+ writel((NFC_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
+ (NFC_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
(NFC_CMD_READSTART << NFC_READ_CMD_OFFSET),
- SUNXI_NFC_BASE + NFC_RCMD_SET);
- writel(((page & 0xFFFF) << 16), SUNXI_NFC_BASE + NFC_ADDR_LOW);
- writel((page >> 16) & 0xFF, SUNXI_NFC_BASE + NFC_ADDR_HIGH);
+ SUNXI_NFC_BASE + NFC_REG_RCMD_SET);
+ writel(((page & 0xFFFF) << 16), SUNXI_NFC_BASE + NFC_REG_ADDR_LOW);
+ writel((page >> 16) & 0xFF, SUNXI_NFC_BASE + NFC_REG_ADDR_HIGH);
- return nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_RAW_CMD |
- NFC_SEND_ADDR | NFC_WAIT_FLAG |
- ((conf->addr_cycles - 1) << NFC_ADDR_NUM_OFFSET));
+ return nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_NORMAL_OP |
+ NFC_SEND_ADR | NFC_WAIT_FLAG |
+ ((conf->addr_cycles - 1) << NFC_ADR_NUM_OFFSET));
}
static int nand_change_column(u16 column)
{
int ret;
- writel((NFC_CMD_RNDOUTSTART << NFC_RANDOM_READ_CMD1_OFFSET) |
- (NFC_CMD_RNDOUT << NFC_RANDOM_READ_CMD0_OFFSET) |
+ writel((NFC_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
+ (NFC_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
(NFC_CMD_RNDOUTSTART << NFC_READ_CMD_OFFSET),
- SUNXI_NFC_BASE + NFC_RCMD_SET);
- writel(column, SUNXI_NFC_BASE + NFC_ADDR_LOW);
+ SUNXI_NFC_BASE + NFC_REG_RCMD_SET);
+ writel(column, SUNXI_NFC_BASE + NFC_REG_ADDR_LOW);
- ret = nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_RAW_CMD |
- (1 << NFC_ADDR_NUM_OFFSET) | NFC_SEND_ADDR |
+ ret = nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_NORMAL_OP |
+ (1 << NFC_ADR_NUM_OFFSET) | NFC_SEND_ADR |
NFC_CMD_RNDOUT);
if (ret)
return ret;
@@ -276,16 +260,16 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
u8 *data = dest + data_off;
/* Clear ECC status and restart ECC engine */
- writel(0, SUNXI_NFC_BASE + NFC_ECC_ST);
+ writel(0, SUNXI_NFC_BASE + NFC_REG_ECC_ST);
writel((rand_seed << 16) | (conf->ecc_strength << 12) |
- (conf->randomize ? NFC_ECC_RANDOM_EN : 0) |
- (conf->ecc_size == 512 ? NFC_ECC_BLOCK_SIZE : 0) |
+ (conf->randomize ? NFC_RANDOM_EN : 0) |
+ (conf->ecc_size == 512 ? NFC_ECC_BLOCK_512 : 0) |
NFC_ECC_EN | NFC_ECC_EXCEPTION,
- SUNXI_NFC_BASE + NFC_ECC_CTL);
+ SUNXI_NFC_BASE + NFC_REG_ECC_CTL);
/* Move the data in SRAM */
nand_change_column(data_off);
- writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_CNT);
+ writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_REG_CNT);
nand_exec_cmd(NFC_DATA_TRANS);
/*
@@ -293,10 +277,10 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
* the data.
*/
nand_change_column(oob_off);
- nand_exec_cmd(NFC_DATA_TRANS | NFC_ECC_CMD);
+ nand_exec_cmd(NFC_DATA_TRANS | NFC_ECC_OP);
/* Get the ECC status */
- ecc_st = readl(SUNXI_NFC_BASE + NFC_ECC_ST);
+ ecc_st = readl(SUNXI_NFC_BASE + NFC_REG_ECC_ST);
/* ECC error detected. */
if (ecc_st & 0xffff)
@@ -315,8 +299,8 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
conf->ecc_size);
/* Stop the ECC engine */
- writel(readl(SUNXI_NFC_BASE + NFC_ECC_CTL) & ~NFC_ECC_EN,
- SUNXI_NFC_BASE + NFC_ECC_CTL);
+ writel(readl(SUNXI_NFC_BASE + NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
+ SUNXI_NFC_BASE + NFC_REG_ECC_CTL);
if (data_off + conf->ecc_size >= len)
break;
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 04/24] mtd: rawnand: sunxi_spl: cosmetic: use definitions from linux/mtd/rawnand.h
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (2 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 03/24] mtd: rawnand: sunxi_spl: cosmetic: harmonize register defines with non spl file Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-17 9:35 ` Andre Przywara
2025-10-16 14:27 ` [PATCH 05/24] mtd: rawnand: sunxi_spl: cosmetic: replace AHB_DIV_1 by CCM_NAND_CTRL_M/N Richard Genoud
` (19 subsequent siblings)
23 siblings, 1 reply; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Remove unneeded definitions NFC_CMD_R* in sunxi_nand_spl.c
No need to define NFC_CMD_RNDOUTSTART, NFC_CMD_RNDOUT and
NFC_CMD_READSTART here since they are already in linux/mtd/rawnand.h
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand_spl.c | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
index 3ccf716b99ac..306c1c0d0989 100644
--- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
@@ -62,10 +62,6 @@
#define NFC_RND_READ_CMD0_OFFSET 8
#define NFC_RND_READ_CMD1_OFFSET 16
-#define NFC_CMD_RNDOUTSTART 0xE0
-#define NFC_CMD_RNDOUT 0x05
-#define NFC_CMD_READSTART 0x30
-
struct nfc_config {
int page_size;
int ecc_strength;
@@ -199,9 +195,9 @@ static int nand_load_page(const struct nfc_config *conf, u32 offs)
{
int page = offs / conf->page_size;
- writel((NFC_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
- (NFC_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
- (NFC_CMD_READSTART << NFC_READ_CMD_OFFSET),
+ writel((NAND_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
+ (NAND_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
+ (NAND_CMD_READSTART << NFC_READ_CMD_OFFSET),
SUNXI_NFC_BASE + NFC_REG_RCMD_SET);
writel(((page & 0xFFFF) << 16), SUNXI_NFC_BASE + NFC_REG_ADDR_LOW);
writel((page >> 16) & 0xFF, SUNXI_NFC_BASE + NFC_REG_ADDR_HIGH);
@@ -215,15 +211,15 @@ static int nand_change_column(u16 column)
{
int ret;
- writel((NFC_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
- (NFC_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
- (NFC_CMD_RNDOUTSTART << NFC_READ_CMD_OFFSET),
+ writel((NAND_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
+ (NAND_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
+ (NAND_CMD_RNDOUTSTART << NFC_READ_CMD_OFFSET),
SUNXI_NFC_BASE + NFC_REG_RCMD_SET);
writel(column, SUNXI_NFC_BASE + NFC_REG_ADDR_LOW);
ret = nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_NORMAL_OP |
(1 << NFC_ADR_NUM_OFFSET) | NFC_SEND_ADR |
- NFC_CMD_RNDOUT);
+ NAND_CMD_RNDOUT);
if (ret)
return ret;
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 05/24] mtd: rawnand: sunxi_spl: cosmetic: replace AHB_DIV_1 by CCM_NAND_CTRL_M/N
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (3 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 04/24] mtd: rawnand: sunxi_spl: cosmetic: use definitions from linux/mtd/rawnand.h Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-17 9:36 ` Andre Przywara
2025-10-16 14:27 ` [PATCH 06/24] mtd: rawnand: sunxi: cosmetic: merge register definitions for sunxi_nand{, _spl}.c Richard Genoud
` (18 subsequent siblings)
23 siblings, 1 reply; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
CCM_NAND_CTRL_M/N is defined in clock headers, and it's more readable
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand_spl.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
index 306c1c0d0989..9f80a8010d7b 100644
--- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
@@ -531,5 +531,6 @@ void nand_deselect(void)
#else
clrbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_DMA));
#endif
- clrbits_le32(&ccm->nand0_clk_cfg, CCM_NAND_CTRL_ENABLE | AHB_DIV_1);
+ clrbits_le32(&ccm->nand0_clk_cfg, CCM_NAND_CTRL_ENABLE |
+ CCM_NAND_CTRL_N(0) | CCM_NAND_CTRL_M(1));
}
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 06/24] mtd: rawnand: sunxi: cosmetic: merge register definitions for sunxi_nand{, _spl}.c
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (4 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 05/24] mtd: rawnand: sunxi_spl: cosmetic: replace AHB_DIV_1 by CCM_NAND_CTRL_M/N Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-17 23:09 ` [PATCH 06/24] mtd: rawnand: sunxi: cosmetic: merge register definitions for sunxi_nand{,_spl}.c Andre Przywara
2025-10-16 14:27 ` [PATCH 07/24] mtd: rawnand: sunxi: cosmetic: add per SoC capabilities Richard Genoud
` (17 subsequent siblings)
23 siblings, 1 reply; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Merge common register definitions from sunxi_nand{,_spl}.c
The Allwinner NAND controller registers where in both files, so let's
just merge all that in a header, it will be easier for maintenance.
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand.c | 123 +-------------------
drivers/mtd/nand/raw/sunxi_nand.h | 156 ++++++++++++++++++++++++++
drivers/mtd/nand/raw/sunxi_nand_spl.c | 45 +-------
3 files changed, 158 insertions(+), 166 deletions(-)
create mode 100644 drivers/mtd/nand/raw/sunxi_nand.h
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index c6b9b2a4ebac..000ebd0439f1 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -46,128 +46,7 @@
#include <asm/gpio.h>
#include <asm/arch/clock.h>
-#define NFC_REG_CTL 0x0000
-#define NFC_REG_ST 0x0004
-#define NFC_REG_INT 0x0008
-#define NFC_REG_TIMING_CTL 0x000C
-#define NFC_REG_TIMING_CFG 0x0010
-#define NFC_REG_ADDR_LOW 0x0014
-#define NFC_REG_ADDR_HIGH 0x0018
-#define NFC_REG_SECTOR_NUM 0x001C
-#define NFC_REG_CNT 0x0020
-#define NFC_REG_CMD 0x0024
-#define NFC_REG_RCMD_SET 0x0028
-#define NFC_REG_WCMD_SET 0x002C
-#define NFC_REG_IO_DATA 0x0030
-#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_USER_DATA(x) (0x0050 + ((x) * 4))
-#define NFC_REG_SPARE_AREA 0x00A0
-#define NFC_REG_PAT_ID 0x00A4
-#define NFC_RAM0_BASE 0x0400
-#define NFC_RAM1_BASE 0x0800
-
-/* define bit use in NFC_CTL */
-#define NFC_EN BIT(0)
-#define NFC_RESET BIT(1)
-#define NFC_BUS_WIDTH_MSK BIT(2)
-#define NFC_BUS_WIDTH_8 (0 << 2)
-#define NFC_BUS_WIDTH_16 (1 << 2)
-#define NFC_RB_SEL_MSK BIT(3)
-#define NFC_RB_SEL(x) ((x) << 3)
-#define NFC_CE_SEL_MSK (0x7 << 24)
-#define NFC_CE_SEL(x) ((x) << 24)
-#define NFC_CE_CTL BIT(6)
-#define NFC_PAGE_SHIFT_MSK (0xf << 8)
-#define NFC_PAGE_SHIFT(x) (((x) < 10 ? 0 : (x) - 10) << 8)
-#define NFC_SAM BIT(12)
-#define NFC_RAM_METHOD BIT(14)
-#define NFC_DEBUG_CTL BIT(31)
-
-/* define bit use in NFC_ST */
-#define NFC_RB_B2R BIT(0)
-#define NFC_CMD_INT_FLAG BIT(1)
-#define NFC_DMA_INT_FLAG BIT(2)
-#define NFC_CMD_FIFO_STATUS BIT(3)
-#define NFC_STA BIT(4)
-#define NFC_NATCH_INT_FLAG BIT(5)
-#define NFC_RB_STATE(x) BIT(x + 8)
-
-/* define bit use in NFC_INT */
-#define NFC_B2R_INT_ENABLE BIT(0)
-#define NFC_CMD_INT_ENABLE BIT(1)
-#define NFC_DMA_INT_ENABLE BIT(2)
-#define NFC_INT_MASK (NFC_B2R_INT_ENABLE | \
- NFC_CMD_INT_ENABLE | \
- NFC_DMA_INT_ENABLE)
-
-/* define bit use in NFC_TIMING_CTL */
-#define NFC_TIMING_CTL_EDO BIT(8)
-
-/* define NFC_TIMING_CFG register layout */
-#define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD) \
- (((tWB) & 0x3) | (((tADL) & 0x3) << 2) | \
- (((tWHR) & 0x3) << 4) | (((tRHW) & 0x3) << 6) | \
- (((tCAD) & 0x7) << 8))
-
-/* define bit use in NFC_CMD */
-#define NFC_CMD_LOW_BYTE_MSK 0xff
-#define NFC_CMD_HIGH_BYTE_MSK (0xff << 8)
-#define NFC_CMD(x) (x)
-#define NFC_ADR_NUM_MSK (0x7 << 16)
-#define NFC_ADR_NUM(x) (((x) - 1) << 16)
-#define NFC_SEND_ADR BIT(19)
-#define NFC_ACCESS_DIR BIT(20)
-#define NFC_DATA_TRANS BIT(21)
-#define NFC_SEND_CMD1 BIT(22)
-#define NFC_WAIT_FLAG BIT(23)
-#define NFC_SEND_CMD2 BIT(24)
-#define NFC_SEQ BIT(25)
-#define NFC_DATA_SWAP_METHOD BIT(26)
-#define NFC_ROW_AUTO_INC BIT(27)
-#define NFC_SEND_CMD3 BIT(28)
-#define NFC_SEND_CMD4 BIT(29)
-#define NFC_CMD_TYPE_MSK (0x3 << 30)
-#define NFC_NORMAL_OP (0 << 30)
-#define NFC_ECC_OP (1 << 30)
-#define NFC_PAGE_OP (2 << 30)
-
-/* define bit use in NFC_RCMD_SET */
-#define NFC_READ_CMD_MSK 0xff
-#define NFC_RND_READ_CMD0_MSK (0xff << 8)
-#define NFC_RND_READ_CMD1_MSK (0xff << 16)
-
-/* define bit use in NFC_WCMD_SET */
-#define NFC_PROGRAM_CMD_MSK 0xff
-#define NFC_RND_WRITE_CMD_MSK (0xff << 8)
-#define NFC_READ_CMD0_MSK (0xff << 16)
-#define NFC_READ_CMD1_MSK (0xff << 24)
-
-/* define bit use in NFC_ECC_CTL */
-#define NFC_ECC_EN BIT(0)
-#define NFC_ECC_PIPELINE BIT(3)
-#define NFC_ECC_EXCEPTION BIT(4)
-#define NFC_ECC_BLOCK_SIZE_MSK BIT(5)
-#define NFC_ECC_BLOCK_512 (1 << 5)
-#define NFC_RANDOM_EN BIT(9)
-#define NFC_RANDOM_DIRECTION BIT(10)
-#define NFC_ECC_MODE_MSK (0xf << 12)
-#define NFC_ECC_MODE(x) ((x) << 12)
-#define NFC_RANDOM_SEED_MSK (0x7fff << 16)
-#define NFC_RANDOM_SEED(x) ((x) << 16)
-
-/* define bit use in NFC_ECC_ST */
-#define NFC_ECC_ERR(x) BIT(x)
-#define NFC_ECC_PAT_FOUND(x) BIT(x + 16)
-#define NFC_ECC_ERR_CNT(b, x) (((x) >> ((b) * 8)) & 0xff)
-
-#define NFC_DEFAULT_TIMEOUT_MS 1000
-
-#define NFC_SRAM_SIZE 1024
-
-#define NFC_MAX_CS 7
+#include "sunxi_nand.h"
/*
* Ready/Busy detection type: describes the Ready/Busy detection modes
diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
new file mode 100644
index 000000000000..59803ccc9f22
--- /dev/null
+++ b/drivers/mtd/nand/raw/sunxi_nand.h
@@ -0,0 +1,156 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2025 Bootlin, Richard GENOUD
+ *
+ * merged defines from sunxi_nand{,_spl}.c
+ * Containing the following copyrights:
+ * Copyright (C) 2013 Boris BREZILLON <b.brezillon.dev@gmail.com>
+ * Copyright (C) 2015 Roy Spliet <r.spliet@ultimaker.com>
+ * Copyright (c) 2014-2015, Antmicro Ltd <www.antmicro.com>
+ * Copyright (c) 2015, AW-SOM Technologies <www.aw-som.com>
+ * Derived from:
+ * https://github.com/yuq/sunxi-nfc-mtd
+ * Copyright (C) 2013 Qiang Yu <yuq825@gmail.com>
+ *
+ * https://github.com/hno/Allwinner-Info
+ * Copyright (C) 2013 Henrik Nordström <Henrik Nordström>
+ *
+ * Copyright (C) 2013 Dmitriy B. <rzk333@gmail.com>
+ * Copyright (C) 2013 Sergey Lapin <slapin@ossfans.org>
+ *
+ */
+
+#ifndef SUNXI_NAND_H
+#define SUNXI_NAND_H
+
+#include <linux/bitops.h>
+
+#define NFC_REG_CTL 0x0000
+#define NFC_REG_ST 0x0004
+#define NFC_REG_INT 0x0008
+#define NFC_REG_TIMING_CTL 0x000C
+#define NFC_REG_TIMING_CFG 0x0010
+#define NFC_REG_ADDR_LOW 0x0014
+#define NFC_REG_ADDR_HIGH 0x0018
+#define NFC_REG_SECTOR_NUM 0x001C
+#define NFC_REG_CNT 0x0020
+#define NFC_REG_CMD 0x0024
+#define NFC_REG_RCMD_SET 0x0028
+#define NFC_REG_WCMD_SET 0x002C
+#define NFC_REG_IO_DATA 0x0030
+#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_USER_DATA(x) (0x0050 + ((x) * 4))
+#define NFC_REG_SPARE_AREA 0x00A0
+#define NFC_REG_PAT_ID 0x00A4
+#define NFC_RAM0_BASE 0x0400
+#define NFC_RAM1_BASE 0x0800
+
+/* define bit use in NFC_CTL */
+#define NFC_EN BIT(0)
+#define NFC_RESET BIT(1)
+#define NFC_BUS_WIDTH_MSK BIT(2)
+#define NFC_BUS_WIDTH_8 (0 << 2)
+#define NFC_BUS_WIDTH_16 (1 << 2)
+#define NFC_RB_SEL_MSK BIT(3)
+#define NFC_RB_SEL(x) ((x) << 3)
+#define NFC_CE_SEL_MSK (0x7 << 24)
+#define NFC_CE_SEL(x) ((x) << 24)
+#define NFC_CE_CTL BIT(6)
+#define NFC_PAGE_SHIFT_MSK (0xf << 8)
+#define NFC_PAGE_SHIFT(x) (((x) < 10 ? 0 : (x) - 10) << 8)
+#define NFC_PAGE_SIZE(a) ((fls(a) - 11) << 8)
+#define NFC_SAM BIT(12)
+#define NFC_RAM_METHOD BIT(14)
+#define NFC_DEBUG_CTL BIT(31)
+
+/* define bit use in NFC_ST */
+#define NFC_RB_B2R BIT(0)
+#define NFC_CMD_INT_FLAG BIT(1)
+#define NFC_DMA_INT_FLAG BIT(2)
+#define NFC_CMD_FIFO_STATUS BIT(3)
+#define NFC_STA BIT(4)
+#define NFC_NATCH_INT_FLAG BIT(5)
+#define NFC_RB_STATE(x) BIT((x) + 8)
+
+/* define bit use in NFC_INT */
+#define NFC_B2R_INT_ENABLE BIT(0)
+#define NFC_CMD_INT_ENABLE BIT(1)
+#define NFC_DMA_INT_ENABLE BIT(2)
+#define NFC_INT_MASK (NFC_B2R_INT_ENABLE | \
+ NFC_CMD_INT_ENABLE | \
+ NFC_DMA_INT_ENABLE)
+
+/* define bit use in NFC_TIMING_CTL */
+#define NFC_TIMING_CTL_EDO BIT(8)
+
+/* define NFC_TIMING_CFG register layout */
+#define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD) \
+ (((tWB) & 0x3) | (((tADL) & 0x3) << 2) | \
+ (((tWHR) & 0x3) << 4) | (((tRHW) & 0x3) << 6) | \
+ (((tCAD) & 0x7) << 8))
+
+/* define bit use in NFC_CMD */
+#define NFC_CMD_LOW_BYTE_MSK 0xff
+#define NFC_CMD_HIGH_BYTE_MSK (0xff << 8)
+#define NFC_CMD(x) (x)
+#define NFC_ADR_NUM_OFFSET 16
+#define NFC_ADR_NUM_MSK (0x7 << NFC_ADR_NUM_OFFSET)
+#define NFC_ADR_NUM(x) (((x) - 1) << NFC_ADR_NUM_OFFSET)
+#define NFC_SEND_ADR BIT(19)
+#define NFC_ACCESS_DIR BIT(20)
+#define NFC_DATA_TRANS BIT(21)
+#define NFC_SEND_CMD1 BIT(22)
+#define NFC_WAIT_FLAG BIT(23)
+#define NFC_SEND_CMD2 BIT(24)
+#define NFC_SEQ BIT(25)
+#define NFC_DATA_SWAP_METHOD BIT(26)
+#define NFC_ROW_AUTO_INC BIT(27)
+#define NFC_SEND_CMD3 BIT(28)
+#define NFC_SEND_CMD4 BIT(29)
+#define NFC_CMD_TYPE_MSK (0x3 << 30)
+#define NFC_NORMAL_OP (0 << 30)
+#define NFC_ECC_OP (1 << 30)
+#define NFC_PAGE_OP (2 << 30)
+
+/* define bit use in NFC_RCMD_SET */
+#define NFC_READ_CMD_OFFSET 0
+#define NFC_READ_CMD_MSK (0xff << NFC_READ_CMD_OFFSET)
+#define NFC_RND_READ_CMD0_OFFSET 8
+#define NFC_RND_READ_CMD0_MSK (0xff << NFC_RND_READ_CMD0_OFFSET)
+#define NFC_RND_READ_CMD1_OFFSET 16
+#define NFC_RND_READ_CMD1_MSK (0xff << NFC_RND_READ_CMD1_OFFSET)
+
+/* define bit use in NFC_WCMD_SET */
+#define NFC_PROGRAM_CMD_MSK 0xff
+#define NFC_RND_WRITE_CMD_MSK (0xff << 8)
+#define NFC_READ_CMD0_MSK (0xff << 16)
+#define NFC_READ_CMD1_MSK (0xff << 24)
+
+/* define bit use in NFC_ECC_CTL */
+#define NFC_ECC_EN BIT(0)
+#define NFC_ECC_PIPELINE BIT(3)
+#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_ECC_MODE_MSK (0xf << 12)
+#define NFC_ECC_MODE(x) ((x) << 12)
+#define NFC_RANDOM_SEED_MSK (0x7fff << 16)
+#define NFC_RANDOM_SEED(x) ((x) << 16)
+
+/* define bit use in NFC_ECC_ST */
+#define NFC_ECC_ERR(x) BIT(x)
+#define NFC_ECC_PAT_FOUND(x) BIT((x) + 16)
+#define NFC_ECC_ERR_CNT(b, x) (((x) >> ((b) * 8)) & 0xff)
+
+#define NFC_DEFAULT_TIMEOUT_MS 1000
+
+#define NFC_SRAM_SIZE 1024
+
+#define NFC_MAX_CS 7
+
+#endif
diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
index 9f80a8010d7b..f75ea473765e 100644
--- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
@@ -13,50 +13,7 @@
#include <linux/delay.h>
#include <linux/mtd/rawnand.h>
-/* registers */
-#define NFC_REG_CTL 0x00000000
-#define NFC_REG_ST 0x00000004
-#define NFC_REG_ADDR_LOW 0x00000014
-#define NFC_REG_ADDR_HIGH 0x00000018
-#define NFC_REG_CNT 0x00000020
-#define NFC_REG_CMD 0x00000024
-#define NFC_REG_RCMD_SET 0x00000028
-#define NFC_REG_ECC_CTL 0x00000034
-#define NFC_REG_ECC_ST 0x00000038
-#define NFC_REG_SPARE_AREA 0x000000A0
-#define NFC_RAM0_BASE 0x00000400
-#define NFC_RAM1_BASE 0x00000800
-
-#define NFC_EN (1 << 0)
-#define NFC_RESET (1 << 1)
-#define NFC_PAGE_SHIFT_MSK (0xf << 8)
-#define NFC_PAGE_SIZE(a) ((fls(a) - 11) << 8)
-
-#define NFC_ECC_EN (1 << 0)
-#define NFC_ECC_EXCEPTION (1 << 4)
-#define NFC_ECC_BLOCK_512 (1 << 5)
-#define NFC_RANDOM_EN (1 << 9)
-#define NFC_RANDOM_DIRECTION (1 << 10)
-
-#define NFC_ADR_NUM_OFFSET 16
-#define NFC_SEND_ADR (1 << 19)
-#define NFC_ACCESS_DIR (1 << 20)
-#define NFC_DATA_TRANS (1 << 21)
-#define NFC_SEND_CMD1 (1 << 22)
-#define NFC_WAIT_FLAG (1 << 23)
-#define NFC_SEND_CMD2 (1 << 24)
-#define NFC_SEQ (1 << 25)
-#define NFC_DATA_SWAP_METHOD (1 << 26)
-#define NFC_ROW_AUTO_INC (1 << 27)
-#define NFC_SEND_CMD3 (1 << 28)
-#define NFC_SEND_CMD4 (1 << 29)
-#define NFC_NORMAL_OP (0 << 30)
-#define NFC_ECC_OP (1 << 30)
-#define NFC_PAGE_OP (2 << 30)
-
-#define NFC_CMD_INT_FLAG (1 << 1)
-#define NFC_DMA_INT_FLAG (1 << 2)
-#define NFC_CMD_FIFO_STATUS (1 << 3)
+#include "sunxi_nand.h"
#define NFC_READ_CMD_OFFSET 0
#define NFC_RND_READ_CMD0_OFFSET 8
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 07/24] mtd: rawnand: sunxi: cosmetic: add per SoC capabilities
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (5 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 06/24] mtd: rawnand: sunxi: cosmetic: merge register definitions for sunxi_nand{, _spl}.c Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-17 23:10 ` Andre Przywara
2025-10-16 14:27 ` [PATCH 08/24] mtd: rawnand: sunxi: cosmetic: move ECC_ERR_CNT register offset in SoC caps Richard Genoud
` (16 subsequent siblings)
23 siblings, 1 reply; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Introduce per SoC capabilities in sunxi_nand.c
This prepares for the H616 support that has quite a lot differences in
registers offset and capabilities.
Start with the ECC strength table.
No functional change.
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand.c | 18 ++++++++++++++++--
drivers/mtd/nand/raw/sunxi_nand.h | 10 ++++++++++
2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 000ebd0439f1..3f30077b3d15 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -149,6 +149,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
* @clk_rate: NAND controller current clock rate
* @chips: a list containing all the NAND chips attached to
* this NAND controller
+ * @caps: NAND Controller capabilities
*/
struct sunxi_nfc {
struct nand_hw_control controller;
@@ -159,6 +160,7 @@ struct sunxi_nfc {
unsigned long assigned_cs;
unsigned long clk_rate;
struct list_head chips;
+ const struct sunxi_nfc_caps *caps;
};
static inline struct sunxi_nfc *to_sunxi_nfc(struct nand_hw_control *ctrl)
@@ -1270,6 +1272,9 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
struct nand_ecc_ctrl *ecc)
{
static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
+ struct nand_chip *nand = mtd_to_nand(mtd);
+ struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
+ struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
struct sunxi_nand_hw_ecc *data;
struct nand_ecclayout *layout;
int nsectors;
@@ -1292,7 +1297,7 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
}
/* 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
@@ -1303,7 +1308,7 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
}
}
- if (i >= ARRAY_SIZE(strengths)) {
+ if (i >= nfc->caps->nstrengths) {
dev_err(mtd->dev, "unsupported strength\n");
ret = -ENOTSUPP;
goto err;
@@ -1681,6 +1686,10 @@ static int sunxi_nand_probe(struct udevice *dev)
if (!nfc->regs)
return -EINVAL;
+ nfc->caps = (const struct sunxi_nfc_caps *)dev_get_driver_data(dev);
+ if (!nfc->caps)
+ return -EINVAL;
+
ret = reset_get_bulk(dev, &rst_bulk);
if (!ret)
reset_deassert_bulk(&rst_bulk);
@@ -1702,9 +1711,14 @@ static int sunxi_nand_probe(struct udevice *dev)
return 0;
}
+static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
+ .nstrengths = 9,
+};
+
static const struct udevice_id sunxi_nand_ids[] = {
{
.compatible = "allwinner,sun4i-a10-nand",
+ .data = (unsigned long)&sunxi_nfc_a10_caps,
},
{ }
};
diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
index 59803ccc9f22..80fbc8df0090 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.h
+++ b/drivers/mtd/nand/raw/sunxi_nand.h
@@ -153,4 +153,14 @@
#define NFC_MAX_CS 7
+/*
+ * NAND Controller capabilities structure: stores NAND controller capabilities
+ * for distinction between compatible strings.
+ *
+ * @nstrengths: Number of element of ECC strengths array
+ */
+struct sunxi_nfc_caps {
+ unsigned int nstrengths;
+};
+
#endif
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 08/24] mtd: rawnand: sunxi: cosmetic: move ECC_ERR_CNT register offset in SoC caps
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (6 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 07/24] mtd: rawnand: sunxi: cosmetic: add per SoC capabilities Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-17 23:10 ` Andre Przywara
2025-10-16 14:27 ` [PATCH 09/24] mtd: rawnand: sunxi: cosmetic: move USER_DATA " Richard Genoud
` (15 subsequent siblings)
23 siblings, 1 reply; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
ECC_ERR_CNT register offset moved in H616, so let's make it a SoC cap
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand.c | 3 ++-
drivers/mtd/nand/raw/sunxi_nand.h | 5 ++++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 3f30077b3d15..359f6cdda08a 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -737,7 +737,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
return 1;
}
- ret = NFC_ECC_ERR_CNT(0, readl(nfc->regs + NFC_REG_ECC_ERR_CNT(0)));
+ ret = NFC_ECC_ERR_CNT(0, readl(nfc->regs + NFC_REG_ECC_ERR_CNT(nfc, 0)));
memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size);
@@ -1713,6 +1713,7 @@ static int sunxi_nand_probe(struct udevice *dev)
static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
.nstrengths = 9,
+ .reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
};
static const struct udevice_id sunxi_nand_ids[] = {
diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
index 80fbc8df0090..b961f2ef3bf2 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.h
+++ b/drivers/mtd/nand/raw/sunxi_nand.h
@@ -41,7 +41,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
@@ -158,9 +159,11 @@
* for distinction between compatible strings.
*
* @nstrengths: Number of element of ECC strengths array
+ * @reg_ecc_err_cnt: ECC error counter register
*/
struct sunxi_nfc_caps {
unsigned int nstrengths;
+ unsigned int reg_ecc_err_cnt;
};
#endif
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 09/24] mtd: rawnand: sunxi: cosmetic: move USER_DATA register offset in SoC caps
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (7 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 08/24] mtd: rawnand: sunxi: cosmetic: move ECC_ERR_CNT register offset in SoC caps Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-17 23:10 ` Andre Przywara
2025-10-16 14:27 ` [PATCH 10/24] mtd: rawnand: sunxi: cosmetic: move ECC_PAT_FOUND register " Richard Genoud
` (14 subsequent siblings)
23 siblings, 1 reply; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
USER_DATA register offset moved in H616, so let's make it a SoC cap
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand.c | 7 ++++---
drivers/mtd/nand/raw/sunxi_nand.h | 5 ++++-
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 359f6cdda08a..64a0db37f3f0 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -767,7 +767,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
* Retrieve the corrected OOB bytes.
*/
sunxi_nfc_user_data_to_buf(readl(nfc->regs +
- NFC_REG_USER_DATA(0)),
+ NFC_REG_USER_DATA(nfc, 0)),
oob);
/* De-randomize the Bad Block Marker. */
@@ -838,10 +838,10 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
memcpy(user_data, oob, 4);
sunxi_nfc_randomize_bbm(mtd, page, user_data);
writel(sunxi_nfc_buf_to_user_data(user_data),
- nfc->regs + NFC_REG_USER_DATA(0));
+ nfc->regs + NFC_REG_USER_DATA(nfc, 0));
} else {
writel(sunxi_nfc_buf_to_user_data(oob),
- nfc->regs + NFC_REG_USER_DATA(0));
+ nfc->regs + NFC_REG_USER_DATA(nfc, 0));
}
if (data_off + ecc->size != oob_off)
@@ -1714,6 +1714,7 @@ static int sunxi_nand_probe(struct udevice *dev)
static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
.nstrengths = 9,
.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
+ .reg_user_data = NFC_REG_A10_USER_DATA,
};
static const struct udevice_id sunxi_nand_ids[] = {
diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
index b961f2ef3bf2..1977d1bd8eaf 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.h
+++ b/drivers/mtd/nand/raw/sunxi_nand.h
@@ -43,7 +43,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_RAM0_BASE 0x0400
@@ -160,10 +161,12 @@
*
* @nstrengths: Number of element of ECC strengths array
* @reg_ecc_err_cnt: ECC error counter register
+ * @reg_user_data: User data register
*/
struct sunxi_nfc_caps {
unsigned int nstrengths;
unsigned int reg_ecc_err_cnt;
+ unsigned int reg_user_data;
};
#endif
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 10/24] mtd: rawnand: sunxi: cosmetic: move ECC_PAT_FOUND register in SoC caps
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (8 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 09/24] mtd: rawnand: sunxi: cosmetic: move USER_DATA " Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-17 23:11 ` Andre Przywara
2025-10-16 14:27 ` [PATCH 11/24] mtd: rawnand: sunxi: cosmetic: add has_ecc_block_512 capability Richard Genoud
` (13 subsequent siblings)
23 siblings, 1 reply; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Move ECC_PAT_FOUND register in SoC capabilities structure
This register offset moved in H616, it's now its own register, not
shared with NFC_ECC_ST.
Push that specificity in caps structure.
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand.c | 9 +++++++--
drivers/mtd/nand/raw/sunxi_nand.h | 16 +++++++++++++++-
2 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 64a0db37f3f0..869b3ddd971c 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -699,6 +699,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
struct nand_ecc_ctrl *ecc = &nand->ecc;
int raw_mode = 0;
u32 status;
+ u32 pattern_found;
int ret;
if (*cur_off != data_off)
@@ -724,8 +725,9 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
*cur_off = oob_off + ecc->bytes + 4;
- status = readl(nfc->regs + NFC_REG_ECC_ST);
- if (status & NFC_ECC_PAT_FOUND(0)) {
+ pattern_found = readl(nfc->regs + nfc->caps->reg_pat_found);
+ pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found);
+ if (pattern_found & NFC_ECC_PAT_FOUND(0)) {
u8 pattern = 0xff;
if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1)))
@@ -744,6 +746,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4, true, page);
+ status = readl(nfc->regs + NFC_REG_ECC_ST);
if (status & NFC_ECC_ERR(0)) {
/*
* Re-read the data with the randomizer disabled to identify
@@ -1715,6 +1718,8 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
.nstrengths = 9,
.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),
};
static const struct udevice_id sunxi_nand_ids[] = {
diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
index 1977d1bd8eaf..35079d37bb1f 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.h
+++ b/drivers/mtd/nand/raw/sunxi_nand.h
@@ -25,6 +25,9 @@
#include <linux/bitops.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
@@ -146,7 +149,14 @@
/* define bit use in NFC_ECC_ST */
#define NFC_ECC_ERR(x) BIT(x)
-#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(x) BIT(x)
+#define NFC_ECC_PAT_FOUND_MSK(nfc) ((nfc)->caps->pat_found_mask)
+
#define NFC_ECC_ERR_CNT(b, x) (((x) >> ((b) * 8)) & 0xff)
#define NFC_DEFAULT_TIMEOUT_MS 1000
@@ -162,11 +172,15 @@
* @nstrengths: Number of element of ECC strengths array
* @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
*/
struct sunxi_nfc_caps {
unsigned int nstrengths;
unsigned int reg_ecc_err_cnt;
unsigned int reg_user_data;
+ unsigned int reg_pat_found;
+ unsigned int pat_found_mask;
};
#endif
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 11/24] mtd: rawnand: sunxi: cosmetic: add has_ecc_block_512 capability
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (9 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 10/24] mtd: rawnand: sunxi: cosmetic: move ECC_PAT_FOUND register " Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-17 23:11 ` Andre Przywara
2025-10-16 14:27 ` [PATCH 12/24] mtd: rawnand: sunxi: cosmetic: move NFC_ECC_MODE offset in SoC caps Richard Genoud
` (12 subsequent siblings)
23 siblings, 1 reply; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Introduce has_ecc_block_512 capability
The 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 +++++++++++---
drivers/mtd/nand/raw/sunxi_nand.h | 2 ++
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 869b3ddd971c..fddb1cada023 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -660,11 +660,12 @@ static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd)
u32 ecc_ctl;
ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
- ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE |
- NFC_ECC_BLOCK_SIZE_MSK);
+ ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE);
+ if (nfc->caps->has_ecc_block_512)
+ ecc_ctl &= ~NFC_ECC_BLOCK_SIZE_MSK;
ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION;
- if (nand->ecc.size == 512)
+ if (nand->ecc.size == 512 && nfc->caps->has_ecc_block_512)
ecc_ctl |= NFC_ECC_BLOCK_512;
writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL);
@@ -1454,6 +1455,8 @@ static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc)
{
struct nand_chip *nand = mtd_to_nand(mtd);
+ struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
+ struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
int ret;
if (!ecc->size) {
@@ -1464,6 +1467,10 @@ static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc)
if (!ecc->size || !ecc->strength)
return -EINVAL;
+ /* If 512B ECC is not supported, switch to 1024 */
+ if (ecc->size == 512 && !nfc->caps->has_ecc_block_512)
+ ecc->size = 1024;
+
switch (ecc->mode) {
case NAND_ECC_SOFT_BCH:
break;
@@ -1715,6 +1722,7 @@ static int sunxi_nand_probe(struct udevice *dev)
}
static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
+ .has_ecc_block_512 = true,
.nstrengths = 9,
.reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
.reg_user_data = NFC_REG_A10_USER_DATA,
diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
index 35079d37bb1f..be294d7cea0a 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.h
+++ b/drivers/mtd/nand/raw/sunxi_nand.h
@@ -169,6 +169,7 @@
* NAND Controller capabilities structure: stores NAND controller capabilities
* for distinction between compatible strings.
*
+ * @has_ecc_block_512: If the ECC can handle 512B or only 1024B chuncks
* @nstrengths: Number of element of ECC strengths array
* @reg_ecc_err_cnt: ECC error counter register
* @reg_user_data: User data register
@@ -176,6 +177,7 @@
* @pat_found_mask: ECC_PAT_FOUND mask in NFC_REG_PAT_FOUND register
*/
struct sunxi_nfc_caps {
+ bool has_ecc_block_512;
unsigned int nstrengths;
unsigned int reg_ecc_err_cnt;
unsigned int reg_user_data;
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 12/24] mtd: rawnand: sunxi: cosmetic: move NFC_ECC_MODE offset in SoC caps
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (10 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 11/24] mtd: rawnand: sunxi: cosmetic: add has_ecc_block_512 capability Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-16 14:27 ` [PATCH 13/24] mtd: rawnand: sunxi: cosmetic: introduce reg_pat_id in sunxi_nfc_caps Richard Genoud
` (11 subsequent siblings)
23 siblings, 0 replies; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
NFC_ECC_MODE register offset moved in H616, so let's make it a SoC cap
No functional change.
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand.c | 6 ++++--
drivers/mtd/nand/raw/sunxi_nand.h | 9 ++++++---
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index fddb1cada023..fd74aa290c92 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -660,10 +660,11 @@ static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd)
u32 ecc_ctl;
ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
- ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE);
+ ecc_ctl &= ~(NFC_ECC_MODE_MSK(nfc) | NFC_ECC_PIPELINE);
if (nfc->caps->has_ecc_block_512)
ecc_ctl &= ~NFC_ECC_BLOCK_SIZE_MSK;
- ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION;
+ ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(nfc, data->mode)
+ | NFC_ECC_EXCEPTION;
if (nand->ecc.size == 512 && nfc->caps->has_ecc_block_512)
ecc_ctl |= NFC_ECC_BLOCK_512;
@@ -1728,6 +1729,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
.reg_user_data = NFC_REG_A10_USER_DATA,
.reg_pat_found = NFC_REG_ECC_ST,
.pat_found_mask = GENMASK(31, 16),
+ .ecc_mode_mask = GENMASK(15, 12),
};
static const struct udevice_id sunxi_nand_ids[] = {
diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
index be294d7cea0a..069beaa5289d 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.h
+++ b/drivers/mtd/nand/raw/sunxi_nand.h
@@ -25,8 +25,9 @@
#include <linux/bitops.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
@@ -142,8 +143,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 (0xf << 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 (0x7fff << 16)
#define NFC_RANDOM_SEED(x) ((x) << 16)
@@ -175,6 +176,7 @@
* @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
+ * @ecc_mode_mask: ECC_MODE mask in NFC_ECC_CTL register
*/
struct sunxi_nfc_caps {
bool has_ecc_block_512;
@@ -183,6 +185,7 @@ struct sunxi_nfc_caps {
unsigned int reg_user_data;
unsigned int reg_pat_found;
unsigned int pat_found_mask;
+ unsigned int ecc_mode_mask;
};
#endif
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 13/24] mtd: rawnand: sunxi: cosmetic: introduce reg_pat_id in sunxi_nfc_caps
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (11 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 12/24] mtd: rawnand: sunxi: cosmetic: move NFC_ECC_MODE offset in SoC caps Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-16 14:27 ` [PATCH 14/24] mtd: rawnand: sunxi_spl: cosmetic: add per SoC capabilities Richard Genoud
` (10 subsequent siblings)
23 siblings, 0 replies; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Introduce NDFC Pattern ID Register in capability structure
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 | 3 ++-
drivers/mtd/nand/raw/sunxi_nand.h | 5 ++++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index fd74aa290c92..1b429e1cbb20 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -732,7 +732,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
if (pattern_found & NFC_ECC_PAT_FOUND(0)) {
u8 pattern = 0xff;
- if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1)))
+ if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID(nfc)) & 0x1)))
pattern = 0x0;
memset(data, pattern, ecc->size);
@@ -1728,6 +1728,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,
+ .reg_pat_id = NFC_REG_A10_PAT_ID,
.pat_found_mask = GENMASK(31, 16),
.ecc_mode_mask = GENMASK(15, 12),
};
diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
index 069beaa5289d..a0ce098db3f9 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.h
+++ b/drivers/mtd/nand/raw/sunxi_nand.h
@@ -50,7 +50,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_RAM0_BASE 0x0400
#define NFC_RAM1_BASE 0x0800
@@ -174,6 +175,7 @@
* @nstrengths: Number of element of ECC strengths array
* @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
* @pat_found_mask: ECC_PAT_FOUND mask in NFC_REG_PAT_FOUND register
* @ecc_mode_mask: ECC_MODE mask in NFC_ECC_CTL register
@@ -183,6 +185,7 @@ struct sunxi_nfc_caps {
unsigned int nstrengths;
unsigned int reg_ecc_err_cnt;
unsigned int reg_user_data;
+ unsigned int reg_pat_id;
unsigned int reg_pat_found;
unsigned int pat_found_mask;
unsigned int ecc_mode_mask;
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 14/24] mtd: rawnand: sunxi_spl: cosmetic: add per SoC capabilities
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (12 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 13/24] mtd: rawnand: sunxi: cosmetic: introduce reg_pat_id in sunxi_nfc_caps Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-16 14:27 ` [PATCH 15/24] mtd: rawnand: sunxi: cosmetic: move NFC_RANDOM_EN register offset in SoC caps Richard Genoud
` (9 subsequent siblings)
23 siblings, 0 replies; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Introduce per SoC capabilities in sunxi_nand_spl.c
Prepare for the H616 support that has quite a lot of differences in
registers offset and capabilities.
Start with the 512 bytes ECC capability.
No functional change.
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand_spl.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
index f75ea473765e..6879890c1536 100644
--- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
@@ -27,6 +27,7 @@ struct nfc_config {
int nseeds;
bool randomize;
bool valid;
+ const struct sunxi_nfc_caps *caps;
};
/* minimal "boot0" style NAND support for Allwinner A20 */
@@ -51,6 +52,10 @@ const uint16_t random_seed[128] = {
0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db,
};
+__maybe_unused static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
+ .has_ecc_block_512 = true,
+};
+
#define DEFAULT_TIMEOUT_US 100000
static int check_value_inner(int offset, int expected_bits,
@@ -211,12 +216,16 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
int data_off = i * conf->ecc_size;
int oob_off = conf->page_size + (i * oob_chunk_sz);
u8 *data = dest + data_off;
+ u32 ecc512_bit = 0;
+
+ if (conf->caps->has_ecc_block_512 && conf->ecc_size == 512)
+ ecc512_bit = NFC_ECC_BLOCK_512;
/* Clear ECC status and restart ECC engine */
writel(0, SUNXI_NFC_BASE + NFC_REG_ECC_ST);
writel((rand_seed << 16) | (conf->ecc_strength << 12) |
(conf->randomize ? NFC_RANDOM_EN : 0) |
- (conf->ecc_size == 512 ? NFC_ECC_BLOCK_512 : 0) |
+ ecc512_bit |
NFC_ECC_EN | NFC_ECC_EXCEPTION,
SUNXI_NFC_BASE + NFC_REG_ECC_CTL);
@@ -380,6 +389,8 @@ static int nand_detect_config(struct nfc_config *conf, u32 offs, void *dest)
if (conf->valid)
return 0;
+ conf->caps = &sunxi_nfc_a10_caps;
+
/*
* Modern NANDs are more likely than legacy ones, so we start testing
* with 5 address cycles.
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 15/24] mtd: rawnand: sunxi: cosmetic: move NFC_RANDOM_EN register offset in SoC caps
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (13 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 14/24] mtd: rawnand: sunxi_spl: cosmetic: add per SoC capabilities Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-16 14:27 ` [PATCH 16/24] mtd: rawnand: sunxi: cosmetic: introduce reg_spare_area in sunxi_nfc_caps Richard Genoud
` (8 subsequent siblings)
23 siblings, 0 replies; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
NFC_RANDOM_{EN,DIRECTION} registers offset moved in H616
Let's make it a SoC capability.
NFC_RANDOM_DIRECTION also moved, but it's unused, just remove it.
No functional change.
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand.c | 5 +++--
drivers/mtd/nand/raw/sunxi_nand.h | 5 +++--
drivers/mtd/nand/raw/sunxi_nand_spl.c | 3 ++-
3 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 1b429e1cbb20..a9fce01fb89c 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -609,7 +609,7 @@ static void sunxi_nfc_randomizer_enable(struct mtd_info *mtd)
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);
}
@@ -621,7 +621,7 @@ static void sunxi_nfc_randomizer_disable(struct mtd_info *mtd)
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);
}
@@ -1731,6 +1731,7 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
.reg_pat_id = NFC_REG_A10_PAT_ID,
.pat_found_mask = GENMASK(31, 16),
.ecc_mode_mask = GENMASK(15, 12),
+ .random_en_mask = BIT(9),
};
static const struct udevice_id sunxi_nand_ids[] = {
diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
index a0ce098db3f9..99bee478665f 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.h
+++ b/drivers/mtd/nand/raw/sunxi_nand.h
@@ -142,8 +142,7 @@
#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_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 (0x7fff << 16)
@@ -179,6 +178,7 @@
* @reg_pat_found: Data Pattern Status Register
* @pat_found_mask: ECC_PAT_FOUND mask in NFC_REG_PAT_FOUND register
* @ecc_mode_mask: ECC_MODE mask in NFC_ECC_CTL register
+ * @random_en_mask: RANDOM_EN mask in NFC_ECC_CTL register
*/
struct sunxi_nfc_caps {
bool has_ecc_block_512;
@@ -189,6 +189,7 @@ struct sunxi_nfc_caps {
unsigned int reg_pat_found;
unsigned int pat_found_mask;
unsigned int ecc_mode_mask;
+ unsigned int random_en_mask;
};
#endif
diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
index 6879890c1536..714518d67740 100644
--- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
@@ -54,6 +54,7 @@ const uint16_t random_seed[128] = {
__maybe_unused static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
.has_ecc_block_512 = true,
+ .random_en_mask = BIT(9),
};
#define DEFAULT_TIMEOUT_US 100000
@@ -224,7 +225,7 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
/* Clear ECC status and restart ECC engine */
writel(0, SUNXI_NFC_BASE + NFC_REG_ECC_ST);
writel((rand_seed << 16) | (conf->ecc_strength << 12) |
- (conf->randomize ? NFC_RANDOM_EN : 0) |
+ (conf->randomize ? NFC_RANDOM_EN(conf) : 0) |
ecc512_bit |
NFC_ECC_EN | NFC_ECC_EXCEPTION,
SUNXI_NFC_BASE + NFC_REG_ECC_CTL);
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 16/24] mtd: rawnand: sunxi: cosmetic: introduce reg_spare_area in sunxi_nfc_caps
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (14 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 15/24] mtd: rawnand: sunxi: cosmetic: move NFC_RANDOM_EN register offset in SoC caps Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-16 14:27 ` [PATCH 17/24] mtd: rawnand: sunxi_spl: use NFC_ECC_ERR_MSK and NFC_ECC_PAT_FOUND Richard Genoud
` (7 subsequent siblings)
23 siblings, 0 replies; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Introduce NDFC Spare Area Register offset in SoC capabilities
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 | 3 ++-
drivers/mtd/nand/raw/sunxi_nand.h | 7 +++++--
drivers/mtd/nand/raw/sunxi_nand_spl.c | 3 ++-
3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index a9fce01fb89c..58c895095ce9 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -329,7 +329,7 @@ static void sunxi_nfc_select_chip(struct mtd_info *mtd, int chip)
ctl |= NFC_RB_SEL(sel->rb.info.nativeid);
}
- 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) {
sunxi_nfc_set_clk_rate(sunxi_nand->clk_rate);
@@ -1728,6 +1728,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,
+ .reg_spare_area = NFC_REG_A10_SPARE_AREA,
.reg_pat_id = NFC_REG_A10_PAT_ID,
.pat_found_mask = GENMASK(31, 16),
.ecc_mode_mask = GENMASK(15, 12),
diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
index 99bee478665f..a8224d1f7c85 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.h
+++ b/drivers/mtd/nand/raw/sunxi_nand.h
@@ -49,8 +49,9 @@
#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_PAT_ID(nfc) ((nfc)->caps->reg_pat_id)
+#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_RAM0_BASE 0x0400
#define NFC_RAM1_BASE 0x0800
@@ -174,6 +175,7 @@
* @nstrengths: Number of element of ECC strengths array
* @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
* @pat_found_mask: ECC_PAT_FOUND mask in NFC_REG_PAT_FOUND register
@@ -185,6 +187,7 @@ struct sunxi_nfc_caps {
unsigned int nstrengths;
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 pat_found_mask;
diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
index 714518d67740..bb0dbd9977f5 100644
--- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
@@ -54,6 +54,7 @@ const uint16_t random_seed[128] = {
__maybe_unused static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
.has_ecc_block_512 = true,
+ .reg_spare_area = NFC_REG_A10_SPARE_AREA,
.random_en_mask = BIT(9),
};
@@ -151,7 +152,7 @@ static void nand_apply_config(const struct nfc_config *conf)
writel(val | NFC_PAGE_SIZE(conf->page_size),
SUNXI_NFC_BASE + NFC_REG_CTL);
writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_REG_CNT);
- writel(conf->page_size, SUNXI_NFC_BASE + NFC_REG_SPARE_AREA);
+ writel(conf->page_size, SUNXI_NFC_BASE + NFC_REG_SPARE_AREA(conf));
}
static int nand_load_page(const struct nfc_config *conf, u32 offs)
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 17/24] mtd: rawnand: sunxi_spl: use NFC_ECC_ERR_MSK and NFC_ECC_PAT_FOUND
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (15 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 16/24] mtd: rawnand: sunxi: cosmetic: introduce reg_spare_area in sunxi_nfc_caps Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-16 14:27 ` [PATCH 18/24] mtd: rawnand: sunxi_spl: increase max_oobsize for 2KiB pages Richard Genoud
` (6 subsequent siblings)
23 siblings, 0 replies; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Use defines instead of hardcoded values for NFC_ECC_{ERR_MSK,PAT_FOUND}
SPL is using hard coded values for ECC error detection and empty chunk
detection.
The H6/H616 registers for that have changed, the pattern found is no
more in the NFC_REG_ECC_ST register.
So, don't presume anymore that pattern_found is in NFC_REG_ECC_ST, and
read the pattern_found register to get this information.
Apart from an additional register reading, no functional change.
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand.h | 3 +++
drivers/mtd/nand/raw/sunxi_nand_spl.c | 21 +++++++++++++++------
2 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
index a8224d1f7c85..52200468d343 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.h
+++ b/drivers/mtd/nand/raw/sunxi_nand.h
@@ -151,6 +151,7 @@
/* define bit use in NFC_ECC_ST */
#define NFC_ECC_ERR(x) BIT(x)
+#define NFC_ECC_ERR_MSK(nfc) ((nfc)->caps->ecc_err_mask)
/*
* define bit use in NFC_REG_PAT_FOUND
@@ -178,6 +179,7 @@
* @reg_spare_area: Spare Area Register
* @reg_pat_id: Pattern ID Register
* @reg_pat_found: Data Pattern Status Register
+ * @ecc_err_mask: ERR_ERR mask in NFC_ECC_ST register
* @pat_found_mask: ECC_PAT_FOUND mask in NFC_REG_PAT_FOUND register
* @ecc_mode_mask: ECC_MODE mask in NFC_ECC_CTL register
* @random_en_mask: RANDOM_EN mask in NFC_ECC_CTL register
@@ -191,6 +193,7 @@ struct sunxi_nfc_caps {
unsigned int reg_pat_id;
unsigned int reg_pat_found;
unsigned int pat_found_mask;
+ unsigned int ecc_err_mask;
unsigned int ecc_mode_mask;
unsigned int random_en_mask;
};
diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
index bb0dbd9977f5..544b46ce1d21 100644
--- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
@@ -55,6 +55,9 @@ const uint16_t random_seed[128] = {
__maybe_unused static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
.has_ecc_block_512 = true,
.reg_spare_area = NFC_REG_A10_SPARE_AREA,
+ .reg_pat_found = NFC_REG_ECC_ST,
+ .pat_found_mask = GENMASK(31, 16),
+ .ecc_err_mask = GENMASK(15, 0),
.random_en_mask = BIT(9),
};
@@ -202,7 +205,7 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
u16 rand_seed = 0;
int oob_chunk_sz = ecc_bytes[conf->ecc_strength];
int page = offs / conf->page_size;
- u32 ecc_st;
+ u32 ecc_st, pattern_found;
int i;
if (offs % conf->page_size || len % conf->ecc_size ||
@@ -247,15 +250,21 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
ecc_st = readl(SUNXI_NFC_BASE + NFC_REG_ECC_ST);
/* ECC error detected. */
- if (ecc_st & 0xffff)
+ if (ecc_st & NFC_ECC_ERR_MSK(conf))
return -EIO;
/*
- * Return 1 if the first chunk is empty (needed for
- * configuration detection).
+ * Return 1 if the first chunk is empty (all 00 or ff)
+ * (needed for configuration detection).
*/
- if (!i && (ecc_st & 0x10000))
- return 1;
+ if (!i) {
+ pattern_found = readl(SUNXI_NFC_BASE +
+ conf->caps->reg_pat_found);
+ pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(conf),
+ pattern_found);
+ if (pattern_found & NFC_ECC_PAT_FOUND(0))
+ return 1;
+ }
/* Retrieve the data from SRAM */
memcpy_fromio(data,
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 18/24] mtd: rawnand: sunxi_spl: increase max_oobsize for 2KiB pages
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (16 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 17/24] mtd: rawnand: sunxi_spl: use NFC_ECC_ERR_MSK and NFC_ECC_PAT_FOUND Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-16 14:27 ` [PATCH 19/24] mtd: rawnand: sunxi_spl: cosmetic: use NFC_ECC_MODE and NFC_RANDOM_SEED macros Richard Genoud
` (5 subsequent siblings)
23 siblings, 0 replies; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Increase max_oobsize to take into account bigger OOB on 2KiB pages
Some NAND chip (e.g. Kioxia TC58NVG1S3HTA00) have a 2KiB page size +
128 bytes OOB.
In order to detect them, the max_oobsize has to be increased from 64 to
128 bytes.
Tested on Kioxia TC58NVG1S3HTA00 NAND chip on Whatsminer H616 board.
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand_spl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
index 544b46ce1d21..42899c9417c5 100644
--- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
@@ -294,7 +294,7 @@ static int nand_max_ecc_strength(struct nfc_config *conf)
*/
switch (conf->page_size) {
case 2048:
- max_oobsize = 64;
+ max_oobsize = 128;
break;
case 4096:
max_oobsize = 256;
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 19/24] mtd: rawnand: sunxi_spl: cosmetic: use NFC_ECC_MODE and NFC_RANDOM_SEED macros
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (17 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 18/24] mtd: rawnand: sunxi_spl: increase max_oobsize for 2KiB pages Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-16 14:27 ` [PATCH 20/24] sunxi: clock: H6: add NAND controller clock registers Richard Genoud
` (4 subsequent siblings)
23 siblings, 0 replies; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Use generic macros for ECC_MODE and RANDOM_SEED
As H6/H616 registers are different, use more generic macros than hard
coded values specific to A10-like SoC.
No functional changes.
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand_spl.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
index 42899c9417c5..0698db95b9c2 100644
--- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
@@ -57,6 +57,7 @@ __maybe_unused static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
.reg_spare_area = NFC_REG_A10_SPARE_AREA,
.reg_pat_found = NFC_REG_ECC_ST,
.pat_found_mask = GENMASK(31, 16),
+ .ecc_mode_mask = GENMASK(15, 12),
.ecc_err_mask = GENMASK(15, 0),
.random_en_mask = BIT(9),
};
@@ -228,7 +229,9 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
/* Clear ECC status and restart ECC engine */
writel(0, SUNXI_NFC_BASE + NFC_REG_ECC_ST);
- writel((rand_seed << 16) | (conf->ecc_strength << 12) |
+
+ writel(NFC_RANDOM_SEED(rand_seed) |
+ NFC_ECC_MODE(conf, conf->ecc_strength) |
(conf->randomize ? NFC_RANDOM_EN(conf) : 0) |
ecc512_bit |
NFC_ECC_EN | NFC_ECC_EXCEPTION,
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 20/24] sunxi: clock: H6: add NAND controller clock registers
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (18 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 19/24] mtd: rawnand: sunxi_spl: cosmetic: use NFC_ECC_MODE and NFC_RANDOM_SEED macros Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-16 14:27 ` [PATCH 21/24] clk: sunxi: Add MBUS Master Clock Gating Register Richard Genoud
` (3 subsequent siblings)
23 siblings, 0 replies; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Add missing NAND controller-related clock registers
The NAND controller on H6/H616 uses one clock for its internal logic
(NAND0_CLK) and one clock for ECC engine (NAND1_CLK) in addition to AHB
and MBUS clocks.
As NAND{0,1}_CLKs and MBUS_GATE are missing, add them.
The bit locations are from H616/H6 User Manual.
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
.../include/asm/arch-sunxi/clock_sun50i_h6.h | 24 +++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
index 45fa4ab6e57c..8d1c7c185486 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun50i_h6.h
@@ -24,7 +24,11 @@
#define CCU_H6_APB2_CFG 0x524
#define CCU_H6_MBUS_CFG 0x540
#define CCU_H6_DRAM_CLK_CFG 0x800
+#define CCU_H6_MBUS_GATE 0x804
#define CCU_H6_DRAM_GATE_RESET 0x80c
+#define CCU_NAND0_CLK_CFG 0x810
+#define CCU_NAND1_CLK_CFG 0x814
+#define CCU_H6_NAND_GATE_RESET 0x82c
#define CCU_MMC0_CLK_CFG 0x830
#define CCU_MMC1_CLK_CFG 0x834
#define CCU_MMC2_CLK_CFG 0x838
@@ -146,6 +150,16 @@
#define RESET_SHIFT (16)
#define GATE_SHIFT (0)
+/* MBUS gate offsets */
+#define MBUS_GATE_OFFSET_DI 11
+#define MBUS_GATE_OFFSET_G2D 10
+#define MBUS_GATE_OFFSET_CSI 8
+#define MBUS_GATE_OFFSET_NAND 5
+#define MBUS_GATE_OFFSET_TS0 3
+#define MBUS_GATE_OFFSET_VE 2
+#define MBUS_GATE_OFFSET_CE 1
+#define MBUS_GATE_OFFSET_DMA 0
+
/* DRAM clock bit field */
#define DRAM_CLK_ENABLE BIT(31)
#define DRAM_MOD_RESET BIT(30)
@@ -155,6 +169,16 @@
#define DRAM_CLK_M_MASK (0x1f)
#define DRAM_CLK_M(m) (((m)-1) << 0)
+/* NAND clock bit field */
+#define CCM_NAND_CTRL_M(x) ((x) - 1)
+#define CCM_NAND_CTRL_N(x) ((x) << 8)
+#define CCM_NAND_CTRL_OSCM24 (0x0 << 24)
+#define CCM_NAND_CTRL_PLL6 (0x1 << 24)
+#define CCM_NAND_CTRL_PLL_PERIPH2 (0x2 << 24)
+#define CCM_NAND_CTRL_PLL6X2 (0x3 << 24)
+#define CCM_NAND_CTRL_PLL_PERIPH2X2 (0x4 << 24)
+#define CCM_NAND_CTRL_ENABLE (0x1 << 31)
+
/* MMC clock bit field */
#define CCM_MMC_CTRL_M(x) ((x) - 1)
#define CCM_MMC_CTRL_N(x) ((x) << 8)
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 21/24] clk: sunxi: Add MBUS Master Clock Gating Register
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (19 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 20/24] sunxi: clock: H6: add NAND controller clock registers Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-16 14:27 ` [PATCH 22/24] mtd: rawnand: sunxi: add support for H6/H616 nand controller Richard Genoud
` (2 subsequent siblings)
23 siblings, 0 replies; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Add MBUS Master Clock Gating Register for H6 and H616
For H6/H616, the NAND controller needs the MBUS NAND clock along with
CLK_NAND0/1 and CLK_BUS_NAND.
The bit locations are from H6/H616 User Manuals.
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/clk/sunxi/clk_h6.c | 2 ++
drivers/clk/sunxi/clk_h616.c | 2 ++
2 files changed, 4 insertions(+)
diff --git a/drivers/clk/sunxi/clk_h6.c b/drivers/clk/sunxi/clk_h6.c
index 1b7bd9dea2f8..81deb5728e5b 100644
--- a/drivers/clk/sunxi/clk_h6.c
+++ b/drivers/clk/sunxi/clk_h6.c
@@ -20,6 +20,8 @@ static struct ccu_clk_gate h6_gates[] = {
[CLK_DE] = GATE(0x600, BIT(31)),
[CLK_BUS_DE] = GATE(0x60c, BIT(0)),
+ [CLK_MBUS_NAND] = GATE(0x804, BIT(5)),
+
[CLK_NAND0] = GATE(0x810, BIT(31)),
[CLK_NAND1] = GATE(0x814, BIT(31)),
[CLK_BUS_NAND] = GATE(0x82c, BIT(0)),
diff --git a/drivers/clk/sunxi/clk_h616.c b/drivers/clk/sunxi/clk_h616.c
index b1e999e18c14..3e7eea25bfe5 100644
--- a/drivers/clk/sunxi/clk_h616.c
+++ b/drivers/clk/sunxi/clk_h616.c
@@ -19,6 +19,8 @@ static struct ccu_clk_gate h616_gates[] = {
[CLK_DE] = GATE(0x600, BIT(31)),
[CLK_BUS_DE] = GATE(0x60c, BIT(0)),
+ [CLK_MBUS_NAND] = GATE(0x804, BIT(5)),
+
[CLK_NAND0] = GATE(0x810, BIT(31)),
[CLK_NAND1] = GATE(0x814, BIT(31)),
[CLK_BUS_NAND] = GATE(0x82c, BIT(0)),
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 22/24] mtd: rawnand: sunxi: add support for H6/H616 nand controller
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (20 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 21/24] clk: sunxi: Add MBUS Master Clock Gating Register Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-20 14:05 ` Richard GENOUD
2025-10-16 14:27 ` [PATCH 23/24] mtd: rawnand: sunxi_spl: " Richard Genoud
2025-10-16 14:27 ` [PATCH 24/24] mtd: rawnand: sunxi_spl: Fix cast to pointer from integer warnings Richard Genoud
23 siblings, 1 reply; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Introduce H6/H616 NAND controller support for U-Boot
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.
Introduce the basic support, with ECC and scrambling, but 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/Kconfig | 3 +-
drivers/mtd/nand/raw/sunxi_nand.c | 112 ++++++++++++++++++++++++++++--
drivers/mtd/nand/raw/sunxi_nand.h | 32 ++++++++-
3 files changed, 139 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 754b99bf3eb6..e4c4d9bcbf63 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -467,7 +467,8 @@ config NAND_SANDBOX
config NAND_SUNXI
bool "Support for NAND on Allwinner SoCs"
default ARCH_SUNXI
- depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUN8I
+ depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUN8I \
+ || MACH_SUN50I_H616
select SYS_NAND_SELF_INIT
select SYS_NAND_U_BOOT_LOCATIONS
select SPL_NAND_SUPPORT
diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
index 58c895095ce9..c9133cdc8844 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.c
+++ b/drivers/mtd/nand/raw/sunxi_nand.c
@@ -170,8 +170,14 @@ static inline struct sunxi_nfc *to_sunxi_nfc(struct nand_hw_control *ctrl)
static void sunxi_nfc_set_clk_rate(unsigned long hz)
{
+#if defined(CONFIG_MACH_SUN50I_H616) || defined(CONFIG_MACH_SUN50I_H6)
+ void * const ccm = (void *)SUNXI_CCM_BASE;
+ void * const nand0_clk_cfg = ccm + CCU_NAND0_CLK_CFG;
+#else
struct sunxi_ccm_reg *const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+ u32 *nand0_clk_cfg = &ccm->nand0_clk_cfg;
+#endif
int div_m, div_n;
div_m = (clock_get_pll6() + hz - 1) / hz;
@@ -186,8 +192,16 @@ static void sunxi_nfc_set_clk_rate(unsigned long hz)
/* config mod clock */
writel(CCM_NAND_CTRL_ENABLE | CCM_NAND_CTRL_PLL6 |
CCM_NAND_CTRL_N(div_n) | CCM_NAND_CTRL_M(div_m),
- &ccm->nand0_clk_cfg);
+ nand0_clk_cfg);
+#if defined(CONFIG_MACH_SUN50I_H616) || defined(CONFIG_MACH_SUN50I_H6)
+ setbits_le32(ccm + CCU_H6_NAND_GATE_RESET,
+ (1 << GATE_SHIFT) | (1 << RESET_SHIFT));
+ setbits_le32(ccm + CCU_H6_MBUS_GATE, (1 << MBUS_GATE_OFFSET_NAND));
+ writel(CCM_NAND_CTRL_ENABLE | CCM_NAND_CTRL_PLL6 |
+ CCM_NAND_CTRL_N(div_n) | CCM_NAND_CTRL_M(div_m),
+ ccm + CCU_NAND1_CLK_CFG);
+#else
/* gate on nand clock */
setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_NAND0));
#ifdef CONFIG_MACH_SUN9I
@@ -195,6 +209,7 @@ static void sunxi_nfc_set_clk_rate(unsigned long hz)
#else
setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_DMA));
#endif
+#endif
}
static int sunxi_nfc_wait_int(struct sunxi_nfc *nfc, u32 flags,
@@ -689,6 +704,53 @@ static inline void sunxi_nfc_user_data_to_buf(u32 user_data, u8 *buf)
buf[3] = user_data >> 24;
}
+/*
+ * On H6/H616 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 int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
u8 *data, int data_off,
u8 *oob, int oob_off,
@@ -716,6 +778,9 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
if (ret)
return ret;
+ sunxi_nfc_reset_user_data_len(nfc);
+ sunxi_nfc_set_user_data_len(nfc, 4, 0);
+
sunxi_nfc_randomizer_enable(mtd);
writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
nfc->regs + NFC_REG_CMD);
@@ -856,6 +921,9 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
if (ret)
return ret;
+ sunxi_nfc_reset_user_data_len(nfc);
+ sunxi_nfc_set_user_data_len(nfc, 4, 0);
+
sunxi_nfc_randomizer_enable(mtd);
writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
NFC_ACCESS_DIR | NFC_ECC_OP,
@@ -1276,7 +1344,6 @@ static int sunxi_nand_chip_init_timings(struct sunxi_nfc *nfc,
static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
struct nand_ecc_ctrl *ecc)
{
- static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
struct nand_chip *nand = mtd_to_nand(mtd);
struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
@@ -1303,12 +1370,12 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
/* Add ECC info retrieval from DT */
for (i = 0; i < nfc->caps->nstrengths; i++) {
- if (ecc->strength <= strengths[i]) {
+ if (ecc->strength <= nfc->caps->ecc_strengths[i]) {
/*
* Update ecc->strength value with the actual strength
* that will be used by the ECC engine.
*/
- ecc->strength = strengths[i];
+ ecc->strength = nfc->caps->ecc_strengths[i];
break;
}
}
@@ -1722,9 +1789,22 @@ static int sunxi_nand_probe(struct udevice *dev)
return 0;
}
+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,
- .nstrengths = 9,
+ .nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
+ .ecc_strengths = sunxi_ecc_strengths_a10,
.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,
@@ -1733,6 +1813,24 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
.pat_found_mask = GENMASK(31, 16),
.ecc_mode_mask = GENMASK(15, 12),
.random_en_mask = BIT(9),
+ .max_ecc_steps = 16,
+};
+
+static const struct sunxi_nfc_caps sunxi_nfc_h616_caps = {
+ .nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_h6),
+ .ecc_strengths = sunxi_ecc_strengths_h6,
+ .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_pat_found = NFC_REG_H6_PAT_FOUND,
+ .reg_spare_area = NFC_REG_H6_SPARE_AREA,
+ .reg_pat_id = NFC_REG_H6_PAT_ID,
+ .pat_found_mask = GENMASK(31, 0),
+ .ecc_mode_mask = GENMASK(15, 8),
+ .random_en_mask = BIT(5),
+ .user_data_len_tab = sunxi_user_data_len_h6,
+ .nuser_data_tab = ARRAY_SIZE(sunxi_user_data_len_h6),
+ .max_ecc_steps = 32,
};
static const struct udevice_id sunxi_nand_ids[] = {
@@ -1740,6 +1838,10 @@ static const struct udevice_id sunxi_nand_ids[] = {
.compatible = "allwinner,sun4i-a10-nand",
.data = (unsigned long)&sunxi_nfc_a10_caps,
},
+ {
+ .compatible = "allwinner,sun50i-h616-nand-controller",
+ .data = (unsigned long)&sunxi_nfc_h616_caps,
+ },
{ }
};
diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
index 52200468d343..966b743e2613 100644
--- a/drivers/mtd/nand/raw/sunxi_nand.h
+++ b/drivers/mtd/nand/raw/sunxi_nand.h
@@ -44,15 +44,26 @@
#define NFC_REG_IO_DATA 0x0030
#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_A10_USER_DATA 0x0050
+#define NFC_REG_H6_USER_DATA 0x0080
+#define NFC_REG_H6_USER_DATA_LEN 0x0070
#define NFC_REG_USER_DATA(nfc, x) ((nfc)->caps->reg_user_data + ((x) * 4))
+
+/* 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_H6_SPARE_AREA 0x0114
+#define NFC_REG_PAT_ID(nfc) ((nfc)->caps->reg_pat_id)
#define NFC_REG_A10_PAT_ID 0x00A4
+#define NFC_REG_H6_PAT_ID 0x0118
#define NFC_RAM0_BASE 0x0400
#define NFC_RAM1_BASE 0x0800
@@ -162,6 +173,9 @@
#define NFC_ECC_ERR_CNT(b, x) (((x) >> ((b) * 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_SRAM_SIZE 1024
@@ -174,8 +188,10 @@
*
* @has_ecc_block_512: If the ECC can handle 512B or only 1024B chuncks
* @nstrengths: Number of element of ECC strengths array
+ * @ecc_strengths: available ECC strengths array
* @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
@@ -183,12 +199,21 @@
* @pat_found_mask: ECC_PAT_FOUND mask in NFC_REG_PAT_FOUND register
* @ecc_mode_mask: ECC_MODE mask in NFC_ECC_CTL register
* @random_en_mask: RANDOM_EN mask in NFC_ECC_CTL register
+ * @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
+ * @max_ecc_steps: Maximum supported steps for ECC, this is also the
+ * number of user data registers
*/
struct sunxi_nfc_caps {
bool has_ecc_block_512;
unsigned int nstrengths;
+ const u8 *ecc_strengths;
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;
@@ -196,6 +221,9 @@ struct sunxi_nfc_caps {
unsigned int ecc_err_mask;
unsigned int ecc_mode_mask;
unsigned int random_en_mask;
+ const u8 *user_data_len_tab;
+ unsigned int nuser_data_tab;
+ unsigned int max_ecc_steps;
};
#endif
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 23/24] mtd: rawnand: sunxi_spl: add support for H6/H616 nand controller
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (21 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 22/24] mtd: rawnand: sunxi: add support for H6/H616 nand controller Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
2025-10-16 14:27 ` [PATCH 24/24] mtd: rawnand: sunxi_spl: Fix cast to pointer from integer warnings Richard Genoud
23 siblings, 0 replies; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Introduce H6/H616 NAND controller support for SPL
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.
For SPL, most of the work was setting the clocks, adding the new
capability structure for H616 and supporting the new USER_DATA_LEN
registers.
Tested on Whatsminer H616 board (with and without scrambling, ECC)
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
board/sunxi/board.c | 17 ++++-
drivers/mtd/nand/raw/sunxi_nand_spl.c | 96 ++++++++++++++++++++++++++-
2 files changed, 109 insertions(+), 4 deletions(-)
diff --git a/board/sunxi/board.c b/board/sunxi/board.c
index 2929bc17f084..0cb8c4ba9942 100644
--- a/board/sunxi/board.c
+++ b/board/sunxi/board.c
@@ -307,15 +307,30 @@ static void nand_pinmux_setup(void)
static void nand_clock_setup(void)
{
+#if defined(CONFIG_MACH_SUN50I_H616) || defined(CONFIG_MACH_SUN50I_H6)
+ void * const ccm = (void *)SUNXI_CCM_BASE;
+ void * const nand0_clk_cfg = ccm + CCU_NAND0_CLK_CFG;
+#else
struct sunxi_ccm_reg *const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+ u32 *nand0_clk_cfg = &ccm->nand0_clk_cfg;
+#endif
+#if defined(CONFIG_MACH_SUN50I_H616) || defined(CONFIG_MACH_SUN50I_H6)
+ setbits_le32(ccm + CCU_H6_NAND_GATE_RESET,
+ (1 << GATE_SHIFT) | (1 << RESET_SHIFT));
+ setbits_le32(ccm + CCU_H6_MBUS_GATE, (1 << MBUS_GATE_OFFSET_NAND));
+ setbits_le32(ccm + CCU_NAND1_CLK_CFG, CCM_NAND_CTRL_ENABLE |
+ CCM_NAND_CTRL_N(0) | CCM_NAND_CTRL_M(1));
+#else
setbits_le32(&ccm->ahb_gate0, (CLK_GATE_OPEN << AHB_GATE_OFFSET_NAND0));
#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I || \
defined CONFIG_MACH_SUN9I || defined CONFIG_MACH_SUN50I
setbits_le32(&ccm->ahb_reset0_cfg, (1 << AHB_GATE_OFFSET_NAND0));
#endif
- setbits_le32(&ccm->nand0_clk_cfg, CCM_NAND_CTRL_ENABLE | AHB_DIV_1);
+#endif
+ setbits_le32(nand0_clk_cfg, CCM_NAND_CTRL_ENABLE |
+ CCM_NAND_CTRL_N(0) | CCM_NAND_CTRL_M(1));
}
void board_nand_init(void)
diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
index 0698db95b9c2..17e6031a9811 100644
--- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
@@ -52,6 +52,10 @@ const uint16_t random_seed[128] = {
0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db,
};
+static const u8 sunxi_user_data_len_h6[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28, 32
+};
+
__maybe_unused static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
.has_ecc_block_512 = true,
.reg_spare_area = NFC_REG_A10_SPARE_AREA,
@@ -62,6 +66,18 @@ __maybe_unused static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
.random_en_mask = BIT(9),
};
+__maybe_unused static const struct sunxi_nfc_caps sunxi_nfc_h616_caps = {
+ .reg_user_data_len = NFC_REG_H6_USER_DATA_LEN,
+ .reg_spare_area = NFC_REG_H6_SPARE_AREA,
+ .reg_pat_found = NFC_REG_H6_PAT_FOUND,
+ .pat_found_mask = GENMASK(31, 0),
+ .ecc_mode_mask = GENMASK(15, 8),
+ .ecc_err_mask = GENMASK(31, 0),
+ .user_data_len_tab = sunxi_user_data_len_h6,
+ .nuser_data_tab = ARRAY_SIZE(sunxi_user_data_len_h6),
+ .random_en_mask = BIT(5),
+};
+
#define DEFAULT_TIMEOUT_US 100000
static int check_value_inner(int offset, int expected_bits,
@@ -197,7 +213,61 @@ static int nand_change_column(u16 column)
return 0;
}
-static const int ecc_bytes[] = {32, 46, 54, 60, 74, 88, 102, 110, 116};
+/*
+ * On H6/H616 the user_data length has to be set in specific registers
+ * before writing.
+ */
+static void sunxi_nfc_reset_user_data_len(const struct nfc_config *nfc)
+{
+ int loop_step = NFC_REG_USER_DATA_LEN_CAPACITY;
+
+ /* not all SoCs have this register */
+ if (!NFC_REG_USER_DATA_LEN(nfc, 0))
+ return;
+
+ for (int i = 0; i < nfc->caps->max_ecc_steps; i += loop_step)
+ writel(0, SUNXI_NFC_BASE + NFC_REG_USER_DATA_LEN(nfc, i));
+}
+
+static void sunxi_nfc_set_user_data_len(const struct nfc_config *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) {
+ printf("Unsupported length for user data reg: %d\n", len);
+ return;
+ }
+
+ val = readl(SUNXI_NFC_BASE + 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, SUNXI_NFC_BASE + NFC_REG_USER_DATA_LEN(nfc, step));
+}
+
+#if defined(CONFIG_MACH_SUN50I_H616) || defined(CONFIG_MACH_SUN50I_H6)
+static const int ecc_bytes[] = {
+ 32, 46, 54, 60, 74, 82, 88, 96, 102, 110, 116, 124, 130, 138, 144
+};
+#else
+static const int ecc_bytes[] = {
+ 32, 46, 54, 60, 74, 88, 102, 110, 116
+};
+#endif
static int nand_read_page(const struct nfc_config *conf, u32 offs,
void *dest, int len)
@@ -247,8 +317,11 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
* the data.
*/
nand_change_column(oob_off);
- nand_exec_cmd(NFC_DATA_TRANS | NFC_ECC_OP);
+ sunxi_nfc_reset_user_data_len(conf);
+ sunxi_nfc_set_user_data_len(conf, 4, 0);
+
+ nand_exec_cmd(NFC_DATA_TRANS | NFC_ECC_OP);
/* Get the ECC status */
ecc_st = readl(SUNXI_NFC_BASE + NFC_REG_ECC_ST);
@@ -403,7 +476,11 @@ static int nand_detect_config(struct nfc_config *conf, u32 offs, void *dest)
if (conf->valid)
return 0;
+#if defined(CONFIG_MACH_SUN50I_H616) || defined(CONFIG_MACH_SUN50I_H6)
+ conf->caps = &sunxi_nfc_h616_caps;
+#else
conf->caps = &sunxi_nfc_a10_caps;
+#endif
/*
* Modern NANDs are more likely than legacy ones, so we start testing
@@ -504,15 +581,28 @@ unsigned int nand_page_size(void)
void nand_deselect(void)
{
+#if defined(CONFIG_MACH_SUN50I_H616) || defined(CONFIG_MACH_SUN50I_H6)
+ void * const ccm = (void *)SUNXI_CCM_BASE;
+ void * const nand0_clk_cfg = ccm + CCU_NAND0_CLK_CFG;
+#else
struct sunxi_ccm_reg *const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
+ u32 *nand0_clk_cfg = &ccm->nand0_clk_cfg;
+#endif
+#if defined(CONFIG_MACH_SUN50I_H616) || defined(CONFIG_MACH_SUN50I_H6)
+ clrbits_le32(ccm + CCU_H6_NAND_GATE_RESET,
+ (1 << GATE_SHIFT) | (1 << RESET_SHIFT));
+ clrbits_le32(ccm + CCU_H6_MBUS_GATE, (1 << MBUS_GATE_OFFSET_NAND));
+ clrbits_le32(ccm + CCU_NAND1_CLK_CFG, CCM_NAND_CTRL_ENABLE);
+#else
clrbits_le32(&ccm->ahb_gate0, (CLK_GATE_OPEN << AHB_GATE_OFFSET_NAND0));
#ifdef CONFIG_MACH_SUN9I
clrbits_le32(&ccm->ahb_gate1, (1 << AHB_GATE_OFFSET_DMA));
#else
clrbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_DMA));
#endif
- clrbits_le32(&ccm->nand0_clk_cfg, CCM_NAND_CTRL_ENABLE |
+#endif
+ clrbits_le32(nand0_clk_cfg, CCM_NAND_CTRL_ENABLE |
CCM_NAND_CTRL_N(0) | CCM_NAND_CTRL_M(1));
}
^ permalink raw reply related [flat|nested] 43+ messages in thread
* [PATCH 24/24] mtd: rawnand: sunxi_spl: Fix cast to pointer from integer warnings
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
` (22 preceding siblings ...)
2025-10-16 14:27 ` [PATCH 23/24] mtd: rawnand: sunxi_spl: " Richard Genoud
@ 2025-10-16 14:27 ` Richard Genoud
23 siblings, 0 replies; 43+ messages in thread
From: Richard Genoud @ 2025-10-16 14:27 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot,
Richard Genoud
Fix a cast to pointer from integer warning on ARM64
On 64bits platform, the casts done in {read,write}l() give that kind of
warnings:
drivers/mtd/nand/raw/sunxi_nand_spl.c: In function ‘check_value_inner’:
./arch/arm/include/asm/io.h:110:43: warning: cast to pointer from \
integer of different size [-Wint-to-pointer-cast]
110 | #define __raw_readl(a) (*(volatile unsigned int *)(a))
| ^
[...]
drivers/mtd/nand/raw/sunxi_nand_spl.c:81:27: note: in expansion of \
macro ‘readl’
81 | int val = readl(offset) & expected_bits;
Introduce {read,write}l_nfc inline function to do the right cast and
push the base address (SUNXI_NFC_BASE) into those functions, making the
code more readable.
Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
---
drivers/mtd/nand/raw/sunxi_nand_spl.c | 97 +++++++++++++++------------
1 file changed, 53 insertions(+), 44 deletions(-)
diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
index 17e6031a9811..8f5057f2841b 100644
--- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
+++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
@@ -80,11 +80,25 @@ __maybe_unused static const struct sunxi_nfc_caps sunxi_nfc_h616_caps = {
#define DEFAULT_TIMEOUT_US 100000
+static inline u32 readl_nfc(u32 offset)
+{
+ void * __iomem base = (void *)(uintptr_t)SUNXI_NFC_BASE;
+
+ return readl(base + offset);
+}
+
+static inline u32 writel_nfc(u32 val, u32 offset)
+{
+ void * __iomem base = (void *)(uintptr_t)SUNXI_NFC_BASE;
+
+ return writel(val, base + offset);
+}
+
static int check_value_inner(int offset, int expected_bits,
int timeout_us, int negation)
{
do {
- int val = readl(offset) & expected_bits;
+ int val = readl_nfc(offset) & expected_bits;
if (negation ? !val : val)
return 1;
udelay(1);
@@ -107,8 +121,8 @@ static inline int check_value_negated(int offset, int unexpected_bits,
static int nand_wait_cmd_fifo_empty(void)
{
- if (!check_value_negated(SUNXI_NFC_BASE + NFC_REG_ST,
- NFC_CMD_FIFO_STATUS, DEFAULT_TIMEOUT_US)) {
+ if (!check_value_negated(NFC_REG_ST, NFC_CMD_FIFO_STATUS,
+ DEFAULT_TIMEOUT_US)) {
printf("nand: timeout waiting for empty cmd FIFO\n");
return -ETIMEDOUT;
}
@@ -118,7 +132,7 @@ static int nand_wait_cmd_fifo_empty(void)
static int nand_wait_int(void)
{
- if (!check_value(SUNXI_NFC_BASE + NFC_REG_ST, NFC_CMD_INT_FLAG,
+ if (!check_value(NFC_REG_ST, NFC_CMD_INT_FLAG,
DEFAULT_TIMEOUT_US)) {
printf("nand: timeout waiting for interruption\n");
return -ETIMEDOUT;
@@ -135,8 +149,8 @@ static int nand_exec_cmd(u32 cmd)
if (ret)
return ret;
- writel(NFC_CMD_INT_FLAG, SUNXI_NFC_BASE + NFC_REG_ST);
- writel(cmd, SUNXI_NFC_BASE + NFC_REG_CMD);
+ writel_nfc(NFC_CMD_INT_FLAG, NFC_REG_ST);
+ writel_nfc(cmd, NFC_REG_CMD);
return nand_wait_int();
}
@@ -147,15 +161,12 @@ void nand_init(void)
board_nand_init();
- val = readl(SUNXI_NFC_BASE + NFC_REG_CTL);
+ val = readl_nfc(NFC_REG_CTL);
/* enable and reset CTL */
- writel(val | NFC_EN | NFC_RESET,
- SUNXI_NFC_BASE + NFC_REG_CTL);
+ writel_nfc(val | NFC_EN | NFC_RESET, NFC_REG_CTL);
- if (!check_value_negated(SUNXI_NFC_BASE + NFC_REG_CTL,
- NFC_RESET, DEFAULT_TIMEOUT_US)) {
+ if (!check_value_negated(NFC_REG_CTL, NFC_RESET, DEFAULT_TIMEOUT_US))
printf("Couldn't initialize nand\n");
- }
/* reset NAND */
nand_exec_cmd(NFC_SEND_CMD1 | NFC_WAIT_FLAG | NAND_CMD_RESET);
@@ -167,24 +178,23 @@ static void nand_apply_config(const struct nfc_config *conf)
nand_wait_cmd_fifo_empty();
- val = readl(SUNXI_NFC_BASE + NFC_REG_CTL);
+ val = readl_nfc(NFC_REG_CTL);
val &= ~NFC_PAGE_SHIFT_MSK;
- writel(val | NFC_PAGE_SIZE(conf->page_size),
- SUNXI_NFC_BASE + NFC_REG_CTL);
- writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_REG_CNT);
- writel(conf->page_size, SUNXI_NFC_BASE + NFC_REG_SPARE_AREA(conf));
+ writel_nfc(val | NFC_PAGE_SIZE(conf->page_size), NFC_REG_CTL);
+ writel_nfc(conf->ecc_size, NFC_REG_CNT);
+ writel_nfc(conf->page_size, NFC_REG_SPARE_AREA(conf));
}
static int nand_load_page(const struct nfc_config *conf, u32 offs)
{
int page = offs / conf->page_size;
- writel((NAND_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
- (NAND_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
- (NAND_CMD_READSTART << NFC_READ_CMD_OFFSET),
- SUNXI_NFC_BASE + NFC_REG_RCMD_SET);
- writel(((page & 0xFFFF) << 16), SUNXI_NFC_BASE + NFC_REG_ADDR_LOW);
- writel((page >> 16) & 0xFF, SUNXI_NFC_BASE + NFC_REG_ADDR_HIGH);
+ writel_nfc((NAND_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
+ (NAND_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
+ (NAND_CMD_READSTART << NFC_READ_CMD_OFFSET),
+ NFC_REG_RCMD_SET);
+ writel_nfc(((page & 0xFFFF) << 16), NFC_REG_ADDR_LOW);
+ writel_nfc((page >> 16) & 0xFF, NFC_REG_ADDR_HIGH);
return nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_NORMAL_OP |
NFC_SEND_ADR | NFC_WAIT_FLAG |
@@ -195,11 +205,11 @@ static int nand_change_column(u16 column)
{
int ret;
- writel((NAND_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
- (NAND_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
- (NAND_CMD_RNDOUTSTART << NFC_READ_CMD_OFFSET),
- SUNXI_NFC_BASE + NFC_REG_RCMD_SET);
- writel(column, SUNXI_NFC_BASE + NFC_REG_ADDR_LOW);
+ writel_nfc((NAND_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
+ (NAND_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
+ (NAND_CMD_RNDOUTSTART << NFC_READ_CMD_OFFSET),
+ NFC_REG_RCMD_SET);
+ writel_nfc(column, NFC_REG_ADDR_LOW);
ret = nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_NORMAL_OP |
(1 << NFC_ADR_NUM_OFFSET) | NFC_SEND_ADR |
@@ -226,7 +236,7 @@ static void sunxi_nfc_reset_user_data_len(const struct nfc_config *nfc)
return;
for (int i = 0; i < nfc->caps->max_ecc_steps; i += loop_step)
- writel(0, SUNXI_NFC_BASE + NFC_REG_USER_DATA_LEN(nfc, i));
+ writel_nfc(0, NFC_REG_USER_DATA_LEN(nfc, i));
}
static void sunxi_nfc_set_user_data_len(const struct nfc_config *nfc,
@@ -252,11 +262,11 @@ static void sunxi_nfc_set_user_data_len(const struct nfc_config *nfc,
return;
}
- val = readl(SUNXI_NFC_BASE + NFC_REG_USER_DATA_LEN(nfc, step));
+ val = readl_nfc(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, SUNXI_NFC_BASE + NFC_REG_USER_DATA_LEN(nfc, step));
+ writel_nfc(val, NFC_REG_USER_DATA_LEN(nfc, step));
}
#if defined(CONFIG_MACH_SUN50I_H616) || defined(CONFIG_MACH_SUN50I_H6)
@@ -298,18 +308,18 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
ecc512_bit = NFC_ECC_BLOCK_512;
/* Clear ECC status and restart ECC engine */
- writel(0, SUNXI_NFC_BASE + NFC_REG_ECC_ST);
+ writel_nfc(0, NFC_REG_ECC_ST);
- writel(NFC_RANDOM_SEED(rand_seed) |
- NFC_ECC_MODE(conf, conf->ecc_strength) |
- (conf->randomize ? NFC_RANDOM_EN(conf) : 0) |
- ecc512_bit |
- NFC_ECC_EN | NFC_ECC_EXCEPTION,
- SUNXI_NFC_BASE + NFC_REG_ECC_CTL);
+ writel_nfc(NFC_RANDOM_SEED(rand_seed) |
+ NFC_ECC_MODE(conf, conf->ecc_strength) |
+ (conf->randomize ? NFC_RANDOM_EN(conf) : 0) |
+ ecc512_bit |
+ NFC_ECC_EN | NFC_ECC_EXCEPTION,
+ NFC_REG_ECC_CTL);
/* Move the data in SRAM */
nand_change_column(data_off);
- writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_REG_CNT);
+ writel_nfc(conf->ecc_size, NFC_REG_CNT);
nand_exec_cmd(NFC_DATA_TRANS);
/*
@@ -323,7 +333,7 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
nand_exec_cmd(NFC_DATA_TRANS | NFC_ECC_OP);
/* Get the ECC status */
- ecc_st = readl(SUNXI_NFC_BASE + NFC_REG_ECC_ST);
+ ecc_st = readl_nfc(NFC_REG_ECC_ST);
/* ECC error detected. */
if (ecc_st & NFC_ECC_ERR_MSK(conf))
@@ -334,8 +344,7 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
* (needed for configuration detection).
*/
if (!i) {
- pattern_found = readl(SUNXI_NFC_BASE +
- conf->caps->reg_pat_found);
+ pattern_found = readl_nfc(conf->caps->reg_pat_found);
pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(conf),
pattern_found);
if (pattern_found & NFC_ECC_PAT_FOUND(0))
@@ -348,8 +357,8 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
conf->ecc_size);
/* Stop the ECC engine */
- writel(readl(SUNXI_NFC_BASE + NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
- SUNXI_NFC_BASE + NFC_REG_ECC_CTL);
+ writel_nfc(readl_nfc(NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
+ NFC_REG_ECC_CTL);
if (data_off + conf->ecc_size >= len)
break;
^ permalink raw reply related [flat|nested] 43+ messages in thread
* Re: [PATCH 01/24] mtd: rawnand: sunxi: cosmetic: remove needless comment
2025-10-16 14:27 ` [PATCH 01/24] mtd: rawnand: sunxi: cosmetic: remove needless comment Richard Genoud
@ 2025-10-17 7:56 ` Andre Przywara
0 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2025-10-17 7:56 UTC (permalink / raw)
To: Richard Genoud, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot
Hi Richard,
many thanks for sending this series, some good work here!
On 16/10/2025 15:27, Richard Genoud wrote:
> Remove 'complete' member from struct sunxi_nfc
>
> The 'complete' member isn't part of the structure, let's remove it.
>
> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Cheers,
Andre
> ---
> drivers/mtd/nand/raw/sunxi_nand.c | 2 --
> 1 file changed, 2 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
> index 1ce09b56b804..c6b9b2a4ebac 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
> @@ -270,8 +270,6 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
> * @clk_rate: NAND controller current clock rate
> * @chips: a list containing all the NAND chips attached to
> * this NAND controller
> - * @complete: a completion object used to wait for NAND
> - * controller events
> */
> struct sunxi_nfc {
> struct nand_hw_control controller;
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 02/24] mtd: rawnand: sunxi_spl: fix pointer from integer without a cast
2025-10-16 14:27 ` [PATCH 02/24] mtd: rawnand: sunxi_spl: fix pointer from integer without a cast Richard Genoud
@ 2025-10-17 7:57 ` Andre Przywara
2025-10-17 12:48 ` Richard GENOUD
0 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2025-10-17 7:57 UTC (permalink / raw)
To: Richard Genoud, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot
Hi,
On 16/10/2025 15:27, Richard Genoud wrote:
> Fix pointer from interget warning when compiling for ARM64
>
> When compiling for arm64, we get this error:
> error: passing argument 2 of ‘__memcpy_fromio’ makes pointer from
> integer without a cast [-Wint-conversion]
>
> Fix that with a cast to (void *)(uintptr_t)
>
> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
> ---
> drivers/mtd/nand/raw/sunxi_nand_spl.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
> index 4f1e2d9a5775..19091ece632b 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
> @@ -310,7 +310,8 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
> return 1;
>
> /* Retrieve the data from SRAM */
> - memcpy_fromio(data, SUNXI_NFC_BASE + NFC_RAM0_BASE,
> + memcpy_fromio(data,
> + (void *)(uintptr_t)SUNXI_NFC_BASE + NFC_RAM0_BASE,
I don't think memcpy_fromio() is correct here in the first place. It
looks tempting to use it, but the implementation is not safe to use with
Allwinner peripherals: we need to stick to the predefined device
register access width. Neither the arm nor the arm64 implementation are
fully compliant. If you go by the book, the peripheral registers are
32-bit wide, and must only be accessed via a 32-bit wide access
(readl/writel). Empirically 8-bit accesses to a 32-bit aligned address
also seem to work, but not to other addresses. Everything else is unsafe
and should be avoided.
So can you please replace this call with a for-loop of readl()
invocations? This should be safe with all devices, and since the base
address is 32-bit aligned, and I assume ecc_size is as well, we are good
here.
Cheers,
Andre
> conf->ecc_size);
>
> /* Stop the ECC engine */
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 03/24] mtd: rawnand: sunxi_spl: cosmetic: harmonize register defines with non spl file
2025-10-16 14:27 ` [PATCH 03/24] mtd: rawnand: sunxi_spl: cosmetic: harmonize register defines with non spl file Richard Genoud
@ 2025-10-17 7:57 ` Andre Przywara
2025-10-17 14:22 ` Richard GENOUD
0 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2025-10-17 7:57 UTC (permalink / raw)
To: Richard Genoud, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot
Hi,
please avoid the use of the word "cosmectic" in the subject if the
change is not really cosmetic, as in just fixing some formatting or a
typo. This is refactoring that should not affect functionality, but this
change is beyond what I would characterise as "cosmetic".
Otherwise those are good changes, many thanks for cleaning this up and
unifying the two drivers!
On 16/10/2025 15:27, Richard Genoud wrote:
> Harmonize registers definition in sunxi_nand{,_spl}.c files
>
> This is a first step to then include the same file from both
> sunxi_nand{,_spl}.c files
Please also mention here that you remove unused definitions.
> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
> ---
> drivers/mtd/nand/raw/sunxi_nand_spl.c | 148 ++++++++++++--------------
> 1 file changed, 66 insertions(+), 82 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
> index 19091ece632b..3ccf716b99ac 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
> @@ -14,48 +14,32 @@
> #include <linux/mtd/rawnand.h>
>
> /* registers */
> -#define NFC_CTL 0x00000000
> -#define NFC_ST 0x00000004
> -#define NFC_INT 0x00000008
> -#define NFC_TIMING_CTL 0x0000000C
> -#define NFC_TIMING_CFG 0x00000010
> -#define NFC_ADDR_LOW 0x00000014
> -#define NFC_ADDR_HIGH 0x00000018
> -#define NFC_SECTOR_NUM 0x0000001C
> -#define NFC_CNT 0x00000020
> -#define NFC_CMD 0x00000024
> -#define NFC_RCMD_SET 0x00000028
> -#define NFC_WCMD_SET 0x0000002C
> -#define NFC_IO_DATA 0x00000030
> -#define NFC_ECC_CTL 0x00000034
> -#define NFC_ECC_ST 0x00000038
> -#define NFC_DEBUG 0x0000003C
> -#define NFC_ECC_CNT0 0x00000040
> -#define NFC_ECC_CNT1 0x00000044
> -#define NFC_ECC_CNT2 0x00000048
> -#define NFC_ECC_CNT3 0x0000004C
> -#define NFC_USER_DATA_BASE 0x00000050
> -#define NFC_EFNAND_STATUS 0x00000090
> -#define NFC_SPARE_AREA 0x000000A0
> -#define NFC_PATTERN_ID 0x000000A4
> +#define NFC_REG_CTL 0x00000000
> +#define NFC_REG_ST 0x00000004
> +#define NFC_REG_ADDR_LOW 0x00000014
> +#define NFC_REG_ADDR_HIGH 0x00000018
> +#define NFC_REG_CNT 0x00000020
> +#define NFC_REG_CMD 0x00000024
> +#define NFC_REG_RCMD_SET 0x00000028
> +#define NFC_REG_ECC_CTL 0x00000034
> +#define NFC_REG_ECC_ST 0x00000038
> +#define NFC_REG_SPARE_AREA 0x000000A0
> #define NFC_RAM0_BASE 0x00000400
> #define NFC_RAM1_BASE 0x00000800
>
> -#define NFC_CTL_EN (1 << 0)
> -#define NFC_CTL_RESET (1 << 1)
> -#define NFC_CTL_RAM_METHOD (1 << 14)
> -#define NFC_CTL_PAGE_SIZE_MASK (0xf << 8)
> -#define NFC_CTL_PAGE_SIZE(a) ((fls(a) - 11) << 8)
> +#define NFC_EN (1 << 0)
Is there a strong reason to lose the _CTL_ infix here? I think it's
better to keep the register name in the bit field definition, otherwise
it becomes too generic and is prone to conflicts.
> +#define NFC_RESET (1 << 1)
> +#define NFC_PAGE_SHIFT_MSK (0xf << 8)
> +#define NFC_PAGE_SIZE(a) ((fls(a) - 11) << 8)
>
> #define NFC_ECC_EN (1 << 0)
> -#define NFC_ECC_PIPELINE (1 << 3)
> #define NFC_ECC_EXCEPTION (1 << 4)
> -#define NFC_ECC_BLOCK_SIZE (1 << 5)
> -#define NFC_ECC_RANDOM_EN (1 << 9)
> -#define NFC_ECC_RANDOM_DIRECTION (1 << 10)
> +#define NFC_ECC_BLOCK_512 (1 << 5)
> +#define NFC_RANDOM_EN (1 << 9)
> +#define NFC_RANDOM_DIRECTION (1 << 10)
>
> -#define NFC_ADDR_NUM_OFFSET 16
> -#define NFC_SEND_ADDR (1 << 19)
> +#define NFC_ADR_NUM_OFFSET 16
> +#define NFC_SEND_ADR (1 << 19)
But ADDR with two D's looks more correct to me?
In general, can't we keep the better version of each name, and adjust
both the SPL and proper code?
Cheers,
Andre
> #define NFC_ACCESS_DIR (1 << 20)
> #define NFC_DATA_TRANS (1 << 21)
> #define NFC_SEND_CMD1 (1 << 22)
> @@ -66,17 +50,17 @@
> #define NFC_ROW_AUTO_INC (1 << 27)
> #define NFC_SEND_CMD3 (1 << 28)
> #define NFC_SEND_CMD4 (1 << 29)
> -#define NFC_RAW_CMD (0 << 30)
> -#define NFC_ECC_CMD (1 << 30)
> -#define NFC_PAGE_CMD (2 << 30)
> +#define NFC_NORMAL_OP (0 << 30)
> +#define NFC_ECC_OP (1 << 30)
> +#define NFC_PAGE_OP (2 << 30)
>
> -#define NFC_ST_CMD_INT_FLAG (1 << 1)
> -#define NFC_ST_DMA_INT_FLAG (1 << 2)
> -#define NFC_ST_CMD_FIFO_STAT (1 << 3)
> +#define NFC_CMD_INT_FLAG (1 << 1)
> +#define NFC_DMA_INT_FLAG (1 << 2)
> +#define NFC_CMD_FIFO_STATUS (1 << 3)
>
> #define NFC_READ_CMD_OFFSET 0
> -#define NFC_RANDOM_READ_CMD0_OFFSET 8
> -#define NFC_RANDOM_READ_CMD1_OFFSET 16
> +#define NFC_RND_READ_CMD0_OFFSET 8
> +#define NFC_RND_READ_CMD1_OFFSET 16
>
> #define NFC_CMD_RNDOUTSTART 0xE0
> #define NFC_CMD_RNDOUT 0x05
> @@ -143,8 +127,8 @@ static inline int check_value_negated(int offset, int unexpected_bits,
>
> static int nand_wait_cmd_fifo_empty(void)
> {
> - if (!check_value_negated(SUNXI_NFC_BASE + NFC_ST, NFC_ST_CMD_FIFO_STAT,
> - DEFAULT_TIMEOUT_US)) {
> + if (!check_value_negated(SUNXI_NFC_BASE + NFC_REG_ST,
> + NFC_CMD_FIFO_STATUS, DEFAULT_TIMEOUT_US)) {
> printf("nand: timeout waiting for empty cmd FIFO\n");
> return -ETIMEDOUT;
> }
> @@ -154,7 +138,7 @@ static int nand_wait_cmd_fifo_empty(void)
>
> static int nand_wait_int(void)
> {
> - if (!check_value(SUNXI_NFC_BASE + NFC_ST, NFC_ST_CMD_INT_FLAG,
> + if (!check_value(SUNXI_NFC_BASE + NFC_REG_ST, NFC_CMD_INT_FLAG,
> DEFAULT_TIMEOUT_US)) {
> printf("nand: timeout waiting for interruption\n");
> return -ETIMEDOUT;
> @@ -171,8 +155,8 @@ static int nand_exec_cmd(u32 cmd)
> if (ret)
> return ret;
>
> - writel(NFC_ST_CMD_INT_FLAG, SUNXI_NFC_BASE + NFC_ST);
> - writel(cmd, SUNXI_NFC_BASE + NFC_CMD);
> + writel(NFC_CMD_INT_FLAG, SUNXI_NFC_BASE + NFC_REG_ST);
> + writel(cmd, SUNXI_NFC_BASE + NFC_REG_CMD);
>
> return nand_wait_int();
> }
> @@ -183,13 +167,13 @@ void nand_init(void)
>
> board_nand_init();
>
> - val = readl(SUNXI_NFC_BASE + NFC_CTL);
> + val = readl(SUNXI_NFC_BASE + NFC_REG_CTL);
> /* enable and reset CTL */
> - writel(val | NFC_CTL_EN | NFC_CTL_RESET,
> - SUNXI_NFC_BASE + NFC_CTL);
> + writel(val | NFC_EN | NFC_RESET,
> + SUNXI_NFC_BASE + NFC_REG_CTL);
>
> - if (!check_value_negated(SUNXI_NFC_BASE + NFC_CTL,
> - NFC_CTL_RESET, DEFAULT_TIMEOUT_US)) {
> + if (!check_value_negated(SUNXI_NFC_BASE + NFC_REG_CTL,
> + NFC_RESET, DEFAULT_TIMEOUT_US)) {
> printf("Couldn't initialize nand\n");
> }
>
> @@ -203,42 +187,42 @@ static void nand_apply_config(const struct nfc_config *conf)
>
> nand_wait_cmd_fifo_empty();
>
> - val = readl(SUNXI_NFC_BASE + NFC_CTL);
> - val &= ~NFC_CTL_PAGE_SIZE_MASK;
> - writel(val | NFC_CTL_PAGE_SIZE(conf->page_size),
> - SUNXI_NFC_BASE + NFC_CTL);
> - writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_CNT);
> - writel(conf->page_size, SUNXI_NFC_BASE + NFC_SPARE_AREA);
> + val = readl(SUNXI_NFC_BASE + NFC_REG_CTL);
> + val &= ~NFC_PAGE_SHIFT_MSK;
> + writel(val | NFC_PAGE_SIZE(conf->page_size),
> + SUNXI_NFC_BASE + NFC_REG_CTL);
> + writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_REG_CNT);
> + writel(conf->page_size, SUNXI_NFC_BASE + NFC_REG_SPARE_AREA);
> }
>
> static int nand_load_page(const struct nfc_config *conf, u32 offs)
> {
> int page = offs / conf->page_size;
>
> - writel((NFC_CMD_RNDOUTSTART << NFC_RANDOM_READ_CMD1_OFFSET) |
> - (NFC_CMD_RNDOUT << NFC_RANDOM_READ_CMD0_OFFSET) |
> + writel((NFC_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
> + (NFC_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
> (NFC_CMD_READSTART << NFC_READ_CMD_OFFSET),
> - SUNXI_NFC_BASE + NFC_RCMD_SET);
> - writel(((page & 0xFFFF) << 16), SUNXI_NFC_BASE + NFC_ADDR_LOW);
> - writel((page >> 16) & 0xFF, SUNXI_NFC_BASE + NFC_ADDR_HIGH);
> + SUNXI_NFC_BASE + NFC_REG_RCMD_SET);
> + writel(((page & 0xFFFF) << 16), SUNXI_NFC_BASE + NFC_REG_ADDR_LOW);
> + writel((page >> 16) & 0xFF, SUNXI_NFC_BASE + NFC_REG_ADDR_HIGH);
>
> - return nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_RAW_CMD |
> - NFC_SEND_ADDR | NFC_WAIT_FLAG |
> - ((conf->addr_cycles - 1) << NFC_ADDR_NUM_OFFSET));
> + return nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_NORMAL_OP |
> + NFC_SEND_ADR | NFC_WAIT_FLAG |
> + ((conf->addr_cycles - 1) << NFC_ADR_NUM_OFFSET));
> }
>
> static int nand_change_column(u16 column)
> {
> int ret;
>
> - writel((NFC_CMD_RNDOUTSTART << NFC_RANDOM_READ_CMD1_OFFSET) |
> - (NFC_CMD_RNDOUT << NFC_RANDOM_READ_CMD0_OFFSET) |
> + writel((NFC_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
> + (NFC_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
> (NFC_CMD_RNDOUTSTART << NFC_READ_CMD_OFFSET),
> - SUNXI_NFC_BASE + NFC_RCMD_SET);
> - writel(column, SUNXI_NFC_BASE + NFC_ADDR_LOW);
> + SUNXI_NFC_BASE + NFC_REG_RCMD_SET);
> + writel(column, SUNXI_NFC_BASE + NFC_REG_ADDR_LOW);
>
> - ret = nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_RAW_CMD |
> - (1 << NFC_ADDR_NUM_OFFSET) | NFC_SEND_ADDR |
> + ret = nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_NORMAL_OP |
> + (1 << NFC_ADR_NUM_OFFSET) | NFC_SEND_ADR |
> NFC_CMD_RNDOUT);
> if (ret)
> return ret;
> @@ -276,16 +260,16 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
> u8 *data = dest + data_off;
>
> /* Clear ECC status and restart ECC engine */
> - writel(0, SUNXI_NFC_BASE + NFC_ECC_ST);
> + writel(0, SUNXI_NFC_BASE + NFC_REG_ECC_ST);
> writel((rand_seed << 16) | (conf->ecc_strength << 12) |
> - (conf->randomize ? NFC_ECC_RANDOM_EN : 0) |
> - (conf->ecc_size == 512 ? NFC_ECC_BLOCK_SIZE : 0) |
> + (conf->randomize ? NFC_RANDOM_EN : 0) |
> + (conf->ecc_size == 512 ? NFC_ECC_BLOCK_512 : 0) |
> NFC_ECC_EN | NFC_ECC_EXCEPTION,
> - SUNXI_NFC_BASE + NFC_ECC_CTL);
> + SUNXI_NFC_BASE + NFC_REG_ECC_CTL);
>
> /* Move the data in SRAM */
> nand_change_column(data_off);
> - writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_CNT);
> + writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_REG_CNT);
> nand_exec_cmd(NFC_DATA_TRANS);
>
> /*
> @@ -293,10 +277,10 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
> * the data.
> */
> nand_change_column(oob_off);
> - nand_exec_cmd(NFC_DATA_TRANS | NFC_ECC_CMD);
> + nand_exec_cmd(NFC_DATA_TRANS | NFC_ECC_OP);
>
> /* Get the ECC status */
> - ecc_st = readl(SUNXI_NFC_BASE + NFC_ECC_ST);
> + ecc_st = readl(SUNXI_NFC_BASE + NFC_REG_ECC_ST);
>
> /* ECC error detected. */
> if (ecc_st & 0xffff)
> @@ -315,8 +299,8 @@ static int nand_read_page(const struct nfc_config *conf, u32 offs,
> conf->ecc_size);
>
> /* Stop the ECC engine */
> - writel(readl(SUNXI_NFC_BASE + NFC_ECC_CTL) & ~NFC_ECC_EN,
> - SUNXI_NFC_BASE + NFC_ECC_CTL);
> + writel(readl(SUNXI_NFC_BASE + NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
> + SUNXI_NFC_BASE + NFC_REG_ECC_CTL);
>
> if (data_off + conf->ecc_size >= len)
> break;
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 04/24] mtd: rawnand: sunxi_spl: cosmetic: use definitions from linux/mtd/rawnand.h
2025-10-16 14:27 ` [PATCH 04/24] mtd: rawnand: sunxi_spl: cosmetic: use definitions from linux/mtd/rawnand.h Richard Genoud
@ 2025-10-17 9:35 ` Andre Przywara
0 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2025-10-17 9:35 UTC (permalink / raw)
To: Richard Genoud, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Anand Gore, Linus Walleij, david regan, Andrew Goodbody,
Miquel Raynal, Thomas Petazzoni, u-boot
Hi,
On 16/10/2025 15:27, Richard Genoud wrote:
> Remove unneeded definitions NFC_CMD_R* in sunxi_nand_spl.c
>
> No need to define NFC_CMD_RNDOUTSTART, NFC_CMD_RNDOUT and
> NFC_CMD_READSTART here since they are already in linux/mtd/rawnand.h
>
> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Cheers,
Andre
> ---
> drivers/mtd/nand/raw/sunxi_nand_spl.c | 18 +++++++-----------
> 1 file changed, 7 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
> index 3ccf716b99ac..306c1c0d0989 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
> @@ -62,10 +62,6 @@
> #define NFC_RND_READ_CMD0_OFFSET 8
> #define NFC_RND_READ_CMD1_OFFSET 16
>
> -#define NFC_CMD_RNDOUTSTART 0xE0
> -#define NFC_CMD_RNDOUT 0x05
> -#define NFC_CMD_READSTART 0x30
> -
> struct nfc_config {
> int page_size;
> int ecc_strength;
> @@ -199,9 +195,9 @@ static int nand_load_page(const struct nfc_config *conf, u32 offs)
> {
> int page = offs / conf->page_size;
>
> - writel((NFC_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
> - (NFC_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
> - (NFC_CMD_READSTART << NFC_READ_CMD_OFFSET),
> + writel((NAND_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
> + (NAND_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
> + (NAND_CMD_READSTART << NFC_READ_CMD_OFFSET),
> SUNXI_NFC_BASE + NFC_REG_RCMD_SET);
> writel(((page & 0xFFFF) << 16), SUNXI_NFC_BASE + NFC_REG_ADDR_LOW);
> writel((page >> 16) & 0xFF, SUNXI_NFC_BASE + NFC_REG_ADDR_HIGH);
> @@ -215,15 +211,15 @@ static int nand_change_column(u16 column)
> {
> int ret;
>
> - writel((NFC_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
> - (NFC_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
> - (NFC_CMD_RNDOUTSTART << NFC_READ_CMD_OFFSET),
> + writel((NAND_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
> + (NAND_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
> + (NAND_CMD_RNDOUTSTART << NFC_READ_CMD_OFFSET),
> SUNXI_NFC_BASE + NFC_REG_RCMD_SET);
> writel(column, SUNXI_NFC_BASE + NFC_REG_ADDR_LOW);
>
> ret = nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_NORMAL_OP |
> (1 << NFC_ADR_NUM_OFFSET) | NFC_SEND_ADR |
> - NFC_CMD_RNDOUT);
> + NAND_CMD_RNDOUT);
> if (ret)
> return ret;
>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 05/24] mtd: rawnand: sunxi_spl: cosmetic: replace AHB_DIV_1 by CCM_NAND_CTRL_M/N
2025-10-16 14:27 ` [PATCH 05/24] mtd: rawnand: sunxi_spl: cosmetic: replace AHB_DIV_1 by CCM_NAND_CTRL_M/N Richard Genoud
@ 2025-10-17 9:36 ` Andre Przywara
2025-10-17 14:26 ` Richard GENOUD
0 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2025-10-17 9:36 UTC (permalink / raw)
To: Richard Genoud, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Anand Gore, Linus Walleij, david regan, Andrew Goodbody,
Miquel Raynal, Thomas Petazzoni, u-boot
Hi,
On 16/10/2025 15:27, Richard Genoud wrote:
> CCM_NAND_CTRL_M/N is defined in clock headers, and it's more readable
>
> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
> ---
> drivers/mtd/nand/raw/sunxi_nand_spl.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
> index 306c1c0d0989..9f80a8010d7b 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
> @@ -531,5 +531,6 @@ void nand_deselect(void)
> #else
> clrbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_DMA));
> #endif
> - clrbits_le32(&ccm->nand0_clk_cfg, CCM_NAND_CTRL_ENABLE | AHB_DIV_1);
> + clrbits_le32(&ccm->nand0_clk_cfg, CCM_NAND_CTRL_ENABLE |
> + CCM_NAND_CTRL_N(0) | CCM_NAND_CTRL_M(1));
The change looks alright, but can you please use the opportunity to
change the CCM access to the new scheme, away from using a struct, and
towards using #define'd offsets? You have that conditionally in a later
patch, so please rather move the legacy users over here.
No need to change *every* clock user for the older SoCs, or to remove
the NAND clocks from the struct, just define the NAND related offsets in
clock_sun4i.h and clock_sun6i.h, then use the H6/H616 way here for all.
Thanks!
Andre
> }
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 02/24] mtd: rawnand: sunxi_spl: fix pointer from integer without a cast
2025-10-17 7:57 ` Andre Przywara
@ 2025-10-17 12:48 ` Richard GENOUD
0 siblings, 0 replies; 43+ messages in thread
From: Richard GENOUD @ 2025-10-17 12:48 UTC (permalink / raw)
To: Andre Przywara, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot
Le 17/10/2025 à 09:57, Andre Przywara a écrit :
> Hi,
>
> On 16/10/2025 15:27, Richard Genoud wrote:
>> Fix pointer from interget warning when compiling for ARM64
>>
>> When compiling for arm64, we get this error:
>> error: passing argument 2 of ‘__memcpy_fromio’ makes pointer from
>> integer without a cast [-Wint-conversion]
>>
>> Fix that with a cast to (void *)(uintptr_t)
>>
>> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
>> ---
>> drivers/mtd/nand/raw/sunxi_nand_spl.c | 3 ++-
>> 1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/
>> raw/sunxi_nand_spl.c
>> index 4f1e2d9a5775..19091ece632b 100644
>> --- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
>> +++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
>> @@ -310,7 +310,8 @@ static int nand_read_page(const struct nfc_config
>> *conf, u32 offs,
>> return 1;
>> /* Retrieve the data from SRAM */
>> - memcpy_fromio(data, SUNXI_NFC_BASE + NFC_RAM0_BASE,
>> + memcpy_fromio(data,
>> + (void *)(uintptr_t)SUNXI_NFC_BASE + NFC_RAM0_BASE,
>
> I don't think memcpy_fromio() is correct here in the first place. It
> looks tempting to use it, but the implementation is not safe to use with
> Allwinner peripherals: we need to stick to the predefined device
> register access width. Neither the arm nor the arm64 implementation are
> fully compliant. If you go by the book, the peripheral registers are 32-
> bit wide, and must only be accessed via a 32-bit wide access (readl/
> writel). Empirically 8-bit accesses to a 32-bit aligned address also
> seem to work, but not to other addresses. Everything else is unsafe and
> should be avoided.
> So can you please replace this call with a for-loop of readl()
> invocations? This should be safe with all devices, and since the base
> address is 32-bit aligned, and I assume ecc_size is as well, we are good
> here.
Ok, sure.
Thanks!
>
> Cheers,
> Andre
>
>> conf->ecc_size);
>> /* Stop the ECC engine */
>
--
Richard Genoud, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 03/24] mtd: rawnand: sunxi_spl: cosmetic: harmonize register defines with non spl file
2025-10-17 7:57 ` Andre Przywara
@ 2025-10-17 14:22 ` Richard GENOUD
2025-10-17 14:27 ` Andre Przywara
0 siblings, 1 reply; 43+ messages in thread
From: Richard GENOUD @ 2025-10-17 14:22 UTC (permalink / raw)
To: Andre Przywara, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot
Hi,
Le 17/10/2025 à 09:57, Andre Przywara a écrit :
> Hi,
>
> please avoid the use of the word "cosmectic" in the subject if the
> change is not really cosmetic, as in just fixing some formatting or a
> typo. This is refactoring that should not affect functionality, but this
> change is beyond what I would characterise as "cosmetic".
>
> Otherwise those are good changes, many thanks for cleaning this up and
> unifying the two drivers!
Ok, I wasn't sure about that.
Thanks for clarifying.
>
> On 16/10/2025 15:27, Richard Genoud wrote:
>> Harmonize registers definition in sunxi_nand{,_spl}.c files
>>
>> This is a first step to then include the same file from both
>> sunxi_nand{,_spl}.c files
>
> Please also mention here that you remove unused definitions.
Indeed, I forgot that.
>
>> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
>> ---
>> drivers/mtd/nand/raw/sunxi_nand_spl.c | 148 ++++++++++++--------------
>> 1 file changed, 66 insertions(+), 82 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/
>> raw/sunxi_nand_spl.c
>> index 19091ece632b..3ccf716b99ac 100644
>> --- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
>> +++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
>> @@ -14,48 +14,32 @@
>> #include <linux/mtd/rawnand.h>
>> /* registers */
>> -#define NFC_CTL 0x00000000
>> -#define NFC_ST 0x00000004
>> -#define NFC_INT 0x00000008
>> -#define NFC_TIMING_CTL 0x0000000C
>> -#define NFC_TIMING_CFG 0x00000010
>> -#define NFC_ADDR_LOW 0x00000014
>> -#define NFC_ADDR_HIGH 0x00000018
>> -#define NFC_SECTOR_NUM 0x0000001C
>> -#define NFC_CNT 0x00000020
>> -#define NFC_CMD 0x00000024
>> -#define NFC_RCMD_SET 0x00000028
>> -#define NFC_WCMD_SET 0x0000002C
>> -#define NFC_IO_DATA 0x00000030
>> -#define NFC_ECC_CTL 0x00000034
>> -#define NFC_ECC_ST 0x00000038
>> -#define NFC_DEBUG 0x0000003C
>> -#define NFC_ECC_CNT0 0x00000040
>> -#define NFC_ECC_CNT1 0x00000044
>> -#define NFC_ECC_CNT2 0x00000048
>> -#define NFC_ECC_CNT3 0x0000004C
>> -#define NFC_USER_DATA_BASE 0x00000050
>> -#define NFC_EFNAND_STATUS 0x00000090
>> -#define NFC_SPARE_AREA 0x000000A0
>> -#define NFC_PATTERN_ID 0x000000A4
>> +#define NFC_REG_CTL 0x00000000
>> +#define NFC_REG_ST 0x00000004
>> +#define NFC_REG_ADDR_LOW 0x00000014
>> +#define NFC_REG_ADDR_HIGH 0x00000018
>> +#define NFC_REG_CNT 0x00000020
>> +#define NFC_REG_CMD 0x00000024
>> +#define NFC_REG_RCMD_SET 0x00000028
>> +#define NFC_REG_ECC_CTL 0x00000034
>> +#define NFC_REG_ECC_ST 0x00000038
>> +#define NFC_REG_SPARE_AREA 0x000000A0
>> #define NFC_RAM0_BASE 0x00000400
>> #define NFC_RAM1_BASE 0x00000800
>> -#define NFC_CTL_EN (1 << 0)
>> -#define NFC_CTL_RESET (1 << 1)
>> -#define NFC_CTL_RAM_METHOD (1 << 14)
>> -#define NFC_CTL_PAGE_SIZE_MASK (0xf << 8)
>> -#define NFC_CTL_PAGE_SIZE(a) ((fls(a) - 11) << 8)
>> +#define NFC_EN (1 << 0)
>
> Is there a strong reason to lose the _CTL_ infix here? I think it's
> better to keep the register name in the bit field definition, otherwise
> it becomes too generic and is prone to conflicts.
Hum, it's like that in the Linux module and in sunxi_nand.c
But otherwise, no strong reason.
>
>> +#define NFC_RESET (1 << 1)
>> +#define NFC_PAGE_SHIFT_MSK (0xf << 8)
>> +#define NFC_PAGE_SIZE(a) ((fls(a) - 11) << 8)
>> #define NFC_ECC_EN (1 << 0)
>> -#define NFC_ECC_PIPELINE (1 << 3)
>> #define NFC_ECC_EXCEPTION (1 << 4)
>> -#define NFC_ECC_BLOCK_SIZE (1 << 5)
>> -#define NFC_ECC_RANDOM_EN (1 << 9)
>> -#define NFC_ECC_RANDOM_DIRECTION (1 << 10)
>> +#define NFC_ECC_BLOCK_512 (1 << 5)
>> +#define NFC_RANDOM_EN (1 << 9)
>> +#define NFC_RANDOM_DIRECTION (1 << 10)
>> -#define NFC_ADDR_NUM_OFFSET 16
>> -#define NFC_SEND_ADDR (1 << 19)
>> +#define NFC_ADR_NUM_OFFSET 16
>> +#define NFC_SEND_ADR (1 << 19)
>
> But ADDR with two D's looks more correct to me?
Defilitely, but same remark, it's NFC_SEND_ADR in the Linux module and
sunxi_nand.c
>
> In general, can't we keep the better version of each name, and adjust
> both the SPL and proper code?
I was a bit more on keeping consistency between the Linux defines and
U-Boot defines, even if I agree with you, some term are so-so.
But if you think I should change them, I'm open to it.
Thanks!
>
> Cheers,
> Andre
>
>> #define NFC_ACCESS_DIR (1 << 20)
>> #define NFC_DATA_TRANS (1 << 21)
>> #define NFC_SEND_CMD1 (1 << 22)
>> @@ -66,17 +50,17 @@
>> #define NFC_ROW_AUTO_INC (1 << 27)
>> #define NFC_SEND_CMD3 (1 << 28)
>> #define NFC_SEND_CMD4 (1 << 29)
>> -#define NFC_RAW_CMD (0 << 30)
>> -#define NFC_ECC_CMD (1 << 30)
>> -#define NFC_PAGE_CMD (2 << 30)
>> +#define NFC_NORMAL_OP (0 << 30)
>> +#define NFC_ECC_OP (1 << 30)
>> +#define NFC_PAGE_OP (2 << 30)
>> -#define NFC_ST_CMD_INT_FLAG (1 << 1)
>> -#define NFC_ST_DMA_INT_FLAG (1 << 2)
>> -#define NFC_ST_CMD_FIFO_STAT (1 << 3)
>> +#define NFC_CMD_INT_FLAG (1 << 1)
>> +#define NFC_DMA_INT_FLAG (1 << 2)
>> +#define NFC_CMD_FIFO_STATUS (1 << 3)
>> #define NFC_READ_CMD_OFFSET 0
>> -#define NFC_RANDOM_READ_CMD0_OFFSET 8
>> -#define NFC_RANDOM_READ_CMD1_OFFSET 16
>> +#define NFC_RND_READ_CMD0_OFFSET 8
>> +#define NFC_RND_READ_CMD1_OFFSET 16
>> #define NFC_CMD_RNDOUTSTART 0xE0
>> #define NFC_CMD_RNDOUT 0x05
>> @@ -143,8 +127,8 @@ static inline int check_value_negated(int offset,
>> int unexpected_bits,
>> static int nand_wait_cmd_fifo_empty(void)
>> {
>> - if (!check_value_negated(SUNXI_NFC_BASE + NFC_ST,
>> NFC_ST_CMD_FIFO_STAT,
>> - DEFAULT_TIMEOUT_US)) {
>> + if (!check_value_negated(SUNXI_NFC_BASE + NFC_REG_ST,
>> + NFC_CMD_FIFO_STATUS, DEFAULT_TIMEOUT_US)) {
>> printf("nand: timeout waiting for empty cmd FIFO\n");
>> return -ETIMEDOUT;
>> }
>> @@ -154,7 +138,7 @@ static int nand_wait_cmd_fifo_empty(void)
>> static int nand_wait_int(void)
>> {
>> - if (!check_value(SUNXI_NFC_BASE + NFC_ST, NFC_ST_CMD_INT_FLAG,
>> + if (!check_value(SUNXI_NFC_BASE + NFC_REG_ST, NFC_CMD_INT_FLAG,
>> DEFAULT_TIMEOUT_US)) {
>> printf("nand: timeout waiting for interruption\n");
>> return -ETIMEDOUT;
>> @@ -171,8 +155,8 @@ static int nand_exec_cmd(u32 cmd)
>> if (ret)
>> return ret;
>> - writel(NFC_ST_CMD_INT_FLAG, SUNXI_NFC_BASE + NFC_ST);
>> - writel(cmd, SUNXI_NFC_BASE + NFC_CMD);
>> + writel(NFC_CMD_INT_FLAG, SUNXI_NFC_BASE + NFC_REG_ST);
>> + writel(cmd, SUNXI_NFC_BASE + NFC_REG_CMD);
>> return nand_wait_int();
>> }
>> @@ -183,13 +167,13 @@ void nand_init(void)
>> board_nand_init();
>> - val = readl(SUNXI_NFC_BASE + NFC_CTL);
>> + val = readl(SUNXI_NFC_BASE + NFC_REG_CTL);
>> /* enable and reset CTL */
>> - writel(val | NFC_CTL_EN | NFC_CTL_RESET,
>> - SUNXI_NFC_BASE + NFC_CTL);
>> + writel(val | NFC_EN | NFC_RESET,
>> + SUNXI_NFC_BASE + NFC_REG_CTL);
>> - if (!check_value_negated(SUNXI_NFC_BASE + NFC_CTL,
>> - NFC_CTL_RESET, DEFAULT_TIMEOUT_US)) {
>> + if (!check_value_negated(SUNXI_NFC_BASE + NFC_REG_CTL,
>> + NFC_RESET, DEFAULT_TIMEOUT_US)) {
>> printf("Couldn't initialize nand\n");
>> }
>> @@ -203,42 +187,42 @@ static void nand_apply_config(const struct
>> nfc_config *conf)
>> nand_wait_cmd_fifo_empty();
>> - val = readl(SUNXI_NFC_BASE + NFC_CTL);
>> - val &= ~NFC_CTL_PAGE_SIZE_MASK;
>> - writel(val | NFC_CTL_PAGE_SIZE(conf->page_size),
>> - SUNXI_NFC_BASE + NFC_CTL);
>> - writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_CNT);
>> - writel(conf->page_size, SUNXI_NFC_BASE + NFC_SPARE_AREA);
>> + val = readl(SUNXI_NFC_BASE + NFC_REG_CTL);
>> + val &= ~NFC_PAGE_SHIFT_MSK;
>> + writel(val | NFC_PAGE_SIZE(conf->page_size),
>> + SUNXI_NFC_BASE + NFC_REG_CTL);
>> + writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_REG_CNT);
>> + writel(conf->page_size, SUNXI_NFC_BASE + NFC_REG_SPARE_AREA);
>> }
>> static int nand_load_page(const struct nfc_config *conf, u32 offs)
>> {
>> int page = offs / conf->page_size;
>> - writel((NFC_CMD_RNDOUTSTART << NFC_RANDOM_READ_CMD1_OFFSET) |
>> - (NFC_CMD_RNDOUT << NFC_RANDOM_READ_CMD0_OFFSET) |
>> + writel((NFC_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
>> + (NFC_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
>> (NFC_CMD_READSTART << NFC_READ_CMD_OFFSET),
>> - SUNXI_NFC_BASE + NFC_RCMD_SET);
>> - writel(((page & 0xFFFF) << 16), SUNXI_NFC_BASE + NFC_ADDR_LOW);
>> - writel((page >> 16) & 0xFF, SUNXI_NFC_BASE + NFC_ADDR_HIGH);
>> + SUNXI_NFC_BASE + NFC_REG_RCMD_SET);
>> + writel(((page & 0xFFFF) << 16), SUNXI_NFC_BASE + NFC_REG_ADDR_LOW);
>> + writel((page >> 16) & 0xFF, SUNXI_NFC_BASE + NFC_REG_ADDR_HIGH);
>> - return nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_RAW_CMD |
>> - NFC_SEND_ADDR | NFC_WAIT_FLAG |
>> - ((conf->addr_cycles - 1) << NFC_ADDR_NUM_OFFSET));
>> + return nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_NORMAL_OP |
>> + NFC_SEND_ADR | NFC_WAIT_FLAG |
>> + ((conf->addr_cycles - 1) << NFC_ADR_NUM_OFFSET));
>> }
>> static int nand_change_column(u16 column)
>> {
>> int ret;
>> - writel((NFC_CMD_RNDOUTSTART << NFC_RANDOM_READ_CMD1_OFFSET) |
>> - (NFC_CMD_RNDOUT << NFC_RANDOM_READ_CMD0_OFFSET) |
>> + writel((NFC_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
>> + (NFC_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
>> (NFC_CMD_RNDOUTSTART << NFC_READ_CMD_OFFSET),
>> - SUNXI_NFC_BASE + NFC_RCMD_SET);
>> - writel(column, SUNXI_NFC_BASE + NFC_ADDR_LOW);
>> + SUNXI_NFC_BASE + NFC_REG_RCMD_SET);
>> + writel(column, SUNXI_NFC_BASE + NFC_REG_ADDR_LOW);
>> - ret = nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_RAW_CMD |
>> - (1 << NFC_ADDR_NUM_OFFSET) | NFC_SEND_ADDR |
>> + ret = nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_NORMAL_OP |
>> + (1 << NFC_ADR_NUM_OFFSET) | NFC_SEND_ADR |
>> NFC_CMD_RNDOUT);
>> if (ret)
>> return ret;
>> @@ -276,16 +260,16 @@ static int nand_read_page(const struct
>> nfc_config *conf, u32 offs,
>> u8 *data = dest + data_off;
>> /* Clear ECC status and restart ECC engine */
>> - writel(0, SUNXI_NFC_BASE + NFC_ECC_ST);
>> + writel(0, SUNXI_NFC_BASE + NFC_REG_ECC_ST);
>> writel((rand_seed << 16) | (conf->ecc_strength << 12) |
>> - (conf->randomize ? NFC_ECC_RANDOM_EN : 0) |
>> - (conf->ecc_size == 512 ? NFC_ECC_BLOCK_SIZE : 0) |
>> + (conf->randomize ? NFC_RANDOM_EN : 0) |
>> + (conf->ecc_size == 512 ? NFC_ECC_BLOCK_512 : 0) |
>> NFC_ECC_EN | NFC_ECC_EXCEPTION,
>> - SUNXI_NFC_BASE + NFC_ECC_CTL);
>> + SUNXI_NFC_BASE + NFC_REG_ECC_CTL);
>> /* Move the data in SRAM */
>> nand_change_column(data_off);
>> - writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_CNT);
>> + writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_REG_CNT);
>> nand_exec_cmd(NFC_DATA_TRANS);
>> /*
>> @@ -293,10 +277,10 @@ static int nand_read_page(const struct
>> nfc_config *conf, u32 offs,
>> * the data.
>> */
>> nand_change_column(oob_off);
>> - nand_exec_cmd(NFC_DATA_TRANS | NFC_ECC_CMD);
>> + nand_exec_cmd(NFC_DATA_TRANS | NFC_ECC_OP);
>> /* Get the ECC status */
>> - ecc_st = readl(SUNXI_NFC_BASE + NFC_ECC_ST);
>> + ecc_st = readl(SUNXI_NFC_BASE + NFC_REG_ECC_ST);
>> /* ECC error detected. */
>> if (ecc_st & 0xffff)
>> @@ -315,8 +299,8 @@ static int nand_read_page(const struct nfc_config
>> *conf, u32 offs,
>> conf->ecc_size);
>> /* Stop the ECC engine */
>> - writel(readl(SUNXI_NFC_BASE + NFC_ECC_CTL) & ~NFC_ECC_EN,
>> - SUNXI_NFC_BASE + NFC_ECC_CTL);
>> + writel(readl(SUNXI_NFC_BASE + NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
>> + SUNXI_NFC_BASE + NFC_REG_ECC_CTL);
>> if (data_off + conf->ecc_size >= len)
>> break;
>
--
Richard Genoud, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 05/24] mtd: rawnand: sunxi_spl: cosmetic: replace AHB_DIV_1 by CCM_NAND_CTRL_M/N
2025-10-17 9:36 ` Andre Przywara
@ 2025-10-17 14:26 ` Richard GENOUD
0 siblings, 0 replies; 43+ messages in thread
From: Richard GENOUD @ 2025-10-17 14:26 UTC (permalink / raw)
To: Andre Przywara, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Anand Gore, Linus Walleij, david regan, Andrew Goodbody,
Miquel Raynal, Thomas Petazzoni, u-boot
Le 17/10/2025 à 11:36, Andre Przywara a écrit :
> Hi,
>
> On 16/10/2025 15:27, Richard Genoud wrote:
>> CCM_NAND_CTRL_M/N is defined in clock headers, and it's more readable
>>
>> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
>> ---
>> drivers/mtd/nand/raw/sunxi_nand_spl.c | 3 ++-
>> 1 file changed, 2 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/
>> raw/sunxi_nand_spl.c
>> index 306c1c0d0989..9f80a8010d7b 100644
>> --- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
>> +++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
>> @@ -531,5 +531,6 @@ void nand_deselect(void)
>> #else
>> clrbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_DMA));
>> #endif
>> - clrbits_le32(&ccm->nand0_clk_cfg, CCM_NAND_CTRL_ENABLE | AHB_DIV_1);
>> + clrbits_le32(&ccm->nand0_clk_cfg, CCM_NAND_CTRL_ENABLE |
>> + CCM_NAND_CTRL_N(0) | CCM_NAND_CTRL_M(1));
>
> The change looks alright, but can you please use the opportunity to
> change the CCM access to the new scheme, away from using a struct, and
> towards using #define'd offsets? You have that conditionally in a later
> patch, so please rather move the legacy users over here.
> No need to change *every* clock user for the older SoCs, or to remove
> the NAND clocks from the struct, just define the NAND related offsets in
> clock_sun4i.h and clock_sun6i.h, then use the H6/H616 way here for all.
Yes, absolutely, it will be cleaner that way.
Thanks!
>
> Thanks!
> Andre
>
>
>> }
>
--
Richard Genoud, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 03/24] mtd: rawnand: sunxi_spl: cosmetic: harmonize register defines with non spl file
2025-10-17 14:22 ` Richard GENOUD
@ 2025-10-17 14:27 ` Andre Przywara
0 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2025-10-17 14:27 UTC (permalink / raw)
To: Richard GENOUD, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot
Hi Richard,
On 17/10/2025 15:22, Richard GENOUD wrote:
> Hi,
> Le 17/10/2025 à 09:57, Andre Przywara a écrit :
>> Hi,
>>
>> please avoid the use of the word "cosmectic" in the subject if the
>> change is not really cosmetic, as in just fixing some formatting or a
>> typo. This is refactoring that should not affect functionality, but
>> this change is beyond what I would characterise as "cosmetic".
>>
>> Otherwise those are good changes, many thanks for cleaning this up and
>> unifying the two drivers!
>
> Ok, I wasn't sure about that.
> Thanks for clarifying.
>
>>
>> On 16/10/2025 15:27, Richard Genoud wrote:
>>> Harmonize registers definition in sunxi_nand{,_spl}.c files
>>>
>>> This is a first step to then include the same file from both
>>> sunxi_nand{,_spl}.c files
>>
>> Please also mention here that you remove unused definitions.
> Indeed, I forgot that.
>
>>
>>> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
>>> ---
>>> drivers/mtd/nand/raw/sunxi_nand_spl.c | 148 ++++++++++++--------------
>>> 1 file changed, 66 insertions(+), 82 deletions(-)
>>>
>>> diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/
>>> nand/ raw/sunxi_nand_spl.c
>>> index 19091ece632b..3ccf716b99ac 100644
>>> --- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
>>> +++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
>>> @@ -14,48 +14,32 @@
>>> #include <linux/mtd/rawnand.h>
>>> /* registers */
>>> -#define NFC_CTL 0x00000000
>>> -#define NFC_ST 0x00000004
>>> -#define NFC_INT 0x00000008
>>> -#define NFC_TIMING_CTL 0x0000000C
>>> -#define NFC_TIMING_CFG 0x00000010
>>> -#define NFC_ADDR_LOW 0x00000014
>>> -#define NFC_ADDR_HIGH 0x00000018
>>> -#define NFC_SECTOR_NUM 0x0000001C
>>> -#define NFC_CNT 0x00000020
>>> -#define NFC_CMD 0x00000024
>>> -#define NFC_RCMD_SET 0x00000028
>>> -#define NFC_WCMD_SET 0x0000002C
>>> -#define NFC_IO_DATA 0x00000030
>>> -#define NFC_ECC_CTL 0x00000034
>>> -#define NFC_ECC_ST 0x00000038
>>> -#define NFC_DEBUG 0x0000003C
>>> -#define NFC_ECC_CNT0 0x00000040
>>> -#define NFC_ECC_CNT1 0x00000044
>>> -#define NFC_ECC_CNT2 0x00000048
>>> -#define NFC_ECC_CNT3 0x0000004C
>>> -#define NFC_USER_DATA_BASE 0x00000050
>>> -#define NFC_EFNAND_STATUS 0x00000090
>>> -#define NFC_SPARE_AREA 0x000000A0
>>> -#define NFC_PATTERN_ID 0x000000A4
>>> +#define NFC_REG_CTL 0x00000000
>>> +#define NFC_REG_ST 0x00000004
>>> +#define NFC_REG_ADDR_LOW 0x00000014
>>> +#define NFC_REG_ADDR_HIGH 0x00000018
>>> +#define NFC_REG_CNT 0x00000020
>>> +#define NFC_REG_CMD 0x00000024
>>> +#define NFC_REG_RCMD_SET 0x00000028
>>> +#define NFC_REG_ECC_CTL 0x00000034
>>> +#define NFC_REG_ECC_ST 0x00000038
>>> +#define NFC_REG_SPARE_AREA 0x000000A0
>>> #define NFC_RAM0_BASE 0x00000400
>>> #define NFC_RAM1_BASE 0x00000800
>>> -#define NFC_CTL_EN (1 << 0)
>>> -#define NFC_CTL_RESET (1 << 1)
>>> -#define NFC_CTL_RAM_METHOD (1 << 14)
>>> -#define NFC_CTL_PAGE_SIZE_MASK (0xf << 8)
>>> -#define NFC_CTL_PAGE_SIZE(a) ((fls(a) - 11) << 8)
>>> +#define NFC_EN (1 << 0)
>>
>> Is there a strong reason to lose the _CTL_ infix here? I think it's
>> better to keep the register name in the bit field definition,
>> otherwise it becomes too generic and is prone to conflicts.
> Hum, it's like that in the Linux module and in sunxi_nand.c
> But otherwise, no strong reason.
Ah, I see. If it's like this in Linux, then please stick to this, even
if the naming raises some eyebrowses.
Thanks,
Andre
P.S. I will continue with the review in the next days, so please wait
before sending another version. I am tempted to take at least the
cleanups in the current merge window still, that should decrease your
patch queue significantly.
>
>>
>>> +#define NFC_RESET (1 << 1)
>>> +#define NFC_PAGE_SHIFT_MSK (0xf << 8)
>>> +#define NFC_PAGE_SIZE(a) ((fls(a) - 11) << 8)
>>> #define NFC_ECC_EN (1 << 0)
>>> -#define NFC_ECC_PIPELINE (1 << 3)
>>> #define NFC_ECC_EXCEPTION (1 << 4)
>>> -#define NFC_ECC_BLOCK_SIZE (1 << 5)
>>> -#define NFC_ECC_RANDOM_EN (1 << 9)
>>> -#define NFC_ECC_RANDOM_DIRECTION (1 << 10)
>>> +#define NFC_ECC_BLOCK_512 (1 << 5)
>>> +#define NFC_RANDOM_EN (1 << 9)
>>> +#define NFC_RANDOM_DIRECTION (1 << 10)
>>> -#define NFC_ADDR_NUM_OFFSET 16
>>> -#define NFC_SEND_ADDR (1 << 19)
>>> +#define NFC_ADR_NUM_OFFSET 16
>>> +#define NFC_SEND_ADR (1 << 19)
>>
>> But ADDR with two D's looks more correct to me?
> Defilitely, but same remark, it's NFC_SEND_ADR in the Linux module and
> sunxi_nand.c
>
>>
>> In general, can't we keep the better version of each name, and adjust
>> both the SPL and proper code?
> I was a bit more on keeping consistency between the Linux defines and U-
> Boot defines, even if I agree with you, some term are so-so.
>
> But if you think I should change them, I'm open to it.
>
> Thanks!
>
>>
>> Cheers,
>> Andre
>>
>>> #define NFC_ACCESS_DIR (1 << 20)
>>> #define NFC_DATA_TRANS (1 << 21)
>>> #define NFC_SEND_CMD1 (1 << 22)
>>> @@ -66,17 +50,17 @@
>>> #define NFC_ROW_AUTO_INC (1 << 27)
>>> #define NFC_SEND_CMD3 (1 << 28)
>>> #define NFC_SEND_CMD4 (1 << 29)
>>> -#define NFC_RAW_CMD (0 << 30)
>>> -#define NFC_ECC_CMD (1 << 30)
>>> -#define NFC_PAGE_CMD (2 << 30)
>>> +#define NFC_NORMAL_OP (0 << 30)
>>> +#define NFC_ECC_OP (1 << 30)
>>> +#define NFC_PAGE_OP (2 << 30)
>>> -#define NFC_ST_CMD_INT_FLAG (1 << 1)
>>> -#define NFC_ST_DMA_INT_FLAG (1 << 2)
>>> -#define NFC_ST_CMD_FIFO_STAT (1 << 3)
>>> +#define NFC_CMD_INT_FLAG (1 << 1)
>>> +#define NFC_DMA_INT_FLAG (1 << 2)
>>> +#define NFC_CMD_FIFO_STATUS (1 << 3)
>>> #define NFC_READ_CMD_OFFSET 0
>>> -#define NFC_RANDOM_READ_CMD0_OFFSET 8
>>> -#define NFC_RANDOM_READ_CMD1_OFFSET 16
>>> +#define NFC_RND_READ_CMD0_OFFSET 8
>>> +#define NFC_RND_READ_CMD1_OFFSET 16
>>> #define NFC_CMD_RNDOUTSTART 0xE0
>>> #define NFC_CMD_RNDOUT 0x05
>>> @@ -143,8 +127,8 @@ static inline int check_value_negated(int offset,
>>> int unexpected_bits,
>>> static int nand_wait_cmd_fifo_empty(void)
>>> {
>>> - if (!check_value_negated(SUNXI_NFC_BASE + NFC_ST,
>>> NFC_ST_CMD_FIFO_STAT,
>>> - DEFAULT_TIMEOUT_US)) {
>>> + if (!check_value_negated(SUNXI_NFC_BASE + NFC_REG_ST,
>>> + NFC_CMD_FIFO_STATUS, DEFAULT_TIMEOUT_US)) {
>>> printf("nand: timeout waiting for empty cmd FIFO\n");
>>> return -ETIMEDOUT;
>>> }
>>> @@ -154,7 +138,7 @@ static int nand_wait_cmd_fifo_empty(void)
>>> static int nand_wait_int(void)
>>> {
>>> - if (!check_value(SUNXI_NFC_BASE + NFC_ST, NFC_ST_CMD_INT_FLAG,
>>> + if (!check_value(SUNXI_NFC_BASE + NFC_REG_ST, NFC_CMD_INT_FLAG,
>>> DEFAULT_TIMEOUT_US)) {
>>> printf("nand: timeout waiting for interruption\n");
>>> return -ETIMEDOUT;
>>> @@ -171,8 +155,8 @@ static int nand_exec_cmd(u32 cmd)
>>> if (ret)
>>> return ret;
>>> - writel(NFC_ST_CMD_INT_FLAG, SUNXI_NFC_BASE + NFC_ST);
>>> - writel(cmd, SUNXI_NFC_BASE + NFC_CMD);
>>> + writel(NFC_CMD_INT_FLAG, SUNXI_NFC_BASE + NFC_REG_ST);
>>> + writel(cmd, SUNXI_NFC_BASE + NFC_REG_CMD);
>>> return nand_wait_int();
>>> }
>>> @@ -183,13 +167,13 @@ void nand_init(void)
>>> board_nand_init();
>>> - val = readl(SUNXI_NFC_BASE + NFC_CTL);
>>> + val = readl(SUNXI_NFC_BASE + NFC_REG_CTL);
>>> /* enable and reset CTL */
>>> - writel(val | NFC_CTL_EN | NFC_CTL_RESET,
>>> - SUNXI_NFC_BASE + NFC_CTL);
>>> + writel(val | NFC_EN | NFC_RESET,
>>> + SUNXI_NFC_BASE + NFC_REG_CTL);
>>> - if (!check_value_negated(SUNXI_NFC_BASE + NFC_CTL,
>>> - NFC_CTL_RESET, DEFAULT_TIMEOUT_US)) {
>>> + if (!check_value_negated(SUNXI_NFC_BASE + NFC_REG_CTL,
>>> + NFC_RESET, DEFAULT_TIMEOUT_US)) {
>>> printf("Couldn't initialize nand\n");
>>> }
>>> @@ -203,42 +187,42 @@ static void nand_apply_config(const struct
>>> nfc_config *conf)
>>> nand_wait_cmd_fifo_empty();
>>> - val = readl(SUNXI_NFC_BASE + NFC_CTL);
>>> - val &= ~NFC_CTL_PAGE_SIZE_MASK;
>>> - writel(val | NFC_CTL_PAGE_SIZE(conf->page_size),
>>> - SUNXI_NFC_BASE + NFC_CTL);
>>> - writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_CNT);
>>> - writel(conf->page_size, SUNXI_NFC_BASE + NFC_SPARE_AREA);
>>> + val = readl(SUNXI_NFC_BASE + NFC_REG_CTL);
>>> + val &= ~NFC_PAGE_SHIFT_MSK;
>>> + writel(val | NFC_PAGE_SIZE(conf->page_size),
>>> + SUNXI_NFC_BASE + NFC_REG_CTL);
>>> + writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_REG_CNT);
>>> + writel(conf->page_size, SUNXI_NFC_BASE + NFC_REG_SPARE_AREA);
>>> }
>>> static int nand_load_page(const struct nfc_config *conf, u32 offs)
>>> {
>>> int page = offs / conf->page_size;
>>> - writel((NFC_CMD_RNDOUTSTART << NFC_RANDOM_READ_CMD1_OFFSET) |
>>> - (NFC_CMD_RNDOUT << NFC_RANDOM_READ_CMD0_OFFSET) |
>>> + writel((NFC_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
>>> + (NFC_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
>>> (NFC_CMD_READSTART << NFC_READ_CMD_OFFSET),
>>> - SUNXI_NFC_BASE + NFC_RCMD_SET);
>>> - writel(((page & 0xFFFF) << 16), SUNXI_NFC_BASE + NFC_ADDR_LOW);
>>> - writel((page >> 16) & 0xFF, SUNXI_NFC_BASE + NFC_ADDR_HIGH);
>>> + SUNXI_NFC_BASE + NFC_REG_RCMD_SET);
>>> + writel(((page & 0xFFFF) << 16), SUNXI_NFC_BASE + NFC_REG_ADDR_LOW);
>>> + writel((page >> 16) & 0xFF, SUNXI_NFC_BASE + NFC_REG_ADDR_HIGH);
>>> - return nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_RAW_CMD |
>>> - NFC_SEND_ADDR | NFC_WAIT_FLAG |
>>> - ((conf->addr_cycles - 1) << NFC_ADDR_NUM_OFFSET));
>>> + return nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 |
>>> NFC_NORMAL_OP |
>>> + NFC_SEND_ADR | NFC_WAIT_FLAG |
>>> + ((conf->addr_cycles - 1) << NFC_ADR_NUM_OFFSET));
>>> }
>>> static int nand_change_column(u16 column)
>>> {
>>> int ret;
>>> - writel((NFC_CMD_RNDOUTSTART << NFC_RANDOM_READ_CMD1_OFFSET) |
>>> - (NFC_CMD_RNDOUT << NFC_RANDOM_READ_CMD0_OFFSET) |
>>> + writel((NFC_CMD_RNDOUTSTART << NFC_RND_READ_CMD1_OFFSET) |
>>> + (NFC_CMD_RNDOUT << NFC_RND_READ_CMD0_OFFSET) |
>>> (NFC_CMD_RNDOUTSTART << NFC_READ_CMD_OFFSET),
>>> - SUNXI_NFC_BASE + NFC_RCMD_SET);
>>> - writel(column, SUNXI_NFC_BASE + NFC_ADDR_LOW);
>>> + SUNXI_NFC_BASE + NFC_REG_RCMD_SET);
>>> + writel(column, SUNXI_NFC_BASE + NFC_REG_ADDR_LOW);
>>> - ret = nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_RAW_CMD |
>>> - (1 << NFC_ADDR_NUM_OFFSET) | NFC_SEND_ADDR |
>>> + ret = nand_exec_cmd(NFC_SEND_CMD1 | NFC_SEND_CMD2 | NFC_NORMAL_OP |
>>> + (1 << NFC_ADR_NUM_OFFSET) | NFC_SEND_ADR |
>>> NFC_CMD_RNDOUT);
>>> if (ret)
>>> return ret;
>>> @@ -276,16 +260,16 @@ static int nand_read_page(const struct
>>> nfc_config *conf, u32 offs,
>>> u8 *data = dest + data_off;
>>> /* Clear ECC status and restart ECC engine */
>>> - writel(0, SUNXI_NFC_BASE + NFC_ECC_ST);
>>> + writel(0, SUNXI_NFC_BASE + NFC_REG_ECC_ST);
>>> writel((rand_seed << 16) | (conf->ecc_strength << 12) |
>>> - (conf->randomize ? NFC_ECC_RANDOM_EN : 0) |
>>> - (conf->ecc_size == 512 ? NFC_ECC_BLOCK_SIZE : 0) |
>>> + (conf->randomize ? NFC_RANDOM_EN : 0) |
>>> + (conf->ecc_size == 512 ? NFC_ECC_BLOCK_512 : 0) |
>>> NFC_ECC_EN | NFC_ECC_EXCEPTION,
>>> - SUNXI_NFC_BASE + NFC_ECC_CTL);
>>> + SUNXI_NFC_BASE + NFC_REG_ECC_CTL);
>>> /* Move the data in SRAM */
>>> nand_change_column(data_off);
>>> - writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_CNT);
>>> + writel(conf->ecc_size, SUNXI_NFC_BASE + NFC_REG_CNT);
>>> nand_exec_cmd(NFC_DATA_TRANS);
>>> /*
>>> @@ -293,10 +277,10 @@ static int nand_read_page(const struct
>>> nfc_config *conf, u32 offs,
>>> * the data.
>>> */
>>> nand_change_column(oob_off);
>>> - nand_exec_cmd(NFC_DATA_TRANS | NFC_ECC_CMD);
>>> + nand_exec_cmd(NFC_DATA_TRANS | NFC_ECC_OP);
>>> /* Get the ECC status */
>>> - ecc_st = readl(SUNXI_NFC_BASE + NFC_ECC_ST);
>>> + ecc_st = readl(SUNXI_NFC_BASE + NFC_REG_ECC_ST);
>>> /* ECC error detected. */
>>> if (ecc_st & 0xffff)
>>> @@ -315,8 +299,8 @@ static int nand_read_page(const struct nfc_config
>>> *conf, u32 offs,
>>> conf->ecc_size);
>>> /* Stop the ECC engine */
>>> - writel(readl(SUNXI_NFC_BASE + NFC_ECC_CTL) & ~NFC_ECC_EN,
>>> - SUNXI_NFC_BASE + NFC_ECC_CTL);
>>> + writel(readl(SUNXI_NFC_BASE + NFC_REG_ECC_CTL) & ~NFC_ECC_EN,
>>> + SUNXI_NFC_BASE + NFC_REG_ECC_CTL);
>>> if (data_off + conf->ecc_size >= len)
>>> break;
>>
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 06/24] mtd: rawnand: sunxi: cosmetic: merge register definitions for sunxi_nand{,_spl}.c
2025-10-16 14:27 ` [PATCH 06/24] mtd: rawnand: sunxi: cosmetic: merge register definitions for sunxi_nand{, _spl}.c Richard Genoud
@ 2025-10-17 23:09 ` Andre Przywara
0 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2025-10-17 23:09 UTC (permalink / raw)
To: Richard Genoud, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Anand Gore, Linus Walleij, david regan, Andrew Goodbody,
Miquel Raynal, Thomas Petazzoni, u-boot
Hi Richard,
On 16/10/2025 15:27, Richard Genoud wrote:
> Merge common register definitions from sunxi_nand{,_spl}.c
>
> The Allwinner NAND controller registers where in both files, so let's
> just merge all that in a header, it will be easier for maintenance.
>
> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
Very nice, verified that this is correct merge:
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Cheers,
Andre
> ---
> drivers/mtd/nand/raw/sunxi_nand.c | 123 +-------------------
> drivers/mtd/nand/raw/sunxi_nand.h | 156 ++++++++++++++++++++++++++
> drivers/mtd/nand/raw/sunxi_nand_spl.c | 45 +-------
> 3 files changed, 158 insertions(+), 166 deletions(-)
> create mode 100644 drivers/mtd/nand/raw/sunxi_nand.h
>
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
> index c6b9b2a4ebac..000ebd0439f1 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
> @@ -46,128 +46,7 @@
> #include <asm/gpio.h>
> #include <asm/arch/clock.h>
>
> -#define NFC_REG_CTL 0x0000
> -#define NFC_REG_ST 0x0004
> -#define NFC_REG_INT 0x0008
> -#define NFC_REG_TIMING_CTL 0x000C
> -#define NFC_REG_TIMING_CFG 0x0010
> -#define NFC_REG_ADDR_LOW 0x0014
> -#define NFC_REG_ADDR_HIGH 0x0018
> -#define NFC_REG_SECTOR_NUM 0x001C
> -#define NFC_REG_CNT 0x0020
> -#define NFC_REG_CMD 0x0024
> -#define NFC_REG_RCMD_SET 0x0028
> -#define NFC_REG_WCMD_SET 0x002C
> -#define NFC_REG_IO_DATA 0x0030
> -#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_USER_DATA(x) (0x0050 + ((x) * 4))
> -#define NFC_REG_SPARE_AREA 0x00A0
> -#define NFC_REG_PAT_ID 0x00A4
> -#define NFC_RAM0_BASE 0x0400
> -#define NFC_RAM1_BASE 0x0800
> -
> -/* define bit use in NFC_CTL */
> -#define NFC_EN BIT(0)
> -#define NFC_RESET BIT(1)
> -#define NFC_BUS_WIDTH_MSK BIT(2)
> -#define NFC_BUS_WIDTH_8 (0 << 2)
> -#define NFC_BUS_WIDTH_16 (1 << 2)
> -#define NFC_RB_SEL_MSK BIT(3)
> -#define NFC_RB_SEL(x) ((x) << 3)
> -#define NFC_CE_SEL_MSK (0x7 << 24)
> -#define NFC_CE_SEL(x) ((x) << 24)
> -#define NFC_CE_CTL BIT(6)
> -#define NFC_PAGE_SHIFT_MSK (0xf << 8)
> -#define NFC_PAGE_SHIFT(x) (((x) < 10 ? 0 : (x) - 10) << 8)
> -#define NFC_SAM BIT(12)
> -#define NFC_RAM_METHOD BIT(14)
> -#define NFC_DEBUG_CTL BIT(31)
> -
> -/* define bit use in NFC_ST */
> -#define NFC_RB_B2R BIT(0)
> -#define NFC_CMD_INT_FLAG BIT(1)
> -#define NFC_DMA_INT_FLAG BIT(2)
> -#define NFC_CMD_FIFO_STATUS BIT(3)
> -#define NFC_STA BIT(4)
> -#define NFC_NATCH_INT_FLAG BIT(5)
> -#define NFC_RB_STATE(x) BIT(x + 8)
> -
> -/* define bit use in NFC_INT */
> -#define NFC_B2R_INT_ENABLE BIT(0)
> -#define NFC_CMD_INT_ENABLE BIT(1)
> -#define NFC_DMA_INT_ENABLE BIT(2)
> -#define NFC_INT_MASK (NFC_B2R_INT_ENABLE | \
> - NFC_CMD_INT_ENABLE | \
> - NFC_DMA_INT_ENABLE)
> -
> -/* define bit use in NFC_TIMING_CTL */
> -#define NFC_TIMING_CTL_EDO BIT(8)
> -
> -/* define NFC_TIMING_CFG register layout */
> -#define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD) \
> - (((tWB) & 0x3) | (((tADL) & 0x3) << 2) | \
> - (((tWHR) & 0x3) << 4) | (((tRHW) & 0x3) << 6) | \
> - (((tCAD) & 0x7) << 8))
> -
> -/* define bit use in NFC_CMD */
> -#define NFC_CMD_LOW_BYTE_MSK 0xff
> -#define NFC_CMD_HIGH_BYTE_MSK (0xff << 8)
> -#define NFC_CMD(x) (x)
> -#define NFC_ADR_NUM_MSK (0x7 << 16)
> -#define NFC_ADR_NUM(x) (((x) - 1) << 16)
> -#define NFC_SEND_ADR BIT(19)
> -#define NFC_ACCESS_DIR BIT(20)
> -#define NFC_DATA_TRANS BIT(21)
> -#define NFC_SEND_CMD1 BIT(22)
> -#define NFC_WAIT_FLAG BIT(23)
> -#define NFC_SEND_CMD2 BIT(24)
> -#define NFC_SEQ BIT(25)
> -#define NFC_DATA_SWAP_METHOD BIT(26)
> -#define NFC_ROW_AUTO_INC BIT(27)
> -#define NFC_SEND_CMD3 BIT(28)
> -#define NFC_SEND_CMD4 BIT(29)
> -#define NFC_CMD_TYPE_MSK (0x3 << 30)
> -#define NFC_NORMAL_OP (0 << 30)
> -#define NFC_ECC_OP (1 << 30)
> -#define NFC_PAGE_OP (2 << 30)
> -
> -/* define bit use in NFC_RCMD_SET */
> -#define NFC_READ_CMD_MSK 0xff
> -#define NFC_RND_READ_CMD0_MSK (0xff << 8)
> -#define NFC_RND_READ_CMD1_MSK (0xff << 16)
> -
> -/* define bit use in NFC_WCMD_SET */
> -#define NFC_PROGRAM_CMD_MSK 0xff
> -#define NFC_RND_WRITE_CMD_MSK (0xff << 8)
> -#define NFC_READ_CMD0_MSK (0xff << 16)
> -#define NFC_READ_CMD1_MSK (0xff << 24)
> -
> -/* define bit use in NFC_ECC_CTL */
> -#define NFC_ECC_EN BIT(0)
> -#define NFC_ECC_PIPELINE BIT(3)
> -#define NFC_ECC_EXCEPTION BIT(4)
> -#define NFC_ECC_BLOCK_SIZE_MSK BIT(5)
> -#define NFC_ECC_BLOCK_512 (1 << 5)
> -#define NFC_RANDOM_EN BIT(9)
> -#define NFC_RANDOM_DIRECTION BIT(10)
> -#define NFC_ECC_MODE_MSK (0xf << 12)
> -#define NFC_ECC_MODE(x) ((x) << 12)
> -#define NFC_RANDOM_SEED_MSK (0x7fff << 16)
> -#define NFC_RANDOM_SEED(x) ((x) << 16)
> -
> -/* define bit use in NFC_ECC_ST */
> -#define NFC_ECC_ERR(x) BIT(x)
> -#define NFC_ECC_PAT_FOUND(x) BIT(x + 16)
> -#define NFC_ECC_ERR_CNT(b, x) (((x) >> ((b) * 8)) & 0xff)
> -
> -#define NFC_DEFAULT_TIMEOUT_MS 1000
> -
> -#define NFC_SRAM_SIZE 1024
> -
> -#define NFC_MAX_CS 7
> +#include "sunxi_nand.h"
>
> /*
> * Ready/Busy detection type: describes the Ready/Busy detection modes
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
> new file mode 100644
> index 000000000000..59803ccc9f22
> --- /dev/null
> +++ b/drivers/mtd/nand/raw/sunxi_nand.h
> @@ -0,0 +1,156 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Copyright (C) 2025 Bootlin, Richard GENOUD
> + *
> + * merged defines from sunxi_nand{,_spl}.c
> + * Containing the following copyrights:
> + * Copyright (C) 2013 Boris BREZILLON <b.brezillon.dev@gmail.com>
> + * Copyright (C) 2015 Roy Spliet <r.spliet@ultimaker.com>
> + * Copyright (c) 2014-2015, Antmicro Ltd <www.antmicro.com>
> + * Copyright (c) 2015, AW-SOM Technologies <www.aw-som.com>
> + * Derived from:
> + * https://github.com/yuq/sunxi-nfc-mtd
> + * Copyright (C) 2013 Qiang Yu <yuq825@gmail.com>
> + *
> + * https://github.com/hno/Allwinner-Info
> + * Copyright (C) 2013 Henrik Nordström <Henrik Nordström>
> + *
> + * Copyright (C) 2013 Dmitriy B. <rzk333@gmail.com>
> + * Copyright (C) 2013 Sergey Lapin <slapin@ossfans.org>
> + *
> + */
> +
> +#ifndef SUNXI_NAND_H
> +#define SUNXI_NAND_H
> +
> +#include <linux/bitops.h>
> +
> +#define NFC_REG_CTL 0x0000
> +#define NFC_REG_ST 0x0004
> +#define NFC_REG_INT 0x0008
> +#define NFC_REG_TIMING_CTL 0x000C
> +#define NFC_REG_TIMING_CFG 0x0010
> +#define NFC_REG_ADDR_LOW 0x0014
> +#define NFC_REG_ADDR_HIGH 0x0018
> +#define NFC_REG_SECTOR_NUM 0x001C
> +#define NFC_REG_CNT 0x0020
> +#define NFC_REG_CMD 0x0024
> +#define NFC_REG_RCMD_SET 0x0028
> +#define NFC_REG_WCMD_SET 0x002C
> +#define NFC_REG_IO_DATA 0x0030
> +#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_USER_DATA(x) (0x0050 + ((x) * 4))
> +#define NFC_REG_SPARE_AREA 0x00A0
> +#define NFC_REG_PAT_ID 0x00A4
> +#define NFC_RAM0_BASE 0x0400
> +#define NFC_RAM1_BASE 0x0800
> +
> +/* define bit use in NFC_CTL */
> +#define NFC_EN BIT(0)
> +#define NFC_RESET BIT(1)
> +#define NFC_BUS_WIDTH_MSK BIT(2)
> +#define NFC_BUS_WIDTH_8 (0 << 2)
> +#define NFC_BUS_WIDTH_16 (1 << 2)
> +#define NFC_RB_SEL_MSK BIT(3)
> +#define NFC_RB_SEL(x) ((x) << 3)
> +#define NFC_CE_SEL_MSK (0x7 << 24)
> +#define NFC_CE_SEL(x) ((x) << 24)
> +#define NFC_CE_CTL BIT(6)
> +#define NFC_PAGE_SHIFT_MSK (0xf << 8)
> +#define NFC_PAGE_SHIFT(x) (((x) < 10 ? 0 : (x) - 10) << 8)
> +#define NFC_PAGE_SIZE(a) ((fls(a) - 11) << 8)
> +#define NFC_SAM BIT(12)
> +#define NFC_RAM_METHOD BIT(14)
> +#define NFC_DEBUG_CTL BIT(31)
> +
> +/* define bit use in NFC_ST */
> +#define NFC_RB_B2R BIT(0)
> +#define NFC_CMD_INT_FLAG BIT(1)
> +#define NFC_DMA_INT_FLAG BIT(2)
> +#define NFC_CMD_FIFO_STATUS BIT(3)
> +#define NFC_STA BIT(4)
> +#define NFC_NATCH_INT_FLAG BIT(5)
> +#define NFC_RB_STATE(x) BIT((x) + 8)
> +
> +/* define bit use in NFC_INT */
> +#define NFC_B2R_INT_ENABLE BIT(0)
> +#define NFC_CMD_INT_ENABLE BIT(1)
> +#define NFC_DMA_INT_ENABLE BIT(2)
> +#define NFC_INT_MASK (NFC_B2R_INT_ENABLE | \
> + NFC_CMD_INT_ENABLE | \
> + NFC_DMA_INT_ENABLE)
> +
> +/* define bit use in NFC_TIMING_CTL */
> +#define NFC_TIMING_CTL_EDO BIT(8)
> +
> +/* define NFC_TIMING_CFG register layout */
> +#define NFC_TIMING_CFG(tWB, tADL, tWHR, tRHW, tCAD) \
> + (((tWB) & 0x3) | (((tADL) & 0x3) << 2) | \
> + (((tWHR) & 0x3) << 4) | (((tRHW) & 0x3) << 6) | \
> + (((tCAD) & 0x7) << 8))
> +
> +/* define bit use in NFC_CMD */
> +#define NFC_CMD_LOW_BYTE_MSK 0xff
> +#define NFC_CMD_HIGH_BYTE_MSK (0xff << 8)
> +#define NFC_CMD(x) (x)
> +#define NFC_ADR_NUM_OFFSET 16
> +#define NFC_ADR_NUM_MSK (0x7 << NFC_ADR_NUM_OFFSET)
> +#define NFC_ADR_NUM(x) (((x) - 1) << NFC_ADR_NUM_OFFSET)
> +#define NFC_SEND_ADR BIT(19)
> +#define NFC_ACCESS_DIR BIT(20)
> +#define NFC_DATA_TRANS BIT(21)
> +#define NFC_SEND_CMD1 BIT(22)
> +#define NFC_WAIT_FLAG BIT(23)
> +#define NFC_SEND_CMD2 BIT(24)
> +#define NFC_SEQ BIT(25)
> +#define NFC_DATA_SWAP_METHOD BIT(26)
> +#define NFC_ROW_AUTO_INC BIT(27)
> +#define NFC_SEND_CMD3 BIT(28)
> +#define NFC_SEND_CMD4 BIT(29)
> +#define NFC_CMD_TYPE_MSK (0x3 << 30)
> +#define NFC_NORMAL_OP (0 << 30)
> +#define NFC_ECC_OP (1 << 30)
> +#define NFC_PAGE_OP (2 << 30)
> +
> +/* define bit use in NFC_RCMD_SET */
> +#define NFC_READ_CMD_OFFSET 0
> +#define NFC_READ_CMD_MSK (0xff << NFC_READ_CMD_OFFSET)
> +#define NFC_RND_READ_CMD0_OFFSET 8
> +#define NFC_RND_READ_CMD0_MSK (0xff << NFC_RND_READ_CMD0_OFFSET)
> +#define NFC_RND_READ_CMD1_OFFSET 16
> +#define NFC_RND_READ_CMD1_MSK (0xff << NFC_RND_READ_CMD1_OFFSET)
> +
> +/* define bit use in NFC_WCMD_SET */
> +#define NFC_PROGRAM_CMD_MSK 0xff
> +#define NFC_RND_WRITE_CMD_MSK (0xff << 8)
> +#define NFC_READ_CMD0_MSK (0xff << 16)
> +#define NFC_READ_CMD1_MSK (0xff << 24)
> +
> +/* define bit use in NFC_ECC_CTL */
> +#define NFC_ECC_EN BIT(0)
> +#define NFC_ECC_PIPELINE BIT(3)
> +#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_ECC_MODE_MSK (0xf << 12)
> +#define NFC_ECC_MODE(x) ((x) << 12)
> +#define NFC_RANDOM_SEED_MSK (0x7fff << 16)
> +#define NFC_RANDOM_SEED(x) ((x) << 16)
> +
> +/* define bit use in NFC_ECC_ST */
> +#define NFC_ECC_ERR(x) BIT(x)
> +#define NFC_ECC_PAT_FOUND(x) BIT((x) + 16)
> +#define NFC_ECC_ERR_CNT(b, x) (((x) >> ((b) * 8)) & 0xff)
> +
> +#define NFC_DEFAULT_TIMEOUT_MS 1000
> +
> +#define NFC_SRAM_SIZE 1024
> +
> +#define NFC_MAX_CS 7
> +
> +#endif
> diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c
> index 9f80a8010d7b..f75ea473765e 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand_spl.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c
> @@ -13,50 +13,7 @@
> #include <linux/delay.h>
> #include <linux/mtd/rawnand.h>
>
> -/* registers */
> -#define NFC_REG_CTL 0x00000000
> -#define NFC_REG_ST 0x00000004
> -#define NFC_REG_ADDR_LOW 0x00000014
> -#define NFC_REG_ADDR_HIGH 0x00000018
> -#define NFC_REG_CNT 0x00000020
> -#define NFC_REG_CMD 0x00000024
> -#define NFC_REG_RCMD_SET 0x00000028
> -#define NFC_REG_ECC_CTL 0x00000034
> -#define NFC_REG_ECC_ST 0x00000038
> -#define NFC_REG_SPARE_AREA 0x000000A0
> -#define NFC_RAM0_BASE 0x00000400
> -#define NFC_RAM1_BASE 0x00000800
> -
> -#define NFC_EN (1 << 0)
> -#define NFC_RESET (1 << 1)
> -#define NFC_PAGE_SHIFT_MSK (0xf << 8)
> -#define NFC_PAGE_SIZE(a) ((fls(a) - 11) << 8)
> -
> -#define NFC_ECC_EN (1 << 0)
> -#define NFC_ECC_EXCEPTION (1 << 4)
> -#define NFC_ECC_BLOCK_512 (1 << 5)
> -#define NFC_RANDOM_EN (1 << 9)
> -#define NFC_RANDOM_DIRECTION (1 << 10)
> -
> -#define NFC_ADR_NUM_OFFSET 16
> -#define NFC_SEND_ADR (1 << 19)
> -#define NFC_ACCESS_DIR (1 << 20)
> -#define NFC_DATA_TRANS (1 << 21)
> -#define NFC_SEND_CMD1 (1 << 22)
> -#define NFC_WAIT_FLAG (1 << 23)
> -#define NFC_SEND_CMD2 (1 << 24)
> -#define NFC_SEQ (1 << 25)
> -#define NFC_DATA_SWAP_METHOD (1 << 26)
> -#define NFC_ROW_AUTO_INC (1 << 27)
> -#define NFC_SEND_CMD3 (1 << 28)
> -#define NFC_SEND_CMD4 (1 << 29)
> -#define NFC_NORMAL_OP (0 << 30)
> -#define NFC_ECC_OP (1 << 30)
> -#define NFC_PAGE_OP (2 << 30)
> -
> -#define NFC_CMD_INT_FLAG (1 << 1)
> -#define NFC_DMA_INT_FLAG (1 << 2)
> -#define NFC_CMD_FIFO_STATUS (1 << 3)
> +#include "sunxi_nand.h"
>
> #define NFC_READ_CMD_OFFSET 0
> #define NFC_RND_READ_CMD0_OFFSET 8
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 07/24] mtd: rawnand: sunxi: cosmetic: add per SoC capabilities
2025-10-16 14:27 ` [PATCH 07/24] mtd: rawnand: sunxi: cosmetic: add per SoC capabilities Richard Genoud
@ 2025-10-17 23:10 ` Andre Przywara
0 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2025-10-17 23:10 UTC (permalink / raw)
To: Richard Genoud, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot
Hi,
On 16/10/2025 15:27, Richard Genoud wrote:
> Introduce per SoC capabilities in sunxi_nand.c
>
> This prepares for the H616 support that has quite a lot differences in
> registers offset and capabilities.
>
> Start with the ECC strength table.
>
> No functional change.
Looks good, just one nit below:
>
> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
> ---
> drivers/mtd/nand/raw/sunxi_nand.c | 18 ++++++++++++++++--
> drivers/mtd/nand/raw/sunxi_nand.h | 10 ++++++++++
> 2 files changed, 26 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
> index 000ebd0439f1..3f30077b3d15 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
> @@ -149,6 +149,7 @@ static inline struct sunxi_nand_chip *to_sunxi_nand(struct nand_chip *nand)
> * @clk_rate: NAND controller current clock rate
> * @chips: a list containing all the NAND chips attached to
> * this NAND controller
> + * @caps: NAND Controller capabilities
Please indent the description to line up with the other ones.
With that fixed:
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Cheers,
Andre
> */
> struct sunxi_nfc {
> struct nand_hw_control controller;
> @@ -159,6 +160,7 @@ struct sunxi_nfc {
> unsigned long assigned_cs;
> unsigned long clk_rate;
> struct list_head chips;
> + const struct sunxi_nfc_caps *caps;
> };
>
> static inline struct sunxi_nfc *to_sunxi_nfc(struct nand_hw_control *ctrl)
> @@ -1270,6 +1272,9 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
> struct nand_ecc_ctrl *ecc)
> {
> static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
> + struct nand_chip *nand = mtd_to_nand(mtd);
> + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
> + struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
> struct sunxi_nand_hw_ecc *data;
> struct nand_ecclayout *layout;
> int nsectors;
> @@ -1292,7 +1297,7 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
> }
>
> /* 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
> @@ -1303,7 +1308,7 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
> }
> }
>
> - if (i >= ARRAY_SIZE(strengths)) {
> + if (i >= nfc->caps->nstrengths) {
> dev_err(mtd->dev, "unsupported strength\n");
> ret = -ENOTSUPP;
> goto err;
> @@ -1681,6 +1686,10 @@ static int sunxi_nand_probe(struct udevice *dev)
> if (!nfc->regs)
> return -EINVAL;
>
> + nfc->caps = (const struct sunxi_nfc_caps *)dev_get_driver_data(dev);
> + if (!nfc->caps)
> + return -EINVAL;
> +
> ret = reset_get_bulk(dev, &rst_bulk);
> if (!ret)
> reset_deassert_bulk(&rst_bulk);
> @@ -1702,9 +1711,14 @@ static int sunxi_nand_probe(struct udevice *dev)
> return 0;
> }
>
> +static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
> + .nstrengths = 9,
> +};
> +
> static const struct udevice_id sunxi_nand_ids[] = {
> {
> .compatible = "allwinner,sun4i-a10-nand",
> + .data = (unsigned long)&sunxi_nfc_a10_caps,
> },
> { }
> };
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
> index 59803ccc9f22..80fbc8df0090 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.h
> +++ b/drivers/mtd/nand/raw/sunxi_nand.h
> @@ -153,4 +153,14 @@
>
> #define NFC_MAX_CS 7
>
> +/*
> + * NAND Controller capabilities structure: stores NAND controller capabilities
> + * for distinction between compatible strings.
> + *
> + * @nstrengths: Number of element of ECC strengths array
> + */
> +struct sunxi_nfc_caps {
> + unsigned int nstrengths;
> +};
> +
> #endif
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 08/24] mtd: rawnand: sunxi: cosmetic: move ECC_ERR_CNT register offset in SoC caps
2025-10-16 14:27 ` [PATCH 08/24] mtd: rawnand: sunxi: cosmetic: move ECC_ERR_CNT register offset in SoC caps Richard Genoud
@ 2025-10-17 23:10 ` Andre Przywara
0 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2025-10-17 23:10 UTC (permalink / raw)
To: Richard Genoud, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Anand Gore, Linus Walleij, david regan, Andrew Goodbody,
Miquel Raynal, Thomas Petazzoni, u-boot
Hi,
On 16/10/2025 15:27, Richard Genoud wrote:
> ECC_ERR_CNT register offset moved in H616, so let's make it a SoC cap
>
> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Thanks,
Andre
> ---
> drivers/mtd/nand/raw/sunxi_nand.c | 3 ++-
> drivers/mtd/nand/raw/sunxi_nand.h | 5 ++++-
> 2 files changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
> index 3f30077b3d15..359f6cdda08a 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
> @@ -737,7 +737,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
> return 1;
> }
>
> - ret = NFC_ECC_ERR_CNT(0, readl(nfc->regs + NFC_REG_ECC_ERR_CNT(0)));
> + ret = NFC_ECC_ERR_CNT(0, readl(nfc->regs + NFC_REG_ECC_ERR_CNT(nfc, 0)));
>
> memcpy_fromio(data, nfc->regs + NFC_RAM0_BASE, ecc->size);
>
> @@ -1713,6 +1713,7 @@ static int sunxi_nand_probe(struct udevice *dev)
>
> static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
> .nstrengths = 9,
> + .reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
> };
>
> static const struct udevice_id sunxi_nand_ids[] = {
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
> index 80fbc8df0090..b961f2ef3bf2 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.h
> +++ b/drivers/mtd/nand/raw/sunxi_nand.h
> @@ -41,7 +41,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
> @@ -158,9 +159,11 @@
> * for distinction between compatible strings.
> *
> * @nstrengths: Number of element of ECC strengths array
> + * @reg_ecc_err_cnt: ECC error counter register
> */
> struct sunxi_nfc_caps {
> unsigned int nstrengths;
> + unsigned int reg_ecc_err_cnt;
> };
>
> #endif
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 09/24] mtd: rawnand: sunxi: cosmetic: move USER_DATA register offset in SoC caps
2025-10-16 14:27 ` [PATCH 09/24] mtd: rawnand: sunxi: cosmetic: move USER_DATA " Richard Genoud
@ 2025-10-17 23:10 ` Andre Przywara
0 siblings, 0 replies; 43+ messages in thread
From: Andre Przywara @ 2025-10-17 23:10 UTC (permalink / raw)
To: Richard Genoud, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Anand Gore, Linus Walleij, david regan, Andrew Goodbody,
Miquel Raynal, Thomas Petazzoni, u-boot
Hi,
On 16/10/2025 15:27, Richard Genoud wrote:
> USER_DATA register offset moved in H616, so let's make it a SoC cap
>
> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
The pattern looks familiar by now ;-)
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Cheers,
Andre
> ---
> drivers/mtd/nand/raw/sunxi_nand.c | 7 ++++---
> drivers/mtd/nand/raw/sunxi_nand.h | 5 ++++-
> 2 files changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
> index 359f6cdda08a..64a0db37f3f0 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
> @@ -767,7 +767,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
> * Retrieve the corrected OOB bytes.
> */
> sunxi_nfc_user_data_to_buf(readl(nfc->regs +
> - NFC_REG_USER_DATA(0)),
> + NFC_REG_USER_DATA(nfc, 0)),
> oob);
>
> /* De-randomize the Bad Block Marker. */
> @@ -838,10 +838,10 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
> memcpy(user_data, oob, 4);
> sunxi_nfc_randomize_bbm(mtd, page, user_data);
> writel(sunxi_nfc_buf_to_user_data(user_data),
> - nfc->regs + NFC_REG_USER_DATA(0));
> + nfc->regs + NFC_REG_USER_DATA(nfc, 0));
> } else {
> writel(sunxi_nfc_buf_to_user_data(oob),
> - nfc->regs + NFC_REG_USER_DATA(0));
> + nfc->regs + NFC_REG_USER_DATA(nfc, 0));
> }
>
> if (data_off + ecc->size != oob_off)
> @@ -1714,6 +1714,7 @@ static int sunxi_nand_probe(struct udevice *dev)
> static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
> .nstrengths = 9,
> .reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
> + .reg_user_data = NFC_REG_A10_USER_DATA,
> };
>
> static const struct udevice_id sunxi_nand_ids[] = {
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
> index b961f2ef3bf2..1977d1bd8eaf 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.h
> +++ b/drivers/mtd/nand/raw/sunxi_nand.h
> @@ -43,7 +43,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_RAM0_BASE 0x0400
> @@ -160,10 +161,12 @@
> *
> * @nstrengths: Number of element of ECC strengths array
> * @reg_ecc_err_cnt: ECC error counter register
> + * @reg_user_data: User data register
> */
> struct sunxi_nfc_caps {
> unsigned int nstrengths;
> unsigned int reg_ecc_err_cnt;
> + unsigned int reg_user_data;
> };
>
> #endif
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 10/24] mtd: rawnand: sunxi: cosmetic: move ECC_PAT_FOUND register in SoC caps
2025-10-16 14:27 ` [PATCH 10/24] mtd: rawnand: sunxi: cosmetic: move ECC_PAT_FOUND register " Richard Genoud
@ 2025-10-17 23:11 ` Andre Przywara
2025-10-20 6:46 ` Richard GENOUD
0 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2025-10-17 23:11 UTC (permalink / raw)
To: Richard Genoud, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Anand Gore, Linus Walleij, david regan, Andrew Goodbody,
Miquel Raynal, Thomas Petazzoni, u-boot
Hi,
On 16/10/2025 15:27, Richard Genoud wrote:
> Move ECC_PAT_FOUND register in SoC capabilities structure
>
> This register offset moved in H616, it's now its own register, not
> shared with NFC_ECC_ST.
> Push that specificity in caps structure.
Right, so if I understand correctly, this moves from bits[31:16] of
ECC_ST to bits[31:0] of a new separate register.
If this is correct, can you add this piece of information to the commit
message, to motivate the addition of the whole field masking operation?
Assuming that this looks alright to me:
> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Cheers,
Andre
> ---
> drivers/mtd/nand/raw/sunxi_nand.c | 9 +++++++--
> drivers/mtd/nand/raw/sunxi_nand.h | 16 +++++++++++++++-
> 2 files changed, 22 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
> index 64a0db37f3f0..869b3ddd971c 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
> @@ -699,6 +699,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
> struct nand_ecc_ctrl *ecc = &nand->ecc;
> int raw_mode = 0;
> u32 status;
> + u32 pattern_found;
> int ret;
>
> if (*cur_off != data_off)
> @@ -724,8 +725,9 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
>
> *cur_off = oob_off + ecc->bytes + 4;
>
> - status = readl(nfc->regs + NFC_REG_ECC_ST);
> - if (status & NFC_ECC_PAT_FOUND(0)) {
> + pattern_found = readl(nfc->regs + nfc->caps->reg_pat_found);
> + pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(nfc), pattern_found);
> + if (pattern_found & NFC_ECC_PAT_FOUND(0)) {
> u8 pattern = 0xff;
>
> if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1)))
> @@ -744,6 +746,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
> nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
> sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4, true, page);
>
> + status = readl(nfc->regs + NFC_REG_ECC_ST);
> if (status & NFC_ECC_ERR(0)) {
> /*
> * Re-read the data with the randomizer disabled to identify
> @@ -1715,6 +1718,8 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
> .nstrengths = 9,
> .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),
> };
>
> static const struct udevice_id sunxi_nand_ids[] = {
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
> index 1977d1bd8eaf..35079d37bb1f 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.h
> +++ b/drivers/mtd/nand/raw/sunxi_nand.h
> @@ -25,6 +25,9 @@
>
> #include <linux/bitops.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
> @@ -146,7 +149,14 @@
>
> /* define bit use in NFC_ECC_ST */
> #define NFC_ECC_ERR(x) BIT(x)
> -#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(x) BIT(x)
> +#define NFC_ECC_PAT_FOUND_MSK(nfc) ((nfc)->caps->pat_found_mask)
> +
> #define NFC_ECC_ERR_CNT(b, x) (((x) >> ((b) * 8)) & 0xff)
>
> #define NFC_DEFAULT_TIMEOUT_MS 1000
> @@ -162,11 +172,15 @@
> * @nstrengths: Number of element of ECC strengths array
> * @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
> */
> struct sunxi_nfc_caps {
> unsigned int nstrengths;
> unsigned int reg_ecc_err_cnt;
> unsigned int reg_user_data;
> + unsigned int reg_pat_found;
> + unsigned int pat_found_mask;
> };
>
> #endif
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 11/24] mtd: rawnand: sunxi: cosmetic: add has_ecc_block_512 capability
2025-10-16 14:27 ` [PATCH 11/24] mtd: rawnand: sunxi: cosmetic: add has_ecc_block_512 capability Richard Genoud
@ 2025-10-17 23:11 ` Andre Przywara
2025-10-20 7:02 ` Richard GENOUD
0 siblings, 1 reply; 43+ messages in thread
From: Andre Przywara @ 2025-10-17 23:11 UTC (permalink / raw)
To: Richard Genoud, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Anand Gore, Linus Walleij, david regan, Andrew Goodbody,
Miquel Raynal, Thomas Petazzoni, u-boot
Hi,
On 16/10/2025 15:27, Richard Genoud wrote:
> Introduce has_ecc_block_512 capability
>
> The 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 +++++++++++---
> drivers/mtd/nand/raw/sunxi_nand.h | 2 ++
> 2 files changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
> index 869b3ddd971c..fddb1cada023 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
> @@ -660,11 +660,12 @@ static void sunxi_nfc_hw_ecc_enable(struct mtd_info *mtd)
> u32 ecc_ctl;
>
> ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
> - ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE |
> - NFC_ECC_BLOCK_SIZE_MSK);
> + ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE);
> + if (nfc->caps->has_ecc_block_512)
> + ecc_ctl &= ~NFC_ECC_BLOCK_SIZE_MSK;
So if I get this correctly, then NFC_ECC_BLOCK_SIZE_MSK and
NFC_ECC_BLOCK_512 are referring to the same single bit register field,
in bit 5? Can we lose the MSK definition then, and clear the field
unconditionally? Or is it that on the H6/H616 we must never touch bit 5,
because it refers to something else (NDFC_RANDOM_EN?)?
In any case I think we don't need identical MSK and BLOCK_512
definitions, do we?
By the way: Do you have any MMIO frame register description for the old
NAND device? I checked some of the older manuals, but the ones I looked
at were only showing timing diagrams, but no register map.
Cheers,
Andre
> ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) | NFC_ECC_EXCEPTION;
>
> - if (nand->ecc.size == 512)
> + if (nand->ecc.size == 512 && nfc->caps->has_ecc_block_512)
> ecc_ctl |= NFC_ECC_BLOCK_512;
>
> writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL);
> @@ -1454,6 +1455,8 @@ static void sunxi_nand_ecc_cleanup(struct nand_ecc_ctrl *ecc)
> static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc)
> {
> struct nand_chip *nand = mtd_to_nand(mtd);
> + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
> + struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
> int ret;
>
> if (!ecc->size) {
> @@ -1464,6 +1467,10 @@ static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct nand_ecc_ctrl *ecc)
> if (!ecc->size || !ecc->strength)
> return -EINVAL;
>
> + /* If 512B ECC is not supported, switch to 1024 */
> + if (ecc->size == 512 && !nfc->caps->has_ecc_block_512)
> + ecc->size = 1024;
> +
> switch (ecc->mode) {
> case NAND_ECC_SOFT_BCH:
> break;
> @@ -1715,6 +1722,7 @@ static int sunxi_nand_probe(struct udevice *dev)
> }
>
> static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
> + .has_ecc_block_512 = true,
> .nstrengths = 9,
> .reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
> .reg_user_data = NFC_REG_A10_USER_DATA,
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
> index 35079d37bb1f..be294d7cea0a 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.h
> +++ b/drivers/mtd/nand/raw/sunxi_nand.h
> @@ -169,6 +169,7 @@
> * NAND Controller capabilities structure: stores NAND controller capabilities
> * for distinction between compatible strings.
> *
> + * @has_ecc_block_512: If the ECC can handle 512B or only 1024B chuncks
> * @nstrengths: Number of element of ECC strengths array
> * @reg_ecc_err_cnt: ECC error counter register
> * @reg_user_data: User data register
> @@ -176,6 +177,7 @@
> * @pat_found_mask: ECC_PAT_FOUND mask in NFC_REG_PAT_FOUND register
> */
> struct sunxi_nfc_caps {
> + bool has_ecc_block_512;
> unsigned int nstrengths;
> unsigned int reg_ecc_err_cnt;
> unsigned int reg_user_data;
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 10/24] mtd: rawnand: sunxi: cosmetic: move ECC_PAT_FOUND register in SoC caps
2025-10-17 23:11 ` Andre Przywara
@ 2025-10-20 6:46 ` Richard GENOUD
0 siblings, 0 replies; 43+ messages in thread
From: Richard GENOUD @ 2025-10-20 6:46 UTC (permalink / raw)
To: Andre Przywara, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Anand Gore, Linus Walleij, david regan, Andrew Goodbody,
Miquel Raynal, Thomas Petazzoni, u-boot
Hi,
Le 18/10/2025 à 01:11, Andre Przywara a écrit :
> Hi,
>
> On 16/10/2025 15:27, Richard Genoud wrote:
>> Move ECC_PAT_FOUND register in SoC capabilities structure
>>
>> This register offset moved in H616, it's now its own register, not
>> shared with NFC_ECC_ST.
>> Push that specificity in caps structure.
>
> Right, so if I understand correctly, this moves from bits[31:16] of
> ECC_ST to bits[31:0] of a new separate register.
> If this is correct, can you add this piece of information to the commit
> message, to motivate the addition of the whole field masking operation?
Yes, exactly.
I'll add that this info in the commit message.
Thanks!
>
> Assuming that this looks alright to me:
>
>> Signed-off-by: Richard Genoud <richard.genoud@bootlin.com>
>
> Reviewed-by: Andre Przywara <andre.przywara@arm.com>
>
> Cheers,
> Andre
>
>
>> ---
>> drivers/mtd/nand/raw/sunxi_nand.c | 9 +++++++--
>> drivers/mtd/nand/raw/sunxi_nand.h | 16 +++++++++++++++-
>> 2 files changed, 22 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/
>> sunxi_nand.c
>> index 64a0db37f3f0..869b3ddd971c 100644
>> --- a/drivers/mtd/nand/raw/sunxi_nand.c
>> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
>> @@ -699,6 +699,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct
>> mtd_info *mtd,
>> struct nand_ecc_ctrl *ecc = &nand->ecc;
>> int raw_mode = 0;
>> u32 status;
>> + u32 pattern_found;
>> int ret;
>> if (*cur_off != data_off)
>> @@ -724,8 +725,9 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct
>> mtd_info *mtd,
>> *cur_off = oob_off + ecc->bytes + 4;
>> - status = readl(nfc->regs + NFC_REG_ECC_ST);
>> - if (status & NFC_ECC_PAT_FOUND(0)) {
>> + pattern_found = readl(nfc->regs + nfc->caps->reg_pat_found);
>> + pattern_found = field_get(NFC_ECC_PAT_FOUND_MSK(nfc),
>> pattern_found);
>> + if (pattern_found & NFC_ECC_PAT_FOUND(0)) {
>> u8 pattern = 0xff;
>> if (unlikely(!(readl(nfc->regs + NFC_REG_PAT_ID) & 0x1)))
>> @@ -744,6 +746,7 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct
>> mtd_info *mtd,
>> nand->cmdfunc(mtd, NAND_CMD_RNDOUT, oob_off, -1);
>> sunxi_nfc_randomizer_read_buf(mtd, oob, ecc->bytes + 4, true,
>> page);
>> + status = readl(nfc->regs + NFC_REG_ECC_ST);
>> if (status & NFC_ECC_ERR(0)) {
>> /*
>> * Re-read the data with the randomizer disabled to identify
>> @@ -1715,6 +1718,8 @@ static const struct sunxi_nfc_caps
>> sunxi_nfc_a10_caps = {
>> .nstrengths = 9,
>> .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),
>> };
>> static const struct udevice_id sunxi_nand_ids[] = {
>> diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/
>> sunxi_nand.h
>> index 1977d1bd8eaf..35079d37bb1f 100644
>> --- a/drivers/mtd/nand/raw/sunxi_nand.h
>> +++ b/drivers/mtd/nand/raw/sunxi_nand.h
>> @@ -25,6 +25,9 @@
>> #include <linux/bitops.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
>> @@ -146,7 +149,14 @@
>> /* define bit use in NFC_ECC_ST */
>> #define NFC_ECC_ERR(x) BIT(x)
>> -#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(x) BIT(x)
>> +#define NFC_ECC_PAT_FOUND_MSK(nfc) ((nfc)->caps->pat_found_mask)
>> +
>> #define NFC_ECC_ERR_CNT(b, x) (((x) >> ((b) * 8)) & 0xff)
>> #define NFC_DEFAULT_TIMEOUT_MS 1000
>> @@ -162,11 +172,15 @@
>> * @nstrengths: Number of element of ECC strengths array
>> * @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
>> */
>> struct sunxi_nfc_caps {
>> unsigned int nstrengths;
>> unsigned int reg_ecc_err_cnt;
>> unsigned int reg_user_data;
>> + unsigned int reg_pat_found;
>> + unsigned int pat_found_mask;
>> };
>> #endif
>
--
Richard Genoud, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 11/24] mtd: rawnand: sunxi: cosmetic: add has_ecc_block_512 capability
2025-10-17 23:11 ` Andre Przywara
@ 2025-10-20 7:02 ` Richard GENOUD
0 siblings, 0 replies; 43+ messages in thread
From: Richard GENOUD @ 2025-10-20 7:02 UTC (permalink / raw)
To: Andre Przywara, Jagan Teki, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Anand Gore, Linus Walleij, david regan, Andrew Goodbody,
Miquel Raynal, Thomas Petazzoni, u-boot
Hi,
Le 18/10/2025 à 01:11, Andre Przywara a écrit :
> Hi,
>
> On 16/10/2025 15:27, Richard Genoud wrote:
>> Introduce has_ecc_block_512 capability
>>
>> The 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 +++++++++++---
>> drivers/mtd/nand/raw/sunxi_nand.h | 2 ++
>> 2 files changed, 13 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/
>> sunxi_nand.c
>> index 869b3ddd971c..fddb1cada023 100644
>> --- a/drivers/mtd/nand/raw/sunxi_nand.c
>> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
>> @@ -660,11 +660,12 @@ static void sunxi_nfc_hw_ecc_enable(struct
>> mtd_info *mtd)
>> u32 ecc_ctl;
>> ecc_ctl = readl(nfc->regs + NFC_REG_ECC_CTL);
>> - ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE |
>> - NFC_ECC_BLOCK_SIZE_MSK);
>> + ecc_ctl &= ~(NFC_ECC_MODE_MSK | NFC_ECC_PIPELINE);
>> + if (nfc->caps->has_ecc_block_512)
>> + ecc_ctl &= ~NFC_ECC_BLOCK_SIZE_MSK;
>
> So if I get this correctly, then NFC_ECC_BLOCK_SIZE_MSK and
> NFC_ECC_BLOCK_512 are referring to the same single bit register field,
> in bit 5? Can we lose the MSK definition then, and clear the field
> unconditionally? Or is it that on the H6/H616 we must never touch bit 5,
> because it refers to something else (NDFC_RANDOM_EN?)?
> In any case I think we don't need identical MSK and BLOCK_512
> definitions, do we?
Yes, 2nd case:
On A23/A10, the bit 5 (NFC_ECC_BLOCK_512) in NDFC_ECC_CTL register
(0x34) is controlling the size of one ECC data block (0: 1024bytes 1:512
bytes).
On H6, this bit NFC_ECC_BLOCK_512 doesn't exists anymore, but instead,
bit 5 of NDFC_ECC_CTL register (0x34) is NDFC_RANDOM_EN (which was
itself on bit 9 for A10/A23)
So yes, we can definitely loose NFC_ECC_BLOCK_SIZE_MSK, and keep
has_ecc_block_512 to differentiate A10 from H6.
>
> By the way: Do you have any MMIO frame register description for the old
> NAND device? I checked some of the older manuals, but the ones I looked
> at were only showing timing diagrams, but no register map.
Yes, the NAND controller in A33 is the same (AFAIK) than on A23:
https://linux-sunxi.org/images/4/49/A33_Nand_Flash_Controller_Specification.pdf
Thanks!
>
> Cheers,
> Andre
>
>> ecc_ctl |= NFC_ECC_EN | NFC_ECC_MODE(data->mode) |
>> NFC_ECC_EXCEPTION;
>> - if (nand->ecc.size == 512)
>> + if (nand->ecc.size == 512 && nfc->caps->has_ecc_block_512)
>> ecc_ctl |= NFC_ECC_BLOCK_512;
>> writel(ecc_ctl, nfc->regs + NFC_REG_ECC_CTL);
>> @@ -1454,6 +1455,8 @@ static void sunxi_nand_ecc_cleanup(struct
>> nand_ecc_ctrl *ecc)
>> static int sunxi_nand_ecc_init(struct mtd_info *mtd, struct
>> nand_ecc_ctrl *ecc)
>> {
>> struct nand_chip *nand = mtd_to_nand(mtd);
>> + struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
>> + struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
>> int ret;
>> if (!ecc->size) {
>> @@ -1464,6 +1467,10 @@ static int sunxi_nand_ecc_init(struct mtd_info
>> *mtd, struct nand_ecc_ctrl *ecc)
>> if (!ecc->size || !ecc->strength)
>> return -EINVAL;
>> + /* If 512B ECC is not supported, switch to 1024 */
>> + if (ecc->size == 512 && !nfc->caps->has_ecc_block_512)
>> + ecc->size = 1024;
>> +
>> switch (ecc->mode) {
>> case NAND_ECC_SOFT_BCH:
>> break;
>> @@ -1715,6 +1722,7 @@ static int sunxi_nand_probe(struct udevice *dev)
>> }
>> static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
>> + .has_ecc_block_512 = true,
>> .nstrengths = 9,
>> .reg_ecc_err_cnt = NFC_REG_A10_ECC_ERR_CNT,
>> .reg_user_data = NFC_REG_A10_USER_DATA,
>> diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/
>> sunxi_nand.h
>> index 35079d37bb1f..be294d7cea0a 100644
>> --- a/drivers/mtd/nand/raw/sunxi_nand.h
>> +++ b/drivers/mtd/nand/raw/sunxi_nand.h
>> @@ -169,6 +169,7 @@
>> * NAND Controller capabilities structure: stores NAND controller
>> capabilities
>> * for distinction between compatible strings.
>> *
>> + * @has_ecc_block_512: If the ECC can handle 512B or only 1024B
>> chuncks
>> * @nstrengths: Number of element of ECC strengths array
>> * @reg_ecc_err_cnt: ECC error counter register
>> * @reg_user_data: User data register
>> @@ -176,6 +177,7 @@
>> * @pat_found_mask: ECC_PAT_FOUND mask in NFC_REG_PAT_FOUND register
>> */
>> struct sunxi_nfc_caps {
>> + bool has_ecc_block_512;
>> unsigned int nstrengths;
>> unsigned int reg_ecc_err_cnt;
>> unsigned int reg_user_data;
>
--
Richard Genoud, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 43+ messages in thread
* Re: [PATCH 22/24] mtd: rawnand: sunxi: add support for H6/H616 nand controller
2025-10-16 14:27 ` [PATCH 22/24] mtd: rawnand: sunxi: add support for H6/H616 nand controller Richard Genoud
@ 2025-10-20 14:05 ` Richard GENOUD
0 siblings, 0 replies; 43+ messages in thread
From: Richard GENOUD @ 2025-10-20 14:05 UTC (permalink / raw)
To: Jagan Teki, Andre Przywara, Tom Rini, Hans de Goede,
Lukasz Majewski, Sean Anderson, Dario Binacchi, Michael Trimarchi
Cc: Jernej Skrabec, Chen-Yu Tsai, Andrey Skvortsov, Marek Vasut,
Dinesh Maniyam, Anand Gore, Linus Walleij, david regan,
Andrew Goodbody, Miquel Raynal, Thomas Petazzoni, u-boot
Hi,
Le 16/10/2025 à 16:27, Richard Genoud a écrit :
> Introduce H6/H616 NAND controller support for U-Boot
>
> 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.
>
> Introduce the basic support, with ECC and scrambling, but 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/Kconfig | 3 +-
> drivers/mtd/nand/raw/sunxi_nand.c | 112 ++++++++++++++++++++++++++++--
> drivers/mtd/nand/raw/sunxi_nand.h | 32 ++++++++-
> 3 files changed, 139 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
> index 754b99bf3eb6..e4c4d9bcbf63 100644
> --- a/drivers/mtd/nand/raw/Kconfig
> +++ b/drivers/mtd/nand/raw/Kconfig
> @@ -467,7 +467,8 @@ config NAND_SANDBOX
> config NAND_SUNXI
> bool "Support for NAND on Allwinner SoCs"
> default ARCH_SUNXI
> - depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUN8I
> + depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I || MACH_SUN8I \
> + || MACH_SUN50I_H616
Hum, it seems I forgot to add MACH_SUN50I_H6 here.
> select SYS_NAND_SELF_INIT
> select SYS_NAND_U_BOOT_LOCATIONS
> select SPL_NAND_SUPPORT
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c
> index 58c895095ce9..c9133cdc8844 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.c
> +++ b/drivers/mtd/nand/raw/sunxi_nand.c
> @@ -170,8 +170,14 @@ static inline struct sunxi_nfc *to_sunxi_nfc(struct nand_hw_control *ctrl)
>
> static void sunxi_nfc_set_clk_rate(unsigned long hz)
> {
> +#if defined(CONFIG_MACH_SUN50I_H616) || defined(CONFIG_MACH_SUN50I_H6)
> + void * const ccm = (void *)SUNXI_CCM_BASE;
> + void * const nand0_clk_cfg = ccm + CCU_NAND0_CLK_CFG;
> +#else
> struct sunxi_ccm_reg *const ccm =
> (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
> + u32 *nand0_clk_cfg = &ccm->nand0_clk_cfg;
> +#endif
> int div_m, div_n;
>
> div_m = (clock_get_pll6() + hz - 1) / hz;
> @@ -186,8 +192,16 @@ static void sunxi_nfc_set_clk_rate(unsigned long hz)
> /* config mod clock */
> writel(CCM_NAND_CTRL_ENABLE | CCM_NAND_CTRL_PLL6 |
> CCM_NAND_CTRL_N(div_n) | CCM_NAND_CTRL_M(div_m),
> - &ccm->nand0_clk_cfg);
> + nand0_clk_cfg);
>
> +#if defined(CONFIG_MACH_SUN50I_H616) || defined(CONFIG_MACH_SUN50I_H6)
> + setbits_le32(ccm + CCU_H6_NAND_GATE_RESET,
> + (1 << GATE_SHIFT) | (1 << RESET_SHIFT));
> + setbits_le32(ccm + CCU_H6_MBUS_GATE, (1 << MBUS_GATE_OFFSET_NAND));
> + writel(CCM_NAND_CTRL_ENABLE | CCM_NAND_CTRL_PLL6 |
> + CCM_NAND_CTRL_N(div_n) | CCM_NAND_CTRL_M(div_m),
> + ccm + CCU_NAND1_CLK_CFG);
> +#else
> /* gate on nand clock */
> setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_NAND0));
> #ifdef CONFIG_MACH_SUN9I
> @@ -195,6 +209,7 @@ static void sunxi_nfc_set_clk_rate(unsigned long hz)
> #else
> setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_DMA));
> #endif
> +#endif
> }
>
> static int sunxi_nfc_wait_int(struct sunxi_nfc *nfc, u32 flags,
> @@ -689,6 +704,53 @@ static inline void sunxi_nfc_user_data_to_buf(u32 user_data, u8 *buf)
> buf[3] = user_data >> 24;
> }
>
> +/*
> + * On H6/H616 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 int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
> u8 *data, int data_off,
> u8 *oob, int oob_off,
> @@ -716,6 +778,9 @@ static int sunxi_nfc_hw_ecc_read_chunk(struct mtd_info *mtd,
> if (ret)
> return ret;
>
> + sunxi_nfc_reset_user_data_len(nfc);
> + sunxi_nfc_set_user_data_len(nfc, 4, 0);
> +
> sunxi_nfc_randomizer_enable(mtd);
> writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD | NFC_ECC_OP,
> nfc->regs + NFC_REG_CMD);
> @@ -856,6 +921,9 @@ static int sunxi_nfc_hw_ecc_write_chunk(struct mtd_info *mtd,
> if (ret)
> return ret;
>
> + sunxi_nfc_reset_user_data_len(nfc);
> + sunxi_nfc_set_user_data_len(nfc, 4, 0);
> +
> sunxi_nfc_randomizer_enable(mtd);
> writel(NFC_DATA_TRANS | NFC_DATA_SWAP_METHOD |
> NFC_ACCESS_DIR | NFC_ECC_OP,
> @@ -1276,7 +1344,6 @@ static int sunxi_nand_chip_init_timings(struct sunxi_nfc *nfc,
> static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
> struct nand_ecc_ctrl *ecc)
> {
> - static const u8 strengths[] = { 16, 24, 28, 32, 40, 48, 56, 60, 64 };
> struct nand_chip *nand = mtd_to_nand(mtd);
> struct sunxi_nand_chip *sunxi_nand = to_sunxi_nand(nand);
> struct sunxi_nfc *nfc = to_sunxi_nfc(sunxi_nand->nand.controller);
> @@ -1303,12 +1370,12 @@ static int sunxi_nand_hw_common_ecc_ctrl_init(struct mtd_info *mtd,
>
> /* Add ECC info retrieval from DT */
> for (i = 0; i < nfc->caps->nstrengths; i++) {
> - if (ecc->strength <= strengths[i]) {
> + if (ecc->strength <= nfc->caps->ecc_strengths[i]) {
> /*
> * Update ecc->strength value with the actual strength
> * that will be used by the ECC engine.
> */
> - ecc->strength = strengths[i];
> + ecc->strength = nfc->caps->ecc_strengths[i];
> break;
> }
> }
> @@ -1722,9 +1789,22 @@ static int sunxi_nand_probe(struct udevice *dev)
> return 0;
> }
>
> +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,
> - .nstrengths = 9,
> + .nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_a10),
> + .ecc_strengths = sunxi_ecc_strengths_a10,
> .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,
> @@ -1733,6 +1813,24 @@ static const struct sunxi_nfc_caps sunxi_nfc_a10_caps = {
> .pat_found_mask = GENMASK(31, 16),
> .ecc_mode_mask = GENMASK(15, 12),
> .random_en_mask = BIT(9),
> + .max_ecc_steps = 16,
> +};
> +
> +static const struct sunxi_nfc_caps sunxi_nfc_h616_caps = {
> + .nstrengths = ARRAY_SIZE(sunxi_ecc_strengths_h6),
> + .ecc_strengths = sunxi_ecc_strengths_h6,
> + .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_pat_found = NFC_REG_H6_PAT_FOUND,
> + .reg_spare_area = NFC_REG_H6_SPARE_AREA,
> + .reg_pat_id = NFC_REG_H6_PAT_ID,
> + .pat_found_mask = GENMASK(31, 0),
> + .ecc_mode_mask = GENMASK(15, 8),
> + .random_en_mask = BIT(5),
> + .user_data_len_tab = sunxi_user_data_len_h6,
> + .nuser_data_tab = ARRAY_SIZE(sunxi_user_data_len_h6),
> + .max_ecc_steps = 32,
> };
>
> static const struct udevice_id sunxi_nand_ids[] = {
> @@ -1740,6 +1838,10 @@ static const struct udevice_id sunxi_nand_ids[] = {
> .compatible = "allwinner,sun4i-a10-nand",
> .data = (unsigned long)&sunxi_nfc_a10_caps,
> },
> + {
> + .compatible = "allwinner,sun50i-h616-nand-controller",
> + .data = (unsigned long)&sunxi_nfc_h616_caps,
> + },
> { }
> };
>
> diff --git a/drivers/mtd/nand/raw/sunxi_nand.h b/drivers/mtd/nand/raw/sunxi_nand.h
> index 52200468d343..966b743e2613 100644
> --- a/drivers/mtd/nand/raw/sunxi_nand.h
> +++ b/drivers/mtd/nand/raw/sunxi_nand.h
> @@ -44,15 +44,26 @@
> #define NFC_REG_IO_DATA 0x0030
> #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_A10_USER_DATA 0x0050
> +#define NFC_REG_H6_USER_DATA 0x0080
> +#define NFC_REG_H6_USER_DATA_LEN 0x0070
> #define NFC_REG_USER_DATA(nfc, x) ((nfc)->caps->reg_user_data + ((x) * 4))
> +
> +/* 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_H6_SPARE_AREA 0x0114
> +#define NFC_REG_PAT_ID(nfc) ((nfc)->caps->reg_pat_id)
> #define NFC_REG_A10_PAT_ID 0x00A4
> +#define NFC_REG_H6_PAT_ID 0x0118
> #define NFC_RAM0_BASE 0x0400
> #define NFC_RAM1_BASE 0x0800
>
> @@ -162,6 +173,9 @@
>
> #define NFC_ECC_ERR_CNT(b, x) (((x) >> ((b) * 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_SRAM_SIZE 1024
> @@ -174,8 +188,10 @@
> *
> * @has_ecc_block_512: If the ECC can handle 512B or only 1024B chuncks
> * @nstrengths: Number of element of ECC strengths array
> + * @ecc_strengths: available ECC strengths array
> * @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
> @@ -183,12 +199,21 @@
> * @pat_found_mask: ECC_PAT_FOUND mask in NFC_REG_PAT_FOUND register
> * @ecc_mode_mask: ECC_MODE mask in NFC_ECC_CTL register
> * @random_en_mask: RANDOM_EN mask in NFC_ECC_CTL register
> + * @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
> + * @max_ecc_steps: Maximum supported steps for ECC, this is also the
> + * number of user data registers
> */
> struct sunxi_nfc_caps {
> bool has_ecc_block_512;
> unsigned int nstrengths;
> + const u8 *ecc_strengths;
> 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;
> @@ -196,6 +221,9 @@ struct sunxi_nfc_caps {
> unsigned int ecc_err_mask;
> unsigned int ecc_mode_mask;
> unsigned int random_en_mask;
> + const u8 *user_data_len_tab;
> + unsigned int nuser_data_tab;
> + unsigned int max_ecc_steps;
> };
>
> #endif
--
Richard Genoud, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 43+ messages in thread
end of thread, other threads:[~2025-10-20 14:05 UTC | newest]
Thread overview: 43+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-16 14:27 [PATCH 00/24] Introduce Allwinner H6/H616 NAND controller support Richard Genoud
2025-10-16 14:27 ` [PATCH 01/24] mtd: rawnand: sunxi: cosmetic: remove needless comment Richard Genoud
2025-10-17 7:56 ` Andre Przywara
2025-10-16 14:27 ` [PATCH 02/24] mtd: rawnand: sunxi_spl: fix pointer from integer without a cast Richard Genoud
2025-10-17 7:57 ` Andre Przywara
2025-10-17 12:48 ` Richard GENOUD
2025-10-16 14:27 ` [PATCH 03/24] mtd: rawnand: sunxi_spl: cosmetic: harmonize register defines with non spl file Richard Genoud
2025-10-17 7:57 ` Andre Przywara
2025-10-17 14:22 ` Richard GENOUD
2025-10-17 14:27 ` Andre Przywara
2025-10-16 14:27 ` [PATCH 04/24] mtd: rawnand: sunxi_spl: cosmetic: use definitions from linux/mtd/rawnand.h Richard Genoud
2025-10-17 9:35 ` Andre Przywara
2025-10-16 14:27 ` [PATCH 05/24] mtd: rawnand: sunxi_spl: cosmetic: replace AHB_DIV_1 by CCM_NAND_CTRL_M/N Richard Genoud
2025-10-17 9:36 ` Andre Przywara
2025-10-17 14:26 ` Richard GENOUD
2025-10-16 14:27 ` [PATCH 06/24] mtd: rawnand: sunxi: cosmetic: merge register definitions for sunxi_nand{, _spl}.c Richard Genoud
2025-10-17 23:09 ` [PATCH 06/24] mtd: rawnand: sunxi: cosmetic: merge register definitions for sunxi_nand{,_spl}.c Andre Przywara
2025-10-16 14:27 ` [PATCH 07/24] mtd: rawnand: sunxi: cosmetic: add per SoC capabilities Richard Genoud
2025-10-17 23:10 ` Andre Przywara
2025-10-16 14:27 ` [PATCH 08/24] mtd: rawnand: sunxi: cosmetic: move ECC_ERR_CNT register offset in SoC caps Richard Genoud
2025-10-17 23:10 ` Andre Przywara
2025-10-16 14:27 ` [PATCH 09/24] mtd: rawnand: sunxi: cosmetic: move USER_DATA " Richard Genoud
2025-10-17 23:10 ` Andre Przywara
2025-10-16 14:27 ` [PATCH 10/24] mtd: rawnand: sunxi: cosmetic: move ECC_PAT_FOUND register " Richard Genoud
2025-10-17 23:11 ` Andre Przywara
2025-10-20 6:46 ` Richard GENOUD
2025-10-16 14:27 ` [PATCH 11/24] mtd: rawnand: sunxi: cosmetic: add has_ecc_block_512 capability Richard Genoud
2025-10-17 23:11 ` Andre Przywara
2025-10-20 7:02 ` Richard GENOUD
2025-10-16 14:27 ` [PATCH 12/24] mtd: rawnand: sunxi: cosmetic: move NFC_ECC_MODE offset in SoC caps Richard Genoud
2025-10-16 14:27 ` [PATCH 13/24] mtd: rawnand: sunxi: cosmetic: introduce reg_pat_id in sunxi_nfc_caps Richard Genoud
2025-10-16 14:27 ` [PATCH 14/24] mtd: rawnand: sunxi_spl: cosmetic: add per SoC capabilities Richard Genoud
2025-10-16 14:27 ` [PATCH 15/24] mtd: rawnand: sunxi: cosmetic: move NFC_RANDOM_EN register offset in SoC caps Richard Genoud
2025-10-16 14:27 ` [PATCH 16/24] mtd: rawnand: sunxi: cosmetic: introduce reg_spare_area in sunxi_nfc_caps Richard Genoud
2025-10-16 14:27 ` [PATCH 17/24] mtd: rawnand: sunxi_spl: use NFC_ECC_ERR_MSK and NFC_ECC_PAT_FOUND Richard Genoud
2025-10-16 14:27 ` [PATCH 18/24] mtd: rawnand: sunxi_spl: increase max_oobsize for 2KiB pages Richard Genoud
2025-10-16 14:27 ` [PATCH 19/24] mtd: rawnand: sunxi_spl: cosmetic: use NFC_ECC_MODE and NFC_RANDOM_SEED macros Richard Genoud
2025-10-16 14:27 ` [PATCH 20/24] sunxi: clock: H6: add NAND controller clock registers Richard Genoud
2025-10-16 14:27 ` [PATCH 21/24] clk: sunxi: Add MBUS Master Clock Gating Register Richard Genoud
2025-10-16 14:27 ` [PATCH 22/24] mtd: rawnand: sunxi: add support for H6/H616 nand controller Richard Genoud
2025-10-20 14:05 ` Richard GENOUD
2025-10-16 14:27 ` [PATCH 23/24] mtd: rawnand: sunxi_spl: " Richard Genoud
2025-10-16 14:27 ` [PATCH 24/24] mtd: rawnand: sunxi_spl: Fix cast to pointer from integer warnings Richard Genoud
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox