public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v6 1/3] i.MX6: nand: add nandbcb command for imx
@ 2019-06-14  7:35 Shyam Saini
  2019-06-14  7:35 ` [U-Boot] [PATCH 2/3] configs: icorem6: Enable nandbcb command Shyam Saini
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Shyam Saini @ 2019-06-14  7:35 UTC (permalink / raw)
  To: u-boot

Writing/updating boot image in nand device is not
straight forward in i.MX6 platform and it requires
boot control block(BCB) to be configured.

It becomes difficult to use uboot 'nand' command to
write BCB since it requires platform specific attributes
need to be taken care of.

It is even difficult to use existing msx-nand.c driver by
incorporating BCB attributes like mxs_dma_desc does
because it requires change in mtd and nand command.

So, cmd_nandbcb implemented in arch/arm/mach-imx

BCB contains two data structures, Firmware Configuration Block(FCB)
and Discovered Bad Block Table(DBBT). FCB has nand timings,
DBBT search area, page address of firmware.

On summary, nandbcb update will
- erase the entire partition
- create BCB by creating 2 FCB/DBBT block followed by
  1 FW block based on partition size and erasesize.
- fill FCB/DBBT structures
- write FW/SPL on FW1
- write FCB/DBBT in first 2 blocks

for nand boot, up on reset bootrom look for FCB structure in
first block's if FCB found the nand timings are loaded for
further reads. once FCB read done, DTTB will load and finally
firmware will be loaded which is boot image.

Refer section "NAND Boot" from doc/imx/common/imx6.txt for more usage
information.

Reviewed-by: Stefano Babic <sbabic@denx.de>
Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
Signed-off-by: Sergey Kubushyn <ksi@koi8.net>
Signed-off-by: Shyam Saini <shyam.saini@amarulasolutions.com>
---
Changes for v6:
- Consolidate v5 patch 1 and patch 2 into one single patch
- Make separate docs patch out of v5 patch 1

Changes for v5:
- Move mxs_nand.h file from drivers/mtd/nand/raw/ to include/ directory so
  that it can be used by both drivers/ and arch/
- Fix command steps output in docs 

Changes for v4:
- Remove obselete apis and use bch_geometry structure for calculating
  ecc level, bad block start bit and bad block byte
- Write firmware only once
- Shorten variable names
- Update commit message
- Update docs as per current patch
- Fix checkpatch warnings

Changes for v3:
- Fixed multi-line comments
- Better error handling for failed allocations

Changes for v2:
- Fixed commit message notes
- Updated proper commit message
- Update doc/README.imx6 with NAND boot details
- Fixed long length variable names.
- Fixed Gigantic variable name.
- NULL checks for kzalloc
- Move Kconfig option in separate patch
- Fixed checkpatch warninigs

 arch/arm/include/asm/mach-imx/imx-nandbcb.h  | 111 ++++++++
 arch/arm/mach-imx/Kconfig                    |  11 +
 arch/arm/mach-imx/Makefile                   |   1 +
 arch/arm/mach-imx/cmd_nandbcb.c              | 369 +++++++++++++++++++++++++++
 drivers/mtd/nand/raw/mxs_nand.c              |   2 +-
 drivers/mtd/nand/raw/mxs_nand_dt.c           |   2 +-
 drivers/mtd/nand/raw/mxs_nand_spl.c          |   2 +-
 {drivers/mtd/nand/raw => include}/mxs_nand.h |   0
 8 files changed, 495 insertions(+), 3 deletions(-)
 create mode 100644 arch/arm/include/asm/mach-imx/imx-nandbcb.h
 create mode 100644 arch/arm/mach-imx/cmd_nandbcb.c
 rename {drivers/mtd/nand/raw => include}/mxs_nand.h (100%)

diff --git a/arch/arm/include/asm/mach-imx/imx-nandbcb.h b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
new file mode 100644
index 0000000000..033659a038
--- /dev/null
+++ b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _IMX_NAND_BCB_H_
+#define _IMX_NAND_BCB_H_
+
+#define FCB_FINGERPRINT		0x20424346      /* 'FCB' */
+#define FCB_VERSION_1		0x01000000
+
+#define DBBT_FINGERPRINT2	0x54424244	/* 'DBBT' */
+#define DBBT_VERSION_1		0x01000000
+
+struct dbbt_block {
+	u32 checksum;	/* reserved on i.MX6 */
+	u32 fingerprint;
+	u32 version;
+	u32 numberbb;	/* reserved on i.MX6 */
+	u32 dbbtpages;
+};
+
+struct fcb_block {
+	u32 checksum;		/* First fingerprint in first byte */
+	u32 fingerprint;	/* 2nd fingerprint at byte 4 */
+	u32 version;		/* 3rd fingerprint at byte 8 */
+	u8 datasetup;
+	u8 datahold;
+	u8 addr_setup;
+	u8 dsample_time;
+
+	/* These are for application use only and not for ROM. */
+	u8 nandtiming;
+	u8 rea;
+	u8 rloh;
+	u8 rhoh;
+	u32 pagesize;		/* 2048 for 2K pages, 4096 for 4K pages */
+	u32 oob_pagesize;	/* 2112 for 2K pages, 4314 for 4K pages */
+	u32 sectors;		/* Number of 2K sections per block */
+	u32 nr_nand;		/* Total Number of NANDs - not used by ROM */
+	u32 nr_die;		/* Number of separate chips in this NAND */
+	u32 celltype;		/* MLC or SLC */
+	u32 ecc_type;		/* Type of ECC, can be one of BCH-0-20 */
+	u32 ecc_nr;		/* Number of bytes for Block0 - BCH */
+
+	/* Block size in bytes for all blocks other than Block0 - BCH */
+	u32 ecc_size;
+	u32 ecc_level;		/* Ecc level for Block 0 - BCH */
+	u32 meta_size;		/* Metadata size - BCH */
+	/* Number of blocks per page for ROM use - BCH */
+	u32 nr_blocks;
+	u32 ecc_type_sdk;	/* Type of ECC, can be one of BCH-0-20 */
+	u32 ecc_nr_sdk;		/* Number of bytes for Block0 - BCH */
+	/* Block size in bytes for all blocks other than Block0 - BCH */
+	u32 ecc_size_sdk;
+	u32 ecc_level_sdk;	/* Ecc level for Block 0 - BCH */
+	/* Number of blocks per page for SDK use - BCH */
+	u32 nr_blocks_sdk;
+	u32 meta_size_sdk;	/* Metadata size - BCH */
+	u32 erase_th;		/* To set into BCH_MODE register */
+
+	/*
+	 * 0: normal boot
+	 * 1: to load patch starting next to FCB
+	 */
+	u32 bootpatch;
+	u32 patch_size;	/* Size of patch in sectors */
+	u32 fw1_start;	/* Firmware image starts on this sector */
+	u32 fw2_start;	/* Secondary FW Image starting Sector */
+	u32 fw1_pages;	/* Number of sectors in firmware image */
+	u32 fw2_pages;	/* Number of sector in secondary FW image */
+	u32 dbbt_start; /* Page address where dbbt search area begins */
+
+	/*
+	 * Byte in page data that have manufacturer marked bad block marker,
+	 * this will be swapped with metadata[0] to complete page data.
+	 */
+	u32 bb_byte;
+
+	/*
+	 * For BCH ECC sizes other than 8 and 16 the bad block marker does not
+	 * start at 0th bit of bb_byte. This field is used to get to
+	 * the start bit of bad block marker byte with in bb_byte
+	 */
+	u32 bb_start_bit;
+
+	/*
+	 * FCB value that gives byte offset for
+	 * bad block marker on physical NAND page
+	 */
+	u32 phy_offset;
+	u32 bchtype;
+
+	u32 readlatency;
+	u32 predelay;
+	u32 cedelay;
+	u32 postdelay;
+	u32 cmdaddpause;
+	u32 datapause;
+	u32 tmspeed;
+	u32 busytimeout;
+
+	/* the flag to enable (1)/disable(0) bi swap */
+	u32 disbbm;
+
+	/* The swap position of main area in spare area */
+	u32 spare_offset;
+};
+
+#endif	/* _IMX_NAND_BCB_H_ */
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index ec09ef240f..5dd286f9a7 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -71,6 +71,17 @@ config CMD_HDMIDETECT
 	  This enables the 'hdmidet' command which detects if an HDMI monitor
 	  is connected.
 
+config CMD_NANDBCB
+	bool "i.MX6 NAND Boot Control Block(BCB) command"
+	depends on NAND && CMD_MTDPARTS
+	default y if ARCH_MX6 && NAND_MXS
+	help
+	  Unlike normal 'nand write/erase' commands, this command update
+	  Boot Control Block(BCB) for i.MX6 platform NAND IP's.
+
+	  This is similar to kobs-ng, which is used in Linux as separate
+	  rootfs package.
+
 config NXP_BOARD_REVISION
 	bool "Read NXP board revision from fuses"
 	depends on ARCH_MX6 || ARCH_MX7
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index c46984994a..96f0b89fd1 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -59,6 +59,7 @@ ifneq ($(CONFIG_SPL_BUILD),y)
 obj-$(CONFIG_CMD_BMODE) += cmd_bmode.o
 obj-$(CONFIG_CMD_HDMIDETECT) += cmd_hdmidet.o
 obj-$(CONFIG_CMD_DEKBLOB) += cmd_dek.o
+obj-$(CONFIG_CMD_NANDBCB) += cmd_nandbcb.o
 endif
 
 PLUGIN = board/$(BOARDDIR)/plugin
diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
new file mode 100644
index 0000000000..065b814b2e
--- /dev/null
+++ b/arch/arm/mach-imx/cmd_nandbcb.c
@@ -0,0 +1,369 @@
+/*
+ * i.MX6 nand boot control block(bcb).
+ *
+ * Based on the common/imx-bbu-nand-fcb.c from barebox and imx kobs-ng
+ *
+ * Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com>
+ * Copyright (C) 2016 Sergey Kubushyn <ksi@koi8.net>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <nand.h>
+
+#include <asm/io.h>
+#include <jffs2/jffs2.h>
+#include <linux/mtd/mtd.h>
+
+#include <asm/mach-imx/imx-nandbcb.h>
+#include <asm/mach-imx/imximage.cfg>
+#include <mxs_nand.h>
+#include <linux/mtd/mtd.h>
+#include <nand.h>
+
+#define BF_VAL(v, bf)		(((v) & bf##_MASK) >> bf##_OFFSET)
+#define GETBIT(v, n)		(((v) >> (n)) & 0x1)
+
+static u8 calculate_parity_13_8(u8 d)
+{
+	u8 p = 0;
+
+	p |= (GETBIT(d, 6) ^ GETBIT(d, 5) ^ GETBIT(d, 3) ^ GETBIT(d, 2)) << 0;
+	p |= (GETBIT(d, 7) ^ GETBIT(d, 5) ^ GETBIT(d, 4) ^ GETBIT(d, 2) ^
+	      GETBIT(d, 1)) << 1;
+	p |= (GETBIT(d, 7) ^ GETBIT(d, 6) ^ GETBIT(d, 5) ^ GETBIT(d, 1) ^
+	      GETBIT(d, 0)) << 2;
+	p |= (GETBIT(d, 7) ^ GETBIT(d, 4) ^ GETBIT(d, 3) ^ GETBIT(d, 0)) << 3;
+	p |= (GETBIT(d, 6) ^ GETBIT(d, 4) ^ GETBIT(d, 3) ^ GETBIT(d, 2) ^
+	      GETBIT(d, 1) ^ GETBIT(d, 0)) << 4;
+
+	return p;
+}
+
+static void encode_hamming_13_8(void *_src, void *_ecc, size_t size)
+{
+	int i;
+	u8 *src = _src;
+	u8 *ecc = _ecc;
+
+	for (i = 0; i < size; i++)
+		ecc[i] = calculate_parity_13_8(src[i]);
+}
+
+static u32 calc_chksum(void *buf, size_t size)
+{
+	u32 chksum = 0;
+	u8 *bp = buf;
+	size_t i;
+
+	for (i = 0; i < size; i++)
+		chksum += bp[i];
+
+	return ~chksum;
+}
+
+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);
+
+	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;
+
+	/* 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;
+
+	/* DBBT search area starts at second page on first block */
+	fcb->dbbt_start = 1;
+
+	fcb->bb_byte = nand_info->bch_geometry.block_mark_byte_offset;
+	fcb->bb_start_bit = nand_info->bch_geometry.block_mark_bit_offset;
+
+	fcb->phy_offset = mtd->writesize;
+
+	fcb->nr_blocks = mtd->writesize / fcb->ecc_nr - 1;
+
+	fcb->checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
+}
+
+static int dbbt_fill_data(struct mtd_info *mtd, void *buf, int num_blocks)
+{
+	int n, n_bad_blocks = 0;
+	u32 *bb = buf + 0x8;
+	u32 *n_bad_blocksp = buf + 0x4;
+
+	for (n = 0; n < num_blocks; n++) {
+		loff_t offset = n * mtd->erasesize;
+			if (mtd_block_isbad(mtd, offset)) {
+				n_bad_blocks++;
+				*bb = n;
+				bb++;
+		}
+	}
+
+	*n_bad_blocksp = n_bad_blocks;
+
+	return n_bad_blocks;
+}
+
+static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
+			  size_t maxsize, const u_char *buf)
+{
+	nand_erase_options_t opts;
+	struct fcb_block *fcb;
+	struct dbbt_block *dbbt;
+	loff_t fw1_off;
+	void *fwbuf, *fcb_raw_page, *dbbt_page, *dbbt_data_page;
+	int nr_blks, nr_blks_fcb, fw1_blk;
+	size_t fwsize, dummy;
+	int i, ret;
+
+	/* erase */
+	memset(&opts, 0, sizeof(opts));
+	opts.offset = off;
+	opts.length = maxsize - 1;
+	ret = nand_erase_opts(mtd, &opts);
+	if (ret) {
+		printf("%s: erase failed (ret = %d)\n", __func__, ret);
+		return ret;
+	}
+
+	/*
+	 * Reference documentation from i.MX6DQRM section 8.5.2.2
+	 *
+	 * Nand Boot Control Block(BCB) contains two data structures,
+	 * - Firmware Configuration Block(FCB)
+	 * - Discovered Bad Block Table(DBBT)
+	 *
+	 * FCB contains,
+	 * - nand timings
+	 * - DBBT search page address,
+	 * - start page address of primary firmware
+	 * - start page address of secondary firmware
+	 *
+	 * setup fcb:
+	 * - number of blocks = mtd partition size / mtd erasesize
+	 * - two firmware blocks, primary and secondary
+	 * - first 4 block for FCB/DBBT
+	 * - rest split in half for primary and secondary firmware
+	 * - same firmware will write two times
+	 */
+	nr_blks_fcb = 2;
+	nr_blks = maxsize / mtd->erasesize;
+	fw1_blk = nr_blks_fcb;
+
+	/* write fw */
+	fwsize = ALIGN(size + FLASH_OFFSET_STANDARD + mtd->writesize,
+		       mtd->writesize);
+	fwbuf = kzalloc(fwsize, GFP_KERNEL);
+	if (!fwbuf) {
+		debug("failed to allocate fwbuf\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	memcpy(fwbuf + FLASH_OFFSET_STANDARD, buf, size);
+	fw1_off = fw1_blk * mtd->erasesize;
+	ret = nand_write_skip_bad(mtd, fw1_off, &fwsize, NULL, maxsize,
+				  (u_char *)fwbuf, WITH_WR_VERIFY);
+	printf("NAND fw write: 0x%llx offset, 0x%x bytes written: %s\n",
+	       fw1_off, fwsize, ret ? "ERROR" : "OK");
+	if (ret)
+		goto fwbuf_err;
+
+	/* fill fcb */
+	fcb = kzalloc(sizeof(*fcb), GFP_KERNEL);
+	if (!fcb) {
+		debug("failed to allocate fcb\n");
+		ret = -ENOMEM;
+		goto fwbuf_err;
+	}
+
+	fcb->fw1_start = (fw1_blk * mtd->erasesize) / mtd->writesize;
+	fcb->fw1_pages = size / mtd->writesize + 1;
+	fill_fcb(fcb, mtd);
+
+	/* 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, nr_blks);
+	if (ret < 0)
+		goto dbbt_data_page_err;
+	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.
+	 */
+	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");
+
+		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;
+		}
+	}
+
+fcb_raw_page_err:
+	kfree(fcb_raw_page);
+dbbt_data_page_err:
+	kfree(dbbt_data_page);
+dbbt_page_err:
+	kfree(dbbt_page);
+fcb_err:
+	kfree(fcb);
+fwbuf_err:
+	kfree(fwbuf);
+err:
+	return ret;
+}
+
+static int do_nandbcb_update(int argc, char * const argv[])
+{
+	struct mtd_info *mtd;
+	loff_t addr, offset, size, maxsize;
+	char *endp;
+	u_char *buf;
+	int dev;
+	int ret;
+
+	if (argc != 4)
+		return CMD_RET_USAGE;
+
+	dev = nand_curr_device;
+	if (dev < 0) {
+		printf("failed to get nand_curr_device, run nand device");
+		return CMD_RET_FAILURE;
+	}
+
+	addr = simple_strtoul(argv[1], &endp, 16);
+	if (*argv[1] == 0 || *endp != 0)
+		return CMD_RET_FAILURE;
+
+	mtd = get_nand_dev_by_index(dev);
+	if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &offset, &size,
+			     &maxsize, MTD_DEV_TYPE_NAND, mtd->size))
+		return CMD_RET_FAILURE;
+
+	buf = map_physmem(addr, size, MAP_WRBACK);
+	if (!buf) {
+		puts("failed to map physical memory\n");
+		return CMD_RET_FAILURE;
+	}
+
+	ret = nandbcb_update(mtd, offset, size, maxsize, buf);
+
+	return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
+}
+
+static int do_nandbcb(cmd_tbl_t *cmdtp, int flag, int argc,
+		      char * const argv[])
+{
+	const char *cmd;
+	int ret = 0;
+
+	if (argc < 5)
+		goto usage;
+
+	cmd = argv[1];
+	--argc;
+	++argv;
+
+	if (strcmp(cmd, "update") == 0) {
+		ret = do_nandbcb_update(argc, argv);
+		goto done;
+	}
+
+done:
+	if (ret != -1)
+		return ret;
+usage:
+	return CMD_RET_USAGE;
+}
+
+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";
+
+U_BOOT_CMD(nandbcb, 5, 1, do_nandbcb,
+	   "i.MX6 Nand BCB",
+	   nandbcb_help_text
+);
diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
index b93d77a395..a41b9620d0 100644
--- a/drivers/mtd/nand/raw/mxs_nand.c
+++ b/drivers/mtd/nand/raw/mxs_nand.c
@@ -25,7 +25,7 @@
 #include <asm/mach-imx/regs-bch.h>
 #include <asm/mach-imx/regs-gpmi.h>
 #include <asm/arch/sys_proto.h>
-#include "mxs_nand.h"
+#include <mxs_nand.h>
 
 #define	MXS_NAND_DMA_DESCRIPTOR_COUNT		4
 
diff --git a/drivers/mtd/nand/raw/mxs_nand_dt.c b/drivers/mtd/nand/raw/mxs_nand_dt.c
index 44dec5dedf..8ad7d618c6 100644
--- a/drivers/mtd/nand/raw/mxs_nand_dt.c
+++ b/drivers/mtd/nand/raw/mxs_nand_dt.c
@@ -15,7 +15,7 @@
 #include <linux/ioport.h>
 #include <linux/printk.h>
 
-#include "mxs_nand.h"
+#include <mxs_nand.h>
 
 struct mxs_nand_dt_data {
 	unsigned int max_ecc_strength_supported;
diff --git a/drivers/mtd/nand/raw/mxs_nand_spl.c b/drivers/mtd/nand/raw/mxs_nand_spl.c
index ee7d9cb957..975a91a37d 100644
--- a/drivers/mtd/nand/raw/mxs_nand_spl.c
+++ b/drivers/mtd/nand/raw/mxs_nand_spl.c
@@ -6,7 +6,7 @@
 #include <common.h>
 #include <nand.h>
 #include <malloc.h>
-#include "mxs_nand.h"
+#include <mxs_nand.h>
 
 static struct mtd_info *mtd;
 static struct nand_chip nand_chip;
diff --git a/drivers/mtd/nand/raw/mxs_nand.h b/include/mxs_nand.h
similarity index 100%
rename from drivers/mtd/nand/raw/mxs_nand.h
rename to include/mxs_nand.h
-- 
2.11.0

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

* [U-Boot] [PATCH 2/3] configs: icorem6: Enable nandbcb command
  2019-06-14  7:35 [U-Boot] [PATCH v6 1/3] i.MX6: nand: add nandbcb command for imx Shyam Saini
@ 2019-06-14  7:35 ` Shyam Saini
  2019-06-14  7:35 ` [U-Boot] [PATCH 3/3] doc: imx: Add documentation for " Shyam Saini
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ messages in thread
From: Shyam Saini @ 2019-06-14  7:35 UTC (permalink / raw)
  To: u-boot

This also enables mtd configs which are required by nandbcb command.

This command would be used to configure boot control block(BCB) while
writing spl image on nand device.

Signed-off-by: Shyam Saini <shyam.saini@amarulasolutions.com>
---
 configs/imx6qdl_icore_mmc_defconfig | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/configs/imx6qdl_icore_mmc_defconfig b/configs/imx6qdl_icore_mmc_defconfig
index b65979967a..620d49f954 100644
--- a/configs/imx6qdl_icore_mmc_defconfig
+++ b/configs/imx6qdl_icore_mmc_defconfig
@@ -15,6 +15,7 @@ CONFIG_DEBUG_UART_BASE=0x021f0000
 CONFIG_DEBUG_UART_CLOCK=24000000
 CONFIG_SPL_LIBDISK_SUPPORT=y
 # CONFIG_CMD_BMODE is not set
+CONFIG_CMD_NANDBCB=y
 CONFIG_DEBUG_UART=y
 CONFIG_FIT=y
 CONFIG_FIT_SIGNATURE=y
@@ -58,6 +59,9 @@ CONFIG_SYS_I2C_MXC=y
 CONFIG_FSL_ESDHC=y
 CONFIG_NAND=y
 CONFIG_NAND_MXS=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_MTDIDS_DEFAULT="nand0=gpmi-nand"
+CONFIG_MTDPARTS_DEFAULT="mtdparts=gpmi-nand:2m(spl),2m(uboot),1m(env),8m(kernel),1m(dtb),-(rootfs)"
 CONFIG_PHYLIB=y
 CONFIG_PHY_SMSC=y
 CONFIG_FEC_MXC=y
-- 
2.11.0

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

* [U-Boot] [PATCH 3/3] doc: imx: Add documentation for nandbcb command
  2019-06-14  7:35 [U-Boot] [PATCH v6 1/3] i.MX6: nand: add nandbcb command for imx Shyam Saini
  2019-06-14  7:35 ` [U-Boot] [PATCH 2/3] configs: icorem6: Enable nandbcb command Shyam Saini
