diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-19 16:34:11 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-19 16:34:11 -0500 |
commit | 4935361766cc73949fe032cd157d314f288922ba (patch) | |
tree | 1584f81525ae05a04d515b13a4787cd8eed46029 /drivers/mtd/nand/cafe.c | |
parent | 2874b391bd78a5b8cb84be67297a345fbdec4ac8 (diff) | |
parent | 4f65992381112acd7d2732665a9eae492c2c9de6 (diff) |
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: (49 commits)
[MTD] [NAND] S3C2412 fix hw ecc
[MTD] [NAND] Work around false compiler warning in CAFÉ driver
[JFFS2] printk warning fixes
[MTD] [MAPS] ichxrom warning fix
[MTD] [MAPS] amd76xrom warning fix
[MTD] [MAPS] esb2rom warning fixes
[MTD] [MAPS] ck804xrom warning fix
[MTD] [MAPS] netsc520 warning fix
[MTD] [MAPS] sc520cdp warning fix
[MTD] [ONENAND] onenand_base warning fix
[MTD] [NAND] eXcite nand flash driver
[MTD] Improve heuristic for detecting wrong-endian RedBoot partition table
[MTD] Fix RedBoot partition parsing regression harder.
[MTD] [NAND] S3C2410: Hardware ECC correction code
[JFFS2] Use MTD_OOB_AUTO to automatically place cleanmarker on NAND
[MTD] Clarify OOB-operation interface comments
[MTD] remove unused ecctype,eccsize fields from struct mtd_info
[MTD] [NOR] Intel: remove ugly PROGREGION macros
[MTD] [NOR] STAA: use writesize instead off eccsize to represent ECC block
[MTD] OneNAND: Invalidate bufferRAM after erase
...
Diffstat (limited to 'drivers/mtd/nand/cafe.c')
-rw-r--r-- | drivers/mtd/nand/cafe.c | 89 |
1 files changed, 36 insertions, 53 deletions
diff --git a/drivers/mtd/nand/cafe.c b/drivers/mtd/nand/cafe.c index 08cb060dfa3d..fd6bb3ed40df 100644 --- a/drivers/mtd/nand/cafe.c +++ b/drivers/mtd/nand/cafe.c | |||
@@ -78,8 +78,9 @@ module_param(regdebug, int, 0644); | |||
78 | static int checkecc = 1; | 78 | static int checkecc = 1; |
79 | module_param(checkecc, int, 0644); | 79 | module_param(checkecc, int, 0644); |
80 | 80 | ||
81 | static int slowtiming = 0; | 81 | static int numtimings; |
82 | module_param(slowtiming, int, 0644); | 82 | static int timing[3]; |
83 | module_param_array(timing, int, &numtimings, 0644); | ||
83 | 84 | ||
84 | /* Hrm. Why isn't this already conditional on something in the struct device? */ | 85 | /* Hrm. Why isn't this already conditional on something in the struct device? */ |
85 | #define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0) | 86 | #define cafe_dev_dbg(dev, args...) do { if (debug) dev_dbg(dev, ##args); } while(0) |
@@ -264,10 +265,10 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | |||
264 | ndelay(100); | 265 | ndelay(100); |
265 | 266 | ||
266 | if (1) { | 267 | if (1) { |
267 | int c = 500000; | 268 | int c; |
268 | uint32_t irqs; | 269 | uint32_t irqs; |
269 | 270 | ||
270 | while (c--) { | 271 | for (c = 500000; c != 0; c--) { |
271 | irqs = cafe_readl(cafe, NAND_IRQ); | 272 | irqs = cafe_readl(cafe, NAND_IRQ); |
272 | if (irqs & doneint) | 273 | if (irqs & doneint) |
273 | break; | 274 | break; |
@@ -529,6 +530,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
529 | { | 530 | { |
530 | struct mtd_info *mtd; | 531 | struct mtd_info *mtd; |
531 | struct cafe_priv *cafe; | 532 | struct cafe_priv *cafe; |
533 | uint32_t timing1, timing2, timing3; | ||
532 | uint32_t ctrl; | 534 | uint32_t ctrl; |
533 | int err = 0; | 535 | int err = 0; |
534 | 536 | ||
@@ -580,31 +582,45 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
580 | cafe->nand.block_bad = cafe_nand_block_bad; | 582 | cafe->nand.block_bad = cafe_nand_block_bad; |
581 | } | 583 | } |
582 | 584 | ||
585 | if (numtimings && numtimings != 3) { | ||
586 | dev_warn(&cafe->pdev->dev, "%d timing register values ignored; precisely three are required\n", numtimings); | ||
587 | } | ||
588 | |||
589 | if (numtimings == 3) { | ||
590 | timing1 = timing[0]; | ||
591 | timing2 = timing[1]; | ||
592 | timing3 = timing[2]; | ||
593 | cafe_dev_dbg(&cafe->pdev->dev, "Using provided timings (%08x %08x %08x)\n", | ||
594 | timing1, timing2, timing3); | ||
595 | } else { | ||
596 | timing1 = cafe_readl(cafe, NAND_TIMING1); | ||
597 | timing2 = cafe_readl(cafe, NAND_TIMING2); | ||
598 | timing3 = cafe_readl(cafe, NAND_TIMING3); | ||
599 | |||
600 | if (timing1 | timing2 | timing3) { | ||
601 | cafe_dev_dbg(&cafe->pdev->dev, "Timing registers already set (%08x %08x %08x)\n", timing1, timing2, timing3); | ||
602 | } else { | ||
603 | dev_warn(&cafe->pdev->dev, "Timing registers unset; using most conservative defaults\n"); | ||
604 | timing1 = timing2 = timing3 = 0xffffffff; | ||
605 | } | ||
606 | } | ||
607 | |||
583 | /* Start off by resetting the NAND controller completely */ | 608 | /* Start off by resetting the NAND controller completely */ |
584 | cafe_writel(cafe, 1, NAND_RESET); | 609 | cafe_writel(cafe, 1, NAND_RESET); |
585 | cafe_writel(cafe, 0, NAND_RESET); | 610 | cafe_writel(cafe, 0, NAND_RESET); |
586 | 611 | ||
587 | cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK); | 612 | cafe_writel(cafe, timing1, NAND_TIMING1); |
613 | cafe_writel(cafe, timing2, NAND_TIMING2); | ||
614 | cafe_writel(cafe, timing3, NAND_TIMING3); | ||
588 | 615 | ||
589 | /* Timings from Marvell's test code (not verified or calculated by us) */ | ||
590 | if (!slowtiming) { | ||
591 | cafe_writel(cafe, 0x01010a0a, NAND_TIMING1); | ||
592 | cafe_writel(cafe, 0x24121212, NAND_TIMING2); | ||
593 | cafe_writel(cafe, 0x11000000, NAND_TIMING3); | ||
594 | } else { | ||
595 | cafe_writel(cafe, 0xffffffff, NAND_TIMING1); | ||
596 | cafe_writel(cafe, 0xffffffff, NAND_TIMING2); | ||
597 | cafe_writel(cafe, 0xffffffff, NAND_TIMING3); | ||
598 | } | ||
599 | cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK); | 616 | cafe_writel(cafe, 0xffffffff, NAND_IRQ_MASK); |
600 | err = request_irq(pdev->irq, &cafe_nand_interrupt, IRQF_SHARED, | 617 | err = request_irq(pdev->irq, &cafe_nand_interrupt, IRQF_SHARED, |
601 | "CAFE NAND", mtd); | 618 | "CAFE NAND", mtd); |
602 | if (err) { | 619 | if (err) { |
603 | dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq); | 620 | dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq); |
604 | |||
605 | goto out_free_dma; | 621 | goto out_free_dma; |
606 | } | 622 | } |
607 | #if 1 | 623 | |
608 | /* Disable master reset, enable NAND clock */ | 624 | /* Disable master reset, enable NAND clock */ |
609 | ctrl = cafe_readl(cafe, GLOBAL_CTRL); | 625 | ctrl = cafe_readl(cafe, GLOBAL_CTRL); |
610 | ctrl &= 0xffffeff0; | 626 | ctrl &= 0xffffeff0; |
@@ -631,32 +647,8 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, | |||
631 | cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK); | 647 | cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK); |
632 | cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n", | 648 | cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n", |
633 | cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK)); | 649 | cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK)); |
634 | #endif | 650 | |
635 | #if 1 | 651 | /* Scan to find existence of the device */ |
636 | mtd->writesize=2048; | ||
637 | mtd->oobsize = 0x40; | ||
638 | memset(cafe->dmabuf, 0x5a, 2112); | ||
639 | cafe->nand.cmdfunc(mtd, NAND_CMD_READID, 0, -1); | ||
640 | cafe->nand.read_byte(mtd); | ||
641 | cafe->nand.read_byte(mtd); | ||
642 | cafe->nand.read_byte(mtd); | ||
643 | cafe->nand.read_byte(mtd); | ||
644 | cafe->nand.read_byte(mtd); | ||
645 | #endif | ||
646 | #if 0 | ||
647 | cafe->nand.cmdfunc(mtd, NAND_CMD_READ0, 0, 0); | ||
648 | // nand_wait_ready(mtd); | ||
649 | cafe->nand.read_byte(mtd); | ||
650 | cafe->nand.read_byte(mtd); | ||
651 | cafe->nand.read_byte(mtd); | ||
652 | cafe->nand.read_byte(mtd); | ||
653 | #endif | ||
654 | #if 0 | ||
655 | writel(0x84600070, cafe->mmio); | ||
656 | udelay(10); | ||
657 | cafe_dev_dbg(&cafe->pdev->dev, "Status %x\n", cafe_readl(cafe, NAND_NONMEM)); | ||
658 | #endif | ||
659 | /* Scan to find existance of the device */ | ||
660 | if (nand_scan_ident(mtd, 1)) { | 652 | if (nand_scan_ident(mtd, 1)) { |
661 | err = -ENXIO; | 653 | err = -ENXIO; |
662 | goto out_irq; | 654 | goto out_irq; |
@@ -760,13 +752,4 @@ module_exit(cafe_nand_exit); | |||
760 | 752 | ||
761 | MODULE_LICENSE("GPL"); | 753 | MODULE_LICENSE("GPL"); |
762 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); | 754 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); |
763 | MODULE_DESCRIPTION("NAND flash driver for OLPC CAFE chip"); | 755 | MODULE_DESCRIPTION("NAND flash driver for OLPC CAFÉ chip"); |
764 | |||
765 | /* Correct ECC for 2048 bytes of 0xff: | ||
766 | 41 a0 71 65 54 27 f3 93 ec a9 be ed 0b a1 */ | ||
767 | |||
768 | /* dwmw2's B-test board, in case of completely screwing it: | ||
769 | Bad eraseblock 2394 at 0x12b40000 | ||
770 | Bad eraseblock 2627 at 0x14860000 | ||
771 | Bad eraseblock 3349 at 0x1a2a0000 | ||
772 | */ | ||