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 <types_ext.h> 10 #include <sys/queue.h> 11 #include <util.h> 12 13 #define ITRF_TRIGGER_LEVEL BIT(0) 14 #define ITRF_SHARED BIT(1) 15 16 struct itr_chip { 17 const struct itr_ops *ops; 18 /* 19 * dt_get_irq - parse a device tree interrupt property 20 * 21 * @properties raw interrupt property from device tree 22 * @count number of elements in @properties 23 * @type If not NULL, output interrupt type (IRQ_TYPE_* defines) 24 * or IRQ_TYPE_NONE if unknown 25 * @prio If not NULL, output interrupt priority value or 0 if unknown 26 */ 27 int (*dt_get_irq)(const uint32_t *properties, int count, uint32_t *type, 28 uint32_t *prio); 29 }; 30 31 struct itr_ops { 32 void (*add)(struct itr_chip *chip, size_t it, uint32_t type, 33 uint32_t prio); 34 void (*enable)(struct itr_chip *chip, size_t it); 35 void (*disable)(struct itr_chip *chip, size_t it); 36 void (*raise_pi)(struct itr_chip *chip, size_t it); 37 void (*raise_sgi)(struct itr_chip *chip, size_t it, 38 uint8_t cpu_mask); 39 void (*set_affinity)(struct itr_chip *chip, size_t it, 40 uint8_t cpu_mask); 41 }; 42 43 enum itr_return { 44 ITRR_NONE, 45 ITRR_HANDLED, 46 }; 47 48 struct itr_handler; 49 50 typedef enum itr_return (*itr_handler_t)(struct itr_handler *h); 51 52 struct itr_handler { 53 size_t it; 54 uint32_t flags; 55 itr_handler_t handler; 56 void *data; 57 SLIST_ENTRY(itr_handler) link; 58 }; 59 60 /* 61 * Initialise core interrupt controller driver 62 * @data Core controller main data reference to register 63 */ 64 void interrupt_main_init(struct itr_chip *data); 65 66 void itr_handle(size_t it); 67 68 #ifdef CFG_DT 69 /* 70 * Get the DT interrupt property at @node. In the DT an interrupt property can 71 * specify additional information which can be retrieved with @type and @prio. 72 * 73 * @fdt reference to the Device Tree 74 * @node is the node offset to read the interrupt property from 75 * @type interrupt type (IRQ_TYPE_* defines) if specified by interrupt property 76 * or IRQ_TYPE_NONE if not. Can be NULL if not needed 77 * @prio interrupt priority if specified by interrupt property or 0 if not. Can 78 * be NULL if not needed 79 * 80 * Returns the interrupt number if value >= 0 81 * otherwise DT_INFO_INVALID_INTERRUPT 82 */ 83 int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type, 84 uint32_t *prio); 85 86 /* 87 * Get the DT interrupt property at @node 88 */ 89 static inline int dt_get_irq(const void *fdt, int node) 90 { 91 return dt_get_irq_type_prio(fdt, node, NULL, NULL); 92 } 93 #endif 94 95 struct itr_handler *itr_alloc_add_type_prio(size_t it, itr_handler_t handler, 96 uint32_t flags, void *data, 97 uint32_t type, uint32_t prio); 98 void itr_free(struct itr_handler *hdl); 99 void itr_add_type_prio(struct itr_handler *handler, uint32_t type, 100 uint32_t prio); 101 void itr_enable(size_t it); 102 void itr_disable(size_t it); 103 /* raise the Peripheral Interrupt corresponding to the interrupt ID */ 104 void itr_raise_pi(size_t it); 105 /* 106 * raise the Software Generated Interrupt corresponding to the interrupt ID, 107 * the cpu_mask represents which cpu interface to forward. 108 */ 109 void itr_raise_sgi(size_t it, uint8_t cpu_mask); 110 /* 111 * let corresponding interrupt forward to the cpu interface 112 * according to the cpu_mask. 113 */ 114 void itr_set_affinity(size_t it, uint8_t cpu_mask); 115 116 /* 117 * __weak overridable function which is called when a secure interrupt is 118 * received. The default function calls panic() immediately, platforms which 119 * expects to receive secure interrupts should override this function. 120 */ 121 void interrupt_main_handler(void); 122 123 static inline void itr_add(struct itr_handler *handler) 124 { 125 itr_add_type_prio(handler, IRQ_TYPE_NONE, 0); 126 } 127 128 static inline struct itr_handler *itr_alloc_add(size_t it, 129 itr_handler_t handler, 130 uint32_t flags, void *data) 131 { 132 return itr_alloc_add_type_prio(it, handler, flags, data, IRQ_TYPE_NONE, 133 0); 134 } 135 136 #endif /*__KERNEL_INTERRUPT_H*/ 137