drivers: interrupt_controller: plic: support edge triggered interrupts

This adds a check and option for edge triggered interrupts

Signed-off-by: Joshua Lilly <jgl@meta.com>
This commit is contained in:
Joshua Lilly 2023-07-26 09:50:10 -07:00 committed by Carles Cufí
commit 67268f5cbd
3 changed files with 50 additions and 2 deletions

View file

@ -10,3 +10,9 @@ config PLIC
help
Platform Level Interrupt Controller provides support
for external interrupt lines defined by the RISC-V SoC.
config PLIC_SUPPORTS_EDGE_IRQ
bool "The given interrupt controller supports edge interrupts"
help
The given interrupt controller supports edge triggered
interrupts.

View file

@ -29,6 +29,9 @@
#define PLIC_IRQS (CONFIG_NUM_IRQS - CONFIG_2ND_LVL_ISR_TBL_OFFSET)
#define PLIC_EN_SIZE ((PLIC_IRQS >> 5) + 1)
#define PLIC_EDGE_TRIG_TYPE (PLIC_MAX_PRIO + DT_INST_PROP(0, riscv_trigger_reg_offset))
#define PLIC_EDGE_TRIG_SHIFT 5
struct plic_regs_t {
uint32_t threshold_prio;
uint32_t claim_complete;
@ -36,6 +39,28 @@ struct plic_regs_t {
static int save_irq;
/**
* @brief return edge irq value or zero
*
* In the event edge irq is enable this will return the trigger
* value of the irq. In the event edge irq is not supported this
* routine will return 0
*
* @param irq IRQ number to add to the trigger
*
* @return irq value when enabled 0 otherwise
*/
static int riscv_plic_is_edge_irq(uint32_t irq)
{
if (IS_ENABLED(CONFIG_PLIC_SUPPORTS_EDGE_IRQ)) {
volatile uint32_t *trig = (volatile uint32_t *)PLIC_EDGE_TRIG_TYPE;
trig += (irq >> PLIC_EDGE_TRIG_SHIFT);
return *trig & BIT(irq);
}
return 0;
}
/**
* @brief Enable a riscv PLIC-specific interrupt line
*
@ -135,6 +160,7 @@ static void plic_irq_handler(const void *arg)
uint32_t irq;
struct _isr_table_entry *ite;
int edge_irq;
/* Get the IRQ number generating the interrupt */
irq = regs->claim_complete;
@ -154,6 +180,16 @@ static void plic_irq_handler(const void *arg)
if (irq == 0U || irq >= PLIC_IRQS)
z_irq_spurious(NULL);
edge_irq = riscv_plic_is_edge_irq(irq);
/*
* For edge triggered interrupts, write to the claim_complete register
* to indicate to the PLIC controller that the IRQ has been handled
* for edge triggered interrupts.
*/
if (edge_irq)
regs->claim_complete = save_irq;
irq += CONFIG_2ND_LVL_ISR_TBL_OFFSET;
/* Call the corresponding IRQ handler in _sw_isr_table */
@ -162,9 +198,11 @@ static void plic_irq_handler(const void *arg)
/*
* Write to claim_complete register to indicate to
* PLIC controller that the IRQ has been handled.
* PLIC controller that the IRQ has been handled
* for level triggered interrupts.
*/
regs->claim_complete = save_irq;
if (!edge_irq)
regs->claim_complete = save_irq;
}
/**

View file

@ -12,3 +12,7 @@ properties:
type: int
description: Number of external interrupts supported
required: true
riscv,trigger-reg-offset:
type: int
default: 4224
description: Offset of the trigger type register if supported