@ 2019-06-14  7:35 ` Shyam Saini
  2019-06-14  8:37   ` Lukasz Majewski
  2019-07-20  8:46   ` sbabic at denx.de
  2019-06-14  9:17 ` [U-Boot] [PATCH v6 1/3] i.MX6: nand: add nandbcb command for imx Igor Opaniuk
  2019-07-20  8:47 ` sbabic at denx.de
  3 siblings, 2 replies; 13+ messages in thread
From: Shyam Saini @ 2019-06-14  7:35 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Shyam Saini <shyam.saini@amarulasolutions.com>
---
 doc/imx/common/imx6.txt | 74 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)

diff --git a/doc/imx/common/imx6.txt b/doc/imx/common/imx6.txt
index eab88353f6..0b5061128c 100644
--- a/doc/imx/common/imx6.txt
+++ b/doc/imx/common/imx6.txt
@@ -88,3 +88,77 @@ Reading bank 4:
 
 Word 0x00000002: 9f027772 00000004
 
+NAND Boot on i.MX6 with SPL support
+--------------------------------------
+
+Writing/updating boot image in nand device is not straight forward in
+i.MX6 platform and it requires boot control block(BCB) to be configured.
+
+BCB contains two data structures, Firmware Configuration Block(FCB) and
+Discovered Bad Block Table(DBBT). FCB has nand timings, DBBT search area,
+and firmware. See IMX6DQRM Section 8.5.2.2
+for more information.
+
+We can't use 'nand write' command to write SPL/firmware image directly
+like other platforms does. So we need special setup to write BCB block
+as per IMX6QDL reference manual 'nandbcb update' command do that job.
+
+for nand boot, up on reset bootrom look for FCB structure in
+first block's if FCB found the nand timings are loaded for
+further reads. once FCB read done, DTTB will be loaded and
+finally firmware will be loaded which is boot image.
+
+cmd_nandbcb will create FCB these structures
+by taking mtd partition as an example.
+- initial code will erase entire partition
+- followed by FCB setup, like first 2 blocks for FCB/DBBT write,
+  and next block for FW1/SPL
+- write firmware at FW1 block and
+- finally write fcb/dttb in first 2 block.
+
+Typical NAND BCB layout:
+=======================
+
+   no.of blocks = partition size / erasesize
+   no.of fcb/dbbt blocks = 2
+   FW1 offset = no.of fcb/dbbt
+
+block  0          1          2
+        -------------------------------
+       |FCB/DBBT 0|FCB/DBBT 1|  FW 1  |
+       --------------------------------
+
+On summary, nandbcb update will
+- erase the entire partition
+- create BCB by creating 2 FCB/BDDT block followed by
+  1 FW blocks based on partition size and erasesize.
+- fill FCB/DBBT structures
+- write FW/SPL in FW1
+- write FCB/DBBT in first 2 blocks
+
+step-1: write SPL
+
+icorem6qdl> ext4load mmc 0:1 $loadaddr SPL
+39936 bytes read in 10 ms (3.8 MiB/s)
+
+icorem6qdl> nandbcb update $loadaddr spl $filesize
+device 0 offset 0x0, size 0x9c00
+Erasing at 0x1c0000 -- 100% complete.
+NAND fw write: 0x80000 offset, 0xb000 bytes written: OK
+
+step-2: write u-boot-dtb.img
+
+icorem6qdl> nand erase.part uboot
+
+NAND erase.part: device 0 offset 0x200000, size 0x200000
+Erasing at 0x3c0000 -- 100% complete.
+OK
+
+icorem6qdl> ext4load mmc 0:1 $loadaddr u-boot-dtb.img
+589094 bytes read in 37 ms (15.2 MiB/s)
+
+icorem6qdl> nand write ${loadaddr} uboot ${filesize}
+
+NAND write: device 0 offset 0x200000, size 0x8fd26
+ 589094 bytes written: OK
+icorem6qdl>
-- 
2.11.0

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

* [U-Boot] [PATCH 3/3] doc: imx: Add documentation for nandbcb command
  2019-06-14  7:35 ` [U-Boot] [PATCH 3/3] doc: imx: Add documentation for " Shyam Saini
@ 2019-06-14  8:37   ` Lukasz Majewski
  2019-06-18  7:57     ` Shyam Saini
  2019-07-20  8:46   ` sbabic at denx.de
  1 sibling, 1 reply; 13+ messages in thread
From: Lukasz Majewski @ 2019-06-14  8:37 UTC (permalink / raw)
  To: u-boot

Hi Shyam,

> Signed-off-by: Shyam Saini <shyam.saini@amarulasolutions.com>
> ---
>  doc/imx/common/imx6.txt | 74
> +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74
> insertions(+)
> 
> diff --git a/doc/imx/common/imx6.txt b/doc/imx/common/imx6.txt
> index eab88353f6..0b5061128c 100644
> --- a/doc/imx/common/imx6.txt
> +++ b/doc/imx/common/imx6.txt
> @@ -88,3 +88,77 @@ Reading bank 4:
>  
>  Word 0x00000002: 9f027772 00000004
>  
> +NAND Boot on i.MX6 with SPL support
> +--------------------------------------
> +
> +Writing/updating boot image in nand device is not straight forward in
> +i.MX6 platform and it requires boot control block(BCB) to be
> configured. +
> +BCB contains two data structures, Firmware Configuration Block(FCB)
> and +Discovered Bad Block Table(DBBT). FCB has nand timings, DBBT
> search area, +and firmware. See IMX6DQRM Section 8.5.2.2
> +for more information.
> +
> +We can't use 'nand write' command to write SPL/firmware image
> directly +like other platforms does. So we need special setup to
> write BCB block +as per IMX6QDL reference manual 'nandbcb update'
> command do that job. +
> +for nand boot, up on reset bootrom look for FCB structure in
> +first block's if FCB found the nand timings are loaded for
> +further reads. once FCB read done, DTTB will be loaded and
> +finally firmware will be loaded which is boot image.
> +
> +cmd_nandbcb will create FCB these structures
> +by taking mtd partition as an example.

I think that the above sentence has a wrong order. Could you rewrite it?

> +- initial code will erase entire partition
> +- followed by FCB setup, like first 2 blocks for FCB/DBBT write,
> +  and next block for FW1/SPL
> +- write firmware at FW1 block and
> +- finally write fcb/dttb in first 2 block.
> +
> +Typical NAND BCB layout:
> +=======================
> +
> +   no.of blocks = partition size / erasesize
> +   no.of fcb/dbbt blocks = 2
> +   FW1 offset = no.of fcb/dbbt
> +
> +block  0          1          2
> +        -------------------------------
> +       |FCB/DBBT 0|FCB/DBBT 1|  FW 1  |
> +       --------------------------------
> +
> +On summary, nandbcb update will
> +- erase the entire partition
> +- create BCB by creating 2 FCB/BDDT block followed by
> +  1 FW blocks based on partition size and erasesize.
> +- fill FCB/DBBT structures
> +- write FW/SPL in FW1
> +- write FCB/DBBT in first 2 blocks
> +
> +step-1: write SPL
> +
> +icorem6qdl> ext4load mmc 0:1 $loadaddr SPL  
> +39936 bytes read in 10 ms (3.8 MiB/s)
> +
> +icorem6qdl> nandbcb update $loadaddr spl $filesize  
> +device 0 offset 0x0, size 0x9c00
> +Erasing at 0x1c0000 -- 100% complete.
> +NAND fw write: 0x80000 offset, 0xb000 bytes written: OK
> +
> +step-2: write u-boot-dtb.img
> +
> +icorem6qdl> nand erase.part uboot  
> +
> +NAND erase.part: device 0 offset 0x200000, size 0x200000
> +Erasing at 0x3c0000 -- 100% complete.
> +OK
> +
> +icorem6qdl> ext4load mmc 0:1 $loadaddr u-boot-dtb.img  
> +589094 bytes read in 37 ms (15.2 MiB/s)
> +
> +icorem6qdl> nand write ${loadaddr} uboot ${filesize}  
> +
> +NAND write: device 0 offset 0x200000, size 0x8fd26
> + 589094 bytes written: OK
> +icorem6qdl>  

Would it be possible to provide nandbcb show command (I guess that I
can dump it with plain nand read)?

It would present the FCB/DBBT structure. Do you think it is
needed/feasible ?

Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma at denx.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20190614/747c9ecd/attachment.sig>

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

* [U-Boot] [PATCH v6 1/3] i.MX6: nand: add nandbcb command for imx
  2019-06-14  7:35 [U-Boot] [PATCH v6 1/3] i.MX6: nand: add nandbcb command for imx Shyam Saini
  2019-06-14  7:35 ` [U-Boot] [PATCH 2/3] configs: icorem6: Enable nandbcb command Shyam Saini
  2019-06-14  7:35 ` [U-Boot] [PATCH 3/3] doc: imx: Add documentation for " Shyam Saini
@ 2019-06-14  9:17 ` Igor Opaniuk
  2019-06-18  7:54   ` Shyam Saini
  2019-07-20  8:47 ` sbabic at denx.de
  3 siblings, 1 reply; 13+ messages in thread
From: Igor Opaniuk @ 2019-06-14  9:17 UTC (permalink / raw)
  To: u-boot

Hi Shyam,

