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