diff options
author | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2012-09-21 08:05:48 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@linux.intel.com> | 2012-09-27 06:05:23 -0400 |
commit | a09820043c9e11149145a1ec221eed4a7b42dcce (patch) | |
tree | 0561b70b0803aec4b57e41e90fa0ece433f9d59f /drivers/dma | |
parent | 4a63a8b3e8d2e4f56174deb728085010aa3ac2a1 (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.c | 46 | ||||
-rw-r--r-- | drivers/dma/dw_dmac_regs.h | 7 |
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 | ||
39 | static inline unsigned int dwc_get_dms(struct dw_dma_slave *slave) | ||
40 | { | ||
41 | return slave ? slave->dst_master : 0; | ||
42 | } | ||
43 | |||
44 | static 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 | ||
755 | slave_sg_todev_fill_desc: | 774 | slave_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 | ||
815 | slave_sg_fromdev_fill_desc: | 837 | slave_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 | ||
203 | static inline struct dw_dma_chan_regs __iomem * | 206 | static 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 | ||