Commit a09820043c9e11149145a1ec221eed4a7b42dcce
Committed by
Vinod Koul
1 parent
4a63a8b3e8
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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>
Showing 5 changed files with 56 additions and 6 deletions Side-by-side Diff
arch/arm/mach-spear13xx/spear13xx.c
arch/avr32/mach-at32ap/at32ap700x.c
drivers/dma/dw_dmac.c
... | ... | @@ -36,12 +36,22 @@ |
36 | 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 | 49 | #define DWC_DEFAULT_CTLLO(_chan) ({ \ |
40 | 50 | struct dw_dma_slave *__slave = (_chan->private); \ |
41 | 51 | struct dw_dma_chan *_dwc = to_dw_dma_chan(_chan); \ |
42 | 52 | struct dma_slave_config *_sconfig = &_dwc->dma_sconfig; \ |
43 | - int _dms = __slave ? __slave->dst_master : 0; \ | |
44 | - int _sms = __slave ? __slave->src_master : 1; \ | |
53 | + int _dms = dwc_get_dms(__slave); \ | |
54 | + int _sms = dwc_get_sms(__slave); \ | |
45 | 55 | u8 _smsize = __slave ? _sconfig->src_maxburst : \ |
46 | 56 | DW_DMA_MSIZE_16; \ |
47 | 57 | u8 _dmsize = __slave ? _sconfig->dst_maxburst : \ |
... | ... | @@ -631,6 +641,7 @@ |
631 | 641 | size_t len, unsigned long flags) |
632 | 642 | { |
633 | 643 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); |
644 | + struct dw_dma_slave *dws = chan->private; | |
634 | 645 | struct dw_desc *desc; |
635 | 646 | struct dw_desc *first; |
636 | 647 | struct dw_desc *prev; |
637 | 648 | |
... | ... | @@ -650,8 +661,12 @@ |
650 | 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)); | |
654 | 666 | |
667 | + dst_width = min_t(unsigned int, dwc->dw->data_width[dwc_get_dms(dws)], | |
668 | + dwc_fast_fls(dest | len)); | |
669 | + | |
655 | 670 | ctllo = DWC_DEFAULT_CTLLO(chan) |
656 | 671 | | DWC_CTLL_DST_WIDTH(dst_width) |
657 | 672 | | DWC_CTLL_SRC_WIDTH(src_width) |
... | ... | @@ -720,6 +735,7 @@ |
720 | 735 | dma_addr_t reg; |
721 | 736 | unsigned int reg_width; |
722 | 737 | unsigned int mem_width; |
738 | + unsigned int data_width; | |
723 | 739 | unsigned int i; |
724 | 740 | struct scatterlist *sg; |
725 | 741 | size_t total_len = 0; |
... | ... | @@ -743,6 +759,8 @@ |
743 | 759 | ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) : |
744 | 760 | DWC_CTLL_FC(DW_DMA_FC_D_M2P); |
745 | 761 | |
762 | + data_width = dwc->dw->data_width[dwc_get_sms(dws)]; | |
763 | + | |
746 | 764 | for_each_sg(sgl, sg, sg_len, i) { |
747 | 765 | struct dw_desc *desc; |
748 | 766 | u32 len, dlen, mem; |
... | ... | @@ -750,7 +768,8 @@ |
750 | 768 | mem = sg_dma_address(sg); |
751 | 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 | 774 | slave_sg_todev_fill_desc: |
756 | 775 | desc = dwc_desc_get(dwc); |
... | ... | @@ -803,6 +822,8 @@ |
803 | 822 | ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) : |
804 | 823 | DWC_CTLL_FC(DW_DMA_FC_D_P2M); |
805 | 824 | |
825 | + data_width = dwc->dw->data_width[dwc_get_dms(dws)]; | |
826 | + | |
806 | 827 | for_each_sg(sgl, sg, sg_len, i) { |
807 | 828 | struct dw_desc *desc; |
808 | 829 | u32 len, dlen, mem; |
... | ... | @@ -810,7 +831,8 @@ |
810 | 831 | mem = sg_dma_address(sg); |
811 | 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 | 837 | slave_sg_fromdev_fill_desc: |
816 | 838 | desc = dwc_desc_get(dwc); |
817 | 839 | |
... | ... | @@ -1415,9 +1437,19 @@ |
1415 | 1437 | dw->regs = regs; |
1416 | 1438 | |
1417 | 1439 | /* get hardware configuration parameters */ |
1418 | - if (autocfg) | |
1440 | + if (autocfg) { | |
1419 | 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 | 1453 | /* Calculate all channel mask before DMA setup */ |
1422 | 1454 | dw->all_chan_mask = (1 << nr_channels) - 1; |
1423 | 1455 | |
... | ... | @@ -1463,6 +1495,8 @@ |
1463 | 1495 | INIT_LIST_HEAD(&dwc->free_list); |
1464 | 1496 | |
1465 | 1497 | channel_clear_bit(dw, CH_EN, dwc->mask); |
1498 | + | |
1499 | + dwc->dw = dw; | |
1466 | 1500 | |
1467 | 1501 | /* hardware configuration */ |
1468 | 1502 | if (autocfg) |
drivers/dma/dw_dmac_regs.h
... | ... | @@ -198,6 +198,9 @@ |
198 | 198 | |
199 | 199 | /* configuration passed via DMA_SLAVE_CONFIG */ |
200 | 200 | struct dma_slave_config dma_sconfig; |
201 | + | |
202 | + /* backlink to dw_dma */ | |
203 | + struct dw_dma *dw; | |
201 | 204 | }; |
202 | 205 | |
203 | 206 | static inline struct dw_dma_chan_regs __iomem * |
... | ... | @@ -223,6 +226,10 @@ |
223 | 226 | struct clk *clk; |
224 | 227 | |
225 | 228 | u8 all_chan_mask; |
229 | + | |
230 | + /* hardware configuration */ | |
231 | + unsigned char nr_masters; | |
232 | + unsigned char data_width[4]; | |
226 | 233 | |
227 | 234 | struct dw_dma_chan chan[0]; |
228 | 235 | }; |
include/linux/dw_dmac.h
... | ... | @@ -20,6 +20,9 @@ |
20 | 20 | * @is_private: The device channels should be marked as private and not for |
21 | 21 | * by the general purpose DMA channel allocator. |
22 | 22 | * @block_size: Maximum block size supported by the controller |
23 | + * @nr_masters: Number of AHB masters supported by the controller | |
24 | + * @data_width: Maximum data width supported by hardware per AHB master | |
25 | + * (0 - 8bits, 1 - 16bits, ..., 5 - 256bits) | |
23 | 26 | */ |
24 | 27 | struct dw_dma_platform_data { |
25 | 28 | unsigned int nr_channels; |
... | ... | @@ -31,6 +34,8 @@ |
31 | 34 | #define CHAN_PRIORITY_DESCENDING 1 /* chan7 highest */ |
32 | 35 | unsigned char chan_priority; |
33 | 36 | unsigned short block_size; |
37 | + unsigned char nr_masters; | |
38 | + unsigned char data_width[4]; | |
34 | 39 | }; |
35 | 40 | |
36 | 41 | /* bursts size */ |