From: Shivamurthy Shastri <sshivamurthy@xxxxxxxxxx> Driver is redesigned using parameter page to support Micron SPI NAND flashes. The reason why spinand_select_op_variant globalized is that the Micron driver no longer calling spinand_match_and_init. Signed-off-by: Shivamurthy Shastri <sshivamurthy@xxxxxxxxxx> --- drivers/mtd/nand/spi/core.c | 2 +- drivers/mtd/nand/spi/micron.c | 61 +++++++++++++++++++++++++---------- include/linux/mtd/spinand.h | 4 +++ 3 files changed, 49 insertions(+), 18 deletions(-) diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 7ae76dab9141..aae715d388b7 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -920,7 +920,7 @@ static void spinand_manufacturer_cleanup(struct spinand_device *spinand) return spinand->manufacturer->ops->cleanup(spinand); } -static const struct spi_mem_op * +const struct spi_mem_op * spinand_select_op_variant(struct spinand_device *spinand, const struct spinand_op_variants *variants) { diff --git a/drivers/mtd/nand/spi/micron.c b/drivers/mtd/nand/spi/micron.c index 95bc5264ebc1..6fde93ec23a1 100644 --- a/drivers/mtd/nand/spi/micron.c +++ b/drivers/mtd/nand/spi/micron.c @@ -90,22 +90,10 @@ static int micron_ecc_get_status(struct spinand_device *spinand, return -EINVAL; } -static const struct spinand_info micron_spinand_table[] = { - SPINAND_INFO("MT29F2G01ABAGD", 0x24, - 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_ECCINFO(µn_ooblayout_ops, - micron_ecc_get_status)), -}; - static int micron_spinand_detect(struct spinand_device *spinand) { + const struct spi_mem_op *op; u8 *id = spinand->id.data; - int ret; /* * Micron SPI NAND read ID need a dummy byte, @@ -114,16 +102,55 @@ static int micron_spinand_detect(struct spinand_device *spinand) if (id[1] != SPINAND_MFR_MICRON) return 0; - ret = spinand_match_and_init(spinand, micron_spinand_table, - ARRAY_SIZE(micron_spinand_table), id[2]); - if (ret) - return ret; + spinand->flags = 0; + spinand->eccinfo.get_status = micron_ecc_get_status; + spinand->eccinfo.ooblayout = µn_ooblayout_ops; + + op = spinand_select_op_variant(spinand, + &read_cache_variants); + if (!op) + return -ENOTSUPP; + + spinand->op_templates.read_cache = op; + + op = spinand_select_op_variant(spinand, + &write_cache_variants); + if (!op) + return -ENOTSUPP; + + spinand->op_templates.write_cache = op; + + op = spinand_select_op_variant(spinand, + &update_cache_variants); + spinand->op_templates.update_cache = op; return 1; } +static void micron_fixup_param_page(struct spinand_device *spinand, + struct nand_onfi_params *p) +{ + /* + * As per Micron datasheets vendor[83] is defined as + * die_select_feature + */ + if (p->vendor[83] && !p->interleaved_bits) + spinand->base.memorg.planes_per_lun = 1 << p->vendor[0]; + + spinand->base.memorg.ntargets = p->lun_count; + spinand->base.memorg.luns_per_target = 1; + + /* + * As per Micron datasheets, + * vendor[82] is ECC maximum correctability + */ + spinand->base.eccreq.strength = p->vendor[82]; + spinand->base.eccreq.step_size = 512; +} + static const struct spinand_manufacturer_ops micron_spinand_manuf_ops = { .detect = micron_spinand_detect, + .fixup_param_page = micron_fixup_param_page, }; const struct spinand_manufacturer micron_spinand_manufacturer = { diff --git a/include/linux/mtd/spinand.h b/include/linux/mtd/spinand.h index fea820a20bc9..ddb2194273a8 100644 --- a/include/linux/mtd/spinand.h +++ b/include/linux/mtd/spinand.h @@ -461,4 +461,8 @@ int spinand_match_and_init(struct spinand_device *dev, int spinand_upd_cfg(struct spinand_device *spinand, u8 mask, u8 val); int spinand_select_target(struct spinand_device *spinand, unsigned int target); +const struct spi_mem_op * +spinand_select_op_variant(struct spinand_device *spinand, + const struct spinand_op_variants *variants); + #endif /* __LINUX_MTD_SPINAND_H */ -- 2.17.1 ______________________________________________________ Linux MTD discussion mailing list http://lists.infradead.org/mailman/listinfo/linux-mtd/