drivers: intc: plic: implement software-generated interrupt
Implement `riscv_plic_irq_set_pending()` to trigger a software-generated interrupt. The "4. Interrupt Pending Bits" of the riscv-plic specs described the reading of the pending bits, but not the writing Since not all PLIC implementations support software-generated interrupt, the function is compiled only when `CONFIG_PLIC_SUPPORTS_SOFT_INTERRUPT` is enabled on PLIC that supports it, such as the Andes' NCEPLIC100. Signed-off-by: Yong Cong Sin <ycsin@meta.com> Signed-off-by: Yong Cong Sin <yongcong.sin@gmail.com>
This commit is contained in:
parent
0cecb2c9af
commit
65fb61bc68
@ -13,6 +13,13 @@ config PLIC
|
||||
|
||||
if PLIC
|
||||
|
||||
config PLIC_SUPPORTS_SOFT_INTERRUPT
|
||||
bool
|
||||
default y
|
||||
depends on DT_HAS_ANDESTECH_NCEPLIC100_ENABLED
|
||||
help
|
||||
Enabled when the PLIC supports software-triggered interrupts.
|
||||
|
||||
config PLIC_IRQ_AFFINITY
|
||||
bool "Configure IRQ affinity"
|
||||
depends on SMP
|
||||
|
||||
@ -39,6 +39,7 @@
|
||||
#define CONTEXT_CLAIM 0x04
|
||||
#define CONTEXT_ENABLE_BASE 0x2000
|
||||
#define CONTEXT_ENABLE_SIZE 0x80
|
||||
#define CONTEXT_PENDING_BASE 0x1000
|
||||
/*
|
||||
* Trigger type is mentioned, but not defined in the RISCV PLIC specs.
|
||||
* However, it is defined and supported by at least the Andes & Telink datasheet, and supported
|
||||
@ -87,6 +88,9 @@ struct plic_config {
|
||||
mem_addr_t prio;
|
||||
mem_addr_t irq_en;
|
||||
mem_addr_t reg;
|
||||
#ifdef CONFIG_PLIC_SUPPORTS_SOFT_INTERRUPT
|
||||
mem_addr_t pend;
|
||||
#endif /* CONFIG_PLIC_SUPPORTS_SOFT_INTERRUPT */
|
||||
mem_addr_t trig;
|
||||
uint32_t max_prio;
|
||||
/* Number of IRQs that the PLIC physically supports */
|
||||
@ -204,6 +208,15 @@ static ALWAYS_INLINE uint32_t local_irq_to_irq(const struct device *dev, uint32_
|
||||
return irq_to_level_2(local_irq) | config->irq;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PLIC_SUPPORTS_SOFT_INTERRUPT
|
||||
static inline mem_addr_t get_pending_reg(const struct device *dev, uint32_t local_irq)
|
||||
{
|
||||
const struct plic_config *config = dev->config;
|
||||
|
||||
return config->pend + local_irq_to_reg_offset(local_irq);
|
||||
}
|
||||
#endif /* CONFIG_PLIC_SUPPORTS_SOFT_INTERRUPT */
|
||||
|
||||
/**
|
||||
* @brief Determine the PLIC device from the IRQ
|
||||
*
|
||||
@ -358,6 +371,19 @@ void riscv_plic_set_priority(uint32_t irq, uint32_t priority)
|
||||
sys_write32(priority, prio_addr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PLIC_SUPPORTS_SOFT_INTERRUPT
|
||||
void riscv_plic_irq_set_pending(uint32_t irq)
|
||||
{
|
||||
const struct device *dev = get_plic_dev_from_irq(irq);
|
||||
const uint32_t local_irq = irq_from_level_2(irq);
|
||||
mem_addr_t pend_addr = get_pending_reg(dev, local_irq);
|
||||
uint32_t pend_value = sys_read32(pend_addr);
|
||||
|
||||
WRITE_BIT(pend_value, local_irq & PLIC_REG_MASK, true);
|
||||
sys_write32(pend_value, pend_addr);
|
||||
}
|
||||
#endif /* CONFIG_PLIC_SUPPORTS_SOFT_INTERRUPT */
|
||||
|
||||
/**
|
||||
* @brief Get riscv PLIC-specific interrupt line causing an interrupt
|
||||
*
|
||||
@ -883,6 +909,8 @@ SHELL_CMD_REGISTER(plic, &plic_cmds, "PLIC shell commands", NULL);
|
||||
.prio = PLIC_BASE_ADDR(n), \
|
||||
.irq_en = PLIC_BASE_ADDR(n) + CONTEXT_ENABLE_BASE, \
|
||||
.reg = PLIC_BASE_ADDR(n) + CONTEXT_BASE, \
|
||||
IF_ENABLED(CONFIG_PLIC_SUPPORTS_SOFT_INTERRUPT, \
|
||||
(.pend = PLIC_BASE_ADDR(n) + CONTEXT_PENDING_BASE,)) \
|
||||
IF_ENABLED(PLIC_SUPPORTS_TRIG_TYPE, \
|
||||
(.trig = PLIC_BASE_ADDR(n) + PLIC_REG_TRIG_TYPE_OFFSET,)) \
|
||||
.max_prio = DT_INST_PROP(n, riscv_max_priority), \
|
||||
|
||||
@ -54,6 +54,13 @@ void riscv_plic_set_priority(uint32_t irq, uint32_t prio);
|
||||
*/
|
||||
int riscv_plic_irq_set_affinity(uint32_t irq, uint32_t cpumask);
|
||||
|
||||
/**
|
||||
* @brief Set interrupt as pending
|
||||
*
|
||||
* @param irq Multi-level encoded interrupt ID
|
||||
*/
|
||||
void riscv_plic_irq_set_pending(uint32_t irq);
|
||||
|
||||
/**
|
||||
* @brief Get active interrupt ID
|
||||
*
|
||||
|
||||
Loading…
Reference in New Issue
Block a user