diff options
-rw-r--r-- | drivers/mtd/nand/raw/Kconfig | 1 | ||||
-rw-r--r-- | drivers/mtd/nand/raw/nand_base.c | 65 |
2 files changed, 59 insertions, 7 deletions
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index 705863c6709a..80b5fec1f75a 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -14,6 +14,7 @@ menuconfig MTD_NAND tristate "Raw/Parallel NAND Device Support" depends on MTD select MTD_NAND_ECC + select MTD_NAND_CORE help This enables support for accessing all type of raw/parallel NAND flash devices. For further information see diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index dbe3d96b74da..071a0c658bfe 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -5484,6 +5484,50 @@ static bool nand_ecc_strength_good(struct nand_chip *chip) return corr >= ds_corr && ecc->strength >= chip->ecc_strength_ds; } +static int rawnand_erase(struct nand_device *nand, const struct nand_pos *pos) +{ + struct nand_chip *chip = container_of(nand, struct nand_chip, + base); + unsigned int eb = nanddev_pos_to_row(nand, pos); + int ret; + + eb >>= nand->rowconv.eraseblock_addr_shift; + + nand_select_target(chip, pos->target); + ret = nand_erase_op(chip, eb); + nand_deselect_target(chip); + + return ret; +} + +static int rawnand_markbad(struct nand_device *nand, + const struct nand_pos *pos) +{ + struct nand_chip *chip = container_of(nand, struct nand_chip, + base); + + return nand_markbad_bbm(chip, nanddev_pos_to_offs(nand, pos)); +} + +static bool rawnand_isbad(struct nand_device *nand, const struct nand_pos *pos) +{ + struct nand_chip *chip = container_of(nand, struct nand_chip, + base); + int ret; + + nand_select_target(chip, pos->target); + ret = nand_isbad_bbm(chip, nanddev_pos_to_offs(nand, pos)); + nand_deselect_target(chip); + + return ret; +} + +static const struct nand_ops rawnand_ops = { + .erase = rawnand_erase, + .markbad = rawnand_markbad, + .isbad = rawnand_isbad, +}; + /** * nand_scan_tail - Scan for the NAND device * @chip: NAND chip object @@ -5752,10 +5796,15 @@ static int nand_scan_tail(struct nand_chip *chip) break; } + ret = nanddev_init(&chip->base, &rawnand_ops, mtd->owner); + if (ret) + goto err_nand_manuf_cleanup; + + /* Adjust the MTD_CAP_ flags when NAND_ROM is set. */ + if (chip->options & NAND_ROM) + mtd->flags = MTD_CAP_ROM; + /* Fill in remaining MTD driver data */ - mtd->type = nand_is_slc(chip) ? MTD_NANDFLASH : MTD_MLCNANDFLASH; - mtd->flags = (chip->options & NAND_ROM) ? MTD_CAP_ROM : - MTD_CAP_NANDFLASH; mtd->_erase = nand_erase; mtd->_point = NULL; mtd->_unpoint = NULL; @@ -5772,7 +5821,6 @@ static int nand_scan_tail(struct nand_chip *chip) mtd->_block_isbad = nand_block_isbad; mtd->_block_markbad = nand_block_markbad; mtd->_max_bad_blocks = nand_max_bad_blocks; - mtd->writebufsize = mtd->writesize; /* * Initialize bitflip_threshold to its default prior scan_bbt() call. @@ -5785,13 +5833,13 @@ static int nand_scan_tail(struct nand_chip *chip) /* Initialize the ->data_interface field. */ ret = nand_init_data_interface(chip); if (ret) - goto err_nand_manuf_cleanup; + goto err_nanddev_cleanup; /* Enter fastest possible mode on all dies. */ for (i = 0; i < chip->numchips; i++) { ret = nand_setup_data_interface(chip, i); if (ret) - goto err_nand_manuf_cleanup; + goto err_nanddev_cleanup; } /* Check, if we should skip the bad block table scan */ @@ -5801,11 +5849,14 @@ static int nand_scan_tail(struct nand_chip *chip) /* Build bad block table */ ret = nand_create_bbt(chip); if (ret) - goto err_nand_manuf_cleanup; + goto err_nanddev_cleanup; return 0; +err_nanddev_cleanup: + nanddev_cleanup(&chip->base); + err_nand_manuf_cleanup: nand_manufacturer_cleanup(chip); |