Commit cc88525e authored by Matthias Fend's avatar Matthias Fend Committed by Vinod Koul
Browse files

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: default avatarMatthias Fend <matthias.fend@wolfvision.net>
Link: https://lore.kernel.org/r/20200115102249.24398-1-matthias.fend@wolfvision.net


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent ffc079a4
Loading
Loading
Loading
Loading
+15 −9
Original line number Diff line number Diff line
@@ -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");