aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSekhar Nori <nsekhar@ti.com>2010-08-09 06:16:36 -0400
committerKevin Hilman <khilman@deeprootsystems.com>2010-09-24 10:40:26 -0400
commita88dbc5bfdd26132bbf0ad19dd672e036971d74d (patch)
tree112aa4d073c606352a2fc938a953a913b21d18bc
parent8060ef4da9e73f461adf2ba1922ea5400a61cf98 (diff)
nand: davinci: add support for timing configuration
This patch modifies the DaVinci NAND driver to use the new AEMIF timing setup API to configure the NAND access timings. Earlier, AEMIF configuration was being done as a special case for DM644x board, but now more boards emerge which have capability to boot for other media (SPI flash, NOR flash) and have the kernel access NAND flash. This means that kernel cannot always depend on the bootloader to setup the NAND. Also, on platforms such as da850/omap-l138, the aemif input frequency changes as cpu frequency changes; necessiating re-calculation of timimg values as part of cpufreq transtitions. This patch forms the basis for adding that support. Signed-off-by: Sekhar Nori <nsekhar@ti.com> Acked-by: Kevin Hilman <khilman@deeprootsystems.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
-rw-r--r--arch/arm/mach-davinci/include/mach/nand.h3
-rw-r--r--drivers/mtd/nand/davinci_nand.c60
2 files changed, 25 insertions, 38 deletions
diff --git a/arch/arm/mach-davinci/include/mach/nand.h b/arch/arm/mach-davinci/include/mach/nand.h
index b5893f035fea..025151049f05 100644
--- a/arch/arm/mach-davinci/include/mach/nand.h
+++ b/arch/arm/mach-davinci/include/mach/nand.h
@@ -80,6 +80,9 @@ struct davinci_nand_pdata { /* platform_data */
80 /* Main and mirror bbt descriptor overrides */ 80 /* Main and mirror bbt descriptor overrides */
81 struct nand_bbt_descr *bbt_td; 81 struct nand_bbt_descr *bbt_td;
82 struct nand_bbt_descr *bbt_md; 82 struct nand_bbt_descr *bbt_md;
83
84 /* Access timings */
85 struct davinci_aemif_timing *timing;
83}; 86};
84 87
85#endif /* __ARCH_ARM_DAVINCI_NAND_H */ 88#endif /* __ARCH_ARM_DAVINCI_NAND_H */
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index 8e2d56c36811..8beb0d0233b5 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -75,6 +75,8 @@ struct davinci_nand_info {
75 uint32_t mask_cle; 75 uint32_t mask_cle;
76 76
77 uint32_t core_chipsel; 77 uint32_t core_chipsel;
78
79 struct davinci_aemif_timing *timing;
78}; 80};
79 81
80static DEFINE_SPINLOCK(davinci_nand_lock); 82static DEFINE_SPINLOCK(davinci_nand_lock);
@@ -479,36 +481,6 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd)
479 return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0); 481 return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0);
480} 482}
481 483
482static void __init nand_dm6446evm_flash_init(struct davinci_nand_info *info)
483{
484 uint32_t regval, a1cr;
485
486 /*
487 * NAND FLASH timings @ PLL1 == 459 MHz
488 * - AEMIF.CLK freq = PLL1/6 = 459/6 = 76.5 MHz
489 * - AEMIF.CLK period = 1/76.5 MHz = 13.1 ns
490 */
491 regval = 0
492 | (0 << 31) /* selectStrobe */
493 | (0 << 30) /* extWait (never with NAND) */
494 | (1 << 26) /* writeSetup 10 ns */
495 | (3 << 20) /* writeStrobe 40 ns */
496 | (1 << 17) /* writeHold 10 ns */
497 | (0 << 13) /* readSetup 10 ns */
498 | (3 << 7) /* readStrobe 60 ns */
499 | (0 << 4) /* readHold 10 ns */
500 | (3 << 2) /* turnAround ?? ns */
501 | (0 << 0) /* asyncSize 8-bit bus */
502 ;
503 a1cr = davinci_nand_readl(info, A1CR_OFFSET);
504 if (a1cr != regval) {
505 dev_dbg(info->dev, "Warning: NAND config: Set A1CR " \
506 "reg to 0x%08x, was 0x%08x, should be done by " \
507 "bootloader.\n", regval, a1cr);
508 davinci_nand_writel(info, A1CR_OFFSET, regval);
509 }
510}
511
512/*----------------------------------------------------------------------*/ 484/*----------------------------------------------------------------------*/
513 485
514/* An ECC layout for using 4-bit ECC with small-page flash, storing 486/* An ECC layout for using 4-bit ECC with small-page flash, storing
@@ -612,6 +584,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
612 info->chip.options = pdata->options; 584 info->chip.options = pdata->options;
613 info->chip.bbt_td = pdata->bbt_td; 585 info->chip.bbt_td = pdata->bbt_td;
614 info->chip.bbt_md = pdata->bbt_md; 586 info->chip.bbt_md = pdata->bbt_md;
587 info->timing = pdata->timing;
615 588
616 info->ioaddr = (uint32_t __force) vaddr; 589 info->ioaddr = (uint32_t __force) vaddr;
617 590
@@ -689,15 +662,25 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
689 goto err_clk_enable; 662 goto err_clk_enable;
690 } 663 }
691 664
692 /* EMIF timings should normally be set by the boot loader, 665 /*
693 * especially after boot-from-NAND. The *only* reason to 666 * Setup Async configuration register in case we did not boot from
694 * have this special casing for the DM6446 EVM is to work 667 * NAND and so bootloader did not bother to set it up.
695 * with boot-from-NOR ... with CS0 manually re-jumpered
696 * (after startup) so it addresses the NAND flash, not NOR.
697 * Even for dev boards, that's unusually rude...
698 */ 668 */
699 if (machine_is_davinci_evm()) 669 val = davinci_nand_readl(info, A1CR_OFFSET + info->core_chipsel * 4);
700 nand_dm6446evm_flash_init(info); 670
671 /* Extended Wait is not valid and Select Strobe mode is not used */
672 val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
673 if (info->chip.options & NAND_BUSWIDTH_16)
674 val |= 0x1;
675
676 davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val);
677
678 ret = davinci_aemif_setup_timing(info->timing, info->base,
679 info->core_chipsel);
680 if (ret < 0) {
681 dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
682 goto err_timing;
683 }
701 684
702 spin_lock_irq(&davinci_nand_lock); 685 spin_lock_irq(&davinci_nand_lock);
703 686
@@ -810,6 +793,7 @@ syndrome_done:
810 return 0; 793 return 0;
811 794
812err_scan: 795err_scan:
796err_timing:
813 clk_disable(info->clk); 797 clk_disable(info->clk);
814 798
815err_clk_enable: 799err_clk_enable: