1 /******************************************************************************
2 * Copyright (c) 2010 Texas Instruments Incorporated - http://www.ti.com
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the
14 * distribution.
15 *
16 * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
34 /******************************************************************************
35 *
36 * File Name: ecc.c
37 *
38 * Description: This file implements ECC algorithm used on micron NAND flash
39 *
40 * History:
41 * SEP/4/2009, Amit Solanki, Created the file
42 *
43 *****************************************************************************/
44 /****************
45 * Include Files
46 ****************/
47 #include "types.h"
48 #include "ecc.h"
50 /*********************************
51 * Defines and Macros and globals
52 *********************************/
53 // Pre-calculated 256-way 1 byte column parity
54 static const Uint8 nand_ecc_precalc_table[] = {
55 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
56 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
57 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
58 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
59 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
60 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
61 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
62 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
63 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
64 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
65 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
66 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
67 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
68 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
69 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
70 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
71 };
73 /******************************************************************************
74 *
75 * Function: nandTransResult
76 *
77 * Description: Creates non-inverted ECC code from line parity
78 *
79 * Parameters: Uint8 uchReg2 - line parity reg 2
80 * Uint8 uchReg3 - line parity reg 3
81 * Uint8 *puchEccCode - ecc
82 *
83 * Return Value: void
84 ******************************************************************************/
85 static void nandTransResult(Uint8 uchReg2, Uint8 uchReg3, Uint8 *puchEccCode)
86 {
87 Uint8 a, b, i, tmp1, tmp2;
89 /* Initialize variables */
90 a = b = 0x80;
91 tmp1 = tmp2 = 0;
93 /* Calculate first ECC byte */
94 for (i = 0; i < 4; i++) {
95 if (uchReg3 & a) /* LP15,13,11,9 --> ecc_code[0] */
96 tmp1 |= b;
97 b >>= 1;
98 if (uchReg2 & a) /* LP14,12,10,8 --> ecc_code[0] */
99 tmp1 |= b;
100 b >>= 1;
101 a >>= 1;
102 }
104 /* Calculate second ECC byte */
105 b = 0x80;
106 for (i = 0; i < 4; i++) {
107 if (uchReg3 & a) /* LP7,5,3,1 --> ecc_code[1] */
108 tmp2 |= b;
109 b >>= 1;
110 if (uchReg2 & a) /* LP6,4,2,0 --> ecc_code[1] */
111 tmp2 |= b;
112 b >>= 1;
113 a >>= 1;
114 }
116 /* Store two of the ECC bytes */
117 puchEccCode[0] = tmp1;
118 puchEccCode[1] = tmp2;
119 }
120 /******************************************************************************
121 *
122 * Function: eccComputeECC
123 *
124 * Description: Compute 3 byte ECC code for 256 byte block
125 *
126 * Parameters: Uint8* puchData - pointer to raw data
127 * Uint8 *puchEccCode - pointer to ECC buffer
128 *
129 * Return Value: status
130 ******************************************************************************/
131 Int32 eccComputeECC(const Uint8 *puchData, Uint8 *puchEccCode)
132 {
133 Uint8 uchIndex, uchReg1, uchReg2, uchReg3;
134 int j;
135 if(puchData == NULL || puchEccCode == NULL)
136 return ECC_FAIL;
138 /* Initialize variables */
139 uchReg1 = uchReg2 = uchReg3 = 0;
140 puchEccCode[0] = puchEccCode[1] = puchEccCode[2] = 0;
142 /* Build up column parity */
143 for(j = 0; j < 256; j++) {
145 /* Get CP0 - CP5 from table */
146 uchIndex = nand_ecc_precalc_table[puchData[j]];
147 uchReg1 ^= (uchIndex & 0x3f);
149 /* All bit XOR = 1 ? */
150 if (uchIndex & 0x40) {
151 uchReg3 ^= (Uint8) j;
152 uchReg2 ^= ~((Uint8) j);
153 }
154 }
156 /* Create non-inverted ECC code from line parity */
157 nandTransResult(uchReg2, uchReg3, puchEccCode);
159 /* Calculate final ECC code */
160 puchEccCode[0] = ~puchEccCode[0];
161 puchEccCode[1] = ~puchEccCode[1];
162 puchEccCode[2] = ((~uchReg1) << 2) | 0x03;
163 return ECC_SUCCESS;
164 }
167 /******************************************************************************
168 *
169 * Function: eccCorrectData
170 *
171 * Description: Detect and correct a 1 bit error for 256 byte block
172 *
173 * Parameters: Uint8* puchData - Raw data read from the chip
174 * Uint8 *puchEccRead - ECC from the chip
175 * Uint8 *puchEccCalc - ECC calculated from raw data
176 *
177 * Return Value: status
178 ******************************************************************************/
179 Int32 eccCorrectData(Uint8 *puchData, Uint8 *puchEccRead, Uint8 *puchEccCalc)
180 {
181 Uint8 a, b, c, d1, d2, d3, add, bit, i;
183 if(puchData == NULL || puchEccRead == NULL || puchEccCalc == NULL)
184 return ECC_FAIL;
186 /* Do error detection */
187 d1 = puchEccCalc[0] ^ puchEccRead[0];
188 d2 = puchEccCalc[1] ^ puchEccRead[1];
189 d3 = puchEccCalc[2] ^ puchEccRead[2];
191 if ((d1 | d2 | d3) == 0) {
192 /* No errors */
193 return ECC_SUCCESS;
194 }
195 else {
196 a = (d1 ^ (d1 >> 1)) & 0x55;
197 b = (d2 ^ (d2 >> 1)) & 0x55;
198 c = (d3 ^ (d3 >> 1)) & 0x54;
200 /* Found and will correct single bit error in the data */
201 if ((a == 0x55) && (b == 0x55) && (c == 0x54)) {
202 c = 0x80;
203 add = 0;
204 a = 0x80;
205 for (i=0; i<4; i++) {
206 if (d1 & c)
207 add |= a;
208 c >>= 2;
209 a >>= 1;
210 }
211 c = 0x80;
212 for (i=0; i<4; i++) {
213 if (d2 & c)
214 add |= a;
215 c >>= 2;
216 a >>= 1;
217 }
218 bit = 0;
219 b = 0x04;
220 c = 0x80;
221 for (i=0; i<3; i++) {
222 if (d3 & c)
223 bit |= b;
224 c >>= 2;
225 b >>= 1;
226 }
227 b = 0x01;
228 a = puchData[add];
229 a ^= (b << bit);
230 puchData[add] = a;
231 return ECC_SUCCESS;
232 } else {
233 i = 0;
234 while (d1) {
235 if (d1 & 0x01)
236 ++i;
237 d1 >>= 1;
238 }
239 while (d2) {
240 if (d2 & 0x01)
241 ++i;
242 d2 >>= 1;
243 }
244 while (d3) {
245 if (d3 & 0x01)
246 ++i;
247 d3 >>= 1;
248 }
249 if (i == 1) {
250 /* ECC Code Error Correction */
251 puchEccRead[0] = puchEccCalc[0];
252 puchEccRead[1] = puchEccCalc[1];
253 puchEccRead[2] = puchEccCalc[2];
254 return ECC_SUCCESS;
255 }
256 else {
257 /* Uncorrectable Error */
258 return ECC_FAIL;
259 }
260 }
261 }
262 }
266 /* The number of bytes required for ecc */
267 Int32 eccNumBytes(void)
268 {
269 return (3);
271 }
274 /* The number of bytes each ECC covers */
275 Int32 eccBytesPerBlock (void)
276 {
277 return (256);
279 }