|
@@ -132,9 +132,10 @@ static const char addressbits[256] = {
|
|
|
* @buf: input buffer with raw data
|
|
|
* @eccsize: data bytes per ECC step (256 or 512)
|
|
|
* @code: output buffer with ECC
|
|
|
+ * @sm_order: Smart Media byte ordering
|
|
|
*/
|
|
|
void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize,
|
|
|
- unsigned char *code)
|
|
|
+ unsigned char *code, bool sm_order)
|
|
|
{
|
|
|
int i;
|
|
|
const uint32_t *bp = (uint32_t *)buf;
|
|
@@ -330,45 +331,26 @@ void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize,
|
|
|
* possible, but benchmarks showed that on the system this is developed
|
|
|
* the code below is the fastest
|
|
|
*/
|
|
|
-#ifdef CONFIG_MTD_NAND_ECC_SMC
|
|
|
- code[0] =
|
|
|
- (invparity[rp7] << 7) |
|
|
|
- (invparity[rp6] << 6) |
|
|
|
- (invparity[rp5] << 5) |
|
|
|
- (invparity[rp4] << 4) |
|
|
|
- (invparity[rp3] << 3) |
|
|
|
- (invparity[rp2] << 2) |
|
|
|
- (invparity[rp1] << 1) |
|
|
|
- (invparity[rp0]);
|
|
|
- code[1] =
|
|
|
- (invparity[rp15] << 7) |
|
|
|
- (invparity[rp14] << 6) |
|
|
|
- (invparity[rp13] << 5) |
|
|
|
- (invparity[rp12] << 4) |
|
|
|
- (invparity[rp11] << 3) |
|
|
|
- (invparity[rp10] << 2) |
|
|
|
- (invparity[rp9] << 1) |
|
|
|
- (invparity[rp8]);
|
|
|
-#else
|
|
|
- code[1] =
|
|
|
- (invparity[rp7] << 7) |
|
|
|
- (invparity[rp6] << 6) |
|
|
|
- (invparity[rp5] << 5) |
|
|
|
- (invparity[rp4] << 4) |
|
|
|
- (invparity[rp3] << 3) |
|
|
|
- (invparity[rp2] << 2) |
|
|
|
- (invparity[rp1] << 1) |
|
|
|
- (invparity[rp0]);
|
|
|
- code[0] =
|
|
|
- (invparity[rp15] << 7) |
|
|
|
- (invparity[rp14] << 6) |
|
|
|
- (invparity[rp13] << 5) |
|
|
|
- (invparity[rp12] << 4) |
|
|
|
- (invparity[rp11] << 3) |
|
|
|
- (invparity[rp10] << 2) |
|
|
|
- (invparity[rp9] << 1) |
|
|
|
- (invparity[rp8]);
|
|
|
-#endif
|
|
|
+ if (sm_order) {
|
|
|
+ code[0] = (invparity[rp7] << 7) | (invparity[rp6] << 6) |
|
|
|
+ (invparity[rp5] << 5) | (invparity[rp4] << 4) |
|
|
|
+ (invparity[rp3] << 3) | (invparity[rp2] << 2) |
|
|
|
+ (invparity[rp1] << 1) | (invparity[rp0]);
|
|
|
+ code[1] = (invparity[rp15] << 7) | (invparity[rp14] << 6) |
|
|
|
+ (invparity[rp13] << 5) | (invparity[rp12] << 4) |
|
|
|
+ (invparity[rp11] << 3) | (invparity[rp10] << 2) |
|
|
|
+ (invparity[rp9] << 1) | (invparity[rp8]);
|
|
|
+ } else {
|
|
|
+ code[1] = (invparity[rp7] << 7) | (invparity[rp6] << 6) |
|
|
|
+ (invparity[rp5] << 5) | (invparity[rp4] << 4) |
|
|
|
+ (invparity[rp3] << 3) | (invparity[rp2] << 2) |
|
|
|
+ (invparity[rp1] << 1) | (invparity[rp0]);
|
|
|
+ code[0] = (invparity[rp15] << 7) | (invparity[rp14] << 6) |
|
|
|
+ (invparity[rp13] << 5) | (invparity[rp12] << 4) |
|
|
|
+ (invparity[rp11] << 3) | (invparity[rp10] << 2) |
|
|
|
+ (invparity[rp9] << 1) | (invparity[rp8]);
|
|
|
+ }
|
|
|
+
|
|
|
if (eccsize_mult == 1)
|
|
|
code[2] =
|
|
|
(invparity[par & 0xf0] << 7) |
|
|
@@ -401,7 +383,9 @@ EXPORT_SYMBOL(__nand_calculate_ecc);
|
|
|
int nand_calculate_ecc(struct nand_chip *chip, const unsigned char *buf,
|
|
|
unsigned char *code)
|
|
|
{
|
|
|
- __nand_calculate_ecc(buf, chip->ecc.size, code);
|
|
|
+ bool sm_order = chip->ecc.options & NAND_ECC_SOFT_HAMMING_SM_ORDER;
|
|
|
+
|
|
|
+ __nand_calculate_ecc(buf, chip->ecc.size, code, sm_order);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -413,12 +397,13 @@ EXPORT_SYMBOL(nand_calculate_ecc);
|
|
|
* @read_ecc: ECC from the chip
|
|
|
* @calc_ecc: the ECC calculated from raw data
|
|
|
* @eccsize: data bytes per ECC step (256 or 512)
|
|
|
+ * @sm_order: Smart Media byte order
|
|
|
*
|
|
|
* Detect and correct a 1 bit error for eccsize byte block
|
|
|
*/
|
|
|
int __nand_correct_data(unsigned char *buf,
|
|
|
unsigned char *read_ecc, unsigned char *calc_ecc,
|
|
|
- unsigned int eccsize)
|
|
|
+ unsigned int eccsize, bool sm_order)
|
|
|
{
|
|
|
unsigned char b0, b1, b2, bit_addr;
|
|
|
unsigned int byte_addr;
|
|
@@ -430,13 +415,14 @@ int __nand_correct_data(unsigned char *buf,
|
|
|
* we might need the xor result more than once,
|
|
|
* so keep them in a local var
|
|
|
*/
|
|
|
-#ifdef CONFIG_MTD_NAND_ECC_SMC
|
|
|
- b0 = read_ecc[0] ^ calc_ecc[0];
|
|
|
- b1 = read_ecc[1] ^ calc_ecc[1];
|
|
|
-#else
|
|
|
- b0 = read_ecc[1] ^ calc_ecc[1];
|
|
|
- b1 = read_ecc[0] ^ calc_ecc[0];
|
|
|
-#endif
|
|
|
+ if (sm_order) {
|
|
|
+ b0 = read_ecc[0] ^ calc_ecc[0];
|
|
|
+ b1 = read_ecc[1] ^ calc_ecc[1];
|
|
|
+ } else {
|
|
|
+ b0 = read_ecc[1] ^ calc_ecc[1];
|
|
|
+ b1 = read_ecc[0] ^ calc_ecc[0];
|
|
|
+ }
|
|
|
+
|
|
|
b2 = read_ecc[2] ^ calc_ecc[2];
|
|
|
|
|
|
/* check if there are any bitfaults */
|
|
@@ -500,7 +486,10 @@ EXPORT_SYMBOL(__nand_correct_data);
|
|
|
int nand_correct_data(struct nand_chip *chip, unsigned char *buf,
|
|
|
unsigned char *read_ecc, unsigned char *calc_ecc)
|
|
|
{
|
|
|
- return __nand_correct_data(buf, read_ecc, calc_ecc, chip->ecc.size);
|
|
|
+ bool sm_order = chip->ecc.options & NAND_ECC_SOFT_HAMMING_SM_ORDER;
|
|
|
+
|
|
|
+ return __nand_correct_data(buf, read_ecc, calc_ecc, chip->ecc.size,
|
|
|
+ sm_order);
|
|
|
}
|
|
|
EXPORT_SYMBOL(nand_correct_data);
|
|
|
|