public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [RFC/PATCH 0/4] BCH8 support for OMAP3
@ 2012-11-23 15:14 Andreas Bießmann
  2012-11-23 15:14 ` [U-Boot] [RFC/PATCH 1/4] omap3/cpu.h: add BCH support Andreas Bießmann
                   ` (5 more replies)
  0 siblings, 6 replies; 32+ messages in thread
From: Andreas Bießmann @ 2012-11-23 15:14 UTC (permalink / raw)
  To: u-boot

This RFC series implements BCH8 for OMAP3 as provided by linux kernel in commit
0e618ef0a6a33cf7ef96c2c824402088dd8ef48c.
This series is heavily influenced by Ilyas series 'NAND support for AM33XX'
thus could share some code.

I have managed to load kernel from an ubifs written by the kernel driver, but is
far away from tested thoroughly.

Cause my NAND device 'NAND device: Manufacturer ID: 0x2c, Chip ID: 0xbc (Micron
NAND 512MiB 1,8V 16-bit)' does support 1bit ECC for first sector if erase is
less than 1000, the rest requires 4bit ECC. Therefore the SPL needs to support
BCH, the impact is about 9k for the SPL.

Andreas Bie?mann (4):
  omap3/cpu.h: add BCH support
  omap3/omap_gpmc.h: add ooblayout for BCH8 as in kernel
  omap_gpmc: add support for hw assisted BCH8
  tricorder: enable hw assisted BCH8 in SPL and u-boot

 arch/arm/cpu/armv7/omap3/board.c            |    8 +-
 arch/arm/include/asm/arch-omap3/cpu.h       |    6 +
 arch/arm/include/asm/arch-omap3/omap_gpmc.h |   12 ++
 drivers/mtd/nand/omap_gpmc.c                |  216 ++++++++++++++++++++++++++-
 include/configs/tricorder.h                 |   10 +-
 lib/Makefile                                |    3 +-
 6 files changed, 248 insertions(+), 7 deletions(-)

-- 
1.7.10.4

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

* [U-Boot] [RFC/PATCH 1/4] omap3/cpu.h: add BCH support
  2012-11-23 15:14 [U-Boot] [RFC/PATCH 0/4] BCH8 support for OMAP3 Andreas Bießmann
@ 2012-11-23 15:14 ` Andreas Bießmann
  2012-11-23 15:14 ` [U-Boot] [RFC/PATCH 2/4] omap3/omap_gpmc.h: add ooblayout for BCH8 as in kernel Andreas Bießmann
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 32+ messages in thread
From: Andreas Bießmann @ 2012-11-23 15:14 UTC (permalink / raw)
  To: u-boot

This patch adds the BCH result registers to register mapping for OMAP3 gpmc.

Signed-off-by: Andreas Bie?mann <andreas.devel@googlemail.com>
Cc: Tom Rini <trini@ti.com>
Cc: Ilya Yanok <ilya.yanok@cogentembedded.com>
Cc: Scott Wood <scottwood@freescale.com>
---
 arch/arm/include/asm/arch-omap3/cpu.h |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/include/asm/arch-omap3/cpu.h b/arch/arm/include/asm/arch-omap3/cpu.h
index 5683e16..c601873 100644
--- a/arch/arm/include/asm/arch-omap3/cpu.h
+++ b/arch/arm/include/asm/arch-omap3/cpu.h
@@ -109,6 +109,10 @@ struct gpmc_cs {
 	u8 res[8];		/* blow up to 0x30 byte */
 };
 
+struct bch_res_0_3 {
+	u32 bch_result_x[4];
+};
+
 struct gpmc {
 	u8 res1[0x10];
 	u32 sysconfig;		/* 0x10 */
@@ -135,6 +139,8 @@ struct gpmc {
 	u32 ecc7_result;	/* 0x218 */
 	u32 ecc8_result;	/* 0x21C */
 	u32 ecc9_result;	/* 0x220 */
+	u8 res7[0x1C];		/* fill up to 0x240 */
+	struct bch_res_0_3 bch_result_0_3[7];	/* 0x240 */
 };
 
 /* Used for board specific gpmc initialization */
-- 
1.7.10.4

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

* [U-Boot] [RFC/PATCH 2/4] omap3/omap_gpmc.h: add ooblayout for BCH8 as in kernel
  2012-11-23 15:14 [U-Boot] [RFC/PATCH 0/4] BCH8 support for OMAP3 Andreas Bießmann
  2012-11-23 15:14 ` [U-Boot] [RFC/PATCH 1/4] omap3/cpu.h: add BCH support Andreas Bießmann
@ 2012-11-23 15:14 ` Andreas Bießmann
  2012-11-23 15:14 ` [U-Boot] [RFC/PATCH 3/4] omap_gpmc: add support for hw assisted BCH8 Andreas Bießmann
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 32+ messages in thread
From: Andreas Bießmann @ 2012-11-23 15:14 UTC (permalink / raw)
  To: u-boot

This patch adds BCH8 ooblayout for NAND as provided by
0e618ef0a6a33cf7ef96c2c824402088dd8ef48c in linux kernel. This Layout is
currently only provided for 64 byte OOB.

Signed-off-by: Andreas Bie?mann <andreas.devel@googlemail.com>
Cc: Tom Rini <trini@ti.com>
Cc: Ilya Yanok <ilya.yanok@cogentembedded.com>
Cc: Scott Wood <scottwood@freescale.com>
---
 arch/arm/include/asm/arch-omap3/omap_gpmc.h |   12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/arm/include/asm/arch-omap3/omap_gpmc.h b/arch/arm/include/asm/arch-omap3/omap_gpmc.h
index 800e4ee..3a3abdf 100644
--- a/arch/arm/include/asm/arch-omap3/omap_gpmc.h
+++ b/arch/arm/include/asm/arch-omap3/omap_gpmc.h
@@ -80,6 +80,18 @@
 }
 #endif
 
+/* use the same layout here as he kernel does (ecc bytes at oob tail) */
+#define GPMC_NAND_HW_BCH8_ECC_LAYOUT {\
+	.eccbytes = 56,\
+	.eccpos = {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,\
+			23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,\
+			37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,\
+			51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63},\
+	.oobfree = {\
+		{.offset = 2,\
+		 .length = 10 } } \
+}
+
 /* GPMC CS configuration for an SMSC LAN9221 ethernet controller */
 #define NET_LAN9221_GPMC_CONFIG1    0x00001000
 #define NET_LAN9221_GPMC_CONFIG2    0x00060700
-- 
1.7.10.4

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

* [U-Boot] [RFC/PATCH 3/4] omap_gpmc: add support for hw assisted BCH8
  2012-11-23 15:14 [U-Boot] [RFC/PATCH 0/4] BCH8 support for OMAP3 Andreas Bießmann
  2012-11-23 15:14 ` [U-Boot] [RFC/PATCH 1/4] omap3/cpu.h: add BCH support Andreas Bießmann
  2012-11-23 15:14 ` [U-Boot] [RFC/PATCH 2/4] omap3/omap_gpmc.h: add ooblayout for BCH8 as in kernel Andreas Bießmann
@ 2012-11-23 15:14 ` Andreas Bießmann
  2012-11-26 21:09   ` Scott Wood
  2012-11-23 15:14 ` [U-Boot] [RFC/PATCH 4/4] tricorder: enable hw assisted BCH8 in SPL and u-boot Andreas Bießmann
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 32+ messages in thread
From: Andreas Bießmann @ 2012-11-23 15:14 UTC (permalink / raw)
  To: u-boot

The BCH for OMAP3 is implemented as the linux kernel in
0e618ef0a6a33cf7ef96c2c824402088dd8ef48c does.

The kernel states:

---8<---
The OMAP3 GPMC hardware BCH engine computes remainder polynomials, it does not
provide automatic error location and correction: this step is implemented using
the BCH library.
--->8---

And we do so in u-boot.

This implementation uses the same layout for BCH8 but it is fix. The current
provided layout does only work with 64 Byte OOB.

Signed-off-by: Andreas Bie?mann <andreas.devel@googlemail.com>
Cc: Tom Rini <trini@ti.com>
Cc: Ilya Yanok <ilya.yanok@cogentembedded.com>
Cc: Scott Wood <scottwood@freescale.com>
---
This patch has some debug stuff in which should be cleaned up.

 arch/arm/cpu/armv7/omap3/board.c |    8 +-
 drivers/mtd/nand/omap_gpmc.c     |  216 +++++++++++++++++++++++++++++++++++++-
 lib/Makefile                     |    3 +-
 3 files changed, 223 insertions(+), 4 deletions(-)

diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c
index f3cd81a..22286c0 100644
--- a/arch/arm/cpu/armv7/omap3/board.c
+++ b/arch/arm/cpu/armv7/omap3/board.c
@@ -330,8 +330,10 @@ static int do_switch_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char * const arg
 {
 	if (argc != 2)
 		goto usage;
-	if (strncmp(argv[1], "hw", 2) == 0)
+	if (strncmp(argv[1], "hw1", 3) == 0)
 		omap_nand_switch_ecc(1);
+	else if (strncmp(argv[1], "hw2", 3) == 0)
+		omap_nand_switch_ecc(2);
 	else if (strncmp(argv[1], "sw", 2) == 0)
 		omap_nand_switch_ecc(0);
 	else
@@ -347,7 +349,9 @@ usage:
 U_BOOT_CMD(
 	nandecc, 2, 1,	do_switch_ecc,
 	"switch OMAP3 NAND ECC calculation algorithm",
-	"[hw/sw] - Switch between NAND hardware (hw) or software (sw) ecc algorithm"
+	"[hw1/hw2/sw] - Switch between NAND hardware (hw1 - 1bit hamming),\n"
+	"\tNAND hardware assisted BCH8 (hw2 - 8bit BCH)\n"
+	"\tor software (sw) ecc algorithm"
 );
 
 #endif /* CONFIG_NAND_OMAP_GPMC & !CONFIG_SPL_BUILD */
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index f1469d1..a5ab046 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -27,6 +27,7 @@
 #include <asm/arch/mem.h>
 #include <asm/arch/omap_gpmc.h>
 #include <linux/mtd/nand_ecc.h>
+#include <linux/bch.h>
 #include <linux/compiler.h>
 #include <nand.h>
 
@@ -234,12 +235,194 @@ static void __maybe_unused omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
 	}
 }
 
+/*
+ * basic BCH8 support
+ */
+#ifdef CONFIG_NAND_OMAP_BCH8
+static struct nand_ecclayout hw_bch8_nand_oob = GPMC_NAND_HW_BCH8_ECC_LAYOUT;
+
+/*
+ * omap_init_hwecc_bch - Initialize the BCH Hardware ECC for NAND flash in
+ *				GPMC controller
+ * @mtd:	MTD device structure
+ * @mode:	Read/Write mode
+ */
+static void omap_init_hwecc_bch(struct nand_chip *chip, int32_t mode)
+{
+	uint32_t val, dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
+
+	/* Clear the ecc result registers, select ecc reg as 1 */
+	writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
+
+	/*
+	 * When using BCH, sector size is hardcoded to 512 bytes.
+	 * 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)
+	 */
+	writel((32 << 22) | (0 << 12), &gpmc_cfg->ecc_size_config);
+
+	/* BCH configuration */
+	val = ((1                        << 16) | /* enable BCH */
+	       (1                        << 12) | /* set fix to BCH8 */
+	       (0x06                     <<  8) | /* wrap mode = 6 */
+	       (dev_width                <<  7) | /* bus width */
+	       (0                        <<  4) | /* number of sectors (we use 1 sector)*/
+	       (cs                       <<  1) | /* ECC CS */
+	       (0x1));                            /* enable ECC */
+//	debug("set ECC_CONFIG = 0x%08x\n", val);
+	writel(val, &gpmc_cfg->ecc_config);
+}
+
+/**
+ * omap3_enable_hwecc_bch - Program OMAP3 GPMC to perform BCH ECC correction
+ * @mtd: MTD device structure
+ * @mode: Read/Write mode
+ */
+static void omap_enable_hwecc_bch(struct mtd_info *mtd, int32_t mode)
+{
+	struct nand_chip *chip = mtd->priv;
+
+	omap_init_hwecc_bch(chip, mode);
+	/* enable ecc */
+	writel((readl(&gpmc_cfg->ecc_config) | 0x1), &gpmc_cfg->ecc_config);
+}
+
+/*
+ * omap_ecc_disable - Disable H/W ECC calculation
+ *
+ * @mtd:	MTD device structure
+ *
+ */
+static void omap_ecc_disable(struct mtd_info *mtd)
+{
+	writel((readl(&gpmc_cfg->ecc_config) & ~0x1),
+		&gpmc_cfg->ecc_config);
+}
+
+/*
+ *  omap_calculate_ecc_bch - 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(struct mtd_info *mtd, const uint8_t *dat,
+				uint8_t *ecc)
+{
+	int ret = 0;
+	size_t i;
+	unsigned long nsectors, val1, val2, val3, val4;
+	uint8_t *pecc = ecc;
+
+	nsectors = ((readl(&gpmc_cfg->ecc_config) >> 4) & 0x7) + 1;
+
+	for (i = 0; i < nsectors; i++) {
+#if 0
+	debug("read res0 @%p, res1 @%p, res2 @%p, res4 @%p\n",
+			&gpmc_cfg->bch_result_0_3[i].bch_result_x[0],
+			&gpmc_cfg->bch_result_0_3[i].bch_result_x[1],
+			&gpmc_cfg->bch_result_0_3[i].bch_result_x[2],
+			&gpmc_cfg->bch_result_0_3[i].bch_result_x[3]);
+#endif
+
+		/* 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]);
+//		debug("val1 = 0x%08lx, val2 = 0x%08lx, val3 = 0x%08lx, val4 = 0x%08lx\n", val1, val2, val3, val4);
+
+		/*
+		 * 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);
+#if 0
+		debug("ecc: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+		    pecc[0], pecc[1], pecc[2], pecc[3], pecc[4], pecc[5], pecc[6],
+		    pecc[7], pecc[8], pecc[9], pecc[10], pecc[11], pecc[12]);
+#endif
+}
+
+	/*
+	 * 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 - Decode received data and correct errors
+ * @mtd: MTD device structure
+ * @data: page data
+ * @read_ecc: ecc read from nand flash
+ * @calc_ecc: ecc read from HW ECC registers
+ */
+static int omap_correct_data_bch(struct mtd_info *mtd, u_char *data,
+				 u_char *read_ecc, u_char *calc_ecc)
+{
+	int i, count;
+	/* cannot correct more than 8 errors */
+	unsigned int errloc[8];
+	struct nand_chip *chip = mtd->priv;
+	struct bch_control *bch = chip->priv;
+
+	count = decode_bch(bch, NULL, 512, read_ecc, calc_ecc, NULL, errloc);
+	if (count > 0) {
+		/* correct errors */
+		for (i = 0; i < count; i++) {
+			/* correct data only, not ecc bytes */
+			if (errloc[i] < 8*512)
+				data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
+			printf("corrected bitflip %u\n", errloc[i]);
+			debug("read_ecc: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+			      read_ecc[0], read_ecc[1], read_ecc[2], read_ecc[3], read_ecc[4], read_ecc[5], read_ecc[6],
+			      read_ecc[7], read_ecc[8], read_ecc[9], read_ecc[10], read_ecc[11], read_ecc[12]);
+			debug("calc_ecc: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+			      calc_ecc[0], calc_ecc[1], calc_ecc[2], calc_ecc[3], calc_ecc[4], calc_ecc[5], calc_ecc[6],
+			      calc_ecc[7], calc_ecc[8], calc_ecc[9], calc_ecc[10], calc_ecc[11], calc_ecc[12]);
+		}
+	} else if (count < 0) {
+		puts("ecc unrecoverable error\n");
+	}
+	return count;
+}
+
+/**
+ * omap_free_bch - Release BCH ecc resources
+ * @mtd: MTD device structure
+ */
+static void omap_free_bch(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	if (chip->priv) {
+		free_bch((struct bch_control *)chip->priv);
+		chip->priv = NULL;
+	}
+}
+#endif /* CONFIG_NAND_OMAP_BCH8 */
+
 #ifndef CONFIG_SPL_BUILD
 /*
  * omap_nand_switch_ecc - switch the ECC operation b/w h/w ecc and s/w ecc.
  * The default is to come up on s/w ecc
  *
- * @hardware - 1 -switch to h/w ecc, 0 - s/w ecc
+ * @hardware - 1 -switch to h/w ecc, 2 - switch to h/w assisted BCH8, 0 - s/w ecc
  *
  */
 void omap_nand_switch_ecc(int32_t hardware)
@@ -279,6 +462,18 @@ void omap_nand_switch_ecc(int32_t hardware)
 		nand->ecc.calculate = omap_calculate_ecc;
 		omap_hwecc_init(nand);
 		printf("HW ECC selected\n");
+#ifdef CONFIG_NAND_OMAP_BCH8
+	} else if (hardware == 2) {
+		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_hwecc_bch;
+		nand->ecc.correct = omap_correct_data_bch;
+		nand->ecc.calculate = omap_calculate_ecc_bch;
+		omap_init_hwecc_bch(nand, NAND_ECC_READ);
+		printf("HW BCH8 selected\n");
+#endif
 	} else {
 		nand->ecc.mode = NAND_ECC_SOFT;
 		/* Use mtd default settings */
@@ -313,6 +508,7 @@ int board_nand_init(struct nand_chip *nand)
 {
 	int32_t gpmc_config = 0;
 	cs = 0;
+	nand->priv = NULL;
 
 	/*
 	 * xloader/Uboot's gpmc configuration would have configured GPMC for
@@ -351,6 +547,23 @@ int board_nand_init(struct nand_chip *nand)
 
 	nand->chip_delay = 100;
 	/* Default ECC mode */
+#ifdef CONFIG_NAND_OMAP_BCH8
+	nand->priv = init_bch(13, 8, 0x201b /* hw polynominal */);
+	if (!nand->priv) {
+		puts("Could not init_bch()\n");
+	}
+#endif
+
+#if 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.hwctl = omap_enable_hwecc_bch;
+	nand->ecc.correct = omap_correct_data_bch;
+	nand->ecc.calculate = omap_calculate_ecc_bch;
+	omap_init_hwecc_bch(nand, NAND_ECC_READ);
+#else
 #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_NAND_SOFTECC)
 	nand->ecc.mode = NAND_ECC_SOFT;
 #else
@@ -363,6 +576,7 @@ int board_nand_init(struct nand_chip *nand)
 	nand->ecc.calculate = omap_calculate_ecc;
 	omap_hwecc_init(nand);
 #endif
+#endif
 
 #ifdef CONFIG_SPL_BUILD
 	if (nand->options & NAND_BUSWIDTH_16)
diff --git a/lib/Makefile b/lib/Makefile
index e44e045..20cc40c 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -25,9 +25,10 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)libgeneric.o
 
+COBJS-$(CONFIG_BCH) += bch.o
+
 ifndef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_ADDR_MAP) += addr_map.o
-COBJS-$(CONFIG_BCH) += bch.o
 COBJS-$(CONFIG_AES) += aes.o
 COBJS-$(CONFIG_BZIP2) += bzlib.o
 COBJS-$(CONFIG_BZIP2) += bzlib_crctable.o
