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 <mm/core_memprot.h> 10 #include <sys/queue.h> 11 #include <tee_api_types.h> 12 #include <types_ext.h> 13 #include <util.h> 14 15 #define ITRF_TRIGGER_LEVEL BIT(0) 16 #define ITRF_SHARED BIT(1) 17 18 struct itr_handler; 19 20 /* 21 * struct itr_chip - Interrupt controller 22 * 23 * @ops Operation callback functions 24 * @name Controller name, for debug purpose 25 * @handlers Registered handlers list head 26 * @dt_get_irq Device tree node parsing function 27 */ 28 struct itr_chip { 29 const struct itr_ops *ops; 30 const char *name; 31 SLIST_HEAD(, itr_handler) handlers; 32 /* 33 * dt_get_irq - parse a device tree interrupt property 34 * 35 * @properties raw interrupt property from device tree 36 * @count number of elements in @properties 37 * @type If not NULL, output interrupt type (IRQ_TYPE_* defines) 38 * or IRQ_TYPE_NONE if unknown 39 * @prio If not NULL, output interrupt priority value or 0 if unknown 40 */ 41 int (*dt_get_irq)(const uint32_t *properties, int count, uint32_t *type, 42 uint32_t *prio); 43 }; 44 45 /* 46 * struct itr_ops - Interrupt controller operations 47 * @add Register and configure an interrupt 48 * @enable Enable an interrupt 49 * @disable Disable an interrupt 50 * @mask Mask an interrupt, may be called from an interrupt context 51 * @unmask Unmask an interrupt, may be called from an interrupt context 52 * @raise_pi Raise per-cpu interrupt or NULL if not applicable 53 * @raise_sgi Raise a SGI or NULL if not applicable to that controller 54 * @set_affinity Set interrupt/cpu affinity or NULL if not applicable 55 * 56 * Handlers @enable, @disable, @mask, @unmask and @add are mandated. Handlers 57 * @mask and @unmask have unpaged memory contrainsts. See itr_chip_is_valid(). 58 */ 59 struct itr_ops { 60 void (*add)(struct itr_chip *chip, size_t it, uint32_t type, 61 uint32_t prio); 62 void (*enable)(struct itr_chip *chip, size_t it); 63 void (*disable)(struct itr_chip *chip, size_t it); 64 void (*mask)(struct itr_chip *chip, size_t it); 65 void (*unmask)(struct itr_chip *chip, size_t it); 66 void (*raise_pi)(struct itr_chip *chip, size_t it); 67 void (*raise_sgi)(struct itr_chip *chip, size_t it, 68 uint8_t cpu_mask); 69 void (*set_affinity)(struct itr_chip *chip, size_t it, 70 uint8_t cpu_mask); 71 }; 72 73 /* Interrupt handler return value */ 74 enum itr_return { 75 ITRR_NONE, 76 ITRR_HANDLED, 77 }; 78 79 /* Interrupt handler signature */ 80 typedef enum itr_return (*itr_handler_t)(struct itr_handler *h); 81 82 /* 83 * struct itr_handler - Interrupt handler reference 84 * @it Interrupt number 85 * @flags Property bit flags (ITRF_*) or 0 86 * @data Private data for that interrupt handler 87 * @chip Interrupt controller chip device 88 * @link Reference in controller handler list 89 */ 90 struct itr_handler { 91 size_t it; 92 uint32_t flags; 93 itr_handler_t handler; 94 void *data; 95 struct itr_chip *chip; 96 SLIST_ENTRY(itr_handler) link; 97 }; 98 99 #define ITR_HANDLER(_chip, _itr_num, _flags, _fn, _priv) \ 100 ((struct itr_handler){ \ 101 .chip = (_chip), .it = (_itr_num), .flags = (_flags), \ 102 .handler = (_fn), .data = (_priv), \ 103 }) 104 105 /* 106 * Return true only if interrupt chip provides required handlers 107 * @chip: Interrupt controller reference 108 */ 109 static inline bool itr_chip_is_valid(struct itr_chip *chip) 110 { 111 return chip && is_unpaged(chip) && chip->ops && 112 is_unpaged((void *)chip->ops) && 113 chip->ops->mask && is_unpaged(chip->ops->mask) && 114 chip->ops->unmask && is_unpaged(chip->ops->unmask) && 115 chip->ops->enable && chip->ops->disable && 116 chip->ops->add; 117 } 118 119 /* 120 * Initialise an interrupt controller handle 121 * @chip Interrupt controller 122 */ 123 TEE_Result itr_chip_init(struct itr_chip *chip); 124 125 /* 126 * Initialise main interrupt controller driver 127 * @data Main controller main data reference to register 128 */ 129 void interrupt_main_init(struct itr_chip *data); 130 131 /* 132 * Call handlers registered for that interrupt in core interrupt controller 133 * @it Interrupt line number 134 */ 135 void itr_handle(size_t it); 136 137 /* Retrieve main interrupt controller reference */ 138 struct itr_chip *interrupt_get_main_chip(void); 139 140 #ifdef CFG_DT 141 /* 142 * Get the DT interrupt property at @node. In the DT an interrupt property can 143 * specify additional information which can be retrieved with @type and @prio. 144 * 145 * @fdt reference to the Device Tree 146 * @node is the node offset to read the interrupt property from 147 * @type interrupt type (IRQ_TYPE_* defines) if specified by interrupt property 148 * or IRQ_TYPE_NONE if not. Can be NULL if not needed 149 * @prio interrupt priority if specified by interrupt property or 0 if not. Can 150 * be NULL if not needed 151 * 152 * Returns the interrupt number if value >= 0 153 * otherwise DT_INFO_INVALID_INTERRUPT 154 */ 155 int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type, 156 uint32_t *prio); 157 158 /* 159 * Get the DT interrupt property at @node 160 */ 161 static inline int dt_get_irq(const void *fdt, int node) 162 { 163 return dt_get_irq_type_prio(fdt, node, NULL, NULL); 164 } 165 #endif 166 167 struct itr_handler *itr_alloc_add_type_prio(size_t it, itr_handler_t handler, 168 uint32_t flags, void *data, 169 uint32_t type, uint32_t prio); 170 void itr_free(struct itr_handler *hdl); 171 void itr_add_type_prio(struct itr_handler *handler, uint32_t type, 172 uint32_t prio); 173 void itr_enable(size_t it); 174 void itr_disable(size_t it); 175 /* raise the Peripheral Interrupt corresponding to the interrupt ID */ 176 void itr_raise_pi(size_t it); 177 /* 178 * raise the Software Generated Interrupt corresponding to the interrupt ID, 179 * the cpu_mask represents which cpu interface to forward. 180 */ 181 void itr_raise_sgi(size_t it, uint8_t cpu_mask); 182 /* 183 * let corresponding interrupt forward to the cpu interface 184 * according to the cpu_mask. 185 */ 186 void itr_set_affinity(size_t it, uint8_t cpu_mask); 187 188 /* 189 * __weak overridable function which is called when a secure interrupt is 190 * received. The default function calls panic() immediately, platforms which 191 * expects to receive secure interrupts should override this function. 192 */ 193 void interrupt_main_handler(void); 194 195 static inline void itr_add(struct itr_handler *handler) 196 { 197 itr_add_type_prio(handler, IRQ_TYPE_NONE, 0); 198 } 199 200 static inline struct itr_handler *itr_alloc_add(size_t it, 201 itr_handler_t handler, 202 uint32_t flags, void *data) 203 { 204 return itr_alloc_add_type_prio(it, handler, flags, data, IRQ_TYPE_NONE, 205 0); 206 } 207 208 /* 209 * Interrupt controller chip API functions 210 */ 211 212 /* 213 * interrupt_call_handlers() - Call registered handlers for an interrupt 214 * @chip Interrupt controller 215 * @itr_num Interrupt number 216 * 217 * This function is called from an interrupt context by a primary interrupt 218 * handler. This function calls the handlers registered for that interrupt. 219 * If interrupt is not handled, it is masked. 220 */ 221 void interrupt_call_handlers(struct itr_chip *chip, size_t itr_num); 222 223 /* 224 * interrupt_mask() - Mask an interrupt 225 * @chip Interrupt controller 226 * @itr_num Interrupt number 227 * 228 * This function may be called in interrupt context 229 */ 230 static inline void interrupt_mask(struct itr_chip *chip, size_t itr_num) 231 { 232 chip->ops->mask(chip, itr_num); 233 } 234 235 /* 236 * interrupt_unmask() - Unmask an interrupt 237 * @chip Interrupt controller 238 * @itr_num Interrupt number 239 * 240 * This function may be called in interrupt context 241 */ 242 static inline void interrupt_unmask(struct itr_chip *chip, size_t itr_num) 243 { 244 chip->ops->unmask(chip, itr_num); 245 } 246 247 /* 248 * interrupt_enable() - Enable an interrupt 249 * @chip Interrupt controller 250 * @itr_num Interrupt number 251 */ 252 static inline void interrupt_enable(struct itr_chip *chip, size_t itr_num) 253 { 254 chip->ops->enable(chip, itr_num); 255 } 256 257 /* 258 * interrupt_disable() - Disable an interrupt 259 * @chip Interrupt controller 260 * @itr_num Interrupt number 261 */ 262 static inline void interrupt_disable(struct itr_chip *chip, size_t itr_num) 263 { 264 chip->ops->disable(chip, itr_num); 265 } 266 267 /* 268 * interrupt_configure() - Configure an interrupt in an interrupt controller 269 * @chip Interrupt controller 270 * @itr_num Interrupt number 271 * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE 272 * @prio Interrupt priority or 0 273 * 274 * Interrupt consumers that get their interrupt from the DT do not need to 275 * call interrupt_configure() since the interrupt configuration has already 276 * been done by interrupt controller based on the DT bidings. 277 */ 278 TEE_Result interrupt_configure(struct itr_chip *chip, size_t itr_num, 279 uint32_t type, uint32_t prio); 280 281 /* 282 * interrupt_add_and_configure_handler() - Register and configure a handler 283 * @hdl Interrupt handler to register 284 * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE 285 * @prio Interrupt priority or 0 286 */ 287 TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl, 288 uint32_t type, uint32_t prio); 289 290 /* 291 * interrupt_add_handler() - Register an interrupt handler 292 * @hdl Interrupt handler to register 293 * 294 * This helper function assumes interrupt type is set to IRQ_TYPE_NONE 295 * and interrupt priority to 0. 296 */ 297 static inline TEE_Result interrupt_add_handler(struct itr_handler *hdl) 298 { 299 return interrupt_add_configure_handler(hdl, IRQ_TYPE_NONE, 0); 300 } 301 302 /* 303 * interrupt_add_handler_with_chip() - Register an interrupt handler providing 304 * the interrupt chip reference in specific argument @chip. 305 * @chip Interrupt controller 306 * @h Interrupt handler to register 307 */ 308 static inline TEE_Result interrupt_add_handler_with_chip(struct itr_chip *chip, 309 struct itr_handler *h) 310 { 311 h->chip = chip; 312 return interrupt_add_handler(h); 313 } 314 315 /* 316 * interrupt_remove_handler() - Remove a registered interrupt handler 317 * @hdl Interrupt handler to remove 318 * 319 * This function is the counterpart of interrupt_add_handler(). 320 * This function may panic on non-NULL invalid @hdl reference. 321 */ 322 void interrupt_remove_handler(struct itr_handler *hdl); 323 324 /* 325 * interrupt_alloc_add_handler() - Allocate and register an interrupt handler 326 * @chip Interrupt controller 327 * @itr_num Interrupt number 328 * @handler Interrupt handler to register 329 * @flags Bitmask flag ITRF_* 330 * @data Private data reference passed to @handler 331 * @out_hdl NULL or output pointer to allocated struct itr_handler 332 */ 333 TEE_Result interrupt_alloc_add_handler(struct itr_chip *chip, size_t it_num, 334 itr_handler_t handler, uint32_t flags, 335 void *data, 336 struct itr_handler **out_hdl); 337 338 /* 339 * interrupt_remove_free_handler() - Remove/free a registered interrupt handler 340 * @hdl Interrupt handler to remove and free 341 * 342 * This function is the counterpart of interrupt_alloc_add_handler(). 343 * This function may panic on non-NULL invalid @hdl reference. 344 */ 345 void interrupt_remove_free_handler(struct itr_handler *hdl); 346 #endif /*__KERNEL_INTERRUPT_H*/ 347