Commit 57c5c28dbc835c67a9c23912bab56b7f165e7715
Committed by
Linus Torvalds
1 parent
ddb22195cb
Exists in
master
and in
4 other branches
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 | } |