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 */