linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Masahiro Yamada <yamada.masahiro@socionext.com>
To: linux-mtd@lists.infradead.org
Cc: Masahiro Yamada <yamada.masahiro@socionext.com>,
	linux-kernel@vger.kernel.org,
	Boris Brezillon <boris.brezillon@free-electrons.com>,
	Marek Vasut <marek.vasut@gmail.com>,
	Brian Norris <computersforpeace@gmail.com>,
	Richard Weinberger <richard@nod.at>,
	David Woodhouse <dwmw2@infradead.org>,
	Cyrille Pitchen <cyrille.pitchen@atmel.com>
Subject: [PATCH 17/39] mtd: nand: denali: support HW_ECC_FIXUP capability
Date: Sun, 27 Nov 2016 03:06:03 +0900	[thread overview]
Message-ID: <1480183585-592-18-git-send-email-yamada.masahiro@socionext.com> (raw)
In-Reply-To: <1480183585-592-1-git-send-email-yamada.masahiro@socionext.com>

Some old versions of the Denali IP (perhaps used only for Intel?)
detects ECC errors and provides correct data via a register, but
does not touch the transferred data.  So, the software must fixup
the data in the buffer according to the provided ECC correction
information.

Newer versions perform ECC correction before transferring the data.
No more software intervention is needed.  The ECC_ERROR_ADDRESS and
ECC_CORRECTION_INFO registers were deprecated.  Instead, the number
of corrected bit-flips can be read from the ECC_COR_INFO register.
When an uncorrectable ECC error happens, a status flag is set to the
INTR_STATUS and ECC_COR_INFO registers.

As is often the case with this IP, the register view of INTR_STATUS
had broken compatibility.

For older versions (SW ECC fixup):
  bit 0:  ECC_TRANSACTION_DONE
  bit 1:  ECC_ERR

For newer versions (HW ECC fixup):
  bit 0:  ECC_UNCOR_ERR
  bit 1:  Reserved

Due to this difference, the irq_mask must be fixed too.  The comment
block in the denali_sw_ecc_fixup() has been moved to the common part
because the comment applies to both cases.

The U-Boot port of this driver already supports the HW ECC fixup.  I
borrowed the comment "Some versions of ..." in denali.h from U-Boot.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

 drivers/mtd/nand/denali.c | 44 ++++++++++++++++++++++++++++++++++----------
 drivers/mtd/nand/denali.h | 14 ++++++++++++++
 2 files changed, 48 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 271b41a..c101e7f 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -894,6 +894,25 @@ static bool is_erased(u8 *buf, int len)
 			return false;
 	return true;
 }
+
+static bool denali_hw_ecc_fixup(struct denali_nand_info *denali,
+				unsigned int *max_bitflips)
+{
+	int bank = denali->flash_bank;
+	u32 ecc_cor;
+
+	ecc_cor = ioread32(denali->flash_reg + ECC_COR_INFO(bank));
+	ecc_cor >>= ECC_COR_INFO_SHIFT(bank);
+
+	if (ecc_cor & ECC_COR_INFO__UNCOR_ERR) {
+		*max_bitflips = 0;
+		return true;
+	}
+
+	*max_bitflips = ecc_cor & ECC_COR_INFO__MAX_ERRORS;
+	return false;
+}
+
 #define ECC_SECTOR_SIZE 512
 
 #define ECC_SECTOR(x)	(((x) & ECC_ERROR_ADDRESS__SECTOR_NR) >> 12)
@@ -949,11 +968,6 @@ static bool denali_sw_ecc_fixup(struct denali_nand_info *denali, u8 *buf,
 				bitflips++;
 			}
 		} else {
-			/*
-			 * if the error is not correctable, need to look at the
-			 * page to see if it is an erased page. if so, then
-			 * it's not a real ECC error
-			 */
 			check_erased_page = true;
 		}
 	} while (!ECC_LAST_ERR(err_correction_info));
@@ -1109,12 +1123,12 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 {
 	unsigned int max_bitflips;
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-
 	dma_addr_t addr = denali->buf.dma_buf;
 	size_t size = mtd->writesize + mtd->oobsize;
-
 	u32 irq_status;
-	u32 irq_mask = INTR_STATUS__ECC_TRANSACTION_DONE | INTR_STATUS__ECC_ERR;
+	u32 irq_mask = denali->caps & DENALI_CAPS_HW_ECC_FIXUP ?
+		INTR_STATUS__DMA_CMD_COMP | INTR_STATUS__ECC_UNCOR_ERR :
+		INTR_STATUS__ECC_TRANSACTION_DONE | INTR_STATUS__ECC_ERR;
 	bool check_erased_page = false;
 
 	if (page != denali->page) {
@@ -1139,11 +1153,21 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 
 	memcpy(buf, denali->buf.buf, mtd->writesize);
 
-	check_erased_page = denali_sw_ecc_fixup(denali, buf, irq_status,
-						&max_bitflips);
+	if (denali->caps & DENALI_CAPS_HW_ECC_FIXUP)
+		check_erased_page = denali_hw_ecc_fixup(denali, &max_bitflips);
+	else
+		check_erased_page = denali_sw_ecc_fixup(denali, buf, irq_status,
+							&max_bitflips);
+
 	denali_enable_dma(denali, false);
 
 	if (check_erased_page) {
+		/*
+		 * If the error is not correctable, need to look at the page to
+		 * see if it is an erased page. If so, then it's not a real ECC
+		 * error.
+		 */
+
 		read_oob_data(mtd, chip->oob_poi, denali->page);
 
 		/* check ECC failures that may have occurred on erased pages */
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index 69314d0..beadc8a 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -20,6 +20,7 @@
 #ifndef __DENALI_H__
 #define __DENALI_H__
 
+#include <linux/bitops.h>
 #include <linux/mtd/nand.h>
 
 #define DEVICE_RESET				0x0
@@ -219,6 +220,13 @@
 #define INTR_STATUS(__bank)	(0x410 + ((__bank) * 0x50))
 #define INTR_EN(__bank)		(0x420 + ((__bank) * 0x50))
 
+/*
+ * Some versions of the IP have the ECC fixup handled in hardware.  In this
+ * configuration we only get interrupted when the error is uncorrectable.
+ * Unfortunately this bit replaces INTR_STATUS__ECC_TRANSACTION_DONE from the
+ * old IP.
+ */
+#define     INTR_STATUS__ECC_UNCOR_ERR			0x0001
 #define     INTR_STATUS__ECC_TRANSACTION_DONE		0x0001
 #define     INTR_STATUS__ECC_ERR			0x0002
 #define     INTR_STATUS__DMA_CMD_COMP			0x0004
@@ -297,6 +305,11 @@
 #define     ERR_CORRECTION_INFO__ERROR_TYPE		0x4000
 #define     ERR_CORRECTION_INFO__LAST_ERR_INFO		0x8000
 
+#define ECC_COR_INFO(__bank)	(0x650 + (__bank) / 2 * 0x10)
+#define ECC_COR_INFO_SHIFT(__bank)	((__bank) % 2 * 8)
+#define     ECC_COR_INFO__MAX_ERRORS			0x007f
+#define     ECC_COR_INFO__UNCOR_ERR			0x0080
+
 #define DMA_ENABLE				0x700
 #define     DMA_ENABLE__FLAG				0x0001
 
@@ -421,6 +434,7 @@ struct denali_nand_info {
 	u32 bbtskipbytes;
 	u32 max_banks;
 	unsigned int caps;
+#define DENALI_CAPS_HW_ECC_FIXUP		BIT(0)
 };
 
 extern int denali_init(struct denali_nand_info *denali);
-- 
2.7.4

  parent reply	other threads:[~2016-11-26 18:09 UTC|newest]

Thread overview: 94+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-26 18:05 [PATCH 00/39] mtd: nand: denali: 2nd round of Denali NAND IP patch bomb Masahiro Yamada
2016-11-26 18:05 ` [PATCH 01/39] mtd: nand: allow to set only one of ECC size and ECC strength from DT Masahiro Yamada
2016-11-27 13:58   ` Boris Brezillon
2016-11-26 18:05 ` [PATCH 02/39] mtd: nand: denali: remove unused CONFIG option and macros Masahiro Yamada
2016-11-26 18:05 ` [PATCH 03/39] mtd: nand: denali: remove redundant define of BANK(x) Masahiro Yamada
2016-11-26 18:05 ` [PATCH 04/39] mtd: nand: denali: remove more unused struct members Masahiro Yamada
2016-11-27 15:12   ` Boris Brezillon
2016-11-30  7:16     ` Masahiro Yamada
2016-11-30  7:47       ` Boris Brezillon
2016-11-26 18:05 ` [PATCH 05/39] mtd: nand: denali: fix comment of denali_nand_info::flash_mem Masahiro Yamada
2016-11-26 18:05 ` [PATCH 06/39] mtd: nand: denali: fix write_oob_data() function Masahiro Yamada
2016-11-26 18:05 ` [PATCH 07/39] mtd: nand: denali: transfer OOB only when oob_required is set Masahiro Yamada
2016-11-26 18:05 ` [PATCH 08/39] mtd: nand: denali: introduce capability flag Masahiro Yamada
2016-11-26 18:05 ` [PATCH 09/39] mtd: nand: denali: fix erased page check code Masahiro Yamada
2016-11-27 15:21   ` Boris Brezillon
2016-12-02  4:33     ` Masahiro Yamada
2016-12-02  7:57       ` Boris Brezillon
2016-11-26 18:05 ` [PATCH 10/39] mtd: nand: denali: remove redundant if conditional of erased_check Masahiro Yamada
2016-11-26 18:05 ` [PATCH 11/39] mtd: nand: denali: increment ecc_stats.failed by one per error Masahiro Yamada
2016-11-26 18:05 ` [PATCH 12/39] mtd: nand: denali: return 0 for uncorrectable ECC error Masahiro Yamada
2016-11-26 18:05 ` [PATCH 13/39] mtd: nand: denali: increment ecc_stats->corrected Masahiro Yamada
2016-11-27 15:31   ` Boris Brezillon
2016-12-02  4:28     ` Masahiro Yamada
2016-11-26 18:06 ` [PATCH 14/39] mtd: nand: denali: replace uint{8/16/32}_t with u{8/16/32} Masahiro Yamada
2016-11-26 18:06 ` [PATCH 15/39] mtd: nand: denali: improve readability of handle_ecc() Masahiro Yamada
2016-11-27 15:34   ` Boris Brezillon
2016-11-27 15:42   ` Boris Brezillon
2016-12-02  4:26     ` Masahiro Yamada
2016-12-02  7:55       ` Boris Brezillon
2016-11-26 18:06 ` [PATCH 16/39] mtd: nand: denali: rename handle_ecc() to denali_sw_ecc_fixup() Masahiro Yamada
2016-11-26 18:06 ` Masahiro Yamada [this message]
2016-11-27 16:09   ` [PATCH 17/39] mtd: nand: denali: support HW_ECC_FIXUP capability Boris Brezillon
2016-11-30  6:20     ` Masahiro Yamada
2016-11-30  7:51       ` Boris Brezillon
2016-11-26 18:06 ` [PATCH 18/39] mtd: nand: denali: move denali_read_page_raw() above denali_read_page() Masahiro Yamada
2016-11-27 16:10   ` Boris Brezillon
2016-11-30  6:13     ` Masahiro Yamada
2016-11-26 18:06 ` [PATCH 19/39] mtd: nand: denali: perform erased check against raw transferred page Masahiro Yamada
2016-11-27 16:12   ` Boris Brezillon
2016-11-30  5:36     ` Masahiro Yamada
2016-11-30  8:00       ` Boris Brezillon
2016-11-26 18:06 ` [PATCH 20/39] mtd: nand: denali_dt: enable HW_ECC_FIXUP capability for DT platform Masahiro Yamada
2016-11-27 16:14   ` Boris Brezillon
2016-11-30  6:14     ` Masahiro Yamada
2016-11-26 18:06 ` [PATCH 21/39] mtd: nand: denali: support 64bit capable DMA engine Masahiro Yamada
2016-11-27 16:16   ` Boris Brezillon
2016-11-30  7:11     ` Masahiro Yamada
2016-11-30  7:17       ` Boris Brezillon
2016-11-26 18:06 ` [PATCH 22/39] mtd: nand: denali_dt: remove dma-mask DT property Masahiro Yamada
2016-12-01 15:56   ` Rob Herring
2016-11-26 18:06 ` [PATCH 23/39] mtd: nand: denali_dt: use pdev instead of ofdev for platform_device Masahiro Yamada
2016-11-26 18:06 ` [PATCH 24/39] mtd: nand: denali: add NEW_N_BANKS_FORMAT capability Masahiro Yamada
2016-11-26 18:06 ` [PATCH 25/39] mtd: nand: denali: use nand_chip to hold frequently accessed data Masahiro Yamada
2016-11-26 18:06 ` [PATCH 26/39] mtd: nand: denali: call nand_set_flash_node() to set DT node Masahiro Yamada
2016-11-26 18:06 ` [PATCH 27/39] mtd: nand: denali: do not set mtd->name Masahiro Yamada
2016-11-26 18:06 ` [PATCH 28/39] mtd: nand: denali: move multi NAND fixup code to a helper function Masahiro Yamada
2016-11-27 16:24   ` Boris Brezillon
2016-11-30  6:09     ` Masahiro Yamada
2016-11-30  8:07       ` Boris Brezillon
2016-11-26 18:06 ` [PATCH 29/39] mtd: nand: denali: refactor multi NAND fixup code in more generic way Masahiro Yamada
2016-11-26 18:06 ` [PATCH 30/39] mtd: nand: denali: set DEVICES_CONNECTED 1 if not set Masahiro Yamada
2016-11-26 18:06 ` [PATCH 31/39] mtd: nand: denali: remove meaningless writes to read-only registers Masahiro Yamada
2016-11-26 18:06 ` [PATCH 32/39] mtd: nand: denali: remove unnecessary writes to ECC_CORRECTION Masahiro Yamada
2016-11-26 18:06 ` [PATCH 33/39] mtd: nand: denali: support 1024 byte ECC step size Masahiro Yamada
2016-12-01 15:58   ` Rob Herring
2016-11-26 18:06 ` [PATCH 34/39] mtd: nand: denali: fix the condition for 15 bit ECC strength Masahiro Yamada
2016-11-26 18:06 ` [PATCH 35/39] mtd: nand: denali: calculate ecc.strength and ecc.bytes generically Masahiro Yamada
2016-11-26 18:06 ` [PATCH 36/39] mtd: nand: denali: allow to use SoC-specific ECC strength Masahiro Yamada
2016-11-26 18:06 ` [PATCH 37/39] mtd: nand: denali: support "nand-ecc-strength" DT property Masahiro Yamada
2016-12-01 15:59   ` Rob Herring
2016-11-26 18:06 ` [PATCH 38/39] mtd: nand: denali: remove Toshiba, Hynix specific fixup code Masahiro Yamada
2016-11-27 16:28   ` Boris Brezillon
2016-11-26 18:06 ` [PATCH 39/39] mtd: nand: denali_dt: add compatible strings for UniPhier SoC variants Masahiro Yamada
2016-12-01 16:05   ` Rob Herring
2016-12-02  2:54     ` Masahiro Yamada
2016-12-02 16:26       ` Rob Herring
2016-12-03  2:41         ` Masahiro Yamada
2016-12-03  2:49           ` Marek Vasut
2016-12-03 22:08             ` Dinh Nguyen
2016-12-05  3:30               ` Masahiro Yamada
2016-12-05  3:44                 ` Marek Vasut
2016-12-05  4:10                   ` Masahiro Yamada
2016-12-05  4:22                     ` Marek Vasut
2016-12-05 20:51                       ` Dinh Nguyen
2016-12-05 21:29                         ` Marek Vasut
2016-12-05 22:31                           ` Dinh Nguyen
2016-11-27 15:04 ` [PATCH 00/39] mtd: nand: denali: 2nd round of Denali NAND IP patch bomb Boris Brezillon
2016-11-30  8:02   ` Masahiro Yamada
2016-11-30  8:17     ` Boris Brezillon
2016-12-01  9:15       ` Masahiro Yamada
2017-03-10 11:00       ` Masahiro Yamada
2017-03-13 11:33         ` Boris Brezillon
2016-11-30  8:13   ` Masahiro Yamada
2016-11-27 16:31 ` Boris Brezillon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1480183585-592-18-git-send-email-yamada.masahiro@socionext.com \
    --to=yamada.masahiro@socionext.com \
    --cc=boris.brezillon@free-electrons.com \
    --cc=computersforpeace@gmail.com \
    --cc=cyrille.pitchen@atmel.com \
    --cc=dwmw2@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=marek.vasut@gmail.com \
    --cc=richard@nod.at \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).