aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2012-09-21 08:05:48 -0400
committerVinod Koul <vinod.koul@linux.intel.com>2012-09-27 06:05:23 -0400
commita09820043c9e11149145a1ec221eed4a7b42dcce (patch)
tree0561b70b0803aec4b57e41e90fa0ece433f9d59f /drivers/dma
parent4a63a8b3e8d2e4f56174deb728085010aa3ac2a1 (diff)
dw_dmac: autoconfigure data_width or get it via platform data
Not all of the controllers support the 64 bit data width. Make it configurable via platform data. The driver will try to get a value from the component parameters, otherwise it will use the platform data. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Vinod Koul <vinod.koul@linux.intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/dw_dmac.c46
-rw-r--r--drivers/dma/dw_dmac_regs.h7
2 files changed, 47 insertions, 6 deletions
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index c143b7e40716..cdc0a1fe2c64 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -36,12 +36,22 @@
36 * which does not support descriptor writeback. 36 * which does not support descriptor writeback.
37 */ 37 */
38 38
39static inline unsigned int dwc_get_dms(struct dw_dma_slave *slave)
40{
41 return slave ? slave->dst_master : 0;
42}
43
44static inline unsigned int dwc_get_sms(struct dw_dma_slave *slave)
45{
46 return slave ? slave->src_master : 1;
47}
48
39#define DWC_DEFAULT_CTLLO(_chan) ({ \ 49#define DWC_DEFAULT_CTLLO(_chan) ({ \
40 struct dw_dma_slave *__slave = (_chan->private); \ 50 struct dw_dma_slave *__slave = (_chan->private); \
41 struct dw_dma_chan *_dwc = to_dw_dma_chan(_chan); \ 51 struct dw_dma_chan *_dwc = to_dw_dma_chan(_chan); \
42 struct dma_slave_config *_sconfig = &_dwc->dma_sconfig; \ 52 struct dma_slave_config *_sconfig = &_dwc->dma_sconfig; \
43 int _dms = __slave ? __slave->dst_master : 0; \ 53 int _dms = dwc_get_dms(__slave); \
44 int _sms = __slave ? __slave->src_master : 1; \ 54 int _sms = dwc_get_sms(__slave); \
45 u8 _smsize = __slave ? _sconfig->src_maxburst : \ 55 u8 _smsize = __slave ? _sconfig->src_maxburst : \
46 DW_DMA_MSIZE_16; \ 56 DW_DMA_MSIZE_16; \
47 u8 _dmsize = __slave ? _sconfig->dst_maxburst : \ 57 u8 _dmsize = __slave ? _sconfig->dst_maxburst : \
@@ -631,6 +641,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
631 size_t len, unsigned long flags) 641 size_t len, unsigned long flags)
632{ 642{
633 struct dw_dma_chan *dwc = to_dw_dma_chan(chan); 643 struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
644 struct dw_dma_slave *dws = chan->private;
634 struct dw_desc *desc; 645 struct dw_desc *desc;
635 struct dw_desc *first; 646 struct dw_desc *first;
636 struct dw_desc *prev; 647 struct dw_desc *prev;
@@ -650,7 +661,11 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
650 return NULL; 661 return NULL;
651 } 662 }
652 663
653 src_width = dst_width = dwc_fast_fls(src | dest | len); 664 src_width = min_t(unsigned int, dwc->dw->data_width[dwc_get_sms(dws)],
665 dwc_fast_fls(src | len));
666
667 dst_width = min_t(unsigned int, dwc->dw->data_width[dwc_get_dms(dws)],
668 dwc_fast_fls(dest | len));
654 669
655 ctllo = DWC_DEFAULT_CTLLO(chan) 670 ctllo = DWC_DEFAULT_CTLLO(chan)
656 | DWC_CTLL_DST_WIDTH(dst_width) 671 | DWC_CTLL_DST_WIDTH(dst_width)
@@ -720,6 +735,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
720 dma_addr_t reg; 735 dma_addr_t reg;
721 unsigned int reg_width; 736 unsigned int reg_width;
722 unsigned int mem_width; 737 unsigned int mem_width;
738 unsigned int data_width;
723 unsigned int i; 739 unsigned int i;
724 struct scatterlist *sg; 740 struct scatterlist *sg;
725 size_t total_len = 0; 741 size_t total_len = 0;
@@ -743,6 +759,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
743 ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) : 759 ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) :
744 DWC_CTLL_FC(DW_DMA_FC_D_M2P); 760 DWC_CTLL_FC(DW_DMA_FC_D_M2P);
745 761
762 data_width = dwc->dw->data_width[dwc_get_sms(dws)];
763
746 for_each_sg(sgl, sg, sg_len, i) { 764 for_each_sg(sgl, sg, sg_len, i) {
747 struct dw_desc *desc; 765 struct dw_desc *desc;
748 u32 len, dlen, mem; 766 u32 len, dlen, mem;
@@ -750,7 +768,8 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
750 mem = sg_dma_address(sg); 768 mem = sg_dma_address(sg);
751 len = sg_dma_len(sg); 769 len = sg_dma_len(sg);
752 770
753 mem_width = dwc_fast_fls(mem | len); 771 mem_width = min_t(unsigned int,
772 data_width, dwc_fast_fls(mem | len));
754 773
755slave_sg_todev_fill_desc: 774slave_sg_todev_fill_desc:
756 desc = dwc_desc_get(dwc); 775 desc = dwc_desc_get(dwc);
@@ -803,6 +822,8 @@ slave_sg_todev_fill_desc:
803 ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) : 822 ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) :
804 DWC_CTLL_FC(DW_DMA_FC_D_P2M); 823 DWC_CTLL_FC(DW_DMA_FC_D_P2M);
805 824
825 data_width = dwc->dw->data_width[dwc_get_dms(dws)];
826
806 for_each_sg(sgl, sg, sg_len, i) { 827 for_each_sg(sgl, sg, sg_len, i) {
807 struct dw_desc *desc; 828 struct dw_desc *desc;
808 u32 len, dlen, mem; 829 u32 len, dlen, mem;
@@ -810,7 +831,8 @@ slave_sg_todev_fill_desc:
810 mem = sg_dma_address(sg); 831 mem = sg_dma_address(sg);
811 len = sg_dma_len(sg); 832 len = sg_dma_len(sg);
812 833
813 mem_width = dwc_fast_fls(mem | len); 834 mem_width = min_t(unsigned int,
835 data_width, dwc_fast_fls(mem | len));
814 836
815slave_sg_fromdev_fill_desc: 837slave_sg_fromdev_fill_desc:
816 desc = dwc_desc_get(dwc); 838 desc = dwc_desc_get(dwc);
@@ -1415,9 +1437,19 @@ static int __devinit dw_probe(struct platform_device *pdev)
1415 dw->regs = regs; 1437 dw->regs = regs;
1416 1438
1417 /* get hardware configuration parameters */ 1439 /* get hardware configuration parameters */
1418 if (autocfg) 1440 if (autocfg) {
1419 max_blk_size = dma_readl(dw, MAX_BLK_SIZE); 1441 max_blk_size = dma_readl(dw, MAX_BLK_SIZE);
1420 1442
1443 dw->nr_masters = (dw_params >> DW_PARAMS_NR_MASTER & 3) + 1;
1444 for (i = 0; i < dw->nr_masters; i++) {
1445 dw->data_width[i] =
1446 (dw_params >> DW_PARAMS_DATA_WIDTH(i) & 3) + 2;
1447 }
1448 } else {
1449 dw->nr_masters = pdata->nr_masters;
1450 memcpy(dw->data_width, pdata->data_width, 4);
1451 }
1452
1421 /* Calculate all channel mask before DMA setup */ 1453 /* Calculate all channel mask before DMA setup */
1422 dw->all_chan_mask = (1 << nr_channels) - 1; 1454 dw->all_chan_mask = (1 << nr_channels) - 1;
1423 1455
@@ -1464,6 +1496,8 @@ static int __devinit dw_probe(struct platform_device *pdev)
1464 1496
1465 channel_clear_bit(dw, CH_EN, dwc->mask); 1497 channel_clear_bit(dw, CH_EN, dwc->mask);
1466 1498
1499 dwc->dw = dw;
1500
1467 /* hardware configuration */ 1501 /* hardware configuration */
1468 if (autocfg) 1502 if (autocfg)
1469 /* Decode maximum block size for given channel. The 1503 /* Decode maximum block size for given channel. The
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 2a1cc533f0c8..06f03914f022 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -198,6 +198,9 @@ struct dw_dma_chan {
198 198
199 /* configuration passed via DMA_SLAVE_CONFIG */ 199 /* configuration passed via DMA_SLAVE_CONFIG */
200 struct dma_slave_config dma_sconfig; 200 struct dma_slave_config dma_sconfig;
201
202 /* backlink to dw_dma */
203 struct dw_dma *dw;
201}; 204};
202 205
203static inline struct dw_dma_chan_regs __iomem * 206static inline struct dw_dma_chan_regs __iomem *
@@ -224,6 +227,10 @@ struct dw_dma {
224 227
225 u8 all_chan_mask; 228 u8 all_chan_mask;
226 229
230 /* hardware configuration */
231 unsigned char nr_masters;
232 unsigned char data_width[4];
233
227 struct dw_dma_chan chan[0]; 234 struct dw_dma_chan chan[0];
228}; 235};
229 236