[PATCH 2/3] mtd: nand: Add support for raw access when using on-die ECC

Richard Weinberger
2015-03-25T14:03:14Z

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(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 92e7ed7..b42f556 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -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);
--
2.3.4