aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Bondarenko <anton.bondarenko.sama@gmail.com>2015-12-05 11:57:00 -0500
committerMark Brown <broonie@kernel.org>2015-12-07 14:53:35 -0500
commitfab44ef1adcc585440c07c90539e2b9e2cded4bf (patch)
tree4f6ae2d976239fe7267c40abb1fb20202cbc76bc
parente47b33c0765400d38ebaf57908f00abab2488f74 (diff)
spi: imx: reorder HW operations enable order to avoid possible RX data loss
The overflow may happen due to rescheduling for another task and/or interrupt if we enable SPI HW before starting RX DMA. So RX DMA enabled first to make sure data would be read out from FIFO ASAP. TX DMA enabled next to start filling TX FIFO with new data. And finaly SPI HW enabled to start actual data transfer. The risk rise in case of heavy system load and high SPI clock. Signed-off-by: Anton Bondarenko <anton.bondarenko.sama@gmail.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/spi/spi-imx.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index d6dc66542811..e6b1c74ade6b 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -956,10 +956,18 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
956 if (left) 956 if (left)
957 writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET), 957 writel(dma | (left << MX51_ECSPI_DMA_RXT_WML_OFFSET),
958 spi_imx->base + MX51_ECSPI_DMA); 958 spi_imx->base + MX51_ECSPI_DMA);
959 /*
960 * Set these order to avoid potential RX overflow. The overflow may
961 * happen if we enable SPI HW before starting RX DMA due to rescheduling
962 * for another task and/or interrupt.
963 * So RX DMA enabled first to make sure data would be read out from FIFO
964 * ASAP. TX DMA enabled next to start filling TX FIFO with new data.
965 * And finaly SPI HW enabled to start actual data transfer.
966 */
967 dma_async_issue_pending(master->dma_rx);
968 dma_async_issue_pending(master->dma_tx);
959 spi_imx->devtype_data->trigger(spi_imx); 969 spi_imx->devtype_data->trigger(spi_imx);
960 970
961 dma_async_issue_pending(master->dma_tx);
962 dma_async_issue_pending(master->dma_rx);
963 /* Wait SDMA to finish the data transfer.*/ 971 /* Wait SDMA to finish the data transfer.*/
964 timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion, 972 timeout = wait_for_completion_timeout(&spi_imx->dma_tx_completion,
965 IMX_DMA_TIMEOUT); 973 IMX_DMA_TIMEOUT);