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 /* Retrieve main interrupt controller reference */ 132 struct itr_chip *interrupt_get_main_chip(void); 133 134 #ifdef CFG_DT 135 /* 136 * Get the DT interrupt property at @node. In the DT an interrupt property can 137 * specify additional information which can be retrieved with @type and @prio. 138 * 139 * @fdt reference to the Device Tree 140 * @node is the node offset to read the interrupt property from 141 * @type interrupt type (IRQ_TYPE_* defines) if specified by interrupt property 142 * or IRQ_TYPE_NONE if not. Can be NULL if not needed 143 * @prio interrupt priority if specified by interrupt property or 0 if not. Can 144 * be NULL if not needed 145 * 146 * Returns the interrupt number if value >= 0 147 * otherwise DT_INFO_INVALID_INTERRUPT 148 */ 149 int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type, 150 uint32_t *prio); 151 152 /* 153 * Get the DT interrupt property at @node 154 */ 155 static inline int dt_get_irq(const void *fdt, int node) 156 { 157 return dt_get_irq_type_prio(fdt, node, NULL, NULL); 158 } 159 #endif 160 161 struct itr_handler *itr_alloc_add_type_prio(size_t it, itr_handler_t handler, 162 uint32_t flags, void *data, 163 uint32_t type, uint32_t prio); 164 void itr_free(struct itr_handler *hdl); 165 void itr_add_type_prio(struct itr_handler *handler, uint32_t type, 166 uint32_t prio); 167 void itr_enable(size_t it); 168 void itr_disable(size_t it); 169 /* raise the Peripheral Interrupt corresponding to the interrupt ID */ 170 void itr_raise_pi(size_t it); 171 /* 172 * raise the Software Generated Interrupt corresponding to the interrupt ID, 173 * the cpu_mask represents which cpu interface to forward. 174 */ 175 void itr_raise_sgi(size_t it, uint8_t cpu_mask); 176 /* 177 * let corresponding interrupt forward to the cpu interface 178 * according to the cpu_mask. 179 */ 180 void itr_set_affinity(size_t it, uint8_t cpu_mask); 181 182 /* 183 * __weak overridable function which is called when a secure interrupt is 184 * received. The default function calls panic() immediately, platforms which 185 * expects to receive secure interrupts should override this function. 186 */ 187 void interrupt_main_handler(void); 188 189 static inline void itr_add(struct itr_handler *handler) 190 { 191 itr_add_type_prio(handler, IRQ_TYPE_NONE, 0); 192 } 193 194 static inline struct itr_handler *itr_alloc_add(size_t it, 195 itr_handler_t handler, 196 uint32_t flags, void *data) 197 { 198 return itr_alloc_add_type_prio(it, handler, flags, data, IRQ_TYPE_NONE, 199 0); 200 } 201 202 /* 203 * Interrupt controller chip API functions 204 */ 205 206 /* 207 * interrupt_call_handlers() - Call registered handlers for an interrupt 208 * @chip Interrupt controller 209 * @itr_num Interrupt number 210 * 211 * This function is called from an interrupt context by a primary interrupt 212 * handler. This function calls the handlers registered for that interrupt. 213 * If interrupt is not handled, it is masked. 214 */ 215 void interrupt_call_handlers(struct itr_chip *chip, size_t itr_num); 216 217 /* 218 * interrupt_mask() - Mask an interrupt 219 * @chip Interrupt controller 220 * @itr_num Interrupt number 221 * 222 * This function may be called in interrupt context 223 */ 224 static inline void interrupt_mask(struct itr_chip *chip, size_t itr_num) 225 { 226 chip->ops->mask(chip, itr_num); 227 } 228 229 /* 230 * interrupt_unmask() - Unmask an interrupt 231 * @chip Interrupt controller 232 * @itr_num Interrupt number 233 * 234 * This function may be called in interrupt context 235 */ 236 static inline void interrupt_unmask(struct itr_chip *chip, size_t itr_num) 237 { 238 chip->ops->unmask(chip, itr_num); 239 } 240 241 /* 242 * interrupt_enable() - Enable an interrupt 243 * @chip Interrupt controller 244 * @itr_num Interrupt number 245 */ 246 static inline void interrupt_enable(struct itr_chip *chip, size_t itr_num) 247 { 248 chip->ops->enable(chip, itr_num); 249 } 250 251 /* 252 * interrupt_disable() - Disable an interrupt 253 * @chip Interrupt controller 254 * @itr_num Interrupt number 255 */ 256 static inline void interrupt_disable(struct itr_chip *chip, size_t itr_num) 257 { 258 chip->ops->disable(chip, itr_num); 259 } 260 261 /* 262 * interrupt_can_raise_pi() - Return whether controller embeds raise_pi 263 * @chip Interrupt controller 264 */ 265 static inline bool interrupt_can_raise_pi(struct itr_chip *chip) 266 { 267 return chip->ops->raise_pi; 268 } 269 270 /* 271 * interrupt_can_raise_sgi() - Return whether controller embeds raise_sgi 272 * @chip Interrupt controller 273 */ 274 static inline bool interrupt_can_raise_sgi(struct itr_chip *chip) 275 { 276 return chip->ops->raise_sgi; 277 } 278 279 /* 280 * interrupt_can_set_affinity() - Return whether controller embeds set_affinity 281 * @chip Interrupt controller 282 */ 283 static inline bool interrupt_can_set_affinity(struct itr_chip *chip) 284 { 285 return chip->ops->set_affinity; 286 } 287 288 /* 289 * interrupt_raise_pi() - Raise a peripheral interrupt of a controller 290 * @chip Interrupt controller 291 * @itr_num Interrupt number to raise 292 */ 293 static inline void interrupt_raise_pi(struct itr_chip *chip, size_t itr_num) 294 { 295 assert(interrupt_can_raise_pi(chip)); 296 chip->ops->raise_pi(chip, itr_num); 297 } 298 299 /* 300 * interrupt_raise_sgi() - Raise a software generiated interrupt of a controller 301 * @chip Interrupt controller 302 * @itr_num Interrupt number to raise 303 * @cpu_mask Mask of the CPUs targeted by the interrupt 304 */ 305 static inline void interrupt_raise_sgi(struct itr_chip *chip, size_t itr_num, 306 uint8_t cpu_mask) 307 { 308 assert(interrupt_can_raise_sgi(chip)); 309 chip->ops->raise_sgi(chip, itr_num, cpu_mask); 310 } 311 312 /* 313 * interrupt_set_affinity() - Set CPU affinity for a controller interrupt 314 * @chip Interrupt controller 315 * @itr_num Interrupt number to raise 316 * @cpu_mask Mask of the CPUs targeted by the interrupt 317 */ 318 static inline void interrupt_set_affinity(struct itr_chip *chip, size_t itr_num, 319 uint8_t cpu_mask) 320 { 321 assert(interrupt_can_set_affinity(chip)); 322 chip->ops->set_affinity(chip, itr_num, cpu_mask); 323 } 324 325 /* 326 * interrupt_configure() - Configure an interrupt in an interrupt controller 327 * @chip Interrupt controller 328 * @itr_num Interrupt number 329 * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE 330 * @prio Interrupt priority or 0 331 * 332 * Interrupt consumers that get their interrupt from the DT do not need to 333 * call interrupt_configure() since the interrupt configuration has already 334 * been done by interrupt controller based on the DT bidings. 335 */ 336 TEE_Result interrupt_configure(struct itr_chip *chip, size_t itr_num, 337 uint32_t type, uint32_t prio); 338 339 /* 340 * interrupt_add_and_configure_handler() - Register and configure a handler 341 * @hdl Interrupt handler to register 342 * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE 343 * @prio Interrupt priority or 0 344 */ 345 TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl, 346 uint32_t type, uint32_t prio); 347 348 /* 349 * interrupt_add_handler() - Register an interrupt handler 350 * @hdl Interrupt handler to register 351 * 352 * This helper function assumes interrupt type is set to IRQ_TYPE_NONE 353 * and interrupt priority to 0. 354 */ 355 static inline TEE_Result interrupt_add_handler(struct itr_handler *hdl) 356 { 357 return interrupt_add_configure_handler(hdl, IRQ_TYPE_NONE, 0); 358 } 359 360 /* 361 * interrupt_add_handler_with_chip() - Register an interrupt handler providing 362 * the interrupt chip reference in specific argument @chip. 363 * @chip Interrupt controller 364 * @h Interrupt handler to register 365 */ 366 static inline TEE_Result interrupt_add_handler_with_chip(struct itr_chip *chip, 367 struct itr_handler *h) 368 { 369 h->chip = chip; 370 return interrupt_add_handler(h); 371 } 372 373 /* 374 * interrupt_remove_handler() - Remove a registered interrupt handler 375 * @hdl Interrupt handler to remove 376 * 377 * This function is the counterpart of interrupt_add_handler(). 378 * This function may panic on non-NULL invalid @hdl reference. 379 */ 380 void interrupt_remove_handler(struct itr_handler *hdl); 381 382 /* 383 * interrupt_alloc_add_conf_handler() - Allocate, configure, register a handler 384 * @chip Interrupt controller 385 * @itr_num Interrupt number 386 * @handler Interrupt handler to register 387 * @flags Bitmask flag ITRF_* 388 * @data Private data reference passed to @handler 389 * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE 390 * @prio Interrupt priority or 0 391 * @out_hdl NULL or output pointer to allocated struct itr_handler 392 */ 393 TEE_Result interrupt_alloc_add_conf_handler(struct itr_chip *chip, 394 size_t it_num, 395 itr_handler_t handler, 396 uint32_t flags, void *data, 397 uint32_t type, uint32_t prio, 398 struct itr_handler **out_hdl); 399 400 /* 401 * interrupt_alloc_add_handler() - Allocate and register an interrupt handler 402 * @chip Interrupt controller 403 * @itr_num Interrupt number 404 * @handler Interrupt handler to register 405 * @flags Bitmask flag ITRF_* 406 * @data Private data reference passed to @handler 407 * @out_hdl NULL or output pointer to allocated struct itr_handler 408 */ 409 static inline TEE_Result interrupt_alloc_add_handler(struct itr_chip *chip, 410 size_t it_num, 411 itr_handler_t handler, 412 uint32_t flags, 413 void *data, 414 struct itr_handler **hdl) 415 { 416 return interrupt_alloc_add_conf_handler(chip, it_num, handler, flags, 417 data, IRQ_TYPE_NONE, 0, hdl); 418 } 419 420 /* 421 * interrupt_remove_free_handler() - Remove/free a registered interrupt handler 422 * @hdl Interrupt handler to remove and free 423 * 424 * This function is the counterpart of interrupt_alloc_add_handler() 425 * and interrupt_alloc_add_conf_handler(). 426 * This function may panic on non-NULL invalid @hdl reference. 427 */ 428 void interrupt_remove_free_handler(struct itr_handler *hdl); 429 #endif /*__KERNEL_INTERRUPT_H*/ 430