]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
dmaengine: dw-edma: Add interrupt-emulation hooks
authorKoichiro Den <den@valinux.co.jp>
Sun, 15 Feb 2026 15:22:15 +0000 (00:22 +0900)
committerVinod Koul <vkoul@kernel.org>
Wed, 25 Feb 2026 09:54:19 +0000 (15:24 +0530)
DesignWare eDMA instances support "interrupt emulation", where a
software write can assert the IRQ line without setting the normal
DONE/ABORT status bits.

Introduce core callbacks needed to support this feature:

  - .ack_emulated_irq(): core-specific sequence to deassert an emulated
    IRQ
  - .db_offset(): offset from the DMA register base that is suitable as a
    host-writable doorbell target for interrupt emulation

Implement both hooks for the v0 register map. For dw-hdma-v0, provide a
stub .db_offset() returning ~0 until the correct offset is known.

The next patch wires these hooks into the dw-edma IRQ path and exports
the doorbell resources to platform users.

Signed-off-by: Koichiro Den <den@valinux.co.jp>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://patch.msgid.link/20260215152216.3393561-2-den@valinux.co.jp
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/dma/dw-edma/dw-edma-core.h
drivers/dma/dw-edma/dw-edma-v0-core.c
drivers/dma/dw-edma/dw-hdma-v0-core.c

index 71894b9e0b1539c636171738963e80a0a5ef43a4..59b24973fa7db99da910952d150e27c36fa4713e 100644 (file)
@@ -126,6 +126,8 @@ struct dw_edma_core_ops {
        void (*start)(struct dw_edma_chunk *chunk, bool first);
        void (*ch_config)(struct dw_edma_chan *chan);
        void (*debugfs_on)(struct dw_edma *dw);
+       void (*ack_emulated_irq)(struct dw_edma *dw);
+       resource_size_t (*db_offset)(struct dw_edma *dw);
 };
 
 struct dw_edma_sg {
@@ -206,4 +208,19 @@ void dw_edma_core_debugfs_on(struct dw_edma *dw)
        dw->core->debugfs_on(dw);
 }
 
+static inline int dw_edma_core_ack_emulated_irq(struct dw_edma *dw)
+{
+       if (!dw->core->ack_emulated_irq)
+               return -EOPNOTSUPP;
+
+       dw->core->ack_emulated_irq(dw);
+       return 0;
+}
+
+static inline resource_size_t
+dw_edma_core_db_offset(struct dw_edma *dw)
+{
+       return dw->core->db_offset(dw);
+}
+
 #endif /* _DW_EDMA_CORE_H */
index b75fdaffad9a4ea6cd8d15e8f43bea550848b46c..69e8279adec81ad940cfe6fcb422adc2017d7f58 100644 (file)
@@ -509,6 +509,25 @@ static void dw_edma_v0_core_debugfs_on(struct dw_edma *dw)
        dw_edma_v0_debugfs_on(dw);
 }
 
+static void dw_edma_v0_core_ack_emulated_irq(struct dw_edma *dw)
+{
+       /*
+        * Interrupt emulation may assert the IRQ without setting
+        * DONE/ABORT status bits. A zero write to INT_CLEAR deasserts the
+        * emulated IRQ, while being a no-op for real interrupts.
+        */
+       SET_BOTH_32(dw, int_clear, 0);
+}
+
+static resource_size_t dw_edma_v0_core_db_offset(struct dw_edma *dw)
+{
+       /*
+        * rd_int_status is chosen arbitrarily, but wr_int_status would be
+        * equally suitable.
+        */
+       return offsetof(struct dw_edma_v0_regs, rd_int_status);
+}
+
 static const struct dw_edma_core_ops dw_edma_v0_core = {
        .off = dw_edma_v0_core_off,
        .ch_count = dw_edma_v0_core_ch_count,
@@ -517,6 +536,8 @@ static const struct dw_edma_core_ops dw_edma_v0_core = {
        .start = dw_edma_v0_core_start,
        .ch_config = dw_edma_v0_core_ch_config,
        .debugfs_on = dw_edma_v0_core_debugfs_on,
+       .ack_emulated_irq = dw_edma_v0_core_ack_emulated_irq,
+       .db_offset = dw_edma_v0_core_db_offset,
 };
 
 void dw_edma_v0_core_register(struct dw_edma *dw)
index e3f8db4fe909a1776bb5899e0b4c9c7a9d178c05..1ae8e44f0a67f653c4bd1a530da27df01fa9ce2f 100644 (file)
@@ -283,6 +283,12 @@ static void dw_hdma_v0_core_debugfs_on(struct dw_edma *dw)
        dw_hdma_v0_debugfs_on(dw);
 }
 
+static resource_size_t dw_hdma_v0_core_db_offset(struct dw_edma *dw)
+{
+       /* Implement once the correct offset is known. */
+       return ~0;
+}
+
 static const struct dw_edma_core_ops dw_hdma_v0_core = {
        .off = dw_hdma_v0_core_off,
        .ch_count = dw_hdma_v0_core_ch_count,
@@ -291,6 +297,7 @@ static const struct dw_edma_core_ops dw_hdma_v0_core = {
        .start = dw_hdma_v0_core_start,
        .ch_config = dw_hdma_v0_core_ch_config,
        .debugfs_on = dw_hdma_v0_core_debugfs_on,
+       .db_offset = dw_hdma_v0_core_db_offset,
 };
 
 void dw_hdma_v0_core_register(struct dw_edma *dw)