diff options
author | Sekhar Nori <nsekhar@ti.com> | 2010-08-09 06:16:36 -0400 |
---|---|---|
committer | Kevin Hilman <khilman@deeprootsystems.com> | 2010-09-24 10:40:26 -0400 |
commit | a88dbc5bfdd26132bbf0ad19dd672e036971d74d (patch) | |
tree | 112aa4d073c606352a2fc938a953a913b21d18bc | |
parent | 8060ef4da9e73f461adf2ba1922ea5400a61cf98 (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.h | 3 | ||||
-rw-r--r-- | drivers/mtd/nand/davinci_nand.c | 60 |
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 | ||
80 | static DEFINE_SPINLOCK(davinci_nand_lock); | 82 | static 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 | ||
482 | static 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 | ||
812 | err_scan: | 795 | err_scan: |
796 | err_timing: | ||
813 | clk_disable(info->clk); | 797 | clk_disable(info->clk); |
814 | 798 | ||
815 | err_clk_enable: | 799 | err_clk_enable: |