1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2016-2019, Linaro Limited 4 */ 5 6 #include <kernel/dt.h> 7 #include <kernel/interrupt.h> 8 #include <kernel/panic.h> 9 #include <libfdt.h> 10 #include <trace.h> 11 #include <assert.h> 12 13 /* 14 * NOTE! 15 * 16 * We're assuming that there's no concurrent use of this interface, except 17 * delivery of interrupts in parallel. Synchronization will be needed when 18 * we begin to modify settings after boot initialization. 19 */ 20 21 static struct itr_chip *itr_chip __nex_bss; 22 static SLIST_HEAD(, itr_handler) handlers __nex_data = 23 SLIST_HEAD_INITIALIZER(handlers); 24 25 void itr_init(struct itr_chip *chip) 26 { 27 itr_chip = chip; 28 } 29 30 #ifdef CFG_DT 31 int dt_get_irq(const void *fdt, int node) 32 { 33 const uint32_t *prop = NULL; 34 int len = 0; 35 int it_num = DT_INFO_INVALID_INTERRUPT; 36 37 if (!itr_chip || !itr_chip->dt_get_irq) 38 return it_num; 39 40 prop = fdt_getprop(fdt, node, "interrupts", &len); 41 if (!prop) 42 return it_num; 43 44 return itr_chip->dt_get_irq(prop, len); 45 } 46 #endif 47 48 void itr_handle(size_t it) 49 { 50 struct itr_handler *h = NULL; 51 bool was_handled = false; 52 53 SLIST_FOREACH(h, &handlers, link) { 54 if (h->it == it) { 55 if (h->handler(h) == ITRR_HANDLED) 56 was_handled = true; 57 else if (!(h->flags & ITRF_SHARED)) 58 break; 59 } 60 } 61 62 if (!was_handled) { 63 EMSG("Disabling unhandled interrupt %zu", it); 64 itr_chip->ops->disable(itr_chip, it); 65 } 66 } 67 68 void itr_add(struct itr_handler *h) 69 { 70 struct itr_handler __maybe_unused *hdl = NULL; 71 72 SLIST_FOREACH(hdl, &handlers, link) 73 if (hdl->it == h->it) 74 assert((hdl->flags & ITRF_SHARED) && 75 (h->flags & ITRF_SHARED)); 76 77 itr_chip->ops->add(itr_chip, h->it, h->flags); 78 SLIST_INSERT_HEAD(&handlers, h, link); 79 } 80 81 void itr_enable(size_t it) 82 { 83 itr_chip->ops->enable(itr_chip, it); 84 } 85 86 void itr_disable(size_t it) 87 { 88 itr_chip->ops->disable(itr_chip, it); 89 } 90 91 void itr_raise_pi(size_t it) 92 { 93 itr_chip->ops->raise_pi(itr_chip, it); 94 } 95 96 void itr_raise_sgi(size_t it, uint8_t cpu_mask) 97 { 98 itr_chip->ops->raise_sgi(itr_chip, it, cpu_mask); 99 } 100 101 void itr_set_affinity(size_t it, uint8_t cpu_mask) 102 { 103 itr_chip->ops->set_affinity(itr_chip, it, cpu_mask); 104 } 105 106 /* This function is supposed to be overridden in platform specific code */ 107 void __weak __noreturn itr_core_handler(void) 108 { 109 panic("Secure interrupt handler not defined"); 110 } 111