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