Line data Source code
1 0 : /* arcv2_irq_unit.h - ARCv2 Interrupt Unit device driver */ 2 : 3 : /* 4 : * Copyright (c) 2014 Wind River Systems, Inc. 5 : * Copyright (c) 2020 Synopsys. 6 : * 7 : * SPDX-License-Identifier: Apache-2.0 8 : */ 9 : 10 : #ifndef ZEPHYR_INCLUDE_ARCH_ARC_V2_ARCV2_IRQ_UNIT_H_ 11 : #define ZEPHYR_INCLUDE_ARCH_ARC_V2_ARCV2_IRQ_UNIT_H_ 12 : 13 : #ifdef __cplusplus 14 : extern "C" { 15 : #endif 16 : 17 : /* configuration flags for interrupt unit */ 18 : #define _ARC_V2_INT_PRIO_MASK 0xf 19 : #define _ARC_V2_INT_DISABLE 0 20 : #define _ARC_V2_INT_ENABLE 1 21 : 22 : #define _ARC_V2_INT_LEVEL 0 23 : #define _ARC_V2_INT_PULSE 1 24 : 25 : #ifndef _ASMLANGUAGE 26 : 27 : /* 28 : * NOTE: 29 : * 30 : * All APIs provided by this file are protected with INTERRUPTS LOCKED. The 31 : * APIs themselves are writing the IRQ_SELECT, selecting which IRQ's registers 32 : * it wants to write to, then write to them: THIS IS NOT AN ATOMIC OPERATION. 33 : * 34 : * Locking the interrupts inside of the APIs are some kind of self-protection 35 : * to guarantee the correctness of operation if the callers don't lock 36 : * the interrupt. 37 : * 38 : */ 39 : 40 : /** 41 : * @brief Enable/disable interrupt 42 : * 43 : * Enables or disables the specified interrupt 44 : * @param irq IRQ line number 45 : * @param enable 1 to enable, 0 to disable 46 : */ 47 : 48 : static ALWAYS_INLINE 49 : void z_arc_v2_irq_unit_irq_enable_set( 50 : int irq, 51 : unsigned char enable 52 : ) 53 : { 54 : unsigned int key = arch_irq_lock(); 55 : 56 : z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq); 57 : z_arc_v2_aux_reg_write(_ARC_V2_IRQ_ENABLE, enable); 58 : 59 : arch_irq_unlock(key); 60 : } 61 : 62 : /** 63 : * @brief Enable interrupt 64 : * 65 : * Enables the specified interrupt 66 : */ 67 : 68 : static ALWAYS_INLINE 69 : void z_arc_v2_irq_unit_int_enable(int irq) 70 : { 71 : z_arc_v2_irq_unit_irq_enable_set(irq, _ARC_V2_INT_ENABLE); 72 : } 73 : 74 : /** 75 : * @brief Disable interrupt 76 : * 77 : * Disables the specified interrupt 78 : */ 79 : 80 : static ALWAYS_INLINE 81 : void z_arc_v2_irq_unit_int_disable(int irq) 82 : { 83 : z_arc_v2_irq_unit_irq_enable_set(irq, _ARC_V2_INT_DISABLE); 84 : } 85 : 86 : /** 87 : * @brief Poll the enable status of interrupt 88 : * 89 : * Polls the enable status of the specified interrupt 90 : * 91 : * @return 1 enabled, 0 disabled 92 : */ 93 : 94 : static ALWAYS_INLINE 95 : bool z_arc_v2_irq_unit_int_enabled(int irq) 96 : { 97 : bool ret; 98 : unsigned int key = arch_irq_lock(); 99 : 100 : z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq); 101 : ret = z_arc_v2_aux_reg_read(_ARC_V2_IRQ_ENABLE) & 0x1; 102 : 103 : arch_irq_unlock(key); 104 : 105 : return ret; 106 : } 107 : 108 : 109 : /** 110 : * @brief Set interrupt priority 111 : * 112 : * Set the priority of the specified interrupt 113 : */ 114 : 115 : static ALWAYS_INLINE 116 : void z_arc_v2_irq_unit_prio_set(int irq, unsigned char prio) 117 : { 118 : 119 : unsigned int key = arch_irq_lock(); 120 : 121 : z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq); 122 : #if defined(CONFIG_ARC_SECURE_FIRMWARE) 123 : z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY, 124 : (z_arc_v2_aux_reg_read(_ARC_V2_IRQ_PRIORITY) & (~_ARC_V2_INT_PRIO_MASK)) 125 : | prio); 126 : #else 127 : z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY, prio); 128 : #endif 129 : arch_irq_unlock(key); 130 : } 131 : 132 : #if defined(CONFIG_ARC_SECURE_FIRMWARE) 133 : /** 134 : * @brief Configure the secure state of interrupt 135 : * 136 : * Configure the secure state of the specified interrupt 137 : */ 138 : static ALWAYS_INLINE 139 : void z_arc_v2_irq_uinit_secure_set(int irq, bool secure) 140 : { 141 : unsigned int key = arch_irq_lock(); 142 : 143 : z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq); 144 : 145 : if (secure) { 146 : z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY, 147 : z_arc_v2_aux_reg_read(_ARC_V2_IRQ_PRIORITY) | 148 : _ARC_V2_IRQ_PRIORITY_SECURE); 149 : } else { 150 : z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY, 151 : z_arc_v2_aux_reg_read(_ARC_V2_IRQ_PRIORITY) & 152 : _ARC_V2_INT_PRIO_MASK); 153 : } 154 : 155 : arch_irq_unlock(key); 156 : } 157 : #endif 158 : 159 : /** 160 : * @brief Set interrupt sensitivity 161 : * 162 : * Set the sensitivity of the specified interrupt to either 163 : * _ARC_V2_INT_LEVEL or _ARC_V2_INT_PULSE. Level interrupts will remain 164 : * asserted until the interrupt handler clears the interrupt at the peripheral. 165 : * Pulse interrupts self-clear as the interrupt handler is entered. 166 : */ 167 : 168 : static ALWAYS_INLINE 169 : void z_arc_v2_irq_unit_sensitivity_set(int irq, int s) 170 : { 171 : unsigned int key = arch_irq_lock(); 172 : 173 : z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq); 174 : z_arc_v2_aux_reg_write(_ARC_V2_IRQ_TRIGGER, s); 175 : 176 : arch_irq_unlock(key); 177 : } 178 : 179 : /* 180 : * @brief Check whether processor in interrupt/exception state 181 : * 182 : * Check whether processor in interrupt/exception state 183 : * 184 : * @return 1 in interrupt/exception state; 0 not in 185 : */ 186 : static ALWAYS_INLINE 187 : bool z_arc_v2_irq_unit_is_in_isr(void) 188 : { 189 : uint32_t act = z_arc_v2_aux_reg_read(_ARC_V2_AUX_IRQ_ACT); 190 : 191 : /* in exception ?*/ 192 : if (z_arc_v2_aux_reg_read(_ARC_V2_STATUS32) & _ARC_V2_STATUS32_AE) { 193 : return true; 194 : } 195 : 196 : return ((act & 0xffff) != 0U); 197 : } 198 : 199 : /** 200 : * @brief Sets an IRQ line to level/pulse trigger 201 : * 202 : * Sets the IRQ line @p irq to trigger an interrupt based on the level or the 203 : * edge of the signal. Valid values for @p trigger are _ARC_V2_INT_LEVEL and 204 : * _ARC_V2_INT_PULSE. 205 : * @param irq IRQ line 206 : * @param trigger Trigger state 207 : */ 208 : static ALWAYS_INLINE 209 : void z_arc_v2_irq_unit_trigger_set(int irq, unsigned int trigger) 210 : { 211 : unsigned int key = arch_irq_lock(); 212 : 213 : z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq); 214 : z_arc_v2_aux_reg_write(_ARC_V2_IRQ_TRIGGER, trigger); 215 : 216 : arch_irq_unlock(key); 217 : } 218 : 219 : /** 220 : * @brief Returns an IRQ line trigger type 221 : * 222 : * Gets the IRQ line @p irq trigger type. 223 : * Valid values for @retval trigger are _ARC_V2_INT_LEVEL and _ARC_V2_INT_PULSE. 224 : * 225 : * @param irq IRQ line 226 : * 227 : * @return trigger state 228 : */ 229 : static ALWAYS_INLINE 230 : unsigned int z_arc_v2_irq_unit_trigger_get(int irq) 231 : { 232 : unsigned int ret; 233 : unsigned int key = arch_irq_lock(); 234 : 235 : z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq); 236 : ret = z_arc_v2_aux_reg_read(_ARC_V2_IRQ_TRIGGER); 237 : 238 : arch_irq_unlock(key); 239 : 240 : return ret; 241 : } 242 : 243 : /** 244 : * @brief Send EOI signal to interrupt unit 245 : * 246 : * This routine sends an EOI (End Of Interrupt) signal to the interrupt unit 247 : * to clear a pulse-triggered interrupt. 248 : */ 249 : static ALWAYS_INLINE 250 : void z_arc_v2_irq_unit_int_eoi(int irq) 251 : { 252 : unsigned int key = arch_irq_lock(); 253 : 254 : z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq); 255 : z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PULSE_CANCEL, 1); 256 : 257 : arch_irq_unlock(key); 258 : } 259 : 260 : #endif /* _ASMLANGUAGE */ 261 : 262 : #ifdef __cplusplus 263 : } 264 : #endif 265 : 266 : #endif /* ZEPHYR_INCLUDE_ARCH_ARC_V2_ARCV2_IRQ_UNIT_H_ */