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 #include <internal/fwk_interrupt.h>
12
13 #include <fwk_arch.h>
14 #include <fwk_interrupt.h>
15 #include <fwk_status.h>
16
17 #include <stdbool.h>
18 #include <stddef.h>
19
20 static bool initialized;
21 static const struct fwk_arch_interrupt_driver *fwk_interrupt_driver;
22
fwk_interrupt_init(const struct fwk_arch_interrupt_driver * driver)23 int fwk_interrupt_init(const struct fwk_arch_interrupt_driver *driver)
24 {
25 /* Validate driver by checking that all function pointers are non-null */
26 if (driver == NULL) {
27 return FWK_E_PARAM;
28 }
29 if (driver->global_enable == NULL) {
30 return FWK_E_PARAM;
31 }
32 if (driver->global_disable == NULL) {
33 return FWK_E_PARAM;
34 }
35 if (driver->is_enabled == NULL) {
36 return FWK_E_PARAM;
37 }
38 if (driver->enable == NULL) {
39 return FWK_E_PARAM;
40 }
41 if (driver->disable == NULL) {
42 return FWK_E_PARAM;
43 }
44 if (driver->is_pending == NULL) {
45 return FWK_E_PARAM;
46 }
47 if (driver->set_pending == NULL) {
48 return FWK_E_PARAM;
49 }
50 if (driver->clear_pending == NULL) {
51 return FWK_E_PARAM;
52 }
53 if (driver->set_isr_irq == NULL) {
54 return FWK_E_PARAM;
55 }
56 if (driver->set_isr_irq_param == NULL) {
57 return FWK_E_PARAM;
58 }
59 if (driver->set_isr_nmi == NULL) {
60 return FWK_E_PARAM;
61 }
62 if (driver->set_isr_nmi_param == NULL) {
63 return FWK_E_PARAM;
64 }
65 if (driver->set_isr_fault == NULL) {
66 return FWK_E_PARAM;
67 }
68 if (driver->get_current == NULL) {
69 return FWK_E_PARAM;
70 }
71
72 fwk_interrupt_driver = driver;
73 initialized = true;
74
75 return FWK_SUCCESS;
76 }
77
fwk_interrupt_is_enabled(unsigned int interrupt,bool * enabled)78 int fwk_interrupt_is_enabled(unsigned int interrupt, bool *enabled)
79 {
80 if (!initialized) {
81 return FWK_E_INIT;
82 }
83
84 if (enabled == NULL) {
85 return FWK_E_PARAM;
86 }
87
88 return fwk_interrupt_driver->is_enabled(interrupt, enabled);
89 }
90
fwk_interrupt_enable(unsigned int interrupt)91 int fwk_interrupt_enable(unsigned int interrupt)
92 {
93 if (!initialized) {
94 return FWK_E_INIT;
95 }
96
97 return fwk_interrupt_driver->enable(interrupt);
98 }
99
fwk_interrupt_disable(unsigned int interrupt)100 int fwk_interrupt_disable(unsigned int interrupt)
101 {
102 if (!initialized) {
103 return FWK_E_INIT;
104 }
105
106 return fwk_interrupt_driver->disable(interrupt);
107 }
108
fwk_interrupt_is_pending(unsigned int interrupt,bool * pending)109 int fwk_interrupt_is_pending(unsigned int interrupt, bool *pending)
110 {
111 if (!initialized) {
112 return FWK_E_INIT;
113 }
114
115 if (pending == NULL) {
116 return FWK_E_PARAM;
117 }
118
119 return fwk_interrupt_driver->is_pending(interrupt, pending);
120 }
121
fwk_interrupt_set_pending(unsigned int interrupt)122 int fwk_interrupt_set_pending(unsigned int interrupt)
123 {
124 if (!initialized) {
125 return FWK_E_INIT;
126 }
127
128 return fwk_interrupt_driver->set_pending(interrupt);
129 }
130
fwk_interrupt_clear_pending(unsigned int interrupt)131 int fwk_interrupt_clear_pending(unsigned int interrupt)
132 {
133 if (!initialized) {
134 return FWK_E_INIT;
135 }
136
137 return fwk_interrupt_driver->clear_pending(interrupt);
138 }
139
fwk_interrupt_set_isr(unsigned int interrupt,void (* isr)(void))140 int fwk_interrupt_set_isr(unsigned int interrupt, void (*isr)(void))
141 {
142 if (!initialized) {
143 return FWK_E_INIT;
144 }
145
146 if (isr == NULL) {
147 return FWK_E_PARAM;
148 }
149
150 if (interrupt == FWK_INTERRUPT_NMI) {
151 return fwk_interrupt_driver->set_isr_nmi(isr);
152 } else {
153 return fwk_interrupt_driver->set_isr_irq(interrupt, isr);
154 }
155 }
156
fwk_interrupt_set_isr_param(unsigned int interrupt,void (* isr)(uintptr_t param),uintptr_t param)157 int fwk_interrupt_set_isr_param(unsigned int interrupt,
158 void (*isr)(uintptr_t param),
159 uintptr_t param)
160 {
161 if (!initialized) {
162 return FWK_E_INIT;
163 }
164
165 if (isr == NULL) {
166 return FWK_E_PARAM;
167 }
168
169 if (interrupt == FWK_INTERRUPT_NMI) {
170 return fwk_interrupt_driver->set_isr_nmi_param(isr, param);
171 } else {
172 return fwk_interrupt_driver->set_isr_irq_param(interrupt, isr, param);
173 }
174 }
175
fwk_interrupt_get_current(unsigned int * interrupt)176 int fwk_interrupt_get_current(unsigned int *interrupt)
177 {
178 if (!initialized) {
179 return FWK_E_INIT;
180 }
181
182 if (interrupt == NULL) {
183 return FWK_E_PARAM;
184 }
185
186 return fwk_interrupt_driver->get_current(interrupt);
187 }
188
fwk_is_interrupt_context(void)189 bool fwk_is_interrupt_context(void)
190 {
191 if (!initialized) {
192 return false;
193 }
194
195 return fwk_interrupt_driver->is_interrupt_context();
196 }
197
198 /* This function is only for internal use by the framework */
fwk_interrupt_set_isr_fault(void (* isr)(void))199 int fwk_interrupt_set_isr_fault(void (*isr)(void))
200 {
201 if (!initialized) {
202 return FWK_E_INIT;
203 }
204
205 if (isr == NULL) {
206 return FWK_E_PARAM;
207 }
208
209 return fwk_interrupt_driver->set_isr_fault(isr);
210 }
211