linux-mtd.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/4]  mtd: nand: omap: add support for BCH16_ECC
@ 2014-03-24 11:20 Pekon Gupta
  2014-03-24 11:20 ` [PATCH v3 1/4] mtd: nand: omap: add support for BCH16_ECC - GPMC driver updates Pekon Gupta
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Pekon Gupta @ 2014-03-24 11:20 UTC (permalink / raw)
  To: Brian Norris
  Cc: Stefan Roese, linux-mtd, Felipe Balbi, Ezequiel Garcia, Pekon Gupta

*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          | 39 +++++++++
 arch/arm/mach-omap2/gpmc.c                         | 15 ++++
 drivers/mtd/devices/elm.c                          | 42 ++++++++++
 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] 8+ messages in thread

* [PATCH v3 1/4] mtd: nand: omap: add support for BCH16_ECC - GPMC driver updates
  2014-03-24 11:20 [PATCH v3 0/4] mtd: nand: omap: add support for BCH16_ECC Pekon Gupta
@ 2014-03-24 11:20 ` Pekon Gupta
  2014-03-24 11:20 ` [PATCH v3 2/4] mtd: nand: omap: add support for BCH16_ECC - ELM " Pekon Gupta
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Pekon Gupta @ 2014-03-24 11:20 UTC (permalink / raw)
  To: Brian Norris
  Cc: Stefan Roese, linux-mtd, Felipe Balbi, Ezequiel Garcia, Pekon Gupta

This patch add support for BCH16_ECC in GPMC (controller) driver:
 - extend configuration space to include BCH16 registers
 - extend 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 ab43755..9b27773 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
@@ -666,6 +669,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;
 	}
 }
 
@@ -1401,6 +1410,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..c2172e8 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] 8+ messages in thread

* [PATCH v3 2/4] mtd: nand: omap: add support for BCH16_ECC - ELM driver updates
  2014-03-24 11:20 [PATCH v3 0/4] mtd: nand: omap: add support for BCH16_ECC Pekon Gupta
  2014-03-24 11:20 ` [PATCH v3 1/4] mtd: nand: omap: add support for BCH16_ECC - GPMC driver updates Pekon Gupta
@ 2014-03-24 11:20 ` Pekon Gupta
  2014-03-24 11:20 ` [PATCH v3 3/4] mtd: nand: omap: add support for BCH16_ECC - NAND " Pekon Gupta
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Pekon Gupta @ 2014-03-24 11:20 UTC (permalink / raw)
  To: Brian Norris
  Cc: Stefan Roese, linux-mtd, Felipe Balbi, Ezequiel Garcia, 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 loading of BCH16 ECC syndrome.

Signed-off-by: Pekon Gupta <pekon@ti.com>
---
 drivers/mtd/devices/elm.c         | 42 +++++++++++++++++++++++++++++++++++++++
 include/linux/platform_data/elm.h |  3 ++-
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/devices/elm.c b/drivers/mtd/devices/elm.c
index 1fd4a0f..b4b02a1 100644
--- a/drivers/mtd/devices/elm.c
+++ b/drivers/mtd/devices/elm.c
@@ -213,6 +213,34 @@ 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 =	ecc[25] << 0  | ecc[24] <<  8 |
+					ecc[23] << 16 | ecc[22] << 24;
+				elm_write_reg(info, offset, val);
+				offset += 4;
+				val =	ecc[21] <<  0 | ecc[20] <<  8 |
+					ecc[19] << 16 | ecc[18] << 24;
+				elm_write_reg(info, offset, val);
+				offset += 4;
+				val =	ecc[17] <<  0 | ecc[16] <<  8 |
+					ecc[15] << 16 | ecc[14] << 24;
+				elm_write_reg(info, offset, val);
+				offset += 4;
+				val =	ecc[13] <<  0 | ecc[12] <<  8 |
+					ecc[11] << 16 | ecc[10] << 24;
+				elm_write_reg(info, offset, val);
+				offset += 4;
+				val =	ecc[9]  <<  0 | ecc[8]  <<  8 |
+					ecc[7]  << 16 | ecc[6]  << 24;
+				elm_write_reg(info, offset, val);
+				offset += 4;
+				val =	ecc[5]  <<  0 | ecc[4]  <<  8 |
+					ecc[3]  << 16 | ecc[2]  << 24;
+				elm_write_reg(info, offset, val);
+				offset += 4;
+				val =	ecc[1]  <<  0 | ecc[0]  <<  8;
+				elm_write_reg(info, offset, val);
+				break;
 			default:
 				pr_err("invalid config bch_type\n");
 			}
@@ -435,6 +463,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 +508,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..ac2f266 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] 8+ messages in thread

* [PATCH v3 3/4] mtd: nand: omap: add support for BCH16_ECC - NAND driver updates
  2014-03-24 11:20 [PATCH v3 0/4] mtd: nand: omap: add support for BCH16_ECC Pekon Gupta
  2014-03-24 11:20 ` [PATCH v3 1/4] mtd: nand: omap: add support for BCH16_ECC - GPMC driver updates Pekon Gupta
  2014-03-24 11:20 ` [PATCH v3 2/4] mtd: nand: omap: add support for BCH16_ECC - ELM " Pekon Gupta
@ 2014-03-24 11:20 ` Pekon Gupta
  2014-03-24 11:20 ` [PATCH v3 4/4] mtd: nand: omap: Documentation: How to select correct ECC scheme for your device ? Pekon Gupta
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Pekon Gupta @ 2014-03-24 11:20 UTC (permalink / raw)
  To: Brian Norris
  Cc: Stefan Roese, linux-mtd, Felipe Balbi, Ezequiel Garcia, 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 d161c9b..c359af0 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};
@@ -1115,6 +1119,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;
 	}
@@ -1163,6 +1180,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;
@@ -1202,6 +1220,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;
 		}
@@ -1228,6 +1281,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;
 		}
@@ -1319,6 +1374,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;
@@ -1402,6 +1461,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:
@@ -1929,6 +1989,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] 8+ messages in thread

* [PATCH v3 4/4] mtd: nand: omap: Documentation: How to select correct ECC scheme for your device ?
  2014-03-24 11:20 [PATCH v3 0/4] mtd: nand: omap: add support for BCH16_ECC Pekon Gupta
                   ` (2 preceding siblings ...)
  2014-03-24 11:20 ` [PATCH v3 3/4] mtd: nand: omap: add support for BCH16_ECC - NAND " Pekon Gupta
@ 2014-03-24 11:20 ` Pekon Gupta
  2014-04-28  5:08 ` [PATCH v3 0/4] mtd: nand: omap: add support for BCH16_ECC Gupta, Pekon
  2014-05-06  4:21 ` Gupta, Pekon
  5 siblings, 0 replies; 8+ messages in thread
From: Pekon Gupta @ 2014-03-24 11:20 UTC (permalink / raw)
  To: Brian Norris
  Cc: Stefan Roese, linux-mtd, Felipe Balbi, Ezequiel Garcia, Pekon Gupta

 - Adds DT binding property for BCH16 ECC scheme
 - Adds describes on factors which determine choice of ECC scheme for particular device

Signed-off-by: Pekon Gupta <pekon@ti.com>
---
 .../devicetree/bindings/mtd/gpmc-nand.txt          | 39 ++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nand.txt b/Documentation/devicetree/bindings/mtd/gpmc-nand.txt
index 5e1f31b..f2dbb33 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,40 @@ 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 like;
+(1) Presence of supporting hardware engines on SoC.
+	Some legacy OMAP SoC do not have ELM h/w engine thus such SoC cannot
+	support BCHx_HW ECC schemes. But such SoC can support
+	BCHx_HW_DETECTION_SW ECC schemes which use s/w library with slight
+	CPU performance panalty only when too bit-flips are detected.
+(2) Device parameters like OOBSIZE
+	Higher ECC schemes require more OOB/Spare area to store ECC.
+	So choice of ECC scheme is limited by NAND oobsize. In general
+	following expression help determine whether given device can
+	accomodate ECC syndrome or not:
+	"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
+		Number of spare/OOB bytes required for using BCH16 ecc-scheme
+		"(2 + (2048 / 512) * 26) = 106 bytes" is greater than OOBSIZE
+		(As per above table for BCH16 ecc-scheme, ECC_BYTES = 26)
+		Thus BCH16 cannot be supported on 2K NAND with OOBSIZE=64 bytes
+
+	Example(b): For a device with PAGESIZE = 2048 and OOBSIZE = 128
+		Number of spare/OOB bytes required for using BCH16 ecc-scheme
+		"(2 + (2048 / 512) * 26) = 106 bytes" is less than OOBSIZE
+		(As per above table for BCH16 ecc-scheme, ECC_BYTES = 26)
+		Thus BCH16 can be supported on 4K NAND with OOBSIZE=128 bytes
-- 
1.8.5.1.163.gd7aced9

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* RE: [PATCH v3 0/4]  mtd: nand: omap: add support for BCH16_ECC
  2014-03-24 11:20 [PATCH v3 0/4] mtd: nand: omap: add support for BCH16_ECC Pekon Gupta
                   ` (3 preceding siblings ...)
  2014-03-24 11:20 ` [PATCH v3 4/4] mtd: nand: omap: Documentation: How to select correct ECC scheme for your device ? Pekon Gupta
@ 2014-04-28  5:08 ` Gupta, Pekon
  2014-05-06  4:21 ` Gupta, Pekon
  5 siblings, 0 replies; 8+ messages in thread
From: Gupta, Pekon @ 2014-04-28  5:08 UTC (permalink / raw)
  To: Brian Norris; +Cc: Stefan Roese, linux-mtd, Balbi, Felipe, Ezequiel Garcia

Hi Brian,

>From: Gupta, Pekon
>
>*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          | 39 +++++++++
> arch/arm/mach-omap2/gpmc.c                         | 15 ++++
> drivers/mtd/devices/elm.c                          | 42 ++++++++++
> 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

If this patch series looks good, them please accept it. This one is needed
for supporting NAND boot with 4K page-sized NAND devices, on TI platforms.

Following patch also needs your attention, it fixes a long term issue.
"mtd: nand: omap: fix BCHx ecc.correct to return detected bit-flips in erased-page"


with regards, pekon

^ permalink raw reply	[flat|nested] 8+ messages in thread

* RE: [PATCH v3 0/4]  mtd: nand: omap: add support for BCH16_ECC
  2014-03-24 11:20 [PATCH v3 0/4] mtd: nand: omap: add support for BCH16_ECC Pekon Gupta
                   ` (4 preceding siblings ...)
  2014-04-28  5:08 ` [PATCH v3 0/4] mtd: nand: omap: add support for BCH16_ECC Gupta, Pekon
@ 2014-05-06  4:21 ` Gupta, Pekon
  5 siblings, 0 replies; 8+ messages in thread
