diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-29 18:34:57 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-29 18:34:57 -0400 |
commit | ef08e78268423fc4d7fbc3e54bd9a67fc8da7cc5 (patch) | |
tree | d0561d3ef89c9cd277a38168e33850666cbd33c4 /drivers/dma/at_hdmac.c | |
parent | 71db34fc4330f7c784397acb9f1e6ee7f7b32eb2 (diff) | |
parent | 5b2e02e401deb44e7f5befe19404d8b2688efea4 (diff) |
Merge branch 'next' of git://git.infradead.org/users/vkoul/slave-dma
Pull slave-dmaengine update from Vinod Koul:
"This includes the cookie cleanup by Russell, the addition of context
parameter for dmaengine APIs, more arm dmaengine driver cleanup by
moving code to dmaengine, this time for imx by Javier and pl330 by
Boojin along with the usual driver fixes."
Fix up some fairly trivial conflicts with various other cleanups.
* 'next' of git://git.infradead.org/users/vkoul/slave-dma: (67 commits)
dmaengine: imx: fix the build failure on x86_64
dmaengine: i.MX: Fix merge of cookie branch.
dmaengine: i.MX: Add support for interleaved transfers.
dmaengine: imx-dma: use 'dev_dbg' and 'dev_warn' for messages.
dmaengine: imx-dma: remove 'imx_dmav1_baseaddr' and 'dma_clk'.
dmaengine: imx-dma: remove unused arg of imxdma_sg_next.
dmaengine: imx-dma: remove internal structure.
dmaengine: imx-dma: remove 'resbytes' field of 'internal' structure.
dmaengine: imx-dma: remove 'in_use' field of 'internal' structure.
dmaengine: imx-dma: remove sg member from internal structure.
dmaengine: imx-dma: remove 'imxdma_setup_sg_hw' function.
dmaengine: imx-dma: remove 'imxdma_config_channel_hw' function.
dmaengine: imx-dma: remove 'imxdma_setup_mem2mem_hw' function.
dmaengine: imx-dma: remove dma_mode member of internal structure.
dmaengine: imx-dma: remove data member from internal structure.
dmaengine: imx-dma: merge old dma-v1.c with imx-dma.c
dmaengine: at_hdmac: add slave config operation
dmaengine: add context parameter to prep_slave_sg and prep_dma_cyclic
dmaengine/dma_slave: introduce inline wrappers
dma: imx-sdma: Treat firmware messages as warnings instead of erros
...
Diffstat (limited to 'drivers/dma/at_hdmac.c')
-rw-r--r-- | drivers/dma/at_hdmac.c | 111 |
1 files changed, 59 insertions, 52 deletions
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index f4aed5fc2cb6..7aa58d204892 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/of_device.h> | 27 | #include <linux/of_device.h> |
28 | 28 | ||
29 | #include "at_hdmac_regs.h" | 29 | #include "at_hdmac_regs.h" |
30 | #include "dmaengine.h" | ||
30 | 31 | ||
31 | /* | 32 | /* |
32 | * Glossary | 33 | * Glossary |
@@ -192,27 +193,6 @@ static void atc_desc_chain(struct at_desc **first, struct at_desc **prev, | |||
192 | } | 193 | } |
193 | 194 | ||
194 | /** | 195 | /** |
195 | * atc_assign_cookie - compute and assign new cookie | ||
196 | * @atchan: channel we work on | ||
197 | * @desc: descriptor to assign cookie for | ||
198 | * | ||
199 | * Called with atchan->lock held and bh disabled | ||
200 | */ | ||
201 | static dma_cookie_t | ||
202 | atc_assign_cookie(struct at_dma_chan *atchan, struct at_desc *desc) | ||
203 | { | ||
204 | dma_cookie_t cookie = atchan->chan_common.cookie; | ||
205 | |||
206 | if (++cookie < 0) | ||
207 | cookie = 1; | ||
208 | |||
209 | atchan->chan_common.cookie = cookie; | ||
210 | desc->txd.cookie = cookie; | ||
211 | |||
212 | return cookie; | ||
213 | } | ||
214 | |||
215 | /** | ||
216 | * atc_dostart - starts the DMA engine for real | 196 | * atc_dostart - starts the DMA engine for real |
217 | * @atchan: the channel we want to start | 197 | * @atchan: the channel we want to start |
218 | * @first: first descriptor in the list we want to begin with | 198 | * @first: first descriptor in the list we want to begin with |
@@ -269,7 +249,7 @@ atc_chain_complete(struct at_dma_chan *atchan, struct at_desc *desc) | |||
269 | dev_vdbg(chan2dev(&atchan->chan_common), | 249 | dev_vdbg(chan2dev(&atchan->chan_common), |
270 | "descriptor %u complete\n", txd->cookie); | 250 | "descriptor %u complete\n", txd->cookie); |
271 | 251 | ||
272 | atchan->completed_cookie = txd->cookie; | 252 | dma_cookie_complete(txd); |
273 | 253 | ||
274 | /* move children to free_list */ | 254 | /* move children to free_list */ |
275 | list_splice_init(&desc->tx_list, &atchan->free_list); | 255 | list_splice_init(&desc->tx_list, &atchan->free_list); |
@@ -547,7 +527,7 @@ static dma_cookie_t atc_tx_submit(struct dma_async_tx_descriptor *tx) | |||
547 | unsigned long flags; | 527 | unsigned long flags; |
548 | 528 | ||
549 | spin_lock_irqsave(&atchan->lock, flags); | 529 | spin_lock_irqsave(&atchan->lock, flags); |
550 | cookie = atc_assign_cookie(atchan, desc); | 530 | cookie = dma_cookie_assign(tx); |
551 | 531 | ||
552 | if (list_empty(&atchan->active_list)) { | 532 | if (list_empty(&atchan->active_list)) { |
553 | dev_vdbg(chan2dev(tx->chan), "tx_submit: started %u\n", | 533 | dev_vdbg(chan2dev(tx->chan), "tx_submit: started %u\n", |
@@ -659,14 +639,16 @@ err_desc_get: | |||
659 | * @sg_len: number of entries in @scatterlist | 639 | * @sg_len: number of entries in @scatterlist |
660 | * @direction: DMA direction | 640 | * @direction: DMA direction |
661 | * @flags: tx descriptor status flags | 641 | * @flags: tx descriptor status flags |
642 | * @context: transaction context (ignored) | ||
662 | */ | 643 | */ |
663 | static struct dma_async_tx_descriptor * | 644 | static struct dma_async_tx_descriptor * |
664 | atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | 645 | atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, |
665 | unsigned int sg_len, enum dma_transfer_direction direction, | 646 | unsigned int sg_len, enum dma_transfer_direction direction, |
666 | unsigned long flags) | 647 | unsigned long flags, void *context) |
667 | { | 648 | { |
668 | struct at_dma_chan *atchan = to_at_dma_chan(chan); | 649 | struct at_dma_chan *atchan = to_at_dma_chan(chan); |
669 | struct at_dma_slave *atslave = chan->private; | 650 | struct at_dma_slave *atslave = chan->private; |
651 | struct dma_slave_config *sconfig = &atchan->dma_sconfig; | ||
670 | struct at_desc *first = NULL; | 652 | struct at_desc *first = NULL; |
671 | struct at_desc *prev = NULL; | 653 | struct at_desc *prev = NULL; |
672 | u32 ctrla; | 654 | u32 ctrla; |
@@ -688,19 +670,18 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
688 | return NULL; | 670 | return NULL; |
689 | } | 671 | } |
690 | 672 | ||
691 | reg_width = atslave->reg_width; | ||
692 | |||
693 | ctrla = ATC_DEFAULT_CTRLA | atslave->ctrla; | 673 | ctrla = ATC_DEFAULT_CTRLA | atslave->ctrla; |
694 | ctrlb = ATC_IEN; | 674 | ctrlb = ATC_IEN; |
695 | 675 | ||
696 | switch (direction) { | 676 | switch (direction) { |
697 | case DMA_MEM_TO_DEV: | 677 | case DMA_MEM_TO_DEV: |
678 | reg_width = convert_buswidth(sconfig->dst_addr_width); | ||
698 | ctrla |= ATC_DST_WIDTH(reg_width); | 679 | ctrla |= ATC_DST_WIDTH(reg_width); |
699 | ctrlb |= ATC_DST_ADDR_MODE_FIXED | 680 | ctrlb |= ATC_DST_ADDR_MODE_FIXED |
700 | | ATC_SRC_ADDR_MODE_INCR | 681 | | ATC_SRC_ADDR_MODE_INCR |
701 | | ATC_FC_MEM2PER | 682 | | ATC_FC_MEM2PER |
702 | | ATC_SIF(AT_DMA_MEM_IF) | ATC_DIF(AT_DMA_PER_IF); | 683 | | ATC_SIF(AT_DMA_MEM_IF) | ATC_DIF(AT_DMA_PER_IF); |
703 | reg = atslave->tx_reg; | 684 | reg = sconfig->dst_addr; |
704 | for_each_sg(sgl, sg, sg_len, i) { | 685 | for_each_sg(sgl, sg, sg_len, i) { |
705 | struct at_desc *desc; | 686 | struct at_desc *desc; |
706 | u32 len; | 687 | u32 len; |
@@ -728,13 +709,14 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
728 | } | 709 | } |
729 | break; | 710 | break; |
730 | case DMA_DEV_TO_MEM: | 711 | case DMA_DEV_TO_MEM: |
712 | reg_width = convert_buswidth(sconfig->src_addr_width); | ||
731 | ctrla |= ATC_SRC_WIDTH(reg_width); | 713 | ctrla |= ATC_SRC_WIDTH(reg_width); |
732 | ctrlb |= ATC_DST_ADDR_MODE_INCR | 714 | ctrlb |= ATC_DST_ADDR_MODE_INCR |
733 | | ATC_SRC_ADDR_MODE_FIXED | 715 | | ATC_SRC_ADDR_MODE_FIXED |
734 | | ATC_FC_PER2MEM | 716 | | ATC_FC_PER2MEM |
735 | | ATC_SIF(AT_DMA_PER_IF) | ATC_DIF(AT_DMA_MEM_IF); | 717 | | ATC_SIF(AT_DMA_PER_IF) | ATC_DIF(AT_DMA_MEM_IF); |
736 | 718 | ||
737 | reg = atslave->rx_reg; | 719 | reg = sconfig->src_addr; |
738 | for_each_sg(sgl, sg, sg_len, i) { | 720 | for_each_sg(sgl, sg, sg_len, i) { |
739 | struct at_desc *desc; | 721 | struct at_desc *desc; |
740 | u32 len; | 722 | u32 len; |
@@ -810,12 +792,15 @@ err_out: | |||
810 | * atc_dma_cyclic_fill_desc - Fill one period decriptor | 792 | * atc_dma_cyclic_fill_desc - Fill one period decriptor |
811 | */ | 793 | */ |
812 | static int | 794 | static int |
813 | atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc, | 795 | atc_dma_cyclic_fill_desc(struct dma_chan *chan, struct at_desc *desc, |
814 | unsigned int period_index, dma_addr_t buf_addr, | 796 | unsigned int period_index, dma_addr_t buf_addr, |
815 | size_t period_len, enum dma_transfer_direction direction) | 797 | unsigned int reg_width, size_t period_len, |
798 | enum dma_transfer_direction direction) | ||
816 | { | 799 | { |
817 | u32 ctrla; | 800 | struct at_dma_chan *atchan = to_at_dma_chan(chan); |
818 | unsigned int reg_width = atslave->reg_width; | 801 | struct at_dma_slave *atslave = chan->private; |
802 | struct dma_slave_config *sconfig = &atchan->dma_sconfig; | ||
803 | u32 ctrla; | ||
819 | 804 | ||
820 | /* prepare common CRTLA value */ | 805 | /* prepare common CRTLA value */ |
821 | ctrla = ATC_DEFAULT_CTRLA | atslave->ctrla | 806 | ctrla = ATC_DEFAULT_CTRLA | atslave->ctrla |
@@ -826,7 +811,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc, | |||
826 | switch (direction) { | 811 | switch (direction) { |
827 | case DMA_MEM_TO_DEV: | 812 | case DMA_MEM_TO_DEV: |
828 | desc->lli.saddr = buf_addr + (period_len * period_index); | 813 | desc->lli.saddr = buf_addr + (period_len * period_index); |
829 | desc->lli.daddr = atslave->tx_reg; | 814 | desc->lli.daddr = sconfig->dst_addr; |
830 | desc->lli.ctrla = ctrla; | 815 | desc->lli.ctrla = ctrla; |
831 | desc->lli.ctrlb = ATC_DST_ADDR_MODE_FIXED | 816 | desc->lli.ctrlb = ATC_DST_ADDR_MODE_FIXED |
832 | | ATC_SRC_ADDR_MODE_INCR | 817 | | ATC_SRC_ADDR_MODE_INCR |
@@ -836,7 +821,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc, | |||
836 | break; | 821 | break; |
837 | 822 | ||
838 | case DMA_DEV_TO_MEM: | 823 | case DMA_DEV_TO_MEM: |
839 | desc->lli.saddr = atslave->rx_reg; | 824 | desc->lli.saddr = sconfig->src_addr; |
840 | desc->lli.daddr = buf_addr + (period_len * period_index); | 825 | desc->lli.daddr = buf_addr + (period_len * period_index); |
841 | desc->lli.ctrla = ctrla; | 826 | desc->lli.ctrla = ctrla; |
842 | desc->lli.ctrlb = ATC_DST_ADDR_MODE_INCR | 827 | desc->lli.ctrlb = ATC_DST_ADDR_MODE_INCR |
@@ -860,16 +845,20 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc, | |||
860 | * @buf_len: total number of bytes for the entire buffer | 845 | * @buf_len: total number of bytes for the entire buffer |
861 | * @period_len: number of bytes for each period | 846 | * @period_len: number of bytes for each period |
862 | * @direction: transfer direction, to or from device | 847 | * @direction: transfer direction, to or from device |
848 | * @context: transfer context (ignored) | ||
863 | */ | 849 | */ |
864 | static struct dma_async_tx_descriptor * | 850 | static struct dma_async_tx_descriptor * |
865 | atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, | 851 | atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, |
866 | size_t period_len, enum dma_transfer_direction direction) | 852 | size_t period_len, enum dma_transfer_direction direction, |
853 | void *context) | ||
867 | { | 854 | { |
868 | struct at_dma_chan *atchan = to_at_dma_chan(chan); | 855 | struct at_dma_chan *atchan = to_at_dma_chan(chan); |
869 | struct at_dma_slave *atslave = chan->private; | 856 | struct at_dma_slave *atslave = chan->private; |
857 | struct dma_slave_config *sconfig = &atchan->dma_sconfig; | ||
870 | struct at_desc *first = NULL; | 858 | struct at_desc *first = NULL; |
871 | struct at_desc *prev = NULL; | 859 | struct at_desc *prev = NULL; |
872 | unsigned long was_cyclic; | 860 | unsigned long was_cyclic; |
861 | unsigned int reg_width; | ||
873 | unsigned int periods = buf_len / period_len; | 862 | unsigned int periods = buf_len / period_len; |
874 | unsigned int i; | 863 | unsigned int i; |
875 | 864 | ||
@@ -889,8 +878,13 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, | |||
889 | return NULL; | 878 | return NULL; |
890 | } | 879 | } |
891 | 880 | ||
881 | if (sconfig->direction == DMA_MEM_TO_DEV) | ||
882 | reg_width = convert_buswidth(sconfig->dst_addr_width); | ||
883 | else | ||
884 | reg_width = convert_buswidth(sconfig->src_addr_width); | ||
885 | |||
892 | /* Check for too big/unaligned periods and unaligned DMA buffer */ | 886 | /* Check for too big/unaligned periods and unaligned DMA buffer */ |
893 | if (atc_dma_cyclic_check_values(atslave->reg_width, buf_addr, | 887 | if (atc_dma_cyclic_check_values(reg_width, buf_addr, |
894 | period_len, direction)) | 888 | period_len, direction)) |
895 | goto err_out; | 889 | goto err_out; |
896 | 890 | ||
@@ -902,8 +896,8 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, | |||
902 | if (!desc) | 896 | if (!desc) |
903 | goto err_desc_get; | 897 | goto err_desc_get; |
904 | 898 | ||
905 | if (atc_dma_cyclic_fill_desc(atslave, desc, i, buf_addr, | 899 | if (atc_dma_cyclic_fill_desc(chan, desc, i, buf_addr, |
906 | period_len, direction)) | 900 | reg_width, period_len, direction)) |
907 | goto err_desc_get; | 901 | goto err_desc_get; |
908 | 902 | ||
909 | atc_desc_chain(&first, &prev, desc); | 903 | atc_desc_chain(&first, &prev, desc); |
@@ -926,6 +920,23 @@ err_out: | |||
926 | return NULL; | 920 | return NULL; |
927 | } | 921 | } |
928 | 922 | ||
923 | static int set_runtime_config(struct dma_chan *chan, | ||
924 | struct dma_slave_config *sconfig) | ||
925 | { | ||
926 | struct at_dma_chan *atchan = to_at_dma_chan(chan); | ||
927 | |||
928 | /* Check if it is chan is configured for slave transfers */ | ||
929 | if (!chan->private) | ||
930 | return -EINVAL; | ||
931 | |||
932 | memcpy(&atchan->dma_sconfig, sconfig, sizeof(*sconfig)); | ||
933 | |||
934 | convert_burst(&atchan->dma_sconfig.src_maxburst); | ||
935 | convert_burst(&atchan->dma_sconfig.dst_maxburst); | ||
936 | |||
937 | return 0; | ||
938 | } | ||
939 | |||
929 | 940 | ||
930 | static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | 941 | static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, |
931 | unsigned long arg) | 942 | unsigned long arg) |
@@ -986,6 +997,8 @@ static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | |||
986 | clear_bit(ATC_IS_CYCLIC, &atchan->status); | 997 | clear_bit(ATC_IS_CYCLIC, &atchan->status); |
987 | 998 | ||
988 | spin_unlock_irqrestore(&atchan->lock, flags); | 999 | spin_unlock_irqrestore(&atchan->lock, flags); |
1000 | } else if (cmd == DMA_SLAVE_CONFIG) { | ||
1001 | return set_runtime_config(chan, (struct dma_slave_config *)arg); | ||
989 | } else { | 1002 | } else { |
990 | return -ENXIO; | 1003 | return -ENXIO; |
991 | } | 1004 | } |
@@ -1016,26 +1029,20 @@ atc_tx_status(struct dma_chan *chan, | |||
1016 | 1029 | ||
1017 | spin_lock_irqsave(&atchan->lock, flags); | 1030 | spin_lock_irqsave(&atchan->lock, flags); |
1018 | 1031 | ||
1019 | last_complete = atchan->completed_cookie; | 1032 | ret = dma_cookie_status(chan, cookie, txstate); |
1020 | last_used = chan->cookie; | ||
1021 | |||
1022 | ret = dma_async_is_complete(cookie, last_complete, last_used); | ||
1023 | if (ret != DMA_SUCCESS) { | 1033 | if (ret != DMA_SUCCESS) { |
1024 | atc_cleanup_descriptors(atchan); | 1034 | atc_cleanup_descriptors(atchan); |
1025 | 1035 | ||
1026 | last_complete = atchan->completed_cookie; | 1036 | ret = dma_cookie_status(chan, cookie, txstate); |
1027 | last_used = chan->cookie; | ||
1028 | |||
1029 | ret = dma_async_is_complete(cookie, last_complete, last_used); | ||
1030 | } | 1037 | } |
1031 | 1038 | ||
1039 | last_complete = chan->completed_cookie; | ||
1040 | last_used = chan->cookie; | ||
1041 | |||
1032 | spin_unlock_irqrestore(&atchan->lock, flags); | 1042 | spin_unlock_irqrestore(&atchan->lock, flags); |
1033 | 1043 | ||
1034 | if (ret != DMA_SUCCESS) | 1044 | if (ret != DMA_SUCCESS) |
1035 | dma_set_tx_state(txstate, last_complete, last_used, | 1045 | dma_set_residue(txstate, atc_first_active(atchan)->len); |
1036 | atc_first_active(atchan)->len); | ||
1037 | else | ||
1038 | dma_set_tx_state(txstate, last_complete, last_used, 0); | ||
1039 | 1046 | ||
1040 | if (atc_chan_is_paused(atchan)) | 1047 | if (atc_chan_is_paused(atchan)) |
1041 | ret = DMA_PAUSED; | 1048 | ret = DMA_PAUSED; |
@@ -1129,7 +1136,7 @@ static int atc_alloc_chan_resources(struct dma_chan *chan) | |||
1129 | spin_lock_irqsave(&atchan->lock, flags); | 1136 | spin_lock_irqsave(&atchan->lock, flags); |
1130 | atchan->descs_allocated = i; | 1137 | atchan->descs_allocated = i; |
1131 | list_splice(&tmp_list, &atchan->free_list); | 1138 | list_splice(&tmp_list, &atchan->free_list); |
1132 | atchan->completed_cookie = chan->cookie = 1; | 1139 | dma_cookie_init(chan); |
1133 | spin_unlock_irqrestore(&atchan->lock, flags); | 1140 | spin_unlock_irqrestore(&atchan->lock, flags); |
1134 | 1141 | ||
1135 | /* channel parameters */ | 1142 | /* channel parameters */ |
@@ -1329,7 +1336,7 @@ static int __init at_dma_probe(struct platform_device *pdev) | |||
1329 | struct at_dma_chan *atchan = &atdma->chan[i]; | 1336 | struct at_dma_chan *atchan = &atdma->chan[i]; |
1330 | 1337 | ||
1331 | atchan->chan_common.device = &atdma->dma_common; | 1338 | atchan->chan_common.device = &atdma->dma_common; |
1332 | atchan->chan_common.cookie = atchan->completed_cookie = 1; | 1339 | dma_cookie_init(&atchan->chan_common); |
1333 | list_add_tail(&atchan->chan_common.device_node, | 1340 | list_add_tail(&atchan->chan_common.device_node, |
1334 | &atdma->dma_common.channels); | 1341 | &atdma->dma_common.channels); |
1335 | 1342 | ||