1 /* Copyright 2018 SiFive, Inc */
2 /* SPDX-License-Identifier: Apache-2.0 */
4 #ifndef METAL__INTERRUPT_H
5 #define METAL__INTERRUPT_H
8 * @brief API for registering and manipulating interrupts
14 * @brief Possible interrupt controllers
16 typedef enum metal_interrupt_controller_ {
17 METAL_CPU_CONTROLLER = 0,
18 METAL_CLINT_CONTROLLER = 1,
19 METAL_CLIC_CONTROLLER = 2,
20 METAL_PLIC_CONTROLLER = 3
21 } metal_intr_cntrl_type;
24 * @brief Possible mode of interrupts to operate
26 typedef enum metal_vector_mode_ {
27 METAL_DIRECT_MODE = 0,
28 METAL_VECTOR_MODE = 1,
29 METAL_SELECTIVE_NONVECTOR_MODE = 2,
30 METAL_SELECTIVE_VECTOR_MODE = 3,
31 METAL_HARDWARE_VECTOR_MODE = 4
35 * @brief Possible mode of privilege interrupts to operate
37 typedef enum metal_intr_priv_mode_ {
38 METAL_INTR_PRIV_M_MODE = 0,
39 METAL_INTR_PRIV_MU_MODE = 1,
40 METAL_INTR_PRIV_MSU_MODE = 2
41 } metal_intr_priv_mode;
44 * @brief Function signature for interrupt callback handlers
46 typedef void (*metal_interrupt_handler_t) (int, void *);
47 typedef void (*metal_interrupt_vector_handler_t) (void);
49 struct metal_interrupt;
51 struct metal_interrupt_vtable {
52 void (*interrupt_init)(struct metal_interrupt *controller);
53 int (*interrupt_set_vector_mode)(struct metal_interrupt *controller, metal_vector_mode mode);
54 metal_vector_mode (*interrupt_get_vector_mode)(struct metal_interrupt *controller);
55 int (*interrupt_set_privilege)(struct metal_interrupt *controller, metal_intr_priv_mode priv);
56 metal_intr_priv_mode (*interrupt_get_privilege)(struct metal_interrupt *controller);
57 int (*interrupt_clear)(struct metal_interrupt *controller, int id);
58 int (*interrupt_set)(struct metal_interrupt *controller, int id);
59 int (*interrupt_register)(struct metal_interrupt *controller, int id,
60 metal_interrupt_handler_t isr, void *priv_data);
61 int (*interrupt_vector_register)(struct metal_interrupt *controller, int id,
62 metal_interrupt_vector_handler_t isr, void *priv_data);
63 int (*interrupt_enable)(struct metal_interrupt *controller, int id);
64 int (*interrupt_disable)(struct metal_interrupt *controller, int id);
65 int (*interrupt_vector_enable)(struct metal_interrupt *controller, int id);
66 int (*interrupt_vector_disable)(struct metal_interrupt *controller, int id);
67 unsigned int (*interrupt_get_threshold)(struct metal_interrupt *controller);
68 int (*interrupt_set_threshold)(struct metal_interrupt *controller, unsigned int threshold);
69 unsigned int (*interrupt_get_priority)(struct metal_interrupt *controller, int id);
70 int (*interrupt_set_priority)(struct metal_interrupt *controller, int id, unsigned int priority);
71 int (*command_request)(struct metal_interrupt *controller, int cmd, void *data);
72 int (*mtimecmp_set)(struct metal_interrupt *controller, int hartid, unsigned long long time);
76 * @brief A handle for an interrupt
78 struct metal_interrupt {
79 const struct metal_interrupt_vtable *vtable;
83 * @brief Initialize a given interrupt controller
85 * Initialize a given interrupt controller. This function must be called
86 * before any interrupts are registered or enabled with the handler. It
87 * is invalid to initialize an interrupt controller more than once.
89 * @param controller The handle for the interrupt controller
91 __inline__ void metal_interrupt_init(struct metal_interrupt *controller)
93 controller->vtable->interrupt_init(controller);
97 * @brief Get the handle for an given interrupt controller type
98 * @param cntrl The type ofinterrupt controller
99 * @param id The instance of the interrupt controller
100 * @return A handle to the interrupt controller (CLINT, CLIC, PLIC), or
101 * NULL if none is found for the requested label
103 struct metal_interrupt* metal_interrupt_get_controller(metal_intr_cntrl_type cntrl,
107 * @brief Configure vector mode for an interrupt controller
109 * Configure vector mode for an interrupt controller.
110 * This function must be called after initialization and before
111 * configuring individual interrupts, registering ISR.
113 * @param controller The handle for the interrupt controller
114 * @param mode The vector mode of the interrupt controller.
115 * @return 0 upon success
117 __inline__ int metal_interrupt_set_vector_mode(struct metal_interrupt *controller,
118 metal_vector_mode mode)
120 return controller->vtable->interrupt_set_vector_mode(controller, mode);
124 * @brief Get vector mode of a given an interrupt controller
126 * Configure vector mode for an interrupt controller.
127 * This function must be called after initialization and before
128 * configuring individual interrupts, registering ISR.
130 * @param controller The handle for the interrupt controller
131 * @param mode The vector mode of the interrupt controller.
132 * @return The interrupt vector mode
134 __inline__ metal_vector_mode metal_interrupt_get_vector_mode(struct metal_interrupt *controller)
136 return controller->vtable->interrupt_get_vector_mode(controller);
140 * @brief Configure privilege mode a of given interrupt controller
142 * Configure privilege mode for a given interrupt controller.
143 * This function must be called after initialization and before
144 * configuring individual interrupts, registering ISR.
146 * @param controller The handle for the interrupt controller
147 * @param privilege The privilege mode of the interrupt controller.
148 * @return 0 upon success
150 __inline__ int metal_interrupt_set_privilege(struct metal_interrupt *controller,
151 metal_intr_priv_mode privilege)
153 return controller->vtable->interrupt_set_privilege(controller, privilege);
157 * @brief Get privilege mode a of given interrupt controller
159 * Get privilege mode for a given interrupt controller.
160 * This function must be called after initialization and before
161 * configuring individual interrupts, registering ISR.
163 * @param controller The handle for the interrupt controller
164 * @return The interrupt privilege mode
166 __inline__ metal_intr_priv_mode metal_interrupt_get_privilege(struct metal_interrupt *controller)
168 return controller->vtable->interrupt_get_privilege(controller);
172 * @brief clear an interrupt
173 * @param controller The handle for the interrupt controller
174 * @param id The interrupt ID to trigger
175 * @return 0 upon success
177 __inline__ int metal_interrupt_clear(struct metal_interrupt *controller, int id)
179 return controller->vtable->interrupt_clear(controller, id);
183 * @brief Set an interrupt
184 * @param controller The handle for the interrupt controller
185 * @param id The interrupt ID to trigger
186 * @return 0 upon success
188 __inline__ int metal_interrupt_set(struct metal_interrupt *controller, int id)
190 return controller->vtable->interrupt_set(controller, id);
194 * @brief Register an interrupt handler
195 * @param controller The handle for the interrupt controller
196 * @param id The interrupt ID to register
197 * @param handler The interrupt handler callback
198 * @param priv_data Private data for the interrupt handler
199 * @return 0 upon success
201 __inline__ int metal_interrupt_register_handler(struct metal_interrupt *controller,
203 metal_interrupt_handler_t handler,
206 return controller->vtable->interrupt_register(controller, id, handler, priv_data);
210 * @brief Register an interrupt vector handler
211 * @param controller The handle for the interrupt controller
212 * @param id The interrupt ID to register
213 * @param handler The interrupt vector handler callback
214 * @param priv_data Private data for the interrupt handler
215 * @return 0 upon success
217 __inline__ int metal_interrupt_register_vector_handler(struct metal_interrupt *controller,
219 metal_interrupt_vector_handler_t handler,
222 return controller->vtable->interrupt_vector_register(controller, id, handler, priv_data);
226 * @brief Enable an interrupt
227 * @param controller The handle for the interrupt controller
228 * @param id The interrupt ID to enable
229 * @return 0 upon success
231 __inline__ int metal_interrupt_enable(struct metal_interrupt *controller, int id)
233 return controller->vtable->interrupt_enable(controller, id);
237 * @brief Disable an interrupt
238 * @param controller The handle for the interrupt controller
239 * @param id The interrupt ID to disable
240 * @return 0 upon success
242 __inline__ int metal_interrupt_disable(struct metal_interrupt *controller, int id)
244 return controller->vtable->interrupt_disable(controller, id);
248 * @brief Set interrupt threshold level
249 * @param controller The handle for the interrupt controller
250 * @param threshold The interrupt threshold level
251 * @return 0 upon success
253 inline int metal_interrupt_set_threshold(struct metal_interrupt *controller, unsigned int level)
255 return controller->vtable->interrupt_set_threshold(controller, level);
259 * @brief Get an interrupt threshold level
260 * @param controller The handle for the interrupt controller
261 * @return The interrupt threshold level
263 inline unsigned int metal_interrupt_get_threshold(struct metal_interrupt *controller)
265 return controller->vtable->interrupt_get_threshold(controller);
269 * @brief Set an interrupt priority level
270 * @param controller The handle for the interrupt controller
271 * @param id The interrupt ID to enable
272 * @param priority The interrupt priority level
273 * @return 0 upon success
275 inline int metal_interrupt_set_priority(struct metal_interrupt *controller,
276 int id, unsigned int priority)
278 return controller->vtable->interrupt_set_priority(controller, id, priority);
282 * @brief Get an interrupt priority level
283 * @param controller The handle for the interrupt controller
284 * @param id The interrupt ID to enable
285 * @return The interrupt priority level
287 inline unsigned int metal_interrupt_get_priority(struct metal_interrupt *controller, int id)
289 return controller->vtable->interrupt_get_priority(controller, id);
293 * @brief Enable an interrupt vector
294 * @param controller The handle for the interrupt controller
295 * @param id The interrupt ID to enable
296 * @return 0 upon success
298 __inline__ int metal_interrupt_vector_enable(struct metal_interrupt *controller, int id)
300 return controller->vtable->interrupt_vector_enable(controller, id);
304 * @brief Disable an interrupt vector
305 * @param controller The handle for the interrupt controller
306 * @param id The interrupt ID to disable
307 * @return 0 upon success
309 __inline__ int metal_interrupt_vector_disable(struct metal_interrupt *controller, int id)
311 return controller->vtable->interrupt_vector_disable(controller, id);
315 * @brief Default interrupt vector handler, that can be overriden by user
319 void __attribute__((weak, interrupt)) metal_interrupt_vector_handler(void);
322 * @brief Metal Software interrupt vector handler, that can be overriden by user
326 void __attribute__((weak, interrupt)) metal_software_interrupt_vector_handler(void);
329 * @brief Metal Timer interrupt vector handler, that can be overriden by user
333 void __attribute__((weak, interrupt)) metal_timer_interrupt_vector_handler(void);
336 * @brief Metal External interrupt vector handler, that can be overriden by user
340 void __attribute__((weak, interrupt)) metal_external_interrupt_vector_handler(void);
343 * @brief Metal Local 0 interrupt vector handler, that can be overriden by user
347 void __attribute__((weak, interrupt)) metal_lc0_interrupt_vector_handler(void);
350 * @brief Metal Local 1 interrupt vector handler, that can be overriden by user
354 void __attribute__((weak, interrupt)) metal_lc1_interrupt_vector_handler(void);
357 * @brief Metal Local 2 interrupt vector handler, that can be overriden by user
361 void __attribute__((weak, interrupt)) metal_lc2_interrupt_vector_handler(void);
364 * @brief Metal Local 3 interrupt vector handler, that can be overriden by user
368 void __attribute__((weak, interrupt)) metal_lc3_interrupt_vector_handler(void);
371 * @brief Metal Local 4 interrupt vector handler, that can be overriden by user
375 void __attribute__((weak, interrupt)) metal_lc4_interrupt_vector_handler(void);
378 * @brief Metal Local 5 interrupt vector handler, that can be overriden by user
382 void __attribute__((weak, interrupt)) metal_lc5_interrupt_vector_handler(void);
385 * @brief Metal Local 6 interrupt vector handler, that can be overriden by user
389 void __attribute__((weak, interrupt)) metal_lc6_interrupt_vector_handler(void);
392 * @brief Metal Local 7 interrupt vector handler, that can be overriden by user
396 void __attribute__((weak, interrupt)) metal_lc7_interrupt_vector_handler(void);
399 * @brief Metal Local 8 interrupt vector handler, that can be overriden by user
403 void __attribute__((weak, interrupt)) metal_lc8_interrupt_vector_handler(void);
406 * @brief Metal Local 9 interrupt vector handler, that can be overriden by user
410 void __attribute__((weak, interrupt)) metal_lc9_interrupt_vector_handler(void);
413 * @brief Metal Local 10 interrupt vector handler, that can be overriden by user
417 void __attribute__((weak, interrupt)) metal_lc10_interrupt_vector_handler(void);
420 * @brief Metal Local 11 interrupt vector handler, that can be overriden by user
424 void __attribute__((weak, interrupt)) metal_lc11_interrupt_vector_handler(void);
427 * @brief Metal Local 12 interrupt vector handler, that can be overriden by user
431 void __attribute__((weak, interrupt)) metal_lc12_interrupt_vector_handler(void);
434 * @brief Metal Local 13 interrupt vector handler, that can be overriden by user
438 void __attribute__((weak, interrupt)) metal_lc13_interrupt_vector_handler(void);
441 * @brief Metal Local 14 interrupt vector handler, that can be overriden by user
445 void __attribute__((weak, interrupt)) metal_lc14_interrupt_vector_handler(void);
448 * @brief Metal Local 15 interrupt vector handler, that can be overriden by user
452 void __attribute__((weak, interrupt)) metal_lc15_interrupt_vector_handler(void);
454 /* Utilities function to controll, manages devices via a given interrupt controller */
455 __inline__ int _metal_interrupt_command_request(struct metal_interrupt *controller,
458 return controller->vtable->command_request(controller, cmd, data);