All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 0/5] imx: nandbcb: support for i.MX7 and bcb only updates
@ 2019-10-21 13:38 Igor Opaniuk
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 1/5] imx: gpmi: add defines for hw randominizer Igor Opaniuk
                   ` (4 more replies)
  0 siblings, 5 replies; 18+ messages in thread
From: Igor Opaniuk @ 2019-10-21 13:38 UTC (permalink / raw)
  To: u-boot

This introduces support for writing BCB(FCB/FDDT) for i.MX7 NAND-based
platforms and additional subcommand for writing BCB
only (without firmware).

v2:
- Switch to runtime detection of SoC(e.g. is_mx7()) instead of ifdeffery
- Fix build for imx6

Igor Opaniuk (5):
  imx: gpmi: add defines for hw randominizer
  nand: mxs_nand: add API for switching different BCH layouts
  imx: nandbcb: add support for i.MX7
  imx: nandbcb: refactor update function
  imx: nandbcb: add support for writing BCB only

 arch/arm/include/asm/mach-imx/imx-nandbcb.h |  12 +
 arch/arm/include/asm/mach-imx/regs-gpmi.h   |   5 +
 arch/arm/mach-imx/Kconfig                   |   2 +-
 arch/arm/mach-imx/cmd_nandbcb.c             | 308 +++++++++++++++-----
 drivers/mtd/nand/raw/mxs_nand.c             | 116 ++++++++
 include/mxs_nand.h                          |  22 ++
 6 files changed, 389 insertions(+), 76 deletions(-)

-- 
2.17.1

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

* [U-Boot] [PATCH v2 1/5] imx: gpmi: add defines for hw randominizer
  2019-10-21 13:38 [U-Boot] [PATCH v2 0/5] imx: nandbcb: support for i.MX7 and bcb only updates Igor Opaniuk
@ 2019-10-21 13:38 ` Igor Opaniuk
  2019-10-23 11:21   ` Oleksandr Suvorov
  2019-10-23 17:51   ` Max Krummenacher
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 2/5] nand: mxs_nand: add API for switching different BCH layouts Igor Opaniuk
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 18+ messages in thread
From: Igor Opaniuk @ 2019-10-21 13:38 UTC (permalink / raw)
  To: u-boot

From: Igor Opaniuk <igor.opaniuk@toradex.com>

Extend GPMI Integrated ECC Control Register Description, include
additional defines for enabling randomizer function and providing
proper randomizer type.

For additional details check i.MX7 APR, section
9.6.6.3 GPMI Integrated ECC Control Register Description
(GPMI_ECCCTRLn)

Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>
---

 arch/arm/include/asm/mach-imx/regs-gpmi.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/include/asm/mach-imx/regs-gpmi.h b/arch/arm/include/asm/mach-imx/regs-gpmi.h
index 80cb731724..33daa53c45 100644
--- a/arch/arm/include/asm/mach-imx/regs-gpmi.h
+++ b/arch/arm/include/asm/mach-imx/regs-gpmi.h
@@ -70,6 +70,11 @@ struct mxs_gpmi_regs {
 #define	GPMI_ECCCTRL_ECC_CMD_OFFSET			13
 #define	GPMI_ECCCTRL_ECC_CMD_DECODE			(0x0 << 13)
 #define	GPMI_ECCCTRL_ECC_CMD_ENCODE			(0x1 << 13)
+#define	GPMI_ECCCTRL_RANDOMIZER_ENABLE			(1 << 11)
+#define	GPMI_ECCCTRL_RANDOMIZER_TYPE0			0
+#define	GPMI_ECCCTRL_RANDOMIZER_TYPE1			(1 << 9)
+#define	GPMI_ECCCTRL_RANDOMIZER_TYPE2			(2 << 9)
+
 #define	GPMI_ECCCTRL_ENABLE_ECC				(1 << 12)
 #define	GPMI_ECCCTRL_BUFFER_MASK_MASK			0x1ff
 #define	GPMI_ECCCTRL_BUFFER_MASK_OFFSET			0
-- 
2.17.1

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

* [U-Boot] [PATCH v2 2/5] nand: mxs_nand: add API for switching different BCH layouts
  2019-10-21 13:38 [U-Boot] [PATCH v2 0/5] imx: nandbcb: support for i.MX7 and bcb only updates Igor Opaniuk
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 1/5] imx: gpmi: add defines for hw randominizer Igor Opaniuk
@ 2019-10-21 13:38 ` Igor Opaniuk
  2019-10-23 11:23   ` Oleksandr Suvorov
  2019-10-23 17:53   ` Max Krummenacher
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 3/5] imx: nandbcb: add support for i.MX7 Igor Opaniuk
                   ` (2 subsequent siblings)
  4 siblings, 2 replies; 18+ messages in thread
From: Igor Opaniuk @ 2019-10-21 13:38 UTC (permalink / raw)
  To: u-boot

From: Igor Opaniuk <igor.opaniuk@toradex.com>

On i.MX7 in a sake of reducing the disturbances caused by a neighboring
cells in the FCB page in the NAND chip, a randomizer is enabled when
reading the FCB page by ROM bootloader.

Add API for setting BCH to specific layout (and restoring it back) used by
ROM bootloader to be able to burn it in a proper way to NAND using
nandbcb command.

Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>
Signed-off-by: Anti Sullin <anti.sullin@artecdesign.ee>
---

 drivers/mtd/nand/raw/mxs_nand.c | 116 ++++++++++++++++++++++++++++++++
 include/mxs_nand.h              |  22 ++++++
 2 files changed, 138 insertions(+)

diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index a41b9620d0..ad7b644886 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -740,6 +740,19 @@ 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) {
+		d->cmd.pio_words[2] |= GPMI_ECCCTRL_RANDOMIZER_ENABLE |
+				       GPMI_ECCCTRL_RANDOMIZER_TYPE2;
+		/*
+		 * Write NAND page number needed to be randomized
+		 * to GPMI_ECCCOUNT register.
+		 *
+		 * 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;
+	}
+
 	mxs_dma_desc_append(channel, d);
 
 	/* Flush caches */
@@ -1003,6 +1016,10 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
 	uint32_t tmp;
 	int ret;
 
+	nand_info->en_randomizer = 0;
+	nand_info->oobsize = mtd->oobsize;
+	nand_info->writesize = mtd->writesize;
+
 	ret = mxs_nand_set_geometry(mtd, geo);
 	if (ret)
 		return ret;
@@ -1020,6 +1037,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
 	tmp |= (geo->gf_len == 14 ? 1 : 0) <<
 		BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
 	writel(tmp, &bch_regs->hw_bch_flash0layout0);
+	nand_info->bch_flash0layout0 = tmp;
 
 	tmp = (mtd->writesize + mtd->oobsize)
 		<< BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
@@ -1028,6 +1046,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
 	tmp |= (geo->gf_len == 14 ? 1 : 0) <<
 		BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
 	writel(tmp, &bch_regs->hw_bch_flash0layout1);
+	nand_info->bch_flash0layout1 = tmp;
 
 	/* Set *all* chip selects to use layout 0 */
 	writel(0, &bch_regs->hw_bch_layoutselect);
@@ -1303,3 +1322,100 @@ err:
 	free(nand_info);
 }
 #endif
+
+/*
+ * Read NAND layout for FCB block generation.
+ */
+void mxs_nand_get_layout(struct mtd_info *mtd, struct mxs_nand_layout *l)
+{
+	struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
+	u32 tmp;
+
+	tmp = readl(&bch_regs->hw_bch_flash0layout0);
+	l->nblocks = (tmp & BCH_FLASHLAYOUT0_NBLOCKS_MASK) >>
+			BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
+	l->meta_size = (tmp & BCH_FLASHLAYOUT0_META_SIZE_MASK) >>
+			BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
+
+	tmp = readl(&bch_regs->hw_bch_flash0layout1);
+	l->data0_size = 4 * ((tmp & BCH_FLASHLAYOUT0_DATA0_SIZE_MASK) >>
+			BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET);
+	l->ecc0 = (tmp & BCH_FLASHLAYOUT0_ECC0_MASK) >>
+			BCH_FLASHLAYOUT0_ECC0_OFFSET;
+	l->datan_size = 4 * ((tmp & BCH_FLASHLAYOUT1_DATAN_SIZE_MASK) >>
+			BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET);
+	l->eccn = (tmp & BCH_FLASHLAYOUT1_ECCN_MASK) >>
+			BCH_FLASHLAYOUT1_ECCN_OFFSET;
+}
+
+/*
+ * Set BCH to specific layout used by ROM bootloader to read FCB.
+ */
+void mxs_nand_mode_fcb(struct mtd_info *mtd)
+{
+	u32 tmp;
+	struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
+
+	nand_info->en_randomizer = 1;
+
+	mtd->writesize = 1024;
+	mtd->oobsize = 1862 - 1024;
+
+	/* 8 ecc_chunks_*/
+	tmp = 7	<< BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
+	/* 32 bytes for metadata */
+	tmp |= 32 << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
+	/* using ECC62 level to be performed */
+	tmp |= 0x1F << BCH_FLASHLAYOUT0_ECC0_OFFSET;
+	/* 0x20 * 4 bytes of the data0 block */
+	tmp |= 0x20 << BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET;
+	tmp |= 0 << BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
+	writel(tmp, &bch_regs->hw_bch_flash0layout0);
+
+	/* 1024 for data + 838 for OOB */
+	tmp = 1862 << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
+	/* using ECC62 level to be performed */
+	tmp |= 0x1F << BCH_FLASHLAYOUT1_ECCN_OFFSET;
+	/* 0x20 * 4 bytes of the data0 block */
+	tmp |= 0x20 << BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET;
+	tmp |= 0 << BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
+	writel(tmp, &bch_regs->hw_bch_flash0layout1);
+}
+
+/*
+ * Restore BCH to normal settings.
+ */
+void mxs_nand_mode_normal(struct mtd_info *mtd)
+{
+	struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
+	struct nand_chip *nand = mtd_to_nand(mtd);
+	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
+
+	nand_info->en_randomizer = 0;
+
+	mtd->writesize = nand_info->writesize;
+	mtd->oobsize = nand_info->oobsize;
+
+	writel(nand_info->bch_flash0layout0, &bch_regs->hw_bch_flash0layout0);
+	writel(nand_info->bch_flash0layout1, &bch_regs->hw_bch_flash0layout1);
+}
+
+uint32_t mxs_nand_mark_byte_offset(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
+	struct bch_geometry *geo = &nand_info->bch_geometry;
+
+	return geo->block_mark_byte_offset;
+}
+
+uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd)
+{
+	struct nand_chip *chip = mtd_to_nand(mtd);
+	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
+	struct bch_geometry *geo = &nand_info->bch_geometry;
+
+	return geo->block_mark_bit_offset;
+}
diff --git a/include/mxs_nand.h b/include/mxs_nand.h
index 4bd65cded9..ada20483d0 100644
--- a/include/mxs_nand.h
+++ b/include/mxs_nand.h
@@ -66,8 +66,30 @@ struct mxs_nand_info {
 	/* DMA descriptors */
 	struct mxs_dma_desc	**desc;
 	uint32_t		desc_index;
+
+	/* Hardware BCH interface and randomizer */
+	u32 en_randomizer;
+	u32 writesize;
+	u32 oobsize;
+	u32 bch_flash0layout0;
+	u32 bch_flash0layout1;
+};
+
+struct mxs_nand_layout {
+	u32 nblocks;
+	u32 meta_size;
+	u32 data0_size;
+	u32 ecc0;
+	u32 datan_size;
+	u32 eccn;
 };
 
 int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info);
 int mxs_nand_init_spl(struct nand_chip *nand);
 int mxs_nand_setup_ecc(struct mtd_info *mtd);
+
+void mxs_nand_mode_fcb(struct mtd_info *mtd);
+void mxs_nand_mode_normal(struct mtd_info *mtd);
+u32 mxs_nand_mark_byte_offset(struct mtd_info *mtd);
+u32 mxs_nand_mark_bit_offset(struct mtd_info *mtd);
+void mxs_nand_get_layout(struct mtd_info *mtd, struct mxs_nand_layout *l);
-- 
2.17.1

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

