[PATCH v2 00/10] Backport BRCMNAND changes from Linux

Hunting down a bug on my system I took to back-porting all reasonable changes from the Linux brcmnand driver that were not yet in the U-Boot derivative.
I noticed that a simple diff -ur between brcmnand.c between the file in Linux and U-Boot was possible to see what differs. Combining this with some git log --oneline manual comparison, fuzzing and manual intervention I backported a set of relevant patches from Linux that compiles and WorksForMe(TM).
The diff between Linux and U-Boot is much smaller after this, the main missing part are subsystem cosmetics changes and the EDU DMA mode support.
This was as much as I could bite off in one go.
All patches countersigned-off and marked as [backported].
ChangeLog v1->v2: - Drop the patch to use the new OOB data layout helpers "mtd: nand: brcm: switch to mtd_ooblayout_ops" - Drop all patches depending on the previous patch, in total 4 patches.
Claire Lin (1): mtd: rawnand: brcmnand: Fix ecc chunk calculation for erased page bitfips
Kamal Dasu (3): mtd: rawnand: brcmnand: Refactored code to introduce helper functions mtd: rawnand: brcmnand: Add support for v7.3 controller mtd: nand: brcmnand: Add support for flash-dma v0
Álvaro Fernández Rojas (6): mtd: rawnand: brcmnand: correctly verify erased pages mtd: rawnand: brcmnand: rename v4 registers mtd: rawnand: brcmnand: fix CS0 layout mtd: rawnand: brcmnand: rename page sizes mtd: rawnand: brcmnand: support v2.1-v2.2 controllers mtd: rawnand: brcmnand: fix OOB R/W with Hamming ECC
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 353 +++++++++++++++++------ 1 file changed, 268 insertions(+), 85 deletions(-)

