davinci_nand: cleanup II (CONFIG_SYS_DAVINCI_BROKEN_ECC)
authorDavid Brownell <dbrownell@users.sourceforge.net>
Tue, 28 Apr 2009 20:19:53 +0000 (13:19 -0700)
committerScott Wood <scottwood@freescale.com>
Tue, 7 Jul 2009 22:58:01 +0000 (17:58 -0500)
Remove CONFIG_SYS_DAVINCI_BROKEN_ECC option.  It's not just nasty;
it's also unused by any current boards, and doesn't even match the
main U-Boot distributions from TI (which use soft ECC, or 4-bit ECC
on newer chips that support it).

DaVinci GIT kernels since 2.6.24, and mainline Linux since 2.6.30,
match non-BROKEN code paths for 1-bit HW ECC.  The BROKEN code paths
do seem to partially match what MontaVista/TI kernels (4.0/2.6.10,
and 5.0/2.6.18) do ... but only for small pages.  Large page support
is really broken (and it's unclear just what software it was trying
to match!), and the ECC layout was making three more bytes available
for use by filesystem (or whatever) code.

Since this option itself seems broken, remove it.  Add a comment
about the MV/TI compat issue, and the most straightforward way to
address it (should someone really need to solve it).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Scott Wood <scottwood@freescale.com>
doc/README.nand
drivers/mtd/nand/davinci_nand.c
include/asm-arm/arch-davinci/nand_defs.h

index bb722892de809f1ffa85f0424f1477b738f9b856..b077d9ab3b77f9aed6a1c731a7bd1e94359bc528 100644 (file)
@@ -101,15 +101,6 @@ Configuration Options:
    CONFIG_SYS_NAND_MAX_CHIPS
       The maximum number of NAND chips per device to be supported.
 
-   CONFIG_SYS_DAVINCI_BROKEN_ECC
-      Versions of U-Boot <= 1.3.3 and Montavista Linux kernels
-      generated bogus ECCs on large-page NAND. Both large and small page
-      NAND ECCs were incompatible with the Linux davinci git tree (since
-      NAND was integrated in 2.6.24).
-      Turn this ON if you want backwards compatibility.
-      Turn this OFF if you want U-Boot and the Linux davinci git kernel
-      to use the same ECC format.
-
 NOTE:
 =====
 
index 8b22024601f97d0691b5bb5344a0df6e19ab3346..9e7b9dd9b155b0770585f76d08b6862ca41ede5c 100644 (file)
@@ -86,45 +86,12 @@ static void nand_davinci_select_chip(struct mtd_info *mtd, int chip)
 }
 
 #ifdef CONFIG_SYS_NAND_HW_ECC
