Received: by 2002:ab2:7855:0:b0:1f9:5764:f03e with SMTP id m21csp137406lqp; Tue, 21 May 2024 22:40:57 -0700 (PDT) X-Forwarded-Encrypted: i=3; AJvYcCWsUOGv6qOdlHvYGZC6L5uU721I+LEukpbI02pJXY3ufP64Stqdx09xOJ8RVrbC0Ls3UcTLYMhGxL1TpR9kOCcVnmhzP8EOj2x51nl/xQ== X-Google-Smtp-Source: AGHT+IGxYG8RJTvAjmRPghYCmWeKT73KFfGip805R8atx6Kp7imsvcJ60zhgUX2YDxEe26wZocdd X-Received: by 2002:a05:6a20:2d2a:b0:1af:a475:e043 with SMTP id adf61e73a8af0-1b1f87e9ec1mr2064604637.32.1716356457149; Tue, 21 May 2024 22:40:57 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1716356457; cv=pass; d=google.com; s=arc-20160816; b=zFMywSbzrlXnuphfbbHOqs1E6NpxpH5g3CDFawHEyHL1Mowhdc1QklCvviTh1c4NZi fFlkoQKWHGWhLcQwhAig/+wd42Fr6Omw83ZATZ28TYJPFuBBhFju7fAWhCaAEa4iYwHK 6syCdOGMMAPT9s2/EM83oXfVyPuM9JhIWIHVscAt1R96bIdg/SIMOhpoBHD6WKnBES95 wz5D/IWJ7cJLQXiqRSqdzBlGrA/M3/afEi65V4asq89nj/q6nOvZW3k0Sp6VDICch2t8 7yG8BHhqIPKU038lTRPaC/fF8FhCZY3Gl2FgQeF4YqwoFr9v1C1WZq/UCcojeY65DpOd 2eZQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:list-unsubscribe:list-subscribe:list-id:precedence :subject:date:from; bh=5Vs37mzsjs8hCoVm4nRvStwuALHScBsR83TLF4+t1D0=; fh=A6vTKu2Ae1sKKtFnOKaQ4OlMrHeYs/jXUw2105gYFpM=; b=yY0S6yZtJ88G0kw8/DzHe3hhojEq+XvZ8rwfuJZ1RDT0fyTIzNuX5WI05Ztn+rnI1T LfKxGJ7JnjSDcR4gWgquqyPsuyUE8PlIbynuQq7Xl/mu9nbdfPFPzEmbsHIOEl5nN01A GP5SsfihpMkAll7ZdP2RucR2c7wo00MJuhJUhD3fyDB8PadwtBRmjCOOOl+x5wBOr+OM 13ySt3kcnxLjMGhvOu7gX0TTgUEx1IGJJPYwO9sU26oMb9A6z8oKOia9sxZqNy6IzN/1 BR4NquiG5Y9f5dytSyTC/ao6YcKWu3XUFz3CiGbbqIBhXPf1LLHLPe+0GFdGc1olbLAO a6uQ==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; arc=pass (i=1 spf=pass spfdomain=pengutronix.de); spf=pass (google.com: domain of linux-kernel+bounces-185781-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-185781-linux.lists.archive=gmail.com@vger.kernel.org" Return-Path: Received: from sv.mirrors.kernel.org (sv.mirrors.kernel.org. [2604:1380:45e3:2400::1]) by mx.google.com with ESMTPS id d9443c01a7336-1ef0bad8441si243361825ad.185.2024.05.21.22.40.56 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 May 2024 22:40:57 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel+bounces-185781-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) client-ip=2604:1380:45e3:2400::1; Authentication-Results: mx.google.com; arc=pass (i=1 spf=pass spfdomain=pengutronix.de); spf=pass (google.com: domain of linux-kernel+bounces-185781-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45e3:2400::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-185781-linux.lists.archive=gmail.com@vger.kernel.org" Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sv.mirrors.kernel.org (Postfix) with ESMTPS id BBD282828FF for ; Wed, 22 May 2024 05:40:56 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 923737711F; Wed, 22 May 2024 05:40:20 +0000 (UTC) Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [185.203.201.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7C7507710C for ; Wed, 22 May 2024 05:40:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.201.7 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716356419; cv=none; b=SRo4hvQ1E/a+FJzuhlNe7OUsniK78S+3kCBcklDioK5ZuXb6eRluBZsr9rqjnf5vmACzFiO8JZejOxjdbrJ+rNe5BHmpl3Nw4X8eJWeHEct0V0jPzJFnRKbgTPDi1rNTA2eJNXUeg0tA4qnuHJV3iRZsU8CeUVY2Nv3cH81J2CY= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1716356419; c=relaxed/simple; bh=7BAnbozBUGliEkFA2yy81ruk4ikDMyqp7A70k41kDBQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WyKWaPBOOTkzp6Yv3LB8rHqkuvmDnZwEnwTozCE2o9lIccWOh4V8/4vYwuq4jIIi8LhwIXOCVRUCmuJukCTRXah/cMdRUJ4E04runymX4rjdPJ33z/6LJAA9JDdZLB2XnVapQ+8+ZsSlWX9I3RfD4Razk1BgZsZh5BpjyTfnYrc= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.201.7 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1s9ehj-0003dZ-JJ; Wed, 22 May 2024 07:39:59 +0200 Received: from [2a0a:edc0:0:1101:1d::28] (helo=dude02.red.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1s9ehg-002U0s-OJ; Wed, 22 May 2024 07:39:56 +0200 Received: from localhost ([::1] helo=dude02.red.stw.pengutronix.de) by dude02.red.stw.pengutronix.de with esmtp (Exim 4.96) (envelope-from ) id 1s9ehg-00Dqu2-26; Wed, 22 May 2024 07:39:56 +0200 From: Sascha Hauer Date: Wed, 22 May 2024 07:39:51 +0200 Subject: [PATCH v4 1/3] mtd: nand: mxc_nand: separate page read from ecc calc Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20240522-mtd-nand-mxc-nand-exec-op-v4-1-75b611e0ac44@pengutronix.de> References: <20240522-mtd-nand-mxc-nand-exec-op-v4-0-75b611e0ac44@pengutronix.de> In-Reply-To: <20240522-mtd-nand-mxc-nand-exec-op-v4-0-75b611e0ac44@pengutronix.de> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra Cc: linux-mtd@lists.infradead.org, linux-kernel@vger.kernel.org, Sascha Hauer X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1716356396; l=7729; i=s.hauer@pengutronix.de; s=20230412; h=from:subject:message-id; bh=7BAnbozBUGliEkFA2yy81ruk4ikDMyqp7A70k41kDBQ=; b=k1rA42IW50j9pVIJPSjaiDAHAQE1zGNksRYIP7CwGs6nq0J0uHy3JeKS6N09Eughvq/6o4Cy1 AzOIdp7zcvbDKDwbiVqBKpxOhgdKtD2YZiJcTiv97zbGwlhmdf8T4Es X-Developer-Key: i=s.hauer@pengutronix.de; a=ed25519; pk=4kuc9ocmECiBJKWxYgqyhtZOHj5AWi7+d0n/UjhkwTg= X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: s.hauer@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org Our read_page hook currently reads out a page and also counts and returns the number of bitflips. In upcoming exec_op conversion we'll need to read the page data in exec_op, but the bitflip information will be needed in mxc_nand_read_page(). To ease exec_op conversion separate the page read out from the bitflip evaluation. For the v2/v3 controllers we can leave the bitflip information in the status register for later evaluation. For the v1 controller this is not possible, because the status register is overwritten with each subpage read. We therefore store the bitflip information in the private data. Signed-off-by: Sascha Hauer --- drivers/mtd/nand/raw/mxc_nand.c | 140 ++++++++++++++++++++++++---------------- 1 file changed, 86 insertions(+), 54 deletions(-) diff --git a/drivers/mtd/nand/raw/mxc_nand.c b/drivers/mtd/nand/raw/mxc_nand.c index 003008355b3c2..3fe0b471f4a2d 100644 --- a/drivers/mtd/nand/raw/mxc_nand.c +++ b/drivers/mtd/nand/raw/mxc_nand.c @@ -20,6 +20,7 @@ #include #include #include +#include #define DRIVER_NAME "mxc_nand" @@ -47,6 +48,8 @@ #define NFC_V1_V2_CONFIG1 (host->regs + 0x1a) #define NFC_V1_V2_CONFIG2 (host->regs + 0x1c) +#define NFC_V1_V2_ECC_STATUS_RESULT_ERM GENMASK(3, 2) + #define NFC_V2_CONFIG1_ECC_MODE_4 (1 << 0) #define NFC_V1_V2_CONFIG1_SP_EN (1 << 2) #define NFC_V1_V2_CONFIG1_ECC_EN (1 << 3) @@ -132,7 +135,7 @@ struct mxc_nand_devtype_data { uint16_t (*get_dev_status)(struct mxc_nand_host *); int (*check_int)(struct mxc_nand_host *); void (*irq_control)(struct mxc_nand_host *, int); - u32 (*get_ecc_status)(struct mxc_nand_host *); + u32 (*get_ecc_status)(struct nand_chip *); const struct mtd_ooblayout_ops *ooblayout; void (*select_chip)(struct nand_chip *chip, int cs); int (*setup_interface)(struct nand_chip *chip, int csline, @@ -175,6 +178,7 @@ struct mxc_nand_host { int eccsize; int used_oobsize; int active_cs; + unsigned int ecc_stats_v1; struct completion op_completion; @@ -406,19 +410,81 @@ static void irq_control(struct mxc_nand_host *host, int activate) } } -static u32 get_ecc_status_v1(struct mxc_nand_host *host) +static u32 get_ecc_status_v1(struct nand_chip *chip) { - return readw(NFC_V1_V2_ECC_STATUS_RESULT); + struct mtd_info *mtd = nand_to_mtd(chip); + struct mxc_nand_host *host = nand_get_controller_data(chip); + unsigned int ecc_stats, max_bitflips = 0; + int no_subpages, i; + + no_subpages = mtd->writesize >> 9; + + ecc_stats = host->ecc_stats_v1; + + for (i = 0; i < no_subpages; i++) { + switch (ecc_stats & 0x3) { + case 0: + default: + break; + case 1: + mtd->ecc_stats.corrected++; + max_bitflips = 1; + break; + case 2: + mtd->ecc_stats.failed++; + break; + } + + ecc_stats >>= 2; + } + + return max_bitflips; } -static u32 get_ecc_status_v2(struct mxc_nand_host *host) +static u32 get_ecc_status_v2_v3(struct nand_chip *chip, unsigned int ecc_stat) { - return readl(NFC_V1_V2_ECC_STATUS_RESULT); + struct mtd_info *mtd = nand_to_mtd(chip); + struct mxc_nand_host *host = nand_get_controller_data(chip); + u8 ecc_bit_mask, err_limit; + unsigned int max_bitflips = 0; + int no_subpages, err; + + ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf; + err_limit = (host->eccsize == 4) ? 0x4 : 0x8; + + no_subpages = mtd->writesize >> 9; + + do { + err = ecc_stat & ecc_bit_mask; + if (err > err_limit) { + mtd->ecc_stats.failed++; + } else { + mtd->ecc_stats.corrected += err; + max_bitflips = max_t(unsigned int, max_bitflips, err); + } + + ecc_stat >>= 4; + } while (--no_subpages); + + return max_bitflips; } -static u32 get_ecc_status_v3(struct mxc_nand_host *host) +static u32 get_ecc_status_v2(struct nand_chip *chip) { - return readl(NFC_V3_ECC_STATUS_RESULT); + struct mxc_nand_host *host = nand_get_controller_data(chip); + + u32 ecc_stat = readl(NFC_V1_V2_ECC_STATUS_RESULT); + + return get_ecc_status_v2_v3(chip, ecc_stat); +} + +static u32 get_ecc_status_v3(struct nand_chip *chip) +{ + struct mxc_nand_host *host = nand_get_controller_data(chip); + + u32 ecc_stat = readl(NFC_V3_ECC_STATUS_RESULT); + + return get_ecc_status_v2_v3(chip, ecc_stat); } static irqreturn_t mxc_nfc_irq(int irq, void *dev_id) @@ -712,9 +778,9 @@ static int mxc_nand_read_page_v1(struct nand_chip *chip, void *buf, void *oob, { struct mtd_info *mtd = nand_to_mtd(chip); struct mxc_nand_host *host = nand_get_controller_data(chip); - unsigned int bitflips_corrected = 0; int no_subpages; int i; + unsigned int ecc_stats = 0; host->devtype_data->enable_hwecc(chip, ecc); @@ -727,8 +793,6 @@ static int mxc_nand_read_page_v1(struct nand_chip *chip, void *buf, void *oob, no_subpages = mtd->writesize >> 9; for (i = 0; i < no_subpages; i++) { - uint16_t ecc_stats; - /* NANDFC buffer 0 is used for page read/write */ writew((host->active_cs << 4) | i, NFC_V1_V2_BUF_ADDR); @@ -737,32 +801,18 @@ static int mxc_nand_read_page_v1(struct nand_chip *chip, void *buf, void *oob, /* Wait for operation to complete */ wait_op_done(host, true); - ecc_stats = get_ecc_status_v1(host); - - ecc_stats >>= 2; - - if (buf && ecc) { - switch (ecc_stats & 0x3) { - case 0: - default: - break; - case 1: - mtd->ecc_stats.corrected++; - bitflips_corrected = 1; - break; - case 2: - mtd->ecc_stats.failed++; - break; - } - } + ecc_stats |= FIELD_GET(NFC_V1_V2_ECC_STATUS_RESULT_ERM, + readw(NFC_V1_V2_ECC_STATUS_RESULT)) << i * 2; } + host->ecc_stats_v1 = ecc_stats; + if (buf) memcpy32_fromio(buf, host->main_area0, mtd->writesize); if (oob) copy_spare(mtd, true, oob); - return bitflips_corrected; + return 0; } static int mxc_nand_read_page_v2_v3(struct nand_chip *chip, void *buf, @@ -770,10 +820,6 @@ static int mxc_nand_read_page_v2_v3(struct nand_chip *chip, void *buf, { struct mtd_info *mtd = nand_to_mtd(chip); struct mxc_nand_host *host = nand_get_controller_data(chip); - unsigned int max_bitflips = 0; - u32 ecc_stat, err; - int no_subpages; - u8 ecc_bit_mask, err_limit; host->devtype_data->enable_hwecc(chip, ecc); @@ -791,26 +837,7 @@ static int mxc_nand_read_page_v2_v3(struct nand_chip *chip, void *buf, if (oob) copy_spare(mtd, true, oob); - ecc_bit_mask = (host->eccsize == 4) ? 0x7 : 0xf; - err_limit = (host->eccsize == 4) ? 0x4 : 0x8; - - no_subpages = mtd->writesize >> 9; - - ecc_stat = host->devtype_data->get_ecc_status(host); - - do { - err = ecc_stat & ecc_bit_mask; - if (err > err_limit) { - mtd->ecc_stats.failed++; - } else { - mtd->ecc_stats.corrected += err; - max_bitflips = max_t(unsigned int, max_bitflips, err); - } - - ecc_stat >>= 4; - } while (--no_subpages); - - return max_bitflips; + return 0; } static int mxc_nand_read_page(struct nand_chip *chip, uint8_t *buf, @@ -818,13 +845,18 @@ static int mxc_nand_read_page(struct nand_chip *chip, uint8_t *buf, { struct mxc_nand_host *host = nand_get_controller_data(chip); void *oob_buf; + int ret; if (oob_required) oob_buf = chip->oob_poi; else oob_buf = NULL; - return host->devtype_data->read_page(chip, buf, oob_buf, 1, page); + ret = host->devtype_data->read_page(chip, buf, oob_buf, 1, page); + if (ret) + return ret; + + return host->devtype_data->get_ecc_status(chip); } static int mxc_nand_read_page_raw(struct nand_chip *chip, uint8_t *buf, -- 2.39.2