1e5acf9c8SMiquel Raynal // SPDX-License-Identifier: GPL-2.0-or-later 2e5acf9c8SMiquel Raynal /* 3e5acf9c8SMiquel Raynal * This file contains an ECC algorithm that detects and corrects 1 bit 4e5acf9c8SMiquel Raynal * errors in a 256 byte block of data. 5e5acf9c8SMiquel Raynal * 6e5acf9c8SMiquel Raynal * Copyright © 2008 Koninklijke Philips Electronics NV. 7e5acf9c8SMiquel Raynal * Author: Frans Meulenbroeks 8e5acf9c8SMiquel Raynal * 9e5acf9c8SMiquel Raynal * Completely replaces the previous ECC implementation which was written by: 10e5acf9c8SMiquel Raynal * Steven J. Hill (sjhill@realitydiluted.com) 11e5acf9c8SMiquel Raynal * Thomas Gleixner (tglx@linutronix.de) 12e5acf9c8SMiquel Raynal * 13e5acf9c8SMiquel Raynal * Information on how this algorithm works and how it was developed 14e5acf9c8SMiquel Raynal * can be found in Documentation/driver-api/mtd/nand_ecc.rst 15e5acf9c8SMiquel Raynal */ 16e5acf9c8SMiquel Raynal 17e5acf9c8SMiquel Raynal #include <linux/types.h> 18e5acf9c8SMiquel Raynal #include <linux/kernel.h> 19e5acf9c8SMiquel Raynal #include <linux/module.h> 20e5acf9c8SMiquel Raynal #include <linux/mtd/mtd.h> 21e5acf9c8SMiquel Raynal #include <linux/mtd/rawnand.h> 22e5acf9c8SMiquel Raynal #include <linux/mtd/nand-ecc-sw-hamming.h> 23e5acf9c8SMiquel Raynal #include <asm/byteorder.h> 24e5acf9c8SMiquel Raynal 25e5acf9c8SMiquel Raynal /* 26e5acf9c8SMiquel Raynal * invparity is a 256 byte table that contains the odd parity 27e5acf9c8SMiquel Raynal * for each byte. So if the number of bits in a byte is even, 28e5acf9c8SMiquel Raynal * the array element is 1, and when the number of bits is odd 29e5acf9c8SMiquel Raynal * the array eleemnt is 0. 30e5acf9c8SMiquel Raynal */ 31e5acf9c8SMiquel Raynal static const char invparity[256] = { 32e5acf9c8SMiquel Raynal 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 33e5acf9c8SMiquel Raynal 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 34e5acf9c8SMiquel Raynal 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 35e5acf9c8SMiquel Raynal 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 36e5acf9c8SMiquel Raynal 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 37e5acf9c8SMiquel Raynal 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 38e5acf9c8SMiquel Raynal 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 39e5acf9c8SMiquel Raynal 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 40e5acf9c8SMiquel Raynal 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 41e5acf9c8SMiquel Raynal 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 42e5acf9c8SMiquel Raynal 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 43e5acf9c8SMiquel Raynal 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 44e5acf9c8SMiquel Raynal 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 45e5acf9c8SMiquel Raynal 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 46e5acf9c8SMiquel Raynal 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 47e5acf9c8SMiquel Raynal 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 48e5acf9c8SMiquel Raynal }; 49e5acf9c8SMiquel Raynal 50e5acf9c8SMiquel Raynal /* 51e5acf9c8SMiquel Raynal * bitsperbyte contains the number of bits per byte 52e5acf9c8SMiquel Raynal * this is only used for testing and repairing parity 53e5acf9c8SMiquel Raynal * (a precalculated value slightly improves performance) 54e5acf9c8SMiquel Raynal */ 55e5acf9c8SMiquel Raynal static const char bitsperbyte[256] = { 56e5acf9c8SMiquel Raynal 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 57e5acf9c8SMiquel Raynal 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 58e5acf9c8SMiquel Raynal 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 59e5acf9c8SMiquel Raynal 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 60e5acf9c8SMiquel Raynal 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 61e5acf9c8SMiquel Raynal 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 62e5acf9c8SMiquel Raynal 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 63e5acf9c8SMiquel Raynal 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 64e5acf9c8SMiquel Raynal 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 65e5acf9c8SMiquel Raynal 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 66e5acf9c8SMiquel Raynal 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 67e5acf9c8SMiquel Raynal 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 68e5acf9c8SMiquel Raynal 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 69e5acf9c8SMiquel Raynal 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 70e5acf9c8SMiquel Raynal 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 71e5acf9c8SMiquel Raynal 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8, 72e5acf9c8SMiquel Raynal }; 73e5acf9c8SMiquel Raynal 74e5acf9c8SMiquel Raynal /* 75e5acf9c8SMiquel Raynal * addressbits is a lookup table to filter out the bits from the xor-ed 76e5acf9c8SMiquel Raynal * ECC data that identify the faulty location. 77e5acf9c8SMiquel Raynal * this is only used for repairing parity 78e5acf9c8SMiquel Raynal * see the comments in nand_correct_data for more details 79e5acf9c8SMiquel Raynal */ 80e5acf9c8SMiquel Raynal static const char addressbits[256] = { 81e5acf9c8SMiquel Raynal 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 82e5acf9c8SMiquel Raynal 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 83e5acf9c8SMiquel Raynal 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 84e5acf9c8SMiquel Raynal 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 85e5acf9c8SMiquel Raynal 0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05, 86e5acf9c8SMiquel Raynal 0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07, 87e5acf9c8SMiquel Raynal 0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05, 88e5acf9c8SMiquel Raynal 0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07, 89e5acf9c8SMiquel Raynal 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 90e5acf9c8SMiquel Raynal 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 91e5acf9c8SMiquel Raynal 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 92e5acf9c8SMiquel Raynal 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 93e5acf9c8SMiquel Raynal 0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05, 94e5acf9c8SMiquel Raynal 0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07, 95e5acf9c8SMiquel Raynal 0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05, 96e5acf9c8SMiquel Raynal 0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07, 97e5acf9c8SMiquel Raynal 0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09, 98e5acf9c8SMiquel Raynal 0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b, 99e5acf9c8SMiquel Raynal 0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09, 100e5acf9c8SMiquel Raynal 0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b, 101e5acf9c8SMiquel Raynal 0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d, 102e5acf9c8SMiquel Raynal 0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f, 103e5acf9c8SMiquel Raynal 0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d, 104e5acf9c8SMiquel Raynal 0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f, 105e5acf9c8SMiquel Raynal 0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09, 106e5acf9c8SMiquel Raynal 0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b, 107e5acf9c8SMiquel Raynal 0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09, 108e5acf9c8SMiquel Raynal 0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b, 109e5acf9c8SMiquel Raynal 0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d, 110e5acf9c8SMiquel Raynal 0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f, 111e5acf9c8SMiquel Raynal 0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d, 112e5acf9c8SMiquel Raynal 0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f 113e5acf9c8SMiquel Raynal }; 114e5acf9c8SMiquel Raynal 115e5acf9c8SMiquel Raynal void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize, 116e5acf9c8SMiquel Raynal unsigned char *code, bool sm_order) 117e5acf9c8SMiquel Raynal { 118e5acf9c8SMiquel Raynal int i; 119e5acf9c8SMiquel Raynal const uint32_t *bp = (uint32_t *)buf; 120e5acf9c8SMiquel Raynal /* 256 or 512 bytes/ecc */ 121e5acf9c8SMiquel Raynal const uint32_t eccsize_mult = eccsize >> 8; 122e5acf9c8SMiquel Raynal uint32_t cur; /* current value in buffer */ 123e5acf9c8SMiquel Raynal /* rp0..rp15..rp17 are the various accumulated parities (per byte) */ 124e5acf9c8SMiquel Raynal uint32_t rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7; 125e5acf9c8SMiquel Raynal uint32_t rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15, rp16; 126e5acf9c8SMiquel Raynal uint32_t rp17; 127e5acf9c8SMiquel Raynal uint32_t par; /* the cumulative parity for all data */ 128e5acf9c8SMiquel Raynal uint32_t tmppar; /* the cumulative parity for this iteration; 129e5acf9c8SMiquel Raynal for rp12, rp14 and rp16 at the end of the 130e5acf9c8SMiquel Raynal loop */ 131e5acf9c8SMiquel Raynal 132e5acf9c8SMiquel Raynal par = 0; 133e5acf9c8SMiquel Raynal rp4 = 0; 134e5acf9c8SMiquel Raynal rp6 = 0; 135e5acf9c8SMiquel Raynal rp8 = 0; 136e5acf9c8SMiquel Raynal rp10 = 0; 137e5acf9c8SMiquel Raynal rp12 = 0; 138e5acf9c8SMiquel Raynal rp14 = 0; 139e5acf9c8SMiquel Raynal rp16 = 0; 140e5acf9c8SMiquel Raynal 141e5acf9c8SMiquel Raynal /* 142e5acf9c8SMiquel Raynal * The loop is unrolled a number of times; 143e5acf9c8SMiquel Raynal * This avoids if statements to decide on which rp value to update 144e5acf9c8SMiquel Raynal * Also we process the data by longwords. 145e5acf9c8SMiquel Raynal * Note: passing unaligned data might give a performance penalty. 146e5acf9c8SMiquel Raynal * It is assumed that the buffers are aligned. 147e5acf9c8SMiquel Raynal * tmppar is the cumulative sum of this iteration. 148e5acf9c8SMiquel Raynal * needed for calculating rp12, rp14, rp16 and par 149e5acf9c8SMiquel Raynal * also used as a performance improvement for rp6, rp8 and rp10 150e5acf9c8SMiquel Raynal */ 151e5acf9c8SMiquel Raynal for (i = 0; i < eccsize_mult << 2; i++) { 152e5acf9c8SMiquel Raynal cur = *bp++; 153e5acf9c8SMiquel Raynal tmppar = cur; 154e5acf9c8SMiquel Raynal rp4 ^= cur; 155e5acf9c8SMiquel Raynal cur = *bp++; 156e5acf9c8SMiquel Raynal tmppar ^= cur; 157e5acf9c8SMiquel Raynal rp6 ^= tmppar; 158e5acf9c8SMiquel Raynal cur = *bp++; 159e5acf9c8SMiquel Raynal tmppar ^= cur; 160e5acf9c8SMiquel Raynal rp4 ^= cur; 161e5acf9c8SMiquel Raynal cur = *bp++; 162e5acf9c8SMiquel Raynal tmppar ^= cur; 163e5acf9c8SMiquel Raynal rp8 ^= tmppar; 164e5acf9c8SMiquel Raynal 165e5acf9c8SMiquel Raynal cur = *bp++; 166e5acf9c8SMiquel Raynal tmppar ^= cur; 167e5acf9c8SMiquel Raynal rp4 ^= cur; 168e5acf9c8SMiquel Raynal rp6 ^= cur; 169e5acf9c8SMiquel Raynal cur = *bp++; 170e5acf9c8SMiquel Raynal tmppar ^= cur; 171e5acf9c8SMiquel Raynal rp6 ^= cur; 172e5acf9c8SMiquel Raynal cur = *bp++; 173e5acf9c8SMiquel Raynal tmppar ^= cur; 174e5acf9c8SMiquel Raynal rp4 ^= cur; 175e5acf9c8SMiquel Raynal cur = *bp++; 176e5acf9c8SMiquel Raynal tmppar ^= cur; 177e5acf9c8SMiquel Raynal rp10 ^= tmppar; 178e5acf9c8SMiquel Raynal 179e5acf9c8SMiquel Raynal cur = *bp++; 180e5acf9c8SMiquel Raynal tmppar ^= cur; 181e5acf9c8SMiquel Raynal rp4 ^= cur; 182e5acf9c8SMiquel Raynal rp6 ^= cur; 183e5acf9c8SMiquel Raynal rp8 ^= cur; 184e5acf9c8SMiquel Raynal cur = *bp++; 185e5acf9c8SMiquel Raynal tmppar ^= cur; 186e5acf9c8SMiquel Raynal rp6 ^= cur; 187e5acf9c8SMiquel Raynal rp8 ^= cur; 188e5acf9c8SMiquel Raynal cur = *bp++; 189e5acf9c8SMiquel Raynal tmppar ^= cur; 190e5acf9c8SMiquel Raynal rp4 ^= cur; 191e5acf9c8SMiquel Raynal rp8 ^= cur; 192e5acf9c8SMiquel Raynal cur = *bp++; 193e5acf9c8SMiquel Raynal tmppar ^= cur; 194e5acf9c8SMiquel Raynal rp8 ^= cur; 195e5acf9c8SMiquel Raynal 196e5acf9c8SMiquel Raynal cur = *bp++; 197e5acf9c8SMiquel Raynal tmppar ^= cur; 198e5acf9c8SMiquel Raynal rp4 ^= cur; 199e5acf9c8SMiquel Raynal rp6 ^= cur; 200e5acf9c8SMiquel Raynal cur = *bp++; 201e5acf9c8SMiquel Raynal tmppar ^= cur; 202e5acf9c8SMiquel Raynal rp6 ^= cur; 203e5acf9c8SMiquel Raynal cur = *bp++; 204e5acf9c8SMiquel Raynal tmppar ^= cur; 205e5acf9c8SMiquel Raynal rp4 ^= cur; 206e5acf9c8SMiquel Raynal cur = *bp++; 207e5acf9c8SMiquel Raynal tmppar ^= cur; 208e5acf9c8SMiquel Raynal 209e5acf9c8SMiquel Raynal par ^= tmppar; 210e5acf9c8SMiquel Raynal if ((i & 0x1) == 0) 211e5acf9c8SMiquel Raynal rp12 ^= tmppar; 212e5acf9c8SMiquel Raynal if ((i & 0x2) == 0) 213e5acf9c8SMiquel Raynal rp14 ^= tmppar; 214e5acf9c8SMiquel Raynal if (eccsize_mult == 2 && (i & 0x4) == 0) 215e5acf9c8SMiquel Raynal rp16 ^= tmppar; 216e5acf9c8SMiquel Raynal } 217e5acf9c8SMiquel Raynal 218e5acf9c8SMiquel Raynal /* 219e5acf9c8SMiquel Raynal * handle the fact that we use longword operations 220e5acf9c8SMiquel Raynal * we'll bring rp4..rp14..rp16 back to single byte entities by 221e5acf9c8SMiquel Raynal * shifting and xoring first fold the upper and lower 16 bits, 222e5acf9c8SMiquel Raynal * then the upper and lower 8 bits. 223e5acf9c8SMiquel Raynal */ 224e5acf9c8SMiquel Raynal rp4 ^= (rp4 >> 16); 225e5acf9c8SMiquel Raynal rp4 ^= (rp4 >> 8); 226e5acf9c8SMiquel Raynal rp4 &= 0xff; 227e5acf9c8SMiquel Raynal rp6 ^= (rp6 >> 16); 228e5acf9c8SMiquel Raynal rp6 ^= (rp6 >> 8); 229e5acf9c8SMiquel Raynal rp6 &= 0xff; 230e5acf9c8SMiquel Raynal rp8 ^= (rp8 >> 16); 231e5acf9c8SMiquel Raynal rp8 ^= (rp8 >> 8); 232e5acf9c8SMiquel Raynal rp8 &= 0xff; 233e5acf9c8SMiquel Raynal rp10 ^= (rp10 >> 16); 234e5acf9c8SMiquel Raynal rp10 ^= (rp10 >> 8); 235e5acf9c8SMiquel Raynal rp10 &= 0xff; 236e5acf9c8SMiquel Raynal rp12 ^= (rp12 >> 16); 237e5acf9c8SMiquel Raynal rp12 ^= (rp12 >> 8); 238e5acf9c8SMiquel Raynal rp12 &= 0xff; 239e5acf9c8SMiquel Raynal rp14 ^= (rp14 >> 16); 240e5acf9c8SMiquel Raynal rp14 ^= (rp14 >> 8); 241e5acf9c8SMiquel Raynal rp14 &= 0xff; 242e5acf9c8SMiquel Raynal if (eccsize_mult == 2) { 243e5acf9c8SMiquel Raynal rp16 ^= (rp16 >> 16); 244e5acf9c8SMiquel Raynal rp16 ^= (rp16 >> 8); 245e5acf9c8SMiquel Raynal rp16 &= 0xff; 246e5acf9c8SMiquel Raynal } 247e5acf9c8SMiquel Raynal 248e5acf9c8SMiquel Raynal /* 249e5acf9c8SMiquel Raynal * we also need to calculate the row parity for rp0..rp3 250e5acf9c8SMiquel Raynal * This is present in par, because par is now 251e5acf9c8SMiquel Raynal * rp3 rp3 rp2 rp2 in little endian and 252e5acf9c8SMiquel Raynal * rp2 rp2 rp3 rp3 in big endian 253e5acf9c8SMiquel Raynal * as well as 254e5acf9c8SMiquel Raynal * rp1 rp0 rp1 rp0 in little endian and 255e5acf9c8SMiquel Raynal * rp0 rp1 rp0 rp1 in big endian 256e5acf9c8SMiquel Raynal * First calculate rp2 and rp3 257e5acf9c8SMiquel Raynal */ 258e5acf9c8SMiquel Raynal #ifdef __BIG_ENDIAN 259e5acf9c8SMiquel Raynal rp2 = (par >> 16); 260e5acf9c8SMiquel Raynal rp2 ^= (rp2 >> 8); 261e5acf9c8SMiquel Raynal rp2 &= 0xff; 262e5acf9c8SMiquel Raynal rp3 = par & 0xffff; 263e5acf9c8SMiquel Raynal rp3 ^= (rp3 >> 8); 264e5acf9c8SMiquel Raynal rp3 &= 0xff; 265e5acf9c8SMiquel Raynal #else 266e5acf9c8SMiquel Raynal rp3 = (par >> 16); 267e5acf9c8SMiquel Raynal rp3 ^= (rp3 >> 8); 268e5acf9c8SMiquel Raynal rp3 &= 0xff; 269e5acf9c8SMiquel Raynal rp2 = par & 0xffff; 270e5acf9c8SMiquel Raynal rp2 ^= (rp2 >> 8); 271e5acf9c8SMiquel Raynal rp2 &= 0xff; 272e5acf9c8SMiquel Raynal #endif 273e5acf9c8SMiquel Raynal 274e5acf9c8SMiquel Raynal /* reduce par to 16 bits then calculate rp1 and rp0 */ 275e5acf9c8SMiquel Raynal par ^= (par >> 16); 276e5acf9c8SMiquel Raynal #ifdef __BIG_ENDIAN 277e5acf9c8SMiquel Raynal rp0 = (par >> 8) & 0xff; 278e5acf9c8SMiquel Raynal rp1 = (par & 0xff); 279e5acf9c8SMiquel Raynal #else 280e5acf9c8SMiquel Raynal rp1 = (par >> 8) & 0xff; 281e5acf9c8SMiquel Raynal rp0 = (par & 0xff); 282e5acf9c8SMiquel Raynal #endif 283e5acf9c8SMiquel Raynal 284e5acf9c8SMiquel Raynal /* finally reduce par to 8 bits */ 285e5acf9c8SMiquel Raynal par ^= (par >> 8); 286e5acf9c8SMiquel Raynal par &= 0xff; 287e5acf9c8SMiquel Raynal 288e5acf9c8SMiquel Raynal /* 289e5acf9c8SMiquel Raynal * and calculate rp5..rp15..rp17 290e5acf9c8SMiquel Raynal * note that par = rp4 ^ rp5 and due to the commutative property 291e5acf9c8SMiquel Raynal * of the ^ operator we can say: 292e5acf9c8SMiquel Raynal * rp5 = (par ^ rp4); 293e5acf9c8SMiquel Raynal * The & 0xff seems superfluous, but benchmarking learned that 294e5acf9c8SMiquel Raynal * leaving it out gives slightly worse results. No idea why, probably 295e5acf9c8SMiquel Raynal * it has to do with the way the pipeline in pentium is organized. 296e5acf9c8SMiquel Raynal */ 297e5acf9c8SMiquel Raynal rp5 = (par ^ rp4) & 0xff; 298e5acf9c8SMiquel Raynal rp7 = (par ^ rp6) & 0xff; 299e5acf9c8SMiquel Raynal rp9 = (par ^ rp8) & 0xff; 300e5acf9c8SMiquel Raynal rp11 = (par ^ rp10) & 0xff; 301e5acf9c8SMiquel Raynal rp13 = (par ^ rp12) & 0xff; 302e5acf9c8SMiquel Raynal rp15 = (par ^ rp14) & 0xff; 303e5acf9c8SMiquel Raynal if (eccsize_mult == 2) 304e5acf9c8SMiquel Raynal rp17 = (par ^ rp16) & 0xff; 305e5acf9c8SMiquel Raynal 306e5acf9c8SMiquel Raynal /* 307e5acf9c8SMiquel Raynal * Finally calculate the ECC bits. 308e5acf9c8SMiquel Raynal * Again here it might seem that there are performance optimisations 309e5acf9c8SMiquel Raynal * possible, but benchmarks showed that on the system this is developed 310e5acf9c8SMiquel Raynal * the code below is the fastest 311e5acf9c8SMiquel Raynal */ 312e5acf9c8SMiquel Raynal if (sm_order) { 313e5acf9c8SMiquel Raynal code[0] = (invparity[rp7] << 7) | (invparity[rp6] << 6) | 314e5acf9c8SMiquel Raynal (invparity[rp5] << 5) | (invparity[rp4] << 4) | 315e5acf9c8SMiquel Raynal (invparity[rp3] << 3) | (invparity[rp2] << 2) | 316e5acf9c8SMiquel Raynal (invparity[rp1] << 1) | (invparity[rp0]); 317e5acf9c8SMiquel Raynal code[1] = (invparity[rp15] << 7) | (invparity[rp14] << 6) | 318e5acf9c8SMiquel Raynal (invparity[rp13] << 5) | (invparity[rp12] << 4) | 319e5acf9c8SMiquel Raynal (invparity[rp11] << 3) | (invparity[rp10] << 2) | 320e5acf9c8SMiquel Raynal (invparity[rp9] << 1) | (invparity[rp8]); 321e5acf9c8SMiquel Raynal } else { 322e5acf9c8SMiquel Raynal code[1] = (invparity[rp7] << 7) | (invparity[rp6] << 6) | 323e5acf9c8SMiquel Raynal (invparity[rp5] << 5) | (invparity[rp4] << 4) | 324e5acf9c8SMiquel Raynal (invparity[rp3] << 3) | (invparity[rp2] << 2) | 325e5acf9c8SMiquel Raynal (invparity[rp1] << 1) | (invparity[rp0]); 326e5acf9c8SMiquel Raynal code[0] = (invparity[rp15] << 7) | (invparity[rp14] << 6) | 327e5acf9c8SMiquel Raynal (invparity[rp13] << 5) | (invparity[rp12] << 4) | 328e5acf9c8SMiquel Raynal (invparity[rp11] << 3) | (invparity[rp10] << 2) | 329e5acf9c8SMiquel Raynal (invparity[rp9] << 1) | (invparity[rp8]); 330e5acf9c8SMiquel Raynal } 331e5acf9c8SMiquel Raynal 332e5acf9c8SMiquel Raynal if (eccsize_mult == 1) 333e5acf9c8SMiquel Raynal code[2] = 334e5acf9c8SMiquel Raynal (invparity[par & 0xf0] << 7) | 335e5acf9c8SMiquel Raynal (invparity[par & 0x0f] << 6) | 336e5acf9c8SMiquel Raynal (invparity[par & 0xcc] << 5) | 337e5acf9c8SMiquel Raynal (invparity[par & 0x33] << 4) | 338e5acf9c8SMiquel Raynal (invparity[par & 0xaa] << 3) | 339e5acf9c8SMiquel Raynal (invparity[par & 0x55] << 2) | 340e5acf9c8SMiquel Raynal 3; 341e5acf9c8SMiquel Raynal else 342e5acf9c8SMiquel Raynal code[2] = 343e5acf9c8SMiquel Raynal (invparity[par & 0xf0] << 7) | 344e5acf9c8SMiquel Raynal (invparity[par & 0x0f] << 6) | 345e5acf9c8SMiquel Raynal (invparity[par & 0xcc] << 5) | 346e5acf9c8SMiquel Raynal (invparity[par & 0x33] << 4) | 347e5acf9c8SMiquel Raynal (invparity[par & 0xaa] << 3) | 348e5acf9c8SMiquel Raynal (invparity[par & 0x55] << 2) | 349e5acf9c8SMiquel Raynal (invparity[rp17] << 1) | 350e5acf9c8SMiquel Raynal (invparity[rp16] << 0); 351e5acf9c8SMiquel Raynal } 352e5acf9c8SMiquel Raynal EXPORT_SYMBOL(__nand_calculate_ecc); 353e5acf9c8SMiquel Raynal 354e5acf9c8SMiquel Raynal /** 355*c50e7f3cSMiquel Raynal * nand_calculate_ecc - Calculate 3-byte ECC for 256/512-byte block 356e5acf9c8SMiquel Raynal * @chip: NAND chip object 357*c50e7f3cSMiquel Raynal * @buf: Input buffer with raw data 358*c50e7f3cSMiquel Raynal * @code: Output buffer with ECC 359e5acf9c8SMiquel Raynal */ 360e5acf9c8SMiquel Raynal int nand_calculate_ecc(struct nand_chip *chip, const unsigned char *buf, 361e5acf9c8SMiquel Raynal unsigned char *code) 362e5acf9c8SMiquel Raynal { 363e5acf9c8SMiquel Raynal bool sm_order = chip->ecc.options & NAND_ECC_SOFT_HAMMING_SM_ORDER; 364e5acf9c8SMiquel Raynal 365e5acf9c8SMiquel Raynal __nand_calculate_ecc(buf, chip->ecc.size, code, sm_order); 366e5acf9c8SMiquel Raynal 367e5acf9c8SMiquel Raynal return 0; 368e5acf9c8SMiquel Raynal } 369e5acf9c8SMiquel Raynal EXPORT_SYMBOL(nand_calculate_ecc); 370e5acf9c8SMiquel Raynal 371e5acf9c8SMiquel Raynal int __nand_correct_data(unsigned char *buf, 372e5acf9c8SMiquel Raynal unsigned char *read_ecc, unsigned char *calc_ecc, 373e5acf9c8SMiquel Raynal unsigned int eccsize, bool sm_order) 374e5acf9c8SMiquel Raynal { 375e5acf9c8SMiquel Raynal unsigned char b0, b1, b2, bit_addr; 376e5acf9c8SMiquel Raynal unsigned int byte_addr; 377e5acf9c8SMiquel Raynal /* 256 or 512 bytes/ecc */ 378e5acf9c8SMiquel Raynal const uint32_t eccsize_mult = eccsize >> 8; 379e5acf9c8SMiquel Raynal 380e5acf9c8SMiquel Raynal /* 381e5acf9c8SMiquel Raynal * b0 to b2 indicate which bit is faulty (if any) 382e5acf9c8SMiquel Raynal * we might need the xor result more than once, 383e5acf9c8SMiquel Raynal * so keep them in a local var 384e5acf9c8SMiquel Raynal */ 385e5acf9c8SMiquel Raynal if (sm_order) { 386e5acf9c8SMiquel Raynal b0 = read_ecc[0] ^ calc_ecc[0]; 387e5acf9c8SMiquel Raynal b1 = read_ecc[1] ^ calc_ecc[1]; 388e5acf9c8SMiquel Raynal } else { 389e5acf9c8SMiquel Raynal b0 = read_ecc[1] ^ calc_ecc[1]; 390e5acf9c8SMiquel Raynal b1 = read_ecc[0] ^ calc_ecc[0]; 391e5acf9c8SMiquel Raynal } 392e5acf9c8SMiquel Raynal 393e5acf9c8SMiquel Raynal b2 = read_ecc[2] ^ calc_ecc[2]; 394e5acf9c8SMiquel Raynal 395e5acf9c8SMiquel Raynal /* check if there are any bitfaults */ 396e5acf9c8SMiquel Raynal 397e5acf9c8SMiquel Raynal /* repeated if statements are slightly more efficient than switch ... */ 398e5acf9c8SMiquel Raynal /* ordered in order of likelihood */ 399e5acf9c8SMiquel Raynal 400e5acf9c8SMiquel Raynal if ((b0 | b1 | b2) == 0) 401e5acf9c8SMiquel Raynal return 0; /* no error */ 402e5acf9c8SMiquel Raynal 403e5acf9c8SMiquel Raynal if ((((b0 ^ (b0 >> 1)) & 0x55) == 0x55) && 404e5acf9c8SMiquel Raynal (((b1 ^ (b1 >> 1)) & 0x55) == 0x55) && 405e5acf9c8SMiquel Raynal ((eccsize_mult == 1 && ((b2 ^ (b2 >> 1)) & 0x54) == 0x54) || 406e5acf9c8SMiquel Raynal (eccsize_mult == 2 && ((b2 ^ (b2 >> 1)) & 0x55) == 0x55))) { 407e5acf9c8SMiquel Raynal /* single bit error */ 408e5acf9c8SMiquel Raynal /* 409e5acf9c8SMiquel Raynal * rp17/rp15/13/11/9/7/5/3/1 indicate which byte is the faulty 410e5acf9c8SMiquel Raynal * byte, cp 5/3/1 indicate the faulty bit. 411e5acf9c8SMiquel Raynal * A lookup table (called addressbits) is used to filter 412e5acf9c8SMiquel Raynal * the bits from the byte they are in. 413e5acf9c8SMiquel Raynal * A marginal optimisation is possible by having three 414e5acf9c8SMiquel Raynal * different lookup tables. 415e5acf9c8SMiquel Raynal * One as we have now (for b0), one for b2 416e5acf9c8SMiquel Raynal * (that would avoid the >> 1), and one for b1 (with all values 417e5acf9c8SMiquel Raynal * << 4). However it was felt that introducing two more tables 418e5acf9c8SMiquel Raynal * hardly justify the gain. 419e5acf9c8SMiquel Raynal * 420e5acf9c8SMiquel Raynal * The b2 shift is there to get rid of the lowest two bits. 421e5acf9c8SMiquel Raynal * We could also do addressbits[b2] >> 1 but for the 422e5acf9c8SMiquel Raynal * performance it does not make any difference 423e5acf9c8SMiquel Raynal */ 424e5acf9c8SMiquel Raynal if (eccsize_mult == 1) 425e5acf9c8SMiquel Raynal byte_addr = (addressbits[b1] << 4) + addressbits[b0]; 426e5acf9c8SMiquel Raynal else 427e5acf9c8SMiquel Raynal byte_addr = (addressbits[b2 & 0x3] << 8) + 428e5acf9c8SMiquel Raynal (addressbits[b1] << 4) + addressbits[b0]; 429e5acf9c8SMiquel Raynal bit_addr = addressbits[b2 >> 2]; 430e5acf9c8SMiquel Raynal /* flip the bit */ 431e5acf9c8SMiquel Raynal buf[byte_addr] ^= (1 << bit_addr); 432e5acf9c8SMiquel Raynal return 1; 433e5acf9c8SMiquel Raynal 434e5acf9c8SMiquel Raynal } 435e5acf9c8SMiquel Raynal /* count nr of bits; use table lookup, faster than calculating it */ 436e5acf9c8SMiquel Raynal if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1) 437e5acf9c8SMiquel Raynal return 1; /* error in ECC data; no action needed */ 438e5acf9c8SMiquel Raynal 439e5acf9c8SMiquel Raynal pr_err("%s: uncorrectable ECC error\n", __func__); 440e5acf9c8SMiquel Raynal return -EBADMSG; 441e5acf9c8SMiquel Raynal } 442e5acf9c8SMiquel Raynal EXPORT_SYMBOL(__nand_correct_data); 443e5acf9c8SMiquel Raynal 444e5acf9c8SMiquel Raynal /** 445*c50e7f3cSMiquel Raynal * nand_correct_data - Detect and correct bit error(s) 446e5acf9c8SMiquel Raynal * @chip: NAND chip object 447*c50e7f3cSMiquel Raynal * @buf: Raw data read from the chip 448*c50e7f3cSMiquel Raynal * @read_ecc: ECC bytes read from the chip 449*c50e7f3cSMiquel Raynal * @calc_ecc: ECC calculated from the raw data 450e5acf9c8SMiquel Raynal * 451*c50e7f3cSMiquel Raynal * Detect and correct up to 1 bit error per 256/512-byte block. 452e5acf9c8SMiquel Raynal */ 453e5acf9c8SMiquel Raynal int nand_correct_data(struct nand_chip *chip, unsigned char *buf, 454e5acf9c8SMiquel Raynal unsigned char *read_ecc, unsigned char *calc_ecc) 455e5acf9c8SMiquel Raynal { 456e5acf9c8SMiquel Raynal bool sm_order = chip->ecc.options & NAND_ECC_SOFT_HAMMING_SM_ORDER; 457e5acf9c8SMiquel Raynal 458e5acf9c8SMiquel Raynal return __nand_correct_data(buf, read_ecc, calc_ecc, chip->ecc.size, 459e5acf9c8SMiquel Raynal sm_order); 460e5acf9c8SMiquel Raynal } 461e5acf9c8SMiquel Raynal EXPORT_SYMBOL(nand_correct_data); 462e5acf9c8SMiquel Raynal 463e5acf9c8SMiquel Raynal MODULE_LICENSE("GPL"); 464e5acf9c8SMiquel Raynal MODULE_AUTHOR("Frans Meulenbroeks <fransmeulenbroeks@gmail.com>"); 4652dbe0192SMiquel Raynal MODULE_DESCRIPTION("NAND software Hamming ECC support"); 466