On Fri, Jun 14, 2019 at 10:37 AM Shyam Saini
<shyam.saini@amarulasolutions.com> wrote:
>
> Writing/updating boot image in nand device is not
> straight forward in i.MX6 platform and it requires
> boot control block(BCB) to be configured.
>
> It becomes difficult to use uboot 'nand' command to
> write BCB since it requires platform specific attributes
> need to be taken care of.
>
> It is even difficult to use existing msx-nand.c driver by
> incorporating BCB attributes like mxs_dma_desc does
> because it requires change in mtd and nand command.
>
> So, cmd_nandbcb implemented in arch/arm/mach-imx
>
> BCB contains two data structures, Firmware Configuration Block(FCB)
> and Discovered Bad Block Table(DBBT). FCB has nand timings,
> DBBT search area, page address of firmware.
>
> On summary, nandbcb update will
> - erase the entire partition
> - create BCB by creating 2 FCB/DBBT block followed by
>   1 FW block based on partition size and erasesize.
> - fill FCB/DBBT structures
> - write FW/SPL on FW1
> - write FCB/DBBT in first 2 blocks
>
> for nand boot, up on reset bootrom look for FCB structure in
> first block's if FCB found the nand timings are loaded for
> further reads. once FCB read done, DTTB will load and finally
> firmware will be loaded which is boot image.
>
> Refer section "NAND Boot" from doc/imx/common/imx6.txt for more usage
> information.
>
> Reviewed-by: Stefano Babic <sbabic@denx.de>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> Signed-off-by: Sergey Kubushyn <ksi@koi8.net>
> Signed-off-by: Shyam Saini <shyam.saini@amarulasolutions.com>
> ---
> Changes for v6:
> - Consolidate v5 patch 1 and patch 2 into one single patch
> - Make separate docs patch out of v5 patch 1
>
> Changes for v5:
> - Move mxs_nand.h file from drivers/mtd/nand/raw/ to include/ directory so
>   that it can be used by both drivers/ and arch/
> - Fix command steps output in docs
>
> Changes for v4:
> - Remove obselete apis and use bch_geometry structure for calculating
>   ecc level, bad block start bit and bad block byte
> - Write firmware only once
> - Shorten variable names
> - Update commit message
> - Update docs as per current patch
> - Fix checkpatch warnings
>
> Changes for v3:
> - Fixed multi-line comments
> - Better error handling for failed allocations
>
> Changes for v2:
> - Fixed commit message notes
> - Updated proper commit message
> - Update doc/README.imx6 with NAND boot details
> - Fixed long length variable names.
> - Fixed Gigantic variable name.
> - NULL checks for kzalloc
> - Move Kconfig option in separate patch
> - Fixed checkpatch warninigs
>
>  arch/arm/include/asm/mach-imx/imx-nandbcb.h  | 111 ++++++++
>  arch/arm/mach-imx/Kconfig                    |  11 +
>  arch/arm/mach-imx/Makefile                   |   1 +
>  arch/arm/mach-imx/cmd_nandbcb.c              | 369 +++++++++++++++++++++++++++
>  drivers/mtd/nand/raw/mxs_nand.c              |   2 +-
>  drivers/mtd/nand/raw/mxs_nand_dt.c           |   2 +-
>  drivers/mtd/nand/raw/mxs_nand_spl.c          |   2 +-
>  {drivers/mtd/nand/raw => include}/mxs_nand.h |   0
>  8 files changed, 495 insertions(+), 3 deletions(-)
>  create mode 100644 arch/arm/include/asm/mach-imx/imx-nandbcb.h
>  create mode 100644 arch/arm/mach-imx/cmd_nandbcb.c
>  rename {drivers/mtd/nand/raw => include}/mxs_nand.h (100%)
>
> diff --git a/arch/arm/include/asm/mach-imx/imx-nandbcb.h b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
> new file mode 100644
> index 0000000000..033659a038
> --- /dev/null
> +++ b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
> @@ -0,0 +1,111 @@
> +/*
> + * Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#ifndef _IMX_NAND_BCB_H_
> +#define _IMX_NAND_BCB_H_
> +
> +#define FCB_FINGERPRINT                0x20424346      /* 'FCB' */
> +#define FCB_VERSION_1          0x01000000
> +
> +#define DBBT_FINGERPRINT2      0x54424244      /* 'DBBT' */
> +#define DBBT_VERSION_1         0x01000000
> +
> +struct dbbt_block {
> +       u32 checksum;   /* reserved on i.MX6 */
> +       u32 fingerprint;
> +       u32 version;
> +       u32 numberbb;   /* reserved on i.MX6 */
> +       u32 dbbtpages;
> +};
> +
> +struct fcb_block {
> +       u32 checksum;           /* First fingerprint in first byte */
> +       u32 fingerprint;        /* 2nd fingerprint at byte 4 */
> +       u32 version;            /* 3rd fingerprint at byte 8 */
> +       u8 datasetup;
> +       u8 datahold;
> +       u8 addr_setup;
> +       u8 dsample_time;
> +
> +       /* These are for application use only and not for ROM. */
> +       u8 nandtiming;
> +       u8 rea;
> +       u8 rloh;
> +       u8 rhoh;
> +       u32 pagesize;           /* 2048 for 2K pages, 4096 for 4K pages */
> +       u32 oob_pagesize;       /* 2112 for 2K pages, 4314 for 4K pages */
> +       u32 sectors;            /* Number of 2K sections per block */
> +       u32 nr_nand;            /* Total Number of NANDs - not used by ROM */
> +       u32 nr_die;             /* Number of separate chips in this NAND */
> +       u32 celltype;           /* MLC or SLC */
> +       u32 ecc_type;           /* Type of ECC, can be one of BCH-0-20 */
> +       u32 ecc_nr;             /* Number of bytes for Block0 - BCH */
> +
> +       /* Block size in bytes for all blocks other than Block0 - BCH */
> +       u32 ecc_size;
> +       u32 ecc_level;          /* Ecc level for Block 0 - BCH */
> +       u32 meta_size;          /* Metadata size - BCH */
> +       /* Number of blocks per page for ROM use - BCH */
> +       u32 nr_blocks;
> +       u32 ecc_type_sdk;       /* Type of ECC, can be one of BCH-0-20 */
> +       u32 ecc_nr_sdk;         /* Number of bytes for Block0 - BCH */
> +       /* Block size in bytes for all blocks other than Block0 - BCH */
> +       u32 ecc_size_sdk;
> +       u32 ecc_level_sdk;      /* Ecc level for Block 0 - BCH */
> +       /* Number of blocks per page for SDK use - BCH */
> +       u32 nr_blocks_sdk;
> +       u32 meta_size_sdk;      /* Metadata size - BCH */
> +       u32 erase_th;           /* To set into BCH_MODE register */
> +
> +       /*
> +        * 0: normal boot
> +        * 1: to load patch starting next to FCB
> +        */
> +       u32 bootpatch;
> +       u32 patch_size; /* Size of patch in sectors */
> +       u32 fw1_start;  /* Firmware image starts on this sector */
> +       u32 fw2_start;  /* Secondary FW Image starting Sector */
> +       u32 fw1_pages;  /* Number of sectors in firmware image */
> +       u32 fw2_pages;  /* Number of sector in secondary FW image */
> +       u32 dbbt_start; /* Page address where dbbt search area begins */
> +
> +       /*
> +        * Byte in page data that have manufacturer marked bad block marker,
> +        * this will be swapped with metadata[0] to complete page data.
> +        */
> +       u32 bb_byte;
> +
> +       /*
> +        * For BCH ECC sizes other than 8 and 16 the bad block marker does not
> +        * start at 0th bit of bb_byte. This field is used to get to
> +        * the start bit of bad block marker byte with in bb_byte
> +        */
> +       u32 bb_start_bit;
> +
> +       /*
> +        * FCB value that gives byte offset for
> +        * bad block marker on physical NAND page
> +        */
> +       u32 phy_offset;
> +       u32 bchtype;
> +
> +       u32 readlatency;
> +       u32 predelay;
> +       u32 cedelay;
> +       u32 postdelay;
> +       u32 cmdaddpause;
> +       u32 datapause;
> +       u32 tmspeed;
> +       u32 busytimeout;
> +
> +       /* the flag to enable (1)/disable(0) bi swap */
> +       u32 disbbm;
> +
> +       /* The swap position of main area in spare area */
> +       u32 spare_offset;
> +};
> +
> +#endif /* _IMX_NAND_BCB_H_ */
> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> index ec09ef240f..5dd286f9a7 100644
> --- a/arch/arm/mach-imx/Kconfig
> +++ b/arch/arm/mach-imx/Kconfig
> @@ -71,6 +71,17 @@ config CMD_HDMIDETECT
>           This enables the 'hdmidet' command which detects if an HDMI monitor
>           is connected.
>
> +config CMD_NANDBCB
> +       bool "i.MX6 NAND Boot Control Block(BCB) command"
> +       depends on NAND && CMD_MTDPARTS
> +       default y if ARCH_MX6 && NAND_MXS

Just curious, are there any plans to enable this also for ARCH_MX7?
I've just compared bcb definition here and in imx-kobs (it also includes
NANDTM timings etc, which are actual for iMX7), so I assume it should
also work for iMX7 SoCs out of the box

