Commit b1178b21 authored by Michael Williamson's avatar Michael Williamson Committed by Grant Likely

spi/davinci: Support DMA transfers larger than 65535 words

The current davinci SPI driver, in DMA mode, is limited to 65535
words for a single transfer.  Modify the driver by configuring a
3 dimensional EDMA transfer to support up to 65535x65535
words.
Signed-off-by: default avatarMichael Williamson <michael.williamson@criticallink.com>
Tested-by: default avatarStefano Babic <sbabic@denx.de>
Signed-off-by: default avatarGrant Likely <grant.likely@secretlab.ca>
parent d09519e4
...@@ -571,6 +571,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) ...@@ -571,6 +571,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
unsigned long tx_reg, rx_reg; unsigned long tx_reg, rx_reg;
struct edmacc_param param; struct edmacc_param param;
void *rx_buf; void *rx_buf;
int b, c;
dma = &dspi->dma; dma = &dspi->dma;
...@@ -599,14 +600,30 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) ...@@ -599,14 +600,30 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
} }
} }
/*
* If number of words is greater than 65535, then we need
* to configure a 3 dimension transfer. Use the BCNTRLD
* feature to allow for transfers that aren't even multiples
* of 65535 (or any other possible b size) by first transferring
* the remainder amount then grabbing the next N blocks of
* 65535 words.
*/
c = dspi->wcount / (SZ_64K - 1); /* N 65535 Blocks */
b = dspi->wcount - c * (SZ_64K - 1); /* Remainder */
if (b)
c++;
else
b = SZ_64K - 1;
param.opt = TCINTEN | EDMA_TCC(dma->tx_channel); param.opt = TCINTEN | EDMA_TCC(dma->tx_channel);
param.src = t->tx_buf ? t->tx_dma : tx_reg; param.src = t->tx_buf ? t->tx_dma : tx_reg;
param.a_b_cnt = dspi->wcount << 16 | data_type; param.a_b_cnt = b << 16 | data_type;
param.dst = tx_reg; param.dst = tx_reg;
param.src_dst_bidx = t->tx_buf ? data_type : 0; param.src_dst_bidx = t->tx_buf ? data_type : 0;
param.link_bcntrld = 0xffff; param.link_bcntrld = 0xffffffff;
param.src_dst_cidx = 0; param.src_dst_cidx = t->tx_buf ? data_type : 0;
param.ccnt = 1; param.ccnt = c;
edma_write_slot(dma->tx_channel, &param); edma_write_slot(dma->tx_channel, &param);
edma_link(dma->tx_channel, dma->dummy_param_slot); edma_link(dma->tx_channel, dma->dummy_param_slot);
...@@ -643,12 +660,12 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) ...@@ -643,12 +660,12 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t)
param.opt = TCINTEN | EDMA_TCC(dma->rx_channel); param.opt = TCINTEN | EDMA_TCC(dma->rx_channel);
param.src = rx_reg; param.src = rx_reg;
param.a_b_cnt = dspi->rcount << 16 | data_type; param.a_b_cnt = b << 16 | data_type;
param.dst = t->rx_dma; param.dst = t->rx_dma;
param.src_dst_bidx = (t->rx_buf ? data_type : 0) << 16; param.src_dst_bidx = (t->rx_buf ? data_type : 0) << 16;
param.link_bcntrld = 0xffff; param.link_bcntrld = 0xffffffff;
param.src_dst_cidx = 0; param.src_dst_cidx = (t->rx_buf ? data_type : 0) << 16;
param.ccnt = 1; param.ccnt = c;
edma_write_slot(dma->rx_channel, &param); edma_write_slot(dma->rx_channel, &param);
if (pdata->cshold_bug) if (pdata->cshold_bug)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment