nand: mxs: correct bitflip for erased NAND page
authorPeng Fan <peng.fan@nxp.com>
Mon, 4 May 2020 14:08:53 +0000 (22:08 +0800)
committerStefano Babic <sbabic@denx.de>
Sun, 10 May 2020 18:55:20 +0000 (20:55 +0200)
This patch is a porting of
http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/
commit/?h=imx_4.1.15_1.0.0_ga&id=e4dacc44d22e9474ec456cb330df525cd805ea38
"
i.MX6QP and i.MX7D BCH module integrated a new feature to detect the
bitflip number for erased NAND page. So for these two platform, set the
erase threshold to gf/2 and if bitflip detected, GPMI driver will
correct the data to all 0xFF.

Also updated the imx6qp dts file to ditinguish the GPMI module for i.MX6Q
with the one for i.MX6QP.
"

In this patch, i.MX6UL is added and threshold changed to use ecc_strength.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
arch/arm/include/asm/mach-imx/regs-bch.h
drivers/mtd/nand/raw/mxs_nand.c

index 39ac5f4d450021d7e4e7002f29d5c297f85d9b78..3c1abb7221c8cbb0d33f618ea24a006110d1880a 100644 (file)
@@ -6,7 +6,8 @@
  * on behalf of DENX Software Engineering GmbH
  *
  * Based on code from LTIB:
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008-2010, 2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
  */
 
 #ifndef __MX28_REGS_BCH_H__
@@ -40,6 +41,7 @@ struct mxs_bch_regs {
        mxs_reg_32(hw_bch_dbgahbmread)
        mxs_reg_32(hw_bch_blockname)
        mxs_reg_32(hw_bch_version)
+       mxs_reg_32(hw_bch_debug1)
 };
 #endif
 
@@ -75,6 +77,9 @@ struct mxs_bch_regs {
 
 #define        BCH_MODE_ERASE_THRESHOLD_MASK                   0xff
 #define        BCH_MODE_ERASE_THRESHOLD_OFFSET                 0
+#define BCH_MODE_ERASE_THRESHOLD(v)                    \
+       (((v) << BCH_MODE_ERASE_THRESHOLD_OFFSET) &     \
+        BCH_MODE_ERASE_THRESHOLD_MASK)
 
 #define        BCH_ENCODEPTR_ADDR_MASK                         0xffffffff
 #define        BCH_ENCODEPTR_ADDR_OFFSET                       0
index 55d24cd0620d05257210d1538d580898f58a3e68..2ac06a573068669aee246748ba0f1966a53aae10 100644 (file)
@@ -10,6 +10,7 @@
  *
  * Copyright (C) 2010 Freescale Semiconductor, Inc.
  * Copyright (C) 2008 Embedded Alley Solutions, Inc.
+ * Copyright 2017-2019 NXP
  */
 
 #include <common.h>
@@ -660,11 +661,13 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
 {
        struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
        struct bch_geometry *geo = &nand_info->bch_geometry;
+       struct mxs_bch_regs *bch_regs = nand_info->bch_regs;
        struct mxs_dma_desc *d;
        uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
        uint32_t corrected = 0, failed = 0;
        uint8_t *status;
        int i, ret;
+       int flag = 0;
 
        /* Compile the DMA descriptor - wait for ready. */
        d = mxs_nand_get_dma_desc(nand_info);
@@ -768,8 +771,13 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
                if (status[i] == 0x00)
                        continue;
 
-               if (status[i] == 0xff)
+               if (status[i] == 0xff) {
+                       if (is_mx6dqp() || is_mx7() ||
+                           is_mx6ul())
+                               if (readl(&bch_regs->hw_bch_debug1))
+                                       flag = 1;
                        continue;
+               }
 
                if (status[i] == 0xfe) {
                        if (mxs_nand_erased_page(mtd, nand,
@@ -801,6 +809,8 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
 
        memcpy(buf, nand_info->data_buf, mtd->writesize);
 
+       if (flag)
+               memset(buf, 0xff, mtd->writesize);
 rtn:
        mxs_nand_return_dma_descs(nand_info);
 
@@ -1160,6 +1170,12 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
        writel(tmp, &bch_regs->hw_bch_flash0layout1);
        nand_info->bch_flash0layout1 = tmp;
 
+       /* Set erase threshold to ecc strength for mx6ul, mx6qp and mx7 */
+       if (is_mx6dqp() || is_mx7() ||
+           is_mx6ul())
+               writel(BCH_MODE_ERASE_THRESHOLD(geo->ecc_strength),
+                      &bch_regs->hw_bch_mode);
+
        /* Set *all* chip selects to use layout 0 */
        writel(0, &bch_regs->hw_bch_layoutselect);