-#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC
-/* Linux-compatible ECC uses MTD defaults. */
-/* These layouts are not compatible with Linux or RBL/UBL. */
-#ifdef CONFIG_SYS_NAND_LARGEPAGE
-static struct nand_ecclayout davinci_nand_ecclayout = {
-       .eccbytes = 12,
-       .eccpos = {8, 9, 10, 24, 25, 26, 40, 41, 42, 56, 57, 58},
-       .oobfree = {
-               {.offset = 2, .length = 6},
-               {.offset = 12, .length = 12},
-               {.offset = 28, .length = 12},
-               {.offset = 44, .length = 12},
-               {.offset = 60, .length = 4}
-       }
-};
-#elif defined(CONFIG_SYS_NAND_SMALLPAGE)
-static struct nand_ecclayout davinci_nand_ecclayout = {
-       .eccbytes = 3,
-       .eccpos = {0, 1, 2},
-       .oobfree = {
-               {.offset = 6, .length = 2},
-               {.offset = 8, .length = 8}
-       }
-};
-#else
-#error "Either CONFIG_SYS_NAND_LARGEPAGE or CONFIG_SYS_NAND_SMALLPAGE must be defined!"
-#endif
-#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */
 
 static void nand_davinci_enable_hwecc(struct mtd_info *mtd, int mode)
 {
        int             dummy;
 
        dummy = emif_regs->NANDF1ECC;
-#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC
-       dummy = emif_regs->NANDF2ECC;
-       dummy = emif_regs->NANDF3ECC;
-       dummy = emif_regs->NANDF4ECC;
-#endif
 
        /* FIXME:  only chipselect 0 is supported for now */
        emif_regs->NANDFCR |= 1 << 8;
@@ -149,29 +116,6 @@ static u_int32_t nand_davinci_readecc(struct mtd_info *mtd, u_int32_t region)
 static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
 {
        u_int32_t               tmp;
-#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC
-       /*
-        * This is not how you should read ECCs on large page Davinci devices.
-        * The region parameter gets you ECCs for flash chips on different chip
-        * selects, not the 4x512 byte pages in a 2048 byte page.
-        *
-        * Preserved for backwards compatibility though.
-        */
-
-       int                     region, n;
-       struct nand_chip        *this = mtd->priv;
-
-       n = (this->ecc.size/512);
-
-       region = 1;
-       while (n--) {
-               tmp = nand_davinci_readecc(mtd, region);
-               *ecc_code++ = tmp;
-               *ecc_code++ = tmp >> 16;
-               *ecc_code++ = ((tmp >> 8) & 0x0f) | ((tmp >> 20) & 0xf0);
-               region++;
-       }
-#else
        const int region = 1;
 
        tmp = nand_davinci_readecc(mtd, region);
@@ -186,148 +130,26 @@ static int nand_davinci_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u
        *ecc_code++ = tmp;
        *ecc_code++ = tmp >>  8;
        *ecc_code++ = tmp >> 16;
-#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */
-       return(0);
-}
-
-#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC
-static void nand_davinci_gen_true_ecc(u_int8_t *ecc_buf)
-{
-       u_int32_t       tmp = ecc_buf[0] | (ecc_buf[1] << 16) | ((ecc_buf[2] & 0xf0) << 20) | ((ecc_buf[2] & 0x0f) << 8);
-
-       ecc_buf[0] = ~(P64o(tmp) | P64e(tmp) | P32o(tmp) | P32e(tmp) | P16o(tmp) | P16e(tmp) | P8o(tmp) | P8e(tmp));
-       ecc_buf[1] = ~(P1024o(tmp) | P1024e(tmp) | P512o(tmp) | P512e(tmp) | P256o(tmp) | P256e(tmp) | P128o(tmp) | P128e(tmp));
-       ecc_buf[2] = ~( P4o(tmp) | P4e(tmp) | P2o(tmp) | P2e(tmp) | P1o(tmp) | P1e(tmp) | P2048o(tmp) | P2048e(tmp));
-}
-
-static int nand_davinci_compare_ecc(u_int8_t *ecc_nand, u_int8_t *ecc_calc, u_int8_t *page_data)
-{
-       u_int32_t       i;
-       u_int8_t        tmp0_bit[8], tmp1_bit[8], tmp2_bit[8];
-       u_int8_t        comp0_bit[8], comp1_bit[8], comp2_bit[8];
-       u_int8_t        ecc_bit[24];
-       u_int8_t        ecc_sum = 0;
-       u_int8_t        find_bit = 0;
-       u_int32_t       find_byte = 0;
-       int             is_ecc_ff;
-
-       is_ecc_ff = ((*ecc_nand == 0xff) && (*(ecc_nand + 1) == 0xff) && (*(ecc_nand + 2) == 0xff));
-
-       nand_davinci_gen_true_ecc(ecc_nand);
-       nand_davinci_gen_true_ecc(ecc_calc);
-
-       for (i = 0; i <= 2; i++) {
-               *(ecc_nand + i) = ~(*(ecc_nand + i));
-               *(ecc_calc + i) = ~(*(ecc_calc + i));
-       }
-
-       for (i = 0; i < 8; i++) {
-               tmp0_bit[i] = *ecc_nand % 2;
-               *ecc_nand = *ecc_nand / 2;
-       }
-
-       for (i = 0; i < 8; i++) {
-               tmp1_bit[i] = *(ecc_nand + 1) % 2;
-               *(ecc_nand + 1) = *(ecc_nand + 1) / 2;
-       }
-
-       for (i = 0; i < 8; i++) {
-               tmp2_bit[i] = *(ecc_nand + 2) % 2;
-               *(ecc_nand + 2) = *(ecc_nand + 2) / 2;
-       }
 
-       for (i = 0; i < 8; i++) {
-               comp0_bit[i] = *ecc_calc % 2;
-               *ecc_calc = *ecc_calc / 2;
-       }
-
-       for (i = 0; i < 8; i++) {
-               comp1_bit[i] = *(ecc_calc + 1) % 2;
-               *(ecc_calc + 1) = *(ecc_calc + 1) / 2;
-       }
-
-       for (i = 0; i < 8; i++) {
-               comp2_bit[i] = *(ecc_calc + 2) % 2;
-               *(ecc_calc + 2) = *(ecc_calc + 2) / 2;
-       }
-
-       for (i = 0; i< 6; i++)
-               ecc_bit[i] = tmp2_bit[i + 2] ^ comp2_bit[i + 2];
-
-       for (i = 0; i < 8; i++)
-               ecc_bit[i + 6] = tmp0_bit[i] ^ comp0_bit[i];
-
-       for (i = 0; i < 8; i++)
-               ecc_bit[i + 14] = tmp1_bit[i] ^ comp1_bit[i];
-
-       ecc_bit[22] = tmp2_bit[0] ^ comp2_bit[0];
-       ecc_bit[23] = tmp2_bit[1] ^ comp2_bit[1];
-
-       for (i = 0; i < 24; i++)
-               ecc_sum += ecc_bit[i];
+       /* NOTE:  the above code matches mainline Linux:
+        *      .PQR.stu ==> ~PQRstu
+        *
+        * MontaVista/TI kernels encode those bytes differently, use
+        * complicated (and allegedly sometimes-wrong) correction code,
+        * and usually shipped with U-Boot that uses software ECC:
+        *      .PQR.stu ==> PsQRtu
+        *
+        * If you need MV/TI compatible NAND I/O in U-Boot, it should
+        * be possible to (a) change the mangling above, (b) reverse
+        * that mangling in nand_davinci_correct_data() below.
+        */
 
-       switch (ecc_sum) {
-               case 0:
-                       /* Not reached because this function is not called if
-                          ECC values are equal */
-                       return 0;
-               case 1:
-                       /* Uncorrectable error */
-                       MTDDEBUG (MTD_DEBUG_LEVEL0,
-                                 "ECC UNCORRECTED_ERROR 1\n");
-                       return(-1);
-               case 12:
-                       /* Correctable error */
-                       find_byte = (ecc_bit[23] << 8) +
-                               (ecc_bit[21] << 7) +
-                               (ecc_bit[19] << 6) +
-                               (ecc_bit[17] << 5) +
-                               (ecc_bit[15] << 4) +
-                               (ecc_bit[13] << 3) +
-                               (ecc_bit[11] << 2) +
-                               (ecc_bit[9]  << 1) +
-                               ecc_bit[7];
-
-                       find_bit = (ecc_bit[5] << 2) + (ecc_bit[3] << 1) + ecc_bit[1];
-
-                       MTDDEBUG (MTD_DEBUG_LEVEL0, "Correcting single bit ECC "
-                                 "error at offset: %d, bit: %d\n",
-                                 find_byte, find_bit);
-
-                       page_data[find_byte] ^= (1 << find_bit);
-
-                       return(0);
-               default:
-                       if (is_ecc_ff) {
-                               if (ecc_calc[0] == 0 && ecc_calc[1] == 0 && ecc_calc[2] == 0)
-                                       return(0);
-                       }
-                       MTDDEBUG (MTD_DEBUG_LEVEL0,
-                                 "UNCORRECTED_ERROR default\n");
-                       return(-1);
-       }
+       return 0;
 }
-#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */
 
 static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc)
 {
        struct nand_chip *this = mtd->priv;
-#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC
-       int                     block_count = 0, i, rc;
-
-       block_count = (this->ecc.size/512);
-       for (i = 0; i < block_count; i++) {
-               if (memcmp(read_ecc, calc_ecc, 3) != 0) {
-                       rc = nand_davinci_compare_ecc(read_ecc, calc_ecc, dat);
-                       if (rc < 0) {
-                               return(rc);
-                       }
-               }
-               read_ecc += 3;
-               calc_ecc += 3;
-               dat += 512;
-       }
-#else
        u_int32_t ecc_nand = read_ecc[0] | (read_ecc[1] << 8) |
                                          (read_ecc[2] << 16);
        u_int32_t ecc_calc = calc_ecc[0] | (calc_ecc[1] << 8) |
@@ -361,7 +183,6 @@ static int nand_davinci_correct_data(struct mtd_info *mtd, u_char *dat, u_char *
                        return -1;
                }
        }
