diff --git a/arch/common/sw_isr_common.c b/arch/common/sw_isr_common.c index a5262e7fa83d5a..a9c0a6df3d24de 100644 --- a/arch/common/sw_isr_common.c +++ b/arch/common/sw_isr_common.c @@ -7,6 +7,7 @@ #include #include #include +#include #include /* * Common code for arches that use software ISR tables (CONFIG_GEN_ISR_TABLES) diff --git a/arch/riscv/core/irq_manage.c b/arch/riscv/core/irq_manage.c index 88fafd34904964..f0a0eae2cd09db 100644 --- a/arch/riscv/core/irq_manage.c +++ b/arch/riscv/core/irq_manage.c @@ -8,6 +8,7 @@ #include #include #include +#include LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); diff --git a/drivers/gpio/gpio_sifive.c b/drivers/gpio/gpio_sifive.c index 440ad3f78ab79f..6288e60dd09d8b 100644 --- a/drivers/gpio/gpio_sifive.c +++ b/drivers/gpio/gpio_sifive.c @@ -17,6 +17,7 @@ #include #include #include +#include #include diff --git a/drivers/interrupt_controller/intc_nuclei_eclic.c b/drivers/interrupt_controller/intc_nuclei_eclic.c index 9f831e5653077f..7c112c1a63f24b 100644 --- a/drivers/interrupt_controller/intc_nuclei_eclic.c +++ b/drivers/interrupt_controller/intc_nuclei_eclic.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff --git a/include/zephyr/irq.h b/include/zephyr/irq.h index 1a94a732bbcf74..1fa559edccd347 100644 --- a/include/zephyr/irq.h +++ b/include/zephyr/irq.h @@ -280,137 +280,6 @@ void z_smp_global_unlock(unsigned int key); #define irq_unlock(key) arch_irq_unlock(key) #endif -/** - * @brief Return IRQ 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) -{ - const uint32_t mask2 = BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS) << - CONFIG_1ST_LEVEL_INTERRUPT_BITS; - const uint32_t mask3 = BIT_MASK(CONFIG_3RD_LEVEL_INTERRUPT_BITS) << - (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS); - - if (IS_ENABLED(CONFIG_3RD_LEVEL_INTERRUPTS) && (irq & mask3) != 0) { - return 3; - } - - if (IS_ENABLED(CONFIG_2ND_LEVEL_INTERRUPTS) && (irq & mask2) != 0) { - return 2; - } - - return 1; -} - -#if defined(CONFIG_2ND_LEVEL_INTERRUPTS) -/** - * @brief Return the 2nd level interrupt number - * - * 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) -{ -#if defined(CONFIG_3RD_LEVEL_INTERRUPTS) - return ((irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) & - BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS)) - 1; -#else - return (irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) - 1; -#endif -} - -/** - * @brief Converts irq from level 1 to level 2 format - * - * - * 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) << CONFIG_1ST_LEVEL_INTERRUPT_BITS; -} - -/** - * @brief Returns the parent IRQ of the level 2 raw IRQ number - * - * - * The parent of a 2nd level interrupt is in the 1st byte - * - * @param irq IRQ number in its zephyr format - * - * @return 2nd level IRQ parent - */ -static inline unsigned int irq_parent_level_2(unsigned int irq) -{ - return irq & BIT_MASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS); -} -#endif - -#ifdef CONFIG_3RD_LEVEL_INTERRUPTS -/** - * @brief Return the 3rd level interrupt number - * - * - * 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 >> (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS)) - 1; -} - -/** - * @brief Converts irq from level 1 to level 3 format - * - * - * 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 3rd level IRQ number - */ -static inline unsigned int irq_to_level_3(unsigned int irq) -{ - return (irq + 1) << (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS); -} - -/** - * @brief Returns the parent IRQ of the level 3 raw IRQ number - * - * - * The parent of a 3rd level interrupt is in the 2nd byte - * - * @param irq IRQ number in its zephyr format - * - * @return 3rd level IRQ parent - */ -static inline unsigned int irq_parent_level_3(unsigned int irq) -{ - return (irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) & - BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS); -} -#endif - /** * @brief Enable an IRQ. * diff --git a/include/zephyr/irq_multilevel.h b/include/zephyr/irq_multilevel.h new file mode 100644 index 00000000000000..f9f082d46ad66c --- /dev/null +++ b/include/zephyr/irq_multilevel.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2023 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Public interface for multi-level interrupts + */ +#ifndef ZEPHYR_INCLUDE_IRQ_MULTILEVEL_H_ +#define ZEPHYR_INCLUDE_IRQ_MULTILEVEL_H_ + +#ifndef _ASMLANGUAGE +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Return IRQ 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) +{ + const uint32_t mask2 = BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS) << + CONFIG_1ST_LEVEL_INTERRUPT_BITS; + const uint32_t mask3 = BIT_MASK(CONFIG_3RD_LEVEL_INTERRUPT_BITS) << + (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS); + + if (IS_ENABLED(CONFIG_3RD_LEVEL_INTERRUPTS) && (irq & mask3) != 0) { + return 3; + } + + if (IS_ENABLED(CONFIG_2ND_LEVEL_INTERRUPTS) && (irq & mask2) != 0) { + return 2; + } + + return 1; +} + +#if defined(CONFIG_2ND_LEVEL_INTERRUPTS) +/** + * @brief Return the 2nd level interrupt number + * + * 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) +{ +#if defined(CONFIG_3RD_LEVEL_INTERRUPTS) + return ((irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) & + BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS)) - 1; +#else + return (irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) - 1; +#endif +} + +/** + * @brief Preprocessor macro to convert `irq` from level 1 to level 2 format + * + * @param irq IRQ number in its zephyr format + * + * @return 2nd level IRQ number + */ +#define IRQ_TO_L2(irq) ((irq + 1) << CONFIG_1ST_LEVEL_INTERRUPT_BITS) + +/** + * @brief Converts irq from level 1 to level 2 format + * + * + * 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_TO_L2(irq); +} + +/** + * @brief Returns the parent IRQ of the level 2 raw IRQ number + * + * + * The parent of a 2nd level interrupt is in the 1st byte + * + * @param irq IRQ number in its zephyr format + * + * @return 2nd level IRQ parent + */ +static inline unsigned int irq_parent_level_2(unsigned int irq) +{ + return irq & BIT_MASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS); +} +#endif + +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS +/** + * @brief Return the 3rd level interrupt number + * + * + * 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 >> (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS)) - 1; +} + +/** + * @brief Preprocessor macro to convert `irq` from level 1 to level 3 format + * + * @param irq IRQ number in its zephyr format + * + * @return 3rd level IRQ number + */ +#define IRQ_TO_L3(irq) \ + ((irq + 1) << (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS)) + +/** + * @brief Converts irq from level 1 to level 3 format + * + * + * 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 3rd level IRQ number + */ +static inline unsigned int irq_to_level_3(unsigned int irq) +{ + return IRQ_TO_L3(irq); +} + +/** + * @brief Returns the parent IRQ of the level 3 raw IRQ number + * + * + * The parent of a 3rd level interrupt is in the 2nd byte + * + * @param irq IRQ number in its zephyr format + * + * @return 3rd level IRQ parent + */ +static inline unsigned int irq_parent_level_3(unsigned int irq) +{ + return (irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) & + BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS); +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ +#endif /* ZEPHYR_INCLUDE_IRQ_MULTILEVEL_H_ */ diff --git a/soc/riscv/riscv-privileged/common/soc_common_irq.c b/soc/riscv/riscv-privileged/common/soc_common_irq.c index c407bc8e20cc1e..f33e4dceeefc3d 100644 --- a/soc/riscv/riscv-privileged/common/soc_common_irq.c +++ b/soc/riscv/riscv-privileged/common/soc_common_irq.c @@ -10,6 +10,7 @@ privileged architecture specification */ #include +#include #include #include diff --git a/tests/kernel/gen_isr_table/src/main.c b/tests/kernel/gen_isr_table/src/main.c index bdb63d69ec0944..c58b866a92efe3 100644 --- a/tests/kernel/gen_isr_table/src/main.c +++ b/tests/kernel/gen_isr_table/src/main.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include