From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from devils.ext.ti.com ([198.47.26.153]) by bombadil.infradead.org with esmtps (Exim 4.69 #1 (Red Hat Linux)) id 1MGfC3-0001dU-FT for linux-mtd@lists.infradead.org; Tue, 16 Jun 2009 20:23:53 +0000 From: s-paulraj@ti.com To: davinci-linux-open-source@linux.davincidsp.com, linux-mtd@lists.infradead.org, dwmw2@infradead.org, tglx@linutronix.de, akpm@linux-foundation.org Subject: [PATCH v2 2/3] NAND: Add new ECC mode - ECC_HW_OOB_FIRST Date: Tue, 16 Jun 2009 16:23:17 -0400 Message-Id: <1245183797-11469-1-git-send-email-s-paulraj@ti.com> Cc: Sneha Narnakaje , Sandeep Paulraj List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Sandeep Paulraj The patch applies to linux-mtd GIT tree 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 4K) 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. "ECC_HW_OOB_FIRST" name suggested by Thomas Gleixner Reviewed-by: David Brownell Signed-off-by: Sneha Narnakaje Signed-off-by: Sandeep Paulraj 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 * @chip: nand chip info structure @@ -2673,6 +2721,17 @@ int nand_scan_tail(struct mtd_info *mtd) */ 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) -- 1.6.0.4