Statistics
| Branch: | Revision:

root / hw / block / ecc.c @ 49ab747f

History | View | Annotate | Download (3 kB)

1
/*
2
 * Calculate Error-correcting Codes. Used by NAND Flash controllers
3
 * (not by NAND chips).
4
 *
5
 * Copyright (c) 2006 Openedhand Ltd.
6
 * Written by Andrzej Zaborowski <balrog@zabor.org>
7
 *
8
 * This code is licensed under the GNU GPL v2.
9
 *
10
 * Contributions after 2012-01-13 are licensed under the terms of the
11
 * GNU GPL, version 2 or (at your option) any later version.
12
 */
13

    
14
#include "hw/hw.h"
15
#include "hw/block/flash.h"
16

    
17
/*
18
 * Pre-calculated 256-way 1 byte column parity.  Table borrowed from Linux.
19
 */
20
static const uint8_t nand_ecc_precalc_table[] = {
21
    0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
22
    0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
23
    0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
24
    0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
25
    0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
26
    0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
27
    0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
28
    0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
29
    0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
30
    0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
31
    0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
32
    0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
33
    0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
34
    0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
35
    0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
36
    0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
37
    0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
38
    0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
39
    0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
40
    0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
41
    0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
42
    0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
43
    0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
44
    0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
45
    0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
46
    0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
47
    0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
48
    0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
49
    0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
50
    0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
51
    0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
52
    0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
53
};
54

    
55
/* Update ECC parity count.  */
56
uint8_t ecc_digest(ECCState *s, uint8_t sample)
57
{
58
    uint8_t idx = nand_ecc_precalc_table[sample];
59

    
60
    s->cp ^= idx & 0x3f;
61
    if (idx & 0x40) {
62
        s->lp[0] ^= ~s->count;
63
        s->lp[1] ^= s->count;
64
    }
65
    s->count ++;
66

    
67
    return sample;
68
}
69

    
70
/* Reinitialise the counters.  */
71
void ecc_reset(ECCState *s)
72
{
73
    s->lp[0] = 0x0000;
74
    s->lp[1] = 0x0000;
75
    s->cp = 0x00;
76
    s->count = 0;
77
}
78

    
79
/* Save/restore */
80
VMStateDescription vmstate_ecc_state = {
81
    .name = "ecc-state",
82
    .version_id = 0,
83
    .minimum_version_id = 0,
84
    .minimum_version_id_old = 0,
85
    .fields = (VMStateField []) {
86
        VMSTATE_UINT8(cp, ECCState),
87
        VMSTATE_UINT16_ARRAY(lp, ECCState, 2),
88
        VMSTATE_UINT16(count, ECCState),
89
        VMSTATE_END_OF_LIST(),
90
    },
91
};