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