1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Description:
8 * Interrupt management.
9 */
10
11 #ifndef FWK_INTERRUPT_H
12 #define FWK_INTERRUPT_H
13
14 #include <fwk_arch.h>
15 #include <fwk_macros.h>
16 #include <fwk_status.h>
17
18 #if FWK_HAS_INCLUDE(<arch_helpers.h>)
19 # include <arch_helpers.h>
20 #endif
21
22 #include <limits.h>
23 #include <stdbool.h>
24 #include <stdint.h>
25
26 /*!
27 * \addtogroup GroupLibFramework Framework
28 * \{
29 */
30
31 /*!
32 * \defgroup GroupInterrupt Interrupt Management
33 * \{
34 */
35
36 /*!
37 * \brief Non-maskable interrupt identifier.
38 *
39 * \note This identifier can only be used in specific functions of this API.
40 * Please refer to the individual function documentation for more details.
41 */
42 #define FWK_INTERRUPT_NMI UINT_MAX
43
44 /*!
45 * \brief Non-existing interrupt identifier.
46 *
47 * \details Non-existing interrupt identifier to be used by configuration data
48 * when an interrupt identifier is expected but the system does not support
49 * it.
50 *
51 * \note This identifier cannot be used with the Interrupt Management component
52 * API. Its intention is to provide a standard way to describe an
53 * unconnected (or invalid) IRQ to the drivers.
54 */
55 #define FWK_INTERRUPT_NONE (UINT_MAX - 1)
56
57 /*!
58 * \brief Exception identifier.
59 *
60 * \details Exception interrupt identifier.
61 *
62 * \note This identifier can only be used in specific functions of this API.
63 * Please refer to the individual function documentation for more details.
64 */
65 #define FWK_INTERRUPT_EXCEPTION (UINT_MAX - 2)
66
67 /*!
68 * \brief Register interrupt driver in the framework.
69 *
70 * \param driver Interrupt driver instance to register
71 *
72 * \retval ::FWK_SUCCESS Operation succeeded.
73 * \retval ::FWK_E_PARAM One or more parameters were invalid.
74 */
75 int fwk_interrupt_init(const struct fwk_arch_interrupt_driver *driver);
76
77 /*!
78 * \brief Enable interrupts.
79 *
80 * \param flags Value returned by fwk_interrupt_global_disable.
81 */
fwk_interrupt_global_enable(unsigned int flags)82 inline static void fwk_interrupt_global_enable(unsigned int flags)
83 {
84 arch_interrupts_enable(flags);
85 }
86
87 /*!
88 * \brief Disable interrupts.
89 *
90 * \retval Opaque value to be passed when enabling.
91 */
fwk_interrupt_global_disable(void)92 inline static unsigned int fwk_interrupt_global_disable(void)
93 {
94 return arch_interrupts_disable();
95 }
96
97 /*!
98 * \brief Test whether an interrupt is enabled.
99 *
100 * \param interrupt Interrupt number.
101 * \param [out] enabled \c true if the interrupt is enabled, else \c false.
102 *
103 * \retval ::FWK_SUCCESS Operation succeeded.
104 * \retval ::FWK_E_PARAM One or more parameters were invalid.
105 * \retval ::FWK_E_INIT The component has not been initialized.
106 */
107 int fwk_interrupt_is_enabled(unsigned int interrupt, bool *enabled);
108
109 /*!
110 * \brief Enable interrupt.
111 *
112 * \param interrupt Interrupt number.
113 *
114 * \retval ::FWK_SUCCESS Operation succeeded.
115 * \retval ::FWK_E_PARAM One or more parameters were invalid.
116 * \retval ::FWK_E_INIT The component has not been initialized.
117 */
118 int fwk_interrupt_enable(unsigned int interrupt);
119
120 /*!
121 * \brief Disable interrupt.
122 *
123 * \param interrupt Interrupt number.
124 *
125 * \retval ::FWK_SUCCESS Operation succeeded.
126 * \retval ::FWK_E_PARAM One or more parameters were invalid.
127 * \retval ::FWK_E_INIT The component has not been initialized.
128 */
129 int fwk_interrupt_disable(unsigned int interrupt);
130
131 /*!
132 * \brief Check if an interrupt is pending.
133 *
134 * \param interrupt Interrupt number.
135 * \param [out] pending \c true if the interrupt is pending, else \c false.
136 *
137 * \retval ::FWK_SUCCESS Operation succeeded.
138 * \retval ::FWK_E_PARAM One or more parameters were invalid.
139 * \retval ::FWK_E_INIT The component has not been initialized.
140 */
141 int fwk_interrupt_is_pending(unsigned int interrupt, bool *pending);
142
143 /*!
144 * \brief Change interrupt status to pending.
145 *
146 * \param interrupt Interrupt number.
147 *
148 * \retval ::FWK_SUCCESS Operation succeeded.
149 * \retval ::FWK_E_PARAM One or more parameters were invalid.
150 * \retval ::FWK_E_INIT The component has not been initialized.
151 */
152 int fwk_interrupt_set_pending(unsigned int interrupt);
153
154 /*!
155 * \brief Clear the interrupt pending status.
156 *
157 * \param interrupt Interrupt number.
158 *
159 * \retval ::FWK_SUCCESS Operation succeeded.
160 * \retval ::FWK_E_PARAM One or more parameters were invalid.
161 * \retval ::FWK_E_INIT The component has not been initialized.
162 */
163 int fwk_interrupt_clear_pending(unsigned int interrupt);
164
165 /*!
166 * \brief Assign an interrupt service routine to an interrupt.
167 *
168 * \param interrupt Interrupt number. This function accepts FWK_INTERRUPT_NMI as
169 * an interrupt number.
170 * \param isr Pointer to the interrupt service routine function.
171 *
172 * \retval ::FWK_SUCCESS Operation succeeded.
173 * \retval ::FWK_E_PARAM One or more parameters were invalid.
174 * \retval ::FWK_E_INIT The component has not been initialized.
175 */
176 int fwk_interrupt_set_isr(unsigned int interrupt, void (*isr)(void));
177
178 /*!
179 * \brief Assign an interrupt service routine that receives a parameter to an
180 * interrupt.
181 *
182 * \param interrupt Interrupt number. This function accepts FWK_INTERRUPT_NMI as
183 * an interrupt number.
184 * \param isr Pointer to the interrupt service routine function.
185 * \param param Parameter that should be passed to the isr when it is called.
186 *
187 * \retval ::FWK_SUCCESS Operation succeeded.
188 * \retval ::FWK_E_PARAM One or more parameters were invalid.
189 * \retval ::FWK_E_INIT The component has not been initialized.
190 */
191 int fwk_interrupt_set_isr_param(unsigned int interrupt,
192 void (*isr)(uintptr_t param),
193 uintptr_t param);
194
195 /*!
196 * \brief Get the interrupt number for the interrupt service routine being
197 * processed.
198 *
199 * \param [out] interrupt Interrupt number. This function may return
200 * also:
201 * * FWK_INTERRUPT_NMI - When the current interrupt is an NMI.
202 * * FWK_INTERRUPT_EXCEPTION - When the current interrupt is an
203 * exception.
204 *
205 * \retval ::FWK_SUCCESS Operation succeeded.
206 * \retval ::FWK_E_PARAM One or more parameters were invalid.
207 * \retval ::FWK_E_STATE An interrupt is not currently being serviced.
208 * \retval ::FWK_E_INIT The component has not been initialized.
209 */
210 int fwk_interrupt_get_current(unsigned int *interrupt);
211
212 /*!
213 * \brief Check if in interrupt context.
214 *
215 * \retval true if in an interrupt context.
216 * \retval false not in an interrupt context.
217 */
218 bool fwk_is_interrupt_context(void);
219
220 /*!
221 * \}
222 */
223
224 /*!
225 * \}
226 */
227
228 #endif /* FWK_INTERRUPT_H */
229