* [PATCH RFC 10/11] dmaengine: bcm2835: add BCM2711 40-bit DMA support
@ 2021-12-27 12:06 Stefan Wahren
2021-12-27 12:06 ` [PATCH RFC 11/11] ARM: dts: bcm2711: add bcm2711-dma node Stefan Wahren
2022-02-15 11:19 ` [PATCH RFC 10/11] dmaengine: bcm2835: add BCM2711 40-bit DMA support Vinod Koul
0 siblings, 2 replies; 3+ messages in thread
From: Stefan Wahren @ 2021-12-27 12:06 UTC (permalink / raw)
To: Vinod Koul, Rob Herring, Florian Fainelli, Nicolas Saenz Julienne
Cc: Ray Jui, Scott Branden, bcm-kernel-feedback-list, dmaengine,
Phil Elwell, devicetree, linux-arm-kernel, Lukas Wunner,
linux-rpi-kernel, Stefan Wahren
BCM2711 has 4 DMA channels with a 40-bit address range, allowing them
to access the full 4GB of memory on a Pi 4. Assume every channel is capable
of 40-bit address range.
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
drivers/dma/bcm2835-dma.c | 243 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 243 insertions(+)
diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
index 7159fa2..83343f9 100644
--- a/drivers/dma/bcm2835-dma.c
+++ b/drivers/dma/bcm2835-dma.c
@@ -36,6 +36,7 @@
#define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14
#define BCM2835_DMA_CHAN_NAME_SIZE 8
+#define BCM2711_DMA40_PHYS_ADDR 0x400000000ULL
/**
* struct bcm2835_dmadev - BCM2835 DMA controller
@@ -65,6 +66,17 @@ struct bcm2835_dma_cb {
uint32_t pad[2];
};
+struct bcm2711_dma40_scb {
+ uint32_t ti;
+ uint32_t src;
+ uint32_t srci;
+ uint32_t dst;
+ uint32_t dsti;
+ uint32_t len;
+ uint32_t next_cb;
+ uint32_t rsvd;
+};
+
struct bcm2835_cb_entry {
struct bcm_dma_cb *cb;
dma_addr_t paddr;
@@ -205,6 +217,49 @@ struct bcm2835_desc {
#define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */
#define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n))
+/* 40-bit DMA support */
+#define BCM2711_DMA40_CS 0x00
+#define BCM2711_DMA40_CB 0x04
+#define BCM2711_DMA40_DEBUG 0x0c
+#define BCM2711_DMA40_TI 0x10
+#define BCM2711_DMA40_SRC 0x14
+#define BCM2711_DMA40_SRCI 0x18
+#define BCM2711_DMA40_DEST 0x1c
+#define BCM2711_DMA40_DESTI 0x20
+#define BCM2711_DMA40_LEN 0x24
+#define BCM2711_DMA40_NEXT_CB 0x28
+#define BCM2711_DMA40_DEBUG2 0x2c
+
+#define BCM2711_DMA40_ACTIVE BIT(0)
+#define BCM2711_DMA40_END BIT(1)
+#define BCM2711_DMA40_INT BIT(2)
+#define BCM2711_DMA40_DREQ BIT(3) /* DREQ state */
+#define BCM2711_DMA40_RD_PAUSED BIT(4) /* Reading is paused */
+#define BCM2711_DMA40_WR_PAUSED BIT(5) /* Writing is paused */
+#define BCM2711_DMA40_DREQ_PAUSED BIT(6) /* Is paused by DREQ flow control */
+#define BCM2711_DMA40_WAITING_FOR_WRITES BIT(7) /* Waiting for last write */
+#define BCM2711_DMA40_ERR BIT(10)
+#define BCM2711_DMA40_QOS(x) (((x) & 0x1f) << 16)
+#define BCM2711_DMA40_PANIC_QOS(x) (((x) & 0x1f) << 20)
+#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)
+
+/* Transfer information 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 to be acked */
+#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) /* enable SREQ for source */
+#define BCM2711_DMA40_D_DREQ BIT(15) /* enable DREQ for destination */
+#define BCM2711_DMA40_S_WAIT(x) ((x & 0xff) << 16) /* add DMA read-wait cycles */
+#define BCM2711_DMA40_D_WAIT(x) ((x & 0xff) << 24) /* add DMA write-wait cycles */
+
+#define BCM2711_DMA40_INC BIT(12)
+#define BCM2711_DMA40_IGNORE BIT(15)
+
/* the max dma length for different channels */
#define MAX_DMA_LEN SZ_1G
#define MAX_LITE_DMA_LEN (SZ_64K - 4)
@@ -297,6 +352,53 @@ static u32 bcm2835_dma_prepare_cb_extra(struct bcm2835_chan *c,
return result;
}
+static u32 bcm2711_dma_prepare_cb_info(struct bcm2835_chan *c,
+ enum dma_transfer_direction direction,
+ bool zero_page)
+{
+ u32 result;
+
+ if (direction == DMA_MEM_TO_MEM)
+ return 0;
+
+ result = BCM2711_DMA40_WAIT_RESP;
+
+ /* Setup DREQ channel */
+ if (c->dreq != 0)
+ result |= BCM2711_DMA40_PER_MAP(c->dreq);
+
+ if (direction == DMA_DEV_TO_MEM) {
+ result |= BCM2711_DMA40_S_DREQ | BCM2711_DMA40_WAIT_RD_RESP;
+ } else {
+ result |= BCM2711_DMA40_D_DREQ;
+ }
+
+ return result;
+}
+
+static u32 bcm2711_dma_prepare_cb_extra(struct bcm2835_chan *c,
+ enum dma_transfer_direction direction,
+ bool cyclic, bool final,
+ unsigned long flags)
+{
+ u32 result = 0;
+
+ if (cyclic) {
+ if (flags & DMA_PREP_INTERRUPT)
+ result |= BCM2711_DMA40_INTEN;
+ } else {
+ if (!final)
+ return 0;
+
+ result |= BCM2711_DMA40_INTEN;
+
+ if (direction == DMA_MEM_TO_MEM)
+ result |= BCM2711_DMA40_WAIT_RESP;
+ }
+
+ return result;
+}
+
static inline bool need_src_incr(enum dma_transfer_direction direction)
{
return direction != DMA_DEV_TO_MEM;
@@ -413,6 +515,120 @@ static dma_addr_t bcm2835_dma_read_addr(struct bcm2835_chan *c,
return 0;
}
+static inline u32 bcm2711_dma_cb_get_length(void *data)
+{
+ struct bcm2711_dma40_scb *scb = data;
+
+ return scb->len;
+}
+
+static inline dma_addr_t
+bcm2711_dma_cb_get_addr(void *data, enum dma_transfer_direction direction)
+{
+ struct bcm2711_dma40_scb *scb = data;
+
+ if (direction == DMA_DEV_TO_MEM)
+ return scb->dst + ((scb->dsti & 0xff) << 8);
+
+ return scb->src + ((scb->srci & 0xff) << 8);
+}
+
+static inline void
+bcm2711_dma_cb_init(void *data, struct bcm2835_chan *c,
+ enum dma_transfer_direction direction, u32 src, u32 dst,
+ bool zero_page)
+{
+ struct bcm2711_dma40_scb *scb = data;
+
+ scb->ti = bcm2711_dma_prepare_cb_info(c, direction, zero_page);
+ scb->src = lower_32_bits(src);
+ scb->srci = upper_32_bits(src);
+
+ if (need_src_incr(direction))
+ scb->srci |= BCM2711_DMA40_INC;
+
+ scb->dst = lower_32_bits(dst);
+ scb->dsti = upper_32_bits(dst);
+
+ if (need_dst_incr(direction))
+ scb->dsti |= BCM2711_DMA40_INC;
+
+ scb->next_cb = 0;
+}
+
+static inline void
+bcm2711_dma_cb_set_src(void *data, enum dma_transfer_direction direction,
+ u32 src)
+{
+ struct bcm2711_dma40_scb *scb = data;
+
+ scb->src = lower_32_bits(src);
+ scb->srci = upper_32_bits(src);
+
+ if (need_src_incr(direction))
+ scb->srci |= BCM2711_DMA40_INC;
+}
+
+static inline void
+bcm2711_dma_cb_set_dst(void *data, enum dma_transfer_direction direction,
+ u32 dst)
+{
+ struct bcm2711_dma40_scb *scb = data;
+
+ scb->dst = lower_32_bits(dst);
+ scb->dsti = upper_32_bits(dst);
+
+ if (need_dst_incr(direction))
+ scb->dsti |= BCM2711_DMA40_INC;
+}
+
+static inline void bcm2711_dma_cb_set_next(void *data, u32 next)
+{
+ struct bcm2711_dma40_scb *scb = data;
+
+ scb->next_cb = next;
+}
+
+static inline void bcm2711_dma_cb_set_length(void *data, u32 length)
+{
+ struct bcm2711_dma40_scb *scb = data;
+
+ scb->len = length;
+}
+
+static inline void
+bcm2711_dma_cb_append_extra(void *data, struct bcm2835_chan *c,
+ enum dma_transfer_direction direction,
+ bool cyclic, bool final, unsigned long flags)
+{
+ struct bcm2711_dma40_scb *scb = data;
+
+ scb->ti |= bcm2711_dma_prepare_cb_extra(c, direction, cyclic, final,
+ flags);
+}
+
+static inline dma_addr_t bcm2711_dma_to_cb_addr(dma_addr_t addr)
+{
+ return (addr >> 5);
+}
+
+static void bcm2711_dma_chan_plat_init(struct bcm2835_chan *c)
+{
+}
+
+static dma_addr_t bcm2711_dma_read_addr(struct bcm2835_chan *c,
+ enum dma_transfer_direction direction)
+{
+ if (direction == DMA_MEM_TO_DEV)
+ return readl(c->chan_base + BCM2711_DMA40_SRC) +
+ ((readl(c->chan_base + BCM2711_DMA40_SRCI) & 0xff) << 8);
+ else if (direction == DMA_DEV_TO_MEM)
+ return readl(c->chan_base + BCM2711_DMA40_DEST) +
+ ((readl(c->chan_base + BCM2711_DMA40_DESTI) & 0xff) << 8);
+
+ return 0;
+}
+
static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc)
{
size_t i;
@@ -1070,8 +1286,35 @@ static const struct bcm2835_dma_cfg bcm2835_data = {
.read_addr = bcm2835_dma_read_addr,
};
+static const struct bcm2835_dma_cfg bcm2711_data = {
+ .addr_offset = BCM2711_DMA40_PHYS_ADDR,
+
+ .cs_reg = BCM2711_DMA40_CS,
+ .cb_reg = BCM2711_DMA40_CB,
+
+ .wait_mask = BCM2711_DMA40_WAITING_FOR_WRITES,
+ .reset_mask = BCM2711_DMA40_HALT,
+ .int_mask = BCM2711_DMA40_INTEN,
+ .active_mask = BCM2711_DMA40_ACTIVE,
+
+ .cb_get_length = bcm2711_dma_cb_get_length,
+ .cb_get_addr = bcm2711_dma_cb_get_addr,
+ .cb_init = bcm2711_dma_cb_init,
+ .cb_set_src = bcm2711_dma_cb_set_src,
+ .cb_set_dst = bcm2711_dma_cb_set_dst,
+ .cb_set_next = bcm2711_dma_cb_set_next,
+ .cb_set_length = bcm2711_dma_cb_set_length,
+ .cb_append_extra = bcm2711_dma_cb_append_extra,
+
+ .to_cb_addr = bcm2711_dma_to_cb_addr,
+
+ .chan_plat_init = bcm2711_dma_chan_plat_init,
+ .read_addr = bcm2711_dma_read_addr,
+};
+
static const struct of_device_id bcm2835_dma_of_match[] = {
{ .compatible = "brcm,bcm2835-dma", .data = &bcm2835_data },
+ { .compatible = "brcm,bcm2711-dma", .data = &bcm2711_data },
{},
};
MODULE_DEVICE_TABLE(of, bcm2835_dma_of_match);
--
2.7.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH RFC 11/11] ARM: dts: bcm2711: add bcm2711-dma node
2021-12-27 12:06 [PATCH RFC 10/11] dmaengine: bcm2835: add BCM2711 40-bit DMA support Stefan Wahren
@ 2021-12-27 12:06 ` Stefan Wahren
2022-02-15 11:19 ` [PATCH RFC 10/11] dmaengine: bcm2835: add BCM2711 40-bit DMA support Vinod Koul
1 sibling, 0 replies; 3+ messages in thread
From: Stefan Wahren @ 2021-12-27 12:06 UTC (permalink / raw)
To: Vinod Koul, Rob Herring, Florian Fainelli, Nicolas Saenz Julienne
Cc: Ray Jui, Scott Branden, bcm-kernel-feedback-list, dmaengine,
Phil Elwell, devicetree, linux-arm-kernel, Lukas Wunner,
linux-rpi-kernel, Stefan Wahren
BCM2711 has 4 DMA channels with a 40-bit address range, allowing them
to access the full 4GB of memory on a Pi 4. Not sure which adjustments to
the parent node (scb) are required.
Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
---
arch/arm/boot/dts/bcm2711.dtsi | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi
index 590068b..12f373b 100644
--- a/arch/arm/boot/dts/bcm2711.dtsi
+++ b/arch/arm/boot/dts/bcm2711.dtsi
@@ -536,6 +536,22 @@
#size-cells = <0x1>;
};
};
+
+ dma40: dma-controller@7e007b00 {
+ compatible = "brcm,bcm2711-dma";
+ reg = <0x0 0x7e007b00 0x400>;
+ interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, /* dma4 11 */
+ <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>, /* dma4 12 */
+ <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>, /* dma4 13 */
+ <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>; /* dma4 14 */
+ interrupt-names = "dma11",
+ "dma12",
+ "dma13",
+ "dma14";
+ #dma-cells = <1>;
+ /* The VPU firmware uses DMA channel 11 for VCHIQ */
+ brcm,dma-channel-mask = <0x7000>;
+ };
};
};
--
2.7.4
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH RFC 10/11] dmaengine: bcm2835: add BCM2711 40-bit DMA support
2021-12-27 12:06 [PATCH RFC 10/11] dmaengine: bcm2835: add BCM2711 40-bit DMA support Stefan Wahren
2021-12-27 12:06 ` [PATCH RFC 11/11] ARM: dts: bcm2711: add bcm2711-dma node Stefan Wahren
@ 2022-02-15 11:19 ` Vinod Koul
1 sibling, 0 replies; 3+ messages in thread
From: Vinod Koul @ 2022-02-15 11:19 UTC (permalink / raw)
To: Stefan Wahren
Cc: Rob Herring, Florian Fainelli, Nicolas Saenz Julienne, Ray Jui,
Scott Branden, bcm-kernel-feedback-list, dmaengine, Phil Elwell,
devicetree, linux-arm-kernel, Lukas Wunner, linux-rpi-kernel
On 27-12-21, 13:06, Stefan Wahren wrote:
> BCM2711 has 4 DMA channels with a 40-bit address range, allowing them
> to access the full 4GB of memory on a Pi 4. Assume every channel is capable
> of 40-bit address range.
>
> Signed-off-by: Stefan Wahren <stefan.wahren@i2se.com>
> ---
> drivers/dma/bcm2835-dma.c | 243 ++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 243 insertions(+)
>
> diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
> index 7159fa2..83343f9 100644
> --- a/drivers/dma/bcm2835-dma.c
> +++ b/drivers/dma/bcm2835-dma.c
> @@ -36,6 +36,7 @@
>
> #define BCM2835_DMA_MAX_DMA_CHAN_SUPPORTED 14
> #define BCM2835_DMA_CHAN_NAME_SIZE 8
> +#define BCM2711_DMA40_PHYS_ADDR 0x400000000ULL
>
> /**
> * struct bcm2835_dmadev - BCM2835 DMA controller
> @@ -65,6 +66,17 @@ struct bcm2835_dma_cb {
> uint32_t pad[2];
> };
>
> +struct bcm2711_dma40_scb {
> + uint32_t ti;
> + uint32_t src;
> + uint32_t srci;
> + uint32_t dst;
> + uint32_t dsti;
> + uint32_t len;
> + uint32_t next_cb;
> + uint32_t rsvd;
> +};
> +
> struct bcm2835_cb_entry {
> struct bcm_dma_cb *cb;
> dma_addr_t paddr;
> @@ -205,6 +217,49 @@ struct bcm2835_desc {
> #define BCM2835_DMA_CHAN(n) ((n) << 8) /* Base address */
> #define BCM2835_DMA_CHANIO(base, n) ((base) + BCM2835_DMA_CHAN(n))
>
> +/* 40-bit DMA support */
> +#define BCM2711_DMA40_CS 0x00
> +#define BCM2711_DMA40_CB 0x04
> +#define BCM2711_DMA40_DEBUG 0x0c
> +#define BCM2711_DMA40_TI 0x10
> +#define BCM2711_DMA40_SRC 0x14
> +#define BCM2711_DMA40_SRCI 0x18
> +#define BCM2711_DMA40_DEST 0x1c
> +#define BCM2711_DMA40_DESTI 0x20
> +#define BCM2711_DMA40_LEN 0x24
> +#define BCM2711_DMA40_NEXT_CB 0x28
> +#define BCM2711_DMA40_DEBUG2 0x2c
> +
> +#define BCM2711_DMA40_ACTIVE BIT(0)
> +#define BCM2711_DMA40_END BIT(1)
> +#define BCM2711_DMA40_INT BIT(2)
> +#define BCM2711_DMA40_DREQ BIT(3) /* DREQ state */
> +#define BCM2711_DMA40_RD_PAUSED BIT(4) /* Reading is paused */
> +#define BCM2711_DMA40_WR_PAUSED BIT(5) /* Writing is paused */
> +#define BCM2711_DMA40_DREQ_PAUSED BIT(6) /* Is paused by DREQ flow control */
> +#define BCM2711_DMA40_WAITING_FOR_WRITES BIT(7) /* Waiting for last write */
> +#define BCM2711_DMA40_ERR BIT(10)
> +#define BCM2711_DMA40_QOS(x) (((x) & 0x1f) << 16)
> +#define BCM2711_DMA40_PANIC_QOS(x) (((x) & 0x1f) << 20)
Use FIELD_PREP() for this ?
> +#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)
> +
> +/* Transfer information 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 to be acked */
> +#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) /* enable SREQ for source */
> +#define BCM2711_DMA40_D_DREQ BIT(15) /* enable DREQ for destination */
> +#define BCM2711_DMA40_S_WAIT(x) ((x & 0xff) << 16) /* add DMA read-wait cycles */
> +#define BCM2711_DMA40_D_WAIT(x) ((x & 0xff) << 24) /* add DMA write-wait cycles */
Use FIELD_PREP() for this ?
> +
> +#define BCM2711_DMA40_INC BIT(12)
> +#define BCM2711_DMA40_IGNORE BIT(15)
> +
> /* the max dma length for different channels */
> #define MAX_DMA_LEN SZ_1G
> #define MAX_LITE_DMA_LEN (SZ_64K - 4)
> @@ -297,6 +352,53 @@ static u32 bcm2835_dma_prepare_cb_extra(struct bcm2835_chan *c,
> return result;
> }
>
> +static u32 bcm2711_dma_prepare_cb_info(struct bcm2835_chan *c,
> + enum dma_transfer_direction direction,
> + bool zero_page)
> +{
> + u32 result;
> +
> + if (direction == DMA_MEM_TO_MEM)
> + return 0;
> +
> + result = BCM2711_DMA40_WAIT_RESP;
> +
> + /* Setup DREQ channel */
> + if (c->dreq != 0)
> + result |= BCM2711_DMA40_PER_MAP(c->dreq);
> +
> + if (direction == DMA_DEV_TO_MEM) {
> + result |= BCM2711_DMA40_S_DREQ | BCM2711_DMA40_WAIT_RD_RESP;
> + } else {
> + result |= BCM2711_DMA40_D_DREQ;
> + }
> +
> + return result;
> +}
> +
> +static u32 bcm2711_dma_prepare_cb_extra(struct bcm2835_chan *c,
> + enum dma_transfer_direction direction,
> + bool cyclic, bool final,
> + unsigned long flags)
> +{
> + u32 result = 0;
> +
> + if (cyclic) {
> + if (flags & DMA_PREP_INTERRUPT)
> + result |= BCM2711_DMA40_INTEN;
> + } else {
> + if (!final)
> + return 0;
> +
> + result |= BCM2711_DMA40_INTEN;
> +
> + if (direction == DMA_MEM_TO_MEM)
> + result |= BCM2711_DMA40_WAIT_RESP;
> + }
> +
> + return result;
> +}
> +
> static inline bool need_src_incr(enum dma_transfer_direction direction)
> {
> return direction != DMA_DEV_TO_MEM;
> @@ -413,6 +515,120 @@ static dma_addr_t bcm2835_dma_read_addr(struct bcm2835_chan *c,
> return 0;
> }
>
> +static inline u32 bcm2711_dma_cb_get_length(void *data)
> +{
> + struct bcm2711_dma40_scb *scb = data;
> +
> + return scb->len;
> +}
> +
> +static inline dma_addr_t
> +bcm2711_dma_cb_get_addr(void *data, enum dma_transfer_direction direction)
> +{
> + struct bcm2711_dma40_scb *scb = data;
> +
> + if (direction == DMA_DEV_TO_MEM)
> + return scb->dst + ((scb->dsti & 0xff) << 8);
> +
> + return scb->src + ((scb->srci & 0xff) << 8);
> +}
> +
> +static inline void
> +bcm2711_dma_cb_init(void *data, struct bcm2835_chan *c,
> + enum dma_transfer_direction direction, u32 src, u32 dst,
> + bool zero_page)
> +{
> + struct bcm2711_dma40_scb *scb = data;
> +
> + scb->ti = bcm2711_dma_prepare_cb_info(c, direction, zero_page);
> + scb->src = lower_32_bits(src);
> + scb->srci = upper_32_bits(src);
> +
> + if (need_src_incr(direction))
> + scb->srci |= BCM2711_DMA40_INC;
> +
> + scb->dst = lower_32_bits(dst);
> + scb->dsti = upper_32_bits(dst);
> +
> + if (need_dst_incr(direction))
> + scb->dsti |= BCM2711_DMA40_INC;
> +
> + scb->next_cb = 0;
> +}
> +
> +static inline void
> +bcm2711_dma_cb_set_src(void *data, enum dma_transfer_direction direction,
> + u32 src)
> +{
> + struct bcm2711_dma40_scb *scb = data;
> +
> + scb->src = lower_32_bits(src);
> + scb->srci = upper_32_bits(src);
> +
> + if (need_src_incr(direction))
> + scb->srci |= BCM2711_DMA40_INC;
> +}
> +
> +static inline void
> +bcm2711_dma_cb_set_dst(void *data, enum dma_transfer_direction direction,
> + u32 dst)
> +{
> + struct bcm2711_dma40_scb *scb = data;
> +
> + scb->dst = lower_32_bits(dst);
> + scb->dsti = upper_32_bits(dst);
> +
> + if (need_dst_incr(direction))
> + scb->dsti |= BCM2711_DMA40_INC;
> +}
> +
> +static inline void bcm2711_dma_cb_set_next(void *data, u32 next)
> +{
> + struct bcm2711_dma40_scb *scb = data;
> +
> + scb->next_cb = next;
> +}
> +
> +static inline void bcm2711_dma_cb_set_length(void *data, u32 length)
> +{
> + struct bcm2711_dma40_scb *scb = data;
> +
> + scb->len = length;
> +}
> +
> +static inline void
> +bcm2711_dma_cb_append_extra(void *data, struct bcm2835_chan *c,
> + enum dma_transfer_direction direction,
> + bool cyclic, bool final, unsigned long flags)
> +{
> + struct bcm2711_dma40_scb *scb = data;
> +
> + scb->ti |= bcm2711_dma_prepare_cb_extra(c, direction, cyclic, final,
> + flags);
> +}
this helper is just a wrapper over bcm2711_dma_prepare_cb_extra() do
consider getting rid of extra layer...
> +
> +static inline dma_addr_t bcm2711_dma_to_cb_addr(dma_addr_t addr)
> +{
> + return (addr >> 5);
> +}
> +
> +static void bcm2711_dma_chan_plat_init(struct bcm2835_chan *c)
> +{
> +}
> +
> +static dma_addr_t bcm2711_dma_read_addr(struct bcm2835_chan *c,
> + enum dma_transfer_direction direction)
> +{
> + if (direction == DMA_MEM_TO_DEV)
> + return readl(c->chan_base + BCM2711_DMA40_SRC) +
> + ((readl(c->chan_base + BCM2711_DMA40_SRCI) & 0xff) << 8);
> + else if (direction == DMA_DEV_TO_MEM)
> + return readl(c->chan_base + BCM2711_DMA40_DEST) +
> + ((readl(c->chan_base + BCM2711_DMA40_DESTI) & 0xff) << 8);
> +
> + return 0;
> +}
> +
> static void bcm2835_dma_free_cb_chain(struct bcm2835_desc *desc)
> {
> size_t i;
> @@ -1070,8 +1286,35 @@ static const struct bcm2835_dma_cfg bcm2835_data = {
> .read_addr = bcm2835_dma_read_addr,
> };
>
> +static const struct bcm2835_dma_cfg bcm2711_data = {
> + .addr_offset = BCM2711_DMA40_PHYS_ADDR,
> +
> + .cs_reg = BCM2711_DMA40_CS,
> + .cb_reg = BCM2711_DMA40_CB,
> +
> + .wait_mask = BCM2711_DMA40_WAITING_FOR_WRITES,
> + .reset_mask = BCM2711_DMA40_HALT,
> + .int_mask = BCM2711_DMA40_INTEN,
> + .active_mask = BCM2711_DMA40_ACTIVE,
> +
> + .cb_get_length = bcm2711_dma_cb_get_length,
> + .cb_get_addr = bcm2711_dma_cb_get_addr,
> + .cb_init = bcm2711_dma_cb_init,
> + .cb_set_src = bcm2711_dma_cb_set_src,
> + .cb_set_dst = bcm2711_dma_cb_set_dst,
> + .cb_set_next = bcm2711_dma_cb_set_next,
> + .cb_set_length = bcm2711_dma_cb_set_length,
> + .cb_append_extra = bcm2711_dma_cb_append_extra,
> +
> + .to_cb_addr = bcm2711_dma_to_cb_addr,
> +
> + .chan_plat_init = bcm2711_dma_chan_plat_init,
> + .read_addr = bcm2711_dma_read_addr,
> +};
> +
> static const struct of_device_id bcm2835_dma_of_match[] = {
> { .compatible = "brcm,bcm2835-dma", .data = &bcm2835_data },
> + { .compatible = "brcm,bcm2711-dma", .data = &bcm2711_data },
> {},
> };
> MODULE_DEVICE_TABLE(of, bcm2835_dma_of_match);
> --
> 2.7.4
--
~Vinod
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2022-02-15 11:20 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-12-27 12:06 [PATCH RFC 10/11] dmaengine: bcm2835: add BCM2711 40-bit DMA support Stefan Wahren
2021-12-27 12:06 ` [PATCH RFC 11/11] ARM: dts: bcm2711: add bcm2711-dma node Stefan Wahren
2022-02-15 11:19 ` [PATCH RFC 10/11] dmaengine: bcm2835: add BCM2711 40-bit DMA support Vinod Koul
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).