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