From patchwork Tue Nov 5 12:55:31 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ezequiel Garcia X-Patchwork-Id: 3142381 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 91CBC9F407 for ; Tue, 5 Nov 2013 15:34:07 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B7B4D20576 for ; Tue, 5 Nov 2013 15:34:02 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D0F2520453 for ; Tue, 5 Nov 2013 15:33:57 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VdgGt-0002VH-8Z; Tue, 05 Nov 2013 13:02:16 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VdgFz-0000dz-Ec; Tue, 05 Nov 2013 13:01:19 +0000 Received: from top.free-electrons.com ([176.31.233.9] helo=mail.free-electrons.com) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VdgCO-00005g-DU; Tue, 05 Nov 2013 12:57:39 +0000 Received: by mail.free-electrons.com (Postfix, from userid 106) id 533FC81D; Tue, 5 Nov 2013 13:57:26 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 Received: from localhost.localdomain (unknown [190.2.98.212]) by mail.free-electrons.com (Postfix) with ESMTPA id 7953A7E4; Tue, 5 Nov 2013 13:57:22 +0100 (CET) From: Ezequiel Garcia To: , Subject: [PATCH v3 24/28] mtd: nand: pxa3xx: Add ECC BCH correctable errors detection Date: Tue, 5 Nov 2013 09:55:31 -0300 Message-Id: <1383656135-8627-25-git-send-email-ezequiel.garcia@free-electrons.com> X-Mailer: git-send-email 1.8.1.5 In-Reply-To: <1383656135-8627-1-git-send-email-ezequiel.garcia@free-electrons.com> References: <1383656135-8627-1-git-send-email-ezequiel.garcia@free-electrons.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20131105_075736_715196_C9CBA4F7 X-CRM114-Status: GOOD ( 14.46 ) X-Spam-Score: -1.2 (-) Cc: Lior Amsalem , Thomas Petazzoni , Jason Cooper , Tawfik Bayouk , Daniel Mack , Huang Shijie , Ezequiel Garcia , Gregory Clement , Brian Norris , Willy Tarreau X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP This commit extends the ECC correctable error detection to include ECC BCH errors. The number of BCH correctable errors can be any up to 16, and the actual value is exposed in the NDSR register. Therefore, we change some symbol names to refer to correctable or uncorrectable (instead of single-bit or double-bit as it was in the Hamming case) and while at it, cleanup the detection code slightly. Signed-off-by: Ezequiel Garcia --- drivers/mtd/nand/pxa3xx_nand.c | 43 +++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 45c7b7c..7945544 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -97,6 +97,9 @@ #define NDCR_INT_MASK (0xFFF) #define NDSR_MASK (0xfff) +#define NDSR_ERR_CNT_OFF (16) +#define NDSR_ERR_CNT_MASK (0x1f) +#define NDSR_ERR_CNT(sr) ((sr >> NDSR_ERR_CNT_OFF) & NDSR_ERR_CNT_MASK) #define NDSR_RDY (0x1 << 12) #define NDSR_FLASH_RDY (0x1 << 11) #define NDSR_CS0_PAGED (0x1 << 10) @@ -105,8 +108,8 @@ #define NDSR_CS1_CMDD (0x1 << 7) #define NDSR_CS0_BBD (0x1 << 6) #define NDSR_CS1_BBD (0x1 << 5) -#define NDSR_DBERR (0x1 << 4) -#define NDSR_SBERR (0x1 << 3) +#define NDSR_UNCORERR (0x1 << 4) +#define NDSR_CORERR (0x1 << 3) #define NDSR_WRDREQ (0x1 << 2) #define NDSR_RDDREQ (0x1 << 1) #define NDSR_WRCMDREQ (0x1) @@ -147,9 +150,9 @@ enum { ERR_NONE = 0, ERR_DMABUSERR = -1, ERR_SENDCMD = -2, - ERR_DBERR = -3, + ERR_UNCORERR = -3, ERR_BBERR = -4, - ERR_SBERR = -5, + ERR_CORERR = -5, }; enum { @@ -240,6 +243,7 @@ struct pxa3xx_nand_info { unsigned int oob_size; unsigned int spare_size; unsigned int ecc_size; + unsigned int ecc_err_cnt; int retcode; /* cached register value */ @@ -590,10 +594,16 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) status = nand_readl(info, NDSR); - if (status & NDSR_DBERR) - info->retcode = ERR_DBERR; - if (status & NDSR_SBERR) - info->retcode = ERR_SBERR; + if (status & NDSR_UNCORERR) + info->retcode = ERR_UNCORERR; + if (status & NDSR_CORERR) { + info->retcode = ERR_CORERR; + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370 && + info->ecc_bch) + info->ecc_err_cnt = NDSR_ERR_CNT(status); + else + info->ecc_err_cnt = 1; + } if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) { /* whether use dma to transfer data */ if (info->use_dma) { @@ -692,6 +702,7 @@ static void prepare_start_command(struct pxa3xx_nand_info *info, int command) info->use_ecc = 0; info->use_spare = 1; info->retcode = ERR_NONE; + info->ecc_err_cnt = 0; info->ndcb3 = 0; switch (command) { @@ -1077,20 +1088,14 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, chip->read_buf(mtd, buf, mtd->writesize); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); - if (info->retcode == ERR_SBERR) { - switch (info->use_ecc) { - case 1: - mtd->ecc_stats.corrected++; - break; - case 0: - default: - break; - } - } else if (info->retcode == ERR_DBERR) { + if (info->retcode == ERR_CORERR && info->use_ecc) { + mtd->ecc_stats.corrected += info->ecc_err_cnt; + + } else if (info->retcode == ERR_UNCORERR) { /* * for blank page (all 0xff), HW will calculate its ECC as * 0, which is different from the ECC information within - * OOB, ignore such double bit errors + * OOB, ignore such ucorrectable errors */ if (is_buf_blank(buf, mtd->writesize)) info->retcode = ERR_NONE;