1 /* 2 * Copyright (c) 2023 Meta 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /** 8 * @file 9 * @brief Public interface for multi-level interrupts 10 */ 11 #ifndef ZEPHYR_INCLUDE_IRQ_MULTILEVEL_H_ 12 #define ZEPHYR_INCLUDE_IRQ_MULTILEVEL_H_ 13 14 #ifndef _ASMLANGUAGE 15 #include <zephyr/sys/util_macro.h> 16 #include <zephyr/types.h> 17 18 #ifdef __cplusplus 19 extern "C" { 20 #endif 21 22 #if defined(CONFIG_MULTI_LEVEL_INTERRUPTS) || defined(__DOXYGEN__) 23 /** 24 * @brief Return IRQ level 25 * This routine returns the interrupt level number of the provided interrupt. 26 * 27 * @param irq IRQ number in its zephyr format 28 * 29 * @return 1 if IRQ level 1, 2 if IRQ level 2, 3 if IRQ level 3 30 */ irq_get_level(unsigned int irq)31static inline unsigned int irq_get_level(unsigned int irq) 32 { 33 const uint32_t mask2 = BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS) << 34 CONFIG_1ST_LEVEL_INTERRUPT_BITS; 35 const uint32_t mask3 = BIT_MASK(CONFIG_3RD_LEVEL_INTERRUPT_BITS) << 36 (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS); 37 38 if (IS_ENABLED(CONFIG_3RD_LEVEL_INTERRUPTS) && (irq & mask3) != 0) { 39 return 3; 40 } 41 42 if (IS_ENABLED(CONFIG_2ND_LEVEL_INTERRUPTS) && (irq & mask2) != 0) { 43 return 2; 44 } 45 46 return 1; 47 } 48 49 /** 50 * @brief Return the 2nd level interrupt number 51 * 52 * This routine returns the second level irq number of the zephyr irq 53 * number passed in 54 * 55 * @param irq IRQ number in its zephyr format 56 * 57 * @return 2nd level IRQ number 58 */ irq_from_level_2(unsigned int irq)59static inline unsigned int irq_from_level_2(unsigned int irq) 60 { 61 if (IS_ENABLED(CONFIG_3RD_LEVEL_INTERRUPTS)) { 62 return ((irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) & 63 BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS)) - 1; 64 } else { 65 return (irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) - 1; 66 } 67 } 68 69 /** 70 * @brief Preprocessor macro to convert `irq` from level 1 to level 2 format 71 * 72 * @param irq IRQ number in its zephyr format 73 * 74 * @return 2nd level IRQ number 75 */ 76 #define IRQ_TO_L2(irq) ((irq + 1) << CONFIG_1ST_LEVEL_INTERRUPT_BITS) 77 78 /** 79 * @brief Converts irq from level 1 to level 2 format 80 * 81 * 82 * This routine converts the input into the level 2 irq number format 83 * 84 * @note Values >= 0xFF are invalid 85 * 86 * @param irq IRQ number in its zephyr format 87 * 88 * @return 2nd level IRQ number 89 */ irq_to_level_2(unsigned int irq)90static inline unsigned int irq_to_level_2(unsigned int irq) 91 { 92 return IRQ_TO_L2(irq); 93 } 94 95 /** 96 * @brief Returns the parent IRQ of the level 2 raw IRQ number 97 * 98 * 99 * The parent of a 2nd level interrupt is in the 1st byte 100 * 101 * @param irq IRQ number in its zephyr format 102 * 103 * @return 2nd level IRQ parent 104 */ irq_parent_level_2(unsigned int irq)105static inline unsigned int irq_parent_level_2(unsigned int irq) 106 { 107 return irq & BIT_MASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS); 108 } 109 110 /** 111 * @brief Return the 3rd level interrupt number 112 * 113 * 114 * This routine returns the third level irq number of the zephyr irq 115 * number passed in 116 * 117 * @param irq IRQ number in its zephyr format 118 * 119 * @return 3rd level IRQ number 120 */ irq_from_level_3(unsigned int irq)121static inline unsigned int irq_from_level_3(unsigned int irq) 122 { 123 return (irq >> (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS)) - 1; 124 } 125 126 /** 127 * @brief Preprocessor macro to convert `irq` from level 1 to level 3 format 128 * 129 * @param irq IRQ number in its zephyr format 130 * 131 * @return 3rd level IRQ number 132 */ 133 #define IRQ_TO_L3(irq) \ 134 ((irq + 1) << (CONFIG_1ST_LEVEL_INTERRUPT_BITS + CONFIG_2ND_LEVEL_INTERRUPT_BITS)) 135 136 /** 137 * @brief Converts irq from level 1 to level 3 format 138 * 139 * 140 * This routine converts the input into the level 3 irq number format 141 * 142 * @note Values >= 0xFF are invalid 143 * 144 * @param irq IRQ number in its zephyr format 145 * 146 * @return 3rd level IRQ number 147 */ irq_to_level_3(unsigned int irq)148static inline unsigned int irq_to_level_3(unsigned int irq) 149 { 150 return IRQ_TO_L3(irq); 151 } 152 153 /** 154 * @brief Returns the parent IRQ of the level 3 raw IRQ number 155 * 156 * 157 * The parent of a 3rd level interrupt is in the 2nd byte 158 * 159 * @param irq IRQ number in its zephyr format 160 * 161 * @return 3rd level IRQ parent 162 */ irq_parent_level_3(unsigned int irq)163static inline unsigned int irq_parent_level_3(unsigned int irq) 164 { 165 return (irq >> CONFIG_1ST_LEVEL_INTERRUPT_BITS) & 166 BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS); 167 } 168 169 #endif /* CONFIG_MULTI_LEVEL_INTERRUPTS */ 170 #ifdef __cplusplus 171 } 172 #endif 173 174 #endif /* _ASMLANGUAGE */ 175 #endif /* ZEPHYR_INCLUDE_IRQ_MULTILEVEL_H_ */ 176