* [U-Boot] [PATCH v2 3/5] imx: nandbcb: add support for i.MX7
  2019-10-21 13:38 [U-Boot] [PATCH v2 0/5] imx: nandbcb: support for i.MX7 and bcb only updates Igor Opaniuk
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 1/5] imx: gpmi: add defines for hw randominizer Igor Opaniuk
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 2/5] nand: mxs_nand: add API for switching different BCH layouts Igor Opaniuk
@ 2019-10-21 13:38 ` Igor Opaniuk
  2019-10-23 11:24   ` Oleksandr Suvorov
                     ` (2 more replies)
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 4/5] imx: nandbcb: refactor update function Igor Opaniuk
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 5/5] imx: nandbcb: add support for writing BCB only Igor Opaniuk
  4 siblings, 3 replies; 18+ messages in thread
From: Igor Opaniuk @ 2019-10-21 13:38 UTC (permalink / raw)
  To: u-boot

From: Igor Opaniuk <igor.opaniuk@toradex.com>

Add support for updating FCB/DBBT on i.MX7:
- additional new fields in FCB structure
- Leverage hardware BCH/randomizer for writing FCB

Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>
---

 arch/arm/include/asm/mach-imx/imx-nandbcb.h |  12 ++
 arch/arm/mach-imx/Kconfig                   |   2 +-
 arch/arm/mach-imx/cmd_nandbcb.c             | 129 +++++++++++++-------
 3 files changed, 100 insertions(+), 43 deletions(-)

diff --git a/arch/arm/include/asm/mach-imx/imx-nandbcb.h b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
index 033659a038..907e7ed8f9 100644
--- a/arch/arm/include/asm/mach-imx/imx-nandbcb.h
+++ b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
@@ -106,6 +106,18 @@ struct fcb_block {
 
 	/* The swap position of main area in spare area */
 	u32 spare_offset;
+
+	/* Actual for iMX7 only */
+	u32 onfi_sync_enable;
+	u32 onfi_sync_speed;
+	u32 onfi_sync_nand_data;
+	u32 reserved2[6];
+	u32 disbbm_search;
+	u32 disbbm_search_limit;
+	u32 reserved3[15];
+	u32 read_retry_enable;
+	u32 reserved4[1];
+	u32 fill_to_1024[183];
 };
 
 #endif	/* _IMX_NAND_BCB_H_ */
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index b0b9d2c070..c22e8f51b4 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -81,7 +81,7 @@ config CMD_HDMIDETECT
 config CMD_NANDBCB
 	bool "i.MX6 NAND Boot Control Block(BCB) command"
 	depends on NAND && CMD_MTDPARTS
-	default y if ARCH_MX6 && NAND_MXS
+	default y if (ARCH_MX6 && NAND_MXS) || (ARCH_MX7 && NAND_MXS)
 	help
 	  Unlike normal 'nand write/erase' commands, this command update
 	  Boot Control Block(BCB) for i.MX6 platform NAND IP's.
diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
index 7811c61d22..aae2cc82f3 100644
--- a/arch/arm/mach-imx/cmd_nandbcb.c
+++ b/arch/arm/mach-imx/cmd_nandbcb.c
@@ -16,6 +16,7 @@
 #include <jffs2/jffs2.h>
 #include <linux/mtd/mtd.h>
 
+#include <asm/arch/sys_proto.h>
 #include <asm/mach-imx/imx-nandbcb.h>
 #include <asm/mach-imx/imximage.cfg>
 #include <mxs_nand.h>
@@ -67,26 +68,36 @@ static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
+	struct mxs_nand_layout l;
+
+	mxs_nand_get_layout(mtd, &l);
 
 	fcb->fingerprint = FCB_FINGERPRINT;
 	fcb->version = FCB_VERSION_1;
+
 	fcb->pagesize = mtd->writesize;
 	fcb->oob_pagesize = mtd->writesize + mtd->oobsize;
 	fcb->sectors = mtd->erasesize / mtd->writesize;
 
-	/* Divide ECC strength by two and save the value into FCB structure. */
-	fcb->ecc_level = nand_info->bch_geometry.ecc_strength >> 1;
-
-	fcb->ecc_type = fcb->ecc_level;
+	fcb->meta_size = l.meta_size;
+	fcb->nr_blocks = l.nblocks;
+	fcb->ecc_nr = l.data0_size;
+	fcb->ecc_level = l.ecc0;
+	fcb->ecc_size = l.datan_size;
+	fcb->ecc_type = l.eccn;
 
 	/* Also hardcoded in kobs-ng */
-	fcb->ecc_nr = 0x00000200;
-	fcb->ecc_size = 0x00000200;
-	fcb->datasetup = 80;
-	fcb->datahold = 60;
-	fcb->addr_setup = 25;
-	fcb->dsample_time = 6;
-	fcb->meta_size = 10;
+	if (is_mx6()) {
+		fcb->datasetup = 80;
+		fcb->datahold = 60;
+		fcb->addr_setup = 25;
+		fcb->dsample_time = 6;
+	} else if (is_mx7()) {
+		fcb->datasetup = 10;
+		fcb->datahold = 7;
+		fcb->addr_setup = 15;
+		fcb->dsample_time = 6;
+	}
 
 	/* DBBT search area starts at second page on first block */
 	fcb->dbbt_start = 1;
@@ -98,6 +109,9 @@ static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd)
 
 	fcb->nr_blocks = mtd->writesize / fcb->ecc_nr - 1;
 
+	fcb->disbbm = 0;
+	fcb->disbbm_search = 0;
+
 	fcb->checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
 }
 
@@ -133,6 +147,7 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
 	size_t fwsize, dummy;
 	int i, ret;
 
+	fcb_raw_page = 0;
 	/* erase */
 	memset(&opts, 0, sizeof(opts));
 	opts.offset = off;
@@ -223,45 +238,74 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
 	else if (ret > 0)
 		dbbt->dbbtpages = 1;
 
-	/* write fcb/dbbt */
-	fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
-	if (!fcb_raw_page) {
-		debug("failed to allocate fcb_raw_page\n");
-		ret = -ENOMEM;
-		goto dbbt_data_page_err;
-	}
-
-	memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
-	encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page + 12 + 512, 512);
 	/*
-	 * Set the first and second byte of OOB data to 0xFF, not 0x00. These
-	 * bytes are used as the Manufacturers Bad Block Marker (MBBM). Since
-	 * the FCB is mostly written to the first page in a block, a scan for
-	 * factory bad blocks will detect these blocks as bad, e.g. when
-	 * function nand_scan_bbt() is executed to build a new bad block table.
+	 * We prepare raw page only for i.MX6, for i.MX7 we
+	 * leverage BCH hw module instead
 	 */
-	memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
+	if (is_mx6()) {
+		/* write fcb/dbbt */
+		fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize,
+				       GFP_KERNEL);
+		if (!fcb_raw_page) {
+			debug("failed to allocate fcb_raw_page\n");
+			ret = -ENOMEM;
+			goto dbbt_data_page_err;
+		}
 
+		memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
+		encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page +
+				    12 + 512, 512);
+		/*
+		 * Set the first and second byte of OOB data to 0xFF,
+		 * not 0x00. These bytes are used as the Manufacturers Bad
+		 * Block Marker (MBBM). Since the FCB is mostly written to
+		 * the first page in a block, a scan for
+		 * factory bad blocks will detect these blocks as bad, e.g.
+		 * when function nand_scan_bbt() is executed to build a new
+		 * bad block table.
+		 */
+		memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
+	}
 	for (i = 0; i < nr_blks_fcb; i++) {
 		if (mtd_block_isbad(mtd, off)) {
 			printf("Block %d is bad, skipped\n", i);
 			continue;
 		}
 
-		/* raw write */
-		mtd_oob_ops_t ops = {
-			.datbuf = (u8 *)fcb_raw_page,
-			.oobbuf = ((u8 *)fcb_raw_page) + mtd->writesize,
-			.len = mtd->writesize,
-			.ooblen = mtd->oobsize,
-			.mode = MTD_OPS_RAW
-		};
-
-		ret = mtd_write_oob(mtd, mtd->erasesize * i, &ops);
-		if (ret)
-			goto fcb_raw_page_err;
-		debug("NAND fcb write: 0x%x offset, 0x%x bytes written: %s\n",
-		      mtd->erasesize * i, ops.len, ret ? "ERROR" : "OK");
+		/*
+		 * User BCH ECC hardware module for i.MX7
+		 */
+		if (is_mx7()) {
+			u32 off = i * mtd->erasesize;
+			size_t rwsize = sizeof(*fcb);
+
+			printf("Writing %d bytes to 0x%x: ", rwsize, off);
+
+			/* switch nand BCH to FCB compatible settings */
+			mxs_nand_mode_fcb(mtd);
+			ret = nand_write(mtd, off, &rwsize,
+					 (unsigned char *)fcb);
+			mxs_nand_mode_normal(mtd);
+
+			printf("%s\n", ret ? "ERROR" : "OK");
+		} else if (is_mx6()) {
+			/* raw write */
+			mtd_oob_ops_t ops = {
+				.datbuf = (u8 *)fcb_raw_page,
+				.oobbuf = ((u8 *)fcb_raw_page) +
+					  mtd->writesize,
+				.len = mtd->writesize,
+				.ooblen = mtd->oobsize,
+				.mode = MTD_OPS_RAW
+			};
+
+			ret = mtd_write_oob(mtd, mtd->erasesize * i, &ops);
+			if (ret)
+				goto fcb_raw_page_err;
+			debug("NAND fcb write: 0x%x offset 0x%x written: %s\n",
+			      mtd->erasesize * i, ops.len, ret ?
+			      "ERROR" : "OK");
+		}
 
 		ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize,
 				mtd->writesize, &dummy, dbbt_page);
@@ -283,7 +327,8 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
 	}
 
 fcb_raw_page_err:
-	kfree(fcb_raw_page);
+	if (is_mx6())
+		kfree(fcb_raw_page);
 dbbt_data_page_err:
 	kfree(dbbt_data_page);
 dbbt_page_err:
-- 
2.17.1

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

* [U-Boot] [PATCH v2 4/5] imx: nandbcb: refactor update function
  2019-10-21 13:38 [U-Boot] [PATCH v2 0/5] imx: nandbcb: support for i.MX7 and bcb only updates Igor Opaniuk
                   ` (2 preceding siblings ...)
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 3/5] imx: nandbcb: add support for i.MX7 Igor Opaniuk
@ 2019-10-21 13:38 ` Igor Opaniuk
  2019-10-23 11:26   ` Oleksandr Suvorov
  2019-10-23 18:31   ` Max Krummenacher
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 5/5] imx: nandbcb: add support for writing BCB only Igor Opaniuk
  4 siblings, 2 replies; 18+ messages in thread
From: Igor Opaniuk @ 2019-10-21 13:38 UTC (permalink / raw)
  To: u-boot

From: Igor Opaniuk <igor.opaniuk@toradex.com>

Move code for writing FCB/DBBT pages to a separate function

Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>
---

 arch/arm/mach-imx/cmd_nandbcb.c | 221 ++++++++++++++++++--------------
 1 file changed, 122 insertions(+), 99 deletions(-)

diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
index aae2cc82f3..fbe780ccda 100644
--- a/arch/arm/mach-imx/cmd_nandbcb.c
+++ b/arch/arm/mach-imx/cmd_nandbcb.c
@@ -64,7 +64,8 @@ static u32 calc_chksum(void *buf, size_t size)
 	return ~chksum;
 }
 
-static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd)
+static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd,
+		     u32 fw1_start, u32 fw2_start, u32 fw_pages)
 {
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
@@ -112,6 +113,11 @@ static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd)
 	fcb->disbbm = 0;
 	fcb->disbbm_search = 0;
 
+	fcb->fw1_start = fw1_start; /* Firmware image starts on this sector */
+	fcb->fw2_start = fw2_start; /* Secondary FW Image starting Sector */
+	fcb->fw1_pages = fw_pages; /* Number of sectors in firmware image */
+	fcb->fw2_pages = fw_pages; /* Number of sector in secondary FW image */
+
 	fcb->checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
 }
 
@@ -135,6 +141,109 @@ static int dbbt_fill_data(struct mtd_info *mtd, void *buf, int num_blocks)
 	return n_bad_blocks;
 }
 
+static int write_fcb_dbbt(struct mtd_info *mtd, struct fcb_block *fcb,
+			  struct dbbt_block *dbbt, void *dbbt_data_page,
+			  loff_t off)
+{
+	void *fcb_raw_page = 0;
+	int i, ret;
+	size_t dummy;
+
+	/*
+	 * We prepare raw page only for i.MX6, for i.MX7 we
+	 * leverage BCH hw module instead
+	 */
+	if (is_mx6()) {
+		/* write fcb/dbbt */
+		fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize,
+				       GFP_KERNEL);
+		if (!fcb_raw_page) {
+			debug("failed to allocate fcb_raw_page\n");
+			ret = -ENOMEM;
+			return ret;
+		}
+
+		memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
+		encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page +
+				    12 + 512, 512);
+		/*
+		 * Set the first and second byte of OOB data to 0xFF,
+		 * not 0x00. These bytes are used as the Manufacturers Bad
+		 * Block Marker (MBBM). Since the FCB is mostly written to
+		 * the first page in a block, a scan for
+		 * factory bad blocks will detect these blocks as bad, e.g.
+		 * when function nand_scan_bbt() is executed to build a new
+		 * bad block table.
+		 */
+		memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
+	}
+	for (i = 0; i < 2; i++) {
+		if (mtd_block_isbad(mtd, off)) {
+			printf("Block %d is bad, skipped\n", i);
+			continue;
+		}
+
+		/*
+		 * User BCH ECC hardware module for i.MX7
+		 */
+		if (is_mx7()) {
+			u32 off = i * mtd->erasesize;
+			size_t rwsize = sizeof(*fcb);
+
+			printf("Writing %d bytes to 0x%x: ", rwsize, off);
+
+			/* switch nand BCH to FCB compatible settings */
+			mxs_nand_mode_fcb(mtd);
+			ret = nand_write(mtd, off, &rwsize,
+					 (unsigned char *)fcb);
+			mxs_nand_mode_normal(mtd);
+
+			printf("%s\n", ret ? "ERROR" : "OK");
+		} else if (is_mx6()) {
+			/* raw write */
+			mtd_oob_ops_t ops = {
+				.datbuf = (u8 *)fcb_raw_page,
+				.oobbuf = ((u8 *)fcb_raw_page) +
+					  mtd->writesize,
+				.len = mtd->writesize,
+				.ooblen = mtd->oobsize,
+				.mode = MTD_OPS_RAW
+			};
+
+			ret = mtd_write_oob(mtd, mtd->erasesize * i, &ops);
+			if (ret)
+				goto fcb_raw_page_err;
+			debug("NAND fcb write: 0x%x offset 0x%x written: %s\n",
+			      mtd->erasesize * i, ops.len, ret ?
+			      "ERROR" : "OK");
+		}
+
+		ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize,
+				mtd->writesize, &dummy, (void *)dbbt);
+		if (ret)
+			goto fcb_raw_page_err;
+		debug("NAND dbbt write: 0x%x offset, 0x%x bytes written: %s\n",
+		      mtd->erasesize * i + mtd->writesize, dummy,
+		      ret ? "ERROR" : "OK");
+
+		/* dbbtpages == 0 if no bad blocks */
+		if (dbbt->dbbtpages > 0) {
+			loff_t to = (mtd->erasesize * i + mtd->writesize * 5);
+
+			ret = mtd_write(mtd, to, mtd->writesize, &dummy,
+					dbbt_data_page);
+			if (ret)
+				goto fcb_raw_page_err;
+		}
+	}
+
+fcb_raw_page_err:
+	if (is_mx6())
+		kfree(fcb_raw_page);
+
+	return ret;
+}
+
 static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
 			  size_t maxsize, const u_char *buf)
 {
@@ -142,12 +251,12 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
 	struct fcb_block *fcb;
 	struct dbbt_block *dbbt;
 	loff_t fw1_off;
-	void *fwbuf, *fcb_raw_page, *dbbt_page, *dbbt_data_page;
+	void *fwbuf, *dbbt_page, *dbbt_data_page;
+	u32 fw1_start, fw1_pages;
 	int nr_blks, nr_blks_fcb, fw1_blk;
-	size_t fwsize, dummy;
-	int i, ret;
+	size_t fwsize;
+	int ret;
 
-	fcb_raw_page = 0;
 	/* erase */
 	memset(&opts, 0, sizeof(opts));
 	opts.offset = off;
@@ -209,9 +318,9 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
 		goto fwbuf_err;
 	}
 
-	fcb->fw1_start = (fw1_blk * mtd->erasesize) / mtd->writesize;
-	fcb->fw1_pages = size / mtd->writesize + 1;
-	fill_fcb(fcb, mtd);
+	fw1_start = (fw1_blk * mtd->erasesize) / mtd->writesize;
+	fw1_pages = size / mtd->writesize + 1;
+	fill_fcb(fcb, mtd, fw1_start, 0, fw1_pages);
 
 	/* fill dbbt */
 	dbbt_page = kzalloc(mtd->writesize, GFP_KERNEL);
@@ -238,97 +347,11 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
 	else if (ret > 0)
 		dbbt->dbbtpages = 1;
 
-	/*
-	 * We prepare raw page only for i.MX6, for i.MX7 we
-	 * leverage BCH hw module instead
-	 */
-	if (is_mx6()) {
-		/* write fcb/dbbt */
-		fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize,
-				       GFP_KERNEL);
-		if (!fcb_raw_page) {
-			debug("failed to allocate fcb_raw_page\n");
-			ret = -ENOMEM;
-			goto dbbt_data_page_err;
-		}
-
-		memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
-		encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page +
-				    12 + 512, 512);
-		/*
-		 * Set the first and second byte of OOB data to 0xFF,
-		 * not 0x00. These bytes are used as the Manufacturers Bad
-		 * Block Marker (MBBM). Since the FCB is mostly written to
-		 * the first page in a block, a scan for
-		 * factory bad blocks will detect these blocks as bad, e.g.
-		 * when function nand_scan_bbt() is executed to build a new
-		 * bad block table.
-		 */
-		memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
-	}
-	for (i = 0; i < nr_blks_fcb; i++) {
-		if (mtd_block_isbad(mtd, off)) {
-			printf("Block %d is bad, skipped\n", i);
-			continue;
-		}
-
-		/*
-		 * User BCH ECC hardware module for i.MX7
-		 */
-		if (is_mx7()) {
-			u32 off = i * mtd->erasesize;
-			size_t rwsize = sizeof(*fcb);
-
-			printf("Writing %d bytes to 0x%x: ", rwsize, off);
-
-			/* switch nand BCH to FCB compatible settings */
-			mxs_nand_mode_fcb(mtd);
-			ret = nand_write(mtd, off, &rwsize,
-					 (unsigned char *)fcb);
-			mxs_nand_mode_normal(mtd);
-
-			printf("%s\n", ret ? "ERROR" : "OK");
-		} else if (is_mx6()) {
-			/* raw write */
-			mtd_oob_ops_t ops = {
-				.datbuf = (u8 *)fcb_raw_page,
-				.oobbuf = ((u8 *)fcb_raw_page) +
-					  mtd->writesize,
-				.len = mtd->writesize,
-				.ooblen = mtd->oobsize,
-				.mode = MTD_OPS_RAW
-			};
-
-			ret = mtd_write_oob(mtd, mtd->erasesize * i, &ops);
-			if (ret)
-				goto fcb_raw_page_err;
-			debug("NAND fcb write: 0x%x offset 0x%x written: %s\n",
-			      mtd->erasesize * i, ops.len, ret ?
-			      "ERROR" : "OK");
-		}
-
-		ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize,
-				mtd->writesize, &dummy, dbbt_page);
-		if (ret)
-			goto fcb_raw_page_err;
-		debug("NAND dbbt write: 0x%x offset, 0x%x bytes written: %s\n",
-		      mtd->erasesize * i + mtd->writesize, dummy,
-		      ret ? "ERROR" : "OK");
-
-		/* dbbtpages == 0 if no bad blocks */
-		if (dbbt->dbbtpages > 0) {
-			loff_t to = (mtd->erasesize * i + mtd->writesize * 5);
-
-			ret = mtd_write(mtd, to, mtd->writesize, &dummy,
-					dbbt_data_page);
-			if (ret)
-				goto fcb_raw_page_err;
-		}
-	}
+	/* write fcb and dbbt to nand */
+	ret = write_fcb_dbbt(mtd, fcb, dbbt, dbbt_data_page, off);
+	if (ret < 0)
+		printf("failed to write FCB/DBBT\n");
 
-fcb_raw_page_err:
-	if (is_mx6())
-		kfree(fcb_raw_page);
 dbbt_data_page_err:
 	kfree(dbbt_data_page);
 dbbt_page_err:
@@ -355,7 +378,7 @@ static int do_nandbcb_update(int argc, char * const argv[])
 
 	dev = nand_curr_device;
 	if (dev < 0) {
-		printf("failed to get nand_curr_device, run nand device");
+		printf("failed to get nand_curr_device, run nand device\n");
 		return CMD_RET_FAILURE;
 	}
 
-- 
2.17.1

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

* [U-Boot] [PATCH v2 5/5] imx: nandbcb: add support for writing BCB only
  2019-10-21 13:38 [U-Boot] [PATCH v2 0/5] imx: nandbcb: support for i.MX7 and bcb only updates Igor Opaniuk
                   ` (3 preceding siblings ...)
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 4/5] imx: nandbcb: refactor update function Igor Opaniuk
@ 2019-10-21 13:38 ` Igor Opaniuk
  2019-10-23 11:28   ` Oleksandr Suvorov
  2019-10-23 18:32   ` Max Krummenacher
  4 siblings, 2 replies; 18+ messages in thread
From: Igor Opaniuk @ 2019-10-21 13:38 UTC (permalink / raw)
  To: u-boot

From: Igor Opaniuk <igor.opaniuk@toradex.com>

Add subcommand for add writing BCB only, where we provide appropriate
offsets for firmware1 and firmware2 and size.

Example of usage:
- nandbcb bcbonly 0x00180000 0x00080000 0x00200000
Writing 1024 bytes to 0x0: randomizing
OK
Writing 1024 bytes to 0x20000: randomizing
OK

Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>
---

 arch/arm/mach-imx/cmd_nandbcb.c | 92 ++++++++++++++++++++++++++++++++-
 1 file changed, 91 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
index fbe780ccda..d11e16cf83 100644
--- a/arch/arm/mach-imx/cmd_nandbcb.c
+++ b/arch/arm/mach-imx/cmd_nandbcb.c
@@ -364,6 +364,88 @@ err:
 	return ret;
 }
 
+static int do_nandbcb_bcbonly(int argc, char * const argv[])
+{
+	struct fcb_block *fcb;
+	struct dbbt_block *dbbt;
+	u32 fw_len, fw1_off, fw2_off;
+	struct mtd_info *mtd;
+	void *dbbt_page, *dbbt_data_page;
+	int dev, ret;
+
+	dev = nand_curr_device;
+	if ((dev < 0) || (dev >= CONFIG_SYS_MAX_NAND_DEVICE) ||
+	    (!get_nand_dev_by_index(dev))) {
+		puts("No devices available\n");
+		return CMD_RET_FAILURE;
+	}
+
+	mtd = get_nand_dev_by_index(dev);
+
+	if (argc < 3)
+		return CMD_RET_FAILURE;
+
+	fw_len = simple_strtoul(argv[1], NULL, 16);
+	fw1_off = simple_strtoul(argv[2], NULL, 16);
+
+	if (argc > 3)
+		fw2_off = simple_strtoul(argv[3], NULL, 16);
+	else
+		fw2_off = fw1_off;
+
+	/* fill fcb */
+	fcb = kzalloc(sizeof(*fcb), GFP_KERNEL);
+	if (!fcb) {
+		debug("failed to allocate fcb\n");
+		ret = -ENOMEM;
+		return CMD_RET_FAILURE;
+	}
+
+	fill_fcb(fcb, mtd, fw1_off / mtd->writesize,
+		 fw2_off / mtd->writesize, fw_len / mtd->writesize);
+
+	/* fill dbbt */
+	dbbt_page = kzalloc(mtd->writesize, GFP_KERNEL);
+	if (!dbbt_page) {
+		debug("failed to allocate dbbt_page\n");
+		ret = -ENOMEM;
+		goto fcb_err;
+	}
+
+	dbbt_data_page = kzalloc(mtd->writesize, GFP_KERNEL);
+	if (!dbbt_data_page) {
+		debug("failed to allocate dbbt_data_page\n");
+		ret = -ENOMEM;
+		goto dbbt_page_err;
+	}
+
+	dbbt = dbbt_page;
+	dbbt->checksum = 0;
+	dbbt->fingerprint = DBBT_FINGERPRINT2;
+	dbbt->version = DBBT_VERSION_1;
+	ret = dbbt_fill_data(mtd, dbbt_data_page, 0);
+	if (ret < 0)
+		goto dbbt_data_page_err;
+	else if (ret > 0)
+		dbbt->dbbtpages = 1;
+
+	/* write fcb and dbbt to nand */
+	ret = write_fcb_dbbt(mtd, fcb, dbbt, dbbt_data_page, 0);
+dbbt_data_page_err:
+	kfree(dbbt_data_page);
+dbbt_page_err:
+	kfree(dbbt_page);
+fcb_err:
+	kfree(fcb);
+
+	if (ret < 0) {
+		printf("failed to write FCB/DBBT\n");
+		return CMD_RET_FAILURE;
+	}
+
+	return CMD_RET_SUCCESS;
+}
+
 static int do_nandbcb_update(int argc, char * const argv[])
 {
 	struct mtd_info *mtd;
@@ -420,6 +502,11 @@ static int do_nandbcb(cmd_tbl_t *cmdtp, int flag, int argc,
 		goto done;
 	}
 
+	if (strcmp(cmd, "bcbonly") == 0) {
+		ret = do_nandbcb_bcbonly(argc, argv);
+		goto done;
+	}
+
 done:
 	if (ret != -1)
 		return ret;
@@ -430,7 +517,10 @@ usage:
 #ifdef CONFIG_SYS_LONGHELP
 static char nandbcb_help_text[] =
 	"update addr off|partition len	- update 'len' bytes starting at\n"
-	"	'off|part' to memory address 'addr', skipping  bad blocks";
+	"       'off|part' to memory address 'addr', skipping  bad blocks\n"
+	"bcbonly fw-size fw1-off [fw2-off] - write only BCB (FCB and DBBT)\n"
+	"       where `fw-size` is fw sizes in bytes, `fw1-off` and\n"
+	"       and `fw2-off` - firmware offsets		";
 #endif
 
 U_BOOT_CMD(nandbcb, 5, 1, do_nandbcb,
-- 
2.17.1

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

* [U-Boot] [PATCH v2 1/5] imx: gpmi: add defines for hw randominizer
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 1/5] imx: gpmi: add defines for hw randominizer Igor Opaniuk
@ 2019-10-23 11:21   ` Oleksandr Suvorov
  2019-10-23 17:51   ` Max Krummenacher
  1 sibling, 0 replies; 18+ messages in thread
From: Oleksandr Suvorov @ 2019-10-23 11:21 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 4:41 PM Igor Opaniuk <igor.opaniuk@gmail.com> wrote:
>
> From: Igor Opaniuk <igor.opaniuk@toradex.com>
>
> Extend GPMI Integrated ECC Control Register Description, include
> additional defines for enabling randomizer function and providing
> proper randomizer type.
>
> For additional details check i.MX7 APR, section
> 9.6.6.3 GPMI Integrated ECC Control Register Description
> (GPMI_ECCCTRLn)
>
> Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>

Reviewed-by: Oleksandr Suvorov <oleksandr.suvorov@toradex.com>

> ---
>
>  arch/arm/include/asm/mach-imx/regs-gpmi.h | 5 +++++
>  1 file changed, 5 insertions(+)
>
> diff --git a/arch/arm/include/asm/mach-imx/regs-gpmi.h b/arch/arm/include/asm/mach-imx/regs-gpmi.h
> index 80cb731724..33daa53c45 100644
> --- a/arch/arm/include/asm/mach-imx/regs-gpmi.h
> +++ b/arch/arm/include/asm/mach-imx/regs-gpmi.h
> @@ -70,6 +70,11 @@ struct mxs_gpmi_regs {
>  #define        GPMI_ECCCTRL_ECC_CMD_OFFSET                     13
>  #define        GPMI_ECCCTRL_ECC_CMD_DECODE                     (0x0 << 13)
>  #define        GPMI_ECCCTRL_ECC_CMD_ENCODE                     (0x1 << 13)
> +#define        GPMI_ECCCTRL_RANDOMIZER_ENABLE                  (1 << 11)
> +#define        GPMI_ECCCTRL_RANDOMIZER_TYPE0                   0
> +#define        GPMI_ECCCTRL_RANDOMIZER_TYPE1                   (1 << 9)
> +#define        GPMI_ECCCTRL_RANDOMIZER_TYPE2                   (2 << 9)
> +
>  #define        GPMI_ECCCTRL_ENABLE_ECC                         (1 << 12)
>  #define        GPMI_ECCCTRL_BUFFER_MASK_MASK                   0x1ff
>  #define        GPMI_ECCCTRL_BUFFER_MASK_OFFSET                 0
> --
> 2.17.1
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot



-- 
Best regards
Oleksandr Suvorov

Toradex AG
Altsagenstrasse 5 | 6048 Horw/Luzern | Switzerland | T: +41 41 500
4800 (main line)

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

* [U-Boot] [PATCH v2 2/5] nand: mxs_nand: add API for switching different BCH layouts
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 2/5] nand: mxs_nand: add API for switching different BCH layouts Igor Opaniuk
@ 2019-10-23 11:23   ` Oleksandr Suvorov
  2019-10-23 17:53   ` Max Krummenacher
  1 sibling, 0 replies; 18+ messages in thread
From: Oleksandr Suvorov @ 2019-10-23 11:23 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 4:41 PM Igor Opaniuk <igor.opaniuk@gmail.com> wrote:
>
> From: Igor Opaniuk <igor.opaniuk@toradex.com>
>
> On i.MX7 in a sake of reducing the disturbances caused by a neighboring
> cells in the FCB page in the NAND chip, a randomizer is enabled when
> reading the FCB page by ROM bootloader.
>
> Add API for setting BCH to specific layout (and restoring it back) used by
> ROM bootloader to be able to burn it in a proper way to NAND using
> nandbcb command.
>
> Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>
> Signed-off-by: Anti Sullin <anti.sullin@artecdesign.ee>

Reviewed-by: Oleksandr Suvorov <oleksandr.suvorov@toradex.com>

> ---
>
>  drivers/mtd/nand/raw/mxs_nand.c | 116 ++++++++++++++++++++++++++++++++
>  include/mxs_nand.h              |  22 ++++++
>  2 files changed, 138 insertions(+)
>
> diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
> index a41b9620d0..ad7b644886 100644
> --- a/drivers/mtd/nand/raw/mxs_nand.c
> +++ b/drivers/mtd/nand/raw/mxs_nand.c
> @@ -740,6 +740,19 @@ 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) {
> +               d->cmd.pio_words[2] |= GPMI_ECCCTRL_RANDOMIZER_ENABLE |
> +                                      GPMI_ECCCTRL_RANDOMIZER_TYPE2;
> +               /*
> +                * Write NAND page number needed to be randomized
> +                * to GPMI_ECCCOUNT register.
> +                *
> +                * 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;
> +       }
> +
>         mxs_dma_desc_append(channel, d);
>
>         /* Flush caches */
> @@ -1003,6 +1016,10 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
>         uint32_t tmp;
>         int ret;
>
> +       nand_info->en_randomizer = 0;
> +       nand_info->oobsize = mtd->oobsize;
> +       nand_info->writesize = mtd->writesize;
> +
>         ret = mxs_nand_set_geometry(mtd, geo);
>         if (ret)
>                 return ret;
> @@ -1020,6 +1037,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
>         tmp |= (geo->gf_len == 14 ? 1 : 0) <<
>                 BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
>         writel(tmp, &bch_regs->hw_bch_flash0layout0);
> +       nand_info->bch_flash0layout0 = tmp;
>
>         tmp = (mtd->writesize + mtd->oobsize)
>                 << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
> @@ -1028,6 +1046,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
>         tmp |= (geo->gf_len == 14 ? 1 : 0) <<
>                 BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
>         writel(tmp, &bch_regs->hw_bch_flash0layout1);
> +       nand_info->bch_flash0layout1 = tmp;
>
>         /* Set *all* chip selects to use layout 0 */
>         writel(0, &bch_regs->hw_bch_layoutselect);
> @@ -1303,3 +1322,100 @@ err:
>         free(nand_info);
>  }
>  #endif
> +
> +/*
> + * Read NAND layout for FCB block generation.
> + */
> +void mxs_nand_get_layout(struct mtd_info *mtd, struct mxs_nand_layout *l)
> +{
> +       struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
> +       u32 tmp;
> +
> +       tmp = readl(&bch_regs->hw_bch_flash0layout0);
> +       l->nblocks = (tmp & BCH_FLASHLAYOUT0_NBLOCKS_MASK) >>
> +                       BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
> +       l->meta_size = (tmp & BCH_FLASHLAYOUT0_META_SIZE_MASK) >>
> +                       BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
> +
> +       tmp = readl(&bch_regs->hw_bch_flash0layout1);
> +       l->data0_size = 4 * ((tmp & BCH_FLASHLAYOUT0_DATA0_SIZE_MASK) >>
> +                       BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET);
> +       l->ecc0 = (tmp & BCH_FLASHLAYOUT0_ECC0_MASK) >>
> +                       BCH_FLASHLAYOUT0_ECC0_OFFSET;
> +       l->datan_size = 4 * ((tmp & BCH_FLASHLAYOUT1_DATAN_SIZE_MASK) >>
> +                       BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET);
> +       l->eccn = (tmp & BCH_FLASHLAYOUT1_ECCN_MASK) >>
> +                       BCH_FLASHLAYOUT1_ECCN_OFFSET;
> +}
> +
> +/*
> + * Set BCH to specific layout used by ROM bootloader to read FCB.
> + */
> +void mxs_nand_mode_fcb(struct mtd_info *mtd)
> +{
> +       u32 tmp;
> +       struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
> +       struct nand_chip *nand = mtd_to_nand(mtd);
> +       struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
> +
> +       nand_info->en_randomizer = 1;
> +
> +       mtd->writesize = 1024;
> +       mtd->oobsize = 1862 - 1024;
> +
> +       /* 8 ecc_chunks_*/
> +       tmp = 7 << BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
> +       /* 32 bytes for metadata */
> +       tmp |= 32 << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
> +       /* using ECC62 level to be performed */
> +       tmp |= 0x1F << BCH_FLASHLAYOUT0_ECC0_OFFSET;
> +       /* 0x20 * 4 bytes of the data0 block */
> +       tmp |= 0x20 << BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET;
> +       tmp |= 0 << BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
> +       writel(tmp, &bch_regs->hw_bch_flash0layout0);
> +
> +       /* 1024 for data + 838 for OOB */
> +       tmp = 1862 << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
> +       /* using ECC62 level to be performed */
> +       tmp |= 0x1F << BCH_FLASHLAYOUT1_ECCN_OFFSET;
> +       /* 0x20 * 4 bytes of the data0 block */
> +       tmp |= 0x20 << BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET;
> +       tmp |= 0 << BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
> +       writel(tmp, &bch_regs->hw_bch_flash0layout1);
> +}
> +
> +/*
> + * Restore BCH to normal settings.
> + */
> +void mxs_nand_mode_normal(struct mtd_info *mtd)
> +{
> +       struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
> +       struct nand_chip *nand = mtd_to_nand(mtd);
> +       struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
> +
> +       nand_info->en_randomizer = 0;
> +
> +       mtd->writesize = nand_info->writesize;
> +       mtd->oobsize = nand_info->oobsize;
> +
> +       writel(nand_info->bch_flash0layout0, &bch_regs->hw_bch_flash0layout0);
> +       writel(nand_info->bch_flash0layout1, &bch_regs->hw_bch_flash0layout1);
> +}
> +
> +uint32_t mxs_nand_mark_byte_offset(struct mtd_info *mtd)
> +{
> +       struct nand_chip *chip = mtd_to_nand(mtd);
> +       struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> +       struct bch_geometry *geo = &nand_info->bch_geometry;
> +
> +       return geo->block_mark_byte_offset;
> +}
> +
> +uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd)
> +{
> +       struct nand_chip *chip = mtd_to_nand(mtd);
> +       struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> +       struct bch_geometry *geo = &nand_info->bch_geometry;
> +
> +       return geo->block_mark_bit_offset;
> +}
> diff --git a/include/mxs_nand.h b/include/mxs_nand.h
> index 4bd65cded9..ada20483d0 100644
> --- a/include/mxs_nand.h
> +++ b/include/mxs_nand.h
> @@ -66,8 +66,30 @@ struct mxs_nand_info {
>         /* DMA descriptors */
>         struct mxs_dma_desc     **desc;
>         uint32_t                desc_index;
> +
> +       /* Hardware BCH interface and randomizer */
> +       u32 en_randomizer;
> +       u32 writesize;
> +       u32 oobsize;
> +       u32 bch_flash0layout0;
> +       u32 bch_flash0layout1;
> +};
> +
> +struct mxs_nand_layout {
> +       u32 nblocks;
> +       u32 meta_size;
> +       u32 data0_size;
> +       u32 ecc0;
> +       u32 datan_size;
> +       u32 eccn;
>  };
>
>  int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info);
>  int mxs_nand_init_spl(struct nand_chip *nand);
>  int mxs_nand_setup_ecc(struct mtd_info *mtd);
> +
> +void mxs_nand_mode_fcb(struct mtd_info *mtd);
> +void mxs_nand_mode_normal(struct mtd_info *mtd);
> +u32 mxs_nand_mark_byte_offset(struct mtd_info *mtd);
> +u32 mxs_nand_mark_bit_offset(struct mtd_info *mtd);
> +void mxs_nand_get_layout(struct mtd_info *mtd, struct mxs_nand_layout *l);
> --
> 2.17.1
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot



-- 
Best regards
Oleksandr Suvorov

Toradex AG
Altsagenstrasse 5 | 6048 Horw/Luzern | Switzerland | T: +41 41 500
4800 (main line)

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

* [U-Boot] [PATCH v2 3/5] imx: nandbcb: add support for i.MX7
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 3/5] imx: nandbcb: add support for i.MX7 Igor Opaniuk
@ 2019-10-23 11:24   ` Oleksandr Suvorov
  2019-10-23 18:30   ` Max Krummenacher
  2019-11-03 13:55   ` Stefano Babic
  2 siblings, 0 replies; 18+ messages in thread
