From patchwork Mon Jan 29 16:01:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Agner X-Patchwork-Id: 867180 X-Patchwork-Delegate: sbabic@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=agner.ch header.i=@agner.ch header.b="n3IqYW7K"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3zVZ7P2DKHz9s7F for ; Tue, 30 Jan 2018 03:03:45 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id E2A89C21F69; Mon, 29 Jan 2018 16:02:46 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_DNSWL_BLOCKED, SPF_HELO_PASS, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 9E76AC21F84; Mon, 29 Jan 2018 16:01:37 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id C3605C21CEC; Mon, 29 Jan 2018 16:01:33 +0000 (UTC) Received: from mail.kmu-office.ch (mail.kmu-office.ch [178.209.48.109]) by lists.denx.de (Postfix) with ESMTPS id 7C8B6C21CA6 for ; Mon, 29 Jan 2018 16:01:33 +0000 (UTC) Received: from trochilidae.toradex.int (unknown [46.140.72.82]) by mail.kmu-office.ch (Postfix) with ESMTPSA id F1C945C52F5; Mon, 29 Jan 2018 16:54:22 +0100 (CET) From: Stefan Agner To: u-boot@lists.denx.de, Stefano Babic Date: Mon, 29 Jan 2018 17:01:22 +0100 Message-Id: <20180129160122.925-4-stefan@agner.ch> X-Mailer: git-send-email 2.16.1 In-Reply-To: <20180129160122.925-1-stefan@agner.ch> References: <20180129160122.925-1-stefan@agner.ch> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=agner.ch; s=dkim; t=1517241263; bh=vW9LfhbbhhWTHgSm0fyo3Zk8L7x0NbQGyHwvav+gtkE=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References; b=n3IqYW7Kej2+za2IKMytGt4UzL4Wh84YaCWU0SRurgVRgL2Urtcx8gFexg/xhHwlJlKBeQyNHzle8h2+YGRkbYz+A8+ViDvmjEIMlEuJgTpe2mJ4d+X+IBfllEnxee5EgOOwz8nzodHb/xPpv37LsQE02qIvQbGOBkFnOTj6IfI= Cc: marex@denx.de, Marcel Ziswiler , Stefan Agner , Max Krummenacher Subject: [U-Boot] [PATCH 4/4] mtd: nand: mxs_nand: add minimal ECC support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: Stefan Agner Add support for minimum ECC strength supported by the NAND chip. This aligns with the behavior when using the fsl,use-minimum-ecc device tree property in Linux. Signed-off-by: Stefan Agner --- drivers/mtd/nand/Kconfig | 8 +++++ drivers/mtd/nand/mxs_nand.c | 71 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 65 insertions(+), 14 deletions(-) diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 1ca86925dc..982e4e8374 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -146,6 +146,14 @@ config NAND_MXS This enables NAND driver for the NAND flash controller on the MXS processors. +if NAND_MXS + +config NAND_MXS_USE_MINIMUM_ECC + bool "Use minimum ECC strength supported by the controller" + default false + +endif + config NAND_ZYNQ bool "Support for Zynq Nand controller" select SYS_NAND_SELF_INIT diff --git a/drivers/mtd/nand/mxs_nand.c b/drivers/mtd/nand/mxs_nand.c index 5b9398bd98..e33b0df7ac 100644 --- a/drivers/mtd/nand/mxs_nand.c +++ b/drivers/mtd/nand/mxs_nand.c @@ -211,11 +211,52 @@ static inline int mxs_nand_calc_mark_offset(struct bch_geometry *geo, return 0; } +static inline unsigned int mxs_nand_max_ecc_strength_supported(void) +{ + /* Refer to Chapter 17 for i.MX6DQ, Chapter 18 for i.MX6SX */ + if (is_mx6sx() || is_mx7()) + return 62; + else + return 40; +} + +static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo, + struct mtd_info *mtd) +{ + struct nand_chip *chip = mtd_to_nand(mtd); + + if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0)) + return -ENOTSUPP; + + switch (chip->ecc_step_ds) { + case SZ_512: + geo->gf_len = 13; + break; + case SZ_1K: + geo->gf_len = 14; + break; + default: + return -EINVAL; + } + + geo->ecc_chunk_size = chip->ecc_step_ds; + geo->ecc_strength = round_up(chip->ecc_strength_ds, 2); + + /* Keep the C >= O */ + if (geo->ecc_chunk_size < mtd->oobsize) + return -EINVAL; + + if (geo->ecc_strength > mxs_nand_max_ecc_strength_supported()) + return -EINVAL; + + geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size; + + return 0; +} + static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo, struct mtd_info *mtd) { - unsigned int max_ecc_strength_supported; - /* The default for the length of Galois Field. */ geo->gf_len = 13; @@ -235,12 +276,6 @@ static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo, geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size; - /* Refer to Chapter 17 for i.MX6DQ, Chapter 18 for i.MX6SX */ - if (is_mx6sx() || is_mx7()) - max_ecc_strength_supported = 62; - else - max_ecc_strength_supported = 40; - /* * Determine the ECC layout with the formula: * ECC bits per chunk = (total page spare data bits) / @@ -252,10 +287,8 @@ static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo, geo->ecc_strength = ((mtd->oobsize - MXS_NAND_METADATA_SIZE) * 8) / (geo->gf_len * geo->ecc_chunk_count); - geo->ecc_strength = min(round_down(geo->ecc_strength, 2), max_ecc_strength_supported); - - if (mxs_nand_calc_mark_offset(geo, mtd->writesize) < 0) - return -EINVAL; + geo->ecc_strength = min(round_down(geo->ecc_strength, 2), + mxs_nand_max_ecc_strength_supported()); return 0; } @@ -1006,9 +1039,19 @@ static int mxs_nand_setup_ecc(struct mtd_info *mtd) struct bch_geometry *geo = &nand_info->bch_geometry; struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE; uint32_t tmp; + int ret = -ENOTSUPP; - if (mxs_nand_calc_ecc_layout(geo, mtd)) - return -EINVAL; +#ifdef CONFIG_NAND_MXS_USE_MINIMUM_ECC + ret = mxs_nand_calc_ecc_layout_by_info(geo, mtd); +#endif + + if (ret == -ENOTSUPP) + ret = mxs_nand_calc_ecc_layout(geo, mtd); + + if (ret) + return ret; + + mxs_nand_calc_mark_offset(geo, mtd->writesize); /* Configure BCH and set NFC geometry */ mxs_reset_block(&bch_regs->hw_bch_ctrl_reg);