-#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */
        return(0);
 }
 #endif /* CONFIG_SYS_NAND_HW_ECC */
@@ -416,21 +237,8 @@ int board_nand_init(struct nand_chip *nand)
 #endif
 #ifdef CONFIG_SYS_NAND_HW_ECC
        nand->ecc.mode = NAND_ECC_HW;
-#ifdef CONFIG_SYS_DAVINCI_BROKEN_ECC
-       nand->ecc.layout  = &davinci_nand_ecclayout;
-#ifdef CONFIG_SYS_NAND_LARGEPAGE
-       nand->ecc.size = 2048;
-       nand->ecc.bytes = 12;
-#elif defined(CONFIG_SYS_NAND_SMALLPAGE)
-       nand->ecc.size = 512;
-       nand->ecc.bytes = 3;
-#else
-#error "Either CONFIG_SYS_NAND_LARGEPAGE or CONFIG_SYS_NAND_SMALLPAGE must be defined!"
-#endif
-#else
        nand->ecc.size = 512;
        nand->ecc.bytes = 3;
-#endif /* CONFIG_SYS_DAVINCI_BROKEN_ECC */
        nand->ecc.calculate = nand_davinci_calculate_ecc;
        nand->ecc.correct  = nand_davinci_correct_data;
        nand->ecc.hwctl  = nand_davinci_enable_hwecc;
