Skip to content

Commit

Permalink
drivers: intc: plic: implement riscv_plic_irq_set_pending()
Browse files Browse the repository at this point in the history
Set a PLIC interrupt line as pending. For more info, see
"4. Interrupt Pending Bits" of the riscv-plic specs.

Signed-off-by: Yong Cong Sin <[email protected]>
Signed-off-by: Yong Cong Sin <[email protected]>
  • Loading branch information
ycsin committed Sep 18, 2024
1 parent 53f547b commit c1ca2ac
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 0 deletions.
21 changes: 21 additions & 0 deletions drivers/interrupt_controller/intc_plic.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -75,6 +76,7 @@ struct plic_config {
mem_addr_t prio;
mem_addr_t irq_en;
mem_addr_t reg;
mem_addr_t pend;
mem_addr_t trig;
uint32_t max_prio;
uint32_t num_irqs;
Expand Down Expand Up @@ -161,6 +163,13 @@ static inline mem_addr_t get_threshold_priority_addr(const struct device *dev, u
return config->reg + (get_hart_context(dev, hartid) * CONTEXT_SIZE);
}

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);
}

/**
* @brief Determine the PLIC device from the IRQ
*
Expand Down Expand Up @@ -302,6 +311,17 @@ void riscv_plic_set_priority(uint32_t irq, uint32_t priority)
sys_write32(priority, prio_addr);
}

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);
}

/**
* @brief Get riscv PLIC-specific interrupt line causing an interrupt
*
Expand Down Expand Up @@ -579,6 +599,7 @@ SHELL_CMD_ARG_REGISTER(plic, &plic_cmds, "PLIC shell commands",
.prio = PLIC_BASE_ADDR(n), \
.irq_en = PLIC_BASE_ADDR(n) + CONTEXT_ENABLE_BASE, \
.reg = PLIC_BASE_ADDR(n) + CONTEXT_BASE, \
.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), \
Expand Down
7 changes: 7 additions & 0 deletions include/zephyr/drivers/interrupt_controller/riscv_plic.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ int riscv_plic_irq_is_enabled(uint32_t irq);
*/
void riscv_plic_set_priority(uint32_t irq, uint32_t prio);

/**
* @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
*
Expand Down

0 comments on commit c1ca2ac

Please sign in to comment.