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 }; 92