Skip to content

Commit 29b478e

Browse files
committed
dmaengine: dw-axi-dmac: Per-channel burst limits
The DesignWare AXI DMAC IP can be configured with heterogeneous channel parameters. Allow maximum burst length to be set per-channel by making snps,axi-max-burst-len an array. Signed-off-by: Phil Elwell <[email protected]>
1 parent 4c325ef commit 29b478e

File tree

2 files changed

+19
-12
lines changed

2 files changed

+19
-12
lines changed

drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,7 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan,
809809
ctlhi = CH_CTL_H_LLI_VALID;
810810

811811
if (chan->chip->dw->hdata->restrict_axi_burst_len) {
812-
burst_len = chan->chip->dw->hdata->axi_rw_burst_len;
812+
burst_len = chan->chip->dw->hdata->axi_rw_burst_len[chan->id];
813813
ctlhi |= CH_CTL_H_ARLEN_EN | CH_CTL_H_AWLEN_EN |
814814
burst_len << CH_CTL_H_ARLEN_POS |
815815
burst_len << CH_CTL_H_AWLEN_POS;
@@ -1087,7 +1087,7 @@ dma_chan_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dst_adr,
10871087

10881088
reg = CH_CTL_H_LLI_VALID;
10891089
if (chan->chip->dw->hdata->restrict_axi_burst_len) {
1090-
u32 burst_len = chan->chip->dw->hdata->axi_rw_burst_len;
1090+
u32 burst_len = chan->chip->dw->hdata->axi_rw_burst_len[chan->id];
10911091

10921092
reg |= (CH_CTL_H_ARLEN_EN |
10931093
burst_len << CH_CTL_H_ARLEN_POS |
@@ -1496,6 +1496,7 @@ static int parse_device_properties(struct axi_dma_chip *chip)
14961496
{
14971497
struct device *dev = chip->dev;
14981498
u32 tmp, carr[DMAC_MAX_CHANNELS];
1499+
u32 val;
14991500
int ret;
15001501

15011502
ret = device_property_read_u32(dev, "dma-channels", &tmp);
@@ -1552,15 +1553,21 @@ static int parse_device_properties(struct axi_dma_chip *chip)
15521553
}
15531554

15541555
/* axi-max-burst-len is optional property */
1555-
ret = device_property_read_u32(dev, "snps,axi-max-burst-len", &tmp);
1556-
if (!ret) {
1557-
if (tmp > DWAXIDMAC_ARWLEN_MAX + 1)
1558-
return -EINVAL;
1559-
if (tmp < DWAXIDMAC_ARWLEN_MIN + 1)
1560-
return -EINVAL;
1561-
1556+
ret = device_property_read_u32_array(dev, "snps,axi-max-burst-len", NULL,
1557+
chip->dw->hdata->nr_channels);
1558+
if ((ret > 0) &&
1559+
!device_property_read_u32_array(dev, "snps,axi-max-burst-len",
1560+
carr, ret)) {
15621561
chip->dw->hdata->restrict_axi_burst_len = true;
1563-
chip->dw->hdata->axi_rw_burst_len = tmp;
1562+
for (tmp = 0; tmp < chip->dw->hdata->nr_channels; tmp++) {
1563+
// Replicate the last value to any remaining channels
1564+
val = carr[min(tmp, (u32)ret - 1)];
1565+
if (val > DWAXIDMAC_ARWLEN_MAX + 1)
1566+
return -EINVAL;
1567+
if (val < DWAXIDMAC_ARWLEN_MIN + 1)
1568+
return -EINVAL;
1569+
chip->dw->hdata->axi_rw_burst_len[tmp] = val;
1570+
}
15641571
}
15651572

15661573
return 0;
@@ -1674,7 +1681,7 @@ static int dw_probe(struct platform_device *pdev)
16741681
dma_cap_set(DMA_CYCLIC, dw->dma.cap_mask);
16751682

16761683
/* DMA capabilities */
1677-
dw->dma.max_burst = hdata->axi_rw_burst_len;
1684+
dw->dma.max_burst = hdata->axi_rw_burst_len[0];
16781685
dw->dma.src_addr_widths = AXI_DMA_BUSWIDTHS;
16791686
dw->dma.dst_addr_widths = AXI_DMA_BUSWIDTHS;
16801687
dw->dma.directions = BIT(DMA_MEM_TO_MEM);

drivers/dma/dw-axi-dmac/dw-axi-dmac.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ struct dw_axi_dma_hcfg {
2929
u32 block_size[DMAC_MAX_CHANNELS];
3030
u32 priority[DMAC_MAX_CHANNELS];
3131
/* maximum supported axi burst length */
32-
u32 axi_rw_burst_len;
32+
u32 axi_rw_burst_len[DMAC_MAX_CHANNELS];
3333
/* Register map for DMAX_NUM_CHANNELS <= 8 */
3434
bool reg_map_8_channels;
3535
bool restrict_axi_burst_len;

0 commit comments

Comments
 (0)