Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Koichiro Den and committed by
Vinod Koul
2e872687 490c367b

+45
+17
drivers/dma/dw-edma/dw-edma-core.h
··· 126 126 void (*start)(struct dw_edma_chunk *chunk, bool first); 127 127 void (*ch_config)(struct dw_edma_chan *chan); 128 128 void (*debugfs_on)(struct dw_edma *dw); 129 + void (*ack_emulated_irq)(struct dw_edma *dw); 130 + resource_size_t (*db_offset)(struct dw_edma *dw); 129 131 }; 130 132 131 133 struct dw_edma_sg { ··· 206 204 void dw_edma_core_debugfs_on(struct dw_edma *dw) 207 205 { 208 206 dw->core->debugfs_on(dw); 207 + } 208 + 209 + static inline int dw_edma_core_ack_emulated_irq(struct dw_edma *dw) 210 + { 211 + if (!dw->core->ack_emulated_irq) 212 + return -EOPNOTSUPP; 213 + 214 + dw->core->ack_emulated_irq(dw); 215 + return 0; 216 + } 217 + 218 + static inline resource_size_t 219 + dw_edma_core_db_offset(struct dw_edma *dw) 220 + { 221 + return dw->core->db_offset(dw); 209 222 } 210 223 211 224 #endif /* _DW_EDMA_CORE_H */
+21
drivers/dma/dw-edma/dw-edma-v0-core.c
··· 509 509 dw_edma_v0_debugfs_on(dw); 510 510 } 511 511 512 + static void dw_edma_v0_core_ack_emulated_irq(struct dw_edma *dw) 513 + { 514 + /* 515 + * Interrupt emulation may assert the IRQ without setting 516 + * DONE/ABORT status bits. A zero write to INT_CLEAR deasserts the 517 + * emulated IRQ, while being a no-op for real interrupts. 518 + */ 519 + SET_BOTH_32(dw, int_clear, 0); 520 + } 521 + 522 + static resource_size_t dw_edma_v0_core_db_offset(struct dw_edma *dw) 523 + { 524 + /* 525 + * rd_int_status is chosen arbitrarily, but wr_int_status would be 526 + * equally suitable. 527 + */ 528 + return offsetof(struct dw_edma_v0_regs, rd_int_status); 529 + } 530 + 512 531 static const struct dw_edma_core_ops dw_edma_v0_core = { 513 532 .off = dw_edma_v0_core_off, 514 533 .ch_count = dw_edma_v0_core_ch_count, ··· 536 517 .start = dw_edma_v0_core_start, 537 518 .ch_config = dw_edma_v0_core_ch_config, 538 519 .debugfs_on = dw_edma_v0_core_debugfs_on, 520 + .ack_emulated_irq = dw_edma_v0_core_ack_emulated_irq, 521 + .db_offset = dw_edma_v0_core_db_offset, 539 522 }; 540 523 541 524 void dw_edma_v0_core_register(struct dw_edma *dw)
+7
drivers/dma/dw-edma/dw-hdma-v0-core.c
··· 283 283 dw_hdma_v0_debugfs_on(dw); 284 284 } 285 285 286 + static resource_size_t dw_hdma_v0_core_db_offset(struct dw_edma *dw) 287 + { 288 + /* Implement once the correct offset is known. */ 289 + return ~0; 290 + } 291 + 286 292 static const struct dw_edma_core_ops dw_hdma_v0_core = { 287 293 .off = dw_hdma_v0_core_off, 288 294 .ch_count = dw_hdma_v0_core_ch_count, ··· 297 291 .start = dw_hdma_v0_core_start, 298 292 .ch_config = dw_hdma_v0_core_ch_config, 299 293 .debugfs_on = dw_hdma_v0_core_debugfs_on, 294 + .db_offset = dw_hdma_v0_core_db_offset, 300 295 }; 301 296 302 297 void dw_hdma_v0_core_register(struct dw_edma *dw)