diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c index c80b41b192..109acbf623 100644 --- a/drivers/mmc/mxsmmc.c +++ b/drivers/mmc/mxsmmc.c @@ -42,6 +42,7 @@ #include #include #include +#include struct mxsmmc_priv { int id; @@ -95,28 +96,33 @@ static int mxsmmc_send_cmd_pio(struct mxsmmc_priv *priv, struct mmc_data *data) static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data) { uint32_t data_count = data->blocksize * data->blocks; - uint32_t cache_data_count; + uint32_t cache_data_count = roundup(data_count, ARCH_DMA_MINALIGN); int dmach; struct mxs_dma_desc *desc = priv->desc; + void *addr, *backup; + uint8_t flags; memset(desc, 0, sizeof(struct mxs_dma_desc)); desc->address = (dma_addr_t)desc; - if (data_count % ARCH_DMA_MINALIGN) - cache_data_count = roundup(data_count, ARCH_DMA_MINALIGN); - else - cache_data_count = data_count; - 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; + addr = data->dest; + flags = GEN_BB_WRITE; } else { priv->desc->cmd.data = MXS_DMA_DESC_COMMAND_DMA_READ; - priv->desc->cmd.address = (dma_addr_t)data->src; + addr = (void *)data->src; + flags = GEN_BB_READ; + } + bounce_buffer_start(&addr, data_count, &backup, flags); + + priv->desc->cmd.address = (dma_addr_t)addr; + + if (data->flags & MMC_DATA_WRITE) { /* 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 + cache_data_count)); + flush_dcache_range((uint32_t)addr, + (uint32_t)(addr) + cache_data_count); } /* Invalidate the area, so no writeback into the RAM races with DMA */ @@ -128,15 +134,19 @@ static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data) dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->id; mxs_dma_desc_append(dmach, priv->desc); - if (mxs_dma_go(dmach)) + if (mxs_dma_go(dmach)) { + bounce_buffer_stop(&addr, data_count, &backup, flags); 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 + cache_data_count)); + invalidate_dcache_range((uint32_t)addr, + (uint32_t)(addr) + cache_data_count); } + bounce_buffer_stop(&addr, data_count, &backup, flags); + return 0; }