diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c
index e8bad9dc751a91778d2ad2d8c803871be56a6144..dfceaef953a918aa38eff4136318c036a7a97426 100644
--- a/drivers/mmc/mxsmmc.c
+++ b/drivers/mmc/mxsmmc.c
@@ -43,6 +43,13 @@
 #include <asm/arch/sys_proto.h>
 #include <asm/arch/dma.h>
 
+/*
+ * CONFIG_MXS_MMC_DMA: This feature is highly experimental and has no
+ *                     performance benefit unless you operate the platform with
+ *                     data cache enabled. This is disabled by default, enable
+ *                     only if you know what you're doing.
+ */
+
 struct mxsmmc_priv {
 	int			id;
 	struct mx28_ssp_regs	*regs;
@@ -66,8 +73,13 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 	struct mx28_ssp_regs *ssp_regs = priv->regs;
 	uint32_t reg;
 	int timeout;
-	uint32_t data_count, cache_data_count;
+	uint32_t data_count;
 	uint32_t ctrl0;
+#ifndef CONFIG_MXS_MMC_DMA
+	uint32_t *data_ptr;
+#else
+	uint32_t cache_data_count;
+#endif
 
 	debug("MMC%d: CMD%d\n", mmc->block_dev.dev, cmd->cmdidx);
 
@@ -185,7 +197,9 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 		return 0;
 
 	data_count = data->blocksize * data->blocks;
+	timeout = MXSMMC_MAX_TIMEOUT;
 
+#ifdef CONFIG_MXS_MMC_DMA
 	if (data_count % ARCH_DMA_MINALIGN)
 		cache_data_count = roundup(data_count, ARCH_DMA_MINALIGN);
 	else
@@ -218,6 +232,38 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 		invalidate_dcache_range((uint32_t)priv->desc->cmd.address,
 			(uint32_t)(priv->desc->cmd.address + cache_data_count));
 	}
+#else
+	if (data->flags & MMC_DATA_READ) {
+		data_ptr = (uint32_t *)data->dest;
+		while (data_count && --timeout) {
+			reg = readl(&ssp_regs->hw_ssp_status);
+			if (!(reg & SSP_STATUS_FIFO_EMPTY)) {
+				*data_ptr++ = readl(&ssp_regs->hw_ssp_data);
+				data_count -= 4;
+				timeout = MXSMMC_MAX_TIMEOUT;
+			} else
+				udelay(1000);
+		}
+	} else {
+		data_ptr = (uint32_t *)data->src;
+		timeout *= 100;
+		while (data_count && --timeout) {
+			reg = readl(&ssp_regs->hw_ssp_status);
+			if (!(reg & SSP_STATUS_FIFO_FULL)) {
+				writel(*data_ptr++, &ssp_regs->hw_ssp_data);
+				data_count -= 4;
+				timeout = MXSMMC_MAX_TIMEOUT;
+			} else
+				udelay(1000);
+		}
+	}
+
+	if (!timeout) {
+		printf("MMC%d: Data timeout with command %d (status 0x%08x)!\n",
+			mmc->block_dev.dev, cmd->cmdidx, reg);
+		return COMM_ERR;
+	}
+#endif
 
 	/* Check data errors */
 	reg = readl(&ssp_regs->hw_ssp_status);