* [PATCH v4 0/4] mtd: nand: omap: add support for BCH16_ECC
@ 2014-05-19 7:54 ` Pekon Gupta
0 siblings, 0 replies; 16+ messages in thread
From: Pekon Gupta @ 2014-05-19 7:54 UTC (permalink / raw)
To: Brian Norris, Tony Lindgren
Cc: linux-mtd, linux-omap, Ezequiel Garcia, Stefan Roese,
Felipe Balbi, Pekon Gupta
As this series touches both linux-mtd and linux-omap (GPMC) sub-systems but in
independent patch-sets, so looping both maintainers. 'Ack' from maintainers would
help in getting this series accepted for 3.16
*changes v3 -> v4*
[PATCH v4 1/4]: minor update in comments
[PATCH v4 2/4]: fixed coding style to keep it generic for big/little endianess
[PATCH v4 3/4]: no change
[PATCH v4 4/4]: use plain english (non linux stuff)
*changes v2 -> v3*
[PATCH v2 3/4] rebased to http://lists.infradead.org/pipermail/linux-mtd/2014-March/052655.html
- no change in other patches
*changes v1 -> v2*
rebased and cleaned on following versions of pending patches
(1) [PATCH v8 0/6] mtd: nand: omap: optimized chip->ecc.correct() for H/W ECC schemes
http://lists.infradead.org/pipermail/linux-mtd/2014-February/052092.html
(2) [PATCH v6 0/4] mtd: nand: omap: optimize chip->ecc.calculate() for H/W ECC schemes
http://lists.infradead.org/pipermail/linux-mtd/2014-February/052272.html
(3) [PATCH v5 0/4] mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes
http://lists.infradead.org/pipermail/linux-mtd/2014-March/052327.html
(4) [PATCH v6 0/4] mtd: devices: elm: add checks ELM H/W constrains, driver code cleanup
http://lists.infradead.org/pipermail/linux-mtd/2014-March/052455.html
Tested on Beaglebone-LT(white) NAND cape having NAND Device with
bus-width=16, block-size=256k, page-size=4k, oob-size=224
*original v1*
http://lists.infradead.org/pipermail/linux-mtd/2013-July/047562.html
With increase in NAND flash densities and shrinking of technology
NAND flash has become more suspectible to multiple bit-flips.
Thus stronger ECC schemes are required for detecting and correcting multiple
simultaneous bit-flips in same NAND page. But stronger ECC schemes have large
ECC syndrome which require more space in OOB/Spare.
This patch add support for BCH16 ecc-scheme on OMAP NAND driver:
(a) BCH16 ecc-scheme can correct 16 bit-flips per 512Bytes of data.
(b) BCH16 ecc-scheme generates 26-bytes of ECC syndrome / 512B.
Due to (b) this scheme can only be used with NAND devices which have enough
OOB to satisfy following equation:
OOBsize per page >= 26 * (page-size / 512)
Pekon Gupta (4):
mtd: nand: omap: add support for BCH16_ECC - GPMC driver updates
mtd: nand: omap: add support for BCH16_ECC - ELM driver updates
mtd: nand: omap: add support for BCH16_ECC - NAND driver updates
mtd: nand: omap: Documentation: How to select correct ECC scheme for
your device ?
.../devicetree/bindings/mtd/gpmc-nand.txt | 45 +++++++++++
arch/arm/mach-omap2/gpmc.c | 15 ++++
drivers/mtd/devices/elm.c | 36 +++++++++
drivers/mtd/nand/omap2.c | 94 ++++++++++++++++++++++
include/linux/platform_data/elm.h | 3 +-
include/linux/platform_data/mtd-nand-omap2.h | 5 ++
6 files changed, 197 insertions(+), 1 deletion(-)
--
1.8.5.1.163.gd7aced9
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v4 0/4] mtd: nand: omap: add support for BCH16_ECC
@ 2014-05-19 7:54 ` Pekon Gupta
0 siblings, 0 replies; 16+ messages in thread
From: Pekon Gupta @ 2014-05-19 7:54 UTC (permalink / raw)
To: Brian Norris, Tony Lindgren
Cc: linux-omap, Felipe Balbi, linux-mtd, Pekon Gupta,
Ezequiel Garcia, Stefan Roese
As this series touches both linux-mtd and linux-omap (GPMC) sub-systems but in
independent patch-sets, so looping both maintainers. 'Ack' from maintainers would
help in getting this series accepted for 3.16
*changes v3 -> v4*
[PATCH v4 1/4]: minor update in comments
[PATCH v4 2/4]: fixed coding style to keep it generic for big/little endianess
[PATCH v4 3/4]: no change
[PATCH v4 4/4]: use plain english (non linux stuff)
*changes v2 -> v3*
[PATCH v2 3/4] rebased to http://lists.infradead.org/pipermail/linux-mtd/2014-March/052655.html
- no change in other patches
*changes v1 -> v2*
rebased and cleaned on following versions of pending patches
(1) [PATCH v8 0/6] mtd: nand: omap: optimized chip->ecc.correct() for H/W ECC schemes
http://lists.infradead.org/pipermail/linux-mtd/2014-February/052092.html
(2) [PATCH v6 0/4] mtd: nand: omap: optimize chip->ecc.calculate() for H/W ECC schemes
http://lists.infradead.org/pipermail/linux-mtd/2014-February/052272.html
(3) [PATCH v5 0/4] mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes
http://lists.infradead.org/pipermail/linux-mtd/2014-March/052327.html
(4) [PATCH v6 0/4] mtd: devices: elm: add checks ELM H/W constrains, driver code cleanup
http://lists.infradead.org/pipermail/linux-mtd/2014-March/052455.html
Tested on Beaglebone-LT(white) NAND cape having NAND Device with
bus-width=16, block-size=256k, page-size=4k, oob-size=224
*original v1*
http://lists.infradead.org/pipermail/linux-mtd/2013-July/047562.html
With increase in NAND flash densities and shrinking of technology
NAND flash has become more suspectible to multiple bit-flips.
Thus stronger ECC schemes are required for detecting and correcting multiple
simultaneous bit-flips in same NAND page. But stronger ECC schemes have large
ECC syndrome which require more space in OOB/Spare.
This patch add support for BCH16 ecc-scheme on OMAP NAND driver:
(a) BCH16 ecc-scheme can correct 16 bit-flips per 512Bytes of data.
(b) BCH16 ecc-scheme generates 26-bytes of ECC syndrome / 512B.
Due to (b) this scheme can only be used with NAND devices which have enough
OOB to satisfy following equation:
OOBsize per page >= 26 * (page-size / 512)
Pekon Gupta (4):
mtd: nand: omap: add support for BCH16_ECC - GPMC driver updates
mtd: nand: omap: add support for BCH16_ECC - ELM driver updates
mtd: nand: omap: add support for BCH16_ECC - NAND driver updates
mtd: nand: omap: Documentation: How to select correct ECC scheme for
your device ?
.../devicetree/bindings/mtd/gpmc-nand.txt | 45 +++++++++++
arch/arm/mach-omap2/gpmc.c | 15 ++++
drivers/mtd/devices/elm.c | 36 +++++++++
drivers/mtd/nand/omap2.c | 94 ++++++++++++++++++++++
include/linux/platform_data/elm.h | 3 +-
include/linux/platform_data/mtd-nand-omap2.h | 5 ++
6 files changed, 197 insertions(+), 1 deletion(-)
--
1.8.5.1.163.gd7aced9
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v4 1/4] mtd: nand: omap: add support for BCH16_ECC - GPMC driver updates
2014-05-19 7:54 ` Pekon Gupta
@ 2014-05-19 7:54 ` Pekon Gupta
-1 siblings, 0 replies; 16+ messages in thread
From: Pekon Gupta @ 2014-05-19 7:54 UTC (permalink / raw)
To: Brian Norris, Tony Lindgren
Cc: linux-mtd, linux-omap, Ezequiel Garcia, Stefan Roese,
Felipe Balbi, Pekon Gupta
This patch add support for BCH16_ECC in GPMC (controller) driver:
- extends configuration space to include BCH16 registers
- extends parsing of DT binding for selecting BCH16 ecc-scheme
Signed-off-by: Pekon Gupta <pekon@ti.com>
---
arch/arm/mach-omap2/gpmc.c | 15 +++++++++++++++
include/linux/platform_data/mtd-nand-omap2.h | 5 +++++
2 files changed, 20 insertions(+)
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 9fe8c94..4fc4963 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -68,6 +68,9 @@
#define GPMC_ECC_BCH_RESULT_1 0x244 /* not available on OMAP2 */
#define GPMC_ECC_BCH_RESULT_2 0x248 /* not available on OMAP2 */
#define GPMC_ECC_BCH_RESULT_3 0x24c /* not available on OMAP2 */
+#define GPMC_ECC_BCH_RESULT_4 0x300 /* not available on OMAP2 */
+#define GPMC_ECC_BCH_RESULT_5 0x304 /* not available on OMAP2 */
+#define GPMC_ECC_BCH_RESULT_6 0x308 /* not available on OMAP2 */
/* GPMC ECC control settings */
#define GPMC_ECC_CTRL_ECCCLEAR 0x100
@@ -677,6 +680,12 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
GPMC_BCH_SIZE * i;
reg->gpmc_bch_result3[i] = gpmc_base + GPMC_ECC_BCH_RESULT_3 +
GPMC_BCH_SIZE * i;
+ reg->gpmc_bch_result4[i] = gpmc_base + GPMC_ECC_BCH_RESULT_4 +
+ i * GPMC_BCH_SIZE;
+ reg->gpmc_bch_result5[i] = gpmc_base + GPMC_ECC_BCH_RESULT_5 +
+ i * GPMC_BCH_SIZE;
+ reg->gpmc_bch_result6[i] = gpmc_base + GPMC_ECC_BCH_RESULT_6 +
+ i * GPMC_BCH_SIZE;
}
}
@@ -1412,6 +1421,12 @@ static int gpmc_probe_nand_child(struct platform_device *pdev,
else
gpmc_nand_data->ecc_opt =
OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
+ else if (!strcmp(s, "bch16"))
+ if (gpmc_nand_data->elm_of_node)
+ gpmc_nand_data->ecc_opt =
+ OMAP_ECC_BCH16_CODE_HW;
+ else
+ pr_err("%s: BCH16 requires ELM support\n", __func__);
else
pr_err("%s: ti,nand-ecc-opt invalid value\n", __func__);
diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h
index 3e9dd66..660c029 100644
--- a/include/linux/platform_data/mtd-nand-omap2.h
+++ b/include/linux/platform_data/mtd-nand-omap2.h
@@ -31,6 +31,8 @@ enum omap_ecc {
OMAP_ECC_BCH8_CODE_HW_DETECTION_SW,
/* 8-bit ECC calculation by GPMC, Error detection by ELM */
OMAP_ECC_BCH8_CODE_HW,
+ /* 16-bit ECC calculation by GPMC, Error detection by ELM */
+ OMAP_ECC_BCH16_CODE_HW,
};
struct gpmc_nand_regs {
@@ -50,6 +52,9 @@ struct gpmc_nand_regs {
void __iomem *gpmc_bch_result1[GPMC_BCH_NUM_REMAINDER];
void __iomem *gpmc_bch_result2[GPMC_BCH_NUM_REMAINDER];
void __iomem *gpmc_bch_result3[GPMC_BCH_NUM_REMAINDER];
+ void __iomem *gpmc_bch_result4[GPMC_BCH_NUM_REMAINDER];
+ void __iomem *gpmc_bch_result5[GPMC_BCH_NUM_REMAINDER];
+ void __iomem *gpmc_bch_result6[GPMC_BCH_NUM_REMAINDER];
};
struct omap_nand_platform_data {
--
1.8.5.1.163.gd7aced9
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v4 1/4] mtd: nand: omap: add support for BCH16_ECC - GPMC driver updates
@ 2014-05-19 7:54 ` Pekon Gupta
0 siblings, 0 replies; 16+ messages in thread
From: Pekon Gupta @ 2014-05-19 7:54 UTC (permalink / raw)
To: Brian Norris, Tony Lindgren
Cc: linux-omap, Felipe Balbi, linux-mtd, Pekon Gupta,
Ezequiel Garcia, Stefan Roese
This patch add support for BCH16_ECC in GPMC (controller) driver:
- extends configuration space to include BCH16 registers
- extends parsing of DT binding for selecting BCH16 ecc-scheme
Signed-off-by: Pekon Gupta <pekon@ti.com>
---
arch/arm/mach-omap2/gpmc.c | 15 +++++++++++++++
include/linux/platform_data/mtd-nand-omap2.h | 5 +++++
2 files changed, 20 insertions(+)
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 9fe8c94..4fc4963 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -68,6 +68,9 @@
#define GPMC_ECC_BCH_RESULT_1 0x244 /* not available on OMAP2 */
#define GPMC_ECC_BCH_RESULT_2 0x248 /* not available on OMAP2 */
#define GPMC_ECC_BCH_RESULT_3 0x24c /* not available on OMAP2 */
+#define GPMC_ECC_BCH_RESULT_4 0x300 /* not available on OMAP2 */
+#define GPMC_ECC_BCH_RESULT_5 0x304 /* not available on OMAP2 */
+#define GPMC_ECC_BCH_RESULT_6 0x308 /* not available on OMAP2 */
/* GPMC ECC control settings */
#define GPMC_ECC_CTRL_ECCCLEAR 0x100
@@ -677,6 +680,12 @@ void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
GPMC_BCH_SIZE * i;
reg->gpmc_bch_result3[i] = gpmc_base + GPMC_ECC_BCH_RESULT_3 +
GPMC_BCH_SIZE * i;
+ reg->gpmc_bch_result4[i] = gpmc_base + GPMC_ECC_BCH_RESULT_4 +
+ i * GPMC_BCH_SIZE;
+ reg->gpmc_bch_result5[i] = gpmc_base + GPMC_ECC_BCH_RESULT_5 +
+ i * GPMC_BCH_SIZE;
+ reg->gpmc_bch_result6[i] = gpmc_base + GPMC_ECC_BCH_RESULT_6 +
+ i * GPMC_BCH_SIZE;
}
}
@@ -1412,6 +1421,12 @@ static int gpmc_probe_nand_child(struct platform_device *pdev,
else
gpmc_nand_data->ecc_opt =
OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
+ else if (!strcmp(s, "bch16"))
+ if (gpmc_nand_data->elm_of_node)
+ gpmc_nand_data->ecc_opt =
+ OMAP_ECC_BCH16_CODE_HW;
+ else
+ pr_err("%s: BCH16 requires ELM support\n", __func__);
else
pr_err("%s: ti,nand-ecc-opt invalid value\n", __func__);
diff --git a/include/linux/platform_data/mtd-nand-omap2.h b/include/linux/platform_data/mtd-nand-omap2.h
index 3e9dd66..660c029 100644
--- a/include/linux/platform_data/mtd-nand-omap2.h
+++ b/include/linux/platform_data/mtd-nand-omap2.h
@@ -31,6 +31,8 @@ enum omap_ecc {
OMAP_ECC_BCH8_CODE_HW_DETECTION_SW,
/* 8-bit ECC calculation by GPMC, Error detection by ELM */
OMAP_ECC_BCH8_CODE_HW,
+ /* 16-bit ECC calculation by GPMC, Error detection by ELM */
+ OMAP_ECC_BCH16_CODE_HW,
};
struct gpmc_nand_regs {
@@ -50,6 +52,9 @@ struct gpmc_nand_regs {
void __iomem *gpmc_bch_result1[GPMC_BCH_NUM_REMAINDER];
void __iomem *gpmc_bch_result2[GPMC_BCH_NUM_REMAINDER];
void __iomem *gpmc_bch_result3[GPMC_BCH_NUM_REMAINDER];
+ void __iomem *gpmc_bch_result4[GPMC_BCH_NUM_REMAINDER];
+ void __iomem *gpmc_bch_result5[GPMC_BCH_NUM_REMAINDER];
+ void __iomem *gpmc_bch_result6[GPMC_BCH_NUM_REMAINDER];
};
struct omap_nand_platform_data {
--
1.8.5.1.163.gd7aced9
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v4 2/4] mtd: nand: omap: add support for BCH16_ECC - ELM driver updates
2014-05-19 7:54 ` Pekon Gupta
@ 2014-05-19 7:54 ` Pekon Gupta
-1 siblings, 0 replies; 16+ messages in thread
From: Pekon Gupta @ 2014-05-19 7:54 UTC (permalink / raw)
To: Brian Norris, Tony Lindgren
Cc: linux-mtd, linux-omap, Ezequiel Garcia, Stefan Roese,
Felipe Balbi, Pekon Gupta
ELM hardware engine is used to detect ECC errors for BCHx ecc-schemes
(like BCH4/BCH8/BCH16). This patch extends configuration of ELM registers
for adding support of BCH16_HW ecc-scheme.
Signed-off-by: Pekon Gupta <pekon@ti.com>
---
drivers/mtd/devices/elm.c | 36 ++++++++++++++++++++++++++++++++++++
include/linux/platform_data/elm.h | 3 ++-
2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/devices/elm.c b/drivers/mtd/devices/elm.c
index 1fd4a0f..8c55e0d 100644
--- a/drivers/mtd/devices/elm.c
+++ b/drivers/mtd/devices/elm.c
@@ -213,6 +213,28 @@ static void elm_load_syndrome(struct elm_info *info,
val = cpu_to_be32(*(u32 *) &ecc[0]) >> 12;
elm_write_reg(info, offset, val);
break;
+ case BCH16_ECC:
+ val = cpu_to_be32(*(u32 *) &ecc[22]);
+ elm_write_reg(info, offset, val);
+ offset += 4;
+ val = cpu_to_be32(*(u32 *) &ecc[18]);
+ elm_write_reg(info, offset, val);
+ offset += 4;
+ val = cpu_to_be32(*(u32 *) &ecc[14]);
+ elm_write_reg(info, offset, val);
+ offset += 4;
+ val = cpu_to_be32(*(u32 *) &ecc[10]);
+ elm_write_reg(info, offset, val);
+ offset += 4;
+ val = cpu_to_be32(*(u32 *) &ecc[6]);
+ elm_write_reg(info, offset, val);
+ offset += 4;
+ val = cpu_to_be32(*(u32 *) &ecc[2]);
+ elm_write_reg(info, offset, val);
+ offset += 4;
+ val = cpu_to_be32(*(u32 *) &ecc[0]) >> 16;
+ elm_write_reg(info, offset, val);
+ break;
default:
pr_err("invalid config bch_type\n");
}
@@ -435,6 +457,13 @@ static int elm_context_save(struct elm_info *info)
for (i = 0; i < ERROR_VECTOR_MAX; i++) {
offset = i * SYNDROME_FRAGMENT_REG_SIZE;
switch (bch_type) {
+ case BCH16_ECC:
+ regs->elm_syndrome_fragment_6[i] = elm_read_reg(info,
+ ELM_SYNDROME_FRAGMENT_6 + offset);
+ regs->elm_syndrome_fragment_5[i] = elm_read_reg(info,
+ ELM_SYNDROME_FRAGMENT_5 + offset);
+ regs->elm_syndrome_fragment_4[i] = elm_read_reg(info,
+ ELM_SYNDROME_FRAGMENT_4 + offset);
case BCH8_ECC:
regs->elm_syndrome_fragment_3[i] = elm_read_reg(info,
ELM_SYNDROME_FRAGMENT_3 + offset);
@@ -473,6 +502,13 @@ static int elm_context_restore(struct elm_info *info)
for (i = 0; i < ERROR_VECTOR_MAX; i++) {
offset = i * SYNDROME_FRAGMENT_REG_SIZE;
switch (bch_type) {
+ case BCH16_ECC:
+ elm_write_reg(info, ELM_SYNDROME_FRAGMENT_6 + offset,
+ regs->elm_syndrome_fragment_6[i]);
+ elm_write_reg(info, ELM_SYNDROME_FRAGMENT_5 + offset,
+ regs->elm_syndrome_fragment_5[i]);
+ elm_write_reg(info, ELM_SYNDROME_FRAGMENT_4 + offset,
+ regs->elm_syndrome_fragment_4[i]);
case BCH8_ECC:
elm_write_reg(info, ELM_SYNDROME_FRAGMENT_3 + offset,
regs->elm_syndrome_fragment_3[i]);
diff --git a/include/linux/platform_data/elm.h b/include/linux/platform_data/elm.h
index 4edb406..780d1e9 100644
--- a/include/linux/platform_data/elm.h
+++ b/include/linux/platform_data/elm.h
@@ -21,6 +21,7 @@
enum bch_ecc {
BCH4_ECC = 0,
BCH8_ECC,
+ BCH16_ECC,
};
/* ELM support 8 error syndrome process */
@@ -38,7 +39,7 @@ struct elm_errorvec {
bool error_reported;
bool error_uncorrectable;
int error_count;
- int error_loc[ERROR_VECTOR_MAX];
+ int error_loc[16];
};
void elm_decode_bch_error_page(struct device *dev, u8 *ecc_calc,
--
1.8.5.1.163.gd7aced9
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v4 2/4] mtd: nand: omap: add support for BCH16_ECC - ELM driver updates
@ 2014-05-19 7:54 ` Pekon Gupta
0 siblings, 0 replies; 16+ messages in thread
From: Pekon Gupta @ 2014-05-19 7:54 UTC (permalink / raw)
To: Brian Norris, Tony Lindgren
Cc: linux-omap, Felipe Balbi, linux-mtd, Pekon Gupta,
Ezequiel Garcia, Stefan Roese
ELM hardware engine is used to detect ECC errors for BCHx ecc-schemes
(like BCH4/BCH8/BCH16). This patch extends configuration of ELM registers
for adding support of BCH16_HW ecc-scheme.
Signed-off-by: Pekon Gupta <pekon@ti.com>
---
drivers/mtd/devices/elm.c | 36 ++++++++++++++++++++++++++++++++++++
include/linux/platform_data/elm.h | 3 ++-
2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/devices/elm.c b/drivers/mtd/devices/elm.c
index 1fd4a0f..8c55e0d 100644
--- a/drivers/mtd/devices/elm.c
+++ b/drivers/mtd/devices/elm.c
@@ -213,6 +213,28 @@ static void elm_load_syndrome(struct elm_info *info,
val = cpu_to_be32(*(u32 *) &ecc[0]) >> 12;
elm_write_reg(info, offset, val);
break;
+ case BCH16_ECC:
+ val = cpu_to_be32(*(u32 *) &ecc[22]);
+ elm_write_reg(info, offset, val);
+ offset += 4;
+ val = cpu_to_be32(*(u32 *) &ecc[18]);
+ elm_write_reg(info, offset, val);
+ offset += 4;
+ val = cpu_to_be32(*(u32 *) &ecc[14]);
+ elm_write_reg(info, offset, val);
+ offset += 4;
+ val = cpu_to_be32(*(u32 *) &ecc[10]);
+ elm_write_reg(info, offset, val);
+ offset += 4;
+ val = cpu_to_be32(*(u32 *) &ecc[6]);
+ elm_write_reg(info, offset, val);
+ offset += 4;
+ val = cpu_to_be32(*(u32 *) &ecc[2]);
+ elm_write_reg(info, offset, val);
+ offset += 4;
+ val = cpu_to_be32(*(u32 *) &ecc[0]) >> 16;
+ elm_write_reg(info, offset, val);
+ break;
default:
pr_err("invalid config bch_type\n");
}
@@ -435,6 +457,13 @@ static int elm_context_save(struct elm_info *info)
for (i = 0; i < ERROR_VECTOR_MAX; i++) {
offset = i * SYNDROME_FRAGMENT_REG_SIZE;
switch (bch_type) {
+ case BCH16_ECC:
+ regs->elm_syndrome_fragment_6[i] = elm_read_reg(info,
+ ELM_SYNDROME_FRAGMENT_6 + offset);
+ regs->elm_syndrome_fragment_5[i] = elm_read_reg(info,
+ ELM_SYNDROME_FRAGMENT_5 + offset);
+ regs->elm_syndrome_fragment_4[i] = elm_read_reg(info,
+ ELM_SYNDROME_FRAGMENT_4 + offset);
case BCH8_ECC:
regs->elm_syndrome_fragment_3[i] = elm_read_reg(info,
ELM_SYNDROME_FRAGMENT_3 + offset);
@@ -473,6 +502,13 @@ static int elm_context_restore(struct elm_info *info)
for (i = 0; i < ERROR_VECTOR_MAX; i++) {
offset = i * SYNDROME_FRAGMENT_REG_SIZE;
switch (bch_type) {
+ case BCH16_ECC:
+ elm_write_reg(info, ELM_SYNDROME_FRAGMENT_6 + offset,
+ regs->elm_syndrome_fragment_6[i]);
+ elm_write_reg(info, ELM_SYNDROME_FRAGMENT_5 + offset,
+ regs->elm_syndrome_fragment_5[i]);
+ elm_write_reg(info, ELM_SYNDROME_FRAGMENT_4 + offset,
+ regs->elm_syndrome_fragment_4[i]);
case BCH8_ECC:
elm_write_reg(info, ELM_SYNDROME_FRAGMENT_3 + offset,
regs->elm_syndrome_fragment_3[i]);
diff --git a/include/linux/platform_data/elm.h b/include/linux/platform_data/elm.h
index 4edb406..780d1e9 100644
--- a/include/linux/platform_data/elm.h
+++ b/include/linux/platform_data/elm.h
@@ -21,6 +21,7 @@
enum bch_ecc {
BCH4_ECC = 0,
BCH8_ECC,
+ BCH16_ECC,
};
/* ELM support 8 error syndrome process */
@@ -38,7 +39,7 @@ struct elm_errorvec {
bool error_reported;
bool error_uncorrectable;
int error_count;
- int error_loc[ERROR_VECTOR_MAX];
+ int error_loc[16];
};
void elm_decode_bch_error_page(struct device *dev, u8 *ecc_calc,
--
1.8.5.1.163.gd7aced9
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v4 3/4] mtd: nand: omap: add support for BCH16_ECC - NAND driver updates
2014-05-19 7:54 ` Pekon Gupta
@ 2014-05-19 7:54 ` Pekon Gupta
-1 siblings, 0 replies; 16+ messages in thread
From: Pekon Gupta @ 2014-05-19 7:54 UTC (permalink / raw)
To: Brian Norris, Tony Lindgren
Cc: linux-mtd, linux-omap, Ezequiel Garcia, Stefan Roese,
Felipe Balbi, Pekon Gupta
This patch add support for BCH16 ecc-scheme in OMAP NAND driver, by extending
following functions:
- omap_enable_hwecc (nand_chip->ecc.hwctl): configure GPMC controller
- omap_calculate_ecc_bch (nand_chip->ecc.calculate): fetch ECC signature from GPMC controller
- omap_elm_correct_data (nand_chip->ecc.correct): detect and correct ECC errors using ELM
(a) BCH16 ecc-scheme can detect and correct 16 bit-flips per 512Bytes of data.
(b) BCH16 ecc-scheme generates 26-bytes of ECC syndrome / 512B.
Due to (b) this scheme can only be used with NAND devices which have enough
OOB to satisfy the relation: "OOBsize per page >= 26 * (page-size / 512)"
Signed-off-by: Pekon Gupta <pekon@ti.com>
---
drivers/mtd/nand/omap2.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 94 insertions(+)
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 0a68508..e0a6c82 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -137,6 +137,10 @@
#define BADBLOCK_MARKER_LENGTH 2
#ifdef CONFIG_MTD_NAND_OMAP_BCH
+static u_char bch16_vector[] = {0xf5, 0x24, 0x1c, 0xd0, 0x61, 0xb3, 0xf1, 0x55,
+ 0x2e, 0x2c, 0x86, 0xa3, 0xed, 0x36, 0x1b, 0x78,
+ 0x48, 0x76, 0xa9, 0x3b, 0x97, 0xd1, 0x7a, 0x93,
+ 0x07, 0x0e};
static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc,
0xac, 0x6b, 0xff, 0x99, 0x7b};
static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10};
@@ -1114,6 +1118,19 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode)
ecc_size1 = BCH_ECC_SIZE1;
}
break;
+ case OMAP_ECC_BCH16_CODE_HW:
+ bch_type = 0x2;
+ nsectors = chip->ecc.steps;
+ if (mode == NAND_ECC_READ) {
+ wr_mode = 0x01;
+ ecc_size0 = 52; /* ECC bits in nibbles per sector */
+ ecc_size1 = 0; /* non-ECC bits in nibbles per sector */
+ } else {
+ wr_mode = 0x01;
+ ecc_size0 = 0; /* extra bits in nibbles per sector */
+ ecc_size1 = 52; /* OOB bits in nibbles per sector */
+ }
+ break;
default:
return;
}
@@ -1162,6 +1179,7 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
struct gpmc_nand_regs *gpmc_regs = &info->reg;
u8 *ecc_code;
unsigned long nsectors, bch_val1, bch_val2, bch_val3, bch_val4;
+ u32 val;
int i;
nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
@@ -1201,6 +1219,41 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
*ecc_code++ = ((bch_val1 >> 4) & 0xFF);
*ecc_code++ = ((bch_val1 & 0xF) << 4);
break;
+ case OMAP_ECC_BCH16_CODE_HW:
+ val = readl(gpmc_regs->gpmc_bch_result6[i]);
+ ecc_code[0] = ((val >> 8) & 0xFF);
+ ecc_code[1] = ((val >> 0) & 0xFF);
+ val = readl(gpmc_regs->gpmc_bch_result5[i]);
+ ecc_code[2] = ((val >> 24) & 0xFF);
+ ecc_code[3] = ((val >> 16) & 0xFF);
+ ecc_code[4] = ((val >> 8) & 0xFF);
+ ecc_code[5] = ((val >> 0) & 0xFF);
+ val = readl(gpmc_regs->gpmc_bch_result4[i]);
+ ecc_code[6] = ((val >> 24) & 0xFF);
+ ecc_code[7] = ((val >> 16) & 0xFF);
+ ecc_code[8] = ((val >> 8) & 0xFF);
+ ecc_code[9] = ((val >> 0) & 0xFF);
+ val = readl(gpmc_regs->gpmc_bch_result3[i]);
+ ecc_code[10] = ((val >> 24) & 0xFF);
+ ecc_code[11] = ((val >> 16) & 0xFF);
+ ecc_code[12] = ((val >> 8) & 0xFF);
+ ecc_code[13] = ((val >> 0) & 0xFF);
+ val = readl(gpmc_regs->gpmc_bch_result2[i]);
+ ecc_code[14] = ((val >> 24) & 0xFF);
+ ecc_code[15] = ((val >> 16) & 0xFF);
+ ecc_code[16] = ((val >> 8) & 0xFF);
+ ecc_code[17] = ((val >> 0) & 0xFF);
+ val = readl(gpmc_regs->gpmc_bch_result1[i]);
+ ecc_code[18] = ((val >> 24) & 0xFF);
+ ecc_code[19] = ((val >> 16) & 0xFF);
+ ecc_code[20] = ((val >> 8) & 0xFF);
+ ecc_code[21] = ((val >> 0) & 0xFF);
+ val = readl(gpmc_regs->gpmc_bch_result0[i]);
+ ecc_code[22] = ((val >> 24) & 0xFF);
+ ecc_code[23] = ((val >> 16) & 0xFF);
+ ecc_code[24] = ((val >> 8) & 0xFF);
+ ecc_code[25] = ((val >> 0) & 0xFF);
+ break;
default:
return -EINVAL;
}
@@ -1227,6 +1280,8 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
/* Set 14th ECC byte as 0x0 for ROM compatibility */
ecc_calc[eccbytes - 1] = 0x0;
break;
+ case OMAP_ECC_BCH16_CODE_HW:
+ break;
default:
return -EINVAL;
}
@@ -1318,6 +1373,10 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
actual_eccbytes = ecc->bytes - 1;
erased_ecc_vec = bch8_vector;
break;
+ case OMAP_ECC_BCH16_CODE_HW:
+ actual_eccbytes = ecc->bytes;
+ erased_ecc_vec = bch16_vector;
+ break;
default:
pr_err("invalid driver configuration\n");
return -EINVAL;
@@ -1401,6 +1460,7 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
BCH4_BIT_PAD;
break;
case OMAP_ECC_BCH8_CODE_HW:
+ case OMAP_ECC_BCH16_CODE_HW:
pos = err_vec[i].error_loc[j];
break;
default:
@@ -1912,6 +1972,40 @@ static int omap_nand_probe(struct platform_device *pdev)
goto return_error;
#endif
+ case OMAP_ECC_BCH16_CODE_HW:
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
+ pr_info("using OMAP_ECC_BCH16_CODE_HW ECC scheme\n");
+ nand_chip->ecc.mode = NAND_ECC_HW;
+ nand_chip->ecc.size = 512;
+ nand_chip->ecc.bytes = 26;
+ nand_chip->ecc.strength = 16;
+ nand_chip->ecc.hwctl = omap_enable_hwecc_bch;
+ nand_chip->ecc.correct = omap_elm_correct_data;
+ nand_chip->ecc.calculate = omap_calculate_ecc_bch;
+ nand_chip->ecc.read_page = omap_read_page_bch;
+ nand_chip->ecc.write_page = omap_write_page_bch;
+ /* This ECC scheme requires ELM H/W block */
+ err = is_elm_present(info, pdata->elm_of_node, BCH16_ECC);
+ if (err < 0) {
+ pr_err("ELM is required for this ECC scheme\n");
+ goto return_error;
+ }
+ /* define ECC layout */
+ ecclayout->eccbytes = nand_chip->ecc.bytes *
+ (mtd->writesize /
+ nand_chip->ecc.size);
+ oob_index = BADBLOCK_MARKER_LENGTH;
+ for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+ ecclayout->eccpos[i] = oob_index;
+ /* reserved marker already included in ecclayout->eccbytes */
+ ecclayout->oobfree->offset =
+ ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
+ break;
+#else
+ pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n");
+ err = -EINVAL;
+ goto return_error;
+#endif
default:
pr_err("nand: error: invalid or unsupported ECC scheme\n");
err = -EINVAL;
--
1.8.5.1.163.gd7aced9
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v4 3/4] mtd: nand: omap: add support for BCH16_ECC - NAND driver updates
@ 2014-05-19 7:54 ` Pekon Gupta
0 siblings, 0 replies; 16+ messages in thread
From: Pekon Gupta @ 2014-05-19 7:54 UTC (permalink / raw)
To: Brian Norris, Tony Lindgren
Cc: linux-omap, Felipe Balbi, linux-mtd, Pekon Gupta,
Ezequiel Garcia, Stefan Roese
This patch add support for BCH16 ecc-scheme in OMAP NAND driver, by extending
following functions:
- omap_enable_hwecc (nand_chip->ecc.hwctl): configure GPMC controller
- omap_calculate_ecc_bch (nand_chip->ecc.calculate): fetch ECC signature from GPMC controller
- omap_elm_correct_data (nand_chip->ecc.correct): detect and correct ECC errors using ELM
(a) BCH16 ecc-scheme can detect and correct 16 bit-flips per 512Bytes of data.
(b) BCH16 ecc-scheme generates 26-bytes of ECC syndrome / 512B.
Due to (b) this scheme can only be used with NAND devices which have enough
OOB to satisfy the relation: "OOBsize per page >= 26 * (page-size / 512)"
Signed-off-by: Pekon Gupta <pekon@ti.com>
---
drivers/mtd/nand/omap2.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 94 insertions(+)
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 0a68508..e0a6c82 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -137,6 +137,10 @@
#define BADBLOCK_MARKER_LENGTH 2
#ifdef CONFIG_MTD_NAND_OMAP_BCH
+static u_char bch16_vector[] = {0xf5, 0x24, 0x1c, 0xd0, 0x61, 0xb3, 0xf1, 0x55,
+ 0x2e, 0x2c, 0x86, 0xa3, 0xed, 0x36, 0x1b, 0x78,
+ 0x48, 0x76, 0xa9, 0x3b, 0x97, 0xd1, 0x7a, 0x93,
+ 0x07, 0x0e};
static u_char bch8_vector[] = {0xf3, 0xdb, 0x14, 0x16, 0x8b, 0xd2, 0xbe, 0xcc,
0xac, 0x6b, 0xff, 0x99, 0x7b};
static u_char bch4_vector[] = {0x00, 0x6b, 0x31, 0xdd, 0x41, 0xbc, 0x10};
@@ -1114,6 +1118,19 @@ static void __maybe_unused omap_enable_hwecc_bch(struct mtd_info *mtd, int mode)
ecc_size1 = BCH_ECC_SIZE1;
}
break;
+ case OMAP_ECC_BCH16_CODE_HW:
+ bch_type = 0x2;
+ nsectors = chip->ecc.steps;
+ if (mode == NAND_ECC_READ) {
+ wr_mode = 0x01;
+ ecc_size0 = 52; /* ECC bits in nibbles per sector */
+ ecc_size1 = 0; /* non-ECC bits in nibbles per sector */
+ } else {
+ wr_mode = 0x01;
+ ecc_size0 = 0; /* extra bits in nibbles per sector */
+ ecc_size1 = 52; /* OOB bits in nibbles per sector */
+ }
+ break;
default:
return;
}
@@ -1162,6 +1179,7 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
struct gpmc_nand_regs *gpmc_regs = &info->reg;
u8 *ecc_code;
unsigned long nsectors, bch_val1, bch_val2, bch_val3, bch_val4;
+ u32 val;
int i;
nsectors = ((readl(info->reg.gpmc_ecc_config) >> 4) & 0x7) + 1;
@@ -1201,6 +1219,41 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
*ecc_code++ = ((bch_val1 >> 4) & 0xFF);
*ecc_code++ = ((bch_val1 & 0xF) << 4);
break;
+ case OMAP_ECC_BCH16_CODE_HW:
+ val = readl(gpmc_regs->gpmc_bch_result6[i]);
+ ecc_code[0] = ((val >> 8) & 0xFF);
+ ecc_code[1] = ((val >> 0) & 0xFF);
+ val = readl(gpmc_regs->gpmc_bch_result5[i]);
+ ecc_code[2] = ((val >> 24) & 0xFF);
+ ecc_code[3] = ((val >> 16) & 0xFF);
+ ecc_code[4] = ((val >> 8) & 0xFF);
+ ecc_code[5] = ((val >> 0) & 0xFF);
+ val = readl(gpmc_regs->gpmc_bch_result4[i]);
+ ecc_code[6] = ((val >> 24) & 0xFF);
+ ecc_code[7] = ((val >> 16) & 0xFF);
+ ecc_code[8] = ((val >> 8) & 0xFF);
+ ecc_code[9] = ((val >> 0) & 0xFF);
+ val = readl(gpmc_regs->gpmc_bch_result3[i]);
+ ecc_code[10] = ((val >> 24) & 0xFF);
+ ecc_code[11] = ((val >> 16) & 0xFF);
+ ecc_code[12] = ((val >> 8) & 0xFF);
+ ecc_code[13] = ((val >> 0) & 0xFF);
+ val = readl(gpmc_regs->gpmc_bch_result2[i]);
+ ecc_code[14] = ((val >> 24) & 0xFF);
+ ecc_code[15] = ((val >> 16) & 0xFF);
+ ecc_code[16] = ((val >> 8) & 0xFF);
+ ecc_code[17] = ((val >> 0) & 0xFF);
+ val = readl(gpmc_regs->gpmc_bch_result1[i]);
+ ecc_code[18] = ((val >> 24) & 0xFF);
+ ecc_code[19] = ((val >> 16) & 0xFF);
+ ecc_code[20] = ((val >> 8) & 0xFF);
+ ecc_code[21] = ((val >> 0) & 0xFF);
+ val = readl(gpmc_regs->gpmc_bch_result0[i]);
+ ecc_code[22] = ((val >> 24) & 0xFF);
+ ecc_code[23] = ((val >> 16) & 0xFF);
+ ecc_code[24] = ((val >> 8) & 0xFF);
+ ecc_code[25] = ((val >> 0) & 0xFF);
+ break;
default:
return -EINVAL;
}
@@ -1227,6 +1280,8 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
/* Set 14th ECC byte as 0x0 for ROM compatibility */
ecc_calc[eccbytes - 1] = 0x0;
break;
+ case OMAP_ECC_BCH16_CODE_HW:
+ break;
default:
return -EINVAL;
}
@@ -1318,6 +1373,10 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
actual_eccbytes = ecc->bytes - 1;
erased_ecc_vec = bch8_vector;
break;
+ case OMAP_ECC_BCH16_CODE_HW:
+ actual_eccbytes = ecc->bytes;
+ erased_ecc_vec = bch16_vector;
+ break;
default:
pr_err("invalid driver configuration\n");
return -EINVAL;
@@ -1401,6 +1460,7 @@ static int omap_elm_correct_data(struct mtd_info *mtd, u_char *data,
BCH4_BIT_PAD;
break;
case OMAP_ECC_BCH8_CODE_HW:
+ case OMAP_ECC_BCH16_CODE_HW:
pos = err_vec[i].error_loc[j];
break;
default:
@@ -1912,6 +1972,40 @@ static int omap_nand_probe(struct platform_device *pdev)
goto return_error;
#endif
+ case OMAP_ECC_BCH16_CODE_HW:
+#ifdef CONFIG_MTD_NAND_OMAP_BCH
+ pr_info("using OMAP_ECC_BCH16_CODE_HW ECC scheme\n");
+ nand_chip->ecc.mode = NAND_ECC_HW;
+ nand_chip->ecc.size = 512;
+ nand_chip->ecc.bytes = 26;
+ nand_chip->ecc.strength = 16;
+ nand_chip->ecc.hwctl = omap_enable_hwecc_bch;
+ nand_chip->ecc.correct = omap_elm_correct_data;
+ nand_chip->ecc.calculate = omap_calculate_ecc_bch;
+ nand_chip->ecc.read_page = omap_read_page_bch;
+ nand_chip->ecc.write_page = omap_write_page_bch;
+ /* This ECC scheme requires ELM H/W block */
+ err = is_elm_present(info, pdata->elm_of_node, BCH16_ECC);
+ if (err < 0) {
+ pr_err("ELM is required for this ECC scheme\n");
+ goto return_error;
+ }
+ /* define ECC layout */
+ ecclayout->eccbytes = nand_chip->ecc.bytes *
+ (mtd->writesize /
+ nand_chip->ecc.size);
+ oob_index = BADBLOCK_MARKER_LENGTH;
+ for (i = 0; i < ecclayout->eccbytes; i++, oob_index++)
+ ecclayout->eccpos[i] = oob_index;
+ /* reserved marker already included in ecclayout->eccbytes */
+ ecclayout->oobfree->offset =
+ ecclayout->eccpos[ecclayout->eccbytes - 1] + 1;
+ break;
+#else
+ pr_err("nand: error: CONFIG_MTD_NAND_OMAP_BCH not enabled\n");
+ err = -EINVAL;
+ goto return_error;
+#endif
default:
pr_err("nand: error: invalid or unsupported ECC scheme\n");
err = -EINVAL;
--
1.8.5.1.163.gd7aced9
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v4 4/4] mtd: nand: omap: Documentation: How to select correct ECC scheme for your device ?
2014-05-19 7:54 ` Pekon Gupta
@ 2014-05-19 7:54 ` Pekon Gupta
-1 siblings, 0 replies; 16+ messages in thread
From: Pekon Gupta @ 2014-05-19 7:54 UTC (permalink / raw)
To: Brian Norris, Tony Lindgren
Cc: linux-mtd, linux-omap, Ezequiel Garcia, Stefan Roese,
Felipe Balbi, Pekon Gupta, devicetree
- Adds DT binding property for BCH16 ECC scheme
- Adds describes on factors which determine choice of ECC scheme for particular device
CC: devicetree@vger.kernel.org
Signed-off-by: Pekon Gupta <pekon@ti.com>
---
.../devicetree/bindings/mtd/gpmc-nand.txt | 45 ++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
index 5e1f31b..eb81435 100644
--- a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
@@ -28,6 +28,8 @@ Optional properties:
"ham1" 1-bit Hamming ecc code
"bch4" 4-bit BCH ecc code
"bch8" 8-bit BCH ecc code
+ "bch16" 16-bit BCH ECC code
+ Refer below "How to select correct ECC scheme for your device ?"
- ti,nand-xfer-type: A string setting the data transfer type. One of:
@@ -90,3 +92,46 @@ Example for an AM33xx board:
};
};
+How to select correct ECC scheme for your device ?
+--------------------------------------------------
+Higher ECC scheme usually means better protection against bit-flips and
+increased system lifetime. However, selection of ECC scheme is dependent
+on various other factors also like;
+
+(1) support of built in hardware engines.
+ Some legacy OMAP SoC do not have ELM harware engine, so those SoC cannot
+ support ecc-schemes with hardware error-correction (BCHx_HW). However
+ such SoC can use ecc-schemes with software library for error-correction
+ (BCHx_HW_DETECTION_SW). The error correction capability with software
+ library remains equivalent to their hardware counter-part, but there is
+ slight CPU penalty when too many bit-flips are detected during reads.
+
+(2) Device parameters like OOBSIZE.
+ Other factor which governs the selection of ecc-scheme is oob-size.
+ Higher ECC schemes require more OOB/Spare area to store ECC syndrome,
+ so the device should have enough free bytes available its OOB/Spare
+ area to accomodate ECC for entire page. In general following expression
+ helps in determining if given device can accomodate ECC syndrome:
+ "2 + (PAGESIZE / 512) * ECC_BYTES" >= OOBSIZE"
+ where
+ OOBSIZE number of bytes in OOB/spare area
+ PAGESIZE number of bytes in main-area of device page
+ ECC_BYTES number of ECC bytes generated to protect
+ 512 bytes of data, which is:
+ '3' for HAM1_xx ecc schemes
+ '7' for BCH4_xx ecc schemes
+ '14' for BCH8_xx ecc schemes
+ '26' for BCH16_xx ecc schemes
+
+ Example(a): For a device with PAGESIZE = 2048 and OOBSIZE = 64 and
+ trying to use BCH16 (ECC_BYTES=26) ecc-scheme.
+ Number of ECC bytes per page = (2 + (2048 / 512) * 26) = 106 B
+ which is greater than capacity of NAND device (OOBSIZE=64)
+ Hence, BCH16 cannot be supported on given device. But it can
+ probably use lower ecc-schemes like BCH8.
+
+ Example(b): For a device with PAGESIZE = 2048 and OOBSIZE = 128 and
+ trying to use BCH16 (ECC_BYTES=26) ecc-scheme.
+ Number of ECC bytes per page = (2 + (2048 / 512) * 26) = 106 B
+ which can be accomodate in the OOB/Spare area of this device
+ (OOBSIZE=128). So this device can use BCH16 ecc-scheme.
--
1.8.5.1.163.gd7aced9
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v4 4/4] mtd: nand: omap: Documentation: How to select correct ECC scheme for your device ?
@ 2014-05-19 7:54 ` Pekon Gupta
0 siblings, 0 replies; 16+ messages in thread
From: Pekon Gupta @ 2014-05-19 7:54 UTC (permalink / raw)
To: Brian Norris, Tony Lindgren
Cc: devicetree, linux-omap, Felipe Balbi, linux-mtd, Pekon Gupta,
Ezequiel Garcia, Stefan Roese
- Adds DT binding property for BCH16 ECC scheme
- Adds describes on factors which determine choice of ECC scheme for particular device
CC: devicetree@vger.kernel.org
Signed-off-by: Pekon Gupta <pekon@ti.com>
---
.../devicetree/bindings/mtd/gpmc-nand.txt | 45 ++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
index 5e1f31b..eb81435 100644
--- a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
@@ -28,6 +28,8 @@ Optional properties:
"ham1" 1-bit Hamming ecc code
"bch4" 4-bit BCH ecc code
"bch8" 8-bit BCH ecc code
+ "bch16" 16-bit BCH ECC code
+ Refer below "How to select correct ECC scheme for your device ?"
- ti,nand-xfer-type: A string setting the data transfer type. One of:
@@ -90,3 +92,46 @@ Example for an AM33xx board:
};
};
+How to select correct ECC scheme for your device ?
+--------------------------------------------------
+Higher ECC scheme usually means better protection against bit-flips and
+increased system lifetime. However, selection of ECC scheme is dependent
+on various other factors also like;
+
+(1) support of built in hardware engines.
+ Some legacy OMAP SoC do not have ELM harware engine, so those SoC cannot
+ support ecc-schemes with hardware error-correction (BCHx_HW). However
+ such SoC can use ecc-schemes with software library for error-correction
+ (BCHx_HW_DETECTION_SW). The error correction capability with software
+ library remains equivalent to their hardware counter-part, but there is
+ slight CPU penalty when too many bit-flips are detected during reads.
+
+(2) Device parameters like OOBSIZE.
+ Other factor which governs the selection of ecc-scheme is oob-size.
+ Higher ECC schemes require more OOB/Spare area to store ECC syndrome,
+ so the device should have enough free bytes available its OOB/Spare
+ area to accomodate ECC for entire page. In general following expression
+ helps in determining if given device can accomodate ECC syndrome:
+ "2 + (PAGESIZE / 512) * ECC_BYTES" >= OOBSIZE"
+ where
+ OOBSIZE number of bytes in OOB/spare area
+ PAGESIZE number of bytes in main-area of device page
+ ECC_BYTES number of ECC bytes generated to protect
+ 512 bytes of data, which is:
+ '3' for HAM1_xx ecc schemes
+ '7' for BCH4_xx ecc schemes
+ '14' for BCH8_xx ecc schemes
+ '26' for BCH16_xx ecc schemes
+
+ Example(a): For a device with PAGESIZE = 2048 and OOBSIZE = 64 and
+ trying to use BCH16 (ECC_BYTES=26) ecc-scheme.
+ Number of ECC bytes per page = (2 + (2048 / 512) * 26) = 106 B
+ which is greater than capacity of NAND device (OOBSIZE=64)
+ Hence, BCH16 cannot be supported on given device. But it can
+ probably use lower ecc-schemes like BCH8.
+
+ Example(b): For a device with PAGESIZE = 2048 and OOBSIZE = 128 and
+ trying to use BCH16 (ECC_BYTES=26) ecc-scheme.
+ Number of ECC bytes per page = (2 + (2048 / 512) * 26) = 106 B
+ which can be accomodate in the OOB/Spare area of this device
+ (OOBSIZE=128). So this device can use BCH16 ecc-scheme.
--
1.8.5.1.163.gd7aced9
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v4 1/4] mtd: nand: omap: add support for BCH16_ECC - GPMC driver updates
2014-05-19 7:54 ` Pekon Gupta
@ 2014-05-19 22:35 ` Tony Lindgren
-1 siblings, 0 replies; 16+ messages in thread
From: Tony Lindgren @ 2014-05-19 22:35 UTC (permalink / raw)
To: Pekon Gupta
Cc: Brian Norris, linux-mtd, linux-omap, Ezequiel Garcia,
Stefan Roese, Felipe Balbi
* Pekon Gupta <pekon@ti.com> [140519 00:55]:
> This patch add support for BCH16_ECC in GPMC (controller) driver:
> - extends configuration space to include BCH16 registers
> - extends parsing of DT binding for selecting BCH16 ecc-scheme
>
> Signed-off-by: Pekon Gupta <pekon@ti.com>
This patch seems OK to merge via the MTD tree, so for the
arch/arm/*omap* changes:
Acked-by: Tony Lindgren <tony@atomide.com>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 1/4] mtd: nand: omap: add support for BCH16_ECC - GPMC driver updates
@ 2014-05-19 22:35 ` Tony Lindgren
0 siblings, 0 replies; 16+ messages in thread
From: Tony Lindgren @ 2014-05-19 22:35 UTC (permalink / raw)
To: Pekon Gupta
Cc: linux-omap, Brian Norris, Felipe Balbi, linux-mtd,
Ezequiel Garcia, Stefan Roese
* Pekon Gupta <pekon@ti.com> [140519 00:55]:
> This patch add support for BCH16_ECC in GPMC (controller) driver:
> - extends configuration space to include BCH16 registers
> - extends parsing of DT binding for selecting BCH16 ecc-scheme
>
> Signed-off-by: Pekon Gupta <pekon@ti.com>
This patch seems OK to merge via the MTD tree, so for the
arch/arm/*omap* changes:
Acked-by: Tony Lindgren <tony@atomide.com>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 0/4] mtd: nand: omap: add support for BCH16_ECC
2014-05-19 7:54 ` Pekon Gupta
@ 2014-05-21 1:05 ` Brian Norris
-1 siblings, 0 replies; 16+ messages in thread
From: Brian Norris @ 2014-05-21 1:05 UTC (permalink / raw)
To: Pekon Gupta
Cc: Tony Lindgren, linux-mtd, linux-omap, Ezequiel Garcia,
Stefan Roese, Felipe Balbi
On Mon, May 19, 2014 at 01:24:38PM +0530, Pekon Gupta wrote:
> As this series touches both linux-mtd and linux-omap (GPMC) sub-systems but in
> independent patch-sets, so looping both maintainers. 'Ack' from maintainers would
> help in getting this series accepted for 3.16
>
> *changes v3 -> v4*
> [PATCH v4 1/4]: minor update in comments
> [PATCH v4 2/4]: fixed coding style to keep it generic for big/little endianess
> [PATCH v4 3/4]: no change
> [PATCH v4 4/4]: use plain english (non linux stuff)
Pushed all 4 to l2-mtd.git. Thanks!
I have one comment for patch 3, but it's not a blocker.
Brian
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 0/4] mtd: nand: omap: add support for BCH16_ECC
@ 2014-05-21 1:05 ` Brian Norris
0 siblings, 0 replies; 16+ messages in thread
From: Brian Norris @ 2014-05-21 1:05 UTC (permalink / raw)
To: Pekon Gupta
Cc: Stefan Roese, Tony Lindgren, Felipe Balbi, linux-mtd,
Ezequiel Garcia, linux-omap
On Mon, May 19, 2014 at 01:24:38PM +0530, Pekon Gupta wrote:
> As this series touches both linux-mtd and linux-omap (GPMC) sub-systems but in
> independent patch-sets, so looping both maintainers. 'Ack' from maintainers would
> help in getting this series accepted for 3.16
>
> *changes v3 -> v4*
> [PATCH v4 1/4]: minor update in comments
> [PATCH v4 2/4]: fixed coding style to keep it generic for big/little endianess
> [PATCH v4 3/4]: no change
> [PATCH v4 4/4]: use plain english (non linux stuff)
Pushed all 4 to l2-mtd.git. Thanks!
I have one comment for patch 3, but it's not a blocker.
Brian
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 3/4] mtd: nand: omap: add support for BCH16_ECC - NAND driver updates
2014-05-19 7:54 ` Pekon Gupta
@ 2014-05-21 1:36 ` Brian Norris
-1 siblings, 0 replies; 16+ messages in thread
From: Brian Norris @ 2014-05-21 1:36 UTC (permalink / raw)
To: Pekon Gupta
Cc: Tony Lindgren, linux-mtd, linux-omap, Ezequiel Garcia,
Stefan Roese, Felipe Balbi
On Mon, May 19, 2014 at 01:24:41PM +0530, Pekon Gupta wrote:
> --- a/drivers/mtd/nand/omap2.c
> +++ b/drivers/mtd/nand/omap2.c
> @@ -1201,6 +1219,41 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
> *ecc_code++ = ((bch_val1 >> 4) & 0xFF);
> *ecc_code++ = ((bch_val1 & 0xF) << 4);
> break;
> + case OMAP_ECC_BCH16_CODE_HW:
> + val = readl(gpmc_regs->gpmc_bch_result6[i]);
For all of these 'gpmc_bch_resultX' fields, couldn't you make this into
a 2-D array? So to access BCH result 6 at sector i, it would be:
val = readl(gpmc_regs->gpmc_bch_result[6][i];
This could help you to rewrite some of this stuff as loops, instead of
giant blocks of copy-paste-modify.
> + ecc_code[0] = ((val >> 8) & 0xFF);
> + ecc_code[1] = ((val >> 0) & 0xFF);
> + val = readl(gpmc_regs->gpmc_bch_result5[i]);
> + ecc_code[2] = ((val >> 24) & 0xFF);
> + ecc_code[3] = ((val >> 16) & 0xFF);
> + ecc_code[4] = ((val >> 8) & 0xFF);
> + ecc_code[5] = ((val >> 0) & 0xFF);
A lot of this code can be rewritten to use the endian swapping macros, I
expect. Something like this looks equivalent:
*((uint32_t *)&ecc_code[2]) = cpu_to_be32(val);
You could probably fix the types up to make this look a little nicer.
> + val = readl(gpmc_regs->gpmc_bch_result4[i]);
> + ecc_code[6] = ((val >> 24) & 0xFF);
> + ecc_code[7] = ((val >> 16) & 0xFF);
> + ecc_code[8] = ((val >> 8) & 0xFF);
> + ecc_code[9] = ((val >> 0) & 0xFF);
> + val = readl(gpmc_regs->gpmc_bch_result3[i]);
> + ecc_code[10] = ((val >> 24) & 0xFF);
> + ecc_code[11] = ((val >> 16) & 0xFF);
> + ecc_code[12] = ((val >> 8) & 0xFF);
> + ecc_code[13] = ((val >> 0) & 0xFF);
> + val = readl(gpmc_regs->gpmc_bch_result2[i]);
> + ecc_code[14] = ((val >> 24) & 0xFF);
> + ecc_code[15] = ((val >> 16) & 0xFF);
> + ecc_code[16] = ((val >> 8) & 0xFF);
> + ecc_code[17] = ((val >> 0) & 0xFF);
> + val = readl(gpmc_regs->gpmc_bch_result1[i]);
> + ecc_code[18] = ((val >> 24) & 0xFF);
> + ecc_code[19] = ((val >> 16) & 0xFF);
> + ecc_code[20] = ((val >> 8) & 0xFF);
> + ecc_code[21] = ((val >> 0) & 0xFF);
> + val = readl(gpmc_regs->gpmc_bch_result0[i]);
> + ecc_code[22] = ((val >> 24) & 0xFF);
> + ecc_code[23] = ((val >> 16) & 0xFF);
> + ecc_code[24] = ((val >> 8) & 0xFF);
> + ecc_code[25] = ((val >> 0) & 0xFF);
> + break;
> default:
> return -EINVAL;
> }
Brian
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v4 3/4] mtd: nand: omap: add support for BCH16_ECC - NAND driver updates
@ 2014-05-21 1:36 ` Brian Norris
0 siblings, 0 replies; 16+ messages in thread
From: Brian Norris @ 2014-05-21 1:36 UTC (permalink / raw)
To: Pekon Gupta
Cc: Stefan Roese, Tony Lindgren, Felipe Balbi, linux-mtd,
Ezequiel Garcia, linux-omap
On Mon, May 19, 2014 at 01:24:41PM +0530, Pekon Gupta wrote:
> --- a/drivers/mtd/nand/omap2.c
> +++ b/drivers/mtd/nand/omap2.c
> @@ -1201,6 +1219,41 @@ static int __maybe_unused omap_calculate_ecc_bch(struct mtd_info *mtd,
> *ecc_code++ = ((bch_val1 >> 4) & 0xFF);
> *ecc_code++ = ((bch_val1 & 0xF) << 4);
> break;
> + case OMAP_ECC_BCH16_CODE_HW:
> + val = readl(gpmc_regs->gpmc_bch_result6[i]);
For all of these 'gpmc_bch_resultX' fields, couldn't you make this into
a 2-D array? So to access BCH result 6 at sector i, it would be:
val = readl(gpmc_regs->gpmc_bch_result[6][i];
This could help you to rewrite some of this stuff as loops, instead of
giant blocks of copy-paste-modify.
> + ecc_code[0] = ((val >> 8) & 0xFF);
> + ecc_code[1] = ((val >> 0) & 0xFF);
> + val = readl(gpmc_regs->gpmc_bch_result5[i]);
> + ecc_code[2] = ((val >> 24) & 0xFF);
> + ecc_code[3] = ((val >> 16) & 0xFF);
> + ecc_code[4] = ((val >> 8) & 0xFF);
> + ecc_code[5] = ((val >> 0) & 0xFF);
A lot of this code can be rewritten to use the endian swapping macros, I
expect. Something like this looks equivalent:
*((uint32_t *)&ecc_code[2]) = cpu_to_be32(val);
You could probably fix the types up to make this look a little nicer.
> + val = readl(gpmc_regs->gpmc_bch_result4[i]);
> + ecc_code[6] = ((val >> 24) & 0xFF);
> + ecc_code[7] = ((val >> 16) & 0xFF);
> + ecc_code[8] = ((val >> 8) & 0xFF);
> + ecc_code[9] = ((val >> 0) & 0xFF);
> + val = readl(gpmc_regs->gpmc_bch_result3[i]);
> + ecc_code[10] = ((val >> 24) & 0xFF);
> + ecc_code[11] = ((val >> 16) & 0xFF);
> + ecc_code[12] = ((val >> 8) & 0xFF);
> + ecc_code[13] = ((val >> 0) & 0xFF);
> + val = readl(gpmc_regs->gpmc_bch_result2[i]);
> + ecc_code[14] = ((val >> 24) & 0xFF);
> + ecc_code[15] = ((val >> 16) & 0xFF);
> + ecc_code[16] = ((val >> 8) & 0xFF);
> + ecc_code[17] = ((val >> 0) & 0xFF);
> + val = readl(gpmc_regs->gpmc_bch_result1[i]);
> + ecc_code[18] = ((val >> 24) & 0xFF);
> + ecc_code[19] = ((val >> 16) & 0xFF);
> + ecc_code[20] = ((val >> 8) & 0xFF);
> + ecc_code[21] = ((val >> 0) & 0xFF);
> + val = readl(gpmc_regs->gpmc_bch_result0[i]);
> + ecc_code[22] = ((val >> 24) & 0xFF);
> + ecc_code[23] = ((val >> 16) & 0xFF);
> + ecc_code[24] = ((val >> 8) & 0xFF);
> + ecc_code[25] = ((val >> 0) & 0xFF);
> + break;
> default:
> return -EINVAL;
> }
Brian
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2014-05-21 1:36 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-19 7:54 [PATCH v4 0/4] mtd: nand: omap: add support for BCH16_ECC Pekon Gupta
2014-05-19 7:54 ` Pekon Gupta
2014-05-19 7:54 ` [PATCH v4 1/4] mtd: nand: omap: add support for BCH16_ECC - GPMC driver updates Pekon Gupta
2014-05-19 7:54 ` Pekon Gupta
2014-05-19 22:35 ` Tony Lindgren
2014-05-19 22:35 ` Tony Lindgren
2014-05-19 7:54 ` [PATCH v4 2/4] mtd: nand: omap: add support for BCH16_ECC - ELM " Pekon Gupta
2014-05-19 7:54 ` Pekon Gupta
2014-05-19 7:54 ` [PATCH v4 3/4] mtd: nand: omap: add support for BCH16_ECC - NAND " Pekon Gupta
2014-05-19 7:54 ` Pekon Gupta
2014-05-21 1:36 ` Brian Norris
2014-05-21 1:36 ` Brian Norris
2014-05-19 7:54 ` [PATCH v4 4/4] mtd: nand: omap: Documentation: How to select correct ECC scheme for your device ? Pekon Gupta
2014-05-19 7:54 ` Pekon Gupta
2014-05-21 1:05 ` [PATCH v4 0/4] mtd: nand: omap: add support for BCH16_ECC Brian Norris
2014-05-21 1:05 ` Brian Norris
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.