From: Oleksandr Suvorov @ 2019-10-23 11:24 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 4:40 PM Igor Opaniuk <igor.opaniuk@gmail.com> wrote:
>
> From: Igor Opaniuk <igor.opaniuk@toradex.com>
>
> Add support for updating FCB/DBBT on i.MX7:
> - additional new fields in FCB structure
> - Leverage hardware BCH/randomizer for writing FCB
>
> Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>

Reviewed-by: Oleksandr Suvorov <oleksandr.suvorov@toradex.com>

> ---
>
>  arch/arm/include/asm/mach-imx/imx-nandbcb.h |  12 ++
>  arch/arm/mach-imx/Kconfig                   |   2 +-
>  arch/arm/mach-imx/cmd_nandbcb.c             | 129 +++++++++++++-------
>  3 files changed, 100 insertions(+), 43 deletions(-)
>
> diff --git a/arch/arm/include/asm/mach-imx/imx-nandbcb.h b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
> index 033659a038..907e7ed8f9 100644
> --- a/arch/arm/include/asm/mach-imx/imx-nandbcb.h
> +++ b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
> @@ -106,6 +106,18 @@ struct fcb_block {
>
>         /* The swap position of main area in spare area */
>         u32 spare_offset;
> +
> +       /* Actual for iMX7 only */
> +       u32 onfi_sync_enable;
> +       u32 onfi_sync_speed;
> +       u32 onfi_sync_nand_data;
> +       u32 reserved2[6];
> +       u32 disbbm_search;
> +       u32 disbbm_search_limit;
> +       u32 reserved3[15];
> +       u32 read_retry_enable;
> +       u32 reserved4[1];
> +       u32 fill_to_1024[183];
>  };
>
>  #endif /* _IMX_NAND_BCB_H_ */
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index b0b9d2c070..c22e8f51b4 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -81,7 +81,7 @@ config CMD_HDMIDETECT
>  config CMD_NANDBCB
>         bool "i.MX6 NAND Boot Control Block(BCB) command"
>         depends on NAND && CMD_MTDPARTS
> -       default y if ARCH_MX6 && NAND_MXS
> +       default y if (ARCH_MX6 && NAND_MXS) || (ARCH_MX7 && NAND_MXS)
>         help
>           Unlike normal 'nand write/erase' commands, this command update
>           Boot Control Block(BCB) for i.MX6 platform NAND IP's.
> diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
> index 7811c61d22..aae2cc82f3 100644
> --- a/arch/arm/mach-imx/cmd_nandbcb.c
> +++ b/arch/arm/mach-imx/cmd_nandbcb.c
> @@ -16,6 +16,7 @@
>  #include <jffs2/jffs2.h>
>  #include <linux/mtd/mtd.h>
>
> +#include <asm/arch/sys_proto.h>
>  #include <asm/mach-imx/imx-nandbcb.h>
>  #include <asm/mach-imx/imximage.cfg>
>  #include <mxs_nand.h>
> @@ -67,26 +68,36 @@ static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd)
>  {
>         struct nand_chip *chip = mtd_to_nand(mtd);
>         struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> +       struct mxs_nand_layout l;
> +
> +       mxs_nand_get_layout(mtd, &l);
>
>         fcb->fingerprint = FCB_FINGERPRINT;
>         fcb->version = FCB_VERSION_1;
> +
>         fcb->pagesize = mtd->writesize;
>         fcb->oob_pagesize = mtd->writesize + mtd->oobsize;
>         fcb->sectors = mtd->erasesize / mtd->writesize;
>
> -       /* Divide ECC strength by two and save the value into FCB structure. */
> -       fcb->ecc_level = nand_info->bch_geometry.ecc_strength >> 1;
> -
> -       fcb->ecc_type = fcb->ecc_level;
> +       fcb->meta_size = l.meta_size;
> +       fcb->nr_blocks = l.nblocks;
> +       fcb->ecc_nr = l.data0_size;
> +       fcb->ecc_level = l.ecc0;
> +       fcb->ecc_size = l.datan_size;
> +       fcb->ecc_type = l.eccn;
>
>         /* Also hardcoded in kobs-ng */
> -       fcb->ecc_nr = 0x00000200;
> -       fcb->ecc_size = 0x00000200;
> -       fcb->datasetup = 80;
> -       fcb->datahold = 60;
> -       fcb->addr_setup = 25;
> -       fcb->dsample_time = 6;
> -       fcb->meta_size = 10;
> +       if (is_mx6()) {
> +               fcb->datasetup = 80;
> +               fcb->datahold = 60;
> +               fcb->addr_setup = 25;
> +               fcb->dsample_time = 6;
> +       } else if (is_mx7()) {
> +               fcb->datasetup = 10;
> +               fcb->datahold = 7;
> +               fcb->addr_setup = 15;
> +               fcb->dsample_time = 6;
> +       }
>
>         /* DBBT search area starts at second page on first block */
>         fcb->dbbt_start = 1;
> @@ -98,6 +109,9 @@ static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd)
>
>         fcb->nr_blocks = mtd->writesize / fcb->ecc_nr - 1;
>
> +       fcb->disbbm = 0;
> +       fcb->disbbm_search = 0;
> +
>         fcb->checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
>  }
>
> @@ -133,6 +147,7 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
>         size_t fwsize, dummy;
>         int i, ret;
>
> +       fcb_raw_page = 0;
>         /* erase */
>         memset(&opts, 0, sizeof(opts));
>         opts.offset = off;
> @@ -223,45 +238,74 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
>         else if (ret > 0)
>                 dbbt->dbbtpages = 1;
>
> -       /* write fcb/dbbt */
> -       fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
> -       if (!fcb_raw_page) {
> -               debug("failed to allocate fcb_raw_page\n");
> -               ret = -ENOMEM;
> -               goto dbbt_data_page_err;
> -       }
> -
> -       memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
> -       encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page + 12 + 512, 512);
>         /*
> -        * Set the first and second byte of OOB data to 0xFF, not 0x00. These
> -        * bytes are used as the Manufacturers Bad Block Marker (MBBM). Since
> -        * the FCB is mostly written to the first page in a block, a scan for
> -        * factory bad blocks will detect these blocks as bad, e.g. when
> -        * function nand_scan_bbt() is executed to build a new bad block table.
> +        * We prepare raw page only for i.MX6, for i.MX7 we
> +        * leverage BCH hw module instead
>          */
> -       memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
> +       if (is_mx6()) {
> +               /* write fcb/dbbt */
> +               fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize,
> +                                      GFP_KERNEL);
> +               if (!fcb_raw_page) {
> +                       debug("failed to allocate fcb_raw_page\n");
> +                       ret = -ENOMEM;
> +                       goto dbbt_data_page_err;
> +               }
>
> +               memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
> +               encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page +
> +                                   12 + 512, 512);
> +               /*
> +                * Set the first and second byte of OOB data to 0xFF,
> +                * not 0x00. These bytes are used as the Manufacturers Bad
> +                * Block Marker (MBBM). Since the FCB is mostly written to
> +                * the first page in a block, a scan for
> +                * factory bad blocks will detect these blocks as bad, e.g.
> +                * when function nand_scan_bbt() is executed to build a new
> +                * bad block table.
> +                */
> +               memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
> +       }
>         for (i = 0; i < nr_blks_fcb; i++) {
>                 if (mtd_block_isbad(mtd, off)) {
>                         printf("Block %d is bad, skipped\n", i);
>                         continue;
>                 }
>
> -               /* raw write */
> -               mtd_oob_ops_t ops = {
> -                       .datbuf = (u8 *)fcb_raw_page,
> -                       .oobbuf = ((u8 *)fcb_raw_page) + mtd->writesize,
> -                       .len = mtd->writesize,
> -                       .ooblen = mtd->oobsize,
> -                       .mode = MTD_OPS_RAW
> -               };
> -
> -               ret = mtd_write_oob(mtd, mtd->erasesize * i, &ops);
> -               if (ret)
> -                       goto fcb_raw_page_err;
> -               debug("NAND fcb write: 0x%x offset, 0x%x bytes written: %s\n",
> -                     mtd->erasesize * i, ops.len, ret ? "ERROR" : "OK");
> +               /*
> +                * User BCH ECC hardware module for i.MX7
> +                */
> +               if (is_mx7()) {
> +                       u32 off = i * mtd->erasesize;
> +                       size_t rwsize = sizeof(*fcb);
> +
> +                       printf("Writing %d bytes to 0x%x: ", rwsize, off);
> +
> +                       /* switch nand BCH to FCB compatible settings */
> +                       mxs_nand_mode_fcb(mtd);
> +                       ret = nand_write(mtd, off, &rwsize,
> +                                        (unsigned char *)fcb);
> +                       mxs_nand_mode_normal(mtd);
> +
> +                       printf("%s\n", ret ? "ERROR" : "OK");
> +               } else if (is_mx6()) {
> +                       /* raw write */
> +                       mtd_oob_ops_t ops = {
> +                               .datbuf = (u8 *)fcb_raw_page,
> +                               .oobbuf = ((u8 *)fcb_raw_page) +
> +                                         mtd->writesize,
> +                               .len = mtd->writesize,
> +                               .ooblen = mtd->oobsize,
> +                               .mode = MTD_OPS_RAW
> +                       };
> +
> +                       ret = mtd_write_oob(mtd, mtd->erasesize * i, &ops);
> +                       if (ret)
> +                               goto fcb_raw_page_err;
> +                       debug("NAND fcb write: 0x%x offset 0x%x written: %s\n",
> +                             mtd->erasesize * i, ops.len, ret ?
> +                             "ERROR" : "OK");
> +               }
>
>                 ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize,
>                                 mtd->writesize, &dummy, dbbt_page);
> @@ -283,7 +327,8 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
>         }
>
>  fcb_raw_page_err:
> -       kfree(fcb_raw_page);
> +       if (is_mx6())
> +               kfree(fcb_raw_page);
>  dbbt_data_page_err:
>         kfree(dbbt_data_page);
>  dbbt_page_err:
> --
> 2.17.1
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot



