xref: /optee_os/core/drivers/aplic_msi.c (revision 69e9ad1b8e9db39a5dce0e620ac5ea77fc93f5a5)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2025 Beijing Institute of Open Source Chip (BOSC)
4  */
5 
6 #include <assert.h>
7 #include <compiler.h>
8 #include <config.h>
9 #include <drivers/aplic.h>
10 #include <drivers/aplic_priv.h>
11 #include <io.h>
12 #include <kernel/interrupt.h>
13 #include <kernel/misc.h>
14 #include <kernel/panic.h>
15 #include <mm/core_memprot.h>
16 #include <mm/core_mmu.h>
17 #include <platform_config.h>
18 #include <stdlib.h>
19 #include <sys/queue.h>
20 #include <trace.h>
21 #include <types_ext.h>
22 #include <util.h>
23 
24 static struct aplic_data aplic_data __nex_bss;
25 
aplic_set_target(struct aplic_data * aplic,uint32_t source,uint32_t hart_idx,uint32_t guest_idx,uint32_t eiid)26 static void aplic_set_target(struct aplic_data *aplic, uint32_t source,
27 			     uint32_t hart_idx, uint32_t guest_idx,
28 			     uint32_t eiid)
29 {
30 	vaddr_t target = 0;
31 	uint32_t val = 0;
32 
33 	val = SHIFT_U32(hart_idx, APLIC_TARGET_HART_IDX_SHIFT) &
34 		APLIC_TARGET_HART_IDX_MASK;
35 	val |= SHIFT_U32(guest_idx, APLIC_TARGET_GUEST_IDX_SHIFT) &
36 		APLIC_TARGET_GUEST_IDX_MASK;
37 	val |= eiid & APLIC_TARGET_EIID_MASK;
38 
39 	target = aplic->aplic_base + APLIC_TARGET_BASE +
40 	    (source - 1) * sizeof(uint32_t);
41 	io_write32(target, val);
42 }
43 
aplic_get_source_mode(struct aplic_data * aplic,uint32_t source)44 static uint32_t __unused aplic_get_source_mode(struct aplic_data *aplic,
45 					       uint32_t source)
46 {
47 	uint32_t sm = 0;
48 
49 	sm = io_read32(aplic->aplic_base + APLIC_SOURCECFG_BASE +
50 		       (source - 1) * sizeof(uint32_t));
51 
52 	return sm & APLIC_SOURCECFG_SM_MASK;
53 }
54 
aplic_init_base_addr(struct aplic_data * aplic,paddr_t aplic_base_pa)55 static void aplic_init_base_addr(struct aplic_data *aplic,
56 				 paddr_t aplic_base_pa)
57 {
58 	vaddr_t aplic_base = 0;
59 
60 	assert(cpu_mmu_enabled());
61 
62 	aplic_base = core_mmu_get_va(aplic_base_pa, MEM_AREA_IO_SEC,
63 				     APLIC_SIZE);
64 	if (!aplic_base)
65 		panic();
66 
67 	aplic->aplic_base = aplic_base;
68 	aplic->size = APLIC_SIZE;
69 	aplic->targets_mmode = false;
70 	aplic->num_idc = 0;
71 	aplic->num_source = APLIC_NUM_SOURCE;
72 }
73 
aplic_op_configure(struct itr_chip * chip,size_t it,uint32_t type,uint32_t prio __unused)74 static void aplic_op_configure(struct itr_chip *chip, size_t it, uint32_t type,
75 			       uint32_t prio __unused)
76 {
77 	struct aplic_data *aplic = container_of(chip, struct aplic_data, chip);
78 	size_t hartid = get_core_pos();
79 
80 	if (aplic_is_bad_it(aplic, it))
81 		panic();
82 
83 	aplic_disable_interrupt(aplic, it);
84 	if (aplic_set_source_mode(aplic, it, type))
85 		panic();
86 
87 	aplic_set_target(aplic, it, hartid, 0, it);
88 }
89 
aplic_op_enable(struct itr_chip * chip,size_t it)90 static void aplic_op_enable(struct itr_chip *chip, size_t it)
91 {
92 	struct aplic_data *aplic = container_of(chip, struct aplic_data, chip);
93 
94 	if (aplic_is_bad_it(aplic, it))
95 		panic();
96 
97 	aplic_enable_interrupt(aplic, it);
98 }
99 
aplic_op_disable(struct itr_chip * chip,size_t it)100 static void aplic_op_disable(struct itr_chip *chip, size_t it)
101 {
102 	struct aplic_data *aplic = container_of(chip, struct aplic_data, chip);
103 
104 	if (aplic_is_bad_it(aplic, it))
105 		panic();
106 
107 	aplic_disable_interrupt(aplic, it);
108 }
109 
aplic_op_raise_pi(struct itr_chip * chip,size_t it)110 static void aplic_op_raise_pi(struct itr_chip *chip, size_t it)
111 {
112 	struct aplic_data *aplic = container_of(chip, struct aplic_data, chip);
113 
114 	if (aplic_is_bad_it(aplic, it))
115 		panic();
116 
117 	aplic_set_pending(aplic, it);
118 }
119 
120 static const struct itr_ops aplic_ops = {
121 	.configure = aplic_op_configure,
122 	.enable = aplic_op_enable,
123 	.disable = aplic_op_disable,
124 	.mask = aplic_op_disable,
125 	.unmask = aplic_op_enable,
126 	.raise_pi = aplic_op_raise_pi,
127 };
128 
aplic_init(paddr_t aplic_base_pa)129 void aplic_init(paddr_t aplic_base_pa)
130 {
131 	struct aplic_data *aplic = &aplic_data;
132 	TEE_Result res = TEE_ERROR_GENERIC;
133 
134 	if (IS_ENABLED(CFG_DT)) {
135 		res = aplic_init_from_device_tree(aplic);
136 		if (res)
137 			panic();
138 	} else {
139 		aplic_init_base_addr(aplic, aplic_base_pa);
140 	}
141 
142 	aplic->chip.ops = &aplic_ops;
143 
144 	io_write32(aplic->aplic_base + APLIC_DOMAINCFG,
145 		   APLIC_DOMAINCFG_IE | APLIC_DOMAINCFG_DM);
146 
147 	interrupt_main_init(&aplic_data.chip);
148 }
149 
aplic_init_per_hart(void)150 void aplic_init_per_hart(void)
151 {
152 }
153 
aplic_it_handle(void)154 void aplic_it_handle(void)
155 {
156 }
157 
aplic_dump_state(void)158 void aplic_dump_state(void)
159 {
160 }
161