Commit 2764c500 authored by Ilkka Koskinen's avatar Ilkka Koskinen Committed by Grant Likely

spi/omap2_mcspi: Verify TX reg is empty after TX only xfer with DMA

In case of TX only with DMA, the driver assumes that the data
has been transferred once DMA callback in invoked. However,
SPI's shift register may still contain data. Thus, the driver
is supposed to verify that the register is empty and the end of
the SPI transfer has been reached.
Signed-off-by: default avatarIlkka Koskinen <ilkka.koskinen@nokia.com>
Tested-by: default avatarTuomas Katila <ext-tuomas.2.katila@nokia.com>
Acked-by: default avatarTony Lindgren <tony@atomide.com>
Signed-off-by: default avatarGrant Likely <grant.likely@secretlab.ca>
parent e1993ed6
...@@ -296,6 +296,19 @@ static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi) ...@@ -296,6 +296,19 @@ static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi)
return 0; return 0;
} }
static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
{
unsigned long timeout;
timeout = jiffies + msecs_to_jiffies(1000);
while (!(__raw_readl(reg) & bit)) {
if (time_after(jiffies, timeout))
return -1;
cpu_relax();
}
return 0;
}
static unsigned static unsigned
omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
{ {
...@@ -309,11 +322,14 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -309,11 +322,14 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
u32 l; u32 l;
u8 * rx; u8 * rx;
const u8 * tx; const u8 * tx;
void __iomem *chstat_reg;
mcspi = spi_master_get_devdata(spi->master); mcspi = spi_master_get_devdata(spi->master);
mcspi_dma = &mcspi->dma_channels[spi->chip_select]; mcspi_dma = &mcspi->dma_channels[spi->chip_select];
l = mcspi_cached_chconf0(spi); l = mcspi_cached_chconf0(spi);
chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;
count = xfer->len; count = xfer->len;
c = count; c = count;
word_len = cs->word_len; word_len = cs->word_len;
...@@ -382,6 +398,16 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -382,6 +398,16 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
if (tx != NULL) { if (tx != NULL) {
wait_for_completion(&mcspi_dma->dma_tx_completion); wait_for_completion(&mcspi_dma->dma_tx_completion);
dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE); dma_unmap_single(NULL, xfer->tx_dma, count, DMA_TO_DEVICE);
/* for TX_ONLY mode, be sure all words have shifted out */
if (rx == NULL) {
if (mcspi_wait_for_reg_bit(chstat_reg,
OMAP2_MCSPI_CHSTAT_TXS) < 0)
dev_err(&spi->dev, "TXS timed out\n");
else if (mcspi_wait_for_reg_bit(chstat_reg,
OMAP2_MCSPI_CHSTAT_EOT) < 0)
dev_err(&spi->dev, "EOT timed out\n");
}
} }
if (rx != NULL) { if (rx != NULL) {
...@@ -435,19 +461,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer) ...@@ -435,19 +461,6 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
return count; return count;
} }
static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
{
unsigned long timeout;
timeout = jiffies + msecs_to_jiffies(1000);
while (!(__raw_readl(reg) & bit)) {
if (time_after(jiffies, timeout))
return -1;
cpu_relax();
}
return 0;
}
static unsigned static unsigned
omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer)
{ {
......
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