[PATCH 5/9] dmaengine: bcm2835: Add BCM2712 support
Peter Robinson
pbrobinson at gmail.com
Mon Nov 2 01:06:55 PST 2026
BCM2712 legacy layout channels carry address bits [39:32] in the
STRIDE field and use 32-byte units for control block pointers.
Channels 6-11 are DMA4 engines. Peripherals are seen at 0x10_7c000000.
Add the brcm,bcm2712-dma compatible with a 40-bit DMA mask.
Signed-off-by: Peter Robinson <pbrobinson at gmail.com>
---
drivers/dma/bcm2835-dma.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
index 35f8c47dea89f..f06609b04a098 100644
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -44,11 +44,14 @@
* @chan_40bit_mask: channels implementing the BCM2711 40-bit register layout
* @periph_offset: offset at which channels with extended addressing see the
* legacy 0x7c000000 - 0x7fffffff peripheral window
+ * @ext_addr: legacy layout channels carry address bits [39:32] in the STRIDE
+ * field and control block pointers are stored right-shifted by 5
*/
struct bcm2835_dma_cfg {
u64 dma_mask;
u32 chan_40bit_mask;
u64 periph_offset;
+ bool ext_addr;
};
/**
@@ -212,6 +215,10 @@ struct bcm2835_desc {
#define MAX_DMA_LEN SZ_1G
#define MAX_LITE_DMA_LEN (SZ_64K - 4)
+/* BCM2712 legacy layout channels: address bits [39:32] in the STRIDE field */
+#define BCM2712_DMA_STRIDE_SRC_HI GENMASK(7, 0)
+#define BCM2712_DMA_STRIDE_DST_HI GENMASK(15, 8)
+
/* Legacy peripheral bus window used by DMA clients for FIFO addresses */
#define BCM2835_DMA_PERIPH_BASE 0x7c000000
#define BCM2835_DMA_PERIPH_END 0x80000000
@@ -271,6 +278,13 @@ static const struct bcm2835_dma_cfg bcm2711_dma_cfg = {
.periph_offset = 0x400000000ULL,
};
+static const struct bcm2835_dma_cfg bcm2712_dma_cfg = {
+ .dma_mask = DMA_BIT_MASK(40),
+ .chan_40bit_mask = GENMASK(11, 6),
+ .periph_offset = 0x1000000000ULL,
+ .ext_addr = true,
+};
+
static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c)
{
/* lite and normal channels have different max frame length */
@@ -349,6 +363,9 @@ static void bcm2835_dma_cb_set_src(struct bcm2835_chan *c,
}
e->cb->src = lower_32_bits(addr);
+ if (c->ext_addr)
+ FIELD_MODIFY(BCM2712_DMA_STRIDE_SRC_HI, &e->cb->stride,
+ upper_32_bits(addr));
}
static void bcm2835_dma_cb_set_dst(struct bcm2835_chan *c,
@@ -362,6 +379,9 @@ static void bcm2835_dma_cb_set_dst(struct bcm2835_chan *c,
}
e->cb->dst = lower_32_bits(addr);
+ if (c->ext_addr)
+ FIELD_MODIFY(BCM2712_DMA_STRIDE_DST_HI, &e->cb->stride,
+ upper_32_bits(addr));
}
static void bcm2835_dma_cb_init(struct bcm2835_chan *c,
@@ -1127,7 +1147,7 @@ static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id,
BCM2835_DMA_DEBUG_LITE)
c->is_lite_channel = true;
- c->ext_addr = c->is_40bit_channel;
+ c->ext_addr = c->is_40bit_channel || d->cfg->ext_addr;
if (c->ext_addr)
c->periph_offset = d->cfg->periph_offset;
@@ -1151,6 +1171,7 @@ static void bcm2835_dma_free(struct bcm2835_dmadev *od)
static const struct of_device_id bcm2835_dma_of_match[] = {
{ .compatible = "brcm,bcm2835-dma", .data = &bcm2835_dma_cfg },
{ .compatible = "brcm,bcm2711-dma", .data = &bcm2711_dma_cfg },
+ { .compatible = "brcm,bcm2712-dma", .data = &bcm2712_dma_cfg },
{},
};
MODULE_DEVICE_TABLE(of, bcm2835_dma_of_match);
--
2.56.0
More information about the linux-arm-kernel
mailing list