-- 
1.7.10.4

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

* [U-Boot] [RFC/PATCH 4/4] tricorder: enable hw assisted BCH8 in SPL and u-boot
  2012-11-23 15:14 [U-Boot] [RFC/PATCH 0/4] BCH8 support for OMAP3 Andreas Bießmann
                   ` (2 preceding siblings ...)
  2012-11-23 15:14 ` [U-Boot] [RFC/PATCH 3/4] omap_gpmc: add support for hw assisted BCH8 Andreas Bießmann
@ 2012-11-23 15:14 ` Andreas Bießmann
  2013-03-28 10:49 ` [U-Boot] [RFC/PATCH 0/4] BCH8 support for OMAP3 Andreas Bießmann
  2013-04-02 16:05 ` [U-Boot] [PATCH v2 1/6] omap3/cpu.h: add BCH support Andreas Bießmann
  5 siblings, 0 replies; 32+ messages in thread
From: Andreas Bießmann @ 2012-11-23 15:14 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Andreas Bie?mann <andreas.devel@googlemail.com>
Cc: Tom Rini <trini@ti.com>
Cc: Thomas Weber <weber@corscience.de>
Cc: Ilya Yanok <ilya.yanok@cogentembedded.com>
Cc: Scott Wood <scottwood@freescale.com>
---
 include/configs/tricorder.h |   10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/include/configs/tricorder.h b/include/configs/tricorder.h
index 4e4e089..9b8fe14 100644
--- a/include/configs/tricorder.h
+++ b/include/configs/tricorder.h
@@ -128,6 +128,8 @@
 
 #define CONFIG_SYS_MAX_NAND_DEVICE	1		/* Max number of NAND */
 							/* devices */
+#define CONFIG_NAND_OMAP_BCH8
+#define CONFIG_BCH
 
 /* commands to include */
 #include <config_cmd_default.h>
@@ -354,11 +356,13 @@
 #define CONFIG_SYS_NAND_OOBSIZE		64
 #define CONFIG_SYS_NAND_BLOCK_SIZE	(128*1024)
 #define CONFIG_SYS_NAND_BAD_BLOCK_POS	NAND_LARGE_BADBLOCK_POS
-#define CONFIG_SYS_NAND_ECCPOS		{2, 3, 4, 5, 6, 7, 8, 9,\
-						10, 11, 12, 13}
+#define CONFIG_SYS_NAND_ECCPOS		{12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,\
+			23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,\
+			37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,\
+			51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63}
 
 #define CONFIG_SYS_NAND_ECCSIZE		512
-#define CONFIG_SYS_NAND_ECCBYTES	3
+#define CONFIG_SYS_NAND_ECCBYTES	13
 
 #define CONFIG_SYS_NAND_U_BOOT_START	CONFIG_SYS_TEXT_BASE
 
-- 
1.7.10.4

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

* [U-Boot] [RFC/PATCH 3/4] omap_gpmc: add support for hw assisted BCH8
  2012-11-23 15:14 ` [U-Boot] [RFC/PATCH 3/4] omap_gpmc: add support for hw assisted BCH8 Andreas Bießmann
@ 2012-11-26 21:09   ` Scott Wood
  0 siblings, 0 replies; 32+ messages in thread
From: Scott Wood @ 2012-11-26 21:09 UTC (permalink / raw)
  To: u-boot

On 11/23/2012 09:14:16 AM, Andreas Bie?mann wrote:
> diff --git a/arch/arm/cpu/armv7/omap3/board.c  
> b/arch/arm/cpu/armv7/omap3/board.c
> index f3cd81a..22286c0 100644
> --- a/arch/arm/cpu/armv7/omap3/board.c
> +++ b/arch/arm/cpu/armv7/omap3/board.c
> @@ -330,8 +330,10 @@ static int do_switch_ecc(cmd_tbl_t * cmdtp, int  
> flag, int argc, char * const arg
>  {
>  	if (argc != 2)
>  		goto usage;
> -	if (strncmp(argv[1], "hw", 2) == 0)
> +	if (strncmp(argv[1], "hw1", 3) == 0)
>  		omap_nand_switch_ecc(1);
> +	else if (strncmp(argv[1], "hw2", 3) == 0)
> +		omap_nand_switch_ecc(2);
>  	else if (strncmp(argv[1], "sw", 2) == 0)
>  		omap_nand_switch_ecc(0);
>  	else

Will this break any existing scripts?  Maybe "hw" should be left alone  
and "hw2" renamed to something more descriptive (e.g. "bch8")?

> @@ -347,7 +349,9 @@ usage:
>  U_BOOT_CMD(
>  	nandecc, 2, 1,	do_switch_ecc,
>  	"switch OMAP3 NAND ECC calculation algorithm",
> -	"[hw/sw] - Switch between NAND hardware (hw) or software (sw)  
> ecc algorithm"
> +	"[hw1/hw2/sw] - Switch between NAND hardware (hw1 - 1bit  
> hamming),\n"
> +	"\tNAND hardware assisted BCH8 (hw2 - 8bit BCH)\n"
> +	"\tor software (sw) ecc algorithm"
>  );
> 
>  #endif /* CONFIG_NAND_OMAP_GPMC & !CONFIG_SPL_BUILD */
> diff --git a/drivers/mtd/nand/omap_gpmc.c  
> b/drivers/mtd/nand/omap_gpmc.c
> index f1469d1..a5ab046 100644
> --- a/drivers/mtd/nand/omap_gpmc.c
> +++ b/drivers/mtd/nand/omap_gpmc.c
> @@ -27,6 +27,7 @@
>  #include <asm/arch/mem.h>
>  #include <asm/arch/omap_gpmc.h>
>  #include <linux/mtd/nand_ecc.h>
> +#include <linux/bch.h>
>  #include <linux/compiler.h>
>  #include <nand.h>
> 
> @@ -234,12 +235,194 @@ static void __maybe_unused  
> omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
>  	}
>  }
> 
> +/*
> + * basic BCH8 support
> + */
> +#ifdef CONFIG_NAND_OMAP_BCH8
> +static struct nand_ecclayout hw_bch8_nand_oob =  
> GPMC_NAND_HW_BCH8_ECC_LAYOUT;

Is this layout going to be used anywhere other than here?  If not, why  
hide the layout in a #define?

> +
> +/*
> + * omap_init_hwecc_bch - Initialize the BCH Hardware ECC for NAND  
> flash in
> + *				GPMC controller
> + * @mtd:	MTD device structure
> + * @mode:	Read/Write mode
> + */
> +static void omap_init_hwecc_bch(struct nand_chip *chip, int32_t mode)
> +{
> +	uint32_t val, dev_width = (chip->options & NAND_BUSWIDTH_16) >>  
> 1;
> +
> +	/* Clear the ecc result registers, select ecc reg as 1 */
> +	writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
> +
> +	/*
> +	 * When using BCH, sector size is hardcoded to 512 bytes.
> +	 * 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)
> +	 */
> +	writel((32 << 22) | (0 << 12), &gpmc_cfg->ecc_size_config);
> +
> +	/* BCH configuration */
> +	val = ((1                        << 16) | /* enable BCH */
> +	       (1                        << 12) | /* set fix to BCH8 */
> +	       (0x06                     <<  8) | /* wrap mode = 6 */
> +	       (dev_width                <<  7) | /* bus width */
> +	       (0                        <<  4) | /* number of sectors  
> (we use 1 sector)*/
> +	       (cs                       <<  1) | /* ECC CS */
> +	       (0x1));                            /* enable ECC */

Most of those magic numbers should be referred to symbolicly.

> +static void omap_free_bch(struct mtd_info *mtd)
> +{
> +	struct nand_chip *chip = mtd->priv;
> +	if (chip->priv) {
> +		free_bch((struct bch_control *)chip->priv);
> +		chip->priv = NULL;
> +	}

Do you really need this cast?

> +#ifdef CONFIG_NAND_OMAP_BCH8
> +	nand->priv = init_bch(13, 8, 0x201b /* hw polynominal */);
> +	if (!nand->priv) {
> +		puts("Could not init_bch()\n");
> +	}
> +#endif
> +
> +#if defined CONFIG_NAND_OMAP_BCH8

Merge these two ifdef sections.

Shouldn't you take some action on the failure case other than printing  
a message and continuing to try to use bch8?

-Scott

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

* [U-Boot] [RFC/PATCH 0/4] BCH8 support for OMAP3
  2012-11-23 15:14 [U-Boot] [RFC/PATCH 0/4] BCH8 support for OMAP3 Andreas Bießmann
                   ` (3 preceding siblings ...)
  2012-11-23 15:14 ` [U-Boot] [RFC/PATCH 4/4] tricorder: enable hw assisted BCH8 in SPL and u-boot Andreas Bießmann
@ 2013-03-28 10:49 ` Andreas Bießmann
  2013-03-28 14:21   ` Tom Rini
  2013-04-02 16:05 ` [U-Boot] [PATCH v2 1/6] omap3/cpu.h: add BCH support Andreas Bießmann
  5 siblings, 1 reply; 32+ messages in thread
From: Andreas Bießmann @ 2013-03-28 10:49 UTC (permalink / raw)
  To: u-boot

On 11/23/2012 04:14 PM, Andreas Bie?mann wrote:
> This RFC series implements BCH8 for OMAP3 as provided by linux kernel in commit
> 0e618ef0a6a33cf7ef96c2c824402088dd8ef48c.
> This series is heavily influenced by Ilyas series 'NAND support for AM33XX'
> thus could share some code.

Any comments on that series? I would appreciate to get the BCH8 support
in for at least the tricorder board.

> I have managed to load kernel from an ubifs written by the kernel driver, but is
> far away from tested thoroughly.

We used that patchset for a while in-house and could not find obvious
issues. However we need to hack the SPL a bit to get the bigger
footprint into SRAM with 2013.01.
I would really appreciate if some other omap users could test it.
One thing is that most current NAND (even SLC) devices require at least
4Bit ecc for most sections.

> Cause my NAND device 'NAND device: Manufacturer ID: 0x2c, Chip ID: 0xbc (Micron
> NAND 512MiB 1,8V 16-bit)' does support 1bit ECC for first sector if erase is
> less than 1000, the rest requires 4bit ECC. Therefore the SPL needs to support
> BCH, the impact is about 9k for the SPL.

So my question here is if this series would be accepted for the upcoming
release. I could work on it next week full time, so if I get a go for
this release I would do so.

Best regards

Andreas Bie?mann

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

* [U-Boot] [RFC/PATCH 0/4] BCH8 support for OMAP3
  2013-03-28 10:49 ` [U-Boot] [RFC/PATCH 0/4] BCH8 support for OMAP3 Andreas Bießmann
@ 2013-03-28 14:21   ` Tom Rini
  2013-04-02  8:49     ` Andreas Bießmann
  0 siblings, 1 reply; 32+ messages in thread
From: Tom Rini @ 2013-03-28 14:21 UTC (permalink / raw)
  To: u-boot

On Thu, Mar 28, 2013 at 11:49:54AM +0100, Andreas Bie??mann wrote:

> On 11/23/2012 04:14 PM, Andreas Bie??mann wrote:
> > This RFC series implements BCH8 for OMAP3 as provided by linux kernel in commit
> > 0e618ef0a6a33cf7ef96c2c824402088dd8ef48c.
> > This series is heavily influenced by Ilyas series 'NAND support for AM33XX'
> > thus could share some code.
> 
> Any comments on that series? I would appreciate to get the BCH8 support
> in for at least the tricorder board.

OK, so, some comments:
- We should pull the gpmc structs out of arch-*/cpu.h and into
  <asm/omap_gpmc.h> which also means merging
  <asm/arch-am33xx/omap_gpmc.h> and <asm/arch-omap3/omap_gpmc.h> but I
  suspect that's easy.
- In terms of 'nandecc' command, I don't like breaking existing
  setup/scripts, so my first thought is "nandecc hw" -> 1bit, "nandecc
  sw" -> sw (both just like today), "nandecc hw bch8" -> bch8 and
  "nandecc hw hamming" -> 1bit, which leaves room down the line for
  someone else to add nandecc hw bch4 -> bch4 (which is possible and I
  know exists in custom solutions somewhere).

> > I have managed to load kernel from an ubifs written by the kernel driver, but is
> > far away from tested thoroughly.
> 
> We used that patchset for a while in-house and could not find obvious
> issues. However we need to hack the SPL a bit to get the bigger
> footprint into SRAM with 2013.01.

What exactly did you do?  We _should_ already be taking up all of SRAM
with a few kb saved off for stack.  We might be able to get away with
less stack, but we'd need to check that a bit with the .su files.

> > Cause my NAND device 'NAND device: Manufacturer ID: 0x2c, Chip ID: 0xbc (Micron
> > NAND 512MiB 1,8V 16-bit)' does support 1bit ECC for first sector if erase is
> > less than 1000, the rest requires 4bit ECC. Therefore the SPL needs to support
> > BCH, the impact is about 9k for the SPL.
> 
> So my question here is if this series would be accepted for the upcoming
> release. I could work on it next week full time, so if I get a go for
> this release I would do so.

The RFC was well in time, so yes, I'm agreeable given the scope of the
changes.

-- 
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/20130328/b2caa293/attachment.pgp>

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

* [U-Boot] [RFC/PATCH 0/4] BCH8 support for OMAP3
  2013-03-28 14:21   ` Tom Rini
@ 2013-04-02  8:49     ` Andreas Bießmann
  2013-04-02 16:13       ` Tom Rini
  0 siblings, 1 reply; 32+ messages in thread
From: Andreas Bießmann @ 2013-04-02  8:49 UTC (permalink / raw)
  To: u-boot

Dear Tom Rini,

On 03/28/2013 03:21 PM, Tom Rini wrote:
> On Thu, Mar 28, 2013 at 11:49:54AM +0100, Andreas Bie??mann wrote:
> 
>> On 11/23/2012 04:14 PM, Andreas Bie??mann wrote:
>>> This RFC series implements BCH8 for OMAP3 as provided by linux kernel in commit
>>> 0e618ef0a6a33cf7ef96c2c824402088dd8ef48c.
>>> This series is heavily influenced by Ilyas series 'NAND support for AM33XX'
>>> thus could share some code.
>>
>> Any comments on that series? I would appreciate to get the BCH8 support
>> in for at least the tricorder board.
> 
> OK, so, some comments:
> - We should pull the gpmc structs out of arch-*/cpu.h and into
>   <asm/omap_gpmc.h> which also means merging
>   <asm/arch-am33xx/omap_gpmc.h> and <asm/arch-omap3/omap_gpmc.h> but I
>   suspect that's easy.

Will do so. But we will need some asm/arch/omap_gpmc.h defining the
differences between both systems (ELM based BCH8 has another OOB
footprint than HW assisted BCH8 on omap3).

> - In terms of 'nandecc' command, I don't like breaking existing
>   setup/scripts, so my first thought is "nandecc hw" -> 1bit, "nandecc
>   sw" -> sw (both just like today), "nandecc hw bch8" -> bch8 and
>   "nandecc hw hamming" -> 1bit, which leaves room down the line for
>   someone else to add nandecc hw bch4 -> bch4 (which is possible and I
>   know exists in custom solutions somewhere).

Sounds good for me. We will end up with 'nandecc hw' -> bch8 on am33xx
and 'nandecc hw' -> hamming on omap3 based boards. To enable bch8
explicitly on omap3 based devices we have the 'nandecc hw bch8'.
I will add another patch to the series changing the interface from
omap_nand_switch_ecc(int32) to omap_nand_switch_ecc(bool hw, uint32
eccbits) (or something like this).

BTW: Has anyone seen that ELM based bch8 on am33xx can not be chosen via
nandecc command?

>>> I have managed to load kernel from an ubifs written by the kernel driver, but is
>>> far away from tested thoroughly.
>>
>> We used that patchset for a while in-house and could not find obvious
>> issues. However we need to hack the SPL a bit to get the bigger
>> footprint into SRAM with 2013.01.
> 
> What exactly did you do? 

Well, disabled FAT for this specific build ...

> We _should_ already be taking up all of SRAM
> with a few kb saved off for stack.

We take 8 kB for stack in most configs on omap3, thus having 54 kB for
.text and .*data. Unfortunately the HW assisted BCH on omap3 based
devices require the bch library to decode ECC, this will grow the .text
+ .*data sections about 9k in sum (AFAIR, I've measured it some day).

>  We might be able to get away with
> less stack, but we'd need to check that a bit with the .su files.

Changing space for stack to 7 kB worked out with all features in SPL
(BCH + FAT for my build), this needs some testing though.

Best regards

Andreas Bie?mann

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

* [U-Boot] [PATCH v2 1/6] omap3/cpu.h: add BCH support
  2012-11-23 15:14 [U-Boot] [RFC/PATCH 0/4] BCH8 support for OMAP3 Andreas Bießmann
                   ` (4 preceding siblings ...)
  2013-03-28 10:49 ` [U-Boot] [RFC/PATCH 0/4] BCH8 support for OMAP3 Andreas Bießmann
@ 2013-04-02 16:05 ` Andreas Bießmann
  2013-04-02 16:05   ` [U-Boot] [PATCH v2 2/6] asm/omap_gpmc.h: consolidate common defines Andreas Bießmann
                     ` (6 more replies)
  5 siblings, 7 replies; 32+ messages in thread
From: Andreas Bießmann @ 2013-04-02 16:05 UTC (permalink / raw)
  To: u-boot

This patch adds the BCH result registers to register mapping for OMAP3 gpmc.

Signed-off-by: Andreas Bie?mann <andreas.devel@googlemail.com>
Cc: Tom Rini <trini@ti.com>
Cc: Ilya Yanok <ilya.yanok@cogentembedded.com>
Cc: Scott Wood <scottwood@freescale.com>
---
since v1: unchanged

 arch/arm/include/asm/arch-omap3/cpu.h |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/arm/include/asm/arch-omap3/cpu.h b/arch/arm/include/asm/arch-omap3/cpu.h
index 5683e16..c601873 100644
--- a/arch/arm/include/asm/arch-omap3/cpu.h
+++ b/arch/arm/include/asm/arch-omap3/cpu.h
@@ -109,6 +109,10 @@ struct gpmc_cs {
 	u8 res[8];		/* blow up to 0x30 byte */
 };
 
+struct bch_res_0_3 {
+	u32 bch_result_x[4];
+};
+
 struct gpmc {
 	u8 res1[0x10];
 	u32 sysconfig;		/* 0x10 */
@@ -135,6 +139,8 @@ struct gpmc {
 	u32 ecc7_result;	/* 0x218 */
 	u32 ecc8_result;	/* 0x21C */
 	u32 ecc9_result;	/* 0x220 */
+	u8 res7[0x1C];		/* fill up to 0x240 */
+	struct bch_res_0_3 bch_result_0_3[7];	/* 0x240 */
 };
 
 /* Used for board specific gpmc initialization */
-- 
1.7.10.4

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

* [U-Boot] [PATCH v2 2/6] asm/omap_gpmc.h: consolidate common defines
  2013-04-02 16:05 ` [U-Boot] [PATCH v2 1/6] omap3/cpu.h: add BCH support Andreas Bießmann
@ 2013-04-02 16:05   ` Andreas Bießmann
  2013-04-02 21:19     ` Tom Rini
  2013-04-02 16:05   ` [U-Boot] [PATCH v2 3/6] omap3/omap_gpmc.h: add ooblayout for BCH8 as in kernel Andreas Bießmann
                     ` (5 subsequent siblings)
  6 siblings, 1 reply; 32+ messages in thread
From: Andreas Bießmann @ 2013-04-02 16:05 UTC (permalink / raw)
  To: u-boot

arch/arm/include/asm/arch-am33xx/omap_gpmc.h and
arch/arm/include/asm/arch-omap3/omap_gpmc.h are almost the same, consolidate
the common parts into a new header.

Introduce a new asm/omap_gpmc.h which defines the command part and pulls in
the architecture specific one.

Signed-off-by: Andreas Bie?mann <andreas.devel@googlemail.com>
Cc: Tom Rini <trini@ti.com>
---
new in v2

 arch/arm/cpu/armv7/am33xx/elm.c                   |    2 +-
 arch/arm/include/asm/arch-am33xx/omap_gpmc.h      |   58 +--------------------
 arch/arm/include/asm/arch-omap3/omap_gpmc.h       |   57 --------------------
 arch/arm/include/asm/{arch-omap3 => }/omap_gpmc.h |   19 +++----
 board/isee/igep00x0/igep00x0.c                    |    2 +-
 board/overo/overo.c                               |    2 +-
 drivers/mtd/nand/omap_gpmc.c                      |    2 +-
 7 files changed, 12 insertions(+), 130 deletions(-)
 copy arch/arm/include/asm/{arch-omap3 => }/omap_gpmc.h (80%)

diff --git a/arch/arm/cpu/armv7/am33xx/elm.c b/arch/arm/cpu/armv7/am33xx/elm.c
index 9eed23d..41df612 100644
--- a/arch/arm/cpu/armv7/am33xx/elm.c
+++ b/arch/arm/cpu/armv7/am33xx/elm.c
@@ -33,7 +33,7 @@
 #include <asm/io.h>
 #include <asm/errno.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/omap_gpmc.h>
+#include <asm/omap_gpmc.h>
 #include <asm/arch/elm.h>
 
 #define ELM_DEFAULT_POLY (0)
diff --git a/arch/arm/include/asm/arch-am33xx/omap_gpmc.h b/arch/arm/include/asm/arch-am33xx/omap_gpmc.h
index 572f9d0..d03f1db 100644
--- a/arch/arm/include/asm/arch-am33xx/omap_gpmc.h
+++ b/arch/arm/include/asm/arch-am33xx/omap_gpmc.h
@@ -23,63 +23,7 @@
 #ifndef __ASM_ARCH_OMAP_GPMC_H
 #define __ASM_ARCH_OMAP_GPMC_H
 
-#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
-#define GPMC_NAND_HW_ECC_LAYOUT {\
-	.eccbytes = 12,\
-	.eccpos = {1, 2, 3, 4, 5, 6, 7, 8,\
-		9, 10, 11, 12},\
-	.oobfree = {\
-		{.offset = 13,\
-		 .length = 51 } } \
-}
-#endif
-
-/* Large Page x16 NAND device Layout */
-#ifdef GPMC_NAND_ECC_LP_x16_LAYOUT
-#define GPMC_NAND_HW_ECC_LAYOUT {\
-	.eccbytes = 12,\
-	.eccpos = {2, 3, 4, 5, 6, 7, 8, 9,\
-		10, 11, 12, 13},\
-	.oobfree = {\
-		{.offset = 14,\
-		 .length = 50 } } \
-}
-#endif
-
-/* Small Page x8 NAND device Layout */
-#ifdef GPMC_NAND_ECC_SP_x8_LAYOUT
-#define GPMC_NAND_HW_ECC_LAYOUT {\
-	.eccbytes = 3,\
-	.eccpos = {1, 2, 3},\
-	.oobfree = {\
-		{.offset = 4,\
-		 .length = 12 } } \
-}
-#endif
-
-/* Small Page x16 NAND device Layout */
-#ifdef GPMC_NAND_ECC_SP_x16_LAYOUT
-#define GPMC_NAND_HW_ECC_LAYOUT {\
-	.eccbytes = 3,\
-	.eccpos = {2, 3, 4},\
-	.oobfree = {\
-		{.offset = 5,\
-		 .length = 11 } } \
-}
-#endif
-
+/* These GPMC_NAND_HW_BCHx_ECC_LAYOUT defines are based on AM33xx ELM */
 #define GPMC_NAND_HW_BCH4_ECC_LAYOUT {\
 	.eccbytes = 32,\
 	.eccpos = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,\
diff --git a/arch/arm/include/asm/arch-omap3/omap_gpmc.h b/arch/arm/include/asm/arch-omap3/omap_gpmc.h
index 800e4ee..13efab0 100644
--- a/arch/arm/include/asm/arch-omap3/omap_gpmc.h
+++ b/arch/arm/include/asm/arch-omap3/omap_gpmc.h
@@ -23,63 +23,6 @@
 #ifndef __ASM_ARCH_OMAP_GPMC_H
 #define __ASM_ARCH_OMAP_GPMC_H
 
-#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
-#define GPMC_NAND_HW_ECC_LAYOUT {\
-	.eccbytes = 12,\
-	.eccpos = {1, 2, 3, 4, 5, 6, 7, 8,\
-		9, 10, 11, 12},\
-	.oobfree = {\
-		{.offset = 13,\
-		 .length = 51 } } \
-}
-#endif
-
-/* Large Page x16 NAND device Layout */
-#ifdef GPMC_NAND_ECC_LP_x16_LAYOUT
-#define GPMC_NAND_HW_ECC_LAYOUT {\
-	.eccbytes = 12,\
-	.eccpos = {2, 3, 4, 5, 6, 7, 8, 9,\
-		10, 11, 12, 13},\
-	.oobfree = {\
-		{.offset = 14,\
-		 .length = 50 } } \
-}
-#endif
-
-/* Small Page x8 NAND device Layout */
-#ifdef GPMC_NAND_ECC_SP_x8_LAYOUT
-#define GPMC_NAND_HW_ECC_LAYOUT {\
-	.eccbytes = 3,\
-	.eccpos = {1, 2, 3},\
-	.oobfree = {\
-		{.offset = 4,\
-		 .length = 12 } } \
-}
-#endif
-
-/* Small Page x16 NAND device Layout */
-#ifdef GPMC_NAND_ECC_SP_x16_LAYOUT
-#define GPMC_NAND_HW_ECC_LAYOUT {\
-	.eccbytes = 3,\
-	.eccpos = {2, 3, 4},\
-	.oobfree = {\
-		{.offset = 5,\
-		 .length = 11 } } \
-}
-#endif
-
 /* GPMC CS configuration for an SMSC LAN9221 ethernet controller */
 #define NET_LAN9221_GPMC_CONFIG1    0x00001000
 #define NET_LAN9221_GPMC_CONFIG2    0x00060700
diff --git a/arch/arm/include/asm/arch-omap3/omap_gpmc.h b/arch/arm/include/asm/omap_gpmc.h
similarity index 80%
copy from arch/arm/include/asm/arch-omap3/omap_gpmc.h
copy to arch/arm/include/asm/omap_gpmc.h
index 800e4ee..5cb1df1 100644
--- a/arch/arm/include/asm/arch-omap3/omap_gpmc.h
+++ b/arch/arm/include/asm/omap_gpmc.h
@@ -2,6 +2,8 @@
  * (C) Copyright 2004-2008 Texas Instruments, <www.ti.com>
  * Rohit Choraria <rohitkc@ti.com>
  *
+ * (C) Copyright 2013 Andreas Bie?mann <andreas.devel@googlemail.com>
+ *
  * See file CREDITS for list of people who contributed to this
  * project.
  *
@@ -20,8 +22,10 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  * MA 02111-1307 USA
  */
-#ifndef __ASM_ARCH_OMAP_GPMC_H
-#define __ASM_ARCH_OMAP_GPMC_H
+#ifndef __ASM_OMAP_GPMC_H
+#define __ASM_OMAP_GPMC_H
+
+#include <asm/arch/omap_gpmc.h>
 
 #define GPMC_BUF_EMPTY	0
 #define GPMC_BUF_FULL	1
@@ -80,13 +84,4 @@
 }
 #endif
 
-/* GPMC CS configuration for an SMSC LAN9221 ethernet controller */
-#define NET_LAN9221_GPMC_CONFIG1    0x00001000
-#define NET_LAN9221_GPMC_CONFIG2    0x00060700
-#define NET_LAN9221_GPMC_CONFIG3    0x00020201
-#define NET_LAN9221_GPMC_CONFIG4    0x06000700
-#define NET_LAN9221_GPMC_CONFIG5    0x0006090A
-#define NET_LAN9221_GPMC_CONFIG6    0x87030000
-#define NET_LAN9221_GPMC_CONFIG7    0x00000f6c
-
-#endif /* __ASM_ARCH_OMAP_GPMC_H */
+#endif /* __ASM_OMAP_GPMC_H */
diff --git a/board/isee/igep00x0/igep00x0.c b/board/isee/igep00x0/igep00x0.c
index 2bac916..0d4679d 100644
--- a/board/isee/igep00x0/igep00x0.c
+++ b/board/isee/igep00x0/igep00x0.c
@@ -24,7 +24,7 @@
 #include <twl4030.h>
 #include <netdev.h>
 #include <asm/gpio.h>
-#include <asm/arch/omap_gpmc.h>
+#include <asm/omap_gpmc.h>
 #include <asm/io.h>
 #include <asm/arch/mem.h>
 #include <asm/arch/mmc_host_def.h>
diff --git a/board/overo/overo.c b/board/overo/overo.c
index 8690450..c10c44c 100644
--- a/board/overo/overo.c
+++ b/board/overo/overo.c
@@ -37,7 +37,7 @@
 #include <asm/arch/mux.h>
 #include <asm/arch/mem.h>
 #include <asm/arch/sys_proto.h>
-#include <asm/arch/omap_gpmc.h>
+#include <asm/omap_gpmc.h>
 #include <asm/gpio.h>
 #include <asm/mach-types.h>
 #include "overo.h"
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index bbf5443..c7d4999 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -26,7 +26,7 @@
 #include <asm/errno.h>
 #include <asm/arch/mem.h>
 #include <asm/arch/cpu.h>
-#include <asm/arch/omap_gpmc.h>
+#include <asm/omap_gpmc.h>
 #include <linux/mtd/nand_ecc.h>
 #include <linux/compiler.h>
 #include <nand.h>
-- 
1.7.10.4

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

* [U-Boot] [PATCH v2 3/6] omap3/omap_gpmc.h: add ooblayout for BCH8 as in kernel
  2013-04-02 16:05 ` [U-Boot] [PATCH v2 1/6] omap3/cpu.h: add BCH support Andreas Bießmann
  2013-04-02 16:05   ` [U-Boot] [PATCH v2 2/6] asm/omap_gpmc.h: consolidate common defines Andreas Bießmann
@ 2013-04-02 16:05   ` Andreas Bießmann
  2013-04-02 21:19     ` Tom Rini
  2013-04-02 16:05   ` [U-Boot] [PATCH v2 4/6] omap_gpmc: change nandecc command Andreas Bießmann
                     ` (4 subsequent siblings)
  6 siblings, 1 reply; 32+ messages in thread
From: Andreas Bießmann @ 2013-04-02 16:05 UTC (permalink / raw)
  To: u-boot

This patch adds BCH8 ooblayout for NAND as provided by
0e618ef0a6a33cf7ef96c2c824402088dd8ef48c in linux kernel. This Layout is
currently only provided for 64 byte OOB.

Signed-off-by: Andreas Bie?mann <andreas.devel@googlemail.com>
Cc: Tom Rini <trini@ti.com>
Cc: Ilya Yanok <ilya.yanok@cogentembedded.com>
Cc: Scott Wood <scottwood@freescale.com>
---
since v1:
 * minor comment changes

 arch/arm/include/asm/arch-omap3/omap_gpmc.h |   17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/arch/arm/include/asm/arch-omap3/omap_gpmc.h b/arch/arm/include/asm/arch-omap3/omap_gpmc.h
index 13efab0..6441281 100644
--- a/arch/arm/include/asm/arch-omap3/omap_gpmc.h
+++ b/arch/arm/include/asm/arch-omap3/omap_gpmc.h
@@ -23,6 +23,23 @@
 #ifndef __ASM_ARCH_OMAP_GPMC_H
 #define __ASM_ARCH_OMAP_GPMC_H
 
+/*
+ * These GPMC_NAND_HW_BCHx_ECC_LAYOUT defines using the BCH library.
+ * The OOB layout was first defined by linx kernel in commit
+ * 0e618ef0a6a33cf7ef96c2c824402088dd8ef48c, we have to reuse it here cause
+ * we want to be compatible.
+ */
+#define GPMC_NAND_HW_BCH8_ECC_LAYOUT {\
+	.eccbytes = 56,\
+	.eccpos = {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,\
+			23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,\
+			37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,\
+			51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63},\
+	.oobfree = {\
+		{.offset = 2,\
+		 .length = 10 } } \
+}
+
 /* GPMC CS configuration for an SMSC LAN9221 ethernet controller */
 #define NET_LAN9221_GPMC_CONFIG1    0x00001000
 #define NET_LAN9221_GPMC_CONFIG2    0x00060700
-- 
1.7.10.4

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

* [U-Boot] [PATCH v2 4/6] omap_gpmc: change nandecc command
  2013-04-02 16:05 ` [U-Boot] [PATCH v2 1/6] omap3/cpu.h: add BCH support Andreas Bießmann
  2013-04-02 16:05   ` [U-Boot] [PATCH v2 2/6] asm/omap_gpmc.h: consolidate common defines Andreas Bießmann
  2013-04-02 16:05   ` [U-Boot] [PATCH v2 3/6] omap3/omap_gpmc.h: add ooblayout for BCH8 as in kernel Andreas Bießmann
@ 2013-04-02 16:05   ` Andreas Bießmann
  2013-04-02 21:19     ` Tom Rini
  2013-04-03 14:50     ` [U-Boot] [PATCH v3 " Andreas Bießmann
  2013-04-02 16:05   ` [U-Boot] [PATCH v2 5/6] omap_gpmc: add support for hw assisted BCH8 Andreas Bießmann
                     ` (3 subsequent siblings)
  6 siblings, 2 replies; 32+ messages in thread
From: Andreas Bießmann @ 2013-04-02 16:05 UTC (permalink / raw)
  To: u-boot

With uppcoming BCH support on OMAP devices we need to decide between differnt
algorithms when switching the ECC engine.  Currently we support 1-bit hammign
and 8-bit BCH on HW backend.

In order to switch between differnet ECC algorithms we need to change the
interface of omap_nand_switch_ecc() also.

Signed-off-by: Andreas Bie?mann <andreas.devel@googlemail.com>
Cc: Tom Rini <trini@ti.com>
---
new in v2

 arch/arm/cpu/armv7/omap3/board.c             |   31 ++++++++++----
 arch/arm/include/asm/arch-am33xx/sys_proto.h |    2 +-
 arch/arm/include/asm/arch-omap3/sys_proto.h  |    2 +-
 drivers/mtd/nand/omap_gpmc.c                 |   56 ++++++++++++++------------
 4 files changed, 55 insertions(+), 36 deletions(-)

diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c
index c6d9a42..b72fadc 100644
--- a/arch/arm/cpu/armv7/omap3/board.c
+++ b/arch/arm/cpu/armv7/omap3/board.c
@@ -328,14 +328,25 @@ void abort(void)
  *****************************************************************************/
 static int do_switch_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
-	if (argc != 2)
+	if (argc < 2 || argc > 3)
 		goto usage;
-	if (strncmp(argv[1], "hw", 2) == 0)
-		omap_nand_switch_ecc(1);
-	else if (strncmp(argv[1], "sw", 2) == 0)
-		omap_nand_switch_ecc(0);
-	else
+
+	if (strncmp(argv[1], "hw", 2) == 0) {
+		if (argc == 2) {
+			omap_nand_switch_ecc(1, 1);
+		} else {
+			if (strncmp(argv[2], "hamming", 7) == 0)
+				omap_nand_switch_ecc(1, 1);
+			else if (strncmp(argv[2], "bch8", 4) == 0)
+				omap_nand_switch_ecc(1, 8);
+			else
+				goto usage;
+		}
+	} else if (strncmp(argv[1], "sw", 2) == 0) {
+		omap_nand_switch_ecc(0, 0);
+	} else {
 		goto usage;
+	}
 
 	return 0;
 
@@ -345,9 +356,13 @@ usage:
 }
 
 U_BOOT_CMD(
-	nandecc, 2, 1,	do_switch_ecc,
+	nandecc, 3, 1,	do_switch_ecc,
 	"switch OMAP3 NAND ECC calculation algorithm",
-	"[hw/sw] - Switch between NAND hardware (hw) or software (sw) ecc algorithm"
+	"hw [hamming|bch8] - Switch between NAND hardware 1-bit hamming and"
+	" 8-bit BCH\n"
+	"                           ecc calculation (second parameter may"
+	" be omitted).\n"
+	"nandecc sw               - Switch to NAND software ecc algorithm."
 );
 
 #endif /* CONFIG_NAND_OMAP_GPMC & !CONFIG_SPL_BUILD */
diff --git a/arch/arm/include/asm/arch-am33xx/sys_proto.h b/arch/arm/include/asm/arch-am33xx/sys_proto.h
index 0910a94..c913b5f 100644
--- a/arch/arm/include/asm/arch-am33xx/sys_proto.h
+++ b/arch/arm/include/asm/arch-am33xx/sys_proto.h
@@ -39,5 +39,5 @@ struct gpmc_cs;
 void gpmc_init(void);
 void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,
 			u32 size);
-void omap_nand_switch_ecc(int);
+void omap_nand_switch_ecc(uint32_t, uint32_t);
 #endif
diff --git a/arch/arm/include/asm/arch-omap3/sys_proto.h b/arch/arm/include/asm/arch-omap3/sys_proto.h
index d60f2ad..dae1312 100644
--- a/arch/arm/include/asm/arch-omap3/sys_proto.h
+++ b/arch/arm/include/asm/arch-omap3/sys_proto.h
@@ -78,7 +78,7 @@ void sr32(void *, u32, u32, u32);
 u32 wait_on_value(u32, u32, void *, u32);
 void sdelay(unsigned long);
 void make_cs1_contiguous(void);
-void omap_nand_switch_ecc(int);
+void omap_nand_switch_ecc(uint32_t, uint32_t);
 void power_init_r(void);
 void dieid_num_r(void);
 void do_omap3_emu_romcode_call(u32 service_id, u32 parameters);
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index c7d4999..f073cbe 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -604,13 +604,14 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
 
 #ifndef CONFIG_SPL_BUILD
 /*
- * omap_nand_switch_ecc - switch the ECC operation b/w h/w ecc and s/w ecc.
- * The default is to come up on s/w ecc
- *
- * @hardware - 1 -switch to h/w ecc, 0 - s/w ecc
+ * omap_nand_switch_ecc - switch the ECC operation between different engines
+ * (h/w and s/w) and different algorithms (hamming and BCHx)
  *
+ * @hardware		- true if one of the HW engines should be used
+ * @eccstrength		- the number of bits that could be corrected
+ *			  (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
  */
-void omap_nand_switch_ecc(int32_t hardware)
+void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
 {
 	struct nand_chip *nand;
 	struct mtd_info *mtd;
@@ -637,28 +638,31 @@ void omap_nand_switch_ecc(int32_t hardware)
 	nand->ecc.calculate = NULL;
 
 	/* Setup the ecc configurations again */
-	if (hardware == 1) {
-		nand->ecc.mode = NAND_ECC_HW;
-		nand->ecc.layout = &hw_nand_oob;
-		nand->ecc.size = 512;
-		nand->ecc.bytes = 3;
-		nand->ecc.hwctl = omap_enable_hwecc;
-		nand->ecc.correct = omap_correct_data;
-		nand->ecc.calculate = omap_calculate_ecc;
-		omap_hwecc_init(nand);
-		printf("HW ECC selected\n");
+	if (hardware) {
+		if (eccstrength == 1) {
+			nand->ecc.mode = NAND_ECC_HW;
+			nand->ecc.layout = &hw_nand_oob;
+			nand->ecc.size = 512;
+			nand->ecc.bytes = 3;
+			nand->ecc.hwctl = omap_enable_hwecc;
+			nand->ecc.correct = omap_correct_data;
+			nand->ecc.calculate = omap_calculate_ecc;
+			omap_hwecc_init(nand);
+			printf("1-bit hamming HW ECC selected\n");
+		}
 #ifdef CONFIG_AM33XX
-	} else if (hardware == 2) {
-		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;
-		omap_hwecc_init_bch(nand, NAND_ECC_READ);
-		printf("HW BCH8 selected\n");
+		else if (eccstrength == 8) {
+			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;
+			omap_hwecc_init_bch(nand, NAND_ECC_READ);
+			printf("8-bit BCH HW ECC selected\n");
+		}
 #endif
 	} else {
 		nand->ecc.mode = NAND_ECC_SOFT;
-- 
1.7.10.4

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

* [U-Boot] [PATCH v2 5/6] omap_gpmc: add support for hw assisted BCH8
  2013-04-02 16:05 ` [U-Boot] [PATCH v2 1/6] omap3/cpu.h: add BCH support Andreas Bießmann
                     ` (2 preceding siblings ...)
  2013-04-02 16:05   ` [U-Boot] [PATCH v2 4/6] omap_gpmc: change nandecc command Andreas Bießmann
@ 2013-04-02 16:05   ` Andreas Bießmann
  2013-04-02 21:19     ` Tom Rini
  2013-04-02 16:05   ` [U-Boot] [PATCH v2 6/6] tricorder: enable hw assisted BCH8 in SPL and u-boot Andreas Bießmann
                     ` (2 subsequent siblings)
  6 siblings, 1 reply; 32+ messages in thread
From: Andreas Bießmann @ 2013-04-02 16:05 UTC (permalink / raw)
  To: u-boot

The BCH for OMAP3 is implemented as the linux kernel in
0e618ef0a6a33cf7ef96c2c824402088dd8ef48c does.

The kernel states:

---8<---
The OMAP3 GPMC hardware BCH engine computes remainder polynomials, it does not
provide automatic error location and correction: this step is implemented using
the BCH library.
--->8---

And we do so in u-boot.

This implementation uses the same layout for BCH8 but it is fix. The current
provided layout does only work with 64 Byte OOB.

Signed-off-by: Andreas Bie?mann <andreas.devel@googlemail.com>
Cc: Tom Rini <trini@ti.com>
Cc: Ilya Yanok <ilya.yanok@cogentembedded.com>
Cc: Scott Wood <scottwood@freescale.com>
Cc: Mansoor Ahamed <mansoor.ahamed@ti.com>
---
since v1:
 * cleanups (remove debug stuff)
 * make checkpach clean (still 2 warnings which I will not fix)
 * merge some code with the AM33XX implementation

known checkpatch errors:
WARNING: line over 80 characters
#92: FILE: drivers/mtd/nand/omap_gpmc.c:273:
+static void __maybe_unused omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)

WARNING: line over 80 characters
#165: FILE: drivers/mtd/nand/omap_gpmc.c:346:
+static void __maybe_unused omap_enable_ecc_bch(struct mtd_info *mtd, int32_t mode)

total: 0 errors, 2 warnings, 0 checks, 428 lines checked

 drivers/mtd/nand/omap_gpmc.c |  347 +++++++++++++++++++++++++++++++-----------
 lib/Makefile                 |    2 +-
 2 files changed, 258 insertions(+), 91 deletions(-)

diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index f073cbe..5f36971 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -28,6 +28,7 @@
 #include <asm/arch/cpu.h>
 #include <asm/omap_gpmc.h>
 #include <linux/mtd/nand_ecc.h>
+#include <linux/bch.h>
 #include <linux/compiler.h>
 #include <nand.h>
 #ifdef CONFIG_AM33XX
@@ -37,6 +38,8 @@
 static uint8_t cs;
 static __maybe_unused struct nand_ecclayout hw_nand_oob =
 	GPMC_NAND_HW_ECC_LAYOUT;
+static __maybe_unused struct nand_ecclayout hw_bch8_nand_oob =
+	GPMC_NAND_HW_BCH8_ECC_LAYOUT;
 
 /*
  * omap_nand_hwcontrol - Set the address pointers corretly for the
@@ -239,13 +242,13 @@ static void __maybe_unused omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
 }
 
 /*
- * BCH8 support (needs ELM and thus AM33xx-only)
+ * Generic BCH interface
  */
-#ifdef CONFIG_AM33XX
 struct nand_bch_priv {
 	uint8_t mode;
 	uint8_t type;
 	uint8_t nibbles;
+	struct bch_control *control;
 };
 
 /* bch types */
@@ -253,21 +256,127 @@ 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
 
-static struct nand_ecclayout hw_bch8_nand_oob = GPMC_NAND_HW_BCH8_ECC_LAYOUT;
-
-static struct nand_bch_priv bch_priv = {
+static __maybe_unused struct nand_bch_priv bch_priv = {
 	.mode = NAND_ECC_HW_BCH,
 	.type = ECC_BCH8,
-	.nibbles = ECC_BCH8_NIBBLES
+	.nibbles = ECC_BCH8_NIBBLES,
+	.control = NULL
 };
 
 /*
+ * omap_hwecc_init_bch - Initialize the BCH Hardware ECC for NAND flash in
+ *				GPMC controller
+ * @mtd:	MTD device structure
+ * @mode:	Read/Write mode
+ */
+static void __maybe_unused 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
+	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);
+
+#ifdef CONFIG_AM33XX
+	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;
+	}
+
+	switch (mode) {
+	case NAND_ECC_WRITE:
+		/* 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;
+	}
+#else
+	/*
+	 * This is for BCH sw library, we need to choose wrap mode 6 and fixed
+	 * layout.
+	 * 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);
+#endif
+	/* ecc size configuration */
+	writel(val, &gpmc_cfg->ecc_size_config);
+
+	/* by default 512bytes sector page is selected */
+	/* set bch mode */
+	val  = (1 << 16);
+	/* bch4 / bch8 / bch16 */
+	val |= (bch->type << 12);
+	val |= (wr_mode << 8);
+	val |= (dev_width << 7);
+	val |= (cs << 1);
+	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
+ */
+static void __maybe_unused 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);
+}
+
+/*
+ * 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);
+}
+
+/*
+ * BCH8 support (needs ELM and thus AM33xx-only)
+ */
+#ifdef CONFIG_AM33XX
+
+/*
  * omap_read_bch8_result - Read BCH result for BCH8 level
  *
  * @mtd:	MTD device structure
@@ -306,18 +415,6 @@ static void omap_read_bch8_result(struct mtd_info *mtd, uint8_t big_endian,
 }
 
 /*
- * omap_ecc_disable - Disable H/W ECC calculation
- *
- * @mtd:	MTD device structure
- *
- */
-static void omap_ecc_disable(struct mtd_info *mtd)
-{
-	writel((readl(&gpmc_cfg->ecc_config) & ~0x1),
-		&gpmc_cfg->ecc_config);
-}
-
-/*
  * omap_rotate_ecc_bch - Rotate the syndrome bytes
  *
  * @mtd:	MTD device structure
@@ -468,76 +565,7 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
 
 	return 0;
 }
-/*
- * omap_hwecc_init_bch - Initialize the BCH Hardware ECC for NAND flash in
- *				GPMC controller
- * @mtd:       MTD device structure
- * @mode:	Read/Write mode
- */
-static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
-{
-	uint32_t val, dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
-	uint32_t unused_length = 0;
-	struct nand_bch_priv *bch = chip->priv;
-
-	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;
-	}
-
-	/* Clear the ecc result registers, select ecc reg as 1 */
-	writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
-
-	switch (mode) {
-	case NAND_ECC_WRITE:
-		/* 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;
-	}
-	/* ecc size configuration */
-	writel(val, &gpmc_cfg->ecc_size_config);
-	/* by default 512bytes sector page is selected */
-	/* set bch mode */
-	val  = (1 << 16);
-	/* bch4 / bch8 / bch16 */
-	val |= (bch->type << 12);
-	/* set wrap mode to 1 */
-	val |= (1 << 8);
-	val |= (dev_width << 7);
-	val |= (cs << 1);
-	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
- *
- */
-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);
-}
 
 /**
  * omap_read_page_bch - hardware ecc based page read function
@@ -602,6 +630,127 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
 }
 #endif /* CONFIG_AM33XX */
 
+/*
+ * basic BCH8 support
+ */
+#ifdef CONFIG_NAND_OMAP_BCH8
+/*
+ *  omap_calculate_ecc_bch - 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(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 - Decode received data and correct errors
+ * @mtd: MTD device structure
+ * @data: page data
+ * @read_ecc: ecc read from nand flash
+ * @calc_ecc: ecc read from HW ECC registers
+ */
+static int omap_correct_data_bch(struct mtd_info *mtd, u_char *data,
+				 u_char *read_ecc, u_char *calc_ecc)
+{
+	int i, count;
+	/* cannot correct more than 8 errors */
+	unsigned int errloc[8];
+	struct nand_chip *chip = mtd->priv;
+	struct nand_bch_priv *chip_priv = chip->priv;
+	struct bch_control *bch = chip_priv->control;
+
+	count = decode_bch(bch, NULL, 512, read_ecc, calc_ecc, NULL, errloc);
+	if (count > 0) {
+		/* correct errors */
+		for (i = 0; i < count; i++) {
+			/* correct data only, not ecc bytes */
+			if (errloc[i] < 8*512)
+				data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
+			printf("corrected bitflip %u\n", errloc[i]);
+#ifdef DEBUG
+			puts("read_ecc: ");
+			/*
+			 * BCH8 have 13 bytes of ECC; BCH4 needs adoption
+			 * here!
+			 */
+			for (i = 0; i < 13; i++)
+				printf("%02x ", read_ecc[i]);
+			puts("\n");
+			puts("calc_ecc: ");
+			for (i = 0; i < 13; i++)
+				printf("%02x ", calc_ecc[i]);
+			puts("\n");
+#endif
+		}
+	} else if (count < 0) {
+		puts("ecc unrecoverable error\n");
+	}
+	return count;
+}
+
+/**
+ * omap_free_bch - Release BCH ecc resources
+ * @mtd: MTD device structure
+ */
+static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct nand_bch_priv *chip_priv = chip->priv;
+	struct bch_control *bch = NULL;
+
+	if (chip_priv)
+		bch = chip_priv->control;
+
+	if (bch) {
+		free_bch(bch);
+		chip_priv->control = NULL;
+	}
+}
+#endif /* CONFIG_NAND_OMAP_BCH8 */
+
 #ifndef CONFIG_SPL_BUILD
 /*
  * omap_nand_switch_ecc - switch the ECC operation between different engines
@@ -650,13 +799,17 @@ void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
 			omap_hwecc_init(nand);
 			printf("1-bit hamming HW ECC selected\n");
 		}
-#ifdef CONFIG_AM33XX
+#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
+			nand->ecc.bytes = 13;
+#endif
 			nand->ecc.hwctl = omap_enable_ecc_bch;
 			nand->ecc.correct = omap_correct_data_bch;
 			nand->ecc.calculate = omap_calculate_ecc_bch;
@@ -736,16 +889,28 @@ 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 */
 	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 */);
+	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 */
-#ifdef CONFIG_AM33XX
+#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;
@@ -753,7 +918,9 @@ int board_nand_init(struct nand_chip *nand)
 	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)
diff --git a/lib/Makefile b/lib/Makefile
index 1bfd3ee..5d71b80 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -27,7 +27,6 @@ LIB	= $(obj)libgeneric.o
 
 ifndef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_ADDR_MAP) += addr_map.o
-COBJS-$(CONFIG_BCH) += bch.o
 COBJS-$(CONFIG_AES) += aes.o
 COBJS-$(CONFIG_BZIP2) += bzlib.o
 COBJS-$(CONFIG_BZIP2) += bzlib_crctable.o
@@ -67,6 +66,7 @@ COBJS-$(CONFIG_SPL_NET_SUPPORT) += errno.o
 COBJS-$(CONFIG_SPL_NET_SUPPORT) += hashtable.o
 COBJS-$(CONFIG_SPL_NET_SUPPORT) += net_utils.o
 endif
+COBJS-$(CONFIG_BCH) += bch.o
 COBJS-y += crc32.o
 COBJS-y += ctype.o
 COBJS-y += div64.o
-- 
1.7.10.4

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

* [U-Boot] [PATCH v2 6/6] tricorder: enable hw assisted BCH8 in SPL and u-boot
  2013-04-02 16:05 ` [U-Boot] [PATCH v2 1/6] omap3/cpu.h: add BCH support Andreas Bießmann
                     ` (3 preceding siblings ...)
  2013-04-02 16:05   ` [U-Boot] [PATCH v2 5/6] omap_gpmc: add support for hw assisted BCH8 Andreas Bießmann
@ 2013-04-02 16:05   ` Andreas Bießmann
  2013-04-02 21:19   ` [U-Boot] [PATCH v2 1/6] omap3/cpu.h: add BCH support Tom Rini
  2013-04-08 16:58   ` Tom Rini
  6 siblings, 0 replies; 32+ messages in thread
From: Andreas Bießmann @ 2013-04-02 16:05 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Andreas Bie?mann <andreas.devel@googlemail.com>
Cc: Tom Rini <trini@ti.com>
Cc: Thomas Weber <weber@corscience.de>
Cc: Ilya Yanok <ilya.yanok@cogentembedded.com>
Cc: Scott Wood <scottwood@freescale.com>
---
since v1:
 * reduce SPL stack size (increase code segment)

 include/configs/tricorder.h |   13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/include/configs/tricorder.h b/include/configs/tricorder.h
index ebd7a25..4c75cc5 100644
--- a/include/configs/tricorder.h
+++ b/include/configs/tricorder.h
@@ -125,6 +125,8 @@
 
 #define CONFIG_SYS_MAX_NAND_DEVICE	1		/* Max number of NAND */
 							/* devices */
+#define CONFIG_NAND_OMAP_BCH8
+#define CONFIG_BCH
 
 /* commands to include */
 #include <config_cmd_default.h>
@@ -290,7 +292,7 @@
 #define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x300 /* address 0x60000 */
 
 #define CONFIG_SPL_TEXT_BASE		0x40200000 /*CONFIG_SYS_SRAM_START*/
-#define CONFIG_SPL_MAX_SIZE		(54 * 1024)	/* 8 KB for stack */
+#define CONFIG_SPL_MAX_SIZE		(55 * 1024)	/* 7 KB for stack */
 #define CONFIG_SPL_STACK		LOW_LEVEL_SRAM_STACK
 
 #define CONFIG_SPL_BSS_START_ADDR	0x80000000 /*CONFIG_SYS_SDRAM_BASE*/
@@ -303,11 +305,14 @@
 #define CONFIG_SYS_NAND_OOBSIZE		64
 #define CONFIG_SYS_NAND_BLOCK_SIZE	(128*1024)
 #define CONFIG_SYS_NAND_BAD_BLOCK_POS	NAND_LARGE_BADBLOCK_POS
-#define CONFIG_SYS_NAND_ECCPOS		{2, 3, 4, 5, 6, 7, 8, 9,\
-						10, 11, 12, 13}
+#define CONFIG_SYS_NAND_ECCPOS		{12, 13, 14, 15, 16, 17, 18, 19, 20,\
+			21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,\
+			34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,\
+			47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\
+			60, 61, 62, 63}
 
 #define CONFIG_SYS_NAND_ECCSIZE		512
-#define CONFIG_SYS_NAND_ECCBYTES	3
+#define CONFIG_SYS_NAND_ECCBYTES	13
 
 #define CONFIG_SYS_NAND_U_BOOT_START	CONFIG_SYS_TEXT_BASE
 
-- 
1.7.10.4

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

* [U-Boot] [RFC/PATCH 0/4] BCH8 support for OMAP3
  2013-04-02  8:49     ` Andreas Bießmann
@ 2013-04-02 16:13       ` Tom Rini
  0 siblings, 0 replies; 32+ messages in thread
From: Tom Rini @ 2013-04-02 16:13 UTC (permalink / raw)
  To: u-boot

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

On 04/02/2013 04:49 AM, Andreas Bie?mann wrote:
> Dear Tom Rini,
> 
> On 03/28/2013 03:21 PM, Tom Rini wrote:
>> On Thu, Mar 28, 2013 at 11:49:54AM +0100, Andreas Bie??mann
>> wrote:
>> 
>>> On 11/23/2012 04:14 PM, Andreas Bie??mann wrote:
>>>> This RFC series implements BCH8 for OMAP3 as provided by
>>>> linux kernel in commit 
>>>> 0e618ef0a6a33cf7ef96c2c824402088dd8ef48c. This series is
>>>> heavily influenced by Ilyas series 'NAND support for AM33XX' 
>>>> thus could share some code.
>>> 
>>> Any comments on that series? I would appreciate to get the BCH8
>>> support in for at least the tricorder board.
>> 
>> OK, so, some comments: - We should pull the gpmc structs out of
>> arch-*/cpu.h and into <asm/omap_gpmc.h> which also means merging 
>> <asm/arch-am33xx/omap_gpmc.h> and <asm/arch-omap3/omap_gpmc.h>
>> but I suspect that's easy.
> 
> Will do so. But we will need some asm/arch/omap_gpmc.h defining
> the differences between both systems (ELM based BCH8 has another
> OOB footprint than HW assisted BCH8 on omap3).

Shoot.  But, we can handle it, see the mmc headers for an example.

>> - In terms of 'nandecc' command, I don't like breaking existing 
>> setup/scripts, so my first thought is "nandecc hw" -> 1bit,
>> "nandecc sw" -> sw (both just like today), "nandecc hw bch8" ->
>> bch8 and "nandecc hw hamming" -> 1bit, which leaves room down the
>> line for someone else to add nandecc hw bch4 -> bch4 (which is
>> possible and I know exists in custom solutions somewhere).
> 
> Sounds good for me. We will end up with 'nandecc hw' -> bch8 on
> am33xx and 'nandecc hw' -> hamming on omap3 based boards. To enable
> bch8

There's no nandecc command for am33xx.  The plan is that we'll
auto-detect when we need BCH16 (as we need BCH8 or BCH16 and the
others don't really have found-today use cases).

> explicitly on omap3 based devices we have the 'nandecc hw bch8'. I
> will add another patch to the series changing the interface from 
> omap_nand_switch_ecc(int32) to omap_nand_switch_ecc(bool hw,
> uint32 eccbits) (or something like this).

OK.

> BTW: Has anyone seen that ELM based bch8 on am33xx can not be
> chosen via nandecc command?

Yes, we only do BCH8 over everything.  The ROM talks BCH8 or BCH16
(given what the NAND chip requires) or you tell it (via SYSBOOT pins)
tha it's an on-die ECC engine.

>>>> I have managed to load kernel from an ubifs written by the
>>>> kernel driver, but is far away from tested thoroughly.
>>> 
>>> We used that patchset for a while in-house and could not find
>>> obvious issues. However we need to hack the SPL a bit to get
>>> the bigger footprint into SRAM with 2013.01.
>> 
>> What exactly did you do?
> 
> Well, disabled FAT for this specific build ...
> 
>> We _should_ already be taking up all of SRAM with a few kb saved
>> off for stack.
> 
> We take 8 kB for stack in most configs on omap3, thus having 54 kB
> for .text and .*data. Unfortunately the HW assisted BCH on omap3
> based devices require the bch library to decode ECC, this will grow
> the .text + .*data sections about 9k in sum (AFAIR, I've measured
> it some day).
> 
>> We might be able to get away with less stack, but we'd need to
>> check that a bit with the .su files.
> 
> Changing space for stack to 7 kB worked out with all features in
> SPL (BCH + FAT for my build), this needs some testing though.

Along with some measurements (which are available today in the .su
files, see doc/README.SPL) we should be able to do this safely.

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

iQIcBAEBAgAGBQJRWwOUAAoJENk4IS6UOR1Wg6YP/23aVKSjbgwEtYt84zi97JXp
OUnRxoERpRBUV4Z1Ie9GTc/kk/Vl34eTJfLo8ApKMnHzuDM8o5hB4KTnXzIVjU7T
DSYkPnxsqB6V2W3FRo/g/MfMX3zYrRz1UYzfOxRwHbhJsfmxnu7YTB5MZSjaB72a
vaHHx83x0vaNJePCroGo/ix3SGC4WzpInibu4JiQ16c53A6K1nG/bmSp0z3qB7VV
4ji2kqYe1c5DFgruFG/Ov6+94Dw4PJbVUe6hdqs29b+zWhghfFcKlRhhDnjq5iZg
cd158frWm2CQ199K2r3WDhenr6rkSX0wN9Av9OAg+8QdYQot6iL13GtuGd+Dhp+I
6K7st/oatJOL0d5oTR32dJIUC3j6ElRQnkmbkUWz8/kYo6prPCpvLeYvajahUg4N
mFoOia1W2C8k5tCgUHbqnuDMJRd3cZ/HHMOEauN7Ha0xrOuPHH46Nuyau/vSbVbD
vFOTz8C1VnpaXla0kn0d41/SIk4TYvJFVYChKfglG5CZ8HrRixUeM4F1q7oYOcbC
QzpK2fpZacB2dYaT7J3+zb74effXzPjPw6YkTzKgGPCPC7fQv73wsG9fjaRyA9Lv
x54ZpyVjOf80/b41VGKbxSvcC0d89EOhcjqh93lzIhbzUrIWOYZkqQ+1NY2pjSr0
Q0nzInNCSmwLBKJgJ4eG
=XOEw
-----END PGP SIGNATURE-----

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

* [U-Boot] [PATCH v2 1/6] omap3/cpu.h: add BCH support
  2013-04-02 16:05 ` [U-Boot] [PATCH v2 1/6] omap3/cpu.h: add BCH support Andreas Bießmann
                     ` (4 preceding siblings ...)
  2013-04-02 16:05   ` [U-Boot] [PATCH v2 6/6] tricorder: enable hw assisted BCH8 in SPL and u-boot Andreas Bießmann
@ 2013-04-02 21:19   ` Tom Rini
  2013-04-08 16:58   ` Tom Rini
  6 siblings, 0 replies; 32+ messages in thread
From: Tom Rini @ 2013-04-02 21:19 UTC (permalink / raw)
  To: u-boot

On Tue, Apr 02, 2013 at 06:05:53PM +0200, Andreas Bie??mann wrote:

> This patch adds the BCH result registers to register mapping for OMAP3 gpmc.
> 
> Signed-off-by: Andreas Bie??mann <andreas.devel@googlemail.com>
> Cc: Tom Rini <trini@ti.com>
> Cc: Ilya Yanok <ilya.yanok@cogentembedded.com>
> Cc: Scott Wood <scottwood@freescale.com>

Reviewed-by: Tom Rini <trini@ti.com>

-- 
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/20130402/7ed01e95/attachment.pgp>

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

* [U-Boot] [PATCH v2 2/6] asm/omap_gpmc.h: consolidate common defines
  2013-04-02 16:05   ` [U-Boot] [PATCH v2 2/6] asm/omap_gpmc.h: consolidate common defines Andreas Bießmann
@ 2013-04-02 21:19     ` Tom Rini
  0 siblings, 0 replies; 32+ messages in thread
From: Tom Rini @ 2013-04-02 21:19 UTC (permalink / raw)
  To: u-boot

On Tue, Apr 02, 2013 at 06:05:54PM +0200, Andreas Bie??mann wrote:

> arch/arm/include/asm/arch-am33xx/omap_gpmc.h and
> arch/arm/include/asm/arch-omap3/omap_gpmc.h are almost the same, consolidate
> the common parts into a new header.
> 
> Introduce a new asm/omap_gpmc.h which defines the command part and pulls in
> the architecture specific one.
> 
> Signed-off-by: Andreas Bie??mann <andreas.devel@googlemail.com>
> Cc: Tom Rini <trini@ti.com>

Reviewed-by: Tom Rini <trini@ti.com>

-- 
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/20130402/99f8b2b6/attachment.pgp>

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

* [U-Boot] [PATCH v2 3/6] omap3/omap_gpmc.h: add ooblayout for BCH8 as in kernel
  2013-04-02 16:05   ` [U-Boot] [PATCH v2 3/6] omap3/omap_gpmc.h: add ooblayout for BCH8 as in kernel Andreas Bießmann
@ 2013-04-02 21:19     ` Tom Rini
  0 siblings, 0 replies; 32+ messages in thread
From: Tom Rini @ 2013-04-02 21:19 UTC (permalink / raw)
  To: u-boot

On Tue, Apr 02, 2013 at 06:05:55PM +0200, Andreas Bie??mann wrote:

> This patch adds BCH8 ooblayout for NAND as provided by
> 0e618ef0a6a33cf7ef96c2c824402088dd8ef48c in linux kernel. This Layout is
> currently only provided for 64 byte OOB.
> 
> Signed-off-by: Andreas Bie??mann <andreas.devel@googlemail.com>
> Cc: Tom Rini <trini@ti.com>
> Cc: Ilya Yanok <ilya.yanok@cogentembedded.com>
> Cc: Scott Wood <scottwood@freescale.com>

Reviewed-by: Tom Rini <trini@ti.com>

-- 
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/20130402/be41a137/attachment.pgp>

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

* [U-Boot] [PATCH v2 4/6] omap_gpmc: change nandecc command
  2013-04-02 16:05   ` [U-Boot] [PATCH v2 4/6] omap_gpmc: change nandecc command Andreas Bießmann
@ 2013-04-02 21:19     ` Tom Rini
  2013-04-03 14:50     ` [U-Boot] [PATCH v3 " Andreas Bießmann
  1 sibling, 0 replies; 32+ messages in thread
From: Tom Rini @ 2013-04-02 21:19 UTC (permalink / raw)
  To: u-boot

On Tue, Apr 02, 2013 at 06:05:56PM +0200, Andreas Bie??mann wrote:

> With uppcoming BCH support on OMAP devices we need to decide between differnt
> algorithms when switching the ECC engine.  Currently we support 1-bit hammign
> and 8-bit BCH on HW backend.
> 
> In order to switch between differnet ECC algorithms we need to change the
> interface of omap_nand_switch_ecc() also.
> 
> Signed-off-by: Andreas Bie??mann <andreas.devel@googlemail.com>
> Cc: Tom Rini <trini@ti.com>

I've merged the bool patch, so we should be able to use that:
> -void omap_nand_switch_ecc(int32_t hardware)
> +void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)

here, yes?

-- 
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/20130402/728b1665/attachment.pgp>

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

* [U-Boot] [PATCH v2 5/6] omap_gpmc: add support for hw assisted BCH8
  2013-04-02 16:05   ` [U-Boot] [PATCH v2 5/6] omap_gpmc: add support for hw assisted BCH8 Andreas Bießmann
@ 2013-04-02 21:19     ` Tom Rini
  0 siblings, 0 replies; 32+ messages in thread
From: Tom Rini @ 2013-04-02 21:19 UTC (permalink / raw)
  To: u-boot

On Tue, Apr 02, 2013 at 06:05:57PM +0200, Andreas Bie??mann wrote:

> The BCH for OMAP3 is implemented as the linux kernel in
> 0e618ef0a6a33cf7ef96c2c824402088dd8ef48c does.
> 
> The kernel states:
> 
> ---8<---
> The OMAP3 GPMC hardware BCH engine computes remainder polynomials, it does not
> provide automatic error location and correction: this step is implemented using
> the BCH library.
> --->8---
> 
> And we do so in u-boot.
> 
> This implementation uses the same layout for BCH8 but it is fix. The current
> provided layout does only work with 64 Byte OOB.
> 
> Signed-off-by: Andreas Bie??mann <andreas.devel@googlemail.com>
> Cc: Tom Rini <trini@ti.com>
> Cc: Ilya Yanok <ilya.yanok@cogentembedded.com>
> Cc: Scott Wood <scottwood@freescale.com>
> Cc: Mansoor Ahamed <mansoor.ahamed@ti.com>
> ---
> since v1:
>  * cleanups (remove debug stuff)
>  * make checkpach clean (still 2 warnings which I will not fix)
>  * merge some code with the AM33XX implementation
> 
> known checkpatch errors:
> WARNING: line over 80 characters
> #92: FILE: drivers/mtd/nand/omap_gpmc.c:273:
> +static void __maybe_unused omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
> 
> WARNING: line over 80 characters
> #165: FILE: drivers/mtd/nand/omap_gpmc.c:346:
> +static void __maybe_unused omap_enable_ecc_bch(struct mtd_info *mtd, int32_t mode)
> 
> total: 0 errors, 2 warnings, 0 checks, 428 lines checked

Please correct these.

> +	default:
> +		/* by default eccsize0 selected for ecc1resultsize */
> +		/* eccsize0 config */

/*
 * Like this.
 */

> +	/* by default 512bytes sector page is selected */

Insert a newline here since this isn't a multi-line comment, but a
general note, followed by comments about what's going on.

> +	/* set bch mode */
> +	val  = (1 << 16);

So newline between these blocks

> +	/* bch4 / bch8 / bch16 */
> +	val |= (bch->type << 12);
> +	val |= (wr_mode << 8);
> +	val |= (dev_width << 7);
> +	val |= (cs << 1);

And here.

> +	debug("set ECC_CONFIG=0x%08x\n", val);
> +	writel(val, &gpmc_cfg->ecc_config);
> +}

And I see these are copied style problems.

-- 
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/20130402/2dcaa5ed/attachment.pgp>

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

* [U-Boot] [PATCH v3 4/6] omap_gpmc: change nandecc command
  2013-04-02 16:05   ` [U-Boot] [PATCH v2 4/6] omap_gpmc: change nandecc command Andreas Bießmann
  2013-04-02 21:19     ` Tom Rini
@ 2013-04-03 14:50     ` Andreas Bießmann
  2013-04-03 14:50       ` [U-Boot] [PATCH v3 5/6] omap_gpmc: add support for hw assisted BCH8 Andreas Bießmann
  2013-04-05  9:52       ` [U-Boot] [PATCH v4 4/6] omap_gpmc: change nandecc command Andreas Bießmann
  1 sibling, 2 replies; 32+ messages in thread
From: Andreas Bießmann @ 2013-04-03 14:50 UTC (permalink / raw)
  To: u-boot

With uppcoming BCH support on OMAP devices we need to decide between differnt
algorithms when switching the ECC engine.  Currently we support 1-bit hammign
and 8-bit BCH on HW backend.

In order to switch between differnet ECC algorithms we need to change the
interface of omap_nand_switch_ecc() also.

Signed-off-by: Andreas Bie?mann <andreas.devel@googlemail.com>
Cc: Tom Rini <trini@ti.com>
---
new in v2

since v2:
 * use void omap_nand_switch_ecc(bool, uint32_t)
 * print warning if unknown HW ecc strengs choosen
 * fix alignment in help test

 arch/arm/cpu/armv7/omap3/board.c             |   31 +++++++++----
 arch/arm/include/asm/arch-am33xx/sys_proto.h |    2 +-
 arch/arm/include/asm/arch-omap3/sys_proto.h  |    2 +-
 drivers/mtd/nand/omap_gpmc.c                 |   61 ++++++++++++++------------
 4 files changed, 59 insertions(+), 37 deletions(-)

diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c
index c6d9a42..0150150 100644
--- a/arch/arm/cpu/armv7/omap3/board.c
+++ b/arch/arm/cpu/armv7/omap3/board.c
@@ -328,14 +328,25 @@ void abort(void)
  *****************************************************************************/
 static int do_switch_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
-	if (argc != 2)
+	if (argc < 2 || argc > 3)
 		goto usage;
-	if (strncmp(argv[1], "hw", 2) == 0)
-		omap_nand_switch_ecc(1);
-	else if (strncmp(argv[1], "sw", 2) == 0)
-		omap_nand_switch_ecc(0);
-	else
+
+	if (strncmp(argv[1], "hw", 2) == 0) {
+		if (argc == 2) {
+			omap_nand_switch_ecc(true, 1);
+		} else {
+			if (strncmp(argv[2], "hamming", 7) == 0)
+				omap_nand_switch_ecc(true, 1);
+			else if (strncmp(argv[2], "bch8", 4) == 0)
+				omap_nand_switch_ecc(true, 8);
+			else
+				goto usage;
+		}
+	} else if (strncmp(argv[1], "sw", 2) == 0) {
+		omap_nand_switch_ecc(false, 0);
+	} else {
 		goto usage;
+	}
 
 	return 0;
 
@@ -345,9 +356,13 @@ usage:
 }
 
 U_BOOT_CMD(
-	nandecc, 2, 1,	do_switch_ecc,
+	nandecc, 3, 1,	do_switch_ecc,
 	"switch OMAP3 NAND ECC calculation algorithm",
-	"[hw/sw] - Switch between NAND hardware (hw) or software (sw) ecc algorithm"
+	"hw [hamming|bch8] - Switch between NAND hardware 1-bit hamming and"
+	" 8-bit BCH\n"
+	"                            ecc calculation (second parameter may"
+	" be omitted).\n"
+	"nandecc sw                - Switch to NAND software ecc algorithm."
 );
 
 #endif /* CONFIG_NAND_OMAP_GPMC & !CONFIG_SPL_BUILD */
diff --git a/arch/arm/include/asm/arch-am33xx/sys_proto.h b/arch/arm/include/asm/arch-am33xx/sys_proto.h
index 0910a94..23a3049 100644
--- a/arch/arm/include/asm/arch-am33xx/sys_proto.h
+++ b/arch/arm/include/asm/arch-am33xx/sys_proto.h
@@ -39,5 +39,5 @@ struct gpmc_cs;
 void gpmc_init(void);
 void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,
 			u32 size);
-void omap_nand_switch_ecc(int);
+void omap_nand_switch_ecc(bool, uint32_t);
 #endif
diff --git a/arch/arm/include/asm/arch-omap3/sys_proto.h b/arch/arm/include/asm/arch-omap3/sys_proto.h
index d60f2ad..4ca4e73 100644
--- a/arch/arm/include/asm/arch-omap3/sys_proto.h
+++ b/arch/arm/include/asm/arch-omap3/sys_proto.h
@@ -78,7 +78,7 @@ void sr32(void *, u32, u32, u32);
 u32 wait_on_value(u32, u32, void *, u32);
 void sdelay(unsigned long);
 void make_cs1_contiguous(void);
-void omap_nand_switch_ecc(int);
+void omap_nand_switch_ecc(bool, uint32_t);
 void power_init_r(void);
 void dieid_num_r(void);
 void do_omap3_emu_romcode_call(u32 service_id, u32 parameters);
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index c7d4999..0647828 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -604,13 +604,14 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
 
 #ifndef CONFIG_SPL_BUILD
 /*
- * omap_nand_switch_ecc - switch the ECC operation b/w h/w ecc and s/w ecc.
- * The default is to come up on s/w ecc
- *
- * @hardware - 1 -switch to h/w ecc, 0 - s/w ecc
+ * omap_nand_switch_ecc - switch the ECC operation between different engines
+ * (h/w and s/w) and different algorithms (hamming and BCHx)
  *
+ * @hardware		- true if one of the HW engines should be used
+ * @eccstrength		- the number of bits that could be corrected
+ *			  (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
  */
-void omap_nand_switch_ecc(int32_t hardware)
+void omap_nand_switch_ecc(bool hardware, uint32_t eccstrength)
 {
 	struct nand_chip *nand;
 	struct mtd_info *mtd;
@@ -637,35 +638,41 @@ void omap_nand_switch_ecc(int32_t hardware)
 	nand->ecc.calculate = NULL;
 
 	/* Setup the ecc configurations again */
-	if (hardware == 1) {
-		nand->ecc.mode = NAND_ECC_HW;
-		nand->ecc.layout = &hw_nand_oob;
-		nand->ecc.size = 512;
-		nand->ecc.bytes = 3;
-		nand->ecc.hwctl = omap_enable_hwecc;
-		nand->ecc.correct = omap_correct_data;
-		nand->ecc.calculate = omap_calculate_ecc;
-		omap_hwecc_init(nand);
-		printf("HW ECC selected\n");
+	if (hardware) {
+		if (eccstrength == 1) {
+			nand->ecc.mode = NAND_ECC_HW;
+			nand->ecc.layout = &hw_nand_oob;
+			nand->ecc.size = 512;
+			nand->ecc.bytes = 3;
+			nand->ecc.hwctl = omap_enable_hwecc;
+			nand->ecc.correct = omap_correct_data;
+			nand->ecc.calculate = omap_calculate_ecc;
+			omap_hwecc_init(nand);
+			puts("1-bit hamming HW ECC selected\n");
+		}
 #ifdef CONFIG_AM33XX
-	} else if (hardware == 2) {
-		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;
-		omap_hwecc_init_bch(nand, NAND_ECC_READ);
-		printf("HW BCH8 selected\n");
+		else if (eccstrength == 8) {
+			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;
+			omap_hwecc_init_bch(nand, NAND_ECC_READ);
+			puts("8-bit BCH HW ECC selected\n");
+		}
 #endif
+		else {
+			puts("Unsupported HW ECC algorithm\n");
+		}
 	} else {
 		nand->ecc.mode = NAND_ECC_SOFT;
 		/* Use mtd default settings */
 		nand->ecc.layout = NULL;
 		nand->ecc.size = 0;
-		printf("SW ECC selected\n");
+		puts("SW ECC selected\n");
 	}
 
 	/* Update NAND handling after ECC mode switch */
-- 
1.7.10.4

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

* [U-Boot] [PATCH v3 5/6] omap_gpmc: add support for hw assisted BCH8
  2013-04-03 14:50     ` [U-Boot] [PATCH v3 " Andreas Bießmann
@ 2013-04-03 14:50       ` Andreas Bießmann
  2013-04-05  8:13         ` Thomas Weber
  2013-04-05 11:44         ` Thomas Weber
  2013-04-05  9:52       ` [U-Boot] [PATCH v4 4/6] omap_gpmc: change nandecc command Andreas Bießmann
  1 sibling, 2 replies; 32+ messages in thread
From: Andreas Bießmann @ 2013-04-03 14:50 UTC (permalink / raw)
  To: u-boot

The kernel states:

---8<---
The OMAP3 GPMC hardware BCH engine computes remainder polynomials, it does not
provide automatic error location and correction: this step is implemented using
the BCH library.
--->8---

And we do so in u-boot.

This implementation uses the same layout for BCH8 but it is fix. The current
provided layout does only work with 64 Byte OOB.

Signed-off-by: Andreas Bie?mann <andreas.devel@googlemail.com>
Cc: Tom Rini <trini@ti.com>
Cc: Ilya Yanok <ilya.yanok@cogentembedded.com>
Cc: Scott Wood <scottwood@freescale.com>
Cc: Mansoor Ahamed <mansoor.ahamed@ti.com>
---
since v1:
 * cleanups (remove debug stuff)
 * make checkpach clean (still 2 warnings which I will not fix)
 * merge some code with the AM33XX implementation

since v2:
 * fix all checkpatch warnings
 * add more comments
 * add NAND section in README.omap3

 doc/README.omap3             |   19 +++
 drivers/mtd/nand/omap_gpmc.c |  367 +++++++++++++++++++++++++++++++-----------
 lib/Makefile                 |    2 +-
 3 files changed, 296 insertions(+), 92 deletions(-)

diff --git a/doc/README.omap3 b/doc/README.omap3
index 0a37de0..56aca8e 100644
--- a/doc/README.omap3
+++ b/doc/README.omap3
@@ -145,6 +145,25 @@ int omap3_dma_wait_for_transfer(uint32_t chan)
 int omap3_dma_get_revision(uint32_t *minor, uint32_t *major)
 	Read silicon Revision of the DMA module
 
+NAND
+====
+
+Ther eare some OMAP3 devices out ther with NAND attached. Due to the fact that
+OMAP3 ROM code can only handle 1-bit hamming ECC for accessing first page
+(place where SPL lives) we require this setup for u-boot at least when reading
+the second progam within SPL.  A lot of newer NAND chips however require more
+than 1-bit ECC for the pages, some can live with 1-bit for the first page. To
+handle this we can switch to another ECC algorithm after reading the payload
+within SPL.
+
+BCH8
+----
+
+To enable hardware assisted BCH8 (8-bit BCH [Bose, Chaudhuri, Hocquenghem]) on
+OMAP3 devices we can use the BCH library in lib/bch.c. To do so add CONFIG_BCH
+to enable the library and CONFIG_NAND_OMAP_BCH8 to your board config.
+The NAND OOB layout is the same as in linux kernel, if the linux kernel BCH8
+implementation for OMAP3 works for you so the u-boot version should also.
 
 Acknowledgements
 ================
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index 0647828..de41e46 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -28,6 +28,7 @@
 #include <asm/arch/cpu.h>
 #include <asm/omap_gpmc.h>
 #include <linux/mtd/nand_ecc.h>
+#include <linux/bch.h>
 #include <linux/compiler.h>
 #include <nand.h>
 #ifdef CONFIG_AM33XX
@@ -37,6 +38,8 @@
 static uint8_t cs;
 static __maybe_unused struct nand_ecclayout hw_nand_oob =
 	GPMC_NAND_HW_ECC_LAYOUT;
+static __maybe_unused struct nand_ecclayout hw_bch8_nand_oob =
+	GPMC_NAND_HW_BCH8_ECC_LAYOUT;
 
 /*
  * omap_nand_hwcontrol - Set the address pointers corretly for the
@@ -239,13 +242,13 @@ static void __maybe_unused omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
 }
 
 /*
- * BCH8 support (needs ELM and thus AM33xx-only)
+ * Generic BCH interface
  */
-#ifdef CONFIG_AM33XX
 struct nand_bch_priv {
 	uint8_t mode;
 	uint8_t type;
 	uint8_t nibbles;
+	struct bch_control *control;
 };
 
 /* bch types */
@@ -253,21 +256,146 @@ 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
 
-static struct nand_ecclayout hw_bch8_nand_oob = GPMC_NAND_HW_BCH8_ECC_LAYOUT;
-
-static struct nand_bch_priv bch_priv = {
+/*
+ * This can be a single instance cause all current users have only one NAND
+ * with nearly the same setup (BCH8, some with ELM and others with sw BCH
+ * library).
+ * 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
+	.nibbles = ECC_BCH8_NIBBLES,
+	.control = NULL
 };
 
 /*
+ * omap_hwecc_init_bch - Initialize the BCH Hardware ECC for NAND flash in
+ *				GPMC controller
+ * @mtd:	MTD device structure
+ * @mode:	Read/Write mode
+ */
+__maybe_unused
+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
+	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);
+
+#ifdef CONFIG_AM33XX
+	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;
+	}
+#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);
+#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);
+}
+
+/*
+ * 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);
+}
+
+/*
+ * BCH8 support (needs ELM and thus AM33xx-only)
+ */
+#ifdef CONFIG_AM33XX
+/*
  * omap_read_bch8_result - Read BCH result for BCH8 level
  *
  * @mtd:	MTD device structure
@@ -306,18 +434,6 @@ static void omap_read_bch8_result(struct mtd_info *mtd, uint8_t big_endian,
 }
 
 /*
- * omap_ecc_disable - Disable H/W ECC calculation
- *
- * @mtd:	MTD device structure
- *
- */
-static void omap_ecc_disable(struct mtd_info *mtd)
-{
-	writel((readl(&gpmc_cfg->ecc_config) & ~0x1),
-		&gpmc_cfg->ecc_config);
-}
-
-/*
  * omap_rotate_ecc_bch - Rotate the syndrome bytes
  *
  * @mtd:	MTD device structure
@@ -468,76 +584,6 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
 
 	return 0;
 }
-/*
- * omap_hwecc_init_bch - Initialize the BCH Hardware ECC for NAND flash in
- *				GPMC controller
- * @mtd:       MTD device structure
- * @mode:	Read/Write mode
- */
-static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
-{
-	uint32_t val, dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
-	uint32_t unused_length = 0;
-	struct nand_bch_priv *bch = chip->priv;
-
-	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;
-	}
-
-	/* Clear the ecc result registers, select ecc reg as 1 */
-	writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
-
-	switch (mode) {
-	case NAND_ECC_WRITE:
-		/* 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;
-	}
-	/* ecc size configuration */
-	writel(val, &gpmc_cfg->ecc_size_config);
-	/* by default 512bytes sector page is selected */
-	/* set bch mode */
-	val  = (1 << 16);
-	/* bch4 / bch8 / bch16 */
-	val |= (bch->type << 12);
-	/* set wrap mode to 1 */
-	val |= (1 << 8);
-	val |= (dev_width << 7);
-	val |= (cs << 1);
-	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
- *
- */
-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);
-}
 
 /**
  * omap_read_page_bch - hardware ecc based page read function
@@ -602,6 +648,127 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
 }
 #endif /* CONFIG_AM33XX */
 
+/*
+ * OMAP3 BCH8 support (with BCH library)
+ */
+#ifdef CONFIG_NAND_OMAP_BCH8
+/*
+ *  omap_calculate_ecc_bch - 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(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 - Decode received data and correct errors
+ * @mtd: MTD device structure
+ * @data: page data
+ * @read_ecc: ecc read from nand flash
+ * @calc_ecc: ecc read from HW ECC registers
+ */
+static int omap_correct_data_bch(struct mtd_info *mtd, u_char *data,
+				 u_char *read_ecc, u_char *calc_ecc)
+{
+	int i, count;
+	/* cannot correct more than 8 errors */
+	unsigned int errloc[8];
+	struct nand_chip *chip = mtd->priv;
+	struct nand_bch_priv *chip_priv = chip->priv;
+	struct bch_control *bch = chip_priv->control;
+
+	count = decode_bch(bch, NULL, 512, read_ecc, calc_ecc, NULL, errloc);
+	if (count > 0) {
+		/* correct errors */
+		for (i = 0; i < count; i++) {
+			/* correct data only, not ecc bytes */
+			if (errloc[i] < 8*512)
+				data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
+			printf("corrected bitflip %u\n", errloc[i]);
+#ifdef DEBUG
+			puts("read_ecc: ");
+			/*
+			 * BCH8 have 13 bytes of ECC; BCH4 needs adoption
+			 * here!
+			 */
+			for (i = 0; i < 13; i++)
+				printf("%02x ", read_ecc[i]);
+			puts("\n");
+			puts("calc_ecc: ");
+			for (i = 0; i < 13; i++)
+				printf("%02x ", calc_ecc[i]);
+			puts("\n");
+#endif
+		}
+	} else if (count < 0) {
+		puts("ecc unrecoverable error\n");
+	}
+	return count;
+}
+
+/**
+ * omap_free_bch - Release BCH ecc resources
+ * @mtd: MTD device structure
+ */
+static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct nand_bch_priv *chip_priv = chip->priv;
+	struct bch_control *bch = NULL;
+
+	if (chip_priv)
+		bch = chip_priv->control;
+
+	if (bch) {
+		free_bch(bch);
+		chip_priv->control = NULL;
+	}
+}
+#endif /* CONFIG_NAND_OMAP_BCH8 */
+
 #ifndef CONFIG_SPL_BUILD
 /*
  * omap_nand_switch_ecc - switch the ECC operation between different engines
@@ -650,13 +817,17 @@ void omap_nand_switch_ecc(bool hardware, uint32_t eccstrength)
 			omap_hwecc_init(nand);
 			puts("1-bit hamming HW ECC selected\n");
 		}
-#ifdef CONFIG_AM33XX
+#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
+			nand->ecc.bytes = 13;
+#endif
 			nand->ecc.hwctl = omap_enable_ecc_bch;
 			nand->ecc.correct = omap_correct_data_bch;
 			nand->ecc.calculate = omap_calculate_ecc_bch;
@@ -739,16 +910,28 @@ 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 */
 	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 */);
+	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 */
-#ifdef CONFIG_AM33XX
+#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;
@@ -756,7 +939,9 @@ int board_nand_init(struct nand_chip *nand)
 	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)
diff --git a/lib/Makefile b/lib/Makefile
index 1bfd3ee..5d71b80 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -27,7 +27,6 @@ LIB	= $(obj)libgeneric.o
 
 ifndef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_ADDR_MAP) += addr_map.o
-COBJS-$(CONFIG_BCH) += bch.o
 COBJS-$(CONFIG_AES) += aes.o
 COBJS-$(CONFIG_BZIP2) += bzlib.o
 COBJS-$(CONFIG_BZIP2) += bzlib_crctable.o
@@ -67,6 +66,7 @@ COBJS-$(CONFIG_SPL_NET_SUPPORT) += errno.o
 COBJS-$(CONFIG_SPL_NET_SUPPORT) += hashtable.o
 COBJS-$(CONFIG_SPL_NET_SUPPORT) += net_utils.o
 endif
+COBJS-$(CONFIG_BCH) += bch.o
 COBJS-y += crc32.o
 COBJS-y += ctype.o
 COBJS-y += div64.o
-- 
1.7.10.4

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

* [U-Boot] [PATCH v3 5/6] omap_gpmc: add support for hw assisted BCH8
  2013-04-03 14:50       ` [U-Boot] [PATCH v3 5/6] omap_gpmc: add support for hw assisted BCH8 Andreas Bießmann
@ 2013-04-05  8:13         ` Thomas Weber
  2013-04-05  9:15           ` Andreas Bießmann
  2013-04-05 11:44         ` Thomas Weber
  1 sibling, 1 reply; 32+ messages in thread
From: Thomas Weber @ 2013-04-05  8:13 UTC (permalink / raw)
  To: u-boot

Hello Andreas,

I have the following problem when switching from nandecc hw hamming to
nandecc hw bch8.

Thomas

-------8<----------
U-Boot 2013.04-rc2-00006-g9abd2ec (Apr 05 2013 - 09:58:48)

OMAP3530-GP ES3.1, CPU-OPP2, L3-165MHz, Max CPU Clock 600 mHz
OMAP3 DevKit8000 + LPDDR/NAND
I2C:   ready
DRAM:  128 MiB
NAND:  128 MiB
MMC:   OMAP SD/MMC: 0
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
ethaddr not set, using Die ID
Die ID #1d82000400000000040365f90100b017
Net:   dm9000
Hit any key to stop autoboot:  0
OMAP3 DevKit8000 # nandecc hw bch8
Unsupported HW ECC algorithm
OMAP3 DevKit8000 # nandecc hw bch8
Unsupported HW ECC algorithm
OMAP3 DevKit8000 # nandecc hw hamming
1-bit hamming HW ECC selected
OMAP3 DevKit8000 # nandecc sw
SW ECC selected
OMAP3 DevKit8000 # nandecc hw bch8
Unsupported HW ECC algorithm
OMAP3 DevKit8000 # nandecc hw hamming
1-bit hamming HW ECC selected
OMAP3 DevKit8000 # nandecc hw bch8
Unsupported HW ECC algorithm
No ECC functions supplied; Hardware ECC not possible
BUG: failure@nand_base.c:3014/nand_scan_tail()!
BUG!
resetting ...
----------->8--------------

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

* [U-Boot] [PATCH v3 5/6] omap_gpmc: add support for hw assisted BCH8
  2013-04-05  8:13         ` Thomas Weber
@ 2013-04-05  9:15           ` Andreas Bießmann
  0 siblings, 0 replies; 32+ messages in thread
From: Andreas Bießmann @ 2013-04-05  9:15 UTC (permalink / raw)
  To: u-boot

Dear Thomas Weber,

On 04/05/2013 10:13 AM, Thomas Weber wrote:
> Hello Andreas,
> 
> I have the following problem when switching from nandecc hw hamming to
> nandecc hw bch8.
> 
> Thomas
> 
> -------8<----------
> U-Boot 2013.04-rc2-00006-g9abd2ec (Apr 05 2013 - 09:58:48)
> 
> OMAP3530-GP ES3.1, CPU-OPP2, L3-165MHz, Max CPU Clock 600 mHz
> OMAP3 DevKit8000 + LPDDR/NAND
> I2C:   ready
> DRAM:  128 MiB
> NAND:  128 MiB
> MMC:   OMAP SD/MMC: 0
> *** Warning - bad CRC, using default environment
> 
> In:    serial
> Out:   serial
> Err:   serial
> ethaddr not set, using Die ID
> Die ID #1d82000400000000040365f90100b017
> Net:   dm9000
> Hit any key to stop autoboot:  0
> OMAP3 DevKit8000 # nandecc hw bch8
> Unsupported HW ECC algorithm
> OMAP3 DevKit8000 # nandecc hw bch8
> Unsupported HW ECC algorithm
> OMAP3 DevKit8000 # nandecc hw hamming
> 1-bit hamming HW ECC selected
> OMAP3 DevKit8000 # nandecc sw
> SW ECC selected
> OMAP3 DevKit8000 # nandecc hw bch8
> Unsupported HW ECC algorithm
> OMAP3 DevKit8000 # nandecc hw hamming
> 1-bit hamming HW ECC selected
> OMAP3 DevKit8000 # nandecc hw bch8
> Unsupported HW ECC algorithm
> No ECC functions supplied; Hardware ECC not possible
> BUG: failure at nand_base.c:3014/nand_scan_tail()!
> BUG!

You are right. I'v never tested the nandecc changes without the new
CONFIG_NAND_OMAP_BCH8 config parameter, many thanks to you!

I've a fix for that and will repost v4 ASAP.

Best regards

Andreas Bie?mann

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

* [U-Boot] [PATCH v4 4/6] omap_gpmc: change nandecc command
  2013-04-03 14:50     ` [U-Boot] [PATCH v3 " Andreas Bießmann
  2013-04-03 14:50       ` [U-Boot] [PATCH v3 5/6] omap_gpmc: add support for hw assisted BCH8 Andreas Bießmann
@ 2013-04-05  9:52       ` Andreas Bießmann
  2013-04-05 11:48         ` Thomas Weber
  1 sibling, 1 reply; 32+ messages in thread
From: Andreas Bießmann @ 2013-04-05  9:52 UTC (permalink / raw)
  To: u-boot

With uppcoming BCH support on OMAP devices we need to decide between differnt
algorithms when switching the ECC engine.  Currently we support 1-bit hammign
and 8-bit BCH on HW backend.

In order to switch between differnet ECC algorithms we need to change the
interface of omap_nand_switch_ecc() also.

Signed-off-by: Andreas Bie?mann <andreas.devel@googlemail.com>
Cc: Tom Rini <trini@ti.com>
Cc: Thomas Weber <thomas.weber.linux@googlemail.com>
---
new in v2

since v2:
 * use void omap_nand_switch_ecc(bool, uint32_t)
 * print warning if unknown HW ecc strengs choosen
 * fix alignment in help test

since v3:
 * reset ecc.mode to NAND_ECC_NONE to prevent a BUG() on wrong eccstrength
   input to changed omap_nand_switch_ecc();
   With this change a user has the chance to switch back to another ECC mode
   via nandecc command.
   Many thanks to Thomas Weber for reporting this.

 arch/arm/cpu/armv7/omap3/board.c             |   31 ++++++++++----
 arch/arm/include/asm/arch-am33xx/sys_proto.h |    2 +-
 arch/arm/include/asm/arch-omap3/sys_proto.h  |    2 +-
 drivers/mtd/nand/omap_gpmc.c                 |   57 ++++++++++++++------------
 4 files changed, 56 insertions(+), 36 deletions(-)

diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c
index c6d9a42..b72fadc 100644
--- a/arch/arm/cpu/armv7/omap3/board.c
+++ b/arch/arm/cpu/armv7/omap3/board.c
@@ -328,14 +328,25 @@ void abort(void)
  *****************************************************************************/
 static int do_switch_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 {
-	if (argc != 2)
+	if (argc < 2 || argc > 3)
 		goto usage;
-	if (strncmp(argv[1], "hw", 2) == 0)
-		omap_nand_switch_ecc(1);
-	else if (strncmp(argv[1], "sw", 2) == 0)
-		omap_nand_switch_ecc(0);
-	else
+
+	if (strncmp(argv[1], "hw", 2) == 0) {
+		if (argc == 2) {
+			omap_nand_switch_ecc(1, 1);
+		} else {
+			if (strncmp(argv[2], "hamming", 7) == 0)
+				omap_nand_switch_ecc(1, 1);
+			else if (strncmp(argv[2], "bch8", 4) == 0)
+				omap_nand_switch_ecc(1, 8);
+			else
+				goto usage;
+		}
+	} else if (strncmp(argv[1], "sw", 2) == 0) {
+		omap_nand_switch_ecc(0, 0);
+	} else {
 		goto usage;
+	}
 
 	return 0;
 
@@ -345,9 +356,13 @@ usage:
 }
 
 U_BOOT_CMD(
-	nandecc, 2, 1,	do_switch_ecc,
+	nandecc, 3, 1,	do_switch_ecc,
 	"switch OMAP3 NAND ECC calculation algorithm",
-	"[hw/sw] - Switch between NAND hardware (hw) or software (sw) ecc algorithm"
+	"hw [hamming|bch8] - Switch between NAND hardware 1-bit hamming and"
+	" 8-bit BCH\n"
+	"                           ecc calculation (second parameter may"
+	" be omitted).\n"
+	"nandecc sw               - Switch to NAND software ecc algorithm."
 );
 
 #endif /* CONFIG_NAND_OMAP_GPMC & !CONFIG_SPL_BUILD */
diff --git a/arch/arm/include/asm/arch-am33xx/sys_proto.h b/arch/arm/include/asm/arch-am33xx/sys_proto.h
index 0910a94..c913b5f 100644
--- a/arch/arm/include/asm/arch-am33xx/sys_proto.h
+++ b/arch/arm/include/asm/arch-am33xx/sys_proto.h
@@ -39,5 +39,5 @@ struct gpmc_cs;
 void gpmc_init(void);
 void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,
 			u32 size);
-void omap_nand_switch_ecc(int);
+void omap_nand_switch_ecc(uint32_t, uint32_t);
 #endif
diff --git a/arch/arm/include/asm/arch-omap3/sys_proto.h b/arch/arm/include/asm/arch-omap3/sys_proto.h
index d60f2ad..dae1312 100644
--- a/arch/arm/include/asm/arch-omap3/sys_proto.h
+++ b/arch/arm/include/asm/arch-omap3/sys_proto.h
@@ -78,7 +78,7 @@ void sr32(void *, u32, u32, u32);
 u32 wait_on_value(u32, u32, void *, u32);
 void sdelay(unsigned long);
 void make_cs1_contiguous(void);
-void omap_nand_switch_ecc(int);
+void omap_nand_switch_ecc(uint32_t, uint32_t);
 void power_init_r(void);
 void dieid_num_r(void);
 void do_omap3_emu_romcode_call(u32 service_id, u32 parameters);
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index c7d4999..3468c78 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -604,13 +604,14 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
 
 #ifndef CONFIG_SPL_BUILD
 /*
- * omap_nand_switch_ecc - switch the ECC operation b/w h/w ecc and s/w ecc.
- * The default is to come up on s/w ecc
- *
- * @hardware - 1 -switch to h/w ecc, 0 - s/w ecc
+ * omap_nand_switch_ecc - switch the ECC operation between different engines
+ * (h/w and s/w) and different algorithms (hamming and BCHx)
  *
+ * @hardware		- true if one of the HW engines should be used
+ * @eccstrength		- the number of bits that could be corrected
+ *			  (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
  */
-void omap_nand_switch_ecc(int32_t hardware)
+void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
 {
 	struct nand_chip *nand;
 	struct mtd_info *mtd;
@@ -628,6 +629,7 @@ void omap_nand_switch_ecc(int32_t hardware)
 	nand->options |= NAND_OWN_BUFFERS;
 
 	/* Reset ecc interface */
+	nand->ecc.mode = NAND_ECC_NONE;
 	nand->ecc.read_page = NULL;
 	nand->ecc.write_page = NULL;
 	nand->ecc.read_oob = NULL;
@@ -637,28 +639,31 @@ void omap_nand_switch_ecc(int32_t hardware)
 	nand->ecc.calculate = NULL;
 
 	/* Setup the ecc configurations again */
-	if (hardware == 1) {
-		nand->ecc.mode = NAND_ECC_HW;
-		nand->ecc.layout = &hw_nand_oob;
-		nand->ecc.size = 512;
-		nand->ecc.bytes = 3;
-		nand->ecc.hwctl = omap_enable_hwecc;
-		nand->ecc.correct = omap_correct_data;
-		nand->ecc.calculate = omap_calculate_ecc;
-		omap_hwecc_init(nand);
-		printf("HW ECC selected\n");
+	if (hardware) {
+		if (eccstrength == 1) {
+			nand->ecc.mode = NAND_ECC_HW;
+			nand->ecc.layout = &hw_nand_oob;
+			nand->ecc.size = 512;
+			nand->ecc.bytes = 3;
+			nand->ecc.hwctl = omap_enable_hwecc;
+			nand->ecc.correct = omap_correct_data;
+			nand->ecc.calculate = omap_calculate_ecc;
+			omap_hwecc_init(nand);
+			printf("1-bit hamming HW ECC selected\n");
+		}
 #ifdef CONFIG_AM33XX
-	} else if (hardware == 2) {
-		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;
-		omap_hwecc_init_bch(nand, NAND_ECC_READ);
-		printf("HW BCH8 selected\n");
+		else if (eccstrength == 8) {
+			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;
+			omap_hwecc_init_bch(nand, NAND_ECC_READ);
+			printf("8-bit BCH HW ECC selected\n");
+		}
 #endif
 	} else {
 		nand->ecc.mode = NAND_ECC_SOFT;
-- 
1.7.10.4

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

* [U-Boot] [PATCH v3 5/6] omap_gpmc: add support for hw assisted BCH8
  2013-04-03 14:50       ` [U-Boot] [PATCH v3 5/6] omap_gpmc: add support for hw assisted BCH8 Andreas Bießmann
  2013-04-05  8:13         ` Thomas Weber
@ 2013-04-05 11:44         ` Thomas Weber
  2013-04-05 13:42           ` Andreas Bießmann
  2013-04-05 14:55           ` [U-Boot] [PATCH v4 " Andreas Bießmann
  1 sibling, 2 replies; 32+ messages in thread
From: Thomas Weber @ 2013-04-05 11:44 UTC (permalink / raw)
  To: u-boot

Hello Andreas,

On 04/03/2013 04:50 PM, Andreas Bie?mann wrote:
> The kernel states:
>
> ---8<---
> The OMAP3 GPMC hardware BCH engine computes remainder polynomials, it does not
> provide automatic error location and correction: this step is implemented using
> the BCH library.
> --->8---
>
> And we do so in u-boot.
>
> This implementation uses the same layout for BCH8 but it is fix. The current
> provided layout does only work with 64 Byte OOB.
>
> Signed-off-by: Andreas Bie?mann <andreas.devel@googlemail.com>
> Cc: Tom Rini <trini@ti.com>
> Cc: Ilya Yanok <ilya.yanok@cogentembedded.com>
> Cc: Scott Wood <scottwood@freescale.com>
> Cc: Mansoor Ahamed <mansoor.ahamed@ti.com>
> ---
> since v1:
>  * cleanups (remove debug stuff)
>  * make checkpach clean (still 2 warnings which I will not fix)
>  * merge some code with the AM33XX implementation
>
> since v2:
>  * fix all checkpatch warnings
>  * add more comments
>  * add NAND section in README.omap3
>
>  doc/README.omap3             |   19 +++
>  drivers/mtd/nand/omap_gpmc.c |  367 +++++++++++++++++++++++++++++++-----------
>  lib/Makefile                 |    2 +-
>  3 files changed, 296 insertions(+), 92 deletions(-)
>
> diff --git a/doc/README.omap3 b/doc/README.omap3
> index 0a37de0..56aca8e 100644
> --- a/doc/README.omap3
> +++ b/doc/README.omap3
> @@ -145,6 +145,25 @@ int omap3_dma_wait_for_transfer(uint32_t chan)
>  int omap3_dma_get_revision(uint32_t *minor, uint32_t *major)
>  	Read silicon Revision of the DMA module
>  
> +NAND
> +====
> +
> +Ther eare some OMAP3 devices out ther with NAND attached. Due to the fact that
    ther -> there
> +OMAP3 ROM code can only handle 1-bit hamming ECC for accessing first page
> +(place where SPL lives) we require this setup for u-boot at least when reading
> +the second progam within SPL.  A lot of newer NAND chips however require more
> +than 1-bit ECC for the pages, some can live with 1-bit for the first page. To
> +handle this we can switch to another ECC algorithm after reading the payload
> +within SPL.
> +
> +BCH8
> +----
> +
> +To enable hardware assisted BCH8 (8-bit BCH [Bose, Chaudhuri, Hocquenghem]) on
> +OMAP3 devices we can use the BCH library in lib/bch.c. To do so add CONFIG_BCH
> +to enable the library and CONFIG_NAND_OMAP_BCH8 to your board config.
> +The NAND OOB layout is the same as in linux kernel, if the linux kernel BCH8
> +implementation for OMAP3 works for you so the u-boot version should also.
>  
>  Acknowledgements
>  ================
>
Thomas

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

* [U-Boot] [PATCH v4 4/6] omap_gpmc: change nandecc command
  2013-04-05  9:52       ` [U-Boot] [PATCH v4 4/6] omap_gpmc: change nandecc command Andreas Bießmann
@ 2013-04-05 11:48         ` Thomas Weber
  2013-04-05 13:39           ` Andreas Bießmann
  0 siblings, 1 reply; 32+ messages in thread
From: Thomas Weber @ 2013-04-05 11:48 UTC (permalink / raw)
  To: u-boot

Hello Andreas,

this patch fixes the reported BUG().

The output is now:

-----8<---------
OMAP3 DevKit8000 # nandecc hw hamming
1-bit hamming HW ECC selected
OMAP3 DevKit8000 # nandecc hw bch8
Unsupported HW ECC algorithm
NAND_ECC_NONE selected by board driver. This is not recommended !!
OMAP3 DevKit8000 #
----->8---------

Thomas

On 04/05/2013 11:52 AM, Andreas Bie?mann wrote:
> With uppcoming BCH support on OMAP devices we need to decide between differnt
> algorithms when switching the ECC engine.  Currently we support 1-bit hammign
> and 8-bit BCH on HW backend.
>
> In order to switch between differnet ECC algorithms we need to change the
> interface of omap_nand_switch_ecc() also.
>
> Signed-off-by: Andreas Bie?mann <andreas.devel@googlemail.com>
> Cc: Tom Rini <trini@ti.com>
> Cc: Thomas Weber <thomas.weber.linux@googlemail.com>
> ---
> new in v2
>
> since v2:
>  * use void omap_nand_switch_ecc(bool, uint32_t)
>  * print warning if unknown HW ecc strengs choosen
>  * fix alignment in help test
>
> since v3:
>  * reset ecc.mode to NAND_ECC_NONE to prevent a BUG() on wrong eccstrength
>    input to changed omap_nand_switch_ecc();
>    With this change a user has the chance to switch back to another ECC mode
>    via nandecc command.
>    Many thanks to Thomas Weber for reporting this.
>
>  arch/arm/cpu/armv7/omap3/board.c             |   31 ++++++++++----
>  arch/arm/include/asm/arch-am33xx/sys_proto.h |    2 +-
>  arch/arm/include/asm/arch-omap3/sys_proto.h  |    2 +-
>  drivers/mtd/nand/omap_gpmc.c                 |   57 ++++++++++++++------------
>  4 files changed, 56 insertions(+), 36 deletions(-)
>
> diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c
> index c6d9a42..b72fadc 100644
> --- a/arch/arm/cpu/armv7/omap3/board.c
> +++ b/arch/arm/cpu/armv7/omap3/board.c
> @@ -328,14 +328,25 @@ void abort(void)
>   *****************************************************************************/
>  static int do_switch_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
>  {
> -	if (argc != 2)
> +	if (argc < 2 || argc > 3)
>  		goto usage;
> -	if (strncmp(argv[1], "hw", 2) == 0)
> -		omap_nand_switch_ecc(1);
> -	else if (strncmp(argv[1], "sw", 2) == 0)
> -		omap_nand_switch_ecc(0);
> -	else
> +
> +	if (strncmp(argv[1], "hw", 2) == 0) {
> +		if (argc == 2) {
> +			omap_nand_switch_ecc(1, 1);
> +		} else {
> +			if (strncmp(argv[2], "hamming", 7) == 0)
> +				omap_nand_switch_ecc(1, 1);
> +			else if (strncmp(argv[2], "bch8", 4) == 0)
> +				omap_nand_switch_ecc(1, 8);
> +			else
> +				goto usage;
> +		}
> +	} else if (strncmp(argv[1], "sw", 2) == 0) {
> +		omap_nand_switch_ecc(0, 0);
> +	} else {
>  		goto usage;
> +	}
>  
>  	return 0;
>  
> @@ -345,9 +356,13 @@ usage:
>  }
>  
>  U_BOOT_CMD(
> -	nandecc, 2, 1,	do_switch_ecc,
> +	nandecc, 3, 1,	do_switch_ecc,
>  	"switch OMAP3 NAND ECC calculation algorithm",
> -	"[hw/sw] - Switch between NAND hardware (hw) or software (sw) ecc algorithm"
> +	"hw [hamming|bch8] - Switch between NAND hardware 1-bit hamming and"
> +	" 8-bit BCH\n"
> +	"                           ecc calculation (second parameter may"
> +	" be omitted).\n"
> +	"nandecc sw               - Switch to NAND software ecc algorithm."
>  );
>  
>  #endif /* CONFIG_NAND_OMAP_GPMC & !CONFIG_SPL_BUILD */
> diff --git a/arch/arm/include/asm/arch-am33xx/sys_proto.h b/arch/arm/include/asm/arch-am33xx/sys_proto.h
> index 0910a94..c913b5f 100644
> --- a/arch/arm/include/asm/arch-am33xx/sys_proto.h
> +++ b/arch/arm/include/asm/arch-am33xx/sys_proto.h
> @@ -39,5 +39,5 @@ struct gpmc_cs;
>  void gpmc_init(void);
>  void enable_gpmc_cs_config(const u32 *gpmc_config, struct gpmc_cs *cs, u32 base,
>  			u32 size);
> -void omap_nand_switch_ecc(int);
> +void omap_nand_switch_ecc(uint32_t, uint32_t);
>  #endif
> diff --git a/arch/arm/include/asm/arch-omap3/sys_proto.h b/arch/arm/include/asm/arch-omap3/sys_proto.h
> index d60f2ad..dae1312 100644
> --- a/arch/arm/include/asm/arch-omap3/sys_proto.h
> +++ b/arch/arm/include/asm/arch-omap3/sys_proto.h
> @@ -78,7 +78,7 @@ void sr32(void *, u32, u32, u32);
>  u32 wait_on_value(u32, u32, void *, u32);
>  void sdelay(unsigned long);
>  void make_cs1_contiguous(void);
> -void omap_nand_switch_ecc(int);
> +void omap_nand_switch_ecc(uint32_t, uint32_t);
>  void power_init_r(void);
>  void dieid_num_r(void);
>  void do_omap3_emu_romcode_call(u32 service_id, u32 parameters);
> diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
> index c7d4999..3468c78 100644
> --- a/drivers/mtd/nand/omap_gpmc.c
> +++ b/drivers/mtd/nand/omap_gpmc.c
> @@ -604,13 +604,14 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
>  
>  #ifndef CONFIG_SPL_BUILD
>  /*
> - * omap_nand_switch_ecc - switch the ECC operation b/w h/w ecc and s/w ecc.
> - * The default is to come up on s/w ecc
> - *
> - * @hardware - 1 -switch to h/w ecc, 0 - s/w ecc
> + * omap_nand_switch_ecc - switch the ECC operation between different engines
> + * (h/w and s/w) and different algorithms (hamming and BCHx)
>   *
> + * @hardware		- true if one of the HW engines should be used
> + * @eccstrength		- the number of bits that could be corrected
> + *			  (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
>   */
> -void omap_nand_switch_ecc(int32_t hardware)
> +void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
>  {
>  	struct nand_chip *nand;
>  	struct mtd_info *mtd;
> @@ -628,6 +629,7 @@ void omap_nand_switch_ecc(int32_t hardware)
>  	nand->options |= NAND_OWN_BUFFERS;
>  
>  	/* Reset ecc interface */
> +	nand->ecc.mode = NAND_ECC_NONE;
>  	nand->ecc.read_page = NULL;
>  	nand->ecc.write_page = NULL;
>  	nand->ecc.read_oob = NULL;
> @@ -637,28 +639,31 @@ void omap_nand_switch_ecc(int32_t hardware)
>  	nand->ecc.calculate = NULL;
>  
>  	/* Setup the ecc configurations again */
> -	if (hardware == 1) {
> -		nand->ecc.mode = NAND_ECC_HW;
> -		nand->ecc.layout = &hw_nand_oob;
> -		nand->ecc.size = 512;
> -		nand->ecc.bytes = 3;
> -		nand->ecc.hwctl = omap_enable_hwecc;
> -		nand->ecc.correct = omap_correct_data;
> -		nand->ecc.calculate = omap_calculate_ecc;
> -		omap_hwecc_init(nand);
> -		printf("HW ECC selected\n");
> +	if (hardware) {
> +		if (eccstrength == 1) {
> +			nand->ecc.mode = NAND_ECC_HW;
> +			nand->ecc.layout = &hw_nand_oob;
> +			nand->ecc.size = 512;
> +			nand->ecc.bytes = 3;
> +			nand->ecc.hwctl = omap_enable_hwecc;
> +			nand->ecc.correct = omap_correct_data;
> +			nand->ecc.calculate = omap_calculate_ecc;
> +			omap_hwecc_init(nand);
> +			printf("1-bit hamming HW ECC selected\n");
> +		}
>  #ifdef CONFIG_AM33XX
> -	} else if (hardware == 2) {
> -		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;
> -		omap_hwecc_init_bch(nand, NAND_ECC_READ);
> -		printf("HW BCH8 selected\n");
> +		else if (eccstrength == 8) {
> +			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;
> +			omap_hwecc_init_bch(nand, NAND_ECC_READ);
> +			printf("8-bit BCH HW ECC selected\n");
> +		}
>  #endif
>  	} else {
>  		nand->ecc.mode = NAND_ECC_SOFT;

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

* [U-Boot] [PATCH v4 4/6] omap_gpmc: change nandecc command
  2013-04-05 11:48         ` Thomas Weber
@ 2013-04-05 13:39           ` Andreas Bießmann
  0 siblings, 0 replies; 32+ messages in thread
From: Andreas Bießmann @ 2013-04-05 13:39 UTC (permalink / raw)
  To: u-boot

Dear Thomas Weber,

On 04/05/2013 01:48 PM, Thomas Weber wrote:
> Hello Andreas,
> 
> this patch fixes the reported BUG().
> 
> The output is now:
> 
> -----8<---------
> OMAP3 DevKit8000 # nandecc hw hamming
> 1-bit hamming HW ECC selected
> OMAP3 DevKit8000 # nandecc hw bch8
> Unsupported HW ECC algorithm
> NAND_ECC_NONE selected by board driver. This is not recommended !!
> OMAP3 DevKit8000 #
> ----->8---------

as expected. It is up to the user to choose the correct setup. Now he
has the opportunity to switch back to hamming for example.

Best regards

Andreas Bie?mann

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

* [U-Boot] [PATCH v3 5/6] omap_gpmc: add support for hw assisted BCH8
  2013-04-05 11:44         ` Thomas Weber
@ 2013-04-05 13:42           ` Andreas Bießmann
  2013-04-05 14:55           ` [U-Boot] [PATCH v4 " Andreas Bießmann
  1 sibling, 0 replies; 32+ messages in thread
From: Andreas Bießmann @ 2013-04-05 13:42 UTC (permalink / raw)
  To: u-boot

Dear Thomas Weber,

On 04/05/2013 01:44 PM, Thomas Weber wrote:
> Hello Andreas,
> 
> On 04/03/2013 04:50 PM, Andreas Bie?mann wrote:

<snip>

>> diff --git a/doc/README.omap3 b/doc/README.omap3
>> index 0a37de0..56aca8e 100644
>> --- a/doc/README.omap3
>> +++ b/doc/README.omap3
>> @@ -145,6 +145,25 @@ int omap3_dma_wait_for_transfer(uint32_t chan)
>>  int omap3_dma_get_revision(uint32_t *minor, uint32_t *major)
>>  	Read silicon Revision of the DMA module
>>  
>> +NAND
>> +====
>> +
>> +Ther eare some OMAP3 devices out ther with NAND attached. Due to the fact that
>     ther -> there

thank you for the hint, will fix. Are you trying this on devkit8000? Can
you share your experience with us and maybe send a Tested-by?

Best regards

Andreas Bie?mann

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

* [U-Boot] [PATCH v4 5/6] omap_gpmc: add support for hw assisted BCH8
  2013-04-05 11:44         ` Thomas Weber
  2013-04-05 13:42           ` Andreas Bießmann
@ 2013-04-05 14:55           ` Andreas Bießmann
  1 sibling, 0 replies; 32+ messages in thread
From: Andreas Bießmann @ 2013-04-05 14:55 UTC (permalink / raw)
  To: u-boot

The kernel states:

---8<---
The OMAP3 GPMC hardware BCH engine computes remainder polynomials, it does not
provide automatic error location and correction: this step is implemented using
the BCH library.
--->8---

And we do so in u-boot.

This implementation uses the same layout for BCH8 but it is fix. The current
provided layout does only work with 64 Byte OOB.

Signed-off-by: Andreas Bie?mann <andreas.devel@googlemail.com>
Cc: Tom Rini <trini@ti.com>
Cc: Ilya Yanok <ilya.yanok@cogentembedded.com>
Cc: Scott Wood <scottwood@freescale.com>
Cc: Mansoor Ahamed <mansoor.ahamed@ti.com>
Cc: Thomas Weber <thomas.weber.linux@googlemail.com>
---
since v1:
 * cleanups (remove debug stuff)
 * make checkpach clean (still 2 warnings which I will not fix)
 * merge some code with the AM33XX implementation

since v2:
 * fix all checkpatch warnings
 * add more comments
 * add NAND section in README.omap3

since v3:
 * fix typos in README (thanks to Thoams Weber)
 * append required parameters for BCH8 in SPL

 doc/README.omap3             |   28 ++++
 drivers/mtd/nand/omap_gpmc.c |  367 +++++++++++++++++++++++++++++++-----------
 lib/Makefile                 |    2 +-
 3 files changed, 305 insertions(+), 92 deletions(-)

diff --git a/doc/README.omap3 b/doc/README.omap3
index 0a37de0..1fbe79d 100644
--- a/doc/README.omap3
+++ b/doc/README.omap3
@@ -145,6 +145,34 @@ int omap3_dma_wait_for_transfer(uint32_t chan)
 int omap3_dma_get_revision(uint32_t *minor, uint32_t *major)
 	Read silicon Revision of the DMA module
 
+NAND
+====
+
+There are some OMAP3 devices out there with NAND attached. Due to the fact that
+OMAP3 ROM code can only handle 1-bit hamming ECC for accessing first page
+(place where SPL lives) we require this setup for u-boot at least when reading
+the second progam within SPL.  A lot of newer NAND chips however require more
+than 1-bit ECC for the pages, some can live with 1-bit for the first page. To
+handle this we can switch to another ECC algorithm after reading the payload
+within SPL.
+
+BCH8
+----
+
+To enable hardware assisted BCH8 (8-bit BCH [Bose, Chaudhuri, Hocquenghem]) on
+OMAP3 devices we can use the BCH library in lib/bch.c. To do so add CONFIG_BCH
+to enable the library and CONFIG_NAND_OMAP_BCH8 to to enable hardware assisted
+syndrom generation to your board config.
+The NAND OOB layout is the same as in linux kernel, if the linux kernel BCH8
+implementation for OMAP3 works for you so the u-boot version should also.
+When you require the SPL to read with BCH8 there are two more configs to
+change:
+
+ * CONFIG_SYS_NAND_ECCPOS (must be the same as .eccpos in
+   GPMC_NAND_HW_BCH8_ECC_LAYOUT defined in
+   arch/arm/include/asm/arch-omap3/omap_gpmc.h)
+ * CONFIG_SYS_NAND_ECCSIZE must be 512
+ * CONFIG_SYS_NAND_ECCBYTES must be 13 for this BCH8 setup
 
 Acknowledgements
 ================
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index 3468c78..bc1bcad 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -28,6 +28,7 @@
 #include <asm/arch/cpu.h>
 #include <asm/omap_gpmc.h>
 #include <linux/mtd/nand_ecc.h>
+#include <linux/bch.h>
 #include <linux/compiler.h>
 #include <nand.h>
 #ifdef CONFIG_AM33XX
@@ -37,6 +38,8 @@
 static uint8_t cs;
 static __maybe_unused struct nand_ecclayout hw_nand_oob =
 	GPMC_NAND_HW_ECC_LAYOUT;
+static __maybe_unused struct nand_ecclayout hw_bch8_nand_oob =
+	GPMC_NAND_HW_BCH8_ECC_LAYOUT;
 
 /*
  * omap_nand_hwcontrol - Set the address pointers corretly for the
@@ -239,13 +242,13 @@ static void __maybe_unused omap_enable_hwecc(struct mtd_info *mtd, int32_t mode)
 }
 
 /*
- * BCH8 support (needs ELM and thus AM33xx-only)
+ * Generic BCH interface
  */
-#ifdef CONFIG_AM33XX
 struct nand_bch_priv {
 	uint8_t mode;
 	uint8_t type;
 	uint8_t nibbles;
+	struct bch_control *control;
 };
 
 /* bch types */
@@ -253,21 +256,146 @@ 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
 
-static struct nand_ecclayout hw_bch8_nand_oob = GPMC_NAND_HW_BCH8_ECC_LAYOUT;
-
-static struct nand_bch_priv bch_priv = {
+/*
+ * This can be a single instance cause all current users have only one NAND
+ * with nearly the same setup (BCH8, some with ELM and others with sw BCH
+ * library).
+ * 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
+	.nibbles = ECC_BCH8_NIBBLES,
+	.control = NULL
 };
 
 /*
+ * omap_hwecc_init_bch - Initialize the BCH Hardware ECC for NAND flash in
+ *				GPMC controller
+ * @mtd:	MTD device structure
+ * @mode:	Read/Write mode
+ */
+__maybe_unused
+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
+	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);
+
+#ifdef CONFIG_AM33XX
+	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;
+	}
+#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);
+#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);
+}
+
+/*
+ * 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);
+}
+
+/*
+ * BCH8 support (needs ELM and thus AM33xx-only)
+ */
+#ifdef CONFIG_AM33XX
+/*
  * omap_read_bch8_result - Read BCH result for BCH8 level
  *
  * @mtd:	MTD device structure
@@ -306,18 +434,6 @@ static void omap_read_bch8_result(struct mtd_info *mtd, uint8_t big_endian,
 }
 
 /*
- * omap_ecc_disable - Disable H/W ECC calculation
- *
- * @mtd:	MTD device structure
- *
- */
-static void omap_ecc_disable(struct mtd_info *mtd)
-{
-	writel((readl(&gpmc_cfg->ecc_config) & ~0x1),
-		&gpmc_cfg->ecc_config);
-}
-
-/*
  * omap_rotate_ecc_bch - Rotate the syndrome bytes
  *
  * @mtd:	MTD device structure
@@ -468,76 +584,6 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
 
 	return 0;
 }
-/*
- * omap_hwecc_init_bch - Initialize the BCH Hardware ECC for NAND flash in
- *				GPMC controller
- * @mtd:       MTD device structure
- * @mode:	Read/Write mode
- */
-static void omap_hwecc_init_bch(struct nand_chip *chip, int32_t mode)
-{
-	uint32_t val, dev_width = (chip->options & NAND_BUSWIDTH_16) >> 1;
-	uint32_t unused_length = 0;
-	struct nand_bch_priv *bch = chip->priv;
-
-	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;
-	}
-
-	/* Clear the ecc result registers, select ecc reg as 1 */
-	writel(ECCCLEAR | ECCRESULTREG1, &gpmc_cfg->ecc_control);
-
-	switch (mode) {
-	case NAND_ECC_WRITE:
-		/* 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;
-	}
-	/* ecc size configuration */
-	writel(val, &gpmc_cfg->ecc_size_config);
-	/* by default 512bytes sector page is selected */
-	/* set bch mode */
-	val  = (1 << 16);
-	/* bch4 / bch8 / bch16 */
-	val |= (bch->type << 12);
-	/* set wrap mode to 1 */
-	val |= (1 << 8);
-	val |= (dev_width << 7);
-	val |= (cs << 1);
-	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
- *
- */
-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);
-}
 
 /**
  * omap_read_page_bch - hardware ecc based page read function
@@ -602,6 +648,127 @@ static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
 }
 #endif /* CONFIG_AM33XX */
 
+/*
+ * OMAP3 BCH8 support (with BCH library)
+ */
+#ifdef CONFIG_NAND_OMAP_BCH8
+/*
+ *  omap_calculate_ecc_bch - 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(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 - Decode received data and correct errors
+ * @mtd: MTD device structure
+ * @data: page data
+ * @read_ecc: ecc read from nand flash
+ * @calc_ecc: ecc read from HW ECC registers
+ */
+static int omap_correct_data_bch(struct mtd_info *mtd, u_char *data,
+				 u_char *read_ecc, u_char *calc_ecc)
+{
+	int i, count;
+	/* cannot correct more than 8 errors */
+	unsigned int errloc[8];
+	struct nand_chip *chip = mtd->priv;
+	struct nand_bch_priv *chip_priv = chip->priv;
+	struct bch_control *bch = chip_priv->control;
+
+	count = decode_bch(bch, NULL, 512, read_ecc, calc_ecc, NULL, errloc);
+	if (count > 0) {
+		/* correct errors */
+		for (i = 0; i < count; i++) {
+			/* correct data only, not ecc bytes */
+			if (errloc[i] < 8*512)
+				data[errloc[i]/8] ^= 1 << (errloc[i] & 7);
+			printf("corrected bitflip %u\n", errloc[i]);
+#ifdef DEBUG
+			puts("read_ecc: ");
+			/*
+			 * BCH8 have 13 bytes of ECC; BCH4 needs adoption
+			 * here!
+			 */
+			for (i = 0; i < 13; i++)
+				printf("%02x ", read_ecc[i]);
+			puts("\n");
+			puts("calc_ecc: ");
+			for (i = 0; i < 13; i++)
+				printf("%02x ", calc_ecc[i]);
+			puts("\n");
+#endif
+		}
+	} else if (count < 0) {
+		puts("ecc unrecoverable error\n");
+	}
+	return count;
+}
+
+/**
+ * omap_free_bch - Release BCH ecc resources
+ * @mtd: MTD device structure
+ */
+static void __maybe_unused omap_free_bch(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct nand_bch_priv *chip_priv = chip->priv;
+	struct bch_control *bch = NULL;
+
+	if (chip_priv)
+		bch = chip_priv->control;
+
+	if (bch) {
+		free_bch(bch);
+		chip_priv->control = NULL;
+	}
+}
+#endif /* CONFIG_NAND_OMAP_BCH8 */
+
 #ifndef CONFIG_SPL_BUILD
 /*
  * omap_nand_switch_ecc - switch the ECC operation between different engines
@@ -651,13 +818,17 @@ void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
 			omap_hwecc_init(nand);
 			printf("1-bit hamming HW ECC selected\n");
 		}
-#ifdef CONFIG_AM33XX
+#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
+			nand->ecc.bytes = 13;
+#endif
 			nand->ecc.hwctl = omap_enable_ecc_bch;
 			nand->ecc.correct = omap_correct_data_bch;
 			nand->ecc.calculate = omap_calculate_ecc_bch;
@@ -737,16 +908,28 @@ 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 */
 	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 */);
+	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 */
-#ifdef CONFIG_AM33XX
+#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;
@@ -754,7 +937,9 @@ int board_nand_init(struct nand_chip *nand)
 	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)
diff --git a/lib/Makefile b/lib/Makefile
index 1bfd3ee..5d71b80 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -27,7 +27,6 @@ LIB	= $(obj)libgeneric.o
 
 ifndef CONFIG_SPL_BUILD
 COBJS-$(CONFIG_ADDR_MAP) += addr_map.o
-COBJS-$(CONFIG_BCH) += bch.o
 COBJS-$(CONFIG_AES) += aes.o
 COBJS-$(CONFIG_BZIP2) += bzlib.o
 COBJS-$(CONFIG_BZIP2) += bzlib_crctable.o
@@ -67,6 +66,7 @@ COBJS-$(CONFIG_SPL_NET_SUPPORT) += errno.o
 COBJS-$(CONFIG_SPL_NET_SUPPORT) += hashtable.o
 COBJS-$(CONFIG_SPL_NET_SUPPORT) += net_utils.o
 endif
+COBJS-$(CONFIG_BCH) += bch.o
 COBJS-y += crc32.o
 COBJS-y += ctype.o
 COBJS-y += div64.o
-- 
1.7.10.4

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

* [U-Boot] [PATCH v2 1/6] omap3/cpu.h: add BCH support
  2013-04-02 16:05 ` [U-Boot] [PATCH v2 1/6] omap3/cpu.h: add BCH support Andreas Bießmann
                     ` (5 preceding siblings ...)
  2013-04-02 21:19   ` [U-Boot] [PATCH v2 1/6] omap3/cpu.h: add BCH support Tom Rini
@ 2013-04-08 16:58   ` Tom Rini
  6 siblings, 0 replies; 32+ messages in thread
From: Tom Rini @ 2013-04-08 16:58 UTC (permalink / raw)
  To: u-boot

On Tue, Apr 02, 2013 at 06:05:53PM +0200, Andreas Bie??mann wrote:

> This patch adds the BCH result registers to register mapping for OMAP3 gpmc.
> 
> Signed-off-by: Andreas Bie??mann <andreas.devel@googlemail.com>
> Cc: Tom Rini <trini@ti.com>
> Cc: Ilya Yanok <ilya.yanok@cogentembedded.com>
> Cc: Scott Wood <scottwood@freescale.com>

This, along with the rest of the series (v4 of 4/6 and 5/6), applied to
u-boot-ti/master, thanks!

-- 
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/20130408/1aa99794/attachment.pgp>

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

end of thread, other threads:[~2013-04-08 16:58 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-23 15:14 [U-Boot] [RFC/PATCH 0/4] BCH8 support for OMAP3 Andreas Bießmann
2012-11-23 15:14 ` [U-Boot] [RFC/PATCH 1/4] omap3/cpu.h: add BCH support Andreas Bießmann
2012-11-23 15:14 ` [U-Boot] [RFC/PATCH 2/4] omap3/omap_gpmc.h: add ooblayout for BCH8 as in kernel Andreas Bießmann
2012-11-23 15:14 ` [U-Boot] [RFC/PATCH 3/4] omap_gpmc: add support for hw assisted BCH8 Andreas Bießmann
2012-11-26 21:09   ` Scott Wood
2012-11-23 15:14 ` [U-Boot] [RFC/PATCH 4/4] tricorder: enable hw assisted BCH8 in SPL and u-boot Andreas Bießmann
2013-03-28 10:49 ` [U-Boot] [RFC/PATCH 0/4] BCH8 support for OMAP3 Andreas Bießmann
2013-03-28 14:21   ` Tom Rini
2013-04-02  8:49     ` Andreas Bießmann
2013-04-02 16:13       ` Tom Rini
2013-04-02 16:05 ` [U-Boot] [PATCH v2 1/6] omap3/cpu.h: add BCH support Andreas Bießmann
2013-04-02 16:05   ` [U-Boot] [PATCH v2 2/6] asm/omap_gpmc.h: consolidate common defines Andreas Bießmann
2013-04-02 21:19     ` Tom Rini
2013-04-02 16:05   ` [U-Boot] [PATCH v2 3/6] omap3/omap_gpmc.h: add ooblayout for BCH8 as in kernel Andreas Bießmann
2013-04-02 21:19     ` Tom Rini
2013-04-02 16:05   ` [U-Boot] [PATCH v2 4/6] omap_gpmc: change nandecc command Andreas Bießmann
2013-04-02 21:19     ` Tom Rini
2013-04-03 14:50     ` [U-Boot] [PATCH v3 " Andreas Bießmann
2013-04-03 14:50       ` [U-Boot] [PATCH v3 5/6] omap_gpmc: add support for hw assisted BCH8 Andreas Bießmann
2013-04-05  8:13         ` Thomas Weber
2013-04-05  9:15           ` Andreas Bießmann
2013-04-05 11:44         ` Thomas Weber
2013-04-05 13:42           ` Andreas Bießmann
2013-04-05 14:55           ` [U-Boot] [PATCH v4 " Andreas Bießmann
2013-04-05  9:52       ` [U-Boot] [PATCH v4 4/6] omap_gpmc: change nandecc command Andreas Bießmann
2013-04-05 11:48         ` Thomas Weber
2013-04-05 13:39           ` Andreas Bießmann
2013-04-02 16:05   ` [U-Boot] [PATCH v2 5/6] omap_gpmc: add support for hw assisted BCH8 Andreas Bießmann
2013-04-02 21:19     ` Tom Rini
2013-04-02 16:05   ` [U-Boot] [PATCH v2 6/6] tricorder: enable hw assisted BCH8 in SPL and u-boot Andreas Bießmann
2013-04-02 21:19   ` [U-Boot] [PATCH v2 1/6] omap3/cpu.h: add BCH support Tom Rini
2013-04-08 16:58   ` Tom Rini

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