Statistics
| Branch: | Revision:

root / hw / ecc.c @ a1bc20df

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 6b620ca3 Paolo Bonzini
 *
10 6b620ca3 Paolo Bonzini
 * Contributions after 2012-01-13 are licensed under the terms of the
11 6b620ca3 Paolo Bonzini
 * GNU GPL, version 2 or (at your option) any later version.
12 3e3d5815 balrog
 */
13 3e3d5815 balrog
14 87ecb68b pbrook
#include "hw.h"
15 87ecb68b pbrook
#include "flash.h"
16 3e3d5815 balrog
17 3e3d5815 balrog
/*
18 3e3d5815 balrog
 * Pre-calculated 256-way 1 byte column parity.  Table borrowed from Linux.
19 3e3d5815 balrog
 */
20 3e3d5815 balrog
static const uint8_t nand_ecc_precalc_table[] = {
21 3e3d5815 balrog
    0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
22 3e3d5815 balrog
    0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
23 3e3d5815 balrog
    0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
24 3e3d5815 balrog
    0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
25 3e3d5815 balrog
    0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
26 3e3d5815 balrog
    0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
27 3e3d5815 balrog
    0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
28 3e3d5815 balrog
    0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
29 3e3d5815 balrog
    0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
30 3e3d5815 balrog
    0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
31 3e3d5815 balrog
    0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
32 3e3d5815 balrog
    0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
33 3e3d5815 balrog
    0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
34 3e3d5815 balrog
    0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
35 3e3d5815 balrog
    0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
36 3e3d5815 balrog
    0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
37 3e3d5815 balrog
    0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
38 3e3d5815 balrog
    0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
39 3e3d5815 balrog
    0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
40 3e3d5815 balrog
    0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
41 3e3d5815 balrog
    0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
42 3e3d5815 balrog
    0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
43 3e3d5815 balrog
    0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
44 3e3d5815 balrog
    0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
45 3e3d5815 balrog
    0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
46 3e3d5815 balrog
    0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
47 3e3d5815 balrog
    0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
48 3e3d5815 balrog
    0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
49 3e3d5815 balrog
    0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
50 3e3d5815 balrog
    0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
51 3e3d5815 balrog
    0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
52 3e3d5815 balrog
    0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
53 3e3d5815 balrog
};
54 3e3d5815 balrog
55 3e3d5815 balrog
/* Update ECC parity count.  */
56 bc24a225 Paul Brook
uint8_t ecc_digest(ECCState *s, uint8_t sample)
57 3e3d5815 balrog
{
58 3e3d5815 balrog
    uint8_t idx = nand_ecc_precalc_table[sample];
59 3e3d5815 balrog
60 3e3d5815 balrog
    s->cp ^= idx & 0x3f;
61 3e3d5815 balrog
    if (idx & 0x40) {
62 3e3d5815 balrog
        s->lp[0] ^= ~s->count;
63 3e3d5815 balrog
        s->lp[1] ^= s->count;
64 3e3d5815 balrog
    }
65 3e3d5815 balrog
    s->count ++;
66 3e3d5815 balrog
67 3e3d5815 balrog
    return sample;
68 3e3d5815 balrog
}
69 3e3d5815 balrog
70 3e3d5815 balrog
/* Reinitialise the counters.  */
71 bc24a225 Paul Brook
void ecc_reset(ECCState *s)
72 3e3d5815 balrog
{
73 3e3d5815 balrog
    s->lp[0] = 0x0000;
74 3e3d5815 balrog
    s->lp[1] = 0x0000;
75 3e3d5815 balrog
    s->cp = 0x00;
76 3e3d5815 balrog
    s->count = 0;
77 3e3d5815 balrog
}
78 aa941b94 balrog
79 aa941b94 balrog
/* Save/restore */
80 34f9f0b5 Dmitry Eremin-Solenikov
VMStateDescription vmstate_ecc_state = {
81 34f9f0b5 Dmitry Eremin-Solenikov
    .name = "ecc-state",
82 34f9f0b5 Dmitry Eremin-Solenikov
    .version_id = 0,
83 34f9f0b5 Dmitry Eremin-Solenikov
    .minimum_version_id = 0,
84 34f9f0b5 Dmitry Eremin-Solenikov
    .minimum_version_id_old = 0,
85 34f9f0b5 Dmitry Eremin-Solenikov
    .fields = (VMStateField []) {
86 34f9f0b5 Dmitry Eremin-Solenikov
        VMSTATE_UINT8(cp, ECCState),
87 34f9f0b5 Dmitry Eremin-Solenikov
        VMSTATE_UINT16_ARRAY(lp, ECCState, 2),
88 34f9f0b5 Dmitry Eremin-Solenikov
        VMSTATE_UINT16(count, ECCState),
89 34f9f0b5 Dmitry Eremin-Solenikov
        VMSTATE_END_OF_LIST(),
90 34f9f0b5 Dmitry Eremin-Solenikov
    },
91 34f9f0b5 Dmitry Eremin-Solenikov
};