From bee3ab8bdd3b13faf08e5b6e0218f59b0a49fcc3 Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Fri, 12 Jun 2020 17:29:01 -0400 Subject: mtd: rawnand: brcmnand: Don't default to edu transfer When flash-dma is absent do not default to using flash-edu. Make sure flash-edu is enabled before setting EDU transfer function. Fixes: a5d53ad26a8b ("mtd: rawnand: brcmnand: Add support for flash-edu for dma transfers") Signed-off-by: Kamal Dasu Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200612212902.21347-2-kdasu.kdev@gmail.com --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/mtd/nand/raw/brcmnand/brcmnand.c') diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index 44068e9eea03..ac934a715a19 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -3023,8 +3023,9 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) if (ret < 0) goto err; - /* set edu transfer function to call */ - ctrl->dma_trans = brcmnand_edu_trans; + if (has_edu(ctrl)) + /* set edu transfer function to call */ + ctrl->dma_trans = brcmnand_edu_trans; } /* Disable automatic device ID config, direct addressing */ -- cgit v1.2.3 From 4551e78ad98add1f16b70cf286d5aad3ce7bcd4c Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Fri, 12 Jun 2020 17:29:02 -0400 Subject: mtd: rawnand: brcmnand: ECC error handling on EDU transfers Implement ECC correctable and uncorrectable error handling for EDU reads. If ECC correctable bitflips are encountered on EDU transfer, read page again using PIO. This is needed due to a NAND controller limitation where corrected data is not transferred to the DMA buffer on ECC error. This applies to ECC correctable errors that are reported by the controller hardware based on set number of bitflips threshold in the controller threshold register, bitflips below the threshold are corrected silently and are not reported by the controller hardware. Fixes: a5d53ad26a8b ("mtd: rawnand: brcmnand: Add support for flash-edu for dma transfers") Signed-off-by: Kamal Dasu Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20200612212902.21347-3-kdasu.kdev@gmail.com --- drivers/mtd/nand/raw/brcmnand/brcmnand.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers/mtd/nand/raw/brcmnand/brcmnand.c') diff --git a/drivers/mtd/nand/raw/brcmnand/brcmnand.c b/drivers/mtd/nand/raw/brcmnand/brcmnand.c index ac934a715a19..a4033d32a710 100644 --- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c +++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c @@ -1918,6 +1918,22 @@ static int brcmnand_edu_trans(struct brcmnand_host *host, u64 addr, u32 *buf, edu_writel(ctrl, EDU_STOP, 0); /* force stop */ edu_readl(ctrl, EDU_STOP); + if (!ret && edu_cmd == EDU_CMD_READ) { + u64 err_addr = 0; + + /* + * check for ECC errors here, subpage ECC errors are + * retained in ECC error address register + */ + err_addr = brcmnand_get_uncorrecc_addr(ctrl); + if (!err_addr) { + err_addr = brcmnand_get_correcc_addr(ctrl); + if (err_addr) + ret = -EUCLEAN; + } else + ret = -EBADMSG; + } + return ret; } @@ -2124,6 +2140,7 @@ static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip, u64 err_addr = 0; int err; bool retry = true; + bool edu_err = false; dev_dbg(ctrl->dev, "read %llx -> %p\n", (unsigned long long)addr, buf); @@ -2141,6 +2158,10 @@ try_dmaread: else return -EIO; } + + if (has_edu(ctrl) && err_addr) + edu_err = true; + } else { if (oob) memset(oob, 0x99, mtd->oobsize); @@ -2188,6 +2209,11 @@ try_dmaread: if (mtd_is_bitflip(err)) { unsigned int corrected = brcmnand_count_corrected(ctrl); + /* in case of EDU correctable error we read again using PIO */ + if (edu_err) + err = brcmnand_read_by_pio(mtd, chip, addr, trans, buf, + oob, &err_addr); + dev_dbg(ctrl->dev, "corrected error at 0x%llx\n", (unsigned long long)err_addr); mtd->ecc_stats.corrected += corrected; -- cgit v1.2.3