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