-- 
Best regards

Oleksandr Suvorov
cryosay at gmail.com

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

* [U-Boot] [PATCH v2 4/5] imx: nandbcb: refactor update function
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 4/5] imx: nandbcb: refactor update function Igor Opaniuk
@ 2019-10-23 11:26   ` Oleksandr Suvorov
  2019-10-23 18:31   ` Max Krummenacher
  1 sibling, 0 replies; 18+ messages in thread
From: Oleksandr Suvorov @ 2019-10-23 11:26 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 4:41 PM Igor Opaniuk <igor.opaniuk@gmail.com> wrote:
>
> From: Igor Opaniuk <igor.opaniuk@toradex.com>
>
> Move code for writing FCB/DBBT pages to a separate function
>
> Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>

Reviewed-by: Oleksandr Suvorov <oleksandr.suvorov@toradex.com>

> ---
>
>  arch/arm/mach-imx/cmd_nandbcb.c | 221 ++++++++++++++++++--------------
>  1 file changed, 122 insertions(+), 99 deletions(-)
>
> diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
> index aae2cc82f3..fbe780ccda 100644
> --- a/arch/arm/mach-imx/cmd_nandbcb.c
> +++ b/arch/arm/mach-imx/cmd_nandbcb.c
> @@ -64,7 +64,8 @@ static u32 calc_chksum(void *buf, size_t size)
>         return ~chksum;
>  }
>
> -static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd)
> +static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd,
> +                    u32 fw1_start, u32 fw2_start, u32 fw_pages)
>  {
>         struct nand_chip *chip = mtd_to_nand(mtd);
>         struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> @@ -112,6 +113,11 @@ static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd)
>         fcb->disbbm = 0;
>         fcb->disbbm_search = 0;
>
> +       fcb->fw1_start = fw1_start; /* Firmware image starts on this sector */
> +       fcb->fw2_start = fw2_start; /* Secondary FW Image starting Sector */
> +       fcb->fw1_pages = fw_pages; /* Number of sectors in firmware image */
> +       fcb->fw2_pages = fw_pages; /* Number of sector in secondary FW image */
> +
>         fcb->checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
>  }
>
> @@ -135,6 +141,109 @@ static int dbbt_fill_data(struct mtd_info *mtd, void *buf, int num_blocks)
>         return n_bad_blocks;
>  }
>
> +static int write_fcb_dbbt(struct mtd_info *mtd, struct fcb_block *fcb,
> +                         struct dbbt_block *dbbt, void *dbbt_data_page,
> +                         loff_t off)
> +{
> +       void *fcb_raw_page = 0;
> +       int i, ret;
> +       size_t dummy;
> +
> +       /*
> +        * We prepare raw page only for i.MX6, for i.MX7 we
> +        * leverage BCH hw module instead
> +        */
> +       if (is_mx6()) {
> +               /* write fcb/dbbt */
> +               fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize,
> +                                      GFP_KERNEL);
> +               if (!fcb_raw_page) {
> +                       debug("failed to allocate fcb_raw_page\n");
> +                       ret = -ENOMEM;
> +                       return ret;
> +               }
> +
> +               memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
> +               encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page +
> +                                   12 + 512, 512);
> +               /*
> +                * Set the first and second byte of OOB data to 0xFF,
> +                * not 0x00. These bytes are used as the Manufacturers Bad
> +                * Block Marker (MBBM). Since the FCB is mostly written to
> +                * the first page in a block, a scan for
> +                * factory bad blocks will detect these blocks as bad, e.g.
> +                * when function nand_scan_bbt() is executed to build a new
> +                * bad block table.
> +                */
> +               memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
> +       }
> +       for (i = 0; i < 2; i++) {
> +               if (mtd_block_isbad(mtd, off)) {
> +                       printf("Block %d is bad, skipped\n", i);
> +                       continue;
> +               }
> +
> +               /*
> +                * User BCH ECC hardware module for i.MX7
> +                */
> +               if (is_mx7()) {
> +                       u32 off = i * mtd->erasesize;
> +                       size_t rwsize = sizeof(*fcb);
> +
> +                       printf("Writing %d bytes to 0x%x: ", rwsize, off);
> +
> +                       /* switch nand BCH to FCB compatible settings */
> +                       mxs_nand_mode_fcb(mtd);
> +                       ret = nand_write(mtd, off, &rwsize,
> +                                        (unsigned char *)fcb);
> +                       mxs_nand_mode_normal(mtd);
> +
> +                       printf("%s\n", ret ? "ERROR" : "OK");
> +               } else if (is_mx6()) {
> +                       /* raw write */
> +                       mtd_oob_ops_t ops = {
> +                               .datbuf = (u8 *)fcb_raw_page,
> +                               .oobbuf = ((u8 *)fcb_raw_page) +
> +                                         mtd->writesize,
> +                               .len = mtd->writesize,
> +                               .ooblen = mtd->oobsize,
> +                               .mode = MTD_OPS_RAW
> +                       };
> +
> +                       ret = mtd_write_oob(mtd, mtd->erasesize * i, &ops);
> +                       if (ret)
> +                               goto fcb_raw_page_err;
> +                       debug("NAND fcb write: 0x%x offset 0x%x written: %s\n",
> +                             mtd->erasesize * i, ops.len, ret ?
> +                             "ERROR" : "OK");
> +               }
> +
> +               ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize,
> +                               mtd->writesize, &dummy, (void *)dbbt);
> +               if (ret)
> +                       goto fcb_raw_page_err;
> +               debug("NAND dbbt write: 0x%x offset, 0x%x bytes written: %s\n",
> +                     mtd->erasesize * i + mtd->writesize, dummy,
> +                     ret ? "ERROR" : "OK");
> +
> +               /* dbbtpages == 0 if no bad blocks */
> +               if (dbbt->dbbtpages > 0) {
> +                       loff_t to = (mtd->erasesize * i + mtd->writesize * 5);
> +
> +                       ret = mtd_write(mtd, to, mtd->writesize, &dummy,
> +                                       dbbt_data_page);
> +                       if (ret)
> +                               goto fcb_raw_page_err;
> +               }
> +       }
> +
> +fcb_raw_page_err:
> +       if (is_mx6())
> +               kfree(fcb_raw_page);
> +
> +       return ret;
> +}
> +
>  static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
>                           size_t maxsize, const u_char *buf)
>  {
> @@ -142,12 +251,12 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
>         struct fcb_block *fcb;
>         struct dbbt_block *dbbt;
>         loff_t fw1_off;
> -       void *fwbuf, *fcb_raw_page, *dbbt_page, *dbbt_data_page;
> +       void *fwbuf, *dbbt_page, *dbbt_data_page;
> +       u32 fw1_start, fw1_pages;
>         int nr_blks, nr_blks_fcb, fw1_blk;
> -       size_t fwsize, dummy;
> -       int i, ret;
> +       size_t fwsize;
> +       int ret;
>
> -       fcb_raw_page = 0;
>         /* erase */
>         memset(&opts, 0, sizeof(opts));
>         opts.offset = off;
> @@ -209,9 +318,9 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
>                 goto fwbuf_err;
>         }
>
> -       fcb->fw1_start = (fw1_blk * mtd->erasesize) / mtd->writesize;
> -       fcb->fw1_pages = size / mtd->writesize + 1;
> -       fill_fcb(fcb, mtd);
> +       fw1_start = (fw1_blk * mtd->erasesize) / mtd->writesize;
> +       fw1_pages = size / mtd->writesize + 1;
> +       fill_fcb(fcb, mtd, fw1_start, 0, fw1_pages);
>
>         /* fill dbbt */
>         dbbt_page = kzalloc(mtd->writesize, GFP_KERNEL);
> @@ -238,97 +347,11 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
>         else if (ret > 0)
>                 dbbt->dbbtpages = 1;
>
> -       /*
> -        * We prepare raw page only for i.MX6, for i.MX7 we
> -        * leverage BCH hw module instead
> -        */
> -       if (is_mx6()) {
> -               /* write fcb/dbbt */
> -               fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize,
> -                                      GFP_KERNEL);
> -               if (!fcb_raw_page) {
> -                       debug("failed to allocate fcb_raw_page\n");
> -                       ret = -ENOMEM;
> -                       goto dbbt_data_page_err;
> -               }
> -
> -               memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
> -               encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page +
> -                                   12 + 512, 512);
> -               /*
> -                * Set the first and second byte of OOB data to 0xFF,
> -                * not 0x00. These bytes are used as the Manufacturers Bad
> -                * Block Marker (MBBM). Since the FCB is mostly written to
> -                * the first page in a block, a scan for
> -                * factory bad blocks will detect these blocks as bad, e.g.
> -                * when function nand_scan_bbt() is executed to build a new
> -                * bad block table.
> -                */
> -               memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
> -       }
> -       for (i = 0; i < nr_blks_fcb; i++) {
> -               if (mtd_block_isbad(mtd, off)) {
> -                       printf("Block %d is bad, skipped\n", i);
> -                       continue;
> -               }
> -
> -               /*
> -                * User BCH ECC hardware module for i.MX7
> -                */
> -               if (is_mx7()) {
> -                       u32 off = i * mtd->erasesize;
> -                       size_t rwsize = sizeof(*fcb);
> -
> -                       printf("Writing %d bytes to 0x%x: ", rwsize, off);
> -
> -                       /* switch nand BCH to FCB compatible settings */
> -                       mxs_nand_mode_fcb(mtd);
> -                       ret = nand_write(mtd, off, &rwsize,
> -                                        (unsigned char *)fcb);
> -                       mxs_nand_mode_normal(mtd);
> -
> -                       printf("%s\n", ret ? "ERROR" : "OK");
> -               } else if (is_mx6()) {
> -                       /* raw write */
> -                       mtd_oob_ops_t ops = {
> -                               .datbuf = (u8 *)fcb_raw_page,
> -                               .oobbuf = ((u8 *)fcb_raw_page) +
> -                                         mtd->writesize,
> -                               .len = mtd->writesize,
> -                               .ooblen = mtd->oobsize,
> -                               .mode = MTD_OPS_RAW
> -                       };
> -
> -                       ret = mtd_write_oob(mtd, mtd->erasesize * i, &ops);
> -                       if (ret)
> -                               goto fcb_raw_page_err;
> -                       debug("NAND fcb write: 0x%x offset 0x%x written: %s\n",
> -                             mtd->erasesize * i, ops.len, ret ?
> -                             "ERROR" : "OK");
> -               }
> -
> -               ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize,
> -                               mtd->writesize, &dummy, dbbt_page);
> -               if (ret)
> -                       goto fcb_raw_page_err;
> -               debug("NAND dbbt write: 0x%x offset, 0x%x bytes written: %s\n",
> -                     mtd->erasesize * i + mtd->writesize, dummy,
> -                     ret ? "ERROR" : "OK");
> -
> -               /* dbbtpages == 0 if no bad blocks */
> -               if (dbbt->dbbtpages > 0) {
> -                       loff_t to = (mtd->erasesize * i + mtd->writesize * 5);
> -
> -                       ret = mtd_write(mtd, to, mtd->writesize, &dummy,
> -                                       dbbt_data_page);
> -                       if (ret)
> -                               goto fcb_raw_page_err;
> -               }
> -       }
> +       /* write fcb and dbbt to nand */
> +       ret = write_fcb_dbbt(mtd, fcb, dbbt, dbbt_data_page, off);
> +       if (ret < 0)
> +               printf("failed to write FCB/DBBT\n");
>
> -fcb_raw_page_err:
> -       if (is_mx6())
> -               kfree(fcb_raw_page);
>  dbbt_data_page_err:
>         kfree(dbbt_data_page);
>  dbbt_page_err:
> @@ -355,7 +378,7 @@ static int do_nandbcb_update(int argc, char * const argv[])
>
>         dev = nand_curr_device;
>         if (dev < 0) {
> -               printf("failed to get nand_curr_device, run nand device");
> +               printf("failed to get nand_curr_device, run nand device\n");
>                 return CMD_RET_FAILURE;
>         }
>
> --
> 2.17.1
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot



