aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@st.com>2012-02-01 05:42:26 -0500
committerVinod Koul <vinod.koul@linux.intel.com>2012-02-22 07:45:38 -0500
commit327e6970258618da810f72e86cf2a8b803927e14 (patch)
treece5d4ac48b3b21a3d70d0acceebaa8b9e212daa1 /drivers
parent6bc711f6bd9dd393e1f9bbae354906affcd02aa5 (diff)
dmaengine/dw_dmac: Add support for DMA_SLAVE_CONFIG
This patch adds support for DMA_SLAVE_CONFIG in dwc DMAC controller. Fields in struct dw_dma_slave for passing similar data are preserved in this patch untill all existing users are fixed. That will be handled later in this patchset. Signed-off-by: Viresh Kumar <viresh.kumar@st.com> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/dma/dw_dmac.c119
-rw-r--r--drivers/dma/dw_dmac_regs.h3
2 files changed, 93 insertions, 29 deletions
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 9f4310f013f5..0e4b5c6a2f86 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -9,6 +9,7 @@
9 * it under the terms of the GNU General Public License version 2 as 9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation. 10 * published by the Free Software Foundation.
11 */ 11 */
12#include <linux/bitops.h>
12#include <linux/clk.h> 13#include <linux/clk.h>
13#include <linux/delay.h> 14#include <linux/delay.h>
14#include <linux/dmaengine.h> 15#include <linux/dmaengine.h>
@@ -33,19 +34,23 @@
33 * which does not support descriptor writeback. 34 * which does not support descriptor writeback.
34 */ 35 */
35 36
36#define DWC_DEFAULT_CTLLO(private) ({ \ 37#define DWC_DEFAULT_CTLLO(_chan) ({ \
37 struct dw_dma_slave *__slave = (private); \ 38 struct dw_dma_slave *__slave = (_chan->private); \
38 int dms = __slave ? __slave->dst_master : 0; \ 39 struct dw_dma_chan *_dwc = to_dw_dma_chan(_chan); \
39 int sms = __slave ? __slave->src_master : 1; \ 40 struct dma_slave_config *_sconfig = &_dwc->dma_sconfig; \
40 u8 smsize = __slave ? __slave->src_msize : DW_DMA_MSIZE_16; \ 41 int _dms = __slave ? __slave->dst_master : 0; \
41 u8 dmsize = __slave ? __slave->dst_msize : DW_DMA_MSIZE_16; \ 42 int _sms = __slave ? __slave->src_master : 1; \
43 u8 _smsize = __slave ? _sconfig->src_maxburst : \
44 DW_DMA_MSIZE_16; \
45 u8 _dmsize = __slave ? _sconfig->dst_maxburst : \
46 DW_DMA_MSIZE_16; \
42 \ 47 \
43 (DWC_CTLL_DST_MSIZE(dmsize) \ 48 (DWC_CTLL_DST_MSIZE(_dmsize) \
44 | DWC_CTLL_SRC_MSIZE(smsize) \ 49 | DWC_CTLL_SRC_MSIZE(_smsize) \
45 | DWC_CTLL_LLP_D_EN \ 50 | DWC_CTLL_LLP_D_EN \
46 | DWC_CTLL_LLP_S_EN \ 51 | DWC_CTLL_LLP_S_EN \
47 | DWC_CTLL_DMS(dms) \ 52 | DWC_CTLL_DMS(_dms) \
48 | DWC_CTLL_SMS(sms)); \ 53 | DWC_CTLL_SMS(_sms)); \
49 }) 54 })
50 55
51/* 56/*
@@ -656,7 +661,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
656 else 661 else
657 src_width = dst_width = 0; 662 src_width = dst_width = 0;
658 663
659 ctllo = DWC_DEFAULT_CTLLO(chan->private) 664 ctllo = DWC_DEFAULT_CTLLO(chan)
660 | DWC_CTLL_DST_WIDTH(dst_width) 665 | DWC_CTLL_DST_WIDTH(dst_width)
661 | DWC_CTLL_SRC_WIDTH(src_width) 666 | DWC_CTLL_SRC_WIDTH(src_width)
662 | DWC_CTLL_DST_INC 667 | DWC_CTLL_DST_INC
@@ -717,6 +722,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
717{ 722{
718 struct dw_dma_chan *dwc = to_dw_dma_chan(chan); 723 struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
719 struct dw_dma_slave *dws = chan->private; 724 struct dw_dma_slave *dws = chan->private;
725 struct dma_slave_config *sconfig = &dwc->dma_sconfig;
720 struct dw_desc *prev; 726 struct dw_desc *prev;
721 struct dw_desc *first; 727 struct dw_desc *first;
722 u32 ctllo; 728 u32 ctllo;
@@ -732,17 +738,20 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
732 if (unlikely(!dws || !sg_len)) 738 if (unlikely(!dws || !sg_len))
733 return NULL; 739 return NULL;
734 740
735 reg_width = dws->reg_width;
736 prev = first = NULL; 741 prev = first = NULL;
737 742
738 switch (direction) { 743 switch (direction) {
739 case DMA_MEM_TO_DEV: 744 case DMA_MEM_TO_DEV:
740 ctllo = (DWC_DEFAULT_CTLLO(chan->private) 745 reg_width = __fls(sconfig->dst_addr_width);
746 reg = sconfig->dst_addr;
747 ctllo = (DWC_DEFAULT_CTLLO(chan)
741 | DWC_CTLL_DST_WIDTH(reg_width) 748 | DWC_CTLL_DST_WIDTH(reg_width)
742 | DWC_CTLL_DST_FIX 749 | DWC_CTLL_DST_FIX
743 | DWC_CTLL_SRC_INC 750 | DWC_CTLL_SRC_INC);
744 | DWC_CTLL_FC(dws->fc)); 751
745 reg = dws->tx_reg; 752 ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) :
753 DWC_CTLL_FC(DW_DMA_FC_D_M2P);
754
746 for_each_sg(sgl, sg, sg_len, i) { 755 for_each_sg(sgl, sg, sg_len, i) {
747 struct dw_desc *desc; 756 struct dw_desc *desc;
748 u32 len, dlen, mem; 757 u32 len, dlen, mem;
@@ -800,13 +809,16 @@ slave_sg_todev_fill_desc:
800 } 809 }
801 break; 810 break;
802 case DMA_DEV_TO_MEM: 811 case DMA_DEV_TO_MEM:
803 ctllo = (DWC_DEFAULT_CTLLO(chan->private) 812 reg_width = __fls(sconfig->src_addr_width);
813 reg = sconfig->src_addr;
814 ctllo = (DWC_DEFAULT_CTLLO(chan)
804 | DWC_CTLL_SRC_WIDTH(reg_width) 815 | DWC_CTLL_SRC_WIDTH(reg_width)
805 | DWC_CTLL_DST_INC 816 | DWC_CTLL_DST_INC
806 | DWC_CTLL_SRC_FIX 817 | DWC_CTLL_SRC_FIX);
807 | DWC_CTLL_FC(dws->fc)); 818
819 ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) :
820 DWC_CTLL_FC(DW_DMA_FC_D_P2M);
808 821
809 reg = dws->rx_reg;
810 for_each_sg(sgl, sg, sg_len, i) { 822 for_each_sg(sgl, sg, sg_len, i) {
811 struct dw_desc *desc; 823 struct dw_desc *desc;
812 u32 len, dlen, mem; 824 u32 len, dlen, mem;
@@ -884,6 +896,39 @@ err_desc_get:
884 return NULL; 896 return NULL;
885} 897}
886 898
899/*
900 * Fix sconfig's burst size according to dw_dmac. We need to convert them as:
901 * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3.
902 *
903 * NOTE: burst size 2 is not supported by controller.
904 *
905 * This can be done by finding least significant bit set: n & (n - 1)
906 */
907static inline void convert_burst(u32 *maxburst)
908{
909 if (*maxburst > 1)
910 *maxburst = fls(*maxburst) - 2;
911 else
912 *maxburst = 0;
913}
914
915static int
916set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
917{
918 struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
919
920 /* Check if it is chan is configured for slave transfers */
921 if (!chan->private)
922 return -EINVAL;
923
924 memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig));
925
926 convert_burst(&dwc->dma_sconfig.src_maxburst);
927 convert_burst(&dwc->dma_sconfig.dst_maxburst);
928
929 return 0;
930}
931
887static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, 932static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
888 unsigned long arg) 933 unsigned long arg)
889{ 934{
@@ -933,8 +978,11 @@ static int dwc_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
933 /* Flush all pending and queued descriptors */ 978 /* Flush all pending and queued descriptors */
934 list_for_each_entry_safe(desc, _desc, &list, desc_node) 979 list_for_each_entry_safe(desc, _desc, &list, desc_node)
935 dwc_descriptor_complete(dwc, desc, false); 980 dwc_descriptor_complete(dwc, desc, false);
936 } else 981 } else if (cmd == DMA_SLAVE_CONFIG) {
982 return set_runtime_config(chan, (struct dma_slave_config *)arg);
983 } else {
937 return -ENXIO; 984 return -ENXIO;
985 }
938 986
939 return 0; 987 return 0;
940} 988}
@@ -1167,11 +1215,11 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
1167 enum dma_transfer_direction direction) 1215 enum dma_transfer_direction direction)
1168{ 1216{
1169 struct dw_dma_chan *dwc = to_dw_dma_chan(chan); 1217 struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
1218 struct dma_slave_config *sconfig = &dwc->dma_sconfig;
1170 struct dw_cyclic_desc *cdesc; 1219 struct dw_cyclic_desc *cdesc;
1171 struct dw_cyclic_desc *retval = NULL; 1220 struct dw_cyclic_desc *retval = NULL;
1172 struct dw_desc *desc; 1221 struct dw_desc *desc;
1173 struct dw_desc *last = NULL; 1222 struct dw_desc *last = NULL;
1174 struct dw_dma_slave *dws = chan->private;
1175 unsigned long was_cyclic; 1223 unsigned long was_cyclic;
1176 unsigned int reg_width; 1224 unsigned int reg_width;
1177 unsigned int periods; 1225 unsigned int periods;
@@ -1195,7 +1243,12 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
1195 } 1243 }
1196 1244
1197 retval = ERR_PTR(-EINVAL); 1245 retval = ERR_PTR(-EINVAL);
1198 reg_width = dws->reg_width; 1246
1247 if (direction == DMA_MEM_TO_DEV)
1248 reg_width = __ffs(sconfig->dst_addr_width);
1249 else
1250 reg_width = __ffs(sconfig->src_addr_width);
1251
1199 periods = buf_len / period_len; 1252 periods = buf_len / period_len;
1200 1253
1201 /* Check for too big/unaligned periods and unaligned DMA buffer. */ 1254 /* Check for too big/unaligned periods and unaligned DMA buffer. */
@@ -1228,26 +1281,34 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
1228 1281
1229 switch (direction) { 1282 switch (direction) {
1230 case DMA_MEM_TO_DEV: 1283 case DMA_MEM_TO_DEV:
1231 desc->lli.dar = dws->tx_reg; 1284 desc->lli.dar = sconfig->dst_addr;
1232 desc->lli.sar = buf_addr + (period_len * i); 1285 desc->lli.sar = buf_addr + (period_len * i);
1233 desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private) 1286 desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan)
1234 | DWC_CTLL_DST_WIDTH(reg_width) 1287 | DWC_CTLL_DST_WIDTH(reg_width)
1235 | DWC_CTLL_SRC_WIDTH(reg_width) 1288 | DWC_CTLL_SRC_WIDTH(reg_width)
1236 | DWC_CTLL_DST_FIX 1289 | DWC_CTLL_DST_FIX
1237 | DWC_CTLL_SRC_INC 1290 | DWC_CTLL_SRC_INC
1238 | DWC_CTLL_FC(dws->fc)
1239 | DWC_CTLL_INT_EN); 1291 | DWC_CTLL_INT_EN);
1292
1293 desc->lli.ctllo |= sconfig->device_fc ?
1294 DWC_CTLL_FC(DW_DMA_FC_P_M2P) :
1295 DWC_CTLL_FC(DW_DMA_FC_D_M2P);
1296
1240 break; 1297 break;
1241 case DMA_DEV_TO_MEM: 1298 case DMA_DEV_TO_MEM:
1242 desc->lli.dar = buf_addr + (period_len * i); 1299 desc->lli.dar = buf_addr + (period_len * i);
1243 desc->lli.sar = dws->rx_reg; 1300 desc->lli.sar = sconfig->src_addr;
1244 desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private) 1301 desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan)
1245 | DWC_CTLL_SRC_WIDTH(reg_width) 1302 | DWC_CTLL_SRC_WIDTH(reg_width)
1246 | DWC_CTLL_DST_WIDTH(reg_width) 1303 | DWC_CTLL_DST_WIDTH(reg_width)
1247 | DWC_CTLL_DST_INC 1304 | DWC_CTLL_DST_INC
1248 | DWC_CTLL_SRC_FIX 1305 | DWC_CTLL_SRC_FIX
1249 | DWC_CTLL_FC(dws->fc)
1250 | DWC_CTLL_INT_EN); 1306 | DWC_CTLL_INT_EN);
1307
1308 desc->lli.ctllo |= sconfig->device_fc ?
1309 DWC_CTLL_FC(DW_DMA_FC_P_P2M) :
1310 DWC_CTLL_FC(DW_DMA_FC_D_P2M);
1311
1251 break; 1312 break;
1252 default: 1313 default:
1253 break; 1314 break;
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 5eef6946a367..2005d301803d 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -153,6 +153,9 @@ struct dw_dma_chan {
153 struct dw_cyclic_desc *cdesc; 153 struct dw_cyclic_desc *cdesc;
154 154
155 unsigned int descs_allocated; 155 unsigned int descs_allocated;
156
157 /* configuration passed via DMA_SLAVE_CONFIG */
158 struct dma_slave_config dma_sconfig;
156}; 159};
157 160
158static inline struct dw_dma_chan_regs __iomem * 161static inline struct dw_dma_chan_regs __iomem *