@@ -1589,16 +1589,21 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
__func__, buf);
read_retry:
+ if (unlikely(ops->mode == MTD_OPS_RAW))
+ nand_setup_on_die_ecc_micron(mtd, 0);
+
chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
/*
* Now read the page into the buffer. Absent an error,
* the read methods return max bitflips per ecc step.
*/
- if (unlikely(ops->mode == MTD_OPS_RAW))
+ if (unlikely(ops->mode == MTD_OPS_RAW)) {
ret = chip->ecc.read_page_raw(mtd, chip, bufpoi,
oob_required,
page);
+ nand_setup_on_die_ecc_micron(mtd, 1);
+ }
else if (!aligned && NAND_HAS_SUBPAGE_READ(chip) &&
!oob)
ret = chip->ecc.read_subpage(mtd, chip,
@@ -1926,9 +1931,11 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
page = realpage & chip->pagemask;
while (1) {
- if (ops->mode == MTD_OPS_RAW)
+ if (ops->mode == MTD_OPS_RAW) {
+ nand_setup_on_die_ecc_micron(mtd, 0);
ret = chip->ecc.read_oob_raw(mtd, chip, page);
- else
+ nand_setup_on_die_ecc_micron(mtd, 1);
+ } else
ret = chip->ecc.read_oob(mtd, chip, page);
if (ret < 0)
@@ -2271,6 +2278,9 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
else
subpage = 0;
+ if (unlikely(raw))
+ nand_setup_on_die_ecc_micron(mtd, 0);
+
chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
if (unlikely(raw))
@@ -2283,7 +2293,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
status = chip->ecc.write_page(mtd, chip, buf, oob_required);
if (status < 0)
- return status;
+ goto out;
/*
* Cached progamming disabled for now. Not sure if it's worth the
@@ -2303,14 +2313,22 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
status = chip->errstat(mtd, chip, FL_WRITING, status,
page);
- if (status & NAND_STATUS_FAIL)
- return -EIO;
+ if (status & NAND_STATUS_FAIL) {
+ status = -EIO;
+ goto out;
+ }
} else {
chip->cmdfunc(mtd, NAND_CMD_CACHEDPROG, -1, -1);
status = chip->waitfunc(mtd, chip);
}
- return 0;
+ status = 0;
+
+out:
+ if (unlikely(raw))
+ nand_setup_on_die_ecc_micron(mtd, 1);
+
+ return status;
}
/**
@@ -2632,9 +2650,11 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
nand_fill_oob(mtd, ops->oobbuf, ops->ooblen, ops);
- if (ops->mode == MTD_OPS_RAW)
+ if (ops->mode == MTD_OPS_RAW) {
+ nand_setup_on_die_ecc_micron(mtd, 0);
status = chip->ecc.write_oob_raw(mtd, chip, page & chip->pagemask);
- else
+ nand_setup_on_die_ecc_micron(mtd, 1);
+ } else
status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
chip->select_chip(mtd, -1);
Implementing raw access for on-die ECC mode is a bit beautiless because we have to disable on-die ECC before sending the NAND read command and re-enable it again at all locations where raw access can happen. If the kernel was built without on-die ECC support or the current ECC mode is not on-die these operations are no-ops. Signed-off-by: Richard Weinberger <richard@nod.at> --- drivers/mtd/nand/nand_base.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-)