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 <kernel/dt_driver.h> 10 #include <mm/core_memprot.h> 11 #include <sys/queue.h> 12 #include <tee_api_types.h> 13 #include <types_ext.h> 14 #include <util.h> 15 16 #define ITRF_TRIGGER_LEVEL BIT(0) 17 #define ITRF_SHARED BIT(1) 18 19 /* Forward the interrupt only to the current CPU */ 20 #define ITR_CPU_MASK_TO_THIS_CPU BIT(31) 21 /* Forward the interrupt to all CPUs except the current CPU */ 22 #define ITR_CPU_MASK_TO_OTHER_CPUS BIT(30) 23 24 struct itr_handler; 25 26 /* 27 * struct itr_chip - Interrupt controller 28 * 29 * @ops Operation callback functions 30 * @name Controller name, for debug purpose 31 * @handlers Registered handlers list head 32 * @dt_get_irq Device tree node parsing function 33 */ 34 struct itr_chip { 35 const struct itr_ops *ops; 36 const char *name; 37 SLIST_HEAD(, itr_handler) handlers; 38 /* 39 * dt_get_irq - parse a device tree interrupt property 40 * 41 * @properties Big-endian interrupt property array from device tree 42 * @count number of elements in @properties 43 * @type If not NULL, output interrupt type (IRQ_TYPE_* defines) 44 * or IRQ_TYPE_NONE if unknown 45 * @prio If not NULL, output interrupt priority value or 0 if unknown 46 */ 47 int (*dt_get_irq)(const uint32_t *properties, int count, uint32_t *type, 48 uint32_t *prio); 49 }; 50 51 /* 52 * struct itr_ops - Interrupt controller operations 53 * @configure Configure an interrupt 54 * @enable Enable an interrupt 55 * @disable Disable an interrupt 56 * @mask Mask an interrupt, may be called from an interrupt context 57 * @unmask Unmask an interrupt, may be called from an interrupt context 58 * @raise_pi Raise per-cpu interrupt or NULL if not applicable 59 * @raise_sgi Raise a SGI or NULL if not applicable to that controller 60 * @set_affinity Set interrupt/cpu affinity or NULL if not applicable 61 * 62 * Handlers @enable, @disable, @mask, @unmask and @configure are mandated. 63 * Handlers @mask and @unmask have unpaged memory constraints. 64 * See itr_chip_is_valid(). 65 */ 66 struct itr_ops { 67 void (*configure)(struct itr_chip *chip, size_t it, uint32_t type, 68 uint32_t prio); 69 void (*enable)(struct itr_chip *chip, size_t it); 70 void (*disable)(struct itr_chip *chip, size_t it); 71 void (*mask)(struct itr_chip *chip, size_t it); 72 void (*unmask)(struct itr_chip *chip, size_t it); 73 void (*raise_pi)(struct itr_chip *chip, size_t it); 74 void (*raise_sgi)(struct itr_chip *chip, size_t it, 75 uint32_t cpu_mask); 76 void (*set_affinity)(struct itr_chip *chip, size_t it, 77 uint8_t cpu_mask); 78 }; 79 80 /* 81 * struct itr_desc - Interrupt description 82 * @chip Interrupt controller reference 83 * @itr_num Interrupt number 84 * 85 * This struct is used for binding interrupt device data between 86 * drivers when using DT_DRIVERS means. See itr_dt_get_func type 87 * definition. 88 */ 89 struct itr_desc { 90 struct itr_chip *chip; 91 size_t itr_num; 92 }; 93 94 /* Interrupt handler return value */ 95 enum itr_return { 96 ITRR_NONE, 97 ITRR_HANDLED, 98 }; 99 100 /* Interrupt handler signature */ 101 typedef enum itr_return (*itr_handler_t)(struct itr_handler *h); 102 103 /* 104 * struct itr_handler - Interrupt handler reference 105 * @it Interrupt number 106 * @flags Property bit flags (ITRF_*) or 0 107 * @data Private data for that interrupt handler 108 * @chip Interrupt controller chip device 109 * @link Reference in controller handler list 110 */ 111 struct itr_handler { 112 size_t it; 113 uint32_t flags; 114 itr_handler_t handler; 115 void *data; 116 struct itr_chip *chip; 117 SLIST_ENTRY(itr_handler) link; 118 }; 119 120 #define ITR_HANDLER(_chip, _itr_num, _flags, _fn, _priv) \ 121 ((struct itr_handler){ \ 122 .chip = (_chip), .it = (_itr_num), .flags = (_flags), \ 123 .handler = (_fn), .data = (_priv), \ 124 }) 125 126 /* 127 * Return true only if interrupt chip provides required handlers 128 * @chip: Interrupt controller reference 129 */ 130 static inline bool itr_chip_is_valid(struct itr_chip *chip) 131 { 132 return chip && is_unpaged(chip) && chip->ops && 133 is_unpaged((void *)chip->ops) && 134 chip->ops->mask && is_unpaged(chip->ops->mask) && 135 chip->ops->unmask && is_unpaged(chip->ops->unmask) && 136 chip->ops->enable && chip->ops->disable && 137 chip->ops->configure; 138 } 139 140 /* 141 * Initialise an interrupt controller handle 142 * @chip Interrupt controller 143 */ 144 TEE_Result itr_chip_init(struct itr_chip *chip); 145 146 /* 147 * Initialise main interrupt controller driver 148 * @data Main controller main data reference to register 149 */ 150 void interrupt_main_init(struct itr_chip *data); 151 152 /* Retrieve main interrupt controller reference */ 153 struct itr_chip *interrupt_get_main_chip(void); 154 /* Retrieve main interrupt controller reference, or NULL on failure */ 155 struct itr_chip *interrupt_get_main_chip_may_fail(void); 156 157 #ifdef CFG_DT 158 /* 159 * Get the DT interrupt property at @node. In the DT an interrupt property can 160 * specify additional information which can be retrieved with @type and @prio. 161 * 162 * @fdt reference to the Device Tree 163 * @node is the node offset to read the interrupt property from 164 * @type interrupt type (IRQ_TYPE_* defines) if specified by interrupt property 165 * or IRQ_TYPE_NONE if not. Can be NULL if not needed 166 * @prio interrupt priority if specified by interrupt property or 0 if not. Can 167 * be NULL if not needed 168 * 169 * Returns the interrupt number if value >= 0 170 * otherwise DT_INFO_INVALID_INTERRUPT 171 */ 172 int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type, 173 uint32_t *prio); 174 175 /* 176 * Get the DT interrupt property at @node 177 */ 178 static inline int dt_get_irq(const void *fdt, int node) 179 { 180 return dt_get_irq_type_prio(fdt, node, NULL, NULL); 181 } 182 #endif 183 184 /* 185 * __weak overridable function which is called when a secure interrupt is 186 * received. The default function calls panic() immediately, platforms which 187 * expects to receive secure interrupts should override this function. 188 */ 189 void interrupt_main_handler(void); 190 191 /* 192 * Interrupt controller chip API functions 193 */ 194 195 /* 196 * interrupt_call_handlers() - Call registered handlers for an interrupt 197 * @chip Interrupt controller 198 * @itr_num Interrupt number 199 * 200 * This function is called from an interrupt context by a primary interrupt 201 * handler. This function calls the handlers registered for that interrupt. 202 * If interrupt is not handled, it is masked. 203 */ 204 void interrupt_call_handlers(struct itr_chip *chip, size_t itr_num); 205 206 /* 207 * interrupt_mask() - Mask an interrupt 208 * @chip Interrupt controller 209 * @itr_num Interrupt number 210 * 211 * This function may be called in interrupt context 212 */ 213 static inline void interrupt_mask(struct itr_chip *chip, size_t itr_num) 214 { 215 chip->ops->mask(chip, itr_num); 216 } 217 218 /* 219 * interrupt_unmask() - Unmask an interrupt 220 * @chip Interrupt controller 221 * @itr_num Interrupt number 222 * 223 * This function may be called in interrupt context 224 */ 225 static inline void interrupt_unmask(struct itr_chip *chip, size_t itr_num) 226 { 227 chip->ops->unmask(chip, itr_num); 228 } 229 230 /* 231 * interrupt_enable() - Enable an interrupt 232 * @chip Interrupt controller 233 * @itr_num Interrupt number 234 */ 235 static inline void interrupt_enable(struct itr_chip *chip, size_t itr_num) 236 { 237 chip->ops->enable(chip, itr_num); 238 } 239 240 /* 241 * interrupt_disable() - Disable an interrupt 242 * @chip Interrupt controller 243 * @itr_num Interrupt number 244 */ 245 static inline void interrupt_disable(struct itr_chip *chip, size_t itr_num) 246 { 247 chip->ops->disable(chip, itr_num); 248 } 249 250 /* 251 * interrupt_can_raise_pi() - Return whether controller embeds raise_pi 252 * @chip Interrupt controller 253 */ 254 static inline bool interrupt_can_raise_pi(struct itr_chip *chip) 255 { 256 return chip->ops->raise_pi; 257 } 258 259 /* 260 * interrupt_can_raise_sgi() - Return whether controller embeds raise_sgi 261 * @chip Interrupt controller 262 */ 263 static inline bool interrupt_can_raise_sgi(struct itr_chip *chip) 264 { 265 return chip->ops->raise_sgi; 266 } 267 268 /* 269 * interrupt_can_set_affinity() - Return whether controller embeds set_affinity 270 * @chip Interrupt controller 271 */ 272 static inline bool interrupt_can_set_affinity(struct itr_chip *chip) 273 { 274 return chip->ops->set_affinity; 275 } 276 277 /* 278 * interrupt_raise_pi() - Raise a peripheral interrupt of a controller 279 * @chip Interrupt controller 280 * @itr_num Interrupt number to raise 281 */ 282 static inline void interrupt_raise_pi(struct itr_chip *chip, size_t itr_num) 283 { 284 assert(interrupt_can_raise_pi(chip)); 285 chip->ops->raise_pi(chip, itr_num); 286 } 287 288 /* 289 * interrupt_raise_sgi() - Raise a software generiated interrupt of a controller 290 * @chip Interrupt controller 291 * @itr_num Interrupt number to raise 292 * @cpu_mask: A bitfield of CPUs to forward the interrupt to, unless 293 * ITR_CPU_MASK_TO_THIS_CPU or ITR_CPU_MASK_TO_OTHER_CPUS 294 * (mutually exclusive) are set. 295 */ 296 static inline void interrupt_raise_sgi(struct itr_chip *chip, size_t itr_num, 297 uint32_t cpu_mask) 298 { 299 assert(interrupt_can_raise_sgi(chip)); 300 chip->ops->raise_sgi(chip, itr_num, cpu_mask); 301 } 302 303 /* 304 * interrupt_set_affinity() - Set CPU affinity for a controller interrupt 305 * @chip Interrupt controller 306 * @itr_num Interrupt number to raise 307 * @cpu_mask Mask of the CPUs targeted by the interrupt 308 */ 309 static inline void interrupt_set_affinity(struct itr_chip *chip, size_t itr_num, 310 uint8_t cpu_mask) 311 { 312 assert(interrupt_can_set_affinity(chip)); 313 chip->ops->set_affinity(chip, itr_num, cpu_mask); 314 } 315 316 /* 317 * interrupt_configure() - Configure an interrupt in an interrupt controller 318 * @chip Interrupt controller 319 * @itr_num Interrupt number 320 * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE 321 * @prio Interrupt priority or 0 322 * 323 * Interrupt consumers that get their interrupt from the DT do not need to 324 * call interrupt_configure() since the interrupt configuration has already 325 * been done by interrupt controller based on the DT bidings. 326 */ 327 TEE_Result interrupt_configure(struct itr_chip *chip, size_t itr_num, 328 uint32_t type, uint32_t prio); 329 330 /* 331 * interrupt_add_and_configure_handler() - Register and configure a handler 332 * @hdl Interrupt handler to register 333 * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE 334 * @prio Interrupt priority or 0 335 */ 336 TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl, 337 uint32_t type, uint32_t prio); 338 339 /* 340 * interrupt_add_handler() - Register an interrupt handler 341 * @hdl Interrupt handler to register 342 * 343 * This helper function assumes interrupt type is set to IRQ_TYPE_NONE 344 * and interrupt priority to 0. 345 */ 346 static inline TEE_Result interrupt_add_handler(struct itr_handler *hdl) 347 { 348 return interrupt_add_configure_handler(hdl, IRQ_TYPE_NONE, 0); 349 } 350 351 /* 352 * interrupt_create_handler() - Allocate/register an interrupt callback handler 353 * @itr_chip Interrupt chip obtained from interrupt_dt_get_by_*() or like 354 * @itr_num Interrupt number obtained from interrupt_dt_get_by_*() or like 355 * @callback Callback handler function 356 * @priv Private dat to pssa to @callback 357 * @flags INTERRUPT_FLAGS_* or 0 358 * @out_hdl Output allocated and registered handler or NULL 359 * 360 * This function differs from interrupt_add_handler() in that the 361 * interrupt is not reconfigured. interrupt_create_handler() expects 362 * @itr_chip and @itr_num were obtained from a call 363 * to interrupt_dt_get_by_index() or interrupt_dt_get_by_name() that 364 * are in charge of configuring the interrupt according to its DT property. 365 */ 366 TEE_Result interrupt_create_handler(struct itr_chip *itr_chip, size_t itr_num, 367 itr_handler_t callback, void *priv, 368 uint32_t flags, 369 struct itr_handler **out_hdl); 370 371 /* 372 * interrupt_add_handler_with_chip() - Register an interrupt handler providing 373 * the interrupt chip reference in specific argument @chip. 374 * @chip Interrupt controller 375 * @h Interrupt handler to register 376 */ 377 static inline TEE_Result interrupt_add_handler_with_chip(struct itr_chip *chip, 378 struct itr_handler *h) 379 { 380 h->chip = chip; 381 return interrupt_add_handler(h); 382 } 383 384 /* 385 * interrupt_remove_handler() - Remove a registered interrupt handler 386 * @hdl Interrupt handler to remove 387 * 388 * This function is the counterpart of interrupt_add_handler(). 389 * This function may panic on non-NULL invalid @hdl reference. 390 */ 391 void interrupt_remove_handler(struct itr_handler *hdl); 392 393 /* 394 * interrupt_alloc_add_conf_handler() - Allocate, configure, register a handler 395 * @chip Interrupt controller 396 * @itr_num Interrupt number 397 * @handler Interrupt handler to register 398 * @flags Bitmask flag ITRF_* 399 * @data Private data reference passed to @handler 400 * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE 401 * @prio Interrupt priority or 0 402 * @out_hdl NULL or output pointer to allocated struct itr_handler 403 */ 404 TEE_Result interrupt_alloc_add_conf_handler(struct itr_chip *chip, 405 size_t it_num, 406 itr_handler_t handler, 407 uint32_t flags, void *data, 408 uint32_t type, uint32_t prio, 409 struct itr_handler **out_hdl); 410 411 /* 412 * interrupt_alloc_add_handler() - Allocate and register an interrupt handler 413 * @chip Interrupt controller 414 * @itr_num Interrupt number 415 * @handler Interrupt handler to register 416 * @flags Bitmask flag ITRF_* 417 * @data Private data reference passed to @handler 418 * @out_hdl NULL or output pointer to allocated struct itr_handler 419 */ 420 static inline TEE_Result interrupt_alloc_add_handler(struct itr_chip *chip, 421 size_t it_num, 422 itr_handler_t handler, 423 uint32_t flags, 424 void *data, 425 struct itr_handler **hdl) 426 { 427 return interrupt_alloc_add_conf_handler(chip, it_num, handler, flags, 428 data, IRQ_TYPE_NONE, 0, hdl); 429 } 430 431 /* 432 * interrupt_remove_free_handler() - Remove/free a registered interrupt handler 433 * @hdl Interrupt handler to remove and free 434 * 435 * This function is the counterpart of interrupt_alloc_add_handler() 436 * and interrupt_alloc_add_conf_handler(). 437 * This function may panic on non-NULL invalid @hdl reference. 438 */ 439 void interrupt_remove_free_handler(struct itr_handler *hdl); 440 441 /* 442 * itr_dt_get_func - Typedef of function to get an interrupt in DT node 443 * 444 * @args Reference to phandle arguments 445 * @data Pointer to data given at interrupt_register_provider() call 446 * @itr_desc_p Pointer to the struct itr_desc to fill 447 * Return TEE_SUCCESS in case of success. 448 * Return TEE_ERROR_DEFER_DRIVER_INIT if controller is not initialized. 449 * Return another TEE_Result code otherwise. 450 * 451 * Upon success, the interrupt is configured and consumer can add a handler 452 * function to the interrupt. Yet, the interrupt is not enabled until consumer 453 * calls interrupt_enable(). 454 */ 455 typedef TEE_Result (*itr_dt_get_func)(struct dt_pargs *args, void *data, 456 struct itr_desc *itr_desc_p); 457 458 #ifdef CFG_DT 459 /** 460 * interrupt_register_provider() - Register an interrupt provider 461 * 462 * @fdt Device tree to work on 463 * @node Node offset of the interrupt controller in the DT 464 * @dt_get_itr Callback to match the devicetree interrupt reference with 465 * @data Data which will be passed to the get_dt_its callback 466 */ 467 TEE_Result interrupt_register_provider(const void *fdt, int node, 468 itr_dt_get_func dt_get_itr, void *data); 469 470 /** 471 * interrupt_dt_get_by_index() - Get an interrupt from DT by interrupt index 472 * 473 * Interrupt index (@index) refers to the index of the target interrupt to be 474 * retrieved as DT binding property "interrupts" may define several 475 * interrupts. 476 * 477 * @fdt Device tree to work on 478 * @node Node offset of the subnode containing interrupt(s) references 479 * @index Index in "interrupts" or "interrupts-extended" property list 480 * @chip Output interrupt controller reference upon success 481 * @itr_num Output interrupt number upon success 482 * 483 * Return TEE_SUCCESS in case of success 484 * Return TEE_ERROR_DEFER_DRIVER_INIT if interrupt driver is not yet initialized 485 * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not reference target interrupt 486 * Return any other TEE_Result compliant code in case of error 487 */ 488 TEE_Result interrupt_dt_get_by_index(const void *fdt, int node, 489 unsigned int index, struct itr_chip **chip, 490 size_t *itr_num); 491 492 /** 493 * interrupt_dt_get_by_name() - Get an interrupt from DT by interrupt name 494 * 495 * @fdt Device tree to work on 496 * @node Node offset of the subnode containing interrupt(s) references 497 * @name Name identifier used in "interrupt-names" property 498 * @chip Output interrupt controller reference upon success 499 * @itr_num Output interrupt number upon success 500 * 501 * Return TEE_SUCCESS in case of success 502 * Return TEE_ERROR_DEFER_DRIVER_INIT if interrupt driver is not yet initialized 503 * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not reference target interrupt 504 * Return any other TEE_Result compliant code in case of error 505 */ 506 TEE_Result interrupt_dt_get_by_name(const void *fdt, int node, const char *name, 507 struct itr_chip **chip, size_t *itr_num); 508 #else 509 static inline TEE_Result interrupt_register_provider(const void *dt __unused, 510 int node __unused, 511 itr_dt_get_func f __unused, 512 void *data __unused) 513 { 514 return TEE_ERROR_NOT_IMPLEMENTED; 515 } 516 517 static inline TEE_Result interrupt_dt_get_by_index(const void *fdt __unused, 518 int node __unused, 519 unsigned int index __unused, 520 struct itr_chip **c __unused, 521 size_t *itr_num __unused) 522 { 523 return TEE_ERROR_NOT_IMPLEMENTED; 524 } 525 526 static inline TEE_Result interrupt_dt_get_by_name(const void *fdt __unused, 527 int node __unused, 528 const char *name __unused, 529 struct itr_chip **ch __unused, 530 size_t *itr_num __unused) 531 { 532 return TEE_ERROR_NOT_IMPLEMENTED; 533 } 534 #endif /*CFG_DT*/ 535 536 /* 537 * Helper function for when caller retrieves the first interrupt defined 538 * in "interrupts" or "interrupts-extended" DT binding property list. 539 */ 540 static inline TEE_Result interrupt_dt_get(const void *fdt, int node, 541 struct itr_chip **chip, 542 size_t *itr_num) 543 { 544 return interrupt_dt_get_by_index(fdt, node, 0, chip, itr_num); 545 } 546 #endif /*__KERNEL_INTERRUPT_H*/ 547