root / hw / ecc.c @ 5703c174
History | View | Annotate | Download (2.9 kB)
1 | 3e3d5815 | balrog | /*
|
---|---|---|---|
2 | 3e3d5815 | balrog | * Calculate Error-correcting Codes. Used by NAND Flash controllers
|
3 | 3e3d5815 | balrog | * (not by NAND chips).
|
4 | 3e3d5815 | balrog | *
|
5 | 3e3d5815 | balrog | * Copyright (c) 2006 Openedhand Ltd.
|
6 | 3e3d5815 | balrog | * Written by Andrzej Zaborowski <balrog@zabor.org>
|
7 | 3e3d5815 | balrog | *
|
8 | 3e3d5815 | balrog | * This code is licensed under the GNU GPL v2.
|
9 | 3e3d5815 | balrog | */
|
10 | 3e3d5815 | balrog | |
11 | 87ecb68b | pbrook | #include "hw.h" |
12 | 87ecb68b | pbrook | #include "flash.h" |
13 | 3e3d5815 | balrog | |
14 | 3e3d5815 | balrog | /*
|
15 | 3e3d5815 | balrog | * Pre-calculated 256-way 1 byte column parity. Table borrowed from Linux.
|
16 | 3e3d5815 | balrog | */
|
17 | 3e3d5815 | balrog | static const uint8_t nand_ecc_precalc_table[] = { |
18 | 3e3d5815 | balrog | 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, |
19 | 3e3d5815 | balrog | 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, |
20 | 3e3d5815 | balrog | 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, |
21 | 3e3d5815 | balrog | 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, |
22 | 3e3d5815 | balrog | 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, |
23 | 3e3d5815 | balrog | 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, |
24 | 3e3d5815 | balrog | 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, |
25 | 3e3d5815 | balrog | 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, |
26 | 3e3d5815 | balrog | 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, |
27 | 3e3d5815 | balrog | 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, |
28 | 3e3d5815 | balrog | 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, |
29 | 3e3d5815 | balrog | 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, |
30 | 3e3d5815 | balrog | 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, |
31 | 3e3d5815 | balrog | 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, |
32 | 3e3d5815 | balrog | 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, |
33 | 3e3d5815 | balrog | 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, |
34 | 3e3d5815 | balrog | 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, |
35 | 3e3d5815 | balrog | 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, |
36 | 3e3d5815 | balrog | 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, |
37 | 3e3d5815 | balrog | 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, |
38 | 3e3d5815 | balrog | 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, |
39 | 3e3d5815 | balrog | 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, |
40 | 3e3d5815 | balrog | 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, |
41 | 3e3d5815 | balrog | 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, |
42 | 3e3d5815 | balrog | 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, |
43 | 3e3d5815 | balrog | 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, |
44 | 3e3d5815 | balrog | 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, |
45 | 3e3d5815 | balrog | 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, |
46 | 3e3d5815 | balrog | 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, |
47 | 3e3d5815 | balrog | 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, |
48 | 3e3d5815 | balrog | 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, |
49 | 3e3d5815 | balrog | 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, |
50 | 3e3d5815 | balrog | }; |
51 | 3e3d5815 | balrog | |
52 | 3e3d5815 | balrog | /* Update ECC parity count. */
|
53 | 9ff6755b | balrog | uint8_t ecc_digest(struct ecc_state_s *s, uint8_t sample)
|
54 | 3e3d5815 | balrog | { |
55 | 3e3d5815 | balrog | uint8_t idx = nand_ecc_precalc_table[sample]; |
56 | 3e3d5815 | balrog | |
57 | 3e3d5815 | balrog | s->cp ^= idx & 0x3f;
|
58 | 3e3d5815 | balrog | if (idx & 0x40) { |
59 | 3e3d5815 | balrog | s->lp[0] ^= ~s->count;
|
60 | 3e3d5815 | balrog | s->lp[1] ^= s->count;
|
61 | 3e3d5815 | balrog | } |
62 | 3e3d5815 | balrog | s->count ++; |
63 | 3e3d5815 | balrog | |
64 | 3e3d5815 | balrog | return sample;
|
65 | 3e3d5815 | balrog | } |
66 | 3e3d5815 | balrog | |
67 | 3e3d5815 | balrog | /* Reinitialise the counters. */
|
68 | 9ff6755b | balrog | void ecc_reset(struct ecc_state_s *s) |
69 | 3e3d5815 | balrog | { |
70 | 3e3d5815 | balrog | s->lp[0] = 0x0000; |
71 | 3e3d5815 | balrog | s->lp[1] = 0x0000; |
72 | 3e3d5815 | balrog | s->cp = 0x00;
|
73 | 3e3d5815 | balrog | s->count = 0;
|
74 | 3e3d5815 | balrog | } |
75 | aa941b94 | balrog | |
76 | aa941b94 | balrog | /* Save/restore */
|
77 | 9ff6755b | balrog | void ecc_put(QEMUFile *f, struct ecc_state_s *s) |
78 | aa941b94 | balrog | { |
79 | aa941b94 | balrog | qemu_put_8s(f, &s->cp); |
80 | aa941b94 | balrog | qemu_put_be16s(f, &s->lp[0]);
|
81 | aa941b94 | balrog | qemu_put_be16s(f, &s->lp[1]);
|
82 | aa941b94 | balrog | qemu_put_be16s(f, &s->count); |
83 | aa941b94 | balrog | } |
84 | aa941b94 | balrog | |
85 | 9ff6755b | balrog | void ecc_get(QEMUFile *f, struct ecc_state_s *s) |
86 | aa941b94 | balrog | { |
87 | aa941b94 | balrog | qemu_get_8s(f, &s->cp); |
88 | aa941b94 | balrog | qemu_get_be16s(f, &s->lp[0]);
|
89 | aa941b94 | balrog | qemu_get_be16s(f, &s->lp[1]);
|
90 | aa941b94 | balrog | qemu_get_be16s(f, &s->count); |
91 | aa941b94 | balrog | } |