diff --git a/include/irq.h b/include/irq.h index 3dcec83ea95..9a513cc0ac8 100644 --- a/include/irq.h +++ b/include/irq.h @@ -252,6 +252,104 @@ void z_smp_global_unlock(unsigned int key); #define irq_unlock(key) arch_irq_unlock(key) #endif +/** + * @brief Return IRQ level + * @def irq_get_level() + * + * This routine returns the interrupt level number of the provided interrupt. + * + * @param irq IRQ number in its zephyr format + * + * @return 1 if IRQ level 1, 2 if IRQ level 2, 3 if IRQ level 3 + */ +static inline unsigned int irq_get_level(unsigned int irq) +{ +#if defined(CONFIG_3RD_LEVEL_INTERRUPTS) + return ((irq >> 16) & 0xFF) != 0 ? 3 : + (((irq >> 8) & 0xFF) == 0 ? 1 : 2); +#elif defined(CONFIG_2ND_LEVEL_INTERRUPTS) + return ((irq >> 8) & 0xFF) == 0 ? 1 : 2; +#else + ARG_UNUSED(irq); + + return 1; +#endif +} + +#ifdef CONFIG_2ND_LEVEL_INTERRUPTS +/** + * @brief Return the 2nd level interrupt number + * @def irq_from_level_2() + * + * This routine returns the second level irq number of the zephyr irq + * number passed in + * + * @param irq IRQ number in its zephyr format + * + * @return 2nd level IRQ number + */ +static inline unsigned int irq_from_level_2(unsigned int irq) +{ +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS + return ((irq >> 8) & 0xFF) - 1; +#else + return (irq >> 8) - 1; +#endif +} + +/** + * @brief Converts irq from level 1 to level 2 format + * @def irq_to_level_2() + * + * This routine converts the input into the level 2 irq number format + * + * @note Values >= 0xFF are invalid + * + * @param irq IRQ number in its zephyr format + * + * @return 2nd level IRQ number + */ +static inline unsigned int irq_to_level_2(unsigned int irq) +{ + return (irq + 1) << 8; +} +#endif + +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS +/** + * @brief Return the 3rd level interrupt number + * @def irq_from_level_3() + * + * This routine returns the third level irq number of the zephyr irq + * number passed in + * + * @param irq IRQ number in its zephyr format + * + * @return 3rd level IRQ number + */ +static inline unsigned int irq_from_level_3(unsigned int irq) +{ + return (irq >> 16) - 1; +} + +/** + * @brief Converts irq from level 1 to level 3 format + * @def irq_to_level_3() + * + * This routine converts the input into the level 3 irq number format + * + * @note Values >= 0xFF are invalid + * + * @param irq IRQ number in its zephyr format + * + * @return 3nd level IRQ number + */ +static inline unsigned int irq_to_level_3(unsigned int irq) +{ + return (irq + 1) << 16; +} +#endif + /** * @brief Enable an IRQ. * diff --git a/soc/riscv/riscv-privilege/common/soc_common_irq.c b/soc/riscv/riscv-privilege/common/soc_common_irq.c index ba33a25cc7d..6f4864f837e 100644 --- a/soc/riscv/riscv-privilege/common/soc_common_irq.c +++ b/soc/riscv/riscv-privilege/common/soc_common_irq.c @@ -11,30 +11,15 @@ */ #include -/** - * @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 arch_irq_enable(unsigned int irq) { u32_t mie; #if defined(CONFIG_RISCV_HAS_PLIC) - unsigned int level = _irq_level(irq); + unsigned int level = irq_get_level(irq); if (level == 2) { - irq = _level2_irq(irq); + irq = irq_from_level_2(irq); riscv_plic_irq_enable(irq); return; } @@ -54,10 +39,10 @@ void arch_irq_disable(unsigned int irq) u32_t mie; #if defined(CONFIG_RISCV_HAS_PLIC) - unsigned int level = _irq_level(irq); + unsigned int level = irq_get_level(irq); if (level == 2) { - irq = _level2_irq(irq); + irq = irq_from_level_2(irq); riscv_plic_irq_disable(irq); return; } @@ -75,10 +60,10 @@ void arch_irq_disable(unsigned int irq) void arch_irq_priority_set(unsigned int irq, unsigned int prio) { #if defined(CONFIG_RISCV_HAS_PLIC) - unsigned int level = _irq_level(irq); + unsigned int level = irq_get_level(irq); if (level == 2) { - irq = _level2_irq(irq); + irq = irq_from_level_2(irq); riscv_plic_set_priority(irq, prio); } #endif @@ -91,10 +76,10 @@ int arch_irq_is_enabled(unsigned int irq) u32_t mie; #if defined(CONFIG_RISCV_HAS_PLIC) - unsigned int level = _irq_level(irq); + unsigned int level = irq_get_level(irq); if (level == 2) { - irq = _level2_irq(irq); + irq = irq_from_level_2(irq); return riscv_plic_irq_is_enabled(irq); } #endif