diff options
author | Nicolas Ferre <nicolas.ferre@atmel.com> | 2012-03-14 07:41:43 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@linux.intel.com> | 2012-03-21 11:42:29 -0400 |
commit | beeaa103eecc7a132682c40867f0ef70655383a5 (patch) | |
tree | c1cc34c65347a04d859eae78076322668d2f636d /drivers/dma/at_hdmac.c | |
parent | 185ecb5f4fd43911c35956d4cc7d94a1da30417f (diff) |
dmaengine: at_hdmac: add slave config operation
This patch introduces DMA_SLAVE_CONFIG to at_hdmac Atmel DMA driver.
It is needed to fix a regression in the use of atmel-mci.c driver on Atmel
AT91 platforms brouth by e2b35f3:
"dmaengine/dw_dmac: Fix dw_dmac user drivers to adapt to slave_config changes"
We remove some parts of the private structure "at_dma_slave" and use the
information provided by "struct dma_slave_config": source/destination
peripheral registers and access width.
AT_DMA_SLAVE_WIDTH_* values used previously are not needed anymore as we
now use the standard ones. Although some conversion functions are needed to
match register expected values.
Some AT91 sub-architecture specific files are slightly touched by this patch
but it cannot be split because it can break compilation.
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Diffstat (limited to 'drivers/dma/at_hdmac.c')
-rw-r--r-- | drivers/dma/at_hdmac.c | 56 |
1 files changed, 43 insertions, 13 deletions
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index f24b16e455fd..7aa58d204892 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c | |||
@@ -648,6 +648,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
648 | { | 648 | { |
649 | struct at_dma_chan *atchan = to_at_dma_chan(chan); | 649 | struct at_dma_chan *atchan = to_at_dma_chan(chan); |
650 | struct at_dma_slave *atslave = chan->private; | 650 | struct at_dma_slave *atslave = chan->private; |
651 | struct dma_slave_config *sconfig = &atchan->dma_sconfig; | ||
651 | struct at_desc *first = NULL; | 652 | struct at_desc *first = NULL; |
652 | struct at_desc *prev = NULL; | 653 | struct at_desc *prev = NULL; |
653 | u32 ctrla; | 654 | u32 ctrla; |
@@ -669,19 +670,18 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
669 | return NULL; | 670 | return NULL; |
670 | } | 671 | } |
671 | 672 | ||
672 | reg_width = atslave->reg_width; | ||
673 | |||
674 | ctrla = ATC_DEFAULT_CTRLA | atslave->ctrla; | 673 | ctrla = ATC_DEFAULT_CTRLA | atslave->ctrla; |
675 | ctrlb = ATC_IEN; | 674 | ctrlb = ATC_IEN; |
676 | 675 | ||
677 | switch (direction) { | 676 | switch (direction) { |
678 | case DMA_MEM_TO_DEV: | 677 | case DMA_MEM_TO_DEV: |
678 | reg_width = convert_buswidth(sconfig->dst_addr_width); | ||
679 | ctrla |= ATC_DST_WIDTH(reg_width); | 679 | ctrla |= ATC_DST_WIDTH(reg_width); |
680 | ctrlb |= ATC_DST_ADDR_MODE_FIXED | 680 | ctrlb |= ATC_DST_ADDR_MODE_FIXED |
681 | | ATC_SRC_ADDR_MODE_INCR | 681 | | ATC_SRC_ADDR_MODE_INCR |
682 | | ATC_FC_MEM2PER | 682 | | ATC_FC_MEM2PER |
683 | | 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); |
684 | reg = atslave->tx_reg; | 684 | reg = sconfig->dst_addr; |
685 | for_each_sg(sgl, sg, sg_len, i) { | 685 | for_each_sg(sgl, sg, sg_len, i) { |
686 | struct at_desc *desc; | 686 | struct at_desc *desc; |
687 | u32 len; | 687 | u32 len; |
@@ -709,13 +709,14 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
709 | } | 709 | } |
710 | break; | 710 | break; |
711 | case DMA_DEV_TO_MEM: | 711 | case DMA_DEV_TO_MEM: |
712 | reg_width = convert_buswidth(sconfig->src_addr_width); | ||
712 | ctrla |= ATC_SRC_WIDTH(reg_width); | 713 | ctrla |= ATC_SRC_WIDTH(reg_width); |
713 | ctrlb |= ATC_DST_ADDR_MODE_INCR | 714 | ctrlb |= ATC_DST_ADDR_MODE_INCR |
714 | | ATC_SRC_ADDR_MODE_FIXED | 715 | | ATC_SRC_ADDR_MODE_FIXED |
715 | | ATC_FC_PER2MEM | 716 | | ATC_FC_PER2MEM |
716 | | 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); |
717 | 718 | ||
718 | reg = atslave->rx_reg; | 719 | reg = sconfig->src_addr; |
719 | for_each_sg(sgl, sg, sg_len, i) { | 720 | for_each_sg(sgl, sg, sg_len, i) { |
720 | struct at_desc *desc; | 721 | struct at_desc *desc; |
721 | u32 len; | 722 | u32 len; |
@@ -791,12 +792,15 @@ err_out: | |||
791 | * atc_dma_cyclic_fill_desc - Fill one period decriptor | 792 | * atc_dma_cyclic_fill_desc - Fill one period decriptor |
792 | */ | 793 | */ |
793 | static int | 794 | static int |
794 | 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, |
795 | unsigned int period_index, dma_addr_t buf_addr, | 796 | unsigned int period_index, dma_addr_t buf_addr, |
796 | size_t period_len, enum dma_transfer_direction direction) | 797 | unsigned int reg_width, size_t period_len, |
798 | enum dma_transfer_direction direction) | ||
797 | { | 799 | { |
798 | u32 ctrla; | 800 | struct at_dma_chan *atchan = to_at_dma_chan(chan); |
799 | 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; | ||
800 | 804 | ||
801 | /* prepare common CRTLA value */ | 805 | /* prepare common CRTLA value */ |
802 | ctrla = ATC_DEFAULT_CTRLA | atslave->ctrla | 806 | ctrla = ATC_DEFAULT_CTRLA | atslave->ctrla |
@@ -807,7 +811,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc, | |||
807 | switch (direction) { | 811 | switch (direction) { |
808 | case DMA_MEM_TO_DEV: | 812 | case DMA_MEM_TO_DEV: |
809 | desc->lli.saddr = buf_addr + (period_len * period_index); | 813 | desc->lli.saddr = buf_addr + (period_len * period_index); |
810 | desc->lli.daddr = atslave->tx_reg; | 814 | desc->lli.daddr = sconfig->dst_addr; |
811 | desc->lli.ctrla = ctrla; | 815 | desc->lli.ctrla = ctrla; |
812 | desc->lli.ctrlb = ATC_DST_ADDR_MODE_FIXED | 816 | desc->lli.ctrlb = ATC_DST_ADDR_MODE_FIXED |
813 | | ATC_SRC_ADDR_MODE_INCR | 817 | | ATC_SRC_ADDR_MODE_INCR |
@@ -817,7 +821,7 @@ atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc, | |||
817 | break; | 821 | break; |
818 | 822 | ||
819 | case DMA_DEV_TO_MEM: | 823 | case DMA_DEV_TO_MEM: |
820 | desc->lli.saddr = atslave->rx_reg; | 824 | desc->lli.saddr = sconfig->src_addr; |
821 | desc->lli.daddr = buf_addr + (period_len * period_index); | 825 | desc->lli.daddr = buf_addr + (period_len * period_index); |
822 | desc->lli.ctrla = ctrla; | 826 | desc->lli.ctrla = ctrla; |
823 | desc->lli.ctrlb = ATC_DST_ADDR_MODE_INCR | 827 | desc->lli.ctrlb = ATC_DST_ADDR_MODE_INCR |
@@ -850,9 +854,11 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, | |||
850 | { | 854 | { |
851 | struct at_dma_chan *atchan = to_at_dma_chan(chan); | 855 | struct at_dma_chan *atchan = to_at_dma_chan(chan); |
852 | struct at_dma_slave *atslave = chan->private; | 856 | struct at_dma_slave *atslave = chan->private; |
857 | struct dma_slave_config *sconfig = &atchan->dma_sconfig; | ||
853 | struct at_desc *first = NULL; | 858 | struct at_desc *first = NULL; |
854 | struct at_desc *prev = NULL; | 859 | struct at_desc *prev = NULL; |
855 | unsigned long was_cyclic; | 860 | unsigned long was_cyclic; |
861 | unsigned int reg_width; | ||
856 | unsigned int periods = buf_len / period_len; | 862 | unsigned int periods = buf_len / period_len; |
857 | unsigned int i; | 863 | unsigned int i; |
858 | 864 | ||
@@ -872,8 +878,13 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, | |||
872 | return NULL; | 878 | return NULL; |
873 | } | 879 | } |
874 | 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 | |||
875 | /* Check for too big/unaligned periods and unaligned DMA buffer */ | 886 | /* Check for too big/unaligned periods and unaligned DMA buffer */ |
876 | if (atc_dma_cyclic_check_values(atslave->reg_width, buf_addr, | 887 | if (atc_dma_cyclic_check_values(reg_width, buf_addr, |
877 | period_len, direction)) | 888 | period_len, direction)) |
878 | goto err_out; | 889 | goto err_out; |
879 | 890 | ||
@@ -885,8 +896,8 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, | |||
885 | if (!desc) | 896 | if (!desc) |
886 | goto err_desc_get; | 897 | goto err_desc_get; |
887 | 898 | ||
888 | if (atc_dma_cyclic_fill_desc(atslave, desc, i, buf_addr, | 899 | if (atc_dma_cyclic_fill_desc(chan, desc, i, buf_addr, |
889 | period_len, direction)) | 900 | reg_width, period_len, direction)) |
890 | goto err_desc_get; | 901 | goto err_desc_get; |
891 | 902 | ||
892 | atc_desc_chain(&first, &prev, desc); | 903 | atc_desc_chain(&first, &prev, desc); |
@@ -909,6 +920,23 @@ err_out: | |||
909 | return NULL; | 920 | return NULL; |
910 | } | 921 | } |
911 | 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 | |||
912 | 940 | ||
913 | 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, |
914 | unsigned long arg) | 942 | unsigned long arg) |
@@ -969,6 +997,8 @@ static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | |||
969 | clear_bit(ATC_IS_CYCLIC, &atchan->status); | 997 | clear_bit(ATC_IS_CYCLIC, &atchan->status); |
970 | 998 | ||
971 | 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); | ||
972 | } else { | 1002 | } else { |
973 | return -ENXIO; | 1003 | return -ENXIO; |
974 | } | 1004 | } |