1 /*****************************************************************************
2 * Copyright 2004 - 2009 Broadcom Corporation. All rights reserved.
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").
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
13 *****************************************************************************/
15 /* ---- Include Files ---------------------------------------------------- */
16 #include <mach/reg_umi.h>
17 #include "nand_bcm_umi.h"
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 ------------------------------------------------ */
31 /****************************************************************************
32 * nand_bch_ecc_flip_bit - Routine to flip an errored bit
35 * This is a helper routine that flips the bit (0 -> 1 or 1 -> 0) of the
36 * errored bit specified
39 * datap - Container that holds the 512 byte data
40 * errorLocation - Location of the bit that needs to be flipped
44 ****************************************************************************/
45 static void nand_bcm_umi_bch_ecc_flip_bit(uint8_t *datap, int errorLocation)
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;
51 uint8_t errorByte = 0;
52 uint8_t byteMask = 1 << locWithinAByte;
54 /* BCH uses big endian, need to change the location
55 * bits to little endian */
56 locWithinAWord = 3 - locWithinAWord;
58 errorByte = datap[locWithinAPage * sizeof(uint32_t) + locWithinAWord];
61 puthexs("\nECC Correct Offset: ",
62 locWithinAPage * sizeof(uint32_t) + locWithinAWord);
63 puthexs(" errorByte:", errorByte);
64 puthex8(" Bit: ", locWithinAByte);
67 if (errorByte & byteMask) {
68 /* bit needs to be cleared */
69 errorByte &= ~byteMask;
71 /* bit needs to be set */
72 errorByte |= byteMask;
75 /* write back the value with the fixed bit */
76 datap[locWithinAPage * sizeof(uint32_t) + locWithinAWord] = errorByte;
79 /****************************************************************************
80 * nand_correct_page_bch - Routine to correct bit errors when reading NAND
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.
88 * datap - Container that holds the 512 byte data
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 ****************************************************************************/
95 int nand_bcm_umi_bch_correct_page(uint8_t *datap, uint8_t *readEccData,
103 /* wait for read ECC to be valid */
104 regValue = nand_bcm_umi_bch_poll_read_ecc_calc();
107 * read the control status register to determine if there
109 * see if errors are correctible
111 if ((regValue & REG_UMI_BCH_CTRL_STATUS_UNCORR_ERR) > 0) {
114 for (i = 0; i < numEccBytes; i++) {
115 if (readEccData[i] != 0xff) {
116 /* errors cannot be fixed, return -1 */
120 /* If ECC is unprogrammed then we can't correct,
121 * assume everything OK */
125 if ((regValue & REG_UMI_BCH_CTRL_STATUS_CORR_ERR) == 0) {
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
135 * 3. Invert the bit in the data
137 numErrors = (regValue & REG_UMI_BCH_CTRL_STATUS_NB_CORR_ERROR) >> 20;
139 for (idx = 0; idx < numErrors; idx++) {
141 REG_UMI_BCH_ERR_LOC_ADDR(idx) & REG_UMI_BCH_ERR_LOC_MASK;
144 nand_bcm_umi_bch_ecc_flip_bit(datap, errorLocation);
146 /* Errors corrected */