From: Gupta, Pekon @ 2014-05-06  4:21 UTC (permalink / raw)
  To: Brian Norris
  Cc: artem.bityutskiy, Stefan Roese, linux-mtd, Balbi, Felipe,
	Ezequiel Garcia

Hello Brian,

 [...]

>>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          | 39 +++++++++
>> arch/arm/mach-omap2/gpmc.c                         | 15 ++++
>> drivers/mtd/devices/elm.c                          | 42 ++++++++++
>> 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
>
>If this patch series looks good, them please accept it. This one is needed
>for supporting NAND boot with 4K page-sized NAND devices, on TI platforms.
>
>Following patch also needs your attention, it fixes a long term issue.
>"mtd: nand: omap: fix BCHx ecc.correct to return detected bit-flips in erased-page"
>

Please see that this series does not miss the 3.16 window.
It has been there from quite long time and all its dependent patches
have been already merged in last cycle.


with regards, pekon

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v3 3/4] mtd: nand: omap: add support for BCH16_ECC - NAND driver updates
  2014-05-09  8:59 Pekon Gupta
@ 2014-05-09  8:59 ` Pekon Gupta
  0 siblings, 0 replies; 8+ messages in thread
From: Pekon Gupta @ 2014-05-09  8:59 UTC (permalink / raw)
  To: Tony Lindgren, Brian Norris
  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 d161c9b..c359af0 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};
@@ -1115,6 +1119,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;
 	}
@@ -1163,6 +1180,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;
@@ -1202,6 +1220,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;
 		}
@@ -1228,6 +1281,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;
 		}
@@ -1319,6 +1374,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;
@@ -1402,6 +1461,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:
@@ -1929,6 +1989,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] 8+ messages in thread

end of thread, other threads:[~2014-05-09  9:00 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-24 11:20 [PATCH v3 0/4] mtd: nand: omap: add support for BCH16_ECC Pekon Gupta
2014-03-24 11:20 ` [PATCH v3 1/4] mtd: nand: omap: add support for BCH16_ECC - GPMC driver updates Pekon Gupta
2014-03-24 11:20 ` [PATCH v3 2/4] mtd: nand: omap: add support for BCH16_ECC - ELM " Pekon Gupta
2014-03-24 11:20 ` [PATCH v3 3/4] mtd: nand: omap: add support for BCH16_ECC - NAND " Pekon Gupta
2014-03-24 11:20 ` [PATCH v3 4/4] mtd: nand: omap: Documentation: How to select correct ECC scheme for your device ? Pekon Gupta
2014-04-28  5:08 ` [PATCH v3 0/4] mtd: nand: omap: add support for BCH16_ECC Gupta, Pekon
2014-05-06  4:21 ` Gupta, Pekon
2014-05-09  8:59 Pekon Gupta
2014-05-09  8:59 ` [PATCH v3 3/4] mtd: nand: omap: add support for BCH16_ECC - NAND driver updates Pekon Gupta

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).