From: Kamal Dasu kdasu.kdev@gmail.com
Refactored NAND ECC and CMD address configuration code to use helper functions.
Signed-off-by: Kamal Dasu kdasu.kdev@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 100 ++++++++++++++--------- 1 file changed, 62 insertions(+), 38 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 74c9348f7fc4..571f1c795da0 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -595,6 +595,54 @@ static inline void brcmnand_write_fc(struct brcmnand_controller *ctrl, __raw_writel(val, ctrl->nand_fc + word * 4); }
+static void brcmnand_clear_ecc_addr(struct brcmnand_controller *ctrl) +{ + + /* Clear error addresses */ + brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_ADDR, 0); + brcmnand_write_reg(ctrl, BRCMNAND_CORR_ADDR, 0); + brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_EXT_ADDR, 0); + brcmnand_write_reg(ctrl, BRCMNAND_CORR_EXT_ADDR, 0); +} + +static u64 brcmnand_get_uncorrecc_addr(struct brcmnand_controller *ctrl) +{ + u64 err_addr; + + err_addr = brcmnand_read_reg(ctrl, BRCMNAND_UNCORR_ADDR); + err_addr |= ((u64)(brcmnand_read_reg(ctrl, + BRCMNAND_UNCORR_EXT_ADDR) + & 0xffff) << 32); + + return err_addr; +} + +static u64 brcmnand_get_correcc_addr(struct brcmnand_controller *ctrl) +{ + u64 err_addr; + + err_addr = brcmnand_read_reg(ctrl, BRCMNAND_CORR_ADDR); + err_addr |= ((u64)(brcmnand_read_reg(ctrl, + BRCMNAND_CORR_EXT_ADDR) + & 0xffff) << 32); + + return err_addr; +} + +static void brcmnand_set_cmd_addr(struct mtd_info *mtd, u64 addr) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + struct brcmnand_host *host = nand_get_controller_data(chip); + struct brcmnand_controller *ctrl = host->ctrl; + + brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS, + (host->cs << 16) | ((addr >> 32) & 0xffff)); + (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS); + brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS, + lower_32_bits(addr)); + (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS); +} + static inline u16 brcmnand_cs_offset(struct brcmnand_controller *ctrl, int cs, enum brcmnand_cs_reg reg) { @@ -1190,9 +1238,12 @@ static void brcmnand_send_cmd(struct brcmnand_host *host, int cmd) { struct brcmnand_controller *ctrl = host->ctrl; int ret; + u64 cmd_addr; + + cmd_addr = brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS); + + dev_dbg(ctrl->dev, "send native cmd %d addr 0x%llx\n", cmd, cmd_addr);
- dev_dbg(ctrl->dev, "send native cmd %d addr_lo 0x%x\n", cmd, - brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS)); BUG_ON(ctrl->cmd_pending != 0); ctrl->cmd_pending = cmd;
@@ -1365,12 +1416,7 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command, if (!native_cmd) return;
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS, - (host->cs << 16) | ((addr >> 32) & 0xffff)); - (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS); - brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS, lower_32_bits(addr)); - (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS); - + brcmnand_set_cmd_addr(mtd, addr); brcmnand_send_cmd(host, native_cmd); brcmnand_waitfunc(mtd, chip);
@@ -1600,20 +1646,10 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, struct brcmnand_controller *ctrl = host->ctrl; int i, j, ret = 0;
- /* Clear error addresses */ - brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_ADDR, 0); - brcmnand_write_reg(ctrl, BRCMNAND_CORR_ADDR, 0); - brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_EXT_ADDR, 0); - brcmnand_write_reg(ctrl, BRCMNAND_CORR_EXT_ADDR, 0); - - brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS, - (host->cs << 16) | ((addr >> 32) & 0xffff)); - (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS); + brcmnand_clear_ecc_addr(ctrl);
for (i = 0; i < trans; i++, addr += FC_BYTES) { - brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS, - lower_32_bits(addr)); - (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS); + brcmnand_set_cmd_addr(mtd, addr); /* SPARE_AREA_READ does not use ECC, so just use PAGE_READ */ brcmnand_send_cmd(host, CMD_PAGE_READ); brcmnand_waitfunc(mtd, chip); @@ -1633,21 +1669,15 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, host->hwcfg.sector_size_1k);
if (ret != -EBADMSG) { - *err_addr = brcmnand_read_reg(ctrl, - BRCMNAND_UNCORR_ADDR) | - ((u64)(brcmnand_read_reg(ctrl, - BRCMNAND_UNCORR_EXT_ADDR) - & 0xffff) << 32); + *err_addr = brcmnand_get_uncorrecc_addr(ctrl); + if (*err_addr) ret = -EBADMSG; }
if (!ret) { - *err_addr = brcmnand_read_reg(ctrl, - BRCMNAND_CORR_ADDR) | - ((u64)(brcmnand_read_reg(ctrl, - BRCMNAND_CORR_EXT_ADDR) - & 0xffff) << 32); + *err_addr = brcmnand_get_correcc_addr(ctrl); + if (*err_addr) ret = -EUCLEAN; } @@ -1721,7 +1751,7 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip, dev_dbg(ctrl->dev, "read %llx -> %p\n", (unsigned long long)addr, buf);
try_dmaread: - brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_COUNT, 0); + brcmnand_clear_ecc_addr(ctrl);
#ifndef __UBOOT__ if (has_flash_dma(ctrl) && !oob && flash_dma_buf_ok(buf)) { @@ -1875,15 +1905,9 @@ static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip, } #endif /* __UBOOT__ */
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS, - (host->cs << 16) | ((addr >> 32) & 0xffff)); - (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS); - for (i = 0; i < trans; i++, addr += FC_BYTES) { /* full address MUST be set before populating FC */ - brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS, - lower_32_bits(addr)); - (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS); + brcmnand_set_cmd_addr(mtd, addr);
if (buf) { brcmnand_soc_data_bus_prepare(ctrl->soc, false);

Hi
On Sat, Feb 11, 2023 at 4:29 PM Linus Walleij linus.walleij@linaro.org wrote:
From: Kamal Dasu kdasu.kdev@gmail.com
Refactored NAND ECC and CMD address configuration code to use helper functions.
Signed-off-by: Kamal Dasu kdasu.kdev@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 100 ++++++++++++++--------- 1 file changed, 62 insertions(+), 38 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 74c9348f7fc4..571f1c795da0 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -595,6 +595,54 @@ static inline void brcmnand_write_fc(struct brcmnand_controller *ctrl, __raw_writel(val, ctrl->nand_fc + word * 4); }
+static void brcmnand_clear_ecc_addr(struct brcmnand_controller *ctrl) +{
/* Clear error addresses */
brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_ADDR, 0);
brcmnand_write_reg(ctrl, BRCMNAND_CORR_ADDR, 0);
brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_EXT_ADDR, 0);
brcmnand_write_reg(ctrl, BRCMNAND_CORR_EXT_ADDR, 0);
+}
+static u64 brcmnand_get_uncorrecc_addr(struct brcmnand_controller *ctrl) +{
u64 err_addr;
err_addr = brcmnand_read_reg(ctrl, BRCMNAND_UNCORR_ADDR);
err_addr |= ((u64)(brcmnand_read_reg(ctrl,
BRCMNAND_UNCORR_EXT_ADDR)
& 0xffff) << 32);
return err_addr;
+}
+static u64 brcmnand_get_correcc_addr(struct brcmnand_controller *ctrl) +{
u64 err_addr;
err_addr = brcmnand_read_reg(ctrl, BRCMNAND_CORR_ADDR);
err_addr |= ((u64)(brcmnand_read_reg(ctrl,
BRCMNAND_CORR_EXT_ADDR)
& 0xffff) << 32);
return err_addr;
+}
+static void brcmnand_set_cmd_addr(struct mtd_info *mtd, u64 addr) +{
struct nand_chip *chip = mtd_to_nand(mtd);
struct brcmnand_host *host = nand_get_controller_data(chip);
struct brcmnand_controller *ctrl = host->ctrl;
brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
(host->cs << 16) | ((addr >> 32) & 0xffff));
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
lower_32_bits(addr));
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
+}
static inline u16 brcmnand_cs_offset(struct brcmnand_controller *ctrl, int cs, enum brcmnand_cs_reg reg) { @@ -1190,9 +1238,12 @@ static void brcmnand_send_cmd(struct brcmnand_host *host, int cmd) { struct brcmnand_controller *ctrl = host->ctrl; int ret;
u64 cmd_addr;
cmd_addr = brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
dev_dbg(ctrl->dev, "send native cmd %d addr 0x%llx\n", cmd, cmd_addr);
dev_dbg(ctrl->dev, "send native cmd %d addr_lo 0x%x\n", cmd,
brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS)); BUG_ON(ctrl->cmd_pending != 0); ctrl->cmd_pending = cmd;
@@ -1365,12 +1416,7 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command, if (!native_cmd) return;
brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
(host->cs << 16) | ((addr >> 32) & 0xffff));
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS, lower_32_bits(addr));
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
brcmnand_set_cmd_addr(mtd, addr); brcmnand_send_cmd(host, native_cmd); brcmnand_waitfunc(mtd, chip);
@@ -1600,20 +1646,10 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, struct brcmnand_controller *ctrl = host->ctrl; int i, j, ret = 0;
/* Clear error addresses */
brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_ADDR, 0);
brcmnand_write_reg(ctrl, BRCMNAND_CORR_ADDR, 0);
brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_EXT_ADDR, 0);
brcmnand_write_reg(ctrl, BRCMNAND_CORR_EXT_ADDR, 0);
brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
(host->cs << 16) | ((addr >> 32) & 0xffff));
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
brcmnand_clear_ecc_addr(ctrl); for (i = 0; i < trans; i++, addr += FC_BYTES) {
brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
lower_32_bits(addr));
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
brcmnand_set_cmd_addr(mtd, addr); /* SPARE_AREA_READ does not use ECC, so just use PAGE_READ */ brcmnand_send_cmd(host, CMD_PAGE_READ); brcmnand_waitfunc(mtd, chip);
@@ -1633,21 +1669,15 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, host->hwcfg.sector_size_1k);
if (ret != -EBADMSG) {
*err_addr = brcmnand_read_reg(ctrl,
BRCMNAND_UNCORR_ADDR) |
((u64)(brcmnand_read_reg(ctrl,
BRCMNAND_UNCORR_EXT_ADDR)
& 0xffff) << 32);
*err_addr = brcmnand_get_uncorrecc_addr(ctrl);
if (*err_addr) ret = -EBADMSG; } if (!ret) {
*err_addr = brcmnand_read_reg(ctrl,
BRCMNAND_CORR_ADDR) |
((u64)(brcmnand_read_reg(ctrl,
BRCMNAND_CORR_EXT_ADDR)
& 0xffff) << 32);
*err_addr = brcmnand_get_correcc_addr(ctrl);
if (*err_addr) ret = -EUCLEAN; }
@@ -1721,7 +1751,7 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip, dev_dbg(ctrl->dev, "read %llx -> %p\n", (unsigned long long)addr, buf);
try_dmaread:
brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_COUNT, 0);
brcmnand_clear_ecc_addr(ctrl);
#ifndef __UBOOT__ if (has_flash_dma(ctrl) && !oob && flash_dma_buf_ok(buf)) { @@ -1875,15 +1905,9 @@ static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip, } #endif /* __UBOOT__ */
brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
(host->cs << 16) | ((addr >> 32) & 0xffff));
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
for (i = 0; i < trans; i++, addr += FC_BYTES) { /* full address MUST be set before populating FC */
brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
lower_32_bits(addr));
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
brcmnand_set_cmd_addr(mtd, addr); if (buf) { brcmnand_soc_data_bus_prepare(ctrl->soc, false);
-- 2.39.1
Reviewed-by: Michael Trimarchi michael@amarulasolutions.com

On 02/11/2023 07:29 AM, Linus Walleij wrote:
From: Kamal Dasu kdasu.kdev@gmail.com
Refactored NAND ECC and CMD address configuration code to use helper functions.
Signed-off-by: Kamal Dasu kdasu.kdev@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 100 ++++++++++++++--------- 1 file changed, 62 insertions(+), 38 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 74c9348f7fc4..571f1c795da0 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -595,6 +595,54 @@ static inline void brcmnand_write_fc(struct brcmnand_controller *ctrl, __raw_writel(val, ctrl->nand_fc + word * 4); }
+static void brcmnand_clear_ecc_addr(struct brcmnand_controller *ctrl) +{
- /* Clear error addresses */
- brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_ADDR, 0);
- brcmnand_write_reg(ctrl, BRCMNAND_CORR_ADDR, 0);
- brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_EXT_ADDR, 0);
- brcmnand_write_reg(ctrl, BRCMNAND_CORR_EXT_ADDR, 0);
+}
+static u64 brcmnand_get_uncorrecc_addr(struct brcmnand_controller *ctrl) +{
- u64 err_addr;
- err_addr = brcmnand_read_reg(ctrl, BRCMNAND_UNCORR_ADDR);
- err_addr |= ((u64)(brcmnand_read_reg(ctrl,
BRCMNAND_UNCORR_EXT_ADDR)
& 0xffff) << 32);
- return err_addr;
+}
+static u64 brcmnand_get_correcc_addr(struct brcmnand_controller *ctrl) +{
- u64 err_addr;
- err_addr = brcmnand_read_reg(ctrl, BRCMNAND_CORR_ADDR);
- err_addr |= ((u64)(brcmnand_read_reg(ctrl,
BRCMNAND_CORR_EXT_ADDR)
& 0xffff) << 32);
- return err_addr;
+}
+static void brcmnand_set_cmd_addr(struct mtd_info *mtd, u64 addr) +{
- struct nand_chip *chip = mtd_to_nand(mtd);
- struct brcmnand_host *host = nand_get_controller_data(chip);
- struct brcmnand_controller *ctrl = host->ctrl;
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
(host->cs << 16) | ((addr >> 32) & 0xffff));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
lower_32_bits(addr));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
+}
- static inline u16 brcmnand_cs_offset(struct brcmnand_controller *ctrl, int cs, enum brcmnand_cs_reg reg) {
@@ -1190,9 +1238,12 @@ static void brcmnand_send_cmd(struct brcmnand_host *host, int cmd) { struct brcmnand_controller *ctrl = host->ctrl; int ret;
- u64 cmd_addr;
- cmd_addr = brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
- dev_dbg(ctrl->dev, "send native cmd %d addr 0x%llx\n", cmd, cmd_addr);
- dev_dbg(ctrl->dev, "send native cmd %d addr_lo 0x%x\n", cmd,
BUG_ON(ctrl->cmd_pending != 0); ctrl->cmd_pending = cmd;brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS));
@@ -1365,12 +1416,7 @@ static void brcmnand_cmdfunc(struct mtd_info *mtd, unsigned command, if (!native_cmd) return;
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
(host->cs << 16) | ((addr >> 32) & 0xffff));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS, lower_32_bits(addr));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
- brcmnand_set_cmd_addr(mtd, addr); brcmnand_send_cmd(host, native_cmd); brcmnand_waitfunc(mtd, chip);
@@ -1600,20 +1646,10 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, struct brcmnand_controller *ctrl = host->ctrl; int i, j, ret = 0;
- /* Clear error addresses */
- brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_ADDR, 0);
- brcmnand_write_reg(ctrl, BRCMNAND_CORR_ADDR, 0);
- brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_EXT_ADDR, 0);
- brcmnand_write_reg(ctrl, BRCMNAND_CORR_EXT_ADDR, 0);
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
(host->cs << 16) | ((addr >> 32) & 0xffff));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
brcmnand_clear_ecc_addr(ctrl);
for (i = 0; i < trans; i++, addr += FC_BYTES) {
brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
lower_32_bits(addr));
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
/* SPARE_AREA_READ does not use ECC, so just use PAGE_READ */ brcmnand_send_cmd(host, CMD_PAGE_READ); brcmnand_waitfunc(mtd, chip);brcmnand_set_cmd_addr(mtd, addr);
@@ -1633,21 +1669,15 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, host->hwcfg.sector_size_1k);
if (ret != -EBADMSG) {
*err_addr = brcmnand_read_reg(ctrl,
BRCMNAND_UNCORR_ADDR) |
((u64)(brcmnand_read_reg(ctrl,
BRCMNAND_UNCORR_EXT_ADDR)
& 0xffff) << 32);
*err_addr = brcmnand_get_uncorrecc_addr(ctrl);
if (*err_addr) ret = -EBADMSG;
}
if (!ret) {
*err_addr = brcmnand_read_reg(ctrl,
BRCMNAND_CORR_ADDR) |
((u64)(brcmnand_read_reg(ctrl,
BRCMNAND_CORR_EXT_ADDR)
& 0xffff) << 32);
*err_addr = brcmnand_get_correcc_addr(ctrl);
}if (*err_addr) ret = -EUCLEAN;
@@ -1721,7 +1751,7 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip, dev_dbg(ctrl->dev, "read %llx -> %p\n", (unsigned long long)addr, buf);
try_dmaread:
- brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_COUNT, 0);
brcmnand_clear_ecc_addr(ctrl);
#ifndef __UBOOT__ if (has_flash_dma(ctrl) && !oob && flash_dma_buf_ok(buf)) {
@@ -1875,15 +1905,9 @@ static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip, } #endif /* __UBOOT__ */
- brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS,
(host->cs << 16) | ((addr >> 32) & 0xffff));
- (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS);
- for (i = 0; i < trans; i++, addr += FC_BYTES) { /* full address MUST be set before populating FC */
brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS,
lower_32_bits(addr));
(void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS);
brcmnand_set_cmd_addr(mtd, addr);
if (buf) { brcmnand_soc_data_bus_prepare(ctrl->soc, false);
Acked-by: William Zhang william.zhang@broadcom.com

From: Kamal Dasu kdasu.kdev@gmail.com
This change adds support for brcm NAND v7.3 controller. This controller uses a newer version of flash_dma engine and change mostly implements these differences.
Signed-off-by: Kamal Dasu kdasu.kdev@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 106 ++++++++++++++++++----- 1 file changed, 84 insertions(+), 22 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 571f1c795da0..170aece0aa79 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -86,6 +86,12 @@ struct brcm_nand_dma_desc { #define FLASH_DMA_ECC_ERROR (1 << 8) #define FLASH_DMA_CORR_ERROR (1 << 9)
+/* Bitfields for DMA_MODE */ +#define FLASH_DMA_MODE_STOP_ON_ERROR BIT(1) /* stop in Uncorr ECC error */ +#define FLASH_DMA_MODE_MODE BIT(0) /* link list */ +#define FLASH_DMA_MODE_MASK (FLASH_DMA_MODE_STOP_ON_ERROR | \ + FLASH_DMA_MODE_MODE) + /* 512B flash cache in the NAND controller HW */ #define FC_SHIFT 9U #define FC_BYTES 512U @@ -98,6 +104,53 @@ struct brcm_nand_dma_desc { #define NAND_CTRL_RDY (INTFC_CTLR_READY | INTFC_FLASH_READY) #define NAND_POLL_STATUS_TIMEOUT_MS 100
+/* flash_dma registers */ +enum flash_dma_reg { + FLASH_DMA_REVISION = 0, + FLASH_DMA_FIRST_DESC, + FLASH_DMA_FIRST_DESC_EXT, + FLASH_DMA_CTRL, + FLASH_DMA_MODE, + FLASH_DMA_STATUS, + FLASH_DMA_INTERRUPT_DESC, + FLASH_DMA_INTERRUPT_DESC_EXT, + FLASH_DMA_ERROR_STATUS, + FLASH_DMA_CURRENT_DESC, + FLASH_DMA_CURRENT_DESC_EXT, +}; + +#ifndef __UBOOT__ +/* flash_dma registers v1*/ +static const u16 flash_dma_regs_v1[] = { + [FLASH_DMA_REVISION] = 0x00, + [FLASH_DMA_FIRST_DESC] = 0x04, + [FLASH_DMA_FIRST_DESC_EXT] = 0x08, + [FLASH_DMA_CTRL] = 0x0c, + [FLASH_DMA_MODE] = 0x10, + [FLASH_DMA_STATUS] = 0x14, + [FLASH_DMA_INTERRUPT_DESC] = 0x18, + [FLASH_DMA_INTERRUPT_DESC_EXT] = 0x1c, + [FLASH_DMA_ERROR_STATUS] = 0x20, + [FLASH_DMA_CURRENT_DESC] = 0x24, + [FLASH_DMA_CURRENT_DESC_EXT] = 0x28, +}; + +/* flash_dma registers v4 */ +static const u16 flash_dma_regs_v4[] = { + [FLASH_DMA_REVISION] = 0x00, + [FLASH_DMA_FIRST_DESC] = 0x08, + [FLASH_DMA_FIRST_DESC_EXT] = 0x0c, + [FLASH_DMA_CTRL] = 0x10, + [FLASH_DMA_MODE] = 0x14, + [FLASH_DMA_STATUS] = 0x18, + [FLASH_DMA_INTERRUPT_DESC] = 0x20, + [FLASH_DMA_INTERRUPT_DESC_EXT] = 0x24, + [FLASH_DMA_ERROR_STATUS] = 0x28, + [FLASH_DMA_CURRENT_DESC] = 0x30, + [FLASH_DMA_CURRENT_DESC_EXT] = 0x34, +}; +#endif /* __UBOOT__ */ + /* Controller feature flags */ enum { BRCMNAND_HAS_1K_SECTORS = BIT(0), @@ -135,6 +188,8 @@ struct brcmnand_controller { /* List of NAND hosts (one for each chip-select) */ struct list_head host_list;
+ /* flash_dma reg */ + const u16 *flash_dma_offsets; struct brcm_nand_dma_desc *dma_desc; dma_addr_t dma_pa;
@@ -473,7 +528,7 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) /* Register offsets */ if (ctrl->nand_version >= 0x0702) ctrl->reg_offsets = brcmnand_regs_v72; - else if (ctrl->nand_version >= 0x0701) + else if (ctrl->nand_version == 0x0701) ctrl->reg_offsets = brcmnand_regs_v71; else if (ctrl->nand_version >= 0x0600) ctrl->reg_offsets = brcmnand_regs_v60; @@ -518,7 +573,7 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) }
/* Maximum spare area sector size (per 512B) */ - if (ctrl->nand_version >= 0x0702) + if (ctrl->nand_version == 0x0702) ctrl->max_oob = 128; else if (ctrl->nand_version >= 0x0600) ctrl->max_oob = 64; @@ -553,6 +608,17 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) return 0; }
+#ifndef __UBOOT__ +static void brcmnand_flash_dma_revision_init(struct brcmnand_controller *ctrl) +{ + /* flash_dma register offsets */ + if (ctrl->nand_version >= 0x0703) + ctrl->flash_dma_offsets = flash_dma_regs_v4; + else + ctrl->flash_dma_offsets = flash_dma_regs_v1; +} +#endif /* __UBOOT__ */ + static inline u32 brcmnand_read_reg(struct brcmnand_controller *ctrl, enum brcmnand_reg reg) { @@ -675,7 +741,7 @@ static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val) enum brcmnand_reg reg = BRCMNAND_CORR_THRESHOLD; int cs = host->cs;
- if (ctrl->nand_version >= 0x0702) + if (ctrl->nand_version == 0x0702) bits = 7; else if (ctrl->nand_version >= 0x0600) bits = 6; @@ -729,7 +795,7 @@ enum {
static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl) { - if (ctrl->nand_version >= 0x0702) + if (ctrl->nand_version == 0x0702) return GENMASK(7, 0); else if (ctrl->nand_version >= 0x0600) return GENMASK(6, 0); @@ -877,20 +943,6 @@ static inline void brcmnand_set_wp(struct brcmnand_controller *ctrl, bool en) * Flash DMA ***********************************************************************/
-enum flash_dma_reg { - FLASH_DMA_REVISION = 0x00, - FLASH_DMA_FIRST_DESC = 0x04, - FLASH_DMA_FIRST_DESC_EXT = 0x08, - FLASH_DMA_CTRL = 0x0c, - FLASH_DMA_MODE = 0x10, - FLASH_DMA_STATUS = 0x14, - FLASH_DMA_INTERRUPT_DESC = 0x18, - FLASH_DMA_INTERRUPT_DESC_EXT = 0x1c, - FLASH_DMA_ERROR_STATUS = 0x20, - FLASH_DMA_CURRENT_DESC = 0x24, - FLASH_DMA_CURRENT_DESC_EXT = 0x28, -}; - static inline bool has_flash_dma(struct brcmnand_controller *ctrl) { return ctrl->flash_dma_base; @@ -906,14 +958,19 @@ static inline bool flash_dma_buf_ok(const void *buf) #endif /* __UBOOT__ */ }
-static inline void flash_dma_writel(struct brcmnand_controller *ctrl, u8 offs, - u32 val) +static inline void flash_dma_writel(struct brcmnand_controller *ctrl, + enum flash_dma_reg dma_reg, u32 val) { + u16 offs = ctrl->flash_dma_offsets[dma_reg]; + brcmnand_writel(val, ctrl->flash_dma_base + offs); }
-static inline u32 flash_dma_readl(struct brcmnand_controller *ctrl, u8 offs) +static inline u32 flash_dma_readl(struct brcmnand_controller *ctrl, + enum flash_dma_reg dma_reg) { + u16 offs = ctrl->flash_dma_offsets[dma_reg]; + return brcmnand_readl(ctrl->flash_dma_base + offs); }
@@ -2470,6 +2527,7 @@ static const struct of_device_id brcmnand_of_match[] = { { .compatible = "brcm,brcmnand-v7.0" }, { .compatible = "brcm,brcmnand-v7.1" }, { .compatible = "brcm,brcmnand-v7.2" }, + { .compatible = "brcm,brcmnand-v7.3" }, {}, }; MODULE_DEVICE_TABLE(of, brcmnand_of_match); @@ -2600,7 +2658,11 @@ int brcmnand_probe(struct udevice *dev, struct brcmnand_soc *soc) goto err; }
- flash_dma_writel(ctrl, FLASH_DMA_MODE, 1); /* linked-list */ + /* initialize the dma version */ + brcmnand_flash_dma_revision_init(ctrl); + + /* linked-list and stop on error */ + flash_dma_writel(ctrl, FLASH_DMA_MODE, FLASH_DMA_MODE_MASK); flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0);
/* Allocate descriptor(s) */

