Devicetree
 help / color / mirror / Atom feed
From: Peter Robinson <pbrobinson@gmail.com>
To: Florian Fainelli <florian.fainelli@broadcom.com>,
	Dave Stevenson <dave.stevenson@raspberrypi.com>,
	Ray Jui <rjui@broadcom.com>,
	Scott Branden <sbranden@broadcom.com>,
	Vinod Koul <vkoul@kernel.org>, Frank Li <Frank.Li@kernel.org>,
	dmaengine@vger.kernel.org, devicetree@vger.kernel.org,
	linux-rpi-kernel@lists.infradead.org,
	linux-arm-kernel@lists.infradead.org,
	bcm-kernel-feedback-list@broadcom.com
Cc: Peter Robinson <pbrobinson@gmail.com>
Subject: [PATCH 4/9] dmaengine: bcm2835: Add BCM2711 40-bit channel support
Date: Mon,  2 Nov 2026 09:06:54 +0000	[thread overview]
Message-ID: <20261102090713.896324-5-pbrobinson@gmail.com> (raw)
In-Reply-To: <20261102090713.896324-1-pbrobinson@gmail.com>

BCM2711 channels 11-14 are DMA4 engines with a 40-bit capable register
and control block layout. They see the legacy 0x7c000000 peripheral
window at 0x4_7c000000, so translate client FIFO addresses accordingly.
Add the brcm,bcm2711-dma compatible for covering these channels.

Signed-off-by: Peter Robinson <pbrobinson@gmail.com>
---
 drivers/dma/bcm2835-dma.c | 278 +++++++++++++++++++++++++++++++++++---
 1 file changed, 256 insertions(+), 22 deletions(-)

diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
index 83ad8815759e8..35f8c47dea89f 100644
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -17,6 +17,7 @@
  *	MARVELL MMP Peripheral DMA Driver
  *	Copyright 2012 Marvell International Ltd.
  */
+#include <linux/bitfield.h>
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmapool.h>
@@ -40,9 +41,14 @@
 /**
  * struct bcm2835_dma_cfg - SoC specific controller properties
  * @dma_mask: addressing capability of the controller
+ * @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
  */
 struct bcm2835_dma_cfg {
 	u64 dma_mask;
+	u32 chan_40bit_mask;
+	u64 periph_offset;
 };
 
 /**
@@ -72,8 +78,25 @@ struct bcm2835_dma_cb {
 	uint32_t pad[2];
 };
 
+/* Control block layout used by BCM2711 40-bit channels */
+struct bcm2711_dma40_cb {
+	u32 ti;
+	u32 src;
+	u32 srci;
+	u32 dst;
+	u32 dsti;
+	u32 len;
+	u32 next_cb;
+	u32 rsvd;
+};
+
+static_assert(sizeof(struct bcm2835_dma_cb) == sizeof(struct bcm2711_dma40_cb));
+
 struct bcm2835_cb_entry {
-	struct bcm2835_dma_cb *cb;
+	union {
+		struct bcm2835_dma_cb *cb;
+		struct bcm2711_dma40_cb *cb40;
+	};
 	dma_addr_t paddr;
 };
 