-- 
Best regards
Oleksandr Suvorov

Toradex AG
Altsagenstrasse 5 | 6048 Horw/Luzern | Switzerland | T: +41 41 500
4800 (main line)

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

* [U-Boot] [PATCH v2 5/5] imx: nandbcb: add support for writing BCB only
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 5/5] imx: nandbcb: add support for writing BCB only Igor Opaniuk
@ 2019-10-23 11:28   ` Oleksandr Suvorov
  2019-10-23 18:32   ` Max Krummenacher
  1 sibling, 0 replies; 18+ messages in thread
From: Oleksandr Suvorov @ 2019-10-23 11:28 UTC (permalink / raw)
  To: u-boot

On Mon, Oct 21, 2019 at 4:41 PM Igor Opaniuk <igor.opaniuk@gmail.com> wrote:
>
> From: Igor Opaniuk <igor.opaniuk@toradex.com>
>
> Add subcommand for add writing BCB only, where we provide appropriate
> offsets for firmware1 and firmware2 and size.
>
> Example of usage:
> - nandbcb bcbonly 0x00180000 0x00080000 0x00200000
> Writing 1024 bytes to 0x0: randomizing
> OK
> Writing 1024 bytes to 0x20000: randomizing
> OK
>
> Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>

Reviewed-by: Oleksandr Suvorov <oleksandr.suvorov@toradex.com>

> ---
>
>  arch/arm/mach-imx/cmd_nandbcb.c | 92 ++++++++++++++++++++++++++++++++-
>  1 file changed, 91 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
> index fbe780ccda..d11e16cf83 100644
> --- a/arch/arm/mach-imx/cmd_nandbcb.c
> +++ b/arch/arm/mach-imx/cmd_nandbcb.c
> @@ -364,6 +364,88 @@ err:
>         return ret;
>  }
>
> +static int do_nandbcb_bcbonly(int argc, char * const argv[])
> +{
> +       struct fcb_block *fcb;
> +       struct dbbt_block *dbbt;
> +       u32 fw_len, fw1_off, fw2_off;
> +       struct mtd_info *mtd;
> +       void *dbbt_page, *dbbt_data_page;
> +       int dev, ret;
> +
> +       dev = nand_curr_device;
> +       if ((dev < 0) || (dev >= CONFIG_SYS_MAX_NAND_DEVICE) ||
> +           (!get_nand_dev_by_index(dev))) {
> +               puts("No devices available\n");
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       mtd = get_nand_dev_by_index(dev);
> +
> +       if (argc < 3)
> +               return CMD_RET_FAILURE;
> +
> +       fw_len = simple_strtoul(argv[1], NULL, 16);
> +       fw1_off = simple_strtoul(argv[2], NULL, 16);
> +
> +       if (argc > 3)
> +               fw2_off = simple_strtoul(argv[3], NULL, 16);
> +       else
> +               fw2_off = fw1_off;
> +
> +       /* fill fcb */
> +       fcb = kzalloc(sizeof(*fcb), GFP_KERNEL);
> +       if (!fcb) {
> +               debug("failed to allocate fcb\n");
> +               ret = -ENOMEM;
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       fill_fcb(fcb, mtd, fw1_off / mtd->writesize,
> +                fw2_off / mtd->writesize, fw_len / mtd->writesize);
> +
> +       /* fill dbbt */
> +       dbbt_page = kzalloc(mtd->writesize, GFP_KERNEL);
> +       if (!dbbt_page) {
> +               debug("failed to allocate dbbt_page\n");
> +               ret = -ENOMEM;
> +               goto fcb_err;
> +       }
> +
> +       dbbt_data_page = kzalloc(mtd->writesize, GFP_KERNEL);
> +       if (!dbbt_data_page) {
> +               debug("failed to allocate dbbt_data_page\n");
> +               ret = -ENOMEM;
> +               goto dbbt_page_err;
> +       }
> +
> +       dbbt = dbbt_page;
> +       dbbt->checksum = 0;
> +       dbbt->fingerprint = DBBT_FINGERPRINT2;
> +       dbbt->version = DBBT_VERSION_1;
> +       ret = dbbt_fill_data(mtd, dbbt_data_page, 0);
> +       if (ret < 0)
> +               goto dbbt_data_page_err;
> +       else if (ret > 0)
> +               dbbt->dbbtpages = 1;
> +
> +       /* write fcb and dbbt to nand */
> +       ret = write_fcb_dbbt(mtd, fcb, dbbt, dbbt_data_page, 0);
> +dbbt_data_page_err:
> +       kfree(dbbt_data_page);
> +dbbt_page_err:
> +       kfree(dbbt_page);
> +fcb_err:
> +       kfree(fcb);
> +
> +       if (ret < 0) {
> +               printf("failed to write FCB/DBBT\n");
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       return CMD_RET_SUCCESS;
> +}
> +
>  static int do_nandbcb_update(int argc, char * const argv[])
>  {
>         struct mtd_info *mtd;
> @@ -420,6 +502,11 @@ static int do_nandbcb(cmd_tbl_t *cmdtp, int flag, int argc,
>                 goto done;
>         }
>
> +       if (strcmp(cmd, "bcbonly") == 0) {
> +               ret = do_nandbcb_bcbonly(argc, argv);
> +               goto done;
> +       }
> +
>  done:
>         if (ret != -1)
>                 return ret;
> @@ -430,7 +517,10 @@ usage:
>  #ifdef CONFIG_SYS_LONGHELP
>  static char nandbcb_help_text[] =
>         "update addr off|partition len  - update 'len' bytes starting at\n"
> -       "       'off|part' to memory address 'addr', skipping  bad blocks";
> +       "       'off|part' to memory address 'addr', skipping  bad blocks\n"
> +       "bcbonly fw-size fw1-off [fw2-off] - write only BCB (FCB and DBBT)\n"
> +       "       where `fw-size` is fw sizes in bytes, `fw1-off` and\n"
> +       "       and `fw2-off` - firmware offsets                ";
>  #endif
>
>  U_BOOT_CMD(nandbcb, 5, 1, do_nandbcb,
> --
> 2.17.1
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot



-- 
Best regards
Oleksandr Suvorov

Toradex AG
Altsagenstrasse 5 | 6048 Horw/Luzern | Switzerland | T: +41 41 500
4800 (main line)

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

* [U-Boot] [PATCH v2 1/5] imx: gpmi: add defines for hw randominizer
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 1/5] imx: gpmi: add defines for hw randominizer Igor Opaniuk
  2019-10-23 11:21   ` Oleksandr Suvorov
@ 2019-10-23 17:51   ` Max Krummenacher
  1 sibling, 0 replies; 18+ messages in thread
From: Max Krummenacher @ 2019-10-23 17:51 UTC (permalink / raw)
  To: u-boot

On Mon, 2019-10-21 at 16:38 +0300, Igor Opaniuk wrote:
> From: Igor Opaniuk <igor.opaniuk@toradex.com>
> 
> Extend GPMI Integrated ECC Control Register Description, include
> additional defines for enabling randomizer function and providing
> proper randomizer type.
> 
> For additional details check i.MX7 APR, section
> 9.6.6.3 GPMI Integrated ECC Control Register Description
> (GPMI_ECCCTRLn)
> 
> Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>

Tested-by: Max Krummenacher <max.krummenacher@toradex.com>

> ---
> 
>  arch/arm/include/asm/mach-imx/regs-gpmi.h | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/arch/arm/include/asm/mach-imx/regs-gpmi.h b/arch/arm/include/asm/mach-imx/regs-gpmi.h
> index 80cb731724..33daa53c45 100644
> --- a/arch/arm/include/asm/mach-imx/regs-gpmi.h
> +++ b/arch/arm/include/asm/mach-imx/regs-gpmi.h
> @@ -70,6 +70,11 @@ struct mxs_gpmi_regs {
>  #define	GPMI_ECCCTRL_ECC_CMD_OFFSET			13
>  #define	GPMI_ECCCTRL_ECC_CMD_DECODE			(0x0 << 13)
>  #define	GPMI_ECCCTRL_ECC_CMD_ENCODE			(0x1 << 13)
> +#define	GPMI_ECCCTRL_RANDOMIZER_ENABLE			(1 << 11)
> +#define	GPMI_ECCCTRL_RANDOMIZER_TYPE0			0
> +#define	GPMI_ECCCTRL_RANDOMIZER_TYPE1			(1 << 9)
> +#define	GPMI_ECCCTRL_RANDOMIZER_TYPE2			(2 << 9)
> +
>  #define	GPMI_ECCCTRL_ENABLE_ECC				(1 << 12)
>  #define	GPMI_ECCCTRL_BUFFER_MASK_MASK			0x1ff
>  #define	GPMI_ECCCTRL_BUFFER_MASK_OFFSET			0

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

* [U-Boot] [PATCH v2 2/5] nand: mxs_nand: add API for switching different BCH layouts
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 2/5] nand: mxs_nand: add API for switching different BCH layouts Igor Opaniuk
  2019-10-23 11:23   ` Oleksandr Suvorov
@ 2019-10-23 17:53   ` Max Krummenacher
  1 sibling, 0 replies; 18+ messages in thread
From: Max Krummenacher @ 2019-10-23 17:53 UTC (permalink / raw)
  To: u-boot

On Mon, 2019-10-21 at 16:38 +0300, Igor Opaniuk wrote:
> From: Igor Opaniuk <igor.opaniuk@toradex.com>
> 
> On i.MX7 in a sake of reducing the disturbances caused by a neighboring
> cells in the FCB page in the NAND chip, a randomizer is enabled when
> reading the FCB page by ROM bootloader.
> 
> Add API for setting BCH to specific layout (and restoring it back) used by
> ROM bootloader to be able to burn it in a proper way to NAND using
> nandbcb command.
> 
> Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>
> Signed-off-by: Anti Sullin <anti.sullin@artecdesign.ee>

Tested-by: Max Krummenacher <max.krummenacher@toradex.com>

> ---
> 
>  drivers/mtd/nand/raw/mxs_nand.c | 116 ++++++++++++++++++++++++++++++++
>  include/mxs_nand.h              |  22 ++++++
>  2 files changed, 138 insertions(+)
> 
> diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
> index a41b9620d0..ad7b644886 100644
> --- a/drivers/mtd/nand/raw/mxs_nand.c
> +++ b/drivers/mtd/nand/raw/mxs_nand.c
> @@ -740,6 +740,19 @@ 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) {
> +		d->cmd.pio_words[2] |= GPMI_ECCCTRL_RANDOMIZER_ENABLE |
> +				       GPMI_ECCCTRL_RANDOMIZER_TYPE2;
> +		/*
> +		 * Write NAND page number needed to be randomized
> +		 * to GPMI_ECCCOUNT register.
> +		 *
> +		 * 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;
> +	}
> +
>  	mxs_dma_desc_append(channel, d);
>  
>  	/* Flush caches */
> @@ -1003,6 +1016,10 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
>  	uint32_t tmp;
>  	int ret;
>  
> +	nand_info->en_randomizer = 0;
> +	nand_info->oobsize = mtd->oobsize;
> +	nand_info->writesize = mtd->writesize;
> +
>  	ret = mxs_nand_set_geometry(mtd, geo);
>  	if (ret)
>  		return ret;
> @@ -1020,6 +1037,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
>  	tmp |= (geo->gf_len == 14 ? 1 : 0) <<
>  		BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
>  	writel(tmp, &bch_regs->hw_bch_flash0layout0);
> +	nand_info->bch_flash0layout0 = tmp;
>  
>  	tmp = (mtd->writesize + mtd->oobsize)
>  		<< BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
> @@ -1028,6 +1046,7 @@ int mxs_nand_setup_ecc(struct mtd_info *mtd)
>  	tmp |= (geo->gf_len == 14 ? 1 : 0) <<
>  		BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
>  	writel(tmp, &bch_regs->hw_bch_flash0layout1);
> +	nand_info->bch_flash0layout1 = tmp;
>  
>  	/* Set *all* chip selects to use layout 0 */
>  	writel(0, &bch_regs->hw_bch_layoutselect);
> @@ -1303,3 +1322,100 @@ err:
>  	free(nand_info);
>  }
>  #endif
> +
> +/*
> + * Read NAND layout for FCB block generation.
> + */
> +void mxs_nand_get_layout(struct mtd_info *mtd, struct mxs_nand_layout *l)
> +{
> +	struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
> +	u32 tmp;
> +
> +	tmp = readl(&bch_regs->hw_bch_flash0layout0);
> +	l->nblocks = (tmp & BCH_FLASHLAYOUT0_NBLOCKS_MASK) >>
> +			BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
> +	l->meta_size = (tmp & BCH_FLASHLAYOUT0_META_SIZE_MASK) >>
> +			BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
> +
> +	tmp = readl(&bch_regs->hw_bch_flash0layout1);
> +	l->data0_size = 4 * ((tmp & BCH_FLASHLAYOUT0_DATA0_SIZE_MASK) >>
> +			BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET);
> +	l->ecc0 = (tmp & BCH_FLASHLAYOUT0_ECC0_MASK) >>
> +			BCH_FLASHLAYOUT0_ECC0_OFFSET;
> +	l->datan_size = 4 * ((tmp & BCH_FLASHLAYOUT1_DATAN_SIZE_MASK) >>
> +			BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET);
> +	l->eccn = (tmp & BCH_FLASHLAYOUT1_ECCN_MASK) >>
> +			BCH_FLASHLAYOUT1_ECCN_OFFSET;
> +}
> +
> +/*
> + * Set BCH to specific layout used by ROM bootloader to read FCB.
> + */
> +void mxs_nand_mode_fcb(struct mtd_info *mtd)
> +{
> +	u32 tmp;
> +	struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
> +	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
> +
> +	nand_info->en_randomizer = 1;
> +
> +	mtd->writesize = 1024;
> +	mtd->oobsize = 1862 - 1024;
> +
> +	/* 8 ecc_chunks_*/
> +	tmp = 7	<< BCH_FLASHLAYOUT0_NBLOCKS_OFFSET;
> +	/* 32 bytes for metadata */
> +	tmp |= 32 << BCH_FLASHLAYOUT0_META_SIZE_OFFSET;
> +	/* using ECC62 level to be performed */
> +	tmp |= 0x1F << BCH_FLASHLAYOUT0_ECC0_OFFSET;
> +	/* 0x20 * 4 bytes of the data0 block */
> +	tmp |= 0x20 << BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET;
> +	tmp |= 0 << BCH_FLASHLAYOUT0_GF13_0_GF14_1_OFFSET;
> +	writel(tmp, &bch_regs->hw_bch_flash0layout0);
> +
> +	/* 1024 for data + 838 for OOB */
> +	tmp = 1862 << BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET;
> +	/* using ECC62 level to be performed */
> +	tmp |= 0x1F << BCH_FLASHLAYOUT1_ECCN_OFFSET;
> +	/* 0x20 * 4 bytes of the data0 block */
> +	tmp |= 0x20 << BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET;
> +	tmp |= 0 << BCH_FLASHLAYOUT1_GF13_0_GF14_1_OFFSET;
> +	writel(tmp, &bch_regs->hw_bch_flash0layout1);
> +}
> +
> +/*
> + * Restore BCH to normal settings.
> + */
> +void mxs_nand_mode_normal(struct mtd_info *mtd)
> +{
> +	struct mxs_bch_regs *bch_regs = (struct mxs_bch_regs *)MXS_BCH_BASE;
> +	struct nand_chip *nand = mtd_to_nand(mtd);
> +	struct mxs_nand_info *nand_info = nand_get_controller_data(nand);
> +
> +	nand_info->en_randomizer = 0;
> +
> +	mtd->writesize = nand_info->writesize;
> +	mtd->oobsize = nand_info->oobsize;
> +
> +	writel(nand_info->bch_flash0layout0, &bch_regs->hw_bch_flash0layout0);
> +	writel(nand_info->bch_flash0layout1, &bch_regs->hw_bch_flash0layout1);
> +}
> +
> +uint32_t mxs_nand_mark_byte_offset(struct mtd_info *mtd)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> +	struct bch_geometry *geo = &nand_info->bch_geometry;
> +
> +	return geo->block_mark_byte_offset;
> +}
> +
> +uint32_t mxs_nand_mark_bit_offset(struct mtd_info *mtd)
> +{
> +	struct nand_chip *chip = mtd_to_nand(mtd);
> +	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> +	struct bch_geometry *geo = &nand_info->bch_geometry;
> +
> +	return geo->block_mark_bit_offset;
> +}
> diff --git a/include/mxs_nand.h b/include/mxs_nand.h
> index 4bd65cded9..ada20483d0 100644
> --- a/include/mxs_nand.h
> +++ b/include/mxs_nand.h
> @@ -66,8 +66,30 @@ struct mxs_nand_info {
>  	/* DMA descriptors */
>  	struct mxs_dma_desc	**desc;
>  	uint32_t		desc_index;
> +
> +	/* Hardware BCH interface and randomizer */
> +	u32 en_randomizer;
> +	u32 writesize;
> +	u32 oobsize;
> +	u32 bch_flash0layout0;
> +	u32 bch_flash0layout1;
> +};
> +
> +struct mxs_nand_layout {
> +	u32 nblocks;
> +	u32 meta_size;
> +	u32 data0_size;
> +	u32 ecc0;
> +	u32 datan_size;
> +	u32 eccn;
>  };
>  
>  int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info);
>  int mxs_nand_init_spl(struct nand_chip *nand);
>  int mxs_nand_setup_ecc(struct mtd_info *mtd);
> +
> +void mxs_nand_mode_fcb(struct mtd_info *mtd);
> +void mxs_nand_mode_normal(struct mtd_info *mtd);
> +u32 mxs_nand_mark_byte_offset(struct mtd_info *mtd);
> +u32 mxs_nand_mark_bit_offset(struct mtd_info *mtd);
> +void mxs_nand_get_layout(struct mtd_info *mtd, struct mxs_nand_layout *l);

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

* [U-Boot] [PATCH v2 3/5] imx: nandbcb: add support for i.MX7
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 3/5] imx: nandbcb: add support for i.MX7 Igor Opaniuk
  2019-10-23 11:24   ` Oleksandr Suvorov
@ 2019-10-23 18:30   ` Max Krummenacher
  2019-11-03 13:55   ` Stefano Babic
  2 siblings, 0 replies; 18+ messages in thread
From: Max Krummenacher @ 2019-10-23 18:30 UTC (permalink / raw)
  To: u-boot

On Mon, 2019-10-21 at 16:38 +0300, Igor Opaniuk wrote:
> From: Igor Opaniuk <igor.opaniuk@toradex.com>
> 
> Add support for updating FCB/DBBT on i.MX7:
> - additional new fields in FCB structure
> - Leverage hardware BCH/randomizer for writing FCB
> 
> Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>
> ---
> 
>  arch/arm/include/asm/mach-imx/imx-nandbcb.h |  12 ++
>  arch/arm/mach-imx/Kconfig                   |   2 +-
>  arch/arm/mach-imx/cmd_nandbcb.c             | 129 +++++++++++++-------
>  3 files changed, 100 insertions(+), 43 deletions(-)
> 
> diff --git a/arch/arm/include/asm/mach-imx/imx-nandbcb.h b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
> index 033659a038..907e7ed8f9 100644
> --- a/arch/arm/include/asm/mach-imx/imx-nandbcb.h
> +++ b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
> @@ -106,6 +106,18 @@ struct fcb_block {
>  
>  	/* The swap position of main area in spare area */
>  	u32 spare_offset;
> +
> +	/* Actual for iMX7 only */
> +	u32 onfi_sync_enable;
> +	u32 onfi_sync_speed;
> +	u32 onfi_sync_nand_data;
> +	u32 reserved2[6];
> +	u32 disbbm_search;
> +	u32 disbbm_search_limit;
> +	u32 reserved3[15];
> +	u32 read_retry_enable;
> +	u32 reserved4[1];
> +	u32 fill_to_1024[183];
>  };
>  
>  #endif	/* _IMX_NAND_BCB_H_ */
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index b0b9d2c070..c22e8f51b4 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -81,7 +81,7 @@ config CMD_HDMIDETECT
>  config CMD_NANDBCB
>  	bool "i.MX6 NAND Boot Control Block(BCB) command"
>  	depends on NAND && CMD_MTDPARTS
> -	default y if ARCH_MX6 && NAND_MXS
> +	default y if (ARCH_MX6 && NAND_MXS) || (ARCH_MX7 && NAND_MXS)
>  	help
>  	  Unlike normal 'nand write/erase' commands, this command update
>  	  Boot Control Block(BCB) for i.MX6 platform NAND IP's.
> diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
> index 7811c61d22..aae2cc82f3 100644
> --- a/arch/arm/mach-imx/cmd_nandbcb.c
> +++ b/arch/arm/mach-imx/cmd_nandbcb.c
> @@ -16,6 +16,7 @@
>  #include <jffs2/jffs2.h>
>  #include <linux/mtd/mtd.h>
>  
> +#include <asm/arch/sys_proto.h>
>  #include <asm/mach-imx/imx-nandbcb.h>
>  #include <asm/mach-imx/imximage.cfg>
>  #include <mxs_nand.h>
> @@ -67,26 +68,36 @@ static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
>  	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> +	struct mxs_nand_layout l;
> +
> +	mxs_nand_get_layout(mtd, &l);
>  
>  	fcb->fingerprint = FCB_FINGERPRINT;
>  	fcb->version = FCB_VERSION_1;
> +
>  	fcb->pagesize = mtd->writesize;
>  	fcb->oob_pagesize = mtd->writesize + mtd->oobsize;
>  	fcb->sectors = mtd->erasesize / mtd->writesize;
>  
> -	/* Divide ECC strength by two and save the value into FCB structure. */
> -	fcb->ecc_level = nand_info->bch_geometry.ecc_strength >> 1;
> -
> -	fcb->ecc_type = fcb->ecc_level;
> +	fcb->meta_size = l.meta_size;
> +	fcb->nr_blocks = l.nblocks;
> +	fcb->ecc_nr = l.data0_size;
> +	fcb->ecc_level = l.ecc0;
> +	fcb->ecc_size = l.datan_size;
> +	fcb->ecc_type = l.eccn;
>  
>  	/* Also hardcoded in kobs-ng */
> -	fcb->ecc_nr = 0x00000200;
> -	fcb->ecc_size = 0x00000200;
> -	fcb->datasetup = 80;
> -	fcb->datahold = 60;
> -	fcb->addr_setup = 25;
> -	fcb->dsample_time = 6;
> -	fcb->meta_size = 10;
> +	if (is_mx6()) {
> +		fcb->datasetup = 80;
> +		fcb->datahold = 60;
> +		fcb->addr_setup = 25;
> +		fcb->dsample_time = 6;
> +	} else if (is_mx7()) {
> +		fcb->datasetup = 10;
> +		fcb->datahold = 7;
> +		fcb->addr_setup = 15;
> +		fcb->dsample_time = 6;
> +	}
>  
>  	/* DBBT search area starts at second page on first block */
>  	fcb->dbbt_start = 1;

The user space tool imx-kobs aligns this to the beginning of the NAND block
immediately following the last fcb instance. If we want to
hardcode I propose to set it to the page number of the first page of the block
immediately following the fcb. I.e. to 2 * (mtd->erasesize / mtd->writesize)

Note that the code which does write the dbbt also assumes a hardcoded '1' here,
so any change here requires a change also further below. I added a comment.

On a Colibri iMX6ULL/iMX7 we actually use page 1 for device information which
then conflicts with the dbbt. 


> @@ -98,6 +109,9 @@ static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd)
>  
>  	fcb->nr_blocks = mtd->writesize / fcb->ecc_nr - 1;
>  
> +	fcb->disbbm = 0;
> +	fcb->disbbm_search = 0;
> +
>  	fcb->checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
>  }
>  
> @@ -133,6 +147,7 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
>  	size_t fwsize, dummy;
>  	int i, ret;
>  
> +	fcb_raw_page = 0;
>  	/* erase */
>  	memset(&opts, 0, sizeof(opts));
>  	opts.offset = off;
> @@ -223,45 +238,74 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
>  	else if (ret > 0)
>  		dbbt->dbbtpages = 1;
>  
> -	/* write fcb/dbbt */
> -	fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
> -	if (!fcb_raw_page) {
> -		debug("failed to allocate fcb_raw_page\n");
> -		ret = -ENOMEM;
> -		goto dbbt_data_page_err;
> -	}
> -
> -	memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
> -	encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page + 12 + 512, 512);
>  	/*
> -	 * Set the first and second byte of OOB data to 0xFF, not 0x00. These
> -	 * bytes are used as the Manufacturers Bad Block Marker (MBBM). Since
> -	 * the FCB is mostly written to the first page in a block, a scan for
> -	 * factory bad blocks will detect these blocks as bad, e.g. when
> -	 * function nand_scan_bbt() is executed to build a new bad block table.
> +	 * We prepare raw page only for i.MX6, for i.MX7 we
> +	 * leverage BCH hw module instead
>  	 */
> -	memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
> +	if (is_mx6()) {
> +		/* write fcb/dbbt */
> +		fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize,
> +				       GFP_KERNEL);
> +		if (!fcb_raw_page) {
> +			debug("failed to allocate fcb_raw_page\n");
> +			ret = -ENOMEM;
> +			goto dbbt_data_page_err;
> +		}
>  
> +		memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
> +		encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page +
> +				    12 + 512, 512);
> +		/*
> +		 * Set the first and second byte of OOB data to 0xFF,
> +		 * not 0x00. These bytes are used as the Manufacturers Bad
> +		 * Block Marker (MBBM). Since the FCB is mostly written to
> +		 * the first page in a block, a scan for
> +		 * factory bad blocks will detect these blocks as bad, e.g.
> +		 * when function nand_scan_bbt() is executed to build a new
> +		 * bad block table.
> +		 */
> +		memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
> +	}
>  	for (i = 0; i < nr_blks_fcb; i++) {
>  		if (mtd_block_isbad(mtd, off)) {
>  			printf("Block %d is bad, skipped\n", i);
>  			continue;
>  		}
>  
> -		/* raw write */
> -		mtd_oob_ops_t ops = {
> -			.datbuf = (u8 *)fcb_raw_page,
> -			.oobbuf = ((u8 *)fcb_raw_page) + mtd->writesize,
> -			.len = mtd->writesize,
> -			.ooblen = mtd->oobsize,
> -			.mode = MTD_OPS_RAW
> -		};
> -
> -		ret = mtd_write_oob(mtd, mtd->erasesize * i, &ops);
> -		if (ret)
> -			goto fcb_raw_page_err;
> -		debug("NAND fcb write: 0x%x offset, 0x%x bytes written: %s\n",
> -		      mtd->erasesize * i, ops.len, ret ? "ERROR" : "OK");
> +		/*
> +		 * User BCH ECC hardware module for i.MX7
> +		 */
> +		if (is_mx7()) {
> +			u32 off = i * mtd->erasesize;
> +			size_t rwsize = sizeof(*fcb);
> +
> +			printf("Writing %d bytes to 0x%x: ", rwsize, off);
> +
> +			/* switch nand BCH to FCB compatible settings */
> +			mxs_nand_mode_fcb(mtd);
> +			ret = nand_write(mtd, off, &rwsize,
> +					 (unsigned char *)fcb);
> +			mxs_nand_mode_normal(mtd);
> +
> +			printf("%s\n", ret ? "ERROR" : "OK");
> +		} else if (is_mx6()) {
> +			/* raw write */
> +			mtd_oob_ops_t ops = {
> +				.datbuf = (u8 *)fcb_raw_page,
> +				.oobbuf = ((u8 *)fcb_raw_page) +
> +					  mtd->writesize,
> +				.len = mtd->writesize,
> +				.ooblen = mtd->oobsize,
> +				.mode = MTD_OPS_RAW
> +			};
> +
> +			ret = mtd_write_oob(mtd, mtd->erasesize * i, &ops);
> +			if (ret)
> +				goto fcb_raw_page_err;
> +			debug("NAND fcb write: 0x%x offset 0x%x written: %s\n",
> +			      mtd->erasesize * i, ops.len, ret ?
> +			      "ERROR" : "OK");
> +		}
>  
>  		ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize,

This assumes a hardcoded 'fcb->dbbt_start = 1;' but it should be start at 
'mtd->erasesize * i + mtd->writesize * fcb->dbbt_start'

With the hardcoded dbbt_start fixed:

Tested-by: Max Krummenacher <max.krummenacher@toradex.com>

Regards
Max

>  				mtd->writesize, &dummy, dbbt_page);
> @@ -283,7 +327,8 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
>  	}
>  
>  fcb_raw_page_err:
> -	kfree(fcb_raw_page);
> +	if (is_mx6())
> +		kfree(fcb_raw_page);
>  dbbt_data_page_err:
>  	kfree(dbbt_data_page);
>  dbbt_page_err:

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

* [U-Boot] [PATCH v2 4/5] imx: nandbcb: refactor update function
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 4/5] imx: nandbcb: refactor update function Igor Opaniuk
  2019-10-23 11:26   ` Oleksandr Suvorov
