1/***************************************************************************** 2* Copyright 2004 - 2009 Broadcom Corporation. All rights reserved. 3* 4* Unless you and Broadcom execute a separate written software license 5* agreement governing use of this software, this software is licensed to you 6* under the terms of the GNU General Public License version 2, available at 7* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). 8* 9* Notwithstanding the above, under no circumstances may you combine this 10* software in any way with any other Broadcom software provided under a 11* license other than the GPL, without Broadcom's express prior written 12* consent. 13*****************************************************************************/ 14 15/* ---- Include Files ---------------------------------------------------- */ 16#include <mach/reg_umi.h> 17#include "nand_bcm_umi.h" 18#ifdef BOOT0_BUILD 19#include <uart.h> 20#endif 21 22/* ---- External Variable Declarations ----------------------------------- */ 23/* ---- External Function Prototypes ------------------------------------- */ 24/* ---- Public Variables ------------------------------------------------- */ 25/* ---- Private Constants and Types -------------------------------------- */ 26/* ---- Private Function Prototypes -------------------------------------- */ 27/* ---- Private Variables ------------------------------------------------ */ 28/* ---- Private Functions ------------------------------------------------ */ 29 30#if NAND_ECC_BCH 31/**************************************************************************** 32* nand_bch_ecc_flip_bit - Routine to flip an errored bit 33* 34* PURPOSE: 35* This is a helper routine that flips the bit (0 -> 1 or 1 -> 0) of the 36* errored bit specified 37* 38* PARAMETERS: 39* datap - Container that holds the 512 byte data 40* errorLocation - Location of the bit that needs to be flipped 41* 42* RETURNS: 43* None 44****************************************************************************/ 45static void nand_bcm_umi_bch_ecc_flip_bit(uint8_t *datap, int errorLocation) 46{ 47 int locWithinAByte = (errorLocation & REG_UMI_BCH_ERR_LOC_BYTE) >> 0; 48 int locWithinAWord = (errorLocation & REG_UMI_BCH_ERR_LOC_WORD) >> 3; 49 int locWithinAPage = (errorLocation & REG_UMI_BCH_ERR_LOC_PAGE) >> 5; 50 51 uint8_t errorByte = 0; 52 uint8_t byteMask = 1 << locWithinAByte; 53 54 /* BCH uses big endian, need to change the location 55 * bits to little endian */ 56 locWithinAWord = 3 - locWithinAWord; 57 58 errorByte = datap[locWithinAPage * sizeof(uint32_t) + locWithinAWord]; 59 60#ifdef BOOT0_BUILD 61 puthexs("\nECC Correct Offset: ", 62 locWithinAPage * sizeof(uint32_t) + locWithinAWord); 63 puthexs(" errorByte:", errorByte); 64 puthex8(" Bit: ", locWithinAByte); 65#endif 66 67 if (errorByte & byteMask) { 68 /* bit needs to be cleared */ 69 errorByte &= ~byteMask; 70 } else { 71 /* bit needs to be set */ 72 errorByte |= byteMask; 73 } 74 75 /* write back the value with the fixed bit */ 76 datap[locWithinAPage * sizeof(uint32_t) + locWithinAWord] = errorByte; 77} 78 79/**************************************************************************** 80* nand_correct_page_bch - Routine to correct bit errors when reading NAND 81* 82* PURPOSE: 83* This routine reads the BCH registers to determine if there are any bit 84* errors during the read of the last 512 bytes of data + ECC bytes. If 85* errors exists, the routine fixes it. 86* 87* PARAMETERS: 88* datap - Container that holds the 512 byte data 89* 90* RETURNS: 91* 0 or greater = Number of errors corrected 92* (No errors are found or errors have been fixed) 93* -1 = Error(s) cannot be fixed 94****************************************************************************/ 95int nand_bcm_umi_bch_correct_page(uint8_t *datap, uint8_t *readEccData, 96 int numEccBytes) 97{ 98 int numErrors; 99 int errorLocation; 100 int idx; 101 uint32_t regValue; 102 103 /* wait for read ECC to be valid */ 104 regValue = nand_bcm_umi_bch_poll_read_ecc_calc(); 105 106 /* 107 * read the control status register to determine if there 108 * are error'ed bits 109 * see if errors are correctible 110 */ 111 if ((regValue & REG_UMI_BCH_CTRL_STATUS_UNCORR_ERR) > 0) { 112 int i; 113 114 for (i = 0; i < numEccBytes; i++) { 115 if (readEccData[i] != 0xff) { 116 /* errors cannot be fixed, return -1 */ 117 return -1; 118 } 119 } 120 /* If ECC is unprogrammed then we can't correct, 121 * assume everything OK */ 122 return 0; 123 } 124 125 if ((regValue & REG_UMI_BCH_CTRL_STATUS_CORR_ERR) == 0) { 126 /* no errors */ 127 return 0; 128 } 129 130 /* 131 * Fix errored bits by doing the following: 132 * 1. Read the number of errors in the control and status register 133 * 2. Read the error location registers that corresponds to the number 134 * of errors reported 135 * 3. Invert the bit in the data 136 */ 137 numErrors = (regValue & REG_UMI_BCH_CTRL_STATUS_NB_CORR_ERROR) >> 20; 138 139 for (idx = 0; idx < numErrors; idx++) { 140 errorLocation = 141 REG_UMI_BCH_ERR_LOC_ADDR(idx) & REG_UMI_BCH_ERR_LOC_MASK; 142 143 /* Flip bit */ 144 nand_bcm_umi_bch_ecc_flip_bit(datap, errorLocation); 145 } 146 /* Errors corrected */ 147 return numErrors; 148} 149#endif 150