diff --git a/drivers/interrupt_controller/Kconfig.plic b/drivers/interrupt_controller/Kconfig.plic index 9613dda5082..7db7039efc5 100644 --- a/drivers/interrupt_controller/Kconfig.plic +++ b/drivers/interrupt_controller/Kconfig.plic @@ -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 diff --git a/drivers/interrupt_controller/intc_plic.c b/drivers/interrupt_controller/intc_plic.c index 9e701fd6133..1b958ce0eb5 100644 --- a/drivers/interrupt_controller/intc_plic.c +++ b/drivers/interrupt_controller/intc_plic.c @@ -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 @@ -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; @@ -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 * @@ -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) { @@ -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); @@ -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]; @@ -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 */ } /** @@ -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), \