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> 97315b7b4SJens Wiklander #include <types_ext.h> 107315b7b4SJens Wiklander #include <sys/queue.h> 111c832d7cSdavidwang #include <util.h> 127315b7b4SJens Wiklander 131c832d7cSdavidwang #define ITRF_TRIGGER_LEVEL BIT(0) 141c832d7cSdavidwang #define ITRF_SHARED BIT(1) 157315b7b4SJens Wiklander 16*a009881dSEtienne Carriere /* 17*a009881dSEtienne Carriere * struct itr_chip - Interrupt controller 18*a009881dSEtienne Carriere * 19*a009881dSEtienne Carriere * @ops Operation callback functions 20*a009881dSEtienne Carriere * @dt_get_irq Device tree node parsing function 21*a009881dSEtienne Carriere */ 227315b7b4SJens Wiklander struct itr_chip { 237315b7b4SJens Wiklander const struct itr_ops *ops; 24702fe5a7SClément Léger /* 25702fe5a7SClément Léger * dt_get_irq - parse a device tree interrupt property 26702fe5a7SClément Léger * 27702fe5a7SClément Léger * @properties raw interrupt property from device tree 28702fe5a7SClément Léger * @count number of elements in @properties 29702fe5a7SClément Léger * @type If not NULL, output interrupt type (IRQ_TYPE_* defines) 30702fe5a7SClément Léger * or IRQ_TYPE_NONE if unknown 31702fe5a7SClément Léger * @prio If not NULL, output interrupt priority value or 0 if unknown 32702fe5a7SClément Léger */ 33702fe5a7SClément Léger int (*dt_get_irq)(const uint32_t *properties, int count, uint32_t *type, 34702fe5a7SClément Léger uint32_t *prio); 357315b7b4SJens Wiklander }; 367315b7b4SJens Wiklander 37*a009881dSEtienne Carriere /* 38*a009881dSEtienne Carriere * struct itr_ops - Interrupt controller operations 39*a009881dSEtienne Carriere * @add Register and configure an interrupt 40*a009881dSEtienne Carriere * @enable Enable an interrupt 41*a009881dSEtienne Carriere * @disable Disable an interrupt 42*a009881dSEtienne Carriere * @raise_pi Raise per-cpu interrupt or NULL if not applicable 43*a009881dSEtienne Carriere * @raise_sgi Raise a SGI or NULL if not applicable to that controller 44*a009881dSEtienne Carriere * @set_affinity Set interrupt/cpu affinity or NULL if not applicable 45*a009881dSEtienne Carriere */ 467315b7b4SJens Wiklander struct itr_ops { 47702fe5a7SClément Léger void (*add)(struct itr_chip *chip, size_t it, uint32_t type, 48702fe5a7SClément Léger uint32_t prio); 497315b7b4SJens Wiklander void (*enable)(struct itr_chip *chip, size_t it); 507315b7b4SJens Wiklander void (*disable)(struct itr_chip *chip, size_t it); 5126ed70ecSGuanchao Liang void (*raise_pi)(struct itr_chip *chip, size_t it); 5226ed70ecSGuanchao Liang void (*raise_sgi)(struct itr_chip *chip, size_t it, 5326ed70ecSGuanchao Liang uint8_t cpu_mask); 5426ed70ecSGuanchao Liang void (*set_affinity)(struct itr_chip *chip, size_t it, 5526ed70ecSGuanchao Liang uint8_t cpu_mask); 567315b7b4SJens Wiklander }; 577315b7b4SJens Wiklander 58*a009881dSEtienne Carriere /* Interrupt handler return value */ 597315b7b4SJens Wiklander enum itr_return { 607315b7b4SJens Wiklander ITRR_NONE, 617315b7b4SJens Wiklander ITRR_HANDLED, 627315b7b4SJens Wiklander }; 637315b7b4SJens Wiklander 64acc5dd21SLudovic Barre struct itr_handler; 65acc5dd21SLudovic Barre 66*a009881dSEtienne Carriere /* Interrupt handler signature */ 67acc5dd21SLudovic Barre typedef enum itr_return (*itr_handler_t)(struct itr_handler *h); 68acc5dd21SLudovic Barre 69*a009881dSEtienne Carriere /* 70*a009881dSEtienne Carriere * struct itr_handler - Interrupt handler reference 71*a009881dSEtienne Carriere * @it Interrupt number 72*a009881dSEtienne Carriere * @flags Property bit flags ITR_FLAG_* 73*a009881dSEtienne Carriere * @data Private data for that interrupt handler 74*a009881dSEtienne Carriere * @link Reference in controller handler list 75*a009881dSEtienne Carriere */ 767315b7b4SJens Wiklander struct itr_handler { 777315b7b4SJens Wiklander size_t it; 787315b7b4SJens Wiklander uint32_t flags; 79acc5dd21SLudovic Barre itr_handler_t handler; 807315b7b4SJens Wiklander void *data; 817315b7b4SJens Wiklander SLIST_ENTRY(itr_handler) link; 827315b7b4SJens Wiklander }; 837315b7b4SJens Wiklander 8401980f3fSEtienne Carriere /* 85*a009881dSEtienne Carriere * Initialise main interrupt controller driver 86*a009881dSEtienne Carriere * @data Main controller main data reference to register 8701980f3fSEtienne Carriere */ 8801980f3fSEtienne Carriere void interrupt_main_init(struct itr_chip *data); 8901980f3fSEtienne Carriere 90*a009881dSEtienne Carriere /* 91*a009881dSEtienne Carriere * Call handlers registered for that interrupt in core interrupt controller 92*a009881dSEtienne Carriere * @it Interrupt line number 93*a009881dSEtienne Carriere */ 947315b7b4SJens Wiklander void itr_handle(size_t it); 957315b7b4SJens Wiklander 96e050e0a7SEtienne Carriere /* Retrieve main interrupt controller reference */ 97e050e0a7SEtienne Carriere struct itr_chip *interrupt_get_main_chip(void); 98e050e0a7SEtienne Carriere 9967729d8dSLudovic Barre #ifdef CFG_DT 10067729d8dSLudovic Barre /* 101702fe5a7SClément Léger * Get the DT interrupt property at @node. In the DT an interrupt property can 102702fe5a7SClément Léger * specify additional information which can be retrieved with @type and @prio. 10367729d8dSLudovic Barre * 10467729d8dSLudovic Barre * @fdt reference to the Device Tree 105702fe5a7SClément Léger * @node is the node offset to read the interrupt property from 106702fe5a7SClément Léger * @type interrupt type (IRQ_TYPE_* defines) if specified by interrupt property 107702fe5a7SClément Léger * or IRQ_TYPE_NONE if not. Can be NULL if not needed 108702fe5a7SClément Léger * @prio interrupt priority if specified by interrupt property or 0 if not. Can 109702fe5a7SClément Léger * be NULL if not needed 11067729d8dSLudovic Barre * 11167729d8dSLudovic Barre * Returns the interrupt number if value >= 0 11267729d8dSLudovic Barre * otherwise DT_INFO_INVALID_INTERRUPT 11367729d8dSLudovic Barre */ 114702fe5a7SClément Léger int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type, 115702fe5a7SClément Léger uint32_t *prio); 116702fe5a7SClément Léger 117702fe5a7SClément Léger /* 118702fe5a7SClément Léger * Get the DT interrupt property at @node 119702fe5a7SClément Léger */ 120702fe5a7SClément Léger static inline int dt_get_irq(const void *fdt, int node) 121702fe5a7SClément Léger { 122702fe5a7SClément Léger return dt_get_irq_type_prio(fdt, node, NULL, NULL); 123702fe5a7SClément Léger } 12467729d8dSLudovic Barre #endif 12567729d8dSLudovic Barre 126702fe5a7SClément Léger struct itr_handler *itr_alloc_add_type_prio(size_t it, itr_handler_t handler, 127702fe5a7SClément Léger uint32_t flags, void *data, 128702fe5a7SClément Léger uint32_t type, uint32_t prio); 129acc5dd21SLudovic Barre void itr_free(struct itr_handler *hdl); 130702fe5a7SClément Léger void itr_add_type_prio(struct itr_handler *handler, uint32_t type, 131702fe5a7SClément Léger uint32_t prio); 13226ed70ecSGuanchao Liang void itr_enable(size_t it); 13326ed70ecSGuanchao Liang void itr_disable(size_t it); 13426ed70ecSGuanchao Liang /* raise the Peripheral Interrupt corresponding to the interrupt ID */ 13526ed70ecSGuanchao Liang void itr_raise_pi(size_t it); 13626ed70ecSGuanchao Liang /* 13726ed70ecSGuanchao Liang * raise the Software Generated Interrupt corresponding to the interrupt ID, 13826ed70ecSGuanchao Liang * the cpu_mask represents which cpu interface to forward. 13926ed70ecSGuanchao Liang */ 14026ed70ecSGuanchao Liang void itr_raise_sgi(size_t it, uint8_t cpu_mask); 14126ed70ecSGuanchao Liang /* 14226ed70ecSGuanchao Liang * let corresponding interrupt forward to the cpu interface 14326ed70ecSGuanchao Liang * according to the cpu_mask. 14426ed70ecSGuanchao Liang */ 14526ed70ecSGuanchao Liang void itr_set_affinity(size_t it, uint8_t cpu_mask); 1467315b7b4SJens Wiklander 147e9f46c74SJens Wiklander /* 148e9f46c74SJens Wiklander * __weak overridable function which is called when a secure interrupt is 149e9f46c74SJens Wiklander * received. The default function calls panic() immediately, platforms which 150e9f46c74SJens Wiklander * expects to receive secure interrupts should override this function. 151e9f46c74SJens Wiklander */ 152358bf47cSEtienne Carriere void interrupt_main_handler(void); 153e9f46c74SJens Wiklander 154702fe5a7SClément Léger static inline void itr_add(struct itr_handler *handler) 155702fe5a7SClément Léger { 156702fe5a7SClément Léger itr_add_type_prio(handler, IRQ_TYPE_NONE, 0); 157702fe5a7SClément Léger } 158702fe5a7SClément Léger 159702fe5a7SClément Léger static inline struct itr_handler *itr_alloc_add(size_t it, 160702fe5a7SClément Léger itr_handler_t handler, 161702fe5a7SClément Léger uint32_t flags, void *data) 162702fe5a7SClément Léger { 163702fe5a7SClément Léger return itr_alloc_add_type_prio(it, handler, flags, data, IRQ_TYPE_NONE, 164702fe5a7SClément Léger 0); 165702fe5a7SClément Léger } 166702fe5a7SClément Léger 1677315b7b4SJens Wiklander #endif /*__KERNEL_INTERRUPT_H*/ 168