Skip to content

Commit

Permalink
spi: omap2_mcspi rxdma bugfix
Browse files Browse the repository at this point in the history
When data is read through DMA, the last element must be read separately
through the RX register.  It cannot be transferred by the DMA.  For
further details see e.g.  OMAP35x TRM (table 19-16).

Without the fix the driver causes extra clocks to be clocked to the bus
after DMA RX operations.  This can cause interesting behaviour with some
devices.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
Signed-off-by: Eero Nurkkala <ext-eero.nurkkala@nokia.com>
[aaro.koskinen@nokia.com: Simplified the patch while keeping the idea.]
Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Eero Nurkkala authored and Linus Torvalds committed Jul 30, 2009
1 parent ddb2219 commit 57c5c28
Showing 1 changed file with 20 additions and 1 deletion.
21 changes: 20 additions & 1 deletion drivers/spi/omap2_mcspi.c
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)

if (rx != NULL) {
omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel,
data_type, element_count, 1,
data_type, element_count - 1, 1,
OMAP_DMA_SYNC_ELEMENT,
mcspi_dma->dma_rx_sync_dev, 1);

Expand Down Expand Up @@ -303,6 +303,25 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)
if (rx != NULL) {
wait_for_completion(&mcspi_dma->dma_rx_completion);
dma_unmap_single(NULL, xfer->rx_dma, count, DMA_FROM_DEVICE);
omap2_mcspi_set_enable(spi, 0);
if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
& OMAP2_MCSPI_CHSTAT_RXS)) {
u32 w;

w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0);
if (word_len <= 8)
((u8 *)xfer->rx_buf)[element_count - 1] = w;
else if (word_len <= 16)
((u16 *)xfer->rx_buf)[element_count - 1] = w;
else /* word_len <= 32 */
((u32 *)xfer->rx_buf)[element_count - 1] = w;
} else {
dev_err(&spi->dev, "DMA RX last word empty");
count -= (word_len <= 8) ? 1 :
(word_len <= 16) ? 2 :
/* word_len <= 32 */ 4;
}
omap2_mcspi_set_enable(spi, 1);
}
return count;
}
Expand Down

0 comments on commit 57c5c28

Please sign in to comment.