diff options
Diffstat (limited to 'drivers/mtd/nand')
50 files changed, 2651 insertions, 1974 deletions
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index d88529841d3..f1cf503517f 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -95,44 +95,16 @@ config MTD_NAND_OMAP2 platforms. config MTD_NAND_OMAP_BCH - depends on MTD_NAND && MTD_NAND_OMAP2 && ARCH_OMAP3 - tristate "Enable support for hardware BCH error correction" + depends on MTD_NAND_OMAP2 + tristate "Support hardware based BCH error correction" default n select BCH - select BCH_CONST_PARAMS help - Support for hardware BCH error correction. - -choice - prompt "BCH error correction capability" - depends on MTD_NAND_OMAP_BCH - -config MTD_NAND_OMAP_BCH8 - bool "8 bits / 512 bytes (recommended)" - help - Support correcting up to 8 bitflips per 512-byte block. - This will use 13 bytes of spare area per 512 bytes of page data. - This is the recommended mode, as 4-bit mode does not work - on some OMAP3 revisions, due to a hardware bug. - -config MTD_NAND_OMAP_BCH4 - bool "4 bits / 512 bytes" - help - Support correcting up to 4 bitflips per 512-byte block. - This will use 7 bytes of spare area per 512 bytes of page data. - Note that this mode does not work on some OMAP3 revisions, due to a - hardware bug. Please check your OMAP datasheet before selecting this - mode. - -endchoice - -if MTD_NAND_OMAP_BCH -config BCH_CONST_M - default 13 -config BCH_CONST_T - default 4 if MTD_NAND_OMAP_BCH4 - default 8 if MTD_NAND_OMAP_BCH8 -endif + This config enables the ELM hardware engine, which can be used to + locate and correct errors when using BCH ECC scheme. This offloads + the cpu from doing ECC error searching and correction. However some + legacy OMAP families like OMAP2xxx, OMAP3xxx do not have ELM engine + so they should not enable this config symbol. config MTD_NAND_IDS tristate @@ -354,11 +326,11 @@ config MTD_NAND_ATMEL on Atmel AT91 and AVR32 processors. config MTD_NAND_PXA3xx - tristate "Support for NAND flash devices on PXA3xx" + tristate "NAND support on PXA3xx and Armada 370/XP" depends on PXA3xx || ARCH_MMP || PLAT_ORION help This enables the driver for the NAND flash device found on - PXA3xx processors + PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2). config MTD_NAND_SLC_LPC32XX tristate "NXP LPC32xx SLC Controller" @@ -456,6 +428,7 @@ config MTD_NAND_FSL_IFC tristate "NAND support for Freescale IFC controller" depends on MTD_NAND && FSL_SOC select FSL_IFC + select MEMORY help Various Freescale chips e.g P1010, include a NAND Flash machine with built-in hardware ECC capabilities. @@ -486,17 +459,19 @@ config MTD_NAND_MXC config MTD_NAND_SH_FLCTL tristate "Support for NAND on Renesas SuperH FLCTL" - depends on SUPERH || ARCH_SHMOBILE + depends on SUPERH || ARCH_SHMOBILE || COMPILE_TEST + depends on HAS_IOMEM + depends on HAS_DMA help Several Renesas SuperH CPU has FLCTL. This option enables support for NAND Flash using FLCTL. config MTD_NAND_DAVINCI - tristate "Support NAND on DaVinci SoC" - depends on ARCH_DAVINCI + tristate "Support NAND on DaVinci/Keystone SoC" + depends on ARCH_DAVINCI || (ARCH_KEYSTONE && TI_AEMIF) help Enable the driver for NAND flash chips on Texas Instruments - DaVinci processors. + DaVinci/Keystone processors. config MTD_NAND_TXX9NDFMC tristate "NAND Flash support for TXx9 SoC" diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index 8611eb4b45f..4936e9e0002 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c @@ -17,7 +17,6 @@ */ #include <linux/slab.h> -#include <linux/init.h> #include <linux/module.h> #include <linux/delay.h> #include <linux/mtd/mtd.h> diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index 060feeaf6b3..4ce181a35bc 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -375,8 +375,7 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len, dma_dev = host->dma_chan->device; - flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP | - DMA_COMPL_SKIP_DEST_UNMAP; + flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; phys_addr = dma_map_single(dma_dev->dev, p, len, dir); if (dma_mapping_error(dma_dev->dev, phys_addr)) { @@ -431,7 +430,7 @@ err_dma: dma_unmap_single(dma_dev->dev, phys_addr, len, dir); err_buf: if (err != 0) - dev_warn(host->dev, "Fall back to CPU I/O\n"); + dev_dbg(host->dev, "Fall back to CPU I/O\n"); return err; } @@ -1062,56 +1061,28 @@ static void atmel_pmecc_core_init(struct mtd_info *mtd) } /* - * Get ECC requirement in ONFI parameters, returns -1 if ONFI - * parameters is not supported. - * return 0 if success to get the ECC requirement. - */ -static int get_onfi_ecc_param(struct nand_chip *chip, - int *ecc_bits, int *sector_size) -{ - *ecc_bits = *sector_size = 0; - - if (chip->onfi_params.ecc_bits == 0xff) - /* TODO: the sector_size and ecc_bits need to be find in - * extended ecc parameter, currently we don't support it. - */ - return -1; - - *ecc_bits = chip->onfi_params.ecc_bits; - - /* The default sector size (ecc codeword size) is 512 */ - *sector_size = 512; - - return 0; -} - -/* - * Get ecc requirement from ONFI parameters ecc requirement. + * Get minimum ecc requirements from NAND. * If pmecc-cap, pmecc-sector-size in DTS are not specified, this function - * will set them according to ONFI ecc requirement. Otherwise, use the + * will set them according to minimum ecc requirement. Otherwise, use the * value in DTS file. * return 0 if success. otherwise return error code. */ static int pmecc_choose_ecc(struct atmel_nand_host *host, int *cap, int *sector_size) { - /* Get ECC requirement from ONFI parameters */ - *cap = *sector_size = 0; - if (host->nand_chip.onfi_version) { - if (!get_onfi_ecc_param(&host->nand_chip, cap, sector_size)) - dev_info(host->dev, "ONFI params, minimum required ECC: %d bits in %d bytes\n", + /* Get minimum ECC requirements */ + if (host->nand_chip.ecc_strength_ds) { + *cap = host->nand_chip.ecc_strength_ds; + *sector_size = host->nand_chip.ecc_step_ds; + dev_info(host->dev, "minimum ECC: %d bits in %d bytes\n", *cap, *sector_size); - else - dev_info(host->dev, "NAND chip ECC reqirement is in Extended ONFI parameter, we don't support yet.\n"); } else { - dev_info(host->dev, "NAND chip is not ONFI compliant, assume ecc_bits is 2 in 512 bytes"); - } - if (*cap == 0 && *sector_size == 0) { *cap = 2; *sector_size = 512; + dev_info(host->dev, "can't detect min. ECC, assume 2 bits in 512 bytes\n"); } - /* If dts file doesn't specify then use the one in ONFI parameters */ + /* If device tree doesn't specify, use NAND's minimum ECC parameters */ if (host->pmecc_corr_cap == 0) { /* use the most fitable ecc bits (the near bigger one ) */ if (*cap <= 2) @@ -1139,7 +1110,7 @@ static int pmecc_choose_ecc(struct atmel_nand_host *host, return 0; } -static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev, +static int atmel_pmecc_nand_init_params(struct platform_device *pdev, struct atmel_nand_host *host) { struct mtd_info *mtd = &host->mtd; @@ -1249,6 +1220,7 @@ static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev, goto err; } + nand_chip->options |= NAND_NO_SUBPAGE_WRITE; nand_chip->ecc.read_page = atmel_nand_pmecc_read_page; nand_chip->ecc.write_page = atmel_nand_pmecc_write_page; @@ -1449,7 +1421,6 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) ecc_writel(host->ecc, CR, ATMEL_ECC_RST); } -#if defined(CONFIG_OF) static int atmel_of_init_port(struct atmel_nand_host *host, struct device_node *np) { @@ -1457,7 +1428,7 @@ static int atmel_of_init_port(struct atmel_nand_host *host, u32 offset[2]; int ecc_mode; struct atmel_nand_data *board = &host->board; - enum of_gpio_flags flags; + enum of_gpio_flags flags = 0; if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) { if (val >= 32) { @@ -1540,15 +1511,8 @@ static int atmel_of_init_port(struct atmel_nand_host *host, return 0; } -#else -static int atmel_of_init_port(struct atmel_nand_host *host, - struct device_node *np) -{ - return -EINVAL; -} -#endif -static int __init atmel_hw_nand_init_params(struct platform_device *pdev, +static int atmel_hw_nand_init_params(struct platform_device *pdev, struct atmel_nand_host *host) { struct mtd_info *mtd = &host->mtd; @@ -1696,8 +1660,8 @@ static void nfc_select_chip(struct mtd_info *mtd, int chip) nfc_writel(host->nfc->hsmc_regs, CTRL, NFC_CTRL_ENABLE); } -static int nfc_make_addr(struct mtd_info *mtd, int column, int page_addr, - unsigned int *addr1234, unsigned int *cycle0) +static int nfc_make_addr(struct mtd_info *mtd, int command, int column, + int page_addr, unsigned int *addr1234, unsigned int *cycle0) { struct nand_chip *chip = mtd->priv; @@ -1711,7 +1675,8 @@ static int nfc_make_addr(struct mtd_info *mtd, int column, int page_addr, *addr1234 = 0; if (column != -1) { - if (chip->options & NAND_BUSWIDTH_16) + if (chip->options & NAND_BUSWIDTH_16 && + !nand_opcode_8bits(command)) column >>= 1; addr_bytes[acycle++] = column & 0xff; if (mtd->writesize > 512) @@ -1824,8 +1789,8 @@ static void nfc_nand_command(struct mtd_info *mtd, unsigned int command, } if (do_addr) - acycle = nfc_make_addr(mtd, column, page_addr, &addr1234, - &cycle0); + acycle = nfc_make_addr(mtd, command, column, page_addr, + &addr1234, &cycle0); nfc_addr_cmd = cmd1 | cmd2 | vcmd2 | acycle | csid | dataen | nfcwr; nfc_send_command(host, nfc_addr_cmd, addr1234, cycle0); @@ -1987,7 +1952,7 @@ static struct platform_driver atmel_nand_nfc_driver; /* * Probe for the NAND device. */ -static int __init atmel_nand_probe(struct platform_device *pdev) +static int atmel_nand_probe(struct platform_device *pdev) { struct atmel_nand_host *host; struct mtd_info *mtd; @@ -1998,10 +1963,8 @@ static int __init atmel_nand_probe(struct platform_device *pdev) /* Allocate memory for the device structure (and zero it) */ host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); - if (!host) { - printk(KERN_ERR "atmel_nand: failed to allocate device structure.\n"); + if (!host) return -ENOMEM; - } res = platform_driver_register(&atmel_nand_nfc_driver); if (res) @@ -2019,7 +1982,8 @@ static int __init atmel_nand_probe(struct platform_device *pdev) mtd = &host->mtd; nand_chip = &host->nand_chip; host->dev = &pdev->dev; - if (pdev->dev.of_node) { + if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) { + /* Only when CONFIG_OF is enabled of_node can be parsed */ res = atmel_of_init_port(host, pdev->dev.of_node); if (res) goto err_nand_ioremap; @@ -2098,14 +2062,14 @@ static int __init atmel_nand_probe(struct platform_device *pdev) } if (gpio_get_value(host->board.det_pin)) { - printk(KERN_INFO "No SmartMedia card inserted.\n"); + dev_info(&pdev->dev, "No SmartMedia card inserted.\n"); res = -ENXIO; goto err_no_card; } } if (host->board.on_flash_bbt || on_flash_bbt) { - printk(KERN_INFO "atmel_nand: Use On Flash BBT\n"); + dev_info(&pdev->dev, "Use On Flash BBT\n"); nand_chip->bbt_options |= NAND_BBT_USE_FLASH; } @@ -2177,14 +2141,13 @@ err_no_card: if (host->dma_chan) dma_release_channel(host->dma_chan); err_nand_ioremap: - platform_driver_unregister(&atmel_nand_nfc_driver); return res; } /* * Remove a NAND device. */ -static int __exit atmel_nand_remove(struct platform_device *pdev) +static int atmel_nand_remove(struct platform_device *pdev) { struct atmel_nand_host *host = platform_get_drvdata(pdev); struct mtd_info *mtd = &host->mtd; @@ -2207,14 +2170,12 @@ static int __exit atmel_nand_remove(struct platform_device *pdev) return 0; } -#if defined(CONFIG_OF) static const struct of_device_id atmel_nand_dt_ids[] = { { .compatible = "atmel,at91rm9200-nand" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, atmel_nand_dt_ids); -#endif static int atmel_nand_nfc_probe(struct platform_device *pdev) { @@ -2253,12 +2214,11 @@ static int atmel_nand_nfc_probe(struct platform_device *pdev) return 0; } -#if defined(CONFIG_OF) -static struct of_device_id atmel_nand_nfc_match[] = { +static const struct of_device_id atmel_nand_nfc_match[] = { { .compatible = "atmel,sama5d3-nfc" }, { /* sentinel */ } }; -#endif +MODULE_DEVICE_TABLE(of, atmel_nand_nfc_match); static struct platform_driver atmel_nand_nfc_driver = { .driver = { @@ -2270,7 +2230,8 @@ static struct platform_driver atmel_nand_nfc_driver = { }; static struct platform_driver atmel_nand_driver = { - .remove = __exit_p(atmel_nand_remove), + .probe = atmel_nand_probe, + .remove = atmel_nand_remove, .driver = { .name = "atmel_nand", .owner = THIS_MODULE, @@ -2278,7 +2239,7 @@ static struct platform_driver atmel_nand_driver = { }, }; -module_platform_driver_probe(atmel_nand_driver, atmel_nand_probe); +module_platform_driver(atmel_nand_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Rick Bronson"); diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index ae8dd7c4103..bc5c518828d 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -11,7 +11,6 @@ #include <linux/slab.h> #include <linux/gpio.h> -#include <linux/init.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/mtd/mtd.h> @@ -308,7 +307,8 @@ static void au1550_command(struct mtd_info *mtd, unsigned command, int column, i /* Serially input address */ if (column != -1) { /* Adjust columns for 16 bit buswidth */ - if (this->options & NAND_BUSWIDTH_16) + if (this->options & NAND_BUSWIDTH_16 && + !nand_opcode_8bits(command)) column >>= 1; ctx->write_byte(mtd, column); } @@ -418,10 +418,8 @@ static int au1550nd_probe(struct platform_device *pdev) } ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) { - dev_err(&pdev->dev, "no memory for NAND context\n"); + if (!ctx) return -ENOMEM; - } r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { @@ -480,6 +478,8 @@ static int au1550nd_probe(struct platform_device *pdev) mtd_device_register(&ctx->info, pd->parts, pd->num_parts); + platform_set_drvdata(pdev, ctx); + return 0; out3: diff --git a/drivers/mtd/nand/bcm47xxnflash/main.c b/drivers/mtd/nand/bcm47xxnflash/main.c index 7bae569fdc7..10744591131 100644 --- a/drivers/mtd/nand/bcm47xxnflash/main.c +++ b/drivers/mtd/nand/bcm47xxnflash/main.c @@ -29,11 +29,9 @@ static int bcm47xxnflash_probe(struct platform_device *pdev) struct bcm47xxnflash *b47n; int err = 0; - b47n = kzalloc(sizeof(*b47n), GFP_KERNEL); - if (!b47n) { - err = -ENOMEM; - goto out; - } + b47n = devm_kzalloc(&pdev->dev, sizeof(*b47n), GFP_KERNEL); + if (!b47n) + return -ENOMEM; b47n->nand_chip.priv = b47n; b47n->mtd.owner = THIS_MODULE; @@ -48,22 +46,16 @@ static int bcm47xxnflash_probe(struct platform_device *pdev) } if (err) { pr_err("Initialization failed: %d\n", err); - goto err_init; + return err; } err = mtd_device_parse_register(&b47n->mtd, probes, NULL, NULL, 0); if (err) { pr_err("Failed to register MTD device: %d\n", err); - goto err_dev_reg; + return err; } return 0; - -err_dev_reg: -err_init: - kfree(b47n); -out: - return err; } static int bcm47xxnflash_remove(struct platform_device *pdev) @@ -85,22 +77,4 @@ static struct platform_driver bcm47xxnflash_driver = { }, }; -static int __init bcm47xxnflash_init(void) -{ - int err; - - err = platform_driver_register(&bcm47xxnflash_driver); - if (err) - pr_err("Failed to register bcm47xx nand flash driver: %d\n", - err); - - return err; -} - -static void __exit bcm47xxnflash_exit(void) -{ - platform_driver_unregister(&bcm47xxnflash_driver); -} - -module_init(bcm47xxnflash_init); -module_exit(bcm47xxnflash_exit); +module_platform_driver(bcm47xxnflash_driver); diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 2c42e125720..722898aea7a 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c @@ -37,7 +37,6 @@ #include <linux/module.h> #include <linux/types.h> -#include <linux/init.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/ioport.h> @@ -680,9 +679,6 @@ static int bf5xx_nand_remove(struct platform_device *pdev) peripheral_free_list(bfin_nfc_pin_req); bf5xx_nand_dma_remove(info); - /* free the common resources */ - kfree(info); - return 0; } @@ -743,11 +739,10 @@ static int bf5xx_nand_probe(struct platform_device *pdev) return -EFAULT; } - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (info == NULL) { - dev_err(&pdev->dev, "no memory for flash info\n"); err = -ENOMEM; - goto out_err_kzalloc; + goto out_err; } platform_set_drvdata(pdev, info); @@ -792,7 +787,7 @@ static int bf5xx_nand_probe(struct platform_device *pdev) /* initialise the hardware */ err = bf5xx_nand_hw_init(info); if (err) - goto out_err_hw_init; + goto out_err; /* setup hardware ECC data struct */ if (hardware_ecc) { @@ -829,9 +824,7 @@ static int bf5xx_nand_probe(struct platform_device *pdev) out_err_nand_scan: bf5xx_nand_dma_remove(info); -out_err_hw_init: - kfree(info); -out_err_kzalloc: +out_err: peripheral_free_list(bfin_nfc_pin_req); return err; 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); } diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c index 39b2ef84881..66ec95e6ca6 100644 --- a/drivers/mtd/nand/cmx270_nand.c +++ b/drivers/mtd/nand/cmx270_nand.c @@ -164,7 +164,6 @@ static int __init cmx270_init(void) sizeof(struct nand_chip), GFP_KERNEL); if (!cmx270_nand_mtd) { - pr_debug("Unable to allocate CM-X270 NAND MTD device structure.\n"); ret = -ENOMEM; goto err_kzalloc; } diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index d469a9a1dea..88109d375ae 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c @@ -199,7 +199,6 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) /* Allocate memory for MTD device structure and private data */ new_mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); if (!new_mtd) { - printk(KERN_WARNING "Unable to allocate CS553X NAND MTD device structure.\n"); err = -ENOMEM; goto out; } diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index b77a01efb48..b922c8efcf4 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c @@ -24,7 +24,6 @@ */ #include <linux/kernel.h> -#include <linux/init.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/err.h> @@ -35,6 +34,7 @@ #include <linux/slab.h> #include <linux/of_device.h> #include <linux/of.h> +#include <linux/of_mtd.h> #include <linux/platform_data/mtd-davinci.h> #include <linux/platform_data/mtd-davinci-aemif.h> @@ -487,7 +487,7 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd) * ten ECC bytes plus the manufacturer's bad block marker byte, and * and not overlapping the default BBT markers. */ -static struct nand_ecclayout hwecc4_small __initconst = { +static struct nand_ecclayout hwecc4_small = { .eccbytes = 10, .eccpos = { 0, 1, 2, 3, 4, /* offset 5 holds the badblock marker */ @@ -503,7 +503,7 @@ static struct nand_ecclayout hwecc4_small __initconst = { * storing ten ECC bytes plus the manufacturer's bad block marker byte, * and not overlapping the default BBT markers. */ -static struct nand_ecclayout hwecc4_2048 __initconst = { +static struct nand_ecclayout hwecc4_2048 = { .eccbytes = 40, .eccpos = { /* at the end of spare sector */ @@ -523,6 +523,7 @@ static struct nand_ecclayout hwecc4_2048 __initconst = { #if defined(CONFIG_OF) static const struct of_device_id davinci_nand_of_match[] = { {.compatible = "ti,davinci-nand", }, + {.compatible = "ti,keystone-nand", }, {}, }; MODULE_DEVICE_TABLE(of, davinci_nand_of_match); @@ -534,17 +535,19 @@ static struct davinci_nand_pdata struct davinci_nand_pdata *pdata; const char *mode; u32 prop; - int len; pdata = devm_kzalloc(&pdev->dev, sizeof(struct davinci_nand_pdata), GFP_KERNEL); pdev->dev.platform_data = pdata; if (!pdata) - return NULL; + return ERR_PTR(-ENOMEM); if (!of_property_read_u32(pdev->dev.of_node, "ti,davinci-chipselect", &prop)) pdev->id = prop; + else + return ERR_PTR(-EINVAL); + if (!of_property_read_u32(pdev->dev.of_node, "ti,davinci-mask-ale", &prop)) pdata->mask_ale = prop; @@ -555,6 +558,8 @@ static struct davinci_nand_pdata "ti,davinci-mask-chipsel", &prop)) pdata->mask_chipsel = prop; if (!of_property_read_string(pdev->dev.of_node, + "nand-ecc-mode", &mode) || + !of_property_read_string(pdev->dev.of_node, "ti,davinci-ecc-mode", &mode)) { if (!strncmp("none", mode, 4)) pdata->ecc_mode = NAND_ECC_NONE; @@ -566,13 +571,22 @@ static struct davinci_nand_pdata if (!of_property_read_u32(pdev->dev.of_node, "ti,davinci-ecc-bits", &prop)) pdata->ecc_bits = prop; - if (!of_property_read_u32(pdev->dev.of_node, + + prop = of_get_nand_bus_width(pdev->dev.of_node); + if (0 < prop || !of_property_read_u32(pdev->dev.of_node, "ti,davinci-nand-buswidth", &prop)) if (prop == 16) pdata->options |= NAND_BUSWIDTH_16; - if (of_find_property(pdev->dev.of_node, - "ti,davinci-nand-use-bbt", &len)) + if (of_property_read_bool(pdev->dev.of_node, + "nand-on-flash-bbt") || + of_property_read_bool(pdev->dev.of_node, + "ti,davinci-nand-use-bbt")) pdata->bbt_options = NAND_BBT_USE_FLASH; + + if (of_device_is_compatible(pdev->dev.of_node, + "ti,keystone-nand")) { + pdata->options |= NAND_NO_SUBPAGE_WRITE; + } } return dev_get_platdata(&pdev->dev); @@ -585,7 +599,7 @@ static struct davinci_nand_pdata } #endif -static int __init nand_davinci_probe(struct platform_device *pdev) +static int nand_davinci_probe(struct platform_device *pdev) { struct davinci_nand_pdata *pdata; struct davinci_nand_info *info; @@ -598,6 +612,9 @@ static int __init nand_davinci_probe(struct platform_device *pdev) nand_ecc_modes_t ecc_mode; pdata = nand_davinci_get_pdata(pdev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + /* insist on board-specific configuration */ if (!pdata) return -ENODEV; @@ -607,11 +624,8 @@ static int __init nand_davinci_probe(struct platform_device *pdev) return -ENODEV; info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); - if (!info) { - dev_err(&pdev->dev, "unable to allocate memory\n"); - ret = -ENOMEM; - goto err_nomem; - } + if (!info) + return -ENOMEM; platform_set_drvdata(pdev, info); @@ -619,19 +633,23 @@ static int __init nand_davinci_probe(struct platform_device *pdev) res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (!res1 || !res2) { dev_err(&pdev->dev, "resource missing\n"); - ret = -EINVAL; - goto err_nomem; + return -EINVAL; } vaddr = devm_ioremap_resource(&pdev->dev, res1); - if (IS_ERR(vaddr)) { - ret = PTR_ERR(vaddr); - goto err_ioremap; - } - base = devm_ioremap_resource(&pdev->dev, res2); - if (IS_ERR(base)) { - ret = PTR_ERR(base); - goto err_ioremap; + if (IS_ERR(vaddr)) + return PTR_ERR(vaddr); + + /* + * This registers range is used to setup NAND settings. In case with + * TI AEMIF driver, the same memory address range is requested already + * by AEMIF, so we cannot request it twice, just ioremap. + * The AEMIF and NAND drivers not use the same registers in this range. + */ + base = devm_ioremap(&pdev->dev, res2->start, resource_size(res2)); + if (!base) { + dev_err(&pdev->dev, "ioremap failed for resource %pR\n", res2); + return -EADDRNOTAVAIL; } info->dev = &pdev->dev; @@ -699,7 +717,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) spin_unlock_irq(&davinci_nand_lock); if (ret == -EBUSY) - goto err_ecc; + return ret; info->chip.ecc.calculate = nand_davinci_calculate_4bit; info->chip.ecc.correct = nand_davinci_correct_4bit; @@ -715,8 +733,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) info->chip.ecc.strength = pdata->ecc_bits; break; default: - ret = -EINVAL; - goto err_ecc; + return -EINVAL; } info->chip.ecc.mode = ecc_mode; @@ -724,7 +741,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) if (IS_ERR(info->clk)) { ret = PTR_ERR(info->clk); dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret); - goto err_clk; + return ret; } ret = clk_prepare_enable(info->clk); @@ -734,28 +751,6 @@ static int __init nand_davinci_probe(struct platform_device *pdev) goto err_clk_enable; } - /* - * Setup Async configuration register in case we did not boot from - * NAND and so bootloader did not bother to set it up. - */ - val = davinci_nand_readl(info, A1CR_OFFSET + info->core_chipsel * 4); - - /* Extended Wait is not valid and Select Strobe mode is not used */ - val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK); - if (info->chip.options & NAND_BUSWIDTH_16) - val |= 0x1; - - davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val); - - ret = 0; - if (info->timing) - ret = davinci_aemif_setup_timing(info->timing, info->base, - info->core_chipsel); - if (ret < 0) { - dev_dbg(&pdev->dev, "NAND timing values setup fail\n"); - goto err_timing; - } - spin_lock_irq(&davinci_nand_lock); /* put CSxNAND into NAND mode */ @@ -769,7 +764,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) ret = nand_scan_ident(&info->mtd, pdata->mask_chipsel ? 2 : 1, NULL); if (ret < 0) { dev_dbg(&pdev->dev, "no NAND chip(s) found\n"); - goto err_scan; + goto err; } /* Update ECC layout if needed ... for 1-bit HW ECC, the default @@ -783,7 +778,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) if (!chunks || info->mtd.oobsize < 16) { dev_dbg(&pdev->dev, "too small\n"); ret = -EINVAL; - goto err_scan; + goto err; } /* For small page chips, preserve the manufacturer's @@ -814,7 +809,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev) dev_warn(&pdev->dev, "no 4-bit ECC support yet " "for 4KiB-page NAND\n"); ret = -EIO; - goto err_scan; + goto err; syndrome_done: info->chip.ecc.layout = &info->ecclayout; @@ -822,7 +817,7 @@ syndrome_done: ret = nand_scan_tail(&info->mtd); if (ret < 0) - goto err_scan; + goto err; if (pdata->parts) ret = mtd_device_parse_register(&info->mtd, NULL, NULL, @@ -835,7 +830,7 @@ syndrome_done: NULL, 0); } if (ret < 0) - goto err_scan; + goto err; val = davinci_nand_readl(info, NRCSR_OFFSET); dev_info(&pdev->dev, "controller rev. %d.%d\n", @@ -843,8 +838,7 @@ syndrome_done: return 0; -err_scan: -err_timing: +err: clk_disable_unprepare(info->clk); err_clk_enable: @@ -852,15 +846,10 @@ err_clk_enable: if (ecc_mode == NAND_ECC_HW_SYNDROME) ecc4_busy = false; spin_unlock_irq(&davinci_nand_lock); - -err_ecc: -err_clk: -err_ioremap: -err_nomem: return ret; } -static int __exit nand_davinci_remove(struct platform_device *pdev) +static int nand_davinci_remove(struct platform_device *pdev) { struct davinci_nand_info *info = platform_get_drvdata(pdev); @@ -877,7 +866,8 @@ static int __exit nand_davinci_remove(struct platform_device *pdev) } static struct platform_driver nand_davinci_driver = { - .remove = __exit_p(nand_davinci_remove), + .probe = nand_davinci_probe, + .remove = nand_davinci_remove, .driver = { .name = "davinci_nand", .owner = THIS_MODULE, @@ -886,7 +876,7 @@ static struct platform_driver nand_davinci_driver = { }; MODULE_ALIAS("platform:davinci_nand"); -module_platform_driver_probe(nand_davinci_driver, nand_davinci_probe); +module_platform_driver(nand_davinci_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Texas Instruments"); diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 2ed2bb33a6e..9f2012a3e76 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -125,7 +125,6 @@ static void reset_buf(struct denali_nand_info *denali) static void write_byte_to_buf(struct denali_nand_info *denali, uint8_t byte) { - BUG_ON(denali->buf.tail >= sizeof(denali->buf.buf)); denali->buf.buf[denali->buf.tail++] = byte; } @@ -897,7 +896,7 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page) /* this function examines buffers to see if they contain data that * indicate that the buffer is part of an erased region of flash. */ -bool is_erased(uint8_t *buf, int len) +static bool is_erased(uint8_t *buf, int len) { int i = 0; for (i = 0; i < len; i++) @@ -1234,7 +1233,7 @@ static int denali_waitfunc(struct mtd_info *mtd, struct nand_chip *chip) return status; } -static void denali_erase(struct mtd_info *mtd, int page) +static int denali_erase(struct mtd_info *mtd, int page) { struct denali_nand_info *denali = mtd_to_denali(mtd); @@ -1251,8 +1250,7 @@ static void denali_erase(struct mtd_info *mtd, int page) irq_status = wait_for_irq(denali, INTR_STATUS__ERASE_COMP | INTR_STATUS__ERASE_FAIL); - denali->status = (irq_status & INTR_STATUS__ERASE_FAIL) ? - NAND_STATUS_FAIL : PASS; + return (irq_status & INTR_STATUS__ERASE_FAIL) ? NAND_STATUS_FAIL : PASS; } static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, @@ -1394,7 +1392,7 @@ static struct nand_bbt_descr bbt_mirror_descr = { }; /* initialize driver data structures */ -void denali_drv_init(struct denali_nand_info *denali) +static void denali_drv_init(struct denali_nand_info *denali) { denali->idx = 0; @@ -1429,20 +1427,12 @@ int denali_init(struct denali_nand_info *denali) } } - /* Is 32-bit DMA supported? */ - ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32)); - if (ret) { - pr_err("Spectra: no usable DMA configuration\n"); - return ret; - } - denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf, - DENALI_BUF_SIZE, - DMA_BIDIRECTIONAL); + /* allocate a temporary buffer for nand_scan_ident() */ + denali->buf.buf = devm_kzalloc(denali->dev, PAGE_SIZE, + GFP_DMA | GFP_KERNEL); + if (!denali->buf.buf) + return -ENOMEM; - if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) { - dev_err(denali->dev, "Spectra: failed to map DMA buffer\n"); - return -EIO; - } denali->mtd.dev.parent = denali->dev; denali_hw_init(denali); denali_drv_init(denali); @@ -1475,12 +1465,29 @@ int denali_init(struct denali_nand_info *denali) goto failed_req_irq; } - /* MTD supported page sizes vary by kernel. We validate our - * kernel supports the device here. - */ - if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) { - ret = -ENODEV; - pr_err("Spectra: device size not supported by this version of MTD."); + /* allocate the right size buffer now */ + devm_kfree(denali->dev, denali->buf.buf); + denali->buf.buf = devm_kzalloc(denali->dev, + denali->mtd.writesize + denali->mtd.oobsize, + GFP_KERNEL); + if (!denali->buf.buf) { + ret = -ENOMEM; + goto failed_req_irq; + } + + /* Is 32-bit DMA supported? */ + ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32)); + if (ret) { + pr_err("Spectra: no usable DMA configuration\n"); + goto failed_req_irq; + } + + denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf, + denali->mtd.writesize + denali->mtd.oobsize, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) { + dev_err(denali->dev, "Spectra: failed to map DMA buffer\n"); + ret = -EIO; goto failed_req_irq; } @@ -1520,7 +1527,7 @@ int denali_init(struct denali_nand_info *denali) * so just let controller do 15bit ECC for MLC and 8bit ECC for * SLC if possible. * */ - if (denali->nand.cellinfo & NAND_CI_CELLTYPE_MSK && + if (!nand_is_slc(&denali->nand) && (denali->mtd.oobsize > (denali->bbtskipbytes + ECC_15BITS * (denali->mtd.writesize / ECC_SECTOR_SIZE)))) { @@ -1576,7 +1583,7 @@ int denali_init(struct denali_nand_info *denali) denali->nand.ecc.write_page_raw = denali_write_page_raw; denali->nand.ecc.read_oob = denali_read_oob; denali->nand.ecc.write_oob = denali_write_oob; - denali->nand.erase_cmd = denali_erase; + denali->nand.erase = denali_erase; if (nand_scan_tail(&denali->mtd)) { ret = -ENXIO; @@ -1602,7 +1609,8 @@ EXPORT_SYMBOL(denali_init); void denali_remove(struct denali_nand_info *denali) { denali_irq_cleanup(denali->irq, denali); - dma_unmap_single(denali->dev, denali->buf.dma_buf, DENALI_BUF_SIZE, + dma_unmap_single(denali->dev, denali->buf.dma_buf, + denali->mtd.writesize + denali->mtd.oobsize, DMA_BIDIRECTIONAL); } EXPORT_SYMBOL(denali_remove); diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h index cec5712862c..96681746242 100644 --- a/drivers/mtd/nand/denali.h +++ b/drivers/mtd/nand/denali.h @@ -455,12 +455,10 @@ #define ECC_SECTOR_SIZE 512 -#define DENALI_BUF_SIZE (NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) - struct nand_buf { int head; int tail; - uint8_t buf[DENALI_BUF_SIZE]; + uint8_t *buf; dma_addr_t dma_buf; }; diff --git a/drivers/mtd/nand/denali_dt.c b/drivers/mtd/nand/denali_dt.c index 92530244e2c..35cb17f5780 100644 --- a/drivers/mtd/nand/denali_dt.c +++ b/drivers/mtd/nand/denali_dt.c @@ -30,24 +30,6 @@ struct denali_dt { struct clk *clk; }; -static void __iomem *request_and_map(struct device *dev, - const struct resource *res) -{ - void __iomem *ptr; - - if (!devm_request_mem_region(dev, res->start, resource_size(res), - "denali-dt")) { - dev_err(dev, "unable to request %s\n", res->name); - return NULL; - } - - ptr = devm_ioremap_nocache(dev, res->start, resource_size(res)); - if (!ptr) - dev_err(dev, "ioremap_nocache of %s failed!", res->name); - - return ptr; -} - static const struct of_device_id denali_nand_dt_ids[] = { { .compatible = "denali,denali-nand-dt" }, { /* sentinel */ } @@ -78,13 +60,6 @@ static int denali_dt_probe(struct platform_device *ofdev) return -ENOMEM; denali = &dt->denali; - denali_reg = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "denali_reg"); - nand_data = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "nand_data"); - if (!denali_reg || !nand_data) { - dev_err(&ofdev->dev, "resources not completely defined\n"); - return -EINVAL; - } - denali->platform = DT; denali->dev = &ofdev->dev; denali->irq = platform_get_irq(ofdev, 0); @@ -93,13 +68,15 @@ static int denali_dt_probe(struct platform_device *ofdev) return denali->irq; } - denali->flash_reg = request_and_map(&ofdev->dev, denali_reg); - if (!denali->flash_reg) - return -ENOMEM; + denali_reg = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "denali_reg"); + denali->flash_reg = devm_ioremap_resource(&ofdev->dev, denali_reg); + if (IS_ERR(denali->flash_reg)) + return PTR_ERR(denali->flash_reg); - denali->flash_mem = request_and_map(&ofdev->dev, nand_data); - if (!denali->flash_mem) - return -ENOMEM; + nand_data = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "nand_data"); + denali->flash_mem = devm_ioremap_resource(&ofdev->dev, nand_data); + if (IS_ERR(denali->flash_mem)) + return PTR_ERR(denali->flash_mem); if (!of_property_read_u32(ofdev->dev.of_node, "dma-mask", (u32 *)&denali_dma_mask)) { @@ -108,7 +85,7 @@ static int denali_dt_probe(struct platform_device *ofdev) denali->dev->dma_mask = NULL; } - dt->clk = clk_get(&ofdev->dev, NULL); + dt->clk = devm_clk_get(&ofdev->dev, NULL); if (IS_ERR(dt->clk)) { dev_err(&ofdev->dev, "no clk available\n"); return PTR_ERR(dt->clk); @@ -124,7 +101,6 @@ static int denali_dt_probe(struct platform_device *ofdev) out_disable_clk: clk_disable_unprepare(dt->clk); - clk_put(dt->clk); return ret; } @@ -135,7 +111,6 @@ static int denali_dt_remove(struct platform_device *ofdev) denali_remove(&dt->denali); clk_disable(dt->clk); - clk_put(dt->clk); return 0; } diff --git a/drivers/mtd/nand/denali_pci.c b/drivers/mtd/nand/denali_pci.c index e3e46623b2b..6e2f387b823 100644 --- a/drivers/mtd/nand/denali_pci.c +++ b/drivers/mtd/nand/denali_pci.c @@ -21,7 +21,7 @@ #define DENALI_NAND_NAME "denali-nand-pci" /* List of platforms this NAND controller has be integrated into */ -static DEFINE_PCI_DEVICE_TABLE(denali_pci_ids) = { +static const struct pci_device_id denali_pci_ids[] = { { PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 }, { PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST }, { /* end: all zeroes */ } @@ -119,7 +119,6 @@ static void denali_pci_remove(struct pci_dev *dev) iounmap(denali->flash_mem); pci_release_regions(dev); pci_disable_device(dev); - pci_set_drvdata(dev, NULL); kfree(denali); } @@ -132,7 +131,6 @@ static struct pci_driver denali_pci_driver = { static int denali_init_pci(void) { - pr_info("Spectra MTD driver built on %s @ %s\n", __DATE__, __TIME__); return pci_register_driver(&denali_pci_driver); } module_init(denali_init_pci); diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index eaa3c29ad86..f68a7bccecd 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -38,7 +38,7 @@ #define CONFIG_MTD_NAND_DISKONCHIP_PROBE_ADDRESS 0 #endif -static unsigned long __initdata doc_locations[] = { +static unsigned long doc_locations[] __initdata = { #if defined (__alpha__) || defined(__i386__) || defined(__x86_64__) #ifdef CONFIG_MTD_NAND_DISKONCHIP_PROBE_HIGH 0xfffc8000, 0xfffca000, 0xfffcc000, 0xfffce000, @@ -698,7 +698,8 @@ static void doc2001plus_command(struct mtd_info *mtd, unsigned command, int colu /* Serially input address */ if (column != -1) { /* Adjust columns for 16 bit buswidth */ - if (this->options & NAND_BUSWIDTH_16) + if (this->options & NAND_BUSWIDTH_16 && + !nand_opcode_8bits(command)) column >>= 1; WriteDOC(column, docptr, Mplus_FlashAddress); } @@ -1058,7 +1059,6 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio buf = kmalloc(mtd->writesize, GFP_KERNEL); if (!buf) { - printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n"); return 0; } if (!(numheaders = find_media_headers(mtd, buf, "ANAND", 1))) @@ -1166,7 +1166,6 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti buf = kmalloc(mtd->writesize, GFP_KERNEL); if (!buf) { - printk(KERN_ERR "DiskOnChip mediaheader kmalloc failed!\n"); return 0; } @@ -1440,10 +1439,13 @@ static int __init doc_probe(unsigned long physadr) int reg, len, numchips; int ret = 0; + if (!request_mem_region(physadr, DOC_IOREMAP_LEN, "DiskOnChip")) + return -EBUSY; virtadr = ioremap(physadr, DOC_IOREMAP_LEN); if (!virtadr) { printk(KERN_ERR "Diskonchip ioremap failed: 0x%x bytes at 0x%lx\n", DOC_IOREMAP_LEN, physadr); - return -EIO; + ret = -EIO; + goto error_ioremap; } /* It's not possible to cleanly detect the DiskOnChip - the @@ -1561,7 +1563,6 @@ static int __init doc_probe(unsigned long physadr) sizeof(struct nand_chip) + sizeof(struct doc_priv) + (2 * sizeof(struct nand_bbt_descr)); mtd = kzalloc(len, GFP_KERNEL); if (!mtd) { - printk(KERN_ERR "DiskOnChip kmalloc (%d bytes) failed!\n", len); ret = -ENOMEM; goto fail; } @@ -1629,6 +1630,10 @@ static int __init doc_probe(unsigned long physadr) WriteDOC(save_control, virtadr, DOCControl); fail: iounmap(virtadr); + +error_ioremap: + release_mem_region(physadr, DOC_IOREMAP_LEN); + return ret; } @@ -1645,6 +1650,7 @@ static void release_nanddoc(void) nextmtd = doc->nextdoc; nand_release(mtd); iounmap(doc->virtadr); + release_mem_region(doc->physadr, DOC_IOREMAP_LEN); kfree(mtd); } } diff --git a/drivers/mtd/nand/docg4.c b/drivers/mtd/nand/docg4.c index 548db2389fa..ce24637e14f 100644 --- a/drivers/mtd/nand/docg4.c +++ b/drivers/mtd/nand/docg4.c @@ -44,6 +44,7 @@ #include <linux/mtd/nand.h> #include <linux/bch.h> #include <linux/bitrev.h> +#include <linux/jiffies.h> /* * In "reliable mode" consecutive 2k pages are used in parallel (in some @@ -269,7 +270,7 @@ static int poll_status(struct docg4_priv *doc) */ uint16_t flash_status; - unsigned int timeo; + unsigned long timeo; void __iomem *docptr = doc->virtadr; dev_dbg(doc->dev, "%s...\n", __func__); @@ -277,22 +278,18 @@ static int poll_status(struct docg4_priv *doc) /* hardware quirk requires reading twice initially */ flash_status = readw(docptr + DOC_FLASHCONTROL); - timeo = 1000; + timeo = jiffies + msecs_to_jiffies(200); /* generous timeout */ do { cpu_relax(); flash_status = readb(docptr + DOC_FLASHCONTROL); - } while (!(flash_status & DOC_CTRL_FLASHREADY) && --timeo); + } while (!(flash_status & DOC_CTRL_FLASHREADY) && + time_before(jiffies, timeo)); - - if (!timeo) { + if (unlikely(!(flash_status & DOC_CTRL_FLASHREADY))) { dev_err(doc->dev, "%s: timed out!\n", __func__); return NAND_STATUS_FAIL; } - if (unlikely(timeo < 50)) - dev_warn(doc->dev, "%s: nearly timed out; %d remaining\n", - __func__, timeo); - return 0; } @@ -494,7 +491,7 @@ static uint8_t docg4_read_byte(struct mtd_info *mtd) return status; } - dev_warn(doc->dev, "unexpectd call to read_byte()\n"); + dev_warn(doc->dev, "unexpected call to read_byte()\n"); return 0; } @@ -875,7 +872,7 @@ static int docg4_read_oob(struct mtd_info *mtd, struct nand_chip *nand, return 0; } -static void docg4_erase_block(struct mtd_info *mtd, int page) +static int docg4_erase_block(struct mtd_info *mtd, int page) { struct nand_chip *nand = mtd->priv; struct docg4_priv *doc = nand->priv; @@ -919,6 +916,8 @@ static void docg4_erase_block(struct mtd_info *mtd, int page) write_nop(docptr); poll_status(doc); write_nop(docptr); + + return nand->waitfunc(mtd, nand); } static int write_page(struct mtd_info *mtd, struct nand_chip *nand, @@ -1239,8 +1238,7 @@ static void __init init_mtd_structs(struct mtd_info *mtd) nand->block_markbad = docg4_block_markbad; nand->read_buf = docg4_read_buf; nand->write_buf = docg4_write_buf16; - nand->scan_bbt = nand_default_bbt; - nand->erase_cmd = docg4_erase_block; + nand->erase = docg4_erase_block; nand->ecc.read_page = docg4_read_page; nand->ecc.write_page = docg4_write_page; nand->ecc.read_page_raw = docg4_read_page_raw; diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 20657209a47..545a5c002f0 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -24,10 +24,10 @@ #include <linux/module.h> #include <linux/types.h> -#include <linux/init.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/ioport.h> +#include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/slab.h> @@ -650,8 +650,6 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) chip->page_shift); dev_dbg(priv->dev, "fsl_elbc_init: nand->phys_erase_shift = %d\n", chip->phys_erase_shift); - dev_dbg(priv->dev, "fsl_elbc_init: nand->ecclayout = %p\n", - chip->ecclayout); dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.mode = %d\n", chip->ecc.mode); dev_dbg(priv->dev, "fsl_elbc_init: nand->ecc.steps = %d\n", @@ -725,6 +723,19 @@ static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip, return 0; } +/* ECC will be calculated automatically, and errors will be detected in + * waitfunc. + */ +static int fsl_elbc_write_subpage(struct mtd_info *mtd, struct nand_chip *chip, + uint32_t offset, uint32_t data_len, + const uint8_t *buf, int oob_required) +{ + fsl_elbc_write_buf(mtd, buf, mtd->writesize); + fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); + + return 0; +} + static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) { struct fsl_lbc_ctrl *ctrl = priv->ctrl; @@ -763,6 +774,7 @@ static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv) chip->ecc.read_page = fsl_elbc_read_page; chip->ecc.write_page = fsl_elbc_write_page; + chip->ecc.write_subpage = fsl_elbc_write_subpage; /* If CS Base Register selects full hardware ECC then use it */ if ((in_be32(&lbc->bank[priv->bank].br) & BR_DECC) == @@ -848,7 +860,6 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev) if (!fsl_lbc_ctrl_dev->nand) { elbc_fcm_ctrl = kzalloc(sizeof(*elbc_fcm_ctrl), GFP_KERNEL); if (!elbc_fcm_ctrl) { - dev_err(dev, "failed to allocate memory\n"); mutex_unlock(&fsl_elbc_nand_mutex); ret = -ENOMEM; goto err; @@ -876,7 +887,7 @@ static int fsl_elbc_nand_probe(struct platform_device *pdev) goto err; } - priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", (unsigned)res.start); + priv->mtd.name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start); if (!priv->mtd.name) { ret = -ENOMEM; goto err; diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 317a771f158..2338124dd05 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -22,14 +22,14 @@ #include <linux/module.h> #include <linux/types.h> -#include <linux/init.h> #include <linux/kernel.h> +#include <linux/of_address.h> #include <linux/slab.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> #include <linux/mtd/nand_ecc.h> -#include <asm/fsl_ifc.h> +#include <linux/fsl_ifc.h> #define FSL_IFC_V1_1_0 0x01010000 #define ERR_BYTE 0xFF /* Value returned for read @@ -56,7 +56,7 @@ struct fsl_ifc_nand_ctrl { struct nand_hw_control controller; struct fsl_ifc_mtd *chips[FSL_IFC_BANK_COUNT]; - u8 __iomem *addr; /* Address of assigned IFC buffer */ + void __iomem *addr; /* Address of assigned IFC buffer */ unsigned int page; /* Last page written to / read from */ unsigned int read_bytes;/* Number of bytes read during command */ unsigned int column; /* Saved column from SEQIN */ @@ -135,6 +135,69 @@ static struct nand_ecclayout oob_4096_ecc8 = { .oobfree = { {2, 6}, {136, 82} }, }; +/* 8192-byte page size with 4-bit ECC */ +static struct nand_ecclayout oob_8192_ecc4 = { + .eccbytes = 128, + .eccpos = { + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, + }, + .oobfree = { {2, 6}, {136, 208} }, +}; + +/* 8192-byte page size with 8-bit ECC -- requires 218-byte OOB */ +static struct nand_ecclayout oob_8192_ecc8 = { + .eccbytes = 256, + .eccpos = { + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, + 128, 129, 130, 131, 132, 133, 134, 135, + 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, + 160, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 171, 172, 173, 174, 175, + 176, 177, 178, 179, 180, 181, 182, 183, + 184, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 205, 206, 207, + 208, 209, 210, 211, 212, 213, 214, 215, + 216, 217, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, 230, 231, + 232, 233, 234, 235, 236, 237, 238, 239, + 240, 241, 242, 243, 244, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, + }, + .oobfree = { {2, 6}, {264, 80} }, +}; /* * Generic flash bbt descriptors @@ -441,20 +504,29 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, if (mtd->writesize > 512) { nand_fcr0 = (NAND_CMD_SEQIN << IFC_NAND_FCR0_CMD0_SHIFT) | - (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD1_SHIFT); + (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) | + (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT); iowrite32be( - (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | - (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | - (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | - (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) | - (IFC_FIR_OP_CW1 << IFC_NAND_FIR0_OP4_SHIFT), - &ifc->ifc_nand.nand_fir0); + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | + (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | + (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) | + (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT), + &ifc->ifc_nand.nand_fir0); + iowrite32be( + (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) | + (IFC_FIR_OP_RDSTAT << + IFC_NAND_FIR1_OP6_SHIFT) | + (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT), + &ifc->ifc_nand.nand_fir1); } else { nand_fcr0 = ((NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD1_SHIFT) | (NAND_CMD_SEQIN << - IFC_NAND_FCR0_CMD2_SHIFT)); + IFC_NAND_FCR0_CMD2_SHIFT) | + (NAND_CMD_STATUS << + IFC_NAND_FCR0_CMD3_SHIFT)); iowrite32be( (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | @@ -463,8 +535,13 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) | (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT), &ifc->ifc_nand.nand_fir0); - iowrite32be(IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT, - &ifc->ifc_nand.nand_fir1); + iowrite32be( + (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) | + (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) | + (IFC_FIR_OP_RDSTAT << + IFC_NAND_FIR1_OP7_SHIFT) | + (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT), + &ifc->ifc_nand.nand_fir1); if (column >= mtd->writesize) nand_fcr0 |= @@ -514,7 +591,10 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, * The chip always seems to report that it is * write-protected, even when it is not. */ - setbits8(ifc_nand_ctrl->addr, NAND_STATUS_WP); + if (chip->options & NAND_BUSWIDTH_16) + setbits16(ifc_nand_ctrl->addr, NAND_STATUS_WP); + else + setbits8(ifc_nand_ctrl->addr, NAND_STATUS_WP); return; case NAND_CMD_RESET: @@ -559,7 +639,7 @@ static void fsl_ifc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) len = bufsize - ifc_nand_ctrl->index; } - memcpy_toio(&ifc_nand_ctrl->addr[ifc_nand_ctrl->index], buf, len); + memcpy_toio(ifc_nand_ctrl->addr + ifc_nand_ctrl->index, buf, len); ifc_nand_ctrl->index += len; } @@ -571,13 +651,16 @@ static uint8_t fsl_ifc_read_byte(struct mtd_info *mtd) { struct nand_chip *chip = mtd->priv; struct fsl_ifc_mtd *priv = chip->priv; + unsigned int offset; /* * If there are still bytes in the IFC buffer, then use the * next byte. */ - if (ifc_nand_ctrl->index < ifc_nand_ctrl->read_bytes) - return in_8(&ifc_nand_ctrl->addr[ifc_nand_ctrl->index++]); + if (ifc_nand_ctrl->index < ifc_nand_ctrl->read_bytes) { + offset = ifc_nand_ctrl->index++; + return in_8(ifc_nand_ctrl->addr + offset); + } dev_err(priv->dev, "%s: beyond end of buffer\n", __func__); return ERR_BYTE; @@ -598,8 +681,7 @@ static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd) * next byte. */ if (ifc_nand_ctrl->index < ifc_nand_ctrl->read_bytes) { - data = in_be16((uint16_t __iomem *)&ifc_nand_ctrl-> - addr[ifc_nand_ctrl->index]); + data = in_be16(ifc_nand_ctrl->addr + ifc_nand_ctrl->index); ifc_nand_ctrl->index += 2; return (uint8_t) data; } @@ -624,7 +706,7 @@ static void fsl_ifc_read_buf(struct mtd_info *mtd, u8 *buf, int len) avail = min((unsigned int)len, ifc_nand_ctrl->read_bytes - ifc_nand_ctrl->index); - memcpy_fromio(buf, &ifc_nand_ctrl->addr[ifc_nand_ctrl->index], avail); + memcpy_fromio(buf, ifc_nand_ctrl->addr + ifc_nand_ctrl->index, avail); ifc_nand_ctrl->index += avail; if (len > avail) @@ -718,8 +800,6 @@ static int fsl_ifc_chip_init_tail(struct mtd_info *mtd) chip->page_shift); dev_dbg(priv->dev, "%s: nand->phys_erase_shift = %d\n", __func__, chip->phys_erase_shift); - dev_dbg(priv->dev, "%s: nand->ecclayout = %p\n", __func__, - chip->ecclayout); dev_dbg(priv->dev, "%s: nand->ecc.mode = %d\n", __func__, chip->ecc.mode); dev_dbg(priv->dev, "%s: nand->ecc.steps = %d\n", __func__, @@ -872,11 +952,25 @@ static int fsl_ifc_chip_init(struct fsl_ifc_mtd *priv) } else { layout = &oob_4096_ecc8; chip->ecc.bytes = 16; + chip->ecc.strength = 8; } priv->bufnum_mask = 1; break; + case CSOR_NAND_PGS_8K: + if ((csor & CSOR_NAND_ECC_MODE_MASK) == + CSOR_NAND_ECC_MODE_4) { + layout = &oob_8192_ecc4; + } else { + layout = &oob_8192_ecc8; + chip->ecc.bytes = 16; + chip->ecc.strength = 8; + } + + priv->bufnum_mask = 0; + break; + default: dev_err(priv->dev, "bad csor %#x: bad page size\n", csor); return -ENODEV; @@ -907,7 +1001,6 @@ static int fsl_ifc_chip_remove(struct fsl_ifc_mtd *priv) iounmap(priv->vbase); ifc_nand_ctrl->chips[priv->bank] = NULL; - dev_set_drvdata(priv->dev, NULL); return 0; } @@ -971,7 +1064,6 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) if (!fsl_ifc_ctrl_dev->nand) { ifc_nand_ctrl = kzalloc(sizeof(*ifc_nand_ctrl), GFP_KERNEL); if (!ifc_nand_ctrl) { - dev_err(&dev->dev, "failed to allocate memory\n"); mutex_unlock(&fsl_ifc_nand_mutex); return -ENOMEM; } @@ -1012,7 +1104,7 @@ static int fsl_ifc_nand_probe(struct platform_device *dev) IFC_NAND_EVTER_INTR_FTOERIR_EN | IFC_NAND_EVTER_INTR_WPERIR_EN, &ifc->ifc_nand.nand_evter_intr_en); - priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", (unsigned)res.start); + priv->mtd.name = kasprintf(GFP_KERNEL, "%llx.flash", (u64)res.start); if (!priv->mtd.name) { ret = -ENOMEM; goto err; @@ -1082,25 +1174,7 @@ static struct platform_driver fsl_ifc_nand_driver = { .remove = fsl_ifc_nand_remove, }; -static int __init fsl_ifc_nand_init(void) -{ - int ret; - - ret = platform_driver_register(&fsl_ifc_nand_driver); - if (ret) - printk(KERN_ERR "fsl-ifc: Failed to register platform" - "driver\n"); - - return ret; -} - -static void __exit fsl_ifc_nand_exit(void) -{ - platform_driver_unregister(&fsl_ifc_nand_driver); -} - -module_init(fsl_ifc_nand_init); -module_exit(fsl_ifc_nand_exit); +module_platform_driver(fsl_ifc_nand_driver); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Freescale"); diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 04e07252d74..4d203e84e8c 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c @@ -18,6 +18,7 @@ #include <linux/mtd/nand_ecc.h> #include <linux/mtd/partitions.h> #include <linux/mtd/mtd.h> +#include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/of_gpio.h> #include <linux/io.h> diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c index 3dc1a7564d8..1550692973d 100644 --- a/drivers/mtd/nand/fsmc_nand.c +++ b/drivers/mtd/nand/fsmc_nand.c @@ -573,8 +573,6 @@ static int dma_xfer(struct fsmc_nand_data *host, void *buffer, int len, dma_dev = chan->device; dma_addr = dma_map_single(dma_dev->dev, buffer, len, direction); - flags |= DMA_COMPL_SKIP_SRC_UNMAP | DMA_COMPL_SKIP_DEST_UNMAP; - if (direction == DMA_TO_DEVICE) { dma_src = dma_addr; dma_dst = host->data_pa; @@ -891,10 +889,8 @@ static int fsmc_nand_probe_config_dt(struct platform_device *pdev, pdata->nand_timings = devm_kzalloc(&pdev->dev, sizeof(*pdata->nand_timings), GFP_KERNEL); - if (!pdata->nand_timings) { - dev_err(&pdev->dev, "no memory for nand_timing\n"); + if (!pdata->nand_timings) return -ENOMEM; - } of_property_read_u8_array(np, "timings", (u8 *)pdata->nand_timings, sizeof(*pdata->nand_timings)); @@ -952,10 +948,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) /* Allocate memory for the device structure (and zero it) */ host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); - if (!host) { - dev_err(&pdev->dev, "failed to allocate device structure\n"); + if (!host) return -ENOMEM; - } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data"); host->data_va = devm_ioremap_resource(&pdev->dev, res); @@ -1110,8 +1104,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) host->ecc_place = &fsmc_ecc4_lp_place; break; default: - printk(KERN_WARNING "No oob scheme defined for " - "oobsize %d\n", mtd->oobsize); + dev_warn(&pdev->dev, "No oob scheme defined for oobsize %d\n", + mtd->oobsize); BUG(); } } else { @@ -1126,8 +1120,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev) nand->ecc.layout = &fsmc_ecc1_128_layout; break; default: - printk(KERN_WARNING "No oob scheme defined for " - "oobsize %d\n", mtd->oobsize); + dev_warn(&pdev->dev, "No oob scheme defined for oobsize %d\n", + mtd->oobsize); BUG(); } } diff --git a/drivers/mtd/nand/gpio.c b/drivers/mtd/nand/gpio.c index e826f898241..117ce333fdd 100644 --- a/drivers/mtd/nand/gpio.c +++ b/drivers/mtd/nand/gpio.c @@ -18,7 +18,6 @@ #include <linux/kernel.h> #include <linux/err.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/platform_device.h> @@ -132,13 +131,17 @@ static int gpio_nand_get_config_of(const struct device *dev, static struct resource *gpio_nand_get_io_sync_of(struct platform_device *pdev) { - struct resource *r = devm_kzalloc(&pdev->dev, sizeof(*r), GFP_KERNEL); + struct resource *r; u64 addr; - if (!r || of_property_read_u64(pdev->dev.of_node, + if (of_property_read_u64(pdev->dev.of_node, "gpio-control-nand,io-sync-reg", &addr)) return NULL; + r = devm_kzalloc(&pdev->dev, sizeof(*r), GFP_KERNEL); + if (!r) + return NULL; + r->start = addr; r->end = r->start + 0x3; r->flags = IORESOURCE_MEM; @@ -211,10 +214,8 @@ static int gpio_nand_probe(struct platform_device *pdev) return -EINVAL; gpiomtd = devm_kzalloc(&pdev->dev, sizeof(*gpiomtd), GFP_KERNEL); - if (!gpiomtd) { - dev_err(&pdev->dev, "failed to create NAND MTD\n"); + if (!gpiomtd) return -ENOMEM; - } chip = &gpiomtd->nand_chip; diff --git a/drivers/mtd/nand/gpmi-nand/bch-regs.h b/drivers/mtd/nand/gpmi-nand/bch-regs.h index 588f5374047..05bb91f2f4c 100644 --- a/drivers/mtd/nand/gpmi-nand/bch-regs.h +++ b/drivers/mtd/nand/gpmi-nand/bch-regs.h @@ -54,7 +54,7 @@ #define MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0 11 #define MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0 (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0) #define BF_BCH_FLASH0LAYOUT0_ECC0(v, x) \ - (GPMI_IS_MX6Q(x) \ + (GPMI_IS_MX6(x) \ ? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT0_ECC0) \ & MX6Q_BM_BCH_FLASH0LAYOUT0_ECC0) \ : (((v) << BP_BCH_FLASH0LAYOUT0_ECC0) \ @@ -65,7 +65,7 @@ #define MX6Q_BM_BCH_FLASH0LAYOUT0_GF_13_14 \ (0x1 << MX6Q_BP_BCH_FLASH0LAYOUT0_GF_13_14) #define BF_BCH_FLASH0LAYOUT0_GF(v, x) \ - ((GPMI_IS_MX6Q(x) && ((v) == 14)) \ + ((GPMI_IS_MX6(x) && ((v) == 14)) \ ? (((1) << MX6Q_BP_BCH_FLASH0LAYOUT0_GF_13_14) \ & MX6Q_BM_BCH_FLASH0LAYOUT0_GF_13_14) \ : 0 \ @@ -77,7 +77,7 @@ #define MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE \ (0x3ff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE) #define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v, x) \ - (GPMI_IS_MX6Q(x) \ + (GPMI_IS_MX6(x) \ ? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \ : ((v) & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE) \ ) @@ -96,7 +96,7 @@ #define MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN 11 #define MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN (0x1f << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN) #define BF_BCH_FLASH0LAYOUT1_ECCN(v, x) \ - (GPMI_IS_MX6Q(x) \ + (GPMI_IS_MX6(x) \ ? (((v) << MX6Q_BP_BCH_FLASH0LAYOUT1_ECCN) \ & MX6Q_BM_BCH_FLASH0LAYOUT1_ECCN) \ : (((v) << BP_BCH_FLASH0LAYOUT1_ECCN) \ @@ -107,7 +107,7 @@ #define MX6Q_BM_BCH_FLASH0LAYOUT1_GF_13_14 \ (0x1 << MX6Q_BP_BCH_FLASH0LAYOUT1_GF_13_14) #define BF_BCH_FLASH0LAYOUT1_GF(v, x) \ - ((GPMI_IS_MX6Q(x) && ((v) == 14)) \ + ((GPMI_IS_MX6(x) && ((v) == 14)) \ ? (((1) << MX6Q_BP_BCH_FLASH0LAYOUT1_GF_13_14) \ & MX6Q_BM_BCH_FLASH0LAYOUT1_GF_13_14) \ : 0 \ @@ -119,7 +119,7 @@ #define MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE \ (0x3ff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) #define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v, x) \ - (GPMI_IS_MX6Q(x) \ + (GPMI_IS_MX6(x) \ ? (((v) >> 2) & MX6Q_BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ : ((v) & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE) \ ) diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index 4f8857fa48a..87e658ce23e 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c @@ -20,6 +20,7 @@ */ #include <linux/delay.h> #include <linux/clk.h> +#include <linux/slab.h> #include "gpmi-nand.h" #include "gpmi-regs.h" @@ -187,6 +188,12 @@ int gpmi_init(struct gpmi_nand_data *this) /* Select BCH ECC. */ writel(BM_GPMI_CTRL1_BCH_MODE, r->gpmi_regs + HW_GPMI_CTRL1_SET); + /* + * Decouple the chip select from dma channel. We use dma0 for all + * the chips. + */ + writel(BM_GPMI_CTRL1_DECOUPLE_CS, r->gpmi_regs + HW_GPMI_CTRL1_SET); + gpmi_disable_clk(this); return 0; err_out: @@ -201,30 +208,41 @@ void gpmi_dump_info(struct gpmi_nand_data *this) u32 reg; int i; - pr_err("Show GPMI registers :\n"); + dev_err(this->dev, "Show GPMI registers :\n"); for (i = 0; i <= HW_GPMI_DEBUG / 0x10 + 1; i++) { reg = readl(r->gpmi_regs + i * 0x10); - pr_err("offset 0x%.3x : 0x%.8x\n", i * 0x10, reg); + dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg); } /* start to print out the BCH info */ - pr_err("Show BCH registers :\n"); + dev_err(this->dev, "Show BCH registers :\n"); for (i = 0; i <= HW_BCH_VERSION / 0x10 + 1; i++) { reg = readl(r->bch_regs + i * 0x10); - pr_err("offset 0x%.3x : 0x%.8x\n", i * 0x10, reg); + dev_err(this->dev, "offset 0x%.3x : 0x%.8x\n", i * 0x10, reg); } - pr_err("BCH Geometry :\n"); - pr_err("GF length : %u\n", geo->gf_len); - pr_err("ECC Strength : %u\n", geo->ecc_strength); - pr_err("Page Size in Bytes : %u\n", geo->page_size); - pr_err("Metadata Size in Bytes : %u\n", geo->metadata_size); - pr_err("ECC Chunk Size in Bytes: %u\n", geo->ecc_chunk_size); - pr_err("ECC Chunk Count : %u\n", geo->ecc_chunk_count); - pr_err("Payload Size in Bytes : %u\n", geo->payload_size); - pr_err("Auxiliary Size in Bytes: %u\n", geo->auxiliary_size); - pr_err("Auxiliary Status Offset: %u\n", geo->auxiliary_status_offset); - pr_err("Block Mark Byte Offset : %u\n", geo->block_mark_byte_offset); - pr_err("Block Mark Bit Offset : %u\n", geo->block_mark_bit_offset); + dev_err(this->dev, "BCH Geometry :\n" + "GF length : %u\n" + "ECC Strength : %u\n" + "Page Size in Bytes : %u\n" + "Metadata Size in Bytes : %u\n" + "ECC Chunk Size in Bytes: %u\n" + "ECC Chunk Count : %u\n" + "Payload Size in Bytes : %u\n" + "Auxiliary Size in Bytes: %u\n" + "Auxiliary Status Offset: %u\n" + "Block Mark Byte Offset : %u\n" + "Block Mark Bit Offset : %u\n", + geo->gf_len, + geo->ecc_strength, + geo->page_size, + geo->metadata_size, + geo->ecc_chunk_size, + geo->ecc_chunk_count, + geo->payload_size, + geo->auxiliary_size, + geo->auxiliary_status_offset, + geo->block_mark_byte_offset, + geo->block_mark_bit_offset); } /* Configures the geometry for BCH. */ @@ -259,8 +277,8 @@ int bch_set_geometry(struct gpmi_nand_data *this) * chip, otherwise it will lock up. So we skip resetting BCH on the MX23. * On the other hand, the MX28 needs the reset, because one case has been * seen where the BCH produced ECC errors constantly after 10000 - * consecutive reboots. The latter case has not been seen on the MX23 yet, - * still we don't know if it could happen there as well. + * consecutive reboots. The latter case has not been seen on the MX23 + * yet, still we don't know if it could happen there as well. */ ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this)); if (ret) @@ -347,7 +365,7 @@ static int gpmi_nfc_compute_hardware_timing(struct gpmi_nand_data *this, improved_timing_is_available = (target.tREA_in_ns >= 0) && (target.tRLOH_in_ns >= 0) && - (target.tRHOH_in_ns >= 0) ; + (target.tRHOH_in_ns >= 0); /* Inspect the clock. */ nfc->clock_frequency_in_hz = clk_get_rate(r->clock[0]); @@ -843,7 +861,7 @@ static void gpmi_compute_edo_timing(struct gpmi_nand_data *this, struct resources *r = &this->resources; unsigned long rate = clk_get_rate(r->clock[0]); int mode = this->timing_mode; - int dll_threshold = 16; /* in ns */ + int dll_threshold = this->devdata->max_chain_delay; unsigned long delay; unsigned long clk_period; int t_rea; @@ -868,9 +886,6 @@ static void gpmi_compute_edo_timing(struct gpmi_nand_data *this, /* [3] for GPMI_HW_GPMI_CTRL1 */ hw->wrn_dly_sel = BV_GPMI_CTRL1_WRN_DLY_SEL_NO_DELAY; - if (GPMI_IS_MX6Q(this)) - dll_threshold = 12; - /* * Enlarge 10 times for the numerator and denominator in {3}. * This make us to get more accurate result. @@ -905,10 +920,14 @@ static int enable_edo_mode(struct gpmi_nand_data *this, int mode) struct resources *r = &this->resources; struct nand_chip *nand = &this->nand; struct mtd_info *mtd = &this->mtd; - uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {}; + uint8_t *feature; unsigned long rate; int ret; + feature = kzalloc(ONFI_SUBFEATURE_PARAM_LEN, GFP_KERNEL); + if (!feature) + return -ENOMEM; + nand->select_chip(mtd, 0); /* [1] send SET FEATURE commond to NAND */ @@ -936,11 +955,13 @@ static int enable_edo_mode(struct gpmi_nand_data *this, int mode) this->flags |= GPMI_ASYNC_EDO_ENABLED; this->timing_mode = mode; + kfree(feature); dev_info(this->dev, "enable the asynchronous EDO mode %d\n", mode); return 0; err_out: nand->select_chip(mtd, -1); + kfree(feature); dev_err(this->dev, "mode:%d ,failed in set feature.\n", mode); return -EINVAL; } @@ -950,7 +971,7 @@ int gpmi_extra_init(struct gpmi_nand_data *this) struct nand_chip *chip = &this->nand; /* Enable the asynchronous EDO feature. */ - if (GPMI_IS_MX6Q(this) && chip->onfi_version) { + if (GPMI_IS_MX6(this) && chip->onfi_version) { int mode = onfi_get_async_timing_mode(chip); /* We only support the timing mode 4 and mode 5. */ @@ -980,7 +1001,7 @@ void gpmi_begin(struct gpmi_nand_data *this) /* Enable the clock. */ ret = gpmi_enable_clk(this); if (ret) { - pr_err("We failed in enable the clk\n"); + dev_err(this->dev, "We failed in enable the clk\n"); goto err_out; } @@ -997,7 +1018,7 @@ void gpmi_begin(struct gpmi_nand_data *this) /* [1] Set HW_GPMI_TIMING0 */ reg = BF_GPMI_TIMING0_ADDRESS_SETUP(hw.address_setup_in_cycles) | BF_GPMI_TIMING0_DATA_HOLD(hw.data_hold_in_cycles) | - BF_GPMI_TIMING0_DATA_SETUP(hw.data_setup_in_cycles) ; + BF_GPMI_TIMING0_DATA_SETUP(hw.data_setup_in_cycles); writel(reg, gpmi_regs + HW_GPMI_TIMING0); @@ -1072,12 +1093,19 @@ int gpmi_is_ready(struct gpmi_nand_data *this, unsigned chip) if (GPMI_IS_MX23(this)) { mask = MX23_BM_GPMI_DEBUG_READY0 << chip; reg = readl(r->gpmi_regs + HW_GPMI_DEBUG); - } else if (GPMI_IS_MX28(this) || GPMI_IS_MX6Q(this)) { + } else if (GPMI_IS_MX28(this) || GPMI_IS_MX6(this)) { + /* + * In the imx6, all the ready/busy pins are bound + * together. So we only need to check chip 0. + */ + if (GPMI_IS_MX6(this)) + chip = 0; + /* MX28 shares the same R/B register as MX6Q. */ mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip); reg = readl(r->gpmi_regs + HW_GPMI_STAT); } else - pr_err("unknow arch.\n"); + dev_err(this->dev, "unknow arch.\n"); return reg & mask; } @@ -1108,10 +1136,8 @@ int gpmi_send_command(struct gpmi_nand_data *this) desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)pio, ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); - if (!desc) { - pr_err("step 1 error\n"); - return -1; - } + if (!desc) + return -EINVAL; /* [2] send out the COMMAND + ADDRESS string stored in @buffer */ sgl = &this->cmd_sgl; @@ -1121,11 +1147,8 @@ int gpmi_send_command(struct gpmi_nand_data *this) desc = dmaengine_prep_slave_sg(channel, sgl, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - - if (!desc) { - pr_err("step 2 error\n"); - return -1; - } + if (!desc) + return -EINVAL; /* [3] submit the DMA */ set_dma_type(this, DMA_FOR_COMMAND); @@ -1154,20 +1177,17 @@ int gpmi_send_data(struct gpmi_nand_data *this) pio[1] = 0; desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)pio, ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); - if (!desc) { - pr_err("step 1 error\n"); - return -1; - } + if (!desc) + return -EINVAL; /* [2] send DMA request */ prepare_data_dma(this, DMA_TO_DEVICE); desc = dmaengine_prep_slave_sg(channel, &this->data_sgl, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!desc) { - pr_err("step 2 error\n"); - return -1; - } + if (!desc) + return -EINVAL; + /* [3] submit the DMA */ set_dma_type(this, DMA_FOR_WRITE_DATA); return start_dma_without_bch_irq(this, desc); @@ -1191,20 +1211,16 @@ int gpmi_read_data(struct gpmi_nand_data *this) desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)pio, ARRAY_SIZE(pio), DMA_TRANS_NONE, 0); - if (!desc) { - pr_err("step 1 error\n"); - return -1; - } + if (!desc) + return -EINVAL; /* [2] : send DMA request */ prepare_data_dma(this, DMA_FROM_DEVICE); desc = dmaengine_prep_slave_sg(channel, &this->data_sgl, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!desc) { - pr_err("step 2 error\n"); - return -1; - } + if (!desc) + return -EINVAL; /* [3] : submit the DMA */ set_dma_type(this, DMA_FOR_READ_DATA); @@ -1249,10 +1265,9 @@ int gpmi_send_page(struct gpmi_nand_data *this, (struct scatterlist *)pio, ARRAY_SIZE(pio), DMA_TRANS_NONE, DMA_CTRL_ACK); - if (!desc) { - pr_err("step 2 error\n"); - return -1; - } + if (!desc) + return -EINVAL; + set_dma_type(this, DMA_FOR_WRITE_ECC_PAGE); return start_dma_with_bch_irq(this, desc); } @@ -1284,10 +1299,8 @@ int gpmi_read_page(struct gpmi_nand_data *this, desc = dmaengine_prep_slave_sg(channel, (struct scatterlist *)pio, 2, DMA_TRANS_NONE, 0); - if (!desc) { - pr_err("step 1 error\n"); - return -1; - } + if (!desc) + return -EINVAL; /* [2] Enable the BCH block and read. */ command_mode = BV_GPMI_CTRL0_COMMAND_MODE__READ; @@ -1314,10 +1327,8 @@ int gpmi_read_page(struct gpmi_nand_data *this, (struct scatterlist *)pio, ARRAY_SIZE(pio), DMA_TRANS_NONE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!desc) { - pr_err("step 2 error\n"); - return -1; - } + if (!desc) + return -EINVAL; /* [3] Disable the BCH block */ command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY; @@ -1335,10 +1346,8 @@ int gpmi_read_page(struct gpmi_nand_data *this, (struct scatterlist *)pio, 3, DMA_TRANS_NONE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if (!desc) { - pr_err("step 3 error\n"); - return -1; - } + if (!desc) + return -EINVAL; /* [4] submit the DMA */ set_dma_type(this, DMA_FOR_READ_ECC_PAGE); diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 59ab0692f0b..f638cd8077c 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -18,9 +18,6 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - #include <linux/clk.h> #include <linux/slab.h> #include <linux/interrupt.h> @@ -30,6 +27,7 @@ #include <linux/of_device.h> #include <linux/of_mtd.h> #include "gpmi-nand.h" +#include "bch-regs.h" /* Resource names for the GPMI NAND driver. */ #define GPMI_NAND_GPMI_REGS_ADDR_RES_NAME "gpmi-nand" @@ -45,13 +43,40 @@ static struct nand_bbt_descr gpmi_bbt_descr = { .pattern = scan_ff_pattern }; -/* We will use all the (page + OOB). */ +/* + * We may change the layout if we can get the ECC info from the datasheet, + * else we will use all the (page + OOB). + */ static struct nand_ecclayout gpmi_hw_ecclayout = { .eccbytes = 0, .eccpos = { 0, }, .oobfree = { {.offset = 0, .length = 0} } }; +static const struct gpmi_devdata gpmi_devdata_imx23 = { + .type = IS_MX23, + .bch_max_ecc_strength = 20, + .max_chain_delay = 16, +}; + +static const struct gpmi_devdata gpmi_devdata_imx28 = { + .type = IS_MX28, + .bch_max_ecc_strength = 20, + .max_chain_delay = 16, +}; + +static const struct gpmi_devdata gpmi_devdata_imx6q = { + .type = IS_MX6Q, + .bch_max_ecc_strength = 40, + .max_chain_delay = 12, +}; + +static const struct gpmi_devdata gpmi_devdata_imx6sx = { + .type = IS_MX6SX, + .bch_max_ecc_strength = 62, + .max_chain_delay = 12, +}; + static irqreturn_t bch_irq(int irq, void *cookie) { struct gpmi_nand_data *this = cookie; @@ -101,14 +126,8 @@ static inline bool gpmi_check_ecc(struct gpmi_nand_data *this) /* The mx23/mx28 only support the GF13. */ if (geo->gf_len == 14) return false; - - if (geo->ecc_strength > MXS_ECC_STRENGTH_MAX) - return false; - } else if (GPMI_IS_MX6Q(this)) { - if (geo->ecc_strength > MX6_ECC_STRENGTH_MAX) - return false; } - return true; + return geo->ecc_strength <= this->devdata->bch_max_ecc_strength; } /* @@ -269,8 +288,7 @@ static int legacy_set_geometry(struct gpmi_nand_data *this) "We can not support this nand chip." " Its required ecc strength(%d) is beyond our" " capability(%d).\n", geo->ecc_strength, - (GPMI_IS_MX6Q(this) ? MX6_ECC_STRENGTH_MAX - : MXS_ECC_STRENGTH_MAX)); + this->devdata->bch_max_ecc_strength); return -EINVAL; } @@ -349,14 +367,16 @@ static int legacy_set_geometry(struct gpmi_nand_data *this) int common_nfc_set_geometry(struct gpmi_nand_data *this) { - return set_geometry_by_ecc_info(this) ? 0 : legacy_set_geometry(this); + if (of_property_read_bool(this->dev->of_node, "fsl,use-minimum-ecc") + && set_geometry_by_ecc_info(this)) + return 0; + return legacy_set_geometry(this); } struct dma_chan *get_dma_chan(struct gpmi_nand_data *this) { - int chipnr = this->current_chip; - - return this->dma_chans[chipnr]; + /* We use the DMA channel 0 to access all the nand chips. */ + return this->dma_chans[0]; } /* Can we use the upper's buffer directly for DMA? */ @@ -365,25 +385,28 @@ void prepare_data_dma(struct gpmi_nand_data *this, enum dma_data_direction dr) struct scatterlist *sgl = &this->data_sgl; int ret; - this->direct_dma_map_ok = true; - /* first try to map the upper buffer directly */ - sg_init_one(sgl, this->upper_buf, this->upper_len); - ret = dma_map_sg(this->dev, sgl, 1, dr); - if (ret == 0) { - /* We have to use our own DMA buffer. */ - sg_init_one(sgl, this->data_buffer_dma, PAGE_SIZE); - - if (dr == DMA_TO_DEVICE) - memcpy(this->data_buffer_dma, this->upper_buf, - this->upper_len); - + if (virt_addr_valid(this->upper_buf) && + !object_is_on_stack(this->upper_buf)) { + sg_init_one(sgl, this->upper_buf, this->upper_len); ret = dma_map_sg(this->dev, sgl, 1, dr); if (ret == 0) - pr_err("DMA mapping failed.\n"); + goto map_fail; - this->direct_dma_map_ok = false; + this->direct_dma_map_ok = true; + return; } + +map_fail: + /* We have to use our own DMA buffer. */ + sg_init_one(sgl, this->data_buffer_dma, this->upper_len); + + if (dr == DMA_TO_DEVICE) + memcpy(this->data_buffer_dma, this->upper_buf, this->upper_len); + + dma_map_sg(this->dev, sgl, 1, dr); + + this->direct_dma_map_ok = false; } /* This will be called after the DMA operation is finished. */ @@ -392,8 +415,6 @@ static void dma_irq_callback(void *param) struct gpmi_nand_data *this = param; struct completion *dma_c = &this->dma_done; - complete(dma_c); - switch (this->dma_type) { case DMA_FOR_COMMAND: dma_unmap_sg(this->dev, &this->cmd_sgl, 1, DMA_TO_DEVICE); @@ -416,8 +437,10 @@ static void dma_irq_callback(void *param) break; default: - pr_err("in wrong DMA operation.\n"); + dev_err(this->dev, "in wrong DMA operation.\n"); } + + complete(dma_c); } int start_dma_without_bch_irq(struct gpmi_nand_data *this, @@ -436,7 +459,8 @@ int start_dma_without_bch_irq(struct gpmi_nand_data *this, /* Wait for the interrupt from the DMA block. */ err = wait_for_completion_timeout(dma_c, msecs_to_jiffies(1000)); if (!err) { - pr_err("DMA timeout, last DMA :%d\n", this->last_dma_type); + dev_err(this->dev, "DMA timeout, last DMA :%d\n", + this->last_dma_type); gpmi_dump_info(this); return -ETIMEDOUT; } @@ -465,7 +489,8 @@ int start_dma_with_bch_irq(struct gpmi_nand_data *this, /* Wait for the interrupt from the BCH block. */ err = wait_for_completion_timeout(bch_c, msecs_to_jiffies(1000)); if (!err) { - pr_err("BCH timeout, last DMA :%d\n", this->last_dma_type); + dev_err(this->dev, "BCH timeout, last DMA :%d\n", + this->last_dma_type); gpmi_dump_info(this); return -ETIMEDOUT; } @@ -481,70 +506,38 @@ static int acquire_register_block(struct gpmi_nand_data *this, void __iomem *p; r = platform_get_resource_byname(pdev, IORESOURCE_MEM, res_name); - if (!r) { - pr_err("Can't get resource for %s\n", res_name); - return -ENODEV; - } - - p = ioremap(r->start, resource_size(r)); - if (!p) { - pr_err("Can't remap %s\n", res_name); - return -ENOMEM; - } + p = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(p)) + return PTR_ERR(p); if (!strcmp(res_name, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME)) res->gpmi_regs = p; else if (!strcmp(res_name, GPMI_NAND_BCH_REGS_ADDR_RES_NAME)) res->bch_regs = p; else - pr_err("unknown resource name : %s\n", res_name); + dev_err(this->dev, "unknown resource name : %s\n", res_name); return 0; } -static void release_register_block(struct gpmi_nand_data *this) -{ - struct resources *res = &this->resources; - if (res->gpmi_regs) - iounmap(res->gpmi_regs); - if (res->bch_regs) - iounmap(res->bch_regs); - res->gpmi_regs = NULL; - res->bch_regs = NULL; -} - static int acquire_bch_irq(struct gpmi_nand_data *this, irq_handler_t irq_h) { struct platform_device *pdev = this->pdev; - struct resources *res = &this->resources; const char *res_name = GPMI_NAND_BCH_INTERRUPT_RES_NAME; struct resource *r; int err; r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, res_name); if (!r) { - pr_err("Can't get resource for %s\n", res_name); + dev_err(this->dev, "Can't get resource for %s\n", res_name); return -ENODEV; } - err = request_irq(r->start, irq_h, 0, res_name, this); - if (err) { - pr_err("Can't own %s\n", res_name); - return err; - } - - res->bch_low_interrupt = r->start; - res->bch_high_interrupt = r->end; - return 0; -} - -static void release_bch_irq(struct gpmi_nand_data *this) -{ - struct resources *res = &this->resources; - int i = res->bch_low_interrupt; + err = devm_request_irq(this->dev, r->start, irq_h, 0, res_name, this); + if (err) + dev_err(this->dev, "error requesting BCH IRQ\n"); - for (; i <= res->bch_high_interrupt; i++) - free_irq(i, this); + return err; } static void release_dma_channels(struct gpmi_nand_data *this) @@ -565,7 +558,7 @@ static int acquire_dma_channels(struct gpmi_nand_data *this) /* request dma channel */ dma_chan = dma_request_slave_channel(&pdev->dev, "rx-tx"); if (!dma_chan) { - pr_err("Failed to request DMA channel.\n"); + dev_err(this->dev, "Failed to request DMA channel.\n"); goto acquire_err; } @@ -577,21 +570,6 @@ acquire_err: return -EINVAL; } -static void gpmi_put_clks(struct gpmi_nand_data *this) -{ - struct resources *r = &this->resources; - struct clk *clk; - int i; - - for (i = 0; i < GPMI_CLK_MAX; i++) { - clk = r->clock[i]; - if (clk) { - clk_put(clk); - r->clock[i] = NULL; - } - } -} - static char *extra_clks_for_mx6q[GPMI_CLK_MAX] = { "gpmi_apb", "gpmi_bch", "gpmi_bch_apb", "per1_bch", }; @@ -604,14 +582,14 @@ static int gpmi_get_clks(struct gpmi_nand_data *this) int err, i; /* The main clock is stored in the first. */ - r->clock[0] = clk_get(this->dev, "gpmi_io"); + r->clock[0] = devm_clk_get(this->dev, "gpmi_io"); if (IS_ERR(r->clock[0])) { err = PTR_ERR(r->clock[0]); goto err_clock; } /* Get extra clocks */ - if (GPMI_IS_MX6Q(this)) + if (GPMI_IS_MX6(this)) extra_clks = extra_clks_for_mx6q; if (!extra_clks) return 0; @@ -620,7 +598,7 @@ static int gpmi_get_clks(struct gpmi_nand_data *this) if (extra_clks[i - 1] == NULL) break; - clk = clk_get(this->dev, extra_clks[i - 1]); + clk = devm_clk_get(this->dev, extra_clks[i - 1]); if (IS_ERR(clk)) { err = PTR_ERR(clk); goto err_clock; @@ -629,9 +607,9 @@ static int gpmi_get_clks(struct gpmi_nand_data *this) r->clock[i] = clk; } - if (GPMI_IS_MX6Q(this)) + if (GPMI_IS_MX6(this)) /* - * Set the default value for the gpmi clock in mx6q: + * Set the default value for the gpmi clock. * * If you want to use the ONFI nand which is in the * Synchronous Mode, you should change the clock as you need. @@ -642,7 +620,6 @@ static int gpmi_get_clks(struct gpmi_nand_data *this) err_clock: dev_dbg(this->dev, "failed in finding the clocks.\n"); - gpmi_put_clks(this); return err; } @@ -664,7 +641,7 @@ static int acquire_resources(struct gpmi_nand_data *this) ret = acquire_dma_channels(this); if (ret) - goto exit_dma_channels; + goto exit_regs; ret = gpmi_get_clks(this); if (ret) @@ -673,18 +650,12 @@ static int acquire_resources(struct gpmi_nand_data *this) exit_clock: release_dma_channels(this); -exit_dma_channels: - release_bch_irq(this); exit_regs: - release_register_block(this); return ret; } static void release_resources(struct gpmi_nand_data *this) { - gpmi_put_clks(this); - release_register_block(this); - release_bch_irq(this); release_dma_channels(this); } @@ -730,8 +701,7 @@ static int read_page_prepare(struct gpmi_nand_data *this, length, DMA_FROM_DEVICE); if (dma_mapping_error(dev, dest_phys)) { if (alt_size < length) { - pr_err("%s, Alternate buffer is too small\n", - __func__); + dev_err(dev, "Alternate buffer is too small\n"); return -ENOMEM; } goto map_failed; @@ -781,8 +751,7 @@ static int send_page_prepare(struct gpmi_nand_data *this, DMA_TO_DEVICE); if (dma_mapping_error(dev, source_phys)) { if (alt_size < length) { - pr_err("%s, Alternate buffer is too small\n", - __func__); + dev_err(dev, "Alternate buffer is too small\n"); return -ENOMEM; } goto map_failed; @@ -835,14 +804,23 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this) { struct bch_geometry *geo = &this->bch_geometry; struct device *dev = this->dev; + struct mtd_info *mtd = &this->mtd; /* [1] Allocate a command buffer. PAGE_SIZE is enough. */ this->cmd_buffer = kzalloc(PAGE_SIZE, GFP_DMA | GFP_KERNEL); if (this->cmd_buffer == NULL) goto error_alloc; - /* [2] Allocate a read/write data buffer. PAGE_SIZE is enough. */ - this->data_buffer_dma = kzalloc(PAGE_SIZE, GFP_DMA | GFP_KERNEL); + /* + * [2] Allocate a read/write data buffer. + * The gpmi_alloc_dma_buffer can be called twice. + * We allocate a PAGE_SIZE length buffer if gpmi_alloc_dma_buffer + * is called before the nand_scan_ident; and we allocate a buffer + * of the real NAND page size when the gpmi_alloc_dma_buffer is + * called after the nand_scan_ident. + */ + this->data_buffer_dma = kzalloc(mtd->writesize ?: PAGE_SIZE, + GFP_DMA | GFP_KERNEL); if (this->data_buffer_dma == NULL) goto error_alloc; @@ -870,7 +848,6 @@ static int gpmi_alloc_dma_buffer(struct gpmi_nand_data *this) error_alloc: gpmi_free_dma_buffer(this); - pr_err("Error allocating DMA buffers!\n"); return -ENOMEM; } @@ -902,7 +879,8 @@ static void gpmi_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl) ret = gpmi_send_command(this); if (ret) - pr_err("Chip: %u, Error %d\n", this->current_chip, ret); + dev_err(this->dev, "Chip: %u, Error %d\n", + this->current_chip, ret); this->command_length = 0; } @@ -933,7 +911,7 @@ static void gpmi_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) struct nand_chip *chip = mtd->priv; struct gpmi_nand_data *this = chip->priv; - pr_debug("len is %d\n", len); + dev_dbg(this->dev, "len is %d\n", len); this->upper_buf = buf; this->upper_len = len; @@ -945,7 +923,7 @@ static void gpmi_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) struct nand_chip *chip = mtd->priv; struct gpmi_nand_data *this = chip->priv; - pr_debug("len is %d\n", len); + dev_dbg(this->dev, "len is %d\n", len); this->upper_buf = (uint8_t *)buf; this->upper_len = len; @@ -1024,13 +1002,13 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, unsigned int max_bitflips = 0; int ret; - pr_debug("page number is : %d\n", page); - ret = read_page_prepare(this, buf, mtd->writesize, + dev_dbg(this->dev, "page number is : %d\n", page); + ret = read_page_prepare(this, buf, nfc_geo->payload_size, this->payload_virt, this->payload_phys, nfc_geo->payload_size, &payload_virt, &payload_phys); if (ret) { - pr_err("Inadequate DMA buffer\n"); + dev_err(this->dev, "Inadequate DMA buffer\n"); ret = -ENOMEM; return ret; } @@ -1039,12 +1017,12 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, /* go! */ ret = gpmi_read_page(this, payload_phys, auxiliary_phys); - read_page_end(this, buf, mtd->writesize, + read_page_end(this, buf, nfc_geo->payload_size, this->payload_virt, this->payload_phys, nfc_geo->payload_size, payload_virt, payload_phys); if (ret) { - pr_err("Error in ECC-based read: %d\n", ret); + dev_err(this->dev, "Error in ECC-based read: %d\n", ret); return ret; } @@ -1081,7 +1059,7 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, chip->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0]; } - read_page_swap_end(this, buf, mtd->writesize, + read_page_swap_end(this, buf, nfc_geo->payload_size, this->payload_virt, this->payload_phys, nfc_geo->payload_size, payload_virt, payload_phys); @@ -1089,6 +1067,90 @@ static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip, return max_bitflips; } +/* Fake a virtual small page for the subpage read */ +static int gpmi_ecc_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, + uint32_t offs, uint32_t len, uint8_t *buf, int page) +{ + struct gpmi_nand_data *this = chip->priv; + void __iomem *bch_regs = this->resources.bch_regs; + struct bch_geometry old_geo = this->bch_geometry; + struct bch_geometry *geo = &this->bch_geometry; + int size = chip->ecc.size; /* ECC chunk size */ + int meta, n, page_size; + u32 r1_old, r2_old, r1_new, r2_new; + unsigned int max_bitflips; + int first, last, marker_pos; + int ecc_parity_size; + int col = 0; + + /* The size of ECC parity */ + ecc_parity_size = geo->gf_len * geo->ecc_strength / 8; + + /* Align it with the chunk size */ + first = offs / size; + last = (offs + len - 1) / size; + + /* + * Find the chunk which contains the Block Marker. If this chunk is + * in the range of [first, last], we have to read out the whole page. + * Why? since we had swapped the data at the position of Block Marker + * to the metadata which is bound with the chunk 0. + */ + marker_pos = geo->block_mark_byte_offset / size; + if (last >= marker_pos && first <= marker_pos) { + dev_dbg(this->dev, "page:%d, first:%d, last:%d, marker at:%d\n", + page, first, last, marker_pos); + return gpmi_ecc_read_page(mtd, chip, buf, 0, page); + } + + meta = geo->metadata_size; + if (first) { + col = meta + (size + ecc_parity_size) * first; + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, col, -1); + + meta = 0; + buf = buf + first * size; + } + + /* Save the old environment */ + r1_old = r1_new = readl(bch_regs + HW_BCH_FLASH0LAYOUT0); + r2_old = r2_new = readl(bch_regs + HW_BCH_FLASH0LAYOUT1); + + /* change the BCH registers and bch_geometry{} */ + n = last - first + 1; + page_size = meta + (size + ecc_parity_size) * n; + + r1_new &= ~(BM_BCH_FLASH0LAYOUT0_NBLOCKS | + BM_BCH_FLASH0LAYOUT0_META_SIZE); + r1_new |= BF_BCH_FLASH0LAYOUT0_NBLOCKS(n - 1) + | BF_BCH_FLASH0LAYOUT0_META_SIZE(meta); + writel(r1_new, bch_regs + HW_BCH_FLASH0LAYOUT0); + + r2_new &= ~BM_BCH_FLASH0LAYOUT1_PAGE_SIZE; + r2_new |= BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size); + writel(r2_new, bch_regs + HW_BCH_FLASH0LAYOUT1); + + geo->ecc_chunk_count = n; + geo->payload_size = n * size; + geo->page_size = page_size; + geo->auxiliary_status_offset = ALIGN(meta, 4); + + dev_dbg(this->dev, "page:%d(%d:%d)%d, chunk:(%d:%d), BCH PG size:%d\n", + page, offs, len, col, first, n, page_size); + + /* Read the subpage now */ + this->swap_block_mark = false; + max_bitflips = gpmi_ecc_read_page(mtd, chip, buf, 0, page); + + /* Restore */ + writel(r1_old, bch_regs + HW_BCH_FLASH0LAYOUT0); + writel(r2_old, bch_regs + HW_BCH_FLASH0LAYOUT1); + this->bch_geometry = old_geo; + this->swap_block_mark = true; + + return max_bitflips; +} + static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required) { @@ -1100,7 +1162,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, dma_addr_t auxiliary_phys; int ret; - pr_debug("ecc write page.\n"); + dev_dbg(this->dev, "ecc write page.\n"); if (this->swap_block_mark) { /* * If control arrives here, we're doing block mark swapping. @@ -1130,7 +1192,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, nfc_geo->payload_size, &payload_virt, &payload_phys); if (ret) { - pr_err("Inadequate payload DMA buffer\n"); + dev_err(this->dev, "Inadequate payload DMA buffer\n"); return 0; } @@ -1140,7 +1202,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, nfc_geo->auxiliary_size, &auxiliary_virt, &auxiliary_phys); if (ret) { - pr_err("Inadequate auxiliary DMA buffer\n"); + dev_err(this->dev, "Inadequate auxiliary DMA buffer\n"); goto exit_auxiliary; } } @@ -1148,7 +1210,7 @@ static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, /* Ask the NFC. */ ret = gpmi_send_page(this, payload_phys, auxiliary_phys); if (ret) - pr_err("Error in ECC-based write: %d\n", ret); + dev_err(this->dev, "Error in ECC-based write: %d\n", ret); if (!this->swap_block_mark) { send_page_end(this, chip->oob_poi, mtd->oobsize, @@ -1238,7 +1300,7 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, { struct gpmi_nand_data *this = chip->priv; - pr_debug("page number is %d\n", page); + dev_dbg(this->dev, "page number is %d\n", page); /* clear the OOB buffer */ memset(chip->oob_poi, ~0, mtd->oobsize); @@ -1263,14 +1325,22 @@ static int gpmi_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *chip, static int gpmi_ecc_write_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) { - /* - * The BCH will use all the (page + oob). - * Our gpmi_hw_ecclayout can only prohibit the JFFS2 to write the oob. - * But it can not stop some ioctls such MEMWRITEOOB which uses - * MTD_OPS_PLACE_OOB. So We have to implement this function to prohibit - * these ioctls too. - */ - return -EPERM; + struct nand_oobfree *of = mtd->ecclayout->oobfree; + int status = 0; + + /* Do we have available oob area? */ + if (!of->length) + return -EPERM; + + if (!nand_is_slc(chip)) + return -EPERM; + + chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize + of->offset, page); + chip->write_buf(mtd, chip->oob_poi + of->offset, of->length); + chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); + + status = chip->waitfunc(mtd, chip); + return status & NAND_STATUS_FAIL ? -EIO : 0; } static int gpmi_block_markbad(struct mtd_info *mtd, loff_t ofs) @@ -1443,7 +1513,6 @@ static int mx23_write_transcription_stamp(struct gpmi_nand_data *this) /* Write the NCB fingerprint into the page buffer. */ memset(buffer, ~0, mtd->writesize); - memset(chip->oob_poi, ~0, mtd->oobsize); memcpy(buffer + 12, fingerprint, strlen(fingerprint)); /* Loop through the first search area, writing NCB fingerprints. */ @@ -1558,7 +1627,7 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this) /* Set up the NFC geometry which is used by BCH. */ ret = bch_set_geometry(this); if (ret) { - pr_err("Error setting BCH geometry : %d\n", ret); + dev_err(this->dev, "Error setting BCH geometry : %d\n", ret); return ret; } @@ -1566,26 +1635,7 @@ static int gpmi_set_geometry(struct gpmi_nand_data *this) return gpmi_alloc_dma_buffer(this); } -static int gpmi_pre_bbt_scan(struct gpmi_nand_data *this) -{ - int ret; - - /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */ - if (GPMI_IS_MX23(this)) - this->swap_block_mark = false; - else - this->swap_block_mark = true; - - /* Set up the medium geometry */ - ret = gpmi_set_geometry(this); - if (ret) - return ret; - - /* NAND boot init, depends on the gpmi_set_geometry(). */ - return nand_boot_init(this); -} - -static void gpmi_nfc_exit(struct gpmi_nand_data *this) +static void gpmi_nand_exit(struct gpmi_nand_data *this) { nand_release(&this->mtd); gpmi_free_dma_buffer(this); @@ -1599,8 +1649,11 @@ static int gpmi_init_last(struct gpmi_nand_data *this) struct bch_geometry *bch_geo = &this->bch_geometry; int ret; - /* Prepare for the BBT scan. */ - ret = gpmi_pre_bbt_scan(this); + /* Set up swap_block_mark, must be set before the gpmi_set_geometry() */ + this->swap_block_mark = !GPMI_IS_MX23(this); + + /* Set up the medium geometry */ + ret = gpmi_set_geometry(this); if (ret) return ret; @@ -1615,6 +1668,17 @@ static int gpmi_init_last(struct gpmi_nand_data *this) ecc->layout = &gpmi_hw_ecclayout; /* + * We only enable the subpage read when: + * (1) the chip is imx6, and + * (2) the size of the ECC parity is byte aligned. + */ + if (GPMI_IS_MX6(this) && + ((bch_geo->gf_len * bch_geo->ecc_strength) % 8) == 0) { + ecc->read_subpage = gpmi_ecc_read_subpage; + chip->options |= NAND_SUBPAGE_READ; + } + + /* * Can we enable the extra features? such as EDO or Sync mode. * * We do not check the return value now. That's means if we fail in @@ -1625,7 +1689,7 @@ static int gpmi_init_last(struct gpmi_nand_data *this) return 0; } -static int gpmi_nfc_init(struct gpmi_nand_data *this) +static int gpmi_nand_init(struct gpmi_nand_data *this) { struct mtd_info *mtd = &this->mtd; struct nand_chip *chip = &this->nand; @@ -1664,7 +1728,7 @@ static int gpmi_nfc_init(struct gpmi_nand_data *this) if (ret) goto err_out; - ret = nand_scan_ident(mtd, 1, NULL); + ret = nand_scan_ident(mtd, GPMI_IS_MX6(this) ? 2 : 1, NULL); if (ret) goto err_out; @@ -1672,10 +1736,16 @@ static int gpmi_nfc_init(struct gpmi_nand_data *this) if (ret) goto err_out; + chip->options |= NAND_SKIP_BBTSCAN; ret = nand_scan_tail(mtd); if (ret) goto err_out; + ret = nand_boot_init(this); + if (ret) + goto err_out; + chip->scan_bbt(mtd); + ppdata.of_node = this->pdev->dev.of_node; ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); if (ret) @@ -1683,27 +1753,23 @@ static int gpmi_nfc_init(struct gpmi_nand_data *this) return 0; err_out: - gpmi_nfc_exit(this); + gpmi_nand_exit(this); return ret; } -static const struct platform_device_id gpmi_ids[] = { - { .name = "imx23-gpmi-nand", .driver_data = IS_MX23, }, - { .name = "imx28-gpmi-nand", .driver_data = IS_MX28, }, - { .name = "imx6q-gpmi-nand", .driver_data = IS_MX6Q, }, - {}, -}; - static const struct of_device_id gpmi_nand_id_table[] = { { .compatible = "fsl,imx23-gpmi-nand", - .data = (void *)&gpmi_ids[IS_MX23] + .data = (void *)&gpmi_devdata_imx23, }, { .compatible = "fsl,imx28-gpmi-nand", - .data = (void *)&gpmi_ids[IS_MX28] + .data = (void *)&gpmi_devdata_imx28, }, { .compatible = "fsl,imx6q-gpmi-nand", - .data = (void *)&gpmi_ids[IS_MX6Q] + .data = (void *)&gpmi_devdata_imx6q, + }, { + .compatible = "fsl,imx6sx-gpmi-nand", + .data = (void *)&gpmi_devdata_imx6sx, }, {} }; MODULE_DEVICE_TABLE(of, gpmi_nand_id_table); @@ -1714,20 +1780,18 @@ static int gpmi_nand_probe(struct platform_device *pdev) const struct of_device_id *of_id; int ret; + this = devm_kzalloc(&pdev->dev, sizeof(*this), GFP_KERNEL); + if (!this) + return -ENOMEM; + of_id = of_match_device(gpmi_nand_id_table, &pdev->dev); if (of_id) { - pdev->id_entry = of_id->data; + this->devdata = of_id->data; } else { - pr_err("Failed to find the right device id.\n"); + dev_err(&pdev->dev, "Failed to find the right device id.\n"); return -ENODEV; } - this = kzalloc(sizeof(*this), GFP_KERNEL); - if (!this) { - pr_err("Failed to allocate per-device memory\n"); - return -ENOMEM; - } - platform_set_drvdata(pdev, this); this->pdev = pdev; this->dev = &pdev->dev; @@ -1740,7 +1804,7 @@ static int gpmi_nand_probe(struct platform_device *pdev) if (ret) goto exit_nfc_init; - ret = gpmi_nfc_init(this); + ret = gpmi_nand_init(this); if (ret) goto exit_nfc_init; @@ -1752,7 +1816,6 @@ exit_nfc_init: release_resources(this); exit_acquire_resources: dev_err(this->dev, "driver registration failed: %d\n", ret); - kfree(this); return ret; } @@ -1761,9 +1824,8 @@ static int gpmi_nand_remove(struct platform_device *pdev) { struct gpmi_nand_data *this = platform_get_drvdata(pdev); - gpmi_nfc_exit(this); + gpmi_nand_exit(this); release_resources(this); - kfree(this); return 0; } @@ -1774,7 +1836,6 @@ static struct platform_driver gpmi_nand_driver = { }, .probe = gpmi_nand_probe, .remove = gpmi_nand_remove, - .id_table = gpmi_ids, }; module_platform_driver(gpmi_nand_driver); diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h index a7685e3a874..32c6ba49f98 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.h +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.h @@ -26,8 +26,6 @@ struct resources { void __iomem *gpmi_regs; void __iomem *bch_regs; - unsigned int bch_low_interrupt; - unsigned int bch_high_interrupt; unsigned int dma_low_channel; unsigned int dma_high_channel; struct clk *clock[GPMI_CLK_MAX]; @@ -121,11 +119,25 @@ struct nand_timing { int8_t tRHOH_in_ns; }; +enum gpmi_type { + IS_MX23, + IS_MX28, + IS_MX6Q, + IS_MX6SX +}; + +struct gpmi_devdata { + enum gpmi_type type; + int bch_max_ecc_strength; + int max_chain_delay; /* See the async EDO mode */ +}; + struct gpmi_nand_data { /* flags */ #define GPMI_ASYNC_EDO_ENABLED (1 << 0) #define GPMI_TIMING_INIT_OK (1 << 1) int flags; + const struct gpmi_devdata *devdata; /* System Interface */ struct device *dev; @@ -283,15 +295,11 @@ extern int gpmi_read_page(struct gpmi_nand_data *, #define STATUS_ERASED 0xff #define STATUS_UNCORRECTABLE 0xfe -/* BCH's bit correction capability. */ -#define MXS_ECC_STRENGTH_MAX 20 /* mx23 and mx28 */ -#define MX6_ECC_STRENGTH_MAX 40 - -/* Use the platform_id to distinguish different Archs. */ -#define IS_MX23 0x0 -#define IS_MX28 0x1 -#define IS_MX6Q 0x2 -#define GPMI_IS_MX23(x) ((x)->pdev->id_entry->driver_data == IS_MX23) -#define GPMI_IS_MX28(x) ((x)->pdev->id_entry->driver_data == IS_MX28) -#define GPMI_IS_MX6Q(x) ((x)->pdev->id_entry->driver_data == IS_MX6Q) +/* Use the devdata to distinguish different Archs. */ +#define GPMI_IS_MX23(x) ((x)->devdata->type == IS_MX23) +#define GPMI_IS_MX28(x) ((x)->devdata->type == IS_MX28) +#define GPMI_IS_MX6Q(x) ((x)->devdata->type == IS_MX6Q) +#define GPMI_IS_MX6SX(x) ((x)->devdata->type == IS_MX6SX) + +#define GPMI_IS_MX6(x) (GPMI_IS_MX6Q(x) || GPMI_IS_MX6SX(x)) #endif diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-regs.h b/drivers/mtd/nand/gpmi-nand/gpmi-regs.h index 53397cc290f..82114cdc833 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-regs.h +++ b/drivers/mtd/nand/gpmi-nand/gpmi-regs.h @@ -108,6 +108,9 @@ #define HW_GPMI_CTRL1_CLR 0x00000068 #define HW_GPMI_CTRL1_TOG 0x0000006c +#define BP_GPMI_CTRL1_DECOUPLE_CS 24 +#define BM_GPMI_CTRL1_DECOUPLE_CS (1 << BP_GPMI_CTRL1_DECOUPLE_CS) + #define BP_GPMI_CTRL1_WRN_DLY_SEL 22 #define BM_GPMI_CTRL1_WRN_DLY_SEL (0x3 << BP_GPMI_CTRL1_WRN_DLY_SEL) #define BF_GPMI_CTRL1_WRN_DLY_SEL(v) \ diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c index a264b888c66..a2c804de156 100644 --- a/drivers/mtd/nand/jz4740_nand.c +++ b/drivers/mtd/nand/jz4740_nand.c @@ -416,10 +416,8 @@ static int jz_nand_probe(struct platform_device *pdev) uint8_t nand_maf_id = 0, nand_dev_id = 0; nand = kzalloc(sizeof(*nand), GFP_KERNEL); - if (!nand) { - dev_err(&pdev->dev, "Failed to allocate device structure.\n"); + if (!nand) return -ENOMEM; - } ret = jz_nand_ioremap_resource(pdev, "mmio", &nand->mem, &nand->base); if (ret) diff --git a/drivers/mtd/nand/lpc32xx_mlc.c b/drivers/mtd/nand/lpc32xx_mlc.c index f4dd2a887ea..687478c9f09 100644 --- a/drivers/mtd/nand/lpc32xx_mlc.c +++ b/drivers/mtd/nand/lpc32xx_mlc.c @@ -539,20 +539,6 @@ static int lpc32xx_write_page_lowlevel(struct mtd_info *mtd, return 0; } -static int lpc32xx_write_page(struct mtd_info *mtd, struct nand_chip *chip, - uint32_t offset, int data_len, const uint8_t *buf, - int oob_required, int page, int cached, int raw) -{ - int res; - - chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); - res = lpc32xx_write_page_lowlevel(mtd, chip, buf, oob_required); - chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); - lpc32xx_waitfunc(mtd, chip); - - return res; -} - static int lpc32xx_read_oob(struct mtd_info *mtd, struct nand_chip *chip, int page) { @@ -627,10 +613,8 @@ static struct lpc32xx_nand_cfg_mlc *lpc32xx_parse_dt(struct device *dev) struct device_node *np = dev->of_node; ncfg = devm_kzalloc(dev, sizeof(*ncfg), GFP_KERNEL); - if (!ncfg) { - dev_err(dev, "could not allocate memory for platform data\n"); + if (!ncfg) return NULL; - } of_property_read_u32(np, "nxp,tcea-delay", &ncfg->tcea_delay); of_property_read_u32(np, "nxp,busy-delay", &ncfg->busy_delay); @@ -666,10 +650,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) /* Allocate memory for the device structure (and zero it) */ host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); - if (!host) { - dev_err(&pdev->dev, "failed to allocate device structure.\n"); + if (!host) return -ENOMEM; - } rc = platform_get_resource(pdev, IORESOURCE_MEM, 0); host->io_base = devm_ioremap_resource(&pdev->dev, rc); @@ -732,9 +714,9 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) nand_chip->ecc.write_oob = lpc32xx_write_oob; nand_chip->ecc.read_oob = lpc32xx_read_oob; nand_chip->ecc.strength = 4; - nand_chip->write_page = lpc32xx_write_page; nand_chip->waitfunc = lpc32xx_waitfunc; + nand_chip->options = NAND_NO_SUBPAGE_WRITE; nand_chip->bbt_options = NAND_BBT_USE_FLASH | NAND_BBT_NO_OOB; nand_chip->bbt_td = &lpc32xx_nand_bbt; nand_chip->bbt_md = &lpc32xx_nand_bbt_mirror; @@ -764,14 +746,12 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) host->dma_buf = devm_kzalloc(&pdev->dev, mtd->writesize, GFP_KERNEL); if (!host->dma_buf) { - dev_err(&pdev->dev, "Error allocating dma_buf memory\n"); res = -ENOMEM; goto err_exit3; } host->dummy_buf = devm_kzalloc(&pdev->dev, mtd->writesize, GFP_KERNEL); if (!host->dummy_buf) { - dev_err(&pdev->dev, "Error allocating dummy_buf memory\n"); res = -ENOMEM; goto err_exit3; } @@ -905,7 +885,7 @@ static struct platform_driver lpc32xx_nand_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, - .of_match_table = of_match_ptr(lpc32xx_nand_match), + .of_match_table = lpc32xx_nand_match, }, }; diff --git a/drivers/mtd/nand/lpc32xx_slc.c b/drivers/mtd/nand/lpc32xx_slc.c index add75709d41..53a6742e3da 100644 --- a/drivers/mtd/nand/lpc32xx_slc.c +++ b/drivers/mtd/nand/lpc32xx_slc.c @@ -725,10 +725,8 @@ static struct lpc32xx_nand_cfg_slc *lpc32xx_parse_dt(struct device *dev) struct device_node *np = dev->of_node; ncfg = devm_kzalloc(dev, sizeof(*ncfg), GFP_KERNEL); - if (!ncfg) { - dev_err(dev, "could not allocate memory for NAND config\n"); + if (!ncfg) return NULL; - } of_property_read_u32(np, "nxp,wdr-clks", &ncfg->wdr_clks); of_property_read_u32(np, "nxp,wwidth", &ncfg->wwidth); @@ -772,10 +770,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) /* Allocate memory for the device structure (and zero it) */ host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); - if (!host) { - dev_err(&pdev->dev, "failed to allocate device structure\n"); + if (!host) return -ENOMEM; - } host->io_base_dma = rc->start; host->io_base = devm_ioremap_resource(&pdev->dev, rc); @@ -791,8 +787,8 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) } if (host->ncfg->wp_gpio == -EPROBE_DEFER) return -EPROBE_DEFER; - if (gpio_is_valid(host->ncfg->wp_gpio) && - gpio_request(host->ncfg->wp_gpio, "NAND WP")) { + if (gpio_is_valid(host->ncfg->wp_gpio) && devm_gpio_request(&pdev->dev, + host->ncfg->wp_gpio, "NAND WP")) { dev_err(&pdev->dev, "GPIO not available\n"); return -EBUSY; } @@ -808,7 +804,7 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) mtd->dev.parent = &pdev->dev; /* Get NAND clock */ - host->clk = clk_get(&pdev->dev, NULL); + host->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(host->clk)) { dev_err(&pdev->dev, "Clock failure\n"); res = -ENOENT; @@ -858,7 +854,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) host->data_buf = devm_kzalloc(&pdev->dev, host->dma_buf_len, GFP_KERNEL); if (host->data_buf == NULL) { - dev_err(&pdev->dev, "Error allocating memory\n"); res = -ENOMEM; goto err_exit2; } @@ -893,7 +888,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) /* Avoid extra scan if using BBT, setup BBT support */ if (host->ncfg->use_bbt) { - chip->options |= NAND_SKIP_BBTSCAN; chip->bbt_options |= NAND_BBT_USE_FLASH; /* @@ -915,13 +909,6 @@ static int lpc32xx_nand_probe(struct platform_device *pdev) goto err_exit3; } - /* Standard layout in FLASH for bad block tables */ - if (host->ncfg->use_bbt) { - if (nand_default_bbt(mtd) < 0) - dev_err(&pdev->dev, - "Error initializing default bad block tables\n"); - } - mtd->name = "nxp_lpc3220_slc"; ppdata.of_node = pdev->dev.of_node; res = mtd_device_parse_register(mtd, NULL, &ppdata, host->ncfg->parts, @@ -935,10 +922,8 @@ err_exit3: dma_release_channel(host->dma_chan); err_exit2: clk_disable(host->clk); - clk_put(host->clk); err_exit1: lpc32xx_wp_enable(host); - gpio_free(host->ncfg->wp_gpio); return res; } @@ -961,9 +946,7 @@ static int lpc32xx_nand_remove(struct platform_device *pdev) writel(tmp, SLC_CTRL(host->io_base)); clk_disable(host->clk); - clk_put(host->clk); lpc32xx_wp_enable(host); - gpio_free(host->ncfg->wp_gpio); return 0; } @@ -1023,7 +1006,7 @@ static struct platform_driver lpc32xx_nand_driver = { .driver = { .name = LPC32XX_MODNAME, .owner = THIS_MODULE, - .of_match_table = of_match_ptr(lpc32xx_nand_match), + .of_match_table = lpc32xx_nand_match, }, }; diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 3c60a000b42..e78841a2dcc 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c @@ -30,13 +30,14 @@ #include <linux/gfp.h> #include <linux/delay.h> #include <linux/err.h> -#include <linux/init.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> +#include <linux/of_address.h> #include <linux/of_device.h> +#include <linux/of_irq.h> #include <linux/of_platform.h> #include <asm/mpc5121.h> @@ -651,10 +652,8 @@ static int mpc5121_nfc_probe(struct platform_device *op) } prv = devm_kzalloc(dev, sizeof(*prv), GFP_KERNEL); - if (!prv) { - dev_err(dev, "Memory exhausted!\n"); + if (!prv) return -ENOMEM; - } mtd = &prv->mtd; chip = &prv->chip; @@ -729,7 +728,7 @@ static int mpc5121_nfc_probe(struct platform_device *op) of_node_put(rootnode); /* Enable NFC clock */ - clk = devm_clk_get(dev, "nfc_clk"); + clk = devm_clk_get(dev, "ipg"); if (IS_ERR(clk)) { dev_err(dev, "Unable to acquire NFC clock!\n"); retval = PTR_ERR(clk); @@ -784,7 +783,6 @@ static int mpc5121_nfc_probe(struct platform_device *op) /* Detect NAND chips */ if (nand_scan(mtd, be32_to_cpup(chips_no))) { dev_err(dev, "NAND Flash not found !\n"); - devm_free_irq(dev, prv->irq, mtd); retval = -ENXIO; goto error; } @@ -809,7 +807,6 @@ static int mpc5121_nfc_probe(struct platform_device *op) default: dev_err(dev, "Unsupported NAND flash!\n"); - devm_free_irq(dev, prv->irq, mtd); retval = -ENXIO; goto error; } @@ -820,7 +817,6 @@ static int mpc5121_nfc_probe(struct platform_device *op) retval = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); if (retval) { dev_err(dev, "Error adding MTD device!\n"); - devm_free_irq(dev, prv->irq, mtd); goto error; } @@ -834,11 +830,8 @@ static int mpc5121_nfc_remove(struct platform_device *op) { struct device *dev = &op->dev; struct mtd_info *mtd = dev_get_drvdata(dev); - struct nand_chip *chip = mtd->priv; - struct mpc5121_nfc_prv *prv = chip->priv; nand_release(mtd); - devm_free_irq(dev, prv->irq, mtd); mpc5121_nfc_free(dev, mtd); return 0; diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index ce8242b6c3e..dba262bf766 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -32,6 +32,7 @@ #include <linux/io.h> #include <linux/irq.h> #include <linux/completion.h> +#include <linux/of.h> #include <linux/of_device.h> #include <linux/of_mtd.h> @@ -395,7 +396,7 @@ static void wait_op_done(struct mxc_nand_host *host, int useirq) if (useirq) { if (!host->devtype_data->check_int(host)) { - INIT_COMPLETION(host->op_completion); + reinit_completion(&host->op_completion); irq_control(host, 1); wait_for_completion(&host->op_completion); } @@ -676,7 +677,6 @@ static int mxc_nand_correct_data_v2_v3(struct mtd_info *mtd, u_char *dat, ecc_stat >>= 4; } while (--no_subpages); - mtd->ecc_stats.corrected += ret; pr_debug("%d Symbol Correctable RS-ECC Error\n", ret); return ret; @@ -1399,12 +1399,15 @@ static int mxcnd_probe(struct platform_device *pdev) int err = 0; /* Allocate memory for MTD device structure and private data */ - host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host) + - NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE, GFP_KERNEL); + host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host), + GFP_KERNEL); if (!host) return -ENOMEM; - host->data_buf = (uint8_t *)(host + 1); + /* allocate a temporary buffer for the nand_scan_ident() */ + host->data_buf = devm_kzalloc(&pdev->dev, PAGE_SIZE, GFP_KERNEL); + if (!host->data_buf) + return -ENOMEM; host->dev = &pdev->dev; /* structures must be linked */ @@ -1498,6 +1501,8 @@ static int mxcnd_probe(struct platform_device *pdev) init_completion(&host->op_completion); host->irq = platform_get_irq(pdev, 0); + if (host->irq < 0) + return host->irq; /* * Use host->devtype_data->irq_control() here instead of irq_control() @@ -1507,11 +1512,13 @@ static int mxcnd_probe(struct platform_device *pdev) host->devtype_data->irq_control(host, 0); err = devm_request_irq(&pdev->dev, host->irq, mxc_nfc_irq, - IRQF_DISABLED, DRIVER_NAME, host); + 0, DRIVER_NAME, host); if (err) return err; - clk_prepare_enable(host->clk); + err = clk_prepare_enable(host->clk); + if (err) + return err; host->clk_act = 1; /* @@ -1530,6 +1537,15 @@ static int mxcnd_probe(struct platform_device *pdev) goto escan; } + /* allocate the right size buffer now */ + devm_kfree(&pdev->dev, (void *)host->data_buf); + host->data_buf = devm_kzalloc(&pdev->dev, mtd->writesize + mtd->oobsize, + GFP_KERNEL); + if (!host->data_buf) { + err = -ENOMEM; + goto escan; + } + /* Call preset again, with correct writesize this time */ host->devtype_data->preset(mtd); @@ -1575,6 +1591,8 @@ static int mxcnd_remove(struct platform_device *pdev) struct mxc_nand_host *host = platform_get_drvdata(pdev); nand_release(&host->mtd); + if (host->clk_act) + clk_disable_unprepare(host->clk); return 0; } diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 7ed4841327f..4f3e80c68a2 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -29,12 +29,15 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/delay.h> #include <linux/errno.h> #include <linux/err.h> #include <linux/sched.h> #include <linux/slab.h> +#include <linux/mm.h> #include <linux/types.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> @@ -202,6 +205,51 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr) } /** + * nand_write_byte - [DEFAULT] write single byte to chip + * @mtd: MTD device structure + * @byte: value to write + * + * Default function to write a byte to I/O[7:0] + */ +static void nand_write_byte(struct mtd_info *mtd, uint8_t byte) +{ + struct nand_chip *chip = mtd->priv; + + chip->write_buf(mtd, &byte, 1); +} + +/** + * nand_write_byte16 - [DEFAULT] write single byte to a chip with width 16 + * @mtd: MTD device structure + * @byte: value to write + * + * Default function to write a byte to I/O[7:0] on a 16-bit wide chip. + */ +static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte) +{ + struct nand_chip *chip = mtd->priv; + uint16_t word = byte; + + /* + * It's not entirely clear what should happen to I/O[15:8] when writing + * a byte. The ONFi spec (Revision 3.1; 2012-09-19, Section 2.16) reads: + * + * When the host supports a 16-bit bus width, only data is + * transferred at the 16-bit width. All address and command line + * transfers shall use only the lower 8-bits of the data bus. During + * command transfers, the host may place any value on the upper + * 8-bits of the data bus. During address transfers, the host shall + * set the upper 8-bits of the data bus to 00h. + * + * One user of the write_byte callback is nand_onfi_set_features. The + * four parameters are specified to be written to I/O[7:0], but this is + * neither an address nor a command transfer. Let's assume a 0 on the + * upper I/O lines is OK. + */ + chip->write_buf(mtd, (uint8_t *)&word, 2); +} + +/** * nand_write_buf - [DEFAULT] write buffer to chip * @mtd: MTD device structure * @buf: data buffer @@ -542,7 +590,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, /* Serially input address */ if (column != -1) { /* Adjust columns for 16 bit buswidth */ - if (chip->options & NAND_BUSWIDTH_16) + if (chip->options & NAND_BUSWIDTH_16 && + !nand_opcode_8bits(command)) column >>= 1; chip->cmd_ctrl(mtd, column, ctrl); ctrl &= ~NAND_CTRL_CHANGE; @@ -633,7 +682,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, /* Serially input address */ if (column != -1) { /* Adjust columns for 16 bit buswidth */ - if (chip->options & NAND_BUSWIDTH_16) + if (chip->options & NAND_BUSWIDTH_16 && + !nand_opcode_8bits(command)) column >>= 1; chip->cmd_ctrl(mtd, column, ctrl); ctrl &= ~NAND_CTRL_CHANGE; @@ -1113,9 +1163,11 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, * @data_offs: offset of requested data within the page * @readlen: data length * @bufpoi: buffer to store read data + * @page: page number to read */ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, - uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi) + uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi, + int page) { int start_step, end_step, num_steps; uint32_t *eccpos = chip->ecc.layout->eccpos; @@ -1123,13 +1175,14 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, int data_col_addr, i, gaps = 0; int datafrag_len, eccfrag_len, aligned_len, aligned_pos; int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1; - int index = 0; + int index; unsigned int max_bitflips = 0; /* Column address within the page aligned to ECC size (256bytes) */ start_step = data_offs / chip->ecc.size; end_step = (data_offs + readlen - 1) / chip->ecc.size; num_steps = end_step - start_step + 1; + index = start_step * chip->ecc.bytes; /* Data size aligned to ECC ecc.size */ datafrag_len = num_steps * chip->ecc.size; @@ -1152,8 +1205,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, * ecc.pos. Let's make sure that there are no gaps in ECC positions. */ for (i = 0; i < eccfrag_len - 1; i++) { - if (eccpos[i + start_step * chip->ecc.bytes] + 1 != - eccpos[i + start_step * chip->ecc.bytes + 1]) { + if (eccpos[i + index] + 1 != eccpos[i + index + 1]) { gaps = 1; break; } @@ -1166,8 +1218,6 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, * Send the command to read the particular ECC bytes take care * about buswidth alignment in read_buf. */ - index = start_step * chip->ecc.bytes; - aligned_pos = eccpos[index] & ~(busw - 1); aligned_len = eccfrag_len; if (eccpos[index] & (busw - 1)) @@ -1408,6 +1458,30 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob, } /** + * nand_setup_read_retry - [INTERN] Set the READ RETRY mode + * @mtd: MTD device structure + * @retry_mode: the retry mode to use + * + * Some vendors supply a special command to shift the Vt threshold, to be used + * when there are too many bitflips in a page (i.e., ECC error). After setting + * a new threshold, the host should retry reading the page. + */ +static int nand_setup_read_retry(struct mtd_info *mtd, int retry_mode) +{ + struct nand_chip *chip = mtd->priv; + + pr_debug("setting READ RETRY mode %d\n", retry_mode); + + if (retry_mode >= chip->read_retries) + return -EINVAL; + + if (!chip->setup_read_retry) + return -EOPNOTSUPP; + + return chip->setup_read_retry(mtd, retry_mode); +} + +/** * nand_do_read_ops - [INTERN] Read data with ECC * @mtd: MTD device structure * @from: offset to read from @@ -1420,7 +1494,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, { int chipnr, page, realpage, col, bytes, aligned, oob_required; struct nand_chip *chip = mtd->priv; - struct mtd_ecc_stats stats; int ret = 0; uint32_t readlen = ops->len; uint32_t oobreadlen = ops->ooblen; @@ -1428,9 +1501,10 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, mtd->oobavail : mtd->oobsize; uint8_t *bufpoi, *oob, *buf; + int use_bufpoi; unsigned int max_bitflips = 0; - - stats = mtd->ecc_stats; + int retry_mode = 0; + bool ecc_fail = false; chipnr = (int)(from >> chip->chip_shift); chip->select_chip(mtd, chipnr); @@ -1445,13 +1519,27 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, oob_required = oob ? 1 : 0; while (1) { + unsigned int ecc_failures = mtd->ecc_stats.failed; + bytes = min(mtd->writesize - col, readlen); aligned = (bytes == mtd->writesize); + if (!aligned) + use_bufpoi = 1; + else if (chip->options & NAND_USE_BOUNCE_BUFFER) + use_bufpoi = !virt_addr_valid(buf); + else + use_bufpoi = 0; + /* Is the current page in the buffer? */ if (realpage != chip->pagebuf || oob) { - bufpoi = aligned ? buf : chip->buffers->databuf; + bufpoi = use_bufpoi ? chip->buffers->databuf : buf; + + if (use_bufpoi && aligned) + pr_debug("%s: using read bounce buffer for buf@%p\n", + __func__, buf); +read_retry: chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page); /* @@ -1465,12 +1553,13 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, else if (!aligned && NAND_HAS_SUBPAGE_READ(chip) && !oob) ret = chip->ecc.read_subpage(mtd, chip, - col, bytes, bufpoi); + col, bytes, bufpoi, + page); else ret = chip->ecc.read_page(mtd, chip, bufpoi, oob_required, page); if (ret < 0) { - if (!aligned) + if (use_bufpoi) /* Invalidate page cache */ chip->pagebuf = -1; break; @@ -1479,9 +1568,9 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, max_bitflips = max_t(unsigned int, max_bitflips, ret); /* Transfer not aligned data */ - if (!aligned) { + if (use_bufpoi) { if (!NAND_HAS_SUBPAGE_READ(chip) && !oob && - !(mtd->ecc_stats.failed - stats.failed) && + !(mtd->ecc_stats.failed - ecc_failures) && (ops->mode != MTD_OPS_RAW)) { chip->pagebuf = realpage; chip->pagebuf_bitflips = ret; @@ -1492,8 +1581,6 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, memcpy(buf, chip->buffers->databuf + col, bytes); } - buf += bytes; - if (unlikely(oob)) { int toread = min(oobreadlen, max_oobsize); @@ -1511,6 +1598,25 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, else nand_wait_ready(mtd); } + + if (mtd->ecc_stats.failed - ecc_failures) { + if (retry_mode + 1 < chip->read_retries) { + retry_mode++; + ret = nand_setup_read_retry(mtd, + retry_mode); + if (ret < 0) + break; + + /* Reset failures; retry */ + mtd->ecc_stats.failed = ecc_failures; + goto read_retry; + } else { + /* No more retry modes; real failure */ + ecc_fail = true; + } + } + + buf += bytes; } else { memcpy(buf, chip->buffers->databuf + col, bytes); buf += bytes; @@ -1520,6 +1626,14 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, readlen -= bytes; + /* Reset to retry mode 0 */ + if (retry_mode) { + ret = nand_setup_read_retry(mtd, 0); + if (ret < 0) + break; + retry_mode = 0; + } + if (!readlen) break; @@ -1545,7 +1659,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, if (ret < 0) return ret; - if (mtd->ecc_stats.failed - stats.failed) + if (ecc_fail) return -EBADMSG; return max_bitflips; @@ -1902,7 +2016,7 @@ static int nand_write_page_raw_syndrome(struct mtd_info *mtd, oob += chip->ecc.prepad; } - chip->read_buf(mtd, oob, eccbytes); + chip->write_buf(mtd, oob, eccbytes); oob += eccbytes; if (chip->ecc.postpad) { @@ -2274,11 +2388,23 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, int bytes = mtd->writesize; int cached = writelen > bytes && page != blockmask; uint8_t *wbuf = buf; + int use_bufpoi; + int part_pagewr = (column || writelen < (mtd->writesize - 1)); + + if (part_pagewr) + use_bufpoi = 1; + else if (chip->options & NAND_USE_BOUNCE_BUFFER) + use_bufpoi = !virt_addr_valid(buf); + else + use_bufpoi = 0; - /* Partial page write? */ - if (unlikely(column || writelen < (mtd->writesize - 1))) { + /* Partial page write?, or need to use bounce buffer */ + if (use_bufpoi) { + pr_debug("%s: using write bounce buffer for buf@%p\n", + __func__, buf); cached = 0; - bytes = min_t(int, bytes - column, (int) writelen); + if (part_pagewr) + bytes = min_t(int, bytes - column, writelen); chip->pagebuf = -1; memset(chip->buffers->databuf, 0xff, mtd->writesize); memcpy(&chip->buffers->databuf[column], buf, bytes); @@ -2516,18 +2642,20 @@ out: } /** - * single_erase_cmd - [GENERIC] NAND standard block erase command function + * single_erase - [GENERIC] NAND standard block erase command function * @mtd: MTD device structure * @page: the page address of the block which will be erased * - * Standard erase command for NAND chips. + * Standard erase command for NAND chips. Returns NAND status. */ -static void single_erase_cmd(struct mtd_info *mtd, int page) +static int single_erase(struct mtd_info *mtd, int page) { struct nand_chip *chip = mtd->priv; /* Send commands to erase a block */ chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1); + + return chip->waitfunc(mtd, chip); } /** @@ -2608,9 +2736,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, (page + pages_per_block)) chip->pagebuf = -1; - chip->erase_cmd(mtd, page & chip->pagemask); - - status = chip->waitfunc(mtd, chip); + status = chip->erase(mtd, page & chip->pagemask); /* * See if operation failed and additional status checks are @@ -2716,6 +2842,7 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip, int addr, uint8_t *subfeature_param) { int status; + int i; if (!chip->onfi_version || !(le16_to_cpu(chip->onfi_params.opt_cmd) @@ -2723,7 +2850,9 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip, return -EINVAL; chip->cmdfunc(mtd, NAND_CMD_SET_FEATURES, addr, -1); - chip->write_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN); + for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) + chip->write_byte(mtd, subfeature_param[i]); + status = chip->waitfunc(mtd, chip); if (status & NAND_STATUS_FAIL) return -EIO; @@ -2740,6 +2869,8 @@ static int nand_onfi_set_features(struct mtd_info *mtd, struct nand_chip *chip, static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip, int addr, uint8_t *subfeature_param) { + int i; + if (!chip->onfi_version || !(le16_to_cpu(chip->onfi_params.opt_cmd) & ONFI_OPT_CMD_SET_GET_FEATURES)) @@ -2749,7 +2880,8 @@ static int nand_onfi_get_features(struct mtd_info *mtd, struct nand_chip *chip, memset(subfeature_param, 0, ONFI_SUBFEATURE_PARAM_LEN); chip->cmdfunc(mtd, NAND_CMD_GET_FEATURES, addr, -1); - chip->read_buf(mtd, subfeature_param, ONFI_SUBFEATURE_PARAM_LEN); + for (i = 0; i < ONFI_SUBFEATURE_PARAM_LEN; ++i) + *subfeature_param++ = chip->read_byte(mtd); return 0; } @@ -2812,6 +2944,8 @@ static void nand_set_defaults(struct nand_chip *chip, int busw) chip->block_markbad = nand_default_block_markbad; if (!chip->write_buf || chip->write_buf == nand_write_buf) chip->write_buf = busw ? nand_write_buf16 : nand_write_buf; + if (!chip->write_byte || chip->write_byte == nand_write_byte) + chip->write_byte = busw ? nand_write_byte16 : nand_write_byte; if (!chip->read_buf || chip->read_buf == nand_read_buf) chip->read_buf = busw ? nand_read_buf16 : nand_read_buf; if (!chip->scan_bbt) @@ -2869,10 +3003,8 @@ static int nand_flash_detect_ext_param_page(struct mtd_info *mtd, len = le16_to_cpu(p->ext_param_page_length) * 16; ep = kmalloc(len, GFP_KERNEL); - if (!ep) { - ret = -ENOMEM; - goto ext_out; - } + if (!ep) + return -ENOMEM; /* Send our own NAND_CMD_PARAM. */ chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); @@ -2914,19 +3046,44 @@ static int nand_flash_detect_ext_param_page(struct mtd_info *mtd, /* get the info we want. */ ecc = (struct onfi_ext_ecc_info *)cursor; - if (ecc->codeword_size) { - chip->ecc_strength_ds = ecc->ecc_bits; - chip->ecc_step_ds = 1 << ecc->codeword_size; + if (!ecc->codeword_size) { + pr_debug("Invalid codeword size\n"); + goto ext_out; } - pr_info("ONFI extended param page detected.\n"); - return 0; + chip->ecc_strength_ds = ecc->ecc_bits; + chip->ecc_step_ds = 1 << ecc->codeword_size; + ret = 0; ext_out: kfree(ep); return ret; } +static int nand_setup_read_retry_micron(struct mtd_info *mtd, int retry_mode) +{ + struct nand_chip *chip = mtd->priv; + uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode}; + + return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY, + feature); +} + +/* + * Configure chip properties from Micron vendor-specific ONFI table + */ +static void nand_onfi_detect_micron(struct nand_chip *chip, + struct nand_onfi_params *p) +{ + struct nand_onfi_vendor_micron *micron = (void *)p->vendor; + + if (le16_to_cpu(p->vendor_revision) < 1) + return; + + chip->read_retries = micron->read_retry_options; + chip->setup_read_retry = nand_setup_read_retry_micron; +} + /* * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise. */ @@ -2934,14 +3091,9 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, int *busw) { struct nand_onfi_params *p = &chip->onfi_params; - int i; + int i, j; int val; - /* ONFI need to be probed in 8 bits mode, and 16 bits should be selected with NAND_BUSWIDTH_AUTO */ - if (chip->options & NAND_BUSWIDTH_16) { - pr_err("Trying ONFI probe in 16 bits mode, aborting !\n"); - return 0; - } /* Try ONFI for unknown chip or LP */ chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1); if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' || @@ -2950,16 +3102,18 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1); for (i = 0; i < 3; i++) { - chip->read_buf(mtd, (uint8_t *)p, sizeof(*p)); + for (j = 0; j < sizeof(*p); j++) + ((uint8_t *)p)[j] = chip->read_byte(mtd); if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) == le16_to_cpu(p->crc)) { - pr_info("ONFI param page %d valid\n", i); break; } } - if (i == 3) + if (i == 3) { + pr_err("Could not find valid ONFI parameter page; aborting\n"); return 0; + } /* Check version */ val = le16_to_cpu(p->revision); @@ -2975,7 +3129,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, chip->onfi_version = 10; if (!chip->onfi_version) { - pr_info("%s: unsupported ONFI version: %d\n", __func__, val); + pr_info("unsupported ONFI version: %d\n", val); return 0; } @@ -2983,11 +3137,23 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, sanitize_string(p->model, sizeof(p->model)); if (!mtd->name) mtd->name = p->model; + mtd->writesize = le32_to_cpu(p->byte_per_page); - mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize; + + /* + * pages_per_block and blocks_per_lun may not be a power-of-2 size + * (don't ask me who thought of this...). MTD assumes that these + * dimensions will be power-of-2, so just truncate the remaining area. + */ + mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1); + mtd->erasesize *= mtd->writesize; + mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); - chip->chipsize = le32_to_cpu(p->blocks_per_lun); + + /* See erasesize comment */ + chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1); chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; + chip->bits_per_cell = p->bits_per_cell; if (onfi_feature(chip) & ONFI_FEATURE_16_BIT_BUS) *busw = NAND_BUSWIDTH_16; @@ -3011,10 +3177,95 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, /* The Extended Parameter Page is supported since ONFI 2.1. */ if (nand_flash_detect_ext_param_page(mtd, chip, p)) - pr_info("Failed to detect the extended param page.\n"); + pr_warn("Failed to detect ONFI extended param page\n"); + } else { + pr_warn("Could not retrieve ONFI ECC requirements\n"); + } + + if (p->jedec_id == NAND_MFR_MICRON) + nand_onfi_detect_micron(chip, p); + + return 1; +} + +/* + * Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise. + */ +static int nand_flash_detect_jedec(struct mtd_info *mtd, struct nand_chip *chip, + int *busw) +{ + struct nand_jedec_params *p = &chip->jedec_params; + struct jedec_ecc_info *ecc; + int val; + int i, j; + + /* Try JEDEC for unknown chip or LP */ + chip->cmdfunc(mtd, NAND_CMD_READID, 0x40, -1); + if (chip->read_byte(mtd) != 'J' || chip->read_byte(mtd) != 'E' || + chip->read_byte(mtd) != 'D' || chip->read_byte(mtd) != 'E' || + chip->read_byte(mtd) != 'C') + return 0; + + chip->cmdfunc(mtd, NAND_CMD_PARAM, 0x40, -1); + for (i = 0; i < 3; i++) { + for (j = 0; j < sizeof(*p); j++) + ((uint8_t *)p)[j] = chip->read_byte(mtd); + + if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 510) == + le16_to_cpu(p->crc)) + break; + } + + if (i == 3) { + pr_err("Could not find valid JEDEC parameter page; aborting\n"); + return 0; + } + + /* Check version */ + val = le16_to_cpu(p->revision); + if (val & (1 << 2)) + chip->jedec_version = 10; + else if (val & (1 << 1)) + chip->jedec_version = 1; /* vendor specific version */ + + if (!chip->jedec_version) { + pr_info("unsupported JEDEC version: %d\n", val); + return 0; + } + + sanitize_string(p->manufacturer, sizeof(p->manufacturer)); + sanitize_string(p->model, sizeof(p->model)); + if (!mtd->name) + mtd->name = p->model; + + mtd->writesize = le32_to_cpu(p->byte_per_page); + + /* Please reference to the comment for nand_flash_detect_onfi. */ + mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1); + mtd->erasesize *= mtd->writesize; + + mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); + + /* Please reference to the comment for nand_flash_detect_onfi. */ + chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1); + chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; + chip->bits_per_cell = p->bits_per_cell; + + if (jedec_feature(chip) & JEDEC_FEATURE_16_BIT_BUS) + *busw = NAND_BUSWIDTH_16; + else + *busw = 0; + + /* ECC info */ + ecc = &p->ecc_info[0]; + + if (ecc->codeword_size >= 9) { + chip->ecc_strength_ds = ecc->ecc_bits; + chip->ecc_step_ds = 1 << ecc->codeword_size; + } else { + pr_warn("Invalid codeword size\n"); } - pr_info("ONFI flash detected\n"); return 1; } @@ -3077,6 +3328,16 @@ static int nand_id_len(u8 *id_data, int arrlen) return arrlen; } +/* Extract the bits of per cell from the 3rd byte of the extended ID */ +static int nand_get_bits_per_cell(u8 cellinfo) +{ + int bits; + + bits = cellinfo & NAND_CI_CELLTYPE_MSK; + bits >>= NAND_CI_CELLTYPE_SHIFT; + return bits + 1; +} + /* * Many new NAND share similar device ID codes, which represent the size of the * chip. The rest of the parameters must be decoded according to generic or @@ -3087,7 +3348,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, { int extid, id_len; /* The 3rd id byte holds MLC / multichip data */ - chip->cellinfo = id_data[2]; + chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]); /* The 4th id byte is the important one */ extid = id_data[3]; @@ -3103,8 +3364,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, * ID to decide what to do. */ if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG && - (chip->cellinfo & NAND_CI_CELLTYPE_MSK) && - id_data[5] != 0x00) { + !nand_is_slc(chip) && id_data[5] != 0x00) { /* Calc pagesize */ mtd->writesize = 2048 << (extid & 0x03); extid >>= 2; @@ -3126,9 +3386,12 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, mtd->oobsize = 512; break; case 6: - default: /* Other cases are "reserved" (unknown) */ mtd->oobsize = 640; break; + case 7: + default: /* Other cases are "reserved" (unknown) */ + mtd->oobsize = 1024; + break; } extid >>= 2; /* Calc blocksize */ @@ -3136,7 +3399,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, (((extid >> 1) & 0x04) | (extid & 0x03)); *busw = 0; } else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX && - (chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { + !nand_is_slc(chip)) { unsigned int tmp; /* Calc pagesize */ @@ -3199,7 +3462,7 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip, * - ID byte 5, bit[7]: 1 -> BENAND, 0 -> raw SLC */ if (id_len >= 6 && id_data[0] == NAND_MFR_TOSHIBA && - !(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && + nand_is_slc(chip) && (id_data[5] & 0x7) == 0x6 /* 24nm */ && !(id_data[4] & 0x80) /* !BENAND */) { mtd->oobsize = 32 * mtd->writesize >> 9; @@ -3224,6 +3487,9 @@ static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip, mtd->oobsize = mtd->writesize / 32; *busw = type->options & NAND_BUSWIDTH_16; + /* All legacy ID NAND are small-page, SLC */ + chip->bits_per_cell = 1; + /* * Check for Spansion/AMD ID + repeating 5th, 6th byte since * some Spansion chips have erasesize that conflicts with size @@ -3260,11 +3526,11 @@ static void nand_decode_bbm_options(struct mtd_info *mtd, * Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba, * AMD/Spansion, and Macronix. All others scan only the first page. */ - if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && + if (!nand_is_slc(chip) && (maf_id == NAND_MFR_SAMSUNG || maf_id == NAND_MFR_HYNIX)) chip->bbt_options |= NAND_BBT_SCANLASTPAGE; - else if ((!(chip->cellinfo & NAND_CI_CELLTYPE_MSK) && + else if ((nand_is_slc(chip) && (maf_id == NAND_MFR_SAMSUNG || maf_id == NAND_MFR_HYNIX || maf_id == NAND_MFR_TOSHIBA || @@ -3288,7 +3554,7 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip, mtd->erasesize = type->erasesize; mtd->oobsize = type->oobsize; - chip->cellinfo = id_data[2]; + chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]); chip->chipsize = (uint64_t)type->chipsize << 20; chip->options |= type->options; chip->ecc_strength_ds = NAND_ECC_STRENGTH(type); @@ -3296,6 +3562,9 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip, *busw = type->options & NAND_BUSWIDTH_16; + if (!mtd->name) + mtd->name = type->name; + return true; } return false; @@ -3306,10 +3575,10 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip, */ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, struct nand_chip *chip, - int busw, int *maf_id, int *dev_id, struct nand_flash_dev *type) { + int busw; int i, maf_idx; u8 id_data[8]; @@ -3343,8 +3612,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, id_data[i] = chip->read_byte(mtd); if (id_data[0] != *maf_id || id_data[1] != *dev_id) { - pr_info("%s: second ID read did not match " - "%02x,%02x against %02x,%02x\n", __func__, + pr_info("second ID read did not match %02x,%02x against %02x,%02x\n", *maf_id, *dev_id, id_data[0], id_data[1]); return ERR_PTR(-ENODEV); } @@ -3363,9 +3631,13 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->onfi_version = 0; if (!type->name || !type->pagesize) { - /* Check is chip is ONFI compliant */ + /* Check if the chip is ONFI compliant */ if (nand_flash_detect_onfi(mtd, chip, &busw)) goto ident_done; + + /* Check if the chip is JEDEC compliant */ + if (nand_flash_detect_jedec(mtd, chip, &busw)) + goto ident_done; } if (!type->name) @@ -3411,10 +3683,10 @@ ident_done: * Check, if buswidth is correct. Hardware drivers should set * chip correct! */ - pr_info("NAND device: Manufacturer ID:" - " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, - *dev_id, nand_manuf_ids[maf_idx].name, mtd->name); - pr_warn("NAND bus width %d instead %d bit\n", + pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n", + *maf_id, *dev_id); + pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, mtd->name); + pr_warn("bus width %d instead %d bit\n", (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, busw ? 16 : 8); return ERR_PTR(-EINVAL); @@ -3437,18 +3709,28 @@ ident_done: } chip->badblockbits = 8; - chip->erase_cmd = single_erase_cmd; + chip->erase = single_erase; /* Do not replace user supplied command function! */ if (mtd->writesize > 512 && chip->cmdfunc == nand_command) chip->cmdfunc = nand_command_lp; - pr_info("NAND device: Manufacturer ID: 0x%02x, Chip ID: 0x%02x (%s %s)," - " %dMiB, page size: %d, OOB size: %d\n", - *maf_id, *dev_id, nand_manuf_ids[maf_idx].name, - chip->onfi_version ? chip->onfi_params.model : type->name, - (int)(chip->chipsize >> 20), mtd->writesize, mtd->oobsize); + pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n", + *maf_id, *dev_id); + if (chip->onfi_version) + pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, + chip->onfi_params.model); + else if (chip->jedec_version) + pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, + chip->jedec_params.model); + else + pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, + type->name); + + pr_info("%dMiB, %s, page size: %d, OOB size: %d\n", + (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC", + mtd->writesize, mtd->oobsize); return type; } @@ -3466,18 +3748,16 @@ ident_done: int nand_scan_ident(struct mtd_info *mtd, int maxchips, struct nand_flash_dev *table) { - int i, busw, nand_maf_id, nand_dev_id; + int i, nand_maf_id, nand_dev_id; struct nand_chip *chip = mtd->priv; struct nand_flash_dev *type; - /* Get buswidth to select the correct functions */ - busw = chip->options & NAND_BUSWIDTH_16; /* Set the default functions */ - nand_set_defaults(chip, busw); + nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16); /* Read the flash type */ - type = nand_get_flash_type(mtd, chip, busw, - &nand_maf_id, &nand_dev_id, table); + type = nand_get_flash_type(mtd, chip, &nand_maf_id, + &nand_dev_id, table); if (IS_ERR(type)) { if (!(chip->options & NAND_SCAN_SILENT_NODEV)) @@ -3504,7 +3784,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, chip->select_chip(mtd, -1); } if (i > 1) - pr_info("%d NAND chips detected\n", i); + pr_info("%d chips detected\n", i); /* Store the number of chips and calc total size for mtd */ chip->numchips = i; @@ -3514,6 +3794,39 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips, } EXPORT_SYMBOL(nand_scan_ident); +/* + * Check if the chip configuration meet the datasheet requirements. + + * If our configuration corrects A bits per B bytes and the minimum + * required correction level is X bits per Y bytes, then we must ensure + * both of the following are true: + * + * (1) A / B >= X / Y + * (2) A >= X + * + * Requirement (1) ensures we can correct for the required bitflip density. + * Requirement (2) ensures we can correct even when all bitflips are clumped + * in the same sector. + */ +static bool nand_ecc_strength_good(struct mtd_info *mtd) +{ + struct nand_chip *chip = mtd->priv; + struct nand_ecc_ctrl *ecc = &chip->ecc; + int corr, ds_corr; + + if (ecc->size == 0 || chip->ecc_step_ds == 0) + /* Not enough information */ + return true; + + /* + * We get the number of corrected bits per page to compare + * the correction density. + */ + corr = (mtd->writesize * ecc->strength) / ecc->size; + ds_corr = (mtd->writesize * chip->ecc_strength_ds) / chip->ecc_step_ds; + + return corr >= ds_corr && ecc->strength >= chip->ecc_strength_ds; +} /** * nand_scan_tail - [NAND Interface] Scan for the NAND device @@ -3527,15 +3840,27 @@ int nand_scan_tail(struct mtd_info *mtd) { int i; struct nand_chip *chip = mtd->priv; + struct nand_ecc_ctrl *ecc = &chip->ecc; + struct nand_buffers *nbuf; /* New bad blocks should be marked in OOB, flash-based BBT, or both */ BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) && !(chip->bbt_options & NAND_BBT_USE_FLASH)); - if (!(chip->options & NAND_OWN_BUFFERS)) - chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL); - if (!chip->buffers) - return -ENOMEM; + if (!(chip->options & NAND_OWN_BUFFERS)) { + nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize + + mtd->oobsize * 3, GFP_KERNEL); + if (!nbuf) + return -ENOMEM; + nbuf->ecccalc = (uint8_t *)(nbuf + 1); + nbuf->ecccode = nbuf->ecccalc + mtd->oobsize; + nbuf->databuf = nbuf->ecccode + mtd->oobsize; + + chip->buffers = nbuf; + } else { + if (!chip->buffers) + return -ENOMEM; + } /* Set the internal oob buffer location, just after the page data */ chip->oob_poi = chip->buffers->databuf + mtd->writesize; @@ -3543,19 +3868,19 @@ int nand_scan_tail(struct mtd_info *mtd) /* * If no default placement scheme is given, select an appropriate one. */ - if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) { + if (!ecc->layout && (ecc->mode != NAND_ECC_SOFT_BCH)) { switch (mtd->oobsize) { case 8: - chip->ecc.layout = &nand_oob_8; + ecc->layout = &nand_oob_8; break; case 16: - chip->ecc.layout = &nand_oob_16; + ecc->layout = &nand_oob_16; break; case 64: - chip->ecc.layout = &nand_oob_64; + ecc->layout = &nand_oob_64; break; case 128: - chip->ecc.layout = &nand_oob_128; + ecc->layout = &nand_oob_128; break; default: pr_warn("No oob scheme defined for oobsize %d\n", @@ -3572,64 +3897,62 @@ int nand_scan_tail(struct mtd_info *mtd) * selected and we have 256 byte pagesize fallback to software ECC */ - switch (chip->ecc.mode) { + switch (ecc->mode) { case NAND_ECC_HW_OOB_FIRST: /* Similar to NAND_ECC_HW, but a separate read_page handle */ - if (!chip->ecc.calculate || !chip->ecc.correct || - !chip->ecc.hwctl) { + if (!ecc->calculate || !ecc->correct || !ecc->hwctl) { pr_warn("No ECC functions supplied; " "hardware ECC not possible\n"); BUG(); } - if (!chip->ecc.read_page) - chip->ecc.read_page = nand_read_page_hwecc_oob_first; + if (!ecc->read_page) + ecc->read_page = nand_read_page_hwecc_oob_first; case NAND_ECC_HW: /* Use standard hwecc read page function? */ - if (!chip->ecc.read_page) - chip->ecc.read_page = nand_read_page_hwecc; - if (!chip->ecc.write_page) - chip->ecc.write_page = nand_write_page_hwecc; - if (!chip->ecc.read_page_raw) - chip->ecc.read_page_raw = nand_read_page_raw; - if (!chip->ecc.write_page_raw) - chip->ecc.write_page_raw = nand_write_page_raw; - if (!chip->ecc.read_oob) - chip->ecc.read_oob = nand_read_oob_std; - if (!chip->ecc.write_oob) - chip->ecc.write_oob = nand_write_oob_std; - if (!chip->ecc.read_subpage) - chip->ecc.read_subpage = nand_read_subpage; - if (!chip->ecc.write_subpage) - chip->ecc.write_subpage = nand_write_subpage_hwecc; + if (!ecc->read_page) + ecc->read_page = nand_read_page_hwecc; + if (!ecc->write_page) + ecc->write_page = nand_write_page_hwecc; + if (!ecc->read_page_raw) + ecc->read_page_raw = nand_read_page_raw; + if (!ecc->write_page_raw) + ecc->write_page_raw = nand_write_page_raw; + if (!ecc->read_oob) + ecc->read_oob = nand_read_oob_std; + if (!ecc->write_oob) + ecc->write_oob = nand_write_oob_std; + if (!ecc->read_subpage) + ecc->read_subpage = nand_read_subpage; + if (!ecc->write_subpage) + ecc->write_subpage = nand_write_subpage_hwecc; case NAND_ECC_HW_SYNDROME: - if ((!chip->ecc.calculate || !chip->ecc.correct || - !chip->ecc.hwctl) && - (!chip->ecc.read_page || - chip->ecc.read_page == nand_read_page_hwecc || - !chip->ecc.write_page || - chip->ecc.write_page == nand_write_page_hwecc)) { + if ((!ecc->calculate || !ecc->correct || !ecc->hwctl) && + (!ecc->read_page || + ecc->read_page == nand_read_page_hwecc || + !ecc->write_page || + ecc->write_page == nand_write_page_hwecc)) { pr_warn("No ECC functions supplied; " "hardware ECC not possible\n"); BUG(); } /* Use standard syndrome read/write page function? */ - if (!chip->ecc.read_page) - chip->ecc.read_page = nand_read_page_syndrome; - if (!chip->ecc.write_page) - chip->ecc.write_page = nand_write_page_syndrome; - if (!chip->ecc.read_page_raw) - chip->ecc.read_page_raw = nand_read_page_raw_syndrome; - if (!chip->ecc.write_page_raw) - chip->ecc.write_page_raw = nand_write_page_raw_syndrome; - if (!chip->ecc.read_oob) - chip->ecc.read_oob = nand_read_oob_syndrome; - if (!chip->ecc.write_oob) - chip->ecc.write_oob = nand_write_oob_syndrome; - - if (mtd->writesize >= chip->ecc.size) { - if (!chip->ecc.strength) { + if (!ecc->read_page) + ecc->read_page = nand_read_page_syndrome; + if (!ecc->write_page) + ecc->write_page = nand_write_page_syndrome; + if (!ecc->read_page_raw) + ecc->read_page_raw = nand_read_page_raw_syndrome; + if (!ecc->write_page_raw) + ecc->write_page_raw = nand_write_page_raw_syndrome; + if (!ecc->read_oob) + ecc->read_oob = nand_read_oob_syndrome; + if (!ecc->write_oob) + ecc->write_oob = nand_write_oob_syndrome; + + if (mtd->writesize >= ecc->size) { + if (!ecc->strength) { pr_warn("Driver must set ecc.strength when using hardware ECC\n"); BUG(); } @@ -3637,112 +3960,112 @@ int nand_scan_tail(struct mtd_info *mtd) } pr_warn("%d byte HW ECC not possible on " "%d byte page size, fallback to SW ECC\n", - chip->ecc.size, mtd->writesize); - chip->ecc.mode = NAND_ECC_SOFT; + ecc->size, mtd->writesize); + ecc->mode = NAND_ECC_SOFT; case NAND_ECC_SOFT: - chip->ecc.calculate = nand_calculate_ecc; - chip->ecc.correct = nand_correct_data; - chip->ecc.read_page = nand_read_page_swecc; - chip->ecc.read_subpage = nand_read_subpage; - chip->ecc.write_page = nand_write_page_swecc; - chip->ecc.read_page_raw = nand_read_page_raw; - chip->ecc.write_page_raw = nand_write_page_raw; - chip->ecc.read_oob = nand_read_oob_std; - chip->ecc.write_oob = nand_write_oob_std; - if (!chip->ecc.size) - chip->ecc.size = 256; - chip->ecc.bytes = 3; - chip->ecc.strength = 1; + ecc->calculate = nand_calculate_ecc; + ecc->correct = nand_correct_data; + ecc->read_page = nand_read_page_swecc; + ecc->read_subpage = nand_read_subpage; + ecc->write_page = nand_write_page_swecc; + ecc->read_page_raw = nand_read_page_raw; + ecc->write_page_raw = nand_write_page_raw; + ecc->read_oob = nand_read_oob_std; + ecc->write_oob = nand_write_oob_std; + if (!ecc->size) + ecc->size = 256; + ecc->bytes = 3; + ecc->strength = 1; break; case NAND_ECC_SOFT_BCH: if (!mtd_nand_has_bch()) { - pr_warn("CONFIG_MTD_ECC_BCH not enabled\n"); + pr_warn("CONFIG_MTD_NAND_ECC_BCH not enabled\n"); BUG(); } - chip->ecc.calculate = nand_bch_calculate_ecc; - chip->ecc.correct = nand_bch_correct_data; - chip->ecc.read_page = nand_read_page_swecc; - chip->ecc.read_subpage = nand_read_subpage; - chip->ecc.write_page = nand_write_page_swecc; - chip->ecc.read_page_raw = nand_read_page_raw; - chip->ecc.write_page_raw = nand_write_page_raw; - chip->ecc.read_oob = nand_read_oob_std; - chip->ecc.write_oob = nand_write_oob_std; + ecc->calculate = nand_bch_calculate_ecc; + ecc->correct = nand_bch_correct_data; + ecc->read_page = nand_read_page_swecc; + ecc->read_subpage = nand_read_subpage; + ecc->write_page = nand_write_page_swecc; + ecc->read_page_raw = nand_read_page_raw; + ecc->write_page_raw = nand_write_page_raw; + ecc->read_oob = nand_read_oob_std; + ecc->write_oob = nand_write_oob_std; /* * Board driver should supply ecc.size and ecc.bytes values to * select how many bits are correctable; see nand_bch_init() * for details. Otherwise, default to 4 bits for large page * devices. */ - if (!chip->ecc.size && (mtd->oobsize >= 64)) { - chip->ecc.size = 512; - chip->ecc.bytes = 7; + if (!ecc->size && (mtd->oobsize >= 64)) { + ecc->size = 512; + ecc->bytes = 7; } - chip->ecc.priv = nand_bch_init(mtd, - chip->ecc.size, - chip->ecc.bytes, - &chip->ecc.layout); - if (!chip->ecc.priv) { + ecc->priv = nand_bch_init(mtd, ecc->size, ecc->bytes, + &ecc->layout); + if (!ecc->priv) { pr_warn("BCH ECC initialization failed!\n"); BUG(); } - chip->ecc.strength = - chip->ecc.bytes * 8 / fls(8 * chip->ecc.size); + ecc->strength = ecc->bytes * 8 / fls(8 * ecc->size); break; case NAND_ECC_NONE: pr_warn("NAND_ECC_NONE selected by board driver. " "This is not recommended!\n"); - chip->ecc.read_page = nand_read_page_raw; - chip->ecc.write_page = nand_write_page_raw; - chip->ecc.read_oob = nand_read_oob_std; - chip->ecc.read_page_raw = nand_read_page_raw; - chip->ecc.write_page_raw = nand_write_page_raw; - chip->ecc.write_oob = nand_write_oob_std; - chip->ecc.size = mtd->writesize; - chip->ecc.bytes = 0; - chip->ecc.strength = 0; + ecc->read_page = nand_read_page_raw; + ecc->write_page = nand_write_page_raw; + ecc->read_oob = nand_read_oob_std; + ecc->read_page_raw = nand_read_page_raw; + ecc->write_page_raw = nand_write_page_raw; + ecc->write_oob = nand_write_oob_std; + ecc->size = mtd->writesize; + ecc->bytes = 0; + ecc->strength = 0; break; default: - pr_warn("Invalid NAND_ECC_MODE %d\n", chip->ecc.mode); + pr_warn("Invalid NAND_ECC_MODE %d\n", ecc->mode); BUG(); } /* For many systems, the standard OOB write also works for raw */ - if (!chip->ecc.read_oob_raw) - chip->ecc.read_oob_raw = chip->ecc.read_oob; - if (!chip->ecc.write_oob_raw) - chip->ecc.write_oob_raw = chip->ecc.write_oob; + if (!ecc->read_oob_raw) + ecc->read_oob_raw = ecc->read_oob; + if (!ecc->write_oob_raw) + ecc->write_oob_raw = ecc->write_oob; /* * The number of bytes available for a client to place data into * the out of band area. */ - chip->ecc.layout->oobavail = 0; - for (i = 0; chip->ecc.layout->oobfree[i].length - && i < ARRAY_SIZE(chip->ecc.layout->oobfree); i++) - chip->ecc.layout->oobavail += - chip->ecc.layout->oobfree[i].length; - mtd->oobavail = chip->ecc.layout->oobavail; + ecc->layout->oobavail = 0; + for (i = 0; ecc->layout->oobfree[i].length + && i < ARRAY_SIZE(ecc->layout->oobfree); i++) + ecc->layout->oobavail += ecc->layout->oobfree[i].length; + mtd->oobavail = ecc->layout->oobavail; + + /* ECC sanity check: warn if it's too weak */ + if (!nand_ecc_strength_good(mtd)) + pr_warn("WARNING: %s: the ECC used on your system is too weak compared to the one required by the NAND chip\n", + mtd->name); /* * Set the number of read / write steps for one page depending on ECC * mode. */ - chip->ecc.steps = mtd->writesize / chip->ecc.size; - if (chip->ecc.steps * chip->ecc.size != mtd->writesize) { + ecc->steps = mtd->writesize / ecc->size; + if (ecc->steps * ecc->size != mtd->writesize) { pr_warn("Invalid ECC parameters\n"); BUG(); } - chip->ecc.total = chip->ecc.steps * chip->ecc.bytes; + ecc->total = ecc->steps * ecc->bytes; /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */ - if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && - !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) { - switch (chip->ecc.steps) { + if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) { + switch (ecc->steps) { case 2: mtd->subpage_sft = 1; break; @@ -3762,11 +4085,19 @@ int nand_scan_tail(struct mtd_info *mtd) chip->pagebuf = -1; /* Large page NAND with SOFT_ECC should support subpage reads */ - if ((chip->ecc.mode == NAND_ECC_SOFT) && (chip->page_shift > 9)) - chip->options |= NAND_SUBPAGE_READ; + switch (ecc->mode) { + case NAND_ECC_SOFT: + case NAND_ECC_SOFT_BCH: + if (chip->page_shift > 9) + chip->options |= NAND_SUBPAGE_READ; + break; + + default: + break; + } /* Fill in remaining MTD driver data */ - mtd->type = MTD_NANDFLASH; + mtd->type = nand_is_slc(chip) ? MTD_NANDFLASH : MTD_MLCNANDFLASH; mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM : MTD_CAP_NANDFLASH; mtd->_erase = nand_erase; @@ -3787,9 +4118,9 @@ int nand_scan_tail(struct mtd_info *mtd) mtd->writebufsize = mtd->writesize; /* propagate ecc info to mtd_info */ - mtd->ecclayout = chip->ecc.layout; - mtd->ecc_strength = chip->ecc.strength; - mtd->ecc_step_size = chip->ecc.size; + mtd->ecclayout = ecc->layout; + mtd->ecc_strength = ecc->strength; + mtd->ecc_step_size = ecc->size; /* * Initialize bitflip_threshold to its default prior scan_bbt() call. * scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index bc06196d573..7f0c3b4c2a4 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -412,25 +412,6 @@ static void read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, } } -/* Scan a given block full */ -static int scan_block_full(struct mtd_info *mtd, struct nand_bbt_descr *bd, - loff_t offs, uint8_t *buf, size_t readlen, - int scanlen, int numpages) -{ - int ret, j; - - ret = scan_read_oob(mtd, buf, offs, readlen); - /* Ignore ECC errors when checking for BBM */ - if (ret && !mtd_is_bitflip_or_eccerr(ret)) - return ret; - - for (j = 0; j < numpages; j++, buf += scanlen) { - if (check_pattern(buf, scanlen, mtd->writesize, bd)) - return 1; - } - return 0; -} - /* Scan a given block partially */ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd, loff_t offs, uint8_t *buf, int numpages) @@ -477,24 +458,17 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip) { struct nand_chip *this = mtd->priv; - int i, numblocks, numpages, scanlen; + int i, numblocks, numpages; int startblock; loff_t from; - size_t readlen; pr_info("Scanning device for bad blocks\n"); - if (bd->options & NAND_BBT_SCANALLPAGES) - numpages = 1 << (this->bbt_erase_shift - this->page_shift); - else if (bd->options & NAND_BBT_SCAN2NDPAGE) + if (bd->options & NAND_BBT_SCAN2NDPAGE) numpages = 2; else numpages = 1; - /* We need only read few bytes from the OOB area */ - scanlen = 0; - readlen = bd->len; - if (chip == -1) { numblocks = mtd->size >> this->bbt_erase_shift; startblock = 0; @@ -519,12 +493,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, BUG_ON(bd->options & NAND_BBT_NO_OOB); - if (bd->options & NAND_BBT_SCANALLPAGES) - ret = scan_block_full(mtd, bd, from, buf, readlen, - scanlen, numpages); - else - ret = scan_block_fast(mtd, bd, from, buf, numpages); - + ret = scan_block_fast(mtd, bd, from, buf, numpages); if (ret < 0) return ret; @@ -559,7 +528,7 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr { struct nand_chip *this = mtd->priv; int i, chips; - int bits, startblock, block, dir; + int startblock, block, dir; int scanlen = mtd->writesize + mtd->oobsize; int bbtblocks; int blocktopage = this->bbt_erase_shift - this->page_shift; @@ -583,9 +552,6 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr bbtblocks = mtd->size >> this->bbt_erase_shift; } - /* Number of bits for each erase block in the bbt */ - bits = td->options & NAND_BBT_NRBITS_MSK; - for (i = 0; i < chips; i++) { /* Reset version information */ td->version[i] = 0; @@ -1316,6 +1282,7 @@ static int nand_create_badblock_pattern(struct nand_chip *this) int nand_default_bbt(struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; + int ret; /* Is a flash based bad block table requested? */ if (this->bbt_options & NAND_BBT_USE_FLASH) { @@ -1334,8 +1301,11 @@ int nand_default_bbt(struct mtd_info *mtd) this->bbt_md = NULL; } - if (!this->badblock_pattern) - nand_create_badblock_pattern(this); + if (!this->badblock_pattern) { + ret = nand_create_badblock_pattern(this); + if (ret) + return ret; + } return nand_scan_bbt(mtd, this->badblock_pattern); } @@ -1392,4 +1362,3 @@ int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs) } EXPORT_SYMBOL(nand_scan_bbt); -EXPORT_SYMBOL(nand_default_bbt); diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c index 053c9a2d47c..97c4c0216c9 100644 --- a/drivers/mtd/nand/nand_ecc.c +++ b/drivers/mtd/nand/nand_ecc.c @@ -506,7 +506,7 @@ int __nand_correct_data(unsigned char *buf, if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1) return 1; /* error in ECC data; no action needed */ - pr_err("%s: uncorrectable ECC error", __func__); + pr_err("%s: uncorrectable ECC error\n", __func__); return -1; } EXPORT_SYMBOL(__nand_correct_data); diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index a87b0a3afa3..3d7c89fc103 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -43,6 +43,9 @@ struct nand_flash_dev nand_flash_ids[] = { {"TC58NVG6D2 64G 3.3V 8-bit", { .id = {0x98, 0xde, 0x94, 0x82, 0x76, 0x56, 0x04, 0x20} }, SZ_8K, SZ_8K, SZ_2M, 0, 8, 640, NAND_ECC_INFO(40, SZ_1K) }, + {"SDTNRGAMA 64G 3.3V 8-bit", + { .id = {0x45, 0xde, 0x94, 0x93, 0x76, 0x50} }, + SZ_16K, SZ_8K, SZ_4M, 0, 6, 1280, NAND_ECC_INFO(40, SZ_1K) }, LEGACY_ID_NAND("NAND 4MiB 5V 8-bit", 0x6B, 4, SZ_8K, SP_OPTIONS), LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS), @@ -169,6 +172,8 @@ struct nand_manufacturers nand_manuf_ids[] = { {NAND_MFR_AMD, "AMD/Spansion"}, {NAND_MFR_MACRONIX, "Macronix"}, {NAND_MFR_EON, "Eon"}, + {NAND_MFR_SANDISK, "SanDisk"}, + {NAND_MFR_INTEL, "Intel"}, {0x0, "Unknown"} }; diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index bdc1d15369f..4f0d83648e5 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -575,12 +575,12 @@ static int alloc_device(struct nandsim *ns) cfile = filp_open(cache_file, O_CREAT | O_RDWR | O_LARGEFILE, 0600); if (IS_ERR(cfile)) return PTR_ERR(cfile); - if (!cfile->f_op || (!cfile->f_op->read && !cfile->f_op->aio_read)) { + if (!(cfile->f_mode & FMODE_CAN_READ)) { NS_ERR("alloc_device: cache file not readable\n"); err = -EINVAL; goto err_close; } - if (!cfile->f_op->write && !cfile->f_op->aio_write) { + if (!(cfile->f_mode & FMODE_CAN_WRITE)) { NS_ERR("alloc_device: cache file not writeable\n"); err = -EINVAL; goto err_close; @@ -2372,7 +2372,7 @@ static int __init ns_init_module(void) if ((retval = init_nandsim(nsmtd)) != 0) goto err_exit; - if ((retval = nand_default_bbt(nsmtd)) != 0) + if ((retval = chip->scan_bbt(nsmtd)) != 0) goto err_exit; if ((retval = parse_badblocks(nand, nsmtd)) != 0) diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 8e148f1478f..69eaba690a9 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -30,6 +30,7 @@ #include <linux/mtd/ndfc.h> #include <linux/slab.h> #include <linux/mtd/mtd.h> +#include <linux/of_address.h> #include <linux/of_platform.h> #include <asm/io.h> diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c index 52115151e4a..e8a5fffd6ab 100644 --- a/drivers/mtd/nand/nuc900_nand.c +++ b/drivers/mtd/nand/nuc900_nand.c @@ -10,7 +10,6 @@ */ #include <linux/slab.h> -#include <linux/init.h> #include <linux/module.h> #include <linux/interrupt.h> #include <linux/io.h> @@ -152,7 +151,8 @@ static void nuc900_nand_command_lp(struct mtd_info *mtd, unsigned int command, if (column != -1 || page_addr != -1) { if (column != -1) { - if (chip->options & NAND_BUSWIDTH_16) + if (chip->options & NAND_BUSWIDTH_16 && + !nand_opcode_8bits(command)) column >>= 1; write_addr_reg(nand, column); write_addr_reg(nand, column >> 8 | ENDADDR); @@ -225,7 +225,7 @@ static void nuc900_nand_enable(struct nuc900_nand *nand) val = __raw_readl(nand->reg + REG_FMICSR); if (!(val & NAND_EN)) - __raw_writel(val | NAND_EN, REG_FMICSR); + __raw_writel(val | NAND_EN, nand->reg + REG_FMICSR); val = __raw_readl(nand->reg + REG_SMCSR); @@ -241,12 +241,10 @@ static int nuc900_nand_probe(struct platform_device *pdev) { struct nuc900_nand *nuc900_nand; struct nand_chip *chip; - int retval; struct resource *res; - retval = 0; - - nuc900_nand = kzalloc(sizeof(struct nuc900_nand), GFP_KERNEL); + nuc900_nand = devm_kzalloc(&pdev->dev, sizeof(struct nuc900_nand), + GFP_KERNEL); if (!nuc900_nand) return -ENOMEM; chip = &(nuc900_nand->chip); @@ -255,11 +253,9 @@ static int nuc900_nand_probe(struct platform_device *pdev) nuc900_nand->mtd.owner = THIS_MODULE; spin_lock_init(&nuc900_nand->lock); - nuc900_nand->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(nuc900_nand->clk)) { - retval = -ENOENT; - goto fail1; - } + nuc900_nand->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(nuc900_nand->clk)) + return -ENOENT; clk_enable(nuc900_nand->clk); chip->cmdfunc = nuc900_nand_command_lp; @@ -272,57 +268,29 @@ static int nuc900_nand_probe(struct platform_device *pdev) chip->ecc.mode = NAND_ECC_SOFT; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - retval = -ENXIO; - goto fail1; - } - - if (!request_mem_region(res->start, resource_size(res), pdev->name)) { - retval = -EBUSY; - goto fail1; - } - - nuc900_nand->reg = ioremap(res->start, resource_size(res)); - if (!nuc900_nand->reg) { - retval = -ENOMEM; - goto fail2; - } + nuc900_nand->reg = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(nuc900_nand->reg)) + return PTR_ERR(nuc900_nand->reg); nuc900_nand_enable(nuc900_nand); - if (nand_scan(&(nuc900_nand->mtd), 1)) { - retval = -ENXIO; - goto fail3; - } + if (nand_scan(&(nuc900_nand->mtd), 1)) + return -ENXIO; mtd_device_register(&(nuc900_nand->mtd), partitions, ARRAY_SIZE(partitions)); platform_set_drvdata(pdev, nuc900_nand); - return retval; - -fail3: iounmap(nuc900_nand->reg); -fail2: release_mem_region(res->start, resource_size(res)); -fail1: kfree(nuc900_nand); - return retval; + return 0; } static int nuc900_nand_remove(struct platform_device *pdev) { struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev); - struct resource *res; nand_release(&nuc900_nand->mtd); - iounmap(nuc900_nand->reg); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - clk_disable(nuc900_nand->clk); - clk_put(nuc900_nand->clk); - - kfree(nuc900_nand); return 0; } diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 4ecf0e5fd48..f0ed92e210a 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -25,10 +25,8 @@ #include <linux/of.h> #include <linux/of_device.h> -#ifdef CONFIG_MTD_NAND_OMAP_BCH -#include <linux/bch.h> +#include <linux/mtd/nand_bch.h> #include <linux/platform_data/elm.h> -#endif #include <linux/platform_data/mtd-nand-omap2.h> @@ -120,14 +118,9 @@ #define OMAP24XX_DMA_GPMC 4 -#define BCH8_MAX_ERROR 8 /* upto 8 bit correctable */ -#define BCH4_MAX_ERROR 4 /* upto 4 bit correctable */ - #define SECTOR_BYTES 512 /* 4 bit padding to make byte aligned, 56 = 52 + 4 */ #define BCH4_BIT_PAD 4 -#define BCH8_ECC_MAX ((SECTOR_BYTES + BCH8_ECC_OOB_BYTES) * 8) -#define BCH4_ECC_MAX ((SECTOR_BYTES + BCH4_ECC_OOB_BYTES) * 8) /* GPMC ecc engine settings for read */ #define BCH_WRAPMODE_1 1 /* BCH wrap mode 1 */ @@ -141,7 +134,13 @@ #define BCH_ECC_SIZE0 0x0 /* ecc_size0 = 0, no oob protection */ #define BCH_ECC_SIZE1 0x20 /* ecc_size1 = 32 */ +#define BADBLOCK_MARKER_LENGTH 2 + #ifdef CONFIG_MTD_NAND_OMAP_BCH +static u_char bch16_vector[] = {0xf5, 0x24, 0x1c, 0xd0, 0x61, 0xb3, 0xf1, 0x55, + 0x2e, 0x2c, 0x86, 0xa3, 0xed, 0x36, 0x1b, 0x78, + 0x48, 0x76, 0xa9, 0x3b, 0x97, 0xd1, 0x7a, 0x93, + 0x07, 0x0e}; static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc, 0xac, 0x6b, 0xff, 0x99, 0x7b}; static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10}; @@ -149,17 +148,6 @@ static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10}; /* oob info generated runtime depending on ecc algorithm and layout selected */ static struct nand_ecclayout omap_oobinfo; -/* Define some generic bad / good block scan pattern which are used - * while scanning a device for factory marked good / bad blocks - */ -static uint8_t scan_ff_pattern[] = { 0xff }; -static struct nand_bbt_descr bb_descrip_flashbased = { - .options = NAND_BBT_SCANALLPAGES, - .offs = 0, - .len = 1, - .pattern = scan_ff_pattern, -}; - struct omap_nand_info { struct nand_hw_control controller; @@ -170,7 +158,7 @@ struct omap_nand_info { int gpmc_cs; unsigned long phys_base; - unsigned long mem_size; + enum omap_ecc ecc_opt; struct completion comp; struct dma_chan *dma; int gpmc_irq_fifo; @@ -182,14 +170,9 @@ struct omap_nand_info { u_char *buf; int buf_len; struct gpmc_nand_regs reg; - -#ifdef CONFIG_MTD_NAND_OMAP_BCH - struct bch_control *bch; - struct nand_ecclayout ecclayout; - bool is_elm_used; + /* fields specific for BCHx_HW ECC scheme */ struct device *elm_dev; struct device_node *of_node; -#endif }; /** @@ -1058,10 +1041,8 @@ static int omap_dev_ready(struct mtd_info *mtd) } } -#ifdef CONFIG_MTD_NAND_OMAP_BCH - /** - * omap3_enable_hwecc_bch - Program OMAP3 GPMC to perform BCH ECC correction + * omap_enable_hwecc_bch - Program GPMC to perform BCH ECC calculation * @mtd: MTD device structure * @mode: Read/Write mode * @@ -1072,50 +1053,86 @@ static int omap_dev_ready(struct mtd_info *mtd) * eccsize0 = 0 (no additional protected byte in spare area) * eccsize1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area) */ -static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode) +static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode) { - int nerrors; + unsigned int bch_type; unsigned int dev_width, nsectors; struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); + enum omap_ecc ecc_opt = info->ecc_opt; struct nand_chip *chip = mtd->priv; u32 val, wr_mode; unsigned int ecc_size1, ecc_size0; - /* Using wrapping mode 6 for writing */ - wr_mode = BCH_WRAPMODE_6; - - /* - * ECC engine enabled for valid ecc_size0 nibbles - * and disabled for ecc_size1 nibbles. - */ - ecc_size0 = BCH_ECC_SIZE0; - ecc_size1 = BCH_ECC_SIZE1; - - /* Perform ecc calculation on 512-byte sector */ - nsectors = 1; - - /* Update number of error correction */ - nerrors = info->nand.ecc.strength; - - /* Multi sector reading/writing for NAND flash with page size < 4096 */ - if (info->is_elm_used && (mtd->writesize <= 4096)) { + /* GPMC configurations for calculating ECC */ + switch (ecc_opt) { + case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: + bch_type = 0; + nsectors = 1; if (mode == NAND_ECC_READ) { - /* Using wrapping mode 1 for reading */ - wr_mode = BCH_WRAPMODE_1; - - /* - * ECC engine enabled for ecc_size0 nibbles - * and disabled for ecc_size1 nibbles. - */ - ecc_size0 = (nerrors == 8) ? - BCH8R_ECC_SIZE0 : BCH4R_ECC_SIZE0; - ecc_size1 = (nerrors == 8) ? - BCH8R_ECC_SIZE1 : BCH4R_ECC_SIZE1; + wr_mode = BCH_WRAPMODE_6; + ecc_size0 = BCH_ECC_SIZE0; + ecc_size1 = BCH_ECC_SIZE1; + } else { + wr_mode = BCH_WRAPMODE_6; + ecc_size0 = BCH_ECC_SIZE0; + ecc_size1 = BCH_ECC_SIZE1; } - - /* Perform ecc calculation for one page (< 4096) */ - nsectors = info->nand.ecc.steps; + break; + case OMAP_ECC_BCH4_CODE_HW: + bch_type = 0; + nsectors = chip->ecc.steps; + if (mode == NAND_ECC_READ) { + wr_mode = BCH_WRAPMODE_1; + ecc_size0 = BCH4R_ECC_SIZE0; + ecc_size1 = BCH4R_ECC_SIZE1; + } else { + wr_mode = BCH_WRAPMODE_6; + ecc_size0 = BCH_ECC_SIZE0; + ecc_size1 = BCH_ECC_SIZE1; + } + break; + case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: + bch_type = 1; + nsectors = 1; + if (mode == NAND_ECC_READ) { + wr_mode = BCH_WRAPMODE_6; + ecc_size0 = BCH_ECC_SIZE0; + ecc_size1 = BCH_ECC_SIZE1; + } else { + wr_mode = BCH_WRAPMODE_6; + ecc_size0 = BCH_ECC_SIZE0; + ecc_size1 = BCH_ECC_SIZE1; + } + break; + case OMAP_ECC_BCH8_CODE_HW: + bch_type = 1; + nsectors = chip->ecc.steps; + if (mode == NAND_ECC_READ) { + wr_mode = BCH_WRAPMODE_1; + ecc_size0 = BCH8R_ECC_SIZE0; + ecc_size1 = BCH8R_ECC_SIZE1; + } else { + wr_mode = BCH_WRAPMODE_6; + ecc_size0 = BCH_ECC_SIZE0; + ecc_size1 = BCH_ECC_SIZE1; + } + break; + case OMAP_ECC_BCH16_CODE_HW: + bch_type = 0x2; + nsectors = chip->ecc.steps; + if (mode == NAND_ECC_READ) { + wr_mode = 0x01; + ecc_size0 = 52; /* ECC bits in nibbles per sector */ + ecc_size1 = 0; /* non-ECC bits in nibbles per sector */ + } else { + wr_mode = 0x01; + ecc_size0 = 0; /* extra bits in nibbles per sector */ + ecc_size1 = 52; /* OOB bits in nibbles per sector */ + } + break; + default: + return; } writel(ECC1, info->reg.gpmc_ecc_control); @@ -1128,7 +1145,7 @@ static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode) /* BCH configuration */ val = ((1 << 16) | /* enable BCH */ - (((nerrors == 8) ? 1 : 0) << 12) | /* 8 or 4 bits */ + (bch_type << 12) | /* BCH4/BCH8/BCH16 */ (wr_mode << 8) | /* wrap mode */ (dev_width << 7) | /* bus width */ (((nsectors-1) & 0x7) << 4) | /* number of sectors */ @@ -1141,127 +1158,40 @@ static void omap3_enable_hwecc_bch(struct mtd_info *mtd, int mode) writel(ECCCLEAR | ECC1, info->reg.gpmc_ecc_control); } -/** - * omap3_calculate_ecc_bch4 - Generate 7 bytes of ECC bytes - * @mtd: MTD device structure - * @dat: The pointer to data on which ecc is computed - * @ecc_code: The ecc_code buffer - */ -static int omap3_calculate_ecc_bch4(struct mtd_info *mtd, const u_char *dat, - u_char *ecc_code) -{ - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - unsigned long nsectors, val1, val2; - int i; - - nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; - - for (i = 0; i < nsectors; i++) { - - /* Read hw-computed remainder */ - val1 = readl(info->reg.gpmc_bch_result0[i]); - val2 = readl(info->reg.gpmc_bch_result1[i]); - - /* - * Add constant polynomial to remainder, in order to get an ecc - * sequence of 0xFFs for a buffer filled with 0xFFs; and - * left-justify the resulting polynomial. - */ - *ecc_code++ = 0x28 ^ ((val2 >> 12) & 0xFF); - *ecc_code++ = 0x13 ^ ((val2 >> 4) & 0xFF); - *ecc_code++ = 0xcc ^ (((val2 & 0xF) << 4)|((val1 >> 28) & 0xF)); - *ecc_code++ = 0x39 ^ ((val1 >> 20) & 0xFF); - *ecc_code++ = 0x96 ^ ((val1 >> 12) & 0xFF); - *ecc_code++ = 0xac ^ ((val1 >> 4) & 0xFF); - *ecc_code++ = 0x7f ^ ((val1 & 0xF) << 4); - } - - return 0; -} - -/** - * omap3_calculate_ecc_bch8 - Generate 13 bytes of ECC bytes - * @mtd: MTD device structure - * @dat: The pointer to data on which ecc is computed - * @ecc_code: The ecc_code buffer - */ -static int omap3_calculate_ecc_bch8(struct mtd_info *mtd, const u_char *dat, - u_char *ecc_code) -{ - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - unsigned long nsectors, val1, val2, val3, val4; - int i; - - nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; - - for (i = 0; i < nsectors; i++) { - - /* Read hw-computed remainder */ - val1 = readl(info->reg.gpmc_bch_result0[i]); - val2 = readl(info->reg.gpmc_bch_result1[i]); - val3 = readl(info->reg.gpmc_bch_result2[i]); - val4 = readl(info->reg.gpmc_bch_result3[i]); - - /* - * Add constant polynomial to remainder, in order to get an ecc - * sequence of 0xFFs for a buffer filled with 0xFFs. - */ - *ecc_code++ = 0xef ^ (val4 & 0xFF); - *ecc_code++ = 0x51 ^ ((val3 >> 24) & 0xFF); - *ecc_code++ = 0x2e ^ ((val3 >> 16) & 0xFF); - *ecc_code++ = 0x09 ^ ((val3 >> 8) & 0xFF); - *ecc_code++ = 0xed ^ (val3 & 0xFF); - *ecc_code++ = 0x93 ^ ((val2 >> 24) & 0xFF); - *ecc_code++ = 0x9a ^ ((val2 >> 16) & 0xFF); - *ecc_code++ = 0xc2 ^ ((val2 >> 8) & 0xFF); - *ecc_code++ = 0x97 ^ (val2 & 0xFF); - *ecc_code++ = 0x79 ^ ((val1 >> 24) & 0xFF); - *ecc_code++ = 0xe5 ^ ((val1 >> 16) & 0xFF); - *ecc_code++ = 0x24 ^ ((val1 >> 8) & 0xFF); - *ecc_code++ = 0xb5 ^ (val1 & 0xFF); - } - - return 0; -} +static u8 bch4_polynomial[] = {0x28, 0x13, 0xcc, 0x39, 0x96, 0xac, 0x7f}; +static u8 bch8_polynomial[] = {0xef, 0x51, 0x2e, 0x09, 0xed, 0x93, 0x9a, 0xc2, + 0x97, 0x79, 0xe5, 0x24, 0xb5}; /** - * omap3_calculate_ecc_bch - Generate bytes of ECC bytes + * omap_calculate_ecc_bch - Generate bytes of ECC bytes * @mtd: MTD device structure * @dat: The pointer to data on which ecc is computed * @ecc_code: The ecc_code buffer * * Support calculating of BCH4/8 ecc vectors for the page */ -static int omap3_calculate_ecc_bch(struct mtd_info *mtd, const u_char *dat, - u_char *ecc_code) +static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd, + const u_char *dat, u_char *ecc_calc) { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); + int eccbytes = info->nand.ecc.bytes; + struct gpmc_nand_regs *gpmc_regs = &info->reg; + u8 *ecc_code; unsigned long nsectors, bch_val1, bch_val2, bch_val3, bch_val4; - int i, eccbchtsel; + u32 val; + int i, j; nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1; - /* - * find BCH scheme used - * 0 -> BCH4 - * 1 -> BCH8 - */ - eccbchtsel = ((readl(info->reg.gpmc_ecc_config) >> 12) & 0x3); - for (i = 0; i < nsectors; i++) { - - /* Read hw-computed remainder */ - bch_val1 = readl(info->reg.gpmc_bch_result0[i]); - bch_val2 = readl(info->reg.gpmc_bch_result1[i]); - if (eccbchtsel) { - bch_val3 = readl(info->reg.gpmc_bch_result2[i]); - bch_val4 = readl(info->reg.gpmc_bch_result3[i]); - } - - if (eccbchtsel) { - /* BCH8 ecc scheme */ + ecc_code = ecc_calc; + switch (info->ecc_opt) { + case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: + case OMAP_ECC_BCH8_CODE_HW: + bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]); + bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]); + bch_val3 = readl(gpmc_regs->gpmc_bch_result2[i]); + bch_val4 = readl(gpmc_regs->gpmc_bch_result3[i]); *ecc_code++ = (bch_val4 & 0xFF); *ecc_code++ = ((bch_val3 >> 24) & 0xFF); *ecc_code++ = ((bch_val3 >> 16) & 0xFF); @@ -1275,14 +1205,11 @@ static int omap3_calculate_ecc_bch(struct mtd_info *mtd, const u_char *dat, *ecc_code++ = ((bch_val1 >> 16) & 0xFF); *ecc_code++ = ((bch_val1 >> 8) & 0xFF); *ecc_code++ = (bch_val1 & 0xFF); - /* - * Setting 14th byte to zero to handle - * erased page & maintain compatibility - * with RBL - */ - *ecc_code++ = 0x0; - } else { - /* BCH4 ecc scheme */ + break; + case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: + case OMAP_ECC_BCH4_CODE_HW: + bch_val1 = readl(gpmc_regs->gpmc_bch_result0[i]); + bch_val2 = readl(gpmc_regs->gpmc_bch_result1[i]); *ecc_code++ = ((bch_val2 >> 12) & 0xFF); *ecc_code++ = ((bch_val2 >> 4) & 0xFF); *ecc_code++ = ((bch_val2 & 0xF) << 4) | @@ -1291,17 +1218,81 @@ static int omap3_calculate_ecc_bch(struct mtd_info *mtd, const u_char *dat, *ecc_code++ = ((bch_val1 >> 12) & 0xFF); *ecc_code++ = ((bch_val1 >> 4) & 0xFF); *ecc_code++ = ((bch_val1 & 0xF) << 4); - /* - * Setting 8th byte to zero to handle - * erased page - */ - *ecc_code++ = 0x0; + break; + case OMAP_ECC_BCH16_CODE_HW: + val = readl(gpmc_regs->gpmc_bch_result6[i]); + ecc_code[0] = ((val >> 8) & 0xFF); + ecc_code[1] = ((val >> 0) & 0xFF); + val = readl(gpmc_regs->gpmc_bch_result5[i]); + ecc_code[2] = ((val >> 24) & 0xFF); + ecc_code[3] = ((val >> 16) & 0xFF); + ecc_code[4] = ((val >> 8) & 0xFF); + ecc_code[5] = ((val >> 0) & 0xFF); + val = readl(gpmc_regs->gpmc_bch_result4[i]); + ecc_code[6] = ((val >> 24) & 0xFF); + ecc_code[7] = ((val >> 16) & 0xFF); + ecc_code[8] = ((val >> 8) & 0xFF); + ecc_code[9] = ((val >> 0) & 0xFF); + val = readl(gpmc_regs->gpmc_bch_result3[i]); + ecc_code[10] = ((val >> 24) & 0xFF); + ecc_code[11] = ((val >> 16) & 0xFF); + ecc_code[12] = ((val >> 8) & 0xFF); + ecc_code[13] = ((val >> 0) & 0xFF); + val = readl(gpmc_regs->gpmc_bch_result2[i]); + ecc_code[14] = ((val >> 24) & 0xFF); + ecc_code[15] = ((val >> 16) & 0xFF); + ecc_code[16] = ((val >> 8) & 0xFF); + ecc_code[17] = ((val >> 0) & 0xFF); + val = readl(gpmc_regs->gpmc_bch_result1[i]); + ecc_code[18] = ((val >> 24) & 0xFF); + ecc_code[19] = ((val >> 16) & 0xFF); + ecc_code[20] = ((val >> 8) & 0xFF); + ecc_code[21] = ((val >> 0) & 0xFF); + val = readl(gpmc_regs->gpmc_bch_result0[i]); + ecc_code[22] = ((val >> 24) & 0xFF); + ecc_code[23] = ((val >> 16) & 0xFF); + ecc_code[24] = ((val >> 8) & 0xFF); + ecc_code[25] = ((val >> 0) & 0xFF); + break; + default: + return -EINVAL; + } + + /* ECC scheme specific syndrome customizations */ + switch (info->ecc_opt) { + case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: + /* Add constant polynomial to remainder, so that + * ECC of blank pages results in 0x0 on reading back */ + for (j = 0; j < eccbytes; j++) + ecc_calc[j] ^= bch4_polynomial[j]; + break; + case OMAP_ECC_BCH4_CODE_HW: + /* Set 8th ECC byte as 0x0 for ROM compatibility */ + ecc_calc[eccbytes - 1] = 0x0; + break; + case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: + /* Add constant polynomial to remainder, so that + * ECC of blank pages results in 0x0 on reading back */ + for (j = 0; j < eccbytes; j++) + ecc_calc[j] ^= bch8_polynomial[j]; + break; + case OMAP_ECC_BCH8_CODE_HW: + /* Set 14th ECC byte as 0x0 for ROM compatibility */ + ecc_calc[eccbytes - 1] = 0x0; + break; + case OMAP_ECC_BCH16_CODE_HW: + break; + default: + return -EINVAL; } + + ecc_calc += eccbytes; } return 0; } +#ifdef CONFIG_MTD_NAND_OMAP_BCH /** * erased_sector_bitflips - count bit flips * @data: data sector buffer @@ -1349,55 +1340,50 @@ static int erased_sector_bitflips(u_char *data, u_char *oob, * @calc_ecc: ecc read from HW ECC registers * * Calculated ecc vector reported as zero in case of non-error pages. - * In case of error/erased pages non-zero error vector is reported. - * In case of non-zero ecc vector, check read_ecc at fixed offset - * (x = 13/7 in case of BCH8/4 == 0) to find page programmed or not. - * To handle bit flips in this data, count the number of 0's in - * read_ecc[x] and check if it greater than 4. If it is less, it is - * programmed page, else erased page. - * - * 1. If page is erased, check with standard ecc vector (ecc vector - * for erased page to find any bit flip). If check fails, bit flip - * is present in erased page. Count the bit flips in erased page and - * if it falls under correctable level, report page with 0xFF and - * update the correctable bit information. - * 2. If error is reported on programmed page, update elm error - * vector and correct the page with ELM error correction routine. - * + * In case of non-zero ecc vector, first filter out erased-pages, and + * then process data via ELM to detect bit-flips. */ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, u_char *read_ecc, u_char *calc_ecc) { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); + struct nand_ecc_ctrl *ecc = &info->nand.ecc; int eccsteps = info->nand.ecc.steps; int i , j, stat = 0; - int eccsize, eccflag, ecc_vector_size; + int eccflag, actual_eccbytes; struct elm_errorvec err_vec[ERROR_VECTOR_MAX]; u_char *ecc_vec = calc_ecc; u_char *spare_ecc = read_ecc; u_char *erased_ecc_vec; - enum bch_ecc type; + u_char *buf; + int bitflip_count; bool is_error_reported = false; + u32 bit_pos, byte_pos, error_max, pos; + int err; - /* Initialize elm error vector to zero */ - memset(err_vec, 0, sizeof(err_vec)); - - if (info->nand.ecc.strength == BCH8_MAX_ERROR) { - type = BCH8_ECC; - erased_ecc_vec = bch8_vector; - } else { - type = BCH4_ECC; + switch (info->ecc_opt) { + case OMAP_ECC_BCH4_CODE_HW: + /* omit 7th ECC byte reserved for ROM code compatibility */ + actual_eccbytes = ecc->bytes - 1; erased_ecc_vec = bch4_vector; + break; + case OMAP_ECC_BCH8_CODE_HW: + /* omit 14th ECC byte reserved for ROM code compatibility */ + actual_eccbytes = ecc->bytes - 1; + erased_ecc_vec = bch8_vector; + break; + case OMAP_ECC_BCH16_CODE_HW: + actual_eccbytes = ecc->bytes; + erased_ecc_vec = bch16_vector; + break; + default: + pr_err("invalid driver configuration\n"); + return -EINVAL; } - ecc_vector_size = info->nand.ecc.bytes; - - /* - * Remove extra byte padding for BCH8 RBL - * compatibility and erased page handling - */ - eccsize = ecc_vector_size - 1; + /* Initialize elm error vector to zero */ + memset(err_vec, 0, sizeof(err_vec)); for (i = 0; i < eccsteps ; i++) { eccflag = 0; /* initialize eccflag */ @@ -1406,8 +1392,7 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, * Check any error reported, * In case of error, non zero ecc reported. */ - - for (j = 0; (j < eccsize); j++) { + for (j = 0; j < actual_eccbytes; j++) { if (calc_ecc[j] != 0) { eccflag = 1; /* non zero ecc, error present */ break; @@ -1415,76 +1400,73 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, } if (eccflag == 1) { - /* - * Set threshold to minimum of 4, half of ecc.strength/2 - * to allow max bit flip in byte to 4 - */ - unsigned int threshold = min_t(unsigned int, 4, - info->nand.ecc.strength / 2); - - /* - * Check data area is programmed by counting - * number of 0's at fixed offset in spare area. - * Checking count of 0's against threshold. - * In case programmed page expects at least threshold - * zeros in byte. - * If zeros are less than threshold for programmed page/ - * zeros are more than threshold erased page, either - * case page reported as uncorrectable. - */ - if (hweight8(~read_ecc[eccsize]) >= threshold) { + if (memcmp(calc_ecc, erased_ecc_vec, + actual_eccbytes) == 0) { /* - * Update elm error vector as - * data area is programmed + * calc_ecc[] matches pattern for ECC(all 0xff) + * so this is definitely an erased-page */ - err_vec[i].error_reported = true; - is_error_reported = true; } else { - /* Error reported in erased page */ - int bitflip_count; - u_char *buf = &data[info->nand.ecc.size * i]; - - if (memcmp(calc_ecc, erased_ecc_vec, eccsize)) { - bitflip_count = erased_sector_bitflips( - buf, read_ecc, info); - - if (bitflip_count) - stat += bitflip_count; - else - return -EINVAL; + buf = &data[info->nand.ecc.size * i]; + /* + * count number of 0-bits in read_buf. + * This check can be removed once a similar + * check is introduced in generic NAND driver + */ + bitflip_count = erased_sector_bitflips( + buf, read_ecc, info); + if (bitflip_count) { + /* + * number of 0-bits within ECC limits + * So this may be an erased-page + */ + stat += bitflip_count; + } else { + /* + * Too many 0-bits. It may be a + * - programmed-page, OR + * - erased-page with many bit-flips + * So this page requires check by ELM + */ + err_vec[i].error_reported = true; + is_error_reported = true; } } } /* Update the ecc vector */ - calc_ecc += ecc_vector_size; - read_ecc += ecc_vector_size; + calc_ecc += ecc->bytes; + read_ecc += ecc->bytes; } /* Check if any error reported */ if (!is_error_reported) - return 0; + return stat; /* Decode BCH error using ELM module */ elm_decode_bch_error_page(info->elm_dev, ecc_vec, err_vec); + err = 0; for (i = 0; i < eccsteps; i++) { - if (err_vec[i].error_reported) { + if (err_vec[i].error_uncorrectable) { + pr_err("nand: uncorrectable bit-flips found\n"); + err = -EBADMSG; + } else if (err_vec[i].error_reported) { for (j = 0; j < err_vec[i].error_count; j++) { - u32 bit_pos, byte_pos, error_max, pos; - - if (type == BCH8_ECC) - error_max = BCH8_ECC_MAX; - else - error_max = BCH4_ECC_MAX; - - if (info->nand.ecc.strength == BCH8_MAX_ERROR) - pos = err_vec[i].error_loc[j]; - else - /* Add 4 to take care 4 bit padding */ + switch (info->ecc_opt) { + case OMAP_ECC_BCH4_CODE_HW: + /* Add 4 bits to take care of padding */ pos = err_vec[i].error_loc[j] + BCH4_BIT_PAD; - + break; + case OMAP_ECC_BCH8_CODE_HW: + case OMAP_ECC_BCH16_CODE_HW: + pos = err_vec[i].error_loc[j]; + break; + default: + return -EINVAL; + } + error_max = (ecc->size + actual_eccbytes) * 8; /* Calculate bit position of error */ bit_pos = pos % 8; @@ -1492,13 +1474,22 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, byte_pos = (error_max - pos - 1) / 8; if (pos < error_max) { - if (byte_pos < 512) + if (byte_pos < 512) { + pr_debug("bitflip@dat[%d]=%x\n", + byte_pos, data[byte_pos]); data[byte_pos] ^= 1 << bit_pos; - else + } else { + pr_debug("bitflip@oob[%d]=%x\n", + (byte_pos - 512), + spare_ecc[byte_pos - 512]); spare_ecc[byte_pos - 512] ^= 1 << bit_pos; + } + } else { + pr_err("invalid bit-flip @ %d:%d\n", + byte_pos, bit_pos); + err = -EBADMSG; } - /* else, not interested to correct ecc */ } } @@ -1506,48 +1497,11 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data, stat += err_vec[i].error_count; /* Update page data with sector size */ - data += info->nand.ecc.size; - spare_ecc += ecc_vector_size; + data += ecc->size; + spare_ecc += ecc->bytes; } - for (i = 0; i < eccsteps; i++) - /* Return error if uncorrectable error present */ - if (err_vec[i].error_uncorrectable) - return -EINVAL; - - return stat; -} - -/** - * omap3_correct_data_bch - Decode received data and correct errors - * @mtd: MTD device structure - * @data: page data - * @read_ecc: ecc read from nand flash - * @calc_ecc: ecc read from HW ECC registers - */ -static int omap3_correct_data_bch(struct mtd_info *mtd, u_char *data, - u_char *read_ecc, u_char *calc_ecc) -{ - int i, count; - /* cannot correct more than 8 errors */ - unsigned int errloc[8]; - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - - count = decode_bch(info->bch, NULL, 512, read_ecc, calc_ecc, NULL, - errloc); - if (count > 0) { - /* correct errors */ - for (i = 0; i < count; i++) { - /* correct data only, not ecc bytes */ - if (errloc[i] < 8*512) - data[errloc[i]/8] ^= 1 << (errloc[i] & 7); - pr_debug("corrected bitflip %u\n", errloc[i]); - } - } else if (count < 0) { - pr_err("ecc unrecoverable error\n"); - } - return count; + return (err) ? err : stat; } /** @@ -1637,197 +1591,48 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip, } /** - * omap3_free_bch - Release BCH ecc resources - * @mtd: MTD device structure - */ -static void omap3_free_bch(struct mtd_info *mtd) -{ - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - if (info->bch) { - free_bch(info->bch); - info->bch = NULL; - } -} - -/** - * omap3_init_bch - Initialize BCH ECC - * @mtd: MTD device structure - * @ecc_opt: OMAP ECC mode (OMAP_ECC_BCH4_CODE_HW or OMAP_ECC_BCH8_CODE_HW) - */ -static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt) -{ - int max_errors; - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); -#ifdef CONFIG_MTD_NAND_OMAP_BCH8 - const int hw_errors = BCH8_MAX_ERROR; -#else - const int hw_errors = BCH4_MAX_ERROR; -#endif - enum bch_ecc bch_type; - const __be32 *parp; - int lenp; - struct device_node *elm_node; - - info->bch = NULL; - - max_errors = (ecc_opt == OMAP_ECC_BCH8_CODE_HW) ? - BCH8_MAX_ERROR : BCH4_MAX_ERROR; - if (max_errors != hw_errors) { - pr_err("cannot configure %d-bit BCH ecc, only %d-bit supported", - max_errors, hw_errors); - goto fail; - } - - info->nand.ecc.size = 512; - info->nand.ecc.hwctl = omap3_enable_hwecc_bch; - info->nand.ecc.mode = NAND_ECC_HW; - info->nand.ecc.strength = max_errors; - - if (hw_errors == BCH8_MAX_ERROR) - bch_type = BCH8_ECC; - else - bch_type = BCH4_ECC; - - /* Detect availability of ELM module */ - parp = of_get_property(info->of_node, "elm_id", &lenp); - if ((parp == NULL) && (lenp != (sizeof(void *) * 2))) { - pr_err("Missing elm_id property, fall back to Software BCH\n"); - info->is_elm_used = false; - } else { - struct platform_device *pdev; - - elm_node = of_find_node_by_phandle(be32_to_cpup(parp)); - pdev = of_find_device_by_node(elm_node); - info->elm_dev = &pdev->dev; - - if (elm_config(info->elm_dev, bch_type) == 0) - info->is_elm_used = true; - } - - if (info->is_elm_used && (mtd->writesize <= 4096)) { - - if (hw_errors == BCH8_MAX_ERROR) - info->nand.ecc.bytes = BCH8_SIZE; - else - info->nand.ecc.bytes = BCH4_SIZE; - - info->nand.ecc.correct = omap_elm_correct_data; - info->nand.ecc.calculate = omap3_calculate_ecc_bch; - info->nand.ecc.read_page = omap_read_page_bch; - info->nand.ecc.write_page = omap_write_page_bch; - } else { - /* - * software bch library is only used to detect and - * locate errors - */ - info->bch = init_bch(13, max_errors, - 0x201b /* hw polynomial */); - if (!info->bch) - goto fail; - - info->nand.ecc.correct = omap3_correct_data_bch; - - /* - * The number of corrected errors in an ecc block that will - * trigger block scrubbing defaults to the ecc strength (4 or 8) - * Set mtd->bitflip_threshold here to define a custom threshold. - */ - - if (max_errors == 8) { - info->nand.ecc.bytes = 13; - info->nand.ecc.calculate = omap3_calculate_ecc_bch8; - } else { - info->nand.ecc.bytes = 7; - info->nand.ecc.calculate = omap3_calculate_ecc_bch4; - } - } - - pr_info("enabling NAND BCH ecc with %d-bit correction\n", max_errors); - return 0; -fail: - omap3_free_bch(mtd); - return -1; -} - -/** - * omap3_init_bch_tail - Build an oob layout for BCH ECC correction. - * @mtd: MTD device structure + * is_elm_present - checks for presence of ELM module by scanning DT nodes + * @omap_nand_info: NAND device structure containing platform data + * @bch_type: 0x0=BCH4, 0x1=BCH8, 0x2=BCH16 */ -static int omap3_init_bch_tail(struct mtd_info *mtd) +static int is_elm_present(struct omap_nand_info *info, + struct device_node *elm_node, enum bch_ecc bch_type) { - int i, steps, offset; - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - struct nand_ecclayout *layout = &info->ecclayout; - - /* build oob layout */ - steps = mtd->writesize/info->nand.ecc.size; - layout->eccbytes = steps*info->nand.ecc.bytes; - - /* do not bother creating special oob layouts for small page devices */ - if (mtd->oobsize < 64) { - pr_err("BCH ecc is not supported on small page devices\n"); - goto fail; + struct platform_device *pdev; + struct nand_ecc_ctrl *ecc = &info->nand.ecc; + int err; + /* check whether elm-id is passed via DT */ + if (!elm_node) { + pr_err("nand: error: ELM DT node not found\n"); + return -ENODEV; } - - /* reserve 2 bytes for bad block marker */ - if (layout->eccbytes+2 > mtd->oobsize) { - pr_err("no oob layout available for oobsize %d eccbytes %u\n", - mtd->oobsize, layout->eccbytes); - goto fail; + pdev = of_find_device_by_node(elm_node); + /* check whether ELM device is registered */ + if (!pdev) { + pr_err("nand: error: ELM device not found\n"); + return -ENODEV; } + /* ELM module available, now configure it */ + info->elm_dev = &pdev->dev; + err = elm_config(info->elm_dev, bch_type, + (info->mtd.writesize / ecc->size), ecc->size, ecc->bytes); - /* ECC layout compatible with RBL for BCH8 */ - if (info->is_elm_used && (info->nand.ecc.bytes == BCH8_SIZE)) - offset = 2; - else - offset = mtd->oobsize - layout->eccbytes; - - /* put ecc bytes at oob tail */ - for (i = 0; i < layout->eccbytes; i++) - layout->eccpos[i] = offset + i; - - if (info->is_elm_used && (info->nand.ecc.bytes == BCH8_SIZE)) - layout->oobfree[0].offset = 2 + layout->eccbytes * steps; - else - layout->oobfree[0].offset = 2; - - layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes; - info->nand.ecc.layout = layout; - - if (!(info->nand.options & NAND_BUSWIDTH_16)) - info->nand.badblock_pattern = &bb_descrip_flashbased; - return 0; -fail: - omap3_free_bch(mtd); - return -1; -} - -#else -static int omap3_init_bch(struct mtd_info *mtd, int ecc_opt) -{ - pr_err("CONFIG_MTD_NAND_OMAP_BCH is not enabled\n"); - return -1; -} -static int omap3_init_bch_tail(struct mtd_info *mtd) -{ - return -1; -} -static void omap3_free_bch(struct mtd_info *mtd) -{ + return err; } -#endif /* CONFIG_MTD_NAND_OMAP_BCH */ +#endif /* CONFIG_MTD_NAND_ECC_BCH */ static int omap_nand_probe(struct platform_device *pdev) { struct omap_nand_info *info; struct omap_nand_platform_data *pdata; + struct mtd_info *mtd; + struct nand_chip *nand_chip; + struct nand_ecclayout *ecclayout; int err; - int i, offset; - dma_cap_mask_t mask; - unsigned sig; + int i; + dma_cap_mask_t mask; + unsigned sig; + unsigned oob_index; struct resource *res; struct mtd_part_parser_data ppdata = {}; @@ -1837,7 +1642,8 @@ static int omap_nand_probe(struct platform_device *pdev) return -ENODEV; } - info = kzalloc(sizeof(struct omap_nand_info), GFP_KERNEL); + info = devm_kzalloc(&pdev->dev, sizeof(struct omap_nand_info), + GFP_KERNEL); if (!info) return -ENOMEM; @@ -1846,47 +1652,30 @@ static int omap_nand_probe(struct platform_device *pdev) spin_lock_init(&info->controller.lock); init_waitqueue_head(&info->controller.wq); - info->pdev = pdev; - + info->pdev = pdev; info->gpmc_cs = pdata->cs; info->reg = pdata->reg; - - info->mtd.priv = &info->nand; - info->mtd.name = dev_name(&pdev->dev); - info->mtd.owner = THIS_MODULE; - - info->nand.options = pdata->devsize; - info->nand.options |= NAND_SKIP_BBTSCAN; -#ifdef CONFIG_MTD_NAND_OMAP_BCH info->of_node = pdata->of_node; -#endif + info->ecc_opt = pdata->ecc_opt; + mtd = &info->mtd; + mtd->priv = &info->nand; + mtd->name = dev_name(&pdev->dev); + mtd->owner = THIS_MODULE; + nand_chip = &info->nand; + nand_chip->ecc.priv = NULL; + nand_chip->options |= NAND_SKIP_BBTSCAN; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - err = -EINVAL; - dev_err(&pdev->dev, "error getting memory resource\n"); - goto out_free_info; - } + nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(nand_chip->IO_ADDR_R)) + return PTR_ERR(nand_chip->IO_ADDR_R); info->phys_base = res->start; - info->mem_size = resource_size(res); - - if (!request_mem_region(info->phys_base, info->mem_size, - pdev->dev.driver->name)) { - err = -EBUSY; - goto out_free_info; - } - - info->nand.IO_ADDR_R = ioremap(info->phys_base, info->mem_size); - if (!info->nand.IO_ADDR_R) { - err = -ENOMEM; - goto out_release_mem_region; - } - info->nand.controller = &info->controller; + nand_chip->controller = &info->controller; - info->nand.IO_ADDR_W = info->nand.IO_ADDR_R; - info->nand.cmd_ctrl = omap_hwcontrol; + nand_chip->IO_ADDR_W = nand_chip->IO_ADDR_R; + nand_chip->cmd_ctrl = omap_hwcontrol; /* * If RDY/BSY line is connected to OMAP then use the omap ready @@ -1896,27 +1685,37 @@ static int omap_nand_probe(struct platform_device *pdev) * device and read status register until you get a failure or success */ if (pdata->dev_ready) { - info->nand.dev_ready = omap_dev_ready; - info->nand.chip_delay = 0; + nand_chip->dev_ready = omap_dev_ready; + nand_chip->chip_delay = 0; } else { - info->nand.waitfunc = omap_wait; - info->nand.chip_delay = 50; + nand_chip->waitfunc = omap_wait; + nand_chip->chip_delay = 50; + } + + /* scan NAND device connected to chip controller */ + nand_chip->options |= pdata->devsize & NAND_BUSWIDTH_16; + if (nand_scan_ident(mtd, 1, NULL)) { + pr_err("nand device scan failed, may be bus-width mismatch\n"); + err = -ENXIO; + goto return_error; + } + + /* check for small page devices */ + if ((mtd->oobsize < 64) && (pdata->ecc_opt != OMAP_ECC_HAM1_CODE_HW)) { + pr_err("small page devices are not supported\n"); + err = -EINVAL; + goto return_error; } + /* re-populate low-level callbacks based on xfer modes */ switch (pdata->xfer_type) { case NAND_OMAP_PREFETCH_POLLED: - info->nand.read_buf = omap_read_buf_pref; - info->nand.write_buf = omap_write_buf_pref; + nand_chip->read_buf = omap_read_buf_pref; + nand_chip->write_buf = omap_write_buf_pref; break; case NAND_OMAP_POLLED: - if (info->nand.options & NAND_BUSWIDTH_16) { - info->nand.read_buf = omap_read_buf16; - info->nand.write_buf = omap_write_buf16; - } else { - info->nand.read_buf = omap_read_buf8; - info->nand.write_buf = omap_write_buf8; - } + /* Use nand_base defaults for {read,write}_buf */ break; case NAND_OMAP_PREFETCH_DMA: @@ -1927,7 +1726,7 @@ static int omap_nand_probe(struct platform_device *pdev) if (!info->dma) { dev_err(&pdev->dev, "DMA engine request failed\n"); err = -ENXIO; - goto out_release_mem_region; + goto return_error; } else { struct dma_slave_config cfg; @@ -1942,10 +1741,10 @@ static int omap_nand_probe(struct platform_device *pdev) if (err) { dev_err(&pdev->dev, "DMA engine slave config failed: %d\n", err); - goto out_release_mem_region; + goto return_error; } - info->nand.read_buf = omap_read_buf_dma_pref; - info->nand.write_buf = omap_write_buf_dma_pref; + nand_chip->read_buf = omap_read_buf_dma_pref; + nand_chip->write_buf = omap_write_buf_dma_pref; } break; @@ -1954,34 +1753,36 @@ static int omap_nand_probe(struct platform_device *pdev) if (info->gpmc_irq_fifo <= 0) { dev_err(&pdev->dev, "error getting fifo irq\n"); err = -ENODEV; - goto out_release_mem_region; + goto return_error; } - err = request_irq(info->gpmc_irq_fifo, omap_nand_irq, - IRQF_SHARED, "gpmc-nand-fifo", info); + err = devm_request_irq(&pdev->dev, info->gpmc_irq_fifo, + omap_nand_irq, IRQF_SHARED, + "gpmc-nand-fifo", info); if (err) { dev_err(&pdev->dev, "requesting irq(%d) error:%d", info->gpmc_irq_fifo, err); info->gpmc_irq_fifo = 0; - goto out_release_mem_region; + goto return_error; } info->gpmc_irq_count = platform_get_irq(pdev, 1); if (info->gpmc_irq_count <= 0) { dev_err(&pdev->dev, "error getting count irq\n"); err = -ENODEV; - goto out_release_mem_region; + goto return_error; } - err = request_irq(info->gpmc_irq_count, omap_nand_irq, - IRQF_SHARED, "gpmc-nand-count", info); + err = devm_request_irq(&pdev->dev, info->gpmc_irq_count, + omap_nand_irq, IRQF_SHARED, + "gpmc-nand-count", info); if (err) { dev_err(&pdev->dev, "requesting irq(%d) error:%d", info->gpmc_irq_count, err); info->gpmc_irq_count = 0; - goto out_release_mem_region; + goto return_error; } - info->nand.read_buf = omap_read_buf_irq_pref; - info->nand.write_buf = omap_write_buf_irq_pref; + nand_chip->read_buf = omap_read_buf_irq_pref; + nand_chip->write_buf = omap_write_buf_irq_pref; break; @@ -1989,117 +1790,275 @@ static int omap_nand_probe(struct platform_device *pdev) dev_err(&pdev->dev, "xfer_type(%d) not supported!\n", pdata->xfer_type); err = -EINVAL; - goto out_release_mem_region; + goto return_error; } - /* select the ecc type */ - if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_DEFAULT) - info->nand.ecc.mode = NAND_ECC_SOFT; - else if ((pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW) || - (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE)) { - info->nand.ecc.bytes = 3; - info->nand.ecc.size = 512; - info->nand.ecc.strength = 1; - info->nand.ecc.calculate = omap_calculate_ecc; - info->nand.ecc.hwctl = omap_enable_hwecc; - info->nand.ecc.correct = omap_correct_data; - info->nand.ecc.mode = NAND_ECC_HW; - } else if ((pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) || - (pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW)) { - err = omap3_init_bch(&info->mtd, pdata->ecc_opt); - if (err) { + /* populate MTD interface based on ECC scheme */ + nand_chip->ecc.layout = &omap_oobinfo; + ecclayout = &omap_oobinfo; + switch (info->ecc_opt) { + case OMAP_ECC_HAM1_CODE_HW: + pr_info("nand: using OMAP_ECC_HAM1_CODE_HW\n"); + nand_chip->ecc.mode = NAND_ECC_HW; + nand_chip->ecc.bytes = 3; + nand_chip->ecc.size = 512; + nand_chip->ecc.strength = 1; + nand_chip->ecc.calculate = omap_calculate_ecc; + nand_chip->ecc.hwctl = omap_enable_hwecc; + nand_chip->ecc.correct = omap_correct_data; + /* define ECC layout */ + ecclayout->eccbytes = nand_chip->ecc.bytes * + (mtd->writesize / + nand_chip->ecc.size); + if (nand_chip->options & NAND_BUSWIDTH_16) + oob_index = BADBLOCK_MARKER_LENGTH; + else + oob_index = 1; + for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) + ecclayout->eccpos[i] = oob_index; + /* no reserved-marker in ecclayout for this ecc-scheme */ + ecclayout->oobfree->offset = + ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; + break; + + case OMAP_ECC_BCH4_CODE_HW_DETECTION_SW: +#ifdef CONFIG_MTD_NAND_ECC_BCH + pr_info("nand: using OMAP_ECC_BCH4_CODE_HW_DETECTION_SW\n"); + nand_chip->ecc.mode = NAND_ECC_HW; + nand_chip->ecc.size = 512; + nand_chip->ecc.bytes = 7; + nand_chip->ecc.strength = 4; + nand_chip->ecc.hwctl = omap_enable_hwecc_bch; + nand_chip->ecc.correct = nand_bch_correct_data; + nand_chip->ecc.calculate = omap_calculate_ecc_bch; + /* define ECC layout */ + ecclayout->eccbytes = nand_chip->ecc.bytes * + (mtd->writesize / + nand_chip->ecc.size); + oob_index = BADBLOCK_MARKER_LENGTH; + for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) { + ecclayout->eccpos[i] = oob_index; + if (((i + 1) % nand_chip->ecc.bytes) == 0) + oob_index++; + } + /* include reserved-marker in ecclayout->oobfree calculation */ + ecclayout->oobfree->offset = 1 + + ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; + /* software bch library is used for locating errors */ + nand_chip->ecc.priv = nand_bch_init(mtd, + nand_chip->ecc.size, + nand_chip->ecc.bytes, + &nand_chip->ecc.layout); + if (!nand_chip->ecc.priv) { + pr_err("nand: error: unable to use s/w BCH library\n"); err = -EINVAL; - goto out_release_mem_region; } - } + break; +#else + pr_err("nand: error: CONFIG_MTD_NAND_ECC_BCH not enabled\n"); + err = -EINVAL; + goto return_error; +#endif - /* DIP switches on some boards change between 8 and 16 bit - * bus widths for flash. Try the other width if the first try fails. - */ - if (nand_scan_ident(&info->mtd, 1, NULL)) { - info->nand.options ^= NAND_BUSWIDTH_16; - if (nand_scan_ident(&info->mtd, 1, NULL)) { - err = -ENXIO; - goto out_release_mem_region; + case OMAP_ECC_BCH4_CODE_HW: +#ifdef CONFIG_MTD_NAND_OMAP_BCH + pr_info("nand: using OMAP_ECC_BCH4_CODE_HW ECC scheme\n"); + nand_chip->ecc.mode = NAND_ECC_HW; + nand_chip->ecc.size = 512; + /* 14th bit is kept reserved for ROM-code compatibility */ + nand_chip->ecc.bytes = 7 + 1; + nand_chip->ecc.strength = 4; + nand_chip->ecc.hwctl = omap_enable_hwecc_bch; + nand_chip->ecc.correct = omap_elm_correct_data; + nand_chip->ecc.calculate = omap_calculate_ecc_bch; + nand_chip->ecc.read_page = omap_read_page_bch; + nand_chip->ecc.write_page = omap_write_page_bch; + /* define ECC layout */ + ecclayout->eccbytes = nand_chip->ecc.bytes * + (mtd->writesize / + nand_chip->ecc.size); + oob_index = BADBLOCK_MARKER_LENGTH; + for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) + ecclayout->eccpos[i] = oob_index; + /* reserved marker already included in ecclayout->eccbytes */ + ecclayout->oobfree->offset = + ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; + /* This ECC scheme requires ELM H/W block */ + if (is_elm_present(info, pdata->elm_of_node, BCH4_ECC) < 0) { + pr_err("nand: error: could not initialize ELM\n"); + err = -ENODEV; + goto return_error; } - } - - /* rom code layout */ - if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE) { + break; +#else + pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n"); + err = -EINVAL; + goto return_error; +#endif - if (info->nand.options & NAND_BUSWIDTH_16) - offset = 2; - else { - offset = 1; - info->nand.badblock_pattern = &bb_descrip_flashbased; + case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: +#ifdef CONFIG_MTD_NAND_ECC_BCH + pr_info("nand: using OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n"); + nand_chip->ecc.mode = NAND_ECC_HW; + nand_chip->ecc.size = 512; + nand_chip->ecc.bytes = 13; + nand_chip->ecc.strength = 8; + nand_chip->ecc.hwctl = omap_enable_hwecc_bch; + nand_chip->ecc.correct = nand_bch_correct_data; + nand_chip->ecc.calculate = omap_calculate_ecc_bch; + /* define ECC layout */ + ecclayout->eccbytes = nand_chip->ecc.bytes * + (mtd->writesize / + nand_chip->ecc.size); + oob_index = BADBLOCK_MARKER_LENGTH; + for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) { + ecclayout->eccpos[i] = oob_index; + if (((i + 1) % nand_chip->ecc.bytes) == 0) + oob_index++; } - omap_oobinfo.eccbytes = 3 * (info->mtd.oobsize/16); - for (i = 0; i < omap_oobinfo.eccbytes; i++) - omap_oobinfo.eccpos[i] = i+offset; - - omap_oobinfo.oobfree->offset = offset + omap_oobinfo.eccbytes; - omap_oobinfo.oobfree->length = info->mtd.oobsize - - (offset + omap_oobinfo.eccbytes); - - info->nand.ecc.layout = &omap_oobinfo; - } else if ((pdata->ecc_opt == OMAP_ECC_BCH4_CODE_HW) || - (pdata->ecc_opt == OMAP_ECC_BCH8_CODE_HW)) { - /* build OOB layout for BCH ECC correction */ - err = omap3_init_bch_tail(&info->mtd); - if (err) { + /* include reserved-marker in ecclayout->oobfree calculation */ + ecclayout->oobfree->offset = 1 + + ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; + /* software bch library is used for locating errors */ + nand_chip->ecc.priv = nand_bch_init(mtd, + nand_chip->ecc.size, + nand_chip->ecc.bytes, + &nand_chip->ecc.layout); + if (!nand_chip->ecc.priv) { + pr_err("nand: error: unable to use s/w BCH library\n"); err = -EINVAL; - goto out_release_mem_region; + goto return_error; + } + break; +#else + pr_err("nand: error: CONFIG_MTD_NAND_ECC_BCH not enabled\n"); + err = -EINVAL; + goto return_error; +#endif + + case OMAP_ECC_BCH8_CODE_HW: +#ifdef CONFIG_MTD_NAND_OMAP_BCH + pr_info("nand: using OMAP_ECC_BCH8_CODE_HW ECC scheme\n"); + nand_chip->ecc.mode = NAND_ECC_HW; + nand_chip->ecc.size = 512; + /* 14th bit is kept reserved for ROM-code compatibility */ + nand_chip->ecc.bytes = 13 + 1; + nand_chip->ecc.strength = 8; + nand_chip->ecc.hwctl = omap_enable_hwecc_bch; + nand_chip->ecc.correct = omap_elm_correct_data; + nand_chip->ecc.calculate = omap_calculate_ecc_bch; + nand_chip->ecc.read_page = omap_read_page_bch; + nand_chip->ecc.write_page = omap_write_page_bch; + /* This ECC scheme requires ELM H/W block */ + err = is_elm_present(info, pdata->elm_of_node, BCH8_ECC); + if (err < 0) { + pr_err("nand: error: could not initialize ELM\n"); + goto return_error; } + /* define ECC layout */ + ecclayout->eccbytes = nand_chip->ecc.bytes * + (mtd->writesize / + nand_chip->ecc.size); + oob_index = BADBLOCK_MARKER_LENGTH; + for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) + ecclayout->eccpos[i] = oob_index; + /* reserved marker already included in ecclayout->eccbytes */ + ecclayout->oobfree->offset = + ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; + break; +#else + pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n"); + err = -EINVAL; + goto return_error; +#endif + + case OMAP_ECC_BCH16_CODE_HW: +#ifdef CONFIG_MTD_NAND_OMAP_BCH + pr_info("using OMAP_ECC_BCH16_CODE_HW ECC scheme\n"); + nand_chip->ecc.mode = NAND_ECC_HW; + nand_chip->ecc.size = 512; + nand_chip->ecc.bytes = 26; + nand_chip->ecc.strength = 16; + nand_chip->ecc.hwctl = omap_enable_hwecc_bch; + nand_chip->ecc.correct = omap_elm_correct_data; + nand_chip->ecc.calculate = omap_calculate_ecc_bch; + nand_chip->ecc.read_page = omap_read_page_bch; + nand_chip->ecc.write_page = omap_write_page_bch; + /* This ECC scheme requires ELM H/W block */ + err = is_elm_present(info, pdata->elm_of_node, BCH16_ECC); + if (err < 0) { + pr_err("ELM is required for this ECC scheme\n"); + goto return_error; + } + /* define ECC layout */ + ecclayout->eccbytes = nand_chip->ecc.bytes * + (mtd->writesize / + nand_chip->ecc.size); + oob_index = BADBLOCK_MARKER_LENGTH; + for (i = 0; i < ecclayout->eccbytes; i++, oob_index++) + ecclayout->eccpos[i] = oob_index; + /* reserved marker already included in ecclayout->eccbytes */ + ecclayout->oobfree->offset = + ecclayout->eccpos[ecclayout->eccbytes - 1] + 1; + break; +#else + pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n"); + err = -EINVAL; + goto return_error; +#endif + default: + pr_err("nand: error: invalid or unsupported ECC scheme\n"); + err = -EINVAL; + goto return_error; + } + + /* all OOB bytes from oobfree->offset till end off OOB are free */ + ecclayout->oobfree->length = mtd->oobsize - ecclayout->oobfree->offset; + /* check if NAND device's OOB is enough to store ECC signatures */ + if (mtd->oobsize < (ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH)) { + pr_err("not enough OOB bytes required = %d, available=%d\n", + ecclayout->eccbytes, mtd->oobsize); + err = -EINVAL; + goto return_error; } /* second phase scan */ - if (nand_scan_tail(&info->mtd)) { + if (nand_scan_tail(mtd)) { err = -ENXIO; - goto out_release_mem_region; + goto return_error; } ppdata.of_node = pdata->of_node; - mtd_device_parse_register(&info->mtd, NULL, &ppdata, pdata->parts, + mtd_device_parse_register(mtd, NULL, &ppdata, pdata->parts, pdata->nr_parts); - platform_set_drvdata(pdev, &info->mtd); + platform_set_drvdata(pdev, mtd); return 0; -out_release_mem_region: +return_error: if (info->dma) dma_release_channel(info->dma); - if (info->gpmc_irq_count > 0) - free_irq(info->gpmc_irq_count, info); - if (info->gpmc_irq_fifo > 0) - free_irq(info->gpmc_irq_fifo, info); - release_mem_region(info->phys_base, info->mem_size); -out_free_info: - kfree(info); - + if (nand_chip->ecc.priv) { + nand_bch_free(nand_chip->ecc.priv); + nand_chip->ecc.priv = NULL; + } return err; } static int omap_nand_remove(struct platform_device *pdev) { struct mtd_info *mtd = platform_get_drvdata(pdev); + struct nand_chip *nand_chip = mtd->priv; struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - omap3_free_bch(&info->mtd); - + if (nand_chip->ecc.priv) { + nand_bch_free(nand_chip->ecc.priv); + nand_chip->ecc.priv = NULL; + } if (info->dma) dma_release_channel(info->dma); - - if (info->gpmc_irq_count > 0) - free_irq(info->gpmc_irq_count, info); - if (info->gpmc_irq_fifo > 0) - free_irq(info->gpmc_irq_fifo, info); - - /* Release NAND device, its internal structures and partitions */ - nand_release(&info->mtd); - iounmap(info->nand.IO_ADDR_R); - release_mem_region(info->phys_base, info->mem_size); - kfree(info); + nand_release(mtd); return 0; } diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index a393a5b6ce1..471b4df3a5a 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c @@ -87,7 +87,6 @@ static int __init orion_nand_probe(struct platform_device *pdev) nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL); if (!nc) { - printk(KERN_ERR "orion_nand: failed to allocate device structure.\n"); ret = -ENOMEM; goto no_res; } @@ -101,7 +100,7 @@ static int __init orion_nand_probe(struct platform_device *pdev) io_base = ioremap(res->start, resource_size(res)); if (!io_base) { - printk(KERN_ERR "orion_nand: ioremap failed\n"); + dev_err(&pdev->dev, "ioremap failed\n"); ret = -EIO; goto no_res; } @@ -110,7 +109,6 @@ static int __init orion_nand_probe(struct platform_device *pdev) board = devm_kzalloc(&pdev->dev, sizeof(struct orion_nand_data), GFP_KERNEL); if (!board) { - printk(KERN_ERR "orion_nand: failed to allocate board structure.\n"); ret = -ENOMEM; goto no_res; } @@ -216,7 +214,7 @@ static int orion_nand_remove(struct platform_device *pdev) } #ifdef CONFIG_OF -static struct of_device_id orion_nand_of_match_table[] = { +static const struct of_device_id orion_nand_of_match_table[] = { { .compatible = "marvell,orion-nand", }, {}, }; diff --git a/drivers/mtd/nand/pasemi_nand.c b/drivers/mtd/nand/pasemi_nand.c index 5a67082c07e..2c98f9da747 100644 --- a/drivers/mtd/nand/pasemi_nand.c +++ b/drivers/mtd/nand/pasemi_nand.c @@ -23,11 +23,12 @@ #undef DEBUG #include <linux/slab.h> -#include <linux/init.h> #include <linux/module.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/nand_ecc.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/pci.h> @@ -221,7 +222,7 @@ MODULE_DEVICE_TABLE(of, pasemi_nand_match); static struct platform_driver pasemi_nand_driver = { .driver = { - .name = (char*)driver_name, + .name = driver_name, .owner = THIS_MODULE, .of_match_table = pasemi_nand_match, }, diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index cad4cdc9df3..0b068a5c0bf 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c @@ -9,6 +9,7 @@ * */ +#include <linux/err.h> #include <linux/io.h> #include <linux/module.h> #include <linux/platform_device.h> @@ -47,30 +48,16 @@ static int plat_nand_probe(struct platform_device *pdev) return -EINVAL; } - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENXIO; - /* Allocate memory for the device structure (and zero it) */ - data = kzalloc(sizeof(struct plat_nand_data), GFP_KERNEL); - if (!data) { - dev_err(&pdev->dev, "failed to allocate device structure.\n"); + data = devm_kzalloc(&pdev->dev, sizeof(struct plat_nand_data), + GFP_KERNEL); + if (!data) return -ENOMEM; - } - - if (!request_mem_region(res->start, resource_size(res), - dev_name(&pdev->dev))) { - dev_err(&pdev->dev, "request_mem_region failed\n"); - err = -EBUSY; - goto out_free; - } - data->io_base = ioremap(res->start, resource_size(res)); - if (data->io_base == NULL) { - dev_err(&pdev->dev, "ioremap failed\n"); - err = -EIO; - goto out_release_io; - } + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + data->io_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(data->io_base)) + return PTR_ERR(data->io_base); data->chip.priv = &data; data->mtd.priv = &data->chip; @@ -122,11 +109,6 @@ static int plat_nand_probe(struct platform_device *pdev) out: if (pdata->ctrl.remove) pdata->ctrl.remove(pdev); - iounmap(data->io_base); -out_release_io: - release_mem_region(res->start, resource_size(res)); -out_free: - kfree(data); return err; } @@ -137,16 +119,10 @@ static int plat_nand_remove(struct platform_device *pdev) { struct plat_nand_data *data = platform_get_drvdata(pdev); struct platform_nand_data *pdata = dev_get_platdata(&pdev->dev); - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); nand_release(&data->mtd); if (pdata->ctrl.remove) pdata->ctrl.remove(pdev); - iounmap(data->io_base); - release_mem_region(res->start, resource_size(res)); - kfree(data); return 0; } diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index dd03dfdfb0d..96b0b1d27df 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -7,6 +7,8 @@ * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. + * + * See Documentation/mtd/nand/pxa3xx-nand.txt for more details. */ #include <linux/kernel.h> @@ -24,6 +26,7 @@ #include <linux/slab.h> #include <linux/of.h> #include <linux/of_device.h> +#include <linux/of_mtd.h> #if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP) #define ARCH_HAS_DMA @@ -39,6 +42,13 @@ #define NAND_STOP_DELAY (2 * HZ/50) #define PAGE_CHUNK_SIZE (2048) +/* + * Define a buffer size for the initial command that detects the flash device: + * STATUS, READID and PARAM. The largest of these is the PARAM command, + * needing 256 bytes. + */ +#define INIT_BUFFER_SIZE 256 + /* registers and bit definitions */ #define NDCR (0x00) /* Control register */ #define NDTR0CS0 (0x04) /* Timing Parameter 0 for CS0 */ @@ -47,6 +57,7 @@ #define NDPCR (0x18) /* Page Count Register */ #define NDBDR0 (0x1C) /* Bad Block Register 0 */ #define NDBDR1 (0x20) /* Bad Block Register 1 */ +#define NDECCCTRL (0x28) /* ECC control */ #define NDDB (0x40) /* Data Buffer */ #define NDCB0 (0x48) /* Command Buffer0 */ #define NDCB1 (0x4C) /* Command Buffer1 */ @@ -73,6 +84,9 @@ #define NDCR_INT_MASK (0xFFF) #define NDSR_MASK (0xfff) +#define NDSR_ERR_CNT_OFF (16) +#define NDSR_ERR_CNT_MASK (0x1f) +#define NDSR_ERR_CNT(sr) ((sr >> NDSR_ERR_CNT_OFF) & NDSR_ERR_CNT_MASK) #define NDSR_RDY (0x1 << 12) #define NDSR_FLASH_RDY (0x1 << 11) #define NDSR_CS0_PAGED (0x1 << 10) @@ -81,8 +95,8 @@ #define NDSR_CS1_CMDD (0x1 << 7) #define NDSR_CS0_BBD (0x1 << 6) #define NDSR_CS1_BBD (0x1 << 5) -#define NDSR_DBERR (0x1 << 4) -#define NDSR_SBERR (0x1 << 3) +#define NDSR_UNCORERR (0x1 << 4) +#define NDSR_CORERR (0x1 << 3) #define NDSR_WRDREQ (0x1 << 2) #define NDSR_RDDREQ (0x1 << 1) #define NDSR_WRCMDREQ (0x1) @@ -91,6 +105,8 @@ #define NDCB0_ST_ROW_EN (0x1 << 26) #define NDCB0_AUTO_RS (0x1 << 25) #define NDCB0_CSEL (0x1 << 24) +#define NDCB0_EXT_CMD_TYPE_MASK (0x7 << 29) +#define NDCB0_EXT_CMD_TYPE(x) (((x) << 29) & NDCB0_EXT_CMD_TYPE_MASK) #define NDCB0_CMD_TYPE_MASK (0x7 << 21) #define NDCB0_CMD_TYPE(x) (((x) << 21) & NDCB0_CMD_TYPE_MASK) #define NDCB0_NC (0x1 << 20) @@ -101,21 +117,29 @@ #define NDCB0_CMD1_MASK (0xff) #define NDCB0_ADDR_CYC_SHIFT (16) +#define EXT_CMD_TYPE_DISPATCH 6 /* Command dispatch */ +#define EXT_CMD_TYPE_NAKED_RW 5 /* Naked read or Naked write */ +#define EXT_CMD_TYPE_READ 4 /* Read */ +#define EXT_CMD_TYPE_DISP_WR 4 /* Command dispatch with write */ +#define EXT_CMD_TYPE_FINAL 3 /* Final command */ +#define EXT_CMD_TYPE_LAST_RW 1 /* Last naked read/write */ +#define EXT_CMD_TYPE_MONO 0 /* Monolithic read/write */ + /* macros for registers read/write */ #define nand_writel(info, off, val) \ - __raw_writel((val), (info)->mmio_base + (off)) + writel_relaxed((val), (info)->mmio_base + (off)) #define nand_readl(info, off) \ - __raw_readl((info)->mmio_base + (off)) + readl_relaxed((info)->mmio_base + (off)) /* error code and state */ enum { ERR_NONE = 0, ERR_DMABUSERR = -1, ERR_SENDCMD = -2, - ERR_DBERR = -3, + ERR_UNCORERR = -3, ERR_BBERR = -4, - ERR_SBERR = -5, + ERR_CORERR = -5, }; enum { @@ -142,7 +166,6 @@ struct pxa3xx_nand_host { void *info_data; /* page size of attached chip */ - unsigned int page_size; int use_ecc; int cs; @@ -160,10 +183,13 @@ struct pxa3xx_nand_info { struct clk *clk; void __iomem *mmio_base; unsigned long mmio_phys; - struct completion cmd_complete; + struct completion cmd_complete, dev_ready; unsigned int buf_start; unsigned int buf_count; + unsigned int buf_size; + unsigned int data_buff_pos; + unsigned int oob_buff_pos; /* DMA information */ int drcmr_dat; @@ -187,13 +213,18 @@ struct pxa3xx_nand_info { int cs; int use_ecc; /* use HW ECC ? */ + int ecc_bch; /* using BCH ECC? */ int use_dma; /* use DMA ? */ int use_spare; /* use spare ? */ - int is_ready; + int need_wait; - unsigned int page_size; /* page size of attached chip */ - unsigned int data_size; /* data size in FIFO */ + unsigned int data_size; /* data to be read from FIFO */ + unsigned int chunk_size; /* split commands chunk size */ unsigned int oob_size; + unsigned int spare_size; + unsigned int ecc_size; + unsigned int ecc_err_cnt; + unsigned int max_bitflips; int retcode; /* cached register value */ @@ -231,6 +262,64 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = { { "256MiB 16-bit", 0xba20, 64, 2048, 16, 16, 2048, &timing[3] }, }; +static u8 bbt_pattern[] = {'M', 'V', 'B', 'b', 't', '0' }; +static u8 bbt_mirror_pattern[] = {'1', 't', 'b', 'B', 'V', 'M' }; + +static struct nand_bbt_descr bbt_main_descr = { + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE + | NAND_BBT_2BIT | NAND_BBT_VERSION, + .offs = 8, + .len = 6, + .veroffs = 14, + .maxblocks = 8, /* Last 8 blocks in each chip */ + .pattern = bbt_pattern +}; + +static struct nand_bbt_descr bbt_mirror_descr = { + .options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE + | NAND_BBT_2BIT | NAND_BBT_VERSION, + .offs = 8, + .len = 6, + .veroffs = 14, + .maxblocks = 8, /* Last 8 blocks in each chip */ + .pattern = bbt_mirror_pattern +}; + +static struct nand_ecclayout ecc_layout_2KB_bch4bit = { + .eccbytes = 32, + .eccpos = { + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63}, + .oobfree = { {2, 30} } +}; + +static struct nand_ecclayout ecc_layout_4KB_bch4bit = { + .eccbytes = 64, + .eccpos = { + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127}, + /* Bootrom looks in bytes 0 & 5 for bad blocks */ + .oobfree = { {6, 26}, { 64, 32} } +}; + +static struct nand_ecclayout ecc_layout_4KB_bch8bit = { + .eccbytes = 128, + .eccpos = { + 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63}, + .oobfree = { } +}; + /* Define a default flash type setting serve as flash detecting only */ #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0]) @@ -248,6 +337,29 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = { /* convert nano-seconds to nand flash controller clock cycles */ #define ns2cycle(ns, clk) (int)((ns) * (clk / 1000000) / 1000) +static const struct of_device_id pxa3xx_nand_dt_ids[] = { + { + .compatible = "marvell,pxa3xx-nand", + .data = (void *)PXA3XX_NAND_VARIANT_PXA, + }, + { + .compatible = "marvell,armada370-nand", + .data = (void *)PXA3XX_NAND_VARIANT_ARMADA370, + }, + {} +}; +MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids); + +static enum pxa3xx_nand_variant +pxa3xx_nand_get_variant(struct platform_device *pdev) +{ + const struct of_device_id *of_id = + of_match_device(pxa3xx_nand_dt_ids, &pdev->dev); + if (!of_id) + return PXA3XX_NAND_VARIANT_PXA; + return (enum pxa3xx_nand_variant)of_id->data; +} + static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host, const struct pxa3xx_nand_timing *t) { @@ -272,25 +384,23 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host, nand_writel(info, NDTR1CS0, ndtr1); } -static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) +/* + * Set the data and OOB size, depending on the selected + * spare and ECC configuration. + * Only applicable to READ0, READOOB and PAGEPROG commands. + */ +static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info, + struct mtd_info *mtd) { - struct pxa3xx_nand_host *host = info->host[info->cs]; int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; - info->data_size = host->page_size; - if (!oob_enable) { - info->oob_size = 0; + info->data_size = mtd->writesize; + if (!oob_enable) return; - } - switch (host->page_size) { - case 2048: - info->oob_size = (info->use_ecc) ? 40 : 64; - break; - case 512: - info->oob_size = (info->use_ecc) ? 8 : 16; - break; - } + info->oob_size = info->spare_size; + if (!info->use_ecc) + info->oob_size += info->ecc_size; } /** @@ -305,10 +415,15 @@ static void pxa3xx_nand_start(struct pxa3xx_nand_info *info) ndcr = info->reg_ndcr; - if (info->use_ecc) + if (info->use_ecc) { ndcr |= NDCR_ECC_EN; - else + if (info->ecc_bch) + nand_writel(info, NDECCCTRL, 0x1); + } else { ndcr &= ~NDCR_ECC_EN; + if (info->ecc_bch) + nand_writel(info, NDECCCTRL, 0x0); + } if (info->use_dma) ndcr |= NDCR_DMA_EN; @@ -367,26 +482,39 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) static void handle_data_pio(struct pxa3xx_nand_info *info) { + unsigned int do_bytes = min(info->data_size, info->chunk_size); + switch (info->state) { case STATE_PIO_WRITING: - __raw_writesl(info->mmio_base + NDDB, info->data_buff, - DIV_ROUND_UP(info->data_size, 4)); + __raw_writesl(info->mmio_base + NDDB, + info->data_buff + info->data_buff_pos, + DIV_ROUND_UP(do_bytes, 4)); + if (info->oob_size > 0) - __raw_writesl(info->mmio_base + NDDB, info->oob_buff, - DIV_ROUND_UP(info->oob_size, 4)); + __raw_writesl(info->mmio_base + NDDB, + info->oob_buff + info->oob_buff_pos, + DIV_ROUND_UP(info->oob_size, 4)); break; case STATE_PIO_READING: - __raw_readsl(info->mmio_base + NDDB, info->data_buff, - DIV_ROUND_UP(info->data_size, 4)); + __raw_readsl(info->mmio_base + NDDB, + info->data_buff + info->data_buff_pos, + DIV_ROUND_UP(do_bytes, 4)); + if (info->oob_size > 0) - __raw_readsl(info->mmio_base + NDDB, info->oob_buff, - DIV_ROUND_UP(info->oob_size, 4)); + __raw_readsl(info->mmio_base + NDDB, + info->oob_buff + info->oob_buff_pos, + DIV_ROUND_UP(info->oob_size, 4)); break; default: dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__, info->state); BUG(); } + + /* Update buffer pointers for multi-page read/write */ + info->data_buff_pos += do_bytes; + info->oob_buff_pos += info->oob_size; + info->data_size -= do_bytes; } #ifdef ARCH_HAS_DMA @@ -444,7 +572,7 @@ static void start_data_dma(struct pxa3xx_nand_info *info) static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) { struct pxa3xx_nand_info *info = devid; - unsigned int status, is_completed = 0; + unsigned int status, is_completed = 0, is_ready = 0; unsigned int ready, cmd_done; if (info->cs == 0) { @@ -457,10 +585,25 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) status = nand_readl(info, NDSR); - if (status & NDSR_DBERR) - info->retcode = ERR_DBERR; - if (status & NDSR_SBERR) - info->retcode = ERR_SBERR; + if (status & NDSR_UNCORERR) + info->retcode = ERR_UNCORERR; + if (status & NDSR_CORERR) { + info->retcode = ERR_CORERR; + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 && + info->ecc_bch) + info->ecc_err_cnt = NDSR_ERR_CNT(status); + else + info->ecc_err_cnt = 1; + + /* + * Each chunk composing a page is corrected independently, + * and we need to store maximum number of corrected bitflips + * to return it to the MTD layer in ecc.read_page(). + */ + info->max_bitflips = max_t(unsigned int, + info->max_bitflips, + info->ecc_err_cnt); + } if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) { /* whether use dma to transfer data */ if (info->use_dma) { @@ -480,8 +623,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) is_completed = 1; } if (status & ready) { - info->is_ready = 1; info->state = STATE_READY; + is_ready = 1; } if (status & NDSR_WRCMDREQ) { @@ -510,6 +653,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) nand_writel(info, NDSR, status); if (is_completed) complete(&info->cmd_complete); + if (is_ready) + complete(&info->dev_ready); NORMAL_IRQ_EXIT: return IRQ_HANDLED; } @@ -522,52 +667,94 @@ static inline int is_buf_blank(uint8_t *buf, size_t len) return 1; } -static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, - uint16_t column, int page_addr) +static void set_command_address(struct pxa3xx_nand_info *info, + unsigned int page_size, uint16_t column, int page_addr) { - int addr_cycle, exec_cmd; - struct pxa3xx_nand_host *host; - struct mtd_info *mtd; + /* small page addr setting */ + if (page_size < PAGE_CHUNK_SIZE) { + info->ndcb1 = ((page_addr & 0xFFFFFF) << 8) + | (column & 0xFF); - host = info->host[info->cs]; - mtd = host->mtd; - addr_cycle = 0; - exec_cmd = 1; + info->ndcb2 = 0; + } else { + info->ndcb1 = ((page_addr & 0xFFFF) << 16) + | (column & 0xFFFF); + + if (page_addr & 0xFF0000) + info->ndcb2 = (page_addr & 0xFF0000) >> 16; + else + info->ndcb2 = 0; + } +} + +static void prepare_start_command(struct pxa3xx_nand_info *info, int command) +{ + struct pxa3xx_nand_host *host = info->host[info->cs]; + struct mtd_info *mtd = host->mtd; /* reset data and oob column point to handle data */ info->buf_start = 0; info->buf_count = 0; info->oob_size = 0; + info->data_buff_pos = 0; + info->oob_buff_pos = 0; info->use_ecc = 0; info->use_spare = 1; - info->use_dma = (use_dma) ? 1 : 0; - info->is_ready = 0; info->retcode = ERR_NONE; - if (info->cs != 0) - info->ndcb0 = NDCB0_CSEL; - else - info->ndcb0 = 0; + info->ecc_err_cnt = 0; + info->ndcb3 = 0; + info->need_wait = 0; switch (command) { case NAND_CMD_READ0: case NAND_CMD_PAGEPROG: info->use_ecc = 1; case NAND_CMD_READOOB: - pxa3xx_set_datasize(info); + pxa3xx_set_datasize(info, mtd); break; case NAND_CMD_PARAM: info->use_spare = 0; break; - case NAND_CMD_SEQIN: - exec_cmd = 0; - break; default: info->ndcb1 = 0; info->ndcb2 = 0; - info->ndcb3 = 0; break; } + /* + * If we are about to issue a read command, or about to set + * the write address, then clean the data buffer. + */ + if (command == NAND_CMD_READ0 || + command == NAND_CMD_READOOB || + command == NAND_CMD_SEQIN) { + + info->buf_count = mtd->writesize + mtd->oobsize; + memset(info->data_buff, 0xFF, info->buf_count); + } + +} + +static int prepare_set_command(struct pxa3xx_nand_info *info, int command, + int ext_cmd_type, uint16_t column, int page_addr) +{ + int addr_cycle, exec_cmd; + struct pxa3xx_nand_host *host; + struct mtd_info *mtd; + + host = info->host[info->cs]; + mtd = host->mtd; + addr_cycle = 0; + exec_cmd = 1; + + if (info->cs != 0) + info->ndcb0 = NDCB0_CSEL; + else + info->ndcb0 = 0; + + if (command == NAND_CMD_SEQIN) + exec_cmd = 0; + addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles + host->col_addr_cycles); @@ -582,30 +769,42 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, if (command == NAND_CMD_READOOB) info->buf_start += mtd->writesize; - /* Second command setting for large pages */ - if (host->page_size >= PAGE_CHUNK_SIZE) + /* + * Multiple page read needs an 'extended command type' field, + * which is either naked-read or last-read according to the + * state. + */ + if (mtd->writesize == PAGE_CHUNK_SIZE) { info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8); + } else if (mtd->writesize > PAGE_CHUNK_SIZE) { + info->ndcb0 |= NDCB0_DBC | (NAND_CMD_READSTART << 8) + | NDCB0_LEN_OVRD + | NDCB0_EXT_CMD_TYPE(ext_cmd_type); + info->ndcb3 = info->chunk_size + + info->oob_size; + } + + set_command_address(info, mtd->writesize, column, page_addr); + break; case NAND_CMD_SEQIN: - /* small page addr setting */ - if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) { - info->ndcb1 = ((page_addr & 0xFFFFFF) << 8) - | (column & 0xFF); - info->ndcb2 = 0; - } else { - info->ndcb1 = ((page_addr & 0xFFFF) << 16) - | (column & 0xFFFF); + info->buf_start = column; + set_command_address(info, mtd->writesize, 0, page_addr); - if (page_addr & 0xFF0000) - info->ndcb2 = (page_addr & 0xFF0000) >> 16; - else - info->ndcb2 = 0; + /* + * Multiple page programming needs to execute the initial + * SEQIN command that sets the page address. + */ + if (mtd->writesize > PAGE_CHUNK_SIZE) { + info->ndcb0 |= NDCB0_CMD_TYPE(0x1) + | NDCB0_EXT_CMD_TYPE(ext_cmd_type) + | addr_cycle + | command; + /* No data transfer in this case */ + info->data_size = 0; + exec_cmd = 1; } - - info->buf_count = mtd->writesize + mtd->oobsize; - memset(info->data_buff, 0xFF, info->buf_count); - break; case NAND_CMD_PAGEPROG: @@ -615,13 +814,40 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, break; } - info->ndcb0 |= NDCB0_CMD_TYPE(0x1) - | NDCB0_AUTO_RS - | NDCB0_ST_ROW_EN - | NDCB0_DBC - | (NAND_CMD_PAGEPROG << 8) - | NAND_CMD_SEQIN - | addr_cycle; + /* Second command setting for large pages */ + if (mtd->writesize > PAGE_CHUNK_SIZE) { + /* + * Multiple page write uses the 'extended command' + * field. This can be used to issue a command dispatch + * or a naked-write depending on the current stage. + */ + info->ndcb0 |= NDCB0_CMD_TYPE(0x1) + | NDCB0_LEN_OVRD + | NDCB0_EXT_CMD_TYPE(ext_cmd_type); + info->ndcb3 = info->chunk_size + + info->oob_size; + + /* + * This is the command dispatch that completes a chunked + * page program operation. + */ + if (info->data_size == 0) { + info->ndcb0 = NDCB0_CMD_TYPE(0x1) + | NDCB0_EXT_CMD_TYPE(ext_cmd_type) + | command; + info->ndcb1 = 0; + info->ndcb2 = 0; + info->ndcb3 = 0; + } + } else { + info->ndcb0 |= NDCB0_CMD_TYPE(0x1) + | NDCB0_AUTO_RS + | NDCB0_ST_ROW_EN + | NDCB0_DBC + | (NAND_CMD_PAGEPROG << 8) + | NAND_CMD_SEQIN + | addr_cycle; + } break; case NAND_CMD_PARAM: @@ -684,8 +910,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, return exec_cmd; } -static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, - int column, int page_addr) +static void nand_cmdfunc(struct mtd_info *mtd, unsigned command, + int column, int page_addr) { struct pxa3xx_nand_host *host = mtd->priv; struct pxa3xx_nand_info *info = host->info_data; @@ -710,10 +936,15 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, nand_writel(info, NDTR1CS0, info->ndtr1cs0); } + prepare_start_command(info, command); + info->state = STATE_PREPARED; - exec_cmd = prepare_command_pool(info, command, column, page_addr); + exec_cmd = prepare_set_command(info, command, 0, column, page_addr); + if (exec_cmd) { init_completion(&info->cmd_complete); + init_completion(&info->dev_ready); + info->need_wait = 1; pxa3xx_nand_start(info); ret = wait_for_completion_timeout(&info->cmd_complete, @@ -727,6 +958,117 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, info->state = STATE_IDLE; } +static void nand_cmdfunc_extended(struct mtd_info *mtd, + const unsigned command, + int column, int page_addr) +{ + struct pxa3xx_nand_host *host = mtd->priv; + struct pxa3xx_nand_info *info = host->info_data; + int ret, exec_cmd, ext_cmd_type; + + /* + * if this is a x16 device then convert the input + * "byte" address into a "word" address appropriate + * for indexing a word-oriented device + */ + if (info->reg_ndcr & NDCR_DWIDTH_M) + column /= 2; + + /* + * There may be different NAND chip hooked to + * different chip select, so check whether + * chip select has been changed, if yes, reset the timing + */ + if (info->cs != host->cs) { + info->cs = host->cs; + nand_writel(info, NDTR0CS0, info->ndtr0cs0); + nand_writel(info, NDTR1CS0, info->ndtr1cs0); + } + + /* Select the extended command for the first command */ + switch (command) { + case NAND_CMD_READ0: + case NAND_CMD_READOOB: + ext_cmd_type = EXT_CMD_TYPE_MONO; + break; + case NAND_CMD_SEQIN: + ext_cmd_type = EXT_CMD_TYPE_DISPATCH; + break; + case NAND_CMD_PAGEPROG: + ext_cmd_type = EXT_CMD_TYPE_NAKED_RW; + break; + default: + ext_cmd_type = 0; + break; + } + + prepare_start_command(info, command); + + /* + * Prepare the "is ready" completion before starting a command + * transaction sequence. If the command is not executed the + * completion will be completed, see below. + * + * We can do that inside the loop because the command variable + * is invariant and thus so is the exec_cmd. + */ + info->need_wait = 1; + init_completion(&info->dev_ready); + do { + info->state = STATE_PREPARED; + exec_cmd = prepare_set_command(info, command, ext_cmd_type, + column, page_addr); + if (!exec_cmd) { + info->need_wait = 0; + complete(&info->dev_ready); + break; + } + + init_completion(&info->cmd_complete); + pxa3xx_nand_start(info); + + ret = wait_for_completion_timeout(&info->cmd_complete, + CHIP_DELAY_TIMEOUT); + if (!ret) { + dev_err(&info->pdev->dev, "Wait time out!!!\n"); + /* Stop State Machine for next command cycle */ + pxa3xx_nand_stop(info); + break; + } + + /* Check if the sequence is complete */ + if (info->data_size == 0 && command != NAND_CMD_PAGEPROG) + break; + + /* + * After a splitted program command sequence has issued + * the command dispatch, the command sequence is complete. + */ + if (info->data_size == 0 && + command == NAND_CMD_PAGEPROG && + ext_cmd_type == EXT_CMD_TYPE_DISPATCH) + break; + + if (command == NAND_CMD_READ0 || command == NAND_CMD_READOOB) { + /* Last read: issue a 'last naked read' */ + if (info->data_size == info->chunk_size) + ext_cmd_type = EXT_CMD_TYPE_LAST_RW; + else + ext_cmd_type = EXT_CMD_TYPE_NAKED_RW; + + /* + * If a splitted program command has no more data to transfer, + * the command dispatch must be issued to complete. + */ + } else if (command == NAND_CMD_PAGEPROG && + info->data_size == 0) { + ext_cmd_type = EXT_CMD_TYPE_DISPATCH; + } + } while (1); + + info->state = STATE_IDLE; +} + static int pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, const uint8_t *buf, int oob_required) { @@ -746,20 +1088,14 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, chip->read_buf(mtd, buf, mtd->writesize); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); - if (info->retcode == ERR_SBERR) { - switch (info->use_ecc) { - case 1: - mtd->ecc_stats.corrected++; - break; - case 0: - default: - break; - } - } else if (info->retcode == ERR_DBERR) { + if (info->retcode == ERR_CORERR && info->use_ecc) { + mtd->ecc_stats.corrected += info->ecc_err_cnt; + + } else if (info->retcode == ERR_UNCORERR) { /* * for blank page (all 0xff), HW will calculate its ECC as * 0, which is different from the ECC information within - * OOB, ignore such double bit errors + * OOB, ignore such uncorrectable errors */ if (is_buf_blank(buf, mtd->writesize)) info->retcode = ERR_NONE; @@ -767,7 +1103,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, mtd->ecc_stats.failed++; } - return 0; + return info->max_bitflips; } static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) @@ -826,21 +1162,27 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) { struct pxa3xx_nand_host *host = mtd->priv; struct pxa3xx_nand_info *info = host->info_data; + int ret; + + if (info->need_wait) { + ret = wait_for_completion_timeout(&info->dev_ready, + CHIP_DELAY_TIMEOUT); + info->need_wait = 0; + if (!ret) { + dev_err(&info->pdev->dev, "Ready time out!!!\n"); + return NAND_STATUS_FAIL; + } + } /* pxa3xx_nand_send_command has waited for command complete */ if (this->state == FL_WRITING || this->state == FL_ERASING) { if (info->retcode == ERR_NONE) return 0; - else { - /* - * any error make it return 0x01 which will tell - * the caller the erase and write fail - */ - return 0x01; - } + else + return NAND_STATUS_FAIL; } - return 0; + return NAND_STATUS_READY; } static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, @@ -862,7 +1204,6 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, } /* calculate flash information */ - host->page_size = f->page_size; host->read_id_bytes = (f->page_size == 2048) ? 4 : 2; /* calculate addressing information */ @@ -899,39 +1240,35 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) uint32_t ndcr = nand_readl(info, NDCR); if (ndcr & NDCR_PAGE_SZ) { - host->page_size = 2048; + /* Controller's FIFO size */ + info->chunk_size = 2048; host->read_id_bytes = 4; } else { - host->page_size = 512; + info->chunk_size = 512; host->read_id_bytes = 2; } + /* Set an initial chunk size */ info->reg_ndcr = ndcr & ~NDCR_INT_MASK; info->ndtr0cs0 = nand_readl(info, NDTR0CS0); info->ndtr1cs0 = nand_readl(info, NDTR1CS0); return 0; } -/* the maximum possible buffer size for large page with OOB data - * is: 2048 + 64 = 2112 bytes, allocate a page here for both the - * data buffer and the DMA descriptor - */ -#define MAX_BUFF_SIZE PAGE_SIZE - #ifdef ARCH_HAS_DMA static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) { struct platform_device *pdev = info->pdev; - int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc); + int data_desc_offset = info->buf_size - sizeof(struct pxa_dma_desc); if (use_dma == 0) { - info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL); + info->data_buff = kmalloc(info->buf_size, GFP_KERNEL); if (info->data_buff == NULL) return -ENOMEM; return 0; } - info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE, + info->data_buff = dma_alloc_coherent(&pdev->dev, info->buf_size, &info->data_buff_phys, GFP_KERNEL); if (info->data_buff == NULL) { dev_err(&pdev->dev, "failed to allocate dma buffer\n"); @@ -945,20 +1282,25 @@ static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) pxa3xx_nand_data_dma_irq, info); if (info->data_dma_ch < 0) { dev_err(&pdev->dev, "failed to request data dma\n"); - dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE, + dma_free_coherent(&pdev->dev, info->buf_size, info->data_buff, info->data_buff_phys); return info->data_dma_ch; } + /* + * Now that DMA buffers are allocated we turn on + * DMA proper for I/O operations. + */ + info->use_dma = 1; return 0; } static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info) { struct platform_device *pdev = info->pdev; - if (use_dma) { + if (info->use_dma) { pxa_free_dma(info->data_dma_ch); - dma_free_coherent(&pdev->dev, MAX_BUFF_SIZE, + dma_free_coherent(&pdev->dev, info->buf_size, info->data_buff, info->data_buff_phys); } else { kfree(info->data_buff); @@ -967,7 +1309,7 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info) #else static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) { - info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL); + info->data_buff = kmalloc(info->buf_size, GFP_KERNEL); if (info->data_buff == NULL) return -ENOMEM; return 0; @@ -982,18 +1324,92 @@ static void pxa3xx_nand_free_buff(struct pxa3xx_nand_info *info) static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) { struct mtd_info *mtd; + struct nand_chip *chip; int ret; + mtd = info->host[info->cs]->mtd; + chip = mtd->priv; + /* use the common timing to make a try */ ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]); if (ret) return ret; - pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0); - if (info->is_ready) - return 0; + chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0); + ret = chip->waitfunc(mtd, chip); + if (ret & NAND_STATUS_FAIL) + return -ENODEV; - return -ENODEV; + return 0; +} + +static int pxa_ecc_init(struct pxa3xx_nand_info *info, + struct nand_ecc_ctrl *ecc, + int strength, int ecc_stepsize, int page_size) +{ + if (strength == 1 && ecc_stepsize == 512 && page_size == 2048) { + info->chunk_size = 2048; + info->spare_size = 40; + info->ecc_size = 24; + ecc->mode = NAND_ECC_HW; + ecc->size = 512; + ecc->strength = 1; + + } else if (strength == 1 && ecc_stepsize == 512 && page_size == 512) { + info->chunk_size = 512; + info->spare_size = 8; + info->ecc_size = 8; + ecc->mode = NAND_ECC_HW; + ecc->size = 512; + ecc->strength = 1; + + /* + * Required ECC: 4-bit correction per 512 bytes + * Select: 16-bit correction per 2048 bytes + */ + } else if (strength == 4 && ecc_stepsize == 512 && page_size == 2048) { + info->ecc_bch = 1; + info->chunk_size = 2048; + info->spare_size = 32; + info->ecc_size = 32; + ecc->mode = NAND_ECC_HW; + ecc->size = info->chunk_size; + ecc->layout = &ecc_layout_2KB_bch4bit; + ecc->strength = 16; + + } else if (strength == 4 && ecc_stepsize == 512 && page_size == 4096) { + info->ecc_bch = 1; + info->chunk_size = 2048; + info->spare_size = 32; + info->ecc_size = 32; + ecc->mode = NAND_ECC_HW; + ecc->size = info->chunk_size; + ecc->layout = &ecc_layout_4KB_bch4bit; + ecc->strength = 16; + + /* + * Required ECC: 8-bit correction per 512 bytes + * Select: 16-bit correction per 1024 bytes + */ + } else if (strength == 8 && ecc_stepsize == 512 && page_size == 4096) { + info->ecc_bch = 1; + info->chunk_size = 1024; + info->spare_size = 0; + info->ecc_size = 32; + ecc->mode = NAND_ECC_HW; + ecc->size = info->chunk_size; + ecc->layout = &ecc_layout_4KB_bch8bit; + ecc->strength = 16; + } else { + dev_err(&info->pdev->dev, + "ECC strength %d at page size %d is not supported\n", + strength, page_size); + return -ENODEV; + } + + dev_info(&info->pdev->dev, "ECC strength %d, ECC step size %d\n", + ecc->strength, ecc->size); + return 0; } static int pxa3xx_nand_scan(struct mtd_info *mtd) @@ -1008,6 +1424,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) uint32_t id = -1; uint64_t chipsize; int i, ret, num; + uint16_t ecc_strength, ecc_step; if (pdata->keep_config && !pxa3xx_nand_detect_config(info)) goto KEEP_CONFIG; @@ -1066,22 +1483,77 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) pxa3xx_flash_ids[1].name = NULL; def = pxa3xx_flash_ids; KEEP_CONFIG: - chip->ecc.mode = NAND_ECC_HW; - chip->ecc.size = host->page_size; - chip->ecc.strength = 1; - if (info->reg_ndcr & NDCR_DWIDTH_M) chip->options |= NAND_BUSWIDTH_16; + /* Device detection must be done with ECC disabled */ + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) + nand_writel(info, NDECCCTRL, 0x0); + if (nand_scan_ident(mtd, 1, def)) return -ENODEV; + + if (pdata->flash_bbt) { + /* + * We'll use a bad block table stored in-flash and don't + * allow writing the bad block marker to the flash. + */ + chip->bbt_options |= NAND_BBT_USE_FLASH | + NAND_BBT_NO_OOB_BBM; + chip->bbt_td = &bbt_main_descr; + chip->bbt_md = &bbt_mirror_descr; + } + + /* + * If the page size is bigger than the FIFO size, let's check + * we are given the right variant and then switch to the extended + * (aka splitted) command handling, + */ + if (mtd->writesize > PAGE_CHUNK_SIZE) { + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) { + chip->cmdfunc = nand_cmdfunc_extended; + } else { + dev_err(&info->pdev->dev, + "unsupported page size on this variant\n"); + return -ENODEV; + } + } + + if (pdata->ecc_strength && pdata->ecc_step_size) { + ecc_strength = pdata->ecc_strength; + ecc_step = pdata->ecc_step_size; + } else { + ecc_strength = chip->ecc_strength_ds; + ecc_step = chip->ecc_step_ds; + } + + /* Set default ECC strength requirements on non-ONFI devices */ + if (ecc_strength < 1 && ecc_step < 1) { + ecc_strength = 1; + ecc_step = 512; + } + + ret = pxa_ecc_init(info, &chip->ecc, ecc_strength, + ecc_step, mtd->writesize); + if (ret) + return ret; + /* calculate addressing information */ if (mtd->writesize >= 2048) host->col_addr_cycles = 2; else host->col_addr_cycles = 1; + /* release the initial buffer */ + kfree(info->data_buff); + + /* allocate the real data + oob buffer */ + info->buf_size = mtd->writesize + mtd->oobsize; + ret = pxa3xx_nand_init_buff(info); + if (ret) + return ret; info->oob_buff = info->data_buff + mtd->writesize; + if ((mtd->size >> chip->page_shift) > 65536) host->row_addr_cycles = 3; else @@ -1106,6 +1578,7 @@ static int alloc_nand_resource(struct platform_device *pdev) return -ENOMEM; info->pdev = pdev; + info->variant = pxa3xx_nand_get_variant(pdev); for (cs = 0; cs < pdata->num_cs; cs++) { mtd = (struct mtd_info *)((unsigned int)&info[1] + (sizeof(*mtd) + sizeof(*host)) * cs); @@ -1123,11 +1596,12 @@ static int alloc_nand_resource(struct platform_device *pdev) chip->controller = &info->controller; chip->waitfunc = pxa3xx_nand_waitfunc; chip->select_chip = pxa3xx_nand_select_chip; - chip->cmdfunc = pxa3xx_nand_cmdfunc; chip->read_word = pxa3xx_nand_read_word; chip->read_byte = pxa3xx_nand_read_byte; chip->read_buf = pxa3xx_nand_read_buf; chip->write_buf = pxa3xx_nand_write_buf; + chip->options |= NAND_NO_SUBPAGE_WRITE; + chip->cmdfunc = nand_cmdfunc; } spin_lock_init(&chip->controller->lock); @@ -1187,15 +1661,18 @@ static int alloc_nand_resource(struct platform_device *pdev) } info->mmio_phys = r->start; - ret = pxa3xx_nand_init_buff(info); - if (ret) + /* Allocate a buffer to allow flash detection */ + info->buf_size = INIT_BUFFER_SIZE; + info->data_buff = kmalloc(info->buf_size, GFP_KERNEL); + if (info->data_buff == NULL) { + ret = -ENOMEM; goto fail_disable_clk; + } /* initialize all interrupts to be disabled */ disable_int(info, NDSR_MASK); - ret = request_irq(irq, pxa3xx_nand_irq, IRQF_DISABLED, - pdev->name, info); + ret = request_irq(irq, pxa3xx_nand_irq, 0, pdev->name, info); if (ret < 0) { dev_err(&pdev->dev, "failed to request IRQ\n"); goto fail_free_buf; @@ -1207,7 +1684,7 @@ static int alloc_nand_resource(struct platform_device *pdev) fail_free_buf: free_irq(irq, info); - pxa3xx_nand_free_buff(info); + kfree(info->data_buff); fail_disable_clk: clk_disable_unprepare(info->clk); return ret; @@ -1236,29 +1713,6 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) return 0; } -static struct of_device_id pxa3xx_nand_dt_ids[] = { - { - .compatible = "marvell,pxa3xx-nand", - .data = (void *)PXA3XX_NAND_VARIANT_PXA, - }, - { - .compatible = "marvell,armada370-nand", - .data = (void *)PXA3XX_NAND_VARIANT_ARMADA370, - }, - {} -}; -MODULE_DEVICE_TABLE(of, pxa3xx_nand_dt_ids); - -static enum pxa3xx_nand_variant -pxa3xx_nand_get_variant(struct platform_device *pdev) -{ - const struct of_device_id *of_id = - of_match_device(pxa3xx_nand_dt_ids, &pdev->dev); - if (!of_id) - return PXA3XX_NAND_VARIANT_PXA; - return (enum pxa3xx_nand_variant)of_id->data; -} - static int pxa3xx_nand_probe_dt(struct platform_device *pdev) { struct pxa3xx_nand_platform_data *pdata; @@ -1278,6 +1732,15 @@ static int pxa3xx_nand_probe_dt(struct platform_device *pdev) if (of_get_property(np, "marvell,nand-keep-config", NULL)) pdata->keep_config = 1; of_property_read_u32(np, "num-cs", &pdata->num_cs); + pdata->flash_bbt = of_get_nand_on_flash_bbt(np); + + pdata->ecc_strength = of_get_nand_ecc_strength(np); + if (pdata->ecc_strength < 0) + pdata->ecc_strength = 0; + + pdata->ecc_step_size = of_get_nand_ecc_step_size(np); + if (pdata->ecc_step_size < 0) + pdata->ecc_step_size = 0; pdev->dev.platform_data = pdata; @@ -1315,12 +1778,16 @@ static int pxa3xx_nand_probe(struct platform_device *pdev) } info = platform_get_drvdata(pdev); - info->variant = pxa3xx_nand_get_variant(pdev); probe_success = 0; for (cs = 0; cs < pdata->num_cs; cs++) { struct mtd_info *mtd = info->host[cs]->mtd; - mtd->name = pdev->name; + /* + * The mtd name matches the one used in 'mtdparts' kernel + * parameter. This name cannot be changed or otherwise + * user's mtd partitions configuration would get broken. + */ + mtd->name = "pxa3xx_nand-0"; info->cs = cs; ret = pxa3xx_nand_scan(mtd); if (ret) { @@ -1407,7 +1874,7 @@ static int pxa3xx_nand_resume(struct platform_device *pdev) static struct platform_driver pxa3xx_nand_driver = { .driver = { .name = "pxa3xx-nand", - .of_match_table = of_match_ptr(pxa3xx_nand_dt_ids), + .of_match_table = pxa3xx_nand_dt_ids, }, .probe = pxa3xx_nand_probe, .remove = pxa3xx_nand_remove, diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index 9dcf02d22aa..baea83f4dea 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c @@ -181,7 +181,7 @@ static void r852_do_dma(struct r852_device *dev, uint8_t *buf, int do_read) /* Set dma direction */ dev->dma_dir = do_read; dev->dma_stage = 1; - INIT_COMPLETION(dev->dma_done); + reinit_completion(&dev->dma_done); dbg_verbose("doing dma %s ", do_read ? "read" : "write"); @@ -245,7 +245,7 @@ static void r852_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) } /* write DWORD chinks - faster */ - while (len) { + while (len >= 4) { reg = buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24; r852_write_reg_dword(dev, R852_DATALINE, reg); buf += 4; @@ -254,8 +254,10 @@ static void r852_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) } /* write rest */ - while (len) + while (len > 0) { r852_write_reg(dev, R852_DATALINE, *buf++); + len--; + } } /* diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index d65cbe903d4..79acbb8691b 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -29,7 +29,6 @@ #include <linux/module.h> #include <linux/types.h> -#include <linux/init.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/io.h> @@ -46,9 +45,43 @@ #include <linux/mtd/nand_ecc.h> #include <linux/mtd/partitions.h> -#include <plat/regs-nand.h> #include <linux/platform_data/mtd-nand-s3c2410.h> +#define S3C2410_NFREG(x) (x) + +#define S3C2410_NFCONF S3C2410_NFREG(0x00) +#define S3C2410_NFCMD S3C2410_NFREG(0x04) +#define S3C2410_NFADDR S3C2410_NFREG(0x08) +#define S3C2410_NFDATA S3C2410_NFREG(0x0C) +#define S3C2410_NFSTAT S3C2410_NFREG(0x10) +#define S3C2410_NFECC S3C2410_NFREG(0x14) +#define S3C2440_NFCONT S3C2410_NFREG(0x04) +#define S3C2440_NFCMD S3C2410_NFREG(0x08) +#define S3C2440_NFADDR S3C2410_NFREG(0x0C) +#define S3C2440_NFDATA S3C2410_NFREG(0x10) +#define S3C2440_NFSTAT S3C2410_NFREG(0x20) +#define S3C2440_NFMECC0 S3C2410_NFREG(0x2C) +#define S3C2412_NFSTAT S3C2410_NFREG(0x28) +#define S3C2412_NFMECC0 S3C2410_NFREG(0x34) +#define S3C2410_NFCONF_EN (1<<15) +#define S3C2410_NFCONF_INITECC (1<<12) +#define S3C2410_NFCONF_nFCE (1<<11) +#define S3C2410_NFCONF_TACLS(x) ((x)<<8) +#define S3C2410_NFCONF_TWRPH0(x) ((x)<<4) +#define S3C2410_NFCONF_TWRPH1(x) ((x)<<0) +#define S3C2410_NFSTAT_BUSY (1<<0) +#define S3C2440_NFCONF_TACLS(x) ((x)<<12) +#define S3C2440_NFCONF_TWRPH0(x) ((x)<<8) +#define S3C2440_NFCONF_TWRPH1(x) ((x)<<4) +#define S3C2440_NFCONT_INITECC (1<<4) +#define S3C2440_NFCONT_nFCE (1<<1) +#define S3C2440_NFCONT_ENABLE (1<<0) +#define S3C2440_NFSTAT_READY (1<<0) +#define S3C2412_NFCONF_NANDBOOT (1<<31) +#define S3C2412_NFCONT_INIT_MAIN_ECC (1<<5) +#define S3C2412_NFCONT_nFCE0 (1<<1) +#define S3C2412_NFSTAT_READY (1<<0) + /* new oob placement block for use with hardware ecc generation */ @@ -919,7 +952,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev) info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (info == NULL) { - dev_err(&pdev->dev, "no memory for flash info\n"); err = -ENOMEM; goto exit_error; } @@ -974,7 +1006,6 @@ static int s3c24xx_nand_probe(struct platform_device *pdev) size = nr_sets * sizeof(*info->mtds); info->mtds = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); if (info->mtds == NULL) { - dev_err(&pdev->dev, "failed to allocate mtd storage\n"); err = -ENOMEM; goto exit_error; } diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index a3c84ebbe39..c0670237e7a 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c @@ -151,7 +151,7 @@ static void flctl_setup_dma(struct sh_flctl *flctl) dma_cap_set(DMA_SLAVE, mask); flctl->chan_fifo0_tx = dma_request_channel(mask, shdma_chan_filter, - (void *)pdata->slave_id_fifo0_tx); + (void *)(uintptr_t)pdata->slave_id_fifo0_tx); dev_dbg(&pdev->dev, "%s: TX: got channel %p\n", __func__, flctl->chan_fifo0_tx); @@ -168,7 +168,7 @@ static void flctl_setup_dma(struct sh_flctl *flctl) goto err; flctl->chan_fifo0_rx = dma_request_channel(mask, shdma_chan_filter, - (void *)pdata->slave_id_fifo0_rx); + (void *)(uintptr_t)pdata->slave_id_fifo0_rx); dev_dbg(&pdev->dev, "%s: RX: got channel %p\n", __func__, flctl->chan_fifo0_rx); @@ -897,7 +897,7 @@ static void flctl_select_chip(struct mtd_info *mtd, int chipnr) if (!flctl->qos_request) { ret = dev_pm_qos_add_request(&flctl->pdev->dev, &flctl->pm_qos, - DEV_PM_QOS_LATENCY, + DEV_PM_QOS_RESUME_LATENCY, 100); if (ret < 0) dev_err(&flctl->pdev->dev, @@ -1021,7 +1021,6 @@ static irqreturn_t flctl_handle_flste(int irq, void *dev_id) return IRQ_HANDLED; } -#ifdef CONFIG_OF struct flctl_soc_config { unsigned long flcmncr_val; unsigned has_hwecc:1; @@ -1059,10 +1058,8 @@ static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev) pdata = devm_kzalloc(dev, sizeof(struct sh_flctl_platform_data), GFP_KERNEL); - if (!pdata) { - dev_err(dev, "%s: failed to allocate config data\n", __func__); + if (!pdata) return NULL; - } /* set SoC specific options */ pdata->flcmncr_val = config->flcmncr_val; @@ -1080,12 +1077,6 @@ static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev) return pdata; } -#else /* CONFIG_OF */ -static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev) -{ - return NULL; -} -#endif /* CONFIG_OF */ static int flctl_probe(struct platform_device *pdev) { @@ -1094,38 +1085,30 @@ static int flctl_probe(struct platform_device *pdev) struct mtd_info *flctl_mtd; struct nand_chip *nand; struct sh_flctl_platform_data *pdata; - int ret = -ENXIO; + int ret; int irq; struct mtd_part_parser_data ppdata = {}; - flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL); - if (!flctl) { - dev_err(&pdev->dev, "failed to allocate driver data\n"); + flctl = devm_kzalloc(&pdev->dev, sizeof(struct sh_flctl), GFP_KERNEL); + if (!flctl) return -ENOMEM; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "failed to get I/O memory\n"); - goto err_iomap; - } - - flctl->reg = ioremap(res->start, resource_size(res)); - if (flctl->reg == NULL) { - dev_err(&pdev->dev, "failed to remap I/O memory\n"); - goto err_iomap; - } + flctl->reg = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(flctl->reg)) + return PTR_ERR(flctl->reg); irq = platform_get_irq(pdev, 0); if (irq < 0) { dev_err(&pdev->dev, "failed to get flste irq data\n"); - goto err_flste; + return -ENXIO; } - ret = request_irq(irq, flctl_handle_flste, IRQF_SHARED, "flste", flctl); + ret = devm_request_irq(&pdev->dev, irq, flctl_handle_flste, IRQF_SHARED, + "flste", flctl); if (ret) { dev_err(&pdev->dev, "request interrupt failed.\n"); - goto err_flste; + return ret; } if (pdev->dev.of_node) @@ -1135,8 +1118,7 @@ static int flctl_probe(struct platform_device *pdev) if (!pdata) { dev_err(&pdev->dev, "no setup data defined\n"); - ret = -EINVAL; - goto err_pdata; + return -EINVAL; } platform_set_drvdata(pdev, flctl); @@ -1190,12 +1172,6 @@ static int flctl_probe(struct platform_device *pdev) err_chip: flctl_release_dma(flctl); pm_runtime_disable(&pdev->dev); -err_pdata: - free_irq(irq, flctl); -err_flste: - iounmap(flctl->reg); -err_iomap: - kfree(flctl); return ret; } @@ -1206,9 +1182,6 @@ static int flctl_remove(struct platform_device *pdev) flctl_release_dma(flctl); nand_release(&flctl->mtd); pm_runtime_disable(&pdev->dev); - free_irq(platform_get_irq(pdev, 0), flctl); - iounmap(flctl->reg); - kfree(flctl); return 0; } diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c index 87908d760fe..e81059b5838 100644 --- a/drivers/mtd/nand/sharpsl.c +++ b/drivers/mtd/nand/sharpsl.c @@ -121,10 +121,8 @@ static int sharpsl_nand_probe(struct platform_device *pdev) /* Allocate memory for MTD device structure and private data */ sharpsl = kzalloc(sizeof(struct sharpsl_nand), GFP_KERNEL); - if (!sharpsl) { - printk("Unable to allocate SharpSL NAND MTD device structure.\n"); + if (!sharpsl) return -ENOMEM; - } r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { @@ -136,7 +134,7 @@ static int sharpsl_nand_probe(struct platform_device *pdev) /* map physical address */ sharpsl->io = ioremap(r->start, resource_size(r)); if (!sharpsl->io) { - printk("ioremap to access Sharp SL NAND chip failed\n"); + dev_err(&pdev->dev, "ioremap to access Sharp SL NAND chip failed\n"); err = -EIO; goto err_ioremap; } diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c index 09dde7d2717..fe8058a4505 100644 --- a/drivers/mtd/nand/socrates_nand.c +++ b/drivers/mtd/nand/socrates_nand.c @@ -15,6 +15,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> +#include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/io.h> @@ -149,17 +150,13 @@ static int socrates_nand_probe(struct platform_device *ofdev) struct mtd_part_parser_data ppdata; /* Allocate memory for the device structure (and zero it) */ - host = kzalloc(sizeof(struct socrates_nand_host), GFP_KERNEL); - if (!host) { - printk(KERN_ERR - "socrates_nand: failed to allocate device structure.\n"); + host = devm_kzalloc(&ofdev->dev, sizeof(*host), GFP_KERNEL); + if (!host) return -ENOMEM; - } host->io_base = of_iomap(ofdev->dev.of_node, 0); if (host->io_base == NULL) { - printk(KERN_ERR "socrates_nand: ioremap failed\n"); - kfree(host); + dev_err(&ofdev->dev, "ioremap failed\n"); return -EIO; } @@ -211,9 +208,7 @@ static int socrates_nand_probe(struct platform_device *ofdev) nand_release(mtd); out: - dev_set_drvdata(&ofdev->dev, NULL); iounmap(host->io_base); - kfree(host); return res; } @@ -227,9 +222,7 @@ static int socrates_nand_remove(struct platform_device *ofdev) nand_release(mtd); - dev_set_drvdata(&ofdev->dev, NULL); iounmap(host->io_base); - kfree(host); return 0; } diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c index 396530d87ec..fb8fd35fa66 100644 --- a/drivers/mtd/nand/tmio_nand.c +++ b/drivers/mtd/nand/tmio_nand.c @@ -371,11 +371,9 @@ static int tmio_probe(struct platform_device *dev) if (data == NULL) dev_warn(&dev->dev, "NULL platform data!\n"); - tmio = kzalloc(sizeof *tmio, GFP_KERNEL); - if (!tmio) { - retval = -ENOMEM; - goto err_kzalloc; - } + tmio = devm_kzalloc(&dev->dev, sizeof(*tmio), GFP_KERNEL); + if (!tmio) + return -ENOMEM; tmio->dev = dev; @@ -385,22 +383,18 @@ static int tmio_probe(struct platform_device *dev) mtd->priv = nand_chip; mtd->name = "tmio-nand"; - tmio->ccr = ioremap(ccr->start, resource_size(ccr)); - if (!tmio->ccr) { - retval = -EIO; - goto err_iomap_ccr; - } + tmio->ccr = devm_ioremap(&dev->dev, ccr->start, resource_size(ccr)); + if (!tmio->ccr) + return -EIO; tmio->fcr_base = fcr->start & 0xfffff; - tmio->fcr = ioremap(fcr->start, resource_size(fcr)); - if (!tmio->fcr) { - retval = -EIO; - goto err_iomap_fcr; - } + tmio->fcr = devm_ioremap(&dev->dev, fcr->start, resource_size(fcr)); + if (!tmio->fcr) + return -EIO; retval = tmio_hw_init(dev, tmio); if (retval) - goto err_hwinit; + return retval; /* Set address of NAND IO lines */ nand_chip->IO_ADDR_R = tmio->fcr; @@ -428,8 +422,8 @@ static int tmio_probe(struct platform_device *dev) /* 15 us command delay time */ nand_chip->chip_delay = 15; - retval = request_irq(irq, &tmio_irq, - IRQF_DISABLED, dev_name(&dev->dev), tmio); + retval = devm_request_irq(&dev->dev, irq, &tmio_irq, 0, + dev_name(&dev->dev), tmio); if (retval) { dev_err(&dev->dev, "request_irq error %d\n", retval); goto err_irq; @@ -441,7 +435,7 @@ static int tmio_probe(struct platform_device *dev) /* Scan to find existence of the device */ if (nand_scan(mtd, 1)) { retval = -ENODEV; - goto err_scan; + goto err_irq; } /* Register the partitions */ retval = mtd_device_parse_register(mtd, NULL, NULL, @@ -452,18 +446,8 @@ static int tmio_probe(struct platform_device *dev) nand_release(mtd); -err_scan: - if (tmio->irq) - free_irq(tmio->irq, tmio); err_irq: tmio_hw_stop(dev, tmio); -err_hwinit: - iounmap(tmio->fcr); -err_iomap_fcr: - iounmap(tmio->ccr); -err_iomap_ccr: - kfree(tmio); -err_kzalloc: return retval; } @@ -472,12 +456,7 @@ static int tmio_remove(struct platform_device *dev) struct tmio_nand *tmio = platform_get_drvdata(dev); nand_release(&tmio->mtd); - if (tmio->irq) - free_irq(tmio->irq, tmio); tmio_hw_stop(dev, tmio); - iounmap(tmio->fcr); - iounmap(tmio->ccr); - kfree(tmio); return 0; } diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c index 235714a421d..c1622a5ba81 100644 --- a/drivers/mtd/nand/txx9ndfmc.c +++ b/drivers/mtd/nand/txx9ndfmc.c @@ -319,11 +319,8 @@ static int __init txx9ndfmc_probe(struct platform_device *dev) continue; txx9_priv = kzalloc(sizeof(struct txx9ndfmc_priv), GFP_KERNEL); - if (!txx9_priv) { - dev_err(&dev->dev, "Unable to allocate " - "TXx9 NDFMC MTD device structure.\n"); + if (!txx9_priv) continue; - } chip = &txx9_priv->chip; mtd = &txx9_priv->mtd; mtd->owner = THIS_MODULE; |
