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:
parent
29ee9aacb3
commit
779d4af3e9
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user