Commit 785818fa authored by Thomas Petazzoni's avatar Thomas Petazzoni Committed by Boris Brezillon

mtd: nand: add core support for on-die ECC

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: default avatarThomas Petazzoni <thomas.petazzoni@free-electrons.com>
Reviewed-by: default avatarRichard Weinberger <richard@nod.at>
Signed-off-by: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
parent 85f94b5e
...@@ -4177,6 +4177,7 @@ static const char * const nand_ecc_modes[] = { ...@@ -4177,6 +4177,7 @@ static const char * const nand_ecc_modes[] = {
[NAND_ECC_HW] = "hw", [NAND_ECC_HW] = "hw",
[NAND_ECC_HW_SYNDROME] = "hw_syndrome", [NAND_ECC_HW_SYNDROME] = "hw_syndrome",
[NAND_ECC_HW_OOB_FIRST] = "hw_oob_first", [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) static int of_get_nand_ecc_mode(struct device_node *np)
...@@ -4717,6 +4718,18 @@ int nand_scan_tail(struct mtd_info *mtd) ...@@ -4717,6 +4718,18 @@ int nand_scan_tail(struct mtd_info *mtd)
} }
break; 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: case NAND_ECC_NONE:
pr_warn("NAND_ECC_NONE selected by board driver. This is not recommended!\n"); pr_warn("NAND_ECC_NONE selected by board driver. This is not recommended!\n");
ecc->read_page = nand_read_page_raw; ecc->read_page = nand_read_page_raw;
......
...@@ -116,6 +116,7 @@ typedef enum { ...@@ -116,6 +116,7 @@ typedef enum {
NAND_ECC_HW, NAND_ECC_HW,
NAND_ECC_HW_SYNDROME, NAND_ECC_HW_SYNDROME,
NAND_ECC_HW_OOB_FIRST, NAND_ECC_HW_OOB_FIRST,
NAND_ECC_ON_DIE,
} nand_ecc_modes_t; } nand_ecc_modes_t;
enum nand_ecc_algo { enum nand_ecc_algo {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment