From 2d7fa2e0306ab5119c54846533ff00ae258fc67e Mon Sep 17 00:00:00 2001 From: lintao Date: Tue, 13 Jan 2015 12:54:45 +0800 Subject: [PATCH] mmc: rk_sdmmc: limit burst to 8 for rk3036 w/ pl330 Signed-off-by: lintao --- drivers/mmc/host/rk_sdmmc.c | 134 +++++++++++++++++++----------------- 1 file changed, 70 insertions(+), 64 deletions(-) diff --git a/drivers/mmc/host/rk_sdmmc.c b/drivers/mmc/host/rk_sdmmc.c index 5388eb64e0d9..7d053d98d60d 100755 --- a/drivers/mmc/host/rk_sdmmc.c +++ b/drivers/mmc/host/rk_sdmmc.c @@ -612,71 +612,77 @@ static void dw_mci_edmac_complete_dma(void *arg) static void dw_mci_edmac_start_dma(struct dw_mci *host, unsigned int sg_len) { - struct dma_slave_config slave_config; - struct dma_async_tx_descriptor *desc = NULL; - struct scatterlist *sgl = host->data->sg; - const u32 mszs[] = {1, 4, 8, 16, 32, 64, 128, 256}; - u32 sg_elems = host->data->sg_len; - u32 fifoth_val, mburst; - int ret = 0; - - /* Set external dma config: burst size, burst width*/ - slave_config.dst_addr = (dma_addr_t)(host->phy_regs + host->data_offset); - slave_config.src_addr = slave_config.dst_addr; - slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; - slave_config.src_addr_width = slave_config.dst_addr_width; - - /* Match FIFO dma burst MSIZE with external dma config*/ - fifoth_val = mci_readl(host, FIFOTH); - mburst = mszs[(fifoth_val >> 28) & 0x7]; - - /* edmac limit burst to 16 */ - slave_config.dst_maxburst = (mburst > 16) ? 16 : mburst; - slave_config.src_maxburst = slave_config.dst_maxburst; - - if(host->data->flags & MMC_DATA_WRITE){ - slave_config.direction = DMA_MEM_TO_DEV; - ret = dmaengine_slave_config(host->dms->ch, &slave_config); - if(ret){ - dev_err(host->dev, "error in dw_mci edma configuration.\n"); - return; - } + struct dma_slave_config slave_config; + struct dma_async_tx_descriptor *desc = NULL; + struct scatterlist *sgl = host->data->sg; + const u32 mszs[] = {1, 4, 8, 16, 32, 64, 128, 256}; + u32 sg_elems = host->data->sg_len; + u32 fifoth_val, mburst; + u32 burst_limit = 0; + int ret = 0; + + /* Set external dma config: burst size, burst width*/ + slave_config.dst_addr = (dma_addr_t)(host->phy_regs + host->data_offset); + slave_config.src_addr = slave_config.dst_addr; + slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + slave_config.src_addr_width = slave_config.dst_addr_width; + + /* Match FIFO dma burst MSIZE with external dma config*/ + fifoth_val = mci_readl(host, FIFOTH); + mburst = mszs[(fifoth_val >> 28) & 0x7]; + + /* edmac limit burst to 16, but work around for rk3036 to 8 */ + if (unlikely(cpu_is_rk3036())) + burst_limit = 8; + else + burst_limit = 16; - desc = dmaengine_prep_slave_sg(host->dms->ch, sgl, sg_len, - DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if(!desc){ - dev_err(host->dev, "We cannot prepare for the dw_mci slave edma!\n"); - return; - } - /* Set dw_mci_edmac_complete_dma as callback */ - desc->callback = dw_mci_edmac_complete_dma; - desc->callback_param = (void *)host; - dmaengine_submit(desc); - - /* Flush cache before write */ - dma_sync_sg_for_device(mmc_dev(host->mmc), sgl, - sg_elems, DMA_TO_DEVICE); - dma_async_issue_pending(host->dms->ch); - }else{ - /* MMC_DATA_READ*/ - slave_config.direction = DMA_DEV_TO_MEM; - ret = dmaengine_slave_config(host->dms->ch, &slave_config); - if(ret){ - dev_err(host->dev, "error in dw_mci edma configuration.\n"); - return; - } - desc = dmaengine_prep_slave_sg(host->dms->ch, sgl, sg_len, - DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); - if(!desc){ - dev_err(host->dev, "We cannot prepare for the dw_mci slave edma!\n"); - return; - } - /* set dw_mci_edmac_complete_dma as callback */ - desc->callback = dw_mci_edmac_complete_dma; - desc->callback_param = (void *)host; - dmaengine_submit(desc); - dma_async_issue_pending(host->dms->ch); - } + slave_config.dst_maxburst = (mburst > burst_limit) ? burst_limit : mburst; + slave_config.src_maxburst = slave_config.dst_maxburst; + + if(host->data->flags & MMC_DATA_WRITE){ + slave_config.direction = DMA_MEM_TO_DEV; + ret = dmaengine_slave_config(host->dms->ch, &slave_config); + if(ret){ + dev_err(host->dev, "error in dw_mci edma configuration.\n"); + return; + } + + desc = dmaengine_prep_slave_sg(host->dms->ch, sgl, sg_len, + DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc) { + dev_err(host->dev, "We cannot prepare for the dw_mci slave edma!\n"); + return; + } + /* Set dw_mci_edmac_complete_dma as callback */ + desc->callback = dw_mci_edmac_complete_dma; + desc->callback_param = (void *)host; + dmaengine_submit(desc); + + /* Flush cache before write */ + dma_sync_sg_for_device(mmc_dev(host->mmc), sgl, + sg_elems, DMA_TO_DEVICE); + dma_async_issue_pending(host->dms->ch); + } else { + /* MMC_DATA_READ*/ + slave_config.direction = DMA_DEV_TO_MEM; + ret = dmaengine_slave_config(host->dms->ch, &slave_config); + if (ret) { + dev_err(host->dev, "error in dw_mci edma configuration.\n"); + return; + } + desc = dmaengine_prep_slave_sg(host->dms->ch, sgl, sg_len, + DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc) { + dev_err(host->dev, "We cannot prepare for the dw_mci slave edma!\n"); + return; + } + /* set dw_mci_edmac_complete_dma as callback */ + desc->callback = dw_mci_edmac_complete_dma; + desc->callback_param = (void *)host; + dmaengine_submit(desc); + dma_async_issue_pending(host->dms->ch); + } } static int dw_mci_edmac_init(struct dw_mci *host) -- 2.34.1