Commit 94554a9a01f80ae24db59b412bccb94258afe85e
1 parent
e5f3cf5b95
Exists in
master
arm:omap:mcspi - DMA support has added for MCSPI
Support for DMA transmission on MCSPI added. 1. MCSPI TX and RX registers are not 256-bit aligned address, as required for Constant address mode in DAM and SAM in EDMA, causing EDMA error generation condition. With this commit SAM and DAM are set to Increment address mode. 2. SPI uses EDMA AB synchronized mode for transmission and EDMA A synchronized mode for reception, which can be used to handle large chunk of data above 64KB with single EDMA completion interrupt. Signed-off-by: Philip, Avinash <avinashphilip@ti.com>
Showing 1 changed file with 64 additions and 45 deletions Side-by-side Diff
drivers/spi/spi-omap2-mcspi.c
... | ... | @@ -40,6 +40,7 @@ |
40 | 40 | #include <plat/dma.h> |
41 | 41 | #include <plat/clock.h> |
42 | 42 | #include <plat/mcspi.h> |
43 | +#include <mach/edma.h> | |
43 | 44 | |
44 | 45 | #define OMAP2_MCSPI_MAX_FREQ 48000000 |
45 | 46 | |
46 | 47 | |
... | ... | @@ -101,12 +102,13 @@ |
101 | 102 | |
102 | 103 | struct completion dma_tx_completion; |
103 | 104 | struct completion dma_rx_completion; |
105 | + int dummy_param_slot; | |
104 | 106 | }; |
105 | 107 | |
106 | 108 | /* use PIO for small transfers, avoiding DMA setup/teardown overhead and |
107 | 109 | * cache operations; better heuristics consider wordsize and bitrate. |
108 | 110 | */ |
109 | -#define DMA_MIN_BYTES (4 * 1024 * 1024) | |
111 | +#define DMA_MIN_BYTES (160) | |
110 | 112 | |
111 | 113 | struct omap2_mcspi { |
112 | 114 | struct work_struct work; |
... | ... | @@ -302,6 +304,7 @@ |
302 | 304 | u8 * rx; |
303 | 305 | const u8 * tx; |
304 | 306 | void __iomem *chstat_reg; |
307 | + struct edmacc_param param; | |
305 | 308 | |
306 | 309 | mcspi = spi_master_get_devdata(spi->master); |
307 | 310 | mcspi_dma = &mcspi->dma_channels[spi->chip_select]; |
308 | 311 | |
309 | 312 | |
310 | 313 | |
311 | 314 | |
312 | 315 | |
... | ... | @@ -331,37 +334,57 @@ |
331 | 334 | } |
332 | 335 | |
333 | 336 | if (tx != NULL) { |
334 | - omap_set_dma_transfer_params(mcspi_dma->dma_tx_channel, | |
335 | - data_type, element_count, 1, | |
336 | - OMAP_DMA_SYNC_ELEMENT, | |
337 | - mcspi_dma->dma_tx_sync_dev, 0); | |
337 | + int a_cnt, b_cnt, c_cnt, b_cntrld; | |
338 | 338 | |
339 | - omap_set_dma_dest_params(mcspi_dma->dma_tx_channel, 0, | |
340 | - OMAP_DMA_AMODE_CONSTANT, | |
341 | - tx_reg, 0, 0); | |
339 | + a_cnt = 1; | |
340 | + b_cnt = 1; | |
341 | + c_cnt = (element_count / a_cnt) / 256; | |
342 | + b_cntrld = SZ_64K - 1; | |
342 | 343 | |
343 | - omap_set_dma_src_params(mcspi_dma->dma_tx_channel, 0, | |
344 | - OMAP_DMA_AMODE_POST_INC, | |
345 | - xfer->tx_dma, 0, 0); | |
344 | + param.opt = TCINTEN | | |
345 | + EDMA_TCC(mcspi_dma->dma_tx_channel) | SYNCDIM ; | |
346 | + param.src = xfer->tx_dma; | |
347 | + param.a_b_cnt = a_cnt | b_cnt << 16; | |
348 | + param.dst = tx_reg; | |
349 | + param.src_dst_bidx = a_cnt; | |
350 | + param.link_bcntrld = b_cntrld << 16; | |
351 | + param.src_dst_cidx = b_cnt; | |
352 | + param.ccnt = element_count; | |
353 | + edma_write_slot(mcspi_dma->dma_tx_channel, ¶m); | |
354 | + edma_link(mcspi_dma->dma_tx_channel, | |
355 | + mcspi_dma->dummy_param_slot); | |
346 | 356 | } |
347 | 357 | |
348 | 358 | if (rx != NULL) { |
359 | + int a_cnt, b_cnt, c_cnt, b_cntrld; | |
360 | + | |
361 | + a_cnt = 1; | |
362 | + c_cnt = (element_count / a_cnt) / (SZ_64K - 1); | |
363 | + b_cnt = element_count - c_cnt * (SZ_64K - 1); | |
364 | + b_cntrld = SZ_64K - 1; | |
365 | + | |
366 | + if (b_cnt) | |
367 | + c_cnt++; | |
368 | + else | |
369 | + b_cnt = SZ_64K - 1; | |
370 | + | |
349 | 371 | elements = element_count - 1; |
350 | 372 | if (l & OMAP2_MCSPI_CHCONF_TURBO) |
351 | 373 | elements--; |
352 | 374 | |
353 | - omap_set_dma_transfer_params(mcspi_dma->dma_rx_channel, | |
354 | - data_type, elements, 1, | |
355 | - OMAP_DMA_SYNC_ELEMENT, | |
356 | - mcspi_dma->dma_rx_sync_dev, 1); | |
375 | + param.opt = TCINTEN | | |
376 | + EDMA_TCC(mcspi_dma->dma_rx_channel); | |
377 | + param.src = rx_reg; | |
378 | + param.a_b_cnt = a_cnt | b_cnt << 16; | |
379 | + param.dst = xfer->rx_dma; | |
380 | + param.src_dst_bidx = a_cnt << 16; | |
381 | + param.link_bcntrld = b_cntrld << 16; | |
382 | + param.src_dst_cidx = 1 << 16; | |
383 | + param.ccnt = c_cnt; | |
384 | + edma_write_slot(mcspi_dma->dma_rx_channel, ¶m); | |
385 | + edma_link(mcspi_dma->dma_rx_channel, | |
386 | + mcspi_dma->dummy_param_slot); | |
357 | 387 | |
358 | - omap_set_dma_src_params(mcspi_dma->dma_rx_channel, 0, | |
359 | - OMAP_DMA_AMODE_CONSTANT, | |
360 | - rx_reg, 0, 0); | |
361 | - | |
362 | - omap_set_dma_dest_params(mcspi_dma->dma_rx_channel, 0, | |
363 | - OMAP_DMA_AMODE_POST_INC, | |
364 | - xfer->rx_dma, 0, 0); | |
365 | 388 | } |
366 | 389 | |
367 | 390 | if (tx != NULL) { |
... | ... | @@ -418,23 +441,6 @@ |
418 | 441 | } |
419 | 442 | } |
420 | 443 | |
421 | - if (likely(mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHSTAT0) | |
422 | - & OMAP2_MCSPI_CHSTAT_RXS)) { | |
423 | - u32 w; | |
424 | - | |
425 | - w = mcspi_read_cs_reg(spi, OMAP2_MCSPI_RX0); | |
426 | - if (word_len <= 8) | |
427 | - ((u8 *)xfer->rx_buf)[elements] = w; | |
428 | - else if (word_len <= 16) | |
429 | - ((u16 *)xfer->rx_buf)[elements] = w; | |
430 | - else /* word_len <= 32 */ | |
431 | - ((u32 *)xfer->rx_buf)[elements] = w; | |
432 | - } else { | |
433 | - dev_err(&spi->dev, "DMA RX last word empty"); | |
434 | - count -= (word_len <= 8) ? 1 : | |
435 | - (word_len <= 16) ? 2 : | |
436 | - /* word_len <= 32 */ 4; | |
437 | - } | |
438 | 444 | omap2_mcspi_set_enable(spi, 1); |
439 | 445 | } |
440 | 446 | return count; |
441 | 447 | |
... | ... | @@ -717,13 +723,13 @@ |
717 | 723 | struct omap2_mcspi *mcspi; |
718 | 724 | struct omap2_mcspi_dma *mcspi_dma; |
719 | 725 | |
726 | + /* We must disable the DMA RX request */ | |
727 | + omap2_mcspi_set_dma_req(spi, 1, 0); | |
720 | 728 | mcspi = spi_master_get_devdata(spi->master); |
721 | 729 | mcspi_dma = &(mcspi->dma_channels[spi->chip_select]); |
722 | 730 | |
723 | 731 | complete(&mcspi_dma->dma_rx_completion); |
724 | 732 | |
725 | - /* We must disable the DMA RX request */ | |
726 | - omap2_mcspi_set_dma_req(spi, 1, 0); | |
727 | 733 | } |
728 | 734 | |
729 | 735 | static void omap2_mcspi_dma_tx_callback(int lch, u16 ch_status, void *data) |
730 | 736 | |
... | ... | @@ -732,13 +738,13 @@ |
732 | 738 | struct omap2_mcspi *mcspi; |
733 | 739 | struct omap2_mcspi_dma *mcspi_dma; |
734 | 740 | |
741 | + /* We must disable the DMA TX request */ | |
742 | + omap2_mcspi_set_dma_req(spi, 0, 0); | |
735 | 743 | mcspi = spi_master_get_devdata(spi->master); |
736 | 744 | mcspi_dma = &(mcspi->dma_channels[spi->chip_select]); |
737 | 745 | |
738 | 746 | complete(&mcspi_dma->dma_tx_completion); |
739 | 747 | |
740 | - /* We must disable the DMA TX request */ | |
741 | - omap2_mcspi_set_dma_req(spi, 0, 0); | |
742 | 748 | } |
743 | 749 | |
744 | 750 | static int omap2_mcspi_request_dma(struct spi_device *spi) |
... | ... | @@ -746,6 +752,7 @@ |
746 | 752 | struct spi_master *master = spi->master; |
747 | 753 | struct omap2_mcspi *mcspi; |
748 | 754 | struct omap2_mcspi_dma *mcspi_dma; |
755 | + int ret = 0; | |
749 | 756 | |
750 | 757 | mcspi = spi_master_get_devdata(master); |
751 | 758 | mcspi_dma = mcspi->dma_channels + spi->chip_select; |
... | ... | @@ -765,6 +772,18 @@ |
765 | 772 | dev_err(&spi->dev, "no TX DMA channel for McSPI\n"); |
766 | 773 | return -EAGAIN; |
767 | 774 | } |
775 | + ret = edma_alloc_slot(EDMA_CTLR(mcspi_dma->dma_tx_channel), | |
776 | + EDMA_SLOT_ANY); | |
777 | + | |
778 | + if (ret < 0) { | |
779 | + pr_err("Unable to request SPI TX DMA param slot\n"); | |
780 | + ret = -EAGAIN; | |
781 | + return ret; | |
782 | + } | |
783 | + | |
784 | + mcspi_dma->dummy_param_slot = ret; | |
785 | + edma_link(mcspi_dma->dummy_param_slot, | |
786 | + mcspi_dma->dummy_param_slot); | |
768 | 787 | |
769 | 788 | init_completion(&mcspi_dma->dma_rx_completion); |
770 | 789 | init_completion(&mcspi_dma->dma_tx_completion); |