xref: /optee_os/core/kernel/interrupt.c (revision 0c1be93b3b78278ab33d004da9968140eb9d6c48)
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>
91c832d7cSdavidwang #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 
19*0c1be93bSVolodymyr Babchuk static struct itr_chip *itr_chip __nex_bss;
20*0c1be93bSVolodymyr Babchuk static SLIST_HEAD(, itr_handler) handlers __nex_data =
21*0c1be93bSVolodymyr Babchuk 	SLIST_HEAD_INITIALIZER(handlers);
227315b7b4SJens Wiklander 
237315b7b4SJens Wiklander void itr_init(struct itr_chip *chip)
247315b7b4SJens Wiklander {
257315b7b4SJens Wiklander 	itr_chip = chip;
267315b7b4SJens Wiklander }
277315b7b4SJens Wiklander 
287315b7b4SJens Wiklander void itr_handle(size_t it)
297315b7b4SJens Wiklander {
301c832d7cSdavidwang 	struct itr_handler *h = NULL;
311c832d7cSdavidwang 	bool was_handled = false;
327315b7b4SJens Wiklander 
331c832d7cSdavidwang 	SLIST_FOREACH(h, &handlers, link) {
341c832d7cSdavidwang 		if (h->it == it) {
351c832d7cSdavidwang 			if (h->handler(h) == ITRR_HANDLED)
361c832d7cSdavidwang 				was_handled = true;
371c832d7cSdavidwang 			else if (!(h->flags & ITRF_SHARED))
381c832d7cSdavidwang 				break;
391c832d7cSdavidwang 		}
407315b7b4SJens Wiklander 	}
417315b7b4SJens Wiklander 
421c832d7cSdavidwang 	if (!was_handled) {
431c832d7cSdavidwang 		EMSG("Disabling unhandled interrupt %zu", it);
447315b7b4SJens Wiklander 		itr_chip->ops->disable(itr_chip, it);
457315b7b4SJens Wiklander 	}
467315b7b4SJens Wiklander }
477315b7b4SJens Wiklander 
487315b7b4SJens Wiklander void itr_add(struct itr_handler *h)
497315b7b4SJens Wiklander {
501c832d7cSdavidwang 	struct itr_handler __maybe_unused *hdl = NULL;
511c832d7cSdavidwang 
521c832d7cSdavidwang 	SLIST_FOREACH(hdl, &handlers, link)
531c832d7cSdavidwang 		if (hdl->it == h->it)
541c832d7cSdavidwang 			assert((hdl->flags & ITRF_SHARED) &&
551c832d7cSdavidwang 			       (h->flags & ITRF_SHARED));
561c832d7cSdavidwang 
577315b7b4SJens Wiklander 	itr_chip->ops->add(itr_chip, h->it, h->flags);
587315b7b4SJens Wiklander 	SLIST_INSERT_HEAD(&handlers, h, link);
597315b7b4SJens Wiklander }
607315b7b4SJens Wiklander 
6126ed70ecSGuanchao Liang void itr_enable(size_t it)
627315b7b4SJens Wiklander {
6326ed70ecSGuanchao Liang 	itr_chip->ops->enable(itr_chip, it);
647315b7b4SJens Wiklander }
657315b7b4SJens Wiklander 
6626ed70ecSGuanchao Liang void itr_disable(size_t it)
677315b7b4SJens Wiklander {
6826ed70ecSGuanchao Liang 	itr_chip->ops->disable(itr_chip, it);
6926ed70ecSGuanchao Liang }
7026ed70ecSGuanchao Liang 
7126ed70ecSGuanchao Liang void itr_raise_pi(size_t it)
7226ed70ecSGuanchao Liang {
7326ed70ecSGuanchao Liang 	itr_chip->ops->raise_pi(itr_chip, it);
7426ed70ecSGuanchao Liang }
7526ed70ecSGuanchao Liang 
7626ed70ecSGuanchao Liang void itr_raise_sgi(size_t it, uint8_t cpu_mask)
7726ed70ecSGuanchao Liang {
7826ed70ecSGuanchao Liang 	itr_chip->ops->raise_sgi(itr_chip, it, cpu_mask);
7926ed70ecSGuanchao Liang }
8026ed70ecSGuanchao Liang 
8126ed70ecSGuanchao Liang void itr_set_affinity(size_t it, uint8_t cpu_mask)
8226ed70ecSGuanchao Liang {
8326ed70ecSGuanchao Liang 	itr_chip->ops->set_affinity(itr_chip, it, cpu_mask);
847315b7b4SJens Wiklander }
85e9f46c74SJens Wiklander 
86e9f46c74SJens Wiklander /* This function is supposed to be overridden in platform specific code */
87e9f46c74SJens Wiklander void __weak __noreturn itr_core_handler(void)
88e9f46c74SJens Wiklander {
89e9f46c74SJens Wiklander 	panic("Secure interrupt handler not defined");
90e9f46c74SJens Wiklander }
91