diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 9076ad4..f5afa9b 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -76,15 +76,17 @@ struct fsl_elbc_ctrl {

 	/* device info */
 	fsl_lbc_t *regs;
-	u8 __iomem *addr;        /* Address of assigned FCM buffer        */
-	unsigned int page;       /* Last page written to / read from      */
-	unsigned int read_bytes; /* Number of bytes read during command   */
-	unsigned int column;     /* Saved column from SEQIN               */
-	unsigned int index;      /* Pointer to next byte to 'read'        */
-	unsigned int status;     /* status read from LTESR after last op  */
-	unsigned int mdr;        /* UPM/FCM Data Register value           */
-	unsigned int use_mdr;    /* Non zero if the MDR is to be set      */
-	unsigned int oob;        /* Non zero if operating on OOB data     */
+	u8 __iomem *addr;           /* Address of assigned FCM buffer       */
+	unsigned int page;          /* Last page written to / read from     */
+	unsigned int read_bytes;    /* Number of bytes read during command  */
+	unsigned int column;        /* Saved column from SEQIN              */
+	unsigned int index;         /* Pointer to next byte to 'read'       */
+	unsigned int status;        /* status read from LTESR after last op */
+	unsigned int mdr;           /* UPM/FCM Data Register value          */
+	unsigned int use_mdr;       /* Non zero if the MDR is to be set     */
+	unsigned int oob;           /* Non zero if operating on OOB data    */
+	uint8_t *buffer;            /* Just used when pagesize is greater   */
+				    /* than FCM RAM 2K limitation           */
 };

 /* These map to the positions used by the FCM hardware ECC generator */
@@ -131,6 +133,10 @@ static struct nand_bbt_descr largepage_memorybased = {
 	.pattern = scan_ff_pattern,
 };

+static u8 migrated_pattern[] = { 0x61, 0xa1, 0x87, 0xf0 };
+#define BADBLOCK_MIGRATED_OFF 1
+#define BADBLOCK_MIGRATED_MB 3
+
 /*
  * ELBC may use HW ECC, so that OOB offsets, that NAND core uses for bbt,
  * interfere with ECC positions, that's why we implement our own descriptors.
@@ -159,6 +165,35 @@ static struct nand_bbt_descr bbt_mirror_descr = {
 	.pattern = mirror_pattern,
 };

+static void io_to_buffer(struct mtd_info *mtd, int subpage, int oob)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_elbc_mtd *priv = chip->priv;
+	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	void *src, *dst;
+	int len = oob ? 64 : 2048;
+
+	/* for emulating 4096+ bytes NAND using 2048-byte FCM RAM */
+	dst = ctrl->buffer + (oob ? mtd->writesize : 0) + subpage * len;
+	src = ctrl->addr + (oob ? 2048 : 0);
+	memcpy_fromio(dst, src, len);
+}
+
+static void buffer_to_io(struct mtd_info *mtd, int subpage, int oob)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct fsl_elbc_mtd *priv = chip->priv;
+	struct fsl_elbc_ctrl *ctrl = priv->ctrl;
+	void *src, *dst;
+	int len = oob ? 64 : 2048;
+
+	src = ctrl->buffer + (oob ? mtd->writesize : 0) + subpage * len;
+	dst = ctrl->addr + (oob ? 2048 : 0);
+	memcpy_toio(dst, src, len);
+	/* See the in_8() in fsl_elbc_write_buf() */
+	in_8(ctrl->addr);
+}
+
 /*=================================*/

 /*
@@ -194,7 +229,7 @@ static void set_addr(struct mtd_info *mtd, int
column, int page_addr, int oob)

 	/* for OOB data point to the second half of the buffer */
 	if (oob)
-		ctrl->index += priv->page_size ? 2048 : 512;
+		ctrl->index += mtd->writesize;

 	vdbg("set_addr: bank=%d, ctrl->addr=0x%p (0x%p), "
