xref: /optee_os/core/include/kernel/interrupt.h (revision a009881d386dea9784f3c8643f036a3e290486df)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * Copyright (c) 2016-2019, Linaro Limited
4  */
5 #ifndef __KERNEL_INTERRUPT_H
6 #define __KERNEL_INTERRUPT_H
7 
8 #include <dt-bindings/interrupt-controller/irq.h>
9 #include <types_ext.h>
10 #include <sys/queue.h>
11 #include <util.h>
12 
13 #define ITRF_TRIGGER_LEVEL	BIT(0)
14 #define ITRF_SHARED		BIT(1)
15 
16 /*
17  * struct itr_chip - Interrupt controller
18  *
19  * @ops Operation callback functions
20  * @dt_get_irq Device tree node parsing function
21  */
22 struct itr_chip {
23 	const struct itr_ops *ops;
24 	/*
25 	 * dt_get_irq - parse a device tree interrupt property
26 	 *
27 	 * @properties raw interrupt property from device tree
28 	 * @count number of elements in @properties
29 	 * @type If not NULL, output interrupt type (IRQ_TYPE_* defines)
30 	 * or IRQ_TYPE_NONE if unknown
31 	 * @prio If not NULL, output interrupt priority value or 0 if unknown
32 	 */
33 	int (*dt_get_irq)(const uint32_t *properties, int count, uint32_t *type,
34 			  uint32_t *prio);
35 };
36 
37 /*
38  * struct itr_ops - Interrupt controller operations
39  * @add		Register and configure an interrupt
40  * @enable	Enable an interrupt
41  * @disable	Disable an interrupt
42  * @raise_pi	Raise per-cpu interrupt or NULL if not applicable
43  * @raise_sgi	Raise a SGI or NULL if not applicable to that controller
44  * @set_affinity Set interrupt/cpu affinity or NULL if not applicable
45  */
46 struct itr_ops {
47 	void (*add)(struct itr_chip *chip, size_t it, uint32_t type,
48 		    uint32_t prio);
49 	void (*enable)(struct itr_chip *chip, size_t it);
50 	void (*disable)(struct itr_chip *chip, size_t it);
51 	void (*raise_pi)(struct itr_chip *chip, size_t it);
52 	void (*raise_sgi)(struct itr_chip *chip, size_t it,
53 		uint8_t cpu_mask);
54 	void (*set_affinity)(struct itr_chip *chip, size_t it,
55 		uint8_t cpu_mask);
56 };
57 
58 /* Interrupt handler return value */
59 enum itr_return {
60 	ITRR_NONE,
61 	ITRR_HANDLED,
62 };
63 
64 struct itr_handler;
65 
66 /* Interrupt handler signature */
67 typedef enum itr_return (*itr_handler_t)(struct itr_handler *h);
68 
69 /*
70  * struct itr_handler - Interrupt handler reference
71  * @it Interrupt number
72  * @flags Property bit flags ITR_FLAG_*
73  * @data Private data for that interrupt handler
74  * @link Reference in controller handler list
75  */
76 struct itr_handler {
77 	size_t it;
78 	uint32_t flags;
79 	itr_handler_t handler;
80 	void *data;
81 	SLIST_ENTRY(itr_handler) link;
82 };
83 
84 /*
85  * Initialise main interrupt controller driver
86  * @data Main controller main data reference to register
87  */
88 void interrupt_main_init(struct itr_chip *data);
89 
90 /*
91  * Call handlers registered for that interrupt in core interrupt controller
92  * @it Interrupt line number
93  */
94 void itr_handle(size_t it);
95 
96 /* Retrieve main interrupt controller reference */
97 struct itr_chip *interrupt_get_main_chip(void);
98 
99 #ifdef CFG_DT
100 /*
101  * Get the DT interrupt property at @node. In the DT an interrupt property can
102  * specify additional information which can be retrieved with @type and @prio.
103  *
104  * @fdt reference to the Device Tree
105  * @node is the node offset to read the interrupt property from
106  * @type interrupt type (IRQ_TYPE_* defines) if specified by interrupt property
107  * or IRQ_TYPE_NONE if not. Can be NULL if not needed
108  * @prio interrupt priority if specified by interrupt property or 0 if not. Can
109  * be NULL if not needed
110  *
111  * Returns the interrupt number if value >= 0
112  * otherwise DT_INFO_INVALID_INTERRUPT
113  */
114 int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type,
115 			 uint32_t *prio);
116 
117 /*
118  * Get the DT interrupt property at @node
119  */
120 static inline int dt_get_irq(const void *fdt, int node)
121 {
122 	return dt_get_irq_type_prio(fdt, node, NULL, NULL);
123 }
124 #endif
125 
126 struct itr_handler *itr_alloc_add_type_prio(size_t it, itr_handler_t handler,
127 					    uint32_t flags, void *data,
128 					    uint32_t type, uint32_t prio);
129 void itr_free(struct itr_handler *hdl);
130 void itr_add_type_prio(struct itr_handler *handler, uint32_t type,
131 		       uint32_t prio);
132 void itr_enable(size_t it);
133 void itr_disable(size_t it);
134 /* raise the Peripheral Interrupt corresponding to the interrupt ID */
135 void itr_raise_pi(size_t it);
136 /*
137  * raise the Software Generated Interrupt corresponding to the interrupt ID,
138  * the cpu_mask represents which cpu interface to forward.
139  */
140 void itr_raise_sgi(size_t it, uint8_t cpu_mask);
141 /*
142  * let corresponding interrupt forward to the cpu interface
143  * according to the cpu_mask.
144  */
145 void itr_set_affinity(size_t it, uint8_t cpu_mask);
146 
147 /*
148  * __weak overridable function which is called when a secure interrupt is
149  * received. The default function calls panic() immediately, platforms which
150  * expects to receive secure interrupts should override this function.
151  */
152 void interrupt_main_handler(void);
153 
154 static inline void itr_add(struct itr_handler *handler)
155 {
156 	itr_add_type_prio(handler, IRQ_TYPE_NONE, 0);
157 }
158 
159 static inline struct itr_handler *itr_alloc_add(size_t it,
160 						itr_handler_t handler,
161 						uint32_t flags, void *data)
162 {
163 	return itr_alloc_add_type_prio(it, handler, flags, data, IRQ_TYPE_NONE,
164 				       0);
165 }
166 
167 #endif /*__KERNEL_INTERRUPT_H*/
168