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 |