|
@@ -324,13 +324,58 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * nand_default_block_markbad - [DEFAULT] mark a block bad
|
|
|
+ * nand_default_block_markbad - [DEFAULT] mark a block bad via bad block marker
|
|
|
* @mtd: MTD device structure
|
|
|
* @ofs: offset from device start
|
|
|
*
|
|
|
* This is the default implementation, which can be overridden by a hardware
|
|
|
- * specific driver. We try operations in the following order, according to our
|
|
|
- * bbt_options (NAND_BBT_NO_OOB_BBM and NAND_BBT_USE_FLASH):
|
|
|
+ * specific driver. It provides the details for writing a bad block marker to a
|
|
|
+ * block.
|
|
|
+ */
|
|
|
+static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|
|
+{
|
|
|
+ struct nand_chip *chip = mtd->priv;
|
|
|
+ struct mtd_oob_ops ops;
|
|
|
+ uint8_t buf[2] = { 0, 0 };
|
|
|
+ int ret = 0, res, i = 0;
|
|
|
+
|
|
|
+ ops.datbuf = NULL;
|
|
|
+ ops.oobbuf = buf;
|
|
|
+ ops.ooboffs = chip->badblockpos;
|
|
|
+ if (chip->options & NAND_BUSWIDTH_16) {
|
|
|
+ ops.ooboffs &= ~0x01;
|
|
|
+ ops.len = ops.ooblen = 2;
|
|
|
+ } else {
|
|
|
+ ops.len = ops.ooblen = 1;
|
|
|
+ }
|
|
|
+ ops.mode = MTD_OPS_PLACE_OOB;
|
|
|
+
|
|
|
+ /* Write to first/last page(s) if necessary */
|
|
|
+ if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
|
|
|
+ ofs += mtd->erasesize - mtd->writesize;
|
|
|
+ do {
|
|
|
+ res = nand_do_write_oob(mtd, ofs, &ops);
|
|
|
+ if (!ret)
|
|
|
+ ret = res;
|
|
|
+
|
|
|
+ i++;
|
|
|
+ ofs += mtd->writesize;
|
|
|
+ } while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2);
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * nand_block_markbad_lowlevel - mark a block bad
|
|
|
+ * @mtd: MTD device structure
|
|
|
+ * @ofs: offset from device start
|
|
|
+ *
|
|
|
+ * This function performs the generic NAND bad block marking steps (i.e., bad
|
|
|
+ * block table(s) and/or marker(s)). We only allow the hardware driver to
|
|
|
+ * specify how to write bad block markers to OOB (chip->block_markbad).
|
|
|
+ *
|
|
|
+ * We try operations in the following order, according to our bbt_options
|
|
|
+ * (NAND_BBT_NO_OOB_BBM and NAND_BBT_USE_FLASH):
|
|
|
* (1) erase the affected block, to allow OOB marker to be written cleanly
|
|
|
* (2) update in-memory BBT
|
|
|
* (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)
|
|
|
* Note that we retain the first error encountered in (3) or (4), finish the
|
|
|
* procedures, and dump the error in the end.
|
|
|
*/
|
|
|
-static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|
|
+static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs)
|
|
|
{
|
|
|
struct nand_chip *chip = mtd->priv;
|
|
|
- uint8_t buf[2] = { 0, 0 };
|
|
|
- int block, res, ret = 0, i = 0;
|
|
|
+ int block, res, ret = 0;
|
|
|
int write_oob = !(chip->bbt_options & NAND_BBT_NO_OOB_BBM);
|
|
|
|
|
|
if (write_oob) {
|
|
@@ -364,34 +408,8 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|
|
|
|
|
/* Write bad block marker to OOB */
|
|
|
if (write_oob) {
|
|
|
- struct mtd_oob_ops ops;
|
|
|
- loff_t wr_ofs = ofs;
|
|
|
-
|
|
|
nand_get_device(mtd, FL_WRITING);
|
|
|
-
|
|
|
- ops.datbuf = NULL;
|
|
|
- ops.oobbuf = buf;
|
|
|
- ops.ooboffs = chip->badblockpos;
|
|
|
- if (chip->options & NAND_BUSWIDTH_16) {
|
|
|
- ops.ooboffs &= ~0x01;
|
|
|
- ops.len = ops.ooblen = 2;
|
|
|
- } else {
|
|
|
- ops.len = ops.ooblen = 1;
|
|
|
- }
|
|
|
- ops.mode = MTD_OPS_PLACE_OOB;
|
|
|
-
|
|
|
- /* Write to first/last page(s) if necessary */
|
|
|
- if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
|
|
|
- wr_ofs += mtd->erasesize - mtd->writesize;
|
|
|
- do {
|
|
|
- res = nand_do_write_oob(mtd, wr_ofs, &ops);
|
|
|
- if (!ret)
|
|
|
- ret = res;
|
|
|
-
|
|
|
- i++;
|
|
|
- wr_ofs += mtd->writesize;
|
|
|
- } while ((chip->bbt_options & NAND_BBT_SCAN2NDPAGE) && i < 2);
|
|
|
-
|
|
|
+ ret = chip->block_markbad(mtd, ofs);
|
|
|
nand_release_device(mtd);
|
|
|
}
|
|
|
|
|
@@ -2683,7 +2701,6 @@ static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
|
|
|
*/
|
|
|
static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|
|
{
|
|
|
- struct nand_chip *chip = mtd->priv;
|
|
|
int ret;
|
|
|
|
|
|
ret = nand_block_isbad(mtd, ofs);
|
|
@@ -2694,7 +2711,7 @@ static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- return chip->block_markbad(mtd, ofs);
|
|
|
+ return nand_block_markbad_lowlevel(mtd, ofs);
|
|
|
}
|
|
|
|
|
|
/**
|