diff mbox series

[v2,07/15] mtd: rawnand: Fill memorg during detection

Message ID 20190304201522.11323-8-miquel.raynal@bootlin.com (mailing list archive)
State New, archived
Headers show
Series mtd: rawnand: 5th batch of cleanups | expand

Commit Message

Miquel Raynal March 4, 2019, 8:15 p.m. UTC
From: Boris Brezillon <bbrezillon@kernel.org>

If we want to use the generic NAND layer, we need to have the memorg
struct appropriately filled. Patch the detection code to fill this
struct.

Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
---
 drivers/mtd/nand/raw/denali.c       |  5 +++
 drivers/mtd/nand/raw/diskonchip.c   |  4 ++
 drivers/mtd/nand/raw/jz4740_nand.c  |  4 ++
 drivers/mtd/nand/raw/nand_amd.c     | 11 +++--
 drivers/mtd/nand/raw/nand_base.c    | 64 ++++++++++++++++++++++++++---
 drivers/mtd/nand/raw/nand_hynix.c   | 48 ++++++++++++++--------
 drivers/mtd/nand/raw/nand_jedec.c   | 22 +++++++---
 drivers/mtd/nand/raw/nand_onfi.c    | 23 ++++++++---
 drivers/mtd/nand/raw/nand_samsung.c | 24 +++++++----
 drivers/mtd/nand/raw/nand_toshiba.c |  9 +++-
 drivers/mtd/nand/raw/nandsim.c      |  5 +++
 11 files changed, 175 insertions(+), 44 deletions(-)

Comments

Frieder Schrempf March 21, 2019, 9:03 a.m. UTC | #1
On 04.03.19 21:15, Miquel Raynal wrote:
> From: Boris Brezillon <bbrezillon@kernel.org>
> 
> If we want to use the generic NAND layer, we need to have the memorg
> struct appropriately filled. Patch the detection code to fill this
> struct.
> 
> Signed-off-by: Boris Brezillon <bbrezillon@kernel.org>
> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>

Reviewed-by: Frieder Schrempf <frieder.schrempf@kontron.de>

