BCH8_ECC scheme implemented in omap_gpmc.c driver has following 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 limits the BCH8_CODE_HW only for AM33xx device 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
- removes CONFIG_AM33xx
        Thus this driver can be reused by all devices having ELM h/w engine.
- removes CONFIG_NAND_OMAP_BCH8 and adds new CONFIG_NAND_OMAP_ECCSCHEME
        CONFIG_NAND_OMAP_ECCSCHEME determines ecc-scheme to be used
        refer doc/README.nand and board/ti/am335x/README
- adds omap_select_ecc_scheme()
        A common function to handle ecc-scheme related configurations. This
        can be used both during device-probe and via user-space u-boot commads
        to change ecc-scheme. During device probe ecc-scheme is selected based
        on CONFIG_NAND_OMAP_ECCSCHEME.
- enables CONFIG_BCH
        S/W library (lib/bch.c) required by OMAP_ECC_BCH8_CODE_HW_DETECTION_SW
        is enabled by CONFIG_BCH.
- enables CONFIG_SYS_NAND_ONFI_DETECTION
        for auto-detection of ONFI compliant NAND devices
- updates following README doc
        doc/README.nand
        board/ti/am335x/README
        doc/README.omap3

Signed-off-by: Pekon Gupta <pe...@ti.com>
---
 arch/arm/include/asm/arch-am33xx/omap_gpmc.h |  52 ++---
 doc/README.nand                              |  38 ++++
 doc/README.omap3                             |   4 +-
 drivers/mtd/nand/omap_gpmc.c                 | 305 ++++++++++++++++-----------
 include/configs/am335x_evm.h                 |  11 +-
 include/configs/tricorder.h                  |   3 +-
 6 files changed, 242 insertions(+), 171 deletions(-)

diff --git a/arch/arm/include/asm/arch-am33xx/omap_gpmc.h 
b/arch/arm/include/asm/arch-am33xx/omap_gpmc.h
index 00ad1d0..62f608e 100644
--- a/arch/arm/include/asm/arch-am33xx/omap_gpmc.h
+++ b/arch/arm/include/asm/arch-am33xx/omap_gpmc.h
@@ -7,42 +7,20 @@
 #ifndef __ASM_ARCH_OMAP_GPMC_H
 #define __ASM_ARCH_OMAP_GPMC_H
 
-/* 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,\
-                               16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,\
-                               28, 29, 30, 31, 32, 33},\
-       .oobfree = {\
-               {.offset = 34,\
-                .length = 30 } } \
-}
+enum omap_ecc {
+       /* 1-bit  ECC calculation by Software, Error detection by Software */
+       OMAP_ECC_HAM1_CODE_SW = 1, /* avoid un-initialized int can be 0x0 */
+       /* 1-bit  ECC calculation by GPMC, Error detection by Software */
+       /* ECC layout compatible to legacy ROMCODE. */
+       OMAP_ECC_HAM1_CODE_HW,
+       /* 4-bit  ECC calculation by GPMC, Error detection by Software */
+       OMAP_ECC_BCH4_CODE_HW_DETECTION_SW,
+       /* 4-bit  ECC calculation by GPMC, Error detection by ELM */
+       OMAP_ECC_BCH4_CODE_HW,
+       /* 8-bit  ECC calculation by GPMC, Error detection by Software */
+       OMAP_ECC_BCH8_CODE_HW_DETECTION_SW,
+       /* 8-bit  ECC calculation by GPMC, Error detection by ELM */
+       OMAP_ECC_BCH8_CODE_HW,
+};
 
-#define GPMC_NAND_HW_BCH8_ECC_LAYOUT {\
-       .eccbytes = 56,\
-       .eccpos = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 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},\
-       .oobfree = {\
-               {.offset = 58,\
-                .length = 6 } } \
-}
-
-#define GPMC_NAND_HW_BCH16_ECC_LAYOUT {\
-       .eccbytes = 104,\
-       .eccpos = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 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,\
-                               64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,\
-                               76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,\
-                               88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\
-                               100, 101, 102, 103, 104, 105},\
-       .oobfree = {\
-               {.offset = 106,\
-                .length = 8 } } \
-}
 #endif /* __ASM_ARCH_OMAP_GPMC_H */
