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 /* 162 * __weak overridable function which is called when a secure interrupt is 163 * received. The default function calls panic() immediately, platforms which 164 * expects to receive secure interrupts should override this function. 165 */ 166 void interrupt_main_handler(void); 167 168 /* 169 * Interrupt controller chip API functions 170 */ 171 172 /* 173 * interrupt_call_handlers() - Call registered handlers for an interrupt 174 * @chip Interrupt controller 175 * @itr_num Interrupt number 176 * 177 * This function is called from an interrupt context by a primary interrupt 178 * handler. This function calls the handlers registered for that interrupt. 179 * If interrupt is not handled, it is masked. 180 */ 181 void interrupt_call_handlers(struct itr_chip *chip, size_t itr_num); 182 183 /* 184 * interrupt_mask() - Mask an interrupt 185 * @chip Interrupt controller 186 * @itr_num Interrupt number 187 * 188 * This function may be called in interrupt context 189 */ 190 static inline void interrupt_mask(struct itr_chip *chip, size_t itr_num) 191 { 192 chip->ops->mask(chip, itr_num); 193 } 194 195 /* 196 * interrupt_unmask() - Unmask an interrupt 197 * @chip Interrupt controller 198 * @itr_num Interrupt number 199 * 200 * This function may be called in interrupt context 201 */ 202 static inline void interrupt_unmask(struct itr_chip *chip, size_t itr_num) 203 { 204 chip->ops->unmask(chip, itr_num); 205 } 206 207 /* 208 * interrupt_enable() - Enable an interrupt 209 * @chip Interrupt controller 210 * @itr_num Interrupt number 211 */ 212 static inline void interrupt_enable(struct itr_chip *chip, size_t itr_num) 213 { 214 chip->ops->enable(chip, itr_num); 215 } 216 217 /* 218 * interrupt_disable() - Disable an interrupt 219 * @chip Interrupt controller 220 * @itr_num Interrupt number 221 */ 222 static inline void interrupt_disable(struct itr_chip *chip, size_t itr_num) 223 { 224 chip->ops->disable(chip, itr_num); 225 } 226 227 /* 228 * interrupt_can_raise_pi() - Return whether controller embeds raise_pi 229 * @chip Interrupt controller 230 */ 231 static inline bool interrupt_can_raise_pi(struct itr_chip *chip) 232 { 233 return chip->ops->raise_pi; 234 } 235 236 /* 237 * interrupt_can_raise_sgi() - Return whether controller embeds raise_sgi 238 * @chip Interrupt controller 239 */ 240 static inline bool interrupt_can_raise_sgi(struct itr_chip *chip) 241 { 242 return chip->ops->raise_sgi; 243 } 244 245 /* 246 * interrupt_can_set_affinity() - Return whether controller embeds set_affinity 247 * @chip Interrupt controller 248 */ 249 static inline bool interrupt_can_set_affinity(struct itr_chip *chip) 250 { 251 return chip->ops->set_affinity; 252 } 253 254 /* 255 * interrupt_raise_pi() - Raise a peripheral interrupt of a controller 256 * @chip Interrupt controller 257 * @itr_num Interrupt number to raise 258 */ 259 static inline void interrupt_raise_pi(struct itr_chip *chip, size_t itr_num) 260 { 261 assert(interrupt_can_raise_pi(chip)); 262 chip->ops->raise_pi(chip, itr_num); 263 } 264 265 /* 266 * interrupt_raise_sgi() - Raise a software generiated interrupt of a controller 267 * @chip Interrupt controller 268 * @itr_num Interrupt number to raise 269 * @cpu_mask Mask of the CPUs targeted by the interrupt 270 */ 271 static inline void interrupt_raise_sgi(struct itr_chip *chip, size_t itr_num, 272 uint8_t cpu_mask) 273 { 274 assert(interrupt_can_raise_sgi(chip)); 275 chip->ops->raise_sgi(chip, itr_num, cpu_mask); 276 } 277 278 /* 279 * interrupt_set_affinity() - Set CPU affinity for a controller interrupt 280 * @chip Interrupt controller 281 * @itr_num Interrupt number to raise 282 * @cpu_mask Mask of the CPUs targeted by the interrupt 283 */ 284 static inline void interrupt_set_affinity(struct itr_chip *chip, size_t itr_num, 285 uint8_t cpu_mask) 286 { 287 assert(interrupt_can_set_affinity(chip)); 288 chip->ops->set_affinity(chip, itr_num, cpu_mask); 289 } 290 291 /* 292 * interrupt_configure() - Configure an interrupt in an interrupt controller 293 * @chip Interrupt controller 294 * @itr_num Interrupt number 295 * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE 296 * @prio Interrupt priority or 0 297 * 298 * Interrupt consumers that get their interrupt from the DT do not need to 299 * call interrupt_configure() since the interrupt configuration has already 300 * been done by interrupt controller based on the DT bidings. 301 */ 302 TEE_Result interrupt_configure(struct itr_chip *chip, size_t itr_num, 303 uint32_t type, uint32_t prio); 304 305 /* 306 * interrupt_add_and_configure_handler() - Register and configure a handler 307 * @hdl Interrupt handler to register 308 * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE 309 * @prio Interrupt priority or 0 310 */ 311 TEE_Result interrupt_add_configure_handler(struct itr_handler *hdl, 312 uint32_t type, uint32_t prio); 313 314 /* 315 * interrupt_add_handler() - Register an interrupt handler 316 * @hdl Interrupt handler to register 317 * 318 * This helper function assumes interrupt type is set to IRQ_TYPE_NONE 319 * and interrupt priority to 0. 320 */ 321 static inline TEE_Result interrupt_add_handler(struct itr_handler *hdl) 322 { 323 return interrupt_add_configure_handler(hdl, IRQ_TYPE_NONE, 0); 324 } 325 326 /* 327 * interrupt_add_handler_with_chip() - Register an interrupt handler providing 328 * the interrupt chip reference in specific argument @chip. 329 * @chip Interrupt controller 330 * @h Interrupt handler to register 331 */ 332 static inline TEE_Result interrupt_add_handler_with_chip(struct itr_chip *chip, 333 struct itr_handler *h) 334 { 335 h->chip = chip; 336 return interrupt_add_handler(h); 337 } 338 339 /* 340 * interrupt_remove_handler() - Remove a registered interrupt handler 341 * @hdl Interrupt handler to remove 342 * 343 * This function is the counterpart of interrupt_add_handler(). 344 * This function may panic on non-NULL invalid @hdl reference. 345 */ 346 void interrupt_remove_handler(struct itr_handler *hdl); 347 348 /* 349 * interrupt_alloc_add_conf_handler() - Allocate, configure, register a handler 350 * @chip Interrupt controller 351 * @itr_num Interrupt number 352 * @handler Interrupt handler to register 353 * @flags Bitmask flag ITRF_* 354 * @data Private data reference passed to @handler 355 * @type Interrupt trigger type (IRQ_TYPE_* defines) or IRQ_TYPE_NONE 356 * @prio Interrupt priority or 0 357 * @out_hdl NULL or output pointer to allocated struct itr_handler 358 */ 359 TEE_Result interrupt_alloc_add_conf_handler(struct itr_chip *chip, 360 size_t it_num, 361 itr_handler_t handler, 362 uint32_t flags, void *data, 363 uint32_t type, uint32_t prio, 364 struct itr_handler **out_hdl); 365 366 /* 367 * interrupt_alloc_add_handler() - Allocate and register an interrupt handler 368 * @chip Interrupt controller 369 * @itr_num Interrupt number 370 * @handler Interrupt handler to register 371 * @flags Bitmask flag ITRF_* 372 * @data Private data reference passed to @handler 373 * @out_hdl NULL or output pointer to allocated struct itr_handler 374 */ 375 static inline TEE_Result interrupt_alloc_add_handler(struct itr_chip *chip, 376 size_t it_num, 377 itr_handler_t handler, 378 uint32_t flags, 379 void *data, 380 struct itr_handler **hdl) 381 { 382 return interrupt_alloc_add_conf_handler(chip, it_num, handler, flags, 383 data, IRQ_TYPE_NONE, 0, hdl); 384 } 385 386 /* 387 * interrupt_remove_free_handler() - Remove/free a registered interrupt handler 388 * @hdl Interrupt handler to remove and free 389 * 390 * This function is the counterpart of interrupt_alloc_add_handler() 391 * and interrupt_alloc_add_conf_handler(). 392 * This function may panic on non-NULL invalid @hdl reference. 393 */ 394 void interrupt_remove_free_handler(struct itr_handler *hdl); 395 #endif /*__KERNEL_INTERRUPT_H*/ 396