diff options
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 | ||