On 02/11/2023 07:29 AM, Linus Walleij wrote:
From: Kamal Dasu kdasu.kdev@gmail.com
This change adds support for brcm NAND v7.3 controller. This controller uses a newer version of flash_dma engine and change mostly implements these differences.
Signed-off-by: Kamal Dasu kdasu.kdev@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 106 ++++++++++++++++++----- 1 file changed, 84 insertions(+), 22 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 571f1c795da0..170aece0aa79 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -86,6 +86,12 @@ struct brcm_nand_dma_desc { #define FLASH_DMA_ECC_ERROR (1 << 8) #define FLASH_DMA_CORR_ERROR (1 << 9)
+/* Bitfields for DMA_MODE */ +#define FLASH_DMA_MODE_STOP_ON_ERROR BIT(1) /* stop in Uncorr ECC error */ +#define FLASH_DMA_MODE_MODE BIT(0) /* link list */ +#define FLASH_DMA_MODE_MASK (FLASH_DMA_MODE_STOP_ON_ERROR | \
FLASH_DMA_MODE_MODE)
- /* 512B flash cache in the NAND controller HW */ #define FC_SHIFT 9U #define FC_BYTES 512U
@@ -98,6 +104,53 @@ struct brcm_nand_dma_desc { #define NAND_CTRL_RDY (INTFC_CTLR_READY | INTFC_FLASH_READY) #define NAND_POLL_STATUS_TIMEOUT_MS 100
+/* flash_dma registers */ +enum flash_dma_reg {
- FLASH_DMA_REVISION = 0,
- FLASH_DMA_FIRST_DESC,
- FLASH_DMA_FIRST_DESC_EXT,
- FLASH_DMA_CTRL,
- FLASH_DMA_MODE,
- FLASH_DMA_STATUS,
- FLASH_DMA_INTERRUPT_DESC,
- FLASH_DMA_INTERRUPT_DESC_EXT,
- FLASH_DMA_ERROR_STATUS,
- FLASH_DMA_CURRENT_DESC,
- FLASH_DMA_CURRENT_DESC_EXT,
+};
+#ifndef __UBOOT__ +/* flash_dma registers v1*/ +static const u16 flash_dma_regs_v1[] = {
- [FLASH_DMA_REVISION] = 0x00,
- [FLASH_DMA_FIRST_DESC] = 0x04,
- [FLASH_DMA_FIRST_DESC_EXT] = 0x08,
- [FLASH_DMA_CTRL] = 0x0c,
- [FLASH_DMA_MODE] = 0x10,
- [FLASH_DMA_STATUS] = 0x14,
- [FLASH_DMA_INTERRUPT_DESC] = 0x18,
- [FLASH_DMA_INTERRUPT_DESC_EXT] = 0x1c,
- [FLASH_DMA_ERROR_STATUS] = 0x20,
- [FLASH_DMA_CURRENT_DESC] = 0x24,
- [FLASH_DMA_CURRENT_DESC_EXT] = 0x28,
+};
+/* flash_dma registers v4 */ +static const u16 flash_dma_regs_v4[] = {
- [FLASH_DMA_REVISION] = 0x00,
- [FLASH_DMA_FIRST_DESC] = 0x08,
- [FLASH_DMA_FIRST_DESC_EXT] = 0x0c,
- [FLASH_DMA_CTRL] = 0x10,
- [FLASH_DMA_MODE] = 0x14,
- [FLASH_DMA_STATUS] = 0x18,
- [FLASH_DMA_INTERRUPT_DESC] = 0x20,
- [FLASH_DMA_INTERRUPT_DESC_EXT] = 0x24,
- [FLASH_DMA_ERROR_STATUS] = 0x28,
- [FLASH_DMA_CURRENT_DESC] = 0x30,
- [FLASH_DMA_CURRENT_DESC_EXT] = 0x34,
+}; +#endif /* __UBOOT__ */
- /* Controller feature flags */ enum { BRCMNAND_HAS_1K_SECTORS = BIT(0),
@@ -135,6 +188,8 @@ struct brcmnand_controller { /* List of NAND hosts (one for each chip-select) */ struct list_head host_list;
- /* flash_dma reg */
- const u16 *flash_dma_offsets; struct brcm_nand_dma_desc *dma_desc; dma_addr_t dma_pa;
@@ -473,7 +528,7 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) /* Register offsets */ if (ctrl->nand_version >= 0x0702) ctrl->reg_offsets = brcmnand_regs_v72;
- else if (ctrl->nand_version >= 0x0701)
- else if (ctrl->nand_version == 0x0701) ctrl->reg_offsets = brcmnand_regs_v71; else if (ctrl->nand_version >= 0x0600) ctrl->reg_offsets = brcmnand_regs_v60;
@@ -518,7 +573,7 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) }
/* Maximum spare area sector size (per 512B) */
- if (ctrl->nand_version >= 0x0702)
- if (ctrl->nand_version == 0x0702) ctrl->max_oob = 128; else if (ctrl->nand_version >= 0x0600) ctrl->max_oob = 64;
@@ -553,6 +608,17 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) return 0; }
+#ifndef __UBOOT__ +static void brcmnand_flash_dma_revision_init(struct brcmnand_controller *ctrl) +{
- /* flash_dma register offsets */
- if (ctrl->nand_version >= 0x0703)
ctrl->flash_dma_offsets = flash_dma_regs_v4;
- else
ctrl->flash_dma_offsets = flash_dma_regs_v1;
+} +#endif /* __UBOOT__ */
- static inline u32 brcmnand_read_reg(struct brcmnand_controller *ctrl, enum brcmnand_reg reg) {
@@ -675,7 +741,7 @@ static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val) enum brcmnand_reg reg = BRCMNAND_CORR_THRESHOLD; int cs = host->cs;
- if (ctrl->nand_version >= 0x0702)
- if (ctrl->nand_version == 0x0702) bits = 7; else if (ctrl->nand_version >= 0x0600) bits = 6;
@@ -729,7 +795,7 @@ enum {
static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl) {
- if (ctrl->nand_version >= 0x0702)
- if (ctrl->nand_version == 0x0702) return GENMASK(7, 0); else if (ctrl->nand_version >= 0x0600) return GENMASK(6, 0);
@@ -877,20 +943,6 @@ static inline void brcmnand_set_wp(struct brcmnand_controller *ctrl, bool en)
- Flash DMA
***********************************************************************/
-enum flash_dma_reg {
- FLASH_DMA_REVISION = 0x00,
- FLASH_DMA_FIRST_DESC = 0x04,
- FLASH_DMA_FIRST_DESC_EXT = 0x08,
- FLASH_DMA_CTRL = 0x0c,
- FLASH_DMA_MODE = 0x10,
- FLASH_DMA_STATUS = 0x14,
- FLASH_DMA_INTERRUPT_DESC = 0x18,
- FLASH_DMA_INTERRUPT_DESC_EXT = 0x1c,
- FLASH_DMA_ERROR_STATUS = 0x20,
- FLASH_DMA_CURRENT_DESC = 0x24,
- FLASH_DMA_CURRENT_DESC_EXT = 0x28,
-};
- static inline bool has_flash_dma(struct brcmnand_controller *ctrl) { return ctrl->flash_dma_base;
@@ -906,14 +958,19 @@ static inline bool flash_dma_buf_ok(const void *buf) #endif /* __UBOOT__ */ }
-static inline void flash_dma_writel(struct brcmnand_controller *ctrl, u8 offs,
u32 val)
+static inline void flash_dma_writel(struct brcmnand_controller *ctrl,
{enum flash_dma_reg dma_reg, u32 val)
- u16 offs = ctrl->flash_dma_offsets[dma_reg];
- brcmnand_writel(val, ctrl->flash_dma_base + offs); }
-static inline u32 flash_dma_readl(struct brcmnand_controller *ctrl, u8 offs) +static inline u32 flash_dma_readl(struct brcmnand_controller *ctrl,
{enum flash_dma_reg dma_reg)
- u16 offs = ctrl->flash_dma_offsets[dma_reg];
- return brcmnand_readl(ctrl->flash_dma_base + offs); }
@@ -2470,6 +2527,7 @@ static const struct of_device_id brcmnand_of_match[] = { { .compatible = "brcm,brcmnand-v7.0" }, { .compatible = "brcm,brcmnand-v7.1" }, { .compatible = "brcm,brcmnand-v7.2" },
- { .compatible = "brcm,brcmnand-v7.3" }, {}, }; MODULE_DEVICE_TABLE(of, brcmnand_of_match);
@@ -2600,7 +2658,11 @@ int brcmnand_probe(struct udevice *dev, struct brcmnand_soc *soc) goto err; }
flash_dma_writel(ctrl, FLASH_DMA_MODE, 1); /* linked-list */
/* initialize the dma version */
brcmnand_flash_dma_revision_init(ctrl);
/* linked-list and stop on error */
flash_dma_writel(ctrl, FLASH_DMA_MODE, FLASH_DMA_MODE_MASK);
flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0);
/* Allocate descriptor(s) */
Acked-by: William Zhang william.zhang@broadcom.com

