xref: /optee_os/core/drivers/hfic.c (revision 99e2612cb7ec7a9ddced18ad03f602848bb97bce)
1a0602052SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2a0602052SJens Wiklander /*
3a0602052SJens Wiklander  * Copyright (c) 2022, Linaro Limited
4a0602052SJens Wiklander  */
5a0602052SJens Wiklander 
6a0602052SJens Wiklander #include <assert.h>
767e55c51SEtienne Carriere #include <compiler.h>
8a0602052SJens Wiklander #include <config.h>
9a0602052SJens Wiklander #include <drivers/hfic.h>
10a0602052SJens Wiklander #include <hafnium.h>
11a0602052SJens Wiklander #include <kernel/interrupt.h>
12a0602052SJens Wiklander #include <kernel/panic.h>
13a0602052SJens Wiklander #include <kernel/thread.h>
14a0602052SJens Wiklander 
1567e55c51SEtienne Carriere struct hfic_data {
1667e55c51SEtienne Carriere 	struct itr_chip chip;
1767e55c51SEtienne Carriere };
1867e55c51SEtienne Carriere 
1967e55c51SEtienne Carriere static struct hfic_data hfic_data __nex_bss;
2067e55c51SEtienne Carriere 
21a0602052SJens Wiklander static void hfic_op_add(struct itr_chip *chip __unused, size_t it __unused,
22a0602052SJens Wiklander 			uint32_t type __unused, uint32_t prio __unused)
23a0602052SJens Wiklander {
24a0602052SJens Wiklander }
25a0602052SJens Wiklander 
26a0602052SJens Wiklander static void hfic_op_enable(struct itr_chip *chip __unused, size_t it)
27a0602052SJens Wiklander {
28a0602052SJens Wiklander 	uint32_t res __maybe_unused = 0;
29a0602052SJens Wiklander 
30a0602052SJens Wiklander 	res = thread_hvc(HF_INTERRUPT_ENABLE, it, HF_ENABLE,
31a0602052SJens Wiklander 			 HF_INTERRUPT_TYPE_IRQ);
32a0602052SJens Wiklander 	assert(!res);
33a0602052SJens Wiklander }
34a0602052SJens Wiklander 
35a0602052SJens Wiklander static void hfic_op_disable(struct itr_chip *chip __unused, size_t it)
36a0602052SJens Wiklander {
37a0602052SJens Wiklander 	uint32_t res __maybe_unused = 0;
38a0602052SJens Wiklander 
39a0602052SJens Wiklander 	res = thread_hvc(HF_INTERRUPT_ENABLE, it, HF_DISABLE,
40a0602052SJens Wiklander 			 HF_INTERRUPT_TYPE_IRQ);
41a0602052SJens Wiklander 	assert(!res);
42a0602052SJens Wiklander }
43a0602052SJens Wiklander 
44a0602052SJens Wiklander static void hfic_op_raise_pi(struct itr_chip *chip __unused, size_t it __unused)
45a0602052SJens Wiklander {
46a0602052SJens Wiklander 	panic();
47a0602052SJens Wiklander }
48a0602052SJens Wiklander 
49a0602052SJens Wiklander static void hfic_op_raise_sgi(struct itr_chip *chip __unused,
50a0602052SJens Wiklander 			      size_t it __unused, uint8_t cpu_mask __unused)
51a0602052SJens Wiklander {
52a0602052SJens Wiklander 	panic();
53a0602052SJens Wiklander }
54a0602052SJens Wiklander 
55a0602052SJens Wiklander static void hfic_op_set_affinity(struct itr_chip *chip __unused,
56a0602052SJens Wiklander 				 size_t it __unused, uint8_t cpu_mask __unused)
57a0602052SJens Wiklander {
58a0602052SJens Wiklander 	panic();
59a0602052SJens Wiklander }
60a0602052SJens Wiklander 
61a0602052SJens Wiklander static const struct itr_ops hfic_ops = {
62a0602052SJens Wiklander 	.add = hfic_op_add,
6359feef28SEtienne Carriere 	.mask = hfic_op_disable,
6459feef28SEtienne Carriere 	.unmask = hfic_op_enable,
65a0602052SJens Wiklander 	.enable = hfic_op_enable,
66a0602052SJens Wiklander 	.disable = hfic_op_disable,
67a0602052SJens Wiklander 	.raise_pi = hfic_op_raise_pi,
68a0602052SJens Wiklander 	.raise_sgi = hfic_op_raise_sgi,
69a0602052SJens Wiklander 	.set_affinity = hfic_op_set_affinity,
70a0602052SJens Wiklander };
71a0602052SJens Wiklander 
7267e55c51SEtienne Carriere void hfic_init(void)
73a0602052SJens Wiklander {
7467e55c51SEtienne Carriere 	hfic_data.chip.ops = &hfic_ops;
7501980f3fSEtienne Carriere 	interrupt_main_init(&hfic_data.chip);
76a0602052SJens Wiklander }
77a0602052SJens Wiklander 
78358bf47cSEtienne Carriere /* Override interrupt_main_handler() with driver implementation */
79358bf47cSEtienne Carriere void interrupt_main_handler(void)
80a0602052SJens Wiklander {
81a0602052SJens Wiklander 	uint32_t id = 0;
82a0602052SJens Wiklander 	uint32_t res __maybe_unused = 0;
83a0602052SJens Wiklander 
84a0602052SJens Wiklander 	id = thread_hvc(HF_INTERRUPT_GET, 0, 0, 0);
85a0602052SJens Wiklander 	if (id == HF_INVALID_INTID) {
86a0602052SJens Wiklander 		DMSG("ignoring invalid interrupt %#"PRIx32, id);
87a0602052SJens Wiklander 		return;
88a0602052SJens Wiklander 	}
89a0602052SJens Wiklander 
90*99e2612cSEtienne Carriere 	interrupt_call_handlers(&hfic_data.chip, id);
91*99e2612cSEtienne Carriere 
92a0602052SJens Wiklander 	res = thread_hvc(HF_INTERRUPT_DEACTIVATE, id, id, 0);
93a0602052SJens Wiklander 	assert(!res);
94a0602052SJens Wiklander }
95