@@ -92,6 +115,9 @@ struct bcm2835_chan {
 	unsigned int irq_flags;
 
 	bool is_lite_channel;
+	bool is_40bit_channel;
+	bool ext_addr;
+	u64 periph_offset;
 };
 
 struct bcm2835_desc {
@@ -148,7 +174,9 @@ struct bcm2835_desc {
 #define BCM2835_DMA_S_WIDTH	BIT(9) /* 128bit writes if set */
 #define BCM2835_DMA_S_DREQ	BIT(10) /* enable SREQ for source */
 #define BCM2835_DMA_S_IGNORE	BIT(11) /* ignore source reads - read 0 */
+#define BCM2835_DMA_BURST_LENGTH_MASK	GENMASK(15, 12)
 #define BCM2835_DMA_BURST_LENGTH(x) ((x & 15) << 12)
+#define BCM2835_DMA_PER_MAP_MASK	GENMASK(20, 16)
 #define BCM2835_DMA_PER_MAP(x)	((x & 31) << 16) /* REQ source */
 #define BCM2835_DMA_WAIT(x)	((x & 31) << 21) /* add DMA-wait cycles */
 #define BCM2835_DMA_NO_WIDE_BURSTS BIT(26) /* no 2 beat write bursts */
@@ -184,10 +212,65 @@ struct bcm2835_desc {
 #define MAX_DMA_LEN SZ_1G
 #define MAX_LITE_DMA_LEN (SZ_64K - 4)
 
+/* Legacy peripheral bus window used by DMA clients for FIFO addresses */
+#define BCM2835_DMA_PERIPH_BASE		0x7c000000
+#define BCM2835_DMA_PERIPH_END		0x80000000
+
+/* BCM2711 40-bit channel registers */
+#define BCM2711_DMA40_CS	0x00
+#define BCM2711_DMA40_CB	0x04
+#define BCM2711_DMA40_DEBUG	0x0c
+#define BCM2711_DMA40_SRC	0x14
+#define BCM2711_DMA40_SRCI	0x18
+#define BCM2711_DMA40_DEST	0x1c
+#define BCM2711_DMA40_DESTI	0x20
+
+/* BCM2711 40-bit CS bits */
+#define BCM2711_DMA40_ACTIVE		BIT(0)
+#define BCM2711_DMA40_END		BIT(1)
+#define BCM2711_DMA40_INT		BIT(2)
+#define BCM2711_DMA40_DREQ		BIT(3)
+#define BCM2711_DMA40_RD_PAUSED		BIT(4)
+#define BCM2711_DMA40_WR_PAUSED		BIT(5)
+#define BCM2711_DMA40_DREQ_PAUSED	BIT(6)
+#define BCM2711_DMA40_WAITING_FOR_WRITES BIT(7)
+#define BCM2711_DMA40_PROT		GENMASK(9, 8) /* secure, supervisor */
+#define BCM2711_DMA40_ERR		BIT(10)
+#define BCM2711_DMA40_TRANSACTIONS	BIT(25)
+#define BCM2711_DMA40_WAIT_FOR_WRITES	BIT(28)
+#define BCM2711_DMA40_DISDEBUG		BIT(29)
+#define BCM2711_DMA40_ABORT		BIT(30)
+#define BCM2711_DMA40_HALT		BIT(31)
+
+/* BCM2711 40-bit TI bits */
+#define BCM2711_DMA40_INTEN		BIT(0)
+#define BCM2711_DMA40_TDMODE		BIT(1) /* 2D-Mode */
+#define BCM2711_DMA40_WAIT_RESP		BIT(2) /* wait for AXI write ack */
+#define BCM2711_DMA40_WAIT_RD_RESP	BIT(3) /* wait for AXI read to complete */
+#define BCM2711_DMA40_PER_MAP(x)	(((x) & 31) << 9) /* REQ source */
+#define BCM2711_DMA40_S_DREQ		BIT(14)
+#define BCM2711_DMA40_D_DREQ		BIT(15)
+
+/* BCM2711 40-bit SRCI/DESTI bits */
+#define BCM2711_DMA40_ADDR_HI		GENMASK(7, 0)
+#define BCM2711_DMA40_BURST_LEN(x)	(((x) & 15) << 8)
+#define BCM2711_DMA40_INC		BIT(12)
+#define BCM2711_DMA40_SIZE_128		FIELD_PREP_CONST(GENMASK(14, 13), 2)
+#define BCM2711_DMA40_IGNORE		BIT(15)
+
+/* BCM2711 40-bit DEBUG bits */
+#define BCM2711_DMA40_DEBUG_RESET		BIT(23)
+
 static const struct bcm2835_dma_cfg bcm2835_dma_cfg = {
 	.dma_mask = DMA_BIT_MASK(32),
 };
 
+static const struct bcm2835_dma_cfg bcm2711_dma_cfg = {
+	.dma_mask = DMA_BIT_MASK(36),
+	.chan_40bit_mask = GENMASK(14, 11),
+	.periph_offset = 0x400000000ULL,
+};
+
 static inline size_t bcm2835_dma_max_frame_length(struct bcm2835_chan *c)
 {
 	/* lite and normal channels have different max frame length */
@@ -217,28 +300,95 @@ static inline struct bcm2835_desc *to_bcm2835_dma_desc(
 	return container_of(t, struct bcm2835_desc, vd.tx);
 }
 
+/* Translate legacy BCM2835 TI bits into the 40-bit channel TI format */
+static u32 bcm2711_dma40_ti(u32 info)
+{
+	u32 ti = BCM2711_DMA40_PER_MAP(FIELD_GET(BCM2835_DMA_PER_MAP_MASK, info));
+
+	if (info & BCM2835_DMA_INT_EN)
+		ti |= BCM2711_DMA40_INTEN;
+	if (info & BCM2835_DMA_WAIT_RESP)
+		ti |= BCM2711_DMA40_WAIT_RESP;
+	if (info & BCM2835_DMA_S_DREQ)
+		ti |= BCM2711_DMA40_S_DREQ | BCM2711_DMA40_WAIT_RD_RESP;
+	if (info & BCM2835_DMA_D_DREQ)
+		ti |= BCM2711_DMA40_D_DREQ;
+
+	return ti;
+}
+
+static u32 bcm2711_dma40_xi(u32 info, u32 inc, u32 width, u32 ignore)
+{
+	u32 xi = BCM2711_DMA40_BURST_LEN(FIELD_GET(BCM2835_DMA_BURST_LENGTH_MASK,
+						   info));
+
+	if (info & inc)
+		xi |= BCM2711_DMA40_INC;
+	if (info & width)
+		xi |= BCM2711_DMA40_SIZE_128;
+	if (info & ignore)
+		xi |= BCM2711_DMA40_IGNORE;
+
+	return xi;
+}
+
+/* Control block pointers of extended channels are 32 byte units */
+static u32 bcm2835_dma_cb_ptr(struct bcm2835_chan *c, dma_addr_t paddr)
+{
+	return c->ext_addr ? paddr >> 5 : paddr;
+}
+
 static void bcm2835_dma_cb_set_src(struct bcm2835_chan *c,
 				   struct bcm2835_cb_entry *e, dma_addr_t addr)
 {
-	e->cb->src = addr;
+	if (c->is_40bit_channel) {
+		e->cb40->src = lower_32_bits(addr);
+		FIELD_MODIFY(BCM2711_DMA40_ADDR_HI, &e->cb40->srci,
+			     upper_32_bits(addr));
+		return;
+	}
+
+	e->cb->src = lower_32_bits(addr);
 }
 
 static void bcm2835_dma_cb_set_dst(struct bcm2835_chan *c,
 				   struct bcm2835_cb_entry *e, dma_addr_t addr)
 {
-	e->cb->dst = addr;
+	if (c->is_40bit_channel) {
+		e->cb40->dst = lower_32_bits(addr);
+		FIELD_MODIFY(BCM2711_DMA40_ADDR_HI, &e->cb40->dsti,
+			     upper_32_bits(addr));
+		return;
+	}
+
+	e->cb->dst = lower_32_bits(addr);
 }
 
 static void bcm2835_dma_cb_init(struct bcm2835_chan *c,
 				struct bcm2835_cb_entry *e, u32 info,
 				dma_addr_t src, dma_addr_t dst)
 {
-	struct bcm2835_dma_cb *cb = e->cb;
+	if (c->is_40bit_channel) {
+		struct bcm2711_dma40_cb *cb = e->cb40;
+
+		cb->ti = bcm2711_dma40_ti(info);
+		cb->srci = bcm2711_dma40_xi(info, BCM2835_DMA_S_INC,
+					    BCM2835_DMA_S_WIDTH,
+					    BCM2835_DMA_S_IGNORE);
+		cb->dsti = bcm2711_dma40_xi(info, BCM2835_DMA_D_INC,
+					    BCM2835_DMA_D_WIDTH,
+					    BCM2835_DMA_D_IGNORE);
+		cb->len = 0;
+		cb->next_cb = 0;
+		cb->rsvd = 0;
+	} else {
+		struct bcm2835_dma_cb *cb = e->cb;
 
-	cb->info = info;
-	cb->length = 0;
-	cb->stride = 0;
-	cb->next = 0;
+		cb->info = info;
+		cb->length = 0;
+		cb->stride = 0;
+		cb->next = 0;
+	}
 
 	bcm2835_dma_cb_set_src(c, e, src);
 	bcm2835_dma_cb_set_dst(c, e, dst);
@@ -247,26 +397,40 @@ static void bcm2835_dma_cb_init(struct bcm2835_chan *c,
 static u32 bcm2835_dma_cb_get_len(struct bcm2835_chan *c,
 				  struct bcm2835_cb_entry *e)
 {
-	return e->cb->length;
+	return c->is_40bit_channel ? e->cb40->len : e->cb->length;
 }
 
 static void bcm2835_dma_cb_set_len(struct bcm2835_chan *c,
 				   struct bcm2835_cb_entry *e, u32 len)
 {
-	e->cb->length = len;
+	if (c->is_40bit_channel)
+		e->cb40->len = len;
+	else
+		e->cb->length = len;
 }
 
 static void bcm2835_dma_cb_add_info(struct bcm2835_chan *c,
 				    struct bcm2835_cb_entry *e, u32 info)
 {
-	e->cb->info |= info;
+	if (c->is_40bit_channel)
+		e->cb40->ti |= bcm2711_dma40_ti(info);
+	else
+		e->cb->info |= info;
 }
 
 static void bcm2835_dma_cb_set_next(struct bcm2835_chan *c,
 				    struct bcm2835_cb_entry *e,
 				    dma_addr_t next)
 {
-	e->cb->next = next;
+	if (c->is_40bit_channel)
+		e->cb40->next_cb = bcm2835_dma_cb_ptr(c, next);
+	else
+		e->cb->next = bcm2835_dma_cb_ptr(c, next);
+}
+
+static dma_addr_t bcm2711_dma40_addr(u32 lo, u32 xi)
+{
+	return (u64)FIELD_GET(BCM2711_DMA40_ADDR_HI, xi) << 32 | lo;
 }
 
 /* Memory side address of a control block */
@@ -274,6 +438,12 @@ static dma_addr_t bcm2835_dma_cb_mem_addr(struct bcm2835_chan *c,
 					  struct bcm2835_cb_entry *e,
 					  enum dma_transfer_direction dir)
 {
+	if (c->is_40bit_channel) {
+		if (dir == DMA_DEV_TO_MEM)
+			return bcm2711_dma40_addr(e->cb40->dst, e->cb40->dsti);
+		return bcm2711_dma40_addr(e->cb40->src, e->cb40->srci);
+	}
+
 	return dir == DMA_DEV_TO_MEM ? e->cb->dst : e->cb->src;
 }
 
@@ -282,11 +452,32 @@ static dma_addr_t bcm2835_dma_get_pos(struct bcm2835_chan *c,
 {
 	void __iomem *base = c->chan_base;
 
+	if (c->is_40bit_channel) {
+		if (dir == DMA_DEV_TO_MEM)
+			return bcm2711_dma40_addr(readl(base + BCM2711_DMA40_DEST),
+						  readl(base + BCM2711_DMA40_DESTI));
+		return bcm2711_dma40_addr(readl(base + BCM2711_DMA40_SRC),
+					  readl(base + BCM2711_DMA40_SRCI));
+	}
+
 	if (dir == DMA_DEV_TO_MEM)
 		return readl(base + BCM2835_DMA_DEST_AD);
 	return readl(base + BCM2835_DMA_SOURCE_AD);
 }
 
+/*
+ * Clients describe peripheral FIFOs by their legacy bus address. Channels
+ * with extended addressing see that window at a SoC specific offset.
+ */
+static dma_addr_t bcm2835_dma_periph_addr(struct bcm2835_chan *c,
+					  dma_addr_t addr)
+{
+	if (addr >= BCM2835_DMA_PERIPH_BASE && addr < BCM2835_DMA_PERIPH_END)
+		addr += c->periph_offset;
+
+	return addr;
+}
+
 static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc)
 {
 	size_t i;
@@ -475,6 +666,27 @@ static void bcm2835_dma_fill_cb_chain_with_sg(
 	}
 }
 
+static void bcm2711_dma40_abort(struct bcm2835_chan *c)
+{
+	void __iomem *chan_base = c->chan_base;
+	long timeout = 10000;
+
+	writel(readl(chan_base + BCM2711_DMA40_CS) & ~BCM2711_DMA40_ACTIVE,
+	       chan_base + BCM2711_DMA40_CS);
+
+	while ((readl(chan_base + BCM2711_DMA40_CS) &
+		BCM2711_DMA40_TRANSACTIONS) && --timeout)
+		cpu_relax();
+
+	if (!timeout)
+		dev_err(c->vc.chan.device->dev,
+			"failed to complete outstanding transactions\n");
+
+	writel(BCM2711_DMA40_PROT, chan_base + BCM2711_DMA40_CS);
+	writel(readl(chan_base + BCM2711_DMA40_DEBUG) | BCM2711_DMA40_DEBUG_RESET,
+	       chan_base + BCM2711_DMA40_DEBUG);
+}
+
 static void bcm2835_dma_abort(struct bcm2835_chan *c)
 {
 	void __iomem *chan_base = c->chan_base;
@@ -483,10 +695,16 @@ static void bcm2835_dma_abort(struct bcm2835_chan *c)
 	/*
 	 * A zero control block address means the channel is idle.
 	 * (The ACTIVE flag in the CS register is not a reliable indicator.)
+	 * The CB register of 40-bit channels is at the same offset.
 	 */
 	if (!readl(chan_base + BCM2835_DMA_ADDR))
 		return;
 
+	if (c->is_40bit_channel) {
+		bcm2711_dma40_abort(c);
+		return;
+	}
+
 	/* Write 0 to the active bit - Pause the DMA */
 	writel(0, chan_base + BCM2835_DMA_CS);
 
@@ -517,8 +735,13 @@ static void bcm2835_dma_start_desc(struct bcm2835_chan *c)
 
 	c->desc = d = to_bcm2835_dma_desc(&vd->tx);
 
-	writel(d->cb_list[0].paddr, c->chan_base + BCM2835_DMA_ADDR);
-	writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS);
+	writel(bcm2835_dma_cb_ptr(c, d->cb_list[0].paddr),
+	       c->chan_base + BCM2835_DMA_ADDR);
+	if (c->is_40bit_channel)
+		writel(BCM2711_DMA40_ACTIVE | BCM2711_DMA40_PROT,
+		       c->chan_base + BCM2711_DMA40_CS);
+	else
+		writel(BCM2835_DMA_ACTIVE, c->chan_base + BCM2835_DMA_CS);
 }
 
 static irqreturn_t bcm2835_dma_callback(int irq, void *data)
@@ -545,8 +768,12 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
 	 * if this IRQ handler is threaded.) If the channel is finished, it
 	 * will remain idle despite the ACTIVE flag being set.
 	 */
-	writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE,
-	       c->chan_base + BCM2835_DMA_CS);
+	if (c->is_40bit_channel)
+		writel(BCM2711_DMA40_INT | BCM2711_DMA40_ACTIVE |
+		       BCM2711_DMA40_PROT, c->chan_base + BCM2711_DMA40_CS);
+	else
+		writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE,
+		       c->chan_base + BCM2835_DMA_CS);
 
 	d = c->desc;
 
@@ -723,12 +950,12 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_slave_sg(
 	if (direction == DMA_DEV_TO_MEM) {
 		if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
 			return NULL;
-		src = c->cfg.src_addr;
+		src = bcm2835_dma_periph_addr(c, c->cfg.src_addr);
 		info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC;
 	} else {
 		if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
 			return NULL;
-		dst = c->cfg.dst_addr;
+		dst = bcm2835_dma_periph_addr(c, c->cfg.dst_addr);
 		info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC;
 	}
 
@@ -797,13 +1024,13 @@ static struct dma_async_tx_descriptor *bcm2835_dma_prep_dma_cyclic(
 	if (direction == DMA_DEV_TO_MEM) {
 		if (c->cfg.src_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
 			return NULL;
-		src = c->cfg.src_addr;
+		src = bcm2835_dma_periph_addr(c, c->cfg.src_addr);
 		dst = buf_addr;
 		info |= BCM2835_DMA_S_DREQ | BCM2835_DMA_D_INC;
 	} else {
 		if (c->cfg.dst_addr_width != DMA_SLAVE_BUSWIDTH_4_BYTES)
 			return NULL;
-		dst = c->cfg.dst_addr;
+		dst = bcm2835_dma_periph_addr(c, c->cfg.dst_addr);
 		src = buf_addr;
 		info |= BCM2835_DMA_D_DREQ | BCM2835_DMA_S_INC;
 
@@ -893,11 +1120,17 @@ static int bcm2835_dma_chan_init(struct bcm2835_dmadev *d, int chan_id,
 	c->irq_number = irq;
 	c->irq_flags = irq_flags;
 
+	if (d->cfg->chan_40bit_mask & BIT(chan_id))
+		c->is_40bit_channel = true;
 	/* check in DEBUG register if this is a LITE channel */
-	if (readl(c->chan_base + BCM2835_DMA_DEBUG) &
-		BCM2835_DMA_DEBUG_LITE)
+	else if (readl(c->chan_base + BCM2835_DMA_DEBUG) &
+		 BCM2835_DMA_DEBUG_LITE)
 		c->is_lite_channel = true;
 
+	c->ext_addr = c->is_40bit_channel;
+	if (c->ext_addr)
+		c->periph_offset = d->cfg->periph_offset;
+
 	return 0;
 }
 
@@ -917,6 +1150,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 },
 	{},
 };
 MODULE_DEVICE_TABLE(of, bcm2835_dma_of_match);
-- 
2.56.0


  parent reply	other threads:[~2026-11-02  9:07 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-02  9:06 [PATCH 0/9] dma: Add BCM2711 and BCM2712 support to bcm2835-dma Peter Robinson
2026-11-02  9:06 ` [PATCH 1/9] dt-bindings: dma: brcm,bcm2835-dma: Add BCM2711 and BCM2712 Peter Robinson
2026-11-02 19:39   ` Conor Dooley
2026-11-02 20:18     ` Peter Robinson
2026-11-02 20:38       ` Florian Fainelli
2026-11-02 21:35         ` Peter Robinson
2026-11-02  9:06 ` [PATCH 2/9] dmaengine: bcm2835: Refactor control block handling Peter Robinson
2026-11-02  9:06 ` [PATCH 3/9] dmaengine: bcm2835: Support controllers split across several nodes Peter Robinson
2026-11-02  9:06 ` Peter Robinson [this message]
2026-11-02  9:06 ` [PATCH 5/9] dmaengine: bcm2835: Add BCM2712 support Peter Robinson
2026-11-02  9:25   ` sashiko-bot
2026-11-02  9:06 ` [PATCH 6/9] ARM: dts: bcm2711: Add 40-bit DMA controller Peter Robinson
2026-11-02  9:06 ` [PATCH 7/9] ARM: dts: bcm2711-rpi: Use 40-bit DMA for HDMI audio Peter Robinson
2026-11-02  9:22   ` sashiko-bot
2026-11-02  9:06 ` [PATCH 8/9] arm64: dts: broadcom: bcm2712: Add DMA controllers Peter Robinson
2026-11-02  9:06 ` [PATCH 9/9] arm64: dts: broadcom: bcm2712-rpi-5-b: Enable HDMI audio Peter Robinson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261102090713.896324-5-pbrobinson@gmail.com \
    --to=pbrobinson@gmail.com \
    --cc=Frank.Li@kernel.org \
    --cc=bcm-kernel-feedback-list@broadcom.com \
    --cc=dave.stevenson@raspberrypi.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dmaengine@vger.kernel.org \
    --cc=florian.fainelli@broadcom.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-rpi-kernel@lists.infradead.org \
    --cc=rjui@broadcom.com \
    --cc=sbranden@broadcom.com \
    --cc=vkoul@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox