diff options
Diffstat (limited to 'drivers/mtd/nand/cafe_nand.c')
| -rw-r--r-- | drivers/mtd/nand/cafe_nand.c | 72 | 
1 files changed, 47 insertions, 25 deletions
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index c34985a5510..4e66726da9a 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,  	struct cafe_priv *cafe;  	uint32_t ctrl;  	int err = 0; +	int old_dma; +	struct nand_buffers *nbuf;  	/* Very old versions shared the same PCI ident for all three  	   functions on the chip. Verify the class too... */ @@ -640,10 +642,8 @@ static int cafe_nand_probe(struct pci_dev *pdev,  	pci_set_master(pdev);  	mtd = kzalloc(sizeof(*mtd) + sizeof(struct cafe_priv), GFP_KERNEL); -	if (!mtd) { -		dev_warn(&pdev->dev, "failed to alloc mtd_info\n"); +	if (!mtd)  		return  -ENOMEM; -	}  	cafe = (void *)(&mtd[1]);  	mtd->dev.parent = &pdev->dev; @@ -657,13 +657,6 @@ static int cafe_nand_probe(struct pci_dev *pdev,  		err = -ENOMEM;  		goto out_free_mtd;  	} -	cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112 + sizeof(struct nand_buffers), -					  &cafe->dmaaddr, GFP_KERNEL); -	if (!cafe->dmabuf) { -		err = -ENOMEM; -		goto out_ior; -	} -	cafe->nand.buffers = (void *)cafe->dmabuf + 2112;  	cafe->rs = init_rs_non_canonical(12, &cafe_mul, 0, 1, 8);  	if (!cafe->rs) { @@ -723,7 +716,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,  			  "CAFE NAND", mtd);  	if (err) {  		dev_warn(&pdev->dev, "Could not register IRQ %d\n", pdev->irq); -		goto out_free_dma; +		goto out_ior;  	}  	/* Disable master reset, enable NAND clock */ @@ -737,6 +730,32 @@ static int cafe_nand_probe(struct pci_dev *pdev,  	cafe_writel(cafe, 0x7006, GLOBAL_CTRL);  	cafe_writel(cafe, 0x700a, GLOBAL_CTRL); +	/* Enable NAND IRQ in global IRQ mask register */ +	cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK); +	cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n", +		cafe_readl(cafe, GLOBAL_CTRL), +		cafe_readl(cafe, GLOBAL_IRQ_MASK)); + +	/* Do not use the DMA for the nand_scan_ident() */ +	old_dma = usedma; +	usedma = 0; + +	/* Scan to find existence of the device */ +	if (nand_scan_ident(mtd, 2, NULL)) { +		err = -ENXIO; +		goto out_irq; +	} + +	cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, +				2112 + sizeof(struct nand_buffers) + +				mtd->writesize + mtd->oobsize, +				&cafe->dmaaddr, GFP_KERNEL); +	if (!cafe->dmabuf) { +		err = -ENOMEM; +		goto out_irq; +	} +	cafe->nand.buffers = nbuf = (void *)cafe->dmabuf + 2112; +  	/* Set up DMA address */  	cafe_writel(cafe, cafe->dmaaddr & 0xffffffff, NAND_DMA_ADDR0);  	if (sizeof(cafe->dmaaddr) > 4) @@ -748,16 +767,13 @@ static int cafe_nand_probe(struct pci_dev *pdev,  	cafe_dev_dbg(&cafe->pdev->dev, "Set DMA address to %x (virt %p)\n",  		cafe_readl(cafe, NAND_DMA_ADDR0), cafe->dmabuf); -	/* Enable NAND IRQ in global IRQ mask register */ -	cafe_writel(cafe, 0x80000007, GLOBAL_IRQ_MASK); -	cafe_dev_dbg(&cafe->pdev->dev, "Control %x, IRQ mask %x\n", -		cafe_readl(cafe, GLOBAL_CTRL), cafe_readl(cafe, GLOBAL_IRQ_MASK)); +	/* this driver does not need the @ecccalc and @ecccode */ +	nbuf->ecccalc = NULL; +	nbuf->ecccode = NULL; +	nbuf->databuf = (uint8_t *)(nbuf + 1); -	/* Scan to find existence of the device */ -	if (nand_scan_ident(mtd, 2, NULL)) { -		err = -ENXIO; -		goto out_irq; -	} +	/* Restore the DMA flag */ +	usedma = old_dma;  	cafe->ctl2 = 1<<27; /* Reed-Solomon ECC */  	if (mtd->writesize == 2048) @@ -775,7 +791,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,  	} else {  		printk(KERN_WARNING "Unexpected NAND flash writesize %d. Aborting\n",  		       mtd->writesize); -		goto out_irq; +		goto out_free_dma;  	}  	cafe->nand.ecc.mode = NAND_ECC_HW_SYNDROME;  	cafe->nand.ecc.size = mtd->writesize; @@ -792,7 +808,7 @@ static int cafe_nand_probe(struct pci_dev *pdev,  	err = nand_scan_tail(mtd);  	if (err) -		goto out_irq; +		goto out_free_dma;  	pci_set_drvdata(pdev, mtd); @@ -801,12 +817,15 @@ static int cafe_nand_probe(struct pci_dev *pdev,  	goto out; + out_free_dma: +	dma_free_coherent(&cafe->pdev->dev, +			2112 + sizeof(struct nand_buffers) + +			mtd->writesize + mtd->oobsize, +			cafe->dmabuf, cafe->dmaaddr);   out_irq:  	/* Disable NAND IRQ in global IRQ mask register */  	cafe_writel(cafe, ~1 & cafe_readl(cafe, GLOBAL_IRQ_MASK), GLOBAL_IRQ_MASK);  	free_irq(pdev->irq, mtd); - out_free_dma: -	dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr);   out_ior:  	pci_iounmap(pdev, cafe->mmio);   out_free_mtd: @@ -826,7 +845,10 @@ static void cafe_nand_remove(struct pci_dev *pdev)  	nand_release(mtd);  	free_rs(cafe->rs);  	pci_iounmap(pdev, cafe->mmio); -	dma_free_coherent(&cafe->pdev->dev, 2112, cafe->dmabuf, cafe->dmaaddr); +	dma_free_coherent(&cafe->pdev->dev, +			2112 + sizeof(struct nand_buffers) + +			mtd->writesize + mtd->oobsize, +			cafe->dmabuf, cafe->dmaaddr);  	kfree(mtd);  }  | 
