diff options
Diffstat (limited to 'drivers/spi/mxs_spi.c')
| -rw-r--r-- | drivers/spi/mxs_spi.c | 43 | 
1 files changed, 25 insertions, 18 deletions
| diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c index c39970700..42e4c9952 100644 --- a/drivers/spi/mxs_spi.c +++ b/drivers/spi/mxs_spi.c @@ -227,6 +227,7 @@ static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,  	const uint32_t dstart = (uint32_t)data;  	int dmach;  	int tl; +	int ret = 0;  	ALLOC_CACHE_ALIGN_BUFFER(struct mxs_dma_desc, desc, desc_count); @@ -240,8 +241,6 @@ static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,  	if (!write)  		ctrl0 |= SSP_CTRL0_READ; -	writel(length, &ssp_regs->hw_ssp_xfer_size); -  	if (length % ARCH_DMA_MINALIGN)  		cache_data_count = roundup(length, ARCH_DMA_MINALIGN);  	else @@ -284,39 +283,47 @@ static int mxs_spi_xfer_dma(struct mxs_spi_slave *slave,  			tl = min(length, xfer_max_sz);  		dp->cmd.data |= -			(tl << MXS_DMA_DESC_BYTES_OFFSET) | -			(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET) | +			((tl & 0xffff) << MXS_DMA_DESC_BYTES_OFFSET) | +			(4 << MXS_DMA_DESC_PIO_WORDS_OFFSET) |  			MXS_DMA_DESC_HALT_ON_TERMINATE |  			MXS_DMA_DESC_TERMINATE_FLUSH; -		dp->cmd.pio_words[0] = ctrl0;  		data += tl;  		length -= tl; +		if (!length) { +			dp->cmd.data |= MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM; + +			if (flags & SPI_XFER_END) { +				ctrl0 &= ~SSP_CTRL0_LOCK_CS; +				ctrl0 |= SSP_CTRL0_IGNORE_CRC; +			} +		} + +		/* +		 * Write CTRL0, CMD0, CMD1, XFER_SIZE registers. It is +		 * essential that the XFER_SIZE register is written on +		 * a per-descriptor basis with the same size as is the +		 * descriptor! +		 */ +		dp->cmd.pio_words[0] = ctrl0; +		dp->cmd.pio_words[1] = 0; +		dp->cmd.pio_words[2] = 0; +		dp->cmd.pio_words[3] = tl; +  		mxs_dma_desc_append(dmach, dp);  		dp++;  	} -	dp->address = (dma_addr_t)dp; -	dp->cmd.address = (dma_addr_t)0; -	dp->cmd.data = MXS_DMA_DESC_COMMAND_NO_DMAXFER | -			(1 << MXS_DMA_DESC_PIO_WORDS_OFFSET) | -			MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM; -	if (flags & SPI_XFER_END) { -		ctrl0 &= ~SSP_CTRL0_LOCK_CS; -		dp->cmd.pio_words[0] = ctrl0 | SSP_CTRL0_IGNORE_CRC; -	} -	mxs_dma_desc_append(dmach, dp); -  	if (mxs_dma_go(dmach)) -		return -EINVAL; +		ret = -EINVAL;  	/* The data arrived into DRAM, invalidate cache over them */  	if (!write)  		invalidate_dcache_range(dstart, dstart + cache_data_count); -	return 0; +	return ret;  }  int spi_xfer(struct spi_slave *slave, unsigned int bitlen, |