xref: /optee_os/core/kernel/interrupt.c (revision 1c832d7c41cdb2f617bffa74c3d70f7c4a5667fc)
11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
27315b7b4SJens Wiklander /*
3e9f46c74SJens Wiklander  * Copyright (c) 2016-2019, Linaro Limited
47315b7b4SJens Wiklander  */
57315b7b4SJens Wiklander 
67315b7b4SJens Wiklander #include <kernel/interrupt.h>
7e9f46c74SJens Wiklander #include <kernel/panic.h>
87315b7b4SJens Wiklander #include <trace.h>
9*1c832d7cSdavidwang #include <assert.h>
107315b7b4SJens Wiklander 
117315b7b4SJens Wiklander /*
127315b7b4SJens Wiklander  * NOTE!
137315b7b4SJens Wiklander  *
147315b7b4SJens Wiklander  * We're assuming that there's no concurrent use of this interface, except
157315b7b4SJens Wiklander  * delivery of interrupts in parallel. Synchronization will be needed when
167315b7b4SJens Wiklander  * we begin to modify settings after boot initialization.
177315b7b4SJens Wiklander  */
187315b7b4SJens Wiklander 
197315b7b4SJens Wiklander static struct itr_chip *itr_chip;
207315b7b4SJens Wiklander static SLIST_HEAD(, itr_handler) handlers = SLIST_HEAD_INITIALIZER(handlers);
217315b7b4SJens Wiklander 
227315b7b4SJens Wiklander void itr_init(struct itr_chip *chip)
237315b7b4SJens Wiklander {
247315b7b4SJens Wiklander 	itr_chip = chip;
257315b7b4SJens Wiklander }
267315b7b4SJens Wiklander 
277315b7b4SJens Wiklander void itr_handle(size_t it)
287315b7b4SJens Wiklander {
29*1c832d7cSdavidwang 	struct itr_handler *h = NULL;
30*1c832d7cSdavidwang 	bool was_handled = false;
317315b7b4SJens Wiklander 
32*1c832d7cSdavidwang 	SLIST_FOREACH(h, &handlers, link) {
33*1c832d7cSdavidwang 		if (h->it == it) {
34*1c832d7cSdavidwang 			if (h->handler(h) == ITRR_HANDLED)
35*1c832d7cSdavidwang 				was_handled = true;
36*1c832d7cSdavidwang 			else if (!(h->flags & ITRF_SHARED))
37*1c832d7cSdavidwang 				break;
38*1c832d7cSdavidwang 		}
397315b7b4SJens Wiklander 	}
407315b7b4SJens Wiklander 
41*1c832d7cSdavidwang 	if (!was_handled) {
42*1c832d7cSdavidwang 		EMSG("Disabling unhandled interrupt %zu", it);
437315b7b4SJens Wiklander 		itr_chip->ops->disable(itr_chip, it);
447315b7b4SJens Wiklander 	}
457315b7b4SJens Wiklander }
467315b7b4SJens Wiklander 
477315b7b4SJens Wiklander void itr_add(struct itr_handler *h)
487315b7b4SJens Wiklander {
49*1c832d7cSdavidwang 	struct itr_handler __maybe_unused *hdl = NULL;
50*1c832d7cSdavidwang 
51*1c832d7cSdavidwang 	SLIST_FOREACH(hdl, &handlers, link)
52*1c832d7cSdavidwang 		if (hdl->it == h->it)
53*1c832d7cSdavidwang 			assert((hdl->flags & ITRF_SHARED) &&
54*1c832d7cSdavidwang 			       (h->flags & ITRF_SHARED));
55*1c832d7cSdavidwang 
567315b7b4SJens Wiklander 	itr_chip->ops->add(itr_chip, h->it, h->flags);
577315b7b4SJens Wiklander 	SLIST_INSERT_HEAD(&handlers, h, link);
587315b7b4SJens Wiklander }
597315b7b4SJens Wiklander 
6026ed70ecSGuanchao Liang void itr_enable(size_t it)
617315b7b4SJens Wiklander {
6226ed70ecSGuanchao Liang 	itr_chip->ops->enable(itr_chip, it);
637315b7b4SJens Wiklander }
647315b7b4SJens Wiklander 
6526ed70ecSGuanchao Liang void itr_disable(size_t it)
667315b7b4SJens Wiklander {
6726ed70ecSGuanchao Liang 	itr_chip->ops->disable(itr_chip, it);
6826ed70ecSGuanchao Liang }
6926ed70ecSGuanchao Liang 
7026ed70ecSGuanchao Liang void itr_raise_pi(size_t it)
7126ed70ecSGuanchao Liang {
7226ed70ecSGuanchao Liang 	itr_chip->ops->raise_pi(itr_chip, it);
7326ed70ecSGuanchao Liang }
7426ed70ecSGuanchao Liang 
7526ed70ecSGuanchao Liang void itr_raise_sgi(size_t it, uint8_t cpu_mask)
7626ed70ecSGuanchao Liang {
7726ed70ecSGuanchao Liang 	itr_chip->ops->raise_sgi(itr_chip, it, cpu_mask);
7826ed70ecSGuanchao Liang }
7926ed70ecSGuanchao Liang 
8026ed70ecSGuanchao Liang void itr_set_affinity(size_t it, uint8_t cpu_mask)
8126ed70ecSGuanchao Liang {
8226ed70ecSGuanchao Liang 	itr_chip->ops->set_affinity(itr_chip, it, cpu_mask);
837315b7b4SJens Wiklander }
84e9f46c74SJens Wiklander 
85e9f46c74SJens Wiklander /* This function is supposed to be overridden in platform specific code */
86e9f46c74SJens Wiklander void __weak __noreturn itr_core_handler(void)
87e9f46c74SJens Wiklander {
88e9f46c74SJens Wiklander 	panic("Secure interrupt handler not defined");
89e9f46c74SJens Wiklander }
90