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.sa...@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 <sba...@denx.de> >>> Signed-off-by: Jagan Teki <ja...@amarulasolutions.com> >>> Signed-off-by: Sergey Kubushyn <k...@koi8.net> >>> Signed-off-by: Shyam Saini <shyam.sa...@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 <ja...@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 <ja...@amarulasolutions.com> >>> + * Copyright (C) 2016 Sergey Kubushyn <k...@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@lists.denx.de >>> https://lists.denx.de/listinfo/u-boot >> >> -- >> Best regards - Freundliche GrĂ¼sse - Meilleures salutations >> >> Igor Opaniuk >> >> mailto: igor.opan...@gmail.com >> skype: igor.opanyuk >> +380 (93) 836 40 67 >> http://ua.linkedin.com/in/iopaniuk > _______________________________________________ > U-Boot mailing list > U-Boot@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: p...@denx.de _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot