diff options
Diffstat (limited to 'drivers/mtd/nand/cafe_nand.c')
-rw-r--r-- | drivers/mtd/nand/cafe_nand.c | 68 |
1 files changed, 46 insertions, 22 deletions
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index f2f64addb5e8..4e66726da9aa 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c | |||
@@ -627,6 +627,8 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
627 | struct cafe_priv *cafe; | 627 | struct cafe_priv *cafe; |
628 | uint32_t ctrl; | 628 | uint32_t ctrl; |
629 | int err = 0; | 629 | int err = 0; |
630 | int old_dma; | ||
631 | struct nand_buffers *nbuf; | ||
630 | 632 | ||
631 | /* Very old versions shared the same PCI ident for all three | 633 | /* Very old versions shared the same PCI ident for all three |
632 | functions on the chip. Verify the class too... */ | 634 | functions on the chip. Verify the class too... */ |
@@ -655,13 +657,6 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
655 | err = -ENOMEM; | 657 | err = -ENOMEM; |
656 | goto out_free_mtd; | 658 | goto out_free_mtd; |
657 | } | 659 | } |
658 | cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112 + sizeof(struct nand_buffers), | ||
659 | &cafe->dmaaddr, GFP_KERNEL); | ||
660 | if (!cafe->dmabuf) { | ||
661 | err = -ENOMEM; | ||
662 | goto out_ior; | ||
663 | } | ||
664 | cafe->nand.buffers = (void *)cafe->dmabuf + 2112; | ||
665 | 660 | ||
666 | cafe->rs = init_rs_non_canonical(12, &cafe_mul, 0, 1, 8); | 661 | cafe->rs = init_rs_non_canonical(12, &cafe_mul, 0, 1, 8); |
667 | if (!cafe->rs) { | 662 | if (!cafe->rs) { |
@@ -721,7 +716,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
721 | "CAFE NAND", mtd); | 716 | "CAFE NAND", mtd); |
722 | if (err) { | 717 | if (err) { |
723 | dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq); | 718 | dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq); |
724 | goto out_free_dma; | 719 | goto out_ior; |
725 | } | 720 | } |
726 | 721 | ||
727 | /* Disable master reset, enable NAND clock */ | 722 | /* Disable master reset, enable NAND clock */ |
@@ -735,6 +730,32 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
735 | cafe_writel(cafe, 0x7006, GLOBAL_CTRL); | 730 | cafe_writel(cafe, 0x7006, GLOBAL_CTRL); |
736 | cafe_writel(cafe, 0x700a, GLOBAL_CTRL); | 731 | cafe_writel(cafe, 0x700a, GLOBAL_CTRL); |
737 | 732 | ||
733 | /* Enable NAND IRQ in global IRQ mask register */ | ||
734 | cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK); | ||
735 | cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n", | ||
736 | cafe_readl(cafe, GLOBAL_CTRL), | ||
737 | cafe_readl(cafe, GLOBAL_IRQ_MASK)); | ||
738 | |||
739 | /* Do not use the DMA for the nand_scan_ident() */ | ||
740 | old_dma = usedma; | ||
741 | usedma = 0; | ||
742 | |||
743 | /* Scan to find existence of the device */ | ||
744 | if (nand_scan_ident(mtd, 2, NULL)) { | ||
745 | err = -ENXIO; | ||
746 | goto out_irq; | ||
747 | } | ||
748 | |||
749 | cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, | ||
750 | 2112 + sizeof(struct nand_buffers) + | ||
751 | mtd->writesize + mtd->oobsize, | ||
752 | &cafe->dmaaddr, GFP_KERNEL); | ||
753 | if (!cafe->dmabuf) { | ||
754 | err = -ENOMEM; | ||
755 | goto out_irq; | ||
756 | } | ||
757 | cafe->nand.buffers = nbuf = (void *)cafe->dmabuf + 2112; | ||
758 | |||
738 | /* Set up DMA address */ | 759 | /* Set up DMA address */ |
739 | cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0); | 760 | cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0); |
740 | if (sizeof(cafe->dmaaddr) > 4) | 761 | if (sizeof(cafe->dmaaddr) > 4) |
@@ -746,16 +767,13 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
746 | cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n", | 767 | cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n", |
747 | cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf); | 768 | cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf); |
748 | 769 | ||
749 | /* Enable NAND IRQ in global IRQ mask register */ | 770 | /* this driver does not need the @ecccalc and @ecccode */ |
750 | cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK); | 771 | nbuf->ecccalc = NULL; |
751 | cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n", | 772 | nbuf->ecccode = NULL; |
752 | cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK)); | 773 | nbuf->databuf = (uint8_t *)(nbuf + 1); |
753 | 774 | ||
754 | /* Scan to find existence of the device */ | 775 | /* Restore the DMA flag */ |
755 | if (nand_scan_ident(mtd, 2, NULL)) { | 776 | usedma = old_dma; |
756 | err = -ENXIO; | ||
757 | goto out_irq; | ||
758 | } | ||
759 | 777 | ||
760 | cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */ | 778 | cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */ |
761 | if (mtd->writesize == 2048) | 779 | if (mtd->writesize == 2048) |
@@ -773,7 +791,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
773 | } else { | 791 | } else { |
774 | printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n", | 792 | printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n", |
775 | mtd->writesize); | 793 | mtd->writesize); |
776 | goto out_irq; | 794 | goto out_free_dma; |
777 | } | 795 | } |
778 | cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME; | 796 | cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME; |
779 | cafe->nand.ecc.size = mtd->writesize; | 797 | cafe->nand.ecc.size = mtd->writesize; |
@@ -790,7 +808,7 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
790 | 808 | ||
791 | err = nand_scan_tail(mtd); | 809 | err = nand_scan_tail(mtd); |
792 | if (err) | 810 | if (err) |
793 | goto out_irq; | 811 | goto out_free_dma; |
794 | 812 | ||
795 | pci_set_drvdata(pdev, mtd); | 813 | pci_set_drvdata(pdev, mtd); |
796 | 814 | ||
@@ -799,12 +817,15 @@ static int cafe_nand_probe(struct pci_dev *pdev, | |||
799 | 817 | ||
800 | goto out; | 818 | goto out; |
801 | 819 | ||
820 | out_free_dma: | ||
821 | dma_free_coherent(&cafe->pdev->dev, | ||
822 | 2112 + sizeof(struct nand_buffers) + | ||
823 | mtd->writesize + mtd->oobsize, | ||
824 | cafe->dmabuf, cafe->dmaaddr); | ||
802 | out_irq: | 825 | out_irq: |
803 | /* Disable NAND IRQ in global IRQ mask register */ | 826 | /* Disable NAND IRQ in global IRQ mask register */ |
804 | cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); | 827 | cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK); |
805 | free_irq(pdev->irq, mtd); | 828 | free_irq(pdev->irq, mtd); |
806 | out_free_dma: | ||
807 | dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr); | ||
808 | out_ior: | 829 | out_ior: |
809 | pci_iounmap(pdev, cafe->mmio); | 830 | pci_iounmap(pdev, cafe->mmio); |
810 | out_free_mtd: | 831 | out_free_mtd: |
@@ -824,7 +845,10 @@ static void cafe_nand_remove(struct pci_dev *pdev) | |||
824 | nand_release(mtd); | 845 | nand_release(mtd); |
825 | free_rs(cafe->rs); | 846 | free_rs(cafe->rs); |
826 | pci_iounmap(pdev, cafe->mmio); | 847 | pci_iounmap(pdev, cafe->mmio); |
827 | dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr); | 848 | dma_free_coherent(&cafe->pdev->dev, |
849 | 2112 + sizeof(struct nand_buffers) + | ||
850 | mtd->writesize + mtd->oobsize, | ||
851 | cafe->dmabuf, cafe->dmaaddr); | ||
828 | kfree(mtd); | 852 | kfree(mtd); |
829 | } | 853 | } |
830 | 854 | ||