]> git.ipfire.org Git - people/ms/u-boot.git/commitdiff
MTD:NAND: ADD new ECC mode NAND_ECC_HW_OOB_FIRST
authorSandeep Paulraj <s-paulraj@ti.com>
Mon, 10 Aug 2009 17:27:56 +0000 (13:27 -0400)
committerScott Wood <scottwood@freescale.com>
Wed, 26 Aug 2009 20:37:03 +0000 (15:37 -0500)
This patch adds the new mode NAND_ECC_HW_OOB_FIRST in the nand code to
support 4-bit ECC on TI DaVinci devices with large page (up to 2K) NAND
chips.  This ECC mode is similar to NAND_ECC_HW, with the exception of
read_page API that first reads the OOB area, reads the data in chunks,
feeds the ECC from OOB area to the ECC hw engine and perform any
correction on the data as per the ECC status reported by the engine.

This patch has been accepted by Andrew Morton and can be found at

http://userweb.kernel.org/~akpm/mmotm/broken-out/mtd-nand-add-new-ecc-mode-ecc_hw_oob_first.patch

Signed-off-by: Sandeep Paulraj <s-paulraj@ti.com>
Signed-off-by: Sneha Narnakaje <nsnehaprabha@ti.com>
Signed-off-by: Scott Wood <scottwood@freescale.com>
drivers/mtd/nand/nand_base.c
include/linux/mtd/nand.h

index ca026286f20ac562bfe249ebca14aa629998b7fb..426bb95e9e9f10f62b13e2877428370158daa3d9 100644 (file)
@@ -1067,6 +1067,54 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
        return 0;
 }
 
+/**
+ * nand_read_page_hwecc_oob_first - [REPLACABLE] hw ecc, read oob first
+ * @mtd:       mtd info structure
+ * @chip:      nand chip info structure
+ * @buf:       buffer to store read data
+ *
+ * Hardware ECC for large page chips, require OOB to be read first.
+ * For this ECC mode, the write_page method is re-used from ECC_HW.
+ * These methods read/write ECC from the OOB area, unlike the
+ * ECC_HW_SYNDROME support with multiple ECC steps, follows the
+ * "infix ECC" scheme and reads/writes ECC from the data area, by
+ * overwriting the NAND manufacturer bad block markings.
+ */
+static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
+       struct nand_chip *chip, uint8_t *buf, int page)
+{
+       int i, eccsize = chip->ecc.size;
+       int eccbytes = chip->ecc.bytes;
+       int eccsteps = chip->ecc.steps;
+       uint8_t *p = buf;
+       uint8_t *ecc_code = chip->buffers->ecccode;
+       uint32_t *eccpos = chip->ecc.layout->eccpos;
+       uint8_t *ecc_calc = chip->buffers->ecccalc;
+
+       /* Read the OOB area first */
+       chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page);
+       chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+       chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+
+       for (i = 0; i < chip->ecc.total; i++)
+               ecc_code[i] = chip->oob_poi[eccpos[i]];
+
+       for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
+               int stat;
+
+               chip->ecc.hwctl(mtd, NAND_ECC_READ);
+               chip->read_buf(mtd, p, eccsize);
+               chip->ecc.calculate(mtd, p, &ecc_calc[i]);
+
+               stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL);
+               if (stat < 0)
+                       mtd->ecc_stats.failed++;
+               else
+                       mtd->ecc_stats.corrected += stat;
+       }
+       return 0;
+}
+
 /**
  * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read
  * @mtd:       mtd info structure
@@ -2730,6 +2778,17 @@ int nand_scan_tail(struct mtd_info *mtd)
                chip->ecc.write_page_raw = nand_write_page_raw;
 
        switch (chip->ecc.mode) {
+       case NAND_ECC_HW_OOB_FIRST:
+               /* Similar to NAND_ECC_HW, but a separate read_page handle */
+               if (!chip->ecc.calculate || !chip->ecc.correct ||
+                    !chip->ecc.hwctl) {
+                       printk(KERN_WARNING "No ECC functions supplied, "
+                              "Hardware ECC not possible\n");
+                       BUG();
+               }
+               if (!chip->ecc.read_page)
+                       chip->ecc.read_page = nand_read_page_hwecc_oob_first;
+
        case NAND_ECC_HW:
                /* Use standard hwecc read page function ? */
                if (!chip->ecc.read_page)
index d6aa392ff42670e6143371bfda53e79265e35d4c..cb7c19a4392bdd49151aa09595520eba31b97e0d 100644 (file)
@@ -128,6 +128,7 @@ typedef enum {
        NAND_ECC_SOFT,
        NAND_ECC_HW,
        NAND_ECC_HW_SYNDROME,
+       NAND_ECC_HW_OOB_FIRST,
 } nand_ecc_modes_t;
 
 /*