Merge git://git.infradead.org/mtd-2.6
[~shefty/rdma-dev.git] / drivers / mtd / nand / davinci_nand.c
index ad51f8ef0d4fcd82ad26345133e9dd764cc82206..a90fde3ede28ca40d992432123cca7e08318e017 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/slab.h>
 
 #include <mach/nand.h>
 #include <linux/slab.h>
 
 #include <mach/nand.h>
+#include <mach/aemif.h>
 
 #include <asm/mach-types.h>
 
 
 #include <asm/mach-types.h>
 
@@ -74,6 +75,8 @@ struct davinci_nand_info {
        uint32_t                mask_cle;
 
        uint32_t                core_chipsel;
        uint32_t                mask_cle;
 
        uint32_t                core_chipsel;
+
+       struct davinci_aemif_timing     *timing;
 };
 
 static DEFINE_SPINLOCK(davinci_nand_lock);
 };
 
 static DEFINE_SPINLOCK(davinci_nand_lock);
@@ -480,36 +483,6 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd)
        return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0);
 }
 
        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
 /*----------------------------------------------------------------------*/
 
 /* An ECC layout for using 4-bit ECC with small-page flash, storing
@@ -613,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->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;
 
 
        info->ioaddr            = (uint32_t __force) vaddr;
 
@@ -690,15 +664,25 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
                goto err_clk_enable;
        }
 
                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);
 
 
        spin_lock_irq(&davinci_nand_lock);
 
@@ -814,6 +798,7 @@ syndrome_done:
        return 0;
 
 err_scan:
        return 0;
 
 err_scan:
+err_timing:
        clk_disable(info->clk);
 
 err_clk_enable:
        clk_disable(info->clk);
 
 err_clk_enable: