11bb92983SJerome Forissier /* SPDX-License-Identifier: BSD-2-Clause */ 27315b7b4SJens Wiklander /* 3e9f46c74SJens Wiklander * Copyright (c) 2016-2019, Linaro Limited 47315b7b4SJens Wiklander */ 57315b7b4SJens Wiklander #ifndef __KERNEL_INTERRUPT_H 67315b7b4SJens Wiklander #define __KERNEL_INTERRUPT_H 77315b7b4SJens Wiklander 8702fe5a7SClément Léger #include <dt-bindings/interrupt-controller/irq.h> 9*33a0c835SEtienne Carriere #include <kernel/dt_driver.h> 10f932e355SEtienne Carriere #include <mm/core_memprot.h> 117315b7b4SJens Wiklander #include <sys/queue.h> 12f932e355SEtienne Carriere #include <tee_api_types.h> 13f932e355SEtienne Carriere #include <types_ext.h> 141c832d7cSdavidwang #include <util.h> 157315b7b4SJens Wiklander 161c832d7cSdavidwang #define ITRF_TRIGGER_LEVEL BIT(0) 171c832d7cSdavidwang #define ITRF_SHARED BIT(1) 187315b7b4SJens Wiklander 19ec740b9fSJens Wiklander /* Forward the interrupt only to the current CPU */ 20ec740b9fSJens Wiklander #define ITR_CPU_MASK_TO_THIS_CPU BIT(31) 21ec740b9fSJens Wiklander /* Forward the interrupt to all CPUs except the current CPU */ 22ec740b9fSJens Wiklander #define ITR_CPU_MASK_TO_OTHER_CPUS BIT(30) 23ec740b9fSJens Wiklander 24f932e355SEtienne Carriere struct itr_handler; 25f932e355SEtienne Carriere 26a009881dSEtienne Carriere /* 27a009881dSEtienne Carriere * struct itr_chip - Interrupt controller 28a009881dSEtienne Carriere * 29a009881dSEtienne Carriere * @ops Operation callback functions 30f932e355SEtienne Carriere * @name Controller name, for debug purpose 31f932e355SEtienne Carriere * @handlers Registered handlers list head 32a009881dSEtienne Carriere * @dt_get_irq Device tree node parsing function 33a009881dSEtienne Carriere */ 347315b7b4SJens Wiklander struct itr_chip { 357315b7b4SJens Wiklander const struct itr_ops *ops; 36f932e355SEtienne Carriere const char *name; 37f932e355SEtienne Carriere SLIST_HEAD(, itr_handler) handlers; 38702fe5a7SClément Léger /* 39702fe5a7SClément Léger * dt_get_irq - parse a device tree interrupt property 40702fe5a7SClément Léger * 41702fe5a7SClément Léger * @properties raw interrupt property from device tree 42702fe5a7SClément Léger * @count number of elements in @properties 43702fe5a7SClément Léger * @type If not NULL, output interrupt type (IRQ_TYPE_* defines) 44702fe5a7SClément Léger * or IRQ_TYPE_NONE if unknown 45702fe5a7SClément Léger * @prio If not NULL, output interrupt priority value or 0 if unknown 46702fe5a7SClément Léger */ 47702fe5a7SClément Léger int (*dt_get_irq)(const uint32_t *properties, int count, uint32_t *type, 48702fe5a7SClément Léger uint32_t *prio); 497315b7b4SJens Wiklander }; 507315b7b4SJens Wiklander 51a009881dSEtienne Carriere /* 52a009881dSEtienne Carriere * struct itr_ops - Interrupt controller operations 53a009881dSEtienne Carriere * @add Register and configure an interrupt 54a009881dSEtienne Carriere * @enable Enable an interrupt 55a009881dSEtienne Carriere * @disable Disable an interrupt 56f932e355SEtienne Carriere * @mask Mask an interrupt, may be called from an interrupt context 57f932e355SEtienne Carriere * @unmask Unmask an interrupt, may be called from an interrupt context 58a009881dSEtienne Carriere * @raise_pi Raise per-cpu interrupt or NULL if not applicable 59a009881dSEtienne Carriere * @raise_sgi Raise a SGI or NULL if not applicable to that controller 60a009881dSEtienne Carriere * @set_affinity Set interrupt/cpu affinity or NULL if not applicable 61f932e355SEtienne Carriere * 62f932e355SEtienne Carriere * Handlers @enable, @disable, @mask, @unmask and @add are mandated. Handlers 63f932e355SEtienne Carriere * @mask and @unmask have unpaged memory contrainsts. See itr_chip_is_valid(). 64a009881dSEtienne Carriere */ 657315b7b4SJens Wiklander struct itr_ops { 66702fe5a7SClément Léger void (*add)(struct itr_chip *chip, size_t it, uint32_t type, 67702fe5a7SClément Léger uint32_t prio); 687315b7b4SJens Wiklander void (*enable)(struct itr_chip *chip, size_t it); 697315b7b4SJens Wiklander void (*disable)(struct itr_chip *chip, size_t it); 70f932e355SEtienne Carriere void (*mask)(struct itr_chip *chip, size_t it); 71f932e355SEtienne Carriere void (*unmask)(struct itr_chip *chip, size_t it); 7226ed70ecSGuanchao Liang void (*raise_pi)(struct itr_chip *chip, size_t it); 7326ed70ecSGuanchao Liang void (*raise_sgi)(struct itr_chip *chip, size_t it, 74ec740b9fSJens Wiklander uint32_t cpu_mask); 7526ed70ecSGuanchao Liang void (*set_affinity)(struct itr_chip *chip, size_t it, 7626ed70ecSGuanchao Liang uint8_t cpu_mask); 777315b7b4SJens Wiklander }; 787315b7b4SJens Wiklander 79*33a0c835SEtienne Carriere /* 80*33a0c835SEtienne Carriere * struct itr_desc - Interrupt description 81*33a0c835SEtienne Carriere * @chip Interrupt controller reference 82*33a0c835SEtienne Carriere * @itr_num Interrupt number 83*33a0c835SEtienne Carriere * 84*33a0c835SEtienne Carriere * This struct is used for binding interrupt device data between 85*33a0c835SEtienne Carriere * drivers when using DT_DRIVERS means. See itr_dt_get_func type 86*33a0c835SEtienne Carriere * definition. 87*33a0c835SEtienne Carriere */ 88*33a0c835SEtienne Carriere struct itr_desc { 89*33a0c835SEtienne Carriere struct itr_chip *chip; 90*33a0c835SEtienne Carriere size_t itr_num; 91*33a0c835SEtienne Carriere }; 92*33a0c835SEtienne Carriere 93a009881dSEtienne Carriere /* Interrupt handler return value */ 947315b7b4SJens Wiklander enum itr_return { 957315b7b4SJens Wiklander ITRR_NONE, 967315b7b4SJens Wiklander ITRR_HANDLED, 977315b7b4SJens Wiklander }; 987315b7b4SJens Wiklander 99a009881dSEtienne Carriere /* Interrupt handler signature */ 100acc5dd21SLudovic Barre typedef enum itr_return (*itr_handler_t)(struct itr_handler *h); 101acc5dd21SLudovic Barre 102a009881dSEtienne Carriere /* 103a009881dSEtienne Carriere * struct itr_handler - Interrupt handler reference 104a009881dSEtienne Carriere * @it Interrupt number 105f932e355SEtienne Carriere * @flags Property bit flags (ITRF_*) or 0 106a009881dSEtienne Carriere * @data Private data for that interrupt handler 107f932e355SEtienne Carriere * @chip Interrupt controller chip device 108a009881dSEtienne Carriere * @link Reference in controller handler list 109a009881dSEtienne Carriere */ 1107315b7b4SJens Wiklander struct itr_handler { 1117315b7b4SJens Wiklander size_t it; 1127315b7b4SJens Wiklander uint32_t flags; 113acc5dd21SLudovic Barre itr_handler_t handler; 1147315b7b4SJens Wiklander void *data; 115f932e355SEtienne Carriere struct itr_chip *chip; 1167315b7b4SJens Wiklander SLIST_ENTRY(itr_handler) link; 1177315b7b4SJens Wiklander }; 1187315b7b4SJens Wiklander 119f932e355SEtienne Carriere #define ITR_HANDLER(_chip, _itr_num, _flags, _fn, _priv) \ 120f932e355SEtienne Carriere ((struct itr_handler){ \ 121f932e355SEtienne Carriere .chip = (_chip), .it = (_itr_num), .flags = (_flags), \ 122f932e355SEtienne Carriere .handler = (_fn), .data = (_priv), \ 123f932e355SEtienne Carriere }) 124f932e355SEtienne Carriere 125f932e355SEtienne Carriere /* 126f932e355SEtienne Carriere * Return true only if interrupt chip provides required handlers 127f932e355SEtienne Carriere * @chip: Interrupt controller reference 128f932e355SEtienne Carriere */ 129f932e355SEtienne Carriere static inline bool itr_chip_is_valid(struct itr_chip *chip) 130f932e355SEtienne Carriere { 131f932e355SEtienne Carriere return chip && is_unpaged(chip) && chip->ops && 132f932e355SEtienne Carriere is_unpaged((void *)chip->ops) && 133f932e355SEtienne Carriere chip->ops->mask && is_unpaged(chip->ops->mask) && 134f932e355SEtienne Carriere chip->ops->unmask && is_unpaged(chip->ops->unmask) && 135f932e355SEtienne Carriere chip->ops->enable && chip->ops->disable && 136f932e355SEtienne Carriere chip->ops->add; 137f932e355SEtienne Carriere } 138f932e355SEtienne Carriere 139f932e355SEtienne Carriere /* 140f932e355SEtienne Carriere * Initialise an interrupt controller handle 141f932e355SEtienne Carriere * @chip Interrupt controller 142f932e355SEtienne Carriere */ 143f932e355SEtienne Carriere TEE_Result itr_chip_init(struct itr_chip *chip); 144f932e355SEtienne Carriere 14501980f3fSEtienne Carriere /* 146a009881dSEtienne Carriere * Initialise main interrupt controller driver 147a009881dSEtienne Carriere * @data Main controller main data reference to register 14801980f3fSEtienne Carriere */ 14901980f3fSEtienne Carriere void interrupt_main_init(struct itr_chip *data); 15001980f3fSEtienne Carriere 151e050e0a7SEtienne Carriere /* Retrieve main interrupt controller reference */ 152e050e0a7SEtienne Carriere struct itr_chip *interrupt_get_main_chip(void); 153e050e0a7SEtienne Carriere 15467729d8dSLudovic Barre #ifdef CFG_DT 15567729d8dSLudovic Barre /* 156702fe5a7SClément Léger * Get the DT interrupt property at @node. In the DT an interrupt property can 157702fe5a7SClément Léger * specify additional information which can be retrieved with @type and @prio. 15867729d8dSLudovic Barre * 15967729d8dSLudovic Barre * @fdt reference to the Device Tree 160702fe5a7SClément Léger * @node is the node offset to read the interrupt property from 161702fe5a7SClément Léger * @type interrupt type (IRQ_TYPE_* defines) if specified by interrupt property 162702fe5a7SClément Léger * or IRQ_TYPE_NONE if not. Can be NULL if not needed 163702fe5a7SClément Léger * @prio interrupt priority if specified by interrupt property or 0 if not. Can 164702fe5a7SClément Léger * be NULL if not needed 16567729d8dSLudovic Barre * 16667729d8dSLudovic Barre * Returns the interrupt number if value >= 0 16767729d8dSLudovic Barre * otherwise DT_INFO_INVALID_INTERRUPT 16867729d8dSLudovic Barre */ 169702fe5a7SClément Léger int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type, 170702fe5a7SClément Léger uint32_t *prio); 171702fe5a7SClément Léger 172702fe5a7SClément Léger /* 173702fe5a7SClément Léger * Get the DT interrupt property at @node 174702fe5a7SClément Léger */ 175702fe5a7SClément Léger static inline int dt_get_irq(const void *fdt, int node) 176702fe5a7SClément Léger { 177702fe5a7SClément Léger return dt_get_irq_type_prio(fdt, node, NULL, NULL); 178702fe5a7SClément Léger } 17967729d8dSLudovic Barre #endif 18067729d8dSLudovic Barre 181e9f46c74SJens Wiklander /* 182e9f46c74SJens Wiklander * __weak overridable function which is called when a secure interrupt is 183e9f46c74SJens Wiklander * received. The default function calls panic() immediately, platforms which 184e9f46c74SJens Wiklander * expects to receive secure interrupts should override this function. 185e9f46c74SJens Wiklander */ 186358bf47cSEtienne Carriere void interrupt_main_handler(void); 187e9f46c74SJens Wiklander 188f932e355SEtienne Carriere /* 189f932e355SEtienne Carriere * Interrupt controller chip API functions 190f932e355SEtienne Carriere */ 191f932e355SEtienne Carriere 192f932e355SEtienne Carriere /* 193f932e355SEtienne Carriere * interrupt_call_handlers() - Call registered handlers for an interrupt 194f932e355SEtienne Carriere * @chip Interrupt controller 195f932e355SEtienne Carriere * @itr_num Interrupt number 196f932e355SEtienne Carriere * 197f932e355SEtienne Carriere * This function is called from an interrupt context by a primary interrupt 198f932e355SEtienne Carriere * handler. This function calls the handlers registered for that interrupt. 199f932e355SEtienne Carriere * If interrupt is not handled, it is masked. 200f932e355SEtienne Carriere */ 201f932e355SEtienne Carriere void interrupt_call_handlers(struct itr_chip *chip, size_t itr_num); 202f932e355SEtienne Carriere 203f932e355SEtienne Carriere /* 204f932e355SEtienne Carriere * interrupt_mask() - Mask an interrupt 205f932e355SEtienne Carriere * @chip Interrupt controller 206f932e355SEtienne Carriere * @itr_num Interrupt number 207f932e355SEtienne Carriere * 208f932e355SEtienne Carriere * This function may be called in interrupt context 209f932e355SEtienne Carriere */ 210f932e355SEtienne Carriere static inline void interrupt_mask(struct itr_chip *chip, size_t itr_num) 211f932e355SEtienne Carriere { 212f932e355SEtienne Carriere chip->ops->mask(chip, itr_num); 213f932e355SEtienne Carriere } 214f932e355SEtienne Carriere 215f932e355SEtienne Carriere /* 216f932e355SEtienne Carriere * interrupt_unmask() - Unmask an interrupt 217f932e355SEtienne Carriere * @chip Interrupt controller 218f932e355SEtienne Carriere * @itr_num Interrupt number 219f932e355SEtienne Carriere * 220f932e355SEtienne Carriere * This function may be called in interrupt context 221f932e355SEtienne Carriere */ 222f932e355SEtienne Carriere static inline void interrupt_unmask(struct itr_chip *chip, size_t itr_num) 223f932e355SEtienne Carriere { 224f932e355SEtienne Carriere chip->ops->unmask(chip, itr_num); 225f932e355SEtienne Carriere } 226f932e355SEtienne Carriere 227f932e355SEtienne Carriere /* 228f932e355SEtienne Carriere * interrupt_enable() - Enable an interrupt 229f932e355SEtienne Carriere * @chip Interrupt controller 230f932e355SEtienne Carriere * @itr_num Interrupt number 231f932e355SEtienne Carriere */ 232f932e355SEtienne Carriere static inline void interrupt_enable(struct itr_chip *chip, size_t itr_num) 233f932e355SEtienne Carriere { 234f932e355SEtienne Carriere chip->ops->enable(chip, itr_num); 235f932e355SEtienne Carriere } 236f932e355SEtienne Carriere 237f932e355SEtienne Carriere /* 238f932e355SEtienne Carriere * interrupt_disable() - Disable an interrupt 239f932e355SEtienne Carriere * @chip Interrupt controller 240f932e355SEtienne Carriere * @itr_num Interrupt number 241f932e355SEtienne Carriere */ 242f932e355SEtienne Carriere static inline void interrupt_disable(struct itr_chip *chip, size_t itr_num) 243f932e355SEtienne Carriere { 244f932e355SEtienne Carriere chip->ops->disable(chip, itr_num); 245f932e355SEtienne Carriere } 246f932e355SEtienne Carriere 247f932e355SEtienne Carriere /* 248b2d6db21SEtienne Carriere * interrupt_can_raise_pi() - Return whether controller embeds raise_pi 249b2d6db21SEtienne Carriere * @chip Interrupt controller 250b2d6db21SEtienne Carriere */ 251b2d6db21SEtienne Carriere static inline bool interrupt_can_raise_pi(struct itr_chip *chip) 252b2d6db21SEtienne Carriere { 253b2d6db21SEtienne Carriere return chip->ops->raise_pi; 254b2d6db21SEtienne Carriere } 255b2d6db21SEtienne Carriere 256b2d6db21SEtienne Carriere /* 257b2d6db21SEtienne Carriere * interrupt_can_raise_sgi() - Return whether controller embeds raise_sgi 258b2d6db21SEtienne Carriere * @chip Interrupt controller 259b2d6db21SEtienne Carriere */ 260b2d6db21SEtienne Carriere static inline bool interrupt_can_raise_sgi(struct itr_chip *chip) 261b2d6db21SEtienne Carriere { 262b2d6db21SEtienne Carriere return chip->ops->raise_sgi; 263b2d6db21SEtienne Carriere } 264b2d6db21SEtienne Carriere 265b2d6db21SEtienne Carriere /* 266b2d6db21SEtienne Carriere * interrupt_can_set_affinity() - Return whether controller embeds set_affinity 267b2d6db21SEtienne Carriere * @chip Interrupt controller 268b2d6db21SEtienne Carriere */ 269b2d6db21SEtienne Carriere static inline bool interrupt_can_set_affinity(struct itr_chip *chip) 270b2d6db21SEtienne Carriere { 271b2d6db21SEtienne Carriere return chip->ops->set_affinity; 272b2d6db21SEtienne Carriere } 273b2d6db21SEtienne Carriere 274b2d6db21SEtienne Carriere /* 275b2d6db21SEtienne Carriere * interrupt_raise_pi() - Raise a peripheral interrupt of a controller 276b2d6db21SEtienne Carriere * @chip Interrupt controller 277b2d6db21SEtienne Carriere * @itr_num Interrupt number to raise 278b2d6db21SEtienne Carriere */ 279b2d6db21SEtienne Carriere static inline void interrupt_raise_pi(struct itr_chip *chip, size_t itr_num) 280b2d6db21SEtienne Carriere { 281b2d6db21SEtienne Carriere assert(interrupt_can_raise_pi(chip)); 282b2d6db21SEtienne Carriere chip->ops->raise_pi(chip, itr_num); 283b2d6db21SEtienne Carriere } 284b2d6db21SEtienne Carriere 285b2d6db21SEtienne Carriere /* 286b2d6db21SEtienne Carriere * interrupt_raise_sgi() - Raise a software generiated interrupt of a controller 287b2d6db21SEtienne Carriere * @chip Interrupt controller 288b2d6db21SEtienne Carriere * @itr_num Interrupt number to raise 289ec740b9fSJens Wiklander * @cpu_mask: A bitfield of CPUs to forward the interrupt to, unless 290ec740b9fSJens Wiklander * ITR_CPU_MASK_TO_THIS_CPU or ITR_CPU_MASK_TO_OTHER_CPUS 291ec740b9fSJens Wiklander * (mutually exclusive) are set. 292b2d6db21SEtienne Carriere */ 293b2d6db21SEtienne Carriere static inline void interrupt_raise_sgi(struct itr_chip *chip, size_t itr_num, 294ec740b9fSJens Wiklander uint32_t cpu_mask) 295b2d6db21SEtienne Carriere { 296b2d6db21SEtienne Carriere assert(interrupt_can_raise_sgi(chip)); 297b2d6db21SEtienne Carriere chip->ops->raise_sgi(chip, itr_num, cpu_mask); 298b2d6db21SEtienne Carriere } 299b2d6db21SEtienne Carriere 300b2d6db21SEtienne Carriere /* 301b2d6db21SEtienne Carriere * interrupt_set_affinity() - Set CPU affinity for a controller interrupt 302b2d6db21SEtienne Carriere * @chip Interrupt controller 303b2d6db21SEtienne Carriere * @itr_num Interrupt number to raise 304b2d6db21SEtienne Carriere * @cpu_mask Mask of the CPUs targeted by the interrupt 305b2d6db21SEtienne Carriere */ 306b2d6db21SEtienne Carriere static inline void interrupt_set_affinity(struct itr_chip *chip, size_t itr_num, 307b2d6db21SEtienne Carriere uint8_t cpu_mask) 308b2d6db21SEtienne Carriere { 309b2d6db21SEtienne Carriere assert(interrupt_can_set_affinity(chip)); 310b2d6db21SEtienne Carriere chip->ops->set_affinity(chip, itr_num, cpu_mask); 311b2d6db21SEtienne Carriere } 312b2d6db21SEtienne Carriere 313b2d6db21SEtienne Carriere /* 314f932e355SEtienne Carriere * interrupt_configure() - Configure an interrupt in an interrupt controller 315f932e355SEtienne Carriere * @chip Interrupt controller 316f932e355SEtienne Carriere * @itr_num Interrupt number 317f932e355SEtienne Carriere * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE 318f932e355SEtienne Carriere * @prio Interrupt priority or 0 319f932e355SEtienne Carriere * 320f932e355SEtienne Carriere * Interrupt consumers that get their interrupt from the DT do not need to 321f932e355SEtienne Carriere * call interrupt_configure() since the interrupt configuration has already 322f932e355SEtienne Carriere * been done by interrupt controller based on the DT bidings. 323f932e355SEtienne Carriere */ 324f932e355SEtienne Carriere TEE_Result interrupt_configure(struct itr_chip *chip, size_t itr_num, 325f932e355SEtienne Carriere uint32_t type, uint32_t prio); 326f932e355SEtienne Carriere 327f932e355SEtienne Carriere /* 328f932e355SEtienne Carriere * interrupt_add_and_configure_handler() - Register and configure a handler 329f932e355SEtienne Carriere * @hdl Interrupt handler to register 330f932e355SEtienne Carriere * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE 331f932e355SEtienne Carriere * @prio Interrupt priority or 0 332f932e355SEtienne Carriere */ 333f932e355SEtienne Carriere TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl, 334f932e355SEtienne Carriere uint32_t type, uint32_t prio); 335f932e355SEtienne Carriere 336f932e355SEtienne Carriere /* 337f932e355SEtienne Carriere * interrupt_add_handler() - Register an interrupt handler 338f932e355SEtienne Carriere * @hdl Interrupt handler to register 339f932e355SEtienne Carriere * 340f932e355SEtienne Carriere * This helper function assumes interrupt type is set to IRQ_TYPE_NONE 341f932e355SEtienne Carriere * and interrupt priority to 0. 342f932e355SEtienne Carriere */ 343f932e355SEtienne Carriere static inline TEE_Result interrupt_add_handler(struct itr_handler *hdl) 344f932e355SEtienne Carriere { 345f932e355SEtienne Carriere return interrupt_add_configure_handler(hdl, IRQ_TYPE_NONE, 0); 346f932e355SEtienne Carriere } 347f932e355SEtienne Carriere 348f932e355SEtienne Carriere /* 349f932e355SEtienne Carriere * interrupt_add_handler_with_chip() - Register an interrupt handler providing 350f932e355SEtienne Carriere * the interrupt chip reference in specific argument @chip. 351f932e355SEtienne Carriere * @chip Interrupt controller 352f932e355SEtienne Carriere * @h Interrupt handler to register 353f932e355SEtienne Carriere */ 354f932e355SEtienne Carriere static inline TEE_Result interrupt_add_handler_with_chip(struct itr_chip *chip, 355f932e355SEtienne Carriere struct itr_handler *h) 356f932e355SEtienne Carriere { 357f932e355SEtienne Carriere h->chip = chip; 358f932e355SEtienne Carriere return interrupt_add_handler(h); 359f932e355SEtienne Carriere } 360f932e355SEtienne Carriere 361f932e355SEtienne Carriere /* 362f932e355SEtienne Carriere * interrupt_remove_handler() - Remove a registered interrupt handler 363f932e355SEtienne Carriere * @hdl Interrupt handler to remove 364f932e355SEtienne Carriere * 365f932e355SEtienne Carriere * This function is the counterpart of interrupt_add_handler(). 366f932e355SEtienne Carriere * This function may panic on non-NULL invalid @hdl reference. 367f932e355SEtienne Carriere */ 368f932e355SEtienne Carriere void interrupt_remove_handler(struct itr_handler *hdl); 369f932e355SEtienne Carriere 370f932e355SEtienne Carriere /* 3711b5c7ca4SEtienne Carriere * interrupt_alloc_add_conf_handler() - Allocate, configure, register a handler 3721b5c7ca4SEtienne Carriere * @chip Interrupt controller 3731b5c7ca4SEtienne Carriere * @itr_num Interrupt number 3741b5c7ca4SEtienne Carriere * @handler Interrupt handler to register 3751b5c7ca4SEtienne Carriere * @flags Bitmask flag ITRF_* 3761b5c7ca4SEtienne Carriere * @data Private data reference passed to @handler 3771b5c7ca4SEtienne Carriere * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE 3781b5c7ca4SEtienne Carriere * @prio Interrupt priority or 0 3791b5c7ca4SEtienne Carriere * @out_hdl NULL or output pointer to allocated struct itr_handler 3801b5c7ca4SEtienne Carriere */ 3811b5c7ca4SEtienne Carriere TEE_Result interrupt_alloc_add_conf_handler(struct itr_chip *chip, 3821b5c7ca4SEtienne Carriere size_t it_num, 3831b5c7ca4SEtienne Carriere itr_handler_t handler, 3841b5c7ca4SEtienne Carriere uint32_t flags, void *data, 3851b5c7ca4SEtienne Carriere uint32_t type, uint32_t prio, 3861b5c7ca4SEtienne Carriere struct itr_handler **out_hdl); 3871b5c7ca4SEtienne Carriere 3881b5c7ca4SEtienne Carriere /* 389f932e355SEtienne Carriere * interrupt_alloc_add_handler() - Allocate and register an interrupt handler 390f932e355SEtienne Carriere * @chip Interrupt controller 391f932e355SEtienne Carriere * @itr_num Interrupt number 392f932e355SEtienne Carriere * @handler Interrupt handler to register 393f932e355SEtienne Carriere * @flags Bitmask flag ITRF_* 394f932e355SEtienne Carriere * @data Private data reference passed to @handler 395f932e355SEtienne Carriere * @out_hdl NULL or output pointer to allocated struct itr_handler 396f932e355SEtienne Carriere */ 3971b5c7ca4SEtienne Carriere static inline TEE_Result interrupt_alloc_add_handler(struct itr_chip *chip, 3981b5c7ca4SEtienne Carriere size_t it_num, 3991b5c7ca4SEtienne Carriere itr_handler_t handler, 4001b5c7ca4SEtienne Carriere uint32_t flags, 401f932e355SEtienne Carriere void *data, 4021b5c7ca4SEtienne Carriere struct itr_handler **hdl) 4031b5c7ca4SEtienne Carriere { 4041b5c7ca4SEtienne Carriere return interrupt_alloc_add_conf_handler(chip, it_num, handler, flags, 4051b5c7ca4SEtienne Carriere data, IRQ_TYPE_NONE, 0, hdl); 4061b5c7ca4SEtienne Carriere } 407f932e355SEtienne Carriere 408f932e355SEtienne Carriere /* 409f932e355SEtienne Carriere * interrupt_remove_free_handler() - Remove/free a registered interrupt handler 410f932e355SEtienne Carriere * @hdl Interrupt handler to remove and free 411f932e355SEtienne Carriere * 4121b5c7ca4SEtienne Carriere * This function is the counterpart of interrupt_alloc_add_handler() 4131b5c7ca4SEtienne Carriere * and interrupt_alloc_add_conf_handler(). 414f932e355SEtienne Carriere * This function may panic on non-NULL invalid @hdl reference. 415f932e355SEtienne Carriere */ 416f932e355SEtienne Carriere void interrupt_remove_free_handler(struct itr_handler *hdl); 417*33a0c835SEtienne Carriere 418*33a0c835SEtienne Carriere /* 419*33a0c835SEtienne Carriere * itr_dt_get_func - Typedef of function to get an interrupt in DT node 420*33a0c835SEtienne Carriere * 421*33a0c835SEtienne Carriere * @args Reference to phandle arguments 422*33a0c835SEtienne Carriere * @data Pointer to data given at interrupt_register_provider() call 423*33a0c835SEtienne Carriere * @itr_desc_p Pointer to the struct itr_desc to fill 424*33a0c835SEtienne Carriere * Return TEE_SUCCESS in case of success. 425*33a0c835SEtienne Carriere * Return TEE_ERROR_DEFER_DRIVER_INIT if controller is not initialized. 426*33a0c835SEtienne Carriere * Return another TEE_Result code otherwise. 427*33a0c835SEtienne Carriere * 428*33a0c835SEtienne Carriere * Upon success, the interrupt is configured and consumer can add a handler 429*33a0c835SEtienne Carriere * function to the interrupt. Yet, the interrupt is not enabled until consumer 430*33a0c835SEtienne Carriere * calls interrupt_enable(). 431*33a0c835SEtienne Carriere */ 432*33a0c835SEtienne Carriere typedef TEE_Result (*itr_dt_get_func)(struct dt_pargs *args, void *data, 433*33a0c835SEtienne Carriere struct itr_desc *itr_desc_p); 434*33a0c835SEtienne Carriere 435*33a0c835SEtienne Carriere #ifdef CFG_DT 436*33a0c835SEtienne Carriere /** 437*33a0c835SEtienne Carriere * interrupt_register_provider() - Register an interrupt provider 438*33a0c835SEtienne Carriere * 439*33a0c835SEtienne Carriere * @fdt Device tree to work on 440*33a0c835SEtienne Carriere * @node Node offset of the interrupt controller in the DT 441*33a0c835SEtienne Carriere * @dt_get_itr Callback to match the devicetree interrupt reference with 442*33a0c835SEtienne Carriere * @data Data which will be passed to the get_dt_its callback 443*33a0c835SEtienne Carriere */ 444*33a0c835SEtienne Carriere TEE_Result interrupt_register_provider(const void *fdt, int node, 445*33a0c835SEtienne Carriere itr_dt_get_func dt_get_itr, void *data); 446*33a0c835SEtienne Carriere 447*33a0c835SEtienne Carriere /** 448*33a0c835SEtienne Carriere * interrupt_dt_get_by_index() - Get an interrupt from DT by interrupt index 449*33a0c835SEtienne Carriere * 450*33a0c835SEtienne Carriere * Interrupt index (@index) refers to the index of the target interrupt to be 451*33a0c835SEtienne Carriere * retrieved as DT binding property "interrupts" may define several 452*33a0c835SEtienne Carriere * interrupts. 453*33a0c835SEtienne Carriere * 454*33a0c835SEtienne Carriere * @fdt Device tree to work on 455*33a0c835SEtienne Carriere * @node Node offset of the subnode containing interrupt(s) references 456*33a0c835SEtienne Carriere * @index Index in "interrupts" or "extended-interrupts" property list 457*33a0c835SEtienne Carriere * @chip Output interrupt controller reference upon success 458*33a0c835SEtienne Carriere * @itr_num Output interrupt number upon success 459*33a0c835SEtienne Carriere * 460*33a0c835SEtienne Carriere * Return TEE_SUCCESS in case of success 461*33a0c835SEtienne Carriere * Return TEE_ERROR_DEFER_DRIVER_INIT if interrupt driver is not yet initialized 462*33a0c835SEtienne Carriere * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not reference target interrupt 463*33a0c835SEtienne Carriere * Return any other TEE_Result compliant code in case of error 464*33a0c835SEtienne Carriere */ 465*33a0c835SEtienne Carriere TEE_Result interrupt_dt_get_by_index(const void *fdt, int node, 466*33a0c835SEtienne Carriere unsigned int index, struct itr_chip **chip, 467*33a0c835SEtienne Carriere size_t *itr_num); 468*33a0c835SEtienne Carriere 469*33a0c835SEtienne Carriere /** 470*33a0c835SEtienne Carriere * interrupt_dt_get_by_name() - Get an interrupt from DT by interrupt name 471*33a0c835SEtienne Carriere * 472*33a0c835SEtienne Carriere * @fdt Device tree to work on 473*33a0c835SEtienne Carriere * @node Node offset of the subnode containing interrupt(s) references 474*33a0c835SEtienne Carriere * @name Name identifier used in "interrupt-names" property 475*33a0c835SEtienne Carriere * @chip Output interrupt controller reference upon success 476*33a0c835SEtienne Carriere * @itr_num Output interrupt number upon success 477*33a0c835SEtienne Carriere * 478*33a0c835SEtienne Carriere * Return TEE_SUCCESS in case of success 479*33a0c835SEtienne Carriere * Return TEE_ERROR_DEFER_DRIVER_INIT if interrupt driver is not yet initialized 480*33a0c835SEtienne Carriere * Return TEE_ERROR_ITEM_NOT_FOUND if the DT does not reference target interrupt 481*33a0c835SEtienne Carriere * Return any other TEE_Result compliant code in case of error 482*33a0c835SEtienne Carriere */ 483*33a0c835SEtienne Carriere TEE_Result interrupt_dt_get_by_name(const void *fdt, int node, const char *name, 484*33a0c835SEtienne Carriere struct itr_chip **chip, size_t *itr_num); 485*33a0c835SEtienne Carriere #else 486*33a0c835SEtienne Carriere static inline TEE_Result interrupt_register_provider(const void *dt __unused, 487*33a0c835SEtienne Carriere int node __unused, 488*33a0c835SEtienne Carriere itr_dt_get_func f __unused, 489*33a0c835SEtienne Carriere void *data __unused) 490*33a0c835SEtienne Carriere { 491*33a0c835SEtienne Carriere return TEE_ERROR_NOT_IMPLEMENTED; 492*33a0c835SEtienne Carriere } 493*33a0c835SEtienne Carriere 494*33a0c835SEtienne Carriere static inline TEE_Result interrupt_dt_get_by_index(const void *fdt __unused, 495*33a0c835SEtienne Carriere int node __unused, 496*33a0c835SEtienne Carriere unsigned int index __unused, 497*33a0c835SEtienne Carriere struct itr_chip **c __unused, 498*33a0c835SEtienne Carriere size_t *itr_num __unused) 499*33a0c835SEtienne Carriere { 500*33a0c835SEtienne Carriere return TEE_ERROR_NOT_IMPLEMENTED; 501*33a0c835SEtienne Carriere } 502*33a0c835SEtienne Carriere 503*33a0c835SEtienne Carriere static inline TEE_Result interrupt_dt_get_by_name(const void *fdt __unused, 504*33a0c835SEtienne Carriere int node __unused, 505*33a0c835SEtienne Carriere const char *name __unused, 506*33a0c835SEtienne Carriere struct itr_chip **ch __unused, 507*33a0c835SEtienne Carriere size_t *itr_num __unused) 508*33a0c835SEtienne Carriere { 509*33a0c835SEtienne Carriere return TEE_ERROR_NOT_IMPLEMENTED; 510*33a0c835SEtienne Carriere } 511*33a0c835SEtienne Carriere #endif /*CFG_DT*/ 512*33a0c835SEtienne Carriere 513*33a0c835SEtienne Carriere /* 514*33a0c835SEtienne Carriere * Helper function for when caller retrieves the first interrupt defined 515*33a0c835SEtienne Carriere * in "interrupts" or "extended-interrupts" DT binding property list. 516*33a0c835SEtienne Carriere */ 517*33a0c835SEtienne Carriere static inline TEE_Result interrupt_dt_get(const void *fdt, int node, 518*33a0c835SEtienne Carriere struct itr_chip **chip, 519*33a0c835SEtienne Carriere size_t *itr_num) 520*33a0c835SEtienne Carriere { 521*33a0c835SEtienne Carriere return interrupt_dt_get_by_index(fdt, node, 0, chip, itr_num); 522*33a0c835SEtienne Carriere } 5237315b7b4SJens Wiklander #endif /*__KERNEL_INTERRUPT_H*/ 524