[U-Boot] [PATCH 2/2] i.MX28: Make MXS MMC driver cache aware

Marek Vasut marex at denx.de
Sat Mar 3 19:54:19 CET 2012


This involves introduction of bounce buffers since the block layer doesn't align
buffers. We'll need to eventually start hunting down all of the places where the
buffers aren't aligned in the block layer, but for now, the small amount of
cases where the access is unaligned/obscure can be handled by bounce buffer.

The slowdown due to the bounce buffer is not noticable, measured with sustained
reads.

Signed-off-by: Marek Vasut <marex at denx.de>
Cc: Stefano Babic <sbabic at denx.de>
Cc: Andy Fleming <afleming at gmail.com>
Cc: Fabio Estevam <festevam at gmail.com>
---
 drivers/mmc/mxsmmc.c |   50 +++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 47 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c
index fcd39a1..3ff4b2b 100644
--- a/drivers/mmc/mxsmmc.c
+++ b/drivers/mmc/mxsmmc.c
@@ -66,8 +66,10 @@ 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;
+	uint32_t data_count, bb_data_count = 0;
 	uint32_t ctrl0;
+	uint8_t *bounce = NULL;
+	int bb = 0;
 
 	debug("MMC%d: CMD%d\n", mmc->block_dev.dev, cmd->cmdidx);
 
@@ -186,12 +188,41 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 
 	data_count = data->blocksize * data->blocks;
 
+	if (data_count % MXS_DMA_ALIGNMENT) {
+		bb_data_count = roundup(data_count, MXS_DMA_ALIGNMENT);
+		bb = 1;
+	}
+
 	if (data->flags & MMC_DATA_READ) {
 		priv->desc->cmd.data = MXS_DMA_DESC_COMMAND_DMA_WRITE;
-		priv->desc->cmd.address = (dma_addr_t)data->dest;
+		/* Alignment fault, bounce */
+		if ((uint32_t)(data->dest) & (MXS_DMA_ALIGNMENT - 1))
+			bb = 1;
+
+		if (bb) {
+			bounce = memalign(bb_data_count, MXS_DMA_ALIGNMENT);
+			priv->desc->cmd.address = (dma_addr_t)bounce;
+		} else {
+			priv->desc->cmd.address = (dma_addr_t)data->dest;
+			bb_data_count = data_count;
+		}
 	} else {
 		priv->desc->cmd.data = MXS_DMA_DESC_COMMAND_DMA_READ;
-		priv->desc->cmd.address = (dma_addr_t)data->src;
+		if ((uint32_t)(data->src) & (MXS_DMA_ALIGNMENT - 1))
+			bb = 1;
+
+		if (bb) {
+			bounce = memalign(bb_data_count, MXS_DMA_ALIGNMENT);
+			priv->desc->cmd.address = (dma_addr_t)bounce;
+			memcpy(bounce, data->src, data_count);
+		} else {
+			priv->desc->cmd.address = (dma_addr_t)data->src;
+			bb_data_count = data_count;
+		}
+
+		/* Flush data to DRAM so DMA can pick them up */
+		flush_dcache_range((uint32_t)priv->desc->cmd.address,
+			(uint32_t)(priv->desc->cmd.address + bb_data_count));
 	}
 
 	priv->desc->cmd.data |= MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM |
@@ -203,6 +234,19 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 		return COMM_ERR;
 	}
 
+	/* The data arrived into DRAM, invalidate cache over them */
+	if (data->flags & MMC_DATA_READ) {
+		invalidate_dcache_range((uint32_t)priv->desc->cmd.address,
+			(uint32_t)(priv->desc->cmd.address + bb_data_count));
+		if (bb) {
+			memcpy(data->dest, bounce, data_count);
+			free(bounce);
+		}
+	} else {
+		if (bb)
+			free(bounce);
+	}
+
 	/* Check data errors */
 	reg = readl(&ssp_regs->hw_ssp_status);
 	if (reg &
-- 
1.7.9



More information about the U-Boot mailing list