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;
|
ctlhi = CH_CTL_H_LLI_VALID;
|
||||||
|
|
||||||
if (chan->chip->dw->hdata->restrict_axi_burst_len) {
|
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 |
|
ctlhi |= CH_CTL_H_ARLEN_EN | CH_CTL_H_AWLEN_EN |
|
||||||
burst_len << CH_CTL_H_ARLEN_POS |
|
burst_len << CH_CTL_H_ARLEN_POS |
|
||||||
burst_len << CH_CTL_H_AWLEN_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;
|
reg = CH_CTL_H_LLI_VALID;
|
||||||
if (chan->chip->dw->hdata->restrict_axi_burst_len) {
|
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 |
|
reg |= (CH_CTL_H_ARLEN_EN |
|
||||||
burst_len << CH_CTL_H_ARLEN_POS |
|
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;
|
struct device *dev = chip->dev;
|
||||||
u32 tmp, carr[DMAC_MAX_CHANNELS];
|
u32 tmp, carr[DMAC_MAX_CHANNELS];
|
||||||
|
u32 val;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = device_property_read_u32(dev, "dma-channels", &tmp);
|
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 */
|
/* axi-max-burst-len is optional property */
|
||||||
ret = device_property_read_u32(dev, "snps,axi-max-burst-len", &tmp);
|
ret = device_property_read_u32_array(dev, "snps,axi-max-burst-len", NULL,
|
||||||
if (!ret) {
|
chip->dw->hdata->nr_channels);
|
||||||
if (tmp > DWAXIDMAC_ARWLEN_MAX + 1)
|
if ((ret > 0) &&
|
||||||
return -EINVAL;
|
!device_property_read_u32_array(dev, "snps,axi-max-burst-len",
|
||||||
if (tmp < DWAXIDMAC_ARWLEN_MIN + 1)
|
carr, ret)) {
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
chip->dw->hdata->restrict_axi_burst_len = true;
|
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;
|
return 0;
|
||||||
@@ -1674,7 +1681,7 @@ static int dw_probe(struct platform_device *pdev)
|
|||||||
dma_cap_set(DMA_CYCLIC, dw->dma.cap_mask);
|
dma_cap_set(DMA_CYCLIC, dw->dma.cap_mask);
|
||||||
|
|
||||||
/* DMA capabilities */
|
/* 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.src_addr_widths = AXI_DMA_BUSWIDTHS;
|
||||||
dw->dma.dst_addr_widths = AXI_DMA_BUSWIDTHS;
|
dw->dma.dst_addr_widths = AXI_DMA_BUSWIDTHS;
|
||||||
dw->dma.directions = BIT(DMA_MEM_TO_MEM);
|
dw->dma.directions = BIT(DMA_MEM_TO_MEM);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ struct dw_axi_dma_hcfg {
|
|||||||
u32 block_size[DMAC_MAX_CHANNELS];
|
u32 block_size[DMAC_MAX_CHANNELS];
|
||||||
u32 priority[DMAC_MAX_CHANNELS];
|
u32 priority[DMAC_MAX_CHANNELS];
|
||||||
/* maximum supported axi burst length */
|
/* 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 */
|
/* Register map for DMAX_NUM_CHANNELS <= 8 */
|
||||||
bool reg_map_8_channels;
|
bool reg_map_8_channels;
|
||||||
bool restrict_axi_burst_len;
|
bool restrict_axi_burst_len;
|
||||||
|
|||||||
Reference in New Issue
Block a user