> ---
>   drivers/mtd/nand/raw/denali.c       |  5 +++
>   drivers/mtd/nand/raw/diskonchip.c   |  4 ++
>   drivers/mtd/nand/raw/jz4740_nand.c  |  4 ++
>   drivers/mtd/nand/raw/nand_amd.c     | 11 +++--
>   drivers/mtd/nand/raw/nand_base.c    | 64 ++++++++++++++++++++++++++---
>   drivers/mtd/nand/raw/nand_hynix.c   | 48 ++++++++++++++--------
>   drivers/mtd/nand/raw/nand_jedec.c   | 22 +++++++---
>   drivers/mtd/nand/raw/nand_onfi.c    | 23 ++++++++---
>   drivers/mtd/nand/raw/nand_samsung.c | 24 +++++++----
>   drivers/mtd/nand/raw/nand_toshiba.c |  9 +++-
>   drivers/mtd/nand/raw/nandsim.c      |  5 +++
>   11 files changed, 175 insertions(+), 44 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c
> index eebac35304c6..86e5df403beb 100644
> --- a/drivers/mtd/nand/raw/denali.c
> +++ b/drivers/mtd/nand/raw/denali.c
> @@ -1119,6 +1119,9 @@ static int denali_multidev_fixup(struct denali_nand_info *denali)
>   {
>   	struct nand_chip *chip = &denali->nand;
>   	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct nand_memory_organization *memorg;
> +
> +	memorg = nanddev_get_memorg(&chip->base);
>   
>   	/*
>   	 * Support for multi device:
> @@ -1148,6 +1151,8 @@ static int denali_multidev_fixup(struct denali_nand_info *denali)
>   	}
>   
>   	/* 2 chips in parallel */
> +	memorg->pagesize <<= 1;
> +	memorg->oobsize <<= 1;
>   	mtd->size <<= 1;
>   	mtd->erasesize <<= 1;
>   	mtd->writesize <<= 1;
> diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c
> index 53f57e0f007e..e9767e06415d 100644
> --- a/drivers/mtd/nand/raw/diskonchip.c
> +++ b/drivers/mtd/nand/raw/diskonchip.c
> @@ -1028,6 +1028,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio
>   {
>   	struct nand_chip *this = mtd_to_nand(mtd);
>   	struct doc_priv *doc = nand_get_controller_data(this);
> +	struct nand_memory_organization *memorg;
>   	int ret = 0;
>   	u_char *buf;
>   	struct NFTLMediaHeader *mh;
> @@ -1036,6 +1037,8 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio
>   	unsigned blocks, maxblocks;
>   	int offs, numheaders;
>   
> +	memorg = nanddev_get_memorg(&this->base);
> +
>   	buf = kmalloc(mtd->writesize, GFP_KERNEL);
>   	if (!buf) {
>   		return 0;
> @@ -1082,6 +1085,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio
>   	   implementation of the NAND layer.  */
>   	if (mh->UnitSizeFactor != 0xff) {
>   		this->bbt_erase_shift += (0xff - mh->UnitSizeFactor);
> +		memorg->pages_per_eraseblock <<= (0xff - mh->UnitSizeFactor);
>   		mtd->erasesize <<= (0xff - mh->UnitSizeFactor);
>   		pr_info("Setting virtual erase size to %d\n", mtd->erasesize);
>   		blocks = mtd->size >> this->bbt_erase_shift;
> diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c
> index f92ae5aa2a54..76a32ad2cf83 100644
> --- a/drivers/mtd/nand/raw/jz4740_nand.c
> +++ b/drivers/mtd/nand/raw/jz4740_nand.c
> @@ -313,8 +313,11 @@ static int jz_nand_detect_bank(struct platform_device *pdev,
>   	uint32_t ctrl;
>   	struct nand_chip *chip = &nand->chip;
>   	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct nand_memory_organization *memorg;
>   	u8 id[2];
>   
> +	memorg = nanddev_get_memorg(&chip->base);
> +
>   	/* Request I/O resource. */
>   	sprintf(res_name, "bank%d", bank);
>   	ret = jz_nand_ioremap_resource(pdev, res_name,
> @@ -352,6 +355,7 @@ static int jz_nand_detect_bank(struct platform_device *pdev,
>   
>   		/* Update size of the MTD. */
>   		chip->numchips++;
> +		memorg->ntargets++;
>   		mtd->size += chip->chipsize;
>   	}
>   
> diff --git a/drivers/mtd/nand/raw/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c
> index 890c5b43e03c..e008fd662ee6 100644
> --- a/drivers/mtd/nand/raw/nand_amd.c
> +++ b/drivers/mtd/nand/raw/nand_amd.c
> @@ -20,6 +20,9 @@
>   static void amd_nand_decode_id(struct nand_chip *chip)
>   {
>   	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct nand_memory_organization *memorg;
> +
> +	memorg = nanddev_get_memorg(&chip->base);
>   
>   	nand_decode_ext_id(chip);
>   
> @@ -31,9 +34,11 @@ static void amd_nand_decode_id(struct nand_chip *chip)
>   	 */
>   	if (chip->id.data[4] != 0x00 && chip->id.data[5] == 0x00 &&
>   	    chip->id.data[6] == 0x00 && chip->id.data[7] == 0x00 &&
> -	    mtd->writesize == 512) {
> -		mtd->erasesize = 128 * 1024;
> -		mtd->erasesize <<= ((chip->id.data[3] & 0x03) << 1);
> +	    memorg->pagesize == 512) {
> +		memorg->pages_per_eraseblock = 256;
> +		memorg->pages_per_eraseblock <<= ((chip->id.data[3] & 0x03) << 1);
> +		mtd->erasesize = memorg->pages_per_eraseblock *
> +				 memorg->pagesize;
>   	}
>   }
>   
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index d3092c9a3e21..5aba1cf38a4b 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
> @@ -4530,21 +4530,30 @@ static int nand_get_bits_per_cell(u8 cellinfo)
>    */
>   void nand_decode_ext_id(struct nand_chip *chip)
>   {
> +	struct nand_memory_organization *memorg;
>   	struct mtd_info *mtd = nand_to_mtd(chip);
>   	int extid;
>   	u8 *id_data = chip->id.data;
> +
> +	memorg = nanddev_get_memorg(&chip->base);
> +
>   	/* The 3rd id byte holds MLC / multichip data */
> +	memorg->bits_per_cell = nand_get_bits_per_cell(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];
>   
>   	/* Calc pagesize */
> -	mtd->writesize = 1024 << (extid & 0x03);
> +	memorg->pagesize = 1024 << (extid & 0x03);
> +	mtd->writesize = memorg->pagesize;
>   	extid >>= 2;
>   	/* Calc oobsize */
> -	mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
> +	memorg->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
> +	mtd->oobsize = memorg->oobsize;
>   	extid >>= 2;
>   	/* Calc blocksize. Blocksize is multiples of 64KiB */
> +	memorg->pages_per_eraseblock = ((64 * 1024) << (extid & 0x03)) /
> +				       memorg->pagesize;
>   	mtd->erasesize = (64 * 1024) << (extid & 0x03);
>   	extid >>= 2;
>   	/* Get buswidth information */
> @@ -4561,12 +4570,19 @@ EXPORT_SYMBOL_GPL(nand_decode_ext_id);
>   static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type)
>   {
>   	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct nand_memory_organization *memorg;
>   
> +	memorg = nanddev_get_memorg(&chip->base);
> +
> +	memorg->pages_per_eraseblock = type->erasesize / type->pagesize;
>   	mtd->erasesize = type->erasesize;
> -	mtd->writesize = type->pagesize;
> -	mtd->oobsize = mtd->writesize / 32;
> +	memorg->pagesize = type->pagesize;
> +	mtd->writesize = memorg->pagesize;
> +	memorg->oobsize = memorg->pagesize / 32;
> +	mtd->oobsize = memorg->oobsize;
>   
>   	/* All legacy ID NAND are small-page, SLC */
> +	memorg->bits_per_cell = 1;
>   	chip->bits_per_cell = 1;
>   }
>   
> @@ -4595,15 +4611,27 @@ static bool find_full_id_nand(struct nand_chip *chip,
>   			      struct nand_flash_dev *type)
>   {
>   	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct nand_memory_organization *memorg;
>   	u8 *id_data = chip->id.data;
>   
> +	memorg = nanddev_get_memorg(&chip->base);
> +
>   	if (!strncmp(type->id, id_data, type->id_len)) {
> -		mtd->writesize = type->pagesize;
> +		memorg->pagesize = type->pagesize;
> +		mtd->writesize = memorg->pagesize;
> +		memorg->pages_per_eraseblock = type->erasesize /
> +					       type->pagesize;
>   		mtd->erasesize = type->erasesize;
> -		mtd->oobsize = type->oobsize;
> +		memorg->oobsize = type->oobsize;
> +		mtd->oobsize = memorg->oobsize;
>   
> +		memorg->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
>   		chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
>   		chip->chipsize = (uint64_t)type->chipsize << 20;
> +		memorg->eraseblocks_per_lun =
> +			DIV_ROUND_DOWN_ULL((u64)type->chipsize << 20,
> +					   memorg->pagesize *
> +					   memorg->pages_per_eraseblock);
>   		chip->options |= type->options;
>   		chip->ecc_strength_ds = NAND_ECC_STRENGTH(type);
>   		chip->ecc_step_ds = NAND_ECC_STEP(type);
> @@ -4632,7 +4660,12 @@ static void nand_manufacturer_detect(struct nand_chip *chip)
>   	 */
>   	if (chip->manufacturer.desc && chip->manufacturer.desc->ops &&
>   	    chip->manufacturer.desc->ops->detect) {
> +		struct nand_memory_organization *memorg;
> +
> +		memorg = nanddev_get_memorg(&chip->base);
> +
>   		/* The 3rd id byte holds MLC / multichip data */
> +		memorg->bits_per_cell = nand_get_bits_per_cell(chip->id.data[2]);
>   		chip->bits_per_cell = nand_get_bits_per_cell(chip->id.data[2]);
>   		chip->manufacturer.desc->ops->detect(chip);
>   	} else {
> @@ -4682,10 +4715,20 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
>   {
>   	const struct nand_manufacturer *manufacturer;
>   	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct nand_memory_organization *memorg;
>   	int busw, ret;
>   	u8 *id_data = chip->id.data;
>   	u8 maf_id, dev_id;
>   
> +	/*
> +	 * Let's start by initializing memorg fields that might be left
> +	 * unassigned by the ID-based detection logic.
> +	 */
> +	memorg = nanddev_get_memorg(&chip->base);
> +	memorg->planes_per_lun = 1;
> +	memorg->luns_per_target = 1;
> +	memorg->ntargets = 1;
> +
>   	/*
>   	 * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
>   	 * after power-up.
> @@ -4790,6 +4833,11 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
>   	/* Get chip options */
>   	chip->options |= type->options;
>   
> +	memorg->eraseblocks_per_lun =
> +			DIV_ROUND_DOWN_ULL((u64)type->chipsize << 20,
> +					   memorg->pagesize *
> +					   memorg->pages_per_eraseblock);
> +
>   ident_done:
>   	if (!mtd->name)
>   		mtd->name = chip->parameters.model;
> @@ -5016,10 +5064,13 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
>   			   struct nand_flash_dev *table)
>   {
>   	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct nand_memory_organization *memorg;
>   	int nand_maf_id, nand_dev_id;
>   	unsigned int i;
>   	int ret;
>   
> +	memorg = nanddev_get_memorg(&chip->base);
> +
>   	/* Assume all dies are deselected when we enter nand_scan_ident(). */
>   	chip->cur_cs = -1;
>   
> @@ -5081,6 +5132,7 @@ static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
>   		pr_info("%d chips detected\n", i);
>   
>   	/* Store the number of chips and calc total size for mtd */
> +	memorg->ntargets = i;
>   	chip->numchips = i;
>   	mtd->size = i * chip->chipsize;
>   
> diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
> index 343f477362d1..94ea8c593589 100644
> --- a/drivers/mtd/nand/raw/nand_hynix.c
> +++ b/drivers/mtd/nand/raw/nand_hynix.c
> @@ -418,24 +418,27 @@ static void hynix_nand_extract_oobsize(struct nand_chip *chip,
>   				       bool valid_jedecid)
>   {
>   	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct nand_memory_organization *memorg;
>   	u8 oobsize;
>   
> +	memorg = nanddev_get_memorg(&chip->base);
> +
>   	oobsize = ((chip->id.data[3] >> 2) & 0x3) |
>   		  ((chip->id.data[3] >> 4) & 0x4);
>   
>   	if (valid_jedecid) {
>   		switch (oobsize) {
>   		case 0:
> -			mtd->oobsize = 2048;
> +			memorg->oobsize = 2048;
>   			break;
>   		case 1:
> -			mtd->oobsize = 1664;
> +			memorg->oobsize = 1664;
>   			break;
>   		case 2:
> -			mtd->oobsize = 1024;
> +			memorg->oobsize = 1024;
>   			break;
>   		case 3:
> -			mtd->oobsize = 640;
> +			memorg->oobsize = 640;
>   			break;
>   		default:
>   			/*
> @@ -450,25 +453,25 @@ static void hynix_nand_extract_oobsize(struct nand_chip *chip,
>   	} else {
>   		switch (oobsize) {
>   		case 0:
> -			mtd->oobsize = 128;
> +			memorg->oobsize = 128;
>   			break;
>   		case 1:
> -			mtd->oobsize = 224;
> +			memorg->oobsize = 224;
>   			break;
>   		case 2:
> -			mtd->oobsize = 448;
> +			memorg->oobsize = 448;
>   			break;
>   		case 3:
> -			mtd->oobsize = 64;
> +			memorg->oobsize = 64;
>   			break;
>   		case 4:
> -			mtd->oobsize = 32;
> +			memorg->oobsize = 32;
>   			break;
>   		case 5:
> -			mtd->oobsize = 16;
> +			memorg->oobsize = 16;
>   			break;
>   		case 6:
> -			mtd->oobsize = 640;
> +			memorg->oobsize = 640;
>   			break;
>   		default:
>   			/*
> @@ -492,8 +495,10 @@ static void hynix_nand_extract_oobsize(struct nand_chip *chip,
>   		 * the actual OOB size for this chip is: 640 * 16k / 8k).
>   		 */
>   		if (chip->id.data[1] == 0xde)
> -			mtd->oobsize *= mtd->writesize / SZ_8K;
> +			memorg->oobsize *= memorg->pagesize / SZ_8K;
>   	}
> +
> +	mtd->oobsize = memorg->oobsize;
>   }
>   
>   static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip,
> @@ -609,9 +614,12 @@ static void hynix_nand_extract_scrambling_requirements(struct nand_chip *chip,
>   static void hynix_nand_decode_id(struct nand_chip *chip)
>   {
>   	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct nand_memory_organization *memorg;
>   	bool valid_jedecid;
>   	u8 tmp;
>   
> +	memorg = nanddev_get_memorg(&chip->base);
> +
>   	/*
>   	 * Exclude all SLC NANDs from this advanced detection scheme.
>   	 * According to the ranges defined in several datasheets, it might
> @@ -625,7 +633,8 @@ static void hynix_nand_decode_id(struct nand_chip *chip)
>   	}
>   
>   	/* Extract pagesize */
> -	mtd->writesize = 2048 << (chip->id.data[3] & 0x03);
> +	memorg->pagesize = 2048 << (chip->id.data[3] & 0x03);
> +	mtd->writesize = memorg->pagesize;
>   
>   	tmp = (chip->id.data[3] >> 4) & 0x3;
>   	/*
> @@ -635,12 +644,19 @@ static void hynix_nand_decode_id(struct nand_chip *chip)
>   	 * The only exception is when ID[3][4:5] == 3 and ID[3][7] == 0, in
>   	 * this case the erasesize is set to 768KiB.
>   	 */
> -	if (chip->id.data[3] & 0x80)
> +	if (chip->id.data[3] & 0x80) {
> +		memorg->pages_per_eraseblock = (SZ_1M << tmp) /
> +					       memorg->pagesize;
>   		mtd->erasesize = SZ_1M << tmp;
> -	else if (tmp == 3)
> +	} else if (tmp == 3) {
> +		memorg->pages_per_eraseblock = (SZ_512K + SZ_256K) /
> +					       memorg->pagesize;
>   		mtd->erasesize = SZ_512K + SZ_256K;
> -	else
> +	} else {
> +		memorg->pages_per_eraseblock = (SZ_128K << tmp) /
> +					       memorg->pagesize;
>   		mtd->erasesize = SZ_128K << tmp;
> +	}
>   
>   	/*
>   	 * Modern Toggle DDR NANDs have a valid JEDECID even though they are
> diff --git a/drivers/mtd/nand/raw/nand_jedec.c b/drivers/mtd/nand/raw/nand_jedec.c
> index 38b5dc22cb30..61e33ee7ee19 100644
> --- a/drivers/mtd/nand/raw/nand_jedec.c
> +++ b/drivers/mtd/nand/raw/nand_jedec.c
> @@ -22,12 +22,15 @@
>   int nand_jedec_detect(struct nand_chip *chip)
>   {
>   	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct nand_memory_organization *memorg;
>   	struct nand_jedec_params *p;
>   	struct jedec_ecc_info *ecc;
>   	int jedec_version = 0;
>   	char id[5];
>   	int i, val, ret;
>   
> +	memorg = nanddev_get_memorg(&chip->base);
> +
>   	/* Try JEDEC for unknown chip or LP */
>   	ret = nand_readid_op(chip, 0x40, id, sizeof(id));
>   	if (ret || strncmp(id, "JEDEC", sizeof(id)))
> @@ -81,17 +84,26 @@ int nand_jedec_detect(struct nand_chip *chip)
>   		goto free_jedec_param_page;
>   	}
>   
> -	mtd->writesize = le32_to_cpu(p->byte_per_page);
> +	memorg->pagesize = le32_to_cpu(p->byte_per_page);
> +	mtd->writesize = memorg->pagesize;
>   
>   	/* 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;
> +	memorg->pages_per_eraseblock =
> +			1 << (fls(le32_to_cpu(p->pages_per_block)) - 1);
> +	mtd->erasesize = memorg->pages_per_eraseblock * memorg->pagesize;
>   
> -	mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
> +	memorg->oobsize = le16_to_cpu(p->spare_bytes_per_page);
> +	mtd->oobsize = memorg->oobsize;
> +
> +	memorg->luns_per_target = p->lun_count;
> +	memorg->planes_per_lun = 1 << p->multi_plane_addr;
>   
>   	/* Please reference to the comment for nand_flash_detect_onfi. */
> -	chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
> +	memorg->eraseblocks_per_lun =
> +		1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
> +	chip->chipsize = memorg->eraseblocks_per_lun;
>   	chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count;
> +	memorg->bits_per_cell = p->bits_per_cell;
>   	chip->bits_per_cell = p->bits_per_cell;
>   
>   	if (le16_to_cpu(p->features) & JEDEC_FEATURE_16_BIT_BUS)
> diff --git a/drivers/mtd/nand/raw/nand_onfi.c b/drivers/mtd/nand/raw/nand_onfi.c
> index d8184cf591ad..f3f59cf37d7f 100644
> --- a/drivers/mtd/nand/raw/nand_onfi.c
> +++ b/drivers/mtd/nand/raw/nand_onfi.c
> @@ -140,12 +140,15 @@ static void nand_bit_wise_majority(const void **srcbufs,
>   int nand_onfi_detect(struct nand_chip *chip)
>   {
>   	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct nand_memory_organization *memorg;
>   	struct nand_onfi_params *p;
>   	struct onfi_params *onfi;
>   	int onfi_version = 0;
>   	char id[4];
>   	int i, ret, val;
>   
> +	memorg = nanddev_get_memorg(&chip->base);
> +
>   	/* Try ONFI for unknown chip or LP */
>   	ret = nand_readid_op(chip, 0x20, id, sizeof(id));
>   	if (ret || strncmp(id, "ONFI", 4))
> @@ -221,21 +224,31 @@ int nand_onfi_detect(struct nand_chip *chip)
>   		goto free_onfi_param_page;
>   	}
>   
> -	mtd->writesize = le32_to_cpu(p->byte_per_page);
> +	memorg->pagesize = le32_to_cpu(p->byte_per_page);
> +	mtd->writesize = memorg->pagesize;
>   
>   	/*
>   	 * pages_per_block and blocks_per_lun may not be a power-of-2 size
>   	 * (don't ask me who thought of this...). MTD assumes that these
>   	 * dimensions will be power-of-2, so just truncate the remaining area.
>   	 */
> -	mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1);
> -	mtd->erasesize *= mtd->writesize;
> +	memorg->pages_per_eraseblock =
> +			1 << (fls(le32_to_cpu(p->pages_per_block)) - 1);
> +	mtd->erasesize = memorg->pages_per_eraseblock * memorg->pagesize;
>   
> -	mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
> +	memorg->oobsize = le16_to_cpu(p->spare_bytes_per_page);
> +	mtd->oobsize = memorg->oobsize;
> +
> +	memorg->luns_per_target = p->lun_count;
> +	memorg->planes_per_lun = 1 << p->interleaved_bits;
>   
>   	/* See erasesize comment */
> -	chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
> +	memorg->eraseblocks_per_lun =
> +		1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
> +	memorg->max_bad_eraseblocks_per_lun = le32_to_cpu(p->blocks_per_lun);
> +	chip->chipsize = memorg->eraseblocks_per_lun;
>   	chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count;
> +	memorg->bits_per_cell = p->bits_per_cell;
>   	chip->bits_per_cell = p->bits_per_cell;
>   
>   	chip->max_bb_per_die = le16_to_cpu(p->bb_per_lun);
> diff --git a/drivers/mtd/nand/raw/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c
> index e46d4c492ad8..9a9ad43cc97d 100644
> --- a/drivers/mtd/nand/raw/nand_samsung.c
> +++ b/drivers/mtd/nand/raw/nand_samsung.c
> @@ -20,6 +20,9 @@
>   static void samsung_nand_decode_id(struct nand_chip *chip)
>   {
>   	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct nand_memory_organization *memorg;
> +
> +	memorg = nanddev_get_memorg(&chip->base);
>   
>   	/* New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) */
>   	if (chip->id.len == 6 && !nand_is_slc(chip) &&
> @@ -27,29 +30,30 @@ static void samsung_nand_decode_id(struct nand_chip *chip)
>   		u8 extid = chip->id.data[3];
>   
>   		/* Get pagesize */
> -		mtd->writesize = 2048 << (extid & 0x03);
> +		memorg->pagesize = 2048 << (extid & 0x03);
> +		mtd->writesize = memorg->pagesize;
>   
>   		extid >>= 2;
>   
>   		/* Get oobsize */
>   		switch (((extid >> 2) & 0x4) | (extid & 0x3)) {
>   		case 1:
> -			mtd->oobsize = 128;
> +			memorg->oobsize = 128;
>   			break;
>   		case 2:
> -			mtd->oobsize = 218;
> +			memorg->oobsize = 218;
>   			break;
>   		case 3:
> -			mtd->oobsize = 400;
> +			memorg->oobsize = 400;
>   			break;
>   		case 4:
> -			mtd->oobsize = 436;
> +			memorg->oobsize = 436;
>   			break;
>   		case 5:
> -			mtd->oobsize = 512;
> +			memorg->oobsize = 512;
>   			break;
>   		case 6:
> -			mtd->oobsize = 640;
> +			memorg->oobsize = 640;
>   			break;
>   		default:
>   			/*
> @@ -62,8 +66,14 @@ static void samsung_nand_decode_id(struct nand_chip *chip)
>   			break;
>   		}
>   
> +		mtd->oobsize = memorg->oobsize;
> +
>   		/* Get blocksize */
>   		extid >>= 2;
> +		memorg->pages_per_eraseblock = (128 * 1024) <<
> +					       (((extid >> 1) & 0x04) |
> +						(extid & 0x03)) /
> +					       memorg->pagesize;
>   		mtd->erasesize = (128 * 1024) <<
>   				 (((extid >> 1) & 0x04) | (extid & 0x03));
>   
> diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
> index d068163b64b3..d8465049dfd6 100644
> --- a/drivers/mtd/nand/raw/nand_toshiba.c
> +++ b/drivers/mtd/nand/raw/nand_toshiba.c
> @@ -101,6 +101,9 @@ static void toshiba_nand_benand_init(struct nand_chip *chip)
>   static void toshiba_nand_decode_id(struct nand_chip *chip)
>   {
>   	struct mtd_info *mtd = nand_to_mtd(chip);
> +	struct nand_memory_organization *memorg;
> +
> +	memorg = nanddev_get_memorg(&chip->base);
>   
>   	nand_decode_ext_id(chip);
>   
> @@ -114,8 +117,10 @@ static void toshiba_nand_decode_id(struct nand_chip *chip)
>   	 */
>   	if (chip->id.len >= 6 && nand_is_slc(chip) &&
>   	    (chip->id.data[5] & 0x7) == 0x6 /* 24nm */ &&
> -	    !(chip->id.data[4] & 0x80) /* !BENAND */)
> -		mtd->oobsize = 32 * mtd->writesize >> 9;
> +	    !(chip->id.data[4] & 0x80) /* !BENAND */) {
> +		memorg->oobsize = 32 * memorg->pagesize >> 9;
> +		mtd->oobsize = memorg->oobsize;
> +	}
>   
>   	/*
>   	 * Extract ECC requirements from 6th id byte.
> diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c
> index 933d1a629c51..07144c992d54 100644
> --- a/drivers/mtd/nand/raw/nandsim.c
> +++ b/drivers/mtd/nand/raw/nandsim.c
> @@ -2302,6 +2302,10 @@ static int __init ns_init_module(void)
>   
>   	if (overridesize) {
>   		uint64_t new_size = (uint64_t)nsmtd->erasesize << overridesize;
> +		struct nand_memory_organization *memorg;
> +
> +		memorg = nanddev_get_memorg(&chip->base);
> +
>   		if (new_size >> overridesize != nsmtd->erasesize) {
>   			NS_ERR("overridesize is too big\n");
>   			retval = -EINVAL;
> @@ -2309,6 +2313,7 @@ static int __init ns_init_module(void)
>   		}
>   		/* N.B. This relies on nand_scan not doing anything with the size before we change it */
>   		nsmtd->size = new_size;
> +		memorg->eraseblocks_per_lun = 1 << overridesize;
>   		chip->chipsize = new_size;
>   		chip->chip_shift = ffs(nsmtd->erasesize) + overridesize - 1;
>   		chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
>
diff mbox series

Patch

diff --git a/drivers/mtd/nand/raw/denali.c b/drivers/mtd/nand/raw/denali.c
index eebac35304c6..86e5df403beb 100644
--- a/drivers/mtd/nand/raw/denali.c
+++ b/drivers/mtd/nand/raw/denali.c
@@ -1119,6 +1119,9 @@  static int denali_multidev_fixup(struct denali_nand_info *denali)
 {
 	struct nand_chip *chip = &denali->nand;
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_memory_organization *memorg;
+
+	memorg = nanddev_get_memorg(&chip->base);
 
 	/*
 	 * Support for multi device:
@@ -1148,6 +1151,8 @@  static int denali_multidev_fixup(struct denali_nand_info *denali)
 	}
 
 	/* 2 chips in parallel */
+	memorg->pagesize <<= 1;
+	memorg->oobsize <<= 1;
 	mtd->size <<= 1;
 	mtd->erasesize <<= 1;
 	mtd->writesize <<= 1;
diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c
index 53f57e0f007e..e9767e06415d 100644
--- a/drivers/mtd/nand/raw/diskonchip.c
+++ b/drivers/mtd/nand/raw/diskonchip.c
@@ -1028,6 +1028,7 @@  static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio
 {
 	struct nand_chip *this = mtd_to_nand(mtd);
 	struct doc_priv *doc = nand_get_controller_data(this);
+	struct nand_memory_organization *memorg;
 	int ret = 0;
 	u_char *buf;
 	struct NFTLMediaHeader *mh;
@@ -1036,6 +1037,8 @@  static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio
 	unsigned blocks, maxblocks;
 	int offs, numheaders;
 
+	memorg = nanddev_get_memorg(&this->base);
+
 	buf = kmalloc(mtd->writesize, GFP_KERNEL);
 	if (!buf) {
 		return 0;
@@ -1082,6 +1085,7 @@  static inline int __init nftl_partscan(struct mtd_info *mtd, struct mtd_partitio
 	   implementation of the NAND layer.  */
 	if (mh->UnitSizeFactor != 0xff) {
 		this->bbt_erase_shift += (0xff - mh->UnitSizeFactor);
+		memorg->pages_per_eraseblock <<= (0xff - mh->UnitSizeFactor);
 		mtd->erasesize <<= (0xff - mh->UnitSizeFactor);
 		pr_info("Setting virtual erase size to %d\n", mtd->erasesize);
 		blocks = mtd->size >> this->bbt_erase_shift;
diff --git a/drivers/mtd/nand/raw/jz4740_nand.c b/drivers/mtd/nand/raw/jz4740_nand.c
index f92ae5aa2a54..76a32ad2cf83 100644
--- a/drivers/mtd/nand/raw/jz4740_nand.c
+++ b/drivers/mtd/nand/raw/jz4740_nand.c
@@ -313,8 +313,11 @@  static int jz_nand_detect_bank(struct platform_device *pdev,
 	uint32_t ctrl;
 	struct nand_chip *chip = &nand->chip;
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_memory_organization *memorg;
 	u8 id[2];
 
+	memorg = nanddev_get_memorg(&chip->base);
+
 	/* Request I/O resource. */
 	sprintf(res_name, "bank%d", bank);
 	ret = jz_nand_ioremap_resource(pdev, res_name,
@@ -352,6 +355,7 @@  static int jz_nand_detect_bank(struct platform_device *pdev,
 
 		/* Update size of the MTD. */
 		chip->numchips++;
+		memorg->ntargets++;
 		mtd->size += chip->chipsize;
 	}
 
diff --git a/drivers/mtd/nand/raw/nand_amd.c b/drivers/mtd/nand/raw/nand_amd.c
index 890c5b43e03c..e008fd662ee6 100644
--- a/drivers/mtd/nand/raw/nand_amd.c
+++ b/drivers/mtd/nand/raw/nand_amd.c
@@ -20,6 +20,9 @@ 
 static void amd_nand_decode_id(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_memory_organization *memorg;
+
+	memorg = nanddev_get_memorg(&chip->base);
 
 	nand_decode_ext_id(chip);
 
@@ -31,9 +34,11 @@  static void amd_nand_decode_id(struct nand_chip *chip)
 	 */
 	if (chip->id.data[4] != 0x00 && chip->id.data[5] == 0x00 &&
 	    chip->id.data[6] == 0x00 && chip->id.data[7] == 0x00 &&
-	    mtd->writesize == 512) {
-		mtd->erasesize = 128 * 1024;
-		mtd->erasesize <<= ((chip->id.data[3] & 0x03) << 1);
+	    memorg->pagesize == 512) {
+		memorg->pages_per_eraseblock = 256;
+		memorg->pages_per_eraseblock <<= ((chip->id.data[3] & 0x03) << 1);
+		mtd->erasesize = memorg->pages_per_eraseblock *
+				 memorg->pagesize;
 	}
 }
 
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
index d3092c9a3e21..5aba1cf38a4b 100644
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4530,21 +4530,30 @@  static int nand_get_bits_per_cell(u8 cellinfo)
  */
 void nand_decode_ext_id(struct nand_chip *chip)
 {
+	struct nand_memory_organization *memorg;
 	struct mtd_info *mtd = nand_to_mtd(chip);
 	int extid;
 	u8 *id_data = chip->id.data;
+
+	memorg = nanddev_get_memorg(&chip->base);
+
 	/* The 3rd id byte holds MLC / multichip data */
+	memorg->bits_per_cell = nand_get_bits_per_cell(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];
 
 	/* Calc pagesize */
-	mtd->writesize = 1024 << (extid & 0x03);
+	memorg->pagesize = 1024 << (extid & 0x03);
+	mtd->writesize = memorg->pagesize;
 	extid >>= 2;
 	/* Calc oobsize */
-	mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
+	memorg->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
+	mtd->oobsize = memorg->oobsize;
 	extid >>= 2;
 	/* Calc blocksize. Blocksize is multiples of 64KiB */
+	memorg->pages_per_eraseblock = ((64 * 1024) << (extid & 0x03)) /
+				       memorg->pagesize;
 	mtd->erasesize = (64 * 1024) << (extid & 0x03);
 	extid >>= 2;
 	/* Get buswidth information */
@@ -4561,12 +4570,19 @@  EXPORT_SYMBOL_GPL(nand_decode_ext_id);
 static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_memory_organization *memorg;
 
+	memorg = nanddev_get_memorg(&chip->base);
+
+	memorg->pages_per_eraseblock = type->erasesize / type->pagesize;
 	mtd->erasesize = type->erasesize;
-	mtd->writesize = type->pagesize;
-	mtd->oobsize = mtd->writesize / 32;
+	memorg->pagesize = type->pagesize;
+	mtd->writesize = memorg->pagesize;
+	memorg->oobsize = memorg->pagesize / 32;
+	mtd->oobsize = memorg->oobsize;
 
 	/* All legacy ID NAND are small-page, SLC */
+	memorg->bits_per_cell = 1;
 	chip->bits_per_cell = 1;
 }
 
@@ -4595,15 +4611,27 @@  static bool find_full_id_nand(struct nand_chip *chip,
 			      struct nand_flash_dev *type)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_memory_organization *memorg;
 	u8 *id_data = chip->id.data;
 
+	memorg = nanddev_get_memorg(&chip->base);
+
 	if (!strncmp(type->id, id_data, type->id_len)) {
-		mtd->writesize = type->pagesize;
+		memorg->pagesize = type->pagesize;
+		mtd->writesize = memorg->pagesize;
+		memorg->pages_per_eraseblock = type->erasesize /
+					       type->pagesize;
 		mtd->erasesize = type->erasesize;
-		mtd->oobsize = type->oobsize;
+		memorg->oobsize = type->oobsize;
+		mtd->oobsize = memorg->oobsize;
 
+		memorg->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
 		chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
 		chip->chipsize = (uint64_t)type->chipsize << 20;
+		memorg->eraseblocks_per_lun =
+			DIV_ROUND_DOWN_ULL((u64)type->chipsize << 20,
+					   memorg->pagesize *
+					   memorg->pages_per_eraseblock);
 		chip->options |= type->options;
 		chip->ecc_strength_ds = NAND_ECC_STRENGTH(type);
 		chip->ecc_step_ds = NAND_ECC_STEP(type);
@@ -4632,7 +4660,12 @@  static void nand_manufacturer_detect(struct nand_chip *chip)
 	 */
 	if (chip->manufacturer.desc && chip->manufacturer.desc->ops &&
 	    chip->manufacturer.desc->ops->detect) {
+		struct nand_memory_organization *memorg;
+
+		memorg = nanddev_get_memorg(&chip->base);
+
 		/* The 3rd id byte holds MLC / multichip data */
+		memorg->bits_per_cell = nand_get_bits_per_cell(chip->id.data[2]);
 		chip->bits_per_cell = nand_get_bits_per_cell(chip->id.data[2]);
 		chip->manufacturer.desc->ops->detect(chip);
 	} else {
@@ -4682,10 +4715,20 @@  static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
 {
 	const struct nand_manufacturer *manufacturer;
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_memory_organization *memorg;
 	int busw, ret;
 	u8 *id_data = chip->id.data;
 	u8 maf_id, dev_id;
 
+	/*
+	 * Let's start by initializing memorg fields that might be left
+	 * unassigned by the ID-based detection logic.
+	 */
+	memorg = nanddev_get_memorg(&chip->base);
+	memorg->planes_per_lun = 1;
+	memorg->luns_per_target = 1;
+	memorg->ntargets = 1;
+
 	/*
 	 * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
 	 * after power-up.
@@ -4790,6 +4833,11 @@  static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
 	/* Get chip options */
 	chip->options |= type->options;
 
+	memorg->eraseblocks_per_lun =
+			DIV_ROUND_DOWN_ULL((u64)type->chipsize << 20,
+					   memorg->pagesize *
+					   memorg->pages_per_eraseblock);
+
 ident_done:
 	if (!mtd->name)
 		mtd->name = chip->parameters.model;
@@ -5016,10 +5064,13 @@  static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
 			   struct nand_flash_dev *table)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_memory_organization *memorg;
 	int nand_maf_id, nand_dev_id;
 	unsigned int i;
 	int ret;
 
+	memorg = nanddev_get_memorg(&chip->base);
+
 	/* Assume all dies are deselected when we enter nand_scan_ident(). */
 	chip->cur_cs = -1;
 
@@ -5081,6 +5132,7 @@  static int nand_scan_ident(struct nand_chip *chip, unsigned int maxchips,
 		pr_info("%d chips detected\n", i);
 
 	/* Store the number of chips and calc total size for mtd */
+	memorg->ntargets = i;
 	chip->numchips = i;
 	mtd->size = i * chip->chipsize;
 
diff --git a/drivers/mtd/nand/raw/nand_hynix.c b/drivers/mtd/nand/raw/nand_hynix.c
index 343f477362d1..94ea8c593589 100644
--- a/drivers/mtd/nand/raw/nand_hynix.c
+++ b/drivers/mtd/nand/raw/nand_hynix.c
@@ -418,24 +418,27 @@  static void hynix_nand_extract_oobsize(struct nand_chip *chip,
 				       bool valid_jedecid)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_memory_organization *memorg;
 	u8 oobsize;
 
+	memorg = nanddev_get_memorg(&chip->base);
+
 	oobsize = ((chip->id.data[3] >> 2) & 0x3) |
 		  ((chip->id.data[3] >> 4) & 0x4);
 
 	if (valid_jedecid) {
 		switch (oobsize) {
 		case 0:
-			mtd->oobsize = 2048;
+			memorg->oobsize = 2048;
 			break;
 		case 1:
-			mtd->oobsize = 1664;
+			memorg->oobsize = 1664;
 			break;
 		case 2:
-			mtd->oobsize = 1024;
+			memorg->oobsize = 1024;
 			break;
 		case 3:
-			mtd->oobsize = 640;
+			memorg->oobsize = 640;
 			break;
 		default:
 			/*
@@ -450,25 +453,25 @@  static void hynix_nand_extract_oobsize(struct nand_chip *chip,
 	} else {
 		switch (oobsize) {
 		case 0:
-			mtd->oobsize = 128;
+			memorg->oobsize = 128;
 			break;
 		case 1:
-			mtd->oobsize = 224;
+			memorg->oobsize = 224;
 			break;
 		case 2:
-			mtd->oobsize = 448;
+			memorg->oobsize = 448;
 			break;
 		case 3:
-			mtd->oobsize = 64;
+			memorg->oobsize = 64;
 			break;
 		case 4:
-			mtd->oobsize = 32;
+			memorg->oobsize = 32;
 			break;
 		case 5:
-			mtd->oobsize = 16;
+			memorg->oobsize = 16;
 			break;
 		case 6:
-			mtd->oobsize = 640;
+			memorg->oobsize = 640;
 			break;
 		default:
 			/*
@@ -492,8 +495,10 @@  static void hynix_nand_extract_oobsize(struct nand_chip *chip,
 		 * the actual OOB size for this chip is: 640 * 16k / 8k).
 		 */
 		if (chip->id.data[1] == 0xde)
-			mtd->oobsize *= mtd->writesize / SZ_8K;
+			memorg->oobsize *= memorg->pagesize / SZ_8K;
 	}
+
+	mtd->oobsize = memorg->oobsize;
 }
 
 static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip,
@@ -609,9 +614,12 @@  static void hynix_nand_extract_scrambling_requirements(struct nand_chip *chip,
 static void hynix_nand_decode_id(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_memory_organization *memorg;
 	bool valid_jedecid;
 	u8 tmp;
 
+	memorg = nanddev_get_memorg(&chip->base);
+
 	/*
 	 * Exclude all SLC NANDs from this advanced detection scheme.
 	 * According to the ranges defined in several datasheets, it might
@@ -625,7 +633,8 @@  static void hynix_nand_decode_id(struct nand_chip *chip)
 	}
 
 	/* Extract pagesize */
-	mtd->writesize = 2048 << (chip->id.data[3] & 0x03);
+	memorg->pagesize = 2048 << (chip->id.data[3] & 0x03);
+	mtd->writesize = memorg->pagesize;
 
 	tmp = (chip->id.data[3] >> 4) & 0x3;
 	/*
@@ -635,12 +644,19 @@  static void hynix_nand_decode_id(struct nand_chip *chip)
 	 * The only exception is when ID[3][4:5] == 3 and ID[3][7] == 0, in
 	 * this case the erasesize is set to 768KiB.
 	 */
-	if (chip->id.data[3] & 0x80)
+	if (chip->id.data[3] & 0x80) {
+		memorg->pages_per_eraseblock = (SZ_1M << tmp) /
+					       memorg->pagesize;
 		mtd->erasesize = SZ_1M << tmp;
-	else if (tmp == 3)
+	} else if (tmp == 3) {
+		memorg->pages_per_eraseblock = (SZ_512K + SZ_256K) /
+					       memorg->pagesize;
 		mtd->erasesize = SZ_512K + SZ_256K;
-	else
+	} else {
+		memorg->pages_per_eraseblock = (SZ_128K << tmp) /
+					       memorg->pagesize;
 		mtd->erasesize = SZ_128K << tmp;
+	}
 
 	/*
 	 * Modern Toggle DDR NANDs have a valid JEDECID even though they are
diff --git a/drivers/mtd/nand/raw/nand_jedec.c b/drivers/mtd/nand/raw/nand_jedec.c
index 38b5dc22cb30..61e33ee7ee19 100644
--- a/drivers/mtd/nand/raw/nand_jedec.c
+++ b/drivers/mtd/nand/raw/nand_jedec.c
@@ -22,12 +22,15 @@ 
 int nand_jedec_detect(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_memory_organization *memorg;
 	struct nand_jedec_params *p;
 	struct jedec_ecc_info *ecc;
 	int jedec_version = 0;
 	char id[5];
 	int i, val, ret;
 
+	memorg = nanddev_get_memorg(&chip->base);
+
 	/* Try JEDEC for unknown chip or LP */
 	ret = nand_readid_op(chip, 0x40, id, sizeof(id));
 	if (ret || strncmp(id, "JEDEC", sizeof(id)))
@@ -81,17 +84,26 @@  int nand_jedec_detect(struct nand_chip *chip)
 		goto free_jedec_param_page;
 	}
 
-	mtd->writesize = le32_to_cpu(p->byte_per_page);
+	memorg->pagesize = le32_to_cpu(p->byte_per_page);
+	mtd->writesize = memorg->pagesize;
 
 	/* 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;
+	memorg->pages_per_eraseblock =
+			1 << (fls(le32_to_cpu(p->pages_per_block)) - 1);
+	mtd->erasesize = memorg->pages_per_eraseblock * memorg->pagesize;
 
-	mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
+	memorg->oobsize = le16_to_cpu(p->spare_bytes_per_page);
+	mtd->oobsize = memorg->oobsize;
+
+	memorg->luns_per_target = p->lun_count;
+	memorg->planes_per_lun = 1 << p->multi_plane_addr;
 
 	/* Please reference to the comment for nand_flash_detect_onfi. */
-	chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
+	memorg->eraseblocks_per_lun =
+		1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
+	chip->chipsize = memorg->eraseblocks_per_lun;
 	chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count;
+	memorg->bits_per_cell = p->bits_per_cell;
 	chip->bits_per_cell = p->bits_per_cell;
 
 	if (le16_to_cpu(p->features) & JEDEC_FEATURE_16_BIT_BUS)
diff --git a/drivers/mtd/nand/raw/nand_onfi.c b/drivers/mtd/nand/raw/nand_onfi.c
index d8184cf591ad..f3f59cf37d7f 100644
--- a/drivers/mtd/nand/raw/nand_onfi.c
+++ b/drivers/mtd/nand/raw/nand_onfi.c
@@ -140,12 +140,15 @@  static void nand_bit_wise_majority(const void **srcbufs,
 int nand_onfi_detect(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_memory_organization *memorg;
 	struct nand_onfi_params *p;
 	struct onfi_params *onfi;
 	int onfi_version = 0;
 	char id[4];
 	int i, ret, val;
 
+	memorg = nanddev_get_memorg(&chip->base);
+
 	/* Try ONFI for unknown chip or LP */
 	ret = nand_readid_op(chip, 0x20, id, sizeof(id));
 	if (ret || strncmp(id, "ONFI", 4))
@@ -221,21 +224,31 @@  int nand_onfi_detect(struct nand_chip *chip)
 		goto free_onfi_param_page;
 	}
 
-	mtd->writesize = le32_to_cpu(p->byte_per_page);
+	memorg->pagesize = le32_to_cpu(p->byte_per_page);
+	mtd->writesize = memorg->pagesize;
 
 	/*
 	 * pages_per_block and blocks_per_lun may not be a power-of-2 size
 	 * (don't ask me who thought of this...). MTD assumes that these
 	 * dimensions will be power-of-2, so just truncate the remaining area.
 	 */
-	mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1);
-	mtd->erasesize *= mtd->writesize;
+	memorg->pages_per_eraseblock =
+			1 << (fls(le32_to_cpu(p->pages_per_block)) - 1);
+	mtd->erasesize = memorg->pages_per_eraseblock * memorg->pagesize;
 
-	mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
+	memorg->oobsize = le16_to_cpu(p->spare_bytes_per_page);
+	mtd->oobsize = memorg->oobsize;
+
+	memorg->luns_per_target = p->lun_count;
+	memorg->planes_per_lun = 1 << p->interleaved_bits;
 
 	/* See erasesize comment */
-	chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
+	memorg->eraseblocks_per_lun =
+		1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1);
+	memorg->max_bad_eraseblocks_per_lun = le32_to_cpu(p->blocks_per_lun);
+	chip->chipsize = memorg->eraseblocks_per_lun;
 	chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count;
+	memorg->bits_per_cell = p->bits_per_cell;
 	chip->bits_per_cell = p->bits_per_cell;
 
 	chip->max_bb_per_die = le16_to_cpu(p->bb_per_lun);
diff --git a/drivers/mtd/nand/raw/nand_samsung.c b/drivers/mtd/nand/raw/nand_samsung.c
index e46d4c492ad8..9a9ad43cc97d 100644
--- a/drivers/mtd/nand/raw/nand_samsung.c
+++ b/drivers/mtd/nand/raw/nand_samsung.c
@@ -20,6 +20,9 @@ 
 static void samsung_nand_decode_id(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_memory_organization *memorg;
+
+	memorg = nanddev_get_memorg(&chip->base);
 
 	/* New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) */
 	if (chip->id.len == 6 && !nand_is_slc(chip) &&
@@ -27,29 +30,30 @@  static void samsung_nand_decode_id(struct nand_chip *chip)
 		u8 extid = chip->id.data[3];
 
 		/* Get pagesize */
-		mtd->writesize = 2048 << (extid & 0x03);
+		memorg->pagesize = 2048 << (extid & 0x03);
+		mtd->writesize = memorg->pagesize;
 
 		extid >>= 2;
 
 		/* Get oobsize */
 		switch (((extid >> 2) & 0x4) | (extid & 0x3)) {
 		case 1:
-			mtd->oobsize = 128;
+			memorg->oobsize = 128;
 			break;
 		case 2:
-			mtd->oobsize = 218;
+			memorg->oobsize = 218;
 			break;
 		case 3:
-			mtd->oobsize = 400;
+			memorg->oobsize = 400;
 			break;
 		case 4:
-			mtd->oobsize = 436;
+			memorg->oobsize = 436;
 			break;
 		case 5:
-			mtd->oobsize = 512;
+			memorg->oobsize = 512;
 			break;
 		case 6:
-			mtd->oobsize = 640;
+			memorg->oobsize = 640;
 			break;
 		default:
 			/*
@@ -62,8 +66,14 @@  static void samsung_nand_decode_id(struct nand_chip *chip)
 			break;
 		}
 
+		mtd->oobsize = memorg->oobsize;
+
 		/* Get blocksize */
 		extid >>= 2;
+		memorg->pages_per_eraseblock = (128 * 1024) <<
+					       (((extid >> 1) & 0x04) |
+						(extid & 0x03)) /
+					       memorg->pagesize;
 		mtd->erasesize = (128 * 1024) <<
 				 (((extid >> 1) & 0x04) | (extid & 0x03));
 
diff --git a/drivers/mtd/nand/raw/nand_toshiba.c b/drivers/mtd/nand/raw/nand_toshiba.c
index d068163b64b3..d8465049dfd6 100644
--- a/drivers/mtd/nand/raw/nand_toshiba.c
+++ b/drivers/mtd/nand/raw/nand_toshiba.c
@@ -101,6 +101,9 @@  static void toshiba_nand_benand_init(struct nand_chip *chip)
 static void toshiba_nand_decode_id(struct nand_chip *chip)
 {
 	struct mtd_info *mtd = nand_to_mtd(chip);
+	struct nand_memory_organization *memorg;
+
+	memorg = nanddev_get_memorg(&chip->base);
 
 	nand_decode_ext_id(chip);
 
@@ -114,8 +117,10 @@  static void toshiba_nand_decode_id(struct nand_chip *chip)
 	 */
 	if (chip->id.len >= 6 && nand_is_slc(chip) &&
 	    (chip->id.data[5] & 0x7) == 0x6 /* 24nm */ &&
-	    !(chip->id.data[4] & 0x80) /* !BENAND */)
-		mtd->oobsize = 32 * mtd->writesize >> 9;
+	    !(chip->id.data[4] & 0x80) /* !BENAND */) {
+		memorg->oobsize = 32 * memorg->pagesize >> 9;
+		mtd->oobsize = memorg->oobsize;
+	}
 
 	/*
 	 * Extract ECC requirements from 6th id byte.
diff --git a/drivers/mtd/nand/raw/nandsim.c b/drivers/mtd/nand/raw/nandsim.c
index 933d1a629c51..07144c992d54 100644
--- a/drivers/mtd/nand/raw/nandsim.c
+++ b/drivers/mtd/nand/raw/nandsim.c
@@ -2302,6 +2302,10 @@  static int __init ns_init_module(void)
 
 	if (overridesize) {
 		uint64_t new_size = (uint64_t)nsmtd->erasesize << overridesize;
+		struct nand_memory_organization *memorg;
+
+		memorg = nanddev_get_memorg(&chip->base);
+
 		if (new_size >> overridesize != nsmtd->erasesize) {
 			NS_ERR("overridesize is too big\n");
 			retval = -EINVAL;
@@ -2309,6 +2313,7 @@  static int __init ns_init_module(void)
 		}
 		/* N.B. This relies on nand_scan not doing anything with the size before we change it */
 		nsmtd->size = new_size;
+		memorg->eraseblocks_per_lun = 1 << overridesize;
 		chip->chipsize = new_size;
 		chip->chip_shift = ffs(nsmtd->erasesize) + overridesize - 1;
 		chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;