aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2013-03-26 10:53:57 -0400
committerVinod Koul <vinod.koul@intel.com>2013-04-15 00:21:19 -0400
commitf776076b9fa82d630651c9af56359d80fce86d68 (patch)
treecb88a7aaa7840ace28833955396c84fd8cef7f9b /drivers/dma
parentbd2e6b664055a115a85be81af0ceb022726c5aef (diff)
dmaengine: dw_dmac: simplify master selection
The patch to add the common DMA binding added a dummy dw_dma_slave structure into the dw_dma_chan structure in order to configure the masters correctly. It turns out that this can be simplified if we pick the DMA masters in the dwc_alloc_chan_resources function instead and save them in the dw_dma_chan structure directly. This could be simplified further once all users that today use dw_dma_slave for configuration get converted to device tree based setup instead. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Cc: linux-arm-kernel@lists.infradead.org Acked-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/dw_dmac.c76
-rw-r--r--drivers/dma/dw_dmac_regs.h5
2 files changed, 33 insertions, 48 deletions
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 274fd7dd81f6..951ef5bc8afb 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -49,29 +49,22 @@ static inline unsigned int dwc_get_sms(struct dw_dma_slave *slave)
49 return slave ? slave->src_master : 1; 49 return slave ? slave->src_master : 1;
50} 50}
51 51
52#define SRC_MASTER 0 52static inline void dwc_set_masters(struct dw_dma_chan *dwc)
53#define DST_MASTER 1
54
55static inline unsigned int dwc_get_master(struct dma_chan *chan, int master)
56{ 53{
57 struct dw_dma *dw = to_dw_dma(chan->device); 54 struct dw_dma *dw = to_dw_dma(dwc->chan.device);
58 struct dw_dma_slave *dws = chan->private; 55 struct dw_dma_slave *dws = dwc->chan.private;
59 unsigned int m; 56 unsigned char mmax = dw->nr_masters - 1;
60
61 if (master == SRC_MASTER)
62 m = dwc_get_sms(dws);
63 else
64 m = dwc_get_dms(dws);
65 57
66 return min_t(unsigned int, dw->nr_masters - 1, m); 58 if (dwc->request_line == ~0) {
59 dwc->src_master = min_t(unsigned char, mmax, dwc_get_sms(dws));
60 dwc->dst_master = min_t(unsigned char, mmax, dwc_get_dms(dws));
61 }
67} 62}
68 63
69#define DWC_DEFAULT_CTLLO(_chan) ({ \ 64#define DWC_DEFAULT_CTLLO(_chan) ({ \
70 struct dw_dma_chan *_dwc = to_dw_dma_chan(_chan); \ 65 struct dw_dma_chan *_dwc = to_dw_dma_chan(_chan); \
71 struct dma_slave_config *_sconfig = &_dwc->dma_sconfig; \ 66 struct dma_slave_config *_sconfig = &_dwc->dma_sconfig; \
72 bool _is_slave = is_slave_direction(_dwc->direction); \ 67 bool _is_slave = is_slave_direction(_dwc->direction); \
73 int _dms = dwc_get_master(_chan, DST_MASTER); \
74 int _sms = dwc_get_master(_chan, SRC_MASTER); \
75 u8 _smsize = _is_slave ? _sconfig->src_maxburst : \ 68 u8 _smsize = _is_slave ? _sconfig->src_maxburst : \
76 DW_DMA_MSIZE_16; \ 69 DW_DMA_MSIZE_16; \
77 u8 _dmsize = _is_slave ? _sconfig->dst_maxburst : \ 70 u8 _dmsize = _is_slave ? _sconfig->dst_maxburst : \
@@ -81,8 +74,8 @@ static inline unsigned int dwc_get_master(struct dma_chan *chan, int master)
81 | DWC_CTLL_SRC_MSIZE(_smsize) \ 74 | DWC_CTLL_SRC_MSIZE(_smsize) \
82 | DWC_CTLL_LLP_D_EN \ 75 | DWC_CTLL_LLP_D_EN \
83 | DWC_CTLL_LLP_S_EN \ 76 | DWC_CTLL_LLP_S_EN \
84 | DWC_CTLL_DMS(_dms) \ 77 | DWC_CTLL_DMS(_dwc->dst_master) \
85 | DWC_CTLL_SMS(_sms)); \ 78 | DWC_CTLL_SMS(_dwc->src_master)); \
86 }) 79 })
87 80
88/* 81/*
@@ -92,13 +85,6 @@ static inline unsigned int dwc_get_master(struct dma_chan *chan, int master)
92 */ 85 */
93#define NR_DESCS_PER_CHANNEL 64 86#define NR_DESCS_PER_CHANNEL 64
94 87
95static inline unsigned int dwc_get_data_width(struct dma_chan *chan, int master)
96{
97 struct dw_dma *dw = to_dw_dma(chan->device);
98
99 return dw->data_width[dwc_get_master(chan, master)];
100}
101
102/*----------------------------------------------------------------------*/ 88/*----------------------------------------------------------------------*/
103 89
104static struct device *chan2dev(struct dma_chan *chan) 90static struct device *chan2dev(struct dma_chan *chan)
@@ -172,13 +158,7 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
172 if (dwc->initialized == true) 158 if (dwc->initialized == true)
173 return; 159 return;
174 160
175 if (dws && dws->cfg_hi == ~0 && dws->cfg_lo == ~0) { 161 if (dws) {
176 /* Autoconfigure based on request line from DT */
177 if (dwc->direction == DMA_MEM_TO_DEV)
178 cfghi = DWC_CFGH_DST_PER(dwc->request_line);
179 else if (dwc->direction == DMA_DEV_TO_MEM)
180 cfghi = DWC_CFGH_SRC_PER(dwc->request_line);
181 } else if (dws) {
182 /* 162 /*
183 * We need controller-specific data to set up slave 163 * We need controller-specific data to set up slave
184 * transfers. 164 * transfers.
@@ -189,9 +169,9 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
189 cfglo |= dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK; 169 cfglo |= dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK;
190 } else { 170 } else {
191 if (dwc->direction == DMA_MEM_TO_DEV) 171 if (dwc->direction == DMA_MEM_TO_DEV)
192 cfghi = DWC_CFGH_DST_PER(dwc->dma_sconfig.slave_id); 172 cfghi = DWC_CFGH_DST_PER(dwc->request_line);
193 else if (dwc->direction == DMA_DEV_TO_MEM) 173 else if (dwc->direction == DMA_DEV_TO_MEM)
194 cfghi = DWC_CFGH_SRC_PER(dwc->dma_sconfig.slave_id); 174 cfghi = DWC_CFGH_SRC_PER(dwc->request_line);
195 } 175 }
196 176
197 channel_writel(dwc, CFG_LO, cfglo); 177 channel_writel(dwc, CFG_LO, cfglo);
@@ -745,6 +725,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
745 size_t len, unsigned long flags) 725 size_t len, unsigned long flags)
746{ 726{
747 struct dw_dma_chan *dwc = to_dw_dma_chan(chan); 727 struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
728 struct dw_dma *dw = to_dw_dma(chan->device);
748 struct dw_desc *desc; 729 struct dw_desc *desc;
749 struct dw_desc *first; 730 struct dw_desc *first;
750 struct dw_desc *prev; 731 struct dw_desc *prev;
@@ -767,8 +748,8 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
767 748
768 dwc->direction = DMA_MEM_TO_MEM; 749 dwc->direction = DMA_MEM_TO_MEM;
769 750
770 data_width = min_t(unsigned int, dwc_get_data_width(chan, SRC_MASTER), 751 data_width = min_t(unsigned int, dw->data_width[dwc->src_master],
771 dwc_get_data_width(chan, DST_MASTER)); 752 dw->data_width[dwc->dst_master]);
772 753
773 src_width = dst_width = min_t(unsigned int, data_width, 754 src_width = dst_width = min_t(unsigned int, data_width,
774 dwc_fast_fls(src | dest | len)); 755 dwc_fast_fls(src | dest | len));
@@ -826,6 +807,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
826 unsigned long flags, void *context) 807 unsigned long flags, void *context)
827{ 808{
828 struct dw_dma_chan *dwc = to_dw_dma_chan(chan); 809 struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
810 struct dw_dma *dw = to_dw_dma(chan->device);
829 struct dma_slave_config *sconfig = &dwc->dma_sconfig; 811 struct dma_slave_config *sconfig = &dwc->dma_sconfig;
830 struct dw_desc *prev; 812 struct dw_desc *prev;
831 struct dw_desc *first; 813 struct dw_desc *first;
@@ -859,7 +841,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
859 ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) : 841 ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) :
860 DWC_CTLL_FC(DW_DMA_FC_D_M2P); 842 DWC_CTLL_FC(DW_DMA_FC_D_M2P);
861 843
862 data_width = dwc_get_data_width(chan, SRC_MASTER); 844 data_width = dw->data_width[dwc->src_master];
863 845
864 for_each_sg(sgl, sg, sg_len, i) { 846 for_each_sg(sgl, sg, sg_len, i) {
865 struct dw_desc *desc; 847 struct dw_desc *desc;
@@ -919,7 +901,7 @@ slave_sg_todev_fill_desc:
919 ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) : 901 ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) :
920 DWC_CTLL_FC(DW_DMA_FC_D_P2M); 902 DWC_CTLL_FC(DW_DMA_FC_D_P2M);
921 903
922 data_width = dwc_get_data_width(chan, DST_MASTER); 904 data_width = dw->data_width[dwc->dst_master];
923 905
924 for_each_sg(sgl, sg, sg_len, i) { 906 for_each_sg(sgl, sg, sg_len, i) {
925 struct dw_desc *desc; 907 struct dw_desc *desc;
@@ -1020,6 +1002,10 @@ set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
1020 memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig)); 1002 memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig));
1021 dwc->direction = sconfig->direction; 1003 dwc->direction = sconfig->direction;
1022 1004
1005 /* Take the request line from slave_id member */
1006 if (dwc->request_line == ~0)
1007 dwc->request_line = sconfig->slave_id;
1008
1023 convert_burst(&dwc->dma_sconfig.src_maxburst); 1009 convert_burst(&dwc->dma_sconfig.src_maxburst);
1024 convert_burst(&dwc->dma_sconfig.dst_maxburst); 1010 convert_burst(&dwc->dma_sconfig.dst_maxburst);
1025 convert_slave_id(dwc); 1011 convert_slave_id(dwc);
@@ -1170,6 +1156,8 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
1170 * doesn't mean what you think it means), and status writeback. 1156 * doesn't mean what you think it means), and status writeback.
1171 */ 1157 */
1172 1158
1159 dwc_set_masters(dwc);
1160
1173 spin_lock_irqsave(&dwc->lock, flags); 1161 spin_lock_irqsave(&dwc->lock, flags);
1174 i = dwc->descs_allocated; 1162 i = dwc->descs_allocated;
1175 while (dwc->descs_allocated < NR_DESCS_PER_CHANNEL) { 1163 while (dwc->descs_allocated < NR_DESCS_PER_CHANNEL) {
@@ -1227,6 +1215,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
1227 list_splice_init(&dwc->free_list, &list); 1215 list_splice_init(&dwc->free_list, &list);
1228 dwc->descs_allocated = 0; 1216 dwc->descs_allocated = 0;
1229 dwc->initialized = false; 1217 dwc->initialized = false;
1218 dwc->request_line = ~0;
1230 1219
1231 /* Disable interrupts */ 1220 /* Disable interrupts */
1232 channel_clear_bit(dw, MASK.XFER, dwc->mask); 1221 channel_clear_bit(dw, MASK.XFER, dwc->mask);
@@ -1254,23 +1243,15 @@ struct dw_dma_of_filter_args {
1254static bool dw_dma_of_filter(struct dma_chan *chan, void *param) 1243static bool dw_dma_of_filter(struct dma_chan *chan, void *param)
1255{ 1244{
1256 struct dw_dma_chan *dwc = to_dw_dma_chan(chan); 1245 struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
1257 struct dw_dma *dw = to_dw_dma(chan->device);
1258 struct dw_dma_of_filter_args *fargs = param; 1246 struct dw_dma_of_filter_args *fargs = param;
1259 struct dw_dma_slave *dws = &dwc->slave;
1260 1247
1261 /* Ensure the device matches our channel */ 1248 /* Ensure the device matches our channel */
1262 if (chan->device != &fargs->dw->dma) 1249 if (chan->device != &fargs->dw->dma)
1263 return false; 1250 return false;
1264 1251
1265 dws->dma_dev = dw->dma.dev;
1266 dws->cfg_hi = ~0;
1267 dws->cfg_lo = ~0;
1268 dws->src_master = fargs->src;
1269 dws->dst_master = fargs->dst;
1270
1271 dwc->request_line = fargs->req; 1252 dwc->request_line = fargs->req;
1272 1253 dwc->src_master = fargs->src;
1273 chan->private = dws; 1254 dwc->dst_master = fargs->dst;
1274 1255
1275 return true; 1256 return true;
1276} 1257}
@@ -1784,6 +1765,7 @@ static int dw_probe(struct platform_device *pdev)
1784 channel_clear_bit(dw, CH_EN, dwc->mask); 1765 channel_clear_bit(dw, CH_EN, dwc->mask);
1785 1766
1786 dwc->direction = DMA_TRANS_NONE; 1767 dwc->direction = DMA_TRANS_NONE;
1768 dwc->request_line = ~0;
1787 1769
1788 /* Hardware configuration */ 1770 /* Hardware configuration */
1789 if (autocfg) { 1771 if (autocfg) {
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 4d02c3669b75..9b0e12e85e31 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -212,8 +212,11 @@ struct dw_dma_chan {
212 /* hardware configuration */ 212 /* hardware configuration */
213 unsigned int block_size; 213 unsigned int block_size;
214 bool nollp; 214 bool nollp;
215
216 /* custom slave configuration */
215 unsigned int request_line; 217 unsigned int request_line;
216 struct dw_dma_slave slave; 218 unsigned char src_master;
219 unsigned char dst_master;
217 220
218 /* configuration passed via DMA_SLAVE_CONFIG */ 221 /* configuration passed via DMA_SLAVE_CONFIG */
219 struct dma_slave_config dma_sconfig; 222 struct dma_slave_config dma_sconfig;