diff options
author | Boris Brezillon <boris.brezillon@bootlin.com> | 2018-09-07 00:38:51 +0200 |
---|---|---|
committer | Miquel Raynal <miquel.raynal@bootlin.com> | 2018-10-03 11:12:25 +0200 |
commit | 8ae3fbf81b9cfdd1fec0451181213742b73fdf1a (patch) | |
tree | 6e7ae4e1bb214e0ce115023e5a30771062572f63 /drivers | |
parent | 1c325cc5077a88510afc08b1d2c75bcf18681f21 (diff) |
mtd: rawnand: Move JEDEC code to nand_jedec.c
This moves JEDEC related code to nand_jedec.c and JEDEC related
struct/macros to include/linux/mtd/jedec.h.
Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mtd/nand/raw/Makefile | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/internals.h | 3 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/nand_base.c | 98 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/nand_jedec.c | 113 |
4 files changed, 118 insertions, 97 deletions
diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile index cc9f50f3ad1b..be2c17863ee5 100644 --- a/drivers/mtd/nand/raw/Makefile +++ b/drivers/mtd/nand/raw/Makefile @@ -59,6 +59,7 @@ obj-$(CONFIG_MTD_NAND_TEGRA) += tegra_nand.o nand-objs := nand_base.o nand_legacy.o nand_bbt.o nand_timings.o nand_ids.o nand-objs += nand_onfi.o +nand-objs += nand_jedec.o nand-objs += nand_amd.o nand-objs += nand_hynix.o nand-objs += nand_macronix.o diff --git a/drivers/mtd/nand/raw/internals.h b/drivers/mtd/nand/raw/internals.h index 1ce720a8d756..88b5da620e7d 100644 --- a/drivers/mtd/nand/raw/internals.h +++ b/drivers/mtd/nand/raw/internals.h @@ -108,4 +108,7 @@ int nand_legacy_check_hooks(struct nand_chip *chip); u16 onfi_crc16(u16 crc, u8 const *p, size_t len); int nand_onfi_detect(struct nand_chip *chip); +/* JEDEC functions */ +int nand_jedec_detect(struct nand_chip *chip); + #endif /* __LINUX_RAWNAND_INTERNALS */ diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 812e8bd6ad82..dc3955da0426 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -4388,102 +4388,6 @@ void sanitize_string(uint8_t *s, size_t len) } /* - * Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise. - */ -static int nand_flash_detect_jedec(struct nand_chip *chip) -{ - struct mtd_info *mtd = nand_to_mtd(chip); - struct nand_jedec_params *p; - struct jedec_ecc_info *ecc; - int jedec_version = 0; - char id[5]; - int i, val, ret; - - /* Try JEDEC for unknown chip or LP */ - ret = nand_readid_op(chip, 0x40, id, sizeof(id)); - if (ret || strncmp(id, "JEDEC", sizeof(id))) - return 0; - - /* JEDEC chip: allocate a buffer to hold its parameter page */ - p = kzalloc(sizeof(*p), GFP_KERNEL); - if (!p) - return -ENOMEM; - - ret = nand_read_param_page_op(chip, 0x40, NULL, 0); - if (ret) { - ret = 0; - goto free_jedec_param_page; - } - - for (i = 0; i < 3; i++) { - ret = nand_read_data_op(chip, p, sizeof(*p), true); - if (ret) { - ret = 0; - goto free_jedec_param_page; - } - - 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"); - goto free_jedec_param_page; - } - - /* Check version */ - val = le16_to_cpu(p->revision); - if (val & (1 << 2)) - jedec_version = 10; - else if (val & (1 << 1)) - jedec_version = 1; /* vendor specific version */ - - if (!jedec_version) { - pr_info("unsupported JEDEC version: %d\n", val); - goto free_jedec_param_page; - } - - sanitize_string(p->manufacturer, sizeof(p->manufacturer)); - sanitize_string(p->model, sizeof(p->model)); - chip->parameters.model = kstrdup(p->model, GFP_KERNEL); - if (!chip->parameters.model) { - ret = -ENOMEM; - goto free_jedec_param_page; - } - - 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 (le16_to_cpu(p->features) & JEDEC_FEATURE_16_BIT_BUS) - chip->options |= NAND_BUSWIDTH_16; - - /* 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"); - } - -free_jedec_param_page: - kfree(p); - return ret; -} - -/* * nand_id_has_period - Check if an ID string has a given wraparound period * @id_data: the ID string * @arrlen: the length of the @id_data array @@ -4795,7 +4699,7 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type) goto ident_done; /* Check if the chip is JEDEC compliant */ - ret = nand_flash_detect_jedec(chip); + ret = nand_jedec_detect(chip); if (ret < 0) return ret; else if (ret) diff --git a/drivers/mtd/nand/raw/nand_jedec.c b/drivers/mtd/nand/raw/nand_jedec.c new file mode 100644 index 000000000000..5c26492c841d --- /dev/null +++ b/drivers/mtd/nand/raw/nand_jedec.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com) + * 2002-2006 Thomas Gleixner (tglx@linutronix.de) + * + * Credits: + * David Woodhouse for adding multichip support + * + * Aleph One Ltd. and Toby Churchill Ltd. for supporting the + * rework for 2K page size chips + * + * This file contains all ONFI helpers. + */ + +#include <linux/slab.h> + +#include "internals.h" + +/* + * Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise. + */ +int nand_jedec_detect(struct nand_chip *chip) +{ + struct mtd_info *mtd = nand_to_mtd(chip); + struct nand_jedec_params *p; + struct jedec_ecc_info *ecc; + int jedec_version = 0; + char id[5]; + int i, val, ret; + + /* Try JEDEC for unknown chip or LP */ + ret = nand_readid_op(chip, 0x40, id, sizeof(id)); + if (ret || strncmp(id, "JEDEC", sizeof(id))) + return 0; + + /* JEDEC chip: allocate a buffer to hold its parameter page */ + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return -ENOMEM; + + ret = nand_read_param_page_op(chip, 0x40, NULL, 0); + if (ret) { + ret = 0; + goto free_jedec_param_page; + } + + for (i = 0; i < 3; i++) { + ret = nand_read_data_op(chip, p, sizeof(*p), true); + if (ret) { + ret = 0; + goto free_jedec_param_page; + } + + 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"); + goto free_jedec_param_page; + } + + /* Check version */ + val = le16_to_cpu(p->revision); + if (val & (1 << 2)) + jedec_version = 10; + else if (val & (1 << 1)) + jedec_version = 1; /* vendor specific version */ + + if (!jedec_version) { + pr_info("unsupported JEDEC version: %d\n", val); + goto free_jedec_param_page; + } + + sanitize_string(p->manufacturer, sizeof(p->manufacturer)); + sanitize_string(p->model, sizeof(p->model)); + chip->parameters.model = kstrdup(p->model, GFP_KERNEL); + if (!chip->parameters.model) { + ret = -ENOMEM; + goto free_jedec_param_page; + } + + 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 (le16_to_cpu(p->features) & JEDEC_FEATURE_16_BIT_BUS) + chip->options |= NAND_BUSWIDTH_16; + + /* 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"); + } + +free_jedec_param_page: + kfree(p); + return ret; +} |