35d7342ef603505754a64803267b6c2dee47fc5b
[openwrt/staging/ansuel.git] /
1 From 95d4bdad3bf5340b0bf1e53e28fcd487d9253315 Mon Sep 17 00:00:00 2001
2 From: Maxime Ripard <maxime@cerno.tech>
3 Date: Mon, 27 Mar 2023 17:10:07 +0200
4 Subject: [PATCH] dmaengine: bcm2835: Fix position reporting for 40
5 bits channels
6
7 For 40 bits channels, the position is reported by reading the upper byte
8 in the SRCI/DESTI registers. However the driver adds that upper byte
9 with an 8-bits left shift, while it should be 32.
10
11 Fixes: 9a52a9918306 ("bcm2835-dma: Add proper 40-bit DMA support")
12 Signed-off-by: Maxime Ripard <maxime@cerno.tech>
13 ---
14 drivers/dma/bcm2835-dma.c | 27 ++++++++++++++++-----------
15 1 file changed, 16 insertions(+), 11 deletions(-)
16
17 --- a/drivers/dma/bcm2835-dma.c
18 +++ b/drivers/dma/bcm2835-dma.c
19 @@ -819,20 +819,25 @@ static enum dma_status bcm2835_dma_tx_st
20 struct bcm2835_desc *d = c->desc;
21 dma_addr_t pos;
22
23 - if (d->dir == DMA_MEM_TO_DEV && c->is_40bit_channel)
24 - pos = readl(c->chan_base + BCM2711_DMA40_SRC) +
25 - ((readl(c->chan_base + BCM2711_DMA40_SRCI) &
26 - 0xff) << 8);
27 - else if (d->dir == DMA_MEM_TO_DEV && !c->is_40bit_channel)
28 + if (d->dir == DMA_MEM_TO_DEV && c->is_40bit_channel) {
29 + u64 lo_bits, hi_bits;
30 +
31 + lo_bits = readl(c->chan_base + BCM2711_DMA40_SRC);
32 + hi_bits = readl(c->chan_base + BCM2711_DMA40_SRCI) & 0xff;
33 + pos = (hi_bits << 32) | lo_bits;
34 + } else if (d->dir == DMA_MEM_TO_DEV && !c->is_40bit_channel) {
35 pos = readl(c->chan_base + BCM2835_DMA_SOURCE_AD);
36 - else if (d->dir == DMA_DEV_TO_MEM && c->is_40bit_channel)
37 - pos = readl(c->chan_base + BCM2711_DMA40_DEST) +
38 - ((readl(c->chan_base + BCM2711_DMA40_DESTI) &
39 - 0xff) << 8);
40 - else if (d->dir == DMA_DEV_TO_MEM && !c->is_40bit_channel)
41 + } else if (d->dir == DMA_DEV_TO_MEM && c->is_40bit_channel) {
42 + u64 lo_bits, hi_bits;
43 +
44 + lo_bits = readl(c->chan_base + BCM2711_DMA40_DEST);
45 + hi_bits = readl(c->chan_base + BCM2711_DMA40_DESTI) & 0xff;
46 + pos = (hi_bits << 32) | lo_bits;
47 + } else if (d->dir == DMA_DEV_TO_MEM && !c->is_40bit_channel) {
48 pos = readl(c->chan_base + BCM2835_DMA_DEST_AD);
49 - else
50 + } else {
51 pos = 0;
52 + }
53
54 txstate->residue = bcm2835_dma_desc_size_pos(d, pos);
55 } else {