2 * (C) Copyright 2000 Texas Instruments
4 * This file os based on the following u-boot file:
7 * See file CREDITS for list of people who contributed to this
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
29 * Pre-calculated 256-way 1 byte column parity
31 static const u_char nand_ecc_precalc_table
[] = {
32 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
33 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
34 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
35 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
36 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
37 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
38 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
39 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
40 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
41 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
42 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
43 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
44 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
45 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
46 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
47 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
52 * Creates non-inverted ECC code from line parity
54 static void nand_trans_result(u_char reg2
, u_char reg3
,
57 u_char a
, b
, i
, tmp1
, tmp2
;
59 /* Initialize variables */
63 /* Calculate first ECC byte */
64 for (i
= 0; i
< 4; i
++) {
65 if (reg3
& a
) /* LP15,13,11,9 --> ecc_code[0] */
68 if (reg2
& a
) /* LP14,12,10,8 --> ecc_code[0] */
74 /* Calculate second ECC byte */
76 for (i
= 0; i
< 4; i
++) {
77 if (reg3
& a
) /* LP7,5,3,1 --> ecc_code[1] */
80 if (reg2
& a
) /* LP6,4,2,0 --> ecc_code[1] */
86 /* Store two of the ECC bytes */
92 * Calculate 3 byte ECC code for 256 byte block
94 /* ECC Calculation is different between NAND and NAND Legacy code
95 * in U-Boot. If NAND_LEGACY is enabled in u-boot it should be
96 * enabled in the config file in x-loader also
99 void nand_calculate_ecc (const u_char
*dat
, u_char
*ecc_code
)
101 u_char idx
, reg1
, reg3
;
104 /* Initialize variables */
106 ecc_code
[0] = ecc_code
[1] = ecc_code
[2] = 0;
108 /* Build up column parity */
109 for(j
= 0; j
< 256; j
++) {
111 /* Get CP0 - CP5 from table */
112 idx
= nand_ecc_precalc_table
[dat
[j
]];
115 /* All bit XOR = 1 ? */
121 /* Create non-inverted ECC code from line parity */
122 nand_trans_result((reg1
& 0x40) ? ~reg3
: reg3
, reg3
, ecc_code
);
124 /* Calculate final ECC code */
125 ecc_code
[0] = ~ecc_code
[0];
126 ecc_code
[1] = ~ecc_code
[1];
127 ecc_code
[2] = ((~reg1
) << 2) | 0x03;
130 void nand_calculate_ecc (const u_char
*dat
, u_char
*ecc_code
)
132 u_char idx
, reg1
, reg2
, reg3
;
135 /* Initialize variables */
136 reg1
= reg2
= reg3
= 0;
137 ecc_code
[0] = ecc_code
[1] = ecc_code
[2] = 0;
139 /* Build up column parity */
140 for(j
= 0; j
< 256; j
++) {
142 /* Get CP0 - CP5 from table */
143 idx
= nand_ecc_precalc_table
[dat
[j
]];
144 reg1
^= (idx
& 0x3f);
146 /* All bit XOR = 1 ? */
149 reg2
^= ~((u_char
) j
);
153 /* Create non-inverted ECC code from line parity */
154 nand_trans_result(reg2
, reg3
, ecc_code
);
156 /* Calculate final ECC code */
157 ecc_code
[0] = ~ecc_code
[0];
158 ecc_code
[1] = ~ecc_code
[1];
159 ecc_code
[2] = ((~reg1
) << 2) | 0x03;
163 * Detect and correct a 1 bit error for 256 byte block
165 int nand_correct_data (u_char
*dat
, u_char
*read_ecc
, u_char
*calc_ecc
)
167 u_char a
, b
, c
, d1
, d2
, d3
, add
, bit
, i
;
169 /* Do error detection */
170 d1
= calc_ecc
[0] ^ read_ecc
[0];
171 d2
= calc_ecc
[1] ^ read_ecc
[1];
172 d3
= calc_ecc
[2] ^ read_ecc
[2];
174 if ((d1
| d2
| d3
) == 0) {
179 a
= (d1
^ (d1
>> 1)) & 0x55;
180 b
= (d2
^ (d2
>> 1)) & 0x55;
181 c
= (d3
^ (d3
>> 1)) & 0x54;
183 /* Found and will correct single bit error in the data */
184 if ((a
== 0x55) && (b
== 0x55) && (c
== 0x54)) {
188 for (i
=0; i
<4; i
++) {
195 for (i
=0; i
<4; i
++) {
204 for (i
=0; i
<3; i
++) {
234 /* ECC Code Error Correction */
235 read_ecc
[0] = calc_ecc
[0];
236 read_ecc
[1] = calc_ecc
[1];
237 read_ecc
[2] = calc_ecc
[2];
241 /* Uncorrectable Error */
247 /* Should never happen */