[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