diff options
Diffstat (limited to 'drivers/spi/spi-imx.c')
-rw-r--r-- | drivers/spi/spi-imx.c | 53 |
1 files changed, 35 insertions, 18 deletions
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 08dd3a31a3e5..dd1ce12aa386 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -63,6 +63,7 @@ struct spi_imx_devtype_data { void (*trigger)(struct spi_imx_data *); int (*rx_available)(struct spi_imx_data *); void (*reset)(struct spi_imx_data *); + void (*setup_wml)(struct spi_imx_data *); void (*disable)(struct spi_imx_data *); bool has_dmamode; bool has_slavemode; @@ -216,7 +217,6 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, struct spi_transfer *transfer) { struct spi_imx_data *spi_imx = spi_master_get_devdata(master); - unsigned int bytes_per_word, i; if (!master->dma_rx) return false; @@ -224,14 +224,9 @@ static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi, if (spi_imx->slave_mode) return false; - bytes_per_word = spi_imx_bytes_per_word(transfer->bits_per_word); - - for (i = spi_imx->devtype_data->fifo_size / 2; i > 0; i--) { - if (!(transfer->len % (i * bytes_per_word))) - break; - } + if (transfer->len < spi_imx->devtype_data->fifo_size) + return false; - spi_imx->wml = i; spi_imx->dynamic_burst = 0; return true; @@ -583,18 +578,21 @@ static int mx51_ecspi_config(struct spi_device *spi) else /* SCLK is _very_ slow */ usleep_range(delay, delay + 10); + return 0; +} + +static void mx51_setup_wml(struct spi_imx_data *spi_imx) +{ /* * Configure the DMA register: setup the watermark * and enable DMA request. */ - writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml) | + writel(MX51_ECSPI_DMA_RX_WML(spi_imx->wml - 1) | MX51_ECSPI_DMA_TX_WML(spi_imx->wml) | MX51_ECSPI_DMA_RXT_WML(spi_imx->wml) | MX51_ECSPI_DMA_TEDEN | MX51_ECSPI_DMA_RXDEN | MX51_ECSPI_DMA_RXTDEN, spi_imx->base + MX51_ECSPI_DMA); - - return 0; } static int mx51_ecspi_rx_available(struct spi_imx_data *spi_imx) @@ -931,6 +929,7 @@ static struct spi_imx_devtype_data imx51_ecspi_devtype_data = { .trigger = mx51_ecspi_trigger, .rx_available = mx51_ecspi_rx_available, .reset = mx51_ecspi_reset, + .setup_wml = mx51_setup_wml, .fifo_size = 64, .has_dmamode = true, .dynamic_burst = true, @@ -1138,7 +1137,6 @@ static int spi_imx_setupxfer(struct spi_device *spi, struct spi_transfer *t) { struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master); - int ret; if (!t) return 0; @@ -1179,12 +1177,6 @@ static int spi_imx_setupxfer(struct spi_device *spi, else spi_imx->usedma = 0; - if (spi_imx->usedma) { - ret = spi_imx_dma_configure(spi->master); - if (ret) - return ret; - } - if (is_imx53_ecspi(spi_imx) && spi_imx->slave_mode) { spi_imx->rx = mx53_ecspi_rx_slave; spi_imx->tx = mx53_ecspi_tx_slave; @@ -1289,6 +1281,31 @@ static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx, unsigned long timeout; struct spi_master *master = spi_imx->bitbang.master; struct sg_table *tx = &transfer->tx_sg, *rx = &transfer->rx_sg; + struct scatterlist *last_sg = sg_last(rx->sgl, rx->nents); + unsigned int bytes_per_word, i; + int ret; + + /* Get the right burst length from the last sg to ensure no tail data */ + bytes_per_word = spi_imx_bytes_per_word(transfer->bits_per_word); + for (i = spi_imx->devtype_data->fifo_size / 2; i > 0; i--) { + if (!(sg_dma_len(last_sg) % (i * bytes_per_word))) + break; + } + /* Use 1 as wml in case no available burst length got */ + if (i == 0) + i = 1; + + spi_imx->wml = i; + + ret = spi_imx_dma_configure(master); + if (ret) + return ret; + + if (!spi_imx->devtype_data->setup_wml) { + dev_err(spi_imx->dev, "No setup_wml()?\n"); + return -EINVAL; + } + spi_imx->devtype_data->setup_wml(spi_imx); /* * The TX DMA setup starts the transfer, so make sure RX is configured |