@ 2019-10-23 18:31   ` Max Krummenacher
  1 sibling, 0 replies; 18+ messages in thread
From: Max Krummenacher @ 2019-10-23 18:31 UTC (permalink / raw)
  To: u-boot

On Mon, 2019-10-21 at 16:38 +0300, Igor Opaniuk wrote:
> From: Igor Opaniuk <igor.opaniuk@toradex.com>
> 
> Move code for writing FCB/DBBT pages to a separate function
> 
> Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>

Tested-by: Max Krummenacher <max.krummenacher@toradex.com>

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

* [U-Boot] [PATCH v2 5/5] imx: nandbcb: add support for writing BCB only
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 5/5] imx: nandbcb: add support for writing BCB only Igor Opaniuk
  2019-10-23 11:28   ` Oleksandr Suvorov
@ 2019-10-23 18:32   ` Max Krummenacher
  1 sibling, 0 replies; 18+ messages in thread
From: Max Krummenacher @ 2019-10-23 18:32 UTC (permalink / raw)
  To: u-boot

On Mon, 2019-10-21 at 16:38 +0300, Igor Opaniuk wrote:
> From: Igor Opaniuk <igor.opaniuk@toradex.com>
> 
> Add subcommand for add writing BCB only, where we provide appropriate
> offsets for firmware1 and firmware2 and size.
> 
> Example of usage:
> - nandbcb bcbonly 0x00180000 0x00080000 0x00200000
> Writing 1024 bytes to 0x0: randomizing
> OK
> Writing 1024 bytes to 0x20000: randomizing
> OK
> 
> Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>

Tested-by: Max Krummenacher <max.krummenacher@toradex.com>

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

* [U-Boot] [PATCH v2 3/5] imx: nandbcb: add support for i.MX7
  2019-10-21 13:38 ` [U-Boot] [PATCH v2 3/5] imx: nandbcb: add support for i.MX7 Igor Opaniuk
  2019-10-23 11:24   ` Oleksandr Suvorov
  2019-10-23 18:30   ` Max Krummenacher
@ 2019-11-03 13:55   ` Stefano Babic
  2019-11-03 15:51     ` Igor Opaniuk
  2 siblings, 1 reply; 18+ messages in thread
From: Stefano Babic @ 2019-11-03 13:55 UTC (permalink / raw)
  To: u-boot

Hi Igor,

On 21/10/19 15:38, Igor Opaniuk wrote:
> From: Igor Opaniuk <igor.opaniuk@toradex.com>
> 
> Add support for updating FCB/DBBT on i.MX7:
> - additional new fields in FCB structure
> - Leverage hardware BCH/randomizer for writing FCB
> 
> Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>
> ---
> 

Patch conflicts with the one for i.MX6UL, that I have currently applied
(you see it on -next branch). Could you please rebase on it and resend ?
Thanks !

Regards,
Stefano

>  arch/arm/include/asm/mach-imx/imx-nandbcb.h |  12 ++
>  arch/arm/mach-imx/Kconfig                   |   2 +-
>  arch/arm/mach-imx/cmd_nandbcb.c             | 129 +++++++++++++-------
>  3 files changed, 100 insertions(+), 43 deletions(-)
> 
> diff --git a/arch/arm/include/asm/mach-imx/imx-nandbcb.h b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
> index 033659a038..907e7ed8f9 100644
> --- a/arch/arm/include/asm/mach-imx/imx-nandbcb.h
> +++ b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
> @@ -106,6 +106,18 @@ struct fcb_block {
>  
>  	/* The swap position of main area in spare area */
>  	u32 spare_offset;
> +
> +	/* Actual for iMX7 only */
> +	u32 onfi_sync_enable;
> +	u32 onfi_sync_speed;
> +	u32 onfi_sync_nand_data;
> +	u32 reserved2[6];
> +	u32 disbbm_search;
> +	u32 disbbm_search_limit;
> +	u32 reserved3[15];
> +	u32 read_retry_enable;
> +	u32 reserved4[1];
> +	u32 fill_to_1024[183];
>  };
>  
>  #endif	/* _IMX_NAND_BCB_H_ */
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index b0b9d2c070..c22e8f51b4 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -81,7 +81,7 @@ config CMD_HDMIDETECT
>  config CMD_NANDBCB
>  	bool "i.MX6 NAND Boot Control Block(BCB) command"
>  	depends on NAND && CMD_MTDPARTS
> -	default y if ARCH_MX6 && NAND_MXS
> +	default y if (ARCH_MX6 && NAND_MXS) || (ARCH_MX7 && NAND_MXS)
>  	help
>  	  Unlike normal 'nand write/erase' commands, this command update
>  	  Boot Control Block(BCB) for i.MX6 platform NAND IP's.
> diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
> index 7811c61d22..aae2cc82f3 100644
> --- a/arch/arm/mach-imx/cmd_nandbcb.c
> +++ b/arch/arm/mach-imx/cmd_nandbcb.c
> @@ -16,6 +16,7 @@
>  #include <jffs2/jffs2.h>
>  #include <linux/mtd/mtd.h>
>  
> +#include <asm/arch/sys_proto.h>
>  #include <asm/mach-imx/imx-nandbcb.h>
>  #include <asm/mach-imx/imximage.cfg>
>  #include <mxs_nand.h>
> @@ -67,26 +68,36 @@ static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd)
>  {
>  	struct nand_chip *chip = mtd_to_nand(mtd);
>  	struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> +	struct mxs_nand_layout l;
> +
> +	mxs_nand_get_layout(mtd, &l);
>  
>  	fcb->fingerprint = FCB_FINGERPRINT;
>  	fcb->version = FCB_VERSION_1;
> +
>  	fcb->pagesize = mtd->writesize;
>  	fcb->oob_pagesize = mtd->writesize + mtd->oobsize;
>  	fcb->sectors = mtd->erasesize / mtd->writesize;
>  
> -	/* Divide ECC strength by two and save the value into FCB structure. */
> -	fcb->ecc_level = nand_info->bch_geometry.ecc_strength >> 1;
> -
> -	fcb->ecc_type = fcb->ecc_level;
> +	fcb->meta_size = l.meta_size;
> +	fcb->nr_blocks = l.nblocks;
> +	fcb->ecc_nr = l.data0_size;
> +	fcb->ecc_level = l.ecc0;
> +	fcb->ecc_size = l.datan_size;
> +	fcb->ecc_type = l.eccn;
>  
>  	/* Also hardcoded in kobs-ng */
> -	fcb->ecc_nr = 0x00000200;
> -	fcb->ecc_size = 0x00000200;
> -	fcb->datasetup = 80;
> -	fcb->datahold = 60;
> -	fcb->addr_setup = 25;
> -	fcb->dsample_time = 6;
> -	fcb->meta_size = 10;
> +	if (is_mx6()) {
> +		fcb->datasetup = 80;
> +		fcb->datahold = 60;
> +		fcb->addr_setup = 25;
> +		fcb->dsample_time = 6;
> +	} else if (is_mx7()) {
> +		fcb->datasetup = 10;
> +		fcb->datahold = 7;
> +		fcb->addr_setup = 15;
> +		fcb->dsample_time = 6;
> +	}
>  
>  	/* DBBT search area starts at second page on first block */
>  	fcb->dbbt_start = 1;
> @@ -98,6 +109,9 @@ static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd)
>  
>  	fcb->nr_blocks = mtd->writesize / fcb->ecc_nr - 1;
>  
> +	fcb->disbbm = 0;
> +	fcb->disbbm_search = 0;
> +
>  	fcb->checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
>  }
>  
> @@ -133,6 +147,7 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
>  	size_t fwsize, dummy;
>  	int i, ret;
>  
> +	fcb_raw_page = 0;
>  	/* erase */
>  	memset(&opts, 0, sizeof(opts));
>  	opts.offset = off;
> @@ -223,45 +238,74 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
>  	else if (ret > 0)
>  		dbbt->dbbtpages = 1;
>  
> -	/* write fcb/dbbt */
> -	fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
> -	if (!fcb_raw_page) {
> -		debug("failed to allocate fcb_raw_page\n");
> -		ret = -ENOMEM;
> -		goto dbbt_data_page_err;
> -	}
> -
> -	memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
> -	encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page + 12 + 512, 512);
>  	/*
> -	 * Set the first and second byte of OOB data to 0xFF, not 0x00. These
> -	 * bytes are used as the Manufacturers Bad Block Marker (MBBM). Since
> -	 * the FCB is mostly written to the first page in a block, a scan for
> -	 * factory bad blocks will detect these blocks as bad, e.g. when
> -	 * function nand_scan_bbt() is executed to build a new bad block table.
> +	 * We prepare raw page only for i.MX6, for i.MX7 we
> +	 * leverage BCH hw module instead
>  	 */
> -	memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
> +	if (is_mx6()) {
> +		/* write fcb/dbbt */
> +		fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize,
> +				       GFP_KERNEL);
> +		if (!fcb_raw_page) {
> +			debug("failed to allocate fcb_raw_page\n");
> +			ret = -ENOMEM;
> +			goto dbbt_data_page_err;
> +		}
>  
> +		memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
> +		encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page +
> +				    12 + 512, 512);
> +		/*
> +		 * Set the first and second byte of OOB data to 0xFF,
> +		 * not 0x00. These bytes are used as the Manufacturers Bad
> +		 * Block Marker (MBBM). Since the FCB is mostly written to
> +		 * the first page in a block, a scan for
> +		 * factory bad blocks will detect these blocks as bad, e.g.
> +		 * when function nand_scan_bbt() is executed to build a new
> +		 * bad block table.
> +		 */
> +		memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
> +	}
>  	for (i = 0; i < nr_blks_fcb; i++) {
>  		if (mtd_block_isbad(mtd, off)) {
>  			printf("Block %d is bad, skipped\n", i);
>  			continue;
>  		}
>  
> -		/* raw write */
> -		mtd_oob_ops_t ops = {
> -			.datbuf = (u8 *)fcb_raw_page,
> -			.oobbuf = ((u8 *)fcb_raw_page) + mtd->writesize,
> -			.len = mtd->writesize,
> -			.ooblen = mtd->oobsize,
> -			.mode = MTD_OPS_RAW
> -		};
> -
> -		ret = mtd_write_oob(mtd, mtd->erasesize * i, &ops);
> -		if (ret)
> -			goto fcb_raw_page_err;
> -		debug("NAND fcb write: 0x%x offset, 0x%x bytes written: %s\n",
> -		      mtd->erasesize * i, ops.len, ret ? "ERROR" : "OK");
> +		/*
> +		 * User BCH ECC hardware module for i.MX7
> +		 */
> +		if (is_mx7()) {
> +			u32 off = i * mtd->erasesize;
> +			size_t rwsize = sizeof(*fcb);
> +
> +			printf("Writing %d bytes to 0x%x: ", rwsize, off);
> +
> +			/* switch nand BCH to FCB compatible settings */
> +			mxs_nand_mode_fcb(mtd);
> +			ret = nand_write(mtd, off, &rwsize,
> +					 (unsigned char *)fcb);
> +			mxs_nand_mode_normal(mtd);
> +
> +			printf("%s\n", ret ? "ERROR" : "OK");
> +		} else if (is_mx6()) {
> +			/* raw write */
> +			mtd_oob_ops_t ops = {
> +				.datbuf = (u8 *)fcb_raw_page,
> +				.oobbuf = ((u8 *)fcb_raw_page) +
> +					  mtd->writesize,
> +				.len = mtd->writesize,
> +				.ooblen = mtd->oobsize,
> +				.mode = MTD_OPS_RAW
> +			};
> +
> +			ret = mtd_write_oob(mtd, mtd->erasesize * i, &ops);
> +			if (ret)
> +				goto fcb_raw_page_err;
> +			debug("NAND fcb write: 0x%x offset 0x%x written: %s\n",
> +			      mtd->erasesize * i, ops.len, ret ?
> +			      "ERROR" : "OK");
> +		}
>  
>  		ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize,
>  				mtd->writesize, &dummy, dbbt_page);
> @@ -283,7 +327,8 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
>  	}
>  
>  fcb_raw_page_err:
> -	kfree(fcb_raw_page);
> +	if (is_mx6())
> +		kfree(fcb_raw_page);
>  dbbt_data_page_err:
>  	kfree(dbbt_data_page);
>  dbbt_page_err:
> 


