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