xref: /linux/drivers/mtd/nand/ecc-sw-hamming.c (revision c50e7f3c86730c7de00209542899795199a4066c)
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