-- 
=====================================================================
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] 18+ messages in thread

* [U-Boot] [PATCH v2 3/5] imx: nandbcb: add support for i.MX7
  2019-11-03 13:55   ` Stefano Babic
@ 2019-11-03 15:51     ` Igor Opaniuk
  0 siblings, 0 replies; 18+ messages in thread
From: Igor Opaniuk @ 2019-11-03 15:51 UTC (permalink / raw)
  To: u-boot

HI Stefano,

On Sun, Nov 3, 2019 at 2:55 PM Stefano Babic <sbabic@denx.de> wrote:
>
> Hi Igor,
>
> On 21/10/19 15:38, Igor Opaniuk wrote:
> > From: Igor Opaniuk <igor.opaniuk@toradex.com>
> >
> > Add support for updating FCB/DBBT on i.MX7:
> > - additional new fields in FCB structure
> > - Leverage hardware BCH/randomizer for writing FCB
> >
> > Signed-off-by: Igor Opaniuk <igor.opaniuk@toradex.com>
> > ---
> >
>
> Patch conflicts with the one for i.MX6UL, that I have currently applied
> (you see it on -next branch). Could you please rebase on it and resend ?
> Thanks !
Done, please check v3 here [1]
Thanks

[1] https://patchwork.ozlabs.org/project/uboot/list/?series=140330

>
> Regards,
> Stefano
>
> >  arch/arm/include/asm/mach-imx/imx-nandbcb.h |  12 ++
> >  arch/arm/mach-imx/Kconfig                   |   2 +-
> >  arch/arm/mach-imx/cmd_nandbcb.c             | 129 +++++++++++++-------
> >  3 files changed, 100 insertions(+), 43 deletions(-)
> >
> > diff --git a/arch/arm/include/asm/mach-imx/imx-nandbcb.h b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
> > index 033659a038..907e7ed8f9 100644
> > --- a/arch/arm/include/asm/mach-imx/imx-nandbcb.h
> > +++ b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
> > @@ -106,6 +106,18 @@ struct fcb_block {
> >
> >       /* The swap position of main area in spare area */
> >       u32 spare_offset;
> > +
> > +     /* Actual for iMX7 only */
> > +     u32 onfi_sync_enable;
> > +     u32 onfi_sync_speed;
> > +     u32 onfi_sync_nand_data;
> > +     u32 reserved2[6];
> > +     u32 disbbm_search;
> > +     u32 disbbm_search_limit;
> > +     u32 reserved3[15];
> > +     u32 read_retry_enable;
> > +     u32 reserved4[1];
> > +     u32 fill_to_1024[183];
> >  };
> >
> >  #endif       /* _IMX_NAND_BCB_H_ */
> > diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> > index b0b9d2c070..c22e8f51b4 100644
> > --- a/arch/arm/mach-imx/Kconfig
> > +++ b/arch/arm/mach-imx/Kconfig
> > @@ -81,7 +81,7 @@ config CMD_HDMIDETECT
> >  config CMD_NANDBCB
> >       bool "i.MX6 NAND Boot Control Block(BCB) command"
> >       depends on NAND && CMD_MTDPARTS
> > -     default y if ARCH_MX6 && NAND_MXS
> > +     default y if (ARCH_MX6 && NAND_MXS) || (ARCH_MX7 && NAND_MXS)
> >       help
> >         Unlike normal 'nand write/erase' commands, this command update
> >         Boot Control Block(BCB) for i.MX6 platform NAND IP's.
> > diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
> > index 7811c61d22..aae2cc82f3 100644
> > --- a/arch/arm/mach-imx/cmd_nandbcb.c
> > +++ b/arch/arm/mach-imx/cmd_nandbcb.c
> > @@ -16,6 +16,7 @@
> >  #include <jffs2/jffs2.h>
> >  #include <linux/mtd/mtd.h>
> >
> > +#include <asm/arch/sys_proto.h>
> >  #include <asm/mach-imx/imx-nandbcb.h>
> >  #include <asm/mach-imx/imximage.cfg>
> >  #include <mxs_nand.h>
> > @@ -67,26 +68,36 @@ static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd)
> >  {
> >       struct nand_chip *chip = mtd_to_nand(mtd);
> >       struct mxs_nand_info *nand_info = nand_get_controller_data(chip);
> > +     struct mxs_nand_layout l;
> > +
> > +     mxs_nand_get_layout(mtd, &l);
> >
> >       fcb->fingerprint = FCB_FINGERPRINT;
> >       fcb->version = FCB_VERSION_1;
> > +
> >       fcb->pagesize = mtd->writesize;
> >       fcb->oob_pagesize = mtd->writesize + mtd->oobsize;
> >       fcb->sectors = mtd->erasesize / mtd->writesize;
> >
> > -     /* Divide ECC strength by two and save the value into FCB structure. */
> > -     fcb->ecc_level = nand_info->bch_geometry.ecc_strength >> 1;
> > -
> > -     fcb->ecc_type = fcb->ecc_level;
> > +     fcb->meta_size = l.meta_size;
> > +     fcb->nr_blocks = l.nblocks;
> > +     fcb->ecc_nr = l.data0_size;
> > +     fcb->ecc_level = l.ecc0;
> > +     fcb->ecc_size = l.datan_size;
> > +     fcb->ecc_type = l.eccn;
> >
> >       /* Also hardcoded in kobs-ng */
> > -     fcb->ecc_nr = 0x00000200;
> > -     fcb->ecc_size = 0x00000200;
> > -     fcb->datasetup = 80;
> > -     fcb->datahold = 60;
> > -     fcb->addr_setup = 25;
> > -     fcb->dsample_time = 6;
> > -     fcb->meta_size = 10;
> > +     if (is_mx6()) {
> > +             fcb->datasetup = 80;
> > +             fcb->datahold = 60;
> > +             fcb->addr_setup = 25;
> > +             fcb->dsample_time = 6;
> > +     } else if (is_mx7()) {
> > +             fcb->datasetup = 10;
> > +             fcb->datahold = 7;
> > +             fcb->addr_setup = 15;
> > +             fcb->dsample_time = 6;
> > +     }
> >
> >       /* DBBT search area starts at second page on first block */
> >       fcb->dbbt_start = 1;
> > @@ -98,6 +109,9 @@ static void fill_fcb(struct fcb_block *fcb, struct mtd_info *mtd)
> >
> >       fcb->nr_blocks = mtd->writesize / fcb->ecc_nr - 1;
> >
> > +     fcb->disbbm = 0;
> > +     fcb->disbbm_search = 0;
> > +
> >       fcb->checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
> >  }
> >
> > @@ -133,6 +147,7 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
> >       size_t fwsize, dummy;
> >       int i, ret;
> >
> > +     fcb_raw_page = 0;
> >       /* erase */
> >       memset(&opts, 0, sizeof(opts));
> >       opts.offset = off;
> > @@ -223,45 +238,74 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
> >       else if (ret > 0)
> >               dbbt->dbbtpages = 1;
> >
> > -     /* write fcb/dbbt */
> > -     fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL);
> > -     if (!fcb_raw_page) {
> > -             debug("failed to allocate fcb_raw_page\n");
> > -             ret = -ENOMEM;
> > -             goto dbbt_data_page_err;
> > -     }
> > -
> > -     memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
> > -     encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page + 12 + 512, 512);
> >       /*
> > -      * Set the first and second byte of OOB data to 0xFF, not 0x00. These
> > -      * bytes are used as the Manufacturers Bad Block Marker (MBBM). Since
> > -      * the FCB is mostly written to the first page in a block, a scan for
> > -      * factory bad blocks will detect these blocks as bad, e.g. when
> > -      * function nand_scan_bbt() is executed to build a new bad block table.
> > +      * We prepare raw page only for i.MX6, for i.MX7 we
> > +      * leverage BCH hw module instead
> >        */
> > -     memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
> > +     if (is_mx6()) {
> > +             /* write fcb/dbbt */
> > +             fcb_raw_page = kzalloc(mtd->writesize + mtd->oobsize,
> > +                                    GFP_KERNEL);
> > +             if (!fcb_raw_page) {
> > +                     debug("failed to allocate fcb_raw_page\n");
> > +                     ret = -ENOMEM;
> > +                     goto dbbt_data_page_err;
> > +             }
> >
> > +             memcpy(fcb_raw_page + 12, fcb, sizeof(struct fcb_block));
> > +             encode_hamming_13_8(fcb_raw_page + 12, fcb_raw_page +
> > +                                 12 + 512, 512);
> > +             /*
> > +              * Set the first and second byte of OOB data to 0xFF,
> > +              * not 0x00. These bytes are used as the Manufacturers Bad
> > +              * Block Marker (MBBM). Since the FCB is mostly written to
> > +              * the first page in a block, a scan for
> > +              * factory bad blocks will detect these blocks as bad, e.g.
> > +              * when function nand_scan_bbt() is executed to build a new
> > +              * bad block table.
> > +              */
> > +             memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
> > +     }
> >       for (i = 0; i < nr_blks_fcb; i++) {
> >               if (mtd_block_isbad(mtd, off)) {
> >                       printf("Block %d is bad, skipped\n", i);
> >                       continue;
> >               }
> >
> > -             /* raw write */
> > -             mtd_oob_ops_t ops = {
> > -                     .datbuf = (u8 *)fcb_raw_page,
> > -                     .oobbuf = ((u8 *)fcb_raw_page) + mtd->writesize,
> > -                     .len = mtd->writesize,
> > -                     .ooblen = mtd->oobsize,
> > -                     .mode = MTD_OPS_RAW
> > -             };
> > -
> > -             ret = mtd_write_oob(mtd, mtd->erasesize * i, &ops);
> > -             if (ret)
> > -                     goto fcb_raw_page_err;
> > -             debug("NAND fcb write: 0x%x offset, 0x%x bytes written: %s\n",
> > -                   mtd->erasesize * i, ops.len, ret ? "ERROR" : "OK");
> > +             /*
> > +              * User BCH ECC hardware module for i.MX7
> > +              */
> > +             if (is_mx7()) {
> > +                     u32 off = i * mtd->erasesize;
> > +                     size_t rwsize = sizeof(*fcb);
> > +
> > +                     printf("Writing %d bytes to 0x%x: ", rwsize, off);
> > +
> > +                     /* switch nand BCH to FCB compatible settings */
> > +                     mxs_nand_mode_fcb(mtd);
> > +                     ret = nand_write(mtd, off, &rwsize,
> > +                                      (unsigned char *)fcb);
> > +                     mxs_nand_mode_normal(mtd);
> > +
> > +                     printf("%s\n", ret ? "ERROR" : "OK");
> > +             } else if (is_mx6()) {
> > +                     /* raw write */
> > +                     mtd_oob_ops_t ops = {
> > +                             .datbuf = (u8 *)fcb_raw_page,
> > +                             .oobbuf = ((u8 *)fcb_raw_page) +
> > +                                       mtd->writesize,
> > +                             .len = mtd->writesize,
> > +                             .ooblen = mtd->oobsize,
> > +                             .mode = MTD_OPS_RAW
> > +                     };
> > +
> > +                     ret = mtd_write_oob(mtd, mtd->erasesize * i, &ops);
> > +                     if (ret)
> > +                             goto fcb_raw_page_err;
> > +                     debug("NAND fcb write: 0x%x offset 0x%x written: %s\n",
> > +                           mtd->erasesize * i, ops.len, ret ?
> > +                           "ERROR" : "OK");
> > +             }
> >
> >               ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize,
> >                               mtd->writesize, &dummy, dbbt_page);
> > @@ -283,7 +327,8 @@ static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
> >       }
> >
> >  fcb_raw_page_err:
> > -     kfree(fcb_raw_page);
> > +     if (is_mx6())
> > +             kfree(fcb_raw_page);
> >  dbbt_data_page_err:
> >       kfree(dbbt_data_page);
> >  dbbt_page_err:
> >
>
>
> --
> =====================================================================
> 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
> =====================================================================



-- 
Best regards - Freundliche Grüsse - Meilleures salutations

Igor Opaniuk

mailto: igor.opaniuk at gmail.com
skype: igor.opanyuk
+380 (93) 836 40 67
http://ua.linkedin.com/in/iopaniuk

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

end of thread, other threads:[~2019-11-03 15:51 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-21 13:38 [U-Boot] [PATCH v2 0/5] imx: nandbcb: support for i.MX7 and bcb only updates Igor Opaniuk
2019-10-21 13:38 ` [U-Boot] [PATCH v2 1/5] imx: gpmi: add defines for hw randominizer Igor Opaniuk
2019-10-23 11:21   ` Oleksandr Suvorov
2019-10-23 17:51   ` Max Krummenacher
2019-10-21 13:38 ` [U-Boot] [PATCH v2 2/5] nand: mxs_nand: add API for switching different BCH layouts Igor Opaniuk
2019-10-23 11:23   ` Oleksandr Suvorov
2019-10-23 17:53   ` Max Krummenacher
2019-10-21 13:38 ` [U-Boot] [PATCH v2 3/5] imx: nandbcb: add support for i.MX7 Igor Opaniuk
2019-10-23 11:24   ` Oleksandr Suvorov
2019-10-23 18:30   ` Max Krummenacher
2019-11-03 13:55   ` Stefano Babic
2019-11-03 15:51     ` Igor Opaniuk
2019-10-21 13:38 ` [U-Boot] [PATCH v2 4/5] imx: nandbcb: refactor update function Igor Opaniuk
2019-10-23 11:26   ` Oleksandr Suvorov
2019-10-23 18:31   ` Max Krummenacher
2019-10-21 13:38 ` [U-Boot] [PATCH v2 5/5] imx: nandbcb: add support for writing BCB only Igor Opaniuk
2019-10-23 11:28   ` Oleksandr Suvorov
2019-10-23 18:32   ` Max Krummenacher

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.