dmaengine: dw-edma: Add interrupt-emulation hooks

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>
This commit is contained in:
Koichiro Den 2026-02-16 00:22:15 +09:00 committed by Vinod Koul
parent 490c367b5f
commit 2e87268795
3 changed files with 45 additions and 0 deletions

View 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 */

View 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)

View 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)