xref: /optee_os/core/kernel/interrupt.c (revision 67729d8d5aaa4023a7f43da0af8535959956ee2e)
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