All of lore.kernel.org
 help / color / mirror / Atom feed
* [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.