diff options
Diffstat (limited to 'drivers/mtd/nand/cafe_nand.c')
| -rw-r--r-- | drivers/mtd/nand/cafe_nand.c | 94 |
1 files changed, 55 insertions, 39 deletions
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index 2bb7170502c..4e66726da9a 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c @@ -303,13 +303,7 @@ static void cafe_nand_cmdfunc(struct mtd_info *mtd, unsigned command, case NAND_CMD_SEQIN: case NAND_CMD_RNDIN: case NAND_CMD_STATUS: - case NAND_CMD_DEPLETE1: case NAND_CMD_RNDOUT: - case NAND_CMD_STATUS_ERROR: - case NAND_CMD_STATUS_ERROR0: - case NAND_CMD_STATUS_ERROR1: - case NAND_CMD_STATUS_ERROR2: - case NAND_CMD_STATUS_ERROR3: cafe_writel(cafe, cafe->ctl2, NAND_CTRL2); return; } @@ -536,8 +530,8 @@ static int cafe_nand_write_page_lowlevel(struct mtd_info *mtd, } static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int oob_required, int page, - int cached, int raw) + uint32_t offset, int data_len, const uint8_t *buf, + int oob_required, int page, int cached, int raw) { int status; @@ -585,7 +579,7 @@ static int cafe_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) } /* F_2[X]/(X**6+X+1) */ -static unsigned short __devinit gf64_mul(u8 a, u8 b) +static unsigned short gf64_mul(u8 a, u8 b) { u8 c; unsigned int i; @@ -604,7 +598,7 @@ static unsigned short __devinit gf64_mul(u8 a, u8 b) } /* F_64[X]/(X**2+X+A**-1) with A the generator of F_64[X] */ -static u16 __devinit gf4096_mul(u16 a, u16 b) +static u16 gf4096_mul(u16 a, u16 b) { u8 ah, al, bh, bl, ch, cl; @@ -619,20 +613,22 @@ static u16 __devinit gf4096_mul(u16 a, u16 b) return (ch << 6) ^ cl; } -static int __devinit cafe_mul(int x) +static int cafe_mul(int x) { if (x == 0) return 1; return gf4096_mul(x, 0xe01); } -static int __devinit cafe_nand_probe(struct pci_dev *pdev, +static int cafe_nand_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct mtd_info *mtd; 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... */ @@ -646,10 +642,8 @@ static int __devinit 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; @@ -663,13 +657,6 @@ static int __devinit 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) { @@ -729,7 +716,7 @@ static int __devinit 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 */ @@ -743,6 +730,32 @@ static int __devinit 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) @@ -754,16 +767,13 @@ static int __devinit 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) @@ -781,7 +791,7 @@ static int __devinit 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; @@ -798,7 +808,7 @@ static int __devinit 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); @@ -807,12 +817,15 @@ static int __devinit 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: @@ -821,7 +834,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev, return err; } -static void __devexit cafe_nand_remove(struct pci_dev *pdev) +static void cafe_nand_remove(struct pci_dev *pdev) { struct mtd_info *mtd = pci_get_drvdata(pdev); struct cafe_priv *cafe = mtd->priv; @@ -832,7 +845,10 @@ static void __devexit 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); } @@ -887,7 +903,7 @@ static struct pci_driver cafe_nand_pci_driver = { .name = "CAFÉ NAND", .id_table = cafe_nand_tbl, .probe = cafe_nand_probe, - .remove = __devexit_p(cafe_nand_remove), + .remove = cafe_nand_remove, .resume = cafe_nand_resume, }; |
