public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver
@ 2013-11-19  5:32 Pekon Gupta
  2013-11-19  5:32 ` [U-Boot] [PATCH v9 1/4] mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes Pekon Gupta
                   ` (6 more replies)
  0 siblings, 7 replies; 10+ messages in thread
From: Pekon Gupta @ 2013-11-19  5:32 UTC (permalink / raw)
  To: u-boot


OMAP NAND drivers support various ecc-schemes like (HAM1, BCH4, BCH8..)
And, each ecc-scheme usually has 2 implementations 
 - HAM1_HW or BCHx_HW (using in-build h/w engine for all computation)
 - HAM1_SW or BCHx_HW_DETECTION_SW) (using software library for some computation)

This patch series is Part-2 (split) from earlier series, as mentioned below:
http://lists.denx.de/pipermail/u-boot/2013-November/167270.html

This series aims at following:
 - cleans-up redundant code, duplicate in different ecc-schemes
 - optimizes ecc calculation and correction paths
 - improves scalability and readability, for adding newer ecc-schemes in future.
 - updates following callbacks for different ecc-schmes: 
 [PATCH 1/4] nand_chip->ecc.hwctl(): configures h/w controller before for Read/Write acccess
 [PATCH 2/4] nand_chip->ecc.calculate(): calculates and fetches ECC syndrome from h/w controller.
 [PATCH 3/4] nand_chip->ecc.correct(): detects and corrects ECC errors on read access
 [PATCH 4/4] update doc and README 


*changes in v9*
 - split from main series, rebased and forked independently


*changes in v8*
 http://lists.denx.de/pipermail/u-boot/2013-October/164648.html
 - minor code clean-up


*changes in v7*
[PATCH 1/4] http://lists.denx.de/pipermail/u-boot/2013-September/163868.html
 - removed: re-configuration of gpmc.config1[dev_width] added in
   previous version of patch


*changes in v6*
 http://lists.denx.de/pipermail/u-boot/2013-September/163099.html
 - cosmetic changes


*changes in v5*
[PATCH 1/4] http://lists.denx.de/pipermail/u-boot/2013-September/162105.html
 - fixed device-width in GPMC_CONFIG1_X to support x16 devices
[PATCH 2/4] http://lists.denx.de/pipermail/u-boot/2013-September/162109.html
 - code clean-up for OMAP_ECC_BCH8_CODE_HW_DETECTION_SW mode
[PATCH 3/4] http://lists.denx.de/pipermail/u-boot/2013-September/162110.html
 - fixed omap_correct_data_bch() for correcting bit-flips using ELM
 - code-cleanup + added omap_reverse_list()
[PATCH 4/4] incorporated feedbacks from Peter Korsgaard <jacmet@sunsite.dk>


*changes in v4*
 http://lists.denx.de/pipermail/u-boot/2013-September/161861.html
 - minor clean-up


*changes in v3*
 http://lists.denx.de/pipermail/u-boot/2013-August/161665.html
 - removed un-used defines from asm/omap_gpmc.h
 - removed omap_calculate_ecc_bch_sw() and omap_calculate_ecc()
   and merged their logic into omap_calculate_ecc_bch()
 - updated return error-code in-case of invalid conditions
 - (new) for board/ti/am335x/README


*changes in v2*
 http://lists.denx.de/pipermail/u-boot/2013-August/160749.html
 - fixed board_nand_init() and omap_enable_hwecc()


*original v1*
  http://lists.denx.de/pipermail/u-boot/2013-August/160218.html


Pekon Gupta (4):
  mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes
  mtd: nand: omap: optimize chip->ecc.calculate() for H/W ECC schemes
  mtd: nand: omap: optimized chip->ecc.correct() for H/W ECC schemes
  board/ti/am335x/README: update for NAND boot

 arch/arm/include/asm/omap_gpmc.h |   7 -
 board/ti/am335x/README           |  53 ++--
 drivers/mtd/nand/omap_gpmc.c     | 565 +++++++++++++--------------------------
 3 files changed, 217 insertions(+), 408 deletions(-)

-- 
1.8.1

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

* [U-Boot] [PATCH v9 1/4] mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes
  2013-11-19  5:32 [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver Pekon Gupta
@ 2013-11-19  5:32 ` Pekon Gupta
  2013-11-19  5:32 ` [U-Boot] [PATCH v9 2/4] mtd: nand: omap: optimize chip->ecc.calculate() " Pekon Gupta
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Pekon Gupta @ 2013-11-19  5:32 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>
---
 arch/arm/include/asm/omap_gpmc.h |   7 --
 drivers/mtd/nand/omap_gpmc.c     | 192 +++++++++++----------------------------
 2 files changed, 54 insertions(+), 145 deletions(-)

diff --git a/arch/arm/include/asm/omap_gpmc.h b/arch/arm/include/asm/omap_gpmc.h
index d4143ec..6ce5e65 100644
--- a/arch/arm/include/asm/omap_gpmc.h
+++ b/arch/arm/include/asm/omap_gpmc.h
@@ -14,13 +14,6 @@
 #define GPMC_BUF_EMPTY	0
 #define GPMC_BUF_FULL	1
 
-#define ECCCLEAR	(0x1 << 8)
-#define ECCRESULTREG1	(0x1 << 0)
-#define ECCSIZE512BYTE	0xFF
-#define ECCSIZE1	(ECCSIZE512BYTE << 22)
-#define ECCSIZE0	(ECCSIZE512BYTE << 12)
-#define ECCSIZE0SEL	(0x000 << 0)
-
 /* Generic ECC Layouts */
 /* Large Page x8 NAND device Layout */
 #ifdef GPMC_NAND_ECC_LP_x8_LAYOUT
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index 2b61784..035b1f7 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -19,6 +19,8 @@
 
 #define BADBLOCK_MARKER_LENGTH	2
 #define SECTOR_BYTES		512
+#define ECCCLEAR		(0x1 << 8)
+#define ECCRESULTREG1		(0x1 << 0)
 
 static uint8_t cs;
 static __maybe_unused struct nand_ecclayout omap_ecclayout;
@@ -60,21 +62,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 +179,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 {
@@ -263,103 +218,65 @@ 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;
-	uint32_t unused_length = 0;
-	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 (bch->ecc_scheme == 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;
+	struct nand_chip	*nand	= mtd->priv;
+	struct nand_bch_priv	*bch	= nand->priv;
+	unsigned int dev_width = (nand->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;
+
+	/* configure GPMC for specific ecc-scheme */
+	switch (bch->ecc_scheme) {
+	case OMAP_ECC_HAM1_CODE_SW:
+		return;
+	case OMAP_ECC_HAM1_CODE_HW:
+		ecc_algo = 0x0;
+		bch_type = 0x0;
+		bch_wrapmode = 0x00;
+		eccsize0 = 0xFF;
+		eccsize1 = 0xFF;
 		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);
+	case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
+	case OMAP_ECC_BCH8_CODE_HW:
+		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 */
+		}
 		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;
-	}
-	} 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);
+		return;
 	}
-	/* 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 */
+			(0x1));			  /* enable ECC */
+	writel(ecc_config_val, &gpmc_cfg->ecc_config);
 }
 
 /*
@@ -827,7 +744,7 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
 		nand->ecc.strength	= 8;
 		nand->ecc.size		= SECTOR_BYTES;
 		nand->ecc.bytes		= 13;
-		nand->ecc.hwctl		= omap_enable_ecc_bch;
+		nand->ecc.hwctl		= omap_enable_hwecc;
 		nand->ecc.correct	= omap_correct_data_bch_sw;
 		nand->ecc.calculate	= omap_calculate_ecc_bch_sw;
 		/* define ecc-layout */
@@ -844,7 +761,6 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
 		ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
 		ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
 						BADBLOCK_MARKER_LENGTH;
-		omap_hwecc_init_bch(nand, NAND_ECC_READ);
 		bch->ecc_scheme		= OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
 		break;
 #else
@@ -869,7 +785,7 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
 		nand->ecc.strength	= 8;
 		nand->ecc.size		= SECTOR_BYTES;
 		nand->ecc.bytes		= 14;
-		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;
-- 
1.8.1

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

* [U-Boot] [PATCH v9 2/4] mtd: nand: omap: optimize chip->ecc.calculate() for H/W ECC schemes
  2013-11-19  5:32 [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver Pekon Gupta
  2013-11-19  5:32 ` [U-Boot] [PATCH v9 1/4] mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes Pekon Gupta
@ 2013-11-19  5:32 ` Pekon Gupta
  2013-11-19  5:32 ` [U-Boot] [PATCH v9 3/4] mtd: nand: omap: optimized chip->ecc.correct() " Pekon Gupta
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Pekon Gupta @ 2013-11-19  5:32 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 multiple chip->calculate API for different ECC schemes
  omap_calculate_ecc() + omap_calculate_ecc_bch() + omap_calculate_ecc_bch_sw()
				==> omap_calculate_ecc()
- removes omap_ecc_disable() and instead uses it as inline.

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

diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index 035b1f7..ea1054b 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -21,7 +21,10 @@
 #define SECTOR_BYTES		512
 #define ECCCLEAR		(0x1 << 8)
 #define ECCRESULTREG1		(0x1 << 0)
-
+#ifdef CONFIG_BCH
+static u8  bch8_polynomial[] = {0xef, 0x51, 0x2e, 0x09, 0xed, 0x93, 0x9a, 0xc2,
+				0x97, 0x79, 0xe5, 0x24, 0xb5};
+#endif
 static uint8_t cs;
 static __maybe_unused struct nand_ecclayout omap_ecclayout;
 
@@ -143,42 +146,6 @@ static int __maybe_unused omap_correct_data(struct mtd_info *mtd, uint8_t *dat,
 }
 
 /*
- *  omap_calculate_ecc - Generate non-inverted ECC bytes.
- *
- *  Using noninverted ECC can be considered ugly since writing a blank
- *  page ie. padding will clear the ECC bytes. This is no problem as
- *  long nobody is trying to write data on the seemingly unused page.
- *  Reading an erased page will produce an ECC mismatch between
- *  generated and read ECC bytes that has to be dealt with separately.
- *  E.g. if page is 0xFF (fresh erased), and if HW ECC engine within GPMC
- *  is used, the result of read will be 0x0 while the ECC offsets of the
- *  spare area will be 0xFF which will result in an ECC mismatch.
- *  @mtd:	MTD structure
- *  @dat:	unused
- *  @ecc_code:	ecc_code buffer
- */
-static int __maybe_unused omap_calculate_ecc(struct mtd_info *mtd,
-		const uint8_t *dat, uint8_t *ecc_code)
-{
-	u_int32_t val;
-
-	/* Start Reading from HW ECC1_Result = 0x200 */
-	val = readl(&gpmc_cfg->ecc1_result);
-
-	ecc_code[0] = val & 0xFF;
-	ecc_code[1] = (val >> 16) & 0xFF;
-	ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0);
-
-	/*
-	 * Stop reading anymore ECC vals and clear old results
-	 * enable will be called if more reads are required
-	 */
-	writel(0x000, &gpmc_cfg->ecc_config);
-
-	return 0;
-}
-
-/*
  * Generic BCH interface
  */
 struct nand_bch_priv {
@@ -194,12 +161,7 @@ struct nand_bch_priv {
 #define ECC_BCH8	1
 #define ECC_BCH16	2
 
-/* GPMC ecc engine settings */
-#define BCH_WRAPMODE_1		1	/* BCH wrap mode 1 */
-#define BCH_WRAPMODE_6		6	/* BCH wrap mode 6 */
-
 /* BCH nibbles for diff bch levels */
-#define NAND_ECC_HW_BCH ((uint8_t)(NAND_ECC_HW_OOB_FIRST) + 1)
 #define ECC_BCH4_NIBBLES	13
 #define ECC_BCH8_NIBBLES	26
 #define ECC_BCH16_NIBBLES	52
@@ -211,7 +173,6 @@ struct nand_bch_priv {
  * When some users with other BCH strength will exists this have to change!
  */
 static __maybe_unused struct nand_bch_priv bch_priv = {
-	.mode = NAND_ECC_HW_BCH,
 	.type = ECC_BCH8,
 	.nibbles = ECC_BCH8_NIBBLES,
 	.control = NULL
@@ -280,57 +241,76 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
 }
 
 /*
- * 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
- */
-#ifdef CONFIG_NAND_OMAP_ELM
-/*
- * 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 - Read ECC result
+ *  @mtd:	MTD structure
+ *  @dat:	unused
+ *  @ecc_code:	ecc_code buffer
+ *  Using noninverted ECC can be considered ugly since writing a blank
+ *  page ie. padding will clear the ECC bytes. This is no problem as
+ *  long nobody is trying to write data on the seemingly unused page.
+ *  Reading an erased page will produce an ECC mismatch between
+ *  generated and read ECC bytes that has to be dealt with separately.
+ *  E.g. if page is 0xFF (fresh erased), and if HW ECC engine within GPMC
+ *  is used, the result of read will be 0x0 while the ECC offsets of the
+ *  spare area will be 0xFF which will result in an ECC mismatch.
  */
-static void omap_read_bch8_result(struct mtd_info *mtd, uint8_t big_endian,
+static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
 				uint8_t *ecc_code)
 {
-	uint32_t *ptr;
+	struct nand_chip *chip = mtd->priv;
+	struct nand_bch_priv *bch = chip->priv;
+	uint32_t *ptr, val = 0;
 	int8_t i = 0, j;
 
-	if (big_endian) {
+	switch (bch->ecc_scheme) {
+	case OMAP_ECC_HAM1_CODE_HW:
+		val = readl(&gpmc_cfg->ecc1_result);
+		ecc_code[0] = val & 0xFF;
+		ecc_code[1] = (val >> 16) & 0xFF;
+		ecc_code[2] = ((val >> 8) & 0x0F) | ((val >> 20) & 0xF0);
+		break;
+#ifdef CONFIG_BCH
+	case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
+#endif
+	case OMAP_ECC_BCH8_CODE_HW:
 		ptr = &gpmc_cfg->bch_result_0_3[0].bch_result_x[3];
-		ecc_code[i++] = readl(ptr) & 0xFF;
+		val = readl(ptr);
+		ecc_code[i++] = (val >>  0) & 0xFF;
 		ptr--;
 		for (j = 0; j < 3; j++) {
-			ecc_code[i++] = (readl(ptr) >> 24) & 0xFF;
-			ecc_code[i++] = (readl(ptr) >> 16) & 0xFF;
-			ecc_code[i++] = (readl(ptr) >>  8) & 0xFF;
-			ecc_code[i++] = readl(ptr) & 0xFF;
+			val = readl(ptr);
+			ecc_code[i++] = (val >> 24) & 0xFF;
+			ecc_code[i++] = (val >> 16) & 0xFF;
+			ecc_code[i++] = (val >>  8) & 0xFF;
+			ecc_code[i++] = (val >>  0) & 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:
+		return -EINVAL;
+	}
+	/* ECC scheme specific syndrome customizations */
+	switch (bch->ecc_scheme) {
+	case OMAP_ECC_HAM1_CODE_HW:
+		break;
+#ifdef CONFIG_BCH
+	case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
+
+		for (i = 0; i < chip->ecc.bytes; i++)
+			*(ecc_code + i) = *(ecc_code + i) ^
+						bch8_polynomial[i];
+		break;
+#endif
+	case OMAP_ECC_BCH8_CODE_HW:
+		ecc_code[chip->ecc.bytes - 1] = 0x00;
+		break;
+	default:
+		return -EINVAL;
 	}
+	return 0;
 }
 
+#ifdef CONFIG_NAND_OMAP_ELM
 /*
  * omap_rotate_ecc_bch - Rotate the syndrome bytes
  *
@@ -367,35 +347,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
@@ -551,57 +502,6 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
  * OMAP3 BCH8 support (with BCH library)
  */
 #ifdef CONFIG_BCH
-/*
- *  omap_calculate_ecc_bch_sw - Read BCH ECC result
- *
- *  @mtd:	MTD device structure
- *  @dat:	The pointer to data on which ecc is computed (unused here)
- *  @ecc:	The ECC output buffer
- */
-static int omap_calculate_ecc_bch_sw(struct mtd_info *mtd, const uint8_t *dat,
-				uint8_t *ecc)
-{
-	int ret = 0;
-	size_t i;
-	unsigned long nsectors, val1, val2, val3, val4;
-
-	nsectors = ((readl(&gpmc_cfg->ecc_config) >> 4) & 0x7) + 1;
-
-	for (i = 0; i < nsectors; i++) {
-		/* Read hw-computed remainder */
-		val1 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[0]);
-		val2 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[1]);
-		val3 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[2]);
-		val4 = readl(&gpmc_cfg->bch_result_0_3[i].bch_result_x[3]);
-
-		/*
-		 * Add constant polynomial to remainder, in order to get an ecc
-		 * sequence of 0xFFs for a buffer filled with 0xFFs.
-		 */
-		*ecc++ = 0xef ^ (val4 & 0xFF);
-		*ecc++ = 0x51 ^ ((val3 >> 24) & 0xFF);
-		*ecc++ = 0x2e ^ ((val3 >> 16) & 0xFF);
-		*ecc++ = 0x09 ^ ((val3 >> 8) & 0xFF);
-		*ecc++ = 0xed ^ (val3 & 0xFF);
-		*ecc++ = 0x93 ^ ((val2 >> 24) & 0xFF);
-		*ecc++ = 0x9a ^ ((val2 >> 16) & 0xFF);
-		*ecc++ = 0xc2 ^ ((val2 >> 8) & 0xFF);
-		*ecc++ = 0x97 ^ (val2 & 0xFF);
-		*ecc++ = 0x79 ^ ((val1 >> 24) & 0xFF);
-		*ecc++ = 0xe5 ^ ((val1 >> 16) & 0xFF);
-		*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);
-
-	return ret;
-}
-
 /**
  * omap_correct_data_bch_sw - Decode received data and correct errors
  * @mtd: MTD device structure
@@ -746,7 +646,7 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
 		nand->ecc.bytes		= 13;
 		nand->ecc.hwctl		= omap_enable_hwecc;
 		nand->ecc.correct	= omap_correct_data_bch_sw;
-		nand->ecc.calculate	= omap_calculate_ecc_bch_sw;
+		nand->ecc.calculate	= omap_calculate_ecc;
 		/* define ecc-layout */
 		ecclayout->eccbytes	= nand->ecc.bytes * eccsteps;
 		ecclayout->eccpos[0]	= BADBLOCK_MARKER_LENGTH;
@@ -787,7 +687,7 @@ static int omap_select_ecc_scheme(struct nand_chip *nand,
 		nand->ecc.bytes		= 14;
 		nand->ecc.hwctl		= omap_enable_hwecc;
 		nand->ecc.correct	= omap_correct_data_bch;
-		nand->ecc.calculate	= omap_calculate_ecc_bch;
+		nand->ecc.calculate	= omap_calculate_ecc;
 		nand->ecc.read_page	= omap_read_page_bch;
 		/* define ecc-layout */
 		ecclayout->eccbytes	= nand->ecc.bytes * eccsteps;
-- 
1.8.1

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

* [U-Boot] [PATCH v9 3/4] mtd: nand: omap: optimized chip->ecc.correct() for H/W ECC schemes
  2013-11-19  5:32 [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver Pekon Gupta
  2013-11-19  5:32 ` [U-Boot] [PATCH v9 1/4] mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes Pekon Gupta
  2013-11-19  5:32 ` [U-Boot] [PATCH v9 2/4] mtd: nand: omap: optimize chip->ecc.calculate() " Pekon Gupta
@ 2013-11-19  5:32 ` Pekon Gupta
  2013-11-19  5:32 ` [U-Boot] [PATCH v9 4/4] board/ti/am335x/README: update for NAND boot Pekon Gupta
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Pekon Gupta @ 2013-11-19  5:32 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 | 161 +++++++++++++++++++------------------------
 1 file changed, 71 insertions(+), 90 deletions(-)

diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index ea1054b..f8616f1 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -21,6 +21,9 @@
 #define SECTOR_BYTES		512
 #define ECCCLEAR		(0x1 << 8)
 #define ECCRESULTREG1		(0x1 << 0)
+/* 4 bit padding to make byte aligned, 56 = 52 + 4 */
+#define BCH4_BIT_PAD		4
+
 #ifdef CONFIG_BCH
 static u8  bch8_polynomial[] = {0xef, 0x51, 0x2e, 0x09, 0xed, 0x93, 0x9a, 0xc2,
 				0x97, 0x79, 0xe5, 0x24, 0xb5};
@@ -179,6 +182,23 @@ static __maybe_unused struct nand_bch_priv bch_priv = {
 };
 
 /*
+ * omap_reverse_list - re-orders list elements in reverse order [internal]
+ * @list:	pointer to start of list
+ * @length:	length of list
+*/
+void omap_reverse_list(u8 *list, unsigned int length)
+{
+	unsigned int i, j;
+	unsigned int half_length = length / 2;
+	u8 tmp;
+	for (i = 0, j = length - 1; i < half_length; i++, j--) {
+		tmp = list[i];
+		list[i] = list[j];
+		list[j] = tmp;
+	}
+}
+
+/*
  * omap_enable_hwecc - configures GPMC as per ECC scheme before read/write
  * @mtd:	MTD device structure
  * @mode:	Read/Write mode
@@ -312,77 +332,6 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const uint8_t *dat,
 
 #ifdef CONFIG_NAND_OMAP_ELM
 /*
- * 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
  *
@@ -398,40 +347,72 @@ 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;
-	uint8_t syndrome[28];
-	uint32_t error_count = 0;
+	uint32_t eccbytes = chip->ecc.bytes;
+	uint32_t error_count = 0, error_max;
 	uint32_t error_loc[8];
-	uint32_t i, ecc_flag;
+	uint32_t i, ecc_flag = 0;
+	uint8_t count, err = 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;
 
-	elm_reset();
-	elm_config((enum bch_level)(bch->type));
-
 	/*
 	 * 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);
-
+	switch (bch->ecc_scheme) {
+	case OMAP_ECC_BCH8_CODE_HW:
+		omap_reverse_list(calc_ecc, eccbytes - 1);
+		break;
+	default:
+		return -EINVAL;
+	}
 	/* use elm module to check for errors */
-	if (elm_check_error(syndrome, bch->nibbles, &error_count,
-				error_loc) != 0) {
-		printf("ECC: uncorrectable.\n");
-		return -1;
+	elm_config((enum bch_level)(bch->type));
+	if (elm_check_error(calc_ecc, bch->nibbles, &error_count, error_loc)) {
+		printf("nand: error: uncorrectable ECC errors\n");
+		return -EINVAL;
 	}
-
 	/* correct bch error */
-	if (error_count > 0)
-		omap_fix_errors_bch(mtd, dat, error_count, error_loc);
-
-	return 0;
+	for (count = 0; count < error_count; count++) {
+		switch (bch->type) {
+		case ECC_BCH8:
+			/* 14th byte in ECC is reserved to match ROM layout */
+			error_max = SECTOR_BYTES + (eccbytes - 1);
+			break;
+		default:
+			return -EINVAL;
+		}
+		byte_pos = error_max - (error_loc[count] / 8) - 1;
+		bit_pos  = error_loc[count] % 8;
+		if (byte_pos < SECTOR_BYTES) {
+			dat[byte_pos] ^= 1 << bit_pos;
+			printf("nand: bit-flip corrected @data=%d\n", byte_pos);
+		} else if (byte_pos < error_max) {
+			read_ecc[byte_pos - SECTOR_BYTES] = 1 << bit_pos;
+			printf("nand: bit-flip corrected @oob=%d\n", byte_pos -
+								SECTOR_BYTES);
+		} else {
+			err = -EBADMSG;
+			printf("nand: error: invalid bit-flip location\n");
+		}
+	}
+	return (err) ? err : error_count;
 }
 
 /**
-- 
1.8.1

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

* [U-Boot] [PATCH v9 4/4] board/ti/am335x/README: update for NAND boot
  2013-11-19  5:32 [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver Pekon Gupta
                   ` (2 preceding siblings ...)
  2013-11-19  5:32 ` [U-Boot] [PATCH v9 3/4] mtd: nand: omap: optimized chip->ecc.correct() " Pekon Gupta
@ 2013-11-19  5:32 ` Pekon Gupta
  2013-11-19 11:27 ` [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver Abraham V.
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 10+ messages in thread
From: Pekon Gupta @ 2013-11-19  5:32 UTC (permalink / raw)
  To: u-boot

NAND boot mode on AM335x EVM has been verified, and steps
to use it has been documented and update in this README

Signed-off-by: Pekon Gupta <pekon@ti.com>
Acked-by: Peter Korsgaard <jacmet@sunsite.dk>
Acked-by: Tom Rini <trini@ti.com>
---
 board/ti/am335x/README | 53 ++++++++++++++++++++++++++++++++++----------------
 1 file changed, 36 insertions(+), 17 deletions(-)

diff --git a/board/ti/am335x/README b/board/ti/am335x/README
index 2a30ab8..947305b 100644
--- a/board/ti/am335x/README
+++ b/board/ti/am335x/README
@@ -46,23 +46,42 @@ NAND
 The AM335x GP EVM ships with a 256MiB NAND available in most profiles.  In
 this example to program the NAND we assume that an SD card has been
 inserted with the files to write in the first SD slot and that mtdparts
-have been configured correctly for the board.  As a time saving measure we
-load MLO into memory in one location, copy it into the three locatations
-that the ROM checks for additional valid copies, then load U-Boot into
-memory.  We then write that whole section of memory to NAND.
-
-U-Boot # mmc rescan
-U-Boot # env default -f -a
-U-Boot # nand erase.chip
-U-Boot # saveenv
-U-Boot # load mmc 0 81000000 MLO
-U-Boot # cp.b 81000000 81020000 20000
-U-Boot # cp.b 81000000 81040000 20000
-U-Boot # cp.b 81000000 81060000 20000
-U-Boot # load mmc 0 81080000 u-boot.img
-U-Boot # nand write 81000000 0 260000
-U-Boot # load mmc 0 ${loadaddr} uImage
-U-Boot # nand write ${loadaddr} kernel 500000
+have been configured correctly for the board. All images are first loaded
+into memory, then written to NAND.
+
+Step-1: Building u-boot for NAND boot
+	Set following CONFIGxx options for NAND device.
+	CONFIG_SYS_NAND_PAGE_SIZE	number of main bytes in NAND page
+	CONFIG_SYS_NAND_OOBSIZE		number of OOB bytes in NAND page
+	CONFIG_SYS_NAND_BLOCK_SIZE	number of bytes in NAND erase-block
+	CONFIG_SYS_NAND_ECCPOS		ECC map for NAND page
+	CONFIG_NAND_OMAP_ECCSCHEME	(refer doc/README.nand)
+
+Step-2: Flashing NAND via MMC/SD
+	# select BOOTSEL to MMC/SD boot and boot from MMC/SD card
+	U-Boot # mmc rescan
+	# erase flash
+	U-Boot # nand erase.chip
+	U-Boot # env default -f -a
+	U-Boot # saveenv
+	# flash MLO. Redundant copies of MLO are kept for failsafe
+	U-Boot # load mmc 0 0x82000000 MLO
+	U-Boot # nand write 0x82000000 0x00000 0x20000
+	U-Boot # nand write 0x82000000 0x20000 0x20000
+	U-Boot # nand write 0x82000000 0x40000 0x20000
+	U-Boot # nand write 0x82000000 0x60000 0x20000
+	# flash u-boot.img
+	U-Boot # load mmc 0 0x82000000 u-boot.img
+	U-Boot # nand write 0x82000000 0x80000 0x60000
+	# flash kernel image
+	U-Boot # load mmc 0 0x82000000 uImage
+	U-Boot # nand write 0x82000000 ${nandsrcaddr} ${nandimgsize}
+	# flash filesystem image
+	U-Boot # load mmc 0 0x82000000 filesystem.img
+	U-Boot # nand write 0x82000000 ${loadaddress} 0x300000
+
+Step-3: Set BOOTSEL pin to select NAND boot, and POR the device.
+	The device should boot from images flashed on NAND device.
 
 NOR
 ===
-- 
1.8.1

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

* [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver
  2013-11-19  5:32 [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver Pekon Gupta
                   ` (3 preceding siblings ...)
  2013-11-19  5:32 ` [U-Boot] [PATCH v9 4/4] board/ti/am335x/README: update for NAND boot Pekon Gupta
@ 2013-11-19 11:27 ` Abraham V.
  2013-11-19 12:04   ` Gupta, Pekon
  2013-11-19 12:13 ` Ezequiel Garcia
  2013-12-06  6:22 ` Gupta, Pekon
  6 siblings, 1 reply; 10+ messages in thread
From: Abraham V. @ 2013-11-19 11:27 UTC (permalink / raw)
  To: u-boot

On Tue, Nov 19, 2013 at 11:02 AM, Pekon Gupta <pekon@ti.com> wrote:

>
> OMAP NAND drivers support various ecc-schemes like (HAM1, BCH4, BCH8..)
> And, each ecc-scheme usually has 2 implementations
>  - HAM1_HW or BCHx_HW (using in-build h/w engine for all computation)
>  - HAM1_SW or BCHx_HW_DETECTION_SW) (using software library for some
> computation)
>

If I make similar changes as these patches suggest, would I be able to
enable NAND support for OMAP4-based boards as well? (OMAP 4460) Or are some
additional changes needed to support NAND on the next OMAP version?

-Abraham V.

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

* [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver
  2013-11-19 11:27 ` [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver Abraham V.
@ 2013-11-19 12:04   ` Gupta, Pekon
  0 siblings, 0 replies; 10+ messages in thread
From: Gupta, Pekon @ 2013-11-19 12:04 UTC (permalink / raw)
  To: u-boot

Hi,

> From: Abraham V. [abraham.varricatt at vvdntech.com]
> > Pekon Gupta <pekon@ti.com> wrote:
> > OMAP NAND drivers support various ecc-schemes like (HAM1, BCH4, BCH8..)
> > And, each ecc-scheme usually has 2 implementations
> >  - HAM1_HW or BCHx_HW (using in-build h/w engine for all computation)
> >  - HAM1_SW or BCHx_HW_DETECTION_SW) (using software library for some computation)

> If I make similar changes as these patches suggest, would I 
> be able to enable NAND support for OMAP4-based boards
> as well? (OMAP 4460) Or are some additional changes needed
> to support NAND on the next OMAP version?
> 
drivers/mtd/nand/omap-gpmc.c is common driver for all OMAP and
AMxxxx platforms like AM33xx, OMAP3, OMAP4, OMAP5.
So these patches would work with OMAP4 also.
You need to just enable GPMC and ELM drivers for OMAP4 board.
And update your board file.
- #define CONFIG_NAND_OMAP_GPMC: enables GPMC driver
- #define CONFIG_NAND_OMAP_ELM: enables ELM driver
As there is no OMAP4 board with NAND flash on it, so these driver
are not enabled by default.

Following steps should help you proceed...
Step-1: As reference copy whatever is under 'CONFIG_NAND' in 
include/configs/am335x_evm.h  include/configs/<your_board.h>
Step-2: update CONFIG_xx_NAND_yy for device on your board
Step-3: add pin-mux for NAND.
Step-4: update arch/arm/cpu/armv7/omap-common/mem-common.c
  (if required)


with regards, pekon

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

* [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver
  2013-11-19  5:32 [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver Pekon Gupta
                   ` (4 preceding siblings ...)
  2013-11-19 11:27 ` [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver Abraham V.
@ 2013-11-19 12:13 ` Ezequiel Garcia
  2013-12-06  6:22 ` Gupta, Pekon
  6 siblings, 0 replies; 10+ messages in thread
From: Ezequiel Garcia @ 2013-11-19 12:13 UTC (permalink / raw)
  To: u-boot

On Tue, Nov 19, 2013 at 11:02:14AM +0530, Pekon Gupta wrote:
> 
> OMAP NAND drivers support various ecc-schemes like (HAM1, BCH4, BCH8..)
> And, each ecc-scheme usually has 2 implementations 
>  - HAM1_HW or BCHx_HW (using in-build h/w engine for all computation)
>  - HAM1_SW or BCHx_HW_DETECTION_SW) (using software library for some computation)
> 
[..]
> 
> 
> Pekon Gupta (4):
>   mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes
>   mtd: nand: omap: optimize chip->ecc.calculate() for H/W ECC schemes
>   mtd: nand: omap: optimized chip->ecc.correct() for H/W ECC schemes
>   board/ti/am335x/README: update for NAND boot
> 
>  arch/arm/include/asm/omap_gpmc.h |   7 -
>  board/ti/am335x/README           |  53 ++--
>  drivers/mtd/nand/omap_gpmc.c     | 565 +++++++++++++--------------------------
>  3 files changed, 217 insertions(+), 408 deletions(-)
> 

Tested-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>

-- 
Ezequiel Garc?a, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com

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

* [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver
  2013-11-19  5:32 [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver Pekon Gupta
                   ` (5 preceding siblings ...)
  2013-11-19 12:13 ` Ezequiel Garcia
@ 2013-12-06  6:22 ` Gupta, Pekon
  2013-12-06  7:00   ` Stefan Roese
  6 siblings, 1 reply; 10+ messages in thread
From: Gupta, Pekon @ 2013-12-06  6:22 UTC (permalink / raw)
  To: u-boot

Hello Scott,

>From: Gupta, Pekon
>Subject: [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver
>
>OMAP NAND drivers support various ecc-schemes like (HAM1, BCH4, BCH8..)
>And, each ecc-scheme usually has 2 implementations
> - HAM1_HW or BCHx_HW (using in-build h/w engine for all computation)
> - HAM1_SW or BCHx_HW_DETECTION_SW) (using software library for some computation)
>
>This patch series is Part-2 (split) from earlier series, as mentioned below:
>http://lists.denx.de/pipermail/u-boot/2013-November/167270.html
>
>This series aims at following:
> - cleans-up redundant code, duplicate in different ecc-schemes
> - optimizes ecc calculation and correction paths
> - improves scalability and readability, for adding newer ecc-schemes in future.
> - updates following callbacks for different ecc-schmes:
> [PATCH 1/4] nand_chip->ecc.hwctl(): configures h/w controller before for Read/Write acccess
> [PATCH 2/4] nand_chip->ecc.calculate(): calculates and fetches ECC syndrome from h/w controller.
> [PATCH 3/4] nand_chip->ecc.correct(): detects and corrects ECC errors on read access
> [PATCH 4/4] update doc and README
>
>
>*changes in v9*
> - split from main series, rebased and forked independently
>

Request you to please review this series. And accept it if it looks okay.

And a bug-fix which causes regression for x8 NAND devices 
using HAM1 ecc-scheme. This was reported & (un-officially) 
tested by Stefan Roese <sr@denx.de>.


with regards, pekon

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

* [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver
  2013-12-06  6:22 ` Gupta, Pekon
@ 2013-12-06  7:00   ` Stefan Roese
  0 siblings, 0 replies; 10+ messages in thread
From: Stefan Roese @ 2013-12-06  7:00 UTC (permalink / raw)
  To: u-boot

On 06.12.2013 07:22, Gupta, Pekon wrote:
>> From: Gupta, Pekon
>> Subject: [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver
>>
>> OMAP NAND drivers support various ecc-schemes like (HAM1, BCH4, BCH8..)
>> And, each ecc-scheme usually has 2 implementations
>> - HAM1_HW or BCHx_HW (using in-build h/w engine for all computation)
>> - HAM1_SW or BCHx_HW_DETECTION_SW) (using software library for some computation)
>>
>> This patch series is Part-2 (split) from earlier series, as mentioned below:
>> http://lists.denx.de/pipermail/u-boot/2013-November/167270.html
>>
>> This series aims at following:
>> - cleans-up redundant code, duplicate in different ecc-schemes
>> - optimizes ecc calculation and correction paths
>> - improves scalability and readability, for adding newer ecc-schemes in future.
>> - updates following callbacks for different ecc-schmes:
>> [PATCH 1/4] nand_chip->ecc.hwctl(): configures h/w controller before for Read/Write acccess
>> [PATCH 2/4] nand_chip->ecc.calculate(): calculates and fetches ECC syndrome from h/w controller.
>> [PATCH 3/4] nand_chip->ecc.correct(): detects and corrects ECC errors on read access
>> [PATCH 4/4] update doc and README
>>
>>
>> *changes in v9*
>> - split from main series, rebased and forked independently
>>
> 
> Request you to please review this series. And accept it if it looks okay.
> 
> And a bug-fix which causes regression for x8 NAND devices 
> using HAM1 ecc-scheme. This was reported & (un-officially) 
> tested by Stefan Roese <sr@denx.de>.

I tested this patch series plus the fix from Pekon on an x8 and x16
OMAP3530 board. Both without any problems. So for this series:

Tested-by: Stefan Roese <sr@denx.de>

Thanks,
Stefan

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

end of thread, other threads:[~2013-12-06  7:00 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-11-19  5:32 [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver Pekon Gupta
2013-11-19  5:32 ` [U-Boot] [PATCH v9 1/4] mtd: nand: omap: optimize chip->ecc.hwctl() for H/W ECC schemes Pekon Gupta
2013-11-19  5:32 ` [U-Boot] [PATCH v9 2/4] mtd: nand: omap: optimize chip->ecc.calculate() " Pekon Gupta
2013-11-19  5:32 ` [U-Boot] [PATCH v9 3/4] mtd: nand: omap: optimized chip->ecc.correct() " Pekon Gupta
2013-11-19  5:32 ` [U-Boot] [PATCH v9 4/4] board/ti/am335x/README: update for NAND boot Pekon Gupta
2013-11-19 11:27 ` [U-Boot] [PATCH v9 0/4] mtd: nand: omap: optimize OMAP NAND driver Abraham V.
2013-11-19 12:04   ` Gupta, Pekon
2013-11-19 12:13 ` Ezequiel Garcia
2013-12-06  6:22 ` Gupta, Pekon
2013-12-06  7:00   ` Stefan Roese

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox