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 607315b7b4SJens Wiklander void itr_init(struct itr_chip *data); 617315b7b4SJens Wiklander void itr_handle(size_t it); 627315b7b4SJens Wiklander 6367729d8dSLudovic Barre #ifdef CFG_DT 6467729d8dSLudovic Barre /* 65702fe5a7SClément Léger * Get the DT interrupt property at @node. In the DT an interrupt property can 66702fe5a7SClément Léger * specify additional information which can be retrieved with @type and @prio. 6767729d8dSLudovic Barre * 6867729d8dSLudovic Barre * @fdt reference to the Device Tree 69702fe5a7SClément Léger * @node is the node offset to read the interrupt property from 70702fe5a7SClément Léger * @type interrupt type (IRQ_TYPE_* defines) if specified by interrupt property 71702fe5a7SClément Léger * or IRQ_TYPE_NONE if not. Can be NULL if not needed 72702fe5a7SClément Léger * @prio interrupt priority if specified by interrupt property or 0 if not. Can 73702fe5a7SClément Léger * be NULL if not needed 7467729d8dSLudovic Barre * 7567729d8dSLudovic Barre * Returns the interrupt number if value >= 0 7667729d8dSLudovic Barre * otherwise DT_INFO_INVALID_INTERRUPT 7767729d8dSLudovic Barre */ 78702fe5a7SClément Léger int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type, 79702fe5a7SClément Léger uint32_t *prio); 80702fe5a7SClément Léger 81702fe5a7SClément Léger /* 82702fe5a7SClément Léger * Get the DT interrupt property at @node 83702fe5a7SClément Léger */ 84702fe5a7SClément Léger static inline int dt_get_irq(const void *fdt, int node) 85702fe5a7SClément Léger { 86702fe5a7SClément Léger return dt_get_irq_type_prio(fdt, node, NULL, NULL); 87702fe5a7SClément Léger } 8867729d8dSLudovic Barre #endif 8967729d8dSLudovic Barre 90702fe5a7SClément Léger struct itr_handler *itr_alloc_add_type_prio(size_t it, itr_handler_t handler, 91702fe5a7SClément Léger uint32_t flags, void *data, 92702fe5a7SClément Léger uint32_t type, uint32_t prio); 93acc5dd21SLudovic Barre void itr_free(struct itr_handler *hdl); 94702fe5a7SClément Léger void itr_add_type_prio(struct itr_handler *handler, uint32_t type, 95702fe5a7SClément Léger uint32_t prio); 9626ed70ecSGuanchao Liang void itr_enable(size_t it); 9726ed70ecSGuanchao Liang void itr_disable(size_t it); 9826ed70ecSGuanchao Liang /* raise the Peripheral Interrupt corresponding to the interrupt ID */ 9926ed70ecSGuanchao Liang void itr_raise_pi(size_t it); 10026ed70ecSGuanchao Liang /* 10126ed70ecSGuanchao Liang * raise the Software Generated Interrupt corresponding to the interrupt ID, 10226ed70ecSGuanchao Liang * the cpu_mask represents which cpu interface to forward. 10326ed70ecSGuanchao Liang */ 10426ed70ecSGuanchao Liang void itr_raise_sgi(size_t it, uint8_t cpu_mask); 10526ed70ecSGuanchao Liang /* 10626ed70ecSGuanchao Liang * let corresponding interrupt forward to the cpu interface 10726ed70ecSGuanchao Liang * according to the cpu_mask. 10826ed70ecSGuanchao Liang */ 10926ed70ecSGuanchao Liang void itr_set_affinity(size_t it, uint8_t cpu_mask); 1107315b7b4SJens Wiklander 111e9f46c74SJens Wiklander /* 112e9f46c74SJens Wiklander * __weak overridable function which is called when a secure interrupt is 113e9f46c74SJens Wiklander * received. The default function calls panic() immediately, platforms which 114e9f46c74SJens Wiklander * expects to receive secure interrupts should override this function. 115e9f46c74SJens Wiklander */ 116*358bf47cSEtienne Carriere void interrupt_main_handler(void); 117e9f46c74SJens Wiklander 118702fe5a7SClément Léger static inline void itr_add(struct itr_handler *handler) 119702fe5a7SClément Léger { 120702fe5a7SClément Léger itr_add_type_prio(handler, IRQ_TYPE_NONE, 0); 121702fe5a7SClément Léger } 122702fe5a7SClément Léger 123702fe5a7SClément Léger static inline struct itr_handler *itr_alloc_add(size_t it, 124702fe5a7SClément Léger itr_handler_t handler, 125702fe5a7SClément Léger uint32_t flags, void *data) 126702fe5a7SClément Léger { 127702fe5a7SClément Léger return itr_alloc_add_type_prio(it, handler, flags, data, IRQ_TYPE_NONE, 128702fe5a7SClément Léger 0); 129702fe5a7SClément Léger } 130702fe5a7SClément Léger 1317315b7b4SJens Wiklander #endif /*__KERNEL_INTERRUPT_H*/ 132