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