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 "qemu/osdep.h"
15#include "migration/vmstate.h"
16#include "hw/block/flash.h"
17
18/*
19 * Pre-calculated 256-way 1 byte column parity. Table borrowed from Linux.
20 */
21static const uint8_t nand_ecc_precalc_table[] = {
22 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
23 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
24 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
25 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
26 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
27 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
28 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
29 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
30 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
31 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
32 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
33 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
34 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
35 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
36 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
37 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
38 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30,
39 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
40 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55,
41 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
42 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56,
43 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
44 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33,
45 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
46 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59,
47 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
48 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c,
49 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
50 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f,
51 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
52 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a,
53 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
54};
55
56/* Update ECC parity count. */
57uint8_t ecc_digest(ECCState *s, uint8_t sample)
58{
59 uint8_t idx = nand_ecc_precalc_table[sample];
60
61 s->cp ^= idx & 0x3f;
62 if (idx & 0x40) {
63 s->lp[0] ^= ~s->count;
64 s->lp[1] ^= s->count;
65 }
66 s->count ++;
67
68 return sample;
69}
70
71/* Reinitialise the counters. */
72void ecc_reset(ECCState *s)
73{
74 s->lp[0] = 0x0000;
75 s->lp[1] = 0x0000;
76 s->cp = 0x00;
77 s->count = 0;
78}
79
80/* Save/restore */
81VMStateDescription vmstate_ecc_state = {
82 .name = "ecc-state",
83 .version_id = 0,
84 .minimum_version_id = 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};
92