From patchwork Tue Sep 3 08:33:47 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: pekon gupta X-Patchwork-Id: 272172 X-Patchwork-Delegate: trini@ti.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 A75E02C00AA for ; Tue, 3 Sep 2013 18:34:39 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id E85094A087; Tue, 3 Sep 2013 10:34:30 +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 tbpy275nM1pH; Tue, 3 Sep 2013 10:34:30 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 08D194A090; Tue, 3 Sep 2013 10:34:19 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id CDF384A067 for ; Tue, 3 Sep 2013 10:34: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 1J282+T9uvg9 for ; Tue, 3 Sep 2013 10:34:09 +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 5B7714A060 for ; Tue, 3 Sep 2013 10:33:58 +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 r838Xu4W024121; Tue, 3 Sep 2013 03:33:56 -0500 Received: from DFLE72.ent.ti.com (dfle72.ent.ti.com [128.247.5.109]) by dlelxv90.itg.ti.com (8.14.3/8.13.8) with ESMTP id r838Xui1000825; Tue, 3 Sep 2013 03:33:56 -0500 Received: from dflp33.itg.ti.com (10.64.6.16) by DFLE72.ent.ti.com (128.247.5.109) with Microsoft SMTP Server id 14.2.342.3; Tue, 3 Sep 2013 03:33:55 -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 r838XpmJ005289; Tue, 3 Sep 2013 03:33:54 -0500 From: Pekon Gupta To: , Date: Tue, 3 Sep 2013 14:03:47 +0530 Message-ID: <1378197229-21596-2-git-send-email-pekon@ti.com> X-Mailer: git-send-email 1.8.1 In-Reply-To: <1378197229-21596-1-git-send-email-pekon@ti.com> References: <1378197229-21596-1-git-send-email-pekon@ti.com> MIME-Version: 1.0 Cc: u-boot@lists.denx.de, balbi@ti.com Subject: [U-Boot] [PATCH v1 1/3] am33xx: elm: add support for BCH16_ECC - ELM driver updates 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 With increase in NAND flash densities occurence of bit-flips has increased. Thus stronger ECC schemes are required for detecting and correcting multiple simultaneous bit-flips in same NAND page. But stronger ECC schemes have large ECC syndrome which require more space in OOB/Spare. This patch add support for BCH16_ECC: (a) BCH16_ECC can correct 16 bit-flips per 512Bytes of data. (b) BCH16_ECC generates 26-bytes of ECC syndrome / 512B. Due to (b) this scheme can only be used with NAND devices which have enough OOB to satisfy following equation: OOBsize per page >= 26 * (page-size / 512) Signed-off-by: Pekon Gupta --- arch/arm/cpu/armv7/am33xx/elm.c | 91 +++++++++++++++++++++++----------- arch/arm/include/asm/arch-am33xx/elm.h | 16 +++--- 2 files changed, 68 insertions(+), 39 deletions(-) diff --git a/arch/arm/cpu/armv7/am33xx/elm.c b/arch/arm/cpu/armv7/am33xx/elm.c index 8f1d6af..47ccbbd 100644 --- a/arch/arm/cpu/armv7/am33xx/elm.c +++ b/arch/arm/cpu/armv7/am33xx/elm.c @@ -27,29 +27,27 @@ struct elm *elm_cfg; /** * elm_load_syndromes - Load BCH syndromes based on nibble selection * @syndrome: BCH syndrome - * @nibbles: * @poly: Syndrome Polynomial set to use * * Load BCH syndromes based on nibble selection */ -static void elm_load_syndromes(u8 *syndrome, u32 nibbles, u8 poly) +static int elm_load_syndromes(u8 *syndrome, u32 bch_type, u8 poly) { u32 *ptr; u32 val; - /* reg 0 */ - ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[0]; - val = syndrome[0] | (syndrome[1] << 8) | (syndrome[2] << 16) | - (syndrome[3] << 24); - writel(val, ptr); - /* reg 1 */ - ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[1]; - val = syndrome[4] | (syndrome[5] << 8) | (syndrome[6] << 16) | - (syndrome[7] << 24); - writel(val, ptr); - - /* BCH 8-bit with 26 nibbles (4*8=32) */ - if (nibbles > 13) { + switch (bch_type) { + case ECC_BCH16: + /* reg 0 */ + ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[0]; + val = syndrome[0] | (syndrome[1] << 8) | (syndrome[2] << 16) | + (syndrome[3] << 24); + writel(val, ptr); + /* reg 1 */ + ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[1]; + val = syndrome[4] | (syndrome[5] << 8) | (syndrome[6] << 16) | + (syndrome[7] << 24); + writel(val, ptr); /* reg 2 */ ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[2]; val = syndrome[8] | (syndrome[9] << 8) | (syndrome[10] << 16) | @@ -60,34 +58,65 @@ static void elm_load_syndromes(u8 *syndrome, u32 nibbles, u8 poly) val = syndrome[12] | (syndrome[13] << 8) | (syndrome[14] << 16) | (syndrome[15] << 24); writel(val, ptr); - } - - /* BCH 16-bit with 52 nibbles (7*8=56) */ - if (nibbles > 26) { /* reg 4 */ ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[4]; val = syndrome[16] | (syndrome[17] << 8) | (syndrome[18] << 16) | (syndrome[19] << 24); writel(val, ptr); - /* reg 5 */ ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[5]; val = syndrome[20] | (syndrome[21] << 8) | (syndrome[22] << 16) | (syndrome[23] << 24); writel(val, ptr); - /* reg 6 */ ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[6]; - val = syndrome[24] | (syndrome[25] << 8) | - (syndrome[26] << 16) | (syndrome[27] << 24); + val = syndrome[24] | (syndrome[25] << 8); + writel(val, ptr); + break; + case ECC_BCH8: + /* reg 0 */ + ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[0]; + val = syndrome[0] | (syndrome[1] << 8) | (syndrome[2] << 16) | + (syndrome[3] << 24); + writel(val, ptr); + /* reg 1 */ + ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[1]; + val = syndrome[4] | (syndrome[5] << 8) | (syndrome[6] << 16) | + (syndrome[7] << 24); + writel(val, ptr); + /* reg 2 */ + ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[2]; + val = syndrome[8] | (syndrome[9] << 8) | (syndrome[10] << 16) | + (syndrome[11] << 24); + writel(val, ptr); + /* reg 3 */ + ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[3]; + val = syndrome[12]; + writel(val, ptr); + break; + case ECC_BCH4: + /* reg 0 */ + ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[0]; + val = syndrome[0] | (syndrome[1] << 8) | (syndrome[2] << 16) | + (syndrome[3] << 24); + writel(val, ptr); + /* reg 1 */ + ptr = &elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[1]; + val = syndrome[4] | (syndrome[5] << 8) | (syndrome[6] << 16) | + (syndrome[7] << 24); writel(val, ptr); + break; + default: + return -1; } + + return 0; } /** - * elm_check_errors - Check for BCH errors and return error locations + * elm_check_error - Check for BCH errors and return error locations * @syndrome: BCH syndrome - * @nibbles: + * @bch_type: BCH4/BCH8/BCH16 * @error_count: Returns number of errrors in the syndrome * @error_locations: Returns error locations (in decimal) in this array * @@ -95,15 +124,17 @@ static void elm_load_syndromes(u8 *syndrome, u32 nibbles, u8 poly) * and locations in the array passed. Returns -1 if error is not correctable, * else returns 0 */ -int elm_check_error(u8 *syndrome, u32 nibbles, u32 *error_count, +int elm_check_error(u8 *syndrome, u32 bch_type, u32 *error_count, u32 *error_locations) { u8 poly = ELM_DEFAULT_POLY; s8 i; u32 location_status; - elm_load_syndromes(syndrome, nibbles, poly); - + if (elm_load_syndromes(syndrome, bch_type, poly)) { + printf("ELM: *Error: invalid driver configuration\n"); + return -1; + } /* start processing */ writel((readl(&elm_cfg->syndrome_fragments[poly].syndrome_fragment_x[6]) | ELM_SYNDROME_FRAGMENT_6_SYNDROME_VALID), @@ -143,14 +174,14 @@ int elm_check_error(u8 *syndrome, u32 nibbles, u32 *error_count, * Currently we are using only syndrome 0 and syndromes 1 to 6 are not used. * Also, the mode is set only for syndrome 0 */ -int elm_config(enum bch_level level) +int elm_config(u32 bch_type) { u32 val; u8 poly = ELM_DEFAULT_POLY; u32 buffer_size = 0x7FF; /* config size and level */ - val = (u32)(level) & ELM_LOCATION_CONFIG_ECC_BCH_LEVEL_MASK; + val = bch_type & ELM_LOCATION_CONFIG_ECC_BCH_LEVEL_MASK; val |= ((buffer_size << ELM_LOCATION_CONFIG_ECC_SIZE_POS) & ELM_LOCATION_CONFIG_ECC_SIZE_MASK); writel(val, &elm_cfg->location_config); diff --git a/arch/arm/include/asm/arch-am33xx/elm.h b/arch/arm/include/asm/arch-am33xx/elm.h index 45454ea..857dc27 100644 --- a/arch/arm/include/asm/arch-am33xx/elm.h +++ b/arch/arm/include/asm/arch-am33xx/elm.h @@ -24,14 +24,12 @@ #define ELM_LOCATION_STATUS_ECC_CORRECTABLE_MASK (0x100) #define ELM_LOCATION_STATUS_ECC_NB_ERRORS_MASK (0x1F) -#ifndef __ASSEMBLY__ - -enum bch_level { - BCH_4_BIT = 0, - BCH_8_BIT, - BCH_16_BIT -}; +/* bch types */ +#define ECC_BCH4 0 +#define ECC_BCH8 1 +#define ECC_BCH16 2 +#ifndef __ASSEMBLY__ /* BCH syndrome registers */ struct syndrome { @@ -68,9 +66,9 @@ struct elm { struct location error_location[8]; /* 0x800 */ }; -int elm_check_error(u8 *syndrome, u32 nibbles, u32 *error_count, +int elm_check_error(u8 *syndrome, u32 bch_type, u32 *error_count, u32 *error_locations); -int elm_config(enum bch_level level); +int elm_config(u32 bch_type); void elm_reset(void); void elm_init(void); #endif /* __ASSEMBLY__ */