aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolas Ferre <nicolas.ferre@atmel.com>2012-03-14 07:41:43 -0400
committerVinod Koul <vinod.koul@linux.intel.com>2012-03-21 11:42:29 -0400
commitbeeaa103eecc7a132682c40867f0ef70655383a5 (patch)
treec1cc34c65347a04d859eae78076322668d2f636d
parent185ecb5f4fd43911c35956d4cc7d94a1da30417f (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>
-rw-r--r--arch/arm/mach-at91/at91sam9g45_devices.c1
-rw-r--r--arch/arm/mach-at91/include/mach/at_hdmac.h15
-rw-r--r--drivers/dma/at_hdmac.c56
-rw-r--r--drivers/dma/at_hdmac_regs.h32
4 files changed, 75 insertions, 29 deletions
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index b7582dd10dc3..1f89b206c26f 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -431,7 +431,6 @@ void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data)
431 431
432 /* DMA slave channel configuration */ 432 /* DMA slave channel configuration */
433 atslave->dma_dev = &at_hdmac_device.dev; 433 atslave->dma_dev = &at_hdmac_device.dev;
434 atslave->reg_width = AT_DMA_SLAVE_WIDTH_32BIT;
435 atslave->cfg = ATC_FIFOCFG_HALFFIFO 434 atslave->cfg = ATC_FIFOCFG_HALFFIFO
436 | ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW; 435 | ATC_SRC_H2SEL_HW | ATC_DST_H2SEL_HW;
437 atslave->ctrla = ATC_SCSIZE_16 | ATC_DCSIZE_16; 436 atslave->ctrla = ATC_SCSIZE_16 | ATC_DCSIZE_16;
diff --git a/arch/arm/mach-at91/include/mach/at_hdmac.h b/arch/arm/mach-at91/include/mach/at_hdmac.h
index 187cb58345c0..fff48d1a0f4e 100644
--- a/arch/arm/mach-at91/include/mach/at_hdmac.h
+++ b/arch/arm/mach-at91/include/mach/at_hdmac.h
@@ -24,18 +24,6 @@ struct at_dma_platform_data {
24}; 24};
25 25
26/** 26/**
27 * enum at_dma_slave_width - DMA slave register access width.
28 * @AT_DMA_SLAVE_WIDTH_8BIT: Do 8-bit slave register accesses
29 * @AT_DMA_SLAVE_WIDTH_16BIT: Do 16-bit slave register accesses
30 * @AT_DMA_SLAVE_WIDTH_32BIT: Do 32-bit slave register accesses
31 */
32enum at_dma_slave_width {
33 AT_DMA_SLAVE_WIDTH_8BIT = 0,
34 AT_DMA_SLAVE_WIDTH_16BIT,
35 AT_DMA_SLAVE_WIDTH_32BIT,
36};
37
38/**
39 * struct at_dma_slave - Controller-specific information about a slave 27 * struct at_dma_slave - Controller-specific information about a slave
40 * @dma_dev: required DMA master device 28 * @dma_dev: required DMA master device
41 * @tx_reg: physical address of data register used for 29 * @tx_reg: physical address of data register used for
@@ -48,9 +36,6 @@ enum at_dma_slave_width {
48 */ 36 */
49struct at_dma_slave { 37struct at_dma_slave {
50 struct device *dma_dev; 38 struct device *dma_dev;
51 dma_addr_t tx_reg;
52 dma_addr_t rx_reg;
53 enum at_dma_slave_width reg_width;
54 u32 cfg; 39 u32 cfg;
55 u32 ctrla; 40 u32 ctrla;
56}; 41};
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 */
793static int 794static int
794atc_dma_cyclic_fill_desc(struct at_dma_slave *atslave, struct at_desc *desc, 795atc_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
923static 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
913static int atc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, 941static 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 }
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
index 08fd8a0ae797..897a8bcaec90 100644
--- a/drivers/dma/at_hdmac_regs.h
+++ b/drivers/dma/at_hdmac_regs.h
@@ -207,6 +207,7 @@ enum atc_status {
207 * @save_cfg: configuration register that is saved on suspend/resume cycle 207 * @save_cfg: configuration register that is saved on suspend/resume cycle
208 * @save_dscr: for cyclic operations, preserve next descriptor address in 208 * @save_dscr: for cyclic operations, preserve next descriptor address in
209 * the cyclic list on suspend/resume cycle 209 * the cyclic list on suspend/resume cycle
210 * @dma_sconfig: configuration for slave transfers, passed via DMA_SLAVE_CONFIG
210 * @lock: serializes enqueue/dequeue operations to descriptors lists 211 * @lock: serializes enqueue/dequeue operations to descriptors lists
211 * @active_list: list of descriptors dmaengine is being running on 212 * @active_list: list of descriptors dmaengine is being running on
212 * @queue: list of descriptors ready to be submitted to engine 213 * @queue: list of descriptors ready to be submitted to engine
@@ -222,6 +223,7 @@ struct at_dma_chan {
222 struct tasklet_struct tasklet; 223 struct tasklet_struct tasklet;
223 u32 save_cfg; 224 u32 save_cfg;
224 u32 save_dscr; 225 u32 save_dscr;
226 struct dma_slave_config dma_sconfig;
225 227
226 spinlock_t lock; 228 spinlock_t lock;
227 229
@@ -243,6 +245,36 @@ static inline struct at_dma_chan *to_at_dma_chan(struct dma_chan *dchan)
243 return container_of(dchan, struct at_dma_chan, chan_common); 245 return container_of(dchan, struct at_dma_chan, chan_common);
244} 246}
245 247
248/*
249 * Fix sconfig's burst size according to at_hdmac. We need to convert them as:
250 * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3, 32 -> 4, 64 -> 5, 128 -> 6, 256 -> 7.
251 *
252 * This can be done by finding most significant bit set.
253 */
254static inline void convert_burst(u32 *maxburst)
255{
256 if (*maxburst > 1)
257 *maxburst = fls(*maxburst) - 2;
258 else
259 *maxburst = 0;
260}
261
262/*
263 * Fix sconfig's bus width according to at_hdmac.
264 * 1 byte -> 0, 2 bytes -> 1, 4 bytes -> 2.
265 */
266static inline u8 convert_buswidth(enum dma_slave_buswidth addr_width)
267{
268 switch (addr_width) {
269 case DMA_SLAVE_BUSWIDTH_2_BYTES:
270 return 1;
271 case DMA_SLAVE_BUSWIDTH_4_BYTES:
272 return 2;
273 default:
274 /* For 1 byte width or fallback */
275 return 0;
276 }
277}
246 278
247/*-- Controller ------------------------------------------------------*/ 279/*-- Controller ------------------------------------------------------*/
248 280