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_ */
|