Line data Source code
1 1 : /* 2 : * Copyright (c) 2014 Wind River Systems, Inc. 3 : * 4 : * SPDX-License-Identifier: Apache-2.0 5 : */ 6 : 7 : /** 8 : * @file 9 : * @brief ARCv2 public interrupt handling 10 : * 11 : * ARCv2 kernel interrupt handling interface. Included by arc/arch.h. 12 : */ 13 : 14 : #ifndef ZEPHYR_INCLUDE_ARCH_ARC_V2_IRQ_H_ 15 : #define ZEPHYR_INCLUDE_ARCH_ARC_V2_IRQ_H_ 16 : 17 : #include <zephyr/arch/arc/v2/aux_regs.h> 18 : #include <zephyr/toolchain/common.h> 19 : #include <zephyr/irq.h> 20 : #include <zephyr/sys/util.h> 21 : #include <zephyr/sw_isr_table.h> 22 : 23 : #ifdef __cplusplus 24 : extern "C" { 25 : #endif 26 : 27 0 : #define ARC_MP_PRIMARY_CPU_ID 0 28 : 29 : #ifndef _ASMLANGUAGE 30 : 31 : extern void z_arc_firq_stack_set(void); 32 0 : extern void arch_irq_enable(unsigned int irq); 33 0 : extern void arch_irq_disable(unsigned int irq); 34 0 : extern int arch_irq_is_enabled(unsigned int irq); 35 : #ifdef CONFIG_TRACING_ISR 36 : extern void sys_trace_isr_enter(void); 37 : extern void sys_trace_isr_exit(void); 38 : #endif 39 : 40 : extern void z_irq_priority_set(unsigned int irq, unsigned int prio, 41 : uint32_t flags); 42 : 43 : /* Z_ISR_DECLARE will populate the .intList section with the interrupt's 44 : * parameters, which will then be used by gen_irq_tables.py to create 45 : * the vector table and the software ISR table. This is all done at 46 : * build-time. 47 : * 48 : * We additionally set the priority in the interrupt controller at 49 : * runtime. 50 : */ 51 0 : #define ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ 52 : { \ 53 : Z_ISR_DECLARE(irq_p, 0, isr_p, isr_param_p); \ 54 : z_irq_priority_set(irq_p, priority_p, flags_p); \ 55 : } 56 : 57 : /** 58 : * Configure a 'direct' static interrupt. 59 : * 60 : * When firq has no separate stack(CONFIG_ARC_FIRQ_STACK=N), it's not safe 61 : * to call C ISR handlers because sp will be switched to bank1's sp which 62 : * is undefined value. 63 : * So for this case, the priority cannot be set to 0 but next level 1 64 : * 65 : * When firq has separate stack (CONFIG_ARC_FIRQ_STACK=y) but at the same 66 : * time stack checking is enabled (CONFIG_ARC_STACK_CHECKING=y) 67 : * the stack checking can raise stack check exception as sp is switched to 68 : * firq's stack (bank1's sp). So for this case, the priority cannot be set 69 : * to 0 but next level 1. 70 : * 71 : * Note that for the above cases, if application still wants to use firq by 72 : * setting priority to 0. Application can call z_irq_priority_set again. 73 : * Then it's left to application to handle the details of firq 74 : * 75 : * See include/irq.h for details. 76 : * All arguments must be computable at build time. 77 : */ 78 1 : #define ARCH_IRQ_DIRECT_CONNECT(irq_p, priority_p, isr_p, flags_p) \ 79 : { \ 80 : Z_ISR_DECLARE_DIRECT(irq_p, ISR_FLAG_DIRECT, isr_p); \ 81 : BUILD_ASSERT(priority_p || !IS_ENABLED(CONFIG_ARC_FIRQ) || \ 82 : (IS_ENABLED(CONFIG_ARC_FIRQ_STACK) && \ 83 : !IS_ENABLED(CONFIG_ARC_STACK_CHECKING)), \ 84 : "irq priority cannot be set to 0 when CONFIG_ARC_FIRQ_STACK" \ 85 : "is not configured or CONFIG_ARC_FIRQ_STACK " \ 86 : "and CONFIG_ARC_STACK_CHECKING are configured together"); \ 87 : z_irq_priority_set(irq_p, priority_p, flags_p); \ 88 : } 89 : 90 : 91 0 : static inline void arch_isr_direct_header(void) 92 : { 93 : #ifdef CONFIG_TRACING_ISR 94 : sys_trace_isr_enter(); 95 : #endif 96 : } 97 : 98 0 : static inline void arch_isr_direct_footer(int maybe_swap) 99 : { 100 : /* clear SW generated interrupt */ 101 : if (z_arc_v2_aux_reg_read(_ARC_V2_ICAUSE) == 102 : z_arc_v2_aux_reg_read(_ARC_V2_AUX_IRQ_HINT)) { 103 : z_arc_v2_aux_reg_write(_ARC_V2_AUX_IRQ_HINT, 0); 104 : } 105 : #ifdef CONFIG_TRACING_ISR 106 : sys_trace_isr_exit(); 107 : #endif 108 : } 109 : 110 0 : #define ARCH_ISR_DIRECT_HEADER() arch_isr_direct_header() 111 : extern void arch_isr_direct_header(void); 112 : 113 0 : #define ARCH_ISR_DIRECT_FOOTER(swap) arch_isr_direct_footer(swap) 114 : 115 : #if defined(__CCAC__) 116 : #define _ARC_DIRECT_ISR_FUNC_ATTRIBUTE __interrupt__ 117 : #else 118 : #define _ARC_DIRECT_ISR_FUNC_ATTRIBUTE interrupt("ilink") 119 : #endif 120 : 121 : /* 122 : * Scheduling can not be done in direct isr. If required, please use kernel 123 : * aware interrupt handling 124 : */ 125 0 : #define ARCH_ISR_DIRECT_DECLARE(name) \ 126 : static inline int name##_body(void); \ 127 : __attribute__ ((_ARC_DIRECT_ISR_FUNC_ATTRIBUTE))void name(void) \ 128 : { \ 129 : ISR_DIRECT_HEADER(); \ 130 : name##_body(); \ 131 : ISR_DIRECT_FOOTER(0); \ 132 : } \ 133 : static inline int name##_body(void) 134 : 135 : 136 : /** 137 : * 138 : * @brief Disable all interrupts on the local CPU 139 : * 140 : * This routine disables interrupts. It can be called from either interrupt or 141 : * thread level. This routine returns an architecture-dependent 142 : * lock-out key representing the "interrupt disable state" prior to the call; 143 : * this key can be passed to irq_unlock() to re-enable interrupts. 144 : * 145 : * The lock-out key should only be used as the argument to the 146 : * irq_unlock() API. It should never be used to manually re-enable 147 : * interrupts or to inspect or manipulate the contents of the source register. 148 : * 149 : * This function can be called recursively: it will return a key to return the 150 : * state of interrupt locking to the previous level. 151 : * 152 : * WARNINGS 153 : * Invoking a kernel routine with interrupts locked may result in 154 : * interrupts being re-enabled for an unspecified period of time. If the 155 : * called routine blocks, interrupts will be re-enabled while another 156 : * thread executes, or while the system is idle. 157 : * 158 : * The "interrupt disable state" is an attribute of a thread. Thus, if a 159 : * thread disables interrupts and subsequently invokes a kernel 160 : * routine that causes the calling thread to block, the interrupt 161 : * disable state will be restored when the thread is later rescheduled 162 : * for execution. 163 : * 164 : * @return An architecture-dependent lock-out key representing the 165 : * "interrupt disable state" prior to the call. 166 : */ 167 : 168 1 : static ALWAYS_INLINE unsigned int arch_irq_lock(void) 169 : { 170 : unsigned int key; 171 : 172 : __asm__ volatile("clri %0" : "=r"(key):: "memory"); 173 : return key; 174 : } 175 : 176 0 : static ALWAYS_INLINE void arch_irq_unlock(unsigned int key) 177 : { 178 : __asm__ volatile("seti %0" : : "ir"(key) : "memory"); 179 : } 180 : 181 0 : static ALWAYS_INLINE bool arch_irq_unlocked(unsigned int key) 182 : { 183 : /* ARC irq lock uses instruction "clri r0", 184 : * r0 == {26’d0, 1’b1, STATUS32.IE, STATUS32.E[3:0] } 185 : * bit4 is used to record IE (Interrupt Enable) bit 186 : */ 187 : return (key & 0x10) == 0x10; 188 : } 189 : 190 : #endif /* _ASMLANGUAGE */ 191 : 192 : #ifdef __cplusplus 193 : } 194 : #endif 195 : 196 : #endif /* ZEPHYR_INCLUDE_ARCH_ARC_V2_IRQ_H_ */