mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
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 <phil@raspberrypi.com>
This commit is contained in:
@@ -809,7 +809,7 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan,
|
||||
ctlhi = CH_CTL_H_LLI_VALID;
|
||||
|
||||
if (chan->chip->dw->hdata->restrict_axi_burst_len) {
|
||||
burst_len = chan->chip->dw->hdata->axi_rw_burst_len;
|
||||
burst_len = chan->chip->dw->hdata->axi_rw_burst_len[chan->id];
|
||||
ctlhi |= CH_CTL_H_ARLEN_EN | CH_CTL_H_AWLEN_EN |
|
||||
burst_len << CH_CTL_H_ARLEN_POS |
|
||||
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,
|
||||
|
||||
reg = CH_CTL_H_LLI_VALID;
|
||||
if (chan->chip->dw->hdata->restrict_axi_burst_len) {
|
||||
u32 burst_len = chan->chip->dw->hdata->axi_rw_burst_len;
|
||||
u32 burst_len = chan->chip->dw->hdata->axi_rw_burst_len[chan->id];
|
||||
|
||||
reg |= (CH_CTL_H_ARLEN_EN |
|
||||
burst_len << CH_CTL_H_ARLEN_POS |
|
||||
@@ -1496,6 +1496,7 @@ static int parse_device_properties(struct axi_dma_chip *chip)
|
||||
{
|
||||
struct device *dev = chip->dev;
|
||||
u32 tmp, carr[DMAC_MAX_CHANNELS];
|
||||
u32 val;
|
||||
int ret;
|
||||
|
||||
ret = device_property_read_u32(dev, "dma-channels", &tmp);
|
||||
@@ -1552,15 +1553,21 @@ static int parse_device_properties(struct axi_dma_chip *chip)
|
||||
}
|
||||
|
||||
/* axi-max-burst-len is optional property */
|
||||
ret = device_property_read_u32(dev, "snps,axi-max-burst-len", &tmp);
|
||||
if (!ret) {
|
||||
if (tmp > DWAXIDMAC_ARWLEN_MAX + 1)
|
||||
return -EINVAL;
|
||||
if (tmp < DWAXIDMAC_ARWLEN_MIN + 1)
|
||||
return -EINVAL;
|
||||
|
||||
ret = device_property_read_u32_array(dev, "snps,axi-max-burst-len", NULL,
|
||||
chip->dw->hdata->nr_channels);
|
||||
if ((ret > 0) &&
|
||||
!device_property_read_u32_array(dev, "snps,axi-max-burst-len",
|
||||
carr, ret)) {
|
||||
chip->dw->hdata->restrict_axi_burst_len = true;
|
||||
chip->dw->hdata->axi_rw_burst_len = tmp;
|
||||
for (tmp = 0; tmp < chip->dw->hdata->nr_channels; tmp++) {
|
||||
// Replicate the last value to any remaining channels
|
||||
val = carr[min(tmp, (u32)ret - 1)];
|
||||
if (val > DWAXIDMAC_ARWLEN_MAX + 1)
|
||||
return -EINVAL;
|
||||
if (val < DWAXIDMAC_ARWLEN_MIN + 1)
|
||||
return -EINVAL;
|
||||
chip->dw->hdata->axi_rw_burst_len[tmp] = val;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1674,7 +1681,7 @@ static int dw_probe(struct platform_device *pdev)
|
||||
dma_cap_set(DMA_CYCLIC, dw->dma.cap_mask);
|
||||
|
||||
/* DMA capabilities */
|
||||
dw->dma.max_burst = hdata->axi_rw_burst_len;
|
||||
dw->dma.max_burst = hdata->axi_rw_burst_len[0];
|
||||
dw->dma.src_addr_widths = AXI_DMA_BUSWIDTHS;
|
||||
dw->dma.dst_addr_widths = AXI_DMA_BUSWIDTHS;
|
||||
dw->dma.directions = BIT(DMA_MEM_TO_MEM);
|
||||
|
||||
@@ -29,7 +29,7 @@ struct dw_axi_dma_hcfg {
|
||||
u32 block_size[DMAC_MAX_CHANNELS];
|
||||
u32 priority[DMAC_MAX_CHANNELS];
|
||||
/* maximum supported axi burst length */
|
||||
u32 axi_rw_burst_len;
|
||||
u32 axi_rw_burst_len[DMAC_MAX_CHANNELS];
|
||||
/* Register map for DMAX_NUM_CHANNELS <= 8 */
|
||||
bool reg_map_8_channels;
|
||||
bool restrict_axi_burst_len;
|
||||
|
||||
Reference in New Issue
Block a user