index 8450b8c69034c60de465314f670dbb73e42e17e5..70094e756db2ac27cfbc4b0d45f8710736da54c7 100644 (file)
 #define NAND_READ_END          0x30
 #define NAND_STATUS            0x70
 
-#ifdef CONFIG_SYS_NAND_HW_ECC
-#define NAND_Ecc_P1e           (1 << 0)
-#define NAND_Ecc_P2e           (1 << 1)
-#define NAND_Ecc_P4e           (1 << 2)
-#define NAND_Ecc_P8e           (1 << 3)
-#define NAND_Ecc_P16e          (1 << 4)
-#define NAND_Ecc_P32e          (1 << 5)
-#define NAND_Ecc_P64e          (1 << 6)
-#define NAND_Ecc_P128e         (1 << 7)
-#define NAND_Ecc_P256e         (1 << 8)
-#define NAND_Ecc_P512e         (1 << 9)
-#define NAND_Ecc_P1024e                (1 << 10)
-#define NAND_Ecc_P2048e                (1 << 11)
-
-#define NAND_Ecc_P1o           (1 << 16)
-#define NAND_Ecc_P2o           (1 << 17)
-#define NAND_Ecc_P4o           (1 << 18)
-#define NAND_Ecc_P8o           (1 << 19)
-#define NAND_Ecc_P16o          (1 << 20)
-#define NAND_Ecc_P32o          (1 << 21)
-#define NAND_Ecc_P64o          (1 << 22)
-#define NAND_Ecc_P128o         (1 << 23)
-#define NAND_Ecc_P256o         (1 << 24)
-#define NAND_Ecc_P512o         (1 << 25)
-#define NAND_Ecc_P1024o                (1 << 26)
-#define NAND_Ecc_P2048o                (1 << 27)
-
-#define TF(v)                  (v ? 1 : 0)
-
-#define P2048e(a)              (TF(a & NAND_Ecc_P2048e) << 0)
-#define P2048o(a)              (TF(a & NAND_Ecc_P2048o) << 1)
-#define P1e(a)                 (TF(a & NAND_Ecc_P1e) << 2)
-#define P1o(a)                 (TF(a & NAND_Ecc_P1o) << 3)
-#define P2e(a)                 (TF(a & NAND_Ecc_P2e) << 4)
-#define P2o(a)                 (TF(a & NAND_Ecc_P2o) << 5)
-#define P4e(a)                 (TF(a & NAND_Ecc_P4e) << 6)
-#define P4o(a)                 (TF(a & NAND_Ecc_P4o) << 7)
-
-#define P8e(a)                 (TF(a & NAND_Ecc_P8e) << 0)
-#define P8o(a)                 (TF(a & NAND_Ecc_P8o) << 1)
-#define P16e(a)                        (TF(a & NAND_Ecc_P16e) << 2)
-#define P16o(a)                        (TF(a & NAND_Ecc_P16o) << 3)
-#define P32e(a)                        (TF(a & NAND_Ecc_P32e) << 4)
-#define P32o(a)                        (TF(a & NAND_Ecc_P32o) << 5)
-#define P64e(a)                        (TF(a & NAND_Ecc_P64e) << 6)
-#define P64o(a)                        (TF(a & NAND_Ecc_P64o) << 7)
-
-#define P128e(a)               (TF(a & NAND_Ecc_P128e) << 0)
-#define P128o(a)               (TF(a & NAND_Ecc_P128o) << 1)
-#define P256e(a)               (TF(a & NAND_Ecc_P256e) << 2)
-#define P256o(a)               (TF(a & NAND_Ecc_P256o) << 3)
-#define P512e(a)               (TF(a & NAND_Ecc_P512e) << 4)
-#define P512o(a)               (TF(a & NAND_Ecc_P512o) << 5)
-#define P1024e(a)              (TF(a & NAND_Ecc_P1024e) << 6)
-#define P1024o(a)              (TF(a & NAND_Ecc_P1024o) << 7)
-
-#define P8e_s(a)               (TF(a & NAND_Ecc_P8e) << 0)
-#define P8o_s(a)               (TF(a & NAND_Ecc_P8o) << 1)
-#define P16e_s(a)              (TF(a & NAND_Ecc_P16e) << 2)
-#define P16o_s(a)              (TF(a & NAND_Ecc_P16o) << 3)
-#define P1e_s(a)               (TF(a & NAND_Ecc_P1e) << 4)
-#define P1o_s(a)               (TF(a & NAND_Ecc_P1o) << 5)
-#define P2e_s(a)               (TF(a & NAND_Ecc_P2e) << 6)
-#define P2o_s(a)               (TF(a & NAND_Ecc_P2o) << 7)
-
-#define P4e_s(a)               (TF(a & NAND_Ecc_P4e) << 0)
-#define P4o_s(a)               (TF(a & NAND_Ecc_P4o) << 1)
-#endif
-
 #endif