All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/14] mtd: nand: i.MX update
@ 2020-05-04 14:08 Peng Fan
  2020-05-04 14:08 ` [PATCH 01/14] mtd: gpmi: change the BCH layout setting for large oob NAND Peng Fan
                   ` (13 more replies)
  0 siblings, 14 replies; 37+ messages in thread
From: Peng Fan @ 2020-05-04 14:08 UTC (permalink / raw)
  To: u-boot

This is to upstream NXP downstream mtd nand patches, including
DT/CLK/i.MX8M/i.MX8/SPL

Alice Guo (2):
  nand: mxs_nand: make imx8mm can use hardware BCH and randomizer
  nand: enable the Randomizer module for i.mx7 and i.mx8

Han Xu (3):
  mtd: nand: mxs_nand: add i.MX6QP compatible string
  mtd: mxs_nand: fix the gf_13/14 definition issue
  mxs_nand: don't check zero count when ECC reading with randomizer

Peng Fan (3):
  nand: mxs: fix the bitflips for erased page when uncorrectable error
  nand: mxs: correct bitflip for erased NAND page
  mtd: nand: support GPMI NAND driver for i.MX8

Ye Li (6):
  mtd: gpmi: change the BCH layout setting for large oob NAND
  mtd: gpmi: provide the option to use legacy bch geometry
  mxs_nand: Add support for i.MX8M
  nand: Update SPL MXS NAND mini driver
  mxs_nand: Update compatible string for i.MX6SX
  MXS_NAND: Add clock support for iMX8

 arch/arm/include/asm/mach-imx/dma.h       |  15 +-
 arch/arm/include/asm/mach-imx/regs-apbh.h |   9 +-
 arch/arm/include/asm/mach-imx/regs-bch.h  |  20 +-
 drivers/dma/Kconfig                       |   2 +-
 drivers/dma/apbh_dma.c                    |  13 +-
 drivers/mtd/nand/raw/Kconfig              |   6 +-
 drivers/mtd/nand/raw/mxs_nand.c           | 291 ++++++++++++++++++++++--------
 drivers/mtd/nand/raw/mxs_nand_dt.c        |  91 ++++++++++
 drivers/mtd/nand/raw/mxs_nand_spl.c       |  41 ++++-
 include/mxs_nand.h                        |  15 +-
 10 files changed, 387 insertions(+), 116 deletions(-)

-- 
2.16.4

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 01/14] mtd: gpmi: change the BCH layout setting for large oob NAND
  2020-05-04 14:08 [PATCH 00/14] mtd: nand: i.MX update Peng Fan
@ 2020-05-04 14:08 ` Peng Fan
  2020-05-11 10:16   ` sbabic at denx.de
  2022-03-14 13:30   ` GPMI NAND Regression on i.MX6S Frieder Schrempf
  2020-05-04 14:08 ` [PATCH 02/14] mtd: gpmi: provide the option to use legacy bch geometry Peng Fan
                   ` (12 subsequent siblings)
  13 siblings, 2 replies; 37+ messages in thread
From: Peng Fan @ 2020-05-04 14:08 UTC (permalink / raw)
  To: u-boot

From: Ye Li <ye.li@nxp.com>

The code change updated the NAND driver BCH ECC layout algorithm to
support large oob size NAND chips(oob > 1024 bytes) and proposed a new
way to set ECC layout.

Current implementation requires each chunk size larger than oob size so
the bad block marker (BBM) can be guaranteed located in data chunk. The
ECC layout always using the unbalanced layout(Ecc for both meta and
Data0 chunk), but for the NAND chips with oob larger than 1k, the driver
cannot support because BCH doesn?t support GF 15 for 2K chunk.

The change keeps the data chunk no larger than 1k and adjust the ECC
strength or ECC layout to locate the BBM in data chunk. General idea for
large oob NAND chips is

1.Try all ECC strength from the minimum value required by NAND spec to
the maximum one that works, any ECC makes the BBM locate in data chunk
can be chosen.

2.If none of them works, using separate ECC for meta, which will add one
extra ecc with the same ECC strength as other data chunks. This extra
ECC can guarantee BBM located in data chunk, of course, we need to check
if oob can afford it.

Previous code has two methods for ECC layout setting, the
legacy_calc_ecc_layout and calc_ecc_layout_by_info, the difference
between these two methods is, legacy_calc_ecc_layout set the chunk size
larger chan oob size and then set the maximum ECC strength that oob can
afford. While the calc_ecc_layout_by_info set chunk size and ECC
strength according to NAND spec. It has been proved that the first
method cannot provide safe ECC strength for some modern NAND chips, so
in current code,

1. Driver read NAND parameters first and then chose the proper ECC
layout setting method.

2. If the oob is large or NAND required data chunk larger than oob size,
chose calc_ecc_for_large_oob, otherwise use calc_ecc_layout_by_info

3. legacy_calc_ecc_layout only used for some NAND chips does not contains
necessary information. So this is only a backup plan, it is NOT
recommended to use these NAND chips.

Signed-off-by: Han Xu <b45815@freescale.com>
Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/mtd/nand/raw/mxs_nand.c | 205 ++++++++++++++++++++++++++--------------
 include/mxs_nand.h              |  12 ++-
 2 files changed, 144 insertions(+), 73 deletions(-)

diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index fe8097c146..8da59e39c0 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -112,53 +112,32 @@ static uint32_t mxs_nand_aux_status_offset(void)
 	return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
 }
 
-static inline int mxs_nand_calc_mark_offset(struct bch_geometry *geo,
-					    uint32_t page_data_size)
+static inline bool mxs_nand_bbm_in_data_chunk(struct bch_geometry *geo, struct mtd_info *mtd,
+		unsigned int *chunk_num)
 {
-	uint32_t chunk_data_size_in_bits = geo->ecc_chunk_size * 8;
-	uint32_t chunk_ecc_size_in_bits = geo->ecc_strength * geo->gf_len;
-	uint32_t chunk_total_size_in_bits;
-	uint32_t block_mark_chunk_number;
-	uint32_t block_mark_chunk_bit_offset;
-	uint32_t block_mark_bit_offset;
+	unsigned int i, j;
 
-	chunk_total_size_in_bits =
-			chunk_data_size_in_bits + chunk_ecc_size_in_bits;
-
-	/* Compute the bit offset of the block mark within the physical page. */
-	block_mark_bit_offset = page_data_size * 8;
-
-	/* Subtract the metadata bits. */
-	block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8;
-
-	/*
-	 * Compute the chunk number (starting at zero) in which the block mark
-	 * appears.
-	 */
-	block_mark_chunk_number =
-			block_mark_bit_offset / chunk_total_size_in_bits;
-
-	/*
-	 * Compute the bit offset of the block mark within its chunk, and
-	 * validate it.
-	 */
-	block_mark_chunk_bit_offset = block_mark_bit_offset -
-			(block_mark_chunk_number * chunk_total_size_in_bits);
+	if (geo->ecc_chunk0_size != geo->ecc_chunkn_size) {
+		dev_err(this->dev, "The size of chunk0 must equal to chunkn\n");
+		return false;
+	}
 
-	if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
-		return -EINVAL;
+	i = (mtd->writesize * 8 - MXS_NAND_METADATA_SIZE * 8) /
+		(geo->gf_len * geo->ecc_strength +
+				geo->ecc_chunkn_size * 8);
 
-	/*
-	 * Now that we know the chunk number in which the block mark appears,
-	 * we can subtract all the ECC bits that appear before it.
-	 */
-	block_mark_bit_offset -=
-		block_mark_chunk_number * chunk_ecc_size_in_bits;
+	j = (mtd->writesize * 8 - MXS_NAND_METADATA_SIZE * 8) -
+		(geo->gf_len * geo->ecc_strength +
+				geo->ecc_chunkn_size * 8) * i;
 
-	geo->block_mark_byte_offset = block_mark_bit_offset >> 3;
-	geo->block_mark_bit_offset = block_mark_bit_offset & 0x7;
+	if (j < geo->ecc_chunkn_size * 8) {
+		*chunk_num = i + 1;
+		dev_dbg(this->dev, "Set ecc to %d and bbm in chunk %d\n",
+			geo->ecc_strength, *chunk_num);
+		return true;
+	}
 
-	return 0;
+	return false;
 }
 
 static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
@@ -168,6 +147,7 @@ static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
+	unsigned int block_mark_bit_offset;
 
 	switch (ecc_step) {
 	case SZ_512:
@@ -180,45 +160,51 @@ static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
 		return -EINVAL;
 	}
 
-	geo->ecc_chunk_size = ecc_step;
+	geo->ecc_chunk0_size = ecc_step;
+	geo->ecc_chunkn_size = ecc_step;
 	geo->ecc_strength = round_up(ecc_strength, 2);
 
 	/* Keep the C >= O */
-	if (geo->ecc_chunk_size < mtd->oobsize)
+	if (geo->ecc_chunkn_size < mtd->oobsize)
 		return -EINVAL;
 
 	if (geo->ecc_strength > nand_info->max_ecc_strength_supported)
 		return -EINVAL;
 
-	geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
+	geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
+
+	/* For bit swap. */
+	block_mark_bit_offset = mtd->writesize * 8 -
+		(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
+				+ MXS_NAND_METADATA_SIZE * 8);
+
+	geo->block_mark_byte_offset = block_mark_bit_offset / 8;
+	geo->block_mark_bit_offset  = block_mark_bit_offset % 8;
 
 	return 0;
 }
 
-static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo,
+static inline int mxs_nand_legacy_calc_ecc_layout(struct bch_geometry *geo,
 					   struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
+	unsigned int block_mark_bit_offset;
 
 	/* The default for the length of Galois Field. */
 	geo->gf_len = 13;
 
 	/* The default for chunk size. */
-	geo->ecc_chunk_size = 512;
+	geo->ecc_chunk0_size = 512;
+	geo->ecc_chunkn_size = 512;
 
-	if (geo->ecc_chunk_size < mtd->oobsize) {
+	if (geo->ecc_chunkn_size < mtd->oobsize) {
 		geo->gf_len = 14;
-		geo->ecc_chunk_size *= 2;
+		geo->ecc_chunk0_size *= 2;
+		geo->ecc_chunkn_size *= 2;
 	}
 
-	if (mtd->oobsize > geo->ecc_chunk_size) {
-		printf("Not support the NAND chips whose oob size is larger then %d bytes!\n",
-		       geo->ecc_chunk_size);
-		return -EINVAL;
-	}
-
-	geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
+	geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
 
 	/*
 	 * Determine the ECC layout with the formula:
@@ -234,6 +220,84 @@ static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo,
 	geo->ecc_strength = min(round_down(geo->ecc_strength, 2),
 				nand_info->max_ecc_strength_supported);
 
+	block_mark_bit_offset = mtd->writesize * 8 -
+		(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
+				+ MXS_NAND_METADATA_SIZE * 8);
+
+	geo->block_mark_byte_offset = block_mark_bit_offset / 8;
+	geo->block_mark_bit_offset  = block_mark_bit_offset % 8;
+
+	return 0;
+}
+
+static inline int mxs_nand_calc_ecc_for_large_oob(struct bch_geometry *geo,
+					   struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
+	unsigned int block_mark_bit_offset;
+	unsigned int max_ecc;
+	unsigned int bbm_chunk;
+	unsigned int i;
+
+	/* sanity check for the minimum ecc nand required */
+	if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
+		return -EINVAL;
+	geo->ecc_strength = chip->ecc_strength_ds;
+
+	/* calculate the maximum ecc platform can support*/
+	geo->gf_len = 14;
+	geo->ecc_chunk0_size = 1024;
+	geo->ecc_chunkn_size = 1024;
+	geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
+	max_ecc = ((mtd->oobsize - MXS_NAND_METADATA_SIZE) * 8)
+			/ (geo->gf_len * geo->ecc_chunk_count);
+	max_ecc = min(round_down(max_ecc, 2),
+				nand_info->max_ecc_strength_supported);
+
+
+	/* search a supported ecc strength that makes bbm */
+	/* located in data chunk  */
+	geo->ecc_strength = chip->ecc_strength_ds;
+	while (!(geo->ecc_strength > max_ecc)) {
+		if (mxs_nand_bbm_in_data_chunk(geo, mtd, &bbm_chunk))
+			break;
+		geo->ecc_strength += 2;
+	}
+
+	/* if none of them works, keep using the minimum ecc */
+	/* nand required but changing ecc page layout  */
+	if (geo->ecc_strength > max_ecc) {
+		geo->ecc_strength = chip->ecc_strength_ds;
+		/* add extra ecc for meta data */
+		geo->ecc_chunk0_size = 0;
+		geo->ecc_chunk_count = (mtd->writesize / geo->ecc_chunkn_size) + 1;
+		geo->ecc_for_meta = 1;
+		/* check if oob can afford this extra ecc chunk */
+		if (mtd->oobsize * 8 < MXS_NAND_METADATA_SIZE * 8 +
+				geo->gf_len * geo->ecc_strength
+				* geo->ecc_chunk_count) {
+			printf("unsupported NAND chip with new layout\n");
+			return -EINVAL;
+		}
+
+		/* calculate in which chunk bbm located */
+		bbm_chunk = (mtd->writesize * 8 - MXS_NAND_METADATA_SIZE * 8 -
+			geo->gf_len * geo->ecc_strength) /
+			(geo->gf_len * geo->ecc_strength +
+					geo->ecc_chunkn_size * 8) + 1;
+	}
+
+	/* calculate the number of ecc chunk behind the bbm */
+	i = (mtd->writesize / geo->ecc_chunkn_size) - bbm_chunk + 1;
+
+	block_mark_bit_offset = mtd->writesize * 8 -
+		(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - i)
+				+ MXS_NAND_METADATA_SIZE * 8);
+
+	geo->block_mark_byte_offset = block_mark_bit_offset / 8;
+	geo->block_mark_bit_offset  = block_mark_bit_offset % 8;
+
 	return 0;
 }
 
@@ -983,18 +1047,23 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, struct bch_geometry *geo)
 	struct nand_chip *nand = mtd_to_nand(mtd);
 	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
 
-	if (chip->ecc.strength > 0 && chip->ecc.size > 0)
-		return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
-				chip->ecc.strength, chip->ecc.size);
+	if (chip->ecc_strength_ds > nand_info->max_ecc_strength_supported) {
+		printf("unsupported NAND chip, minimum ecc required %d\n"
+			, chip->ecc_strength_ds);
+		return -EINVAL;
+	}
+
+	if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
+			(mtd->oobsize < 1024)) {
+		dev_warn(this->dev, "use legacy bch geometry\n");
+		return mxs_nand_legacy_calc_ecc_layout(geo, mtd);
+	}
 
-	if (nand_info->use_minimum_ecc ||
-		mxs_nand_calc_ecc_layout(geo, mtd)) {
-		if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
-			return -EINVAL;
+	if (mtd->oobsize > 1024 || chip->ecc_step_ds < mtd->oobsize)
+		return mxs_nand_calc_ecc_for_large_oob(geo, mtd);
 
-		return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
+	return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
 				chip->ecc_strength_ds, chip->ecc_step_ds);
-	}
 
 	return 0;
 }
@@ -1025,8 +1094,6 @@ int mxs_nand_setup_ecc(struct mtd_info *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);
 
@@ -1034,7 +1101,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
 	tmp = (geo->ecc_chunk_count - 1) << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
 	tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
 	tmp |= (geo->ecc_strength >> 1) << BCH_FLASHLAYOUT0_ECC0_OFFSET;
-	tmp |= geo->ecc_chunk_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
+	tmp |= geo->ecc_chunk0_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
 	tmp |= (geo->gf_len == 14 ? 1 : 0) <<
 		BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
 	writel(tmp, &bch_regs->hw_bch_flash0layout0);
@@ -1043,7 +1110,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
 	tmp = (mtd->writesize + mtd->oobsize)
 		<< BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
 	tmp |= (geo->ecc_strength >> 1) << BCH_FLASHLAYOUT1_ECCN_OFFSET;
-	tmp |= geo->ecc_chunk_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
+	tmp |= geo->ecc_chunkn_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
 	tmp |= (geo->gf_len == 14 ? 1 : 0) <<
 		BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
 	writel(tmp, &bch_regs->hw_bch_flash0layout1);
@@ -1268,7 +1335,7 @@ int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info)
 
 	nand->ecc.layout	= &fake_ecc_layout;
 	nand->ecc.mode		= NAND_ECC_HW;
-	nand->ecc.size		= nand_info->bch_geometry.ecc_chunk_size;
+	nand->ecc.size		= nand_info->bch_geometry.ecc_chunkn_size;
 	nand->ecc.strength	= nand_info->bch_geometry.ecc_strength;
 
 	/* second phase scan */
diff --git a/include/mxs_nand.h b/include/mxs_nand.h
index ada20483d0..497da77a16 100644
--- a/include/mxs_nand.h
+++ b/include/mxs_nand.h
@@ -16,22 +16,26 @@
  * @gf_len:                   The length of Galois Field. (e.g., 13 or 14)
  * @ecc_strength:             A number that describes the strength of the ECC
  *                            algorithm.
- * @ecc_chunk_size:           The size, in bytes, of a single ECC chunk. Note
- *                            the first chunk in the page includes both data and
- *                            metadata, so it's a bit larger than this value.
+ * @ecc_chunk0_size:          The size, in bytes, of a first ECC chunk.
+ * @ecc_chunkn_size:          The size, in bytes, of a single ECC chunk after
+ *                            the first chunk in the page.
  * @ecc_chunk_count:          The number of ECC chunks in the page,
  * @block_mark_byte_offset:   The byte offset in the ECC-based page view at
  *                            which the underlying physical block mark appears.
  * @block_mark_bit_offset:    The bit offset into the ECC-based page view at
  *                            which the underlying physical block mark appears.
+ * @ecc_for_meta:             The flag to indicate if there is a dedicate ecc
+ *                            for meta.
  */
 struct bch_geometry {
 	unsigned int  gf_len;
 	unsigned int  ecc_strength;
-	unsigned int  ecc_chunk_size;
+	unsigned int  ecc_chunk0_size;
+	unsigned int  ecc_chunkn_size;
 	unsigned int  ecc_chunk_count;
 	unsigned int  block_mark_byte_offset;
 	unsigned int  block_mark_bit_offset;
+	unsigned int  ecc_for_meta; /* ECC for meta data */
 };
 
 struct mxs_nand_info {
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 02/14] mtd: gpmi: provide the option to use legacy bch geometry
  2020-05-04 14:08 [PATCH 00/14] mtd: nand: i.MX update Peng Fan
  2020-05-04 14:08 ` [PATCH 01/14] mtd: gpmi: change the BCH layout setting for large oob NAND Peng Fan
@ 2020-05-04 14:08 ` Peng Fan
  2020-05-11 10:17   ` sbabic at denx.de
  2020-05-04 14:08 ` [PATCH 03/14] nand: mxs: fix the bitflips for erased page when uncorrectable error Peng Fan
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 37+ messages in thread
From: Peng Fan @ 2020-05-04 14:08 UTC (permalink / raw)
  To: u-boot

From: Ye Li <ye.li@nxp.com>

Provide an option in DT to use legacy bch geometry, which compatible
with the 3.10 kernel bch setting. To enable the feature, adding
"fsl,legacy-bch-geometry" under gpmi-nand node.

NOTICE: The feature must be enabled/disabled in both u-boot and kernel.

Signed-off-by: Han Xu <han.xu@nxp.com>
Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/mtd/nand/raw/mxs_nand.c    | 4 ++--
 drivers/mtd/nand/raw/mxs_nand_dt.c | 2 ++
 include/mxs_nand.h                 | 2 ++
 3 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index 8da59e39c0..3247064c3f 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -1053,8 +1053,8 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, struct bch_geometry *geo)
 		return -EINVAL;
 	}
 
-	if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
-			(mtd->oobsize < 1024)) {
+	if ((!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
+	     mtd->oobsize < 1024) || nand_info->legacy_bch_geometry) {
 		dev_warn(this->dev, "use legacy bch geometry\n");
 		return mxs_nand_legacy_calc_ecc_layout(geo, mtd);
 	}
diff --git a/drivers/mtd/nand/raw/mxs_nand_dt.c b/drivers/mtd/nand/raw/mxs_nand_dt.c
index 8ad7d618c6..7a32b284f7 100644
--- a/drivers/mtd/nand/raw/mxs_nand_dt.c
+++ b/drivers/mtd/nand/raw/mxs_nand_dt.c
@@ -69,6 +69,8 @@ static int mxs_nand_dt_probe(struct udevice *dev)
 
 	info->use_minimum_ecc = dev_read_bool(dev, "fsl,use-minimum-ecc");
 
+	info->legacy_bch_geometry = dev_read_bool(dev, "fsl,legacy-bch-geometry");
+
 	return mxs_nand_init_ctrl(info);
 }
 
diff --git a/include/mxs_nand.h b/include/mxs_nand.h
index 497da77a16..1ac628d064 100644
--- a/include/mxs_nand.h
+++ b/include/mxs_nand.h
@@ -43,6 +43,8 @@ struct mxs_nand_info {
 	struct udevice *dev;
 	unsigned int	max_ecc_strength_supported;
 	bool		use_minimum_ecc;
+	/* legacy bch geometry flag */
+	bool		legacy_bch_geometry;
 	int		cur_chip;
 
 	uint32_t	cmd_queue_len;
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 03/14] nand: mxs: fix the bitflips for erased page when uncorrectable error
  2020-05-04 14:08 [PATCH 00/14] mtd: nand: i.MX update Peng Fan
  2020-05-04 14:08 ` [PATCH 01/14] mtd: gpmi: change the BCH layout setting for large oob NAND Peng Fan
  2020-05-04 14:08 ` [PATCH 02/14] mtd: gpmi: provide the option to use legacy bch geometry Peng Fan
@ 2020-05-04 14:08 ` Peng Fan
  2020-05-11 10:19   ` sbabic at denx.de
  2020-05-04 14:08 ` [PATCH 04/14] nand: mxs: correct bitflip for erased NAND page Peng Fan
                   ` (10 subsequent siblings)
  13 siblings, 1 reply; 37+ messages in thread
From: Peng Fan @ 2020-05-04 14:08 UTC (permalink / raw)
  To: u-boot

This patch is porting from linux:
http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/commit/
?h=imx_4.1.15_1.0.0_ga&id=3d42fcece496224fde59f9343763fb2dfc5b0768

"
We may meet the bitflips in reading an erased page(contains all 0xFF),
this may causes the UBIFS corrupt, please see the log from Elie:

-----------------------------------------------------------------
[    3.831323] UBI warning: ubi_io_read: error -74 (ECC error) while reading 16384 bytes from PEB 443:245760, read only 16384 bytes, retry
[    3.845026] UBI warning: ubi_io_read: error -74 (ECC error) while reading 16384 bytes from PEB 443:245760, read only 16384 bytes, retry
[    3.858710] UBI warning: ubi_io_read: error -74 (ECC error) while reading 16384 bytes from PEB 443:245760, read only 16384 bytes, retry
[    3.872408] UBI error: ubi_io_read: error -74 (ECC error) while reading 16384 bytes from PEB 443:245760, read 16384 bytes
...
[    4.011529] UBIFS error (pid 36): ubifs_recover_leb: corrupt empty space LEB 27:237568, corruption starts at 9815
[    4.021897] UBIFS error (pid 36): ubifs_scanned_corruption: corruption at LEB 27:247383
[    4.030000] UBIFS error (pid 36): ubifs_scanned_corruption: first 6569 bytes from LEB 27:247383
-----------------------------------------------------------------

This patch does a check for the uncorrectable failure in the following steps:

   [0] set the threshold.
       The threshold is set based on the truth:
       "A single 0 bit will lead to gf_len(13 or 14) bits 0 after the BCH
        do the ECC."

        For the sake of safe, we will set the threshold with half the gf_len, and
        do not make it bigger the ECC strength.

   [1] count the bitflips of the current ECC chunk, assume it is N.

   [2] if the (N <= threshold) is true, we continue to read out the page with
       ECC disabled. and we count the bitflips again, assume it is N2.
       (We read out the whole page, not just a chunk, this makes the check
        more strictly, and make the code more simple.)

   [3] if the (N2 <= threshold) is true again, we can regard this is a erased
       page. This is because a real erased page is full of 0xFF(maybe also has
       several bitflips), while a page contains the 0xFF data will definitely
       has many bitflips in the ECC parity areas.

   [4] if the [3] fails, we can regard this is a page filled with the '0xFF'
       data.
"

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/mtd/nand/raw/mxs_nand.c | 44 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index 3247064c3f..55d24cd062 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -612,6 +612,45 @@ static uint8_t mxs_nand_read_byte(struct mtd_info *mtd)
 	return buf;
 }
 
+static bool mxs_nand_erased_page(struct mtd_info *mtd, struct nand_chip *nand,
+				 u8 *buf, int chunk, int page)
+{
+	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
+	struct bch_geometry *geo = &nand_info->bch_geometry;
+	unsigned int flip_bits = 0, flip_bits_noecc = 0;
+	unsigned int threshold;
+	unsigned int base = geo->ecc_chunkn_size * chunk;
+	u32 *dma_buf = (u32 *)buf;
+	int i;
+
+	threshold = geo->gf_len / 2;
+	if (threshold > geo->ecc_strength)
+		threshold = geo->ecc_strength;
+
+	for (i = 0; i < geo->ecc_chunkn_size; i++) {
+		flip_bits += hweight8(~buf[base + i]);
+		if (flip_bits > threshold)
+			return false;
+	}
+
+	nand->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+	nand->read_buf(mtd, buf, mtd->writesize);
+
+	for (i = 0; i < mtd->writesize / 4; i++) {
+		flip_bits_noecc += hweight32(~dma_buf[i]);
+		if (flip_bits_noecc > threshold)
+			return false;
+	}
+
+	mtd->ecc_stats.corrected += flip_bits;
+
+	memset(buf, 0xff, mtd->writesize);
+
+	printf("The page(%d) is an erased page(%d,%d,%d,%d).\n", page, chunk, threshold, flip_bits, flip_bits_noecc);
+
+	return true;
+}
+
 /*
  * Read a page from NAND.
  */
@@ -715,6 +754,8 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
 		goto rtn;
 	}
 
+	mxs_nand_return_dma_descs(nand_info);
+
 	/* Invalidate caches */
 	mxs_nand_inval_data_buf(nand_info);
 
@@ -731,6 +772,9 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
 			continue;
 
 		if (status[i] == 0xfe) {
+			if (mxs_nand_erased_page(mtd, nand,
+						 nand_info->data_buf, i, page))
+				break;
 			failed++;
 			continue;
 		}
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 04/14] nand: mxs: correct bitflip for erased NAND page
  2020-05-04 14:08 [PATCH 00/14] mtd: nand: i.MX update Peng Fan
                   ` (2 preceding siblings ...)
  2020-05-04 14:08 ` [PATCH 03/14] nand: mxs: fix the bitflips for erased page when uncorrectable error Peng Fan
@ 2020-05-04 14:08 ` Peng Fan
  2020-05-11 10:17   ` sbabic at denx.de
  2020-05-04 14:08 ` [PATCH 05/14] mxs_nand: Add support for i.MX8M Peng Fan
                   ` (9 subsequent siblings)
  13 siblings, 1 reply; 37+ messages in thread
From: Peng Fan @ 2020-05-04 14:08 UTC (permalink / raw)
  To: u-boot

This patch is a porting of
http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/
commit/?h=imx_4.1.15_1.0.0_ga&id=e4dacc44d22e9474ec456cb330df525cd805ea38
"
i.MX6QP and i.MX7D BCH module integrated a new feature to detect the
bitflip number for erased NAND page. So for these two platform, set the
erase threshold to gf/2 and if bitflip detected, GPMI driver will
correct the data to all 0xFF.

Also updated the imx6qp dts file to ditinguish the GPMI module for i.MX6Q
with the one for i.MX6QP.
"

In this patch, i.MX6UL is added and threshold changed to use ecc_strength.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 arch/arm/include/asm/mach-imx/regs-bch.h |  7 ++++++-
 drivers/mtd/nand/raw/mxs_nand.c          | 18 +++++++++++++++++-
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/mach-imx/regs-bch.h b/arch/arm/include/asm/mach-imx/regs-bch.h
index 39ac5f4d45..3c1abb7221 100644
--- a/arch/arm/include/asm/mach-imx/regs-bch.h
+++ b/arch/arm/include/asm/mach-imx/regs-bch.h
@@ -6,7 +6,8 @@
  * on behalf of DENX Software Engineering GmbH
  *
  * Based on code from LTIB:
- * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2008-2010, 2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
  */
 
 #ifndef __MX28_REGS_BCH_H__
@@ -40,6 +41,7 @@ struct mxs_bch_regs {
 	mxs_reg_32(hw_bch_dbgahbmread)
 	mxs_reg_32(hw_bch_blockname)
 	mxs_reg_32(hw_bch_version)
+	mxs_reg_32(hw_bch_debug1)
 };
 #endif
 
@@ -75,6 +77,9 @@ struct mxs_bch_regs {
 
 #define	BCH_MODE_ERASE_THRESHOLD_MASK			0xff
 #define	BCH_MODE_ERASE_THRESHOLD_OFFSET			0
+#define BCH_MODE_ERASE_THRESHOLD(v)			\
+	(((v) << BCH_MODE_ERASE_THRESHOLD_OFFSET) &	\
+	 BCH_MODE_ERASE_THRESHOLD_MASK)
 
 #define	BCH_ENCODEPTR_ADDR_MASK				0xffffffff
 #define	BCH_ENCODEPTR_ADDR_OFFSET			0
diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index 55d24cd062..2ac06a5730 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -10,6 +10,7 @@
  *
  * Copyright (C) 2010 Freescale Semiconductor, Inc.
  * Copyright (C) 2008 Embedded Alley Solutions, Inc.
+ * Copyright 2017-2019 NXP
  */
 
 #include <common.h>
@@ -660,11 +661,13 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
 {
 	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
 	struct bch_geometry *geo = &nand_info->bch_geometry;
+	struct mxs_bch_regs *bch_regs = nand_info->bch_regs;
 	struct mxs_dma_desc *d;
 	uint32_t channel = MXS_DMA_CHANNEL_AHB_APBH_GPMI0 + nand_info->cur_chip;
 	uint32_t corrected = 0, failed = 0;
 	uint8_t	*status;
 	int i, ret;
+	int flag = 0;
 
 	/* Compile the DMA descriptor - wait for ready. */
 	d = mxs_nand_get_dma_desc(nand_info);
@@ -768,8 +771,13 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
 		if (status[i] == 0x00)
 			continue;
 
-		if (status[i] == 0xff)
+		if (status[i] == 0xff) {
+			if (is_mx6dqp() || is_mx7() ||
+			    is_mx6ul())
+				if (readl(&bch_regs->hw_bch_debug1))
+					flag = 1;
 			continue;
+		}
 
 		if (status[i] == 0xfe) {
 			if (mxs_nand_erased_page(mtd, nand,
@@ -801,6 +809,8 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
 
 	memcpy(buf, nand_info->data_buf, mtd->writesize);
 
+	if (flag)
+		memset(buf, 0xff, mtd->writesize);
 rtn:
 	mxs_nand_return_dma_descs(nand_info);
 
@@ -1160,6 +1170,12 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
 	writel(tmp, &bch_regs->hw_bch_flash0layout1);
 	nand_info->bch_flash0layout1 = tmp;
 
+	/* Set erase threshold to ecc strength for mx6ul, mx6qp and mx7 */
+	if (is_mx6dqp() || is_mx7() ||
+	    is_mx6ul())
+		writel(BCH_MODE_ERASE_THRESHOLD(geo->ecc_strength),
+		       &bch_regs->hw_bch_mode);
+
 	/* Set *all* chip selects to use layout 0 */
 	writel(0, &bch_regs->hw_bch_layoutselect);
 
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 05/14] mxs_nand: Add support for i.MX8M
  2020-05-04 14:08 [PATCH 00/14] mtd: nand: i.MX update Peng Fan
                   ` (3 preceding siblings ...)
  2020-05-04 14:08 ` [PATCH 04/14] nand: mxs: correct bitflip for erased NAND page Peng Fan
@ 2020-05-04 14:08 ` Peng Fan
  2020-05-11 10:17   ` sbabic at denx.de
  2020-05-04 14:08 ` [PATCH 06/14] nand: Update SPL MXS NAND mini driver Peng Fan
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 37+ messages in thread
From: Peng Fan @ 2020-05-04 14:08 UTC (permalink / raw)
  To: u-boot

From: Ye Li <ye.li@nxp.com>

Update the gpmi/apbh_dma/bch drivers and relevant registers for i.MX8M.

Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 arch/arm/include/asm/mach-imx/dma.h       | 2 +-
 arch/arm/include/asm/mach-imx/regs-apbh.h | 6 +++---
 arch/arm/include/asm/mach-imx/regs-bch.h  | 4 ++--
 drivers/dma/Kconfig                       | 2 +-
 drivers/dma/apbh_dma.c                    | 2 +-
 drivers/mtd/nand/raw/Kconfig              | 6 +++---
 drivers/mtd/nand/raw/mxs_nand.c           | 8 ++++----
 7 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/arch/arm/include/asm/mach-imx/dma.h b/arch/arm/include/asm/mach-imx/dma.h
index ca70731b9e..cb73aaeeb5 100644
--- a/arch/arm/include/asm/mach-imx/dma.h
+++ b/arch/arm/include/asm/mach-imx/dma.h
@@ -53,7 +53,7 @@ enum {
 	MXS_DMA_CHANNEL_AHB_APBH_RESERVED1,
 	MXS_MAX_DMA_CHANNELS,
 };
