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