xref: /optee_os/core/kernel/interrupt.c (revision 7315b7b47303ec73b8f5a994c37bb6bed0d00e37)
1*7315b7b4SJens Wiklander /*
2*7315b7b4SJens Wiklander  * Copyright (c) 2016, Linaro Limited
3*7315b7b4SJens Wiklander  * All rights reserved.
4*7315b7b4SJens Wiklander  *
5*7315b7b4SJens Wiklander  * Redistribution and use in source and binary forms, with or without
6*7315b7b4SJens Wiklander  * modification, are permitted provided that the following conditions are met:
7*7315b7b4SJens Wiklander  *
8*7315b7b4SJens Wiklander  * 1. Redistributions of source code must retain the above copyright notice,
9*7315b7b4SJens Wiklander  * this list of conditions and the following disclaimer.
10*7315b7b4SJens Wiklander  *
11*7315b7b4SJens Wiklander  * 2. Redistributions in binary form must reproduce the above copyright notice,
12*7315b7b4SJens Wiklander  * this list of conditions and the following disclaimer in the documentation
13*7315b7b4SJens Wiklander  * and/or other materials provided with the distribution.
14*7315b7b4SJens Wiklander  *
15*7315b7b4SJens Wiklander  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16*7315b7b4SJens Wiklander  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*7315b7b4SJens Wiklander  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*7315b7b4SJens Wiklander  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19*7315b7b4SJens Wiklander  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20*7315b7b4SJens Wiklander  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21*7315b7b4SJens Wiklander  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22*7315b7b4SJens Wiklander  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23*7315b7b4SJens Wiklander  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24*7315b7b4SJens Wiklander  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25*7315b7b4SJens Wiklander  * POSSIBILITY OF SUCH DAMAGE.
26*7315b7b4SJens Wiklander  */
27*7315b7b4SJens Wiklander 
28*7315b7b4SJens Wiklander #include <kernel/interrupt.h>
29*7315b7b4SJens Wiklander #include <trace.h>
30*7315b7b4SJens Wiklander 
31*7315b7b4SJens Wiklander /*
32*7315b7b4SJens Wiklander  * NOTE!
33*7315b7b4SJens Wiklander  *
34*7315b7b4SJens Wiklander  * We're assuming that there's no concurrent use of this interface, except
35*7315b7b4SJens Wiklander  * delivery of interrupts in parallel. Synchronization will be needed when
36*7315b7b4SJens Wiklander  * we begin to modify settings after boot initialization.
37*7315b7b4SJens Wiklander  */
38*7315b7b4SJens Wiklander 
39*7315b7b4SJens Wiklander static struct itr_chip *itr_chip;
40*7315b7b4SJens Wiklander static SLIST_HEAD(, itr_handler) handlers = SLIST_HEAD_INITIALIZER(handlers);
41*7315b7b4SJens Wiklander 
42*7315b7b4SJens Wiklander void itr_init(struct itr_chip *chip)
43*7315b7b4SJens Wiklander {
44*7315b7b4SJens Wiklander 	itr_chip = chip;
45*7315b7b4SJens Wiklander }
46*7315b7b4SJens Wiklander 
47*7315b7b4SJens Wiklander static struct itr_handler *find_handler(size_t it)
48*7315b7b4SJens Wiklander {
49*7315b7b4SJens Wiklander 	struct itr_handler *h;
50*7315b7b4SJens Wiklander 
51*7315b7b4SJens Wiklander 	SLIST_FOREACH(h, &handlers, link)
52*7315b7b4SJens Wiklander 		if (h->it == it)
53*7315b7b4SJens Wiklander 			return h;
54*7315b7b4SJens Wiklander 	return NULL;
55*7315b7b4SJens Wiklander }
56*7315b7b4SJens Wiklander 
57*7315b7b4SJens Wiklander void itr_handle(size_t it)
58*7315b7b4SJens Wiklander {
59*7315b7b4SJens Wiklander 	struct itr_handler *h = find_handler(it);
60*7315b7b4SJens Wiklander 
61*7315b7b4SJens Wiklander 	if (!h) {
62*7315b7b4SJens Wiklander 		EMSG("Disabling unhandled interrupt %zu", it);
63*7315b7b4SJens Wiklander 		itr_chip->ops->disable(itr_chip, it);
64*7315b7b4SJens Wiklander 		return;
65*7315b7b4SJens Wiklander 	}
66*7315b7b4SJens Wiklander 
67*7315b7b4SJens Wiklander 	if (h->handler(h) != ITRR_HANDLED) {
68*7315b7b4SJens Wiklander 		EMSG("Disabling interrupt %zu not handled by handler", it);
69*7315b7b4SJens Wiklander 		itr_chip->ops->disable(itr_chip, it);
70*7315b7b4SJens Wiklander 	}
71*7315b7b4SJens Wiklander }
72*7315b7b4SJens Wiklander 
73*7315b7b4SJens Wiklander void itr_add(struct itr_handler *h)
74*7315b7b4SJens Wiklander {
75*7315b7b4SJens Wiklander 	itr_chip->ops->add(itr_chip, h->it, h->flags);
76*7315b7b4SJens Wiklander 	SLIST_INSERT_HEAD(&handlers, h, link);
77*7315b7b4SJens Wiklander }
78*7315b7b4SJens Wiklander 
79*7315b7b4SJens Wiklander void itr_enable(struct itr_handler *h)
80*7315b7b4SJens Wiklander {
81*7315b7b4SJens Wiklander 	itr_chip->ops->enable(itr_chip, h->it);
82*7315b7b4SJens Wiklander }
83*7315b7b4SJens Wiklander 
84*7315b7b4SJens Wiklander void itr_disable(struct itr_handler *h)
85*7315b7b4SJens Wiklander {
86*7315b7b4SJens Wiklander 	itr_chip->ops->disable(itr_chip, h->it);
87*7315b7b4SJens Wiklander }
88