From 5854d4a6cc356ba3e16d8593ac1c089a32d1759c Mon Sep 17 00:00:00 2001 From: Tudor Ambarus Date: Fri, 29 Oct 2021 20:26:12 +0300 Subject: mtd: spi-nor: Get rid of nor->page_size nor->page_size duplicated what nor->params->page_size indicates for no good reason. page_size is a flash parameter of fixed value and it is better suited to be found in nor->params->page_size. Signed-off-by: Tudor Ambarus Reviewed-by: Pratyush Yadav Reviewed-by: Michael Walle Link: https://lore.kernel.org/r/20211029172633.886453-5-tudor.ambarus@microchip.com --- include/linux/mtd/spi-nor.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index f67457748ed8..fc90fce26e33 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -371,7 +371,6 @@ struct spi_nor_flash_parameter; * @bouncebuf_size: size of the bounce buffer * @info: SPI NOR part JEDEC MFR ID and other info * @manufacturer: SPI NOR manufacturer - * @page_size: the page size of the SPI NOR * @addr_width: number of address bytes * @erase_opcode: the opcode for erasing a sector * @read_opcode: the read opcode @@ -401,7 +400,6 @@ struct spi_nor { size_t bouncebuf_size; const struct flash_info *info; const struct spi_nor_manufacturer *manufacturer; - u32 page_size; u8 addr_width; u8 erase_opcode; u8 read_opcode; -- cgit v1.2.3 From d8466f73010faf71effb21228ae1cbf577dab130 Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sat, 16 Oct 2021 14:22:27 +0100 Subject: mtd: rawnand: Export nand_read_page_hwecc_oob_first() Move the function nand_read_page_hwecc_oob_first() (previously nand_davinci_read_page_hwecc_oob_first()) to nand_base.c, and export it as a GPL symbol, so that it can be used by more modules. Cc: # v5.2 Fixes: a0ac778eb82c ("mtd: rawnand: ingenic: Add support for the JZ4740") Signed-off-by: Paul Cercueil Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20211016132228.40254-4-paul@crapouillou.net --- drivers/mtd/nand/raw/davinci_nand.c | 69 +------------------------------------ drivers/mtd/nand/raw/nand_base.c | 67 +++++++++++++++++++++++++++++++++++ include/linux/mtd/rawnand.h | 2 ++ 3 files changed, 70 insertions(+), 68 deletions(-) (limited to 'include') diff --git a/drivers/mtd/nand/raw/davinci_nand.c b/drivers/mtd/nand/raw/davinci_nand.c index fe2511cdcae3..45fec8c192ab 100644 --- a/drivers/mtd/nand/raw/davinci_nand.c +++ b/drivers/mtd/nand/raw/davinci_nand.c @@ -371,73 +371,6 @@ correct: return corrected; } -/** - * nand_davinci_read_page_hwecc_oob_first - Hardware ECC page read with ECC - * data read from OOB area - * @chip: nand chip info structure - * @buf: buffer to store read data - * @oob_required: caller requires OOB data read to chip->oob_poi - * @page: page number to read - * - * Hardware ECC for large page chips, which requires the ECC data to be - * extracted from the OOB before the actual data is read. - */ -static int nand_davinci_read_page_hwecc_oob_first(struct nand_chip *chip, - uint8_t *buf, - int oob_required, int page) -{ - struct mtd_info *mtd = nand_to_mtd(chip); - int i, eccsize = chip->ecc.size, ret; - int eccbytes = chip->ecc.bytes; - int eccsteps = chip->ecc.steps; - uint8_t *p = buf; - uint8_t *ecc_code = chip->ecc.code_buf; - unsigned int max_bitflips = 0; - - /* Read the OOB area first */ - ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize); - if (ret) - return ret; - - /* Move read cursor to start of page */ - ret = nand_change_read_column_op(chip, 0, NULL, 0, false); - if (ret) - return ret; - - ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, - chip->ecc.total); - if (ret) - return ret; - - for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { - int stat; - - chip->ecc.hwctl(chip, NAND_ECC_READ); - - ret = nand_read_data_op(chip, p, eccsize, false, false); - if (ret) - return ret; - - stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL); - if (stat == -EBADMSG && - (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) { - /* check for empty pages with bitflips */ - stat = nand_check_erased_ecc_chunk(p, eccsize, - &ecc_code[i], - eccbytes, NULL, 0, - chip->ecc.strength); - } - - if (stat < 0) { - mtd->ecc_stats.failed++; - } else { - mtd->ecc_stats.corrected += stat; - max_bitflips = max_t(unsigned int, max_bitflips, stat); - } - } - return max_bitflips; -} - /*----------------------------------------------------------------------*/ /* An ECC layout for using 4-bit ECC with small-page flash, storing @@ -647,7 +580,7 @@ static int davinci_nand_attach_chip(struct nand_chip *chip) } else if (chunks == 4 || chunks == 8) { mtd_set_ooblayout(mtd, nand_get_large_page_ooblayout()); - chip->ecc.read_page = nand_davinci_read_page_hwecc_oob_first; + chip->ecc.read_page = nand_read_page_hwecc_oob_first; } else { return -EIO; } diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 3d6c6e880520..113a2e9f43b1 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -3160,6 +3160,73 @@ static int nand_read_page_hwecc(struct nand_chip *chip, uint8_t *buf, return max_bitflips; } +/** + * nand_read_page_hwecc_oob_first - Hardware ECC page read with ECC + * data read from OOB area + * @chip: nand chip info structure + * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi + * @page: page number to read + * + * Hardware ECC for large page chips, which requires the ECC data to be + * extracted from the OOB before the actual data is read. + */ +int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + int i, eccsize = chip->ecc.size, ret; + int eccbytes = chip->ecc.bytes; + int eccsteps = chip->ecc.steps; + uint8_t *p = buf; + uint8_t *ecc_code = chip->ecc.code_buf; + unsigned int max_bitflips = 0; + + /* Read the OOB area first */ + ret = nand_read_oob_op(chip, page, 0, chip->oob_poi, mtd->oobsize); + if (ret) + return ret; + + /* Move read cursor to start of page */ + ret = nand_change_read_column_op(chip, 0, NULL, 0, false); + if (ret) + return ret; + + ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0, + chip->ecc.total); + if (ret) + return ret; + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) { + int stat; + + chip->ecc.hwctl(chip, NAND_ECC_READ); + + ret = nand_read_data_op(chip, p, eccsize, false, false); + if (ret) + return ret; + + stat = chip->ecc.correct(chip, p, &ecc_code[i], NULL); + if (stat == -EBADMSG && + (chip->ecc.options & NAND_ECC_GENERIC_ERASED_CHECK)) { + /* check for empty pages with bitflips */ + stat = nand_check_erased_ecc_chunk(p, eccsize, + &ecc_code[i], + eccbytes, NULL, 0, + chip->ecc.strength); + } + + if (stat < 0) { + mtd->ecc_stats.failed++; + } else { + mtd->ecc_stats.corrected += stat; + max_bitflips = max_t(unsigned int, max_bitflips, stat); + } + } + return max_bitflips; +} +EXPORT_SYMBOL_GPL(nand_read_page_hwecc_oob_first); + /** * nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read * @chip: nand chip info structure diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index b2f9dd3cbd69..5b88cd51fadb 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -1539,6 +1539,8 @@ int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len, bool force_8bit, bool check_only); int nand_write_data_op(struct nand_chip *chip, const void *buf, unsigned int len, bool force_8bit); +int nand_read_page_hwecc_oob_first(struct nand_chip *chip, uint8_t *buf, + int oob_required, int page); /* Scan and identify a NAND device */ int nand_scan_with_ids(struct nand_chip *chip, unsigned int max_chips, -- cgit v1.2.3 From e2748ad5257754a47376e28c0f9dda4f5c1e5ca3 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Tue, 2 Nov 2021 16:02:00 -0600 Subject: mtd: remove unused header file Commit d24dbd7541ff ("mtd: maps: Get rid of the latch-addr-flash driver") removed the last user of but left the header file behind. Nothing uses this file, delete it now. Cc: Boris Brezillon Cc: Miquel Raynal Cc: Richard Weinberger Cc: Vignesh Raghavendra Cc: linux-mtd@lists.infradead.org Signed-off-by: Jonathan Corbet Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20211102220203.940290-7-corbet@lwn.net --- include/linux/mtd/latch-addr-flash.h | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 include/linux/mtd/latch-addr-flash.h (limited to 'include') diff --git a/include/linux/mtd/latch-addr-flash.h b/include/linux/mtd/latch-addr-flash.h deleted file mode 100644 index e94b8e128074..000000000000 --- a/include/linux/mtd/latch-addr-flash.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Interface for NOR flash driver whose high address lines are latched - * - * Copyright © 2008 MontaVista Software, Inc. - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ -#ifndef __LATCH_ADDR_FLASH__ -#define __LATCH_ADDR_FLASH__ - -struct map_info; -struct mtd_partition; - -struct latch_addr_flash_data { - unsigned int width; - unsigned int size; - - int (*init)(void *data, int cs); - void (*done)(void *data); - void (*set_window)(unsigned long offset, void *data); - void *data; - - unsigned int nr_parts; - struct mtd_partition *parts; -}; - -#endif -- cgit v1.2.3 From 67b967ddd93d0ed57d392a00f6f90060f0910c0e Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Thu, 18 Nov 2021 12:46:59 +0100 Subject: mtd: Introduce an expert mode for forensics and debugging purposes When developping NAND controller drivers or when debugging filesystem corruptions, it is quite common to need hacking locally into the MTD/NAND core in order to get access to the content of the bad blocks. Instead of having multiple implementations out there let's provide a simple yet effective specific MTD-wide debugfs entry to fully disable these checks on purpose. A warning is added to inform the user when this mode gets enabled. Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20211118114659.1282855-1-miquel.raynal@bootlin.com --- drivers/mtd/mtdcore.c | 10 ++++++++++ drivers/mtd/nand/core.c | 3 +++ drivers/mtd/nand/raw/nand_base.c | 3 +++ drivers/mtd/nand/raw/nand_bbt.c | 3 +++ include/linux/mtd/mtd.h | 3 +++ 5 files changed, 22 insertions(+) (limited to 'include') diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index a7723a708ea7..70f492dce158 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -2370,6 +2370,14 @@ static struct backing_dev_info * __init mtd_bdi_init(const char *name) return ret ? ERR_PTR(ret) : bdi; } +char *mtd_expert_analysis_warning = + "Bad block checks have been entirely disabled.\n" + "This is only reserved for post-mortem forensics and debug purposes.\n" + "Never enable this mode if you do not know what you are doing!\n"; +EXPORT_SYMBOL_GPL(mtd_expert_analysis_warning); +bool mtd_expert_analysis_mode; +EXPORT_SYMBOL_GPL(mtd_expert_analysis_mode); + static struct proc_dir_entry *proc_mtd; static int __init init_mtd(void) @@ -2393,6 +2401,8 @@ static int __init init_mtd(void) goto out_procfs; dfs_dir_mtd = debugfs_create_dir("mtd", NULL); + debugfs_create_bool("expert_analysis_mode", 0600, dfs_dir_mtd, + &mtd_expert_analysis_mode); return 0; diff --git a/drivers/mtd/nand/core.c b/drivers/mtd/nand/core.c index 5e13a03d2b32..416947f28b67 100644 --- a/drivers/mtd/nand/core.c +++ b/drivers/mtd/nand/core.c @@ -21,6 +21,9 @@ */ bool nanddev_isbad(struct nand_device *nand, const struct nand_pos *pos) { + if (WARN_ONCE(mtd_expert_analysis_mode, mtd_expert_analysis_warning)) + return false; + if (nanddev_bbt_is_initialized(nand)) { unsigned int entry; int status; diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 3d6c6e880520..b3a9bc08b4bb 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -321,6 +321,9 @@ static int nand_isbad_bbm(struct nand_chip *chip, loff_t ofs) if (nand_region_is_secured(chip, ofs, mtd->erasesize)) return -EIO; + if (WARN_ONCE(mtd_expert_analysis_mode, mtd_expert_analysis_warning)) + return 0; + if (chip->legacy.block_bad) return chip->legacy.block_bad(chip, ofs); diff --git a/drivers/mtd/nand/raw/nand_bbt.c b/drivers/mtd/nand/raw/nand_bbt.c index b7ad030225f8..ab630af3a309 100644 --- a/drivers/mtd/nand/raw/nand_bbt.c +++ b/drivers/mtd/nand/raw/nand_bbt.c @@ -1455,6 +1455,9 @@ int nand_isbad_bbt(struct nand_chip *this, loff_t offs, int allowbbt) pr_debug("nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n", (unsigned int)offs, block, res); + if (WARN_ONCE(mtd_expert_analysis_mode, mtd_expert_analysis_warning)) + return 0; + switch (res) { case BBT_BLOCK_GOOD: return 0; diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index f5e7dfc2e4e9..1ffa933121f6 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -711,4 +711,7 @@ static inline int mtd_is_bitflip_or_eccerr(int err) { unsigned mtd_mmap_capabilities(struct mtd_info *mtd); +extern char *mtd_expert_analysis_warning; +extern bool mtd_expert_analysis_mode; + #endif /* __MTD_MTD_H__ */ -- cgit v1.2.3 From f2f8115fe8b390af27d013411045bd712a812103 Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 21 Dec 2021 15:17:56 +0200 Subject: memory: omap-gpmc: Use a compatible match table when checking for NAND controller As more compatibles can be added to the GPMC NAND controller driver use a compatible match table. Signed-off-by: Roger Quadros Acked-by: Miquel Raynal Link: https://lore.kernel.org/r/20211221131757.2030-4-rogerq@kernel.org [krzysztof: remove "is_nand" variable] Signed-off-by: Krzysztof Kozlowski --- drivers/memory/omap-gpmc.c | 2 +- drivers/mtd/nand/raw/omap2.c | 5 +---- include/linux/platform_data/mtd-nand-omap2.h | 9 ++++++++- 3 files changed, 10 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index 5e2ba39b6450..ed11887c1b7c 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c @@ -2183,7 +2183,7 @@ static int gpmc_probe_generic_child(struct platform_device *pdev, } } - if (of_device_is_compatible(child, "ti,omap2-nand")) { + if (of_match_node(omap_nand_ids, child)) { /* NAND specific setup */ val = 8; of_property_read_u32(child, "nand-bus-width", &val); diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c index b26d4947af02..e6dd8b4cf0d2 100644 --- a/drivers/mtd/nand/raw/omap2.c +++ b/drivers/mtd/nand/raw/omap2.c @@ -2352,10 +2352,7 @@ static int omap_nand_remove(struct platform_device *pdev) return ret; } -static const struct of_device_id omap_nand_ids[] = { - { .compatible = "ti,omap2-nand", }, - {}, -}; +/* omap_nand_ids defined in linux/platform_data/mtd-nand-omap2.h */ MODULE_DEVICE_TABLE(of, omap_nand_ids); static struct platform_driver omap_nand_driver = { diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h index de6ada739121..92f011805ad4 100644 --- a/include/linux/platform_data/mtd-nand-omap2.h +++ b/include/linux/platform_data/mtd-nand-omap2.h @@ -7,6 +7,7 @@ #define _MTD_NAND_OMAP2_H #include +#include #define GPMC_BCH_NUM_REMAINDER 8 @@ -61,4 +62,10 @@ struct gpmc_nand_regs { void __iomem *gpmc_bch_result5[GPMC_BCH_NUM_REMAINDER]; void __iomem *gpmc_bch_result6[GPMC_BCH_NUM_REMAINDER]; }; -#endif + +static const struct of_device_id omap_nand_ids[] = { + { .compatible = "ti,omap2-nand", }, + {}, +}; + +#endif /* _MTD_NAND_OMAP2_H */ -- cgit v1.2.3