[PATCH] [MTD] [NAND] nand_ecc.c: adding support for 512 byte ecc
Singh, Vimal
vimalsingh at ti.com
Fri Aug 22 01:39:13 EDT 2008
Hi Frans,
>I tried to apply your patch, but only hunk 1 succeeded with fuzz 2.
>Guess this is because shortly after submitting my patch another patch
>has been applied to it.
>Could you verify against the latest version in git and resubmit the patch.
I have prepared the patch once again on top of latest version in git.
Hopefully it should apply properly.
Regards,
vimal
Signed-off-by: Vimal Singh <vimalsingh at ti.com>
-----
nand_ecc.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 49 insertions(+), 13 deletions(-)
--- a/drivers/mtd/nand/nand_ecc.c 2008-08-22 10:41:53.000000000 +0530
+++ b/drivers/mtd/nand/nand_ecc.c 2008-08-22 10:47:40.000000000 +0530
@@ -42,6 +42,8 @@
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#else
#include <stdint.h>
@@ -154,10 +156,12 @@ int nand_calculate_ecc(struct mtd_info *
{
int i;
const uint32_t *bp = (uint32_t *)buf;
+ /* 256 or 512 bytes/ecc */
+ uint32_t j =(((struct nand_chip *)mtd->priv)->ecc.size) >> 8;
uint32_t cur; /* current value in buffer */
- /* rp0..rp15 are the various accumulated parities (per byte) */
+ /* rp0..rp15..rp17 are the various accumulated parities (per byte) */
uint32_t rp0, rp1, rp2, rp3, rp4, rp5, rp6, rp7;
- uint32_t rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15;
+ uint32_t rp8, rp9, rp10, rp11, rp12, rp13, rp14, rp15, rp16, rp17;
uint32_t par; /* the cumulative parity for all data */
uint32_t tmppar; /* the cumulative parity for this iteration;
for rp12 and rp14 at the end of the loop */
@@ -169,6 +173,8 @@ int nand_calculate_ecc(struct mtd_info *
rp10 = 0;
rp12 = 0;
rp14 = 0;
+ rp16 = 0;
+ rp17 = 0; /* to make cmpiler happy */
/*
* The loop is unrolled a number of times;
@@ -180,7 +186,7 @@ int nand_calculate_ecc(struct mtd_info *
* needed for calculating rp12, rp14 and par
* also used as a performance improvement for rp6, rp8 and rp10
*/
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < 4*j; i++) {
cur = *bp++;
tmppar = cur;
rp4 ^= cur;
@@ -243,6 +249,8 @@ int nand_calculate_ecc(struct mtd_info *
rp12 ^= tmppar;
if ((i & 0x2) == 0)
rp14 ^= tmppar;
+ if (j == 2 && (i & 0x4) == 0)
+ rp16 ^= tmppar;
}
/*
@@ -269,6 +277,11 @@ int nand_calculate_ecc(struct mtd_info *
rp14 ^= (rp14 >> 16);
rp14 ^= (rp14 >> 8);
rp14 &= 0xff;
+ if (j == 2) {
+ rp16 ^= (rp16 >> 16);
+ rp16 ^= (rp16 >> 8);
+ rp16 &= 0xff;
+ }
/*
* we also need to calculate the row parity for rp0..rp3
@@ -311,6 +324,8 @@ int nand_calculate_ecc(struct mtd_info *
rp11 = (par ^ rp10) & 0xff;
rp13 = (par ^ rp12) & 0xff;
rp15 = (par ^ rp14) & 0xff;
+ if (j == 2)
+ rp17 = (par ^ rp16) & 0xff;
/*
* Finally calculate the ecc bits.
@@ -357,14 +372,25 @@ int nand_calculate_ecc(struct mtd_info *
(invparity[rp9] << 1) |
(invparity[rp8]);
#endif
- code[2] =
- (invparity[par & 0xf0] << 7) |
- (invparity[par & 0x0f] << 6) |
- (invparity[par & 0xcc] << 5) |
- (invparity[par & 0x33] << 4) |
- (invparity[par & 0xaa] << 3) |
- (invparity[par & 0x55] << 2) |
- 3;
+ if (j == 1)
+ code[2] =
+ (invparity[par & 0xf0] << 7) |
+ (invparity[par & 0x0f] << 6) |
+ (invparity[par & 0xcc] << 5) |
+ (invparity[par & 0x33] << 4) |
+ (invparity[par & 0xaa] << 3) |
+ (invparity[par & 0x55] << 2) |
+ 3;
+ else if (j == 2)
+ code[2] =
+ (invparity[par & 0xf0] << 7) |
+ (invparity[par & 0x0f] << 6) |
+ (invparity[par & 0xcc] << 5) |
+ (invparity[par & 0x33] << 4) |
+ (invparity[par & 0xaa] << 3) |
+ (invparity[par & 0x55] << 2) |
+ (invparity[rp17] << 1) |
+ (invparity[rp16] << 0);
return 0;
}
EXPORT_SYMBOL(nand_calculate_ecc);
@@ -384,6 +410,8 @@ int nand_correct_data(struct mtd_info *m
int nr_bits;
unsigned char b0, b1, b2;
unsigned char byte_addr, bit_addr;
+ /* 256 or 512 bytes/ecc */
+ uint32_t j = (((struct nand_chip *)mtd->priv)->ecc.size) >> 8;
/*
* b0 to b2 indicate which bit is faulty (if any)
@@ -408,7 +436,11 @@ int nand_correct_data(struct mtd_info *m
/* ordered in order of likelihood */
if (nr_bits == 0)
return 0; /* no error */
- if (nr_bits == 11) { /* correctable error */
+ if ((((b0 ^ (b0 >> 1)) & 0x55) == 0x55) &&
+ (((b1 ^ (b1 >> 1)) & 0x55) == 0x55) &&
+ ((j == 1 && ((b2 ^ (b2 >> 1)) & 0x54) == 0x54) ||
+ (j == 2 && ((b2 ^ (b2 >> 1)) & 0x55) == 0x55))) {
+ /* single bit error */
/*
* rp15/13/11/9/7/5/3/1 indicate which byte is the faulty byte
* cp 5/3/1 indicate the faulty bit.
@@ -425,7 +457,11 @@ int nand_correct_data(struct mtd_info *m
* We could also do addressbits[b2] >> 1 but for the
* performace it does not make any difference
*/
- byte_addr = (addressbits[b1] << 4) + addressbits[b0];
+ if (j == 1)
+ byte_addr = (addressbits[b1] << 4) + addressbits[b0];
+ else if (j == 2)
+ byte_addr = (addressbits[b2 & 0x3] << 8) +
+ (addressbits[b1] << 4) + addressbits[b0];
bit_addr = addressbits[b2 >> 2];
/* flip the bit */
buf[byte_addr] ^= (1 << bit_addr);
More information about the linux-mtd
mailing list