From a6eaa2ae7820f0cca742917f85f34ef1eed2c95d Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 2 Sep 2013 23:37:53 -0300 Subject: of_mtd: Add no-op stubs to support CONFIG_OF=n Just like the rest of the subsystems, let's add the required no-op functions to implement stubs when CONFIG_OF=n. This prevents MTD drivers from having ugly ifdefs in their code, and instead hide the ifdef monster in the header closet (far away from people's sight). Signed-off-by: Ezequiel Garcia Signed-off-by: Brian Norris --- include/linux/of_mtd.h | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/of_mtd.h b/include/linux/of_mtd.h index ed7f267e6389..6f10e938ff7e 100644 --- a/include/linux/of_mtd.h +++ b/include/linux/of_mtd.h @@ -10,10 +10,29 @@ #define __LINUX_OF_NET_H #ifdef CONFIG_OF_MTD + #include int of_get_nand_ecc_mode(struct device_node *np); int of_get_nand_bus_width(struct device_node *np); bool of_get_nand_on_flash_bbt(struct device_node *np); -#endif + +#else /* CONFIG_OF_MTD */ + +static inline int of_get_nand_ecc_mode(struct device_node *np) +{ + return -ENOSYS; +} + +static inline int of_get_nand_bus_width(struct device_node *np) +{ + return -ENOSYS; +} + +static inline bool of_get_nand_on_flash_bbt(struct device_node *np) +{ + return false; +} + +#endif /* CONFIG_OF_MTD */ #endif /* __LINUX_OF_MTD_H */ -- cgit v1.2.3 From aaadd9819a128fb7ad988b6808581e3175859e2f Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Fri, 23 Aug 2013 23:24:47 -0700 Subject: mtd: nand: remove obsolete 'ecclayout' field This field is never used, except to print it out. Signed-off-by: Brian Norris --- drivers/mtd/nand/fsl_elbc_nand.c | 2 -- drivers/mtd/nand/fsl_ifc_nand.c | 2 -- include/linux/mtd/nand.h | 2 -- 3 files changed, 6 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 20657209a472..c6ef9f1c7a82 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c @@ -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", diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 317a771f1587..47acda6c4e92 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -718,8 +718,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__, diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index ac8e89d5a792..129548169400 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -498,7 +498,6 @@ struct nand_buffers { * supported, 0 otherwise. * @onfi_set_features: [REPLACEABLE] set the features for ONFI nand * @onfi_get_features: [REPLACEABLE] get the features for ONFI nand - * @ecclayout: [REPLACEABLE] the default ECC placement scheme * @bbt: [INTERN] bad block table pointer * @bbt_td: [REPLACEABLE] bad block table descriptor for flash * lookup. @@ -572,7 +571,6 @@ struct nand_chip { uint8_t *oob_poi; struct nand_hw_control *controller; - struct nand_ecclayout *ecclayout; struct nand_ecc_ctrl ecc; struct nand_buffers *buffers; -- cgit v1.2.3 From 1d0ed69ddd714b6e2a974f42896463366923ded6 Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Wed, 25 Sep 2013 14:58:10 +0800 Subject: mtd: nand: add a helper to check the SLC/MLC nand chip Add a helper to check if a nand chip is SLC or MLC. This helper makes the code more readable. Signed-off-by: Huang Shijie Signed-off-by: Brian Norris --- drivers/mtd/nand/denali.c | 2 +- drivers/mtd/nand/nand_base.c | 14 ++++++-------- include/linux/mtd/nand.h | 9 +++++++++ 3 files changed, 16 insertions(+), 9 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index 154b033b4e8e..370b9dd7a278 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c @@ -1520,7 +1520,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)))) { diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 0b39d0c03f1e..6ea66270dbf5 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3108,8 +3108,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; @@ -3141,7 +3140,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 */ @@ -3204,7 +3203,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; @@ -3265,11 +3264,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 || @@ -3745,8 +3744,7 @@ int nand_scan_tail(struct mtd_info *mtd) chip->ecc.total = chip->ecc.steps * chip->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)) { + if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) { switch (chip->ecc.steps) { case 2: mtd->subpage_sft = 1; diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 129548169400..5c05bab0ad89 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -795,4 +795,13 @@ static inline int onfi_get_sync_timing_mode(struct nand_chip *chip) return le16_to_cpu(chip->onfi_params.src_sync_timing_mode); } +/* + * Check if it is a SLC nand. + * The !nand_is_slc() can be used to check the MLC/TLC nand chips. + * We do not distinguish the MLC and TLC now. + */ +static inline bool nand_is_slc(struct nand_chip *chip) +{ + return !(chip->cellinfo & NAND_CI_CELLTYPE_MSK); +} #endif /* __LINUX_MTD_NAND_H */ -- cgit v1.2.3 From 7db906b79f69b6ed936a1ef1d788f02e3ad42462 Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Wed, 25 Sep 2013 14:58:11 +0800 Subject: mtd: nand: rename the cellinfo to bits_per_cell The @cellinfo fields contains unused information, such as write caching, internal chip numbering, etc. But we only use it to check the SLC or MLC. This patch tries to make it more clear and simple, renames the @cellinfo to @bits_per_cell. In order to avoiding the bisect issue, this patch also does the following changes: (0) add a macro NAND_CI_CELLTYPE_SHIFT to avoid the hardcode. (1) add a helper to parse out the cell type : nand_get_bits_per_cell() (2) parse out the cell type for extended-ID chips and the full-id nand chips. Signed-off-by: Huang Shijie Signed-off-by: Brian Norris --- drivers/mtd/nand/nand_base.c | 14 ++++++++++++-- include/linux/mtd/nand.h | 7 ++++--- 2 files changed, 16 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 6ea66270dbf5..5fb00957fd25 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -3082,6 +3082,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 @@ -3092,7 +3102,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]; @@ -3292,7 +3302,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); diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 5c05bab0ad89..9e6c8f9f306e 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -198,6 +198,7 @@ typedef enum { /* Cell info constants */ #define NAND_CI_CHIPNR_MSK 0x03 #define NAND_CI_CELLTYPE_MSK 0x0C +#define NAND_CI_CELLTYPE_SHIFT 2 /* Keep gcc happy */ struct nand_chip; @@ -477,7 +478,7 @@ struct nand_buffers { * @badblockbits: [INTERN] minimum number of set bits in a good block's * bad block marker position; i.e., BBM == 11110111b is * not bad when badblockbits == 7 - * @cellinfo: [INTERN] MLC/multichip data from chip ident + * @bits_per_cell: [INTERN] number of bits per cell. i.e., 1 means SLC. * @ecc_strength_ds: [INTERN] ECC correctability from the datasheet. * Minimum amount of bit errors per @ecc_step_ds guaranteed * to be correctable. If unknown, set to zero. @@ -558,7 +559,7 @@ struct nand_chip { int pagebuf; unsigned int pagebuf_bitflips; int subpagesize; - uint8_t cellinfo; + uint8_t bits_per_cell; uint16_t ecc_strength_ds; uint16_t ecc_step_ds; int badblockpos; @@ -802,6 +803,6 @@ static inline int onfi_get_sync_timing_mode(struct nand_chip *chip) */ static inline bool nand_is_slc(struct nand_chip *chip) { - return !(chip->cellinfo & NAND_CI_CELLTYPE_MSK); + return chip->bits_per_cell == 1; } #endif /* __LINUX_MTD_NAND_H */ -- cgit v1.2.3 From 818b97392932ac4cecc36ab839957258367004a9 Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Wed, 25 Sep 2013 14:58:17 +0800 Subject: mtd: nand: add a helper to detect the nand type This helper detects that whether the mtd's type is nand type. Now, it's clear that the MTD_NANDFLASH stands for SLC nand only. So use the mtd_type_is_nand() to replace the old check method to do the nand type (include the SLC and MLC) check. Signed-off-by: Huang Shijie Signed-off-by: Brian Norris --- drivers/mtd/inftlcore.c | 2 +- drivers/mtd/nftlcore.c | 2 +- drivers/mtd/ssfdc.c | 2 +- drivers/mtd/tests/nandbiterrs.c | 2 +- drivers/mtd/tests/oobtest.c | 2 +- drivers/mtd/tests/pagetest.c | 2 +- drivers/mtd/tests/subpagetest.c | 2 +- include/linux/mtd/mtd.h | 5 +++++ 8 files changed, 12 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index 3af351484098..b66b541877f0 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c @@ -50,7 +50,7 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) struct INFTLrecord *inftl; unsigned long temp; - if (mtd->type != MTD_NANDFLASH || mtd->size > UINT_MAX) + if (!mtd_type_is_nand(mtd) || mtd->size > UINT_MAX) return; /* OK, this is moderately ugly. But probably safe. Alternatives? */ if (memcmp(mtd->name, "DiskOnChip", 10)) diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c index c5f4ebf4b384..46f27de018c3 100644 --- a/drivers/mtd/nftlcore.c +++ b/drivers/mtd/nftlcore.c @@ -50,7 +50,7 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) struct NFTLrecord *nftl; unsigned long temp; - if (mtd->type != MTD_NANDFLASH || mtd->size > UINT_MAX) + if (!mtd_type_is_nand(mtd) || mtd->size > UINT_MAX) return; /* OK, this is moderately ugly. But probably safe. Alternatives? */ if (memcmp(mtd->name, "DiskOnChip", 10)) diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c index ab2a52a039c3..daf82ba7aba0 100644 --- a/drivers/mtd/ssfdc.c +++ b/drivers/mtd/ssfdc.c @@ -290,7 +290,7 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd) int cis_sector; /* Check for small page NAND flash */ - if (mtd->type != MTD_NANDFLASH || mtd->oobsize != OOB_SIZE || + if (!mtd_type_is_nand(mtd) || mtd->oobsize != OOB_SIZE || mtd->size > UINT_MAX) return; diff --git a/drivers/mtd/tests/nandbiterrs.c b/drivers/mtd/tests/nandbiterrs.c index 3cd3aabbe1cd..6f976159611f 100644 --- a/drivers/mtd/tests/nandbiterrs.c +++ b/drivers/mtd/tests/nandbiterrs.c @@ -349,7 +349,7 @@ static int __init mtd_nandbiterrs_init(void) goto exit_mtddev; } - if (mtd->type != MTD_NANDFLASH) { + if (!mtd_type_is_nand(mtd)) { pr_info("this test requires NAND flash\n"); err = -ENODEV; goto exit_nand; diff --git a/drivers/mtd/tests/oobtest.c b/drivers/mtd/tests/oobtest.c index ff35c465bfee..2e9e2d11f204 100644 --- a/drivers/mtd/tests/oobtest.c +++ b/drivers/mtd/tests/oobtest.c @@ -289,7 +289,7 @@ static int __init mtd_oobtest_init(void) return err; } - if (mtd->type != MTD_NANDFLASH) { + if (!mtd_type_is_nand(mtd)) { pr_info("this test requires NAND flash\n"); goto out; } diff --git a/drivers/mtd/tests/pagetest.c b/drivers/mtd/tests/pagetest.c index 44b96e999ad4..ed2d3f656fd2 100644 --- a/drivers/mtd/tests/pagetest.c +++ b/drivers/mtd/tests/pagetest.c @@ -353,7 +353,7 @@ static int __init mtd_pagetest_init(void) return err; } - if (mtd->type != MTD_NANDFLASH) { + if (!mtd_type_is_nand(mtd)) { pr_info("this test requires NAND flash\n"); goto out; } diff --git a/drivers/mtd/tests/subpagetest.c b/drivers/mtd/tests/subpagetest.c index e2c0adf24cfc..a876371ad410 100644 --- a/drivers/mtd/tests/subpagetest.c +++ b/drivers/mtd/tests/subpagetest.c @@ -299,7 +299,7 @@ static int __init mtd_subpagetest_init(void) return err; } - if (mtd->type != MTD_NANDFLASH) { + if (!mtd_type_is_nand(mtd)) { pr_info("this test requires NAND flash\n"); goto out; } diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index f9bfe526d310..88409b813418 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -354,6 +354,11 @@ static inline int mtd_has_oob(const struct mtd_info *mtd) return mtd->_read_oob && mtd->_write_oob; } +static inline int mtd_type_is_nand(const struct mtd_info *mtd) +{ + return mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH; +} + static inline int mtd_can_have_bb(const struct mtd_info *mtd) { return !!mtd->_block_isbad; -- cgit v1.2.3 From f83c3838b9146b891d0405d3a83660e8f6aed02f Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Sun, 13 Oct 2013 18:05:23 -0300 Subject: mtd: Move major number definitions to major.h This patch moves the char and block major number definitions to major.h to be with the rest of the major numbers. While doing this, include major.h in the files that need it. Signed-off-by: Ezequiel Garcia Signed-off-by: Brian Norris --- drivers/mtd/devices/block2mtd.c | 1 + drivers/mtd/mtdblock.c | 1 + drivers/mtd/mtdblock_ro.c | 1 + drivers/mtd/mtdchar.c | 1 + drivers/mtd/mtdcore.c | 1 + drivers/mtd/mtdsuper.c | 1 + drivers/mtd/ubi/build.c | 1 + include/linux/mtd/mtd.h | 3 --- include/uapi/linux/major.h | 2 ++ 9 files changed, 9 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 5cb4c04726b2..d9fd87a4c8dc 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -20,6 +20,7 @@ #include #include #include +#include /* Info for the block device */ struct block2mtd_dev { diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c index 53884cc25916..485ea751c7f9 100644 --- a/drivers/mtd/mtdblock.c +++ b/drivers/mtd/mtdblock.c @@ -32,6 +32,7 @@ #include #include #include +#include struct mtdblk_dev { diff --git a/drivers/mtd/mtdblock_ro.c b/drivers/mtd/mtdblock_ro.c index 70d27b4d632b..fb5dc89369de 100644 --- a/drivers/mtd/mtdblock_ro.c +++ b/drivers/mtd/mtdblock_ro.c @@ -24,6 +24,7 @@ #include #include #include +#include static int mtdblock_readsect(struct mtd_blktrans_dev *dev, unsigned long block, char *buf) diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 684bfa39e4ee..9aa0c5e49c1d 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 92311a56939f..7189089d87e3 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c index 334da5f583c0..20c02a3b7417 100644 --- a/drivers/mtd/mtdsuper.c +++ b/drivers/mtd/mtdsuper.c @@ -17,6 +17,7 @@ #include #include #include +#include /* * compare superblocks to see if they're equivalent diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 315dcc6ec1f5..e05dc6298c1d 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "ubi.h" /* Maximum length of the 'mtd=' parameter */ diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 88409b813418..8cc0e2fb6894 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -29,9 +29,6 @@ #include -#define MTD_CHAR_MAJOR 90 -#define MTD_BLOCK_MAJOR 31 - #define MTD_ERASE_PENDING 0x01 #define MTD_ERASING 0x02 #define MTD_ERASE_SUSPEND 0x04 diff --git a/include/uapi/linux/major.h b/include/uapi/linux/major.h index 6a8ca98c9a96..620252e69b44 100644 --- a/include/uapi/linux/major.h +++ b/include/uapi/linux/major.h @@ -54,6 +54,7 @@ #define ACSI_MAJOR 28 #define AZTECH_CDROM_MAJOR 29 #define FB_MAJOR 29 /* /dev/fb* framebuffers */ +#define MTD_BLOCK_MAJOR 31 #define CM206_CDROM_MAJOR 32 #define IDE2_MAJOR 33 #define IDE3_MAJOR 34 @@ -105,6 +106,7 @@ #define IDE6_MAJOR 88 #define IDE7_MAJOR 89 #define IDE8_MAJOR 90 +#define MTD_CHAR_MAJOR 90 #define IDE9_MAJOR 91 #define DASD_MAJOR 94 -- cgit v1.2.3 From a4d62babf988fe5dfde24437fa135ef147bc7aa0 Mon Sep 17 00:00:00 2001 From: Wang Haitao Date: Thu, 22 Aug 2013 19:32:38 +0800 Subject: mtd: map: fixed bug in 64-bit systems Hardware: CPU: XLP832,the 64-bit OS NOR Flash:S29GL128S 128M Software: Kernel:2.6.32.41 Filesystem:JFFS2 When writing files, errors appear: Write len 182 but return retlen 180 Write of 182 bytes at 0x072c815c failed. returned -5, retlen 180 Write len 186 but return retlen 184 Write of 186 bytes at 0x072caff4 failed. returned -5, retlen 184 These errors exist only in 64-bit systems,not in 32-bit systems. After analysis, we found that the left shift operation is wrong in map_word_load_partial. For instance: unsigned char buf[3] ={0x9e,0x3a,0xea}; map_bankwidth(map) is 4; for (i=0; i < 3; i++) { int bitpos; bitpos = (map_bankwidth(map)-1-i)*8; orig.x[0] &= ~(0xff << bitpos); orig.x[0] |= buf[i] << bitpos; } The value of orig.x[0] is expected to be 0x9e3aeaff, but in this situation(64-bit System) we'll get the wrong value of 0xffffffff9e3aeaff due to the 64-bit sign extension: buf[i] is defined as "unsigned char" and the left-shift operation will convert it to the type of "signed int", so when left-shift buf[i] by 24 bits, the final result will get the wrong value: 0xffffffff9e3aeaff. If the left-shift bits are less than 24, then sign extension will not occur. Whereas the bankwidth of the nor flash we used is 4, therefore this BUG emerges. Signed-off-by: Pang Xunlei Signed-off-by: Zhang Yi Signed-off-by: Lu Zhongjun Cc: Signed-off-by: Brian Norris --- include/linux/mtd/map.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index 4b02512e421c..5f487d776411 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -365,7 +365,7 @@ static inline map_word map_word_load_partial(struct map_info *map, map_word orig bitpos = (map_bankwidth(map)-1-i)*8; #endif orig.x[0] &= ~(0xff << bitpos); - orig.x[0] |= buf[i-start] << bitpos; + orig.x[0] |= (unsigned long)buf[i-start] << bitpos; } } return orig; @@ -384,7 +384,7 @@ static inline map_word map_word_ff(struct map_info *map) if (map_bankwidth(map) < MAP_FF_LIMIT) { int bw = 8 * map_bankwidth(map); - r.x[0] = (1 << bw) - 1; + r.x[0] = (1UL << bw) - 1; } else { for (i=0; i Date: Thu, 24 Oct 2013 18:20:17 +0530 Subject: ARM: OMAP2+: cleaned-up DT support of various ECC schemes OMAP NAND driver support multiple ECC scheme, which can used in different flavours, depending on in-build Hardware engines present on SoC. This patch updates following in DT bindings related to sectionion of ecc-schemes - ti,elm-id: replaces elm_id (maintains backward compatibility) - ti,nand-ecc-opts: selection of h/w or s/w implementation of an ecc-scheme depends on ti,elm-id. (supported values ham1, bch4, and bch8) - maintain backward compatibility to deprecated DT bindings (sw, hw, hw-romcode) Below table shows different flavours of ecc-schemes supported by OMAP devices +---------------------------------------+---------------+---------------+ | ECC scheme |ECC calculation|Error detection| +---------------------------------------+---------------+---------------+ |OMAP_ECC_HAM1_CODE_HW |H/W (GPMC) |S/W | +---------------------------------------+---------------+---------------+ |OMAP_ECC_BCH8_CODE_HW_DETECTION_SW |H/W (GPMC) |S/W | |(requires CONFIG_MTD_NAND_ECC_BCH) | | | +---------------------------------------+---------------+---------------+ |OMAP_ECC_BCH8_CODE_HW |H/W (GPMC) |H/W (ELM) | |(requires CONFIG_MTD_NAND_OMAP_BCH && | | | | ti,elm-id in DT) | | | +---------------------------------------+---------------+---------------+ To optimize footprint of omap2-nand driver, selection of some ECC schemes also require enabling following Kconfigs, in addition to setting appropriate DT bindings - Kconfig:CONFIG_MTD_NAND_ECC_BCH error detection done in software - Kconfig:CONFIG_MTD_NAND_OMAP_BCH error detection done by h/w engine Signed-off-by: Pekon Gupta Reviewed-by: Felipe Balbi Acked-by: Tony Lindgren Tested-by: Ezequiel Garcia Signed-off-by: Brian Norris --- .../devicetree/bindings/mtd/gpmc-nand.txt | 8 +++- arch/arm/mach-omap2/gpmc.c | 48 +++++++++++++++------- include/linux/platform_data/mtd-nand-omap2.h | 13 +++++- 3 files changed, 51 insertions(+), 18 deletions(-) (limited to 'include/linux') diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt index df338cb5059c..bfe07e152738 100644 --- a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt +++ b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt @@ -36,8 +36,12 @@ Optional properties: "prefetch-dma" Prefetch enabled sDMA mode "prefetch-irq" Prefetch enabled irq mode - - elm_id: Specifies elm device node. This is required to support BCH - error correction using ELM module. + - elm_id: use "ti,elm-id" instead + - ti,elm-id: Specifies phandle of the ELM devicetree node. + ELM is an on-chip hardware engine on TI SoC which is used for + locating ECC errors for BCHx algorithms. SoC devices which have + ELM hardware engines should specify this device node in .dtsi + Using ELM for ECC error correction frees some CPU cycles. For inline partiton table parsing (optional): diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 579697adaae7..c877129142ba 100644 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -1341,14 +1341,6 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np, #ifdef CONFIG_MTD_NAND -static const char * const nand_ecc_opts[] = { - [OMAP_ECC_HAMMING_CODE_DEFAULT] = "sw", - [OMAP_ECC_HAMMING_CODE_HW] = "hw", - [OMAP_ECC_HAMMING_CODE_HW_ROMCODE] = "hw-romcode", - [OMAP_ECC_BCH4_CODE_HW] = "bch4", - [OMAP_ECC_BCH8_CODE_HW] = "bch8", -}; - static const char * const nand_xfer_types[] = { [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled", [NAND_OMAP_POLLED] = "polled", @@ -1378,13 +1370,41 @@ static int gpmc_probe_nand_child(struct platform_device *pdev, gpmc_nand_data->cs = val; gpmc_nand_data->of_node = child; - if (!of_property_read_string(child, "ti,nand-ecc-opt", &s)) - for (val = 0; val < ARRAY_SIZE(nand_ecc_opts); val++) - if (!strcasecmp(s, nand_ecc_opts[val])) { - gpmc_nand_data->ecc_opt = val; - break; - } + /* Detect availability of ELM module */ + gpmc_nand_data->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0); + if (gpmc_nand_data->elm_of_node == NULL) + gpmc_nand_data->elm_of_node = + of_parse_phandle(child, "elm_id", 0); + if (gpmc_nand_data->elm_of_node == NULL) + pr_warn("%s: ti,elm-id property not found\n", __func__); + + /* select ecc-scheme for NAND */ + if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) { + pr_err("%s: ti,nand-ecc-opt not found\n", __func__); + return -ENODEV; + } + if (!strcmp(s, "ham1") || !strcmp(s, "sw") || + !strcmp(s, "hw") || !strcmp(s, "hw-romcode")) + gpmc_nand_data->ecc_opt = + OMAP_ECC_HAM1_CODE_HW; + else if (!strcmp(s, "bch4")) + if (gpmc_nand_data->elm_of_node) + gpmc_nand_data->ecc_opt = + OMAP_ECC_BCH4_CODE_HW; + else + gpmc_nand_data->ecc_opt = + OMAP_ECC_BCH4_CODE_HW_DETECTION_SW; + else if (!strcmp(s, "bch8")) + if (gpmc_nand_data->elm_of_node) + gpmc_nand_data->ecc_opt = + OMAP_ECC_BCH8_CODE_HW; + else + gpmc_nand_data->ecc_opt = + OMAP_ECC_BCH8_CODE_HW_DETECTION_SW; + else + pr_err("%s: ti,nand-ecc-opt invalid value\n", __func__); + /* select data transfer mode for NAND controller */ if (!of_property_read_string(child, "ti,nand-xfer-type", &s)) for (val = 0; val < ARRAY_SIZE(nand_xfer_types); val++) if (!strcasecmp(s, nand_xfer_types[val])) { diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h index 6bf9ef43ddb1..e4128f1510bf 100644 --- a/include/linux/platform_data/mtd-nand-omap2.h +++ b/include/linux/platform_data/mtd-nand-omap2.h @@ -28,8 +28,16 @@ enum omap_ecc { OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */ /* 1-bit ecc: stored at beginning of spare area as romcode */ OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */ - OMAP_ECC_BCH4_CODE_HW, /* 4-bit BCH ecc code */ - OMAP_ECC_BCH8_CODE_HW, /* 8-bit BCH ecc code */ + /* 1-bit ECC calculation by GPMC, Error detection by Software */ + OMAP_ECC_HAM1_CODE_HW, + /* 4-bit ECC calculation by GPMC, Error detection by Software */ + OMAP_ECC_BCH4_CODE_HW_DETECTION_SW, + /* 4-bit ECC calculation by GPMC, Error detection by ELM */ + OMAP_ECC_BCH4_CODE_HW, + /* 8-bit ECC calculation by GPMC, Error detection by Software */ + OMAP_ECC_BCH8_CODE_HW_DETECTION_SW, + /* 8-bit ECC calculation by GPMC, Error detection by ELM */ + OMAP_ECC_BCH8_CODE_HW, }; struct gpmc_nand_regs { @@ -63,5 +71,6 @@ struct omap_nand_platform_data { /* for passing the partitions */ struct device_node *of_node; + struct device_node *elm_of_node; }; #endif -- cgit v1.2.3 From c66d039197e42af8867e5d0d9b904daf0fb9e6bc Mon Sep 17 00:00:00 2001 From: Pekon Gupta Date: Thu, 24 Oct 2013 18:20:18 +0530 Subject: mtd: nand: omap: combine different flavours of 1-bit hamming ecc schemes OMAP NAND driver currently supports multiple flavours of 1-bit Hamming ecc-scheme, like: - OMAP_ECC_HAMMING_CODE_DEFAULT 1-bit hamming ecc code using software library - OMAP_ECC_HAMMING_CODE_HW 1-bit hamming ecc-code using GPMC h/w engine - OMAP_ECC_HAMMING_CODE_HW_ROMCODE 1-bit hamming ecc-code using GPMC h/w engin with ecc-layout compatible to ROM code. This patch combines above multiple ecc-schemes into single implementation: - OMAP_ECC_HAM1_CODE_HW 1-bit hamming ecc-code using GPMC h/w engine with ROM-code compatible ecc-layout. Signed-off-by: Pekon Gupta Reviewed-by: Felipe Balbi Acked-by: Tony Lindgren Tested-by: Ezequiel Garcia Signed-off-by: Brian Norris --- Documentation/devicetree/bindings/mtd/gpmc-nand.txt | 8 ++++---- arch/arm/mach-omap2/board-flash.c | 2 +- drivers/mtd/nand/omap2.c | 9 +++------ include/linux/platform_data/mtd-nand-omap2.h | 7 +------ 4 files changed, 9 insertions(+), 17 deletions(-) (limited to 'include/linux') diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt index bfe07e152738..5e1f31b5ff70 100644 --- a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt +++ b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt @@ -22,10 +22,10 @@ Optional properties: width of 8 is assumed. - ti,nand-ecc-opt: A string setting the ECC layout to use. One of: - - "sw" Software method (default) - "hw" Hardware method - "hw-romcode" gpmc hamming mode method & romcode layout + "sw" use "ham1" instead + "hw" use "ham1" instead + "hw-romcode" use "ham1" instead + "ham1" 1-bit Hamming ecc code "bch4" 4-bit BCH ecc code "bch8" 8-bit BCH ecc code diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c index fc20a61f6b2a..ac82512b9c8c 100644 --- a/arch/arm/mach-omap2/board-flash.c +++ b/arch/arm/mach-omap2/board-flash.c @@ -142,7 +142,7 @@ __init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, board_nand_data.nr_parts = nr_parts; board_nand_data.devsize = nand_type; - board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT; + board_nand_data.ecc_opt = OMAP_ECC_BCH8_CODE_HW; gpmc_nand_init(&board_nand_data, gpmc_t); } #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */ diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 4ecf0e5fd484..8d521aa001c8 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1993,10 +1993,7 @@ static int omap_nand_probe(struct platform_device *pdev) } /* 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)) { + if (pdata->ecc_opt == OMAP_ECC_HAM1_CODE_HW) { info->nand.ecc.bytes = 3; info->nand.ecc.size = 512; info->nand.ecc.strength = 1; @@ -2025,7 +2022,7 @@ static int omap_nand_probe(struct platform_device *pdev) } /* rom code layout */ - if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE) { + if (pdata->ecc_opt == OMAP_ECC_HAM1_CODE_HW) { if (info->nand.options & NAND_BUSWIDTH_16) offset = 2; @@ -2033,7 +2030,7 @@ static int omap_nand_probe(struct platform_device *pdev) offset = 1; info->nand.badblock_pattern = &bb_descrip_flashbased; } - omap_oobinfo.eccbytes = 3 * (info->mtd.oobsize/16); + omap_oobinfo.eccbytes = 3 * (info->mtd.writesize / 512); for (i = 0; i < omap_oobinfo.eccbytes; i++) omap_oobinfo.eccpos[i] = i+offset; diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h index e4128f1510bf..4da5bfa2147f 100644 --- a/include/linux/platform_data/mtd-nand-omap2.h +++ b/include/linux/platform_data/mtd-nand-omap2.h @@ -23,13 +23,8 @@ enum nand_io { }; enum omap_ecc { - /* 1-bit ecc: stored at end of spare area */ - OMAP_ECC_HAMMING_CODE_DEFAULT = 0, /* Default, s/w method */ - OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */ - /* 1-bit ecc: stored at beginning of spare area as romcode */ - OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */ /* 1-bit ECC calculation by GPMC, Error detection by Software */ - OMAP_ECC_HAM1_CODE_HW, + OMAP_ECC_HAM1_CODE_HW = 0, /* 4-bit ECC calculation by GPMC, Error detection by Software */ OMAP_ECC_BCH4_CODE_HW_DETECTION_SW, /* 4-bit ECC calculation by GPMC, Error detection by ELM */ -- cgit v1.2.3 From 5961ad2cb4dd14933889f5219e0d8505669d752d Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 30 Oct 2013 00:41:30 -0400 Subject: mtd: nand_bbt: kill NAND_BBT_SCANALLPAGES Now that the last user of NAND_BBT_SCANALLPAGES has been removed, let's kill this peculiar BBT feature flag. Signed-off-by: Brian Norris Reviewed-by: Ezequiel Garcia Signed-off-by: Artem Bityutskiy --- Documentation/DocBook/mtdnand.tmpl | 2 -- drivers/mtd/nand/nand_bbt.c | 37 +++---------------------------------- include/linux/mtd/bbm.h | 2 -- 3 files changed, 3 insertions(+), 38 deletions(-) (limited to 'include/linux') diff --git a/Documentation/DocBook/mtdnand.tmpl b/Documentation/DocBook/mtdnand.tmpl index a248f42a121e..cd11926e07c7 100644 --- a/Documentation/DocBook/mtdnand.tmpl +++ b/Documentation/DocBook/mtdnand.tmpl @@ -1222,8 +1222,6 @@ in this page #define NAND_BBT_VERSION 0x00000100 /* Create a bbt if none axists */ #define NAND_BBT_CREATE 0x00000200 -/* Search good / bad pattern through all pages of a block */ -#define NAND_BBT_SCANALLPAGES 0x00000400 /* Write bbt if neccecary */ #define NAND_BBT_WRITE 0x00001000 /* Read and write back block contents when writing bbt */ diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index c75b6a7c6ea4..c0615d1526f9 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; diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h index 95fc482cef36..36bb6a503f19 100644 --- a/include/linux/mtd/bbm.h +++ b/include/linux/mtd/bbm.h @@ -91,8 +91,6 @@ struct nand_bbt_descr { * with NAND_BBT_CREATE. */ #define NAND_BBT_CREATE_EMPTY 0x00000400 -/* Search good / bad pattern through all pages of a block */ -#define NAND_BBT_SCANALLPAGES 0x00000800 /* Write bbt if neccecary */ #define NAND_BBT_WRITE 0x00002000 /* Read and write back block contents when writing bbt */ -- cgit v1.2.3