From: Claire Lin claire.lin@broadcom.com
In brcmstb_nand_verify_erased_page(), the ECC chunk pointer calculation while correcting erased page bitflips is wrong, fix it.
Fixes: 02b88eea9f9c ("mtd: brcmnand: Add check for erased page bitflips") Signed-off-by: Claire Lin claire.lin@broadcom.com Reviewed-by: Ray Jui ray.jui@broadcom.com Signed-off-by: Kamal Dasu kdasu.kdev@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 170aece0aa79..0402cb06a74b 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -1765,6 +1765,7 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd, int bitflips = 0; int page = addr >> chip->page_shift; int ret; + void *ecc_chunk;
if (!buf) { #ifndef __UBOOT__ @@ -1784,7 +1785,9 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd, return ret;
for (i = 0; i < chip->ecc.steps; i++, oob += sas) { - ret = nand_check_erased_ecc_chunk(buf, chip->ecc.size, + ecc_chunk = buf + chip->ecc.size * i; + ret = nand_check_erased_ecc_chunk(ecc_chunk, + chip->ecc.size, oob, sas, NULL, 0, chip->ecc.strength); if (ret < 0)

On 02/11/2023 07:29 AM, Linus Walleij wrote:
From: Claire Lin claire.lin@broadcom.com
In brcmstb_nand_verify_erased_page(), the ECC chunk pointer calculation while correcting erased page bitflips is wrong, fix it.
Fixes: 02b88eea9f9c ("mtd: brcmnand: Add check for erased page bitflips") Signed-off-by: Claire Lin claire.lin@broadcom.com Reviewed-by: Ray Jui ray.jui@broadcom.com Signed-off-by: Kamal Dasu kdasu.kdev@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 170aece0aa79..0402cb06a74b 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -1765,6 +1765,7 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd, int bitflips = 0; int page = addr >> chip->page_shift; int ret;
void *ecc_chunk;
if (!buf) { #ifndef __UBOOT__
@@ -1784,7 +1785,9 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd, return ret;
for (i = 0; i < chip->ecc.steps; i++, oob += sas) {
ret = nand_check_erased_ecc_chunk(buf, chip->ecc.size,
ecc_chunk = buf + chip->ecc.size * i;
ret = nand_check_erased_ecc_chunk(ecc_chunk,
if (ret < 0)chip->ecc.size, oob, sas, NULL, 0, chip->ecc.strength);
Acked-by: William Zhang william.zhang@broadcom.com

From: Kamal Dasu kdasu.kdev@gmail.com
This change adds support for flash dma v0.0.
Signed-off-by: Kamal Dasu kdasu.kdev@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 0402cb06a74b..a934373a2992 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -120,6 +120,18 @@ enum flash_dma_reg { };
#ifndef __UBOOT__ +/* flash_dma registers v0*/ +static const u16 flash_dma_regs_v0[] = { + [FLASH_DMA_REVISION] = 0x00, + [FLASH_DMA_FIRST_DESC] = 0x04, + [FLASH_DMA_CTRL] = 0x08, + [FLASH_DMA_MODE] = 0x0c, + [FLASH_DMA_STATUS] = 0x10, + [FLASH_DMA_INTERRUPT_DESC] = 0x14, + [FLASH_DMA_ERROR_STATUS] = 0x18, + [FLASH_DMA_CURRENT_DESC] = 0x1c, +}; + /* flash_dma registers v1*/ static const u16 flash_dma_regs_v1[] = { [FLASH_DMA_REVISION] = 0x00, @@ -614,6 +626,8 @@ static void brcmnand_flash_dma_revision_init(struct brcmnand_controller *ctrl) /* flash_dma register offsets */ if (ctrl->nand_version >= 0x0703) ctrl->flash_dma_offsets = flash_dma_regs_v4; + else if (ctrl->nand_version == 0x0602) + ctrl->flash_dma_offsets = flash_dma_regs_v0; else ctrl->flash_dma_offsets = flash_dma_regs_v1; } @@ -1645,8 +1659,11 @@ static void brcmnand_dma_run(struct brcmnand_host *host, dma_addr_t desc)
flash_dma_writel(ctrl, FLASH_DMA_FIRST_DESC, lower_32_bits(desc)); (void)flash_dma_readl(ctrl, FLASH_DMA_FIRST_DESC); - flash_dma_writel(ctrl, FLASH_DMA_FIRST_DESC_EXT, upper_32_bits(desc)); - (void)flash_dma_readl(ctrl, FLASH_DMA_FIRST_DESC_EXT); + if (ctrl->nand_version > 0x0602) { + flash_dma_writel(ctrl, FLASH_DMA_FIRST_DESC_EXT, + upper_32_bits(desc)); + (void)flash_dma_readl(ctrl, FLASH_DMA_FIRST_DESC_EXT); + }
/* Start FLASH_DMA engine */ ctrl->dma_pending = true;

On 02/11/2023 07:29 AM, Linus Walleij wrote:
From: Kamal Dasu kdasu.kdev@gmail.com
This change adds support for flash dma v0.0.
Signed-off-by: Kamal Dasu kdasu.kdev@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 0402cb06a74b..a934373a2992 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -120,6 +120,18 @@ enum flash_dma_reg { };
#ifndef __UBOOT__ +/* flash_dma registers v0*/ +static const u16 flash_dma_regs_v0[] = {
- [FLASH_DMA_REVISION] = 0x00,
- [FLASH_DMA_FIRST_DESC] = 0x04,
- [FLASH_DMA_CTRL] = 0x08,
- [FLASH_DMA_MODE] = 0x0c,
- [FLASH_DMA_STATUS] = 0x10,
- [FLASH_DMA_INTERRUPT_DESC] = 0x14,
- [FLASH_DMA_ERROR_STATUS] = 0x18,
- [FLASH_DMA_CURRENT_DESC] = 0x1c,
+};
- /* flash_dma registers v1*/ static const u16 flash_dma_regs_v1[] = { [FLASH_DMA_REVISION] = 0x00,
@@ -614,6 +626,8 @@ static void brcmnand_flash_dma_revision_init(struct brcmnand_controller *ctrl) /* flash_dma register offsets */ if (ctrl->nand_version >= 0x0703) ctrl->flash_dma_offsets = flash_dma_regs_v4;
- else if (ctrl->nand_version == 0x0602)
else ctrl->flash_dma_offsets = flash_dma_regs_v1; }ctrl->flash_dma_offsets = flash_dma_regs_v0;
@@ -1645,8 +1659,11 @@ static void brcmnand_dma_run(struct brcmnand_host *host, dma_addr_t desc)
flash_dma_writel(ctrl, FLASH_DMA_FIRST_DESC, lower_32_bits(desc)); (void)flash_dma_readl(ctrl, FLASH_DMA_FIRST_DESC);
- flash_dma_writel(ctrl, FLASH_DMA_FIRST_DESC_EXT, upper_32_bits(desc));
- (void)flash_dma_readl(ctrl, FLASH_DMA_FIRST_DESC_EXT);
if (ctrl->nand_version > 0x0602) {
flash_dma_writel(ctrl, FLASH_DMA_FIRST_DESC_EXT,
upper_32_bits(desc));
(void)flash_dma_readl(ctrl, FLASH_DMA_FIRST_DESC_EXT);
}
/* Start FLASH_DMA engine */ ctrl->dma_pending = true;
Acked-by: William Zhang william.zhang@broadcom.com

From: Álvaro Fernández Rojas noltari@gmail.com
The current code checks that the whole OOB area is erased. This is a problem when JFFS2 cleanmarkers are added to the OOB, since it will fail due to the usable OOB bytes not being 0xff. Correct this by only checking that data and ECC bytes aren't 0xff.
Fixes: 02b88eea9f9c ("mtd: brcmnand: Add check for erased page bitflips") Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20200512082451.771212-1-noltari@gmail.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index a934373a2992..5d3fb460d89a 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -1777,11 +1777,12 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd, struct nand_chip *chip, void *buf, u64 addr) { - int i, sas; - void *oob = chip->oob_poi; + struct mtd_oob_region ecc; + int i; int bitflips = 0; int page = addr >> chip->page_shift; int ret; + void *ecc_bytes; void *ecc_chunk;
if (!buf) { @@ -1794,18 +1795,20 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd, chip->pagebuf = -1; }
- sas = mtd->oobsize / chip->ecc.steps; - /* read without ecc for verification */ ret = chip->ecc.read_page_raw(mtd, chip, buf, true, page); if (ret) return ret;
- for (i = 0; i < chip->ecc.steps; i++, oob += sas) { + for (i = 0; i < chip->ecc.steps; i++) { ecc_chunk = buf + chip->ecc.size * i; - ret = nand_check_erased_ecc_chunk(ecc_chunk, - chip->ecc.size, - oob, sas, NULL, 0, + + mtd_ooblayout_ecc(mtd, i, &ecc); + ecc_bytes = chip->oob_poi + ecc.offset; + + ret = nand_check_erased_ecc_chunk(ecc_chunk, chip->ecc.size, + ecc_bytes, ecc.length, + NULL, 0, chip->ecc.strength); if (ret < 0) return ret;

On 02/11/2023 07:29 AM, Linus Walleij wrote:
From: Álvaro Fernández Rojas noltari@gmail.com
The current code checks that the whole OOB area is erased. This is a problem when JFFS2 cleanmarkers are added to the OOB, since it will fail due to the usable OOB bytes not being 0xff. Correct this by only checking that data and ECC bytes aren't 0xff.
Fixes: 02b88eea9f9c ("mtd: brcmnand: Add check for erased page bitflips") Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20200512082451.771212-1-noltari@gmail.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index a934373a2992..5d3fb460d89a 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -1777,11 +1777,12 @@ static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd, struct nand_chip *chip, void *buf, u64 addr) {
- int i, sas;
- void *oob = chip->oob_poi;
struct mtd_oob_region ecc;
int i; int bitflips = 0; int page = addr >> chip->page_shift; int ret;
void *ecc_bytes; void *ecc_chunk;
if (!buf) {
@@ -1794,18 +1795,20 @@ static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd, chip->pagebuf = -1; }
sas = mtd->oobsize / chip->ecc.steps;
/* read without ecc for verification */ ret = chip->ecc.read_page_raw(mtd, chip, buf, true, page); if (ret) return ret;
for (i = 0; i < chip->ecc.steps; i++, oob += sas) {
- for (i = 0; i < chip->ecc.steps; i++) { ecc_chunk = buf + chip->ecc.size * i;
ret = nand_check_erased_ecc_chunk(ecc_chunk,
chip->ecc.size,
oob, sas, NULL, 0,
mtd_ooblayout_ecc(mtd, i, &ecc);
ecc_bytes = chip->oob_poi + ecc.offset;
ret = nand_check_erased_ecc_chunk(ecc_chunk, chip->ecc.size,
ecc_bytes, ecc.length,
if (ret < 0) return ret;NULL, 0, chip->ecc.strength);
Acked-by: William Zhang william.zhang@broadcom.com

From: Álvaro Fernández Rojas noltari@gmail.com
These registers are also used on v3.3.
Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Reviewed-by: Miquel Raynal miquel.raynal@bootlin.com Acked-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20200522121524.4161539-2-noltari@gmail.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 5d3fb460d89a..ee7c3a21602e 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -293,8 +293,8 @@ enum brcmnand_reg { BRCMNAND_FC_BASE, };
-/* BRCMNAND v4.0 */ -static const u16 brcmnand_regs_v40[] = { +/* BRCMNAND v3.3-v4.0 */ +static const u16 brcmnand_regs_v33[] = { [BRCMNAND_CMD_START] = 0x04, [BRCMNAND_CMD_EXT_ADDRESS] = 0x08, [BRCMNAND_CMD_ADDRESS] = 0x0c, @@ -546,8 +546,8 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) ctrl->reg_offsets = brcmnand_regs_v60; else if (ctrl->nand_version >= 0x0500) ctrl->reg_offsets = brcmnand_regs_v50; - else if (ctrl->nand_version >= 0x0400) - ctrl->reg_offsets = brcmnand_regs_v40; + else if (ctrl->nand_version >= 0x0303) + ctrl->reg_offsets = brcmnand_regs_v33;
/* Chip-select stride */ if (ctrl->nand_version >= 0x0701)

Hi
On Sat, Feb 11, 2023 at 4:29 PM Linus Walleij linus.walleij@linaro.org wrote:
From: Álvaro Fernández Rojas noltari@gmail.com
These registers are also used on v3.3.
Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Reviewed-by: Miquel Raynal miquel.raynal@bootlin.com Acked-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20200522121524.4161539-2-noltari@gmail.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 5d3fb460d89a..ee7c3a21602e 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -293,8 +293,8 @@ enum brcmnand_reg { BRCMNAND_FC_BASE, };
-/* BRCMNAND v4.0 */ -static const u16 brcmnand_regs_v40[] = { +/* BRCMNAND v3.3-v4.0 */ +static const u16 brcmnand_regs_v33[] = { [BRCMNAND_CMD_START] = 0x04, [BRCMNAND_CMD_EXT_ADDRESS] = 0x08, [BRCMNAND_CMD_ADDRESS] = 0x0c, @@ -546,8 +546,8 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) ctrl->reg_offsets = brcmnand_regs_v60; else if (ctrl->nand_version >= 0x0500) ctrl->reg_offsets = brcmnand_regs_v50;
else if (ctrl->nand_version >= 0x0400)
ctrl->reg_offsets = brcmnand_regs_v40;
else if (ctrl->nand_version >= 0x0303)
ctrl->reg_offsets = brcmnand_regs_v33; /* Chip-select stride */ if (ctrl->nand_version >= 0x0701)
-- 2.39.1
Reviewed-by: Michael Trimarchi michael@amarulasolutions.com

On 02/11/2023 07:29 AM, Linus Walleij wrote:
From: Álvaro Fernández Rojas noltari@gmail.com
These registers are also used on v3.3.
Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Reviewed-by: Miquel Raynal miquel.raynal@bootlin.com Acked-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20200522121524.4161539-2-noltari@gmail.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 5d3fb460d89a..ee7c3a21602e 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -293,8 +293,8 @@ enum brcmnand_reg { BRCMNAND_FC_BASE, };
-/* BRCMNAND v4.0 */ -static const u16 brcmnand_regs_v40[] = { +/* BRCMNAND v3.3-v4.0 */ +static const u16 brcmnand_regs_v33[] = { [BRCMNAND_CMD_START] = 0x04, [BRCMNAND_CMD_EXT_ADDRESS] = 0x08, [BRCMNAND_CMD_ADDRESS] = 0x0c, @@ -546,8 +546,8 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) ctrl->reg_offsets = brcmnand_regs_v60; else if (ctrl->nand_version >= 0x0500) ctrl->reg_offsets = brcmnand_regs_v50;
- else if (ctrl->nand_version >= 0x0400)
ctrl->reg_offsets = brcmnand_regs_v40;
else if (ctrl->nand_version >= 0x0303)
ctrl->reg_offsets = brcmnand_regs_v33;
/* Chip-select stride */ if (ctrl->nand_version >= 0x0701)
Acked-by: William Zhang william.zhang@broadcom.com

From: Álvaro Fernández Rojas noltari@gmail.com
Only v3.3-v5.0 have a different CS0 layout. Controllers before v3.3 use the same layout for every CS.
Fixes: 27c5b17cd1b1 ("mtd: nand: add NAND driver "library" for Broadcom STB NAND controller") Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Acked-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20200522121524.4161539-3-noltari@gmail.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index ee7c3a21602e..1ea9091e6497 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -561,8 +561,9 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) } else { ctrl->cs_offsets = brcmnand_cs_offsets;
- /* v5.0 and earlier has a different CS0 offset layout */ - if (ctrl->nand_version <= 0x0500) + /* v3.3-5.0 have a different CS0 offset layout */ + if (ctrl->nand_version >= 0x0303 && + ctrl->nand_version <= 0x0500) ctrl->cs0_offsets = brcmnand_cs_offsets_cs0; }

On Sat, Feb 11, 2023 at 4:29 PM Linus Walleij linus.walleij@linaro.org wrote:
From: Álvaro Fernández Rojas noltari@gmail.com
Only v3.3-v5.0 have a different CS0 layout. Controllers before v3.3 use the same layout for every CS.
Fixes: 27c5b17cd1b1 ("mtd: nand: add NAND driver "library" for Broadcom STB NAND controller") Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Acked-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20200522121524.4161539-3-noltari@gmail.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index ee7c3a21602e..1ea9091e6497 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -561,8 +561,9 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) } else { ctrl->cs_offsets = brcmnand_cs_offsets;
/* v5.0 and earlier has a different CS0 offset layout */
if (ctrl->nand_version <= 0x0500)
/* v3.3-5.0 have a different CS0 offset layout */
if (ctrl->nand_version >= 0x0303 &&
ctrl->nand_version <= 0x0500) ctrl->cs0_offsets = brcmnand_cs_offsets_cs0; }
Reviewed-by: Michael Trimarchi michael@amarulasolutions.com
-- 2.39.1

On 02/11/2023 07:29 AM, Linus Walleij wrote:
From: Álvaro Fernández Rojas noltari@gmail.com
Only v3.3-v5.0 have a different CS0 layout. Controllers before v3.3 use the same layout for every CS.
Fixes: 27c5b17cd1b1 ("mtd: nand: add NAND driver "library" for Broadcom STB NAND controller") Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Acked-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20200522121524.4161539-3-noltari@gmail.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index ee7c3a21602e..1ea9091e6497 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -561,8 +561,9 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) } else { ctrl->cs_offsets = brcmnand_cs_offsets;
/* v5.0 and earlier has a different CS0 offset layout */
if (ctrl->nand_version <= 0x0500)
/* v3.3-5.0 have a different CS0 offset layout */
if (ctrl->nand_version >= 0x0303 &&
}ctrl->nand_version <= 0x0500) ctrl->cs0_offsets = brcmnand_cs_offsets_cs0;
Acked-by: William Zhang william.zhang@broadcom.com

From: Álvaro Fernández Rojas noltari@gmail.com
Current pages sizes apply to controllers after v3.4
Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Acked-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20200522121524.4161539-4-noltari@gmail.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 1ea9091e6497..10a2e2c0f599 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -526,7 +526,7 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) { static const unsigned int block_sizes_v6[] = { 8, 16, 128, 256, 512, 1024, 2048, 0 }; static const unsigned int block_sizes_v4[] = { 16, 128, 8, 512, 256, 1024, 2048, 0 }; - static const unsigned int page_sizes[] = { 512, 2048, 4096, 8192, 0 }; + static const unsigned int page_sizes_v3_4[] = { 512, 2048, 4096, 8192, 0 };
ctrl->nand_version = nand_readreg(ctrl, 0) & 0xffff;
@@ -573,7 +573,7 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) ctrl->max_page_size = 16 * 1024; ctrl->max_block_size = 2 * 1024 * 1024; } else { - ctrl->page_sizes = page_sizes; + ctrl->page_sizes = page_sizes_v3_4; if (ctrl->nand_version >= 0x0600) ctrl->block_sizes = block_sizes_v6; else

On 02/11/2023 07:29 AM, Linus Walleij wrote:
From: Álvaro Fernández Rojas noltari@gmail.com
Current pages sizes apply to controllers after v3.4
Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Acked-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20200522121524.4161539-4-noltari@gmail.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 1ea9091e6497..10a2e2c0f599 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -526,7 +526,7 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) { static const unsigned int block_sizes_v6[] = { 8, 16, 128, 256, 512, 1024, 2048, 0 }; static const unsigned int block_sizes_v4[] = { 16, 128, 8, 512, 256, 1024, 2048, 0 };
- static const unsigned int page_sizes[] = { 512, 2048, 4096, 8192, 0 };
static const unsigned int page_sizes_v3_4[] = { 512, 2048, 4096, 8192, 0 };
ctrl->nand_version = nand_readreg(ctrl, 0) & 0xffff;
@@ -573,7 +573,7 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) ctrl->max_page_size = 16 * 1024; ctrl->max_block_size = 2 * 1024 * 1024; } else {
ctrl->page_sizes = page_sizes;
if (ctrl->nand_version >= 0x0600) ctrl->block_sizes = block_sizes_v6; elsectrl->page_sizes = page_sizes_v3_4;
Acked-by: William Zhang william.zhang@broadcom.com

From: Álvaro Fernández Rojas noltari@gmail.com
v2.1: tested on Netgear DGND3700v1 (BCM6368) v2.2: tested on Netgear DGND3700v2 (BCM6362)
Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Acked-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20200522121524.4161539-6-noltari@gmail.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 85 +++++++++++++++++++++--- 1 file changed, 76 insertions(+), 9 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 10a2e2c0f599..b2ebcaf7a5bf 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -217,6 +217,7 @@ struct brcmnand_controller { const unsigned int *block_sizes; unsigned int max_page_size; const unsigned int *page_sizes; + unsigned int page_size_shift; unsigned int max_oob; u32 features;
@@ -293,6 +294,36 @@ enum brcmnand_reg { BRCMNAND_FC_BASE, };
+/* BRCMNAND v2.1-v2.2 */ +static const u16 brcmnand_regs_v21[] = { + [BRCMNAND_CMD_START] = 0x04, + [BRCMNAND_CMD_EXT_ADDRESS] = 0x08, + [BRCMNAND_CMD_ADDRESS] = 0x0c, + [BRCMNAND_INTFC_STATUS] = 0x5c, + [BRCMNAND_CS_SELECT] = 0x14, + [BRCMNAND_CS_XOR] = 0x18, + [BRCMNAND_LL_OP] = 0, + [BRCMNAND_CS0_BASE] = 0x40, + [BRCMNAND_CS1_BASE] = 0, + [BRCMNAND_CORR_THRESHOLD] = 0, + [BRCMNAND_CORR_THRESHOLD_EXT] = 0, + [BRCMNAND_UNCORR_COUNT] = 0, + [BRCMNAND_CORR_COUNT] = 0, + [BRCMNAND_CORR_EXT_ADDR] = 0x60, + [BRCMNAND_CORR_ADDR] = 0x64, + [BRCMNAND_UNCORR_EXT_ADDR] = 0x68, + [BRCMNAND_UNCORR_ADDR] = 0x6c, + [BRCMNAND_SEMAPHORE] = 0x50, + [BRCMNAND_ID] = 0x54, + [BRCMNAND_ID_EXT] = 0, + [BRCMNAND_LL_RDATA] = 0, + [BRCMNAND_OOB_READ_BASE] = 0x20, + [BRCMNAND_OOB_READ_10_BASE] = 0, + [BRCMNAND_OOB_WRITE_BASE] = 0x30, + [BRCMNAND_OOB_WRITE_10_BASE] = 0, + [BRCMNAND_FC_BASE] = 0x200, +}; + /* BRCMNAND v3.3-v4.0 */ static const u16 brcmnand_regs_v33[] = { [BRCMNAND_CMD_START] = 0x04, @@ -491,6 +522,9 @@ enum { CFG_BUS_WIDTH = BIT(CFG_BUS_WIDTH_SHIFT), CFG_DEVICE_SIZE_SHIFT = 24,
+ /* Only for v2.1 */ + CFG_PAGE_SIZE_SHIFT_v2_1 = 30, + /* Only for pre-v7.1 (with no CFG_EXT register) */ CFG_PAGE_SIZE_SHIFT = 20, CFG_BLK_SIZE_SHIFT = 28, @@ -526,12 +560,16 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) { static const unsigned int block_sizes_v6[] = { 8, 16, 128, 256, 512, 1024, 2048, 0 }; static const unsigned int block_sizes_v4[] = { 16, 128, 8, 512, 256, 1024, 2048, 0 }; + static const unsigned int block_sizes_v2_2[] = { 16, 128, 8, 512, 256, 0 }; + static const unsigned int block_sizes_v2_1[] = { 16, 128, 8, 512, 0 }; static const unsigned int page_sizes_v3_4[] = { 512, 2048, 4096, 8192, 0 }; + static const unsigned int page_sizes_v2_2[] = { 512, 2048, 4096, 0 }; + static const unsigned int page_sizes_v2_1[] = { 512, 2048, 0 };
ctrl->nand_version = nand_readreg(ctrl, 0) & 0xffff;
- /* Only support v4.0+? */ - if (ctrl->nand_version < 0x0400) { + /* Only support v2.1+ */ + if (ctrl->nand_version < 0x0201) { dev_err(ctrl->dev, "version %#x not supported\n", ctrl->nand_version); return -ENODEV; @@ -548,6 +586,8 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) ctrl->reg_offsets = brcmnand_regs_v50; else if (ctrl->nand_version >= 0x0303) ctrl->reg_offsets = brcmnand_regs_v33; + else if (ctrl->nand_version >= 0x0201) + ctrl->reg_offsets = brcmnand_regs_v21;
/* Chip-select stride */ if (ctrl->nand_version >= 0x0701) @@ -573,14 +613,32 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) ctrl->max_page_size = 16 * 1024; ctrl->max_block_size = 2 * 1024 * 1024; } else { - ctrl->page_sizes = page_sizes_v3_4; + if (ctrl->nand_version >= 0x0304) + ctrl->page_sizes = page_sizes_v3_4; + else if (ctrl->nand_version >= 0x0202) + ctrl->page_sizes = page_sizes_v2_2; + else + ctrl->page_sizes = page_sizes_v2_1; + + if (ctrl->nand_version >= 0x0202) + ctrl->page_size_shift = CFG_PAGE_SIZE_SHIFT; + else + ctrl->page_size_shift = CFG_PAGE_SIZE_SHIFT_v2_1; + if (ctrl->nand_version >= 0x0600) ctrl->block_sizes = block_sizes_v6; - else + else if (ctrl->nand_version >= 0x0400) ctrl->block_sizes = block_sizes_v4; + else if (ctrl->nand_version >= 0x0202) + ctrl->block_sizes = block_sizes_v2_2; + else + ctrl->block_sizes = block_sizes_v2_1;
if (ctrl->nand_version < 0x0400) { - ctrl->max_page_size = 4096; + if (ctrl->nand_version < 0x0202) + ctrl->max_page_size = 2048; + else + ctrl->max_page_size = 4096; ctrl->max_block_size = 512 * 1024; } } @@ -756,6 +814,9 @@ static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val) enum brcmnand_reg reg = BRCMNAND_CORR_THRESHOLD; int cs = host->cs;
+ if (!ctrl->reg_offsets[reg]) + return; + if (ctrl->nand_version == 0x0702) bits = 7; else if (ctrl->nand_version >= 0x0600) @@ -814,8 +875,10 @@ static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl) return GENMASK(7, 0); else if (ctrl->nand_version >= 0x0600) return GENMASK(6, 0); - else + else if (ctrl->nand_version >= 0x0303) return GENMASK(5, 0); + else + return GENMASK(4, 0); }
#define NAND_ACC_CONTROL_ECC_SHIFT 16 @@ -2149,7 +2212,7 @@ static int brcmnand_set_cfg(struct brcmnand_host *host, (!!(cfg->device_width == 16) << CFG_BUS_WIDTH_SHIFT) | (device_size << CFG_DEVICE_SIZE_SHIFT); if (cfg_offs == cfg_ext_offs) { - tmp |= (page_size << CFG_PAGE_SIZE_SHIFT) | + tmp |= (page_size << ctrl->page_size_shift) | (block_size << CFG_BLK_SIZE_SHIFT); nand_writereg(ctrl, cfg_offs, tmp); } else { @@ -2161,9 +2224,11 @@ static int brcmnand_set_cfg(struct brcmnand_host *host,
tmp = nand_readreg(ctrl, acc_control_offs); tmp &= ~brcmnand_ecc_level_mask(ctrl); - tmp |= cfg->ecc_level << NAND_ACC_CONTROL_ECC_SHIFT; tmp &= ~brcmnand_spare_area_mask(ctrl); - tmp |= cfg->spare_area_size; + if (ctrl->nand_version >= 0x0302) { + tmp |= cfg->ecc_level << NAND_ACC_CONTROL_ECC_SHIFT; + tmp |= cfg->spare_area_size; + } nand_writereg(ctrl, acc_control_offs, tmp);
brcmnand_set_sector_size_1k(host, cfg->sector_size_1k); @@ -2543,6 +2608,8 @@ const struct dev_pm_ops brcmnand_pm_ops = { EXPORT_SYMBOL_GPL(brcmnand_pm_ops);
static const struct of_device_id brcmnand_of_match[] = { + { .compatible = "brcm,brcmnand-v2.1" }, + { .compatible = "brcm,brcmnand-v2.2" }, { .compatible = "brcm,brcmnand-v4.0" }, { .compatible = "brcm,brcmnand-v5.0" }, { .compatible = "brcm,brcmnand-v6.0" },

On 02/11/2023 07:29 AM, Linus Walleij wrote:
From: Álvaro Fernández Rojas noltari@gmail.com
v2.1: tested on Netgear DGND3700v1 (BCM6368) v2.2: tested on Netgear DGND3700v2 (BCM6362)
Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Acked-by: Florian Fainelli f.fainelli@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20200522121524.4161539-6-noltari@gmail.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 85 +++++++++++++++++++++--- 1 file changed, 76 insertions(+), 9 deletions(-)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 10a2e2c0f599..b2ebcaf7a5bf 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -217,6 +217,7 @@ struct brcmnand_controller { const unsigned int *block_sizes; unsigned int max_page_size; const unsigned int *page_sizes;
- unsigned int page_size_shift; unsigned int max_oob; u32 features;
@@ -293,6 +294,36 @@ enum brcmnand_reg { BRCMNAND_FC_BASE, };
+/* BRCMNAND v2.1-v2.2 */ +static const u16 brcmnand_regs_v21[] = {
- [BRCMNAND_CMD_START] = 0x04,
- [BRCMNAND_CMD_EXT_ADDRESS] = 0x08,
- [BRCMNAND_CMD_ADDRESS] = 0x0c,
- [BRCMNAND_INTFC_STATUS] = 0x5c,
- [BRCMNAND_CS_SELECT] = 0x14,
- [BRCMNAND_CS_XOR] = 0x18,
- [BRCMNAND_LL_OP] = 0,
- [BRCMNAND_CS0_BASE] = 0x40,
- [BRCMNAND_CS1_BASE] = 0,
- [BRCMNAND_CORR_THRESHOLD] = 0,
- [BRCMNAND_CORR_THRESHOLD_EXT] = 0,
- [BRCMNAND_UNCORR_COUNT] = 0,
- [BRCMNAND_CORR_COUNT] = 0,
- [BRCMNAND_CORR_EXT_ADDR] = 0x60,
- [BRCMNAND_CORR_ADDR] = 0x64,
- [BRCMNAND_UNCORR_EXT_ADDR] = 0x68,
- [BRCMNAND_UNCORR_ADDR] = 0x6c,
- [BRCMNAND_SEMAPHORE] = 0x50,
- [BRCMNAND_ID] = 0x54,
- [BRCMNAND_ID_EXT] = 0,
- [BRCMNAND_LL_RDATA] = 0,
- [BRCMNAND_OOB_READ_BASE] = 0x20,
- [BRCMNAND_OOB_READ_10_BASE] = 0,
- [BRCMNAND_OOB_WRITE_BASE] = 0x30,
- [BRCMNAND_OOB_WRITE_10_BASE] = 0,
- [BRCMNAND_FC_BASE] = 0x200,
+};
- /* BRCMNAND v3.3-v4.0 */ static const u16 brcmnand_regs_v33[] = { [BRCMNAND_CMD_START] = 0x04,
@@ -491,6 +522,9 @@ enum { CFG_BUS_WIDTH = BIT(CFG_BUS_WIDTH_SHIFT), CFG_DEVICE_SIZE_SHIFT = 24,
- /* Only for v2.1 */
- CFG_PAGE_SIZE_SHIFT_v2_1 = 30,
- /* Only for pre-v7.1 (with no CFG_EXT register) */ CFG_PAGE_SIZE_SHIFT = 20, CFG_BLK_SIZE_SHIFT = 28,
@@ -526,12 +560,16 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) { static const unsigned int block_sizes_v6[] = { 8, 16, 128, 256, 512, 1024, 2048, 0 }; static const unsigned int block_sizes_v4[] = { 16, 128, 8, 512, 256, 1024, 2048, 0 };
static const unsigned int block_sizes_v2_2[] = { 16, 128, 8, 512, 256, 0 };
static const unsigned int block_sizes_v2_1[] = { 16, 128, 8, 512, 0 }; static const unsigned int page_sizes_v3_4[] = { 512, 2048, 4096, 8192, 0 };
static const unsigned int page_sizes_v2_2[] = { 512, 2048, 4096, 0 };
static const unsigned int page_sizes_v2_1[] = { 512, 2048, 0 };
ctrl->nand_version = nand_readreg(ctrl, 0) & 0xffff;
- /* Only support v4.0+? */
- if (ctrl->nand_version < 0x0400) {
- /* Only support v2.1+ */
- if (ctrl->nand_version < 0x0201) { dev_err(ctrl->dev, "version %#x not supported\n", ctrl->nand_version); return -ENODEV;
@@ -548,6 +586,8 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) ctrl->reg_offsets = brcmnand_regs_v50; else if (ctrl->nand_version >= 0x0303) ctrl->reg_offsets = brcmnand_regs_v33;
else if (ctrl->nand_version >= 0x0201)
ctrl->reg_offsets = brcmnand_regs_v21;
/* Chip-select stride */ if (ctrl->nand_version >= 0x0701)
@@ -573,14 +613,32 @@ static int brcmnand_revision_init(struct brcmnand_controller *ctrl) ctrl->max_page_size = 16 * 1024; ctrl->max_block_size = 2 * 1024 * 1024; } else {
ctrl->page_sizes = page_sizes_v3_4;
if (ctrl->nand_version >= 0x0304)
ctrl->page_sizes = page_sizes_v3_4;
else if (ctrl->nand_version >= 0x0202)
ctrl->page_sizes = page_sizes_v2_2;
else
ctrl->page_sizes = page_sizes_v2_1;
if (ctrl->nand_version >= 0x0202)
ctrl->page_size_shift = CFG_PAGE_SIZE_SHIFT;
else
ctrl->page_size_shift = CFG_PAGE_SIZE_SHIFT_v2_1;
- if (ctrl->nand_version >= 0x0600) ctrl->block_sizes = block_sizes_v6;
else
else if (ctrl->nand_version >= 0x0400) ctrl->block_sizes = block_sizes_v4;
else if (ctrl->nand_version >= 0x0202)
ctrl->block_sizes = block_sizes_v2_2;
else
ctrl->block_sizes = block_sizes_v2_1;
if (ctrl->nand_version < 0x0400) {
ctrl->max_page_size = 4096;
if (ctrl->nand_version < 0x0202)
ctrl->max_page_size = 2048;
else
} }ctrl->max_page_size = 4096; ctrl->max_block_size = 512 * 1024;
@@ -756,6 +814,9 @@ static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val) enum brcmnand_reg reg = BRCMNAND_CORR_THRESHOLD; int cs = host->cs;
- if (!ctrl->reg_offsets[reg])
return;
- if (ctrl->nand_version == 0x0702) bits = 7; else if (ctrl->nand_version >= 0x0600)
@@ -814,8 +875,10 @@ static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl) return GENMASK(7, 0); else if (ctrl->nand_version >= 0x0600) return GENMASK(6, 0);
- else
else if (ctrl->nand_version >= 0x0303) return GENMASK(5, 0);
else
return GENMASK(4, 0);
}
#define NAND_ACC_CONTROL_ECC_SHIFT 16
@@ -2149,7 +2212,7 @@ static int brcmnand_set_cfg(struct brcmnand_host *host, (!!(cfg->device_width == 16) << CFG_BUS_WIDTH_SHIFT) | (device_size << CFG_DEVICE_SIZE_SHIFT); if (cfg_offs == cfg_ext_offs) {
tmp |= (page_size << CFG_PAGE_SIZE_SHIFT) |
nand_writereg(ctrl, cfg_offs, tmp); } else {tmp |= (page_size << ctrl->page_size_shift) | (block_size << CFG_BLK_SIZE_SHIFT);
@@ -2161,9 +2224,11 @@ static int brcmnand_set_cfg(struct brcmnand_host *host,
tmp = nand_readreg(ctrl, acc_control_offs); tmp &= ~brcmnand_ecc_level_mask(ctrl);
- tmp |= cfg->ecc_level << NAND_ACC_CONTROL_ECC_SHIFT; tmp &= ~brcmnand_spare_area_mask(ctrl);
- tmp |= cfg->spare_area_size;
if (ctrl->nand_version >= 0x0302) {
tmp |= cfg->ecc_level << NAND_ACC_CONTROL_ECC_SHIFT;
tmp |= cfg->spare_area_size;
} nand_writereg(ctrl, acc_control_offs, tmp);
brcmnand_set_sector_size_1k(host, cfg->sector_size_1k);
@@ -2543,6 +2608,8 @@ const struct dev_pm_ops brcmnand_pm_ops = { EXPORT_SYMBOL_GPL(brcmnand_pm_ops);
static const struct of_device_id brcmnand_of_match[] = {
- { .compatible = "brcm,brcmnand-v2.1" },
- { .compatible = "brcm,brcmnand-v2.2" }, { .compatible = "brcm,brcmnand-v4.0" }, { .compatible = "brcm,brcmnand-v5.0" }, { .compatible = "brcm,brcmnand-v6.0" },
Acked-by: William Zhang william.zhang@broadcom.com

From: Álvaro Fernández Rojas noltari@gmail.com
Hamming ECC doesn't cover the OOB data, so reading or writing OOB shall always be done without ECC enabled. This is a problem when adding JFFS2 cleanmarkers to erased blocks. If JFFS2 clenmarkers are added to the OOB with ECC enabled, OOB bytes will be changed from ff ff ff to 00 00 00, reporting incorrect ECC errors.
Fixes: 27c5b17cd1b1 ("mtd: nand: add NAND driver "library" for Broadcom STB NAND controller") Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Acked-by: Brian Norris computersforpeace@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20210224080210.23686-1-noltari@gmail.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index b2ebcaf7a5bf..efbf9a3120a4 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -2515,6 +2515,12 @@ static int brcmnand_init_cs(struct brcmnand_host *host, ofnode dn) ret = nand_register(0, mtd); #endif /* __UBOOT__ */
+ /* If OOB is written with ECC enabled it will cause ECC errors */ + if (is_hamming_ecc(host->ctrl, &host->hwcfg)) { + chip->ecc.write_oob = brcmnand_write_oob_raw; + chip->ecc.read_oob = brcmnand_read_oob_raw; + } + return ret; }

On 02/11/2023 07:29 AM, Linus Walleij wrote:
From: Álvaro Fernández Rojas noltari@gmail.com
Hamming ECC doesn't cover the OOB data, so reading or writing OOB shall always be done without ECC enabled. This is a problem when adding JFFS2 cleanmarkers to erased blocks. If JFFS2 clenmarkers are added to the OOB with ECC enabled, OOB bytes will be changed from ff ff ff to 00 00 00, reporting incorrect ECC errors.
Fixes: 27c5b17cd1b1 ("mtd: nand: add NAND driver "library" for Broadcom STB NAND controller") Signed-off-by: Álvaro Fernández Rojas noltari@gmail.com Acked-by: Brian Norris computersforpeace@gmail.com Signed-off-by: Miquel Raynal miquel.raynal@bootlin.com Link: https://lore.kernel.org/linux-mtd/20210224080210.23686-1-noltari@gmail.com [Ported to U-Boot from the Linux kernel] Signed-off-by: Linus Walleij linus.walleij@linaro.org
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index b2ebcaf7a5bf..efbf9a3120a4 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -2515,6 +2515,12 @@ static int brcmnand_init_cs(struct brcmnand_host *host, ofnode dn) ret = nand_register(0, mtd); #endif /* __UBOOT__ */
- /* If OOB is written with ECC enabled it will cause ECC errors */
- if (is_hamming_ecc(host->ctrl, &host->hwcfg)) {
chip->ecc.write_oob = brcmnand_write_oob_raw;
chip->ecc.read_oob = brcmnand_read_oob_raw;
- }
- return ret; }
Acked-by: William Zhang william.zhang@broadcom.com

Hi Linus.
On 02/11/2023 07:28 AM, Linus Walleij wrote:
Hunting down a bug on my system I took to back-porting all reasonable changes from the Linux brcmnand driver that were not yet in the U-Boot derivative.
I noticed that a simple diff -ur between brcmnand.c between the file in Linux and U-Boot was possible to see what differs. Combining this with some git log --oneline manual comparison, fuzzing and manual intervention I backported a set of relevant patches from Linux that compiles and WorksForMe(TM).
The diff between Linux and U-Boot is much smaller after this, the main missing part are subsystem cosmetics changes and the EDU DMA mode support.
This was as much as I could bite off in one go.
All patches countersigned-off and marked as [backported].
ChangeLog v1->v2:
- Drop the patch to use the new OOB data layout helpers "mtd: nand: brcm: switch to mtd_ooblayout_ops"
- Drop all patches depending on the previous patch, in total 4 patches.
Claire Lin (1): mtd: rawnand: brcmnand: Fix ecc chunk calculation for erased page bitfips
Kamal Dasu (3): mtd: rawnand: brcmnand: Refactored code to introduce helper functions mtd: rawnand: brcmnand: Add support for v7.3 controller mtd: nand: brcmnand: Add support for flash-dma v0
Álvaro Fernández Rojas (6): mtd: rawnand: brcmnand: correctly verify erased pages mtd: rawnand: brcmnand: rename v4 registers mtd: rawnand: brcmnand: fix CS0 layout mtd: rawnand: brcmnand: rename page sizes mtd: rawnand: brcmnand: support v2.1-v2.2 controllers mtd: rawnand: brcmnand: fix OOB R/W with Hamming ECC
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 353 +++++++++++++++++------ 1 file changed, 268 insertions(+), 85 deletions(-)
Sorry for the delay. Finally I got some time to try your patches on a BCM63158 based board with NAND controller 7.1. It works fine.

Hi
On Wed, Feb 22, 2023 at 2:28 AM William Zhang william.zhang@broadcom.com wrote:
Hi Linus.
On 02/11/2023 07:28 AM, Linus Walleij wrote:
Hunting down a bug on my system I took to back-porting all reasonable changes from the Linux brcmnand driver that were not yet in the U-Boot derivative.
I noticed that a simple diff -ur between brcmnand.c between the file in Linux and U-Boot was possible to see what differs. Combining this with some git log --oneline manual comparison, fuzzing and manual intervention I backported a set of relevant patches from Linux that compiles and WorksForMe(TM).
The diff between Linux and U-Boot is much smaller after this, the main missing part are subsystem cosmetics changes and the EDU DMA mode support.
This was as much as I could bite off in one go.
All patches countersigned-off and marked as [backported].
ChangeLog v1->v2:
- Drop the patch to use the new OOB data layout helpers "mtd: nand: brcm: switch to mtd_ooblayout_ops"
- Drop all patches depending on the previous patch, in total 4 patches.
Claire Lin (1): mtd: rawnand: brcmnand: Fix ecc chunk calculation for erased page bitfips
Kamal Dasu (3): mtd: rawnand: brcmnand: Refactored code to introduce helper functions mtd: rawnand: brcmnand: Add support for v7.3 controller mtd: nand: brcmnand: Add support for flash-dma v0
Álvaro Fernández Rojas (6): mtd: rawnand: brcmnand: correctly verify erased pages mtd: rawnand: brcmnand: rename v4 registers mtd: rawnand: brcmnand: fix CS0 layout mtd: rawnand: brcmnand: rename page sizes mtd: rawnand: brcmnand: support v2.1-v2.2 controllers mtd: rawnand: brcmnand: fix OOB R/W with Hamming ECC
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 353 +++++++++++++++++------ 1 file changed, 268 insertions(+), 85 deletions(-)
Sorry for the delay. Finally I got some time to try your patches on a BCM63158 based board with NAND controller 7.1. It works fine.
We will queue this week, thank you
Michael
participants (3)
-
Linus Walleij
-
Michael Nazzareno Trimarchi
-
William Zhang