interrupt: Convert RISC-V plic to use multi-level irq support

Utilize the multi-level irq infrastructure and replace custom handling
for PLIC on riscv-privilege SoCs.  The old code offset IRQs in drivers
and various places with RISCV_MAX_GENERIC_IRQ.  Instead utilize Zephyr's
encoded IRQ and replace offsets in drivers with the IRQ define from DTS.

Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
This commit is contained in:
Kumar Gala 2019-08-08 23:01:37 -05:00 committed by Kumar Gala
parent d16b9c37af
commit 95f78bcacf
10 changed files with 121 additions and 67 deletions

View file

@ -68,8 +68,7 @@ static void gpio_sifive_irq_handler(void *arg)
int pin_mask;
/* Get the pin number generating the interrupt */
pin_mask = 1 << (riscv_plic_get_irq() -
(cfg->gpio_irq_base - RISCV_MAX_GENERIC_IRQ));
pin_mask = 1 << (riscv_plic_get_irq() - cfg->gpio_irq_base);
/* Call the corresponding callback registered for the pin */
gpio_fire_callbacks(&data->cb, dev, pin_mask);
@ -375,7 +374,7 @@ static void gpio_sifive_cfg_0(void);
static const struct gpio_sifive_config gpio_sifive_config0 = {
.gpio_base_addr = DT_INST_0_SIFIVE_GPIO0_BASE_ADDRESS,
.gpio_irq_base = RISCV_MAX_GENERIC_IRQ + DT_INST_0_SIFIVE_GPIO0_IRQ_0,
.gpio_irq_base = DT_INST_0_SIFIVE_GPIO0_IRQ_0,
.gpio_cfg_func = gpio_sifive_cfg_0,
};
@ -388,7 +387,7 @@ DEVICE_AND_API_INIT(gpio_sifive_0, DT_INST_0_SIFIVE_GPIO0_LABEL,
&gpio_sifive_driver);
#define IRQ_INIT(n) \
IRQ_CONNECT(RISCV_MAX_GENERIC_IRQ + DT_INST_0_SIFIVE_GPIO0_IRQ_##n, \
IRQ_CONNECT(DT_INST_0_SIFIVE_GPIO0_IRQ_##n, \
CONFIG_GPIO_SIFIVE_##n##_PRIORITY, \
gpio_sifive_irq_handler, \
DEVICE_GET(gpio_sifive_0), \

View file

@ -100,6 +100,8 @@ config PLIC
default y
depends on SOC_FAMILY_RISCV_PRIVILEGE
select RISCV_HAS_PLIC
select MULTI_LEVEL_INTERRUPTS
select 2ND_LEVEL_INTERRUPTS
help
Platform Level Interrupt Controller provides support
for external interrupt lines defined by the RISC-V SoC;

View file

@ -17,7 +17,7 @@
#include <sw_isr_table.h>
#define PLIC_IRQS (CONFIG_NUM_IRQS - RISCV_MAX_GENERIC_IRQ)
#define PLIC_IRQS (CONFIG_NUM_IRQS - CONFIG_2ND_LVL_ISR_TBL_OFFSET)
#define PLIC_EN_SIZE ((PLIC_IRQS >> 5) + 1)
struct plic_regs_t {
@ -34,8 +34,7 @@ static int save_irq;
* This routine enables a RISCV PLIC-specific interrupt line.
* riscv_plic_irq_enable is called by SOC_FAMILY_RISCV_PRIVILEGE
* z_arch_irq_enable function to enable external interrupts for
* IRQS > RISCV_MAX_GENERIC_IRQ, whenever CONFIG_RISCV_HAS_PLIC
* variable is set.
* IRQS level == 2, whenever CONFIG_RISCV_HAS_PLIC variable is set.
* @param irq IRQ number to enable
*
* @return N/A
@ -43,13 +42,12 @@ static int save_irq;
void riscv_plic_irq_enable(u32_t irq)
{
u32_t key;
u32_t plic_irq = irq - RISCV_MAX_GENERIC_IRQ;
volatile u32_t *en =
(volatile u32_t *)DT_INST_0_SIFIVE_PLIC_1_0_0_IRQ_EN_BASE_ADDRESS;
key = irq_lock();
en += (plic_irq >> 5);
*en |= (1 << (plic_irq & 31));
en += (irq >> 5);
*en |= (1 << (irq & 31));
irq_unlock(key);
}
@ -60,8 +58,7 @@ void riscv_plic_irq_enable(u32_t irq)
* This routine disables a RISCV PLIC-specific interrupt line.
* riscv_plic_irq_disable is called by SOC_FAMILY_RISCV_PRIVILEGE
* z_arch_irq_disable function to disable external interrupts, for
* IRQS > RISCV_MAX_GENERIC_IRQ, whenever CONFIG_RISCV_HAS_PLIC
* variable is set.
* IRQS level == 2, whenever CONFIG_RISCV_HAS_PLIC variable is set.
* @param irq IRQ number to disable
*
* @return N/A
@ -69,13 +66,12 @@ void riscv_plic_irq_enable(u32_t irq)
void riscv_plic_irq_disable(u32_t irq)
{
u32_t key;
u32_t plic_irq = irq - RISCV_MAX_GENERIC_IRQ;
volatile u32_t *en =
(volatile u32_t *)DT_INST_0_SIFIVE_PLIC_1_0_0_IRQ_EN_BASE_ADDRESS;
key = irq_lock();
en += (plic_irq >> 5);
*en &= ~(1 << (plic_irq & 31));
en += (irq >> 5);
*en &= ~(1 << (irq & 31));
irq_unlock(key);
}
@ -92,10 +88,9 @@ int riscv_plic_irq_is_enabled(u32_t irq)
{
volatile u32_t *en =
(volatile u32_t *)DT_INST_0_SIFIVE_PLIC_1_0_0_IRQ_EN_BASE_ADDRESS;
u32_t plic_irq = irq - RISCV_MAX_GENERIC_IRQ;
en += (plic_irq >> 5);
return !!(*en & (1 << (plic_irq & 31)));
en += (irq >> 5);
return !!(*en & (1 << (irq & 31)));
}
/**
@ -103,7 +98,7 @@ int riscv_plic_irq_is_enabled(u32_t irq)
* @brief Set priority of a riscv PLIC-specific interrupt line
*
* This routine set the priority of a RISCV PLIC-specific interrupt line.
* riscv_plic_irq_set_prio is called by riscv Z_ARCH_IRQ_CONNECT to set
* riscv_plic_irq_set_prio is called by riscv z_arch_irq_priority_set to set
* the priority of an interrupt whenever CONFIG_RISCV_HAS_PLIC variable is set.
* @param irq IRQ number for which to set priority
*
@ -114,14 +109,10 @@ void riscv_plic_set_priority(u32_t irq, u32_t priority)
volatile u32_t *prio =
(volatile u32_t *)DT_INST_0_SIFIVE_PLIC_1_0_0_PRIO_BASE_ADDRESS;
/* Can set priority only for PLIC-specific interrupt line */
if (irq <= RISCV_MAX_GENERIC_IRQ)
return;
if (priority > DT_INST_0_SIFIVE_PLIC_1_0_0_RISCV_MAX_PRIORITY)
priority = DT_INST_0_SIFIVE_PLIC_1_0_0_RISCV_MAX_PRIORITY;
prio += (irq - RISCV_MAX_GENERIC_IRQ);
prio += irq;
*prio = priority;
}
@ -166,7 +157,7 @@ static void plic_irq_handler(void *arg)
if (irq == 0U || irq >= PLIC_IRQS)
z_irq_spurious(NULL);
irq += RISCV_MAX_GENERIC_IRQ;
irq += CONFIG_2ND_LVL_ISR_TBL_OFFSET;
/* Call the corresponding IRQ handler in _sw_isr_table */
ite = (struct _isr_table_entry *)&_sw_isr_table[irq];

View file

@ -400,12 +400,12 @@ DEVICE_AND_API_INIT(uart_sifive_0, DT_INST_0_SIFIVE_UART0_LABEL,
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
static void uart_sifive_irq_cfg_func_0(void)
{
IRQ_CONNECT(RISCV_MAX_GENERIC_IRQ + DT_INST_0_SIFIVE_UART0_IRQ_0,
IRQ_CONNECT(DT_INST_0_SIFIVE_UART0_IRQ_0,
CONFIG_UART_SIFIVE_PORT_0_IRQ_PRIORITY,
uart_sifive_irq_handler, DEVICE_GET(uart_sifive_0),
0);
irq_enable(RISCV_MAX_GENERIC_IRQ + DT_INST_0_SIFIVE_UART0_IRQ_0);
irq_enable(DT_INST_0_SIFIVE_UART0_IRQ_0);
}
#endif
@ -439,12 +439,12 @@ DEVICE_AND_API_INIT(uart_sifive_1, DT_INST_1_SIFIVE_UART0_LABEL,
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
static void uart_sifive_irq_cfg_func_1(void)
{
IRQ_CONNECT(RISCV_MAX_GENERIC_IRQ + DT_INST_1_SIFIVE_UART0_IRQ_0,
IRQ_CONNECT(DT_INST_1_SIFIVE_UART0_IRQ_0,
CONFIG_UART_SIFIVE_PORT_1_IRQ_PRIORITY,
uart_sifive_irq_handler, DEVICE_GET(uart_sifive_1),
0);
irq_enable(RISCV_MAX_GENERIC_IRQ + DT_INST_1_SIFIVE_UART0_IRQ_0);
irq_enable(DT_INST_1_SIFIVE_UART0_IRQ_0);
}
#endif

View file

@ -66,6 +66,7 @@ extern u32_t __soc_get_irq(void);
void z_arch_irq_enable(unsigned int irq);
void z_arch_irq_disable(unsigned int irq);
int z_arch_irq_is_enabled(unsigned int irq);
void z_arch_irq_priority_set(unsigned int irq, unsigned int prio);
void z_irq_spurious(void *unused);
@ -86,7 +87,7 @@ void z_irq_spurious(void *unused);
#define Z_ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \
({ \
Z_ISR_DECLARE(irq_p, 0, isr_p, isr_param_p); \
riscv_plic_set_priority(irq_p, priority_p); \
z_arch_irq_priority_set(irq_p, priority_p); \
irq_p; \
})
#else

View file

@ -17,8 +17,6 @@
#define RISCV_MACHINE_TIMER_IRQ 7 /* Machine Timer Interrupt */
#define RISCV_MACHINE_EXT_IRQ 11 /* Machine External Interrupt */
#define RISCV_MAX_GENERIC_IRQ 11 /* Max Generic Interrupt */
/* Exception numbers */
#define RISCV_MACHINE_ECALL_EXP 11 /* Machine ECALL instruction */

View file

@ -11,12 +11,30 @@
*/
#include <irq.h>
/**
* @brief Get an IRQ's level
* @param irq The IRQ number in the Zephyr irq.h numbering system
* @return IRQ level, either 1 or 2
*/
static inline unsigned int _irq_level(unsigned int irq)
{
return ((irq >> 8) & 0xff) == 0U ? 1 : 2;
}
static inline unsigned int _level2_irq(unsigned int irq)
{
return (irq >> 8) - 1;
}
void z_arch_irq_enable(unsigned int irq)
{
u32_t mie;
#if defined(CONFIG_RISCV_HAS_PLIC)
if (irq > RISCV_MAX_GENERIC_IRQ) {
unsigned int level = _irq_level(irq);
if (level == 2) {
irq = _level2_irq(irq);
riscv_plic_irq_enable(irq);
return;
}
@ -36,7 +54,10 @@ void z_arch_irq_disable(unsigned int irq)
u32_t mie;
#if defined(CONFIG_RISCV_HAS_PLIC)
if (irq > RISCV_MAX_GENERIC_IRQ) {
unsigned int level = _irq_level(irq);
if (level == 2) {
irq = _level2_irq(irq);
riscv_plic_irq_disable(irq);
return;
}
@ -51,13 +72,31 @@ void z_arch_irq_disable(unsigned int irq)
: "r" (1 << irq));
};
void z_arch_irq_priority_set(unsigned int irq, unsigned int prio)
{
#if defined(CONFIG_RISCV_HAS_PLIC)
unsigned int level = _irq_level(irq);
if (level == 2) {
irq = _level2_irq(irq);
riscv_plic_set_priority(irq, prio);
}
#endif
return ;
}
int z_arch_irq_is_enabled(unsigned int irq)
{
u32_t mie;
#if defined(CONFIG_RISCV_HAS_PLIC)
if (irq > RISCV_MAX_GENERIC_IRQ)
unsigned int level = _irq_level(irq);
if (level == 2) {
irq = _level2_irq(irq);
return riscv_plic_irq_is_enabled(irq);
}
#endif
__asm__ volatile ("csrr %0, mie" : "=r" (mie));

View file

@ -22,6 +22,18 @@ config RISCV_HAS_PLIC
bool
default y
config 2ND_LVL_ISR_TBL_OFFSET
int
default 12
config 2ND_LVL_INTR_00_OFFSET
int
default 11
config MAX_IRQ_PER_AGGREGATOR
int
default 30
config NUM_IRQS
int
default 42

View file

@ -8,38 +8,38 @@
#include <generated_dts_board.h>
/* GPIO Interrupts */
#define MIV_GPIO_0_IRQ (RISCV_MAX_GENERIC_IRQ + 0)
#define MIV_GPIO_1_IRQ (RISCV_MAX_GENERIC_IRQ + 1)
#define MIV_GPIO_2_IRQ (RISCV_MAX_GENERIC_IRQ + 2)
#define MIV_GPIO_3_IRQ (RISCV_MAX_GENERIC_IRQ + 3)
#define MIV_GPIO_4_IRQ (RISCV_MAX_GENERIC_IRQ + 4)
#define MIV_GPIO_5_IRQ (RISCV_MAX_GENERIC_IRQ + 5)
#define MIV_GPIO_6_IRQ (RISCV_MAX_GENERIC_IRQ + 6)
#define MIV_GPIO_7_IRQ (RISCV_MAX_GENERIC_IRQ + 7)
#define MIV_GPIO_8_IRQ (RISCV_MAX_GENERIC_IRQ + 8)
#define MIV_GPIO_9_IRQ (RISCV_MAX_GENERIC_IRQ + 9)
#define MIV_GPIO_10_IRQ (RISCV_MAX_GENERIC_IRQ + 10)
#define MIV_GPIO_11_IRQ (RISCV_MAX_GENERIC_IRQ + 11)
#define MIV_GPIO_12_IRQ (RISCV_MAX_GENERIC_IRQ + 12)
#define MIV_GPIO_13_IRQ (RISCV_MAX_GENERIC_IRQ + 13)
#define MIV_GPIO_14_IRQ (RISCV_MAX_GENERIC_IRQ + 14)
#define MIV_GPIO_15_IRQ (RISCV_MAX_GENERIC_IRQ + 15)
#define MIV_GPIO_16_IRQ (RISCV_MAX_GENERIC_IRQ + 16)
#define MIV_GPIO_17_IRQ (RISCV_MAX_GENERIC_IRQ + 17)
#define MIV_GPIO_18_IRQ (RISCV_MAX_GENERIC_IRQ + 18)
#define MIV_GPIO_19_IRQ (RISCV_MAX_GENERIC_IRQ + 19)
#define MIV_GPIO_20_IRQ (RISCV_MAX_GENERIC_IRQ + 20)
#define MIV_GPIO_21_IRQ (RISCV_MAX_GENERIC_IRQ + 21)
#define MIV_GPIO_22_IRQ (RISCV_MAX_GENERIC_IRQ + 22)
#define MIV_GPIO_23_IRQ (RISCV_MAX_GENERIC_IRQ + 23)
#define MIV_GPIO_24_IRQ (RISCV_MAX_GENERIC_IRQ + 24)
#define MIV_GPIO_25_IRQ (RISCV_MAX_GENERIC_IRQ + 25)
#define MIV_GPIO_26_IRQ (RISCV_MAX_GENERIC_IRQ + 26)
#define MIV_GPIO_27_IRQ (RISCV_MAX_GENERIC_IRQ + 27)
#define MIV_GPIO_28_IRQ (RISCV_MAX_GENERIC_IRQ + 28)
#define MIV_GPIO_29_IRQ (RISCV_MAX_GENERIC_IRQ + 29)
#define MIV_GPIO_30_IRQ (RISCV_MAX_GENERIC_IRQ + 30)
#define MIV_GPIO_31_IRQ (RISCV_MAX_GENERIC_IRQ + 31)
#define MIV_GPIO_0_IRQ (0)
#define MIV_GPIO_1_IRQ (1)
#define MIV_GPIO_2_IRQ (2)
#define MIV_GPIO_3_IRQ (3)
#define MIV_GPIO_4_IRQ (4)
#define MIV_GPIO_5_IRQ (5)
#define MIV_GPIO_6_IRQ (6)
#define MIV_GPIO_7_IRQ (7)
#define MIV_GPIO_8_IRQ (8)
#define MIV_GPIO_9_IRQ (9)
#define MIV_GPIO_10_IRQ (10)
#define MIV_GPIO_11_IRQ (11)
#define MIV_GPIO_12_IRQ (12)
#define MIV_GPIO_13_IRQ (13)
#define MIV_GPIO_14_IRQ (14)
#define MIV_GPIO_15_IRQ (15)
#define MIV_GPIO_16_IRQ (16)
#define MIV_GPIO_17_IRQ (17)
#define MIV_GPIO_18_IRQ (18)
#define MIV_GPIO_19_IRQ (19)
#define MIV_GPIO_20_IRQ (20)
#define MIV_GPIO_21_IRQ (21)
#define MIV_GPIO_22_IRQ (22)
#define MIV_GPIO_23_IRQ (23)
#define MIV_GPIO_24_IRQ (24)
#define MIV_GPIO_25_IRQ (25)
#define MIV_GPIO_26_IRQ (26)
#define MIV_GPIO_27_IRQ (27)
#define MIV_GPIO_28_IRQ (28)
#define MIV_GPIO_29_IRQ (29)
#define MIV_GPIO_30_IRQ (30)
#define MIV_GPIO_31_IRQ (31)
/* UART Configuration */
#define MIV_UART_0_LINECFG 0x1

View file

@ -22,6 +22,18 @@ config RISCV_HAS_PLIC
bool
default y
config 2ND_LVL_ISR_TBL_OFFSET
int
default 12
config 2ND_LVL_INTR_00_OFFSET
int
default 11
config MAX_IRQ_PER_AGGREGATOR
int
default 52
config NUM_IRQS
int
default 64