diff --git a/doc/README.nand b/doc/README.nand
index 913e9b5..5a04d42 100644
--- a/doc/README.nand
+++ b/doc/README.nand
@@ -169,6 +169,44 @@ 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_SYS_NAND_ONFI_DETECTION
+       Enables detection of ONFI compliant devices during probe.
+       And fetching device parameters flashed on device, by parsing
+       ONFI parameter page.
+
+   CONFIG_BCH
+       Enables software based BCH ECC algorithm present in lib/bch.c
+       This is used by SoC platforms which do not have built-in ELM
+       hardware engine required for BCH ECC correction.
+
+Platform specific options
+=========================
+
+   CONFIG_NAND_OMAP_ECCSCHEME
+       On OMAP platforms, this CONFIG specifies NAND ECC scheme.
+       It can take following values:
+
+       OMAP_ECC_HAM1_CODE_SW
+               1-bit Hamming code using software lib.
+               (for legacy devices only)
+       OMAP_ECC_HAM1_CODE_HW
+               1-bit Hamming code using GPMC hardware.
+               (for legacy devices only)
+       OMAP_ECC_BCH4_CODE_HW_DETECTION_SW
+               4-bit BCH code (unsupported)
+       OMAP_ECC_BCH4_CODE_HW
+               4-bit BCH code (unsupported)
+       OMAP_ECC_BCH8_CODE_HW_DETECTION_SW
+               8-bit BCH code with
+               - ecc calculation using GPMC hardware engine,
+               - error detection using software library.
+               - requires CONFIG_BCH to enable software BCH library
+               (For legacy device which do not have ELM h/w engine)
+       OMAP_ECC_BCH8_CODE_HW
+               8-bit BCH code with
+               - ecc calculation using GPMC hardware engine,
+               - error detection using ELM hardware engine.
+
 NOTE:
 =====
 
diff --git a/doc/README.omap3 b/doc/README.omap3
index 1fbe79d..fd85b22 100644
--- a/doc/README.omap3
+++ b/doc/README.omap3
@@ -161,8 +161,8 @@ 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.
+to enable the library and set CONFIG_NAND_OMAP_ECCSCHEME=5 (as per README.nand)
+to enable BCH8_SW ecc scheme.
 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
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index ec1787f..48bdcbb 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -15,15 +15,13 @@
 #include <linux/bch.h>
 #include <linux/compiler.h>
 #include <nand.h>
-#ifdef CONFIG_AM33XX
 #include <asm/arch/elm.h>
-#endif
+
+#define BADBLOCK_MARKER_LENGTH 2
+#define SECTOR_BYTES           512
 
 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;
+static __maybe_unused struct nand_ecclayout omap_ecclayout;
 
 /*
  * omap_nand_hwcontrol - Set the address pointers corretly for the
@@ -233,6 +231,7 @@ struct nand_bch_priv {
        uint8_t type;
        uint8_t nibbles;
        struct bch_control *control;
+       enum omap_ecc ecc_scheme;
 };
 
 /* bch types */
@@ -274,17 +273,15 @@ 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;
+       if (bch->ecc_scheme == OMAP_ECC_BCH8_CODE_HW) {
+               wr_mode = BCH_WRAPMODE_1;
 
        switch (bch->nibbles) {
        case ECC_BCH4_NIBBLES:
@@ -320,7 +317,7 @@ static void omap_hwecc_init_bch(struct nand_chip *chip, 
int32_t mode)
                val |= (unused_length << 22);
                break;
        }
-#else
+       } else {
        /*
         * This ecc_size_config setting is for BCH sw library.
         *
@@ -333,7 +330,7 @@ static void omap_hwecc_init_bch(struct nand_chip *chip, 
int32_t mode)
         *  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);
 
@@ -376,9 +373,8 @@ static void __maybe_unused omap_ecc_disable(struct mtd_info 
*mtd)
 }
 
 /*
- * BCH8 support (needs ELM and thus AM33xx-only)
+ * BCH support using ELM module
  */
-#ifdef CONFIG_AM33XX
 /*
  * omap_read_bch8_result - Read BCH result for BCH8 level
  *
@@ -631,20 +627,19 @@ static int omap_read_page_bch(struct mtd_info *mtd, 
struct nand_chip *chip,
        }
        return 0;
 }
-#endif /* CONFIG_AM33XX */
 
 /*
  * OMAP3 BCH8 support (with BCH library)
  */
-#ifdef CONFIG_NAND_OMAP_BCH8
+#ifdef CONFIG_BCH
 /*
- *  omap_calculate_ecc_bch - Read BCH ECC result
+ *  omap_calculate_ecc_bch_sw - Read BCH ECC result
  *
  *  @mtd:      MTD device structure
  *  @dat:      The pointer to data on which ecc is computed (unused here)
  *  @ecc:      The ECC output buffer
  */
-static int omap_calculate_ecc_bch(struct mtd_info *mtd, const uint8_t *dat,
+static int omap_calculate_ecc_bch_sw(struct mtd_info *mtd, const uint8_t *dat,
                                uint8_t *ecc)
 {
        int ret = 0;
@@ -689,13 +684,13 @@ static int omap_calculate_ecc_bch(struct mtd_info *mtd, 
const uint8_t *dat,
 }
 
 /**
- * omap_correct_data_bch - Decode received data and correct errors
+ * omap_correct_data_bch_sw - 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,
+static int omap_correct_data_bch_sw(struct mtd_info *mtd, u_char *data,
                                 u_char *read_ecc, u_char *calc_ecc)
 {
        int i, count;
@@ -752,7 +747,138 @@ static void __maybe_unused omap_free_bch(struct mtd_info 
*mtd)
                chip_priv->control = NULL;
        }
 }
-#endif /* CONFIG_NAND_OMAP_BCH8 */
+#endif /* CONFIG_BCH */
+
+/**
+ * omap_select_ecc_scheme - configures driver for particular ecc-scheme
+ * @nand: NAND chip device structure
+ * @ecc_scheme: ecc scheme to configure
+ * @pagesize: number of main-area bytes per page of NAND device
+ * @oobsize: number of OOB/spare bytes per page of NAND device
+ */
+static int omap_select_ecc_scheme(struct nand_chip *nand,
+       enum omap_ecc ecc_scheme, unsigned int pagesize, unsigned int oobsize) {
+       struct nand_bch_priv    *bch            = nand->priv;
+       struct nand_ecclayout   *ecclayout      = nand->ecc.layout;
+       int eccsteps = pagesize / SECTOR_BYTES;
+       int i;
+
+       switch (ecc_scheme) {
+       case OMAP_ECC_HAM1_CODE_SW:
+               debug("nand: selected OMAP_ECC_HAM1_CODE_SW\n");
+               /* check ecc-scheme requirements before updating ecc info */
+               if ((3 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
+                       printf("nand: error: insufficient OOB: require=%d\n", (
+                               (3 * eccsteps) + BADBLOCK_MARKER_LENGTH));
+                       return -EINVAL;
+               }
+               bch_priv.control        = NULL;
+               bch_priv.type           = 0;
+               /* populate ecc specific fields */
+               nand->ecc.mode          = NAND_ECC_SOFT;
+               nand->ecc.layout        = NULL;
+               nand->ecc.size          = pagesize;
+               nand->ecc.strength      = 1;
+               bch->ecc_scheme         = OMAP_ECC_HAM1_CODE_SW;
+               break;
+       case OMAP_ECC_HAM1_CODE_HW:
+               debug("nand: selected OMAP_ECC_HAM1_CODE_HW\n");
+               /* check ecc-scheme requirements before updating ecc info */
+               if ((3 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
+                       printf("nand: error: insufficient OOB: require=%d\n", (
+                               (3 * eccsteps) + BADBLOCK_MARKER_LENGTH));
+                       return -EINVAL;
+               }
+               bch_priv.control        = NULL;
+               bch_priv.type           = 0;
+               /* populate ecc specific fields */
+               nand->ecc.mode          = NAND_ECC_HW;
+               nand->ecc.strength      = 1;
+               nand->ecc.size          = SECTOR_BYTES;
+               nand->ecc.bytes         = 3;
+               nand->ecc.hwctl         = omap_enable_hwecc;
+               nand->ecc.correct       = omap_correct_data;
+               nand->ecc.calculate     = omap_calculate_ecc;
+               /* define ecc-layout */
+               ecclayout->eccbytes     = nand->ecc.bytes * eccsteps;
+               for (i = 0; i < ecclayout->eccbytes; i++)
+                       ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
+               ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
+               ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
+                                               BADBLOCK_MARKER_LENGTH;
+               bch->ecc_scheme         = OMAP_ECC_HAM1_CODE_HW;
+               break;
+#ifdef CONFIG_BCH
+       case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW:
+               debug("nand: selected OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n");
+               /* check ecc-scheme requirements before updating ecc info */
+               if ((13 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
+                       printf("nand: error: insufficient OOB: require=%d\n", (
+                               (13 * eccsteps) + BADBLOCK_MARKER_LENGTH));
+                       return -EINVAL;
+               }
+               /* check if BCH S/W library can be used for error detection */
+               bch_priv.control = init_bch(13, 8, 0x201b);
+               if (!bch_priv.control) {
+                       printf("nand: error: could not init_bch()\n");
+                       return -ENODEV;
+               }
+               bch_priv.type = ECC_BCH8;
+               /* populate ecc specific fields */
+               nand->ecc.mode          = NAND_ECC_HW;
+               nand->ecc.strength      = 8;
+               nand->ecc.size          = SECTOR_BYTES;
+               nand->ecc.bytes         = 13;
+               nand->ecc.hwctl         = omap_enable_ecc_bch;
+               nand->ecc.correct       = omap_correct_data_bch_sw;
+               nand->ecc.calculate     = omap_calculate_ecc_bch_sw;
+               /* define ecc-layout */
+               ecclayout->eccbytes     = nand->ecc.bytes * eccsteps;
+               for (i = 0; i < ecclayout->eccbytes; i++)
+                       ecclayout->eccpos[i] = i + (oobsize -
+                                               ecclayout->eccbytes);
+               ecclayout->oobfree[0].offset = BADBLOCK_MARKER_LENGTH;
+               ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
+                                               BADBLOCK_MARKER_LENGTH;
+               omap_hwecc_init_bch(nand, NAND_ECC_READ);
+               bch->ecc_scheme         = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
+               break;
+#endif
+       case OMAP_ECC_BCH8_CODE_HW:
+               debug("nand: selected OMAP_ECC_BCH8_CODE_HW\n");
+               /* check ecc-scheme requirements before updating ecc info */
+               if ((14 * eccsteps) + BADBLOCK_MARKER_LENGTH > oobsize) {
+                       printf("nand: error: insufficient OOB: require=%d\n", (
+                               (14 * eccsteps) + BADBLOCK_MARKER_LENGTH));
+                       return -EINVAL;
+               }
+               /* intialize ELM for ECC error detection */
+               elm_init();
+               bch_priv.type           = ECC_BCH8;
+               /* populate ecc specific fields */
+               nand->ecc.mode          = NAND_ECC_HW;
+               nand->ecc.strength      = 8;
+               nand->ecc.size          = SECTOR_BYTES;
+               nand->ecc.bytes         = 14;
+               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;
+               /* define ecc-layout */
+               ecclayout->eccbytes     = nand->ecc.bytes * eccsteps;
+               for (i = 0; i < ecclayout->eccbytes; i++)
+                       ecclayout->eccpos[i] = i + BADBLOCK_MARKER_LENGTH;
+               ecclayout->oobfree[0].offset = i + BADBLOCK_MARKER_LENGTH;
+               ecclayout->oobfree[0].length = oobsize - ecclayout->eccbytes -
+                                               BADBLOCK_MARKER_LENGTH;
+               bch->ecc_scheme         = OMAP_ECC_BCH8_CODE_HW;
+               break;
+       default:
+               debug("nand: error: ecc scheme not enabled or supported\n");
+               return -EINVAL;
+       }
+       return 0;
+}
 
 #ifndef CONFIG_SPL_BUILD
 /*
@@ -763,77 +889,47 @@ static void __maybe_unused omap_free_bch(struct mtd_info 
*mtd)
  * @eccstrength                - the number of bits that could be corrected
  *                       (1 - hamming, 4 - BCH4, 8 - BCH8, 16 - BCH16)
  */
-void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
+int omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength)
 {
        struct nand_chip *nand;
        struct mtd_info *mtd;
+       struct nand_bch_priv *bch;
+       int err = 0;
 
        if (nand_curr_device < 0 ||
            nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
            !nand_info[nand_curr_device].name) {
-               printf("Error: Can't switch ecc, no devices available\n");
-               return;
+               printf("nand: error: no NAND devices found\n");
+               return -ENODEV;
        }
 
        mtd = &nand_info[nand_curr_device];
        nand = mtd->priv;
-
+       bch = nand->priv;
        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;
-       nand->ecc.write_oob = NULL;
-       nand->ecc.hwctl = NULL;
-       nand->ecc.correct = NULL;
-       nand->ecc.calculate = NULL;
-       nand->ecc.strength = eccstrength;
-
        /* Setup the ecc configurations again */
        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");
-               }
-#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;
-                       omap_hwecc_init_bch(nand, NAND_ECC_READ);
-                       printf("8-bit BCH HW ECC selected\n");
+                       err = omap_select_ecc_scheme(nand,
+                                       OMAP_ECC_HAM1_CODE_HW,
+                                       mtd->writesize, mtd->oobsize);
+               } else if (eccstrength == 8) {
+                       err = omap_select_ecc_scheme(nand,
+                                       OMAP_ECC_BCH8_CODE_HW,
+                                       mtd->writesize, mtd->oobsize);
+               } else {
+                       printf("nand: error: unsupported ECC scheme\n");
+                       return -EINVAL;
                }
-#endif
        } else {
-               nand->ecc.mode = NAND_ECC_SOFT;
-               /* Use mtd default settings */
-               nand->ecc.layout = NULL;
-               nand->ecc.size = 0;
-               printf("SW ECC selected\n");
+               err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW,
+                                       mtd->writesize, mtd->oobsize);
        }
 
        /* Update NAND handling after ECC mode switch */
-       nand_scan_tail(mtd);
-
-       nand->options &= ~NAND_OWN_BUFFERS;
+       if (!err)
+               err = nand_scan_tail(mtd);
+       return err;
 }
 #endif /* CONFIG_SPL_BUILD */
 
@@ -873,7 +969,7 @@ int board_nand_init(struct nand_chip *nand)
                cs++;
        }
        if (cs >= GPMC_MAX_CS) {
-               printf("NAND: Unable to find NAND settings in "
+               printf("nand: error: Unable to find NAND settings in "
                        "GPMC Configuration - quitting\n");
                return -ENODEV;
        }
@@ -885,64 +981,23 @@ int board_nand_init(struct nand_chip *nand)
 
        nand->IO_ADDR_R = (void __iomem *)&gpmc_cfg->cs[cs].nand_dat;
        nand->IO_ADDR_W = (void __iomem *)&gpmc_cfg->cs[cs].nand_cmd;
-
-       nand->cmd_ctrl = omap_nand_hwcontrol;
-       nand->options = NAND_NO_PADDING | NAND_CACHEPRG;
+       nand->priv      = &bch_priv;
+       nand->cmd_ctrl  = omap_nand_hwcontrol;
+       nand->options   |= NAND_NO_PADDING | NAND_CACHEPRG;
        /* If we are 16 bit dev, our gpmc config tells us that */
        if ((readl(&gpmc_cfg->cs[cs].config1) & 0x3000) == 0x1000)
                nand->options |= NAND_BUSWIDTH_16;
 
        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;
+       nand->ecc.layout = &omap_ecclayout;
+
+       /* select ECC scheme */
+       if (omap_select_ecc_scheme(nand, CONFIG_NAND_OMAP_ECCSCHEME,
+                                  CONFIG_SYS_NAND_PAGE_SIZE,
+                                  CONFIG_SYS_NAND_OOBSIZE)) {
+               printf("nand: error: unsupported ecc scheme specified\n");
+               return -EINVAL;
        }
-#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)
-       nand->ecc.mode = NAND_ECC_SOFT;
-#else
-       nand->ecc.mode = NAND_ECC_HW;
-       nand->ecc.layout = &hw_nand_oob;
-       nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
-       nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
-       nand->ecc.hwctl = omap_enable_hwecc;
-       nand->ecc.correct = omap_correct_data;
-       nand->ecc.calculate = omap_calculate_ecc;
-       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 f746e48..7bc7feb 100644
--- a/include/configs/am335x_evm.h
+++ b/include/configs/am335x_evm.h
@@ -222,11 +222,11 @@
 
 #ifdef CONFIG_NAND
 #define CONFIG_SYS_NAND_5_ADDR_CYCLE
-#define CONFIG_SYS_NAND_PAGE_COUNT     (CONFIG_SYS_NAND_BLOCK_SIZE / \
-                                        CONFIG_SYS_NAND_PAGE_SIZE)
+#define CONFIG_SYS_NAND_BLOCK_SIZE     131072
 #define CONFIG_SYS_NAND_PAGE_SIZE      2048
 #define CONFIG_SYS_NAND_OOBSIZE                64
