[U-Boot] [PATCH] mtd: nand: fsl_ifc: Fix eccstat array overflow for IFC ver >= 2.0.0

Number of ECC status registers i.e. (ECCSTATx) has been increased in IFC version 2.0.0 due to increase in SRAM size. This is causing eccstat array to over flow.
So, replace eccstat array with u32 variable to make it fail-safe and independent of number of ECC status registers or SRAM size.
Signed-off-by: Prabhakar Kushwaha prabhakar.kushwaha@nxp.com Signed-off-by: Jagdish Gediya jagdish.gediya@nxp.com --- drivers/mtd/nand/fsl_ifc_nand.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-)
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index d1165f7..34016cb 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -270,14 +270,9 @@ static int is_blank(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
/* returns nonzero if entire page is blank */ static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl, - u32 *eccstat, unsigned int bufnum) + u32 eccstat, unsigned int bufnum) { - u32 reg = eccstat[bufnum / 4]; - int errors; - - errors = (reg >> ((3 - bufnum % 4) * 8)) & 15; - - return errors; + return (eccstat >> ((3 - bufnum % 4) * 8)) & 15; }
/* @@ -291,7 +286,7 @@ static int fsl_ifc_run_command(struct mtd_info *mtd) struct fsl_ifc_runtime *ifc = ctrl->regs.rregs; u32 timeo = (CONFIG_SYS_HZ * 10) / 1000; u32 time_start; - u32 eccstat[8] = {0}; + u32 eccstat; int i;
/* set the chip select for NAND Transaction */ @@ -324,17 +319,18 @@ static int fsl_ifc_run_command(struct mtd_info *mtd) int sector = bufnum * chip->ecc.steps; int sector_end = sector + chip->ecc.steps - 1;
- for (i = sector / 4; i <= sector_end / 4; i++) { - if (i >= ARRAY_SIZE(eccstat)) { - printf("%s: eccstat too small for %d\n", - __func__, i); - return -EIO; - } - - eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]); - } + eccstat = 0;
for (i = sector; i <= sector_end; i++) { + + /* + * sector is not necessarily aligned on 4 and + * we need to read the eccstat in this case, + * hence the sector test. + */ + if ((i % 4 == 0) || (sector == sector_end)) + eccstat = ifc_in32(&ifc->ifc_nand.nand_eccstat[i / 4]); + errors = check_read_ecc(mtd, ctrl, eccstat, i);
if (errors == 15) {

As per the IFC hardware manual, Most significant 2 bytes in nand_fsr register are the outcome of NAND READ STATUS command.
So status value need to be shifted and aligned as per the nand framework requirement.
Signed-off-by: Jagdish Gediya jagdish.gediya@nxp.com Reviewed-by: Prabhakar Kushwaha prabhakar.kushwaha@nxp.com --- drivers/mtd/nand/fsl_ifc_nand.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 34016cb..e34eb3d 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -725,10 +725,11 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) return NAND_STATUS_FAIL;
nand_fsr = ifc_in32(&ifc->ifc_nand.nand_fsr); + nand_fsr >>= 16; + nand_fsr = (nand_fsr >> 8) | (nand_fsr << 8);
/* Chip sometimes reporting write protect even when it's not */ - nand_fsr = nand_fsr | NAND_STATUS_WP; - return nand_fsr; + return (nand_fsr & 0xff) | NAND_STATUS_WP; }
static int fsl_ifc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
participants (1)
-
Jagdish Gediya