From patchwork Fri Sep 6 13:55:09 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: pekon gupta X-Patchwork-Id: 273207 X-Patchwork-Delegate: scottwood@freescale.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id E6B452C00EF for ; Fri, 6 Sep 2013 23:56:23 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 973244A08E; Fri, 6 Sep 2013 15:56:13 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id uAQpjz5WhVo7; Fri, 6 Sep 2013 15:56:13 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 835CA4A08F; Fri, 6 Sep 2013 15:55:51 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 0EA7B4A064 for ; Fri, 6 Sep 2013 15:55:44 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 7BdzE5stEUrf for ; Fri, 6 Sep 2013 15:55:37 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from bear.ext.ti.com (bear.ext.ti.com [192.94.94.41]) by theia.denx.de (Postfix) with ESMTPS id 13E604A065 for ; Fri, 6 Sep 2013 15:55:24 +0200 (CEST) Received: from dlelxv90.itg.ti.com ([172.17.2.17]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id r86DtJAt017127; Fri, 6 Sep 2013 08:55:19 -0500 Received: from DFLE73.ent.ti.com (dfle73.ent.ti.com [128.247.5.110]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id r86DtJVN022644; Fri, 6 Sep 2013 08:55:19 -0500 Received: from dflp33.itg.ti.com (10.64.6.16) by DFLE73.ent.ti.com (128.247.5.110) with Microsoft SMTP Server id 14.2.342.3; Fri, 6 Sep 2013 08:55:19 -0500 Received: from psplinux064.india.ti.com (ileax41-snat.itg.ti.com [10.172.224.153]) by dflp33.itg.ti.com (8.14.3/8.13.8) with ESMTP id r86DtE43015923; Fri, 6 Sep 2013 08:55:17 -0500 From: Pekon Gupta To: , Date: Fri, 6 Sep 2013 19:25:09 +0530 Message-ID: <1378475713-7546-2-git-send-email-pekon@ti.com> X-Mailer: git-send-email 1.8.1 In-Reply-To: <1378475713-7546-1-git-send-email-pekon@ti.com> References: <1378475713-7546-1-git-send-email-pekon@ti.com> MIME-Version: 1.0 Cc: u-boot@lists.denx.de, balbi@ti.com Subject: [U-Boot] [PATCH v5 1/5] mtd: nand: omap: enable BCH ECC scheme using ELM for generic platform X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de 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. - 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. - adds CONFIG_BCH S/W library (lib/bch.c) required by OMAP_ECC_BCH8_CODE_HW_DETECTION_SW is enabled by CONFIG_BCH. - adds CONFIG_SYS_NAND_ECCSCHEME (new) user specified CONFIG to determine ecc-scheme used during boot - adds CONFIG_SYS_NAND_ONFI_DETECTION enable auto-detection of ONFI compliant devices Signed-off-by: Pekon Gupta --- arch/arm/include/asm/arch-am33xx/omap_gpmc.h | 48 +---- doc/README.nand | 13 ++ drivers/mtd/nand/omap_gpmc.c | 298 ++++++++++++++++----------- include/configs/am335x_evm.h | 2 + include/configs/tricorder.h | 2 + 5 files changed, 204 insertions(+), 159 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..69982c1 100644 --- a/arch/arm/include/asm/arch-am33xx/omap_gpmc.h +++ b/arch/arm/include/asm/arch-am33xx/omap_gpmc.h @@ -7,42 +7,16 @@ #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 = 0, + /* 1-bit ECC calculation by GPMC, Error detection by Software */ + /* ECC layout compatible to legacy ROMCODE. */ + OMAP_ECC_HAM1_CODE_HW_ROMCODE, + /* 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..f72f618 100644 --- a/doc/README.nand +++ b/doc/README.nand @@ -169,6 +169,19 @@ 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 in-build hardware + engine to calculate and correct BCH ECC. + + CONFIG_SYS_NAND_ECCSCHEME + specifies which ECC scheme to use. + NOTE: ===== diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c index ec1787f..ae9afe2 100644 --- a/drivers/mtd/nand/omap_gpmc.c +++ b/drivers/mtd/nand/omap_gpmc.c @@ -15,15 +15,13 @@ #include #include #include -#ifdef CONFIG_AM33XX #include -#endif + +#define BADBLOCK_MARKER_LENGTH 0x2 +#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,127 @@ 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, int ecc_scheme, + unsigned int pagesize, unsigned int oobsize) { + struct nand_bch_priv *bch = nand->priv; + struct nand_ecclayout *ecclayout = nand->ecc.layout; + int i; + + /* 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; + + switch (ecc_scheme) { + case OMAP_ECC_HAM1_CODE_SW: + debug("nand: selected OMAP_ECC_HAM1_CODE_SW\n"); + nand->ecc.mode = NAND_ECC_SOFT; + nand->ecc.layout = NULL; + nand->ecc.size = 0; + nand->ecc.strength = 1; + bch->ecc_scheme = OMAP_ECC_HAM1_CODE_SW; + break; + case OMAP_ECC_HAM1_CODE_HW_ROMCODE: + debug("nand: selected OMAP_ECC_HAM1_CODE_HW_ROMCODE\n"); + nand->ecc.mode = NAND_ECC_HW; + nand->ecc.strength = 1; + 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; + /* define ecc-layout */ + ecclayout->eccbytes = nand->ecc.bytes * + (pagesize / SECTOR_BYTES); + 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 - nand->ecc.bytes - + BADBLOCK_MARKER_LENGTH; + bch->ecc_scheme = OMAP_ECC_HAM1_CODE_HW_ROMCODE; + break; +#ifdef CONFIG_BCH + case OMAP_ECC_BCH8_CODE_HW_DETECTION_SW: + debug("nand: selected OMAP_ECC_BCH8_CODE_HW_DETECTION_SW\n"); + nand->ecc.mode = NAND_ECC_HW; + nand->ecc.strength = 8; + nand->ecc.size = 512; + 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; + /* BCH SW library is 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; + } + /* define ecc-layout */ + ecclayout->eccbytes = nand->ecc.bytes * + (pagesize / SECTOR_BYTES); + 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 - nand->ecc.bytes - + 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"); + nand->ecc.mode = NAND_ECC_HW; + nand->ecc.strength = 8; + nand->ecc.size = 512; + 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; + /* ELM is used for ECC error detection */ + elm_init(); + /* define ecc-layout */ + ecclayout->eccbytes = nand->ecc.bytes * + (pagesize / SECTOR_BYTES); + 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 - nand->ecc.bytes - + 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; + } + + /* check if NAND spare/OOB has enough bytes to accomodate ecclayout */ + if ((ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH) > oobsize) { + printf("nand: error: insufficient OOB bytes. require=%d\n", + (ecclayout->eccbytes + BADBLOCK_MARKER_LENGTH)); + return -EINVAL; + } + return 0; +} #ifndef CONFIG_SPL_BUILD /* @@ -767,67 +882,41 @@ void 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"); + printf("nand: error: no devices available\n"); return; } 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 (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_ROMCODE, + 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"); + err = -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"); + else + err = omap_select_ecc_scheme(nand, OMAP_ECC_HAM1_CODE_SW, + mtd->writesize, mtd->oobsize); + if (err) { + printf("nand: error: could not switch ecc, reverting\n"); + omap_select_ecc_scheme(nand, bch->ecc_scheme, + mtd->writesize, mtd->oobsize); } /* Update NAND handling after ECC mode switch */ @@ -854,6 +943,10 @@ void omap_nand_switch_ecc(uint32_t hardware, uint32_t eccstrength) */ int board_nand_init(struct nand_chip *nand) { + struct mtd_info *mtd; +#ifdef CONFIG_SPL_BUILD + struct mtd_info nand_info[CONFIG_SYS_MAX_NAND_DEVICE]; +#endif int32_t gpmc_config = 0; cs = 0; @@ -873,7 +966,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; } @@ -883,66 +976,27 @@ int board_nand_init(struct nand_chip *nand) gpmc_config |= 0x10; writel(gpmc_config, &gpmc_cfg->config); + mtd = &nand_info[0]; + mtd->priv = 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_SYS_NAND_ECCSCHEME, + CONFIG_SYS_NAND_PAGE_SIZE, + CONFIG_SYS_NAND_OOBSIZE)) { + printf("nand: error: cannot select ecc scheme\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 e0a87f8..c2d25a4 100644 --- a/include/configs/am335x_evm.h +++ b/include/configs/am335x_evm.h @@ -259,6 +259,8 @@ #define CONFIG_SYS_NAND_ECCSIZE 512 #define CONFIG_SYS_NAND_ECCBYTES 14 +#define CONFIG_SYS_NAND_ECCSCHEME 3 +#define CONFIG_SYS_NAND_ONFI_DETECTION #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_NAND_U_BOOT_OFFS 0x80000 diff --git a/include/configs/tricorder.h b/include/configs/tricorder.h index a9b2714..2b01486 100644 --- a/include/configs/tricorder.h +++ b/include/configs/tricorder.h @@ -298,6 +298,8 @@ #define CONFIG_SYS_NAND_ECCSIZE 512 #define CONFIG_SYS_NAND_ECCBYTES 13 +#define CONFIG_SYS_NAND_ECCSCHEME 3 +#define CONFIG_SYS_NAND_ONFI_DETECTION #define CONFIG_SYS_NAND_U_BOOT_START CONFIG_SYS_TEXT_BASE