1 /* 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 *
45 * @return N/A
46 */
47
48 static ALWAYS_INLINE
z_arc_v2_irq_unit_irq_enable_set(int irq,unsigned char enable)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 * @return N/A
68 */
69
70 static ALWAYS_INLINE
z_arc_v2_irq_unit_int_enable(int irq)71 void z_arc_v2_irq_unit_int_enable(int irq)
72 {
73 z_arc_v2_irq_unit_irq_enable_set(irq, _ARC_V2_INT_ENABLE);
74 }
75
76 /*
77 * @brief Disable interrupt
78 *
79 * Disables the specified interrupt
80 *
81 * @return N/A
82 */
83
84 static ALWAYS_INLINE
z_arc_v2_irq_unit_int_disable(int irq)85 void z_arc_v2_irq_unit_int_disable(int irq)
86 {
87 z_arc_v2_irq_unit_irq_enable_set(irq, _ARC_V2_INT_DISABLE);
88 }
89
90 /*
91 * @brief Poll the enable status of interrupt
92 *
93 * Polls the enable status of the specified interrupt
94 *
95 * @return 1 enabled, 0 disabled
96 */
97
98 static ALWAYS_INLINE
z_arc_v2_irq_unit_int_enabled(int irq)99 bool z_arc_v2_irq_unit_int_enabled(int irq)
100 {
101 bool ret;
102 unsigned int key = arch_irq_lock();
103
104 z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq);
105 ret = z_arc_v2_aux_reg_read(_ARC_V2_IRQ_ENABLE) & 0x1;
106
107 arch_irq_unlock(key);
108
109 return ret;
110 }
111
112
113 /*
114 * @brief Set interrupt priority
115 *
116 * Set the priority of the specified interrupt
117 *
118 * @return N/A
119 */
120
121 static ALWAYS_INLINE
z_arc_v2_irq_unit_prio_set(int irq,unsigned char prio)122 void z_arc_v2_irq_unit_prio_set(int irq, unsigned char prio)
123 {
124
125 unsigned int key = arch_irq_lock();
126
127 z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq);
128 #if defined(CONFIG_ARC_SECURE_FIRMWARE)
129 z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY,
130 (z_arc_v2_aux_reg_read(_ARC_V2_IRQ_PRIORITY) & (~_ARC_V2_INT_PRIO_MASK))
131 | prio);
132 #else
133 z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY, prio);
134 #endif
135 arch_irq_unlock(key);
136 }
137
138 #if defined(CONFIG_ARC_SECURE_FIRMWARE)
139 /*
140 * @brief Configure the secure state of interrupt
141 *
142 * Configure the secure state of the specified interrupt
143 *
144 * @return N/A
145 */
146 static ALWAYS_INLINE
z_arc_v2_irq_uinit_secure_set(int irq,bool secure)147 void z_arc_v2_irq_uinit_secure_set(int irq, bool secure)
148 {
149 unsigned int key = arch_irq_lock();
150
151 z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq);
152
153 if (secure) {
154 z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY,
155 z_arc_v2_aux_reg_read(_ARC_V2_IRQ_PRIORITY) |
156 _ARC_V2_IRQ_PRIORITY_SECURE);
157 } else {
158 z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PRIORITY,
159 z_arc_v2_aux_reg_read(_ARC_V2_IRQ_PRIORITY) &
160 _ARC_V2_INT_PRIO_MASK);
161 }
162
163 arch_irq_unlock(key);
164 }
165 #endif
166
167 /*
168 * @brief Set interrupt sensitivity
169 *
170 * Set the sensitivity of the specified interrupt to either
171 * _ARC_V2_INT_LEVEL or _ARC_V2_INT_PULSE. Level interrupts will remain
172 * asserted until the interrupt handler clears the interrupt at the peripheral.
173 * Pulse interrupts self-clear as the interrupt handler is entered.
174 *
175 * @return N/A
176 */
177
178 static ALWAYS_INLINE
z_arc_v2_irq_unit_sensitivity_set(int irq,int s)179 void z_arc_v2_irq_unit_sensitivity_set(int irq, int s)
180 {
181 unsigned int key = arch_irq_lock();
182
183 z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq);
184 z_arc_v2_aux_reg_write(_ARC_V2_IRQ_TRIGGER, s);
185
186 arch_irq_unlock(key);
187 }
188
189 /*
190 * @brief Check whether processor in interrupt/exception state
191 *
192 * Check whether processor in interrupt/exception state
193 *
194 * @return 1 in interrupt/exception state; 0 not in
195 */
196 static ALWAYS_INLINE
z_arc_v2_irq_unit_is_in_isr(void)197 bool z_arc_v2_irq_unit_is_in_isr(void)
198 {
199 uint32_t act = z_arc_v2_aux_reg_read(_ARC_V2_AUX_IRQ_ACT);
200
201 /* in exception ?*/
202 if (z_arc_v2_aux_reg_read(_ARC_V2_STATUS32) & _ARC_V2_STATUS32_AE) {
203 return true;
204 }
205
206 return ((act & 0xffff) != 0U);
207 }
208
209 /*
210 * @brief Sets an IRQ line to level/pulse trigger
211 *
212 * Sets the IRQ line <irq> to trigger an interrupt based on the level or the
213 * edge of the signal. Valid values for <trigger> are _ARC_V2_INT_LEVEL and
214 * _ARC_V2_INT_PULSE.
215 *
216 * @return N/A
217 */
218 static ALWAYS_INLINE
z_arc_v2_irq_unit_trigger_set(int irq,unsigned int trigger)219 void z_arc_v2_irq_unit_trigger_set(int irq, unsigned int trigger)
220 {
221 unsigned int key = arch_irq_lock();
222
223 z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq);
224 z_arc_v2_aux_reg_write(_ARC_V2_IRQ_TRIGGER, trigger);
225
226 arch_irq_unlock(key);
227 }
228
229 /*
230 * @brief Returns an IRQ line trigger type
231 *
232 * Gets the IRQ line <irq> trigger type.
233 * Valid values for <trigger> are _ARC_V2_INT_LEVEL and _ARC_V2_INT_PULSE.
234 *
235 * @return trigger state
236 */
237 static ALWAYS_INLINE
z_arc_v2_irq_unit_trigger_get(int irq)238 unsigned int z_arc_v2_irq_unit_trigger_get(int irq)
239 {
240 unsigned int ret;
241 unsigned int key = arch_irq_lock();
242
243 z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq);
244 ret = z_arc_v2_aux_reg_read(_ARC_V2_IRQ_TRIGGER);
245
246 arch_irq_unlock(key);
247
248 return ret;
249 }
250
251 /*
252 * @brief Send EOI signal to interrupt unit
253 *
254 * This routine sends an EOI (End Of Interrupt) signal to the interrupt unit
255 * to clear a pulse-triggered interrupt.
256 *
257 * @return N/A
258 */
259 static ALWAYS_INLINE
z_arc_v2_irq_unit_int_eoi(int irq)260 void z_arc_v2_irq_unit_int_eoi(int irq)
261 {
262 unsigned int key = arch_irq_lock();
263
264 z_arc_v2_aux_reg_write(_ARC_V2_IRQ_SELECT, irq);
265 z_arc_v2_aux_reg_write(_ARC_V2_IRQ_PULSE_CANCEL, 1);
266
267 arch_irq_unlock(key);
268 }
269
270 #endif /* _ASMLANGUAGE */
271
272 #ifdef __cplusplus
273 }
274 #endif
275
276 #endif /* ZEPHYR_INCLUDE_ARCH_ARC_V2_ARCV2_IRQ_UNIT_H_ */
277