diff options
author | David Woodhouse <dwmw2@infradead.org> | 2007-01-23 02:35:27 -0500 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2007-01-23 10:36:42 -0500 |
commit | 527a4f45ef8a4599a899c997e40dbf2feb0a47f8 (patch) | |
tree | ae0c8490c561d22be28d4284381f88590f49774a /drivers/mtd | |
parent | 9ee79a3d372fcb6729893437f4923c5efd1f85db (diff) |
[MTD] [NAND] Inherit CAFÉ NAND timing setup from firmware
The precise timings are board-specific (or NAND chip specific) and don't
belong here. If they're set already, then use what we find there.
Otherwise, revert to the most conservative default values (and whinge).
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/cafe.c | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/drivers/mtd/nand/cafe.c b/drivers/mtd/nand/cafe.c index b8d9b64cccc0..3346aab275c7 100644 --- a/drivers/mtd/nand/cafe.c +++ b/drivers/mtd/nand/cafe.c | |||
@@ -77,8 +77,9 @@ module_param(regdebug, int, 0644); | |||
77 | static int checkecc = 1; | 77 | static int checkecc = 1; |
78 | module_param(checkecc, int, 0644); | 78 | module_param(checkecc, int, 0644); |
79 | 79 | ||
80 | static int slowtiming = 0; | 80 | static int numtimings; |
81 | module_param(slowtiming, int, 0644); | 81 | static int timing[3]; |
82 | module_param_array(timing, int, &numtimings, 0644); | ||
82 | 83 | ||
83 | /* Hrm. Why isn't this already conditional on something in the struct device? */ | 84 | /* Hrm. Why isn't this already conditional on something in the struct device? */ |
84 | #define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0) | 85 | #define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0) |
@@ -528,6 +529,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
528 | { | 529 | { |
529 | struct mtd_info *mtd; | 530 | struct mtd_info *mtd; |
530 | struct cafe_priv *cafe; | 531 | struct cafe_priv *cafe; |
532 | uint32_t timing1, timing2, timing3; | ||
531 | uint32_t ctrl; | 533 | uint32_t ctrl; |
532 | int err = 0; | 534 | int err = 0; |
533 | 535 | ||
@@ -579,27 +581,41 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
579 | cafe->nand.block_bad = cafe_nand_block_bad; | 581 | cafe->nand.block_bad = cafe_nand_block_bad; |
580 | } | 582 | } |
581 | 583 | ||
584 | if (numtimings && numtimings != 3) { | ||
585 | dev_warn(&cafe->pdev->dev, "%d timing register values ignored; precisely three are required\n", numtimings); | ||
586 | } | ||
587 | |||
588 | if (numtimings == 3) { | ||
589 | timing1 = timing[0]; | ||
590 | timing2 = timing[1]; | ||
591 | timing3 = timing[2]; | ||
592 | cafe_dev_dbg(&cafe->pdev->dev, "Using provided timings (%08x %08x %08x)\n", | ||
593 | timing1, timing2, timing3); | ||
594 | } else { | ||
595 | timing1 = cafe_readl(cafe, NAND_TIMING1); | ||
596 | timing2 = cafe_readl(cafe, NAND_TIMING2); | ||
597 | timing3 = cafe_readl(cafe, NAND_TIMING3); | ||
598 | |||
599 | if (timing1 | timing2 | timing3) { | ||
600 | cafe_dev_dbg(&cafe->pdev->dev, "Timing registers already set (%08x %08x %08x)\n", timing1, timing2, timing3); | ||
601 | } else { | ||
602 | dev_warn(&cafe->pdev->dev, "Timing registers unset; using most conservative defaults\n"); | ||
603 | timing1 = timing2 = timing3 = 0xffffffff; | ||
604 | } | ||
605 | } | ||
606 | |||
582 | /* Start off by resetting the NAND controller completely */ | 607 | /* Start off by resetting the NAND controller completely */ |
583 | cafe_writel(cafe, 1, NAND_RESET); | 608 | cafe_writel(cafe, 1, NAND_RESET); |
584 | cafe_writel(cafe, 0, NAND_RESET); | 609 | cafe_writel(cafe, 0, NAND_RESET); |
585 | 610 | ||
586 | cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK); | 611 | cafe_writel(cafe, timing1, NAND_TIMING1); |
612 | cafe_writel(cafe, timing2, NAND_TIMING2); | ||
613 | cafe_writel(cafe, timing3, NAND_TIMING3); | ||
587 | 614 | ||
588 | /* Timings from Marvell's test code (not verified or calculated by us) */ | ||
589 | if (!slowtiming) { | ||
590 | cafe_writel(cafe, 0x01010a0a, NAND_TIMING1); | ||
591 | cafe_writel(cafe, 0x24121212, NAND_TIMING2); | ||
592 | cafe_writel(cafe, 0x11000000, NAND_TIMING3); | ||
593 | } else { | ||
594 | cafe_writel(cafe, 0xffffffff, NAND_TIMING1); | ||
595 | cafe_writel(cafe, 0xffffffff, NAND_TIMING2); | ||
596 | cafe_writel(cafe, 0xffffffff, NAND_TIMING3); | ||
597 | } | ||
598 | cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK); | 615 | cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK); |
599 | err = request_irq(pdev->irq, &cafe_nand_interrupt, SA_SHIRQ, "CAFE NAND", mtd); | 616 | err = request_irq(pdev->irq, &cafe_nand_interrupt, SA_SHIRQ, "CAFE NAND", mtd); |
600 | if (err) { | 617 | if (err) { |
601 | dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq); | 618 | dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq); |
602 | |||
603 | goto out_free_dma; | 619 | goto out_free_dma; |
604 | } | 620 | } |
605 | #if 1 | 621 | #if 1 |