All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 0/4] mtd: nand: omap: optimize and clean-up of OMAP NAND driver
@ 2013-08-14  6:16 Pekon Gupta
  2013-08-14  6:16 ` [U-Boot] [PATCH v2 1/4] mtd: nand: omap: enable BCH ECC scheme using ELM for generic platform Pekon Gupta
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Pekon Gupta @ 2013-08-14  6:16 UTC (permalink / raw)
  To: u-boot

[changes in v2]
- added documentation for CONFIG_NAND_OMAP_xx in doc/README.nand
- added CONFIG_BCH along with CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW
  to include software library lib/bch.c
- fixed board_nand_init() and omap_enable_hwecc()

[Original v1]
This patch series updates BCH8_ECC schemes in mtd/nand/omap_gpmc.c driver
- adds scalability for higher ECC schemes in future.
- removes CONFIG_AM335x and it makes it generic for all platforms.
- optimizes read_data paths

This series is tested for H/W BCH8_ECC scheme on
- AM335x_EVM and TI814x_EVM

Pekon Gupta (4):
[PATCH 1/4] mtd: nand: omap: enable BCH ECC scheme using ELM for generic platform
[PATCH 2/4] mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes
[PATCH 3/4] mtd: nand: omap: optimize chip->ecc.calculate() for H/W ECC schemes
[PATCH 4/4] mtd: nand: omap: optimized chip->ecc.correct() for H/W ECC schemes

 doc/README.nand              |  20 ++
 drivers/mtd/nand/omap_gpmc.c | 514 +++++++++++++++----------------------------
 include/configs/am335x_evm.h |   1 +
 include/configs/ti814x_evm.h |   2 +-
 include/configs/tricorder.h  |   2 +-
 5 files changed, 203 insertions(+), 336 deletions(-)

-- 
1.8.1

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

* [U-Boot] [PATCH v2 1/4] mtd: nand: omap: enable BCH ECC scheme using ELM for generic platform
  2013-08-14  6:16 [U-Boot] [PATCH v2 0/4] mtd: nand: omap: optimize and clean-up of OMAP NAND driver Pekon Gupta
@ 2013-08-14  6:16 ` Pekon Gupta
  2013-08-22 22:25   ` Scott Wood
  2013-08-14  6:16 ` [U-Boot] [PATCH v2 2/4] mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes Pekon Gupta
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Pekon Gupta @ 2013-08-14  6:16 UTC (permalink / raw)
  To: u-boot

BCH8_ECC scheme implemented in omap_gpmc.c driver has following two favours
+-----------------------------------+-----------------+-----------------+
|ECC Scheme                         | ECC Calculation | Error Detection |
+-----------------------------------+-----------------+-----------------+
|OMAP_ECC_BCH8_CODE_HW              |GPMC             |ELM H/W engine   |
|OMAP_ECC_BCH8_CODE_HW_DETECTION_SW |GPMC             |S/W BCH library  |
+-----------------------------------+-----------------+-----------------+

Current implementation enables of BCH8_CODE_HW only for AM33xx SoC family.
(using CONFIG_AM33XX). However, other SoC families (like TI81xx) also have
ELM hardware module, and can support ECC error detection using ELM.

This patch
- replaces CONFIG_AM33xx define with
	CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW
  so that all device families having required h/w capability can use ELM for
  error detection in ECC_BCHx schemes.

- replaces CONFIG_NAND_OMAP_BCH8 with
	CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW && CONFIG_BCH
  and separates out code for above mentioned BCH8_ECC implementations so that
  driver can be build independently using anyone of them.
  CONFIG_BCH is used to enable software BCH library in lib/bch.c

Signed-off-by: Pekon Gupta <pekon@ti.com>
---
 doc/README.nand              |  20 +++++++
 drivers/mtd/nand/omap_gpmc.c | 128 ++++++++++++++++++++++++-------------------
 include/configs/am335x_evm.h |   1 +
 include/configs/ti814x_evm.h |   2 +-
 include/configs/tricorder.h  |   2 +-
 5 files changed, 96 insertions(+), 57 deletions(-)

diff --git a/doc/README.nand b/doc/README.nand
index 913e9b5..b84fce7 100644
--- a/doc/README.nand
+++ b/doc/README.nand
@@ -169,6 +169,26 @@ Configuration Options:
       Please convert your driver even if you don't need the extra
       flexibility, so that one day we can eliminate the old mechanism.
 
+   CONFIG_BCH
+	Enables software based BCH ECC algorithm present in lib/bch.c
+	This is used by SoC platforms which do not have in-build hardware
+	engine to calculate and correct BCH ECC.
+
+
+Platform specific configs
+   CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW
+	Enables 8-bit BCH ECC scheme on NAND with following attributes
+	- ECC calculation done by GPMC hardware engine
+	- ECC error detection done by ELM hardware engine
+	- ECC layout compatible with ROM code
+
+   CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW
+	- ECC calculation done by GPMC hardware engine
+	- ECC error detection done using /lib/bch.c software library
+	- ECC layout is comapatible to SW ECC scheme
+	* requires CONFIG_BCH for enabling lib/bch.c
+
+
 NOTE:
 =====
 
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index ec1787f..d9a4a5e 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -15,9 +15,7 @@
 #include <linux/bch.h>
 #include <linux/compiler.h>
 #include <nand.h>
-#ifdef CONFIG_AM33XX
 #include <asm/arch/elm.h>
-#endif
 
 static uint8_t cs;
 static __maybe_unused struct nand_ecclayout hw_nand_oob =
@@ -274,7 +272,7 @@ static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
 {
 	uint32_t val;
 	uint32_t dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
-#ifdef CONFIG_AM33XX
+#if defined(CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW)
 	uint32_t unused_length = 0;
 #endif
 	uint32_t wr_mode = BCH_WRAPMODE_6;
@@ -283,7 +281,7 @@ static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
 	/* Clear the ecc result registers, select ecc reg as 1 */
 	writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
 
-#ifdef CONFIG_AM33XX
+#if defined(CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW)
 	wr_mode = BCH_WRAPMODE_1;
 
 	switch (bch->nibbles) {
@@ -375,10 +373,11 @@ static void __maybe_unused omap_ecc_disable(struct mtd_info *mtd)
 	writel((readl(&gpmc_cfg->ecc_config) & ~0x1), &gpmc_cfg->ecc_config);
 }
 
+
 /*
- * BCH8 support (needs ELM and thus AM33xx-only)
+ * BCH support using ELM module
  */
-#ifdef CONFIG_AM33XX
+#if defined(CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW)
 /*
  * omap_read_bch8_result - Read BCH result for BCH8 level
  *
@@ -631,12 +630,13 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
 	}
 	return 0;
 }
-#endif /* CONFIG_AM33XX */
+#endif /* CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW */
 
 /*
  * OMAP3 BCH8 support (with BCH library)
  */
-#ifdef CONFIG_NAND_OMAP_BCH8
+#if defined(CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW) && \
+	defined(CONFIG_BCH)
 /*
  *  omap_calculate_ecc_bch - Read BCH ECC result
  *
@@ -752,7 +752,7 @@ static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
 		chip_priv->control = NULL;
 	}
 }
-#endif /* CONFIG_NAND_OMAP_BCH8 */
+#endif /* CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW && CONFIG_BCH */
 
 #ifndef CONFIG_SPL_BUILD
 /*
@@ -803,25 +803,43 @@ void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
 			nand->ecc.calculate = omap_calculate_ecc;
 			omap_hwecc_init(nand);
 			printf("1-bit hamming HW ECC selected\n");
-		}
-#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8)
-		else if (eccstrength == 8) {
-			nand->ecc.mode = NAND_ECC_HW;
-			nand->ecc.layout = &hw_bch8_nand_oob;
-			nand->ecc.size = 512;
-#ifdef CONFIG_AM33XX
-			nand->ecc.bytes = 14;
-			nand->ecc.read_page = omap_read_page_bch;
+		} else if (eccstrength == 8) {
+#if defined(CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW)
+			nand->ecc.mode		= NAND_ECC_HW;
+			nand->ecc.layout	= &hw_bch8_nand_oob;
+			nand->ecc.size		= 512;
+			nand->ecc.bytes		= 14;
+			nand->ecc.read_page	= omap_read_page_bch;
+			nand->ecc.hwctl		= omap_enable_ecc_bch;
+			nand->ecc.correct	= omap_correct_data_bch;
+			nand->ecc.calculate	= omap_calculate_ecc_bch;
+			/* ELM is used for ECC error detection */
+			elm_init();
+			nand->priv = &bch_priv;
+			omap_hwecc_init_bch(nand, NAND_ECC_READ);
+			printf("using OMAP_ECC_BCH8_CODE_HW\n");
+#elif defined(CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW) && \
+	defined(CONFIG_BCH)
+			nand->ecc.mode		= NAND_ECC_HW;
+			nand->ecc.layout	= &hw_bch8_nand_oob;
+			nand->ecc.size		= 512;
+			nand->ecc.bytes		= 13;
+			nand->ecc.hwctl		= omap_enable_ecc_bch;
+			nand->ecc.correct	= omap_correct_data_bch;
+			nand->ecc.calculate	= omap_calculate_ecc_bch;
+			/* BCH SW library is used for error detection */
+			bch_priv.control	= init_bch(13, 8, 0x201b);
+			if (!bch_priv.control) {
+				puts("Could not init_bch()\n");
+				return -ENODEV;
+			}
+			nand->priv = &bch_priv;
+			omap_hwecc_init_bch(nand, NAND_ECC_READ);
+			printf("using OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
 #else
-			nand->ecc.bytes = 13;
+			printf("selected ECC not supported or not enabled\n");
 #endif
-			nand->ecc.hwctl = omap_enable_ecc_bch;
-			nand->ecc.correct = omap_correct_data_bch;
-			nand->ecc.calculate = omap_calculate_ecc_bch;
-			omap_hwecc_init_bch(nand, NAND_ECC_READ);
-			printf("8-bit BCH HW ECC selected\n");
 		}
-#endif
 	} else {
 		nand->ecc.mode = NAND_ECC_SOFT;
 		/* Use mtd default settings */
@@ -894,44 +912,45 @@ int board_nand_init(struct nand_chip *nand)
 
 	nand->chip_delay = 100;
 
-#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8)
-#ifdef CONFIG_AM33XX
-	/* AM33xx uses the ELM */
-	/* required in case of BCH */
+#if defined(CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW)
+	printf("NAND: using OMAP_ECC_BCH8_CODE_HW\n");
+	nand->ecc.mode		= NAND_ECC_HW;
+	nand->ecc.layout	= &hw_bch8_nand_oob;
+	nand->ecc.size		= CONFIG_SYS_NAND_ECCSIZE;
+	nand->ecc.bytes		= CONFIG_SYS_NAND_ECCBYTES;
+	nand->ecc.strength	= 8;
+	nand->ecc.hwctl		= omap_enable_ecc_bch;
+	nand->ecc.correct	= omap_correct_data_bch;
+	nand->ecc.calculate	= omap_calculate_ecc_bch;
+	nand->ecc.read_page	= omap_read_page_bch;
+	/* ELM is used for ECC error detection */
 	elm_init();
-#else
-	/*
-	 * Whereas other OMAP based SoC do not have the ELM, they use the BCH
-	 * SW library.
-	 */
-	bch_priv.control = init_bch(13, 8, 0x201b /* hw polynominal */);
+	nand->priv = &bch_priv;
+	omap_hwecc_init_bch(nand, NAND_ECC_READ);
+#elif defined(CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW) && \
+	defined(CONFIG_BCH)
+	printf("NAND: using OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
+	nand->ecc.mode		= NAND_ECC_HW;
+	nand->ecc.layout	= &hw_bch8_nand_oob;
+	nand->ecc.size		= CONFIG_SYS_NAND_ECCSIZE;
+	nand->ecc.bytes		= CONFIG_SYS_NAND_ECCBYTES;
+	nand->ecc.strength	= 8;
+	nand->ecc.hwctl		= omap_enable_ecc_bch;
+	nand->ecc.correct	= omap_correct_data_bch;
+	nand->ecc.calculate	= omap_calculate_ecc_bch;
+	/* BCH SW library is used for error detection */
+	bch_priv.control	= init_bch(13, 8, 0x201b /* hw polynominal */);
 	if (!bch_priv.control) {
 		puts("Could not init_bch()\n");
 		return -ENODEV;
 	}
-#endif
-	/* BCH info that will be correct for SPL or overridden otherwise. */
 	nand->priv = &bch_priv;
-#endif
-
-	/* Default ECC mode */
-#if defined(CONFIG_AM33XX) || defined(CONFIG_NAND_OMAP_BCH8)
-	nand->ecc.mode = NAND_ECC_HW;
-	nand->ecc.layout = &hw_bch8_nand_oob;
-	nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
-	nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
-	nand->ecc.strength = 8;
-	nand->ecc.hwctl = omap_enable_ecc_bch;
-	nand->ecc.correct = omap_correct_data_bch;
-	nand->ecc.calculate = omap_calculate_ecc_bch;
-#ifdef CONFIG_AM33XX
-	nand->ecc.read_page = omap_read_page_bch;
-#endif
 	omap_hwecc_init_bch(nand, NAND_ECC_READ);
-#else
-#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_NAND_SOFTECC)
+#elif !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_NAND_SOFTECC)
+	printf("NAND: using OMAP_ECC_HAM1_CODE_SW\n");
 	nand->ecc.mode = NAND_ECC_SOFT;
 #else
+	printf("NAND: using OMAP_ECC_HAM1_CODE_HW\n");
 	nand->ecc.mode = NAND_ECC_HW;
 	nand->ecc.layout = &hw_nand_oob;
 	nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
@@ -942,7 +961,6 @@ int board_nand_init(struct nand_chip *nand)
 	nand->ecc.strength = 1;
 	omap_hwecc_init(nand);
 #endif
-#endif
 
 #ifdef CONFIG_SPL_BUILD
 	if (nand->options & NAND_BUSWIDTH_16)
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h
index c5a6d4b..8f3bd54 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -493,6 +493,7 @@
 #define CONFIG_NAND
 /* NAND support */
 #ifdef CONFIG_NAND
+#define CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW
 #define CONFIG_CMD_NAND
 #define CONFIG_CMD_MTDPARTS
 #define MTDIDS_DEFAULT			"nand0=omap2-nand.0"
diff --git a/include/configs/ti814x_evm.h b/include/configs/ti814x_evm.h
index b6fafc7..546cc07 100644
--- a/include/configs/ti814x_evm.h
+++ b/include/configs/ti814x_evm.h
@@ -286,7 +286,7 @@
 #define CONFIG_NAND
 /* NAND support */
 #ifdef CONFIG_NAND
-#define CONFIG_MTD_NAND_OMAP_BCH
+#define CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW
 #define CONFIG_CMD_NAND
 #define CONFIG_CMD_MTDPARTS
 #define MTDIDS_DEFAULT			"nand0=omap2-nand.0"
diff --git a/include/configs/tricorder.h b/include/configs/tricorder.h
index 4e2cb65..dc4f6dc 100644
--- a/include/configs/tricorder.h
+++ b/include/configs/tricorder.h
@@ -109,7 +109,7 @@
 
 #define CONFIG_SYS_MAX_NAND_DEVICE	1		/* Max number of NAND */
 							/* devices */
-#define CONFIG_NAND_OMAP_BCH8
+#define CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW
 #define CONFIG_BCH
 
 /* commands to include */
-- 
1.8.1

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

* [U-Boot] [PATCH v2 2/4] mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes
  2013-08-14  6:16 [U-Boot] [PATCH v2 0/4] mtd: nand: omap: optimize and clean-up of OMAP NAND driver Pekon Gupta
  2013-08-14  6:16 ` [U-Boot] [PATCH v2 1/4] mtd: nand: omap: enable BCH ECC scheme using ELM for generic platform Pekon Gupta
@ 2013-08-14  6:16 ` Pekon Gupta
  2013-08-14  6:16 ` [U-Boot] [PATCH v2 3/4] mtd: nand: omap: optimize chip->ecc.calculate() " Pekon Gupta
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Pekon Gupta @ 2013-08-14  6:16 UTC (permalink / raw)
  To: u-boot

chip->ecc.hwctl() is used for preparing the H/W controller before read/write
NAND accesses (like assigning data-buf, enabling ECC scheme configs, etc.)

Though all ECC schemes in OMAP NAND driver use GPMC controller for generating
ECC syndrome (for both Read/Write accesses). But but in current code
HAM1_ECC and BCHx_ECC schemes implement individual function to achieve this.
This patch
(1) removes omap_hwecc_init() and omap_hwecc_init_bch()
as chip->ecc.hwctl will re-initializeGPMC before every read/write call.
omap_hwecc_init_bch() -> omap_enable_ecc_bch()

(2) merges the GPMC configuration code for all ECC schemes into
single omap_enable_hwecc(), thus adding scalability for future ECC schemes.
omap_enable_hwecc() + omap_enable_ecc_bch() -> omap_enable_hwecc()

Signed-off-by: Pekon Gupta <pekon@ti.com>
---
 drivers/mtd/nand/omap_gpmc.c | 207 ++++++++++++-------------------------------
 1 file changed, 58 insertions(+), 149 deletions(-)

diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index d9a4a5e..b8f0e86 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -17,6 +17,9 @@
 #include <nand.h>
 #include <asm/arch/elm.h>
 
+
+#define SECTOR_BYTES		512
+
 static uint8_t cs;
 static __maybe_unused struct nand_ecclayout hw_nand_oob =
 	GPMC_NAND_HW_ECC_LAYOUT;
@@ -60,21 +63,6 @@ int omap_spl_dev_ready(struct mtd_info *mtd)
 }
 #endif
 
-/*
- * omap_hwecc_init - Initialize the Hardware ECC for NAND flash in
- *                   GPMC controller
- * @mtd:        MTD device structure
- *
- */
-static void __maybe_unused omap_hwecc_init(struct nand_chip *chip)
-{
-	/*
-	 * Init ECC Control Register
-	 * Clear all ECC | Enable Reg1
-	 */
-	writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
-	writel(ECCSIZE1 | ECCSIZE0 | ECCSIZE0SEL, &gpmc_cfg->ecc_size_config);
-}
 
 /*
  * gen_true_ecc - This function will generate true ECC value, which
@@ -192,38 +180,6 @@ static int __maybe_unused omap_calculate_ecc(struct mtd_info *mtd,
 }
 
 /*
- * omap_enable_ecc - This function enables the hardware ecc functionality
- * @mtd:        MTD device structure
- * @mode:       Read/Write mode
- */
-static void __maybe_unused omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
-{
-	struct nand_chip *chip = mtd->priv;
-	uint32_t val, dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
-
-	switch (mode) {
-	case NAND_ECC_READ:
-	case NAND_ECC_WRITE:
-		/* Clear the ecc result registers, select ecc reg as 1 */
-		writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
-
-		/*
-		 * Size 0 = 0xFF, Size1 is 0xFF - both are 512 bytes
-		 * tell all regs to generate size0 sized regs
-		 * we just have a single ECC engine for all CS
-		 */
-		writel(ECCSIZE1 | ECCSIZE0 | ECCSIZE0SEL,
-			&gpmc_cfg->ecc_size_config);
-		val = (dev_width << 7) | (cs << 1) | (0x1);
-		writel(val, &gpmc_cfg->ecc_config);
-		break;
-	default:
-		printf("Error: Unrecognized Mode[%d]!\n", mode);
-		break;
-	}
-}
-
-/*
  * Generic BCH interface
  */
 struct nand_bch_priv {
@@ -262,105 +218,63 @@ static __maybe_unused struct nand_bch_priv bch_priv = {
 };
 
 /*
- * omap_hwecc_init_bch - Initialize the BCH Hardware ECC for NAND flash in
- *				GPMC controller
+ * omap_enable_hwecc - configures GPMC as per ECC scheme before read/write
  * @mtd:	MTD device structure
  * @mode:	Read/Write mode
  */
 __maybe_unused
-static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
+static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
 {
-	uint32_t val;
-	uint32_t dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
-#if defined(CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW)
-	uint32_t unused_length = 0;
-#endif
-	uint32_t wr_mode = BCH_WRAPMODE_6;
-	struct nand_bch_priv *bch = chip->priv;
-
-	/* Clear the ecc result registers, select ecc reg as 1 */
-	writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
-
-#if defined(CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW)
-	wr_mode = BCH_WRAPMODE_1;
-
-	switch (bch->nibbles) {
-	case ECC_BCH4_NIBBLES:
-		unused_length = 3;
-		break;
-	case ECC_BCH8_NIBBLES:
-		unused_length = 2;
-		break;
-	case ECC_BCH16_NIBBLES:
-		unused_length = 0;
-		break;
-	}
-
-	/*
-	 * This is ecc_size_config for ELM mode.
-	 * Here we are using different settings for read and write access and
-	 * also depending on BCH strength.
-	 */
-	switch (mode) {
-	case NAND_ECC_WRITE:
-		/* write access only setup eccsize1 config */
-		val = ((unused_length + bch->nibbles) << 22);
-		break;
-
-	case NAND_ECC_READ:
-	default:
-		/*
-		 * by default eccsize0 selected for ecc1resultsize
-		 * eccsize0 config.
-		 */
-		val  = (bch->nibbles << 12);
-		/* eccsize1 config */
-		val |= (unused_length << 22);
-		break;
-	}
+	struct nand_chip *chip = mtd->priv;
+	unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0;
+	unsigned int ecc_algo = 0;
+	unsigned int bch_type = 0;
+	unsigned int eccsize1 = 0x00, eccsize0 = 0x00, bch_wrapmode = 0x00;
+	u32 ecc_size_config_val = 0;
+	u32 ecc_config_val = 0;
+
+	if (chip->ecc.strength == 1) {
+		ecc_algo = 0x0;
+		bch_type = 0x0;
+		bch_wrapmode = 0x00;
+		eccsize0 = 0xFF;
+		eccsize1 = 0xFF;
+#if defined(CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW) || \
+	defined(CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW)
+	} else if (chip->ecc.strength == 8) {
+		ecc_algo = 0x1;
+		bch_type = 0x1;
+		if (mode == NAND_ECC_WRITE) {
+			bch_wrapmode = 0x01;
+			eccsize0 = 0;  /* extra bits in nibbles per sector */
+			eccsize1 = 28; /* OOB bits in nibbles per sector */
+		} else {
+			bch_wrapmode = 0x01;
+			eccsize0 = 26; /* ECC bits in nibbles per sector */
+			eccsize1 = 2;  /* non-ECC bits in nibbles per sector */
+		}
 #else
-	/*
-	 * This ecc_size_config setting is for BCH sw library.
-	 *
-	 * Note: we only support BCH8 currently with BCH sw library!
-	 * Should be really easy to adobt to BCH4, however some omap3 have
-	 * flaws with BCH4.
-	 *
-	 * Here we are using wrapping mode 6 both for reading and writing, with:
-	 *  size0 = 0  (no additional protected byte in spare area)
-	 *  size1 = 32 (skip 32 nibbles = 16 bytes per sector in spare area)
-	 */
-	val = (32 << 22) | (0 << 12);
+	} else {
+		printf("*Error: invalid driver configuration\n");
 #endif
-	/* ecc size configuration */
-	writel(val, &gpmc_cfg->ecc_size_config);
-
-	/*
-	 * Configure the ecc engine in gpmc
-	 * We assume 512 Byte sector pages for access to NAND.
-	 */
-	val  = (1 << 16);		/* enable BCH mode */
-	val |= (bch->type << 12);	/* setup BCH type */
-	val |= (wr_mode << 8);		/* setup wrapping mode */
-	val |= (dev_width << 7);	/* setup device width (16 or 8 bit) */
-	val |= (cs << 1);		/* setup chip select to work on */
-	debug("set ECC_CONFIG=0x%08x\n", val);
-	writel(val, &gpmc_cfg->ecc_config);
-}
-
-/*
- * omap_enable_ecc_bch - This function enables the bch h/w ecc functionality
- * @mtd:	MTD device structure
- * @mode:	Read/Write mode
- */
-__maybe_unused
-static void omap_enable_ecc_bch(struct mtd_info *mtd, int32_t mode)
-{
-	struct nand_chip *chip = mtd->priv;
-
-	omap_hwecc_init_bch(chip, mode);
-	/* enable ecc */
-	writel((readl(&gpmc_cfg->ecc_config) | 0x1), &gpmc_cfg->ecc_config);
+	}
+	/* Clear ecc and enable bits */
+	writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
+	/* Configure ecc size for BCH */
+	ecc_size_config_val = (eccsize1 << 22) | (eccsize0 << 12);
+	writel(ecc_size_config_val, &gpmc_cfg->ecc_size_config);
+
+	/* Configure device details for BCH engine */
+	ecc_config_val = ((ecc_algo << 16)	| /* HAM1 | BCHx */
+			(bch_type << 12)	| /* BCH4/BCH8/BCH16 */
+			(bch_wrapmode << 8)	| /* wrap mode */
+			(dev_width << 7)	| /* bus width */
+			(0x0 << 4)		| /* number of sectors */
+			(cs <<  1)		| /* ECC CS */
+			(0x0));			/* disable ECC */
+	writel(ecc_config_val, &gpmc_cfg->ecc_config);
+	/* enable ECC engine */
+	writel(ecc_config_val | 0x1, &gpmc_cfg->ecc_config);
 }
 
 /*
@@ -801,7 +715,7 @@ void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
 			nand->ecc.hwctl = omap_enable_hwecc;
 			nand->ecc.correct = omap_correct_data;
 			nand->ecc.calculate = omap_calculate_ecc;
-			omap_hwecc_init(nand);
+			omap_enable_hwecc(mtd, NAND_ECC_READ);
 			printf("1-bit hamming HW ECC selected\n");
 		} else if (eccstrength == 8) {
 #if defined(CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW)
@@ -810,13 +724,12 @@ void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
 			nand->ecc.size		= 512;
 			nand->ecc.bytes		= 14;
 			nand->ecc.read_page	= omap_read_page_bch;
-			nand->ecc.hwctl		= omap_enable_ecc_bch;
+			nand->ecc.hwctl		= omap_enable_hwecc;
 			nand->ecc.correct	= omap_correct_data_bch;
 			nand->ecc.calculate	= omap_calculate_ecc_bch;
 			/* ELM is used for ECC error detection */
 			elm_init();
 			nand->priv = &bch_priv;
-			omap_hwecc_init_bch(nand, NAND_ECC_READ);
 			printf("using OMAP_ECC_BCH8_CODE_HW\n");
 #elif defined(CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW) && \
 	defined(CONFIG_BCH)
@@ -824,7 +737,7 @@ void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
 			nand->ecc.layout	= &hw_bch8_nand_oob;
 			nand->ecc.size		= 512;
 			nand->ecc.bytes		= 13;
-			nand->ecc.hwctl		= omap_enable_ecc_bch;
+			nand->ecc.hwctl		= omap_enable_hwecc;
 			nand->ecc.correct	= omap_correct_data_bch;
 			nand->ecc.calculate	= omap_calculate_ecc_bch;
 			/* BCH SW library is used for error detection */
@@ -834,7 +747,6 @@ void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
 				return -ENODEV;
 			}
 			nand->priv = &bch_priv;
-			omap_hwecc_init_bch(nand, NAND_ECC_READ);
 			printf("using OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
 #else
 			printf("selected ECC not supported or not enabled\n");
@@ -919,14 +831,13 @@ int board_nand_init(struct nand_chip *nand)
 	nand->ecc.size		= CONFIG_SYS_NAND_ECCSIZE;
 	nand->ecc.bytes		= CONFIG_SYS_NAND_ECCBYTES;
 	nand->ecc.strength	= 8;
-	nand->ecc.hwctl		= omap_enable_ecc_bch;
+	nand->ecc.hwctl		= omap_enable_hwecc;
 	nand->ecc.correct	= omap_correct_data_bch;
 	nand->ecc.calculate	= omap_calculate_ecc_bch;
 	nand->ecc.read_page	= omap_read_page_bch;
 	/* ELM is used for ECC error detection */
 	elm_init();
 	nand->priv = &bch_priv;
-	omap_hwecc_init_bch(nand, NAND_ECC_READ);
 #elif defined(CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW) && \
 	defined(CONFIG_BCH)
 	printf("NAND: using OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
@@ -935,7 +846,7 @@ int board_nand_init(struct nand_chip *nand)
 	nand->ecc.size		= CONFIG_SYS_NAND_ECCSIZE;
 	nand->ecc.bytes		= CONFIG_SYS_NAND_ECCBYTES;
 	nand->ecc.strength	= 8;
-	nand->ecc.hwctl		= omap_enable_ecc_bch;
+	nand->ecc.hwctl		= omap_enable_hwecc;
 	nand->ecc.correct	= omap_correct_data_bch;
 	nand->ecc.calculate	= omap_calculate_ecc_bch;
 	/* BCH SW library is used for error detection */
@@ -945,7 +856,6 @@ int board_nand_init(struct nand_chip *nand)
 		return -ENODEV;
 	}
 	nand->priv = &bch_priv;
-	omap_hwecc_init_bch(nand, NAND_ECC_READ);
 #elif !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_NAND_SOFTECC)
 	printf("NAND: using OMAP_ECC_HAM1_CODE_SW\n");
 	nand->ecc.mode = NAND_ECC_SOFT;
@@ -959,7 +869,6 @@ int board_nand_init(struct nand_chip *nand)
 	nand->ecc.correct = omap_correct_data;
 	nand->ecc.calculate = omap_calculate_ecc;
 	nand->ecc.strength = 1;
-	omap_hwecc_init(nand);
 #endif
 
 #ifdef CONFIG_SPL_BUILD
-- 
1.8.1

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

* [U-Boot] [PATCH v2 3/4] mtd: nand: omap: optimize chip->ecc.calculate() for H/W ECC schemes
  2013-08-14  6:16 [U-Boot] [PATCH v2 0/4] mtd: nand: omap: optimize and clean-up of OMAP NAND driver Pekon Gupta
  2013-08-14  6:16 ` [U-Boot] [PATCH v2 1/4] mtd: nand: omap: enable BCH ECC scheme using ELM for generic platform Pekon Gupta
  2013-08-14  6:16 ` [U-Boot] [PATCH v2 2/4] mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes Pekon Gupta
@ 2013-08-14  6:16 ` Pekon Gupta
  2013-08-14  6:16 ` [U-Boot] [PATCH v2 4/4] mtd: nand: omap: optimized chip->ecc.correct() " Pekon Gupta
  2013-08-23 22:19 ` [U-Boot] [PATCH v2 0/4] mtd: nand: omap: optimize and clean-up of OMAP NAND driver Tom Rini
  4 siblings, 0 replies; 10+ messages in thread
From: Pekon Gupta @ 2013-08-14  6:16 UTC (permalink / raw)
  To: u-boot

chip->ecc.calculate() is used for calculating and fetching of ECC syndrome by
processing the data passed during Read/Write accesses.

All H/W based ECC schemes use GPMC controller to calculate ECC syndrome.
But each BCHx_ECC scheme has its own implemetation of post-processing and
fetching ECC syndrome from GPMC controller.

This patch updates OMAP_ECC_BCH8_CODE_HW ECC scheme in following way:
- merges various sub-functions into single omap_calculate_ecc_bch().
- removes omap_ecc_disable() and instead uses it as inline.

Signed-off-by: Pekon Gupta <pekon@ti.com>
---
 drivers/mtd/nand/omap_gpmc.c | 81 ++++++++++----------------------------------
 1 file changed, 18 insertions(+), 63 deletions(-)

diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index b8f0e86..fa3a82a 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -277,35 +277,28 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
 	writel(ecc_config_val | 0x1, &gpmc_cfg->ecc_config);
 }
 
-/*
- * omap_ecc_disable - Disable H/W ECC calculation
- *
- * @mtd:	MTD device structure
- */
-static void __maybe_unused omap_ecc_disable(struct mtd_info *mtd)
-{
-	writel((readl(&gpmc_cfg->ecc_config) & ~0x1), &gpmc_cfg->ecc_config);
-}
-
 
 /*
  * BCH support using ELM module
  */
 #if defined(CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW)
 /*
- * omap_read_bch8_result - Read BCH result for BCH8 level
- *
- * @mtd:	MTD device structure
- * @big_endian:	When set read register 3 first
- * @ecc_code:	Read syndrome from BCH result registers
+ *  omap_calculate_ecc_bch - Read BCH ECC result
+ *  @mtd:	MTD structure
+ *  @dat:	unused
+ *  @ecc_code:	ecc_code buffer
  */
-static void omap_read_bch8_result(struct mtd_info *mtd, uint8_t big_endian,
+static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
 				uint8_t *ecc_code)
 {
+	struct nand_chip *chip = mtd->priv;
+	struct nand_bch_priv *bch = chip->priv;
+	int8_t ret = 0;
 	uint32_t *ptr;
 	int8_t i = 0, j;
 
-	if (big_endian) {
+	switch (bch->type) {
+	case ECC_BCH8:
 		ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3];
 		ecc_code[i++] = readl(ptr) & 0xFF;
 		ptr--;
@@ -316,18 +309,13 @@ static void omap_read_bch8_result(struct mtd_info *mtd, uint8_t big_endian,
 			ecc_code[i++] = readl(ptr) & 0xFF;
 			ptr--;
 		}
-	} else {
-		ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[0];
-		for (j = 0; j < 3; j++) {
-			ecc_code[i++] = readl(ptr) & 0xFF;
-			ecc_code[i++] = (readl(ptr) >>  8) & 0xFF;
-			ecc_code[i++] = (readl(ptr) >> 16) & 0xFF;
-			ecc_code[i++] = (readl(ptr) >> 24) & 0xFF;
-			ptr++;
-		}
-		ecc_code[i++] = readl(ptr) & 0xFF;
-		ecc_code[i++] = 0;	/* 14th byte is always zero */
+		break;
+	default:
+		ret = -1;
 	}
+	/* clear result and disable engine */
+	writel((readl(&gpmc_cfg->ecc_config) & ~0x1), &gpmc_cfg->ecc_config);
+	return ret;
 }
 
 /*
@@ -366,35 +354,6 @@ static void omap_rotate_ecc_bch(struct mtd_info *mtd, uint8_t *calc_ecc,
 }
 
 /*
- *  omap_calculate_ecc_bch - Read BCH ECC result
- *
- *  @mtd:	MTD structure
- *  @dat:	unused
- *  @ecc_code:	ecc_code buffer
- */
-static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
-				uint8_t *ecc_code)
-{
-	struct nand_chip *chip = mtd->priv;
-	struct nand_bch_priv *bch = chip->priv;
-	uint8_t big_endian = 1;
-	int8_t ret = 0;
-
-	if (bch->type == ECC_BCH8)
-		omap_read_bch8_result(mtd, big_endian, ecc_code);
-	else /* BCH4 and BCH16 currently not supported */
-		ret = -1;
-
-	/*
-	 * Stop reading anymore ECC vals and clear old results
-	 * enable will be called if more reads are required
-	 */
-	omap_ecc_disable(mtd);
-
-	return ret;
-}
-
-/*
  * omap_fix_errors_bch - Correct bch error in the data
  *
  * @mtd:	MTD device structure
@@ -592,12 +551,8 @@ static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
 		*ecc++ = 0x24 ^ ((val1 >> 8) & 0xFF);
 		*ecc++ = 0xb5 ^ (val1 & 0xFF);
 	}
-
-	/*
-	 * Stop reading anymore ECC vals and clear old results
-	 * enable will be called if more reads are required
-	 */
-	omap_ecc_disable(mtd);
+	/* Stop reading anymore ECC vals and clear old results */
+	writel((readl(&gpmc_cfg->ecc_config) & ~0x1), &gpmc_cfg->ecc_config);
 
 	return ret;
 }
-- 
1.8.1

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

* [U-Boot] [PATCH v2 4/4] mtd: nand: omap: optimized chip->ecc.correct() for H/W ECC schemes
  2013-08-14  6:16 [U-Boot] [PATCH v2 0/4] mtd: nand: omap: optimize and clean-up of OMAP NAND driver Pekon Gupta
                   ` (2 preceding siblings ...)
  2013-08-14  6:16 ` [U-Boot] [PATCH v2 3/4] mtd: nand: omap: optimize chip->ecc.calculate() " Pekon Gupta
@ 2013-08-14  6:16 ` Pekon Gupta
  2013-08-23 22:19 ` [U-Boot] [PATCH v2 0/4] mtd: nand: omap: optimize and clean-up of OMAP NAND driver Tom Rini
  4 siblings, 0 replies; 10+ messages in thread
From: Pekon Gupta @ 2013-08-14  6:16 UTC (permalink / raw)
  To: u-boot

chip->ecc.correct() is used for detecting and correcting bit-flips during read
operations. In omap-nand driver it implemented as:
(a) omap_correct_data(): for h/w based ECC_HAM1 scheme
(b) omap_correct_data_bch() + CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW
	for ECC_BCH8 scheme using GPMC and software lib/bch.c
(c) omap_correct_data_bch() + CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW
	for ECC_BCH8 scheme using GPMC and ELM

