aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/davinci_nand.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/davinci_nand.c')
-rw-r--r--drivers/mtd/nand/davinci_nand.c72
1 files changed, 31 insertions, 41 deletions
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index 2ac7367afe77..a90fde3ede28 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -35,6 +35,7 @@
#include <linux/slab.h>
#include <mach/nand.h>
+#include <mach/aemif.h>
#include <asm/mach-types.h>
@@ -74,6 +75,8 @@ struct davinci_nand_info {
uint32_t mask_cle;
uint32_t core_chipsel;
+
+ struct davinci_aemif_timing *timing;
};
static DEFINE_SPINLOCK(davinci_nand_lock);
@@ -313,7 +316,7 @@ static int nand_davinci_correct_4bit(struct mtd_info *mtd,
u32 syndrome[4];
u32 ecc_state;
unsigned num_errors, corrected;
- unsigned long timeo = jiffies + msecs_to_jiffies(100);
+ unsigned long timeo;
/* All bytes 0xff? It's an erased page; ignore its ECC. */
for (i = 0; i < 10; i++) {
@@ -369,9 +372,11 @@ compare:
* 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 less than 4, which means ECC HW has entered correction state.
+ * The recommendation from the hardware team is to initially delay as
+ * long as ECC_STATE reads less than 4. After that, ECC HW has entered
+ * correction state.
*/
+ timeo = jiffies + usecs_to_jiffies(100);
do {
ecc_state = (davinci_nand_readl(info,
NANDFSR_OFFSET) >> 8) & 0x0f;
@@ -478,36 +483,6 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd)
return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0);
}
-static void __init nand_dm6446evm_flash_init(struct davinci_nand_info *info)
-{
- uint32_t regval, a1cr;
-
- /*
- * NAND FLASH timings @ PLL1 == 459 MHz
- * - AEMIF.CLK freq = PLL1/6 = 459/6 = 76.5 MHz
- * - AEMIF.CLK period = 1/76.5 MHz = 13.1 ns
- */
- regval = 0
- | (0 << 31) /* selectStrobe */
- | (0 << 30) /* extWait (never with NAND) */
- | (1 << 26) /* writeSetup 10 ns */
- | (3 << 20) /* writeStrobe 40 ns */
- | (1 << 17) /* writeHold 10 ns */
- | (0 << 13) /* readSetup 10 ns */
- | (3 << 7) /* readStrobe 60 ns */
- | (0 << 4) /* readHold 10 ns */
- | (3 << 2) /* turnAround ?? ns */
- | (0 << 0) /* asyncSize 8-bit bus */
- ;
- a1cr = davinci_nand_readl(info, A1CR_OFFSET);
- if (a1cr != regval) {
- dev_dbg(info->dev, "Warning: NAND config: Set A1CR " \
- "reg to 0x%08x, was 0x%08x, should be done by " \
- "bootloader.\n", regval, a1cr);
- davinci_nand_writel(info, A1CR_OFFSET, regval);
- }
-}
-
/*----------------------------------------------------------------------*/
/* An ECC layout for using 4-bit ECC with small-page flash, storing
@@ -611,6 +586,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
info->chip.options = pdata->options;
info->chip.bbt_td = pdata->bbt_td;
info->chip.bbt_md = pdata->bbt_md;
+ info->timing = pdata->timing;
info->ioaddr = (uint32_t __force) vaddr;
@@ -688,15 +664,25 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
goto err_clk_enable;
}
- /* EMIF timings should normally be set by the boot loader,
- * especially after boot-from-NAND. The *only* reason to
- * have this special casing for the DM6446 EVM is to work
- * with boot-from-NOR ... with CS0 manually re-jumpered
- * (after startup) so it addresses the NAND flash, not NOR.
- * Even for dev boards, that's unusually rude...
+ /*
+ * Setup Async configuration register in case we did not boot from
+ * NAND and so bootloader did not bother to set it up.
*/
- if (machine_is_davinci_evm())
- nand_dm6446evm_flash_init(info);
+ val = davinci_nand_readl(info, A1CR_OFFSET + info->core_chipsel * 4);
+
+ /* Extended Wait is not valid and Select Strobe mode is not used */
+ val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
+ if (info->chip.options & NAND_BUSWIDTH_16)
+ val |= 0x1;
+
+ davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val);
+
+ ret = davinci_aemif_setup_timing(info->timing, info->base,
+ info->core_chipsel);
+ if (ret < 0) {
+ dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
+ goto err_timing;
+ }
spin_lock_irq(&davinci_nand_lock);
@@ -749,6 +735,9 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
* breaks userspace ioctl interface with mtd-utils. Once we
* resolve this issue, NAND_ECC_HW_OOB_FIRST mode can be used
* for the 4KiB page chips.
+ *
+ * TODO: Note that nand_ecclayout has now been expanded and can
+ * hold plenty of OOB entries.
*/
dev_warn(&pdev->dev, "no 4-bit ECC support yet "
"for 4KiB-page NAND\n");
@@ -809,6 +798,7 @@ syndrome_done:
return 0;
err_scan:
+err_timing:
clk_disable(info->clk);
err_clk_enable: