dmaengine: zynqmp_dma: fix burst length configuration

Since the dma engine expects the burst length register content as
power of 2 value, the burst length needs to be converted first.
Additionally add a burst length range check to avoid corrupting unrelated
register bits.

Signed-off-by: Matthias Fend <matthias.fend@wolfvision.net>
Link: https://lore.kernel.org/r/20200115102249.24398-1-matthias.fend@wolfvision.net
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Matthias Fend 2020-01-15 11:22:49 +01:00 committed by Vinod Koul
parent ffc079a4ac
commit cc88525ebf
1 changed files with 15 additions and 9 deletions

View File

@ -123,10 +123,12 @@
/* Max transfer size per descriptor */
#define ZYNQMP_DMA_MAX_TRANS_LEN 0x40000000
/* Max burst lengths */
#define ZYNQMP_DMA_MAX_DST_BURST_LEN 32768U
#define ZYNQMP_DMA_MAX_SRC_BURST_LEN 32768U
/* Reset values for data attributes */
#define ZYNQMP_DMA_AXCACHE_VAL 0xF
#define ZYNQMP_DMA_ARLEN_RST_VAL 0xF
#define ZYNQMP_DMA_AWLEN_RST_VAL 0xF
#define ZYNQMP_DMA_SRC_ISSUE_RST_VAL 0x1F
@ -534,17 +536,19 @@ static void zynqmp_dma_handle_ovfl_int(struct zynqmp_dma_chan *chan, u32 status)
static void zynqmp_dma_config(struct zynqmp_dma_chan *chan)
{
u32 val;
u32 val, burst_val;
val = readl(chan->regs + ZYNQMP_DMA_CTRL0);
val |= ZYNQMP_DMA_POINT_TYPE_SG;
writel(val, chan->regs + ZYNQMP_DMA_CTRL0);
val = readl(chan->regs + ZYNQMP_DMA_DATA_ATTR);
burst_val = __ilog2_u32(chan->src_burst_len);
val = (val & ~ZYNQMP_DMA_ARLEN) |
(chan->src_burst_len << ZYNQMP_DMA_ARLEN_OFST);
((burst_val << ZYNQMP_DMA_ARLEN_OFST) & ZYNQMP_DMA_ARLEN);
burst_val = __ilog2_u32(chan->dst_burst_len);
val = (val & ~ZYNQMP_DMA_AWLEN) |
(chan->dst_burst_len << ZYNQMP_DMA_AWLEN_OFST);
((burst_val << ZYNQMP_DMA_AWLEN_OFST) & ZYNQMP_DMA_AWLEN);
writel(val, chan->regs + ZYNQMP_DMA_DATA_ATTR);
}
@ -560,8 +564,10 @@ static int zynqmp_dma_device_config(struct dma_chan *dchan,
{
struct zynqmp_dma_chan *chan = to_chan(dchan);
chan->src_burst_len = config->src_maxburst;
chan->dst_burst_len = config->dst_maxburst;
chan->src_burst_len = clamp(config->src_maxburst, 1U,
ZYNQMP_DMA_MAX_SRC_BURST_LEN);
chan->dst_burst_len = clamp(config->dst_maxburst, 1U,
ZYNQMP_DMA_MAX_DST_BURST_LEN);
return 0;
}
@ -887,8 +893,8 @@ static int zynqmp_dma_chan_probe(struct zynqmp_dma_device *zdev,
return PTR_ERR(chan->regs);
chan->bus_width = ZYNQMP_DMA_BUS_WIDTH_64;
chan->dst_burst_len = ZYNQMP_DMA_AWLEN_RST_VAL;
chan->src_burst_len = ZYNQMP_DMA_ARLEN_RST_VAL;
chan->dst_burst_len = ZYNQMP_DMA_MAX_DST_BURST_LEN;
chan->src_burst_len = ZYNQMP_DMA_MAX_SRC_BURST_LEN;
err = of_property_read_u32(node, "xlnx,bus-width", &chan->bus_width);
if (err < 0) {
dev_err(&pdev->dev, "missing xlnx,bus-width property\n");