From patchwork Fri Oct 18 23:02:41 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ezequiel Garcia X-Patchwork-Id: 3070451 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 73358BF924 for ; Fri, 18 Oct 2013 23:10:01 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9755620489 for ; Fri, 18 Oct 2013 23:10:00 +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 77A1820222 for ; Fri, 18 Oct 2013 23:09:59 +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 1VXJ9p-0005Gb-Mx; Fri, 18 Oct 2013 23:08:38 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VXJ9b-0001Wc-Pt; Fri, 18 Oct 2013 23:08:23 +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 1VXJ5I-00010J-MG; Fri, 18 Oct 2013 23:03:58 +0000 Received: by mail.free-electrons.com (Postfix, from userid 106) id 127838C1; Sat, 19 Oct 2013 01:03:40 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Spam-Level: X-Spam-Status: No, score=-4.6 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 7177C8B8; Sat, 19 Oct 2013 01:03:36 +0200 (CEST) From: Ezequiel Garcia To: , Subject: [PATCH v2 14/27] mtd: nand: pxa3xx: Add driver-specific ECC BCH support Date: Fri, 18 Oct 2013 20:02:41 -0300 Message-Id: <1382137374-21251-15-git-send-email-ezequiel.garcia@free-electrons.com> X-Mailer: git-send-email 1.8.1.5 In-Reply-To: <1382137374-21251-1-git-send-email-ezequiel.garcia@free-electrons.com> References: <1382137374-21251-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-20131018_190356_980107_BD5A11A2 X-CRM114-Status: GOOD ( 17.20 ) X-Spam-Score: -1.7 (-) Cc: Lior Amsalem , Thomas Petazzoni , Jason Cooper , Tawfik Bayouk , Daniel Mack , 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 adds the BCH ECC support available in NFCv2 controller. Depending on the detected required strength the respective ECC layout is selected. This commit adds an empty ECC layout, since support to access large pages is first required. Once that support is added, a proper ECC layout will be added as well. Signed-off-by: Ezequiel Garcia --- drivers/mtd/nand/pxa3xx_nand.c | 90 +++++++++++++++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 18 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 451ebb6..5774ce9 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -56,6 +56,7 @@ #define NDPCR (0x18) /* Page Count Register */ #define NDBDR0 (0x1C) /* Bad Block Register 0 */ #define NDBDR1 (0x20) /* Bad Block Register 1 */ +#define NDECCCTRL (0x28) /* ECC control */ #define NDDB (0x40) /* Data Buffer */ #define NDCB0 (0x48) /* Command Buffer0 */ #define NDCB1 (0x4C) /* Command Buffer1 */ @@ -196,6 +197,7 @@ struct pxa3xx_nand_info { int cs; int use_ecc; /* use HW ECC ? */ + int ecc_bch; /* using BCH ECC? */ int use_dma; /* use DMA ? */ int use_spare; /* use spare ? */ @@ -209,6 +211,8 @@ struct pxa3xx_nand_info { unsigned int fifo_size; /* max. data size in the FIFO */ unsigned int data_size; /* data to be read from FIFO */ unsigned int oob_size; + unsigned int spare_size; + unsigned int ecc_size; int retcode; /* cached register value */ @@ -343,19 +347,12 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; info->data_size = info->fifo_size; - if (!oob_enable) { + if (!oob_enable) info->oob_size = 0; - return; - } - - switch (info->fifo_size) { - case 2048: - info->oob_size = (info->use_ecc) ? 40 : 64; - break; - case 512: - info->oob_size = (info->use_ecc) ? 8 : 16; - break; - } + else if (info->use_ecc) + info->oob_size = info->spare_size; + else + info->oob_size = info->spare_size + info->ecc_size; } /** @@ -370,10 +367,15 @@ static void pxa3xx_nand_start(struct pxa3xx_nand_info *info) ndcr = info->reg_ndcr; - if (info->use_ecc) + if (info->use_ecc) { ndcr |= NDCR_ECC_EN; - else + if (info->ecc_bch) + nand_writel(info, NDECCCTRL, 0x1); + } else { ndcr &= ~NDCR_ECC_EN; + if (info->ecc_bch) + nand_writel(info, NDECCCTRL, 0x0); + } if (info->use_dma) ndcr |= NDCR_DMA_EN; @@ -1074,6 +1076,43 @@ static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) return -ENODEV; } +static int pxa_ecc_init(struct pxa3xx_nand_info *info, + struct nand_ecc_ctrl *ecc, + int strength, int page_size) +{ + /* + * We don't use strength here as the PXA variant + * is used with non-ONFI compliant devices. + */ + if (page_size == 2048) { + ecc->mode = NAND_ECC_HW; + ecc->size = 512; + ecc->strength = 1; + + info->spare_size = 40; + info->ecc_size = 24; + return 1; + + } else if (page_size == 512) { + ecc->mode = NAND_ECC_HW; + ecc->size = 512; + ecc->strength = 1; + + info->spare_size = 8; + info->ecc_size = 8; + return 1; + } + return 0; +} + +static int armada370_ecc_init(struct pxa3xx_nand_info *info, + struct nand_ecc_ctrl *ecc, + int strength, int page_size) +{ + /* Unimplemented yet */ + return 0; +} + static int pxa3xx_nand_scan(struct mtd_info *mtd) { struct pxa3xx_nand_host *host = mtd->priv; @@ -1144,13 +1183,13 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) pxa3xx_flash_ids[1].name = NULL; def = pxa3xx_flash_ids; KEEP_CONFIG: - chip->ecc.mode = NAND_ECC_HW; - chip->ecc.size = host->page_size; - chip->ecc.strength = 1; - if (info->reg_ndcr & NDCR_DWIDTH_M) chip->options |= NAND_BUSWIDTH_16; + /* Device detection must be done with ECC disabled */ + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) + nand_writel(info, NDECCCTRL, 0x0); + if (nand_scan_ident(mtd, 1, def)) return -ENODEV; @@ -1161,6 +1200,21 @@ KEEP_CONFIG: chip->bbt_md = &bbt_mirror_descr; } + if (info->variant == PXA3XX_NAND_VARIANT_ARMADA370) + ret = armada370_ecc_init(info, &chip->ecc, + chip->ecc_strength_ds, + mtd->writesize); + else + ret = pxa_ecc_init(info, &chip->ecc, + chip->ecc_strength_ds, + mtd->writesize); + if (!ret) { + dev_err(&info->pdev->dev, + "ECC strength %d at page size %d is not supported\n", + chip->ecc_strength_ds, mtd->writesize); + return -ENODEV; + } + /* calculate addressing information */ if (mtd->writesize >= 2048) host->col_addr_cycles = 2;