diff options
author | Masahiro Yamada <yamada.masahiro@socionext.com> | 2017-03-22 16:07:01 -0400 |
---|---|---|
committer | Boris Brezillon <boris.brezillon@free-electrons.com> | 2017-03-24 04:47:43 -0400 |
commit | c120e75e0e7deff88119376298342df139b9b17c (patch) | |
tree | 2124abb2038c31bec3857dadc616e333c1985707 /drivers/mtd/nand | |
parent | 9fe4b66efb77fec71a9c11de58e5e51c5c826190 (diff) |
mtd: nand: use read_oob() instead of cmdfunc() for bad block check
The nand_default_block_markbad() and scan_block_fast() use high
level APIs to get access to the BBM.
On the other hand, nand_block_bad (the default implementation of
->block_bad) calls the lower level ->cmdfunc hook. This prevents
drivers from using ->ecc.read_oob() even if optimized read operation
is implemented. Besides, some NAND controllers may protect the BBM
with ECC.
Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 34 |
1 files changed, 13 insertions, 21 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index d3545c9a792a..afbb80f4375a 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -354,40 +354,32 @@ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) | |||
354 | */ | 354 | */ |
355 | static int nand_block_bad(struct mtd_info *mtd, loff_t ofs) | 355 | static int nand_block_bad(struct mtd_info *mtd, loff_t ofs) |
356 | { | 356 | { |
357 | int page, res = 0, i = 0; | 357 | int page, page_end, res; |
358 | struct nand_chip *chip = mtd_to_nand(mtd); | 358 | struct nand_chip *chip = mtd_to_nand(mtd); |
359 | u16 bad; | 359 | u8 bad; |
360 | 360 | ||
361 | if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) | 361 | if (chip->bbt_options & NAND_BBT_SCANLASTPAGE) |
362 | ofs += mtd->erasesize - mtd->writesize; | 362 | ofs += mtd->erasesize - mtd->writesize; |
363 | 363 | ||
364 | page = (int)(ofs >> chip->page_shift) & chip->pagemask; | 364 | page = (int)(ofs >> chip->page_shift) & chip->pagemask; |
365 | page_end = page + (chip->bbt_options & NAND_BBT_SCAN2NDPAGE ? 2 : 1); | ||
365 | 366 | ||
366 | do { | 367 | for (; page < page_end; page++) { |
367 | if (chip->options & NAND_BUSWIDTH_16) { | 368 | res = chip->ecc.read_oob(mtd, chip, page); |
368 | chip->cmdfunc(mtd, NAND_CMD_READOOB, | 369 | if (res) |
369 | chip->badblockpos & 0xFE, page); | 370 | return res; |
370 | bad = cpu_to_le16(chip->read_word(mtd)); | 371 | |
371 | if (chip->badblockpos & 0x1) | 372 | bad = chip->oob_poi[chip->badblockpos]; |
372 | bad >>= 8; | ||
373 | else | ||
374 | bad &= 0xFF; | ||
375 | } else { | ||
376 | chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos, | ||
377 | page); | ||
378 | bad = chip->read_byte(mtd); | ||
379 | } | ||
380 | 373 | ||
381 | if (likely(chip->badblockbits == 8)) | 374 | if (likely(chip->badblockbits == 8)) |
382 | res = bad != 0xFF; | 375 | res = bad != 0xFF; |
383 | else | 376 | else |
384 | res = hweight8(bad) < chip->badblockbits; | 377 | res = hweight8(bad) < chip->badblockbits; |
385 | ofs += mtd->writesize; | 378 | if (res) |
386 | page = (int)(ofs >> chip->page_shift) & chip->pagemask; | 379 | return res; |
387 | i++; | 380 | } |
388 | } while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE)); | ||
389 | 381 | ||
390 | return res; | 382 | return 0; |
391 | } | 383 | } |
392 | 384 | ||
393 | /** | 385 | /** |