spi: omap2-mcspi: Set FIFO DMA trigger level to word length
McSPI has 32 byte FIFO in Transmit-Receive mode. Current code tries to configuration FIFO watermark level for DMA trigger to be GCD of transfer length and max FIFO size which would mean trigger level may be set to 32 for transmit-receive mode if length is aligned. This does not work in case of SPI slave mode where FIFO always needs to have data ready whenever master starts the clock. With DMA trigger size of 32 there will be a small window during slave TX where DMA is still putting data into FIFO but master would have started clock for next byte, resulting in shifting out of stale data. Similarly, on Slave RX side there may be RX FIFO overflow Fix this by setting FIFO watermark for DMA trigger to word length. This means DMA is triggered as soon as FIFO has space for word length bytes and DMA would make sure FIFO is almost always full therefore improving FIFO occupancy in both master and slave mode. Signed-off-by: Vignesh R <vigneshr@ti.com> Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Родитель
13d515c796
Коммит
b682cffa3a
|
@ -300,7 +300,7 @@ static void omap2_mcspi_set_fifo(const struct spi_device *spi,
|
|||
struct omap2_mcspi_cs *cs = spi->controller_state;
|
||||
struct omap2_mcspi *mcspi;
|
||||
unsigned int wcnt;
|
||||
int max_fifo_depth, fifo_depth, bytes_per_word;
|
||||
int max_fifo_depth, bytes_per_word;
|
||||
u32 chconf, xferlevel;
|
||||
|
||||
mcspi = spi_master_get_devdata(master);
|
||||
|
@ -316,10 +316,6 @@ static void omap2_mcspi_set_fifo(const struct spi_device *spi,
|
|||
else
|
||||
max_fifo_depth = OMAP2_MCSPI_MAX_FIFODEPTH;
|
||||
|
||||
fifo_depth = gcd(t->len, max_fifo_depth);
|
||||
if (fifo_depth < 2 || fifo_depth % bytes_per_word != 0)
|
||||
goto disable_fifo;
|
||||
|
||||
wcnt = t->len / bytes_per_word;
|
||||
if (wcnt > OMAP2_MCSPI_MAX_FIFOWCNT)
|
||||
goto disable_fifo;
|
||||
|
@ -327,16 +323,17 @@ static void omap2_mcspi_set_fifo(const struct spi_device *spi,
|
|||
xferlevel = wcnt << 16;
|
||||
if (t->rx_buf != NULL) {
|
||||
chconf |= OMAP2_MCSPI_CHCONF_FFER;
|
||||
xferlevel |= (fifo_depth - 1) << 8;
|
||||
xferlevel |= (bytes_per_word - 1) << 8;
|
||||
}
|
||||
|
||||
if (t->tx_buf != NULL) {
|
||||
chconf |= OMAP2_MCSPI_CHCONF_FFET;
|
||||
xferlevel |= fifo_depth - 1;
|
||||
xferlevel |= bytes_per_word - 1;
|
||||
}
|
||||
|
||||
mcspi_write_reg(master, OMAP2_MCSPI_XFERLEVEL, xferlevel);
|
||||
mcspi_write_chconf0(spi, chconf);
|
||||
mcspi->fifo_depth = fifo_depth;
|
||||
mcspi->fifo_depth = max_fifo_depth;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -576,7 +573,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
|
|||
struct dma_slave_config cfg;
|
||||
enum dma_slave_buswidth width;
|
||||
unsigned es;
|
||||
u32 burst;
|
||||
void __iomem *chstat_reg;
|
||||
void __iomem *irqstat_reg;
|
||||
int wait_res;
|
||||
|
@ -596,22 +592,14 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
|
|||
}
|
||||
|
||||
count = xfer->len;
|
||||
burst = 1;
|
||||
|
||||
if (mcspi->fifo_depth > 0) {
|
||||
if (count > mcspi->fifo_depth)
|
||||
burst = mcspi->fifo_depth / es;
|
||||
else
|
||||
burst = count / es;
|
||||
}
|
||||
|
||||
memset(&cfg, 0, sizeof(cfg));
|
||||
cfg.src_addr = cs->phys + OMAP2_MCSPI_RX0;
|
||||
cfg.dst_addr = cs->phys + OMAP2_MCSPI_TX0;
|
||||
cfg.src_addr_width = width;
|
||||
cfg.dst_addr_width = width;
|
||||
cfg.src_maxburst = burst;
|
||||
cfg.dst_maxburst = burst;
|
||||
cfg.src_maxburst = es;
|
||||
cfg.dst_maxburst = es;
|
||||
|
||||
rx = xfer->rx_buf;
|
||||
tx = xfer->tx_buf;
|
||||
|
|
Загрузка…
Ссылка в новой задаче