diff --git a/doc/README.nand b/doc/README.nand
index e29188f1ec0cd4dd97a38ddb4bb7ed85645f83fe..dee0e00a61708825f347104a4acf9a8d4de9bb9c 100644
--- a/doc/README.nand
+++ b/doc/README.nand
@@ -304,6 +304,11 @@ Platform specific options
 		Thus BCH16 can be supported on 4K page NAND.
 
 
+    CONFIG_NAND_OMAP_GPMC_PREFETCH
+	On OMAP platforms that use the GPMC controller
+	(CONFIG_NAND_OMAP_GPMC_PREFETCH), this options enables the code that
+	uses the prefetch mode to speed up read operations.
+
 NOTE:
 =====
 
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index 459904d81c21a2356e353c642ef065151006c257..fc64f4814484e8052410f4769c60240ae67dc510 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -441,6 +441,115 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat,
 	return (err) ? err : error_count;
 }
 
+#ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH
+
+#define PREFETCH_CONFIG1_CS_SHIFT	24
+#define PREFETCH_FIFOTHRESHOLD_MAX	0x40
+#define PREFETCH_FIFOTHRESHOLD(val)	((val) << 8)
+#define PREFETCH_STATUS_COUNT(val)	(val & 0x00003fff)
+#define PREFETCH_STATUS_FIFO_CNT(val)	((val >> 24) & 0x7F)
+#define ENABLE_PREFETCH			(1 << 7)
+
+/**
+ * omap_prefetch_enable - configures and starts prefetch transfer
+ * @fifo_th: fifo threshold to be used for read/ write
+ * @count: number of bytes to be transferred
+ * @is_write: prefetch read(0) or write post(1) mode
+ * @cs: chip select to use
+ */
+static int omap_prefetch_enable(int fifo_th, unsigned int count, int is_write, int cs)
+{
+	uint32_t val;
+
+	if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX)
+		return -EINVAL;
+
+	if (readl(&gpmc_cfg->prefetch_control))
+		return -EBUSY;
+
+	/* Set the amount of bytes to be prefetched */
+	writel(count, &gpmc_cfg->prefetch_config2);
+
+	val = (cs << PREFETCH_CONFIG1_CS_SHIFT) | (is_write & 1) |
+		PREFETCH_FIFOTHRESHOLD(fifo_th) | ENABLE_PREFETCH;
+	writel(val, &gpmc_cfg->prefetch_config1);
+
+	/*  Start the prefetch engine */
+	writel(1, &gpmc_cfg->prefetch_control);
+
+	return 0;
+}
+
+/**
+ * omap_prefetch_reset - disables and stops the prefetch engine
+ */
+static void omap_prefetch_reset(void)
+{
+	writel(0, &gpmc_cfg->prefetch_control);
+	writel(0, &gpmc_cfg->prefetch_config1);
+}
+
+static int __read_prefetch_aligned(struct nand_chip *chip, uint32_t *buf, int len)
+{
+	int ret;
+	uint32_t cnt;
+	struct omap_nand_info *info = chip->priv;
+
+	ret = omap_prefetch_enable(PREFETCH_FIFOTHRESHOLD_MAX, len, 0, info->cs);
+	if (ret < 0)
+		return ret;
+
+	do {
+		int i;
+
+		cnt = readl(&gpmc_cfg->prefetch_status);
+		cnt = PREFETCH_STATUS_FIFO_CNT(cnt);
+
+		for (i = 0; i < cnt / 4; i++) {
+			*buf++ = readl(CONFIG_SYS_NAND_BASE);
+			len -= 4;
+		}
+	} while (len);
+
+	omap_prefetch_reset();
+
+	return 0;
+}
+
+static void omap_nand_read_prefetch8(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+	int ret;
+	uint32_t head, tail;
+	struct nand_chip *chip = mtd->priv;
+
+	/*
+	 * If the destination buffer is unaligned, start with reading
+	 * the overlap byte-wise.
+	 */
+	head = ((uint32_t) buf) % 4;
+	if (head) {
+		nand_read_buf(mtd, buf, head);
+		buf += head;
+		len -= head;
+	}
+
+	/*
+	 * Only transfer multiples of 4 bytes in a pre-fetched fashion.
+	 * If there's a residue, care for it byte-wise afterwards.
+	 */
+	tail = len % 4;
+
+	ret = __read_prefetch_aligned(chip, (uint32_t *) buf, len - tail);
+	if (ret < 0) {
+		/* fallback in case the prefetch engine is busy */
+		nand_read_buf(mtd, buf, len);
+	} else if (tail) {
+		buf += len - tail;
+		nand_read_buf(mtd, buf, tail);
+	}
+}
+#endif /* CONFIG_NAND_OMAP_GPMC_PREFETCH */
+
 /**
  * omap_read_page_bch - hardware ecc based page read function
  * @mtd:	mtd info structure
@@ -880,11 +989,12 @@ int board_nand_init(struct nand_chip *nand)
 	if (err)
 		return err;
 
-#ifdef CONFIG_SPL_BUILD
+#ifdef CONFIG_NAND_OMAP_GPMC_PREFETCH
+	/* TODO: Implement for 16-bit bus width */
 	if (nand->options & NAND_BUSWIDTH_16)
 		nand->read_buf = nand_read_buf16;
 	else
-		nand->read_buf = nand_read_buf;
+		nand->read_buf = omap_nand_read_prefetch8;
 #endif
 
 	nand->dev_ready = omap_dev_ready;
diff --git a/include/linux/mtd/omap_gpmc.h b/include/linux/mtd/omap_gpmc.h
index 9a8658257ff9953b5c410713a36d1315e6e29059..6cbae450221ffc9bec9d63b190bf3cfd77963010 100644
--- a/include/linux/mtd/omap_gpmc.h
+++ b/include/linux/mtd/omap_gpmc.h
@@ -66,7 +66,11 @@ struct gpmc {
 	u32 status;		/* 0x54 */
 	u8 res5[0x8];		/* 0x58 */
 	struct gpmc_cs cs[8];	/* 0x60, 0x90, .. */
-	u8 res6[0x14];		/* 0x1E0 */
+	u32 prefetch_config1;	/* 0x1E0 */
+	u32 prefetch_config2;	/* 0x1E4 */
+	u32 res6;		/* 0x1E8 */
+	u32 prefetch_control;	/* 0x1EC */
+	u32 prefetch_status;	/* 0x1F0 */
 	u32 ecc_config;		/* 0x1F4 */
 	u32 ecc_control;	/* 0x1F8 */
 	u32 ecc_size_config;	/* 0x1FC */