-#define CONFIG_SYS_NAND_BLOCK_SIZE     (128*1024)
+#define CONFIG_SYS_NAND_PAGE_COUNT     (CONFIG_SYS_NAND_BLOCK_SIZE / \
+                                        CONFIG_SYS_NAND_PAGE_SIZE)
 #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, 14, 15, 16, 17, \
@@ -238,9 +238,8 @@
 
 #define CONFIG_SYS_NAND_ECCSIZE                512
 #define CONFIG_SYS_NAND_ECCBYTES       14
-
-#define CONFIG_SYS_NAND_U_BOOT_START   CONFIG_SYS_TEXT_BASE
-#define CONFIG_SYS_NAND_U_BOOT_OFFS    0x80000
+#define CONFIG_SYS_NAND_ONFI_DETECTION
+#define CONFIG_NAND_OMAP_ECCSCHEME     OMAP_ECC_BCH8_CODE_HW
 #endif
 #endif
 
diff --git a/include/configs/tricorder.h b/include/configs/tricorder.h
index a9b2714..e2fd978 100644
--- a/include/configs/tricorder.h
+++ b/include/configs/tricorder.h
@@ -110,7 +110,6 @@
 
 #define CONFIG_SYS_MAX_NAND_DEVICE     1               /* Max number of NAND */
                                                        /* devices */
-#define CONFIG_NAND_OMAP_BCH8
 #define CONFIG_BCH
 
 /* commands to include */
@@ -298,6 +297,8 @@
 
 #define CONFIG_SYS_NAND_ECCSIZE                512
 #define CONFIG_SYS_NAND_ECCBYTES       13
+#define CONFIG_NAND_OMAP_ECCSCHEME     OMAP_ECC_BCH8_CODE_HW_DETECTION_SW
+#define CONFIG_SYS_NAND_ONFI_DETECTION
 
 #define CONFIG_SYS_NAND_U_BOOT_START   CONFIG_SYS_TEXT_BASE
 
-- 
1.8.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to