Commit 57c5c28dbc835c67a9c23912bab56b7f165e7715

Authored by Eero Nurkkala
Committed by Linus Torvalds
1 parent ddb22195cb

spi: omap2_mcspi rxdma bugfix

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>

Showing 1 changed file with 20 additions and 1 deletions Side-by-side Diff

drivers/spi/omap2_mcspi.c
... ... @@ -272,7 +272,7 @@
272 272  
273 273 if (rx != NULL) {
274 274 omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel,
275   - data_type, element_count, 1,
  275 + data_type, element_count - 1, 1,
276 276 OMAP_DMA_SYNC_ELEMENT,
277 277 mcspi_dma->dma_rx_sync_dev, 1);
278 278  
... ... @@ -303,6 +303,25 @@
303 303 if (rx != NULL) {
304 304 wait_for_completion(&mcspi_dma->dma_rx_completion);
305 305 dma_unmap_single(NULL, xfer->rx_dma, count, DMA_FROM_DEVICE);
  306 + omap2_mcspi_set_enable(spi, 0);
  307 + if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0)
  308 + & OMAP2_MCSPI_CHSTAT_RXS)) {
  309 + u32 w;
  310 +
  311 + w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0);
  312 + if (word_len <= 8)
  313 + ((u8 *)xfer->rx_buf)[element_count - 1] = w;
  314 + else if (word_len <= 16)
  315 + ((u16 *)xfer->rx_buf)[element_count - 1] = w;
  316 + else /* word_len <= 32 */
  317 + ((u32 *)xfer->rx_buf)[element_count - 1] = w;
  318 + } else {
  319 + dev_err(&spi->dev, "DMA RX last word empty");
  320 + count -= (word_len <= 8) ? 1 :
  321 + (word_len <= 16) ? 2 :
  322 + /* word_len <= 32 */ 4;
  323 + }
  324 + omap2_mcspi_set_enable(spi, 1);
306 325 }
307 326 return count;
308 327 }