diff options
author | Robin Gong <b38343@freescale.com> | 2015-03-31 15:20:13 +0800 |
---|---|---|
committer | guoyin.chen <guoyin.chen@freescale.com> | 2015-05-08 17:24:34 +0800 |
commit | 29770bf28c1f6e89c493a6df815122813b705621 (patch) | |
tree | da5e99f0a4a5997086269c6fde97680883fe895b /drivers | |
parent | 6c13a85e79cb4ddaa0a5a365e297fb051c19d8cb (diff) |
MLK-10502-1 spi: spi-imx: add bits_per_word checking in dma mode
Before, hardcode buswidth as 1byte while config dma channel. Correct it to
dynamically config per buswidth setting. This patch cherry-pick from v3.10.y
ccf74d50f7f85b6606d06a0245a72d22601ac9d8
Signed-off-by: Robin Gong <b38343@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/spi/spi-imx.c | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index f09739a76210..f9ad2713a613 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -112,6 +112,8 @@ struct spi_imx_data { u32 rxt_wml; struct completion dma_rx_completion; struct completion dma_tx_completion; + struct dma_slave_config rx_config; + struct dma_slave_config tx_config; const struct spi_imx_devtype_data *devtype_data; int chipselect[0]; @@ -762,6 +764,7 @@ static int spi_imx_setupxfer(struct spi_device *spi, { struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); struct spi_imx_config config; + int ret; config.bpw = t ? t->bits_per_word : spi->bits_per_word; config.speed_hz = t ? t->speed_hz : spi->max_speed_hz; @@ -777,12 +780,35 @@ static int spi_imx_setupxfer(struct spi_device *spi, if (config.bpw <= 8) { spi_imx->rx = spi_imx_buf_rx_u8; spi_imx->tx = spi_imx_buf_tx_u8; + spi_imx->tx_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + spi_imx->rx_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; } else if (config.bpw <= 16) { spi_imx->rx = spi_imx_buf_rx_u16; spi_imx->tx = spi_imx_buf_tx_u16; + spi_imx->tx_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + spi_imx->rx_config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES; } else { spi_imx->rx = spi_imx_buf_rx_u32; spi_imx->tx = spi_imx_buf_tx_u32; + spi_imx->tx_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + spi_imx->rx_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + } + + if (spi_imx->bitbang.master->can_dma && + spi_imx_can_dma(spi_imx->bitbang.master, spi, t)) { + ret = dmaengine_slave_config(spi_imx->bitbang.master->dma_tx, + &spi_imx->tx_config); + if (ret) { + dev_err(&spi->dev, "error in TX dma configuration.\n"); + return ret; + } + + ret = dmaengine_slave_config(spi_imx->bitbang.master->dma_rx, + &spi_imx->rx_config); + if (ret) { + dev_err(&spi->dev, "error in RX dma configuration.\n"); + return ret; + } } spi_imx->devtype_data->config(spi_imx, &config); @@ -811,7 +837,6 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, struct spi_master *master, const struct resource *res) { - struct dma_slave_config slave_config = {}; int ret; /* Prepare for TX DMA: */ @@ -822,11 +847,11 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, goto err; } - slave_config.direction = DMA_MEM_TO_DEV; - slave_config.dst_addr = res->start + MXC_CSPITXDATA; - slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; - slave_config.dst_maxburst = spi_imx_get_fifosize(spi_imx) / 4; - ret = dmaengine_slave_config(master->dma_tx, &slave_config); + spi_imx->tx_config.direction = DMA_MEM_TO_DEV; + spi_imx->tx_config.dst_addr = res->start + MXC_CSPITXDATA; + spi_imx->tx_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + spi_imx->tx_config.dst_maxburst = spi_imx_get_fifosize(spi_imx) / 4; + ret = dmaengine_slave_config(master->dma_tx, &spi_imx->tx_config); if (ret) { dev_err(dev, "error in TX dma configuration.\n"); goto err; @@ -840,11 +865,11 @@ static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data *spi_imx, goto err; } - slave_config.direction = DMA_DEV_TO_MEM; - slave_config.src_addr = res->start + MXC_CSPIRXDATA; - slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; - slave_config.src_maxburst = spi_imx_get_fifosize(spi_imx) / 2; - ret = dmaengine_slave_config(master->dma_rx, &slave_config); + spi_imx->rx_config.direction = DMA_DEV_TO_MEM; + spi_imx->rx_config.src_addr = res->start + MXC_CSPIRXDATA; + spi_imx->rx_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + spi_imx->rx_config.src_maxburst = spi_imx_get_fifosize(spi_imx) / 2; + ret = dmaengine_slave_config(master->dma_rx, &spi_imx->rx_config); if (ret) { dev_err(dev, "error in RX dma configuration.\n"); goto err; @@ -1005,6 +1030,7 @@ static int spi_imx_transfer(struct spi_device *spi, spi_imx_can_dma(spi_imx->bitbang.master, spi, transfer)) { spi_imx->usedma = true; ret = spi_imx_dma_transfer(spi_imx, transfer); + spi_imx->usedma = false; /* clear the dma flag */ if (ret != -EAGAIN) return ret; } |