Skip to content

Commit a098200

Browse files
andy-shevVinod Koul
authored andcommitted
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>
1 parent 4a63a8b commit a098200

File tree

5 files changed

+56
-6
lines changed

5 files changed

+56
-6
lines changed

arch/arm/mach-spear13xx/spear13xx.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ struct dw_dma_platform_data dmac_plat_data = {
7979
.chan_allocation_order = CHAN_ALLOCATION_DESCENDING,
8080
.chan_priority = CHAN_PRIORITY_DESCENDING,
8181
.block_size = 4095U,
82+
.nr_masters = 2,
83+
.data_width = { 3, 3, 0, 0 },
8284
};
8385

8486
void __init spear13xx_l2x0_init(void)

arch/avr32/mach-at32ap/at32ap700x.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,8 @@ static void __init genclk_init_parent(struct clk *clk)
606606
static struct dw_dma_platform_data dw_dmac0_data = {
607607
.nr_channels = 3,
608608
.block_size = 4095U,
609+
.nr_masters = 2,
610+
.data_width = { 2, 2, 0, 0 },
609611
};
610612

611613
static struct resource dw_dmac0_resource[] = {

drivers/dma/dw_dmac.c

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,22 @@
3636
* which does not support descriptor writeback.
3737
*/
3838

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+
3949
#define DWC_DEFAULT_CTLLO(_chan) ({ \
4050
struct dw_dma_slave *__slave = (_chan->private); \
4151
struct dw_dma_chan *_dwc = to_dw_dma_chan(_chan); \
4252
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); \
4555
u8 _smsize = __slave ? _sconfig->src_maxburst : \
4656
DW_DMA_MSIZE_16; \
4757
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,
631641
size_t len, unsigned long flags)
632642
{
633643
struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
644+
struct dw_dma_slave *dws = chan->private;
634645
struct dw_desc *desc;
635646
struct dw_desc *first;
636647
struct dw_desc *prev;
@@ -650,7 +661,11 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
650661
return NULL;
651662
}
652663

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));
654669

655670
ctllo = DWC_DEFAULT_CTLLO(chan)
656671
| DWC_CTLL_DST_WIDTH(dst_width)
@@ -720,6 +735,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
720735
dma_addr_t reg;
721736
unsigned int reg_width;
722737
unsigned int mem_width;
738+
unsigned int data_width;
723739
unsigned int i;
724740
struct scatterlist *sg;
725741
size_t total_len = 0;
@@ -743,14 +759,17 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
743759
ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_M2P) :
744760
DWC_CTLL_FC(DW_DMA_FC_D_M2P);
745761

762+
data_width = dwc->dw->data_width[dwc_get_sms(dws)];
763+
746764
for_each_sg(sgl, sg, sg_len, i) {
747765
struct dw_desc *desc;
748766
u32 len, dlen, mem;
749767

750768
mem = sg_dma_address(sg);
751769
len = sg_dma_len(sg);
752770

753-
mem_width = dwc_fast_fls(mem | len);
771+
mem_width = min_t(unsigned int,
772+
data_width, dwc_fast_fls(mem | len));
754773

755774
slave_sg_todev_fill_desc:
756775
desc = dwc_desc_get(dwc);
@@ -803,14 +822,17 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
803822
ctllo |= sconfig->device_fc ? DWC_CTLL_FC(DW_DMA_FC_P_P2M) :
804823
DWC_CTLL_FC(DW_DMA_FC_D_P2M);
805824

825+
data_width = dwc->dw->data_width[dwc_get_dms(dws)];
826+
806827
for_each_sg(sgl, sg, sg_len, i) {
807828
struct dw_desc *desc;
808829
u32 len, dlen, mem;
809830

810831
mem = sg_dma_address(sg);
811832
len = sg_dma_len(sg);
812833

813-
mem_width = dwc_fast_fls(mem | len);
834+
mem_width = min_t(unsigned int,
835+
data_width, dwc_fast_fls(mem | len));
814836

815837
slave_sg_fromdev_fill_desc:
816838
desc = dwc_desc_get(dwc);
@@ -1415,9 +1437,19 @@ static int __devinit dw_probe(struct platform_device *pdev)
14151437
dw->regs = regs;
14161438

14171439
/* get hardware configuration parameters */
1418-
if (autocfg)
1440+
if (autocfg) {
14191441
max_blk_size = dma_readl(dw, MAX_BLK_SIZE);
14201442

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+
14211453
/* Calculate all channel mask before DMA setup */
14221454
dw->all_chan_mask = (1 << nr_channels) - 1;
14231455

@@ -1464,6 +1496,8 @@ static int __devinit dw_probe(struct platform_device *pdev)
14641496

14651497
channel_clear_bit(dw, CH_EN, dwc->mask);
14661498

1499+
dwc->dw = dw;
1500+
14671501
/* hardware configuration */
14681502
if (autocfg)
14691503
/* Decode maximum block size for given channel. The

drivers/dma/dw_dmac_regs.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ struct dw_dma_chan {
198198

199199
/* configuration passed via DMA_SLAVE_CONFIG */
200200
struct dma_slave_config dma_sconfig;
201+
202+
/* backlink to dw_dma */
203+
struct dw_dma *dw;
201204
};
202205

203206
static inline struct dw_dma_chan_regs __iomem *
@@ -224,6 +227,10 @@ struct dw_dma {
224227

225228
u8 all_chan_mask;
226229

230+
/* hardware configuration */
231+
unsigned char nr_masters;
232+
unsigned char data_width[4];
233+
227234
struct dw_dma_chan chan[0];
228235
};
229236

include/linux/dw_dmac.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
* @is_private: The device channels should be marked as private and not for
2121
* by the general purpose DMA channel allocator.
2222
* @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)
2326
*/
2427
struct dw_dma_platform_data {
2528
unsigned int nr_channels;
@@ -31,6 +34,8 @@ struct dw_dma_platform_data {
3134
#define CHAN_PRIORITY_DESCENDING 1 /* chan7 highest */
3235
unsigned char chan_priority;
3336
unsigned short block_size;
37+
unsigned char nr_masters;
38+
unsigned char data_width[4];
3439
};
3540

3641
/* bursts size */

0 commit comments

Comments
 (0)