Commit 2708ed60 authored by Matthias Fend's avatar Matthias Fend Committed by Greg Kroah-Hartman

dmaengine: zynqmp_dma: fix burst length configuration

[ Upstream commit cc88525e ]

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: default avatarMatthias Fend <matthias.fend@wolfvision.net>
Link: https://lore.kernel.org/r/20200115102249.24398-1-matthias.fend@wolfvision.netSigned-off-by: default avatarVinod Koul <vkoul@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 714ddb5e
......@@ -127,10 +127,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
......@@ -536,17 +538,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);
}
......@@ -562,8 +566,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;
}
......@@ -884,8 +890,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");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment