* [PATCH v2 0/5] mtd: nand: add support for on-die ECC
@ 2017-04-29 9:06 Thomas Petazzoni
[not found] ` <1493456806-18898-1-git-send-email-thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
0 siblings, 1 reply; 7+ messages in thread
From: Thomas Petazzoni @ 2017-04-29 9:06 UTC (permalink / raw)
To: Boris Brezillon, Marek Vasut, Richard Weinberger, Cyrille Pitchen,
David Woodhouse, Brian Norris,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala
Cc: Thomas Petazzoni
Hello,
This patch series adds support for on-die ECC, i.e ECC performed by
the NAND chip itself, as opposed to having the ECC calculated by the
NAND controller or in software.
It is useful in situations where the NAND chip has an ECC requirement
that is not met by the ECC capabilities of the NAND controller.
Patch 1 adjusts the NAND generic DT binding to add "on-die" as an
nand-ecc-mode.
Patch 2 adds the core support for on-die ECC, which is really simple
and minimal: all the work is really done in the vendor-specific NAND
code.
Patch 3 and 4 adds the on-die ECC implementation for Micron NANDs.
Patch 5 allows the FSMC NAND driver to use on-die ECC.
This series was tested on a SPEAr600 platform, with a Micron
MT29F1G08ABADAWP NAND. The mtd_nandbiterrs.ko test is passing
successfully, which shows that the on-die ECC is correcting bitflips
as expected.
This series is based on the current nand-next branch, as it depends on
the rework from Boris of the vendor-specific NAND code.
Many thanks to Boris from providing lots of useful feedback and
discussion during the development of this patch series.
Changes since v1:
- Rebased on the latest nand/next branch.
- Reworked the mechanism to detect if the Micron NAND suppors on-die
ECC. We realized that the READ_ID command only indicates if on-die
ECC is currently enabled or not, not whether it is supported by the
NAND. After discussion with Bean Huo from Micron we came up with a
logic to determine if the NAND has on-die ECC support, which PATCH
4/5 implements.
Note that we intentionally only support cases that we could
test. Therefore, we error out if the NAND has an on-die ECC that
cannot be disabled, and we error out if the NAND uses a 8 bits per
512 bytes on-die ECC, since it requires a slightly different
handling than the 4 bits per 512 bytes on-die ECC our NAND is
using.
- Added Acked-by from Rob Herring on PATCH 1/5 (DT binding)
- Added Acked-by from Richard Weinberger on all patches, except PATCH
4/5 since it was significantly changed.
Best regards,
Thomas
Thomas Petazzoni (5):
dt-bindings: mtd: document new "on-die" nand-ecc-mode
mtd: nand: add core support for on-die ECC
mtd: nand: export nand_{read,write}_page_raw()
mtd: nand: add support for Micron on-die ECC
mtd: nand: fsmc_nand: handle on-die ECC case
Documentation/devicetree/bindings/mtd/nand.txt | 2 +-
drivers/mtd/nand/fsmc_nand.c | 3 +
drivers/mtd/nand/nand_base.c | 23 ++-
drivers/mtd/nand/nand_micron.c | 215 +++++++++++++++++++++++++
include/linux/mtd/nand.h | 11 ++
5 files changed, 249 insertions(+), 5 deletions(-)
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/5] dt-bindings: mtd: document new "on-die" nand-ecc-mode
[not found] ` <1493456806-18898-1-git-send-email-thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
@ 2017-04-29 9:06 ` Thomas Petazzoni
2017-04-29 9:06 ` [PATCH v2 2/5] mtd: nand: add core support for on-die ECC Thomas Petazzoni
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Thomas Petazzoni @ 2017-04-29 9:06 UTC (permalink / raw)
To: Boris Brezillon, Marek Vasut, Richard Weinberger, Cyrille Pitchen,
David Woodhouse, Brian Norris,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala
Cc: Thomas Petazzoni
A number of NAND chips support a feature called on-die ECC, where the
NAND chip itself is capable of doing error detection and correction. The
new "on-die" value for nand-ecc-mode indicates that we want this
functionality to be used.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Reviewed-by: Richard Weinberger <richard-/L3Ra7n9ekc@public.gmane.org>
---
Documentation/devicetree/bindings/mtd/nand.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/mtd/nand.txt b/Documentation/devicetree/bindings/mtd/nand.txt
index b056016..133f381 100644
--- a/Documentation/devicetree/bindings/mtd/nand.txt
+++ b/Documentation/devicetree/bindings/mtd/nand.txt
@@ -21,7 +21,7 @@ Optional NAND chip properties:
- nand-ecc-mode : String, operation mode of the NAND ecc mode.
Supported values are: "none", "soft", "hw", "hw_syndrome",
- "hw_oob_first".
+ "hw_oob_first", "on-die".
Deprecated values:
"soft_bch": use "soft" and nand-ecc-algo instead
- nand-ecc-algo: string, algorithm of NAND ECC.
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 2/5] mtd: nand: add core support for on-die ECC
[not found] ` <1493456806-18898-1-git-send-email-thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
2017-04-29 9:06 ` [PATCH v2 1/5] dt-bindings: mtd: document new "on-die" nand-ecc-mode Thomas Petazzoni
@ 2017-04-29 9:06 ` Thomas Petazzoni
2017-04-29 9:06 ` [PATCH v2 3/5] mtd: nand: export nand_{read,write}_page_raw() Thomas Petazzoni
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Thomas Petazzoni @ 2017-04-29 9:06 UTC (permalink / raw)
To: Boris Brezillon, Marek Vasut, Richard Weinberger, Cyrille Pitchen,
David Woodhouse, Brian Norris,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala
Cc: Thomas Petazzoni
A number of NAND flashes have a capability called "on-die ECC" where the
NAND chip itself is capable of detecting and correcting errors.
Linux already has support for using the ECC implementation of the NAND
controller, or a software based ECC implementation, but not for using
the ECC implementation of the NAND controller. However, such an
implementation is sometimes useful in situations where the NAND
controller provides ECC algorithms that are not strong enough for the
NAND chip used on the system. A typical case is a NAND chip that
requires a 4-bit ECC, while the NAND controller only provides a 1-bit
ECC algorithm.
This commit introduces the support for the NAND_ECC_ON_DIE ECC mode:
- Parsing of the "on-die" value for the "nand-ecc-mode" Device Tree
property
- Handling NAND_ECC_ON_DIE case in nand_scan_tail(). The idea is that
the vendor specific code for the NAND chip must implement
->read_page() and ->write_page(). It may optionally provide its own
->read_page_raw() and ->write_page_raw() as well. For OOB operation,
we assume the standard operations are good enough, but they can be
overridden by the vendor specific code if needed.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Reviewed-by: Richard Weinberger <richard-/L3Ra7n9ekc@public.gmane.org>
---
drivers/mtd/nand/nand_base.c | 13 +++++++++++++
include/linux/mtd/nand.h | 1 +
2 files changed, 14 insertions(+)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index ed49a1d..b639e88 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -4109,6 +4109,7 @@ static const char * const nand_ecc_modes[] = {
[NAND_ECC_HW] = "hw",
[NAND_ECC_HW_SYNDROME] = "hw_syndrome",
[NAND_ECC_HW_OOB_FIRST] = "hw_oob_first",
+ [NAND_ECC_ON_DIE] = "on-die",
};
static int of_get_nand_ecc_mode(struct device_node *np)
@@ -4649,6 +4650,18 @@ int nand_scan_tail(struct mtd_info *mtd)
}
break;
+ case NAND_ECC_ON_DIE:
+ if (!ecc->read_page || !ecc->write_page) {
+ WARN(1, "No ECC functions supplied; on-die ECC not possible\n");
+ ret = -EINVAL;
+ goto err_free;
+ }
+ if (!ecc->read_oob)
+ ecc->read_oob = nand_read_oob_std;
+ if (!ecc->write_oob)
+ ecc->write_oob = nand_write_oob_std;
+ break;
+
case NAND_ECC_NONE:
pr_warn("NAND_ECC_NONE selected by board driver. This is not recommended!\n");
ecc->read_page = nand_read_page_raw;
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 8f67b15..6035220 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -116,6 +116,7 @@ typedef enum {
NAND_ECC_HW,
NAND_ECC_HW_SYNDROME,
NAND_ECC_HW_OOB_FIRST,
+ NAND_ECC_ON_DIE,
} nand_ecc_modes_t;
enum nand_ecc_algo {
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 3/5] mtd: nand: export nand_{read,write}_page_raw()
[not found] ` <1493456806-18898-1-git-send-email-thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
2017-04-29 9:06 ` [PATCH v2 1/5] dt-bindings: mtd: document new "on-die" nand-ecc-mode Thomas Petazzoni
2017-04-29 9:06 ` [PATCH v2 2/5] mtd: nand: add core support for on-die ECC Thomas Petazzoni
@ 2017-04-29 9:06 ` Thomas Petazzoni
2017-04-29 9:06 ` [PATCH v2 4/5] mtd: nand: add support for Micron on-die ECC Thomas Petazzoni
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Thomas Petazzoni @ 2017-04-29 9:06 UTC (permalink / raw)
To: Boris Brezillon, Marek Vasut, Richard Weinberger, Cyrille Pitchen,
David Woodhouse, Brian Norris,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala
Cc: Thomas Petazzoni
The nand_read_page_raw() and nand_write_page_raw() functions might be
re-used by vendor-specific implementations of the read_page/write_page
functions. Instead of having vendor-specific code duplicate this code,
it is much better to export those functions and allow them to be
re-used.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Reviewed-by: Richard Weinberger <richard-/L3Ra7n9ekc@public.gmane.org>
---
drivers/mtd/nand/nand_base.c | 10 ++++++----
include/linux/mtd/nand.h | 8 ++++++++
2 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index b639e88..3282738 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1456,14 +1456,15 @@ EXPORT_SYMBOL(nand_check_erased_ecc_chunk);
*
* Not for syndrome calculating ECC controllers, which use a special oob layout.
*/
-static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page)
+int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf, int oob_required, int page)
{
chip->read_buf(mtd, buf, mtd->writesize);
if (oob_required)
chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
return 0;
}
+EXPORT_SYMBOL(nand_read_page_raw);
/**
* nand_read_page_raw_syndrome - [INTERN] read raw page data without ecc
@@ -2401,8 +2402,8 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
*
* Not for syndrome calculating ECC controllers, which use a special oob layout.
*/
-static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required, int page)
+int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf, int oob_required, int page)
{
chip->write_buf(mtd, buf, mtd->writesize);
if (oob_required)
@@ -2410,6 +2411,7 @@ static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
return 0;
}
+EXPORT_SYMBOL(nand_write_page_raw);
/**
* nand_write_page_raw_syndrome - [INTERN] raw page write function
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 6035220..7a01d2e 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -1259,6 +1259,14 @@ int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip, int page);
int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
int page);
+/* Default read_page_raw implementation */
+int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf, int oob_required, int page);
+
+/* Default write_page_raw implementation */
+int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf, int oob_required, int page);
+
/* Reset and initialize a NAND device */
int nand_reset(struct nand_chip *chip, int chipnr);
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 4/5] mtd: nand: add support for Micron on-die ECC
[not found] ` <1493456806-18898-1-git-send-email-thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
` (2 preceding siblings ...)
2017-04-29 9:06 ` [PATCH v2 3/5] mtd: nand: export nand_{read,write}_page_raw() Thomas Petazzoni
@ 2017-04-29 9:06 ` Thomas Petazzoni
2017-04-29 9:06 ` [PATCH v2 5/5] mtd: nand: fsmc_nand: handle on-die ECC case Thomas Petazzoni
2017-05-15 19:36 ` [PATCH v2 0/5] mtd: nand: add support for on-die ECC Boris Brezillon
5 siblings, 0 replies; 7+ messages in thread
From: Thomas Petazzoni @ 2017-04-29 9:06 UTC (permalink / raw)
To: Boris Brezillon, Marek Vasut, Richard Weinberger, Cyrille Pitchen,
David Woodhouse, Brian Norris,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala
Cc: Thomas Petazzoni
Now that the core NAND subsystem has support for on-die ECC, this commit
brings the necessary code to support on-die ECC on Micron NANDs.
In micron_nand_init(), we detect if the Micron NAND chip supports on-die
ECC mode, by checking a number of conditions:
- It must be an ONFI NAND
- It must be a SLC NAND
- Enabling *and* disabling on-die ECC must work
- The on-die ECC must be correcting 4 bits per 512 bytes of data. Some
Micron NAND chips have an on-die ECC able to correct 8 bits per 512
bytes of data, but they work slightly differently and therefore we
don't support them in this patch.
Then, if the on-die ECC cannot be disabled (some Micron NAND have on-die
ECC forcefully enabled), we bail out, as we don't support such
NANDs. Indeed, the implementation of raw_read()/raw_write() make the
assumption that on-die ECC can be disabled. Support for Micron NANDs
with on-die ECC forcefully enabled can easily be added, but in the
absence of such HW for testing, we preferred to simply bail out.
If the on-die ECC is supported, and requested in the Device Tree, then
it is indeed enabled, by using custom implementations of the
->read_page(), ->read_page_raw(), ->write_page() and ->write_page_raw()
operation to properly handle the on-die ECC.
In the non-raw functions, we need to enable the internal ECC engine
before issuing the NAND_CMD_READ0 or NAND_CMD_SEQIN commands, which is
why we set the NAND_ECC_CUSTOM_PAGE_ACCESS option at initialization
time (it asks the NAND core to let the NAND driver issue those
commands).
Signed-off-by: Thomas Petazzoni <thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
drivers/mtd/nand/nand_micron.c | 215 +++++++++++++++++++++++++++++++++++++++++
include/linux/mtd/nand.h | 2 +
2 files changed, 217 insertions(+)
diff --git a/drivers/mtd/nand/nand_micron.c b/drivers/mtd/nand/nand_micron.c
index 8770110..0987f32 100644
--- a/drivers/mtd/nand/nand_micron.c
+++ b/drivers/mtd/nand/nand_micron.c
@@ -17,6 +17,12 @@
#include <linux/mtd/nand.h>
+/*
+ * Special Micron status bit that indicates when the block has been
+ * corrected by on-die ECC and should be rewritten
+ */
+#define NAND_STATUS_WRITE_RECOMMENDED BIT(3)
+
struct nand_onfi_vendor_micron {
u8 two_plane_read;
u8 read_cache;
@@ -66,9 +72,191 @@ static int micron_nand_onfi_init(struct nand_chip *chip)
return 0;
}
+static int micron_nand_on_die_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ if (section >= 4)
+ return -ERANGE;
+
+ oobregion->offset = (section * 16) + 8;
+ oobregion->length = 8;
+
+ return 0;
+}
+
+static int micron_nand_on_die_ooblayout_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobregion)
+{
+ if (section >= 4)
+ return -ERANGE;
+
+ oobregion->offset = (section * 16) + 2;
+ oobregion->length = 6;
+
+ return 0;
+}
+
+static const struct mtd_ooblayout_ops micron_nand_on_die_ooblayout_ops = {
+ .ecc = micron_nand_on_die_ooblayout_ecc,
+ .free = micron_nand_on_die_ooblayout_free,
+};
+
+static int micron_nand_on_die_ecc_setup(struct nand_chip *chip, bool enable)
+{
+ u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = { 0, };
+
+ if (enable)
+ feature[0] |= ONFI_FEATURE_ON_DIE_ECC_EN;
+
+ return chip->onfi_set_features(nand_to_mtd(chip), chip,
+ ONFI_FEATURE_ON_DIE_ECC, feature);
+}
+
+static int
+micron_nand_read_page_on_die_ecc(struct mtd_info *mtd, struct nand_chip *chip,
+ uint8_t *buf, int oob_required,
+ int page)
+{
+ int status;
+ int max_bitflips = 0;
+
+ micron_nand_on_die_ecc_setup(chip, true);
+
+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+ chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
+ status = chip->read_byte(mtd);
+ if (status & NAND_STATUS_FAIL)
+ mtd->ecc_stats.failed++;
+ /*
+ * The internal ECC doesn't tell us the number of bitflips
+ * that have been corrected, but tells us if it recommends to
+ * rewrite the block. If it's the case, then we pretend we had
+ * a number of bitflips equal to the ECC strength, which will
+ * hint the NAND core to rewrite the block.
+ */
+ else if (status & NAND_STATUS_WRITE_RECOMMENDED)
+ max_bitflips = chip->ecc.strength;
+
+ chip->cmdfunc(mtd, NAND_CMD_READ0, -1, -1);
+
+ nand_read_page_raw(mtd, chip, buf, oob_required, page);
+
+ micron_nand_on_die_ecc_setup(chip, false);
+
+ return max_bitflips;
+}
+
+static int
+micron_nand_write_page_on_die_ecc(struct mtd_info *mtd, struct nand_chip *chip,
+ const uint8_t *buf, int oob_required,
+ int page)
+{
+ micron_nand_on_die_ecc_setup(chip, true);
+
+ chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+ nand_write_page_raw(mtd, chip, buf, oob_required, page);
+ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+ micron_nand_on_die_ecc_setup(chip, false);
+
+ return 0;
+}
+
+static int
+micron_nand_read_page_raw_on_die_ecc(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ uint8_t *buf, int oob_required,
+ int page)
+{
+ chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+ nand_read_page_raw(mtd, chip, buf, oob_required, page);
+
+ return 0;
+}
+
+static int
+micron_nand_write_page_raw_on_die_ecc(struct mtd_info *mtd,
+ struct nand_chip *chip,
+ const uint8_t *buf, int oob_required,
+ int page)
+{
+ chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+ nand_write_page_raw(mtd, chip, buf, oob_required, page);
+ chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+ return 0;
+}
+
+enum {
+ /* The NAND flash doesn't support on-die ECC */
+ MICRON_ON_DIE_UNSUPPORTED,
+
+ /*
+ * The NAND flash supports on-die ECC and it can be
+ * enabled/disabled by a set features command.
+ */
+ MICRON_ON_DIE_SUPPORTED,
+
+ /*
+ * The NAND flash supports on-die ECC, and it cannot be
+ * disabled.
+ */
+ MICRON_ON_DIE_MANDATORY,
+};
+
+/*
+ * Try to detect if the NAND support on-die ECC. To do this, we enable
+ * the feature, and read back if it has been enabled as expected. We
+ * also check if it can be disabled, because some Micron NANDs do not
+ * allow disabling the on-die ECC and we don't support such NANDs for
+ * now.
+ *
+ * This function also has the side effect of disabling on-die ECC if
+ * it had been left enabled by the firmware/bootloader.
+ */
+static int micron_supports_on_die_ecc(struct nand_chip *chip)
+{
+ u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = { 0, };
+ int ret;
+
+ if (chip->onfi_version == 0)
+ return MICRON_ON_DIE_UNSUPPORTED;
+
+ if (chip->bits_per_cell != 1)
+ return MICRON_ON_DIE_UNSUPPORTED;
+
+ ret = micron_nand_on_die_ecc_setup(chip, true);
+ if (ret)
+ return MICRON_ON_DIE_UNSUPPORTED;
+
+ chip->onfi_get_features(nand_to_mtd(chip), chip,
+ ONFI_FEATURE_ON_DIE_ECC, feature);
+ if ((feature[0] & ONFI_FEATURE_ON_DIE_ECC_EN) == 0)
+ return MICRON_ON_DIE_UNSUPPORTED;
+
+ ret = micron_nand_on_die_ecc_setup(chip, false);
+ if (ret)
+ return MICRON_ON_DIE_UNSUPPORTED;
+
+ chip->onfi_get_features(nand_to_mtd(chip), chip,
+ ONFI_FEATURE_ON_DIE_ECC, feature);
+ if (feature[0] & ONFI_FEATURE_ON_DIE_ECC_EN)
+ return MICRON_ON_DIE_MANDATORY;
+
+ /*
+ * Some Micron NANDs have an on-die ECC of 4/512, some other
+ * 8/512. We only support the former.
+ */
+ if (chip->onfi_params.ecc_bits != 4)
+ return MICRON_ON_DIE_UNSUPPORTED;
+
+ return MICRON_ON_DIE_SUPPORTED;
+}
+
static int micron_nand_init(struct nand_chip *chip)
{
struct mtd_info *mtd = nand_to_mtd(chip);
+ int ondie;
int ret;
ret = micron_nand_onfi_init(chip);
@@ -78,6 +266,33 @@ static int micron_nand_init(struct nand_chip *chip)
if (mtd->writesize == 2048)
chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+ ondie = micron_supports_on_die_ecc(chip);
+
+ if (ondie == MICRON_ON_DIE_MANDATORY) {
+ pr_err("On-die ECC forcefully enabled, not supported\n");
+ return -EINVAL;
+ }
+
+ if (chip->ecc.mode == NAND_ECC_ON_DIE) {
+ if (ondie == MICRON_ON_DIE_UNSUPPORTED) {
+ pr_err("On-die ECC selected but not supported\n");
+ return -EINVAL;
+ }
+
+ chip->ecc.options = NAND_ECC_CUSTOM_PAGE_ACCESS;
+ chip->ecc.bytes = 32;
+ chip->ecc.strength = 4;
+ chip->ecc.algo = NAND_ECC_BCH;
+ chip->ecc.read_page = micron_nand_read_page_on_die_ecc;
+ chip->ecc.write_page = micron_nand_write_page_on_die_ecc;
+ chip->ecc.read_page_raw =
+ micron_nand_read_page_raw_on_die_ecc;
+ chip->ecc.write_page_raw =
+ micron_nand_write_page_raw_on_die_ecc;
+
+ mtd_set_ooblayout(mtd, µn_nand_on_die_ooblayout_ops);
+ }
+
return 0;
}
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 7a01d2e..f019916 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -258,6 +258,8 @@ struct nand_chip;
/* Vendor-specific feature address (Micron) */
#define ONFI_FEATURE_ADDR_READ_RETRY 0x89
+#define ONFI_FEATURE_ON_DIE_ECC 0x90
+#define ONFI_FEATURE_ON_DIE_ECC_EN BIT(3)
/* ONFI subfeature parameters length */
#define ONFI_SUBFEATURE_PARAM_LEN 4
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH v2 5/5] mtd: nand: fsmc_nand: handle on-die ECC case
[not found] ` <1493456806-18898-1-git-send-email-thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
` (3 preceding siblings ...)
2017-04-29 9:06 ` [PATCH v2 4/5] mtd: nand: add support for Micron on-die ECC Thomas Petazzoni
@ 2017-04-29 9:06 ` Thomas Petazzoni
2017-05-15 19:36 ` [PATCH v2 0/5] mtd: nand: add support for on-die ECC Boris Brezillon
5 siblings, 0 replies; 7+ messages in thread
From: Thomas Petazzoni @ 2017-04-29 9:06 UTC (permalink / raw)
To: Boris Brezillon, Marek Vasut, Richard Weinberger, Cyrille Pitchen,
David Woodhouse, Brian Norris,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala
Cc: Thomas Petazzoni
This commit adjusts the fsmc_nand driver so that it accepts the
NAND_ECC_ON_DIE case. It simply does nothing in this case, since both
the ECC operations and OOB layout will be defined by the NAND chip code
rather than by the NAND controller code.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Reviewed-by: Richard Weinberger <richard-/L3Ra7n9ekc@public.gmane.org>
---
drivers/mtd/nand/fsmc_nand.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index cea50d2..5c058e8 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -986,6 +986,9 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
break;
}
+ case NAND_ECC_ON_DIE:
+ break;
+
default:
dev_err(&pdev->dev, "Unsupported ECC mode!\n");
goto err_probe;
--
2.7.4
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2 0/5] mtd: nand: add support for on-die ECC
[not found] ` <1493456806-18898-1-git-send-email-thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
` (4 preceding siblings ...)
2017-04-29 9:06 ` [PATCH v2 5/5] mtd: nand: fsmc_nand: handle on-die ECC case Thomas Petazzoni
@ 2017-05-15 19:36 ` Boris Brezillon
5 siblings, 0 replies; 7+ messages in thread
From: Boris Brezillon @ 2017-05-15 19:36 UTC (permalink / raw)
To: Thomas Petazzoni
Cc: Marek Vasut, Richard Weinberger, Cyrille Pitchen, David Woodhouse,
Brian Norris, linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring, Ian Campbell,
Pawel Moll, Mark Rutland, Kumar Gala
On Sat, 29 Apr 2017 11:06:41 +0200
Thomas Petazzoni <thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> Hello,
>
> This patch series adds support for on-die ECC, i.e ECC performed by
> the NAND chip itself, as opposed to having the ECC calculated by the
> NAND controller or in software.
>
> It is useful in situations where the NAND chip has an ECC requirement
> that is not met by the ECC capabilities of the NAND controller.
>
> Patch 1 adjusts the NAND generic DT binding to add "on-die" as an
> nand-ecc-mode.
>
> Patch 2 adds the core support for on-die ECC, which is really simple
> and minimal: all the work is really done in the vendor-specific NAND
> code.
>
> Patch 3 and 4 adds the on-die ECC implementation for Micron NANDs.
>
> Patch 5 allows the FSMC NAND driver to use on-die ECC.
>
> This series was tested on a SPEAr600 platform, with a Micron
> MT29F1G08ABADAWP NAND. The mtd_nandbiterrs.ko test is passing
> successfully, which shows that the on-die ECC is correcting bitflips
> as expected.
>
> This series is based on the current nand-next branch, as it depends on
> the rework from Boris of the vendor-specific NAND code.
>
> Many thanks to Boris from providing lots of useful feedback and
> discussion during the development of this patch series.
Applied to nand/next.
Thanks,
Boris
>
> Changes since v1:
>
> - Rebased on the latest nand/next branch.
>
> - Reworked the mechanism to detect if the Micron NAND suppors on-die
> ECC. We realized that the READ_ID command only indicates if on-die
> ECC is currently enabled or not, not whether it is supported by the
> NAND. After discussion with Bean Huo from Micron we came up with a
> logic to determine if the NAND has on-die ECC support, which PATCH
> 4/5 implements.
>
> Note that we intentionally only support cases that we could
> test. Therefore, we error out if the NAND has an on-die ECC that
> cannot be disabled, and we error out if the NAND uses a 8 bits per
> 512 bytes on-die ECC, since it requires a slightly different
> handling than the 4 bits per 512 bytes on-die ECC our NAND is
> using.
>
> - Added Acked-by from Rob Herring on PATCH 1/5 (DT binding)
>
> - Added Acked-by from Richard Weinberger on all patches, except PATCH
> 4/5 since it was significantly changed.
>
> Best regards,
>
> Thomas
>
>
> Thomas Petazzoni (5):
> dt-bindings: mtd: document new "on-die" nand-ecc-mode
> mtd: nand: add core support for on-die ECC
> mtd: nand: export nand_{read,write}_page_raw()
> mtd: nand: add support for Micron on-die ECC
> mtd: nand: fsmc_nand: handle on-die ECC case
>
> Documentation/devicetree/bindings/mtd/nand.txt | 2 +-
> drivers/mtd/nand/fsmc_nand.c | 3 +
> drivers/mtd/nand/nand_base.c | 23 ++-
> drivers/mtd/nand/nand_micron.c | 215 +++++++++++++++++++++++++
> include/linux/mtd/nand.h | 11 ++
> 5 files changed, 249 insertions(+), 5 deletions(-)
>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2017-05-15 19:36 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-04-29 9:06 [PATCH v2 0/5] mtd: nand: add support for on-die ECC Thomas Petazzoni
[not found] ` <1493456806-18898-1-git-send-email-thomas.petazzoni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
2017-04-29 9:06 ` [PATCH v2 1/5] dt-bindings: mtd: document new "on-die" nand-ecc-mode Thomas Petazzoni
2017-04-29 9:06 ` [PATCH v2 2/5] mtd: nand: add core support for on-die ECC Thomas Petazzoni
2017-04-29 9:06 ` [PATCH v2 3/5] mtd: nand: export nand_{read,write}_page_raw() Thomas Petazzoni
2017-04-29 9:06 ` [PATCH v2 4/5] mtd: nand: add support for Micron on-die ECC Thomas Petazzoni
2017-04-29 9:06 ` [PATCH v2 5/5] mtd: nand: fsmc_nand: handle on-die ECC case Thomas Petazzoni
2017-05-15 19:36 ` [PATCH v2 0/5] mtd: nand: add support for on-die ECC Boris Brezillon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).