diff options
author | Miquel Raynal <miquel.raynal@bootlin.com> | 2021-09-03 00:04:16 +0200 |
---|---|---|
committer | Miquel Raynal <miquel.raynal@bootlin.com> | 2021-09-03 00:04:16 +0200 |
commit | c1fe77e42440d2cad76055df6fb58caabf622d51 (patch) | |
tree | ac61d6979fbf5f2cf50bf00922a2cd29320f080c | |
parent | ee28b42006c37aaeb68c83300fe5608db662082f (diff) | |
parent | 6b430c7595e4eb95fae8fb54adc3c3ce002e75ae (diff) | |
download | linux-stable-c1fe77e42440d2cad76055df6fb58caabf622d51.tar.gz linux-stable-c1fe77e42440d2cad76055df6fb58caabf622d51.tar.bz2 linux-stable-c1fe77e42440d2cad76055df6fb58caabf622d51.zip |
Merge tag 'nand/for-5.15' into mtd/next
NAND core changes:
* Repair Miquel Raynal's email address in MAINTAINERS
* Fix a couple of spelling mistakes in Kconfig
* bbt: Skip bad blocks when searching for the BBT in NAND
* Remove never changed ret variable
Raw NAND changes:
* cafe: Fix a resource leak in the error handling path of 'cafe_nand_probe()'
* intel: Fix error handling in probe
* omap: Fix kernel doc warning on 'calcuate' typo
* gpmc: Fix the ECC bytes vs. OOB bytes equation
SPI-NAND core changes:
* Properly fill the OOB area.
* Fix comment
SPI-NAND drivers changes:
* macronix: Add Quad support for serial NAND flash
-rw-r--r-- | Documentation/devicetree/bindings/mtd/gpmc-nand.txt | 2 | ||||
-rw-r--r-- | MAINTAINERS | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/Kconfig | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/cafe_nand.c | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/intel-nand-controller.c | 27 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/meson_nand.c | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/nand_bbt.c | 33 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/omap2.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/spi/core.c | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/spi/macronix.c | 16 |
10 files changed, 73 insertions, 27 deletions
diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt index 44919d48d241..c459f169a904 100644 --- a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt +++ b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt @@ -122,7 +122,7 @@ on various other factors also like; so the device should have enough free bytes available its OOB/Spare area to accommodate ECC for entire page. In general following expression helps in determining if given device can accommodate ECC syndrome: - "2 + (PAGESIZE / 512) * ECC_BYTES" >= OOBSIZE" + "2 + (PAGESIZE / 512) * ECC_BYTES" <= OOBSIZE" where OOBSIZE number of bytes in OOB/spare area PAGESIZE number of bytes in main-area of device page diff --git a/MAINTAINERS b/MAINTAINERS index a61f4f3b78a9..10d3fafe056c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1475,7 +1475,7 @@ F: drivers/amba/ F: include/linux/amba/bus.h ARM PRIMECELL PL35X NAND CONTROLLER DRIVER -M: Miquel Raynal <miquel.raynal@bootlin.com@bootlin.com> +M: Miquel Raynal <miquel.raynal@bootlin.com> M: Naga Sureshkumar Relli <nagasure@xilinx.com> L: linux-mtd@lists.infradead.org S: Maintained @@ -1483,7 +1483,7 @@ F: Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml F: drivers/mtd/nand/raw/pl35x-nand-controller.c ARM PRIMECELL PL35X SMC DRIVER -M: Miquel Raynal <miquel.raynal@bootlin.com@bootlin.com> +M: Miquel Raynal <miquel.raynal@bootlin.com> M: Naga Sureshkumar Relli <nagasure@xilinx.com> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index 630728de4b7c..67b7cb67c030 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -480,9 +480,9 @@ config MTD_NAND_RICOH select MTD_SM_COMMON help Enable support for Ricoh R5C852 xD card reader - You also need to enable ether + You also need to enable either NAND SSFDC (SmartMedia) read only translation layer' or new - expermental, readwrite + experimental, readwrite 'SmartMedia/xD new translation layer' config MTD_NAND_DISKONCHIP diff --git a/drivers/mtd/nand/raw/cafe_nand.c b/drivers/mtd/nand/raw/cafe_nand.c index d0e8ffd55c22..9dbf031716a6 100644 --- a/drivers/mtd/nand/raw/cafe_nand.c +++ b/drivers/mtd/nand/raw/cafe_nand.c @@ -751,7 +751,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_ior; + goto out_free_rs; } /* Disable master reset, enable NAND clock */ @@ -795,6 +795,8 @@ static int cafe_nand_probe(struct pci_dev *pdev, /* 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_rs: + free_rs(cafe->rs); out_ior: pci_iounmap(pdev, cafe->mmio); out_free_mtd: diff --git a/drivers/mtd/nand/raw/intel-nand-controller.c b/drivers/mtd/nand/raw/intel-nand-controller.c index 8b49fd56cf96..29e8a546dcd6 100644 --- a/drivers/mtd/nand/raw/intel-nand-controller.c +++ b/drivers/mtd/nand/raw/intel-nand-controller.c @@ -631,19 +631,26 @@ static int ebu_nand_probe(struct platform_device *pdev) ebu_host->clk_rate = clk_get_rate(ebu_host->clk); ebu_host->dma_tx = dma_request_chan(dev, "tx"); - if (IS_ERR(ebu_host->dma_tx)) - return dev_err_probe(dev, PTR_ERR(ebu_host->dma_tx), - "failed to request DMA tx chan!.\n"); + if (IS_ERR(ebu_host->dma_tx)) { + ret = dev_err_probe(dev, PTR_ERR(ebu_host->dma_tx), + "failed to request DMA tx chan!.\n"); + goto err_disable_unprepare_clk; + } ebu_host->dma_rx = dma_request_chan(dev, "rx"); - if (IS_ERR(ebu_host->dma_rx)) - return dev_err_probe(dev, PTR_ERR(ebu_host->dma_rx), - "failed to request DMA rx chan!.\n"); + if (IS_ERR(ebu_host->dma_rx)) { + ret = dev_err_probe(dev, PTR_ERR(ebu_host->dma_rx), + "failed to request DMA rx chan!.\n"); + ebu_host->dma_rx = NULL; + goto err_cleanup_dma; + } resname = devm_kasprintf(dev, GFP_KERNEL, "addr_sel%d", cs); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, resname); - if (!res) - return -EINVAL; + if (!res) { + ret = -EINVAL; + goto err_cleanup_dma; + } ebu_host->cs[cs].addr_sel = res->start; writel(ebu_host->cs[cs].addr_sel | EBU_ADDR_MASK(5) | EBU_ADDR_SEL_REGEN, ebu_host->ebu + EBU_ADDR_SEL(cs)); @@ -653,7 +660,8 @@ static int ebu_nand_probe(struct platform_device *pdev) mtd = nand_to_mtd(&ebu_host->chip); if (!mtd->name) { dev_err(ebu_host->dev, "NAND label property is mandatory\n"); - return -EINVAL; + ret = -EINVAL; + goto err_cleanup_dma; } mtd->dev.parent = dev; @@ -681,6 +689,7 @@ err_clean_nand: nand_cleanup(&ebu_host->chip); err_cleanup_dma: ebu_dma_cleanup(ebu_host); +err_disable_unprepare_clk: clk_disable_unprepare(ebu_host->clk); return ret; diff --git a/drivers/mtd/nand/raw/meson_nand.c b/drivers/mtd/nand/raw/meson_nand.c index 817bddccb775..ac3be92872d0 100644 --- a/drivers/mtd/nand/raw/meson_nand.c +++ b/drivers/mtd/nand/raw/meson_nand.c @@ -580,7 +580,7 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand, u32 *addrs = nfc->cmdfifo.rw.addrs; u32 cs = nfc->param.chip_select; u32 cmd0, cmd_num, row_start; - int ret = 0, i; + int i; cmd_num = sizeof(struct nand_rw_cmd) / sizeof(int); @@ -620,7 +620,7 @@ static int meson_nfc_rw_cmd_prepare_and_execute(struct nand_chip *nand, meson_nfc_cmd_idle(nfc, nfc->timing.tadl); } - return ret; + return 0; } static int meson_nfc_write_page_sub(struct nand_chip *nand, diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c index dced32a126d9..b7ad030225f8 100644 --- a/drivers/mtd/nand/raw/nand_bbt.c +++ b/drivers/mtd/nand/raw/nand_bbt.c @@ -447,6 +447,35 @@ static int scan_block_fast(struct nand_chip *this, struct nand_bbt_descr *bd, return 0; } +/* Check if a potential BBT block is marked as bad */ +static int bbt_block_checkbad(struct nand_chip *this, struct nand_bbt_descr *td, + loff_t offs, uint8_t *buf) +{ + struct nand_bbt_descr *bd = this->badblock_pattern; + + /* + * No need to check for a bad BBT block if the BBM area overlaps with + * the bad block table marker area in OOB since writing a BBM here + * invalidates the bad block table marker anyway. + */ + if (!(td->options & NAND_BBT_NO_OOB) && + td->offs >= bd->offs && td->offs < bd->offs + bd->len) + return 0; + + /* + * There is no point in checking for a bad block marker if writing + * such marker is not supported + */ + if (this->bbt_options & NAND_BBT_NO_OOB_BBM || + this->options & NAND_NO_BBM_QUIRK) + return 0; + + if (scan_block_fast(this, bd, offs, buf) > 0) + return 1; + + return 0; +} + /** * create_bbt - [GENERIC] Create a bad block table by scanning the device * @this: NAND chip object @@ -560,6 +589,10 @@ static int search_bbt(struct nand_chip *this, uint8_t *buf, int actblock = startblock + dir * block; loff_t offs = (loff_t)actblock << this->bbt_erase_shift; + /* Check if block is marked bad */ + if (bbt_block_checkbad(this, td, offs, buf)) + continue; + /* Read first page */ scan_read(this, buf, offs, mtd->writesize, td); if (!check_pattern(buf, scanlen, mtd->writesize, td)) { diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index b1839eef5b65..b26d4947af02 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -911,7 +911,7 @@ static int omap_correct_data(struct nand_chip *chip, u_char *dat, } /** - * omap_calcuate_ecc - Generate non-inverted ECC bytes. + * omap_calculate_ecc - Generate non-inverted ECC bytes. * @chip: NAND chip object * @dat: The pointer to data on which ecc is computed * @ecc_code: The ecc_code buffer diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 446ba8d43fbc..2c8685f1f2fa 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -288,6 +288,8 @@ static int spinand_ondie_ecc_prepare_io_req(struct nand_device *nand, struct spinand_device *spinand = nand_to_spinand(nand); bool enable = (req->mode != MTD_OPS_RAW); + memset(spinand->oobbuf, 0xff, nanddev_per_page_oobsize(nand)); + /* Only enable or disable the engine */ return spinand_ecc_enable(spinand, enable); } @@ -307,7 +309,7 @@ static int spinand_ondie_ecc_finish_io_req(struct nand_device *nand, if (req->type == NAND_PAGE_WRITE) return 0; - /* Finish a page write: check the status, report errors/bitflips */ + /* Finish a page read: check the status, report errors/bitflips */ ret = spinand_check_ecc_status(spinand, engine_conf->status); if (ret == -EBADMSG) mtd->ecc_stats.failed++; diff --git a/drivers/mtd/nand/spi/macronix.c b/drivers/mtd/nand/spi/macronix.c index a9890350db02..3f31f1381a62 100644 --- a/drivers/mtd/nand/spi/macronix.c +++ b/drivers/mtd/nand/spi/macronix.c @@ -126,7 +126,7 @@ static const struct spinand_info macronix_spinand_table[] = { SPINAND_INFO_OP_VARIANTS(&read_cache_variants, &write_cache_variants, &update_cache_variants), - 0, + SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, mx35lf1ge4ab_ecc_get_status)), SPINAND_INFO("MX35LF4GE4AD", @@ -136,7 +136,7 @@ static const struct spinand_info macronix_spinand_table[] = { SPINAND_INFO_OP_VARIANTS(&read_cache_variants, &write_cache_variants, &update_cache_variants), - 0, + SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, mx35lf1ge4ab_ecc_get_status)), SPINAND_INFO("MX35LF1G24AD", @@ -146,16 +146,16 @@ static const struct spinand_info macronix_spinand_table[] = { SPINAND_INFO_OP_VARIANTS(&read_cache_variants, &write_cache_variants, &update_cache_variants), - 0, + SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)), SPINAND_INFO("MX35LF2G24AD", SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x24), - NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 1, 1, 1), + NAND_MEMORG(1, 2048, 128, 64, 2048, 40, 2, 1, 1), NAND_ECCREQ(8, 512), SPINAND_INFO_OP_VARIANTS(&read_cache_variants, &write_cache_variants, &update_cache_variants), - 0, + SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)), SPINAND_INFO("MX35LF4G24AD", SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x35), @@ -164,7 +164,7 @@ static const struct spinand_info macronix_spinand_table[] = { SPINAND_INFO_OP_VARIANTS(&read_cache_variants, &write_cache_variants, &update_cache_variants), - 0, + SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, NULL)), SPINAND_INFO("MX31LF1GE4BC", SPINAND_ID(SPINAND_READID_METHOD_OPCODE_DUMMY, 0x1e), @@ -173,7 +173,7 @@ static const struct spinand_info macronix_spinand_table[] = { SPINAND_INFO_OP_VARIANTS(&read_cache_variants, &write_cache_variants, &update_cache_variants), - 0 /*SPINAND_HAS_QE_BIT*/, + SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, mx35lf1ge4ab_ecc_get_status)), SPINAND_INFO("MX31UF1GE4BC", @@ -183,7 +183,7 @@ static const struct spinand_info macronix_spinand_table[] = { SPINAND_INFO_OP_VARIANTS(&read_cache_variants, &write_cache_variants, &update_cache_variants), - 0 /*SPINAND_HAS_QE_BIT*/, + SPINAND_HAS_QE_BIT, SPINAND_ECCINFO(&mx35lfxge4ab_ooblayout, mx35lf1ge4ab_ecc_get_status)), |