arch/risc-v/src/litex: Claim all pending PLIC interrupts.

Attempt to service all interrupts pending in the PLIC's claim register. Ideally, this is more efficient than switching context for each interrupt received.
This commit is contained in:
Stuart Ianna 2024-09-12 04:32:03 +00:00 committed by Xiang Xiao
parent 29ee9aacb3
commit 779d4af3e9

View File

@ -47,48 +47,38 @@
* riscv_dispatch_irq * riscv_dispatch_irq
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_LITEX_CORE_VEXRISCV_SMP
void *riscv_dispatch_irq(uintptr_t vector, uintreg_t *regs) void *riscv_dispatch_irq(uintptr_t vector, uintreg_t *regs)
{ {
#ifdef CONFIG_LITEX_CORE_VEXRISCV_SMP
int irq = (vector & 0x3f); int irq = (vector & 0x3f);
DEBUGASSERT(irq <= RISCV_IRQ_EXT);
if ((vector & RISCV_IRQ_BIT) != 0) if ((vector & RISCV_IRQ_BIT) != 0)
{ {
irq += RISCV_IRQ_ASYNC; irq += RISCV_IRQ_ASYNC;
} }
/* Firstly, check if the irq is machine external interrupt */ if (irq < RISCV_IRQ_EXT)
if (irq == RISCV_IRQ_EXT)
{ {
uint32_t ext = getreg32(LITEX_PLIC_CLAIM);
/* Add the value to nuttx irq which is offset to the ext */
irq = RISCV_IRQ_EXT + ext;
}
/* Acknowledge the interrupt */
riscv_ack_irq(irq);
/* EXT means no interrupt */
if (irq != RISCV_IRQ_EXT)
{
/* Deliver the IRQ */
regs = riscv_doirq(irq, regs); regs = riscv_doirq(irq, regs);
} }
else
if (irq > RISCV_IRQ_EXT)
{ {
/* Then write PLIC_CLAIM to clear pending in PLIC */ uint32_t ext = getreg32(LITEX_PLIC_CLAIM);
do
putreg32(irq - RISCV_IRQ_EXT, LITEX_PLIC_CLAIM); {
regs = riscv_doirq(RISCV_IRQ_EXT + ext, regs);
putreg32(ext, LITEX_PLIC_CLAIM);
ext = getreg32(LITEX_PLIC_CLAIM);
}
while (ext);
} }
return regs;
}
#else #else
void *riscv_dispatch_irq(uintptr_t vector, uintreg_t *regs)
{
int i; int i;
int irq = (vector >> RV_IRQ_MASK) | (vector & 0xf); int irq = (vector >> RV_IRQ_MASK) | (vector & 0xf);
@ -127,6 +117,6 @@ void *riscv_dispatch_irq(uintptr_t vector, uintreg_t *regs)
regs = riscv_doirq(irq, regs); regs = riscv_doirq(irq, regs);
#endif /* CONFIG_LITEX_CORE_VEXRISCV_SMP */
return regs; return regs;
} }
#endif