This patch updates (c)
- checks for calc_ecc[]==0x00 so that error_correction is not required for
  known good pages.
- adds scalability for other ECC_BCHx scheme by merging following
  omap_rotate_ecc_bch() + omap_fix_errors_bch() => omap_correct_data_bch()
- fixing logic for bit-flip correction based on error_loc[count]

Signed-off-by: Pekon Gupta <pekon@ti.com>
---
 drivers/mtd/nand/omap_gpmc.c | 124 +++++++++++++++----------------------------
 1 file changed, 44 insertions(+), 80 deletions(-)

diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index fa3a82a..8c2ba53 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -19,6 +19,8 @@
 
 
 #define SECTOR_BYTES		512
+/* 4 bit padding to make byte aligned, 56 = 52 + 4 */
+#define BCH4_BIT_PAD		4
 
 static uint8_t cs;
 static __maybe_unused struct nand_ecclayout hw_nand_oob =
@@ -319,77 +321,6 @@ static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
 }
 
 /*
- * omap_rotate_ecc_bch - Rotate the syndrome bytes
- *
- * @mtd:	MTD device structure
- * @calc_ecc:	ECC read from ECC registers
- * @syndrome:	Rotated syndrome will be retuned in this array
- *
- */
-static void omap_rotate_ecc_bch(struct mtd_info *mtd, uint8_t *calc_ecc,
-		uint8_t *syndrome)
-{
-	struct nand_chip *chip = mtd->priv;
-	struct nand_bch_priv *bch = chip->priv;
-	uint8_t n_bytes = 0;
-	int8_t i, j;
-
-	switch (bch->type) {
-	case ECC_BCH4:
-		n_bytes = 8;
-		break;
-
-	case ECC_BCH16:
-		n_bytes = 28;
-		break;
-
-	case ECC_BCH8:
-	default:
-		n_bytes = 13;
-		break;
-	}
-
-	for (i = 0, j = (n_bytes-1); i < n_bytes; i++, j--)
-		syndrome[i] =  calc_ecc[j];
-}
-
-/*
- * omap_fix_errors_bch - Correct bch error in the data
- *
- * @mtd:	MTD device structure
- * @data:	Data read from flash
- * @error_count:Number of errors in data
- * @error_loc:	Locations of errors in the data
- *
- */
-static void omap_fix_errors_bch(struct mtd_info *mtd, uint8_t *data,
-		uint32_t error_count, uint32_t *error_loc)
-{
-	struct nand_chip *chip = mtd->priv;
-	struct nand_bch_priv *bch = chip->priv;
-	uint8_t count = 0;
-	uint32_t error_byte_pos;
-	uint32_t error_bit_mask;
-	uint32_t last_bit = (bch->nibbles * 4) - 1;
-
-	/* Flip all bits as specified by the error location array. */
-	/* FOR( each found error location flip the bit ) */
-	for (count = 0; count < error_count; count++) {
-		if (error_loc[count] > last_bit) {
-			/* Remove the ECC spare bits from correction. */
-			error_loc[count] -= (last_bit + 1);
-			/* Offset bit in data region */
-			error_byte_pos = ((512 * 8) -
-					(error_loc[count]) - 1) / 8;
-			/* Error Bit mask */
-			error_bit_mask = 0x1 << (error_loc[count] % 8);
-			/* Toggle the error bit to make the correction. */
-			data[error_byte_pos] ^= error_bit_mask;
-		}
-	}
-}
-
-/*
  * omap_correct_data_bch - Compares the ecc read from nand spare area
  * with ECC registers values and corrects one bit error if it has occured
  *
@@ -405,16 +336,26 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
 {
 	struct nand_chip *chip = mtd->priv;
 	struct nand_bch_priv *bch = chip->priv;
+	uint32_t eccbytes = chip->ecc.bytes;
 	uint8_t syndrome[28];
-	uint32_t error_count = 0;
+	uint32_t error_count = 0, error_max;
 	uint32_t error_loc[8];
-	uint32_t i, ecc_flag;
+	uint32_t i, j, ecc_flag = 0;
+	uint8_t count, ret = 0;
+	uint32_t byte_pos, bit_pos;
+
+	/* check calculated ecc */
+	for (i = 0; i < chip->ecc.bytes && !ecc_flag; i++)
+		if (calc_ecc[i] != 0x00)
+			ecc_flag = 1;
+	if (!ecc_flag)
+		return 0;
 
+	/* check for whether its a erased-page */
 	ecc_flag = 0;
-	for (i = 0; i < chip->ecc.bytes; i++)
+	for (i = 0; i < chip->ecc.bytes && !ecc_flag; i++)
 		if (read_ecc[i] != 0xff)
 			ecc_flag = 1;
-
 	if (!ecc_flag)
 		return 0;
 
@@ -425,20 +366,43 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
 	 * while reading ECC result we read it in big endian.
 	 * Hence while loading to ELM we have rotate to get the right endian.
 	 */
-	omap_rotate_ecc_bch(mtd, calc_ecc, syndrome);
+	for (i = 0, j = (eccbytes-1); i < eccbytes; i++, j--)
+		syndrome[i] =  calc_ecc[j];
 
 	/* use elm module to check for errors */
 	if (elm_check_error(syndrome, bch->nibbles, &error_count,
 				error_loc) != 0) {
-		printf("ECC: uncorrectable.\n");
+		printf("nand: uncorrectable ECC errors\n");
 		return -1;
 	}
 
 	/* correct bch error */
-	if (error_count > 0)
-		omap_fix_errors_bch(mtd, dat, error_count, error_loc);
+	for (count = 0; count < error_count; count++) {
+		switch (bch->type) {
+		case ECC_BCH4:
+			error_max = SECTOR_BYTES + (eccbytes - 1);
+			/* add 4 to take care 4 bit padding */
+			error_loc[count] += BCH4_BIT_PAD;
+			break;
+		case ECC_BCH8:
+			/* 14th byte in ECC is reserved to match ROM layout */
+			error_max = SECTOR_BYTES + (eccbytes - 1);
+			break;
+		default:
+			return -1;
+		}
+		byte_pos = error_max - ((error_loc[count] - 1) / 8);
+		bit_pos  = error_loc[count] % 8;
 
-	return 0;
+		if (byte_pos < SECTOR_BYTES)
+			dat[byte_pos] ^= 1 << bit_pos;
+		else if (byte_pos < error_max)
+			read_ecc[byte_pos - SECTOR_BYTES] = 1 << bit_pos;
+		else
+			ret = -1;
+	}
+
+	return ret;
 }
 
 /**
-- 
1.8.1

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

* [U-Boot] [PATCH v2 1/4] mtd: nand: omap: enable BCH ECC scheme using ELM for generic platform
  2013-08-14  6:16 ` [U-Boot] [PATCH v2 1/4] mtd: nand: omap: enable BCH ECC scheme using ELM for generic platform Pekon Gupta
@ 2013-08-22 22:25   ` Scott Wood
  2013-08-23 12:43     ` Tom Rini
  0 siblings, 1 reply; 10+ messages in thread
From: Scott Wood @ 2013-08-22 22:25 UTC (permalink / raw)
  To: u-boot

On Wed, 2013-08-14 at 11:46 +0530, Pekon Gupta wrote:
> BCH8_ECC scheme implemented in omap_gpmc.c driver has following two favours
> +-----------------------------------+-----------------+-----------------+
> |ECC Scheme                         | ECC Calculation | Error Detection |
> +-----------------------------------+-----------------+-----------------+
> |OMAP_ECC_BCH8_CODE_HW              |GPMC             |ELM H/W engine   |
> |OMAP_ECC_BCH8_CODE_HW_DETECTION_SW |GPMC             |S/W BCH library  |
> +-----------------------------------+-----------------+-----------------+
> 
> Current implementation enables of BCH8_CODE_HW only for AM33xx SoC family.
> (using CONFIG_AM33XX). However, other SoC families (like TI81xx) also have
> ELM hardware module, and can support ECC error detection using ELM.
> 
> This patch
> - replaces CONFIG_AM33xx define with
> 	CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW
>   so that all device families having required h/w capability can use ELM for
>   error detection in ECC_BCHx schemes.
> 
> - replaces CONFIG_NAND_OMAP_BCH8 with
> 	CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW && CONFIG_BCH
>   and separates out code for above mentioned BCH8_ECC implementations so that
>   driver can be build independently using anyone of them.
>   CONFIG_BCH is used to enable software BCH library in lib/bch.c
> 
> Signed-off-by: Pekon Gupta <pekon@ti.com>
> ---
>  doc/README.nand              |  20 +++++++
>  drivers/mtd/nand/omap_gpmc.c | 128 ++++++++++++++++++++++++-------------------
>  include/configs/am335x_evm.h |   1 +
>  include/configs/ti814x_evm.h |   2 +-
>  include/configs/tricorder.h  |   2 +-
>  5 files changed, 96 insertions(+), 57 deletions(-)

The ti814x_evm.h changes do not apply.  What tree is this against?

Can someone familiar with the OMAP driver review this patchset?

-Scott

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

* [U-Boot] [PATCH v2 1/4] mtd: nand: omap: enable BCH ECC scheme using ELM for generic platform
  2013-08-22 22:25   ` Scott Wood
@ 2013-08-23 12:43     ` Tom Rini
  2013-08-23 17:55       ` Scott Wood
  0 siblings, 1 reply; 10+ messages in thread
From: Tom Rini @ 2013-08-23 12:43 UTC (permalink / raw)
  To: u-boot

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 08/22/2013 06:25 PM, Scott Wood wrote:
> On Wed, 2013-08-14 at 11:46 +0530, Pekon Gupta wrote:
>> BCH8_ECC scheme implemented in omap_gpmc.c driver has following 
>> two favours 
>> +-----------------------------------+-----------------+-----------------+
>>
>>
>> 
|ECC Scheme                         | ECC Calculation | Error Detection |
>> +-----------------------------------+-----------------+-----------------+
>>
>>
>> 
|OMAP_ECC_BCH8_CODE_HW              |GPMC             |ELM H/W engine   |
>> |OMAP_ECC_BCH8_CODE_HW_DETECTION_SW |GPMC             |S/W BCH 
>> library  | 
>> +-----------------------------------+-----------------+-----------------+
>>
>>
>>
>> 
Current implementation enables of BCH8_CODE_HW only for AM33xx SoC family.
>> (using CONFIG_AM33XX). However, other SoC families (like TI81xx) 
>> also have ELM hardware module, and can support ECC error 
>> detection using ELM.
>> 
>> This patch - replaces CONFIG_AM33xx define with 
>> CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW so that all device families 
>> having required h/w capability can use ELM for error detection
>> in ECC_BCHx schemes.
>> 
>> - replaces CONFIG_NAND_OMAP_BCH8 with 
>> CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW && CONFIG_BCH and 
>> separates out code for above mentioned BCH8_ECC implementations 
>> so that driver can be build independently using anyone of them. 
>> CONFIG_BCH is used to enable software BCH library in lib/bch.c
>> 
>> Signed-off-by: Pekon Gupta <pekon@ti.com> --- doc/README.nand |
>> 20 +++++++ drivers/mtd/nand/omap_gpmc.c | 128 
>> ++++++++++++++++++++++++------------------- 
>> include/configs/am335x_evm.h |   1 +
>> include/configs/ti814x_evm.h |   2 +- include/configs/tricorder.h
>> |   2 +- 5 files changed, 96 insertions(+), 57 deletions(-)
> 
> The ti814x_evm.h changes do not apply.  What tree is this against?
> 
> Can someone familiar with the OMAP driver review this patchset?

The ti814x_evm.h part depends on his earlier patch I suspect.  If
you're happy NAND-wise, I'll pick these up (and formally review 'em, I
have skimmed) for the TI tree if that works for you.

- -- 
Tom
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBAgAGBQJSF1kHAAoJENk4IS6UOR1WpSQP/RKHIQxwNKNhHA1QpwJHBW1w
jQcil0HA1GEtovq4YdoYjIENzdVa9pElY+YvkOMy8/sf8CAxgpXDBuFwuJJEkdX7
FVX+HBvMDFvEp7b2epm2Icz2/SQGFMDM2XX1yOT8ojBmuS9vPXylBbQwZBSdq4V8
kdZ4065PtsPZ7ZtH43CwKYEMeYUPLxQOelQZDKY0OZYymfgsuIA7P57g21AD9EtR
P+njljb8PHTaTabD35DMKdds3hNy/MYBpZ0VxCWH9O6t6K9eo6TWo+WhEYTyanI+
JE3Dj1YZecyPFLAqdeY6Irz1hGwBtkkS1He6InBsIOlJ5dsjSZmU5ABqNKP8i3Sx
4BypEIo0OUIz8p26DzppSPvy1tvxib2wEY2mDqKKqqhKHwo9XgmJfRDfIYurhKxY
N3DgoOPoNuVUKsVFEkD4r9gvlrSyl1wZgRf0sc3qvFQvbOzgIz8AQ+DOPrGTKVGk
/HDVH0I9uRkJFtAIBOY5ckygIb0uuzyXc6W7yuNpDu6nVt0Vb4/Uk0OeIBIagbR8
1dN0nqRyu6f4+xwtRF7DrdfgULyAgKnubjr9i0eR6KE+xVdcKq9zStzMCN/hE623
0g/kfVEM8iIPZYb6oxeMx7N2mEe8L/W9lz3bXTibtwCSB+NJF7RjTto7ltT+R9Az
3Nr2HudfhOUBpQISAmyA
=cJ/1
-----END PGP SIGNATURE-----

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

* [U-Boot] [PATCH v2 1/4] mtd: nand: omap: enable BCH ECC scheme using ELM for generic platform
  2013-08-23 12:43     ` Tom Rini
@ 2013-08-23 17:55       ` Scott Wood
  0 siblings, 0 replies; 10+ messages in thread
From: Scott Wood @ 2013-08-23 17:55 UTC (permalink / raw)
  To: u-boot

On Fri, 2013-08-23 at 08:43 -0400, Tom Rini wrote:
> On 08/22/2013 06:25 PM, Scott Wood wrote:
> > On Wed, 2013-08-14 at 11:46 +0530, Pekon Gupta wrote:
> >> BCH8_ECC scheme implemented in omap_gpmc.c driver has following 
> >> two favours 
> >> +-----------------------------------+-----------------+-----------------+
> >>
> >>
> >> 
> |ECC Scheme                         | ECC Calculation | Error Detection |
> >> +-----------------------------------+-----------------+-----------------+
> >>
> >>
> >> 
> |OMAP_ECC_BCH8_CODE_HW              |GPMC             |ELM H/W engine   |
> >> |OMAP_ECC_BCH8_CODE_HW_DETECTION_SW |GPMC             |S/W BCH 
> >> library  | 
> >> +-----------------------------------+-----------------+-----------------+
> >>
> >>
> >>
> >> 
> Current implementation enables of BCH8_CODE_HW only for AM33xx SoC family.
> >> (using CONFIG_AM33XX). However, other SoC families (like TI81xx) 
> >> also have ELM hardware module, and can support ECC error 
> >> detection using ELM.
> >> 
> >> This patch - replaces CONFIG_AM33xx define with 
> >> CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW so that all device families 
> >> having required h/w capability can use ELM for error detection
> >> in ECC_BCHx schemes.
> >> 
> >> - replaces CONFIG_NAND_OMAP_BCH8 with 
> >> CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW && CONFIG_BCH and 
> >> separates out code for above mentioned BCH8_ECC implementations 
> >> so that driver can be build independently using anyone of them. 
> >> CONFIG_BCH is used to enable software BCH library in lib/bch.c
> >> 
> >> Signed-off-by: Pekon Gupta <pekon@ti.com> --- doc/README.nand |
> >> 20 +++++++ drivers/mtd/nand/omap_gpmc.c | 128 
> >> ++++++++++++++++++++++++------------------- 
> >> include/configs/am335x_evm.h |   1 +
> >> include/configs/ti814x_evm.h |   2 +- include/configs/tricorder.h
> >> |   2 +- 5 files changed, 96 insertions(+), 57 deletions(-)
> > 
> > The ti814x_evm.h changes do not apply.  What tree is this against?
> > 
> > Can someone familiar with the OMAP driver review this patchset?
> 
> The ti814x_evm.h part depends on his earlier patch I suspect.  If
> you're happy NAND-wise, I'll pick these up (and formally review 'em, I
> have skimmed) for the TI tree if that works for you.

OK: Acked-by: Scott Wood <scottwood@freescale.com>

-Scott

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

* [U-Boot] [PATCH v2 0/4] mtd: nand: omap: optimize and clean-up of OMAP NAND driver
  2013-08-14  6:16 [U-Boot] [PATCH v2 0/4] mtd: nand: omap: optimize and clean-up of OMAP NAND driver Pekon Gupta
                   ` (3 preceding siblings ...)
  2013-08-14  6:16 ` [U-Boot] [PATCH v2 4/4] mtd: nand: omap: optimized chip->ecc.correct() " Pekon Gupta
@ 2013-08-23 22:19 ` Tom Rini
  2013-08-24  4:01   ` Gupta, Pekon
  4 siblings, 1 reply; 10+ messages in thread
From: Tom Rini @ 2013-08-23 22:19 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 14, 2013 at 11:46:51AM +0530, Pekon Gupta wrote:
> [changes in v2]
> - added documentation for CONFIG_NAND_OMAP_xx in doc/README.nand
> - added CONFIG_BCH along with CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW
>   to include software library lib/bch.c
> - fixed board_nand_init() and omap_enable_hwecc()
> 
> [Original v1]
> This patch series updates BCH8_ECC schemes in mtd/nand/omap_gpmc.c driver
> - adds scalability for higher ECC schemes in future.
> - removes CONFIG_AM335x and it makes it generic for all platforms.
> - optimizes read_data paths
> 
> This series is tested for H/W BCH8_ECC scheme on
> - AM335x_EVM and TI814x_EVM
> 
> Pekon Gupta (4):
> [PATCH 1/4] mtd: nand: omap: enable BCH ECC scheme using ELM for generic platform
> [PATCH 2/4] mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes
> [PATCH 3/4] mtd: nand: omap: optimize chip->ecc.calculate() for H/W ECC schemes
> [PATCH 4/4] mtd: nand: omap: optimized chip->ecc.correct() for H/W ECC schemes
> 
>  doc/README.nand              |  20 ++
>  drivers/mtd/nand/omap_gpmc.c | 514 +++++++++++++++----------------------------
>  include/configs/am335x_evm.h |   1 +
>  include/configs/ti814x_evm.h |   2 +-
>  include/configs/tricorder.h  |   2 +-
>  5 files changed, 203 insertions(+), 336 deletions(-)

Series looks good to me, I'll pick these up soon, after I test them on
beagle as well.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20130823/4b7c5b67/attachment.pgp>

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

* [U-Boot] [PATCH v2 0/4] mtd: nand: omap: optimize and clean-up of OMAP NAND driver
  2013-08-23 22:19 ` [U-Boot] [PATCH v2 0/4] mtd: nand: omap: optimize and clean-up of OMAP NAND driver Tom Rini
@ 2013-08-24  4:01   ` Gupta, Pekon
  0 siblings, 0 replies; 10+ messages in thread
From: Gupta, Pekon @ 2013-08-24  4:01 UTC (permalink / raw)
  To: u-boot


________________________________________
From: Tom Rini [tom.rini at gmail.com] on behalf of Rini, Tom
Sent: Saturday, August 24, 2013 3:49 AM
To: Gupta, Pekon
Cc: scottwood at freescale.com; u-boot at lists.denx.de
Subject: Re: [U-Boot] [PATCH v2 0/4] mtd: nand: omap: optimize and clean-up of OMAP NAND driver

> On Wed, Aug 14, 2013 at 11:46:51AM +0530, Pekon Gupta wrote:
> > [changes in v2]
> > - added documentation for CONFIG_NAND_OMAP_xx in doc/README.nand
> > - added CONFIG_BCH along with CONFIG_NAND_OMAP_ECC_BCH8_CODE_HW_DETECTION_SW
> >   to include software library lib/bch.c
> > - fixed board_nand_init() and omap_enable_hwecc()
> >
> > [Original v1]
> > This patch series updates BCH8_ECC schemes in mtd/nand/omap_gpmc.c driver
> > - adds scalability for higher ECC schemes in future.
> > - removes CONFIG_AM335x and it makes it generic for all platforms.
> > - optimizes read_data paths
> >
> > This series is tested for H/W BCH8_ECC scheme on
> > - AM335x_EVM and TI814x_EVM
> >
> > Pekon Gupta (4):
> > [PATCH 1/4] mtd: nand: omap: enable BCH ECC scheme usinmg ELM for generic platform
> > [PATCH 2/4] mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes
> > [PATCH 3/4] mtd: nand: omap: optimize chip->ecc.calculate() for H/W ECC schemes
> > [PATCH 4/4] mtd: nand: omap: optimized chip->ecc.correct() for H/W ECC schemes
> >
> >  doc/README.nand              |  20 ++
> >  drivers/mtd/nand/omap_gpmc.c | 514 +++++++++++++++----------------------------
> >  include/configs/am335x_evm.h |   1 +
> >  include/configs/ti814x_evm.h |   2 +-
> >  include/configs/tricorder.h  |   2 +-
> >  5 files changed, 203 insertions(+), 336 deletions(-)
> 
> Series looks good to me, I'll pick these up soon, after I test them on
> beagle as well.
> 
> --
> Tom

Thanks Scott and Tom for reviews..
- I just realized few minor cleanup that could help in future.
- Also, I'll split the patch-set for AM335x and TI814x boards so that they can 
  be independently tested. 
So plz wait as I'll post a v3 for this and TI814x series soon, and then may be you
can verify them independently.

with regards, pekon

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

end of thread, other threads:[~2013-08-24  4:01 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-08-14  6:16 [U-Boot] [PATCH v2 0/4] mtd: nand: omap: optimize and clean-up of OMAP NAND driver Pekon Gupta
2013-08-14  6:16 ` [U-Boot] [PATCH v2 1/4] mtd: nand: omap: enable BCH ECC scheme using ELM for generic platform Pekon Gupta
2013-08-22 22:25   ` Scott Wood
2013-08-23 12:43     ` Tom Rini
2013-08-23 17:55       ` Scott Wood
2013-08-14  6:16 ` [U-Boot] [PATCH v2 2/4] mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes Pekon Gupta
2013-08-14  6:16 ` [U-Boot] [PATCH v2 3/4] mtd: nand: omap: optimize chip->ecc.calculate() " Pekon Gupta
2013-08-14  6:16 ` [U-Boot] [PATCH v2 4/4] mtd: nand: omap: optimized chip->ecc.correct() " Pekon Gupta
2013-08-23 22:19 ` [U-Boot] [PATCH v2 0/4] mtd: nand: omap: optimize and clean-up of OMAP NAND driver Tom Rini
2013-08-24  4:01   ` Gupta, Pekon

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.