aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma/ste_dma40.c
diff options
context:
space:
mode:
authorLee Jones <lee.jones@linaro.org>2013-05-15 05:51:57 -0400
committerLinus Walleij <linus.walleij@linaro.org>2013-06-04 05:12:09 -0400
commit43f2e1a3be5d83004f09bcb53c46f273e7473a00 (patch)
treeaf13dad918da322ee4984925453dbe157731d790 /drivers/dma/ste_dma40.c
parent16db3411ebd4777b0b1b7207b10730b726fb751c (diff)
dmaengine: ste_dma40: Convert data_width from register bit format to value
When a DMA client requests and configures a DMA channel, it requests data_width in Bytes. The DMA40 driver then swiftly converts it over to the necessary register bit value. Unfortunately, for any subsequent calculations we have to shift '1' by the bit pattern (1 << data_width) times to make any sense of it. This patch flips the semantics on its head and only converts the value to its respective register bit pattern when writing to registers. This way we can use the true data_width (in Bytes) value. Cc: Dan Williams <djbw@fb.com> Cc: Per Forlin <per.forlin@stericsson.com> Cc: Rabin Vincent <rabin@rab.in> Acked-by: Vinod Koul <vinod.koul@intel.com> Signed-off-by: Lee Jones <lee.jones@linaro.org> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/dma/ste_dma40.c')
-rw-r--r--drivers/dma/ste_dma40.c63
1 files changed, 25 insertions, 38 deletions
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c
index 483da1660eae..76c255fcdc2d 100644
--- a/drivers/dma/ste_dma40.c
+++ b/drivers/dma/ste_dma40.c
@@ -80,11 +80,11 @@ struct stedma40_chan_cfg dma40_memcpy_conf_phy = {
80 .mode = STEDMA40_MODE_PHYSICAL, 80 .mode = STEDMA40_MODE_PHYSICAL,
81 .dir = DMA_MEM_TO_MEM, 81 .dir = DMA_MEM_TO_MEM,
82 82
83 .src_info.data_width = STEDMA40_BYTE_WIDTH, 83 .src_info.data_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
84 .src_info.psize = STEDMA40_PSIZE_PHY_1, 84 .src_info.psize = STEDMA40_PSIZE_PHY_1,
85 .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, 85 .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
86 86
87 .dst_info.data_width = STEDMA40_BYTE_WIDTH, 87 .dst_info.data_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
88 .dst_info.psize = STEDMA40_PSIZE_PHY_1, 88 .dst_info.psize = STEDMA40_PSIZE_PHY_1,
89 .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, 89 .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
90}; 90};
@@ -94,11 +94,11 @@ struct stedma40_chan_cfg dma40_memcpy_conf_log = {
94 .mode = STEDMA40_MODE_LOGICAL, 94 .mode = STEDMA40_MODE_LOGICAL,
95 .dir = DMA_MEM_TO_MEM, 95 .dir = DMA_MEM_TO_MEM,
96 96
97 .src_info.data_width = STEDMA40_BYTE_WIDTH, 97 .src_info.data_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
98 .src_info.psize = STEDMA40_PSIZE_LOG_1, 98 .src_info.psize = STEDMA40_PSIZE_LOG_1,
99 .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, 99 .src_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
100 100
101 .dst_info.data_width = STEDMA40_BYTE_WIDTH, 101 .dst_info.data_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
102 .dst_info.psize = STEDMA40_PSIZE_LOG_1, 102 .dst_info.psize = STEDMA40_PSIZE_LOG_1,
103 .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL, 103 .dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL,
104}; 104};
@@ -1005,20 +1005,21 @@ static int d40_psize_2_burst_size(bool is_log, int psize)
1005 1005
1006/* 1006/*
1007 * The dma only supports transmitting packages up to 1007 * The dma only supports transmitting packages up to
1008 * STEDMA40_MAX_SEG_SIZE << data_width. Calculate the total number of 1008 * STEDMA40_MAX_SEG_SIZE * data_width, where data_width is stored in Bytes.
1009 * dma elements required to send the entire sg list 1009 *
1010 * Calculate the total number of dma elements required to send the entire sg list.
1010 */ 1011 */
1011static int d40_size_2_dmalen(int size, u32 data_width1, u32 data_width2) 1012static int d40_size_2_dmalen(int size, u32 data_width1, u32 data_width2)
1012{ 1013{
1013 int dmalen; 1014 int dmalen;
1014 u32 max_w = max(data_width1, data_width2); 1015 u32 max_w = max(data_width1, data_width2);
1015 u32 min_w = min(data_width1, data_width2); 1016 u32 min_w = min(data_width1, data_width2);
1016 u32 seg_max = ALIGN(STEDMA40_MAX_SEG_SIZE << min_w, 1 << max_w); 1017 u32 seg_max = ALIGN(STEDMA40_MAX_SEG_SIZE * min_w, max_w);
1017 1018
1018 if (seg_max > STEDMA40_MAX_SEG_SIZE) 1019 if (seg_max > STEDMA40_MAX_SEG_SIZE)
1019 seg_max -= (1 << max_w); 1020 seg_max -= max_w;
1020 1021
1021 if (!IS_ALIGNED(size, 1 << max_w)) 1022 if (!IS_ALIGNED(size, max_w))
1022 return -EINVAL; 1023 return -EINVAL;
1023 1024
1024 if (size <= seg_max) 1025 if (size <= seg_max)
@@ -1464,7 +1465,7 @@ static u32 d40_residue(struct d40_chan *d40c)
1464 >> D40_SREG_ELEM_PHY_ECNT_POS; 1465 >> D40_SREG_ELEM_PHY_ECNT_POS;
1465 } 1466 }
1466 1467
1467 return num_elt * (1 << d40c->dma_cfg.dst_info.data_width); 1468 return num_elt * d40c->dma_cfg.dst_info.data_width;
1468} 1469}
1469 1470
1470static bool d40_tx_is_linked(struct d40_chan *d40c) 1471static bool d40_tx_is_linked(struct d40_chan *d40c)
@@ -1784,9 +1785,9 @@ static int d40_validate_conf(struct d40_chan *d40c,
1784 } 1785 }
1785 1786
1786 if (d40_psize_2_burst_size(is_log, conf->src_info.psize) * 1787 if (d40_psize_2_burst_size(is_log, conf->src_info.psize) *
1787 (1 << conf->src_info.data_width) != 1788 conf->src_info.data_width !=
1788 d40_psize_2_burst_size(is_log, conf->dst_info.psize) * 1789 d40_psize_2_burst_size(is_log, conf->dst_info.psize) *
1789 (1 << conf->dst_info.data_width)) { 1790 conf->dst_info.data_width) {
1790 /* 1791 /*
1791 * The DMAC hardware only supports 1792 * The DMAC hardware only supports
1792 * src (burst x width) == dst (burst x width) 1793 * src (burst x width) == dst (burst x width)
@@ -2673,33 +2674,10 @@ static void d40_terminate_all(struct dma_chan *chan)
2673static int 2674static int
2674dma40_config_to_halfchannel(struct d40_chan *d40c, 2675dma40_config_to_halfchannel(struct d40_chan *d40c,
2675 struct stedma40_half_channel_info *info, 2676 struct stedma40_half_channel_info *info,
2676 enum dma_slave_buswidth width,
2677 u32 maxburst) 2677 u32 maxburst)
2678{ 2678{
2679 enum stedma40_periph_data_width addr_width;
2680 int psize; 2679 int psize;
2681 2680
2682 switch (width) {
2683 case DMA_SLAVE_BUSWIDTH_1_BYTE:
2684 addr_width = STEDMA40_BYTE_WIDTH;
2685 break;
2686 case DMA_SLAVE_BUSWIDTH_2_BYTES:
2687 addr_width = STEDMA40_HALFWORD_WIDTH;
2688 break;
2689 case DMA_SLAVE_BUSWIDTH_4_BYTES:
2690 addr_width = STEDMA40_WORD_WIDTH;
2691 break;
2692 case DMA_SLAVE_BUSWIDTH_8_BYTES:
2693 addr_width = STEDMA40_DOUBLEWORD_WIDTH;
2694 break;
2695 default:
2696 dev_err(d40c->base->dev,
2697 "illegal peripheral address width "
2698 "requested (%d)\n",
2699 width);
2700 return -EINVAL;
2701 }
2702
2703 if (chan_is_logical(d40c)) { 2681 if (chan_is_logical(d40c)) {
2704 if (maxburst >= 16) 2682 if (maxburst >= 16)
2705 psize = STEDMA40_PSIZE_LOG_16; 2683 psize = STEDMA40_PSIZE_LOG_16;
@@ -2720,7 +2698,6 @@ dma40_config_to_halfchannel(struct d40_chan *d40c,
2720 psize = STEDMA40_PSIZE_PHY_1; 2698 psize = STEDMA40_PSIZE_PHY_1;
2721 } 2699 }
2722 2700
2723 info->data_width = addr_width;
2724 info->psize = psize; 2701 info->psize = psize;
2725 info->flow_ctrl = STEDMA40_NO_FLOW_CTRL; 2702 info->flow_ctrl = STEDMA40_NO_FLOW_CTRL;
2726 2703
@@ -2804,14 +2781,24 @@ static int d40_set_runtime_config(struct dma_chan *chan,
2804 src_maxburst = dst_maxburst * dst_addr_width / src_addr_width; 2781 src_maxburst = dst_maxburst * dst_addr_width / src_addr_width;
2805 } 2782 }
2806 2783
2784 /* Only valid widths are; 1, 2, 4 and 8. */
2785 if (src_addr_width <= DMA_SLAVE_BUSWIDTH_UNDEFINED ||
2786 src_addr_width > DMA_SLAVE_BUSWIDTH_8_BYTES ||
2787 dst_addr_width <= DMA_SLAVE_BUSWIDTH_UNDEFINED ||
2788 dst_addr_width > DMA_SLAVE_BUSWIDTH_8_BYTES ||
2789 ((src_addr_width > 1) && (src_addr_width & 1)) ||
2790 ((dst_addr_width > 1) && (dst_addr_width & 1)))
2791 return -EINVAL;
2792
2793 cfg->src_info.data_width = src_addr_width;
2794 cfg->dst_info.data_width = dst_addr_width;
2795
2807 ret = dma40_config_to_halfchannel(d40c, &cfg->src_info, 2796 ret = dma40_config_to_halfchannel(d40c, &cfg->src_info,
2808 src_addr_width,
2809 src_maxburst); 2797 src_maxburst);
2810 if (ret) 2798 if (ret)
2811 return ret; 2799 return ret;
2812 2800
2813 ret = dma40_config_to_halfchannel(d40c, &cfg->dst_info, 2801 ret = dma40_config_to_halfchannel(d40c, &cfg->dst_info,
2814 dst_addr_width,
2815 dst_maxburst); 2802 dst_maxburst);
2816 if (ret) 2803 if (ret)
2817 return ret; 2804 return ret;