> +       help
> +         Unlike normal 'nand write/erase' commands, this command update
> +         Boot Control Block(BCB) for i.MX6 platform NAND IP's.
> +
> +         This is similar to kobs-ng, which is used in Linux as separate
> +         rootfs package.
> +
>  config NXP_BOARD_REVISION
>         bool "Read NXP board revision from fuses"
>         depends on ARCH_MX6 || ARCH_MX7
> diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
> index c46984994a..96f0b89fd1 100644
> --- a/arch/arm/mach-imx/Makefile
> +++ b/arch/arm/mach-imx/Makefile
> @@ -59,6 +59,7 @@ ifneq ($(CONFIG_SPL_BUILD),y)
>  obj-$(CONFIG_CMD_BMODE) += cmd_bmode.o
>  obj-$(CONFIG_CMD_HDMIDETECT) += cmd_hdmidet.o
>  obj-$(CONFIG_CMD_DEKBLOB) += cmd_dek.o
> +obj-$(CONFIG_CMD_NANDBCB) += cmd_nandbcb.o
>  endif
>
>  PLUGIN = board/$(BOARDDIR)/plugin
> diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
> new file mode 100644
> index 0000000000..065b814b2e
> --- /dev/null
> +++ b/arch/arm/mach-imx/cmd_nandbcb.c
> @@ -0,0 +1,369 @@
> +/*
> + * i.MX6 nand boot control block(bcb).
> + *
> + * Based on the common/imx-bbu-nand-fcb.c from barebox and imx kobs-ng
> + *
> + * Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com>
> + * Copyright (C) 2016 Sergey Kubushyn <ksi@koi8.net>
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <nand.h>
> +
> +#include <asm/io.h>
> +#include <jffs2/jffs2.h>
> +#include <linux/mtd/mtd.h>
> +
> +#include <asm/mach-imx/imx-nandbcb.h>
> +#include <asm/mach-imx/imximage.cfg>
> +#include <mxs_nand.h>
> +#include <linux/mtd/mtd.h>
> +#include <nand.h>
> +
> +#define BF_VAL(v, bf)          (((v) & bf##_MASK) >> bf##_OFFSET)
> +#define GETBIT(v, n)           (((v) >> (n)) & 0x1)
> +
> +static u8 calculate_parity_13_8(u8 d)
> +{
> +       u8 p = 0;
> +
> +       p |= (GETBIT(d, 6) ^ GETBIT(d, 5) ^ GETBIT(d, 3) ^ GETBIT(d, 2)) << 0;
> +       p |= (GETBIT(d, 7) ^ GETBIT(d, 5) ^ GETBIT(d, 4) ^ GETBIT(d, 2) ^
> +             GETBIT(d, 1)) << 1;
> +       p |= (GETBIT(d, 7) ^ GETBIT(d, 6) ^ GETBIT(d, 5) ^ GETBIT(d, 1) ^
> +             GETBIT(d, 0)) << 2;
> +       p |= (GETBIT(d, 7) ^ GETBIT(d, 4) ^ GETBIT(d, 3) ^ GETBIT(d, 0)) << 3;
> +       p |= (GETBIT(d, 6) ^ GETBIT(d, 4) ^ GETBIT(d, 3) ^ GETBIT(d, 2) ^
> +             GETBIT(d, 1) ^ GETBIT(d, 0)) << 4;
> +
> +       return p;
> +}
> +
> +static void encode_hamming_13_8(void *_src, void *_ecc, size_t size)
> +{
> +       int i;
> +       u8 *src = _src;
> +       u8 *ecc = _ecc;
> +
> +       for (i = 0; i < size; i++)
> +               ecc[i] = calculate_parity_13_8(src[i]);
> +}
> +
> +static u32 calc_chksum(void *buf, size_t size)
> +{
> +       u32 chksum = 0;
> +       u8 *bp = buf;
> +       size_t i;
> +
> +       for (i = 0; i < size; i++)
> +               chksum += bp[i];
> +
> +       return ~chksum;
> +}
> +
> +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);
> +
> +       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;
> +
> +       /* 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;
> +
> +       /* DBBT search area starts at second page on first block */
> +       fcb->dbbt_start = 1;
> +
> +       fcb->bb_byte = nand_info->bch_geometry.block_mark_byte_offset;
> +       fcb->bb_start_bit = nand_info->bch_geometry.block_mark_bit_offset;
> +
> +       fcb->phy_offset = mtd->writesize;
> +
> +       fcb->nr_blocks = mtd->writesize / fcb->ecc_nr - 1;
> +
> +       fcb->checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
> +}
> +
> +static int dbbt_fill_data(struct mtd_info *mtd, void *buf, int num_blocks)
> +{
> +       int n, n_bad_blocks = 0;
> +       u32 *bb = buf + 0x8;
> +       u32 *n_bad_blocksp = buf + 0x4;
> +
> +       for (n = 0; n < num_blocks; n++) {
> +               loff_t offset = n * mtd->erasesize;
> +                       if (mtd_block_isbad(mtd, offset)) {
> +                               n_bad_blocks++;
> +                               *bb = n;
> +                               bb++;
> +               }
> +       }
> +
> +       *n_bad_blocksp = n_bad_blocks;
> +
> +       return n_bad_blocks;
> +}
> +
> +static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
> +                         size_t maxsize, const u_char *buf)
> +{
> +       nand_erase_options_t opts;
> +       struct fcb_block *fcb;
> +       struct dbbt_block *dbbt;
> +       loff_t fw1_off;
> +       void *fwbuf, *fcb_raw_page, *dbbt_page, *dbbt_data_page;
> +       int nr_blks, nr_blks_fcb, fw1_blk;
> +       size_t fwsize, dummy;
> +       int i, ret;
> +
> +       /* erase */
> +       memset(&opts, 0, sizeof(opts));
> +       opts.offset = off;
> +       opts.length = maxsize - 1;
> +       ret = nand_erase_opts(mtd, &opts);
> +       if (ret) {
> +               printf("%s: erase failed (ret = %d)\n", __func__, ret);
> +               return ret;
> +       }
> +
> +       /*
> +        * Reference documentation from i.MX6DQRM section 8.5.2.2
> +        *
> +        * Nand Boot Control Block(BCB) contains two data structures,
> +        * - Firmware Configuration Block(FCB)
> +        * - Discovered Bad Block Table(DBBT)
> +        *
> +        * FCB contains,
> +        * - nand timings
> +        * - DBBT search page address,
> +        * - start page address of primary firmware
> +        * - start page address of secondary firmware
> +        *
> +        * setup fcb:
> +        * - number of blocks = mtd partition size / mtd erasesize
> +        * - two firmware blocks, primary and secondary
> +        * - first 4 block for FCB/DBBT
> +        * - rest split in half for primary and secondary firmware
> +        * - same firmware will write two times
> +        */
> +       nr_blks_fcb = 2;
> +       nr_blks = maxsize / mtd->erasesize;
> +       fw1_blk = nr_blks_fcb;
> +
> +       /* write fw */
> +       fwsize = ALIGN(size + FLASH_OFFSET_STANDARD + mtd->writesize,
> +                      mtd->writesize);
> +       fwbuf = kzalloc(fwsize, GFP_KERNEL);
> +       if (!fwbuf) {
> +               debug("failed to allocate fwbuf\n");
> +               ret = -ENOMEM;
> +               goto err;
> +       }
> +
> +       memcpy(fwbuf + FLASH_OFFSET_STANDARD, buf, size);
> +       fw1_off = fw1_blk * mtd->erasesize;
> +       ret = nand_write_skip_bad(mtd, fw1_off, &fwsize, NULL, maxsize,
> +                                 (u_char *)fwbuf, WITH_WR_VERIFY);
> +       printf("NAND fw write: 0x%llx offset, 0x%x bytes written: %s\n",
> +              fw1_off, fwsize, ret ? "ERROR" : "OK");
> +       if (ret)
> +               goto fwbuf_err;
> +
> +       /* fill fcb */
> +       fcb = kzalloc(sizeof(*fcb), GFP_KERNEL);
> +       if (!fcb) {
> +               debug("failed to allocate fcb\n");
> +               ret = -ENOMEM;
> +               goto fwbuf_err;
> +       }
> +
> +       fcb->fw1_start = (fw1_blk * mtd->erasesize) / mtd->writesize;
> +       fcb->fw1_pages = size / mtd->writesize + 1;
> +       fill_fcb(fcb, mtd);
> +
> +       /* 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, nr_blks);
> +       if (ret < 0)
> +               goto dbbt_data_page_err;
> +       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.
> +        */
> +       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");
> +
> +               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;
> +               }
> +       }
> +
> +fcb_raw_page_err:
> +       kfree(fcb_raw_page);
> +dbbt_data_page_err:
> +       kfree(dbbt_data_page);
> +dbbt_page_err:
> +       kfree(dbbt_page);
> +fcb_err:
> +       kfree(fcb);
> +fwbuf_err:
> +       kfree(fwbuf);
> +err:
> +       return ret;
> +}
> +
> +static int do_nandbcb_update(int argc, char * const argv[])
> +{
> +       struct mtd_info *mtd;
> +       loff_t addr, offset, size, maxsize;
> +       char *endp;
> +       u_char *buf;
> +       int dev;
> +       int ret;
> +
> +       if (argc != 4)
> +               return CMD_RET_USAGE;
> +
> +       dev = nand_curr_device;
> +       if (dev < 0) {
> +               printf("failed to get nand_curr_device, run nand device");
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       addr = simple_strtoul(argv[1], &endp, 16);
> +       if (*argv[1] == 0 || *endp != 0)
> +               return CMD_RET_FAILURE;
> +
> +       mtd = get_nand_dev_by_index(dev);
> +       if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &offset, &size,
> +                            &maxsize, MTD_DEV_TYPE_NAND, mtd->size))
> +               return CMD_RET_FAILURE;
> +
> +       buf = map_physmem(addr, size, MAP_WRBACK);
> +       if (!buf) {
> +               puts("failed to map physical memory\n");
> +               return CMD_RET_FAILURE;
> +       }
> +
> +       ret = nandbcb_update(mtd, offset, size, maxsize, buf);
> +
> +       return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
> +}
> +
> +static int do_nandbcb(cmd_tbl_t *cmdtp, int flag, int argc,
> +                     char * const argv[])
> +{
> +       const char *cmd;
> +       int ret = 0;
> +
> +       if (argc < 5)
> +               goto usage;
> +
> +       cmd = argv[1];
> +       --argc;
> +       ++argv;
> +
> +       if (strcmp(cmd, "update") == 0) {
> +               ret = do_nandbcb_update(argc, argv);
> +               goto done;
> +       }
> +
> +done:
> +       if (ret != -1)
> +               return ret;
> +usage:
> +       return CMD_RET_USAGE;
> +}
> +
> +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";
> +
> +U_BOOT_CMD(nandbcb, 5, 1, do_nandbcb,
> +          "i.MX6 Nand BCB",
> +          nandbcb_help_text
> +);
> diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
> index b93d77a395..a41b9620d0 100644
> --- a/drivers/mtd/nand/raw/mxs_nand.c
> +++ b/drivers/mtd/nand/raw/mxs_nand.c
> @@ -25,7 +25,7 @@
>  #include <asm/mach-imx/regs-bch.h>
>  #include <asm/mach-imx/regs-gpmi.h>
>  #include <asm/arch/sys_proto.h>
> -#include "mxs_nand.h"
> +#include <mxs_nand.h>
>
>  #define        MXS_NAND_DMA_DESCRIPTOR_COUNT           4
>
> diff --git a/drivers/mtd/nand/raw/mxs_nand_dt.c b/drivers/mtd/nand/raw/mxs_nand_dt.c
> index 44dec5dedf..8ad7d618c6 100644
> --- a/drivers/mtd/nand/raw/mxs_nand_dt.c
> +++ b/drivers/mtd/nand/raw/mxs_nand_dt.c
> @@ -15,7 +15,7 @@
>  #include <linux/ioport.h>
>  #include <linux/printk.h>
>
> -#include "mxs_nand.h"
> +#include <mxs_nand.h>
>
>  struct mxs_nand_dt_data {
>         unsigned int max_ecc_strength_supported;
> diff --git a/drivers/mtd/nand/raw/mxs_nand_spl.c b/drivers/mtd/nand/raw/mxs_nand_spl.c
> index ee7d9cb957..975a91a37d 100644
> --- a/drivers/mtd/nand/raw/mxs_nand_spl.c
> +++ b/drivers/mtd/nand/raw/mxs_nand_spl.c
> @@ -6,7 +6,7 @@
>  #include <common.h>
>  #include <nand.h>
>  #include <malloc.h>
> -#include "mxs_nand.h"
> +#include <mxs_nand.h>
>
>  static struct mtd_info *mtd;
>  static struct nand_chip nand_chip;
> diff --git a/drivers/mtd/nand/raw/mxs_nand.h b/include/mxs_nand.h
> similarity index 100%
> rename from drivers/mtd/nand/raw/mxs_nand.h
> rename to include/mxs_nand.h
> --
> 2.11.0
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot

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

* [U-Boot] [PATCH v6 1/3] i.MX6: nand: add nandbcb command for imx
  2019-06-14  9:17 ` [U-Boot] [PATCH v6 1/3] i.MX6: nand: add nandbcb command for imx Igor Opaniuk
@ 2019-06-18  7:54   ` Shyam Saini
  2019-06-28 17:46     ` Parthiban Nallathambi
  0 siblings, 1 reply; 13+ messages in thread
From: Shyam Saini @ 2019-06-18  7:54 UTC (permalink / raw)
  To: u-boot

Hi Igor,

> Hi Shyam,
>
> On Fri, Jun 14, 2019 at 10:37 AM Shyam Saini
> <shyam.saini@amarulasolutions.com> wrote:
> >
> > Writing/updating boot image in nand device is not
> > straight forward in i.MX6 platform and it requires
> > boot control block(BCB) to be configured.
> >
> > It becomes difficult to use uboot 'nand' command to
> > write BCB since it requires platform specific attributes
> > need to be taken care of.
> >
> > It is even difficult to use existing msx-nand.c driver by
> > incorporating BCB attributes like mxs_dma_desc does
> > because it requires change in mtd and nand command.
> >
> > So, cmd_nandbcb implemented in arch/arm/mach-imx
> >
> > BCB contains two data structures, Firmware Configuration Block(FCB)
> > and Discovered Bad Block Table(DBBT). FCB has nand timings,
> > DBBT search area, page address of firmware.
> >
> > On summary, nandbcb update will
> > - erase the entire partition
> > - create BCB by creating 2 FCB/DBBT block followed by
> >   1 FW block based on partition size and erasesize.
> > - fill FCB/DBBT structures
> > - write FW/SPL on FW1
> > - write FCB/DBBT in first 2 blocks
> >
> > for nand boot, up on reset bootrom look for FCB structure in
> > first block's if FCB found the nand timings are loaded for
> > further reads. once FCB read done, DTTB will load and finally
> > firmware will be loaded which is boot image.
> >
> > Refer section "NAND Boot" from doc/imx/common/imx6.txt for more usage
> > information.
> >
> > Reviewed-by: Stefano Babic <sbabic@denx.de>
> > Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> > Signed-off-by: Sergey Kubushyn <ksi@koi8.net>
> > Signed-off-by: Shyam Saini <shyam.saini@amarulasolutions.com>
> > ---
> > Changes for v6:
> > - Consolidate v5 patch 1 and patch 2 into one single patch
> > - Make separate docs patch out of v5 patch 1
> >
> > Changes for v5:
> > - Move mxs_nand.h file from drivers/mtd/nand/raw/ to include/ directory so
> >   that it can be used by both drivers/ and arch/
> > - Fix command steps output in docs
> >
> > Changes for v4:
> > - Remove obselete apis and use bch_geometry structure for calculating
> >   ecc level, bad block start bit and bad block byte
> > - Write firmware only once
> > - Shorten variable names
> > - Update commit message
> > - Update docs as per current patch
> > - Fix checkpatch warnings
> >
> > Changes for v3:
> > - Fixed multi-line comments
> > - Better error handling for failed allocations
> >
> > Changes for v2:
> > - Fixed commit message notes
> > - Updated proper commit message
> > - Update doc/README.imx6 with NAND boot details
> > - Fixed long length variable names.
> > - Fixed Gigantic variable name.
> > - NULL checks for kzalloc
> > - Move Kconfig option in separate patch
> > - Fixed checkpatch warninigs
> >
> >  arch/arm/include/asm/mach-imx/imx-nandbcb.h  | 111 ++++++++
> >  arch/arm/mach-imx/Kconfig                    |  11 +
> >  arch/arm/mach-imx/Makefile                   |   1 +
> >  arch/arm/mach-imx/cmd_nandbcb.c              | 369 +++++++++++++++++++++++++++
> >  drivers/mtd/nand/raw/mxs_nand.c              |   2 +-
> >  drivers/mtd/nand/raw/mxs_nand_dt.c           |   2 +-
> >  drivers/mtd/nand/raw/mxs_nand_spl.c          |   2 +-
> >  {drivers/mtd/nand/raw => include}/mxs_nand.h |   0
> >  8 files changed, 495 insertions(+), 3 deletions(-)
> >  create mode 100644 arch/arm/include/asm/mach-imx/imx-nandbcb.h
> >  create mode 100644 arch/arm/mach-imx/cmd_nandbcb.c
> >  rename {drivers/mtd/nand/raw => include}/mxs_nand.h (100%)
> >
> > diff --git a/arch/arm/include/asm/mach-imx/imx-nandbcb.h b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
> > new file mode 100644
> > index 0000000000..033659a038
> > --- /dev/null
> > +++ b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
> > @@ -0,0 +1,111 @@
> > +/*
> > + * Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com>
> > + *
> > + * SPDX-License-Identifier:    GPL-2.0+
> > + */
> > +
> > +#ifndef _IMX_NAND_BCB_H_
> > +#define _IMX_NAND_BCB_H_
> > +
> > +#define FCB_FINGERPRINT                0x20424346      /* 'FCB' */
> > +#define FCB_VERSION_1          0x01000000
> > +
> > +#define DBBT_FINGERPRINT2      0x54424244      /* 'DBBT' */
> > +#define DBBT_VERSION_1         0x01000000
> > +
> > +struct dbbt_block {
> > +       u32 checksum;   /* reserved on i.MX6 */
> > +       u32 fingerprint;
> > +       u32 version;
> > +       u32 numberbb;   /* reserved on i.MX6 */
> > +       u32 dbbtpages;
> > +};
> > +
> > +struct fcb_block {
> > +       u32 checksum;           /* First fingerprint in first byte */
> > +       u32 fingerprint;        /* 2nd fingerprint at byte 4 */
> > +       u32 version;            /* 3rd fingerprint at byte 8 */
> > +       u8 datasetup;
> > +       u8 datahold;
> > +       u8 addr_setup;
> > +       u8 dsample_time;
> > +
> > +       /* These are for application use only and not for ROM. */
> > +       u8 nandtiming;
> > +       u8 rea;
> > +       u8 rloh;
> > +       u8 rhoh;
> > +       u32 pagesize;           /* 2048 for 2K pages, 4096 for 4K pages */
> > +       u32 oob_pagesize;       /* 2112 for 2K pages, 4314 for 4K pages */
> > +       u32 sectors;            /* Number of 2K sections per block */
> > +       u32 nr_nand;            /* Total Number of NANDs - not used by ROM */
> > +       u32 nr_die;             /* Number of separate chips in this NAND */
> > +       u32 celltype;           /* MLC or SLC */
> > +       u32 ecc_type;           /* Type of ECC, can be one of BCH-0-20 */
> > +       u32 ecc_nr;             /* Number of bytes for Block0 - BCH */
> > +
> > +       /* Block size in bytes for all blocks other than Block0 - BCH */
> > +       u32 ecc_size;
> > +       u32 ecc_level;          /* Ecc level for Block 0 - BCH */
> > +       u32 meta_size;          /* Metadata size - BCH */
> > +       /* Number of blocks per page for ROM use - BCH */
> > +       u32 nr_blocks;
> > +       u32 ecc_type_sdk;       /* Type of ECC, can be one of BCH-0-20 */
> > +       u32 ecc_nr_sdk;         /* Number of bytes for Block0 - BCH */
> > +       /* Block size in bytes for all blocks other than Block0 - BCH */
> > +       u32 ecc_size_sdk;
> > +       u32 ecc_level_sdk;      /* Ecc level for Block 0 - BCH */
> > +       /* Number of blocks per page for SDK use - BCH */
> > +       u32 nr_blocks_sdk;
> > +       u32 meta_size_sdk;      /* Metadata size - BCH */
> > +       u32 erase_th;           /* To set into BCH_MODE register */
> > +
> > +       /*
> > +        * 0: normal boot
> > +        * 1: to load patch starting next to FCB
> > +        */
> > +       u32 bootpatch;
> > +       u32 patch_size; /* Size of patch in sectors */
> > +       u32 fw1_start;  /* Firmware image starts on this sector */
> > +       u32 fw2_start;  /* Secondary FW Image starting Sector */
> > +       u32 fw1_pages;  /* Number of sectors in firmware image */
> > +       u32 fw2_pages;  /* Number of sector in secondary FW image */
> > +       u32 dbbt_start; /* Page address where dbbt search area begins */
> > +
> > +       /*
> > +        * Byte in page data that have manufacturer marked bad block marker,
> > +        * this will be swapped with metadata[0] to complete page data.
> > +        */
> > +       u32 bb_byte;
> > +
> > +       /*
> > +        * For BCH ECC sizes other than 8 and 16 the bad block marker does not
> > +        * start at 0th bit of bb_byte. This field is used to get to
> > +        * the start bit of bad block marker byte with in bb_byte
> > +        */
> > +       u32 bb_start_bit;
> > +
> > +       /*
> > +        * FCB value that gives byte offset for
> > +        * bad block marker on physical NAND page
> > +        */
> > +       u32 phy_offset;
> > +       u32 bchtype;
> > +
> > +       u32 readlatency;
> > +       u32 predelay;
> > +       u32 cedelay;
> > +       u32 postdelay;
> > +       u32 cmdaddpause;
> > +       u32 datapause;
> > +       u32 tmspeed;
> > +       u32 busytimeout;
> > +
> > +       /* the flag to enable (1)/disable(0) bi swap */
> > +       u32 disbbm;
> > +
> > +       /* The swap position of main area in spare area */
> > +       u32 spare_offset;
> > +};
> > +
> > +#endif /* _IMX_NAND_BCB_H_ */
> > diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
> > index ec09ef240f..5dd286f9a7 100644
> > --- a/arch/arm/mach-imx/Kconfig
> > +++ b/arch/arm/mach-imx/Kconfig
> > @@ -71,6 +71,17 @@ config CMD_HDMIDETECT
> >           This enables the 'hdmidet' command which detects if an HDMI monitor
> >           is connected.
> >
> > +config CMD_NANDBCB
> > +       bool "i.MX6 NAND Boot Control Block(BCB) command"
> > +       depends on NAND && CMD_MTDPARTS
> > +       default y if ARCH_MX6 && NAND_MXS
>
> Just curious, are there any plans to enable this also for ARCH_MX7?
> I've just compared bcb definition here and in imx-kobs (it also includes
> NANDTM timings etc, which are actual for iMX7), so I assume it should
> also work for iMX7 SoCs out of the box

Yes, it is true that we are using original structure from kobs-ng but
this current patch
only supports imx6q variants and we are working on to add suppport for imx6ul(l)

We don't have any imx7 board so no plan for imx7. But, it would be
great help if you
could add support for imx7 :-)


Thanks

>
> > +       help
> > +         Unlike normal 'nand write/erase' commands, this command update
> > +         Boot Control Block(BCB) for i.MX6 platform NAND IP's.
> > +
> > +         This is similar to kobs-ng, which is used in Linux as separate
> > +         rootfs package.
> > +
> >  config NXP_BOARD_REVISION
> >         bool "Read NXP board revision from fuses"
> >         depends on ARCH_MX6 || ARCH_MX7
> > diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
> > index c46984994a..96f0b89fd1 100644
> > --- a/arch/arm/mach-imx/Makefile
> > +++ b/arch/arm/mach-imx/Makefile
> > @@ -59,6 +59,7 @@ ifneq ($(CONFIG_SPL_BUILD),y)
> >  obj-$(CONFIG_CMD_BMODE) += cmd_bmode.o
> >  obj-$(CONFIG_CMD_HDMIDETECT) += cmd_hdmidet.o
> >  obj-$(CONFIG_CMD_DEKBLOB) += cmd_dek.o
> > +obj-$(CONFIG_CMD_NANDBCB) += cmd_nandbcb.o
> >  endif
> >
> >  PLUGIN = board/$(BOARDDIR)/plugin
> > diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
> > new file mode 100644
> > index 0000000000..065b814b2e
> > --- /dev/null
> > +++ b/arch/arm/mach-imx/cmd_nandbcb.c
> > @@ -0,0 +1,369 @@
> > +/*
> > + * i.MX6 nand boot control block(bcb).
> > + *
> > + * Based on the common/imx-bbu-nand-fcb.c from barebox and imx kobs-ng
> > + *
> > + * Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com>
> > + * Copyright (C) 2016 Sergey Kubushyn <ksi@koi8.net>
> > + *
> > + * SPDX-License-Identifier:    GPL-2.0+
> > + */
> > +
> > +#include <common.h>
> > +#include <nand.h>
> > +
> > +#include <asm/io.h>
> > +#include <jffs2/jffs2.h>
> > +#include <linux/mtd/mtd.h>
> > +
> > +#include <asm/mach-imx/imx-nandbcb.h>
> > +#include <asm/mach-imx/imximage.cfg>
> > +#include <mxs_nand.h>
> > +#include <linux/mtd/mtd.h>
> > +#include <nand.h>
> > +
> > +#define BF_VAL(v, bf)          (((v) & bf##_MASK) >> bf##_OFFSET)
> > +#define GETBIT(v, n)           (((v) >> (n)) & 0x1)
> > +
> > +static u8 calculate_parity_13_8(u8 d)
> > +{
> > +       u8 p = 0;
> > +
> > +       p |= (GETBIT(d, 6) ^ GETBIT(d, 5) ^ GETBIT(d, 3) ^ GETBIT(d, 2)) << 0;
> > +       p |= (GETBIT(d, 7) ^ GETBIT(d, 5) ^ GETBIT(d, 4) ^ GETBIT(d, 2) ^
> > +             GETBIT(d, 1)) << 1;
> > +       p |= (GETBIT(d, 7) ^ GETBIT(d, 6) ^ GETBIT(d, 5) ^ GETBIT(d, 1) ^
> > +             GETBIT(d, 0)) << 2;
> > +       p |= (GETBIT(d, 7) ^ GETBIT(d, 4) ^ GETBIT(d, 3) ^ GETBIT(d, 0)) << 3;
> > +       p |= (GETBIT(d, 6) ^ GETBIT(d, 4) ^ GETBIT(d, 3) ^ GETBIT(d, 2) ^
> > +             GETBIT(d, 1) ^ GETBIT(d, 0)) << 4;
> > +
> > +       return p;
> > +}
> > +
> > +static void encode_hamming_13_8(void *_src, void *_ecc, size_t size)
> > +{
> > +       int i;
> > +       u8 *src = _src;
> > +       u8 *ecc = _ecc;
> > +
> > +       for (i = 0; i < size; i++)
> > +               ecc[i] = calculate_parity_13_8(src[i]);
> > +}
> > +
> > +static u32 calc_chksum(void *buf, size_t size)
> > +{
> > +       u32 chksum = 0;
> > +       u8 *bp = buf;
> > +       size_t i;
> > +
> > +       for (i = 0; i < size; i++)
> > +               chksum += bp[i];
> > +
> > +       return ~chksum;
> > +}
> > +
> > +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);
> > +
> > +       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;
> > +
> > +       /* 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;
> > +
> > +       /* DBBT search area starts at second page on first block */
> > +       fcb->dbbt_start = 1;
> > +
> > +       fcb->bb_byte = nand_info->bch_geometry.block_mark_byte_offset;
> > +       fcb->bb_start_bit = nand_info->bch_geometry.block_mark_bit_offset;
> > +
> > +       fcb->phy_offset = mtd->writesize;
> > +
> > +       fcb->nr_blocks = mtd->writesize / fcb->ecc_nr - 1;
> > +
> > +       fcb->checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
> > +}
> > +
> > +static int dbbt_fill_data(struct mtd_info *mtd, void *buf, int num_blocks)
> > +{
> > +       int n, n_bad_blocks = 0;
> > +       u32 *bb = buf + 0x8;
> > +       u32 *n_bad_blocksp = buf + 0x4;
> > +
> > +       for (n = 0; n < num_blocks; n++) {
> > +               loff_t offset = n * mtd->erasesize;
> > +                       if (mtd_block_isbad(mtd, offset)) {
> > +                               n_bad_blocks++;
> > +                               *bb = n;
> > +                               bb++;
> > +               }
> > +       }
> > +
> > +       *n_bad_blocksp = n_bad_blocks;
> > +
> > +       return n_bad_blocks;
> > +}
> > +
> > +static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
> > +                         size_t maxsize, const u_char *buf)
> > +{
> > +       nand_erase_options_t opts;
> > +       struct fcb_block *fcb;
> > +       struct dbbt_block *dbbt;
> > +       loff_t fw1_off;
> > +       void *fwbuf, *fcb_raw_page, *dbbt_page, *dbbt_data_page;
> > +       int nr_blks, nr_blks_fcb, fw1_blk;
> > +       size_t fwsize, dummy;
> > +       int i, ret;
> > +
> > +       /* erase */
> > +       memset(&opts, 0, sizeof(opts));
> > +       opts.offset = off;
> > +       opts.length = maxsize - 1;
> > +       ret = nand_erase_opts(mtd, &opts);
> > +       if (ret) {
> > +               printf("%s: erase failed (ret = %d)\n", __func__, ret);
> > +               return ret;
> > +       }
> > +
> > +       /*
> > +        * Reference documentation from i.MX6DQRM section 8.5.2.2
> > +        *
> > +        * Nand Boot Control Block(BCB) contains two data structures,
> > +        * - Firmware Configuration Block(FCB)
> > +        * - Discovered Bad Block Table(DBBT)
> > +        *
> > +        * FCB contains,
> > +        * - nand timings
> > +        * - DBBT search page address,
> > +        * - start page address of primary firmware
> > +        * - start page address of secondary firmware
> > +        *
> > +        * setup fcb:
> > +        * - number of blocks = mtd partition size / mtd erasesize
> > +        * - two firmware blocks, primary and secondary
> > +        * - first 4 block for FCB/DBBT
> > +        * - rest split in half for primary and secondary firmware
> > +        * - same firmware will write two times
> > +        */
> > +       nr_blks_fcb = 2;
> > +       nr_blks = maxsize / mtd->erasesize;
> > +       fw1_blk = nr_blks_fcb;
> > +
> > +       /* write fw */
> > +       fwsize = ALIGN(size + FLASH_OFFSET_STANDARD + mtd->writesize,
> > +                      mtd->writesize);
> > +       fwbuf = kzalloc(fwsize, GFP_KERNEL);
> > +       if (!fwbuf) {
> > +               debug("failed to allocate fwbuf\n");
> > +               ret = -ENOMEM;
> > +               goto err;
> > +       }
> > +
> > +       memcpy(fwbuf + FLASH_OFFSET_STANDARD, buf, size);
> > +       fw1_off = fw1_blk * mtd->erasesize;
> > +       ret = nand_write_skip_bad(mtd, fw1_off, &fwsize, NULL, maxsize,
> > +                                 (u_char *)fwbuf, WITH_WR_VERIFY);
> > +       printf("NAND fw write: 0x%llx offset, 0x%x bytes written: %s\n",
> > +              fw1_off, fwsize, ret ? "ERROR" : "OK");
> > +       if (ret)
> > +               goto fwbuf_err;
> > +
> > +       /* fill fcb */
> > +       fcb = kzalloc(sizeof(*fcb), GFP_KERNEL);
> > +       if (!fcb) {
> > +               debug("failed to allocate fcb\n");
> > +               ret = -ENOMEM;
> > +               goto fwbuf_err;
> > +       }
> > +
> > +       fcb->fw1_start = (fw1_blk * mtd->erasesize) / mtd->writesize;
> > +       fcb->fw1_pages = size / mtd->writesize + 1;
> > +       fill_fcb(fcb, mtd);
> > +
> > +       /* 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, nr_blks);
> > +       if (ret < 0)
> > +               goto dbbt_data_page_err;
> > +       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.
> > +        */
> > +       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");
> > +
> > +               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;
> > +               }
> > +       }
> > +
> > +fcb_raw_page_err:
> > +       kfree(fcb_raw_page);
> > +dbbt_data_page_err:
> > +       kfree(dbbt_data_page);
> > +dbbt_page_err:
> > +       kfree(dbbt_page);
> > +fcb_err:
> > +       kfree(fcb);
> > +fwbuf_err:
> > +       kfree(fwbuf);
> > +err:
> > +       return ret;
> > +}
> > +
> > +static int do_nandbcb_update(int argc, char * const argv[])
> > +{
> > +       struct mtd_info *mtd;
> > +       loff_t addr, offset, size, maxsize;
> > +       char *endp;
> > +       u_char *buf;
> > +       int dev;
> > +       int ret;
> > +
> > +       if (argc != 4)
> > +               return CMD_RET_USAGE;
> > +
> > +       dev = nand_curr_device;
> > +       if (dev < 0) {
> > +               printf("failed to get nand_curr_device, run nand device");
> > +               return CMD_RET_FAILURE;
> > +       }
> > +
> > +       addr = simple_strtoul(argv[1], &endp, 16);
> > +       if (*argv[1] == 0 || *endp != 0)
> > +               return CMD_RET_FAILURE;
> > +
> > +       mtd = get_nand_dev_by_index(dev);
> > +       if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &offset, &size,
> > +                            &maxsize, MTD_DEV_TYPE_NAND, mtd->size))
> > +               return CMD_RET_FAILURE;
> > +
> > +       buf = map_physmem(addr, size, MAP_WRBACK);
> > +       if (!buf) {
> > +               puts("failed to map physical memory\n");
> > +               return CMD_RET_FAILURE;
> > +       }
> > +
> > +       ret = nandbcb_update(mtd, offset, size, maxsize, buf);
> > +
> > +       return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
> > +}
> > +
> > +static int do_nandbcb(cmd_tbl_t *cmdtp, int flag, int argc,
> > +                     char * const argv[])
> > +{
> > +       const char *cmd;
> > +       int ret = 0;
> > +
> > +       if (argc < 5)
> > +               goto usage;
> > +
> > +       cmd = argv[1];
> > +       --argc;
> > +       ++argv;
> > +
> > +       if (strcmp(cmd, "update") == 0) {
> > +               ret = do_nandbcb_update(argc, argv);
> > +               goto done;
> > +       }
> > +
> > +done:
> > +       if (ret != -1)
> > +               return ret;
> > +usage:
> > +       return CMD_RET_USAGE;
> > +}
> > +
> > +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";
> > +
> > +U_BOOT_CMD(nandbcb, 5, 1, do_nandbcb,
> > +          "i.MX6 Nand BCB",
> > +          nandbcb_help_text
> > +);
> > diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
> > index b93d77a395..a41b9620d0 100644
> > --- a/drivers/mtd/nand/raw/mxs_nand.c
> > +++ b/drivers/mtd/nand/raw/mxs_nand.c
> > @@ -25,7 +25,7 @@
> >  #include <asm/mach-imx/regs-bch.h>
> >  #include <asm/mach-imx/regs-gpmi.h>
> >  #include <asm/arch/sys_proto.h>
> > -#include "mxs_nand.h"
> > +#include <mxs_nand.h>
> >
> >  #define        MXS_NAND_DMA_DESCRIPTOR_COUNT           4
> >
> > diff --git a/drivers/mtd/nand/raw/mxs_nand_dt.c b/drivers/mtd/nand/raw/mxs_nand_dt.c
> > index 44dec5dedf..8ad7d618c6 100644
> > --- a/drivers/mtd/nand/raw/mxs_nand_dt.c
> > +++ b/drivers/mtd/nand/raw/mxs_nand_dt.c
> > @@ -15,7 +15,7 @@
> >  #include <linux/ioport.h>
> >  #include <linux/printk.h>
> >
> > -#include "mxs_nand.h"
> > +#include <mxs_nand.h>
> >
> >  struct mxs_nand_dt_data {
> >         unsigned int max_ecc_strength_supported;
> > diff --git a/drivers/mtd/nand/raw/mxs_nand_spl.c b/drivers/mtd/nand/raw/mxs_nand_spl.c
> > index ee7d9cb957..975a91a37d 100644
> > --- a/drivers/mtd/nand/raw/mxs_nand_spl.c
> > +++ b/drivers/mtd/nand/raw/mxs_nand_spl.c
> > @@ -6,7 +6,7 @@
> >  #include <common.h>
> >  #include <nand.h>
> >  #include <malloc.h>
> > -#include "mxs_nand.h"
> > +#include <mxs_nand.h>
> >
> >  static struct mtd_info *mtd;
> >  static struct nand_chip nand_chip;
> > diff --git a/drivers/mtd/nand/raw/mxs_nand.h b/include/mxs_nand.h
> > similarity index 100%
> > rename from drivers/mtd/nand/raw/mxs_nand.h
> > rename to include/mxs_nand.h
> > --
> > 2.11.0
> >
> > _______________________________________________
> > U-Boot mailing list
> > U-Boot at lists.denx.de
> > https://lists.denx.de/listinfo/u-boot
>
> --
> 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] 13+ messages in thread

* [U-Boot] [PATCH 3/3] doc: imx: Add documentation for nandbcb command
  2019-06-14  8:37   ` Lukasz Majewski
@ 2019-06-18  7:57     ` Shyam Saini
  2019-06-18  8:04       ` Lukasz Majewski
  0 siblings, 1 reply; 13+ messages in thread
From: Shyam Saini @ 2019-06-18  7:57 UTC (permalink / raw)
  To: u-boot

Hi Lukasz,


> Hi Shyam,
>
> > Signed-off-by: Shyam Saini <shyam.saini@amarulasolutions.com>
> > ---
> >  doc/imx/common/imx6.txt | 74
> > +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74
> > insertions(+)
> >
> > diff --git a/doc/imx/common/imx6.txt b/doc/imx/common/imx6.txt
> > index eab88353f6..0b5061128c 100644
> > --- a/doc/imx/common/imx6.txt
> > +++ b/doc/imx/common/imx6.txt
> > @@ -88,3 +88,77 @@ Reading bank 4:
> >
> >  Word 0x00000002: 9f027772 00000004
> >
> > +NAND Boot on i.MX6 with SPL support
> > +--------------------------------------
> > +
> > +Writing/updating boot image in nand device is not straight forward in
> > +i.MX6 platform and it requires boot control block(BCB) to be
> > configured. +
> > +BCB contains two data structures, Firmware Configuration Block(FCB)
> > and +Discovered Bad Block Table(DBBT). FCB has nand timings, DBBT
> > search area, +and firmware. See IMX6DQRM Section 8.5.2.2
> > +for more information.
> > +
> > +We can't use 'nand write' command to write SPL/firmware image
> > directly +like other platforms does. So we need special setup to
> > write BCB block +as per IMX6QDL reference manual 'nandbcb update'
> > command do that job. +
> > +for nand boot, up on reset bootrom look for FCB structure in
> > +first block's if FCB found the nand timings are loaded for
> > +further reads. once FCB read done, DTTB will be loaded and
> > +finally firmware will be loaded which is boot image.
> > +
> > +cmd_nandbcb will create FCB these structures
> > +by taking mtd partition as an example.
>
> I think that the above sentence has a wrong order. Could you rewrite it?
I'll fix this in next version.

>
> > +- initial code will erase entire partition
> > +- followed by FCB setup, like first 2 blocks for FCB/DBBT write,
> > +  and next block for FW1/SPL
> > +- write firmware at FW1 block and
> > +- finally write fcb/dttb in first 2 block.
> > +
> > +Typical NAND BCB layout:
> > +=======================
> > +
> > +   no.of blocks = partition size / erasesize
> > +   no.of fcb/dbbt blocks = 2
> > +   FW1 offset = no.of fcb/dbbt
> > +
> > +block  0          1          2
> > +        -------------------------------
> > +       |FCB/DBBT 0|FCB/DBBT 1|  FW 1  |
> > +       --------------------------------
> > +
> > +On summary, nandbcb update will
> > +- erase the entire partition
> > +- create BCB by creating 2 FCB/BDDT block followed by
> > +  1 FW blocks based on partition size and erasesize.
> > +- fill FCB/DBBT structures
> > +- write FW/SPL in FW1
> > +- write FCB/DBBT in first 2 blocks
> > +
> > +step-1: write SPL
> > +
> > +icorem6qdl> ext4load mmc 0:1 $loadaddr SPL
> > +39936 bytes read in 10 ms (3.8 MiB/s)
> > +
> > +icorem6qdl> nandbcb update $loadaddr spl $filesize
> > +device 0 offset 0x0, size 0x9c00
> > +Erasing at 0x1c0000 -- 100% complete.
> > +NAND fw write: 0x80000 offset, 0xb000 bytes written: OK
> > +
> > +step-2: write u-boot-dtb.img
> > +
> > +icorem6qdl> nand erase.part uboot
> > +
> > +NAND erase.part: device 0 offset 0x200000, size 0x200000
> > +Erasing at 0x3c0000 -- 100% complete.
> > +OK
> > +
> > +icorem6qdl> ext4load mmc 0:1 $loadaddr u-boot-dtb.img
> > +589094 bytes read in 37 ms (15.2 MiB/s)
> > +
> > +icorem6qdl> nand write ${loadaddr} uboot ${filesize}
> > +
> > +NAND write: device 0 offset 0x200000, size 0x8fd26
> > + 589094 bytes written: OK
> > +icorem6qdl>
>
> Would it be possible to provide nandbcb show command (I guess that I
> can dump it with plain nand read)?

As of now, fcb/dbbt structure are set only with nandbcb command
so before "nand info" we have to run nandbcb atleast once.

If we consider kobs-ng in linux it prints fcb content when we write some image
so it means fcb is already populated at that time.

> It would present the FCB/DBBT structure. Do you think it is
> needed/feasible ?

Not sure if is it needed or not
if you have any proposal or suggestion about this then please let me know.

Thanks a lot,
Shyam





> Best regards,
>
> Lukasz Majewski
>
> --
>
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma at denx.de

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

* [U-Boot] [PATCH 3/3] doc: imx: Add documentation for nandbcb command
  2019-06-18  7:57     ` Shyam Saini
@ 2019-06-18  8:04       ` Lukasz Majewski
  2019-06-18  8:28         ` Shyam Saini
  0 siblings, 1 reply; 13+ messages in thread
From: Lukasz Majewski @ 2019-06-18  8:04 UTC (permalink / raw)
  To: u-boot

On Tue, 18 Jun 2019 13:27:13 +0530
Shyam Saini <shyam.saini@amarulasolutions.com> wrote:

> Hi Lukasz,
> 
> 
> > Hi Shyam,
> >  
> > > Signed-off-by: Shyam Saini <shyam.saini@amarulasolutions.com>
> > > ---
> > >  doc/imx/common/imx6.txt | 74
> > > +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed,
> > > 74 insertions(+)
> > >
> > > diff --git a/doc/imx/common/imx6.txt b/doc/imx/common/imx6.txt
> > > index eab88353f6..0b5061128c 100644
> > > --- a/doc/imx/common/imx6.txt
> > > +++ b/doc/imx/common/imx6.txt
> > > @@ -88,3 +88,77 @@ Reading bank 4:
> > >
> > >  Word 0x00000002: 9f027772 00000004
> > >
> > > +NAND Boot on i.MX6 with SPL support
> > > +--------------------------------------
> > > +
> > > +Writing/updating boot image in nand device is not straight
> > > forward in +i.MX6 platform and it requires boot control
> > > block(BCB) to be configured. +
> > > +BCB contains two data structures, Firmware Configuration
> > > Block(FCB) and +Discovered Bad Block Table(DBBT). FCB has nand
> > > timings, DBBT search area, +and firmware. See IMX6DQRM Section
> > > 8.5.2.2 +for more information.
> > > +
> > > +We can't use 'nand write' command to write SPL/firmware image
> > > directly +like other platforms does. So we need special setup to
> > > write BCB block +as per IMX6QDL reference manual 'nandbcb update'
> > > command do that job. +
> > > +for nand boot, up on reset bootrom look for FCB structure in
> > > +first block's if FCB found the nand timings are loaded for
> > > +further reads. once FCB read done, DTTB will be loaded and
> > > +finally firmware will be loaded which is boot image.
> > > +
> > > +cmd_nandbcb will create FCB these structures
> > > +by taking mtd partition as an example.  
> >
> > I think that the above sentence has a wrong order. Could you
> > rewrite it?  
> I'll fix this in next version.
> 
> >  
> > > +- initial code will erase entire partition
> > > +- followed by FCB setup, like first 2 blocks for FCB/DBBT write,
> > > +  and next block for FW1/SPL
> > > +- write firmware at FW1 block and
> > > +- finally write fcb/dttb in first 2 block.
> > > +
> > > +Typical NAND BCB layout:
> > > +=======================
> > > +
> > > +   no.of blocks = partition size / erasesize
> > > +   no.of fcb/dbbt blocks = 2
> > > +   FW1 offset = no.of fcb/dbbt
> > > +
> > > +block  0          1          2
> > > +        -------------------------------
> > > +       |FCB/DBBT 0|FCB/DBBT 1|  FW 1  |
> > > +       --------------------------------
> > > +
> > > +On summary, nandbcb update will
> > > +- erase the entire partition
> > > +- create BCB by creating 2 FCB/BDDT block followed by
> > > +  1 FW blocks based on partition size and erasesize.
> > > +- fill FCB/DBBT structures
> > > +- write FW/SPL in FW1
> > > +- write FCB/DBBT in first 2 blocks
> > > +
> > > +step-1: write SPL
> > > +  
> > > +icorem6qdl> ext4load mmc 0:1 $loadaddr SPL  
> > > +39936 bytes read in 10 ms (3.8 MiB/s)
> > > +  
> > > +icorem6qdl> nandbcb update $loadaddr spl $filesize  
> > > +device 0 offset 0x0, size 0x9c00
> > > +Erasing at 0x1c0000 -- 100% complete.
> > > +NAND fw write: 0x80000 offset, 0xb000 bytes written: OK
> > > +
> > > +step-2: write u-boot-dtb.img
> > > +  
> > > +icorem6qdl> nand erase.part uboot  
> > > +
> > > +NAND erase.part: device 0 offset 0x200000, size 0x200000
> > > +Erasing at 0x3c0000 -- 100% complete.
> > > +OK
> > > +  
> > > +icorem6qdl> ext4load mmc 0:1 $loadaddr u-boot-dtb.img  
> > > +589094 bytes read in 37 ms (15.2 MiB/s)
> > > +  
> > > +icorem6qdl> nand write ${loadaddr} uboot ${filesize}  
> > > +
> > > +NAND write: device 0 offset 0x200000, size 0x8fd26
> > > + 589094 bytes written: OK  
> > > +icorem6qdl>  
> >
> > Would it be possible to provide nandbcb show command (I guess that I
> > can dump it with plain nand read)?  
> 
> As of now, fcb/dbbt structure are set only with nandbcb command
> so before "nand info" we have to run nandbcb atleast once.
> 
> If we consider kobs-ng in linux it prints fcb content when we write
> some image so it means fcb is already populated at that time.
> 
> > It would present the FCB/DBBT structure. Do you think it is
> > needed/feasible ?  
> 
> Not sure if is it needed or not
> if you have any proposal or suggestion about this then please let me
> know.

The idea/use case which I do think of is as follows:

1. I do receive a board with BCB written by bootloader from board
vendor. It has parameters to configure the nand

2. I do use some command to read those parameters - to avoid situation
that I lost them after first update (nand dump shall do the trick +
hexeditor). Those parameters would be presented in a form easier to
read/store than ones from hexeditor

3. I use nandbcb command to store those values read previously.

> 
> Thanks a lot,
> Shyam
> 
> 
> 
> 
> 
> > Best regards,
> >
> > Lukasz Majewski
> >
> > --
> >
> > DENX Software Engineering GmbH,      Managing Director: Wolfgang
> > Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell,
> > Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email:
> > lukma at denx.de  




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma at denx.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20190618/6cd4c72f/attachment.sig>

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

* [U-Boot] [PATCH 3/3] doc: imx: Add documentation for nandbcb command
  2019-06-18  8:04       ` Lukasz Majewski
@ 2019-06-18  8:28         ` Shyam Saini
  2019-06-18  8:36           ` Lukasz Majewski
  0 siblings, 1 reply; 13+ messages in thread
From: Shyam Saini @ 2019-06-18  8:28 UTC (permalink / raw)
  To: u-boot

> On Tue, 18 Jun 2019 13:27:13 +0530
> Shyam Saini <shyam.saini@amarulasolutions.com> wrote:
>
> > Hi Lukasz,
> >
> >
> > > Hi Shyam,
> > >
> > > > Signed-off-by: Shyam Saini <shyam.saini@amarulasolutions.com>
> > > > ---
> > > >  doc/imx/common/imx6.txt | 74
> > > > +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed,
> > > > 74 insertions(+)
> > > >
> > > > diff --git a/doc/imx/common/imx6.txt b/doc/imx/common/imx6.txt
> > > > index eab88353f6..0b5061128c 100644
> > > > --- a/doc/imx/common/imx6.txt
> > > > +++ b/doc/imx/common/imx6.txt
> > > > @@ -88,3 +88,77 @@ Reading bank 4:
> > > >
> > > >  Word 0x00000002: 9f027772 00000004
> > > >
> > > > +NAND Boot on i.MX6 with SPL support
> > > > +--------------------------------------
> > > > +
> > > > +Writing/updating boot image in nand device is not straight
> > > > forward in +i.MX6 platform and it requires boot control
> > > > block(BCB) to be configured. +
> > > > +BCB contains two data structures, Firmware Configuration
> > > > Block(FCB) and +Discovered Bad Block Table(DBBT). FCB has nand
> > > > timings, DBBT search area, +and firmware. See IMX6DQRM Section
> > > > 8.5.2.2 +for more information.
> > > > +
> > > > +We can't use 'nand write' command to write SPL/firmware image
> > > > directly +like other platforms does. So we need special setup to
> > > > write BCB block +as per IMX6QDL reference manual 'nandbcb update'
> > > > command do that job. +
> > > > +for nand boot, up on reset bootrom look for FCB structure in
> > > > +first block's if FCB found the nand timings are loaded for
> > > > +further reads. once FCB read done, DTTB will be loaded and
> > > > +finally firmware will be loaded which is boot image.
> > > > +
> > > > +cmd_nandbcb will create FCB these structures
> > > > +by taking mtd partition as an example.
> > >
> > > I think that the above sentence has a wrong order. Could you
> > > rewrite it?
> > I'll fix this in next version.
> >
> > >
> > > > +- initial code will erase entire partition
> > > > +- followed by FCB setup, like first 2 blocks for FCB/DBBT write,
> > > > +  and next block for FW1/SPL
> > > > +- write firmware at FW1 block and
> > > > +- finally write fcb/dttb in first 2 block.
> > > > +
> > > > +Typical NAND BCB layout:
> > > > +=======================
> > > > +
> > > > +   no.of blocks = partition size / erasesize
> > > > +   no.of fcb/dbbt blocks = 2
> > > > +   FW1 offset = no.of fcb/dbbt
> > > > +
> > > > +block  0          1          2
> > > > +        -------------------------------
> > > > +       |FCB/DBBT 0|FCB/DBBT 1|  FW 1  |
> > > > +       --------------------------------
> > > > +
> > > > +On summary, nandbcb update will
> > > > +- erase the entire partition
> > > > +- create BCB by creating 2 FCB/BDDT block followed by
> > > > +  1 FW blocks based on partition size and erasesize.
> > > > +- fill FCB/DBBT structures
> > > > +- write FW/SPL in FW1
> > > > +- write FCB/DBBT in first 2 blocks
> > > > +
> > > > +step-1: write SPL
> > > > +
> > > > +icorem6qdl> ext4load mmc 0:1 $loadaddr SPL
> > > > +39936 bytes read in 10 ms (3.8 MiB/s)
> > > > +
> > > > +icorem6qdl> nandbcb update $loadaddr spl $filesize
> > > > +device 0 offset 0x0, size 0x9c00
> > > > +Erasing at 0x1c0000 -- 100% complete.
> > > > +NAND fw write: 0x80000 offset, 0xb000 bytes written: OK
> > > > +
> > > > +step-2: write u-boot-dtb.img
> > > > +
> > > > +icorem6qdl> nand erase.part uboot
> > > > +
> > > > +NAND erase.part: device 0 offset 0x200000, size 0x200000
> > > > +Erasing at 0x3c0000 -- 100% complete.
> > > > +OK
> > > > +
> > > > +icorem6qdl> ext4load mmc 0:1 $loadaddr u-boot-dtb.img
> > > > +589094 bytes read in 37 ms (15.2 MiB/s)
> > > > +
> > > > +icorem6qdl> nand write ${loadaddr} uboot ${filesize}
> > > > +
> > > > +NAND write: device 0 offset 0x200000, size 0x8fd26
> > > > + 589094 bytes written: OK
> > > > +icorem6qdl>
> > >
> > > Would it be possible to provide nandbcb show command (I guess that I
> > > can dump it with plain nand read)?
> >
> > As of now, fcb/dbbt structure are set only with nandbcb command
> > so before "nand info" we have to run nandbcb atleast once.
> >
> > If we consider kobs-ng in linux it prints fcb content when we write
> > some image so it means fcb is already populated at that time.
> >
> > > It would present the FCB/DBBT structure. Do you think it is
> > > needed/feasible ?
> >
> > Not sure if is it needed or not
> > if you have any proposal or suggestion about this then please let me
> > know.
>
> The idea/use case which I do think of is as follows:
>
> 1. I do receive a board with BCB written by bootloader from board
> vendor. It has parameters to configure the nand
>
> 2. I do use some command to read those parameters - to avoid situation
> that I lost them after first update (nand dump shall do the trick +
> hexeditor). Those parameters would be presented in a form easier to
> read/store than ones from hexeditor
>
> 3. I use nandbcb command to store those values read previously.

okay, it means simply printing fcb structure elements no matter it is
populated or not.
Is this you are suggesting ?

>
> >
> > Thanks a lot,
> > Shyam
> >
> >
> >
> >
> >
> > > Best regards,
> > >
> > > Lukasz Majewski
> > >
> > > --
> > >
> > > DENX Software Engineering GmbH,      Managing Director: Wolfgang
> > > Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell,
> > > Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email:
> > > lukma at denx.de
>
>
>
>
> Best regards,
>
> Lukasz Majewski
>
> --
>
> DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
> HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
> Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma at denx.de

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

* [U-Boot] [PATCH 3/3] doc: imx: Add documentation for nandbcb command
  2019-06-18  8:28         ` Shyam Saini
@ 2019-06-18  8:36           ` Lukasz Majewski
  0 siblings, 0 replies; 13+ messages in thread
From: Lukasz Majewski @ 2019-06-18  8:36 UTC (permalink / raw)
  To: u-boot

On Tue, 18 Jun 2019 13:58:38 +0530
Shyam Saini <shyam.saini@amarulasolutions.com> wrote:

> > On Tue, 18 Jun 2019 13:27:13 +0530
> > Shyam Saini <shyam.saini@amarulasolutions.com> wrote:
> >  
> > > Hi Lukasz,
> > >
> > >  
> > > > Hi Shyam,
> > > >  
> > > > > Signed-off-by: Shyam Saini <shyam.saini@amarulasolutions.com>
> > > > > ---
> > > > >  doc/imx/common/imx6.txt | 74
> > > > > +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file
> > > > > changed, 74 insertions(+)
> > > > >
> > > > > diff --git a/doc/imx/common/imx6.txt b/doc/imx/common/imx6.txt
> > > > > index eab88353f6..0b5061128c 100644
> > > > > --- a/doc/imx/common/imx6.txt
> > > > > +++ b/doc/imx/common/imx6.txt
> > > > > @@ -88,3 +88,77 @@ Reading bank 4:
> > > > >
> > > > >  Word 0x00000002: 9f027772 00000004
> > > > >
> > > > > +NAND Boot on i.MX6 with SPL support
> > > > > +--------------------------------------
> > > > > +
> > > > > +Writing/updating boot image in nand device is not straight
> > > > > forward in +i.MX6 platform and it requires boot control
> > > > > block(BCB) to be configured. +
> > > > > +BCB contains two data structures, Firmware Configuration
> > > > > Block(FCB) and +Discovered Bad Block Table(DBBT). FCB has nand
> > > > > timings, DBBT search area, +and firmware. See IMX6DQRM Section
> > > > > 8.5.2.2 +for more information.
> > > > > +
> > > > > +We can't use 'nand write' command to write SPL/firmware image
> > > > > directly +like other platforms does. So we need special setup
> > > > > to write BCB block +as per IMX6QDL reference manual 'nandbcb
> > > > > update' command do that job. +
> > > > > +for nand boot, up on reset bootrom look for FCB structure in
> > > > > +first block's if FCB found the nand timings are loaded for
> > > > > +further reads. once FCB read done, DTTB will be loaded and
> > > > > +finally firmware will be loaded which is boot image.
> > > > > +
> > > > > +cmd_nandbcb will create FCB these structures
> > > > > +by taking mtd partition as an example.  
> > > >
> > > > I think that the above sentence has a wrong order. Could you
> > > > rewrite it?  
> > > I'll fix this in next version.
> > >  
> > > >  
> > > > > +- initial code will erase entire partition
> > > > > +- followed by FCB setup, like first 2 blocks for FCB/DBBT
> > > > > write,
> > > > > +  and next block for FW1/SPL
> > > > > +- write firmware at FW1 block and
> > > > > +- finally write fcb/dttb in first 2 block.
> > > > > +
> > > > > +Typical NAND BCB layout:
> > > > > +=======================
> > > > > +
> > > > > +   no.of blocks = partition size / erasesize
> > > > > +   no.of fcb/dbbt blocks = 2
> > > > > +   FW1 offset = no.of fcb/dbbt
> > > > > +
> > > > > +block  0          1          2
> > > > > +        -------------------------------
> > > > > +       |FCB/DBBT 0|FCB/DBBT 1|  FW 1  |
> > > > > +       --------------------------------
> > > > > +
> > > > > +On summary, nandbcb update will
> > > > > +- erase the entire partition
> > > > > +- create BCB by creating 2 FCB/BDDT block followed by
> > > > > +  1 FW blocks based on partition size and erasesize.
> > > > > +- fill FCB/DBBT structures
> > > > > +- write FW/SPL in FW1
> > > > > +- write FCB/DBBT in first 2 blocks
> > > > > +
> > > > > +step-1: write SPL
> > > > > +  
> > > > > +icorem6qdl> ext4load mmc 0:1 $loadaddr SPL  
> > > > > +39936 bytes read in 10 ms (3.8 MiB/s)
> > > > > +  
> > > > > +icorem6qdl> nandbcb update $loadaddr spl $filesize  
> > > > > +device 0 offset 0x0, size 0x9c00
> > > > > +Erasing at 0x1c0000 -- 100% complete.
> > > > > +NAND fw write: 0x80000 offset, 0xb000 bytes written: OK
> > > > > +
> > > > > +step-2: write u-boot-dtb.img
> > > > > +  
> > > > > +icorem6qdl> nand erase.part uboot  
> > > > > +
> > > > > +NAND erase.part: device 0 offset 0x200000, size 0x200000
> > > > > +Erasing at 0x3c0000 -- 100% complete.
> > > > > +OK
> > > > > +  
> > > > > +icorem6qdl> ext4load mmc 0:1 $loadaddr u-boot-dtb.img  
> > > > > +589094 bytes read in 37 ms (15.2 MiB/s)
> > > > > +  
> > > > > +icorem6qdl> nand write ${loadaddr} uboot ${filesize}  
> > > > > +
> > > > > +NAND write: device 0 offset 0x200000, size 0x8fd26
> > > > > + 589094 bytes written: OK  
> > > > > +icorem6qdl>  
> > > >
> > > > Would it be possible to provide nandbcb show command (I guess
> > > > that I can dump it with plain nand read)?  
> > >
> > > As of now, fcb/dbbt structure are set only with nandbcb command
> > > so before "nand info" we have to run nandbcb atleast once.
> > >
> > > If we consider kobs-ng in linux it prints fcb content when we
> > > write some image so it means fcb is already populated at that
> > > time. 
> > > > It would present the FCB/DBBT structure. Do you think it is
> > > > needed/feasible ?  
> > >
> > > Not sure if is it needed or not
> > > if you have any proposal or suggestion about this then please let
> > > me know.  
> >
> > The idea/use case which I do think of is as follows:
> >
> > 1. I do receive a board with BCB written by bootloader from board
> > vendor. It has parameters to configure the nand
> >
> > 2. I do use some command to read those parameters - to avoid
> > situation that I lost them after first update (nand dump shall do
> > the trick + hexeditor). Those parameters would be presented in a
> > form easier to read/store than ones from hexeditor
> >
> > 3. I use nandbcb command to store those values read previously.  
> 
> okay, it means simply printing fcb structure elements no matter it is
> populated or not.
> Is this you are suggesting ?

I think yes. To have it in a more readable format.

> 
> >  
> > >
> > > Thanks a lot,
> > > Shyam
> > >
> > >
> > >
> > >
> > >  
> > > > Best regards,
> > > >
> > > > Lukasz Majewski
> > > >
> > > > --
> > > >
> > > > DENX Software Engineering GmbH,      Managing Director: Wolfgang
> > > > Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194
> > > > Groebenzell, Germany Phone: (+49)-8142-66989-59 Fax:
> > > > (+49)-8142-66989-80 Email: lukma at denx.de  
> >
> >
> >
> >
> > Best regards,
> >
> > Lukasz Majewski
> >
> > --
> >
> > DENX Software Engineering GmbH,      Managing Director: Wolfgang
> > Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell,
> > Germany Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email:
> > lukma at denx.de  




Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma at denx.de
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20190618/553bce65/attachment.sig>

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

* [U-Boot] [PATCH v6 1/3] i.MX6: nand: add nandbcb command for imx
  2019-06-18  7:54   ` Shyam Saini
@ 2019-06-28 17:46     ` Parthiban Nallathambi
  0 siblings, 0 replies; 13+ messages in thread
From: Parthiban Nallathambi @ 2019-06-28 17:46 UTC (permalink / raw)
  To: u-boot

Hello Shyam,

On 6/18/19 9:54 AM, Shyam Saini wrote:
> Hi Igor,
> 
>> Hi Shyam,
>>
>> On Fri, Jun 14, 2019 at 10:37 AM Shyam Saini
>> <shyam.saini@amarulasolutions.com> wrote:
>>>
>>> Writing/updating boot image in nand device is not
>>> straight forward in i.MX6 platform and it requires
>>> boot control block(BCB) to be configured.
>>>
>>> It becomes difficult to use uboot 'nand' command to
>>> write BCB since it requires platform specific attributes
>>> need to be taken care of.
>>>
>>> It is even difficult to use existing msx-nand.c driver by
>>> incorporating BCB attributes like mxs_dma_desc does
>>> because it requires change in mtd and nand command.
>>>
>>> So, cmd_nandbcb implemented in arch/arm/mach-imx
>>>
>>> BCB contains two data structures, Firmware Configuration Block(FCB)
>>> and Discovered Bad Block Table(DBBT). FCB has nand timings,
>>> DBBT search area, page address of firmware.
>>>
>>> On summary, nandbcb update will
>>> - erase the entire partition
>>> - create BCB by creating 2 FCB/DBBT block followed by
>>>   1 FW block based on partition size and erasesize.
>>> - fill FCB/DBBT structures
>>> - write FW/SPL on FW1
>>> - write FCB/DBBT in first 2 blocks
>>>
>>> for nand boot, up on reset bootrom look for FCB structure in
>>> first block's if FCB found the nand timings are loaded for
>>> further reads. once FCB read done, DTTB will load and finally
>>> firmware will be loaded which is boot image.
>>>
>>> Refer section "NAND Boot" from doc/imx/common/imx6.txt for more usage
>>> information.
>>>
>>> Reviewed-by: Stefano Babic <sbabic@denx.de>
>>> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
>>> Signed-off-by: Sergey Kubushyn <ksi@koi8.net>
>>> Signed-off-by: Shyam Saini <shyam.saini@amarulasolutions.com>
>>> ---
>>> Changes for v6:
>>> - Consolidate v5 patch 1 and patch 2 into one single patch
>>> - Make separate docs patch out of v5 patch 1
>>>
>>> Changes for v5:
>>> - Move mxs_nand.h file from drivers/mtd/nand/raw/ to include/ directory so
>>>   that it can be used by both drivers/ and arch/
>>> - Fix command steps output in docs
>>>
>>> Changes for v4:
>>> - Remove obselete apis and use bch_geometry structure for calculating
>>>   ecc level, bad block start bit and bad block byte
>>> - Write firmware only once
>>> - Shorten variable names
>>> - Update commit message
>>> - Update docs as per current patch
>>> - Fix checkpatch warnings
>>>
>>> Changes for v3:
>>> - Fixed multi-line comments
>>> - Better error handling for failed allocations
>>>
>>> Changes for v2:
>>> - Fixed commit message notes
>>> - Updated proper commit message
>>> - Update doc/README.imx6 with NAND boot details
>>> - Fixed long length variable names.
>>> - Fixed Gigantic variable name.
>>> - NULL checks for kzalloc
>>> - Move Kconfig option in separate patch
>>> - Fixed checkpatch warninigs
>>>
>>>  arch/arm/include/asm/mach-imx/imx-nandbcb.h  | 111 ++++++++
>>>  arch/arm/mach-imx/Kconfig                    |  11 +
>>>  arch/arm/mach-imx/Makefile                   |   1 +
>>>  arch/arm/mach-imx/cmd_nandbcb.c              | 369 +++++++++++++++++++++++++++
>>>  drivers/mtd/nand/raw/mxs_nand.c              |   2 +-
>>>  drivers/mtd/nand/raw/mxs_nand_dt.c           |   2 +-
>>>  drivers/mtd/nand/raw/mxs_nand_spl.c          |   2 +-
>>>  {drivers/mtd/nand/raw => include}/mxs_nand.h |   0
>>>  8 files changed, 495 insertions(+), 3 deletions(-)
>>>  create mode 100644 arch/arm/include/asm/mach-imx/imx-nandbcb.h
>>>  create mode 100644 arch/arm/mach-imx/cmd_nandbcb.c
>>>  rename {drivers/mtd/nand/raw => include}/mxs_nand.h (100%)
>>>
>>> diff --git a/arch/arm/include/asm/mach-imx/imx-nandbcb.h b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
>>> new file mode 100644
>>> index 0000000000..033659a038
>>> --- /dev/null
>>> +++ b/arch/arm/include/asm/mach-imx/imx-nandbcb.h
>>> @@ -0,0 +1,111 @@
>>> +/*
>>> + * Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com>
>>> + *
>>> + * SPDX-License-Identifier:    GPL-2.0+
>>> + */
>>> +
>>> +#ifndef _IMX_NAND_BCB_H_
>>> +#define _IMX_NAND_BCB_H_
>>> +
>>> +#define FCB_FINGERPRINT                0x20424346      /* 'FCB' */
>>> +#define FCB_VERSION_1          0x01000000
>>> +
>>> +#define DBBT_FINGERPRINT2      0x54424244      /* 'DBBT' */
>>> +#define DBBT_VERSION_1         0x01000000
>>> +
>>> +struct dbbt_block {
>>> +       u32 checksum;   /* reserved on i.MX6 */
>>> +       u32 fingerprint;
>>> +       u32 version;
>>> +       u32 numberbb;   /* reserved on i.MX6 */
>>> +       u32 dbbtpages;
>>> +};
>>> +
>>> +struct fcb_block {
>>> +       u32 checksum;           /* First fingerprint in first byte */
>>> +       u32 fingerprint;        /* 2nd fingerprint at byte 4 */
>>> +       u32 version;            /* 3rd fingerprint at byte 8 */
>>> +       u8 datasetup;
>>> +       u8 datahold;
>>> +       u8 addr_setup;
>>> +       u8 dsample_time;
>>> +
>>> +       /* These are for application use only and not for ROM. */
>>> +       u8 nandtiming;
>>> +       u8 rea;
>>> +       u8 rloh;
>>> +       u8 rhoh;
>>> +       u32 pagesize;           /* 2048 for 2K pages, 4096 for 4K pages */
>>> +       u32 oob_pagesize;       /* 2112 for 2K pages, 4314 for 4K pages */
>>> +       u32 sectors;            /* Number of 2K sections per block */
>>> +       u32 nr_nand;            /* Total Number of NANDs - not used by ROM */
>>> +       u32 nr_die;             /* Number of separate chips in this NAND */
>>> +       u32 celltype;           /* MLC or SLC */
>>> +       u32 ecc_type;           /* Type of ECC, can be one of BCH-0-20 */
>>> +       u32 ecc_nr;             /* Number of bytes for Block0 - BCH */
>>> +
>>> +       /* Block size in bytes for all blocks other than Block0 - BCH */
>>> +       u32 ecc_size;
>>> +       u32 ecc_level;          /* Ecc level for Block 0 - BCH */
>>> +       u32 meta_size;          /* Metadata size - BCH */
>>> +       /* Number of blocks per page for ROM use - BCH */
>>> +       u32 nr_blocks;
>>> +       u32 ecc_type_sdk;       /* Type of ECC, can be one of BCH-0-20 */
>>> +       u32 ecc_nr_sdk;         /* Number of bytes for Block0 - BCH */
>>> +       /* Block size in bytes for all blocks other than Block0 - BCH */
>>> +       u32 ecc_size_sdk;
>>> +       u32 ecc_level_sdk;      /* Ecc level for Block 0 - BCH */
>>> +       /* Number of blocks per page for SDK use - BCH */
>>> +       u32 nr_blocks_sdk;
>>> +       u32 meta_size_sdk;      /* Metadata size - BCH */
>>> +       u32 erase_th;           /* To set into BCH_MODE register */
>>> +
>>> +       /*
>>> +        * 0: normal boot
>>> +        * 1: to load patch starting next to FCB
>>> +        */
>>> +       u32 bootpatch;
>>> +       u32 patch_size; /* Size of patch in sectors */
>>> +       u32 fw1_start;  /* Firmware image starts on this sector */
>>> +       u32 fw2_start;  /* Secondary FW Image starting Sector */
>>> +       u32 fw1_pages;  /* Number of sectors in firmware image */
>>> +       u32 fw2_pages;  /* Number of sector in secondary FW image */
>>> +       u32 dbbt_start; /* Page address where dbbt search area begins */
>>> +
>>> +       /*
>>> +        * Byte in page data that have manufacturer marked bad block marker,
>>> +        * this will be swapped with metadata[0] to complete page data.
>>> +        */
>>> +       u32 bb_byte;
>>> +
>>> +       /*
>>> +        * For BCH ECC sizes other than 8 and 16 the bad block marker does not
>>> +        * start at 0th bit of bb_byte. This field is used to get to
>>> +        * the start bit of bad block marker byte with in bb_byte
>>> +        */
>>> +       u32 bb_start_bit;
>>> +
>>> +       /*
>>> +        * FCB value that gives byte offset for
>>> +        * bad block marker on physical NAND page
>>> +        */
>>> +       u32 phy_offset;
>>> +       u32 bchtype;
>>> +
>>> +       u32 readlatency;
>>> +       u32 predelay;
>>> +       u32 cedelay;
>>> +       u32 postdelay;
>>> +       u32 cmdaddpause;
>>> +       u32 datapause;
>>> +       u32 tmspeed;
>>> +       u32 busytimeout;
>>> +
>>> +       /* the flag to enable (1)/disable(0) bi swap */
>>> +       u32 disbbm;
>>> +
>>> +       /* The swap position of main area in spare area */
>>> +       u32 spare_offset;
>>> +};
>>> +
>>> +#endif /* _IMX_NAND_BCB_H_ */
>>> diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
>>> index ec09ef240f..5dd286f9a7 100644
>>> --- a/arch/arm/mach-imx/Kconfig
>>> +++ b/arch/arm/mach-imx/Kconfig
>>> @@ -71,6 +71,17 @@ config CMD_HDMIDETECT
>>>           This enables the 'hdmidet' command which detects if an HDMI monitor
>>>           is connected.
>>>
>>> +config CMD_NANDBCB
>>> +       bool "i.MX6 NAND Boot Control Block(BCB) command"
>>> +       depends on NAND && CMD_MTDPARTS
>>> +       default y if ARCH_MX6 && NAND_MXS
>>
>> Just curious, are there any plans to enable this also for ARCH_MX7?
>> I've just compared bcb definition here and in imx-kobs (it also includes
>> NANDTM timings etc, which are actual for iMX7), so I assume it should
>> also work for iMX7 SoCs out of the box
> 
> Yes, it is true that we are using original structure from kobs-ng but
> this current patch
> only supports imx6q variants and we are working on to add suppport for imx6ul(l)

