Skip to content

Commit

Permalink
drivers: intc: plic: convert trigger type to use Kconfig
Browse files Browse the repository at this point in the history
Convert the compilation of the trigger type feature to depend
on Kconfig, following the same pattern of software-triggered
interrupt.

Signed-off-by: Yong Cong Sin <[email protected]>
Signed-off-by: Yong Cong Sin <[email protected]>
  • Loading branch information
ycsin authored and aescolar committed Oct 9, 2024
1 parent 65fb61b commit 9109cfe
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 28 deletions.
31 changes: 31 additions & 0 deletions drivers/interrupt_controller/Kconfig.plic
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,37 @@ config PLIC_SUPPORTS_SOFT_INTERRUPT
help
Enabled when the PLIC supports software-triggered interrupts.

config PLIC_SUPPORTS_TRIG_TYPE
bool
default y
depends on DT_HAS_ANDESTECH_NCEPLIC100_ENABLED
help
Enabled when the PLIC supports multiple trigger types,
such as level, edge, etc.

if PLIC_SUPPORTS_TRIG_TYPE

config PLIC_TRIG_TYPE_REG_OFFSET
hex "Trigger type register offset"
default 0x1080 if DT_HAS_ANDESTECH_NCEPLIC100_ENABLED
help
Offset to the 'trigger type' register.

config PLIC_TRIG_TYPE_BITWIDTH
int "Trigger type bitwidth"
default 1
help
Number of bits required to differentiate between the trigger types.

config PLIC_SUPPORTS_TRIG_EDGE
bool
default y
depends on DT_HAS_ANDESTECH_NCEPLIC100_ENABLED
help
Enabled when the PLIC supports edge-triggered interrupt.

endif # PLIC_SUPPORTS_TRIG_TYPE

config PLIC_IRQ_AFFINITY
bool "Configure IRQ affinity"
depends on SMP
Expand Down
47 changes: 19 additions & 28 deletions drivers/interrupt_controller/intc_plic.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,16 @@
#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
* in Linux's SiFive PLIC driver
*/
#ifdef CONFIG_PLIC_SUPPORTS_TRIG_TYPE
#define PLIC_TRIG_LEVEL ((uint32_t)0)
#define PLIC_TRIG_EDGE ((uint32_t)1)
#define PLIC_DRV_HAS_COMPAT(compat) \
DT_NODE_HAS_COMPAT(DT_COMPAT_GET_ANY_STATUS_OKAY(DT_DRV_COMPAT), compat)

#if PLIC_DRV_HAS_COMPAT(andestech_nceplic100)
#define PLIC_SUPPORTS_TRIG_TYPE 1
#define PLIC_REG_TRIG_TYPE_WIDTH 1
#define PLIC_REG_TRIG_TYPE_OFFSET 0x1080
#else
/* Trigger-type not supported */
#define PLIC_REG_TRIG_TYPE_WIDTH 0
#endif
#endif /* CONFIG_PLIC_SUPPORTS_TRIG_TYPE */

/* PLIC registers are 32-bit memory-mapped */
#define PLIC_REG_SIZE 32
Expand Down Expand Up @@ -91,7 +83,9 @@ struct plic_config {
#ifdef CONFIG_PLIC_SUPPORTS_SOFT_INTERRUPT
mem_addr_t pend;
#endif /* CONFIG_PLIC_SUPPORTS_SOFT_INTERRUPT */
#ifdef CONFIG_PLIC_SUPPORTS_TRIG_TYPE
mem_addr_t trig;
#endif /* CONFIG_PLIC_SUPPORTS_TRIG_TYPE */
uint32_t max_prio;
/* Number of IRQs that the PLIC physically supports */
uint32_t riscv_ndev;
Expand Down Expand Up @@ -233,6 +227,7 @@ static inline const struct device *get_plic_dev_from_irq(uint32_t irq)
#endif
}

#ifdef CONFIG_PLIC_SUPPORTS_TRIG_TYPE
/**
* @brief Return the value of the trigger type register for the IRQ
*
Expand All @@ -245,18 +240,15 @@ static inline const struct device *get_plic_dev_from_irq(uint32_t irq)
*
* @return Trigger type register value if PLIC supports trigger type, PLIC_TRIG_LEVEL otherwise
*/
static uint32_t __maybe_unused riscv_plic_irq_trig_val(const struct device *dev, uint32_t local_irq)
static uint32_t riscv_plic_irq_trig_val(const struct device *dev, uint32_t local_irq)
{
if (!IS_ENABLED(PLIC_SUPPORTS_TRIG_TYPE)) {
return PLIC_TRIG_LEVEL;
}

const struct plic_config *config = dev->config;
mem_addr_t trig_addr = config->trig + local_irq_to_reg_offset(local_irq);
uint32_t offset = local_irq * PLIC_REG_TRIG_TYPE_WIDTH;
uint32_t offset = local_irq * CONFIG_PLIC_TRIG_TYPE_BITWIDTH;

return sys_read32(trig_addr) & GENMASK(offset + PLIC_REG_TRIG_TYPE_WIDTH - 1, offset);
return sys_read32(trig_addr) & GENMASK(offset + CONFIG_PLIC_TRIG_TYPE_BITWIDTH - 1, offset);
}
#endif /* CONFIG_PLIC_SUPPORTS_TRIG_TYPE */

static void plic_irq_enable_set_state(uint32_t irq, bool enable)
{
Expand Down Expand Up @@ -493,7 +485,6 @@ static void plic_irq_handler(const struct device *dev)
const struct plic_config *config = dev->config;
mem_addr_t claim_complete_addr = get_claim_complete_addr(dev);
struct _isr_table_entry *ite;
uint32_t __maybe_unused trig_val;
uint32_t cpu_id = arch_proc_id();
/* Get the IRQ number generating the interrupt */
const uint32_t local_irq = sys_read32(claim_complete_addr);
Expand Down Expand Up @@ -540,16 +531,16 @@ static void plic_irq_handler(const struct device *dev)
z_irq_spurious(NULL);
}

#if PLIC_DRV_HAS_COMPAT(andestech_nceplic100)
trig_val = riscv_plic_irq_trig_val(dev, local_irq);
#ifdef CONFIG_PLIC_SUPPORTS_TRIG_EDGE
uint32_t trig_val = riscv_plic_irq_trig_val(dev, local_irq);
/*
* Edge-triggered interrupts on Andes NCEPLIC100 have to be acknowledged first before
* Edge-triggered interrupts have to be acknowledged first before
* getting handled so that we don't miss on the next edge-triggered interrupt.
*/
if (trig_val == PLIC_TRIG_EDGE) {
sys_write32(local_irq, claim_complete_addr);
}
#endif
#endif /* CONFIG_PLIC_SUPPORTS_TRIG_EDGE */

/* Call the corresponding IRQ handler in _sw_isr_table */
ite = &config->isr_table[local_irq];
Expand All @@ -560,14 +551,14 @@ static void plic_irq_handler(const struct device *dev)
* PLIC controller that the IRQ has been handled
* for level triggered interrupts.
*/
#if PLIC_DRV_HAS_COMPAT(andestech_nceplic100)
/* For NCEPLIC100, handle only if level-triggered */
#ifdef CONFIG_PLIC_SUPPORTS_TRIG_EDGE
/* Handle only if level-triggered */
if (trig_val == PLIC_TRIG_LEVEL) {
sys_write32(local_irq, claim_complete_addr);
}
#else
sys_write32(local_irq, claim_complete_addr);
#endif
#endif /* #ifdef CONFIG_PLIC_SUPPORTS_TRIG_EDGE */
}

/**
Expand Down Expand Up @@ -911,8 +902,8 @@ SHELL_CMD_REGISTER(plic, &plic_cmds, "PLIC shell commands", NULL);
.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,)) \
IF_ENABLED(CONFIG_PLIC_SUPPORTS_TRIG_TYPE, \
(.trig = PLIC_BASE_ADDR(n) + CONFIG_PLIC_TRIG_TYPE_REG_OFFSET,)) \
.max_prio = DT_INST_PROP(n, riscv_max_priority), \
.riscv_ndev = DT_INST_PROP(n, riscv_ndev), \
.nr_irqs = PLIC_MIN_IRQ_NUM(n), \
Expand Down

0 comments on commit 9109cfe

Please sign in to comment.