1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41#ifndef STANDALONE
42#include <linux/types.h>
43#include <linux/kernel.h>
44#include <linux/module.h>
45#include <linux/mtd/mtd.h>
46#include <linux/mtd/nand.h>
47#include <linux/mtd/nand_ecc.h>
48#include <asm/byteorder.h>
49#else
50#include <stdint.h>
51struct mtd_info;
52#define EXPORT_SYMBOL(x)
53
54#define MODULE_LICENSE(x)
55#define MODULE_AUTHOR(x)
56#define MODULE_DESCRIPTION(x)
57
58#define printk printf
59#define KERN_ERR ""
60#endif
61
62
63
64
65
66
67
68static const char invparity[256] = {
69 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
70 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
71 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
72 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
73 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
74 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
75 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
76 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
77 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
78 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
79 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
80 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
81 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
82 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
83 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
84 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
85};
86
87
88
89
90
91
92static const char bitsperbyte[256] = {
93 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
94 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
95 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
96 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
97 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
98 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
99 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
100 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
101 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
102 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
103 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
104 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
105 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
106 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
107 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
108 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
109};
110
111
112
113
114
115
116
117static const char addressbits[256] = {
118 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
119 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03,
120 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
121 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03,
122 0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05,
123 0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07,
124 0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05,
125 0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07,
126 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
127 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03,
128 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
129 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03,
130 0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05,
131 0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07,
132 0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05,
133 0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07,
134 0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09,
135 0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b,
136 0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09,
137 0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b,
138 0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d,
139 0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f,
140 0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d,
141 0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f,
142 0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09,
143 0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b,
144 0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09,
145 0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b,
146 0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d,
147 0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f,
148 0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d,
149 0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f
150};
151
152
153
154
155
156
157
158
159int nand_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
160 unsigned char *code)
161{
162 int i;
163 const uint32_t *bp = (uint32_t *)buf;
164
165 const uint32_t eccsize_mult =
166 (((struct nand_chip *)mtd->priv)->ecc.size) >> 8;
167 uint32_t cur;
168
169 uint32_t rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7;
170 uint32_t rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15, rp16;
171 uint32_t uninitialized_var(rp17);
172 uint32_t par;
173 uint32_t tmppar;
174
175
176
177 par = 0;
178 rp4 = 0;
179 rp6 = 0;
180 rp8 = 0;
181 rp10 = 0;
182 rp12 = 0;
183 rp14 = 0;
184 rp16 = 0;
185
186
187
188
189
190
191
192
193
194
195
196 for (i = 0; i < eccsize_mult << 2; i++) {
197 cur = *bp++;
198 tmppar = cur;
199 rp4 ^= cur;
200 cur = *bp++;
201 tmppar ^= cur;
202 rp6 ^= tmppar;
203 cur = *bp++;
204 tmppar ^= cur;
205 rp4 ^= cur;
206 cur = *bp++;
207 tmppar ^= cur;
208 rp8 ^= tmppar;
209
210 cur = *bp++;
211 tmppar ^= cur;
212 rp4 ^= cur;
213 rp6 ^= cur;
214 cur = *bp++;
215 tmppar ^= cur;
216 rp6 ^= cur;
217 cur = *bp++;
218 tmppar ^= cur;
219 rp4 ^= cur;
220 cur = *bp++;
221 tmppar ^= cur;
222 rp10 ^= tmppar;
223
224 cur = *bp++;
225 tmppar ^= cur;
226 rp4 ^= cur;
227 rp6 ^= cur;
228 rp8 ^= cur;
229 cur = *bp++;
230 tmppar ^= cur;
231 rp6 ^= cur;
232 rp8 ^= cur;
233 cur = *bp++;
234 tmppar ^= cur;
235 rp4 ^= cur;
236 rp8 ^= cur;
237 cur = *bp++;
238 tmppar ^= cur;
239 rp8 ^= cur;
240
241 cur = *bp++;
242 tmppar ^= cur;
243 rp4 ^= cur;
244 rp6 ^= cur;
245 cur = *bp++;
246 tmppar ^= cur;
247 rp6 ^= cur;
248 cur = *bp++;
249 tmppar ^= cur;
250 rp4 ^= cur;
251 cur = *bp++;
252 tmppar ^= cur;
253
254 par ^= tmppar;
255 if ((i & 0x1) == 0)
256 rp12 ^= tmppar;
257 if ((i & 0x2) == 0)
258 rp14 ^= tmppar;
259 if (eccsize_mult == 2 && (i & 0x4) == 0)
260 rp16 ^= tmppar;
261 }
262
263
264
265
266
267
268
269 rp4 ^= (rp4 >> 16);
270 rp4 ^= (rp4 >> 8);
271 rp4 &= 0xff;
272 rp6 ^= (rp6 >> 16);
273 rp6 ^= (rp6 >> 8);
274 rp6 &= 0xff;
275 rp8 ^= (rp8 >> 16);
276 rp8 ^= (rp8 >> 8);
277 rp8 &= 0xff;
278 rp10 ^= (rp10 >> 16);
279 rp10 ^= (rp10 >> 8);
280 rp10 &= 0xff;
281 rp12 ^= (rp12 >> 16);
282 rp12 ^= (rp12 >> 8);
283 rp12 &= 0xff;
284 rp14 ^= (rp14 >> 16);
285 rp14 ^= (rp14 >> 8);
286 rp14 &= 0xff;
287 if (eccsize_mult == 2) {
288 rp16 ^= (rp16 >> 16);
289 rp16 ^= (rp16 >> 8);
290 rp16 &= 0xff;
291 }
292
293
294
295
296
297
298
299
300
301
302
303#ifdef __BIG_ENDIAN
304 rp2 = (par >> 16);
305 rp2 ^= (rp2 >> 8);
306 rp2 &= 0xff;
307 rp3 = par & 0xffff;
308 rp3 ^= (rp3 >> 8);
309 rp3 &= 0xff;
310#else
311 rp3 = (par >> 16);
312 rp3 ^= (rp3 >> 8);
313 rp3 &= 0xff;
314 rp2 = par & 0xffff;
315 rp2 ^= (rp2 >> 8);
316 rp2 &= 0xff;
317#endif
318
319
320 par ^= (par >> 16);
321#ifdef __BIG_ENDIAN
322 rp0 = (par >> 8) & 0xff;
323 rp1 = (par & 0xff);
324#else
325 rp1 = (par >> 8) & 0xff;
326 rp0 = (par & 0xff);
327#endif
328
329
330 par ^= (par >> 8);
331 par &= 0xff;
332
333
334
335
336
337
338
339
340
341
342 rp5 = (par ^ rp4) & 0xff;
343 rp7 = (par ^ rp6) & 0xff;
344 rp9 = (par ^ rp8) & 0xff;
345 rp11 = (par ^ rp10) & 0xff;
346 rp13 = (par ^ rp12) & 0xff;
347 rp15 = (par ^ rp14) & 0xff;
348 if (eccsize_mult == 2)
349 rp17 = (par ^ rp16) & 0xff;
350
351
352
353
354
355
356
357#ifdef CONFIG_MTD_NAND_ECC_SMC
358 code[0] =
359 (invparity[rp7] << 7) |
360 (invparity[rp6] << 6) |
361 (invparity[rp5] << 5) |
362 (invparity[rp4] << 4) |
363 (invparity[rp3] << 3) |
364 (invparity[rp2] << 2) |
365 (invparity[rp1] << 1) |
366 (invparity[rp0]);
367 code[1] =
368 (invparity[rp15] << 7) |
369 (invparity[rp14] << 6) |
370 (invparity[rp13] << 5) |
371 (invparity[rp12] << 4) |
372 (invparity[rp11] << 3) |
373 (invparity[rp10] << 2) |
374 (invparity[rp9] << 1) |
375 (invparity[rp8]);
376#else
377 code[1] =
378 (invparity[rp7] << 7) |
379 (invparity[rp6] << 6) |
380 (invparity[rp5] << 5) |
381 (invparity[rp4] << 4) |
382 (invparity[rp3] << 3) |
383 (invparity[rp2] << 2) |
384 (invparity[rp1] << 1) |
385 (invparity[rp0]);
386 code[0] =
387 (invparity[rp15] << 7) |
388 (invparity[rp14] << 6) |
389 (invparity[rp13] << 5) |
390 (invparity[rp12] << 4) |
391 (invparity[rp11] << 3) |
392 (invparity[rp10] << 2) |
393 (invparity[rp9] << 1) |
394 (invparity[rp8]);
395#endif
396 if (eccsize_mult == 1)
397 code[2] =
398 (invparity[par & 0xf0] << 7) |
399 (invparity[par & 0x0f] << 6) |
400 (invparity[par & 0xcc] << 5) |
401 (invparity[par & 0x33] << 4) |
402 (invparity[par & 0xaa] << 3) |
403 (invparity[par & 0x55] << 2) |
404 3;
405 else
406 code[2] =
407 (invparity[par & 0xf0] << 7) |
408 (invparity[par & 0x0f] << 6) |
409 (invparity[par & 0xcc] << 5) |
410 (invparity[par & 0x33] << 4) |
411 (invparity[par & 0xaa] << 3) |
412 (invparity[par & 0x55] << 2) |
413 (invparity[rp17] << 1) |
414 (invparity[rp16] << 0);
415 return 0;
416}
417EXPORT_SYMBOL(nand_calculate_ecc);
418
419
420
421
422
423
424
425
426
427
428int __nand_correct_data(unsigned char *buf,
429 unsigned char *read_ecc, unsigned char *calc_ecc,
430 unsigned int eccsize)
431{
432 unsigned char b0, b1, b2, bit_addr;
433 unsigned int byte_addr;
434
435 const uint32_t eccsize_mult = eccsize >> 8;
436
437
438
439
440
441
442#ifdef CONFIG_MTD_NAND_ECC_SMC
443 b0 = read_ecc[0] ^ calc_ecc[0];
444 b1 = read_ecc[1] ^ calc_ecc[1];
445#else
446 b0 = read_ecc[1] ^ calc_ecc[1];
447 b1 = read_ecc[0] ^ calc_ecc[0];
448#endif
449 b2 = read_ecc[2] ^ calc_ecc[2];
450
451
452
453
454
455
456 if ((b0 | b1 | b2) == 0)
457 return 0;
458
459 if ((((b0 ^ (b0 >> 1)) & 0x55) == 0x55) &&
460 (((b1 ^ (b1 >> 1)) & 0x55) == 0x55) &&
461 ((eccsize_mult == 1 && ((b2 ^ (b2 >> 1)) & 0x54) == 0x54) ||
462 (eccsize_mult == 2 && ((b2 ^ (b2 >> 1)) & 0x55) == 0x55))) {
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480 if (eccsize_mult == 1)
481 byte_addr = (addressbits[b1] << 4) + addressbits[b0];
482 else
483 byte_addr = (addressbits[b2 & 0x3] << 8) +
484 (addressbits[b1] << 4) + addressbits[b0];
485 bit_addr = addressbits[b2 >> 2];
486
487 buf[byte_addr] ^= (1 << bit_addr);
488 return 1;
489
490 }
491
492 if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1)
493 return 1;
494
495 printk(KERN_ERR "uncorrectable error : ");
496 return -1;
497}
498EXPORT_SYMBOL(__nand_correct_data);
499
500
501
502
503
504
505
506
507
508
509int nand_correct_data(struct mtd_info *mtd, unsigned char *buf,
510 unsigned char *read_ecc, unsigned char *calc_ecc)
511{
512 return __nand_correct_data(buf, read_ecc, calc_ecc,
513 ((struct nand_chip *)mtd->priv)->ecc.size);
514}
515EXPORT_SYMBOL(nand_correct_data);
516
517MODULE_LICENSE("GPL");
518MODULE_AUTHOR("Frans Meulenbroeks <fransmeulenbroeks@gmail.com>");
519MODULE_DESCRIPTION("Generic NAND ECC support");
520