18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * This file contains an ECC algorithm that detects and corrects 1 bit
48c2ecf20Sopenharmony_ci * errors in a 256 byte block of data.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Copyright © 2008 Koninklijke Philips Electronics NV.
78c2ecf20Sopenharmony_ci *                  Author: Frans Meulenbroeks
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Completely replaces the previous ECC implementation which was written by:
108c2ecf20Sopenharmony_ci *   Steven J. Hill (sjhill@realitydiluted.com)
118c2ecf20Sopenharmony_ci *   Thomas Gleixner (tglx@linutronix.de)
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * Information on how this algorithm works and how it was developed
148c2ecf20Sopenharmony_ci * can be found in Documentation/driver-api/mtd/nand_ecc.rst
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include <linux/types.h>
188c2ecf20Sopenharmony_ci#include <linux/kernel.h>
198c2ecf20Sopenharmony_ci#include <linux/module.h>
208c2ecf20Sopenharmony_ci#include <linux/mtd/mtd.h>
218c2ecf20Sopenharmony_ci#include <linux/mtd/rawnand.h>
228c2ecf20Sopenharmony_ci#include <linux/mtd/nand_ecc.h>
238c2ecf20Sopenharmony_ci#include <asm/byteorder.h>
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci/*
268c2ecf20Sopenharmony_ci * invparity is a 256 byte table that contains the odd parity
278c2ecf20Sopenharmony_ci * for each byte. So if the number of bits in a byte is even,
288c2ecf20Sopenharmony_ci * the array element is 1, and when the number of bits is odd
298c2ecf20Sopenharmony_ci * the array eleemnt is 0.
308c2ecf20Sopenharmony_ci */
318c2ecf20Sopenharmony_cistatic const char invparity[256] = {
328c2ecf20Sopenharmony_ci	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
338c2ecf20Sopenharmony_ci	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
348c2ecf20Sopenharmony_ci	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
358c2ecf20Sopenharmony_ci	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
368c2ecf20Sopenharmony_ci	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
378c2ecf20Sopenharmony_ci	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
388c2ecf20Sopenharmony_ci	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
398c2ecf20Sopenharmony_ci	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
408c2ecf20Sopenharmony_ci	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
418c2ecf20Sopenharmony_ci	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
428c2ecf20Sopenharmony_ci	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
438c2ecf20Sopenharmony_ci	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
448c2ecf20Sopenharmony_ci	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
458c2ecf20Sopenharmony_ci	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
468c2ecf20Sopenharmony_ci	0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
478c2ecf20Sopenharmony_ci	1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
488c2ecf20Sopenharmony_ci};
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci/*
518c2ecf20Sopenharmony_ci * bitsperbyte contains the number of bits per byte
528c2ecf20Sopenharmony_ci * this is only used for testing and repairing parity
538c2ecf20Sopenharmony_ci * (a precalculated value slightly improves performance)
548c2ecf20Sopenharmony_ci */
558c2ecf20Sopenharmony_cistatic const char bitsperbyte[256] = {
568c2ecf20Sopenharmony_ci	0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
578c2ecf20Sopenharmony_ci	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
588c2ecf20Sopenharmony_ci	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
598c2ecf20Sopenharmony_ci	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
608c2ecf20Sopenharmony_ci	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
618c2ecf20Sopenharmony_ci	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
628c2ecf20Sopenharmony_ci	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
638c2ecf20Sopenharmony_ci	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
648c2ecf20Sopenharmony_ci	1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
658c2ecf20Sopenharmony_ci	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
668c2ecf20Sopenharmony_ci	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
678c2ecf20Sopenharmony_ci	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
688c2ecf20Sopenharmony_ci	2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
698c2ecf20Sopenharmony_ci	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
708c2ecf20Sopenharmony_ci	3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
718c2ecf20Sopenharmony_ci	4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8,
728c2ecf20Sopenharmony_ci};
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci/*
758c2ecf20Sopenharmony_ci * addressbits is a lookup table to filter out the bits from the xor-ed
768c2ecf20Sopenharmony_ci * ECC data that identify the faulty location.
778c2ecf20Sopenharmony_ci * this is only used for repairing parity
788c2ecf20Sopenharmony_ci * see the comments in nand_correct_data for more details
798c2ecf20Sopenharmony_ci */
808c2ecf20Sopenharmony_cistatic const char addressbits[256] = {
818c2ecf20Sopenharmony_ci	0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
828c2ecf20Sopenharmony_ci	0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03,
838c2ecf20Sopenharmony_ci	0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
848c2ecf20Sopenharmony_ci	0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03,
858c2ecf20Sopenharmony_ci	0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05,
868c2ecf20Sopenharmony_ci	0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07,
878c2ecf20Sopenharmony_ci	0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05,
888c2ecf20Sopenharmony_ci	0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07,
898c2ecf20Sopenharmony_ci	0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
908c2ecf20Sopenharmony_ci	0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03,
918c2ecf20Sopenharmony_ci	0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
928c2ecf20Sopenharmony_ci	0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03,
938c2ecf20Sopenharmony_ci	0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05,
948c2ecf20Sopenharmony_ci	0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07,
958c2ecf20Sopenharmony_ci	0x04, 0x04, 0x05, 0x05, 0x04, 0x04, 0x05, 0x05,
968c2ecf20Sopenharmony_ci	0x06, 0x06, 0x07, 0x07, 0x06, 0x06, 0x07, 0x07,
978c2ecf20Sopenharmony_ci	0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09,
988c2ecf20Sopenharmony_ci	0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b,
998c2ecf20Sopenharmony_ci	0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09,
1008c2ecf20Sopenharmony_ci	0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b,
1018c2ecf20Sopenharmony_ci	0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d,
1028c2ecf20Sopenharmony_ci	0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f,
1038c2ecf20Sopenharmony_ci	0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d,
1048c2ecf20Sopenharmony_ci	0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f,
1058c2ecf20Sopenharmony_ci	0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09,
1068c2ecf20Sopenharmony_ci	0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b,
1078c2ecf20Sopenharmony_ci	0x08, 0x08, 0x09, 0x09, 0x08, 0x08, 0x09, 0x09,
1088c2ecf20Sopenharmony_ci	0x0a, 0x0a, 0x0b, 0x0b, 0x0a, 0x0a, 0x0b, 0x0b,
1098c2ecf20Sopenharmony_ci	0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d,
1108c2ecf20Sopenharmony_ci	0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f,
1118c2ecf20Sopenharmony_ci	0x0c, 0x0c, 0x0d, 0x0d, 0x0c, 0x0c, 0x0d, 0x0d,
1128c2ecf20Sopenharmony_ci	0x0e, 0x0e, 0x0f, 0x0f, 0x0e, 0x0e, 0x0f, 0x0f
1138c2ecf20Sopenharmony_ci};
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci/**
1168c2ecf20Sopenharmony_ci * __nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte
1178c2ecf20Sopenharmony_ci *			 block
1188c2ecf20Sopenharmony_ci * @buf:	input buffer with raw data
1198c2ecf20Sopenharmony_ci * @eccsize:	data bytes per ECC step (256 or 512)
1208c2ecf20Sopenharmony_ci * @code:	output buffer with ECC
1218c2ecf20Sopenharmony_ci * @sm_order:	Smart Media byte ordering
1228c2ecf20Sopenharmony_ci */
1238c2ecf20Sopenharmony_civoid __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize,
1248c2ecf20Sopenharmony_ci			  unsigned char *code, bool sm_order)
1258c2ecf20Sopenharmony_ci{
1268c2ecf20Sopenharmony_ci	int i;
1278c2ecf20Sopenharmony_ci	const uint32_t *bp = (uint32_t *)buf;
1288c2ecf20Sopenharmony_ci	/* 256 or 512 bytes/ecc  */
1298c2ecf20Sopenharmony_ci	const uint32_t eccsize_mult = eccsize >> 8;
1308c2ecf20Sopenharmony_ci	uint32_t cur;		/* current value in buffer */
1318c2ecf20Sopenharmony_ci	/* rp0..rp15..rp17 are the various accumulated parities (per byte) */
1328c2ecf20Sopenharmony_ci	uint32_t rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7;
1338c2ecf20Sopenharmony_ci	uint32_t rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15, rp16;
1348c2ecf20Sopenharmony_ci	uint32_t rp17;
1358c2ecf20Sopenharmony_ci	uint32_t par;		/* the cumulative parity for all data */
1368c2ecf20Sopenharmony_ci	uint32_t tmppar;	/* the cumulative parity for this iteration;
1378c2ecf20Sopenharmony_ci				   for rp12, rp14 and rp16 at the end of the
1388c2ecf20Sopenharmony_ci				   loop */
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	par = 0;
1418c2ecf20Sopenharmony_ci	rp4 = 0;
1428c2ecf20Sopenharmony_ci	rp6 = 0;
1438c2ecf20Sopenharmony_ci	rp8 = 0;
1448c2ecf20Sopenharmony_ci	rp10 = 0;
1458c2ecf20Sopenharmony_ci	rp12 = 0;
1468c2ecf20Sopenharmony_ci	rp14 = 0;
1478c2ecf20Sopenharmony_ci	rp16 = 0;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	/*
1508c2ecf20Sopenharmony_ci	 * The loop is unrolled a number of times;
1518c2ecf20Sopenharmony_ci	 * This avoids if statements to decide on which rp value to update
1528c2ecf20Sopenharmony_ci	 * Also we process the data by longwords.
1538c2ecf20Sopenharmony_ci	 * Note: passing unaligned data might give a performance penalty.
1548c2ecf20Sopenharmony_ci	 * It is assumed that the buffers are aligned.
1558c2ecf20Sopenharmony_ci	 * tmppar is the cumulative sum of this iteration.
1568c2ecf20Sopenharmony_ci	 * needed for calculating rp12, rp14, rp16 and par
1578c2ecf20Sopenharmony_ci	 * also used as a performance improvement for rp6, rp8 and rp10
1588c2ecf20Sopenharmony_ci	 */
1598c2ecf20Sopenharmony_ci	for (i = 0; i < eccsize_mult << 2; i++) {
1608c2ecf20Sopenharmony_ci		cur = *bp++;
1618c2ecf20Sopenharmony_ci		tmppar = cur;
1628c2ecf20Sopenharmony_ci		rp4 ^= cur;
1638c2ecf20Sopenharmony_ci		cur = *bp++;
1648c2ecf20Sopenharmony_ci		tmppar ^= cur;
1658c2ecf20Sopenharmony_ci		rp6 ^= tmppar;
1668c2ecf20Sopenharmony_ci		cur = *bp++;
1678c2ecf20Sopenharmony_ci		tmppar ^= cur;
1688c2ecf20Sopenharmony_ci		rp4 ^= cur;
1698c2ecf20Sopenharmony_ci		cur = *bp++;
1708c2ecf20Sopenharmony_ci		tmppar ^= cur;
1718c2ecf20Sopenharmony_ci		rp8 ^= tmppar;
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci		cur = *bp++;
1748c2ecf20Sopenharmony_ci		tmppar ^= cur;
1758c2ecf20Sopenharmony_ci		rp4 ^= cur;
1768c2ecf20Sopenharmony_ci		rp6 ^= cur;
1778c2ecf20Sopenharmony_ci		cur = *bp++;
1788c2ecf20Sopenharmony_ci		tmppar ^= cur;
1798c2ecf20Sopenharmony_ci		rp6 ^= cur;
1808c2ecf20Sopenharmony_ci		cur = *bp++;
1818c2ecf20Sopenharmony_ci		tmppar ^= cur;
1828c2ecf20Sopenharmony_ci		rp4 ^= cur;
1838c2ecf20Sopenharmony_ci		cur = *bp++;
1848c2ecf20Sopenharmony_ci		tmppar ^= cur;
1858c2ecf20Sopenharmony_ci		rp10 ^= tmppar;
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci		cur = *bp++;
1888c2ecf20Sopenharmony_ci		tmppar ^= cur;
1898c2ecf20Sopenharmony_ci		rp4 ^= cur;
1908c2ecf20Sopenharmony_ci		rp6 ^= cur;
1918c2ecf20Sopenharmony_ci		rp8 ^= cur;
1928c2ecf20Sopenharmony_ci		cur = *bp++;
1938c2ecf20Sopenharmony_ci		tmppar ^= cur;
1948c2ecf20Sopenharmony_ci		rp6 ^= cur;
1958c2ecf20Sopenharmony_ci		rp8 ^= cur;
1968c2ecf20Sopenharmony_ci		cur = *bp++;
1978c2ecf20Sopenharmony_ci		tmppar ^= cur;
1988c2ecf20Sopenharmony_ci		rp4 ^= cur;
1998c2ecf20Sopenharmony_ci		rp8 ^= cur;
2008c2ecf20Sopenharmony_ci		cur = *bp++;
2018c2ecf20Sopenharmony_ci		tmppar ^= cur;
2028c2ecf20Sopenharmony_ci		rp8 ^= cur;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci		cur = *bp++;
2058c2ecf20Sopenharmony_ci		tmppar ^= cur;
2068c2ecf20Sopenharmony_ci		rp4 ^= cur;
2078c2ecf20Sopenharmony_ci		rp6 ^= cur;
2088c2ecf20Sopenharmony_ci		cur = *bp++;
2098c2ecf20Sopenharmony_ci		tmppar ^= cur;
2108c2ecf20Sopenharmony_ci		rp6 ^= cur;
2118c2ecf20Sopenharmony_ci		cur = *bp++;
2128c2ecf20Sopenharmony_ci		tmppar ^= cur;
2138c2ecf20Sopenharmony_ci		rp4 ^= cur;
2148c2ecf20Sopenharmony_ci		cur = *bp++;
2158c2ecf20Sopenharmony_ci		tmppar ^= cur;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci		par ^= tmppar;
2188c2ecf20Sopenharmony_ci		if ((i & 0x1) == 0)
2198c2ecf20Sopenharmony_ci			rp12 ^= tmppar;
2208c2ecf20Sopenharmony_ci		if ((i & 0x2) == 0)
2218c2ecf20Sopenharmony_ci			rp14 ^= tmppar;
2228c2ecf20Sopenharmony_ci		if (eccsize_mult == 2 && (i & 0x4) == 0)
2238c2ecf20Sopenharmony_ci			rp16 ^= tmppar;
2248c2ecf20Sopenharmony_ci	}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	/*
2278c2ecf20Sopenharmony_ci	 * handle the fact that we use longword operations
2288c2ecf20Sopenharmony_ci	 * we'll bring rp4..rp14..rp16 back to single byte entities by
2298c2ecf20Sopenharmony_ci	 * shifting and xoring first fold the upper and lower 16 bits,
2308c2ecf20Sopenharmony_ci	 * then the upper and lower 8 bits.
2318c2ecf20Sopenharmony_ci	 */
2328c2ecf20Sopenharmony_ci	rp4 ^= (rp4 >> 16);
2338c2ecf20Sopenharmony_ci	rp4 ^= (rp4 >> 8);
2348c2ecf20Sopenharmony_ci	rp4 &= 0xff;
2358c2ecf20Sopenharmony_ci	rp6 ^= (rp6 >> 16);
2368c2ecf20Sopenharmony_ci	rp6 ^= (rp6 >> 8);
2378c2ecf20Sopenharmony_ci	rp6 &= 0xff;
2388c2ecf20Sopenharmony_ci	rp8 ^= (rp8 >> 16);
2398c2ecf20Sopenharmony_ci	rp8 ^= (rp8 >> 8);
2408c2ecf20Sopenharmony_ci	rp8 &= 0xff;
2418c2ecf20Sopenharmony_ci	rp10 ^= (rp10 >> 16);
2428c2ecf20Sopenharmony_ci	rp10 ^= (rp10 >> 8);
2438c2ecf20Sopenharmony_ci	rp10 &= 0xff;
2448c2ecf20Sopenharmony_ci	rp12 ^= (rp12 >> 16);
2458c2ecf20Sopenharmony_ci	rp12 ^= (rp12 >> 8);
2468c2ecf20Sopenharmony_ci	rp12 &= 0xff;
2478c2ecf20Sopenharmony_ci	rp14 ^= (rp14 >> 16);
2488c2ecf20Sopenharmony_ci	rp14 ^= (rp14 >> 8);
2498c2ecf20Sopenharmony_ci	rp14 &= 0xff;
2508c2ecf20Sopenharmony_ci	if (eccsize_mult == 2) {
2518c2ecf20Sopenharmony_ci		rp16 ^= (rp16 >> 16);
2528c2ecf20Sopenharmony_ci		rp16 ^= (rp16 >> 8);
2538c2ecf20Sopenharmony_ci		rp16 &= 0xff;
2548c2ecf20Sopenharmony_ci	}
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	/*
2578c2ecf20Sopenharmony_ci	 * we also need to calculate the row parity for rp0..rp3
2588c2ecf20Sopenharmony_ci	 * This is present in par, because par is now
2598c2ecf20Sopenharmony_ci	 * rp3 rp3 rp2 rp2 in little endian and
2608c2ecf20Sopenharmony_ci	 * rp2 rp2 rp3 rp3 in big endian
2618c2ecf20Sopenharmony_ci	 * as well as
2628c2ecf20Sopenharmony_ci	 * rp1 rp0 rp1 rp0 in little endian and
2638c2ecf20Sopenharmony_ci	 * rp0 rp1 rp0 rp1 in big endian
2648c2ecf20Sopenharmony_ci	 * First calculate rp2 and rp3
2658c2ecf20Sopenharmony_ci	 */
2668c2ecf20Sopenharmony_ci#ifdef __BIG_ENDIAN
2678c2ecf20Sopenharmony_ci	rp2 = (par >> 16);
2688c2ecf20Sopenharmony_ci	rp2 ^= (rp2 >> 8);
2698c2ecf20Sopenharmony_ci	rp2 &= 0xff;
2708c2ecf20Sopenharmony_ci	rp3 = par & 0xffff;
2718c2ecf20Sopenharmony_ci	rp3 ^= (rp3 >> 8);
2728c2ecf20Sopenharmony_ci	rp3 &= 0xff;
2738c2ecf20Sopenharmony_ci#else
2748c2ecf20Sopenharmony_ci	rp3 = (par >> 16);
2758c2ecf20Sopenharmony_ci	rp3 ^= (rp3 >> 8);
2768c2ecf20Sopenharmony_ci	rp3 &= 0xff;
2778c2ecf20Sopenharmony_ci	rp2 = par & 0xffff;
2788c2ecf20Sopenharmony_ci	rp2 ^= (rp2 >> 8);
2798c2ecf20Sopenharmony_ci	rp2 &= 0xff;
2808c2ecf20Sopenharmony_ci#endif
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	/* reduce par to 16 bits then calculate rp1 and rp0 */
2838c2ecf20Sopenharmony_ci	par ^= (par >> 16);
2848c2ecf20Sopenharmony_ci#ifdef __BIG_ENDIAN
2858c2ecf20Sopenharmony_ci	rp0 = (par >> 8) & 0xff;
2868c2ecf20Sopenharmony_ci	rp1 = (par & 0xff);
2878c2ecf20Sopenharmony_ci#else
2888c2ecf20Sopenharmony_ci	rp1 = (par >> 8) & 0xff;
2898c2ecf20Sopenharmony_ci	rp0 = (par & 0xff);
2908c2ecf20Sopenharmony_ci#endif
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	/* finally reduce par to 8 bits */
2938c2ecf20Sopenharmony_ci	par ^= (par >> 8);
2948c2ecf20Sopenharmony_ci	par &= 0xff;
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	/*
2978c2ecf20Sopenharmony_ci	 * and calculate rp5..rp15..rp17
2988c2ecf20Sopenharmony_ci	 * note that par = rp4 ^ rp5 and due to the commutative property
2998c2ecf20Sopenharmony_ci	 * of the ^ operator we can say:
3008c2ecf20Sopenharmony_ci	 * rp5 = (par ^ rp4);
3018c2ecf20Sopenharmony_ci	 * The & 0xff seems superfluous, but benchmarking learned that
3028c2ecf20Sopenharmony_ci	 * leaving it out gives slightly worse results. No idea why, probably
3038c2ecf20Sopenharmony_ci	 * it has to do with the way the pipeline in pentium is organized.
3048c2ecf20Sopenharmony_ci	 */
3058c2ecf20Sopenharmony_ci	rp5 = (par ^ rp4) & 0xff;
3068c2ecf20Sopenharmony_ci	rp7 = (par ^ rp6) & 0xff;
3078c2ecf20Sopenharmony_ci	rp9 = (par ^ rp8) & 0xff;
3088c2ecf20Sopenharmony_ci	rp11 = (par ^ rp10) & 0xff;
3098c2ecf20Sopenharmony_ci	rp13 = (par ^ rp12) & 0xff;
3108c2ecf20Sopenharmony_ci	rp15 = (par ^ rp14) & 0xff;
3118c2ecf20Sopenharmony_ci	if (eccsize_mult == 2)
3128c2ecf20Sopenharmony_ci		rp17 = (par ^ rp16) & 0xff;
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	/*
3158c2ecf20Sopenharmony_ci	 * Finally calculate the ECC bits.
3168c2ecf20Sopenharmony_ci	 * Again here it might seem that there are performance optimisations
3178c2ecf20Sopenharmony_ci	 * possible, but benchmarks showed that on the system this is developed
3188c2ecf20Sopenharmony_ci	 * the code below is the fastest
3198c2ecf20Sopenharmony_ci	 */
3208c2ecf20Sopenharmony_ci	if (sm_order) {
3218c2ecf20Sopenharmony_ci		code[0] = (invparity[rp7] << 7) | (invparity[rp6] << 6) |
3228c2ecf20Sopenharmony_ci			  (invparity[rp5] << 5) | (invparity[rp4] << 4) |
3238c2ecf20Sopenharmony_ci			  (invparity[rp3] << 3) | (invparity[rp2] << 2) |
3248c2ecf20Sopenharmony_ci			  (invparity[rp1] << 1) | (invparity[rp0]);
3258c2ecf20Sopenharmony_ci		code[1] = (invparity[rp15] << 7) | (invparity[rp14] << 6) |
3268c2ecf20Sopenharmony_ci			  (invparity[rp13] << 5) | (invparity[rp12] << 4) |
3278c2ecf20Sopenharmony_ci			  (invparity[rp11] << 3) | (invparity[rp10] << 2) |
3288c2ecf20Sopenharmony_ci			  (invparity[rp9] << 1) | (invparity[rp8]);
3298c2ecf20Sopenharmony_ci	} else {
3308c2ecf20Sopenharmony_ci		code[1] = (invparity[rp7] << 7) | (invparity[rp6] << 6) |
3318c2ecf20Sopenharmony_ci			  (invparity[rp5] << 5) | (invparity[rp4] << 4) |
3328c2ecf20Sopenharmony_ci			  (invparity[rp3] << 3) | (invparity[rp2] << 2) |
3338c2ecf20Sopenharmony_ci			  (invparity[rp1] << 1) | (invparity[rp0]);
3348c2ecf20Sopenharmony_ci		code[0] = (invparity[rp15] << 7) | (invparity[rp14] << 6) |
3358c2ecf20Sopenharmony_ci			  (invparity[rp13] << 5) | (invparity[rp12] << 4) |
3368c2ecf20Sopenharmony_ci			  (invparity[rp11] << 3) | (invparity[rp10] << 2) |
3378c2ecf20Sopenharmony_ci			  (invparity[rp9] << 1) | (invparity[rp8]);
3388c2ecf20Sopenharmony_ci	}
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	if (eccsize_mult == 1)
3418c2ecf20Sopenharmony_ci		code[2] =
3428c2ecf20Sopenharmony_ci		    (invparity[par & 0xf0] << 7) |
3438c2ecf20Sopenharmony_ci		    (invparity[par & 0x0f] << 6) |
3448c2ecf20Sopenharmony_ci		    (invparity[par & 0xcc] << 5) |
3458c2ecf20Sopenharmony_ci		    (invparity[par & 0x33] << 4) |
3468c2ecf20Sopenharmony_ci		    (invparity[par & 0xaa] << 3) |
3478c2ecf20Sopenharmony_ci		    (invparity[par & 0x55] << 2) |
3488c2ecf20Sopenharmony_ci		    3;
3498c2ecf20Sopenharmony_ci	else
3508c2ecf20Sopenharmony_ci		code[2] =
3518c2ecf20Sopenharmony_ci		    (invparity[par & 0xf0] << 7) |
3528c2ecf20Sopenharmony_ci		    (invparity[par & 0x0f] << 6) |
3538c2ecf20Sopenharmony_ci		    (invparity[par & 0xcc] << 5) |
3548c2ecf20Sopenharmony_ci		    (invparity[par & 0x33] << 4) |
3558c2ecf20Sopenharmony_ci		    (invparity[par & 0xaa] << 3) |
3568c2ecf20Sopenharmony_ci		    (invparity[par & 0x55] << 2) |
3578c2ecf20Sopenharmony_ci		    (invparity[rp17] << 1) |
3588c2ecf20Sopenharmony_ci		    (invparity[rp16] << 0);
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__nand_calculate_ecc);
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci/**
3638c2ecf20Sopenharmony_ci * nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte
3648c2ecf20Sopenharmony_ci *			 block
3658c2ecf20Sopenharmony_ci * @chip:	NAND chip object
3668c2ecf20Sopenharmony_ci * @buf:	input buffer with raw data
3678c2ecf20Sopenharmony_ci * @code:	output buffer with ECC
3688c2ecf20Sopenharmony_ci */
3698c2ecf20Sopenharmony_ciint nand_calculate_ecc(struct nand_chip *chip, const unsigned char *buf,
3708c2ecf20Sopenharmony_ci		       unsigned char *code)
3718c2ecf20Sopenharmony_ci{
3728c2ecf20Sopenharmony_ci	bool sm_order = chip->ecc.options & NAND_ECC_SOFT_HAMMING_SM_ORDER;
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	__nand_calculate_ecc(buf, chip->ecc.size, code, sm_order);
3758c2ecf20Sopenharmony_ci
3768c2ecf20Sopenharmony_ci	return 0;
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ciEXPORT_SYMBOL(nand_calculate_ecc);
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci/**
3818c2ecf20Sopenharmony_ci * __nand_correct_data - [NAND Interface] Detect and correct bit error(s)
3828c2ecf20Sopenharmony_ci * @buf:	raw data read from the chip
3838c2ecf20Sopenharmony_ci * @read_ecc:	ECC from the chip
3848c2ecf20Sopenharmony_ci * @calc_ecc:	the ECC calculated from raw data
3858c2ecf20Sopenharmony_ci * @eccsize:	data bytes per ECC step (256 or 512)
3868c2ecf20Sopenharmony_ci * @sm_order:	Smart Media byte order
3878c2ecf20Sopenharmony_ci *
3888c2ecf20Sopenharmony_ci * Detect and correct a 1 bit error for eccsize byte block
3898c2ecf20Sopenharmony_ci */
3908c2ecf20Sopenharmony_ciint __nand_correct_data(unsigned char *buf,
3918c2ecf20Sopenharmony_ci			unsigned char *read_ecc, unsigned char *calc_ecc,
3928c2ecf20Sopenharmony_ci			unsigned int eccsize, bool sm_order)
3938c2ecf20Sopenharmony_ci{
3948c2ecf20Sopenharmony_ci	unsigned char b0, b1, b2, bit_addr;
3958c2ecf20Sopenharmony_ci	unsigned int byte_addr;
3968c2ecf20Sopenharmony_ci	/* 256 or 512 bytes/ecc  */
3978c2ecf20Sopenharmony_ci	const uint32_t eccsize_mult = eccsize >> 8;
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	/*
4008c2ecf20Sopenharmony_ci	 * b0 to b2 indicate which bit is faulty (if any)
4018c2ecf20Sopenharmony_ci	 * we might need the xor result  more than once,
4028c2ecf20Sopenharmony_ci	 * so keep them in a local var
4038c2ecf20Sopenharmony_ci	*/
4048c2ecf20Sopenharmony_ci	if (sm_order) {
4058c2ecf20Sopenharmony_ci		b0 = read_ecc[0] ^ calc_ecc[0];
4068c2ecf20Sopenharmony_ci		b1 = read_ecc[1] ^ calc_ecc[1];
4078c2ecf20Sopenharmony_ci	} else {
4088c2ecf20Sopenharmony_ci		b0 = read_ecc[1] ^ calc_ecc[1];
4098c2ecf20Sopenharmony_ci		b1 = read_ecc[0] ^ calc_ecc[0];
4108c2ecf20Sopenharmony_ci	}
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	b2 = read_ecc[2] ^ calc_ecc[2];
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	/* check if there are any bitfaults */
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	/* repeated if statements are slightly more efficient than switch ... */
4178c2ecf20Sopenharmony_ci	/* ordered in order of likelihood */
4188c2ecf20Sopenharmony_ci
4198c2ecf20Sopenharmony_ci	if ((b0 | b1 | b2) == 0)
4208c2ecf20Sopenharmony_ci		return 0;	/* no error */
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	if ((((b0 ^ (b0 >> 1)) & 0x55) == 0x55) &&
4238c2ecf20Sopenharmony_ci	    (((b1 ^ (b1 >> 1)) & 0x55) == 0x55) &&
4248c2ecf20Sopenharmony_ci	    ((eccsize_mult == 1 && ((b2 ^ (b2 >> 1)) & 0x54) == 0x54) ||
4258c2ecf20Sopenharmony_ci	     (eccsize_mult == 2 && ((b2 ^ (b2 >> 1)) & 0x55) == 0x55))) {
4268c2ecf20Sopenharmony_ci	/* single bit error */
4278c2ecf20Sopenharmony_ci		/*
4288c2ecf20Sopenharmony_ci		 * rp17/rp15/13/11/9/7/5/3/1 indicate which byte is the faulty
4298c2ecf20Sopenharmony_ci		 * byte, cp 5/3/1 indicate the faulty bit.
4308c2ecf20Sopenharmony_ci		 * A lookup table (called addressbits) is used to filter
4318c2ecf20Sopenharmony_ci		 * the bits from the byte they are in.
4328c2ecf20Sopenharmony_ci		 * A marginal optimisation is possible by having three
4338c2ecf20Sopenharmony_ci		 * different lookup tables.
4348c2ecf20Sopenharmony_ci		 * One as we have now (for b0), one for b2
4358c2ecf20Sopenharmony_ci		 * (that would avoid the >> 1), and one for b1 (with all values
4368c2ecf20Sopenharmony_ci		 * << 4). However it was felt that introducing two more tables
4378c2ecf20Sopenharmony_ci		 * hardly justify the gain.
4388c2ecf20Sopenharmony_ci		 *
4398c2ecf20Sopenharmony_ci		 * The b2 shift is there to get rid of the lowest two bits.
4408c2ecf20Sopenharmony_ci		 * We could also do addressbits[b2] >> 1 but for the
4418c2ecf20Sopenharmony_ci		 * performance it does not make any difference
4428c2ecf20Sopenharmony_ci		 */
4438c2ecf20Sopenharmony_ci		if (eccsize_mult == 1)
4448c2ecf20Sopenharmony_ci			byte_addr = (addressbits[b1] << 4) + addressbits[b0];
4458c2ecf20Sopenharmony_ci		else
4468c2ecf20Sopenharmony_ci			byte_addr = (addressbits[b2 & 0x3] << 8) +
4478c2ecf20Sopenharmony_ci				    (addressbits[b1] << 4) + addressbits[b0];
4488c2ecf20Sopenharmony_ci		bit_addr = addressbits[b2 >> 2];
4498c2ecf20Sopenharmony_ci		/* flip the bit */
4508c2ecf20Sopenharmony_ci		buf[byte_addr] ^= (1 << bit_addr);
4518c2ecf20Sopenharmony_ci		return 1;
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	}
4548c2ecf20Sopenharmony_ci	/* count nr of bits; use table lookup, faster than calculating it */
4558c2ecf20Sopenharmony_ci	if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1)
4568c2ecf20Sopenharmony_ci		return 1;	/* error in ECC data; no action needed */
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	pr_err("%s: uncorrectable ECC error\n", __func__);
4598c2ecf20Sopenharmony_ci	return -EBADMSG;
4608c2ecf20Sopenharmony_ci}
4618c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__nand_correct_data);
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci/**
4648c2ecf20Sopenharmony_ci * nand_correct_data - [NAND Interface] Detect and correct bit error(s)
4658c2ecf20Sopenharmony_ci * @chip:	NAND chip object
4668c2ecf20Sopenharmony_ci * @buf:	raw data read from the chip
4678c2ecf20Sopenharmony_ci * @read_ecc:	ECC from the chip
4688c2ecf20Sopenharmony_ci * @calc_ecc:	the ECC calculated from raw data
4698c2ecf20Sopenharmony_ci *
4708c2ecf20Sopenharmony_ci * Detect and correct a 1 bit error for 256/512 byte block
4718c2ecf20Sopenharmony_ci */
4728c2ecf20Sopenharmony_ciint nand_correct_data(struct nand_chip *chip, unsigned char *buf,
4738c2ecf20Sopenharmony_ci		      unsigned char *read_ecc, unsigned char *calc_ecc)
4748c2ecf20Sopenharmony_ci{
4758c2ecf20Sopenharmony_ci	bool sm_order = chip->ecc.options & NAND_ECC_SOFT_HAMMING_SM_ORDER;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	return __nand_correct_data(buf, read_ecc, calc_ecc, chip->ecc.size,
4788c2ecf20Sopenharmony_ci				   sm_order);
4798c2ecf20Sopenharmony_ci}
4808c2ecf20Sopenharmony_ciEXPORT_SYMBOL(nand_correct_data);
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
4838c2ecf20Sopenharmony_ciMODULE_AUTHOR("Frans Meulenbroeks <fransmeulenbroeks@gmail.com>");
4848c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Generic NAND ECC support");
485