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