-#elif defined(CONFIG_MX6) || defined(CONFIG_MX7)
+#elif (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
 enum {
 	MXS_DMA_CHANNEL_AHB_APBH_GPMI0 = 0,
 	MXS_DMA_CHANNEL_AHB_APBH_GPMI1,
diff --git a/arch/arm/include/asm/mach-imx/regs-apbh.h b/arch/arm/include/asm/mach-imx/regs-apbh.h
index d7baf13343..d68953efd2 100644
--- a/arch/arm/include/asm/mach-imx/regs-apbh.h
+++ b/arch/arm/include/asm/mach-imx/regs-apbh.h
@@ -95,7 +95,7 @@ struct mxs_apbh_regs {
 	mxs_reg_32(hw_apbh_version)
 };
 
-#elif (defined(CONFIG_MX28) || defined(CONFIG_MX6) || defined(CONFIG_MX7))
+#elif (defined(CONFIG_MX28) || defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
 struct mxs_apbh_regs {
 	mxs_reg_32(hw_apbh_ctrl0)
 	mxs_reg_32(hw_apbh_ctrl1)
@@ -274,7 +274,7 @@ struct mxs_apbh_regs {
 #define	APBH_CTRL0_CLKGATE_CHANNEL_NAND7		0x0800
 #define	APBH_CTRL0_CLKGATE_CHANNEL_HSADC		0x1000
 #define	APBH_CTRL0_CLKGATE_CHANNEL_LCDIF		0x2000
-#elif (defined(CONFIG_MX6) || defined(CONFIG_MX7))
+#elif (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
 #define	APBH_CTRL0_CLKGATE_CHANNEL_OFFSET		0
 #define	APBH_CTRL0_CLKGATE_CHANNEL_NAND0		0x0001
 #define	APBH_CTRL0_CLKGATE_CHANNEL_NAND1		0x0002
@@ -390,7 +390,7 @@ struct mxs_apbh_regs {
 #define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_LCDIF		0x2000
 #endif
 
-#if (defined(CONFIG_MX6) || defined(CONFIG_MX7))
+#if (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
 #define	APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET		16
 #endif
 
diff --git a/arch/arm/include/asm/mach-imx/regs-bch.h b/arch/arm/include/asm/mach-imx/regs-bch.h
index 3c1abb7221..4b99edbb3d 100644
--- a/arch/arm/include/asm/mach-imx/regs-bch.h
+++ b/arch/arm/include/asm/mach-imx/regs-bch.h
@@ -127,7 +127,7 @@ struct mxs_bch_regs {
 #define	BCH_FLASHLAYOUT0_NBLOCKS_OFFSET			24
 #define	BCH_FLASHLAYOUT0_META_SIZE_MASK			(0xff << 16)
 #define	BCH_FLASHLAYOUT0_META_SIZE_OFFSET		16
-#if (defined(CONFIG_MX6) || defined(CONFIG_MX7))
+#if (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
 #define	BCH_FLASHLAYOUT0_ECC0_MASK			(0x1f << 11)
 #define	BCH_FLASHLAYOUT0_ECC0_OFFSET			11
 #else
@@ -158,7 +158,7 @@ struct mxs_bch_regs {
 
 #define	BCH_FLASHLAYOUT1_PAGE_SIZE_MASK			(0xffff << 16)
 #define	BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET		16
-#if (defined(CONFIG_MX6) || defined(CONFIG_MX7))
+#if (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
 #define	BCH_FLASHLAYOUT1_ECCN_MASK			(0x1f << 11)
 #define	BCH_FLASHLAYOUT1_ECCN_OFFSET			11
 #else
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 4f37ba7d35..655e79fbaf 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -44,7 +44,7 @@ config TI_EDMA3
 
 config APBH_DMA
 	bool "Support APBH DMA"
-	depends on MX23 || MX28 || MX6 || MX7
+	depends on MX23 || MX28 || MX6 || MX7 || IMX8M
 	help
 	  Enable APBH DMA driver.
 
diff --git a/drivers/dma/apbh_dma.c b/drivers/dma/apbh_dma.c
index 15133128be..8d17f8f01d 100644
--- a/drivers/dma/apbh_dma.c
+++ b/drivers/dma/apbh_dma.c
@@ -215,7 +215,7 @@ static int mxs_dma_reset(int channel)
 #if defined(CONFIG_MX23)
 	uint32_t setreg = (uint32_t)(&apbh_regs->hw_apbh_ctrl0_set);
 	uint32_t offset = APBH_CTRL0_RESET_CHANNEL_OFFSET;
-#elif (defined(CONFIG_MX28) || defined(CONFIG_MX6) || defined(CONFIG_MX7))
+#elif (defined(CONFIG_MX28) || defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
 	uint32_t setreg = (uint32_t)(&apbh_regs->hw_apbh_channel_ctrl_set);
 	uint32_t offset = APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET;
 #endif
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index 23201ca720..c46fec3d32 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -259,12 +259,12 @@ config NAND_MXC
 
 config NAND_MXS
 	bool "MXS NAND support"
-	depends on MX23 || MX28 || MX6 || MX7
+	depends on MX23 || MX28 || MX6 || MX7 || IMX8M
 	select SYS_NAND_SELF_INIT
 	imply CMD_NAND
 	select APBH_DMA
-	select APBH_DMA_BURST if ARCH_MX6 || ARCH_MX7
-	select APBH_DMA_BURST8 if ARCH_MX6 || ARCH_MX7
+	select APBH_DMA_BURST if ARCH_MX6 || ARCH_MX7 || ARCH_IMX8M
+	select APBH_DMA_BURST8 if ARCH_MX6 || ARCH_MX7 || ARCH_IMX8M
 	help
 	  This enables NAND driver for the NAND flash controller on the
 	  MXS processors.
diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index 2ac06a5730..facedf92c5 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -31,7 +31,7 @@
 
 #define	MXS_NAND_DMA_DESCRIPTOR_COUNT		4
 
-#if (defined(CONFIG_MX6) || defined(CONFIG_MX7))
+#if (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
 #define	MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT	2
 #else
 #define	MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT	0
@@ -773,7 +773,7 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
 
 		if (status[i] == 0xff) {
 			if (is_mx6dqp() || is_mx7() ||
-			    is_mx6ul())
+			    is_mx6ul() || is_imx8m())
 				if (readl(&bch_regs->hw_bch_debug1))
 					flag = 1;
 			continue;
@@ -1172,7 +1172,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
 
 	/* Set erase threshold to ecc strength for mx6ul, mx6qp and mx7 */
 	if (is_mx6dqp() || is_mx7() ||
-	    is_mx6ul())
+	    is_mx6ul() || is_imx8m())
 		writel(BCH_MODE_ERASE_THRESHOLD(geo->ecc_strength),
 		       &bch_regs->hw_bch_mode);
 
@@ -1311,7 +1311,7 @@ int mxs_nand_init_spl(struct nand_chip *nand)
 	nand_info->gpmi_regs = (struct mxs_gpmi_regs *)MXS_GPMI_BASE;
 	nand_info->bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
 
-	if (is_mx6sx() || is_mx7())
+	if (is_mx6sx() || is_mx7() || is_imx8m())
 		nand_info->max_ecc_strength_supported = 62;
 	else
 		nand_info->max_ecc_strength_supported = 40;
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 06/14] nand: Update SPL MXS NAND mini driver
  2020-05-04 14:08 [PATCH 00/14] mtd: nand: i.MX update Peng Fan
                   ` (4 preceding siblings ...)
  2020-05-04 14:08 ` [PATCH 05/14] mxs_nand: Add support for i.MX8M Peng Fan
@ 2020-05-04 14:08 ` Peng Fan
  2020-05-11 10:16   ` sbabic at denx.de
  2020-05-04 14:08 ` [PATCH 07/14] mxs_nand: Update compatible string for i.MX6SX Peng Fan
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 37+ messages in thread
From: Peng Fan @ 2020-05-04 14:08 UTC (permalink / raw)
  To: u-boot

From: Ye Li <ye.li@nxp.com>

Update the mini driver to add support for getting ecc info from ONFI and
support read image data from page unaligned NAND address.

Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/mtd/nand/raw/mxs_nand_spl.c | 41 ++++++++++++++++++++++++++++++-------
 1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/raw/mxs_nand_spl.c b/drivers/mtd/nand/raw/mxs_nand_spl.c
index a653dfa5ed..ae50cc37b5 100644
--- a/drivers/mtd/nand/raw/mxs_nand_spl.c
+++ b/drivers/mtd/nand/raw/mxs_nand_spl.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (C) 2014 Gateworks Corporation
+ * Copyright 2019 NXP
  * Author: Tim Harvey <tharvey@gateworks.com>
  */
 #include <common.h>
@@ -38,6 +39,12 @@ static void mxs_nand_command(struct mtd_info *mtd, unsigned int command,
 	if (command == NAND_CMD_READ0) {
 		chip->cmd_ctrl(mtd, NAND_CMD_READSTART, NAND_CLE);
 		chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0);
+	} else if (command == NAND_CMD_RNDOUT) {
+		/* No ready / busy check necessary */
+		chip->cmd_ctrl(mtd, NAND_CMD_RNDOUTSTART,
+			       NAND_NCE | NAND_CLE);
+		chip->cmd_ctrl(mtd, NAND_CMD_NONE,
+			       NAND_NCE);
 	}
 
 	/* wait for nand ready */
@@ -212,23 +219,39 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *buf)
 	unsigned int page;
 	unsigned int nand_page_per_block;
 	unsigned int sz = 0;
+	u8 *page_buf = NULL;
+	u32 page_off;
 
 	chip = mtd_to_nand(mtd);
 	if (!chip->numchips)
 		return -ENODEV;
+
+	page_buf = malloc(mtd->writesize);
+	if (!page_buf)
+		return -ENOMEM;
+
 	page = offs >> chip->page_shift;
+	page_off = offs & (mtd->writesize - 1);
 	nand_page_per_block = mtd->erasesize / mtd->writesize;
 
-	debug("%s offset:0x%08x len:%d page:%d\n", __func__, offs, size, page);
+	debug("%s offset:0x%08x len:%d page:%x\n", __func__, offs, size, page);
 
-	size = roundup(size, mtd->writesize);
-	while (sz < size) {
-		if (mxs_read_page_ecc(mtd, buf, page) < 0)
+	while (size) {
+		if (mxs_read_page_ecc(mtd, page_buf, page) < 0)
 			return -1;
-		sz += mtd->writesize;
+
+		if (size > (mtd->writesize - page_off))
+			sz = (mtd->writesize - page_off);
+		else
+			sz = size;
+
+		memcpy(buf, page_buf + page_off, sz);
+
 		offs += mtd->writesize;
 		page++;
-		buf += mtd->writesize;
+		buf += (mtd->writesize - page_off);
+		page_off = 0;
+		size -= sz;
 
 		/*
 		 * Check if we have crossed a block boundary, and if so
@@ -242,12 +265,16 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *buf)
 			while (is_badblock(mtd, offs, 1)) {
 				page = page + nand_page_per_block;
 				/* Check i we've reached the end of flash. */
-				if (page >= mtd->size >> chip->page_shift)
+				if (page >= mtd->size >> chip->page_shift) {
+					free(page_buf);
 					return -ENOMEM;
+				}
 			}
 		}
 	}
 
+	free(page_buf);
+
 	return 0;
 }
 
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 07/14] mxs_nand: Update compatible string for i.MX6SX
  2020-05-04 14:08 [PATCH 00/14] mtd: nand: i.MX update Peng Fan
                   ` (5 preceding siblings ...)
  2020-05-04 14:08 ` [PATCH 06/14] nand: Update SPL MXS NAND mini driver Peng Fan
@ 2020-05-04 14:08 ` Peng Fan
  2020-05-11 10:15   ` sbabic at denx.de
  2020-05-04 14:08 ` [PATCH 08/14] mtd: nand: mxs_nand: add i.MX6QP compatible string Peng Fan
                   ` (6 subsequent siblings)
  13 siblings, 1 reply; 37+ messages in thread
From: Peng Fan @ 2020-05-04 14:08 UTC (permalink / raw)
  To: u-boot

From: Ye Li <ye.li@nxp.com>

The iMX6SX uses compatible string "fsl,imx6sx-gpmi-nand" for gpmi
node in DTS, so update the driver for the string

Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/mtd/nand/raw/mxs_nand_dt.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/mtd/nand/raw/mxs_nand_dt.c b/drivers/mtd/nand/raw/mxs_nand_dt.c
index 7a32b284f7..7efc9684db 100644
--- a/drivers/mtd/nand/raw/mxs_nand_dt.c
+++ b/drivers/mtd/nand/raw/mxs_nand_dt.c
@@ -25,6 +25,10 @@ static const struct mxs_nand_dt_data mxs_nand_imx6q_data = {
 	.max_ecc_strength_supported = 40,
 };
 
+static const struct mxs_nand_dt_data mxs_nand_imx6sx_data = {
+	.max_ecc_strength_supported = 62,
+};
+
 static const struct mxs_nand_dt_data mxs_nand_imx7d_data = {
 	.max_ecc_strength_supported = 62,
 };
@@ -34,6 +38,10 @@ static const struct udevice_id mxs_nand_dt_ids[] = {
 		.compatible = "fsl,imx6q-gpmi-nand",
 		.data = (unsigned long)&mxs_nand_imx6q_data,
 	},
+	{
+		.compatible = "fsl,imx6sx-gpmi-nand",
+		.data = (unsigned long)&mxs_nand_imx6sx_data,
+	},
 	{
 		.compatible = "fsl,imx7d-gpmi-nand",
 		.data = (unsigned long)&mxs_nand_imx7d_data,
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 08/14] mtd: nand: mxs_nand: add i.MX6QP compatible string
  2020-05-04 14:08 [PATCH 00/14] mtd: nand: i.MX update Peng Fan
                   ` (6 preceding siblings ...)
  2020-05-04 14:08 ` [PATCH 07/14] mxs_nand: Update compatible string for i.MX6SX Peng Fan
@ 2020-05-04 14:08 ` Peng Fan
  2020-05-11 10:15   ` sbabic at denx.de
  2020-05-04 14:08 ` [PATCH 09/14] mtd: mxs_nand: fix the gf_13/14 definition issue Peng Fan
                   ` (5 subsequent siblings)
  13 siblings, 1 reply; 37+ messages in thread
From: Peng Fan @ 2020-05-04 14:08 UTC (permalink / raw)
  To: u-boot

From: Han Xu <han.xu@nxp.com>

add the dedicate compatible string for i.MX6QP

Signed-off-by: Han Xu <han.xu@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/mtd/nand/raw/mxs_nand_dt.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/mtd/nand/raw/mxs_nand_dt.c b/drivers/mtd/nand/raw/mxs_nand_dt.c
index 7efc9684db..bd429e0d62 100644
--- a/drivers/mtd/nand/raw/mxs_nand_dt.c
+++ b/drivers/mtd/nand/raw/mxs_nand_dt.c
@@ -38,6 +38,10 @@ static const struct udevice_id mxs_nand_dt_ids[] = {
 		.compatible = "fsl,imx6q-gpmi-nand",
 		.data = (unsigned long)&mxs_nand_imx6q_data,
 	},
+	{
+		.compatible = "fsl,imx6qp-gpmi-nand",
+		.data = (unsigned long)&mxs_nand_imx6q_data,
+	},
 	{
 		.compatible = "fsl,imx6sx-gpmi-nand",
 		.data = (unsigned long)&mxs_nand_imx6sx_data,
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 09/14] mtd: mxs_nand: fix the gf_13/14 definition issue
  2020-05-04 14:08 [PATCH 00/14] mtd: nand: i.MX update Peng Fan
                   ` (7 preceding siblings ...)
  2020-05-04 14:08 ` [PATCH 08/14] mtd: nand: mxs_nand: add i.MX6QP compatible string Peng Fan
@ 2020-05-04 14:08 ` Peng Fan
  2020-05-11 10:18   ` sbabic at denx.de
  2020-05-04 14:08 ` [PATCH 10/14] nand: mxs_nand: make imx8mm can use hardware BCH and randomizer Peng Fan
                   ` (4 subsequent siblings)
  13 siblings, 1 reply; 37+ messages in thread
From: Peng Fan @ 2020-05-04 14:08 UTC (permalink / raw)
  To: u-boot

From: Han Xu <han.xu@nxp.com>

gf_13/14 mask was not set correctly in register definition.

Signed-off-by: Han Xu <han.xu@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 arch/arm/include/asm/mach-imx/regs-bch.h | 8 ++++----
 drivers/mtd/nand/raw/mxs_nand.c          | 2 ++
 include/mxs_nand.h                       | 1 +
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/mach-imx/regs-bch.h b/arch/arm/include/asm/mach-imx/regs-bch.h
index 4b99edbb3d..664fb9fd4d 100644
--- a/arch/arm/include/asm/mach-imx/regs-bch.h
+++ b/arch/arm/include/asm/mach-imx/regs-bch.h
@@ -151,9 +151,9 @@ struct mxs_bch_regs {
 #define	BCH_FLASHLAYOUT0_ECC0_ECC28			(0xe << 12)
 #define	BCH_FLASHLAYOUT0_ECC0_ECC30			(0xf << 12)
 #define	BCH_FLASHLAYOUT0_ECC0_ECC32			(0x10 << 12)
-#define	BCH_FLASHLAYOUT0_GF13_0_GF14_1			(1 << 10)
+#define	BCH_FLASHLAYOUT0_GF13_0_GF14_1_MASK		BIT(10)
 #define	BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET		10
-#define	BCH_FLASHLAYOUT0_DATA0_SIZE_MASK		0xfff
+#define	BCH_FLASHLAYOUT0_DATA0_SIZE_MASK		0x3ff
 #define	BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET		0
 
 #define	BCH_FLASHLAYOUT1_PAGE_SIZE_MASK			(0xffff << 16)
@@ -182,9 +182,9 @@ struct mxs_bch_regs {
 #define	BCH_FLASHLAYOUT1_ECCN_ECC28			(0xe << 12)
 #define	BCH_FLASHLAYOUT1_ECCN_ECC30			(0xf << 12)
 #define	BCH_FLASHLAYOUT1_ECCN_ECC32			(0x10 << 12)
-#define	BCH_FLASHLAYOUT1_GF13_0_GF14_1			(1 << 10)
+#define	BCH_FLASHLAYOUT1_GF13_0_GF14_1_MASK		BIT(10)
 #define	BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET		10
-#define	BCH_FLASHLAYOUT1_DATAN_SIZE_MASK		0xfff
+#define	BCH_FLASHLAYOUT1_DATAN_SIZE_MASK		0x3ff
 #define	BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET		0
 
 #define	BCH_DEBUG0_RSVD1_MASK				(0x1f << 27)
diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index facedf92c5..1b66636a4f 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -1474,6 +1474,8 @@ void mxs_nand_get_layout(struct mtd_info *mtd, struct mxs_nand_layout *l)
 			BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET);
 	l->eccn = (tmp & BCH_FLASHLAYOUT1_ECCN_MASK) >>
 			BCH_FLASHLAYOUT1_ECCN_OFFSET;
+	l->gf_len = (tmp & BCH_FLASHLAYOUT1_GF13_0_GF14_1_MASK) >>
+		     BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
 }
 
 /*
diff --git a/include/mxs_nand.h b/include/mxs_nand.h
index 1ac628d064..21d68a909d 100644
--- a/include/mxs_nand.h
+++ b/include/mxs_nand.h
@@ -88,6 +88,7 @@ struct mxs_nand_layout {
 	u32 ecc0;
 	u32 datan_size;
 	u32 eccn;
+	u32 gf_len;
 };
 
 int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info);
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 10/14] nand: mxs_nand: make imx8mm can use hardware BCH and randomizer
  2020-05-04 14:08 [PATCH 00/14] mtd: nand: i.MX update Peng Fan
                   ` (8 preceding siblings ...)
  2020-05-04 14:08 ` [PATCH 09/14] mtd: mxs_nand: fix the gf_13/14 definition issue Peng Fan
@ 2020-05-04 14:08 ` Peng Fan
  2020-05-11 10:15   ` sbabic at denx.de
  2020-05-04 14:09 ` [PATCH 11/14] mtd: nand: support GPMI NAND driver for i.MX8 Peng Fan
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 37+ messages in thread
From: Peng Fan @ 2020-05-04 14:08 UTC (permalink / raw)
  To: u-boot

From: Alice Guo <alice.guo@nxp.com>

imx8mm needs to BCH encode and set NAND page number needed to be
randomized

modify conditional compilation

Use CONFIG_IMX8M, so it apply to imx8mq/mm/mn

Signed-off-by: Alice Guo <alice.guo@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/mtd/nand/raw/mxs_nand.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index 1b66636a4f..3bf5ab2d8c 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -859,7 +859,7 @@ static int mxs_nand_ecc_write_page(struct mtd_info *mtd,
 	d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
 	d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
 
-	if (is_mx7() && nand_info->en_randomizer) {
+	if ((is_mx7() || is_imx8m()) && nand_info->en_randomizer) {
 		d->cmd.pio_words[2] |= GPMI_ECCCTRL_RANDOMIZER_ENABLE |
 				       GPMI_ECCCTRL_RANDOMIZER_TYPE2;
 		/*
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 11/14] mtd: nand: support GPMI NAND driver for i.MX8
  2020-05-04 14:08 [PATCH 00/14] mtd: nand: i.MX update Peng Fan
                   ` (9 preceding siblings ...)
  2020-05-04 14:08 ` [PATCH 10/14] nand: mxs_nand: make imx8mm can use hardware BCH and randomizer Peng Fan
@ 2020-05-04 14:09 ` Peng Fan
  2020-05-11 10:16   ` sbabic at denx.de
  2020-05-04 14:09 ` [PATCH 12/14] MXS_NAND: Add clock support for iMX8 Peng Fan
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 37+ messages in thread
From: Peng Fan @ 2020-05-04 14:09 UTC (permalink / raw)
  To: u-boot

enable the GPMI NAND driver for i.MX8, i.MX8 use similar controller as
i.MX8M

- register definition for i.mx8
- DMA structure must be 32bit address

Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 arch/arm/include/asm/mach-imx/dma.h       | 15 ++++++++-------
 arch/arm/include/asm/mach-imx/regs-apbh.h |  9 ++++-----
 arch/arm/include/asm/mach-imx/regs-bch.h  |  5 +++--
 drivers/dma/Kconfig                       |  2 +-
 drivers/dma/apbh_dma.c                    | 13 ++++++++-----
 drivers/mtd/nand/raw/Kconfig              |  6 +++---
 drivers/mtd/nand/raw/mxs_nand.c           | 15 ++++++++-------
 drivers/mtd/nand/raw/mxs_nand_dt.c        |  8 ++++++++
 8 files changed, 43 insertions(+), 30 deletions(-)

diff --git a/arch/arm/include/asm/mach-imx/dma.h b/arch/arm/include/asm/mach-imx/dma.h
index cb73aaeeb5..247a91afb0 100644
--- a/arch/arm/include/asm/mach-imx/dma.h
+++ b/arch/arm/include/asm/mach-imx/dma.h
@@ -7,6 +7,7 @@
  *
  * Based on code from LTIB:
  * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2020 NXP
  */
 
 #ifndef __DMA_H__
@@ -53,7 +54,7 @@ enum {
 	MXS_DMA_CHANNEL_AHB_APBH_RESERVED1,
 	MXS_MAX_DMA_CHANNELS,
 };
-#elif (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
+#else
 enum {
 	MXS_DMA_CHANNEL_AHB_APBH_GPMI0 = 0,
 	MXS_DMA_CHANNEL_AHB_APBH_GPMI1,
@@ -95,13 +96,13 @@ enum {
 #define	MXS_DMA_DESC_BYTES_OFFSET	16
 
 struct mxs_dma_cmd {
-	unsigned long		next;
-	unsigned long		data;
+	u32		next;
+	u32		data;
 	union {
-		dma_addr_t	address;
-		unsigned long	alternate;
+		u32	address;
+		u32	alternate;
 	};
-	unsigned long		pio_words[DMA_PIO_WORDS];
+	u32		pio_words[DMA_PIO_WORDS];
 };
 
 /*
@@ -117,7 +118,7 @@ struct mxs_dma_cmd {
 struct mxs_dma_desc {
 	struct mxs_dma_cmd	cmd;
 	unsigned int		flags;
-	dma_addr_t		address;
+	u32			address;
 	void			*buffer;
 	struct list_head	node;
 } __aligned(MXS_DMA_ALIGNMENT);
diff --git a/arch/arm/include/asm/mach-imx/regs-apbh.h b/arch/arm/include/asm/mach-imx/regs-apbh.h
index d68953efd2..94c330c7f9 100644
--- a/arch/arm/include/asm/mach-imx/regs-apbh.h
+++ b/arch/arm/include/asm/mach-imx/regs-apbh.h
@@ -7,6 +7,7 @@
  *
  * Based on code from LTIB:
  * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2020 NXP
  */
 
 #ifndef __REGS_APBH_H__
@@ -95,7 +96,7 @@ struct mxs_apbh_regs {
 	mxs_reg_32(hw_apbh_version)
 };
 
-#elif (defined(CONFIG_MX28) || defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
+#else
 struct mxs_apbh_regs {
 	mxs_reg_32(hw_apbh_ctrl0)
 	mxs_reg_32(hw_apbh_ctrl1)
@@ -274,7 +275,7 @@ struct mxs_apbh_regs {
 #define	APBH_CTRL0_CLKGATE_CHANNEL_NAND7		0x0800
 #define	APBH_CTRL0_CLKGATE_CHANNEL_HSADC		0x1000
 #define	APBH_CTRL0_CLKGATE_CHANNEL_LCDIF		0x2000
-#elif (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
+#elif (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M))
 #define	APBH_CTRL0_CLKGATE_CHANNEL_OFFSET		0
 #define	APBH_CTRL0_CLKGATE_CHANNEL_NAND0		0x0001
 #define	APBH_CTRL0_CLKGATE_CHANNEL_NAND1		0x0002
@@ -357,7 +358,6 @@ struct mxs_apbh_regs {
 
 #if defined(CONFIG_MX28)
 #define	APBH_CHANNEL_CTRL_RESET_CHANNEL_MASK		(0xffff << 16)
-#define	APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET		16
 #define	APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP0		(0x0001 << 16)
 #define	APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP1		(0x0002 << 16)
 #define	APBH_CHANNEL_CTRL_RESET_CHANNEL_SSP2		(0x0004 << 16)
@@ -390,9 +390,8 @@ struct mxs_apbh_regs {
 #define	APBH_CHANNEL_CTRL_FREEZE_CHANNEL_LCDIF		0x2000
 #endif
 
-#if (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
+/* Not on i.MX23 */
 #define	APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET		16
-#endif
 
 #if defined(CONFIG_MX23)
 #define	APBH_DEVSEL_CH7_MASK				(0xf << 28)
diff --git a/arch/arm/include/asm/mach-imx/regs-bch.h b/arch/arm/include/asm/mach-imx/regs-bch.h
index 664fb9fd4d..5a149002e2 100644
--- a/arch/arm/include/asm/mach-imx/regs-bch.h
+++ b/arch/arm/include/asm/mach-imx/regs-bch.h
@@ -7,6 +7,7 @@
  *
  * Based on code from LTIB:
  * Copyright 2008-2010, 2016 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2020 NXP
  *
  */
 
@@ -127,7 +128,7 @@ struct mxs_bch_regs {
 #define	BCH_FLASHLAYOUT0_NBLOCKS_OFFSET			24
 #define	BCH_FLASHLAYOUT0_META_SIZE_MASK			(0xff << 16)
 #define	BCH_FLASHLAYOUT0_META_SIZE_OFFSET		16
-#if (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
+#if (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M))
 #define	BCH_FLASHLAYOUT0_ECC0_MASK			(0x1f << 11)
 #define	BCH_FLASHLAYOUT0_ECC0_OFFSET			11
 #else
@@ -158,7 +159,7 @@ struct mxs_bch_regs {
 
 #define	BCH_FLASHLAYOUT1_PAGE_SIZE_MASK			(0xffff << 16)
 #define	BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET		16
-#if (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
+#if (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8) || defined(CONFIG_IMX8M))
 #define	BCH_FLASHLAYOUT1_ECCN_MASK			(0x1f << 11)
 #define	BCH_FLASHLAYOUT1_ECCN_OFFSET			11
 #else
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 655e79fbaf..1993c1d31d 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -44,7 +44,7 @@ config TI_EDMA3
 
 config APBH_DMA
 	bool "Support APBH DMA"
-	depends on MX23 || MX28 || MX6 || MX7 || IMX8M
+	depends on MX23 || MX28 || MX6 || MX7 || IMX8 || IMX8M
 	help
 	  Enable APBH DMA driver.
 
diff --git a/drivers/dma/apbh_dma.c b/drivers/dma/apbh_dma.c
index 8d17f8f01d..69eb040d32 100644
--- a/drivers/dma/apbh_dma.c
+++ b/drivers/dma/apbh_dma.c
@@ -7,6 +7,8 @@
  *
  * Based on code from LTIB:
  * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2017 NXP
+ *
  */
 
 #include <cpu_func.h>
@@ -88,7 +90,7 @@ void mxs_dma_flush_desc(struct mxs_dma_desc *desc)
 	uint32_t addr;
 	uint32_t size;
 
-	addr = (uint32_t)desc;
+	addr = (uintptr_t)desc;
 	size = roundup(sizeof(struct mxs_dma_desc), MXS_DMA_ALIGNMENT);
 
 	flush_dcache_range(addr, addr + size);
@@ -215,16 +217,17 @@ static int mxs_dma_reset(int channel)
 #if defined(CONFIG_MX23)
 	uint32_t setreg = (uint32_t)(&apbh_regs->hw_apbh_ctrl0_set);
 	uint32_t offset = APBH_CTRL0_RESET_CHANNEL_OFFSET;
-#elif (defined(CONFIG_MX28) || defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
-	uint32_t setreg = (uint32_t)(&apbh_regs->hw_apbh_channel_ctrl_set);
-	uint32_t offset = APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET;
+#elif defined(CONFIG_MX28) || defined(CONFIG_MX6) || defined(CONFIG_MX7) || \
+	defined(CONFIG_IMX8) || defined(CONFIG_IMX8M)
+	u32 setreg = (uintptr_t)(&apbh_regs->hw_apbh_channel_ctrl_set);
+	u32 offset = APBH_CHANNEL_CTRL_RESET_CHANNEL_OFFSET;
 #endif
 
 	ret = mxs_dma_validate_chan(channel);
 	if (ret)
 		return ret;
 
-	writel(1 << (channel + offset), setreg);
+	writel(1 << (channel + offset), (uintptr_t)setreg);
 
 	return 0;
 }
diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig
index c46fec3d32..c4d9d31388 100644
--- a/drivers/mtd/nand/raw/Kconfig
+++ b/drivers/mtd/nand/raw/Kconfig
@@ -259,12 +259,12 @@ config NAND_MXC
 
 config NAND_MXS
 	bool "MXS NAND support"
-	depends on MX23 || MX28 || MX6 || MX7 || IMX8M
+	depends on MX23 || MX28 || MX6 || MX7 || IMX8 || IMX8M
 	select SYS_NAND_SELF_INIT
 	imply CMD_NAND
 	select APBH_DMA
-	select APBH_DMA_BURST if ARCH_MX6 || ARCH_MX7 || ARCH_IMX8M
-	select APBH_DMA_BURST8 if ARCH_MX6 || ARCH_MX7 || ARCH_IMX8M
+	select APBH_DMA_BURST if ARCH_MX6 || ARCH_MX7 || ARCH_IMX8 || ARCH_IMX8M
+	select APBH_DMA_BURST8 if ARCH_MX6 || ARCH_MX7 || ARCH_IMX8 || ARCH_IMX8M
 	help
 	  This enables NAND driver for the NAND flash controller on the
 	  MXS processors.
diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index 3bf5ab2d8c..b6e65c616d 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -31,7 +31,8 @@
 
 #define	MXS_NAND_DMA_DESCRIPTOR_COUNT		4
 
-#if (defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8M))
+#if defined(CONFIG_MX6) || defined(CONFIG_MX7) || defined(CONFIG_IMX8) || \
+	defined(CONFIG_IMX8M)
 #define	MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT	2
 #else
 #define	MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT	0
@@ -55,21 +56,21 @@ struct nand_ecclayout fake_ecc_layout;
 #if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF)
 static void mxs_nand_flush_data_buf(struct mxs_nand_info *info)
 {
-	uint32_t addr = (uint32_t)info->data_buf;
+	uint32_t addr = (uintptr_t)info->data_buf;
 
 	flush_dcache_range(addr, addr + info->data_buf_size);
 }
 
 static void mxs_nand_inval_data_buf(struct mxs_nand_info *info)
 {
-	uint32_t addr = (uint32_t)info->data_buf;
+	uint32_t addr = (uintptr_t)info->data_buf;
 
 	invalidate_dcache_range(addr, addr + info->data_buf_size);
 }
 
 static void mxs_nand_flush_cmd_buf(struct mxs_nand_info *info)
 {
-	uint32_t addr = (uint32_t)info->cmd_buf;
+	uint32_t addr = (uintptr_t)info->cmd_buf;
 
 	flush_dcache_range(addr, addr + MXS_NAND_COMMAND_BUFFER_SIZE);
 }
@@ -773,7 +774,7 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
 
 		if (status[i] == 0xff) {
 			if (is_mx6dqp() || is_mx7() ||
-			    is_mx6ul() || is_imx8m())
+			    is_mx6ul() || is_imx8() || is_imx8m())
 				if (readl(&bch_regs->hw_bch_debug1))
 					flag = 1;
 			continue;
@@ -1172,7 +1173,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
 
 	/* Set erase threshold to ecc strength for mx6ul, mx6qp and mx7 */
 	if (is_mx6dqp() || is_mx7() ||
-	    is_mx6ul() || is_imx8m())
+	    is_mx6ul() || is_imx8() || is_imx8m())
 		writel(BCH_MODE_ERASE_THRESHOLD(geo->ecc_strength),
 		       &bch_regs->hw_bch_mode);
 
@@ -1311,7 +1312,7 @@ int mxs_nand_init_spl(struct nand_chip *nand)
 	nand_info->gpmi_regs = (struct mxs_gpmi_regs *)MXS_GPMI_BASE;
 	nand_info->bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
 
-	if (is_mx6sx() || is_mx7() || is_imx8m())
+	if (is_mx6sx() || is_mx7() || is_imx8() || is_imx8m())
 		nand_info->max_ecc_strength_supported = 62;
 	else
 		nand_info->max_ecc_strength_supported = 40;
diff --git a/drivers/mtd/nand/raw/mxs_nand_dt.c b/drivers/mtd/nand/raw/mxs_nand_dt.c
index bd429e0d62..c4dc0bb1dd 100644
--- a/drivers/mtd/nand/raw/mxs_nand_dt.c
+++ b/drivers/mtd/nand/raw/mxs_nand_dt.c
@@ -33,6 +33,10 @@ static const struct mxs_nand_dt_data mxs_nand_imx7d_data = {
 	.max_ecc_strength_supported = 62,
 };
 
+static const struct mxs_nand_dt_data mxs_nand_imx8qxp_data = {
+	.max_ecc_strength_supported = 62,
+};
+
 static const struct udevice_id mxs_nand_dt_ids[] = {
 	{
 		.compatible = "fsl,imx6q-gpmi-nand",
@@ -50,6 +54,10 @@ static const struct udevice_id mxs_nand_dt_ids[] = {
 		.compatible = "fsl,imx7d-gpmi-nand",
 		.data = (unsigned long)&mxs_nand_imx7d_data,
 	},
+	{
+		.compatible = "fsl,imx8qxp-gpmi-nand",
+		.data = (unsigned long)&mxs_nand_imx8qxp_data,
+	},
 	{ /* sentinel */ }
 };
 
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 12/14] MXS_NAND: Add clock support for iMX8
  2020-05-04 14:08 [PATCH 00/14] mtd: nand: i.MX update Peng Fan
                   ` (10 preceding siblings ...)
  2020-05-04 14:09 ` [PATCH 11/14] mtd: nand: support GPMI NAND driver for i.MX8 Peng Fan
@ 2020-05-04 14:09 ` Peng Fan
  2020-05-11 10:18   ` sbabic at denx.de
  2020-05-04 14:09 ` [PATCH 13/14] mxs_nand: don't check zero count when ECC reading with randomizer Peng Fan
  2020-05-04 14:09 ` [PATCH 14/14] nand: enable the Randomizer module for i.mx7 and i.mx8 Peng Fan
  13 siblings, 1 reply; 37+ messages in thread
From: Peng Fan @ 2020-05-04 14:09 UTC (permalink / raw)
  To: u-boot

From: Ye Li <ye.li@nxp.com>

Since iMX8 has enabled clock uclass, we can parse the clocks from DTB
and enable them in GPMI driver.

Signed-off-by: Ye Li <ye.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/mtd/nand/raw/mxs_nand_dt.c | 69 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 69 insertions(+)

diff --git a/drivers/mtd/nand/raw/mxs_nand_dt.c b/drivers/mtd/nand/raw/mxs_nand_dt.c
index c4dc0bb1dd..43dbe9e66e 100644
--- a/drivers/mtd/nand/raw/mxs_nand_dt.c
+++ b/drivers/mtd/nand/raw/mxs_nand_dt.c
@@ -2,6 +2,8 @@
  * NXP GPMI NAND flash driver (DT initialization)
  *
  * Copyright (C) 2018 Toradex
+ * Copyright 2019 NXP
+ *
  * Authors:
  * Stefan Agner <stefan.agner@toradex.com>
  *
@@ -14,6 +16,7 @@
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/printk.h>
+#include <clk.h>
 
 #include <mxs_nand.h>
 
@@ -91,6 +94,72 @@ static int mxs_nand_dt_probe(struct udevice *dev)
 
 	info->legacy_bch_geometry = dev_read_bool(dev, "fsl,legacy-bch-geometry");
 
+	if (IS_ENABLED(CONFIG_CLK) && IS_ENABLED(CONFIG_IMX8)) {
+		/* Assigned clock already set clock */
+		struct clk gpmi_clk;
+
+		ret = clk_get_by_name(dev, "gpmi_io", &gpmi_clk);
+		if (ret < 0) {
+			debug("Can't get gpmi io clk: %d\n", ret);
+			return ret;
+		}
+
+		ret = clk_enable(&gpmi_clk);
+		if (ret < 0) {
+			debug("Can't enable gpmi io clk: %d\n", ret);
+			return ret;
+		}
+
+		ret = clk_get_by_name(dev, "gpmi_apb", &gpmi_clk);
+		if (ret < 0) {
+			debug("Can't get gpmi_apb clk: %d\n", ret);
+			return ret;
+		}
+
+		ret = clk_enable(&gpmi_clk);
+		if (ret < 0) {
+			debug("Can't enable gpmi_apb clk: %d\n", ret);
+			return ret;
+		}
+
+		ret = clk_get_by_name(dev, "gpmi_bch", &gpmi_clk);
+		if (ret < 0) {
+			debug("Can't get gpmi_bch clk: %d\n", ret);
+			return ret;
+		}
+
+		ret = clk_enable(&gpmi_clk);
+		if (ret < 0) {
+			debug("Can't enable gpmi_bch clk: %d\n", ret);
+			return ret;
+		}
+
+		ret = clk_get_by_name(dev, "gpmi_apb_bch", &gpmi_clk);
+		if (ret < 0) {
+			debug("Can't get gpmi_apb_bch clk: %d\n", ret);
+			return ret;
+		}
+
+		ret = clk_enable(&gpmi_clk);
+		if (ret < 0) {
+			debug("Can't enable gpmi_apb_bch clk: %d\n", ret);
+			return ret;
+		}
+
+		/* this clock is used for apbh_dma, since the apbh dma does not support DM,
+		  * we optionally enable it here
+		  */
+		ret = clk_get_by_name(dev, "gpmi_apbh_dma", &gpmi_clk);
+		if (ret < 0) {
+			debug("Can't get gpmi_apbh_dma clk: %d\n", ret);
+		} else {
+			ret = clk_enable(&gpmi_clk);
+			if (ret < 0) {
+				debug("Can't enable gpmi_apbh_dma clk: %d\n", ret);
+			}
+		}
+	}
+
 	return mxs_nand_init_ctrl(info);
 }
 
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 13/14] mxs_nand: don't check zero count when ECC reading with randomizer
  2020-05-04 14:08 [PATCH 00/14] mtd: nand: i.MX update Peng Fan
                   ` (11 preceding siblings ...)
  2020-05-04 14:09 ` [PATCH 12/14] MXS_NAND: Add clock support for iMX8 Peng Fan
@ 2020-05-04 14:09 ` Peng Fan
  2020-05-11 10:18   ` sbabic at denx.de
  2020-05-04 14:09 ` [PATCH 14/14] nand: enable the Randomizer module for i.mx7 and i.mx8 Peng Fan
  13 siblings, 1 reply; 37+ messages in thread
From: Peng Fan @ 2020-05-04 14:09 UTC (permalink / raw)
  To: u-boot

From: Han Xu <han.xu@nxp.com>

When enabled randomizer during ECC reading, the controller reported it's
erased page. Checking zero count will cause data get modified to all
0xFF. Stop checking during randomizer to workaround this issue.

Signed-off-by: Han Xu <han.xu@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/mtd/nand/raw/mxs_nand.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index b6e65c616d..3fd21e51f2 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -773,8 +773,9 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
 			continue;
 
 		if (status[i] == 0xff) {
-			if (is_mx6dqp() || is_mx7() ||
-			    is_mx6ul() || is_imx8() || is_imx8m())
+			if (!nand_info->en_randomizer &&
+			    (is_mx6dqp() || is_mx7() || is_mx6ul() ||
+			     is_imx8() || is_imx8m()))
 				if (readl(&bch_regs->hw_bch_debug1))
 					flag = 1;
 			continue;
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 14/14] nand: enable the Randomizer module for i.mx7 and i.mx8
  2020-05-04 14:08 [PATCH 00/14] mtd: nand: i.MX update Peng Fan
                   ` (12 preceding siblings ...)
  2020-05-04 14:09 ` [PATCH 13/14] mxs_nand: don't check zero count when ECC reading with randomizer Peng Fan
@ 2020-05-04 14:09 ` Peng Fan
  2020-05-11 10:16   ` sbabic at denx.de
  13 siblings, 1 reply; 37+ messages in thread
From: Peng Fan @ 2020-05-04 14:09 UTC (permalink / raw)
  To: u-boot

From: Alice Guo <alice.guo@nxp.com>

To enable the Randomizer module, set GPMI_ECCCTRL[RANDOMIZER_ENABLE] to
1, then set GPMI_ECCCOUNT[RANDOMIZER_PAGE] to select randomizer page
number needed to be randomized.

Signed-off-by: Alice Guo <alice.guo@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
 drivers/mtd/nand/raw/mxs_nand.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index 3fd21e51f2..c3191feca8 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -710,6 +710,12 @@ static int mxs_nand_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
 	d->cmd.pio_words[4] = (dma_addr_t)nand_info->data_buf;
 	d->cmd.pio_words[5] = (dma_addr_t)nand_info->oob_buf;
 
+	if ((is_mx7() || is_imx8m()) && nand_info->en_randomizer) {
+		d->cmd.pio_words[2] |= GPMI_ECCCTRL_RANDOMIZER_ENABLE |
+				       GPMI_ECCCTRL_RANDOMIZER_TYPE2;
+		d->cmd.pio_words[3] |= (page % 256) << 16;
+	}
+
 	mxs_dma_desc_append(channel, d);
 
 	/* Compile the DMA descriptor - disable the BCH block. */
@@ -871,7 +877,7 @@ static int mxs_nand_ecc_write_page(struct mtd_info *mtd,
 		 * The value is between 0-255. For additional details
 		 * check 9.6.6.4 of i.MX7D Applications Processor reference
 		 */
-		d->cmd.pio_words[3] |= (page % 255) << 16;
+		d->cmd.pio_words[3] |= (page % 256) << 16;
 	}
 
 	mxs_dma_desc_append(channel, d);
-- 
2.16.4

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [PATCH 07/14] mxs_nand: Update compatible string for i.MX6SX
  2020-05-04 14:08 ` [PATCH 07/14] mxs_nand: Update compatible string for i.MX6SX Peng Fan
@ 2020-05-11 10:15   ` sbabic at denx.de
  0 siblings, 0 replies; 37+ messages in thread
From: sbabic at denx.de @ 2020-05-11 10:15 UTC (permalink / raw)
  To: u-boot

> From: Ye Li <ye.li@nxp.com>
> The iMX6SX uses compatible string "fsl,imx6sx-gpmi-nand" for gpmi
> node in DTS, so update the driver for the string
> Signed-off-by: Ye Li <ye.li@nxp.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 10/14] nand: mxs_nand: make imx8mm can use hardware BCH and randomizer
  2020-05-04 14:08 ` [PATCH 10/14] nand: mxs_nand: make imx8mm can use hardware BCH and randomizer Peng Fan
@ 2020-05-11 10:15   ` sbabic at denx.de
  0 siblings, 0 replies; 37+ messages in thread
From: sbabic at denx.de @ 2020-05-11 10:15 UTC (permalink / raw)
  To: u-boot

> From: Alice Guo <alice.guo@nxp.com>
> imx8mm needs to BCH encode and set NAND page number needed to be
> randomized
> modify conditional compilation
> Use CONFIG_IMX8M, so it apply to imx8mq/mm/mn
> Signed-off-by: Alice Guo <alice.guo@nxp.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 08/14] mtd: nand: mxs_nand: add i.MX6QP compatible string
  2020-05-04 14:08 ` [PATCH 08/14] mtd: nand: mxs_nand: add i.MX6QP compatible string Peng Fan
@ 2020-05-11 10:15   ` sbabic at denx.de
  0 siblings, 0 replies; 37+ messages in thread
From: sbabic at denx.de @ 2020-05-11 10:15 UTC (permalink / raw)
  To: u-boot

> From: Han Xu <han.xu@nxp.com>
> add the dedicate compatible string for i.MX6QP
> Signed-off-by: Han Xu <han.xu@nxp.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 11/14] mtd: nand: support GPMI NAND driver for i.MX8
  2020-05-04 14:09 ` [PATCH 11/14] mtd: nand: support GPMI NAND driver for i.MX8 Peng Fan
@ 2020-05-11 10:16   ` sbabic at denx.de
  0 siblings, 0 replies; 37+ messages in thread
From: sbabic at denx.de @ 2020-05-11 10:16 UTC (permalink / raw)
  To: u-boot

> enable the GPMI NAND driver for i.MX8, i.MX8 use similar controller as
> i.MX8M
> - register definition for i.mx8
> - DMA structure must be 32bit address
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 14/14] nand: enable the Randomizer module for i.mx7 and i.mx8
  2020-05-04 14:09 ` [PATCH 14/14] nand: enable the Randomizer module for i.mx7 and i.mx8 Peng Fan
@ 2020-05-11 10:16   ` sbabic at denx.de
  0 siblings, 0 replies; 37+ messages in thread
From: sbabic at denx.de @ 2020-05-11 10:16 UTC (permalink / raw)
  To: u-boot

> From: Alice Guo <alice.guo@nxp.com>
> To enable the Randomizer module, set GPMI_ECCCTRL[RANDOMIZER_ENABLE] to
> 1, then set GPMI_ECCCOUNT[RANDOMIZER_PAGE] to select randomizer page
> number needed to be randomized.
> Signed-off-by: Alice Guo <alice.guo@nxp.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 01/14] mtd: gpmi: change the BCH layout setting for large oob NAND
  2020-05-04 14:08 ` [PATCH 01/14] mtd: gpmi: change the BCH layout setting for large oob NAND Peng Fan
@ 2020-05-11 10:16   ` sbabic at denx.de
  2022-03-14 13:30   ` GPMI NAND Regression on i.MX6S Frieder Schrempf
  1 sibling, 0 replies; 37+ messages in thread
From: sbabic at denx.de @ 2020-05-11 10:16 UTC (permalink / raw)
  To: u-boot

> From: Ye Li <ye.li@nxp.com>
> The code change updated the NAND driver BCH ECC layout algorithm to
> support large oob size NAND chips(oob > 1024 bytes) and proposed a new
> way to set ECC layout.
> Current implementation requires each chunk size larger than oob size so
> the bad block marker (BBM) can be guaranteed located in data chunk. The
> ECC layout always using the unbalanced layout(Ecc for both meta and
> Data0 chunk), but for the NAND chips with oob larger than 1k, the driver
> cannot support because BCH doesn?t support GF 15 for 2K chunk.
> The change keeps the data chunk no larger than 1k and adjust the ECC
> strength or ECC layout to locate the BBM in data chunk. General idea for
> large oob NAND chips is
> 1.Try all ECC strength from the minimum value required by NAND spec to
> the maximum one that works, any ECC makes the BBM locate in data chunk
> can be chosen.
> 2.If none of them works, using separate ECC for meta, which will add one
> extra ecc with the same ECC strength as other data chunks. This extra
> ECC can guarantee BBM located in data chunk, of course, we need to check
> if oob can afford it.
> Previous code has two methods for ECC layout setting, the
> legacy_calc_ecc_layout and calc_ecc_layout_by_info, the difference
> between these two methods is, legacy_calc_ecc_layout set the chunk size
> larger chan oob size and then set the maximum ECC strength that oob can
> afford. While the calc_ecc_layout_by_info set chunk size and ECC
> strength according to NAND spec. It has been proved that the first
> method cannot provide safe ECC strength for some modern NAND chips, so
> in current code,
> 1. Driver read NAND parameters first and then chose the proper ECC
> layout setting method.
> 2. If the oob is large or NAND required data chunk larger than oob size,
> chose calc_ecc_for_large_oob, otherwise use calc_ecc_layout_by_info
> 3. legacy_calc_ecc_layout only used for some NAND chips does not contains
> necessary information. So this is only a backup plan, it is NOT
> recommended to use these NAND chips.
> Signed-off-by: Han Xu <b45815@freescale.com>
> Signed-off-by: Ye Li <ye.li@nxp.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 06/14] nand: Update SPL MXS NAND mini driver
  2020-05-04 14:08 ` [PATCH 06/14] nand: Update SPL MXS NAND mini driver Peng Fan
@ 2020-05-11 10:16   ` sbabic at denx.de
  0 siblings, 0 replies; 37+ messages in thread
From: sbabic at denx.de @ 2020-05-11 10:16 UTC (permalink / raw)
  To: u-boot

> From: Ye Li <ye.li@nxp.com>
> Update the mini driver to add support for getting ecc info from ONFI and
> support read image data from page unaligned NAND address.
> Signed-off-by: Ye Li <ye.li@nxp.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 02/14] mtd: gpmi: provide the option to use legacy bch geometry
  2020-05-04 14:08 ` [PATCH 02/14] mtd: gpmi: provide the option to use legacy bch geometry Peng Fan
@ 2020-05-11 10:17   ` sbabic at denx.de
  0 siblings, 0 replies; 37+ messages in thread
From: sbabic at denx.de @ 2020-05-11 10:17 UTC (permalink / raw)
  To: u-boot

> From: Ye Li <ye.li@nxp.com>
> Provide an option in DT to use legacy bch geometry, which compatible
> with the 3.10 kernel bch setting. To enable the feature, adding
> "fsl,legacy-bch-geometry" under gpmi-nand node.
> NOTICE: The feature must be enabled/disabled in both u-boot and kernel.
> Signed-off-by: Han Xu <han.xu@nxp.com>
> Signed-off-by: Ye Li <ye.li@nxp.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 04/14] nand: mxs: correct bitflip for erased NAND page
  2020-05-04 14:08 ` [PATCH 04/14] nand: mxs: correct bitflip for erased NAND page Peng Fan
@ 2020-05-11 10:17   ` sbabic at denx.de
  0 siblings, 0 replies; 37+ messages in thread
From: sbabic at denx.de @ 2020-05-11 10:17 UTC (permalink / raw)
  To: u-boot

> This patch is a porting of
> http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/
> commit/?h=imx_4.1.15_1.0.0_ga&id=e4dacc44d22e9474ec456cb330df525cd805ea38
> "
> i.MX6QP and i.MX7D BCH module integrated a new feature to detect the
> bitflip number for erased NAND page. So for these two platform, set the
> erase threshold to gf/2 and if bitflip detected, GPMI driver will
> correct the data to all 0xFF.
> Also updated the imx6qp dts file to ditinguish the GPMI module for i.MX6Q
> with the one for i.MX6QP.
> "
> In this patch, i.MX6UL is added and threshold changed to use ecc_strength.
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 05/14] mxs_nand: Add support for i.MX8M
  2020-05-04 14:08 ` [PATCH 05/14] mxs_nand: Add support for i.MX8M Peng Fan
@ 2020-05-11 10:17   ` sbabic at denx.de
  0 siblings, 0 replies; 37+ messages in thread
From: sbabic at denx.de @ 2020-05-11 10:17 UTC (permalink / raw)
  To: u-boot

> From: Ye Li <ye.li@nxp.com>
> Update the gpmi/apbh_dma/bch drivers and relevant registers for i.MX8M.
> Signed-off-by: Ye Li <ye.li@nxp.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 12/14] MXS_NAND: Add clock support for iMX8
  2020-05-04 14:09 ` [PATCH 12/14] MXS_NAND: Add clock support for iMX8 Peng Fan
@ 2020-05-11 10:18   ` sbabic at denx.de
  0 siblings, 0 replies; 37+ messages in thread
From: sbabic at denx.de @ 2020-05-11 10:18 UTC (permalink / raw)
  To: u-boot

> From: Ye Li <ye.li@nxp.com>
> Since iMX8 has enabled clock uclass, we can parse the clocks from DTB
> and enable them in GPMI driver.
> Signed-off-by: Ye Li <ye.li@nxp.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 09/14] mtd: mxs_nand: fix the gf_13/14 definition issue
  2020-05-04 14:08 ` [PATCH 09/14] mtd: mxs_nand: fix the gf_13/14 definition issue Peng Fan
@ 2020-05-11 10:18   ` sbabic at denx.de
  0 siblings, 0 replies; 37+ messages in thread
From: sbabic at denx.de @ 2020-05-11 10:18 UTC (permalink / raw)
  To: u-boot

> From: Han Xu <han.xu@nxp.com>
> gf_13/14 mask was not set correctly in register definition.
> Signed-off-by: Han Xu <han.xu@nxp.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 13/14] mxs_nand: don't check zero count when ECC reading with randomizer
  2020-05-04 14:09 ` [PATCH 13/14] mxs_nand: don't check zero count when ECC reading with randomizer Peng Fan
@ 2020-05-11 10:18   ` sbabic at denx.de
  0 siblings, 0 replies; 37+ messages in thread
From: sbabic at denx.de @ 2020-05-11 10:18 UTC (permalink / raw)
  To: u-boot

> From: Han Xu <han.xu@nxp.com>
> When enabled randomizer during ECC reading, the controller reported it's
> erased page. Checking zero count will cause data get modified to all
> 0xFF. Stop checking during randomizer to workaround this issue.
> Signed-off-by: Han Xu <han.xu@nxp.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [PATCH 03/14] nand: mxs: fix the bitflips for erased page when uncorrectable error
  2020-05-04 14:08 ` [PATCH 03/14] nand: mxs: fix the bitflips for erased page when uncorrectable error Peng Fan
@ 2020-05-11 10:19   ` sbabic at denx.de
  0 siblings, 0 replies; 37+ messages in thread
From: sbabic at denx.de @ 2020-05-11 10:19 UTC (permalink / raw)
  To: u-boot

> This patch is porting from linux:
> http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/commit/
> ?h=imx_4.1.15_1.0.0_ga&id=3d42fcece496224fde59f9343763fb2dfc5b0768
> "
> We may meet the bitflips in reading an erased page(contains all 0xFF),
> this may causes the UBIFS corrupt, please see the log from Elie:
> -----------------------------------------------------------------
> [    3.831323] UBI warning: ubi_io_read: error -74 (ECC error) while reading 16384 bytes from PEB 443:245760, read only 16384 bytes, retry
> [    3.845026] UBI warning: ubi_io_read: error -74 (ECC error) while reading 16384 bytes from PEB 443:245760, read only 16384 bytes, retry
> [    3.858710] UBI warning: ubi_io_read: error -74 (ECC error) while reading 16384 bytes from PEB 443:245760, read only 16384 bytes, retry
> [    3.872408] UBI error: ubi_io_read: error -74 (ECC error) while reading 16384 bytes from PEB 443:245760, read 16384 bytes
> ...
> [    4.011529] UBIFS error (pid 36): ubifs_recover_leb: corrupt empty space LEB 27:237568, corruption starts at 9815
> [    4.021897] UBIFS error (pid 36): ubifs_scanned_corruption: corruption at LEB 27:247383
> [    4.030000] UBIFS error (pid 36): ubifs_scanned_corruption: first 6569 bytes from LEB 27:247383
> -----------------------------------------------------------------
> This patch does a check for the uncorrectable failure in the following steps:
>    [0] set the threshold.
>        The threshold is set based on the truth:
>        "A single 0 bit will lead to gf_len(13 or 14) bits 0 after the BCH
>         do the ECC."
>         For the sake of safe, we will set the threshold with half the gf_len, and
>         do not make it bigger the ECC strength.
>    [1] count the bitflips of the current ECC chunk, assume it is N.
>    [2] if the (N <= threshold) is true, we continue to read out the page with
>        ECC disabled. and we count the bitflips again, assume it is N2.
>        (We read out the whole page, not just a chunk, this makes the check
>         more strictly, and make the code more simple.)
>    [3] if the (N2 <= threshold) is true again, we can regard this is a erased
>        page. This is because a real erased page is full of 0xFF(maybe also has
>        several bitflips), while a page contains the 0xFF data will definitely
>        has many bitflips in the ECC parity areas.
>    [4] if the [3] fails, we can regard this is a page filled with the '0xFF'
>        data.
> "
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 37+ messages in thread

* GPMI NAND Regression on i.MX6S
  2020-05-04 14:08 ` [PATCH 01/14] mtd: gpmi: change the BCH layout setting for large oob NAND Peng Fan
  2020-05-11 10:16   ` sbabic at denx.de
@ 2022-03-14 13:30   ` Frieder Schrempf
  2022-03-16 14:08     ` Fabio Estevam
  1 sibling, 1 reply; 37+ messages in thread
From: Frieder Schrempf @ 2022-03-14 13:30 UTC (permalink / raw)
  To: Peng Fan, sbabic, festevam, Ye Li; +Cc: uboot-imx, u-boot, Han Xu

Hello everyone,

sorry to dig out an old thread, but the below patch which was applied
upstream as 616f03dabacb causes a regression for me when trying to
attach an UBI volume with U-Boot 2022.01 on a board with i.MX6 Solo and
AMD/Spansion parallel NAND.

The failure looks like this:

ubi0: attaching mtd2
ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes
from PEB 0:0, read 64 bytes
ubi0 error: ubi_io_read: error -74 (ECC error) while reading 2048 bytes
from PEB 0:2048, read 2048 bytes
ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes
from PEB 1:0, read 64 bytes
ubi0 error: ubi_io_read: error -74 (ECC error) while reading 2048 bytes
from PEB 1:2048, read 2048 bytes

The NAND as reported by Linux is:

nand: device found, Manufacturer ID: 0x01, Chip ID: 0xdc
nand: AMD/Spansion S34ML04G1
nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64

A different revision of the same board with a different NAND from
manufacturer ESMT doesn't show the issue:

nand: device found, Manufacturer ID: 0xc8, Chip ID: 0xdc
nand: ESMT NAND 512MiB 3,3V 8-bit
nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64

When I revert the mentioned commit (see patch here: [1]), the UBI boot
starts working again.

Does anyone know what the problem is and how to properly solve it?

Thanks for any help!
Frieder

[1]
https://zerobin.net/?57a57a322bbdcf3c#rZa3vHlWi+RxtRomoljtrngqWwiv6v4Js/2LNfdV10o=

Am 04.05.20 um 16:08 schrieb Peng Fan:
> From: Ye Li <ye.li@nxp.com>
> 
> The code change updated the NAND driver BCH ECC layout algorithm to
> support large oob size NAND chips(oob > 1024 bytes) and proposed a new
> way to set ECC layout.
> 
> Current implementation requires each chunk size larger than oob size so
> the bad block marker (BBM) can be guaranteed located in data chunk. The
> ECC layout always using the unbalanced layout(Ecc for both meta and
> Data0 chunk), but for the NAND chips with oob larger than 1k, the driver
> cannot support because BCH doesn’t support GF 15 for 2K chunk.
> 
> The change keeps the data chunk no larger than 1k and adjust the ECC
> strength or ECC layout to locate the BBM in data chunk. General idea for
> large oob NAND chips is
> 
> 1.Try all ECC strength from the minimum value required by NAND spec to
> the maximum one that works, any ECC makes the BBM locate in data chunk
> can be chosen.
> 
> 2.If none of them works, using separate ECC for meta, which will add one
> extra ecc with the same ECC strength as other data chunks. This extra
> ECC can guarantee BBM located in data chunk, of course, we need to check
> if oob can afford it.
> 
> Previous code has two methods for ECC layout setting, the
> legacy_calc_ecc_layout and calc_ecc_layout_by_info, the difference
> between these two methods is, legacy_calc_ecc_layout set the chunk size
> larger chan oob size and then set the maximum ECC strength that oob can
> afford. While the calc_ecc_layout_by_info set chunk size and ECC
> strength according to NAND spec. It has been proved that the first
> method cannot provide safe ECC strength for some modern NAND chips, so
> in current code,
> 
> 1. Driver read NAND parameters first and then chose the proper ECC
> layout setting method.
> 
> 2. If the oob is large or NAND required data chunk larger than oob size,
> chose calc_ecc_for_large_oob, otherwise use calc_ecc_layout_by_info
> 
> 3. legacy_calc_ecc_layout only used for some NAND chips does not contains
> necessary information. So this is only a backup plan, it is NOT
> recommended to use these NAND chips.
> 
> Signed-off-by: Han Xu <b45815@freescale.com>
> Signed-off-by: Ye Li <ye.li@nxp.com>
> Signed-off-by: Peng Fan <peng.fan@nxp.com>
> ---
>  drivers/mtd/nand/raw/mxs_nand.c | 205 ++++++++++++++++++++++++++--------------
>  include/mxs_nand.h              |  12 ++-
>  2 files changed, 144 insertions(+), 73 deletions(-)
> 
> diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
> index fe8097c146..8da59e39c0 100644
> --- a/drivers/mtd/nand/raw/mxs_nand.c
> +++ b/drivers/mtd/nand/raw/mxs_nand.c
> @@ -112,53 +112,32 @@ static uint32_t mxs_nand_aux_status_offset(void)
>  	return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
>  }
>  
> -static inline int mxs_nand_calc_mark_offset(struct bch_geometry *geo,
> -					    uint32_t page_data_size)
> +static inline bool mxs_nand_bbm_in_data_chunk(struct bch_geometry *geo, struct mtd_info *mtd,
> +		unsigned int *chunk_num)
>  {
> -	uint32_t chunk_data_size_in_bits = geo->ecc_chunk_size * 8;
> -	uint32_t chunk_ecc_size_in_bits = geo->ecc_strength * geo->gf_len;
> -	uint32_t chunk_total_size_in_bits;
> -	uint32_t block_mark_chunk_number;
> -	uint32_t block_mark_chunk_bit_offset;
> -	uint32_t block_mark_bit_offset;
> +	unsigned int i, j;
>  
> -	chunk_total_size_in_bits =
> -			chunk_data_size_in_bits + chunk_ecc_size_in_bits;
> -
> -	/* Compute the bit offset of the block mark within the physical page. */
> -	block_mark_bit_offset = page_data_size * 8;
> -
> -	/* Subtract the metadata bits. */
> -	block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8;
> -
> -	/*
> -	 * Compute the chunk number (starting at zero) in which the block mark
> -	 * appears.
> -	 */
> -	block_mark_chunk_number =
> -			block_mark_bit_offset / chunk_total_size_in_bits;
> -
> -	/*
> -	 * Compute the bit offset of the block mark within its chunk, and
> -	 * validate it.
> -	 */
> -	block_mark_chunk_bit_offset = block_mark_bit_offset -
> -			(block_mark_chunk_number * chunk_total_size_in_bits);
> +	if (geo->ecc_chunk0_size != geo->ecc_chunkn_size) {
> +		dev_err(this->dev, "The size of chunk0 must equal to chunkn\n");
> +		return false;
> +	}
>  
> -	if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
> -		return -EINVAL;
> +	i = (mtd->writesize * 8 - MXS_NAND_METADATA_SIZE * 8) /
> +		(geo->gf_len * geo->ecc_strength +
> +				geo->ecc_chunkn_size * 8);
>  
> -	/*
> -	 * Now that we know the chunk number in which the block mark appears,
> -	 * we can subtract all the ECC bits that appear before it.
> -	 */
> -	block_mark_bit_offset -=
> -		block_mark_chunk_number * chunk_ecc_size_in_bits;
> +	j = (mtd->writesize * 8 - MXS_NAND_METADATA_SIZE * 8) -
> +		(geo->gf_len * geo->ecc_strength +
> +				geo->ecc_chunkn_size * 8) * i;
>  
> -	geo->block_mark_byte_offset = block_mark_bit_offset >> 3;
> -	geo->block_mark_bit_offset = block_mark_bit_offset & 0x7;
> +	if (j < geo->ecc_chunkn_size * 8) {
> +		*chunk_num = i + 1;
> +		dev_dbg(this->dev, "Set ecc to %d and bbm in chunk %d\n",
> +			geo->ecc_strength, *chunk_num);
> +		return true;
> +	}
>  
> -	return 0;
> +	return false;
>  }
>  
>  static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
> @@ -168,6 +147,7 @@ static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
>  	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> +	unsigned int block_mark_bit_offset;
>  
>  	switch (ecc_step) {
>  	case SZ_512:
> @@ -180,45 +160,51 @@ static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
>  		return -EINVAL;
>  	}
>  
> -	geo->ecc_chunk_size = ecc_step;
> +	geo->ecc_chunk0_size = ecc_step;
> +	geo->ecc_chunkn_size = ecc_step;
>  	geo->ecc_strength = round_up(ecc_strength, 2);
>  
>  	/* Keep the C >= O */
> -	if (geo->ecc_chunk_size < mtd->oobsize)
> +	if (geo->ecc_chunkn_size < mtd->oobsize)
>  		return -EINVAL;
>  
>  	if (geo->ecc_strength > nand_info->max_ecc_strength_supported)
>  		return -EINVAL;
>  
> -	geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
> +	geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
> +
> +	/* For bit swap. */
> +	block_mark_bit_offset = mtd->writesize * 8 -
> +		(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
> +				+ MXS_NAND_METADATA_SIZE * 8);
> +
> +	geo->block_mark_byte_offset = block_mark_bit_offset / 8;
> +	geo->block_mark_bit_offset  = block_mark_bit_offset % 8;
>  
>  	return 0;
>  }
>  
> -static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo,
> +static inline int mxs_nand_legacy_calc_ecc_layout(struct bch_geometry *geo,
>  					   struct mtd_info *mtd)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
>  	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> +	unsigned int block_mark_bit_offset;
>  
>  	/* The default for the length of Galois Field. */
>  	geo->gf_len = 13;
>  
>  	/* The default for chunk size. */
> -	geo->ecc_chunk_size = 512;
> +	geo->ecc_chunk0_size = 512;
> +	geo->ecc_chunkn_size = 512;
>  
> -	if (geo->ecc_chunk_size < mtd->oobsize) {
> +	if (geo->ecc_chunkn_size < mtd->oobsize) {
>  		geo->gf_len = 14;
> -		geo->ecc_chunk_size *= 2;
> +		geo->ecc_chunk0_size *= 2;
> +		geo->ecc_chunkn_size *= 2;
>  	}
>  
> -	if (mtd->oobsize > geo->ecc_chunk_size) {
> -		printf("Not support the NAND chips whose oob size is larger then %d bytes!\n",
> -		       geo->ecc_chunk_size);
> -		return -EINVAL;
> -	}
> -
> -	geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
> +	geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
>  
>  	/*
>  	 * Determine the ECC layout with the formula:
> @@ -234,6 +220,84 @@ static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo,
>  	geo->ecc_strength = min(round_down(geo->ecc_strength, 2),
>  				nand_info->max_ecc_strength_supported);
>  
> +	block_mark_bit_offset = mtd->writesize * 8 -
> +		(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
> +				+ MXS_NAND_METADATA_SIZE * 8);
> +
> +	geo->block_mark_byte_offset = block_mark_bit_offset / 8;
> +	geo->block_mark_bit_offset  = block_mark_bit_offset % 8;
> +
> +	return 0;
> +}
> +
> +static inline int mxs_nand_calc_ecc_for_large_oob(struct bch_geometry *geo,
> +					   struct mtd_info *mtd)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> +	unsigned int block_mark_bit_offset;
> +	unsigned int max_ecc;
> +	unsigned int bbm_chunk;
> +	unsigned int i;
> +
> +	/* sanity check for the minimum ecc nand required */
> +	if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
> +		return -EINVAL;
> +	geo->ecc_strength = chip->ecc_strength_ds;
> +
> +	/* calculate the maximum ecc platform can support*/
> +	geo->gf_len = 14;
> +	geo->ecc_chunk0_size = 1024;
> +	geo->ecc_chunkn_size = 1024;
> +	geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
> +	max_ecc = ((mtd->oobsize - MXS_NAND_METADATA_SIZE) * 8)
> +			/ (geo->gf_len * geo->ecc_chunk_count);
> +	max_ecc = min(round_down(max_ecc, 2),
> +				nand_info->max_ecc_strength_supported);
> +
> +
> +	/* search a supported ecc strength that makes bbm */
> +	/* located in data chunk  */
> +	geo->ecc_strength = chip->ecc_strength_ds;
> +	while (!(geo->ecc_strength > max_ecc)) {
> +		if (mxs_nand_bbm_in_data_chunk(geo, mtd, &bbm_chunk))
> +			break;
> +		geo->ecc_strength += 2;
> +	}
> +
> +	/* if none of them works, keep using the minimum ecc */
> +	/* nand required but changing ecc page layout  */
> +	if (geo->ecc_strength > max_ecc) {
> +		geo->ecc_strength = chip->ecc_strength_ds;
> +		/* add extra ecc for meta data */
> +		geo->ecc_chunk0_size = 0;
> +		geo->ecc_chunk_count = (mtd->writesize / geo->ecc_chunkn_size) + 1;
> +		geo->ecc_for_meta = 1;
> +		/* check if oob can afford this extra ecc chunk */
> +		if (mtd->oobsize * 8 < MXS_NAND_METADATA_SIZE * 8 +
> +				geo->gf_len * geo->ecc_strength
> +				* geo->ecc_chunk_count) {
> +			printf("unsupported NAND chip with new layout\n");
> +			return -EINVAL;
> +		}
> +
> +		/* calculate in which chunk bbm located */
> +		bbm_chunk = (mtd->writesize * 8 - MXS_NAND_METADATA_SIZE * 8 -
> +			geo->gf_len * geo->ecc_strength) /
> +			(geo->gf_len * geo->ecc_strength +
> +					geo->ecc_chunkn_size * 8) + 1;
> +	}
> +
> +	/* calculate the number of ecc chunk behind the bbm */
> +	i = (mtd->writesize / geo->ecc_chunkn_size) - bbm_chunk + 1;
> +
> +	block_mark_bit_offset = mtd->writesize * 8 -
> +		(geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - i)
> +				+ MXS_NAND_METADATA_SIZE * 8);
> +
> +	geo->block_mark_byte_offset = block_mark_bit_offset / 8;
> +	geo->block_mark_bit_offset  = block_mark_bit_offset % 8;
> +
>  	return 0;
>  }
>  
> @@ -983,18 +1047,23 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, struct bch_geometry *geo)
>  	struct nand_chip *nand = mtd_to_nand(mtd);
>  	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
>  
> -	if (chip->ecc.strength > 0 && chip->ecc.size > 0)
> -		return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
> -				chip->ecc.strength, chip->ecc.size);
> +	if (chip->ecc_strength_ds > nand_info->max_ecc_strength_supported) {
> +		printf("unsupported NAND chip, minimum ecc required %d\n"
> +			, chip->ecc_strength_ds);
> +		return -EINVAL;
> +	}
> +
> +	if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
> +			(mtd->oobsize < 1024)) {
> +		dev_warn(this->dev, "use legacy bch geometry\n");
> +		return mxs_nand_legacy_calc_ecc_layout(geo, mtd);
> +	}
>  
> -	if (nand_info->use_minimum_ecc ||
> -		mxs_nand_calc_ecc_layout(geo, mtd)) {
> -		if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
> -			return -EINVAL;
> +	if (mtd->oobsize > 1024 || chip->ecc_step_ds < mtd->oobsize)
> +		return mxs_nand_calc_ecc_for_large_oob(geo, mtd);
>  
> -		return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
> +	return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
>  				chip->ecc_strength_ds, chip->ecc_step_ds);
> -	}
>  
>  	return 0;
>  }
> @@ -1025,8 +1094,6 @@ int mxs_nand_setup_ecc(struct mtd_info *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);
>  
> @@ -1034,7 +1101,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
>  	tmp = (geo->ecc_chunk_count - 1) << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
>  	tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
>  	tmp |= (geo->ecc_strength >> 1) << BCH_FLASHLAYOUT0_ECC0_OFFSET;
> -	tmp |= geo->ecc_chunk_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
> +	tmp |= geo->ecc_chunk0_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
>  	tmp |= (geo->gf_len == 14 ? 1 : 0) <<
>  		BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
>  	writel(tmp, &bch_regs->hw_bch_flash0layout0);
> @@ -1043,7 +1110,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
>  	tmp = (mtd->writesize + mtd->oobsize)
>  		<< BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
>  	tmp |= (geo->ecc_strength >> 1) << BCH_FLASHLAYOUT1_ECCN_OFFSET;
> -	tmp |= geo->ecc_chunk_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
> +	tmp |= geo->ecc_chunkn_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
>  	tmp |= (geo->gf_len == 14 ? 1 : 0) <<
>  		BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
>  	writel(tmp, &bch_regs->hw_bch_flash0layout1);
> @@ -1268,7 +1335,7 @@ int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info)
>  
>  	nand->ecc.layout	= &fake_ecc_layout;
>  	nand->ecc.mode		= NAND_ECC_HW;
> -	nand->ecc.size		= nand_info->bch_geometry.ecc_chunk_size;
> +	nand->ecc.size		= nand_info->bch_geometry.ecc_chunkn_size;
>  	nand->ecc.strength	= nand_info->bch_geometry.ecc_strength;
>  
>  	/* second phase scan */
> diff --git a/include/mxs_nand.h b/include/mxs_nand.h
> index ada20483d0..497da77a16 100644
> --- a/include/mxs_nand.h
> +++ b/include/mxs_nand.h
> @@ -16,22 +16,26 @@
>   * @gf_len:                   The length of Galois Field. (e.g., 13 or 14)
>   * @ecc_strength:             A number that describes the strength of the ECC
>   *                            algorithm.
> - * @ecc_chunk_size:           The size, in bytes, of a single ECC chunk. Note
> - *                            the first chunk in the page includes both data and
> - *                            metadata, so it's a bit larger than this value.
> + * @ecc_chunk0_size:          The size, in bytes, of a first ECC chunk.
> + * @ecc_chunkn_size:          The size, in bytes, of a single ECC chunk after
> + *                            the first chunk in the page.
>   * @ecc_chunk_count:          The number of ECC chunks in the page,
>   * @block_mark_byte_offset:   The byte offset in the ECC-based page view at
>   *                            which the underlying physical block mark appears.
>   * @block_mark_bit_offset:    The bit offset into the ECC-based page view at
>   *                            which the underlying physical block mark appears.
> + * @ecc_for_meta:             The flag to indicate if there is a dedicate ecc
> + *                            for meta.
>   */
>  struct bch_geometry {
>  	unsigned int  gf_len;
>  	unsigned int  ecc_strength;
> -	unsigned int  ecc_chunk_size;
> +	unsigned int  ecc_chunk0_size;
> +	unsigned int  ecc_chunkn_size;
>  	unsigned int  ecc_chunk_count;
>  	unsigned int  block_mark_byte_offset;
>  	unsigned int  block_mark_bit_offset;
> +	unsigned int  ecc_for_meta; /* ECC for meta data */
>  };
>  
>  struct mxs_nand_info {
> 

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: GPMI NAND Regression on i.MX6S
  2022-03-14 13:30   ` GPMI NAND Regression on i.MX6S Frieder Schrempf
@ 2022-03-16 14:08     ` Fabio Estevam
  2022-03-16 16:34       ` Tim Harvey
  0 siblings, 1 reply; 37+ messages in thread
From: Fabio Estevam @ 2022-03-16 14:08 UTC (permalink / raw)
  To: Frieder Schrempf, Han Xu
  Cc: Peng Fan, Stefano Babic, Ye Li, dl-uboot-imx, U-Boot-Denx

Adding Han Xu's NXP email on Cc.

On Mon, Mar 14, 2022 at 10:31 AM Frieder Schrempf
<frieder.schrempf@kontron.de> wrote:
>
> Hello everyone,
>
> sorry to dig out an old thread, but the below patch which was applied
> upstream as 616f03dabacb causes a regression for me when trying to
> attach an UBI volume with U-Boot 2022.01 on a board with i.MX6 Solo and
> AMD/Spansion parallel NAND.
>
> The failure looks like this:
>
> ubi0: attaching mtd2
> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes
> from PEB 0:0, read 64 bytes
> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 2048 bytes
> from PEB 0:2048, read 2048 bytes
> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes
> from PEB 1:0, read 64 bytes
> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 2048 bytes
> from PEB 1:2048, read 2048 bytes
>
> The NAND as reported by Linux is:
>
> nand: device found, Manufacturer ID: 0x01, Chip ID: 0xdc
> nand: AMD/Spansion S34ML04G1
> nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
>
> A different revision of the same board with a different NAND from
> manufacturer ESMT doesn't show the issue:
>
> nand: device found, Manufacturer ID: 0xc8, Chip ID: 0xdc
> nand: ESMT NAND 512MiB 3,3V 8-bit
> nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
>
> When I revert the mentioned commit (see patch here: [1]), the UBI boot
> starts working again.
>
> Does anyone know what the problem is and how to properly solve it?
>
> Thanks for any help!
> Frieder
>
> [1]
> https://zerobin.net/?57a57a322bbdcf3c#rZa3vHlWi+RxtRomoljtrngqWwiv6v4Js/2LNfdV10o=
>
> Am 04.05.20 um 16:08 schrieb Peng Fan:
> > From: Ye Li <ye.li@nxp.com>
> >
> > The code change updated the NAND driver BCH ECC layout algorithm to
> > support large oob size NAND chips(oob > 1024 bytes) and proposed a new
> > way to set ECC layout.
> >
> > Current implementation requires each chunk size larger than oob size so
> > the bad block marker (BBM) can be guaranteed located in data chunk. The
> > ECC layout always using the unbalanced layout(Ecc for both meta and
> > Data0 chunk), but for the NAND chips with oob larger than 1k, the driver
> > cannot support because BCH doesn’t support GF 15 for 2K chunk.
> >
> > The change keeps the data chunk no larger than 1k and adjust the ECC
> > strength or ECC layout to locate the BBM in data chunk. General idea for
> > large oob NAND chips is
> >
> > 1.Try all ECC strength from the minimum value required by NAND spec to
> > the maximum one that works, any ECC makes the BBM locate in data chunk
> > can be chosen.
> >
> > 2.If none of them works, using separate ECC for meta, which will add one
> > extra ecc with the same ECC strength as other data chunks. This extra
> > ECC can guarantee BBM located in data chunk, of course, we need to check
> > if oob can afford it.
> >
> > Previous code has two methods for ECC layout setting, the
> > legacy_calc_ecc_layout and calc_ecc_layout_by_info, the difference
> > between these two methods is, legacy_calc_ecc_layout set the chunk size
> > larger chan oob size and then set the maximum ECC strength that oob can
> > afford. While the calc_ecc_layout_by_info set chunk size and ECC
> > strength according to NAND spec. It has been proved that the first
> > method cannot provide safe ECC strength for some modern NAND chips, so
> > in current code,
> >
> > 1. Driver read NAND parameters first and then chose the proper ECC
> > layout setting method.
> >
> > 2. If the oob is large or NAND required data chunk larger than oob size,
> > chose calc_ecc_for_large_oob, otherwise use calc_ecc_layout_by_info
> >
> > 3. legacy_calc_ecc_layout only used for some NAND chips does not contains
> > necessary information. So this is only a backup plan, it is NOT
> > recommended to use these NAND chips.
> >
> > Signed-off-by: Han Xu <b45815@freescale.com>
> > Signed-off-by: Ye Li <ye.li@nxp.com>
> > Signed-off-by: Peng Fan <peng.fan@nxp.com>
> > ---
> >  drivers/mtd/nand/raw/mxs_nand.c | 205 ++++++++++++++++++++++++++--------------
> >  include/mxs_nand.h              |  12 ++-
> >  2 files changed, 144 insertions(+), 73 deletions(-)
> >
> > diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
> > index fe8097c146..8da59e39c0 100644
> > --- a/drivers/mtd/nand/raw/mxs_nand.c
> > +++ b/drivers/mtd/nand/raw/mxs_nand.c
> > @@ -112,53 +112,32 @@ static uint32_t mxs_nand_aux_status_offset(void)
> >       return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
> >  }
> >
> > -static inline int mxs_nand_calc_mark_offset(struct bch_geometry *geo,
> > -                                         uint32_t page_data_size)
> > +static inline bool mxs_nand_bbm_in_data_chunk(struct bch_geometry *geo, struct mtd_info *mtd,
> > +             unsigned int *chunk_num)
> >  {
> > -     uint32_t chunk_data_size_in_bits = geo->ecc_chunk_size * 8;
> > -     uint32_t chunk_ecc_size_in_bits = geo->ecc_strength * geo->gf_len;
> > -     uint32_t chunk_total_size_in_bits;
> > -     uint32_t block_mark_chunk_number;
> > -     uint32_t block_mark_chunk_bit_offset;
> > -     uint32_t block_mark_bit_offset;
> > +     unsigned int i, j;
> >
> > -     chunk_total_size_in_bits =
> > -                     chunk_data_size_in_bits + chunk_ecc_size_in_bits;
> > -
> > -     /* Compute the bit offset of the block mark within the physical page. */
> > -     block_mark_bit_offset = page_data_size * 8;
> > -
> > -     /* Subtract the metadata bits. */
> > -     block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8;
> > -
> > -     /*
> > -      * Compute the chunk number (starting at zero) in which the block mark
> > -      * appears.
> > -      */
> > -     block_mark_chunk_number =
> > -                     block_mark_bit_offset / chunk_total_size_in_bits;
> > -
> > -     /*
> > -      * Compute the bit offset of the block mark within its chunk, and
> > -      * validate it.
> > -      */
> > -     block_mark_chunk_bit_offset = block_mark_bit_offset -
> > -                     (block_mark_chunk_number * chunk_total_size_in_bits);
> > +     if (geo->ecc_chunk0_size != geo->ecc_chunkn_size) {
> > +             dev_err(this->dev, "The size of chunk0 must equal to chunkn\n");
> > +             return false;
> > +     }
> >
> > -     if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
> > -             return -EINVAL;
> > +     i = (mtd->writesize * 8 - MXS_NAND_METADATA_SIZE * 8) /
> > +             (geo->gf_len * geo->ecc_strength +
> > +                             geo->ecc_chunkn_size * 8);
> >
> > -     /*
> > -      * Now that we know the chunk number in which the block mark appears,
> > -      * we can subtract all the ECC bits that appear before it.
> > -      */
> > -     block_mark_bit_offset -=
> > -             block_mark_chunk_number * chunk_ecc_size_in_bits;
> > +     j = (mtd->writesize * 8 - MXS_NAND_METADATA_SIZE * 8) -
> > +             (geo->gf_len * geo->ecc_strength +
> > +                             geo->ecc_chunkn_size * 8) * i;
> >
> > -     geo->block_mark_byte_offset = block_mark_bit_offset >> 3;
> > -     geo->block_mark_bit_offset = block_mark_bit_offset & 0x7;
> > +     if (j < geo->ecc_chunkn_size * 8) {
> > +             *chunk_num = i + 1;
> > +             dev_dbg(this->dev, "Set ecc to %d and bbm in chunk %d\n",
> > +                     geo->ecc_strength, *chunk_num);
> > +             return true;
> > +     }
> >
> > -     return 0;
> > +     return false;
> >  }
> >
> >  static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
> > @@ -168,6 +147,7 @@ static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
> >  {
> >       struct nand_chip *chip = mtd_to_nand(mtd);
> >       struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> > +     unsigned int block_mark_bit_offset;
> >
> >       switch (ecc_step) {
> >       case SZ_512:
> > @@ -180,45 +160,51 @@ static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
> >               return -EINVAL;
> >       }
> >
> > -     geo->ecc_chunk_size = ecc_step;
> > +     geo->ecc_chunk0_size = ecc_step;
> > +     geo->ecc_chunkn_size = ecc_step;
> >       geo->ecc_strength = round_up(ecc_strength, 2);
> >
> >       /* Keep the C >= O */
> > -     if (geo->ecc_chunk_size < mtd->oobsize)
> > +     if (geo->ecc_chunkn_size < mtd->oobsize)
> >               return -EINVAL;
> >
> >       if (geo->ecc_strength > nand_info->max_ecc_strength_supported)
> >               return -EINVAL;
> >
> > -     geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
> > +     geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
> > +
> > +     /* For bit swap. */
> > +     block_mark_bit_offset = mtd->writesize * 8 -
> > +             (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
> > +                             + MXS_NAND_METADATA_SIZE * 8);
> > +
> > +     geo->block_mark_byte_offset = block_mark_bit_offset / 8;
> > +     geo->block_mark_bit_offset  = block_mark_bit_offset % 8;
> >
> >       return 0;
> >  }
> >
> > -static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo,
> > +static inline int mxs_nand_legacy_calc_ecc_layout(struct bch_geometry *geo,
> >                                          struct mtd_info *mtd)
> >  {
> >       struct nand_chip *chip = mtd_to_nand(mtd);
> >       struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> > +     unsigned int block_mark_bit_offset;
> >
> >       /* The default for the length of Galois Field. */
> >       geo->gf_len = 13;
> >
> >       /* The default for chunk size. */
> > -     geo->ecc_chunk_size = 512;
> > +     geo->ecc_chunk0_size = 512;
> > +     geo->ecc_chunkn_size = 512;
> >
> > -     if (geo->ecc_chunk_size < mtd->oobsize) {
> > +     if (geo->ecc_chunkn_size < mtd->oobsize) {
> >               geo->gf_len = 14;
> > -             geo->ecc_chunk_size *= 2;
> > +             geo->ecc_chunk0_size *= 2;
> > +             geo->ecc_chunkn_size *= 2;
> >       }
> >
> > -     if (mtd->oobsize > geo->ecc_chunk_size) {
> > -             printf("Not support the NAND chips whose oob size is larger then %d bytes!\n",
> > -                    geo->ecc_chunk_size);
> > -             return -EINVAL;
> > -     }
> > -
> > -     geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
> > +     geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
> >
> >       /*
> >        * Determine the ECC layout with the formula:
> > @@ -234,6 +220,84 @@ static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo,
> >       geo->ecc_strength = min(round_down(geo->ecc_strength, 2),
> >                               nand_info->max_ecc_strength_supported);
> >
> > +     block_mark_bit_offset = mtd->writesize * 8 -
> > +             (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
> > +                             + MXS_NAND_METADATA_SIZE * 8);
> > +
> > +     geo->block_mark_byte_offset = block_mark_bit_offset / 8;
> > +     geo->block_mark_bit_offset  = block_mark_bit_offset % 8;
> > +
> > +     return 0;
> > +}
> > +
> > +static inline int mxs_nand_calc_ecc_for_large_oob(struct bch_geometry *geo,
> > +                                        struct mtd_info *mtd)
> > +{
> > +     struct nand_chip *chip = mtd_to_nand(mtd);
> > +     struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> > +     unsigned int block_mark_bit_offset;
> > +     unsigned int max_ecc;
> > +     unsigned int bbm_chunk;
> > +     unsigned int i;
> > +
> > +     /* sanity check for the minimum ecc nand required */
> > +     if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
> > +             return -EINVAL;
> > +     geo->ecc_strength = chip->ecc_strength_ds;
> > +
> > +     /* calculate the maximum ecc platform can support*/
> > +     geo->gf_len = 14;
> > +     geo->ecc_chunk0_size = 1024;
> > +     geo->ecc_chunkn_size = 1024;
> > +     geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
> > +     max_ecc = ((mtd->oobsize - MXS_NAND_METADATA_SIZE) * 8)
> > +                     / (geo->gf_len * geo->ecc_chunk_count);
> > +     max_ecc = min(round_down(max_ecc, 2),
> > +                             nand_info->max_ecc_strength_supported);
> > +
> > +
> > +     /* search a supported ecc strength that makes bbm */
> > +     /* located in data chunk  */
> > +     geo->ecc_strength = chip->ecc_strength_ds;
> > +     while (!(geo->ecc_strength > max_ecc)) {
> > +             if (mxs_nand_bbm_in_data_chunk(geo, mtd, &bbm_chunk))
> > +                     break;
> > +             geo->ecc_strength += 2;
> > +     }
> > +
> > +     /* if none of them works, keep using the minimum ecc */
> > +     /* nand required but changing ecc page layout  */
> > +     if (geo->ecc_strength > max_ecc) {
> > +             geo->ecc_strength = chip->ecc_strength_ds;
> > +             /* add extra ecc for meta data */
> > +             geo->ecc_chunk0_size = 0;
> > +             geo->ecc_chunk_count = (mtd->writesize / geo->ecc_chunkn_size) + 1;
> > +             geo->ecc_for_meta = 1;
> > +             /* check if oob can afford this extra ecc chunk */
> > +             if (mtd->oobsize * 8 < MXS_NAND_METADATA_SIZE * 8 +
> > +                             geo->gf_len * geo->ecc_strength
> > +                             * geo->ecc_chunk_count) {
> > +                     printf("unsupported NAND chip with new layout\n");
> > +                     return -EINVAL;
> > +             }
> > +
> > +             /* calculate in which chunk bbm located */
> > +             bbm_chunk = (mtd->writesize * 8 - MXS_NAND_METADATA_SIZE * 8 -
> > +                     geo->gf_len * geo->ecc_strength) /
> > +                     (geo->gf_len * geo->ecc_strength +
> > +                                     geo->ecc_chunkn_size * 8) + 1;
> > +     }
> > +
> > +     /* calculate the number of ecc chunk behind the bbm */
> > +     i = (mtd->writesize / geo->ecc_chunkn_size) - bbm_chunk + 1;
> > +
> > +     block_mark_bit_offset = mtd->writesize * 8 -
> > +             (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - i)
> > +                             + MXS_NAND_METADATA_SIZE * 8);
> > +
> > +     geo->block_mark_byte_offset = block_mark_bit_offset / 8;
> > +     geo->block_mark_bit_offset  = block_mark_bit_offset % 8;
> > +
> >       return 0;
> >  }
> >
> > @@ -983,18 +1047,23 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, struct bch_geometry *geo)
> >       struct nand_chip *nand = mtd_to_nand(mtd);
> >       struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
> >
> > -     if (chip->ecc.strength > 0 && chip->ecc.size > 0)
> > -             return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
> > -                             chip->ecc.strength, chip->ecc.size);
> > +     if (chip->ecc_strength_ds > nand_info->max_ecc_strength_supported) {
> > +             printf("unsupported NAND chip, minimum ecc required %d\n"
> > +                     , chip->ecc_strength_ds);
> > +             return -EINVAL;
> > +     }
> > +
> > +     if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
> > +                     (mtd->oobsize < 1024)) {
> > +             dev_warn(this->dev, "use legacy bch geometry\n");
> > +             return mxs_nand_legacy_calc_ecc_layout(geo, mtd);
> > +     }
> >
> > -     if (nand_info->use_minimum_ecc ||
> > -             mxs_nand_calc_ecc_layout(geo, mtd)) {
> > -             if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
> > -                     return -EINVAL;
> > +     if (mtd->oobsize > 1024 || chip->ecc_step_ds < mtd->oobsize)
> > +             return mxs_nand_calc_ecc_for_large_oob(geo, mtd);
> >
> > -             return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
> > +     return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
> >                               chip->ecc_strength_ds, chip->ecc_step_ds);
> > -     }
> >
> >       return 0;
> >  }
> > @@ -1025,8 +1094,6 @@ int mxs_nand_setup_ecc(struct mtd_info *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);
> >
> > @@ -1034,7 +1101,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
> >       tmp = (geo->ecc_chunk_count - 1) << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
> >       tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
> >       tmp |= (geo->ecc_strength >> 1) << BCH_FLASHLAYOUT0_ECC0_OFFSET;
> > -     tmp |= geo->ecc_chunk_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
> > +     tmp |= geo->ecc_chunk0_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
> >       tmp |= (geo->gf_len == 14 ? 1 : 0) <<
> >               BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
> >       writel(tmp, &bch_regs->hw_bch_flash0layout0);
> > @@ -1043,7 +1110,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
> >       tmp = (mtd->writesize + mtd->oobsize)
> >               << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
> >       tmp |= (geo->ecc_strength >> 1) << BCH_FLASHLAYOUT1_ECCN_OFFSET;
> > -     tmp |= geo->ecc_chunk_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
> > +     tmp |= geo->ecc_chunkn_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
> >       tmp |= (geo->gf_len == 14 ? 1 : 0) <<
> >               BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
> >       writel(tmp, &bch_regs->hw_bch_flash0layout1);
> > @@ -1268,7 +1335,7 @@ int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info)
> >
> >       nand->ecc.layout        = &fake_ecc_layout;
> >       nand->ecc.mode          = NAND_ECC_HW;
> > -     nand->ecc.size          = nand_info->bch_geometry.ecc_chunk_size;
> > +     nand->ecc.size          = nand_info->bch_geometry.ecc_chunkn_size;
> >       nand->ecc.strength      = nand_info->bch_geometry.ecc_strength;
> >
> >       /* second phase scan */
> > diff --git a/include/mxs_nand.h b/include/mxs_nand.h
> > index ada20483d0..497da77a16 100644
> > --- a/include/mxs_nand.h
> > +++ b/include/mxs_nand.h
> > @@ -16,22 +16,26 @@
> >   * @gf_len:                   The length of Galois Field. (e.g., 13 or 14)
> >   * @ecc_strength:             A number that describes the strength of the ECC
> >   *                            algorithm.
> > - * @ecc_chunk_size:           The size, in bytes, of a single ECC chunk. Note
> > - *                            the first chunk in the page includes both data and
> > - *                            metadata, so it's a bit larger than this value.
> > + * @ecc_chunk0_size:          The size, in bytes, of a first ECC chunk.
> > + * @ecc_chunkn_size:          The size, in bytes, of a single ECC chunk after
> > + *                            the first chunk in the page.
> >   * @ecc_chunk_count:          The number of ECC chunks in the page,
> >   * @block_mark_byte_offset:   The byte offset in the ECC-based page view at
> >   *                            which the underlying physical block mark appears.
> >   * @block_mark_bit_offset:    The bit offset into the ECC-based page view at
> >   *                            which the underlying physical block mark appears.
> > + * @ecc_for_meta:             The flag to indicate if there is a dedicate ecc
> > + *                            for meta.
> >   */
> >  struct bch_geometry {
> >       unsigned int  gf_len;
> >       unsigned int  ecc_strength;
> > -     unsigned int  ecc_chunk_size;
> > +     unsigned int  ecc_chunk0_size;
> > +     unsigned int  ecc_chunkn_size;
> >       unsigned int  ecc_chunk_count;
> >       unsigned int  block_mark_byte_offset;
> >       unsigned int  block_mark_bit_offset;
> > +     unsigned int  ecc_for_meta; /* ECC for meta data */
> >  };
> >
> >  struct mxs_nand_info {
> >

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: GPMI NAND Regression on i.MX6S
  2022-03-16 14:08     ` Fabio Estevam
@ 2022-03-16 16:34       ` Tim Harvey
  2022-03-17  8:06         ` Frieder Schrempf
  0 siblings, 1 reply; 37+ messages in thread
From: Tim Harvey @ 2022-03-16 16:34 UTC (permalink / raw)
  To: Fabio Estevam, Frieder Schrempf
  Cc: Han Xu, Peng Fan, Stefano Babic, Ye Li, dl-uboot-imx, U-Boot-Denx

On Wed, Mar 16, 2022 at 7:09 AM Fabio Estevam <festevam@gmail.com> wrote:
>
> Adding Han Xu's NXP email on Cc.
>
> On Mon, Mar 14, 2022 at 10:31 AM Frieder Schrempf
> <frieder.schrempf@kontron.de> wrote:
> >
> > Hello everyone,
> >
> > sorry to dig out an old thread, but the below patch which was applied
> > upstream as 616f03dabacb causes a regression for me when trying to
> > attach an UBI volume with U-Boot 2022.01 on a board with i.MX6 Solo and
> > AMD/Spansion parallel NAND.
> >
> > The failure looks like this:
> >
> > ubi0: attaching mtd2
> > ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes
> > from PEB 0:0, read 64 bytes
> > ubi0 error: ubi_io_read: error -74 (ECC error) while reading 2048 bytes
> > from PEB 0:2048, read 2048 bytes
> > ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes
> > from PEB 1:0, read 64 bytes
> > ubi0 error: ubi_io_read: error -74 (ECC error) while reading 2048 bytes
> > from PEB 1:2048, read 2048 bytes
> >
> > The NAND as reported by Linux is:
> >
> > nand: device found, Manufacturer ID: 0x01, Chip ID: 0xdc
> > nand: AMD/Spansion S34ML04G1
> > nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
> >
> > A different revision of the same board with a different NAND from
> > manufacturer ESMT doesn't show the issue:
> >
> > nand: device found, Manufacturer ID: 0xc8, Chip ID: 0xdc
> > nand: ESMT NAND 512MiB 3,3V 8-bit
> > nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
> >
> > When I revert the mentioned commit (see patch here: [1]), the UBI boot
> > starts working again.
> >
> > Does anyone know what the problem is and how to properly solve it?
> >
> > Thanks for any help!
> > Frieder
> >
> > [1]
> > https://zerobin.net/?57a57a322bbdcf3c#rZa3vHlWi+RxtRomoljtrngqWwiv6v4Js/2LNfdV10o=
> >

Frieder,

I see the same issue here with IMX6Q/DL GPMI NAND.

If I re-flash the ubi within U-Boot (tftpboot $loadaddr rootfs.ubi &&
nand erase.part rootfs && nand write $loadaddr rootfs $filesize) I
find that U-Boot can attach and mount the ubi fine but Linux will have
issues

Ventana > ubi part rootfs
ubi0: attaching mtd3
ubi0: scanning is finished
ubi0: attached mtd3 (name "rootfs", size 2031 MiB)
ubi0: PEB size: 262144 bytes (256 KiB), LEB size: 253952 bytes
ubi0: min./max. I/O unit sizes: 4096/4096, sub-page size 4096
ubi0: VID header offset: 4096 (aligned 4096), data offset: 8192
ubi0: good PEBs: 8123, bad PEBs: 1, corrupted PEBs: 0
ubi0: user volume: 3, internal volumes: 1, max. volumes count: 128
ubi0: max/mean erase counter: 1/0, WL threshold: 4096, image sequence
number: 1632759352
ubi0: available PEBs: 0, total reserved PEBs: 8123, PEBs reserved for
bad PEB handling: 159
Ventana > ubifsmount ubi0:boot
Ventana > ubifsls
            38158  Mon Sep 27 17:18:10 2021  gateworks-imx6-imx6q-gw5400-a.dtb
            41659  Mon Sep 27 17:18:07 2021  gateworks-imx6-imx6dl-gw53xx.dtb
            42964  Mon Sep 27 17:18:10 2021  gateworks-imx6-imx6q-gw53xx.dtb
...

[    2.065328] ubi0: attaching mtd2
[    2.092015] ubi0 warning: ubi_io_read: error -74 (ECC error) while
reading 253952 bytes from PEB 11:8192, read only 253952 bytes, retry
[    2.096132] mmc0: host does not support reading read-only switch,
assuming write-enable
[    2.119427] mmc0: new high speed SDHC card at address 0007
[    2.126035] mmcblk0: mmc0:0007 SD32G 29.9 GiB
[    2.130221] ubi0 warning: ubi_io_read: error -74 (ECC error) while
reading 253952 bytes from PEB 11:8192, read only 253952 bytes, retry
[    2.131746]  mmcblk0: p1
[    2.164579] ubi0 warning: ubi_io_read: error -74 (ECC error) while
reading 253952 bytes from PEB 11:8192, read only 253952 bytes, retry
[    2.197969] ubi0 error: ubi_io_read: error -74 (ECC error) while
reading 253952 bytes from PEB 11:8192, read 253952 bytes

Best regards,

Tim

> > Am 04.05.20 um 16:08 schrieb Peng Fan:
> > > From: Ye Li <ye.li@nxp.com>
> > >
> > > The code change updated the NAND driver BCH ECC layout algorithm to
> > > support large oob size NAND chips(oob > 1024 bytes) and proposed a new
> > > way to set ECC layout.
> > >
> > > Current implementation requires each chunk size larger than oob size so
> > > the bad block marker (BBM) can be guaranteed located in data chunk. The
> > > ECC layout always using the unbalanced layout(Ecc for both meta and
> > > Data0 chunk), but for the NAND chips with oob larger than 1k, the driver
> > > cannot support because BCH doesn’t support GF 15 for 2K chunk.
> > >
> > > The change keeps the data chunk no larger than 1k and adjust the ECC
> > > strength or ECC layout to locate the BBM in data chunk. General idea for
> > > large oob NAND chips is
> > >
> > > 1.Try all ECC strength from the minimum value required by NAND spec to
> > > the maximum one that works, any ECC makes the BBM locate in data chunk
> > > can be chosen.
> > >
> > > 2.If none of them works, using separate ECC for meta, which will add one
> > > extra ecc with the same ECC strength as other data chunks. This extra
> > > ECC can guarantee BBM located in data chunk, of course, we need to check
> > > if oob can afford it.
> > >
> > > Previous code has two methods for ECC layout setting, the
> > > legacy_calc_ecc_layout and calc_ecc_layout_by_info, the difference
> > > between these two methods is, legacy_calc_ecc_layout set the chunk size
> > > larger chan oob size and then set the maximum ECC strength that oob can
> > > afford. While the calc_ecc_layout_by_info set chunk size and ECC
> > > strength according to NAND spec. It has been proved that the first
> > > method cannot provide safe ECC strength for some modern NAND chips, so
> > > in current code,
> > >
> > > 1. Driver read NAND parameters first and then chose the proper ECC
> > > layout setting method.
> > >
> > > 2. If the oob is large or NAND required data chunk larger than oob size,
> > > chose calc_ecc_for_large_oob, otherwise use calc_ecc_layout_by_info
> > >
> > > 3. legacy_calc_ecc_layout only used for some NAND chips does not contains
> > > necessary information. So this is only a backup plan, it is NOT
> > > recommended to use these NAND chips.
> > >
> > > Signed-off-by: Han Xu <b45815@freescale.com>
> > > Signed-off-by: Ye Li <ye.li@nxp.com>
> > > Signed-off-by: Peng Fan <peng.fan@nxp.com>
> > > ---
> > >  drivers/mtd/nand/raw/mxs_nand.c | 205 ++++++++++++++++++++++++++--------------
> > >  include/mxs_nand.h              |  12 ++-
> > >  2 files changed, 144 insertions(+), 73 deletions(-)
> > >
> > > diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
> > > index fe8097c146..8da59e39c0 100644
> > > --- a/drivers/mtd/nand/raw/mxs_nand.c
> > > +++ b/drivers/mtd/nand/raw/mxs_nand.c
> > > @@ -112,53 +112,32 @@ static uint32_t mxs_nand_aux_status_offset(void)
> > >       return (MXS_NAND_METADATA_SIZE + 0x3) & ~0x3;
> > >  }
> > >
> > > -static inline int mxs_nand_calc_mark_offset(struct bch_geometry *geo,
> > > -                                         uint32_t page_data_size)
> > > +static inline bool mxs_nand_bbm_in_data_chunk(struct bch_geometry *geo, struct mtd_info *mtd,
> > > +             unsigned int *chunk_num)
> > >  {
> > > -     uint32_t chunk_data_size_in_bits = geo->ecc_chunk_size * 8;
> > > -     uint32_t chunk_ecc_size_in_bits = geo->ecc_strength * geo->gf_len;
> > > -     uint32_t chunk_total_size_in_bits;
> > > -     uint32_t block_mark_chunk_number;
> > > -     uint32_t block_mark_chunk_bit_offset;
> > > -     uint32_t block_mark_bit_offset;
> > > +     unsigned int i, j;
> > >
> > > -     chunk_total_size_in_bits =
> > > -                     chunk_data_size_in_bits + chunk_ecc_size_in_bits;
> > > -
> > > -     /* Compute the bit offset of the block mark within the physical page. */
> > > -     block_mark_bit_offset = page_data_size * 8;
> > > -
> > > -     /* Subtract the metadata bits. */
> > > -     block_mark_bit_offset -= MXS_NAND_METADATA_SIZE * 8;
> > > -
> > > -     /*
> > > -      * Compute the chunk number (starting at zero) in which the block mark
> > > -      * appears.
> > > -      */
> > > -     block_mark_chunk_number =
> > > -                     block_mark_bit_offset / chunk_total_size_in_bits;
> > > -
> > > -     /*
> > > -      * Compute the bit offset of the block mark within its chunk, and
> > > -      * validate it.
> > > -      */
> > > -     block_mark_chunk_bit_offset = block_mark_bit_offset -
> > > -                     (block_mark_chunk_number * chunk_total_size_in_bits);
> > > +     if (geo->ecc_chunk0_size != geo->ecc_chunkn_size) {
> > > +             dev_err(this->dev, "The size of chunk0 must equal to chunkn\n");
> > > +             return false;
> > > +     }
> > >
> > > -     if (block_mark_chunk_bit_offset > chunk_data_size_in_bits)
> > > -             return -EINVAL;
> > > +     i = (mtd->writesize * 8 - MXS_NAND_METADATA_SIZE * 8) /
> > > +             (geo->gf_len * geo->ecc_strength +
> > > +                             geo->ecc_chunkn_size * 8);
> > >
> > > -     /*
> > > -      * Now that we know the chunk number in which the block mark appears,
> > > -      * we can subtract all the ECC bits that appear before it.
> > > -      */
> > > -     block_mark_bit_offset -=
> > > -             block_mark_chunk_number * chunk_ecc_size_in_bits;
> > > +     j = (mtd->writesize * 8 - MXS_NAND_METADATA_SIZE * 8) -
> > > +             (geo->gf_len * geo->ecc_strength +
> > > +                             geo->ecc_chunkn_size * 8) * i;
> > >
> > > -     geo->block_mark_byte_offset = block_mark_bit_offset >> 3;
> > > -     geo->block_mark_bit_offset = block_mark_bit_offset & 0x7;
> > > +     if (j < geo->ecc_chunkn_size * 8) {
> > > +             *chunk_num = i + 1;
> > > +             dev_dbg(this->dev, "Set ecc to %d and bbm in chunk %d\n",
> > > +                     geo->ecc_strength, *chunk_num);
> > > +             return true;
> > > +     }
> > >
> > > -     return 0;
> > > +     return false;
> > >  }
> > >
> > >  static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
> > > @@ -168,6 +147,7 @@ static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
> > >  {
> > >       struct nand_chip *chip = mtd_to_nand(mtd);
> > >       struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> > > +     unsigned int block_mark_bit_offset;
> > >
> > >       switch (ecc_step) {
> > >       case SZ_512:
> > > @@ -180,45 +160,51 @@ static inline int mxs_nand_calc_ecc_layout_by_info(struct bch_geometry *geo,
> > >               return -EINVAL;
> > >       }
> > >
> > > -     geo->ecc_chunk_size = ecc_step;
> > > +     geo->ecc_chunk0_size = ecc_step;
> > > +     geo->ecc_chunkn_size = ecc_step;
> > >       geo->ecc_strength = round_up(ecc_strength, 2);
> > >
> > >       /* Keep the C >= O */
> > > -     if (geo->ecc_chunk_size < mtd->oobsize)
> > > +     if (geo->ecc_chunkn_size < mtd->oobsize)
> > >               return -EINVAL;
> > >
> > >       if (geo->ecc_strength > nand_info->max_ecc_strength_supported)
> > >               return -EINVAL;
> > >
> > > -     geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
> > > +     geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
> > > +
> > > +     /* For bit swap. */
> > > +     block_mark_bit_offset = mtd->writesize * 8 -
> > > +             (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
> > > +                             + MXS_NAND_METADATA_SIZE * 8);
> > > +
> > > +     geo->block_mark_byte_offset = block_mark_bit_offset / 8;
> > > +     geo->block_mark_bit_offset  = block_mark_bit_offset % 8;
> > >
> > >       return 0;
> > >  }
> > >
> > > -static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo,
> > > +static inline int mxs_nand_legacy_calc_ecc_layout(struct bch_geometry *geo,
> > >                                          struct mtd_info *mtd)
> > >  {
> > >       struct nand_chip *chip = mtd_to_nand(mtd);
> > >       struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> > > +     unsigned int block_mark_bit_offset;
> > >
> > >       /* The default for the length of Galois Field. */
> > >       geo->gf_len = 13;
> > >
> > >       /* The default for chunk size. */
> > > -     geo->ecc_chunk_size = 512;
> > > +     geo->ecc_chunk0_size = 512;
> > > +     geo->ecc_chunkn_size = 512;
> > >
> > > -     if (geo->ecc_chunk_size < mtd->oobsize) {
> > > +     if (geo->ecc_chunkn_size < mtd->oobsize) {
> > >               geo->gf_len = 14;
> > > -             geo->ecc_chunk_size *= 2;
> > > +             geo->ecc_chunk0_size *= 2;
> > > +             geo->ecc_chunkn_size *= 2;
> > >       }
> > >
> > > -     if (mtd->oobsize > geo->ecc_chunk_size) {
> > > -             printf("Not support the NAND chips whose oob size is larger then %d bytes!\n",
> > > -                    geo->ecc_chunk_size);
> > > -             return -EINVAL;
> > > -     }
> > > -
> > > -     geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size;
> > > +     geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
> > >
> > >       /*
> > >        * Determine the ECC layout with the formula:
> > > @@ -234,6 +220,84 @@ static inline int mxs_nand_calc_ecc_layout(struct bch_geometry *geo,
> > >       geo->ecc_strength = min(round_down(geo->ecc_strength, 2),
> > >                               nand_info->max_ecc_strength_supported);
> > >
> > > +     block_mark_bit_offset = mtd->writesize * 8 -
> > > +             (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - 1)
> > > +                             + MXS_NAND_METADATA_SIZE * 8);
> > > +
> > > +     geo->block_mark_byte_offset = block_mark_bit_offset / 8;
> > > +     geo->block_mark_bit_offset  = block_mark_bit_offset % 8;
> > > +
> > > +     return 0;
> > > +}
> > > +
> > > +static inline int mxs_nand_calc_ecc_for_large_oob(struct bch_geometry *geo,
> > > +                                        struct mtd_info *mtd)
> > > +{
> > > +     struct nand_chip *chip = mtd_to_nand(mtd);
> > > +     struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> > > +     unsigned int block_mark_bit_offset;
> > > +     unsigned int max_ecc;
> > > +     unsigned int bbm_chunk;
> > > +     unsigned int i;
> > > +
> > > +     /* sanity check for the minimum ecc nand required */
> > > +     if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
> > > +             return -EINVAL;
> > > +     geo->ecc_strength = chip->ecc_strength_ds;
> > > +
> > > +     /* calculate the maximum ecc platform can support*/
> > > +     geo->gf_len = 14;
> > > +     geo->ecc_chunk0_size = 1024;
> > > +     geo->ecc_chunkn_size = 1024;
> > > +     geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunkn_size;
> > > +     max_ecc = ((mtd->oobsize - MXS_NAND_METADATA_SIZE) * 8)
> > > +                     / (geo->gf_len * geo->ecc_chunk_count);
> > > +     max_ecc = min(round_down(max_ecc, 2),
> > > +                             nand_info->max_ecc_strength_supported);
> > > +
> > > +
> > > +     /* search a supported ecc strength that makes bbm */
> > > +     /* located in data chunk  */
> > > +     geo->ecc_strength = chip->ecc_strength_ds;
> > > +     while (!(geo->ecc_strength > max_ecc)) {
> > > +             if (mxs_nand_bbm_in_data_chunk(geo, mtd, &bbm_chunk))
> > > +                     break;
> > > +             geo->ecc_strength += 2;
> > > +     }
> > > +
> > > +     /* if none of them works, keep using the minimum ecc */
> > > +     /* nand required but changing ecc page layout  */
> > > +     if (geo->ecc_strength > max_ecc) {
> > > +             geo->ecc_strength = chip->ecc_strength_ds;
> > > +             /* add extra ecc for meta data */
> > > +             geo->ecc_chunk0_size = 0;
> > > +             geo->ecc_chunk_count = (mtd->writesize / geo->ecc_chunkn_size) + 1;
> > > +             geo->ecc_for_meta = 1;
> > > +             /* check if oob can afford this extra ecc chunk */
> > > +             if (mtd->oobsize * 8 < MXS_NAND_METADATA_SIZE * 8 +
> > > +                             geo->gf_len * geo->ecc_strength
> > > +                             * geo->ecc_chunk_count) {
> > > +                     printf("unsupported NAND chip with new layout\n");
> > > +                     return -EINVAL;
> > > +             }
> > > +
> > > +             /* calculate in which chunk bbm located */
> > > +             bbm_chunk = (mtd->writesize * 8 - MXS_NAND_METADATA_SIZE * 8 -
> > > +                     geo->gf_len * geo->ecc_strength) /
> > > +                     (geo->gf_len * geo->ecc_strength +
> > > +                                     geo->ecc_chunkn_size * 8) + 1;
> > > +     }
> > > +
> > > +     /* calculate the number of ecc chunk behind the bbm */
> > > +     i = (mtd->writesize / geo->ecc_chunkn_size) - bbm_chunk + 1;
> > > +
> > > +     block_mark_bit_offset = mtd->writesize * 8 -
> > > +             (geo->ecc_strength * geo->gf_len * (geo->ecc_chunk_count - i)
> > > +                             + MXS_NAND_METADATA_SIZE * 8);
> > > +
> > > +     geo->block_mark_byte_offset = block_mark_bit_offset / 8;
> > > +     geo->block_mark_bit_offset  = block_mark_bit_offset % 8;
> > > +
> > >       return 0;
> > >  }
> > >
> > > @@ -983,18 +1047,23 @@ static int mxs_nand_set_geometry(struct mtd_info *mtd, struct bch_geometry *geo)
> > >       struct nand_chip *nand = mtd_to_nand(mtd);
> > >       struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
> > >
> > > -     if (chip->ecc.strength > 0 && chip->ecc.size > 0)
> > > -             return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
> > > -                             chip->ecc.strength, chip->ecc.size);
> > > +     if (chip->ecc_strength_ds > nand_info->max_ecc_strength_supported) {
> > > +             printf("unsupported NAND chip, minimum ecc required %d\n"
> > > +                     , chip->ecc_strength_ds);
> > > +             return -EINVAL;
> > > +     }
> > > +
> > > +     if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0) &&
> > > +                     (mtd->oobsize < 1024)) {
> > > +             dev_warn(this->dev, "use legacy bch geometry\n");
> > > +             return mxs_nand_legacy_calc_ecc_layout(geo, mtd);
> > > +     }
> > >
> > > -     if (nand_info->use_minimum_ecc ||
> > > -             mxs_nand_calc_ecc_layout(geo, mtd)) {
> > > -             if (!(chip->ecc_strength_ds > 0 && chip->ecc_step_ds > 0))
> > > -                     return -EINVAL;
> > > +     if (mtd->oobsize > 1024 || chip->ecc_step_ds < mtd->oobsize)
> > > +             return mxs_nand_calc_ecc_for_large_oob(geo, mtd);
> > >
> > > -             return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
> > > +     return mxs_nand_calc_ecc_layout_by_info(geo, mtd,
> > >                               chip->ecc_strength_ds, chip->ecc_step_ds);
> > > -     }
> > >
> > >       return 0;
> > >  }
> > > @@ -1025,8 +1094,6 @@ int mxs_nand_setup_ecc(struct mtd_info *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);
> > >
> > > @@ -1034,7 +1101,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
> > >       tmp = (geo->ecc_chunk_count - 1) << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
> > >       tmp |= MXS_NAND_METADATA_SIZE << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
> > >       tmp |= (geo->ecc_strength >> 1) << BCH_FLASHLAYOUT0_ECC0_OFFSET;
> > > -     tmp |= geo->ecc_chunk_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
> > > +     tmp |= geo->ecc_chunk0_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
> > >       tmp |= (geo->gf_len == 14 ? 1 : 0) <<
> > >               BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
> > >       writel(tmp, &bch_regs->hw_bch_flash0layout0);
> > > @@ -1043,7 +1110,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
> > >       tmp = (mtd->writesize + mtd->oobsize)
> > >               << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
> > >       tmp |= (geo->ecc_strength >> 1) << BCH_FLASHLAYOUT1_ECCN_OFFSET;
> > > -     tmp |= geo->ecc_chunk_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
> > > +     tmp |= geo->ecc_chunkn_size >> MXS_NAND_CHUNK_DATA_CHUNK_SIZE_SHIFT;
> > >       tmp |= (geo->gf_len == 14 ? 1 : 0) <<
> > >               BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
> > >       writel(tmp, &bch_regs->hw_bch_flash0layout1);
> > > @@ -1268,7 +1335,7 @@ int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info)
> > >
> > >       nand->ecc.layout        = &fake_ecc_layout;
> > >       nand->ecc.mode          = NAND_ECC_HW;
> > > -     nand->ecc.size          = nand_info->bch_geometry.ecc_chunk_size;
> > > +     nand->ecc.size          = nand_info->bch_geometry.ecc_chunkn_size;
> > >       nand->ecc.strength      = nand_info->bch_geometry.ecc_strength;
> > >
> > >       /* second phase scan */
> > > diff --git a/include/mxs_nand.h b/include/mxs_nand.h
> > > index ada20483d0..497da77a16 100644
> > > --- a/include/mxs_nand.h
> > > +++ b/include/mxs_nand.h
> > > @@ -16,22 +16,26 @@
> > >   * @gf_len:                   The length of Galois Field. (e.g., 13 or 14)
> > >   * @ecc_strength:             A number that describes the strength of the ECC
> > >   *                            algorithm.
> > > - * @ecc_chunk_size:           The size, in bytes, of a single ECC chunk. Note
> > > - *                            the first chunk in the page includes both data and
> > > - *                            metadata, so it's a bit larger than this value.
> > > + * @ecc_chunk0_size:          The size, in bytes, of a first ECC chunk.
> > > + * @ecc_chunkn_size:          The size, in bytes, of a single ECC chunk after
> > > + *                            the first chunk in the page.
> > >   * @ecc_chunk_count:          The number of ECC chunks in the page,
> > >   * @block_mark_byte_offset:   The byte offset in the ECC-based page view at
> > >   *                            which the underlying physical block mark appears.
> > >   * @block_mark_bit_offset:    The bit offset into the ECC-based page view at
> > >   *                            which the underlying physical block mark appears.
> > > + * @ecc_for_meta:             The flag to indicate if there is a dedicate ecc
> > > + *                            for meta.
> > >   */
> > >  struct bch_geometry {
> > >       unsigned int  gf_len;
> > >       unsigned int  ecc_strength;
> > > -     unsigned int  ecc_chunk_size;
> > > +     unsigned int  ecc_chunk0_size;
> > > +     unsigned int  ecc_chunkn_size;
> > >       unsigned int  ecc_chunk_count;
> > >       unsigned int  block_mark_byte_offset;
> > >       unsigned int  block_mark_bit_offset;
> > > +     unsigned int  ecc_for_meta; /* ECC for meta data */
> > >  };
> > >
> > >  struct mxs_nand_info {
> > >

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: GPMI NAND Regression on i.MX6S
  2022-03-16 16:34       ` Tim Harvey
@ 2022-03-17  8:06         ` Frieder Schrempf
  2022-03-17 12:59           ` Frieder Schrempf
  2022-03-18  8:47           ` [EXT] " Ye Li
  0 siblings, 2 replies; 37+ messages in thread
From: Frieder Schrempf @ 2022-03-17  8:06 UTC (permalink / raw)
  To: Tim Harvey, Fabio Estevam
  Cc: Han Xu, Peng Fan, Stefano Babic, Ye Li, dl-uboot-imx, U-Boot-Denx

Hi Tim,

Am 16.03.22 um 17:34 schrieb Tim Harvey:
> On Wed, Mar 16, 2022 at 7:09 AM Fabio Estevam <festevam@gmail.com> wrote:
>>
>> Adding Han Xu's NXP email on Cc.
>>
>> On Mon, Mar 14, 2022 at 10:31 AM Frieder Schrempf
>> <frieder.schrempf@kontron.de> wrote:
>>>
>>> Hello everyone,
>>>
>>> sorry to dig out an old thread, but the below patch which was applied
>>> upstream as 616f03dabacb causes a regression for me when trying to
>>> attach an UBI volume with U-Boot 2022.01 on a board with i.MX6 Solo and
>>> AMD/Spansion parallel NAND.
>>>
>>> The failure looks like this:
>>>
>>> ubi0: attaching mtd2
>>> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes
>>> from PEB 0:0, read 64 bytes
>>> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 2048 bytes
>>> from PEB 0:2048, read 2048 bytes
>>> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes
>>> from PEB 1:0, read 64 bytes
>>> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 2048 bytes
>>> from PEB 1:2048, read 2048 bytes
>>>
>>> The NAND as reported by Linux is:
>>>
>>> nand: device found, Manufacturer ID: 0x01, Chip ID: 0xdc
>>> nand: AMD/Spansion S34ML04G1
>>> nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
>>>
>>> A different revision of the same board with a different NAND from
>>> manufacturer ESMT doesn't show the issue:
>>>
>>> nand: device found, Manufacturer ID: 0xc8, Chip ID: 0xdc
>>> nand: ESMT NAND 512MiB 3,3V 8-bit
>>> nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
>>>
>>> When I revert the mentioned commit (see patch here: [1]), the UBI boot
>>> starts working again.
>>>
>>> Does anyone know what the problem is and how to properly solve it?
>>>
>>> Thanks for any help!
>>> Frieder
>>>
>>> [1]
>>> https://eur04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fzerobin.net%2F%3F57a57a322bbdcf3c%23rZa3vHlWi%2BRxtRomoljtrngqWwiv6v4Js%2F2LNfdV10o%3D&amp;data=04%7C01%7Cfrieder.schrempf%40kontron.de%7C978979eaf1fa48171bab08da076aea84%7C8c9d3c973fd941c8a2b1646f3942daf1%7C0%7C0%7C637830453031595997%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=NGl%2FrFnffV2oC90js0aHyTvoZjnrzW%2FD830lOnR4TbQ%3D&amp;reserved=0
>>>
> 
> Frieder,
> 
> I see the same issue here with IMX6Q/DL GPMI NAND.
> 
> If I re-flash the ubi within U-Boot (tftpboot $loadaddr rootfs.ubi &&
> nand erase.part rootfs && nand write $loadaddr rootfs $filesize) I
> find that U-Boot can attach and mount the ubi fine but Linux will have
> issues

Interesting! This sounds like U-Boot and Linux somehow diverge in how
they handle the ECC data in OOB. I'm pretty confident that Linux does
things "correctly" and U-Boot should match what Linux does in this case.

Does the patch (revert of 616f03dabacb) I mentioned before "solve" the
issue for your case, too?

@Han, Ye, Peng: As you signed-off the mentioned commit, do you have any
ideas for a fix?

Thanks
Frieder

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: GPMI NAND Regression on i.MX6S
  2022-03-17  8:06         ` Frieder Schrempf
@ 2022-03-17 12:59           ` Frieder Schrempf
  2022-03-17 13:14             ` Sean Nyekjaer
  2022-03-18  8:47           ` [EXT] " Ye Li
  1 sibling, 1 reply; 37+ messages in thread
From: Frieder Schrempf @ 2022-03-17 12:59 UTC (permalink / raw)
  To: Tim Harvey, Fabio Estevam
  Cc: Han Xu, Peng Fan, Stefano Babic, Ye Li, dl-uboot-imx,
	U-Boot-Denx, Sean Nyekjaer

Am 17.03.22 um 09:06 schrieb Frieder Schrempf:
> Hi Tim,
> 
> Am 16.03.22 um 17:34 schrieb Tim Harvey:
>> On Wed, Mar 16, 2022 at 7:09 AM Fabio Estevam <festevam@gmail.com> wrote:
>>>
>>> Adding Han Xu's NXP email on Cc.
>>>
>>> On Mon, Mar 14, 2022 at 10:31 AM Frieder Schrempf
>>> <frieder.schrempf@kontron.de> wrote:
>>>>
>>>> Hello everyone,
>>>>
>>>> sorry to dig out an old thread, but the below patch which was applied
>>>> upstream as 616f03dabacb causes a regression for me when trying to
>>>> attach an UBI volume with U-Boot 2022.01 on a board with i.MX6 Solo and
>>>> AMD/Spansion parallel NAND.
>>>>
>>>> The failure looks like this:
>>>>
>>>> ubi0: attaching mtd2
>>>> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes
>>>> from PEB 0:0, read 64 bytes
>>>> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 2048 bytes
>>>> from PEB 0:2048, read 2048 bytes
>>>> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes
>>>> from PEB 1:0, read 64 bytes
>>>> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 2048 bytes
>>>> from PEB 1:2048, read 2048 bytes
>>>>
>>>> The NAND as reported by Linux is:
>>>>
>>>> nand: device found, Manufacturer ID: 0x01, Chip ID: 0xdc
>>>> nand: AMD/Spansion S34ML04G1
>>>> nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
>>>>
>>>> A different revision of the same board with a different NAND from
>>>> manufacturer ESMT doesn't show the issue:
>>>>
>>>> nand: device found, Manufacturer ID: 0xc8, Chip ID: 0xdc
>>>> nand: ESMT NAND 512MiB 3,3V 8-bit
>>>> nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
>>>>
>>>> When I revert the mentioned commit (see patch here: [1]), the UBI boot
>>>> starts working again.
>>>>
>>>> Does anyone know what the problem is and how to properly solve it?
>>>>
>>>> Thanks for any help!
>>>> Frieder
>>>>
>>>> [1]
>>>> https://eur04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fzerobin.net%2F%3F57a57a322bbdcf3c%23rZa3vHlWi%2BRxtRomoljtrngqWwiv6v4Js%2F2LNfdV10o%3D&amp;data=04%7C01%7Cfrieder.schrempf%40kontron.de%7C978979eaf1fa48171bab08da076aea84%7C8c9d3c973fd941c8a2b1646f3942daf1%7C0%7C0%7C637830453031595997%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=NGl%2FrFnffV2oC90js0aHyTvoZjnrzW%2FD830lOnR4TbQ%3D&amp;reserved=0
>>>>
>>
>> Frieder,
>>
>> I see the same issue here with IMX6Q/DL GPMI NAND.
>>
>> If I re-flash the ubi within U-Boot (tftpboot $loadaddr rootfs.ubi &&
>> nand erase.part rootfs && nand write $loadaddr rootfs $filesize) I
>> find that U-Boot can attach and mount the ubi fine but Linux will have
>> issues
> 
> Interesting! This sounds like U-Boot and Linux somehow diverge in how
> they handle the ECC data in OOB. I'm pretty confident that Linux does
> things "correctly" and U-Boot should match what Linux does in this case.
> 
> Does the patch (revert of 616f03dabacb) I mentioned before "solve" the
> issue for your case, too?
> 
> @Han, Ye, Peng: As you signed-off the mentioned commit, do you have any
> ideas for a fix?

So the proper fix seems to be to revert to the "legacy" BCH layout that
is used by Linux. Sean already tried to get this fixed almost a year ago
[1] but Han turned the change down in favor of changing the layout on
the kernel side. But this series [2] never made it upstream and it
doesn't look like it will anytime soon.

I will try to resurrect Sean's fix.

[1]
https://patchwork.ozlabs.org/project/uboot/patch/20210510100043.449294-1-sean@geanix.com/
[2]
https://patchwork.ozlabs.org/project/linux-mtd/patch/20210522205136.19465-1-han.xu@nxp.com/


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: GPMI NAND Regression on i.MX6S
  2022-03-17 12:59           ` Frieder Schrempf
@ 2022-03-17 13:14             ` Sean Nyekjaer
  2022-03-17 13:19               ` Frieder Schrempf
  0 siblings, 1 reply; 37+ messages in thread
From: Sean Nyekjaer @ 2022-03-17 13:14 UTC (permalink / raw)
  To: Frieder Schrempf
  Cc: Tim Harvey, Fabio Estevam, Han Xu, Peng Fan, Stefano Babic,
	Ye Li, dl-uboot-imx, U-Boot-Denx

Hi Frieder,

On Thu, Mar 17, 2022 at 01:59:07PM +0100, Frieder Schrempf wrote:
> Am 17.03.22 um 09:06 schrieb Frieder Schrempf:
> > Hi Tim,
> > 
> > Am 16.03.22 um 17:34 schrieb Tim Harvey:
> >> On Wed, Mar 16, 2022 at 7:09 AM Fabio Estevam <festevam@gmail.com> wrote:
> >>>
> >>> Adding Han Xu's NXP email on Cc.
> >>>
> >>> On Mon, Mar 14, 2022 at 10:31 AM Frieder Schrempf
> >>> <frieder.schrempf@kontron.de> wrote:
> >>>>
> >>>> Hello everyone,
> >>>>
> >>>> sorry to dig out an old thread, but the below patch which was applied
> >>>> upstream as 616f03dabacb causes a regression for me when trying to
> >>>> attach an UBI volume with U-Boot 2022.01 on a board with i.MX6 Solo and
> >>>> AMD/Spansion parallel NAND.
> >>>>
> >>>> The failure looks like this:
> >>>>
> >>>> ubi0: attaching mtd2
> >>>> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes
> >>>> from PEB 0:0, read 64 bytes
> >>>> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 2048 bytes
> >>>> from PEB 0:2048, read 2048 bytes
> >>>> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes
> >>>> from PEB 1:0, read 64 bytes
> >>>> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 2048 bytes
> >>>> from PEB 1:2048, read 2048 bytes
> >>>>
> >>>> The NAND as reported by Linux is:
> >>>>
> >>>> nand: device found, Manufacturer ID: 0x01, Chip ID: 0xdc
> >>>> nand: AMD/Spansion S34ML04G1
> >>>> nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
> >>>>
> >>>> A different revision of the same board with a different NAND from
> >>>> manufacturer ESMT doesn't show the issue:
> >>>>
> >>>> nand: device found, Manufacturer ID: 0xc8, Chip ID: 0xdc
> >>>> nand: ESMT NAND 512MiB 3,3V 8-bit
> >>>> nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
> >>>>
> >>>> When I revert the mentioned commit (see patch here: [1]), the UBI boot
> >>>> starts working again.
> >>>>
> >>>> Does anyone know what the problem is and how to properly solve it?
> >>>>
> >>>> Thanks for any help!
> >>>> Frieder
> >>>>
> >>>> [1]
> >>>> https://eur04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fzerobin.net%2F%3F57a57a322bbdcf3c%23rZa3vHlWi%2BRxtRomoljtrngqWwiv6v4Js%2F2LNfdV10o%3D&amp;data=04%7C01%7Cfrieder.schrempf%40kontron.de%7C978979eaf1fa48171bab08da076aea84%7C8c9d3c973fd941c8a2b1646f3942daf1%7C0%7C0%7C637830453031595997%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=NGl%2FrFnffV2oC90js0aHyTvoZjnrzW%2FD830lOnR4TbQ%3D&amp;reserved=0
> >>>>
> >>
> >> Frieder,
> >>
> >> I see the same issue here with IMX6Q/DL GPMI NAND.
> >>
> >> If I re-flash the ubi within U-Boot (tftpboot $loadaddr rootfs.ubi &&
> >> nand erase.part rootfs && nand write $loadaddr rootfs $filesize) I
> >> find that U-Boot can attach and mount the ubi fine but Linux will have
> >> issues
> > 
> > Interesting! This sounds like U-Boot and Linux somehow diverge in how
> > they handle the ECC data in OOB. I'm pretty confident that Linux does
> > things "correctly" and U-Boot should match what Linux does in this case.
> > 
> > Does the patch (revert of 616f03dabacb) I mentioned before "solve" the
> > issue for your case, too?
> > 
> > @Han, Ye, Peng: As you signed-off the mentioned commit, do you have any
> > ideas for a fix?
> 
> So the proper fix seems to be to revert to the "legacy" BCH layout that
> is used by Linux. Sean already tried to get this fixed almost a year ago
> [1] but Han turned the change down in favor of changing the layout on
> the kernel side. But this series [2] never made it upstream and it
> doesn't look like it will anytime soon.
> 
> I will try to resurrect Sean's fix.
> 
> [1]
> https://patchwork.ozlabs.org/project/uboot/patch/20210510100043.449294-1-sean@geanix.com/
> [2]
> https://patchwork.ozlabs.org/project/linux-mtd/patch/20210522205136.19465-1-han.xu@nxp.com/
> 

Thanks for bringing this up again. I have only had time to send Han a
ping a few times.
I would still prefer that we added the new(correct) metod as a option.

/Sean

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: GPMI NAND Regression on i.MX6S
  2022-03-17 13:14             ` Sean Nyekjaer
@ 2022-03-17 13:19               ` Frieder Schrempf
  0 siblings, 0 replies; 37+ messages in thread
From: Frieder Schrempf @ 2022-03-17 13:19 UTC (permalink / raw)
  To: Sean Nyekjaer
  Cc: Tim Harvey, Fabio Estevam, Han Xu, Peng Fan, Stefano Babic,
	Ye Li, dl-uboot-imx, U-Boot-Denx

Hi Sean,

Am 17.03.22 um 14:14 schrieb Sean Nyekjaer:
> [Sie erhalten nicht oft E-Mail von "sean@geanix.com". Weitere Informationen, warum dies wichtig ist, finden Sie unter "http://aka.ms/LearnAboutSenderIdentification".]
> 
> Hi Frieder,
> 
> On Thu, Mar 17, 2022 at 01:59:07PM +0100, Frieder Schrempf wrote:
>> Am 17.03.22 um 09:06 schrieb Frieder Schrempf:
>>> Hi Tim,
>>>
>>> Am 16.03.22 um 17:34 schrieb Tim Harvey:
>>>> On Wed, Mar 16, 2022 at 7:09 AM Fabio Estevam <festevam@gmail.com> wrote:
>>>>>
>>>>> Adding Han Xu's NXP email on Cc.
>>>>>
>>>>> On Mon, Mar 14, 2022 at 10:31 AM Frieder Schrempf
>>>>> <frieder.schrempf@kontron.de> wrote:
>>>>>>
>>>>>> Hello everyone,
>>>>>>
>>>>>> sorry to dig out an old thread, but the below patch which was applied
>>>>>> upstream as 616f03dabacb causes a regression for me when trying to
>>>>>> attach an UBI volume with U-Boot 2022.01 on a board with i.MX6 Solo and
>>>>>> AMD/Spansion parallel NAND.
>>>>>>
>>>>>> The failure looks like this:
>>>>>>
>>>>>> ubi0: attaching mtd2
>>>>>> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes
>>>>>> from PEB 0:0, read 64 bytes
>>>>>> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 2048 bytes
>>>>>> from PEB 0:2048, read 2048 bytes
>>>>>> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64 bytes
>>>>>> from PEB 1:0, read 64 bytes
>>>>>> ubi0 error: ubi_io_read: error -74 (ECC error) while reading 2048 bytes
>>>>>> from PEB 1:2048, read 2048 bytes
>>>>>>
>>>>>> The NAND as reported by Linux is:
>>>>>>
>>>>>> nand: device found, Manufacturer ID: 0x01, Chip ID: 0xdc
>>>>>> nand: AMD/Spansion S34ML04G1
>>>>>> nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
>>>>>>
>>>>>> A different revision of the same board with a different NAND from
>>>>>> manufacturer ESMT doesn't show the issue:
>>>>>>
>>>>>> nand: device found, Manufacturer ID: 0xc8, Chip ID: 0xdc
>>>>>> nand: ESMT NAND 512MiB 3,3V 8-bit
>>>>>> nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB size: 64
>>>>>>
>>>>>> When I revert the mentioned commit (see patch here: [1]), the UBI boot
>>>>>> starts working again.
>>>>>>
>>>>>> Does anyone know what the problem is and how to properly solve it?
>>>>>>
>>>>>> Thanks for any help!
>>>>>> Frieder
>>>>>>
>>>>>> [1]
>>>>>> https://eur04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fzerobin.net%2F%3F57a57a322bbdcf3c%23rZa3vHlWi%2BRxtRomoljtrngqWwiv6v4Js%2F2LNfdV10o%3D&amp;data=04%7C01%7Cfrieder.schrempf%40kontron.de%7C7a58965995b34fe86ef808da08180b2a%7C8c9d3c973fd941c8a2b1646f3942daf1%7C0%7C0%7C637831196603019724%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=eexagX96EdnCNJiOvxTL%2FXVVWtQYsF5yt1zeMy2SghQ%3D&amp;reserved=0
>>>>>>
>>>>
>>>> Frieder,
>>>>
>>>> I see the same issue here with IMX6Q/DL GPMI NAND.
>>>>
>>>> If I re-flash the ubi within U-Boot (tftpboot $loadaddr rootfs.ubi &&
>>>> nand erase.part rootfs && nand write $loadaddr rootfs $filesize) I
>>>> find that U-Boot can attach and mount the ubi fine but Linux will have
>>>> issues
>>>
>>> Interesting! This sounds like U-Boot and Linux somehow diverge in how
>>> they handle the ECC data in OOB. I'm pretty confident that Linux does
>>> things "correctly" and U-Boot should match what Linux does in this case.
>>>
>>> Does the patch (revert of 616f03dabacb) I mentioned before "solve" the
>>> issue for your case, too?
>>>
>>> @Han, Ye, Peng: As you signed-off the mentioned commit, do you have any
>>> ideas for a fix?
>>
>> So the proper fix seems to be to revert to the "legacy" BCH layout that
>> is used by Linux. Sean already tried to get this fixed almost a year ago
>> [1] but Han turned the change down in favor of changing the layout on
>> the kernel side. But this series [2] never made it upstream and it
>> doesn't look like it will anytime soon.
>>
>> I will try to resurrect Sean's fix.
>>
>> [1]
>> https://eur04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.ozlabs.org%2Fproject%2Fuboot%2Fpatch%2F20210510100043.449294-1-sean%40geanix.com%2F&amp;data=04%7C01%7Cfrieder.schrempf%40kontron.de%7C7a58965995b34fe86ef808da08180b2a%7C8c9d3c973fd941c8a2b1646f3942daf1%7C0%7C0%7C637831196603019724%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=ZzCm2Jl9BPd8hP%2B13judqwblR4tzmyZnIHUR922KLdQ%3D&amp;reserved=0
>> [2]
>> https://eur04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fpatchwork.ozlabs.org%2Fproject%2Flinux-mtd%2Fpatch%2F20210522205136.19465-1-han.xu%40nxp.com%2F&amp;data=04%7C01%7Cfrieder.schrempf%40kontron.de%7C7a58965995b34fe86ef808da08180b2a%7C8c9d3c973fd941c8a2b1646f3942daf1%7C0%7C0%7C637831196603019724%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000&amp;sdata=iiBenZkPMWw%2Bg%2FLQjnBSgqZABScRQXt6%2F08typx7buY%3D&amp;reserved=0
>>
> 
> Thanks for bringing this up again. I have only had time to send Han a
> ping a few times.
> I would still prefer that we added the new(correct) metod as a option.

The top priority should be to fix the regression. And reading the
discussion with the Linux MTD maintainer Miquel in the thread for Han's
kernel patches linked above makes me doubt that the new method is really
a good option. Even if it would land in the kernel, it would break
systems that use older versions of U-Boot which is just not acceptable
in my opinion.

Frieder

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [EXT] Re: GPMI NAND Regression on i.MX6S
  2022-03-17  8:06         ` Frieder Schrempf
  2022-03-17 12:59           ` Frieder Schrempf
@ 2022-03-18  8:47           ` Ye Li
  1 sibling, 0 replies; 37+ messages in thread
From: Ye Li @ 2022-03-18  8:47 UTC (permalink / raw)
  To: festevam, frieder.schrempf, tharvey
  Cc: Peng Fan, Han Xu, u-boot, dl-uboot-imx, sbabic

Hi Frieder,

On Thu, 2022-03-17 at 09:06 +0100, Frieder Schrempf wrote:
> Caution: EXT Email
> 
> Hi Tim,
> 
> Am 16.03.22 um 17:34 schrieb Tim Harvey:
> > 
> > On Wed, Mar 16, 2022 at 7:09 AM Fabio Estevam <festevam@gmail.com>
> > wrote:
> > > 
> > > 
> > > Adding Han Xu's NXP email on Cc.
> > > 
> > > On Mon, Mar 14, 2022 at 10:31 AM Frieder Schrempf
> > > <frieder.schrempf@kontron.de> wrote:
> > > > 
> > > > 
> > > > Hello everyone,
> > > > 
> > > > sorry to dig out an old thread, but the below patch which was
> > > > applied
> > > > upstream as 616f03dabacb causes a regression for me when trying
> > > > to
> > > > attach an UBI volume with U-Boot 2022.01 on a board with i.MX6
> > > > Solo and
> > > > AMD/Spansion parallel NAND.
> > > > 
> > > > The failure looks like this:
> > > > 
> > > > ubi0: attaching mtd2
> > > > ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64
> > > > bytes
> > > > from PEB 0:0, read 64 bytes
> > > > ubi0 error: ubi_io_read: error -74 (ECC error) while reading
> > > > 2048 bytes
> > > > from PEB 0:2048, read 2048 bytes
> > > > ubi0 error: ubi_io_read: error -74 (ECC error) while reading 64
> > > > bytes
> > > > from PEB 1:0, read 64 bytes
> > > > ubi0 error: ubi_io_read: error -74 (ECC error) while reading
> > > > 2048 bytes
> > > > from PEB 1:2048, read 2048 bytes
> > > > 
> > > > The NAND as reported by Linux is:
> > > > 
> > > > nand: device found, Manufacturer ID: 0x01, Chip ID: 0xdc
> > > > nand: AMD/Spansion S34ML04G1
> > > > nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB
> > > > size: 64
> > > > 
> > > > A different revision of the same board with a different NAND
> > > > from
> > > > manufacturer ESMT doesn't show the issue:
> > > > 
> > > > nand: device found, Manufacturer ID: 0xc8, Chip ID: 0xdc
> > > > nand: ESMT NAND 512MiB 3,3V 8-bit
> > > > nand: 512 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB
> > > > size: 64
> > > > 
> > > > When I revert the mentioned commit (see patch here: [1]), the
> > > > UBI boot
> > > > starts working again.
> > > > 
> > > > Does anyone know what the problem is and how to properly solve
> > > > it?
> > > > 
> > > > Thanks for any help!
> > > > Frieder
> > > > 
> > > > [1]
> > > > https://eur01.safelinks.protection.outlook.com/?url=https%3A%2F
> > > > %2Fzerobin.net%2F%3F57a57a322bbdcf3c%23rZa3vHlWi%2BRxtRomoljtrn
> > > > gqWwiv6v4Js%2F2LNfdV10o%3D&amp;data=04%7C01%7Cye.li%40nxp.com%7
> > > > Cee3b85ceee3d4ece78e108da07ed1e2c%7C686ea1d3bc2b4c6fa92cd99c5c3
> > > > 01635%7C0%7C0%7C637831012279864791%7CUnknown%7CTWFpbGZsb3d8eyJW
> > > > IjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%
> > > > 7C3000&amp;sdata=O6MzwCv9ClB8ZW7i3%2BV1RmOaviGqQRNa8L0uxE4M%2F%
> > > > 2BI%3D&amp;reserved=0
> > > > 
> > Frieder,
> > 
> > I see the same issue here with IMX6Q/DL GPMI NAND.
> > 
> > If I re-flash the ubi within U-Boot (tftpboot $loadaddr rootfs.ubi
> > &&
> > nand erase.part rootfs && nand write $loadaddr rootfs $filesize) I
> > find that U-Boot can attach and mount the ubi fine but Linux will
> > have
> > issues
> Interesting! This sounds like U-Boot and Linux somehow diverge in how
> they handle the ECC data in OOB. I'm pretty confident that Linux does
> things "correctly" and U-Boot should match what Linux does in this
> case.
> 
> Does the patch (revert of 616f03dabacb) I mentioned before "solve"
> the
> issue for your case, too?
> 
> @Han, Ye, Peng: As you signed-off the mentioned commit, do you have
> any
> ideas for a fix?

The dt nand driver will check "fsl,legacy-bch-geometry" property to use
legacy bch. If this can't work for you in case you don't use DM driver,
I prefer adding a config to select the legacy bch not reverting the
patch. 

Best regards,
Ye Li
> 
> Thanks
> Frieder

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2022-03-18  8:47 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-04 14:08 [PATCH 00/14] mtd: nand: i.MX update Peng Fan
2020-05-04 14:08 ` [PATCH 01/14] mtd: gpmi: change the BCH layout setting for large oob NAND Peng Fan
2020-05-11 10:16   ` sbabic at denx.de
2022-03-14 13:30   ` GPMI NAND Regression on i.MX6S Frieder Schrempf
2022-03-16 14:08     ` Fabio Estevam
2022-03-16 16:34       ` Tim Harvey
2022-03-17  8:06         ` Frieder Schrempf
2022-03-17 12:59           ` Frieder Schrempf
2022-03-17 13:14             ` Sean Nyekjaer
2022-03-17 13:19               ` Frieder Schrempf
2022-03-18  8:47           ` [EXT] " Ye Li
2020-05-04 14:08 ` [PATCH 02/14] mtd: gpmi: provide the option to use legacy bch geometry Peng Fan
2020-05-11 10:17   ` sbabic at denx.de
2020-05-04 14:08 ` [PATCH 03/14] nand: mxs: fix the bitflips for erased page when uncorrectable error Peng Fan
2020-05-11 10:19   ` sbabic at denx.de
2020-05-04 14:08 ` [PATCH 04/14] nand: mxs: correct bitflip for erased NAND page Peng Fan
2020-05-11 10:17   ` sbabic at denx.de
2020-05-04 14:08 ` [PATCH 05/14] mxs_nand: Add support for i.MX8M Peng Fan
2020-05-11 10:17   ` sbabic at denx.de
2020-05-04 14:08 ` [PATCH 06/14] nand: Update SPL MXS NAND mini driver Peng Fan
2020-05-11 10:16   ` sbabic at denx.de
2020-05-04 14:08 ` [PATCH 07/14] mxs_nand: Update compatible string for i.MX6SX Peng Fan
2020-05-11 10:15   ` sbabic at denx.de
2020-05-04 14:08 ` [PATCH 08/14] mtd: nand: mxs_nand: add i.MX6QP compatible string Peng Fan
2020-05-11 10:15   ` sbabic at denx.de
2020-05-04 14:08 ` [PATCH 09/14] mtd: mxs_nand: fix the gf_13/14 definition issue Peng Fan
2020-05-11 10:18   ` sbabic at denx.de
2020-05-04 14:08 ` [PATCH 10/14] nand: mxs_nand: make imx8mm can use hardware BCH and randomizer Peng Fan
2020-05-11 10:15   ` sbabic at denx.de
2020-05-04 14:09 ` [PATCH 11/14] mtd: nand: support GPMI NAND driver for i.MX8 Peng Fan
2020-05-11 10:16   ` sbabic at denx.de
2020-05-04 14:09 ` [PATCH 12/14] MXS_NAND: Add clock support for iMX8 Peng Fan
2020-05-11 10:18   ` sbabic at denx.de
2020-05-04 14:09 ` [PATCH 13/14] mxs_nand: don't check zero count when ECC reading with randomizer Peng Fan
2020-05-11 10:18   ` sbabic at denx.de
2020-05-04 14:09 ` [PATCH 14/14] nand: enable the Randomizer module for i.mx7 and i.mx8 Peng Fan
2020-05-11 10:16   ` sbabic at denx.de

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.