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 167315b7b4SJens Wiklander struct itr_chip { 177315b7b4SJens Wiklander const struct itr_ops *ops; 18702fe5a7SClément Léger /* 19702fe5a7SClément Léger * dt_get_irq - parse a device tree interrupt property 20702fe5a7SClément Léger * 21702fe5a7SClément Léger * @properties raw interrupt property from device tree 22702fe5a7SClément Léger * @count number of elements in @properties 23702fe5a7SClément Léger * @type If not NULL, output interrupt type (IRQ_TYPE_* defines) 24702fe5a7SClément Léger * or IRQ_TYPE_NONE if unknown 25702fe5a7SClément Léger * @prio If not NULL, output interrupt priority value or 0 if unknown 26702fe5a7SClément Léger */ 27702fe5a7SClément Léger int (*dt_get_irq)(const uint32_t *properties, int count, uint32_t *type, 28702fe5a7SClément Léger uint32_t *prio); 297315b7b4SJens Wiklander }; 307315b7b4SJens Wiklander 317315b7b4SJens Wiklander struct itr_ops { 32702fe5a7SClément Léger void (*add)(struct itr_chip *chip, size_t it, uint32_t type, 33702fe5a7SClément Léger uint32_t prio); 347315b7b4SJens Wiklander void (*enable)(struct itr_chip *chip, size_t it); 357315b7b4SJens Wiklander void (*disable)(struct itr_chip *chip, size_t it); 3626ed70ecSGuanchao Liang void (*raise_pi)(struct itr_chip *chip, size_t it); 3726ed70ecSGuanchao Liang void (*raise_sgi)(struct itr_chip *chip, size_t it, 3826ed70ecSGuanchao Liang uint8_t cpu_mask); 3926ed70ecSGuanchao Liang void (*set_affinity)(struct itr_chip *chip, size_t it, 4026ed70ecSGuanchao Liang uint8_t cpu_mask); 417315b7b4SJens Wiklander }; 427315b7b4SJens Wiklander 437315b7b4SJens Wiklander enum itr_return { 447315b7b4SJens Wiklander ITRR_NONE, 457315b7b4SJens Wiklander ITRR_HANDLED, 467315b7b4SJens Wiklander }; 477315b7b4SJens Wiklander 48acc5dd21SLudovic Barre struct itr_handler; 49acc5dd21SLudovic Barre 50acc5dd21SLudovic Barre typedef enum itr_return (*itr_handler_t)(struct itr_handler *h); 51acc5dd21SLudovic Barre 527315b7b4SJens Wiklander struct itr_handler { 537315b7b4SJens Wiklander size_t it; 547315b7b4SJens Wiklander uint32_t flags; 55acc5dd21SLudovic Barre itr_handler_t handler; 567315b7b4SJens Wiklander void *data; 577315b7b4SJens Wiklander SLIST_ENTRY(itr_handler) link; 587315b7b4SJens Wiklander }; 597315b7b4SJens Wiklander 6001980f3fSEtienne Carriere /* 6101980f3fSEtienne Carriere * Initialise core interrupt controller driver 6201980f3fSEtienne Carriere * @data Core controller main data reference to register 6301980f3fSEtienne Carriere */ 6401980f3fSEtienne Carriere void interrupt_main_init(struct itr_chip *data); 6501980f3fSEtienne Carriere 667315b7b4SJens Wiklander void itr_handle(size_t it); 677315b7b4SJens Wiklander 68*e050e0a7SEtienne Carriere /* Retrieve main interrupt controller reference */ 69*e050e0a7SEtienne Carriere struct itr_chip *interrupt_get_main_chip(void); 70*e050e0a7SEtienne Carriere 7167729d8dSLudovic Barre #ifdef CFG_DT 7267729d8dSLudovic Barre /* 73702fe5a7SClément Léger * Get the DT interrupt property at @node. In the DT an interrupt property can 74702fe5a7SClément Léger * specify additional information which can be retrieved with @type and @prio. 7567729d8dSLudovic Barre * 7667729d8dSLudovic Barre * @fdt reference to the Device Tree 77702fe5a7SClément Léger * @node is the node offset to read the interrupt property from 78702fe5a7SClément Léger * @type interrupt type (IRQ_TYPE_* defines) if specified by interrupt property 79702fe5a7SClément Léger * or IRQ_TYPE_NONE if not. Can be NULL if not needed 80702fe5a7SClément Léger * @prio interrupt priority if specified by interrupt property or 0 if not. Can 81702fe5a7SClément Léger * be NULL if not needed 8267729d8dSLudovic Barre * 8367729d8dSLudovic Barre * Returns the interrupt number if value >= 0 8467729d8dSLudovic Barre * otherwise DT_INFO_INVALID_INTERRUPT 8567729d8dSLudovic Barre */ 86702fe5a7SClément Léger int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type, 87702fe5a7SClément Léger uint32_t *prio); 88702fe5a7SClément Léger 89702fe5a7SClément Léger /* 90702fe5a7SClément Léger * Get the DT interrupt property at @node 91702fe5a7SClément Léger */ 92702fe5a7SClément Léger static inline int dt_get_irq(const void *fdt, int node) 93702fe5a7SClément Léger { 94702fe5a7SClément Léger return dt_get_irq_type_prio(fdt, node, NULL, NULL); 95702fe5a7SClément Léger } 9667729d8dSLudovic Barre #endif 9767729d8dSLudovic Barre 98702fe5a7SClément Léger struct itr_handler *itr_alloc_add_type_prio(size_t it, itr_handler_t handler, 99702fe5a7SClément Léger uint32_t flags, void *data, 100702fe5a7SClément Léger uint32_t type, uint32_t prio); 101acc5dd21SLudovic Barre void itr_free(struct itr_handler *hdl); 102702fe5a7SClément Léger void itr_add_type_prio(struct itr_handler *handler, uint32_t type, 103702fe5a7SClément Léger uint32_t prio); 10426ed70ecSGuanchao Liang void itr_enable(size_t it); 10526ed70ecSGuanchao Liang void itr_disable(size_t it); 10626ed70ecSGuanchao Liang /* raise the Peripheral Interrupt corresponding to the interrupt ID */ 10726ed70ecSGuanchao Liang void itr_raise_pi(size_t it); 10826ed70ecSGuanchao Liang /* 10926ed70ecSGuanchao Liang * raise the Software Generated Interrupt corresponding to the interrupt ID, 11026ed70ecSGuanchao Liang * the cpu_mask represents which cpu interface to forward. 11126ed70ecSGuanchao Liang */ 11226ed70ecSGuanchao Liang void itr_raise_sgi(size_t it, uint8_t cpu_mask); 11326ed70ecSGuanchao Liang /* 11426ed70ecSGuanchao Liang * let corresponding interrupt forward to the cpu interface 11526ed70ecSGuanchao Liang * according to the cpu_mask. 11626ed70ecSGuanchao Liang */ 11726ed70ecSGuanchao Liang void itr_set_affinity(size_t it, uint8_t cpu_mask); 1187315b7b4SJens Wiklander 119e9f46c74SJens Wiklander /* 120e9f46c74SJens Wiklander * __weak overridable function which is called when a secure interrupt is 121e9f46c74SJens Wiklander * received. The default function calls panic() immediately, platforms which 122e9f46c74SJens Wiklander * expects to receive secure interrupts should override this function. 123e9f46c74SJens Wiklander */ 124358bf47cSEtienne Carriere void interrupt_main_handler(void); 125e9f46c74SJens Wiklander 126702fe5a7SClément Léger static inline void itr_add(struct itr_handler *handler) 127702fe5a7SClément Léger { 128702fe5a7SClément Léger itr_add_type_prio(handler, IRQ_TYPE_NONE, 0); 129702fe5a7SClément Léger } 130702fe5a7SClément Léger 131702fe5a7SClément Léger static inline struct itr_handler *itr_alloc_add(size_t it, 132702fe5a7SClément Léger itr_handler_t handler, 133702fe5a7SClément Léger uint32_t flags, void *data) 134702fe5a7SClément Léger { 135702fe5a7SClément Léger return itr_alloc_add_type_prio(it, handler, flags, data, IRQ_TYPE_NONE, 136702fe5a7SClément Léger 0); 137702fe5a7SClément Léger } 138702fe5a7SClément Léger 1397315b7b4SJens Wiklander #endif /*__KERNEL_INTERRUPT_H*/ 140