aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/nand_base.c
diff options
context:
space:
mode:
authorBrian Norris <computersforpeace@gmail.com>2013-07-30 20:52:58 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2013-08-30 11:47:52 -0400
commit5a0edb251ae91c6f9b1f28dc165becd955666118 (patch)
tree2411a390a1c5350baaf152e431e579a2487de57a /drivers/mtd/nand/nand_base.c
parent39dbb02998d859f0fa12c5b495fe90681ba45ce2 (diff)
mtd: nand: refactor chip->block_markbad interface
The chip->block_markbad pointer should really only be responsible for writing a bad block marker for new bad blocks. It should not take care of BBT-related functionality, nor should it handle bookkeeping of bad block stats. This patch refactors the 3 users of the block_markbad interface (plus the default nand_base implementation) so that the common code is kept in nand_block_markbad_lowlevel(). It removes some inconsistencies between the various implementations and should allow for more centralized improvements in the future. Because gpmi-nand no longer needs the nand_update_bbt() function, let's stop exporting it as well. Signed-off-by: Brian Norris <computersforpeace@gmail.com> Acked-by: Huang Shijie <b32955@freescale.com> (for gpmi-nand parts) Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/nand/nand_base.c')
-rw-r--r--drivers/mtd/nand/nand_base.c87
1 files changed, 52 insertions, 35 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 158240d5649a..5a7467c33757 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -324,13 +324,58 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
324} 324}
325 325
326/** 326/**
327 * nand_default_block_markbad - [DEFAULT] mark a block bad 327 * nand_default_block_markbad - [DEFAULT] mark a block bad via bad block marker
328 * @mtd: MTD device structure 328 * @mtd: MTD device structure
329 * @ofs: offset from device start 329 * @ofs: offset from device start
330 * 330 *
331 * This is the default implementation, which can be overridden by a hardware 331 * This is the default implementation, which can be overridden by a hardware
332 * specific driver. We try operations in the following order, according to our 332 * specific driver. It provides the details for writing a bad block marker to a
333 * bbt_options (NAND_BBT_NO_OOB_BBM and NAND_BBT_USE_FLASH): 333 * block.
334 */
335static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
336{
337 struct nand_chip *chip = mtd->priv;
338 struct mtd_oob_ops ops;
339 uint8_t buf[2] = { 0, 0 };
340 int ret = 0, res, i = 0;
341
342 ops.datbuf = NULL;
343 ops.oobbuf = buf;
344 ops.ooboffs = chip->badblockpos;
345 if (chip->options & NAND_BUSWIDTH_16) {
346 ops.ooboffs &= ~0x01;
347 ops.len = ops.ooblen = 2;
348 } else {
349 ops.len = ops.ooblen = 1;
350 }
351 ops.mode = MTD_OPS_PLACE_OOB;
352
353 /* Write to first/last page(s) if necessary */
354 if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
355 ofs += mtd->erasesize - mtd->writesize;
356 do {
357 res = nand_do_write_oob(mtd, ofs, &ops);
358 if (!ret)
359 ret = res;
360
361 i++;
362 ofs += mtd->writesize;
363 } while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2);
364
365 return ret;
366}
367
368/**
369 * nand_block_markbad_lowlevel - mark a block bad
370 * @mtd: MTD device structure
371 * @ofs: offset from device start
372 *
373 * This function performs the generic NAND bad block marking steps (i.e., bad
374 * block table(s) and/or marker(s)). We only allow the hardware driver to
375 * specify how to write bad block markers to OOB (chip->block_markbad).
376 *
377 * We try operations in the following order, according to our bbt_options
378 * (NAND_BBT_NO_OOB_BBM and NAND_BBT_USE_FLASH):
334 * (1) erase the affected block, to allow OOB marker to be written cleanly 379 * (1) erase the affected block, to allow OOB marker to be written cleanly
335 * (2) update in-memory BBT 380 * (2) update in-memory BBT
336 * (3) write bad block marker to OOB area of affected block 381 * (3) write bad block marker to OOB area of affected block
@@ -338,11 +383,10 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
338 * Note that we retain the first error encountered in (3) or (4), finish the 383 * Note that we retain the first error encountered in (3) or (4), finish the
339 * procedures, and dump the error in the end. 384 * procedures, and dump the error in the end.
340*/ 385*/
341static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) 386static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
342{ 387{
343 struct nand_chip *chip = mtd->priv; 388 struct nand_chip *chip = mtd->priv;
344 uint8_t buf[2] = { 0, 0 }; 389 int block, res, ret = 0;
345 int block, res, ret = 0, i = 0;
346 int write_oob = !(chip->bbt_options & NAND_BBT_NO_OOB_BBM); 390 int write_oob = !(chip->bbt_options & NAND_BBT_NO_OOB_BBM);
347 391
348 if (write_oob) { 392 if (write_oob) {
@@ -364,34 +408,8 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
364 408
365 /* Write bad block marker to OOB */ 409 /* Write bad block marker to OOB */
366 if (write_oob) { 410 if (write_oob) {
367 struct mtd_oob_ops ops;
368 loff_t wr_ofs = ofs;
369
370 nand_get_device(mtd, FL_WRITING); 411 nand_get_device(mtd, FL_WRITING);
371 412 ret = chip->block_markbad(mtd, ofs);
372 ops.datbuf = NULL;
373 ops.oobbuf = buf;
374 ops.ooboffs = chip->badblockpos;
375 if (chip->options & NAND_BUSWIDTH_16) {
376 ops.ooboffs &= ~0x01;
377 ops.len = ops.ooblen = 2;
378 } else {
379 ops.len = ops.ooblen = 1;
380 }
381 ops.mode = MTD_OPS_PLACE_OOB;
382
383 /* Write to first/last page(s) if necessary */
384 if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
385 wr_ofs += mtd->erasesize - mtd->writesize;
386 do {
387 res = nand_do_write_oob(mtd, wr_ofs, &ops);
388 if (!ret)
389 ret = res;
390
391 i++;
392 wr_ofs += mtd->writesize;
393 } while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2);
394
395 nand_release_device(mtd); 413 nand_release_device(mtd);
396 } 414 }
397 415
@@ -2683,7 +2701,6 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
2683 */ 2701 */
2684static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs) 2702static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
2685{ 2703{
2686 struct nand_chip *chip = mtd->priv;
2687 int ret; 2704 int ret;
2688 2705
2689 ret = nand_block_isbad(mtd, ofs); 2706 ret = nand_block_isbad(mtd, ofs);
@@ -2694,7 +2711,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
2694 return ret; 2711 return ret;
2695 } 2712 }
2696 2713
2697 return chip->block_markbad(mtd, ofs); 2714 return nand_block_markbad_lowlevel(mtd, ofs);
2698} 2715}
2699 2716
2700/** 2717/**