1 /*
2 * Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 /*
8 * @file irq.h
9 * @brief Interrupt handling primitives for libmetal.
10 */
11
12 #ifndef __METAL_IRQ_CONTROLLER__H__
13 #define __METAL_IRQ_CONTROLLER__H__
14
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18
19 /** \defgroup irq Interrupt Handling Interfaces
20 * @{
21 */
22
23 #include <metal/irq.h>
24 #include <metal/list.h>
25 #include <stdlib.h>
26
27 /** IRQ ANY ID */
28 #define METAL_IRQ_ANY (-1)
29
30 /** IRQ state macro which will be passed to metal irq set state function
31 * to indicate which state the caller want the IRQ to change to.
32 */
33 #define METAL_IRQ_DISABLE 0U
34 #define METAL_IRQ_ENABLE 1U
35
36 struct metal_irq_controller;
37
38 /**
39 * @brief type of interrupt controller to set irq enable
40 * @param[in] irq_cntr pointer to interrupt controller
41 * @param[in] irq interrupt id
42 * @param[in] enable IRQ state
43 */
44 typedef void (*metal_irq_set_enable) (struct metal_irq_controller *irq_cntr,
45 int irq, unsigned int enable);
46
47 /**
48 * @brief type of controller specific registering interrupt function
49 * @param[in] irq_cntr pointer to interrupt controller
50 * @param[in] irq interrupt id
51 * @param[in] hd interrupt handler
52 * @param[in] arg argument which will be passed to the interrupt handler
53 * @return 0 for success, negative value for failure
54 */
55 typedef int (*metal_cntr_irq_register) (struct metal_irq_controller *irq_cntr,
56 int irq, metal_irq_handler hd,
57 void *arg);
58
59 /** Libmetal interrupt structure */
60 struct metal_irq {
61 metal_irq_handler hd; /**< Interrupt handler */
62 void *arg; /**< Argument to pass to the interrupt handler */
63 };
64
65 /** Libmetal interrupt controller structure */
66 struct metal_irq_controller {
67 int irq_base; /**< Start of IRQ number of the range managed by
68 * the IRQ controller
69 */
70 int irq_num; /**< Number of IRQs managed by the IRQ controller */
71 void *arg; /**< Argument to pass to interrupt controller function */
72 metal_irq_set_enable irq_set_enable; /**< function to set IRQ enable */
73 metal_cntr_irq_register irq_register; /**< function to register IRQ
74 * handler
75 */
76 struct metal_list node; /**< list node */
77 struct metal_irq *irqs; /**< Array of IRQs managed by the controller */
78 };
79
80 #define METAL_IRQ_CONTROLLER_DECLARE(_irq_controller, \
81 _irq_base, _irq_num, \
82 _arg, \
83 _irq_set_enable, \
84 _irq_register, \
85 _irqs) \
86 struct metal_irq_controller _irq_controller = { \
87 .irq_base = _irq_base, \
88 .irq_num = _irq_num, \
89 .arg = _arg, \
90 .irq_set_enable = _irq_set_enable, \
91 .irq_register = _irq_register, \
92 .irqs = _irqs,\
93 }
94
95 /**
96 * @brief metal_irq_register_controller
97 *
98 * Register IRQ controller
99 * This function will allocate IRQ ids if it was
100 * not predefined in the irq controller. There is no
101 * locking in the function, it is not supposed to be
102 * called by multiple threads.
103 *
104 * @param[in] cntr Interrupt controller to register
105 * @return 0 on success, or negative value for failure.
106 */
107 int metal_irq_register_controller(struct metal_irq_controller *cntr);
108
109 /**
110 * @brief metal_irq_handle
111 *
112 * Call registered IRQ handler
113 *
114 * @param[in] irq_data metal IRQ structure
115 * @param[in] irq IRQ id which will be passed to handler
116 * @return IRQ handler status
117 */
118 static inline
metal_irq_handle(struct metal_irq * irq_data,int irq)119 int metal_irq_handle(struct metal_irq *irq_data, int irq)
120 {
121 if (irq_data && irq_data->hd) {
122 return irq_data->hd(irq, irq_data->arg);
123 } else {
124 return METAL_IRQ_NOT_HANDLED;
125 }
126 }
127
128 /** @} */
129
130 #ifdef __cplusplus
131 }
132 #endif
133
134 #endif /* __METAL_IRQ__H__ */
135