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