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 <mm/core_memprot.h> 10 #include <sys/queue.h> 11 #include <tee_api_types.h> 12 #include <types_ext.h> 13 #include <util.h> 14 15 #define ITRF_TRIGGER_LEVEL BIT(0) 16 #define ITRF_SHARED BIT(1) 17 18 struct itr_handler; 19 20 /* 21 * struct itr_chip - Interrupt controller 22 * 23 * @ops Operation callback functions 24 * @name Controller name, for debug purpose 25 * @handlers Registered handlers list head 26 * @dt_get_irq Device tree node parsing function 27 */ 28 struct itr_chip { 29 const struct itr_ops *ops; 30 const char *name; 31 SLIST_HEAD(, itr_handler) handlers; 32 /* 33 * dt_get_irq - parse a device tree interrupt property 34 * 35 * @properties raw interrupt property from device tree 36 * @count number of elements in @properties 37 * @type If not NULL, output interrupt type (IRQ_TYPE_* defines) 38 * or IRQ_TYPE_NONE if unknown 39 * @prio If not NULL, output interrupt priority value or 0 if unknown 40 */ 41 int (*dt_get_irq)(const uint32_t *properties, int count, uint32_t *type, 42 uint32_t *prio); 43 }; 44 45 /* 46 * struct itr_ops - Interrupt controller operations 47 * @add Register and configure an interrupt 48 * @enable Enable an interrupt 49 * @disable Disable an interrupt 50 * @mask Mask an interrupt, may be called from an interrupt context 51 * @unmask Unmask an interrupt, may be called from an interrupt context 52 * @raise_pi Raise per-cpu interrupt or NULL if not applicable 53 * @raise_sgi Raise a SGI or NULL if not applicable to that controller 54 * @set_affinity Set interrupt/cpu affinity or NULL if not applicable 55 * 56 * Handlers @enable, @disable, @mask, @unmask and @add are mandated. Handlers 57 * @mask and @unmask have unpaged memory contrainsts. See itr_chip_is_valid(). 58 */ 59 struct itr_ops { 60 void (*add)(struct itr_chip *chip, size_t it, uint32_t type, 61 uint32_t prio); 62 void (*enable)(struct itr_chip *chip, size_t it); 63 void (*disable)(struct itr_chip *chip, size_t it); 64 void (*mask)(struct itr_chip *chip, size_t it); 65 void (*unmask)(struct itr_chip *chip, size_t it); 66 void (*raise_pi)(struct itr_chip *chip, size_t it); 67 void (*raise_sgi)(struct itr_chip *chip, size_t it, 68 uint8_t cpu_mask); 69 void (*set_affinity)(struct itr_chip *chip, size_t it, 70 uint8_t cpu_mask); 71 }; 72 73 /* Interrupt handler return value */ 74 enum itr_return { 75 ITRR_NONE, 76 ITRR_HANDLED, 77 }; 78 79 /* Interrupt handler signature */ 80 typedef enum itr_return (*itr_handler_t)(struct itr_handler *h); 81 82 /* 83 * struct itr_handler - Interrupt handler reference 84 * @it Interrupt number 85 * @flags Property bit flags (ITRF_*) or 0 86 * @data Private data for that interrupt handler 87 * @chip Interrupt controller chip device 88 * @link Reference in controller handler list 89 */ 90 struct itr_handler { 91 size_t it; 92 uint32_t flags; 93 itr_handler_t handler; 94 void *data; 95 struct itr_chip *chip; 96 SLIST_ENTRY(itr_handler) link; 97 }; 98 99 #define ITR_HANDLER(_chip, _itr_num, _flags, _fn, _priv) \ 100 ((struct itr_handler){ \ 101 .chip = (_chip), .it = (_itr_num), .flags = (_flags), \ 102 .handler = (_fn), .data = (_priv), \ 103 }) 104 105 /* 106 * Return true only if interrupt chip provides required handlers 107 * @chip: Interrupt controller reference 108 */ 109 static inline bool itr_chip_is_valid(struct itr_chip *chip) 110 { 111 return chip && is_unpaged(chip) && chip->ops && 112 is_unpaged((void *)chip->ops) && 113 chip->ops->mask && is_unpaged(chip->ops->mask) && 114 chip->ops->unmask && is_unpaged(chip->ops->unmask) && 115 chip->ops->enable && chip->ops->disable && 116 chip->ops->add; 117 } 118 119 /* 120 * Initialise an interrupt controller handle 121 * @chip Interrupt controller 122 */ 123 TEE_Result itr_chip_init(struct itr_chip *chip); 124 125 /* 126 * Initialise main interrupt controller driver 127 * @data Main controller main data reference to register 128 */ 129 void interrupt_main_init(struct itr_chip *data); 130 131 /* Retrieve main interrupt controller reference */ 132 struct itr_chip *interrupt_get_main_chip(void); 133 134 #ifdef CFG_DT 135 /* 136 * Get the DT interrupt property at @node. In the DT an interrupt property can 137 * specify additional information which can be retrieved with @type and @prio. 138 * 139 * @fdt reference to the Device Tree 140 * @node is the node offset to read the interrupt property from 141 * @type interrupt type (IRQ_TYPE_* defines) if specified by interrupt property 142 * or IRQ_TYPE_NONE if not. Can be NULL if not needed 143 * @prio interrupt priority if specified by interrupt property or 0 if not. Can 144 * be NULL if not needed 145 * 146 * Returns the interrupt number if value >= 0 147 * otherwise DT_INFO_INVALID_INTERRUPT 148 */ 149 int dt_get_irq_type_prio(const void *fdt, int node, uint32_t *type, 150 uint32_t *prio); 151 152 /* 153 * Get the DT interrupt property at @node 154 */ 155 static inline int dt_get_irq(const void *fdt, int node) 156 { 157 return dt_get_irq_type_prio(fdt, node, NULL, NULL); 158 } 159 #endif 160 161 struct itr_handler *itr_alloc_add_type_prio(size_t it, itr_handler_t handler, 162 uint32_t flags, void *data, 163 uint32_t type, uint32_t prio); 164 void itr_free(struct itr_handler *hdl); 165 void itr_add_type_prio(struct itr_handler *handler, uint32_t type, 166 uint32_t prio); 167 void itr_enable(size_t it); 168 void itr_disable(size_t it); 169 /* raise the Peripheral Interrupt corresponding to the interrupt ID */ 170 void itr_raise_pi(size_t it); 171 /* 172 * raise the Software Generated Interrupt corresponding to the interrupt ID, 173 * the cpu_mask represents which cpu interface to forward. 174 */ 175 void itr_raise_sgi(size_t it, uint8_t cpu_mask); 176 /* 177 * let corresponding interrupt forward to the cpu interface 178 * according to the cpu_mask. 179 */ 180 void itr_set_affinity(size_t it, uint8_t cpu_mask); 181 182 /* 183 * __weak overridable function which is called when a secure interrupt is 184 * received. The default function calls panic() immediately, platforms which 185 * expects to receive secure interrupts should override this function. 186 */ 187 void interrupt_main_handler(void); 188 189 static inline void itr_add(struct itr_handler *handler) 190 { 191 itr_add_type_prio(handler, IRQ_TYPE_NONE, 0); 192 } 193 194 static inline struct itr_handler *itr_alloc_add(size_t it, 195 itr_handler_t handler, 196 uint32_t flags, void *data) 197 { 198 return itr_alloc_add_type_prio(it, handler, flags, data, IRQ_TYPE_NONE, 199 0); 200 } 201 202 /* 203 * Interrupt controller chip API functions 204 */ 205 206 /* 207 * interrupt_call_handlers() - Call registered handlers for an interrupt 208 * @chip Interrupt controller 209 * @itr_num Interrupt number 210 * 211 * This function is called from an interrupt context by a primary interrupt 212 * handler. This function calls the handlers registered for that interrupt. 213 * If interrupt is not handled, it is masked. 214 */ 215 void interrupt_call_handlers(struct itr_chip *chip, size_t itr_num); 216 217 /* 218 * interrupt_mask() - Mask an interrupt 219 * @chip Interrupt controller 220 * @itr_num Interrupt number 221 * 222 * This function may be called in interrupt context 223 */ 224 static inline void interrupt_mask(struct itr_chip *chip, size_t itr_num) 225 { 226 chip->ops->mask(chip, itr_num); 227 } 228 229 /* 230 * interrupt_unmask() - Unmask an interrupt 231 * @chip Interrupt controller 232 * @itr_num Interrupt number 233 * 234 * This function may be called in interrupt context 235 */ 236 static inline void interrupt_unmask(struct itr_chip *chip, size_t itr_num) 237 { 238 chip->ops->unmask(chip, itr_num); 239 } 240 241 /* 242 * interrupt_enable() - Enable an interrupt 243 * @chip Interrupt controller 244 * @itr_num Interrupt number 245 */ 246 static inline void interrupt_enable(struct itr_chip *chip, size_t itr_num) 247 { 248 chip->ops->enable(chip, itr_num); 249 } 250 251 /* 252 * interrupt_disable() - Disable an interrupt 253 * @chip Interrupt controller 254 * @itr_num Interrupt number 255 */ 256 static inline void interrupt_disable(struct itr_chip *chip, size_t itr_num) 257 { 258 chip->ops->disable(chip, itr_num); 259 } 260 261 /* 262 * interrupt_configure() - Configure an interrupt in an interrupt controller 263 * @chip Interrupt controller 264 * @itr_num Interrupt number 265 * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE 266 * @prio Interrupt priority or 0 267 * 268 * Interrupt consumers that get their interrupt from the DT do not need to 269 * call interrupt_configure() since the interrupt configuration has already 270 * been done by interrupt controller based on the DT bidings. 271 */ 272 TEE_Result interrupt_configure(struct itr_chip *chip, size_t itr_num, 273 uint32_t type, uint32_t prio); 274 275 /* 276 * interrupt_add_and_configure_handler() - Register and configure a handler 277 * @hdl Interrupt handler to register 278 * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE 279 * @prio Interrupt priority or 0 280 */ 281 TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl, 282 uint32_t type, uint32_t prio); 283 284 /* 285 * interrupt_add_handler() - Register an interrupt handler 286 * @hdl Interrupt handler to register 287 * 288 * This helper function assumes interrupt type is set to IRQ_TYPE_NONE 289 * and interrupt priority to 0. 290 */ 291 static inline TEE_Result interrupt_add_handler(struct itr_handler *hdl) 292 { 293 return interrupt_add_configure_handler(hdl, IRQ_TYPE_NONE, 0); 294 } 295 296 /* 297 * interrupt_add_handler_with_chip() - Register an interrupt handler providing 298 * the interrupt chip reference in specific argument @chip. 299 * @chip Interrupt controller 300 * @h Interrupt handler to register 301 */ 302 static inline TEE_Result interrupt_add_handler_with_chip(struct itr_chip *chip, 303 struct itr_handler *h) 304 { 305 h->chip = chip; 306 return interrupt_add_handler(h); 307 } 308 309 /* 310 * interrupt_remove_handler() - Remove a registered interrupt handler 311 * @hdl Interrupt handler to remove 312 * 313 * This function is the counterpart of interrupt_add_handler(). 314 * This function may panic on non-NULL invalid @hdl reference. 315 */ 316 void interrupt_remove_handler(struct itr_handler *hdl); 317 318 /* 319 * interrupt_alloc_add_handler() - Allocate and register an interrupt handler 320 * @chip Interrupt controller 321 * @itr_num Interrupt number 322 * @handler Interrupt handler to register 323 * @flags Bitmask flag ITRF_* 324 * @data Private data reference passed to @handler 325 * @out_hdl NULL or output pointer to allocated struct itr_handler 326 */ 327 TEE_Result interrupt_alloc_add_handler(struct itr_chip *chip, size_t it_num, 328 itr_handler_t handler, uint32_t flags, 329 void *data, 330 struct itr_handler **out_hdl); 331 332 /* 333 * interrupt_remove_free_handler() - Remove/free a registered interrupt handler 334 * @hdl Interrupt handler to remove and free 335 * 336 * This function is the counterpart of interrupt_alloc_add_handler(). 337 * This function may panic on non-NULL invalid @hdl reference. 338 */ 339 void interrupt_remove_free_handler(struct itr_handler *hdl); 340 #endif /*__KERNEL_INTERRUPT_H*/ 341