What's the potential changes required for imx6UL? I am currently in need of booting
the SPL from NAND, but currently getting it done using kobs-ng.

Thanks,
Parthiban N

> 
> We don't have any imx7 board so no plan for imx7. But, it would be
> great help if you
> could add support for imx7 :-)
> 
> 
> Thanks
> 
>>
>>> +       help
>>> +         Unlike normal 'nand write/erase' commands, this command update
>>> +         Boot Control Block(BCB) for i.MX6 platform NAND IP's.
>>> +
>>> +         This is similar to kobs-ng, which is used in Linux as separate
>>> +         rootfs package.
>>> +
>>>  config NXP_BOARD_REVISION
>>>         bool "Read NXP board revision from fuses"
>>>         depends on ARCH_MX6 || ARCH_MX7
>>> diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
>>> index c46984994a..96f0b89fd1 100644
>>> --- a/arch/arm/mach-imx/Makefile
>>> +++ b/arch/arm/mach-imx/Makefile
>>> @@ -59,6 +59,7 @@ ifneq ($(CONFIG_SPL_BUILD),y)
>>>  obj-$(CONFIG_CMD_BMODE) += cmd_bmode.o
>>>  obj-$(CONFIG_CMD_HDMIDETECT) += cmd_hdmidet.o
>>>  obj-$(CONFIG_CMD_DEKBLOB) += cmd_dek.o
>>> +obj-$(CONFIG_CMD_NANDBCB) += cmd_nandbcb.o
>>>  endif
>>>
>>>  PLUGIN = board/$(BOARDDIR)/plugin
>>> diff --git a/arch/arm/mach-imx/cmd_nandbcb.c b/arch/arm/mach-imx/cmd_nandbcb.c
>>> new file mode 100644
>>> index 0000000000..065b814b2e
>>> --- /dev/null
>>> +++ b/arch/arm/mach-imx/cmd_nandbcb.c
>>> @@ -0,0 +1,369 @@
>>> +/*
>>> + * i.MX6 nand boot control block(bcb).
>>> + *
>>> + * Based on the common/imx-bbu-nand-fcb.c from barebox and imx kobs-ng
>>> + *
>>> + * Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com>
>>> + * Copyright (C) 2016 Sergey Kubushyn <ksi@koi8.net>
>>> + *
>>> + * SPDX-License-Identifier:    GPL-2.0+
>>> + */
>>> +
>>> +#include <common.h>
>>> +#include <nand.h>
>>> +
>>> +#include <asm/io.h>
>>> +#include <jffs2/jffs2.h>
>>> +#include <linux/mtd/mtd.h>
>>> +
>>> +#include <asm/mach-imx/imx-nandbcb.h>
>>> +#include <asm/mach-imx/imximage.cfg>
>>> +#include <mxs_nand.h>
>>> +#include <linux/mtd/mtd.h>
>>> +#include <nand.h>
>>> +
>>> +#define BF_VAL(v, bf)          (((v) & bf##_MASK) >> bf##_OFFSET)
>>> +#define GETBIT(v, n)           (((v) >> (n)) & 0x1)
>>> +
>>> +static u8 calculate_parity_13_8(u8 d)
>>> +{
>>> +       u8 p = 0;
>>> +
>>> +       p |= (GETBIT(d, 6) ^ GETBIT(d, 5) ^ GETBIT(d, 3) ^ GETBIT(d, 2)) << 0;
>>> +       p |= (GETBIT(d, 7) ^ GETBIT(d, 5) ^ GETBIT(d, 4) ^ GETBIT(d, 2) ^
>>> +             GETBIT(d, 1)) << 1;
>>> +       p |= (GETBIT(d, 7) ^ GETBIT(d, 6) ^ GETBIT(d, 5) ^ GETBIT(d, 1) ^
>>> +             GETBIT(d, 0)) << 2;
>>> +       p |= (GETBIT(d, 7) ^ GETBIT(d, 4) ^ GETBIT(d, 3) ^ GETBIT(d, 0)) << 3;
>>> +       p |= (GETBIT(d, 6) ^ GETBIT(d, 4) ^ GETBIT(d, 3) ^ GETBIT(d, 2) ^
>>> +             GETBIT(d, 1) ^ GETBIT(d, 0)) << 4;
>>> +
>>> +       return p;
>>> +}
>>> +
>>> +static void encode_hamming_13_8(void *_src, void *_ecc, size_t size)
>>> +{
>>> +       int i;
>>> +       u8 *src = _src;
>>> +       u8 *ecc = _ecc;
>>> +
>>> +       for (i = 0; i < size; i++)
>>> +               ecc[i] = calculate_parity_13_8(src[i]);
>>> +}
>>> +
>>> +static u32 calc_chksum(void *buf, size_t size)
>>> +{
>>> +       u32 chksum = 0;
>>> +       u8 *bp = buf;
>>> +       size_t i;
>>> +
>>> +       for (i = 0; i < size; i++)
>>> +               chksum += bp[i];
>>> +
>>> +       return ~chksum;
>>> +}
>>> +
>>> +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);
>>> +
>>> +       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;
>>> +
>>> +       /* 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;
>>> +
>>> +       /* DBBT search area starts at second page on first block */
>>> +       fcb->dbbt_start = 1;
>>> +
>>> +       fcb->bb_byte = nand_info->bch_geometry.block_mark_byte_offset;
>>> +       fcb->bb_start_bit = nand_info->bch_geometry.block_mark_bit_offset;
>>> +
>>> +       fcb->phy_offset = mtd->writesize;
>>> +
>>> +       fcb->nr_blocks = mtd->writesize / fcb->ecc_nr - 1;
>>> +
>>> +       fcb->checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
>>> +}
>>> +
>>> +static int dbbt_fill_data(struct mtd_info *mtd, void *buf, int num_blocks)
>>> +{
>>> +       int n, n_bad_blocks = 0;
>>> +       u32 *bb = buf + 0x8;
>>> +       u32 *n_bad_blocksp = buf + 0x4;
>>> +
>>> +       for (n = 0; n < num_blocks; n++) {
>>> +               loff_t offset = n * mtd->erasesize;
>>> +                       if (mtd_block_isbad(mtd, offset)) {
>>> +                               n_bad_blocks++;
>>> +                               *bb = n;
>>> +                               bb++;
>>> +               }
>>> +       }
>>> +
>>> +       *n_bad_blocksp = n_bad_blocks;
>>> +
>>> +       return n_bad_blocks;
>>> +}
>>> +
>>> +static int nandbcb_update(struct mtd_info *mtd, loff_t off, size_t size,
>>> +                         size_t maxsize, const u_char *buf)
>>> +{
>>> +       nand_erase_options_t opts;
>>> +       struct fcb_block *fcb;
>>> +       struct dbbt_block *dbbt;
>>> +       loff_t fw1_off;
>>> +       void *fwbuf, *fcb_raw_page, *dbbt_page, *dbbt_data_page;
>>> +       int nr_blks, nr_blks_fcb, fw1_blk;
>>> +       size_t fwsize, dummy;
>>> +       int i, ret;
>>> +
>>> +       /* erase */
>>> +       memset(&opts, 0, sizeof(opts));
>>> +       opts.offset = off;
>>> +       opts.length = maxsize - 1;
>>> +       ret = nand_erase_opts(mtd, &opts);
>>> +       if (ret) {
>>> +               printf("%s: erase failed (ret = %d)\n", __func__, ret);
>>> +               return ret;
>>> +       }
>>> +
>>> +       /*
>>> +        * Reference documentation from i.MX6DQRM section 8.5.2.2
>>> +        *
>>> +        * Nand Boot Control Block(BCB) contains two data structures,
>>> +        * - Firmware Configuration Block(FCB)
>>> +        * - Discovered Bad Block Table(DBBT)
>>> +        *
>>> +        * FCB contains,
>>> +        * - nand timings
>>> +        * - DBBT search page address,
>>> +        * - start page address of primary firmware
>>> +        * - start page address of secondary firmware
>>> +        *
>>> +        * setup fcb:
>>> +        * - number of blocks = mtd partition size / mtd erasesize
>>> +        * - two firmware blocks, primary and secondary
>>> +        * - first 4 block for FCB/DBBT
>>> +        * - rest split in half for primary and secondary firmware
>>> +        * - same firmware will write two times
>>> +        */
>>> +       nr_blks_fcb = 2;
>>> +       nr_blks = maxsize / mtd->erasesize;
>>> +       fw1_blk = nr_blks_fcb;
>>> +
>>> +       /* write fw */
>>> +       fwsize = ALIGN(size + FLASH_OFFSET_STANDARD + mtd->writesize,
>>> +                      mtd->writesize);
>>> +       fwbuf = kzalloc(fwsize, GFP_KERNEL);
>>> +       if (!fwbuf) {
>>> +               debug("failed to allocate fwbuf\n");
>>> +               ret = -ENOMEM;
>>> +               goto err;
>>> +       }
>>> +
>>> +       memcpy(fwbuf + FLASH_OFFSET_STANDARD, buf, size);
>>> +       fw1_off = fw1_blk * mtd->erasesize;
>>> +       ret = nand_write_skip_bad(mtd, fw1_off, &fwsize, NULL, maxsize,
>>> +                                 (u_char *)fwbuf, WITH_WR_VERIFY);
>>> +       printf("NAND fw write: 0x%llx offset, 0x%x bytes written: %s\n",
>>> +              fw1_off, fwsize, ret ? "ERROR" : "OK");
>>> +       if (ret)
>>> +               goto fwbuf_err;
>>> +
>>> +       /* fill fcb */
>>> +       fcb = kzalloc(sizeof(*fcb), GFP_KERNEL);
>>> +       if (!fcb) {
>>> +               debug("failed to allocate fcb\n");
>>> +               ret = -ENOMEM;
>>> +               goto fwbuf_err;
>>> +       }
>>> +
>>> +       fcb->fw1_start = (fw1_blk * mtd->erasesize) / mtd->writesize;
>>> +       fcb->fw1_pages = size / mtd->writesize + 1;
>>> +       fill_fcb(fcb, mtd);
>>> +
>>> +       /* 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, nr_blks);
>>> +       if (ret < 0)
>>> +               goto dbbt_data_page_err;
>>> +       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.
>>> +        */
>>> +       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");
>>> +
>>> +               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;
>>> +               }
>>> +       }
>>> +
>>> +fcb_raw_page_err:
>>> +       kfree(fcb_raw_page);
>>> +dbbt_data_page_err:
>>> +       kfree(dbbt_data_page);
>>> +dbbt_page_err:
>>> +       kfree(dbbt_page);
>>> +fcb_err:
>>> +       kfree(fcb);
>>> +fwbuf_err:
>>> +       kfree(fwbuf);
>>> +err:
>>> +       return ret;
>>> +}
>>> +
>>> +static int do_nandbcb_update(int argc, char * const argv[])
>>> +{
>>> +       struct mtd_info *mtd;
>>> +       loff_t addr, offset, size, maxsize;
>>> +       char *endp;
>>> +       u_char *buf;
>>> +       int dev;
>>> +       int ret;
>>> +
>>> +       if (argc != 4)
>>> +               return CMD_RET_USAGE;
>>> +
>>> +       dev = nand_curr_device;
>>> +       if (dev < 0) {
>>> +               printf("failed to get nand_curr_device, run nand device");
>>> +               return CMD_RET_FAILURE;
>>> +       }
>>> +
>>> +       addr = simple_strtoul(argv[1], &endp, 16);
>>> +       if (*argv[1] == 0 || *endp != 0)
>>> +               return CMD_RET_FAILURE;
>>> +
>>> +       mtd = get_nand_dev_by_index(dev);
>>> +       if (mtd_arg_off_size(argc - 2, argv + 2, &dev, &offset, &size,
>>> +                            &maxsize, MTD_DEV_TYPE_NAND, mtd->size))
>>> +               return CMD_RET_FAILURE;
>>> +
>>> +       buf = map_physmem(addr, size, MAP_WRBACK);
>>> +       if (!buf) {
>>> +               puts("failed to map physical memory\n");
>>> +               return CMD_RET_FAILURE;
>>> +       }
>>> +
>>> +       ret = nandbcb_update(mtd, offset, size, maxsize, buf);
>>> +
>>> +       return ret == 0 ? CMD_RET_SUCCESS : CMD_RET_FAILURE;
>>> +}
>>> +
>>> +static int do_nandbcb(cmd_tbl_t *cmdtp, int flag, int argc,
>>> +                     char * const argv[])
>>> +{
>>> +       const char *cmd;
>>> +       int ret = 0;
>>> +
>>> +       if (argc < 5)
>>> +               goto usage;
>>> +
>>> +       cmd = argv[1];
>>> +       --argc;
>>> +       ++argv;
>>> +
>>> +       if (strcmp(cmd, "update") == 0) {
>>> +               ret = do_nandbcb_update(argc, argv);
>>> +               goto done;
>>> +       }
>>> +
>>> +done:
>>> +       if (ret != -1)
>>> +               return ret;
>>> +usage:
>>> +       return CMD_RET_USAGE;
>>> +}
>>> +
>>> +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";
>>> +
>>> +U_BOOT_CMD(nandbcb, 5, 1, do_nandbcb,
>>> +          "i.MX6 Nand BCB",
>>> +          nandbcb_help_text
>>> +);
>>> diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c
>>> index b93d77a395..a41b9620d0 100644
>>> --- a/drivers/mtd/nand/raw/mxs_nand.c
>>> +++ b/drivers/mtd/nand/raw/mxs_nand.c
>>> @@ -25,7 +25,7 @@
>>>  #include <asm/mach-imx/regs-bch.h>
>>>  #include <asm/mach-imx/regs-gpmi.h>
>>>  #include <asm/arch/sys_proto.h>
>>> -#include "mxs_nand.h"
>>> +#include <mxs_nand.h>
>>>
>>>  #define        MXS_NAND_DMA_DESCRIPTOR_COUNT           4
>>>
>>> diff --git a/drivers/mtd/nand/raw/mxs_nand_dt.c b/drivers/mtd/nand/raw/mxs_nand_dt.c
>>> index 44dec5dedf..8ad7d618c6 100644
>>> --- a/drivers/mtd/nand/raw/mxs_nand_dt.c
>>> +++ b/drivers/mtd/nand/raw/mxs_nand_dt.c
>>> @@ -15,7 +15,7 @@
>>>  #include <linux/ioport.h>
>>>  #include <linux/printk.h>
>>>
>>> -#include "mxs_nand.h"
>>> +#include <mxs_nand.h>
>>>
>>>  struct mxs_nand_dt_data {
>>>         unsigned int max_ecc_strength_supported;
>>> diff --git a/drivers/mtd/nand/raw/mxs_nand_spl.c b/drivers/mtd/nand/raw/mxs_nand_spl.c
>>> index ee7d9cb957..975a91a37d 100644
>>> --- a/drivers/mtd/nand/raw/mxs_nand_spl.c
>>> +++ b/drivers/mtd/nand/raw/mxs_nand_spl.c
>>> @@ -6,7 +6,7 @@
>>>  #include <common.h>
>>>  #include <nand.h>
>>>  #include <malloc.h>
>>> -#include "mxs_nand.h"
>>> +#include <mxs_nand.h>
>>>
>>>  static struct mtd_info *mtd;
>>>  static struct nand_chip nand_chip;
>>> diff --git a/drivers/mtd/nand/raw/mxs_nand.h b/include/mxs_nand.h
>>> similarity index 100%
>>> rename from drivers/mtd/nand/raw/mxs_nand.h
>>> rename to include/mxs_nand.h
>>> --
>>> 2.11.0
>>>
>>> _______________________________________________
>>> U-Boot mailing list
>>> U-Boot at lists.denx.de
>>> https://lists.denx.de/listinfo/u-boot
>>
>> --
>> 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
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot
> 

-- 
Thanks,
Parthiban N

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

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

* [U-Boot] [PATCH 3/3] doc: imx: Add documentation for nandbcb command
  2019-06-14  7:35 ` [U-Boot] [PATCH 3/3] doc: imx: Add documentation for " Shyam Saini
  2019-06-14  8:37   ` Lukasz Majewski
@ 2019-07-20  8:46   ` sbabic at denx.de
  1 sibling, 0 replies; 13+ messages in thread
From: sbabic at denx.de @ 2019-07-20  8:46 UTC (permalink / raw)
  To: u-boot

> Signed-off-by: Shyam Saini <shyam.saini@amarulasolutions.com>

Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

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

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

* [U-Boot]  [PATCH v6 1/3] i.MX6: nand: add nandbcb command for imx
  2019-06-14  7:35 [U-Boot] [PATCH v6 1/3] i.MX6: nand: add nandbcb command for imx Shyam Saini
                   ` (2 preceding siblings ...)
  2019-06-14  9:17 ` [U-Boot] [PATCH v6 1/3] i.MX6: nand: add nandbcb command for imx Igor Opaniuk
@ 2019-07-20  8:47 ` sbabic at denx.de
  3 siblings, 0 replies; 13+ messages in thread
From: sbabic at denx.de @ 2019-07-20  8:47 UTC (permalink / raw)
  To: u-boot

> Writing/updating boot image in nand device is not
> straight forward in i.MX6 platform and it requires
> boot control block(BCB) to be configured.
> It becomes difficult to use uboot 'nand' command to
> write BCB since it requires platform specific attributes
> need to be taken care of.
> It is even difficult to use existing msx-nand.c driver by
> incorporating BCB attributes like mxs_dma_desc does
> because it requires change in mtd and nand command.
> So, cmd_nandbcb implemented in arch/arm/mach-imx
> BCB contains two data structures, Firmware Configuration Block(FCB)
> and Discovered Bad Block Table(DBBT). FCB has nand timings,
> DBBT search area, page address of firmware.
> On summary, nandbcb update will
> - erase the entire partition
> - create BCB by creating 2 FCB/DBBT block followed by
>   1 FW block based on partition size and erasesize.
> - fill FCB/DBBT structures
> - write FW/SPL on FW1
> - write FCB/DBBT in first 2 blocks
> for nand boot, up on reset bootrom look for FCB structure in
> first block's if FCB found the nand timings are loaded for
> further reads. once FCB read done, DTTB will load and finally
> firmware will be loaded which is boot image.
> Refer section "NAND Boot" from doc/imx/common/imx6.txt for more usage
> information.
> Reviewed-by: Stefano Babic <sbabic@denx.de>
> Signed-off-by: Jagan Teki <jagan@amarulasolutions.com>
> Signed-off-by: Sergey Kubushyn <ksi@koi8.net>
> Signed-off-by: Shyam Saini <shyam.saini@amarulasolutions.com>

Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

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

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

end of thread, other threads:[~2019-07-20  8:47 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-06-14  7:35 [U-Boot] [PATCH v6 1/3] i.MX6: nand: add nandbcb command for imx Shyam Saini
2019-06-14  7:35 ` [U-Boot] [PATCH 2/3] configs: icorem6: Enable nandbcb command Shyam Saini
2019-06-14  7:35 ` [U-Boot] [PATCH 3/3] doc: imx: Add documentation for " Shyam Saini
2019-06-14  8:37   ` Lukasz Majewski
2019-06-18  7:57     ` Shyam Saini
2019-06-18  8:04       ` Lukasz Majewski
2019-06-18  8:28         ` Shyam Saini
2019-06-18  8:36           ` Lukasz Majewski
2019-07-20  8:46   ` sbabic at denx.de
2019-06-14  9:17 ` [U-Boot] [PATCH v6 1/3] i.MX6: nand: add nandbcb command for imx Igor Opaniuk
2019-06-18  7:54   ` Shyam Saini
2019-06-28 17:46     ` Parthiban Nallathambi
2019-07-20  8:47 ` sbabic at denx.de

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox