On TI's DA830/OMAP-L137, DA850/OMAP-L138 and DM365, after setting the 4BITECC_ADD_CALC_START bit in the NAND Flash control register to 1 and before waiting for the NAND Flash status register to be equal to 1, 2 or 3, we have to wait till the ECC HW goes to correction state. Without this wait, ECC correction calculations will not be proper.
This has been tested on DA830/OMAP-L137, DA850/OMAP-L138, DM355 and DM365 EVMs. Signed-off-by: Sudhakar Rajashekhara <[email protected]> Acked-by: Sneha Narnakaje <[email protected]> Cc: David Woodhouse <[email protected]> Signed-off-by: Andrew Morton <[email protected]> --- Since v1: a. Timeout has been changed from 100 msec to 100 usec. b. Comment above the do, while loop was not matching the code. This has been corrected. c. Initialization of 'timeo' variable has been moved down. d. It was observed that, while calculating the time in the loop, if there is a context switch between setting the 4BITECC_ADD_CALC_START bit and reading of ECC_STATE field, then the loop will not come out until the timeout happens. To prevent the context switch, spin_lock_irqsave and spin_unlock_irqrestore are used. drivers/mtd/nand/davinci_nand.c | 22 ++++++++++++++++++++++ 1 files changed, 22 insertions(+), 0 deletions(-) diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 9c9d893..1e2657c 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -311,7 +311,11 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd, unsigned short ecc10[8]; unsigned short *ecc16; u32 syndrome[4]; + u32 ecc_state; unsigned num_errors, corrected; + unsigned long timeo; + DEFINE_SPINLOCK(ecc_spin_lock); + unsigned long flags; /* All bytes 0xff? It's an erased page; ignore its ECC. */ for (i = 0; i < 10; i++) { @@ -355,12 +359,30 @@ compare: */ davinci_nand_readl(info, NAND_ERR_ADD1_OFFSET); + spin_lock_irqsave(&ecc_spin_lock, flags); /* Start address calculation, and wait for it to complete. * We _could_ start reading more data while this is working, * to speed up the overall page read. */ davinci_nand_writel(info, NANDFCR_OFFSET, davinci_nand_readl(info, NANDFCR_OFFSET) | BIT(13)); + + /* + * ECC_STATE field reads 0x3 (Error correction complete) immediately + * after setting the 4BITECC_ADD_CALC_START bit. So if you immediately + * begin trying to poll for the state, you may fall right out of your + * loop without any of the correction calculations having taken place. + * The recommendation from the hardware team is to wait till ECC_STATE + * reads >= 4, which means ECC HW has entered correction state. + */ + timeo = jiffies + usecs_to_jiffies(100); + do { + ecc_state = (davinci_nand_readl(info, + NANDFSR_OFFSET) >> 8) & 0x0f; + cpu_relax(); + } while ((ecc_state < 4) && time_before(jiffies, timeo)); + spin_unlock_irqrestore(&ecc_spin_lock, flags); + for (;;) { u32 fsr = davinci_nand_readl(info, NANDFSR_OFFSET); -- 1.5.6 _______________________________________________ Davinci-linux-open-source mailing list [email protected] http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source
