diff options
Diffstat (limited to 'drivers/mtd/nand/raw/nand_base.c')
-rw-r--r-- | drivers/mtd/nand/raw/nand_base.c | 64 |
1 files changed, 58 insertions, 6 deletions
diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index ddd396e93e32..dbe3d96b74da 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -4485,21 +4485,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 */ @@ -4516,12 +4525,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; } @@ -4550,15 +4566,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); @@ -4587,7 +4615,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 { @@ -4637,11 +4670,21 @@ 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. */ @@ -4745,6 +4788,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; @@ -4971,10 +5019,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; @@ -5042,6 +5093,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; |