xref: /optee_os/core/drivers/imsic.c (revision f4b54213e855ff3b67f052923fab966614797036)
1*f4b54213SHuang Borong // SPDX-License-Identifier: BSD-2-Clause
2*f4b54213SHuang Borong /*
3*f4b54213SHuang Borong  * Copyright (c) 2021 Western Digital Corporation or its affiliates.
4*f4b54213SHuang Borong  * Copyright (c) 2022 Ventana Micro Systems Inc.
5*f4b54213SHuang Borong  * Copyright (c) 2025 Beijing Institute of Open Source Chip (BOSC)
6*f4b54213SHuang Borong  *
7*f4b54213SHuang Borong  * Authors:
8*f4b54213SHuang Borong  *   Anup Patel <anup.patel@wdc.com>
9*f4b54213SHuang Borong  *   Huang Borong <huangborong@bosc.ac.cn>
10*f4b54213SHuang Borong  */
11*f4b54213SHuang Borong 
12*f4b54213SHuang Borong #include <compiler.h>
13*f4b54213SHuang Borong #include <drivers/imsic.h>
14*f4b54213SHuang Borong #include <io.h>
15*f4b54213SHuang Borong #include <kernel/dt.h>
16*f4b54213SHuang Borong #include <kernel/interrupt.h>
17*f4b54213SHuang Borong #include <libfdt.h>
18*f4b54213SHuang Borong #include <mm/core_mmu.h>
19*f4b54213SHuang Borong #include <platform_config.h>
20*f4b54213SHuang Borong #include <riscv.h>
21*f4b54213SHuang Borong #include <string.h>
22*f4b54213SHuang Borong #include <trace.h>
23*f4b54213SHuang Borong #include <util.h>
24*f4b54213SHuang Borong 
25*f4b54213SHuang Borong #define IMSIC_MMIO_PAGE_SHIFT     12
26*f4b54213SHuang Borong #define IMSIC_MMIO_PAGE_SZ        BIT(IMSIC_MMIO_PAGE_SHIFT)
27*f4b54213SHuang Borong 
28*f4b54213SHuang Borong #define IMSIC_MIN_ID              63
29*f4b54213SHuang Borong #define IMSIC_MAX_ID              2048
30*f4b54213SHuang Borong 
31*f4b54213SHuang Borong #define IMSIC_TOPEI_ID_SHIFT      16
32*f4b54213SHuang Borong 
33*f4b54213SHuang Borong #define IMSIC_IPI_ID              1
34*f4b54213SHuang Borong 
35*f4b54213SHuang Borong #define IMSIC_COMPATIBLE          "riscv,imsics"
36*f4b54213SHuang Borong 
37*f4b54213SHuang Borong /* IMSIC CSRs */
38*f4b54213SHuang Borong #define IMSIC_EIDELIVERY          0x70
39*f4b54213SHuang Borong #define IMSIC_EITHRESHOLD         0x72
40*f4b54213SHuang Borong 
41*f4b54213SHuang Borong #define IMSIC_EIP0                0x80
42*f4b54213SHuang Borong #define IMSIC_EIP63               0xBF
43*f4b54213SHuang Borong #define IMSIC_EIPx_BITS           32
44*f4b54213SHuang Borong 
45*f4b54213SHuang Borong #define IMSIC_EIE0                0xC0
46*f4b54213SHuang Borong #define IMSIC_EIE63               0xFF
47*f4b54213SHuang Borong #define IMSIC_EIEx_BITS           32
48*f4b54213SHuang Borong 
49*f4b54213SHuang Borong #define IMSIC_DISABLE_EIDELIVERY  0
50*f4b54213SHuang Borong #define IMSIC_ENABLE_EIDELIVERY   1
51*f4b54213SHuang Borong 
52*f4b54213SHuang Borong #define IMSIC_DISABLE_EITHRESHOLD 1
53*f4b54213SHuang Borong #define IMSIC_ENABLE_EITHRESHOLD  0
54*f4b54213SHuang Borong 
55*f4b54213SHuang Borong static struct imsic_data imsic_data __nex_bss;
56*f4b54213SHuang Borong 
57*f4b54213SHuang Borong /*
58*f4b54213SHuang Borong  * The IMSIC CSRs need to be indirectly accessed through
59*f4b54213SHuang Borong  * the *iselect(miselect/siselect) and *ireg(mireg/sireg) CSRs.
60*f4b54213SHuang Borong  */
imsic_csr_write(unsigned long reg,unsigned long val)61*f4b54213SHuang Borong static void imsic_csr_write(unsigned long reg, unsigned long val)
62*f4b54213SHuang Borong {
63*f4b54213SHuang Borong 	write_csr(CSR_XISELECT, reg);
64*f4b54213SHuang Borong 	write_csr(CSR_XIREG, val);
65*f4b54213SHuang Borong }
66*f4b54213SHuang Borong 
imsic_csr_read(unsigned long reg)67*f4b54213SHuang Borong static unsigned long __unused imsic_csr_read(unsigned long reg)
68*f4b54213SHuang Borong {
69*f4b54213SHuang Borong 	write_csr(CSR_XISELECT, reg);
70*f4b54213SHuang Borong 	return read_csr(CSR_XIREG);
71*f4b54213SHuang Borong }
72*f4b54213SHuang Borong 
imsic_csr_set(unsigned long reg,unsigned long val)73*f4b54213SHuang Borong static void imsic_csr_set(unsigned long reg, unsigned long val)
74*f4b54213SHuang Borong {
75*f4b54213SHuang Borong 	write_csr(CSR_XISELECT, reg);
76*f4b54213SHuang Borong 	set_csr(CSR_XIREG, val);
77*f4b54213SHuang Borong }
78*f4b54213SHuang Borong 
imsic_csr_clear(unsigned long reg,unsigned long val)79*f4b54213SHuang Borong static void imsic_csr_clear(unsigned long reg, unsigned long val)
80*f4b54213SHuang Borong {
81*f4b54213SHuang Borong 	write_csr(CSR_XISELECT, reg);
82*f4b54213SHuang Borong 	clear_csr(CSR_XIREG, val);
83*f4b54213SHuang Borong }
84*f4b54213SHuang Borong 
imsic_enable_interrupt_delivery(void)85*f4b54213SHuang Borong static void imsic_enable_interrupt_delivery(void)
86*f4b54213SHuang Borong {
87*f4b54213SHuang Borong 	imsic_csr_write(IMSIC_EIDELIVERY, IMSIC_ENABLE_EIDELIVERY);
88*f4b54213SHuang Borong }
89*f4b54213SHuang Borong 
imsic_disable_interrupt_delivery(void)90*f4b54213SHuang Borong static void __unused imsic_disable_interrupt_delivery(void)
91*f4b54213SHuang Borong {
92*f4b54213SHuang Borong 	imsic_csr_write(IMSIC_EIDELIVERY, IMSIC_DISABLE_EIDELIVERY);
93*f4b54213SHuang Borong }
94*f4b54213SHuang Borong 
imsic_enable_interrupt_threshold(void)95*f4b54213SHuang Borong static void imsic_enable_interrupt_threshold(void)
96*f4b54213SHuang Borong {
97*f4b54213SHuang Borong 	imsic_csr_write(IMSIC_EITHRESHOLD, IMSIC_ENABLE_EITHRESHOLD);
98*f4b54213SHuang Borong }
99*f4b54213SHuang Borong 
imsic_disable_interrupt_threshold(void)100*f4b54213SHuang Borong static void __unused imsic_disable_interrupt_threshold(void)
101*f4b54213SHuang Borong {
102*f4b54213SHuang Borong 	imsic_csr_write(IMSIC_EITHRESHOLD, IMSIC_DISABLE_EITHRESHOLD);
103*f4b54213SHuang Borong }
104*f4b54213SHuang Borong 
imsic_claim_interrupt(void)105*f4b54213SHuang Borong static uint32_t imsic_claim_interrupt(void)
106*f4b54213SHuang Borong {
107*f4b54213SHuang Borong 	uint32_t val = swap_csr(CSR_XTOPEI, 0);
108*f4b54213SHuang Borong 
109*f4b54213SHuang Borong 	return val >> IMSIC_TOPEI_ID_SHIFT;
110*f4b54213SHuang Borong }
111*f4b54213SHuang Borong 
imsic_local_eix_update(uint32_t base_id,uint32_t num_id,bool pend,bool val)112*f4b54213SHuang Borong static void imsic_local_eix_update(uint32_t base_id, uint32_t num_id,
113*f4b54213SHuang Borong 				   bool pend, bool val)
114*f4b54213SHuang Borong {
115*f4b54213SHuang Borong 	uint32_t i = 0;
116*f4b54213SHuang Borong 	uint32_t isel = 0;
117*f4b54213SHuang Borong 	uint32_t ireg = 0;
118*f4b54213SHuang Borong 	uint32_t id = base_id;
119*f4b54213SHuang Borong 	uint32_t last_id = base_id + num_id;
120*f4b54213SHuang Borong 
121*f4b54213SHuang Borong 	while (id < last_id) {
122*f4b54213SHuang Borong 		isel = ROUNDDOWN(id, RISCV_XLEN_BITS) / IMSIC_EIPx_BITS;
123*f4b54213SHuang Borong 		isel += (pend) ? IMSIC_EIP0 : IMSIC_EIE0;
124*f4b54213SHuang Borong 
125*f4b54213SHuang Borong 		ireg = 0;
126*f4b54213SHuang Borong 		for (i = id & (RISCV_XLEN_BITS - 1);
127*f4b54213SHuang Borong 		     (id < last_id) && (i < RISCV_XLEN_BITS); i++) {
128*f4b54213SHuang Borong 			ireg |= BIT(i);
129*f4b54213SHuang Borong 			id++;
130*f4b54213SHuang Borong 		}
131*f4b54213SHuang Borong 
132*f4b54213SHuang Borong 		if (val)
133*f4b54213SHuang Borong 			imsic_csr_set(isel, ireg);
134*f4b54213SHuang Borong 		else
135*f4b54213SHuang Borong 			imsic_csr_clear(isel, ireg);
136*f4b54213SHuang Borong 	}
137*f4b54213SHuang Borong }
138*f4b54213SHuang Borong 
imsic_it_enable(uint32_t id)139*f4b54213SHuang Borong static void imsic_it_enable(uint32_t id)
140*f4b54213SHuang Borong {
141*f4b54213SHuang Borong 	imsic_local_eix_update(id, 1, false, true);
142*f4b54213SHuang Borong }
143*f4b54213SHuang Borong 
imsic_it_disable(uint32_t id)144*f4b54213SHuang Borong static void imsic_it_disable(uint32_t id)
145*f4b54213SHuang Borong {
146*f4b54213SHuang Borong 	imsic_local_eix_update(id, 1, false, false);
147*f4b54213SHuang Borong }
148*f4b54213SHuang Borong 
imsic_it_set_pending(uint32_t id)149*f4b54213SHuang Borong static void imsic_it_set_pending(uint32_t id)
150*f4b54213SHuang Borong {
151*f4b54213SHuang Borong 	imsic_local_eix_update(id, 1, true, true);
152*f4b54213SHuang Borong }
153*f4b54213SHuang Borong 
imsic_it_clear_pending(uint32_t id)154*f4b54213SHuang Borong static void imsic_it_clear_pending(uint32_t id)
155*f4b54213SHuang Borong {
156*f4b54213SHuang Borong 	imsic_local_eix_update(id, 1, true, false);
157*f4b54213SHuang Borong }
158*f4b54213SHuang Borong 
imsic_is_bad_it(struct imsic_data * imsic,size_t it)159*f4b54213SHuang Borong static bool imsic_is_bad_it(struct imsic_data *imsic, size_t it)
160*f4b54213SHuang Borong {
161*f4b54213SHuang Borong 	assert(imsic == &imsic_data);
162*f4b54213SHuang Borong 	return (!it || it > imsic->num_ids);
163*f4b54213SHuang Borong }
164*f4b54213SHuang Borong 
imsic_op_configure(struct itr_chip * chip,size_t it,uint32_t type,uint32_t prio __unused)165*f4b54213SHuang Borong static void imsic_op_configure(struct itr_chip *chip, size_t it,
166*f4b54213SHuang Borong 			       uint32_t type, uint32_t prio __unused)
167*f4b54213SHuang Borong {
168*f4b54213SHuang Borong 	struct imsic_data *imsic = container_of(chip, struct imsic_data, chip);
169*f4b54213SHuang Borong 	TEE_Result res = TEE_ERROR_GENERIC;
170*f4b54213SHuang Borong 
171*f4b54213SHuang Borong 	if (imsic_is_bad_it(imsic, it))
172*f4b54213SHuang Borong 		panic();
173*f4b54213SHuang Borong 
174*f4b54213SHuang Borong 	if (imsic->aplic_chip) {
175*f4b54213SHuang Borong 		res = interrupt_configure(imsic->aplic_chip, it, type, prio);
176*f4b54213SHuang Borong 		if (res)
177*f4b54213SHuang Borong 			panic();
178*f4b54213SHuang Borong 	}
179*f4b54213SHuang Borong 	imsic_it_disable(it);
180*f4b54213SHuang Borong 	imsic_it_clear_pending(it);
181*f4b54213SHuang Borong }
182*f4b54213SHuang Borong 
imsic_op_enable(struct itr_chip * chip,size_t it)183*f4b54213SHuang Borong static void imsic_op_enable(struct itr_chip *chip, size_t it)
184*f4b54213SHuang Borong {
185*f4b54213SHuang Borong 	struct imsic_data *imsic = container_of(chip, struct imsic_data, chip);
186*f4b54213SHuang Borong 
187*f4b54213SHuang Borong 	if (imsic_is_bad_it(imsic, it))
188*f4b54213SHuang Borong 		panic();
189*f4b54213SHuang Borong 
190*f4b54213SHuang Borong 	if (imsic->aplic_chip)
191*f4b54213SHuang Borong 		interrupt_enable(imsic->aplic_chip, it);
192*f4b54213SHuang Borong 	imsic_it_enable(it);
193*f4b54213SHuang Borong }
194*f4b54213SHuang Borong 
imsic_op_disable(struct itr_chip * chip,size_t it)195*f4b54213SHuang Borong static void imsic_op_disable(struct itr_chip *chip, size_t it)
196*f4b54213SHuang Borong {
197*f4b54213SHuang Borong 	struct imsic_data *imsic = container_of(chip, struct imsic_data, chip);
198*f4b54213SHuang Borong 
199*f4b54213SHuang Borong 	if (imsic_is_bad_it(imsic, it))
200*f4b54213SHuang Borong 		panic();
201*f4b54213SHuang Borong 
202*f4b54213SHuang Borong 	imsic_it_disable(it);
203*f4b54213SHuang Borong 	if (imsic->aplic_chip)
204*f4b54213SHuang Borong 		interrupt_disable(imsic->aplic_chip, it);
205*f4b54213SHuang Borong }
206*f4b54213SHuang Borong 
imsic_op_raise_pi(struct itr_chip * chip,size_t it)207*f4b54213SHuang Borong static void imsic_op_raise_pi(struct itr_chip *chip, size_t it)
208*f4b54213SHuang Borong {
209*f4b54213SHuang Borong 	struct imsic_data *imsic = container_of(chip, struct imsic_data, chip);
210*f4b54213SHuang Borong 
211*f4b54213SHuang Borong 	if (imsic_is_bad_it(imsic, it))
212*f4b54213SHuang Borong 		panic();
213*f4b54213SHuang Borong 
214*f4b54213SHuang Borong 	imsic_it_set_pending(it);
215*f4b54213SHuang Borong }
216*f4b54213SHuang Borong 
217*f4b54213SHuang Borong static const struct itr_ops imsic_ops = {
218*f4b54213SHuang Borong 	.configure = imsic_op_configure,
219*f4b54213SHuang Borong 	.enable = imsic_op_enable,
220*f4b54213SHuang Borong 	.disable = imsic_op_disable,
221*f4b54213SHuang Borong 	.mask = imsic_op_disable,
222*f4b54213SHuang Borong 	.unmask = imsic_op_enable,
223*f4b54213SHuang Borong 	.raise_pi = imsic_op_raise_pi,
224*f4b54213SHuang Borong };
225*f4b54213SHuang Borong 
imsic_init_base_addr(paddr_t imsic_base_pa)226*f4b54213SHuang Borong static void imsic_init_base_addr(paddr_t imsic_base_pa)
227*f4b54213SHuang Borong {
228*f4b54213SHuang Borong 	struct imsic_data *imsic = &imsic_data;
229*f4b54213SHuang Borong 	vaddr_t imsic_base = 0;
230*f4b54213SHuang Borong 
231*f4b54213SHuang Borong 	assert(cpu_mmu_enabled());
232*f4b54213SHuang Borong 
233*f4b54213SHuang Borong 	imsic_base = core_mmu_get_va(imsic_base_pa, MEM_AREA_IO_SEC,
234*f4b54213SHuang Borong 				     IMSIC_SIZE);
235*f4b54213SHuang Borong 	if (!imsic_base)
236*f4b54213SHuang Borong 		panic();
237*f4b54213SHuang Borong 
238*f4b54213SHuang Borong 	imsic->imsic_base = imsic_base;
239*f4b54213SHuang Borong 	imsic->size = IMSIC_SIZE;
240*f4b54213SHuang Borong 	imsic->targets_mmode = false;
241*f4b54213SHuang Borong 	imsic->num_ids = IMSIC_NUM_IDS;
242*f4b54213SHuang Borong 	imsic->guest_index_bits = IMSIC_GUEST_INDEX_BITS;
243*f4b54213SHuang Borong 	imsic->hart_index_bits = IMSIC_HART_INDEX_BITS;
244*f4b54213SHuang Borong 	imsic->group_index_bits = IMSIC_GROUP_INDEX_BITS;
245*f4b54213SHuang Borong 	imsic->group_index_shift = IMSIC_GROUP_INDEX_SHIFT;
246*f4b54213SHuang Borong }
247*f4b54213SHuang Borong 
248*f4b54213SHuang Borong #if defined(CFG_DT) && defined(CFG_RISCV_IMSIC)
imisc_parse_fdt_node(const void * fdt,int nodeoff,struct imsic_data * imsic)249*f4b54213SHuang Borong TEE_Result imisc_parse_fdt_node(const void *fdt, int nodeoff,
250*f4b54213SHuang Borong 				struct imsic_data *imsic)
251*f4b54213SHuang Borong {
252*f4b54213SHuang Borong 	const fdt32_t *val = NULL;
253*f4b54213SHuang Borong 	paddr_t reg_addr = 0;
254*f4b54213SHuang Borong 	size_t reg_size = 0;
255*f4b54213SHuang Borong 	int i = 0;
256*f4b54213SHuang Borong 	int rc = -1;
257*f4b54213SHuang Borong 	int len = 0;
258*f4b54213SHuang Borong 
259*f4b54213SHuang Borong 	if (nodeoff < 0 || !imsic || !fdt)
260*f4b54213SHuang Borong 		return TEE_ERROR_BAD_PARAMETERS;
261*f4b54213SHuang Borong 
262*f4b54213SHuang Borong 	rc = fdt_reg_info(fdt, nodeoff, &reg_addr, &reg_size);
263*f4b54213SHuang Borong 	if (rc < 0 || !reg_addr || !reg_size)
264*f4b54213SHuang Borong 		return TEE_ERROR_ITEM_NOT_FOUND;
265*f4b54213SHuang Borong 	imsic->imsic_base = core_mmu_get_va(reg_addr, MEM_AREA_IO_SEC,
266*f4b54213SHuang Borong 					    reg_size);
267*f4b54213SHuang Borong 	if (!imsic->imsic_base)
268*f4b54213SHuang Borong 		return TEE_ERROR_GENERIC;
269*f4b54213SHuang Borong 	imsic->size = reg_size;
270*f4b54213SHuang Borong 
271*f4b54213SHuang Borong 	imsic->targets_mmode = false;
272*f4b54213SHuang Borong 	val = fdt_getprop(fdt, nodeoff, "interrupts-extended", &len);
273*f4b54213SHuang Borong 	if (val && (size_t)len >= (2 * sizeof(fdt32_t))) {
274*f4b54213SHuang Borong 		len = len / sizeof(fdt32_t);
275*f4b54213SHuang Borong 		for (i = 0; i < len; i += 2) {
276*f4b54213SHuang Borong 			if (fdt32_to_cpu(val[i + 1]) == IRQ_M_EXT) {
277*f4b54213SHuang Borong 				imsic->targets_mmode = true;
278*f4b54213SHuang Borong 				break;
279*f4b54213SHuang Borong 			}
280*f4b54213SHuang Borong 		}
281*f4b54213SHuang Borong 	} else {
282*f4b54213SHuang Borong 		return TEE_ERROR_ITEM_NOT_FOUND;
283*f4b54213SHuang Borong 	}
284*f4b54213SHuang Borong 
285*f4b54213SHuang Borong 	val = fdt_getprop(fdt, nodeoff, "riscv,guest-index-bits", &len);
286*f4b54213SHuang Borong 	if (val && len > 0)
287*f4b54213SHuang Borong 		imsic->guest_index_bits = fdt32_to_cpu(*val);
288*f4b54213SHuang Borong 	else
289*f4b54213SHuang Borong 		imsic->guest_index_bits = 0;
290*f4b54213SHuang Borong 
291*f4b54213SHuang Borong 	val = fdt_getprop(fdt, nodeoff, "riscv,hart-index-bits", &len);
292*f4b54213SHuang Borong 	if (val && len > 0)
293*f4b54213SHuang Borong 		imsic->hart_index_bits = fdt32_to_cpu(*val);
294*f4b54213SHuang Borong 	else
295*f4b54213SHuang Borong 		imsic->hart_index_bits =
296*f4b54213SHuang Borong 			32 - __builtin_clz(CFG_TEE_CORE_NB_CORE - 1);
297*f4b54213SHuang Borong 
298*f4b54213SHuang Borong 	val = fdt_getprop(fdt, nodeoff, "riscv,group-index-bits", &len);
299*f4b54213SHuang Borong 	if (val && len > 0)
300*f4b54213SHuang Borong 		imsic->group_index_bits = fdt32_to_cpu(*val);
301*f4b54213SHuang Borong 	else
302*f4b54213SHuang Borong 		imsic->group_index_bits = 0;
303*f4b54213SHuang Borong 
304*f4b54213SHuang Borong 	val = fdt_getprop(fdt, nodeoff, "riscv,group-index-shift", &len);
305*f4b54213SHuang Borong 	if (val && len > 0)
306*f4b54213SHuang Borong 		imsic->group_index_shift = fdt32_to_cpu(*val);
307*f4b54213SHuang Borong 	else
308*f4b54213SHuang Borong 		imsic->group_index_shift = 2 * IMSIC_MMIO_PAGE_SHIFT;
309*f4b54213SHuang Borong 
310*f4b54213SHuang Borong 	val = fdt_getprop(fdt, nodeoff, "riscv,num-ids", &len);
311*f4b54213SHuang Borong 	if (val && len > 0)
312*f4b54213SHuang Borong 		imsic->num_ids = fdt32_to_cpu(*val);
313*f4b54213SHuang Borong 	else
314*f4b54213SHuang Borong 		return TEE_ERROR_ITEM_NOT_FOUND;
315*f4b54213SHuang Borong 
316*f4b54213SHuang Borong 	return TEE_SUCCESS;
317*f4b54213SHuang Borong }
318*f4b54213SHuang Borong #endif
319*f4b54213SHuang Borong 
imsic_init_from_device_tree(struct imsic_data * imsic)320*f4b54213SHuang Borong static TEE_Result imsic_init_from_device_tree(struct imsic_data *imsic)
321*f4b54213SHuang Borong {
322*f4b54213SHuang Borong 	void *fdt = NULL;
323*f4b54213SHuang Borong 	int node = FDT_ERR_NOTFOUND;
324*f4b54213SHuang Borong 	TEE_Result res = TEE_ERROR_GENERIC;
325*f4b54213SHuang Borong 
326*f4b54213SHuang Borong 	fdt = get_dt();
327*f4b54213SHuang Borong 	if (!fdt) {
328*f4b54213SHuang Borong 		EMSG("Unable to get DTB, IMSIC init failed");
329*f4b54213SHuang Borong 		return TEE_ERROR_ITEM_NOT_FOUND;
330*f4b54213SHuang Borong 	}
331*f4b54213SHuang Borong 
332*f4b54213SHuang Borong 	/*
333*f4b54213SHuang Borong 	 * Currently, only the S-level interrupt file is considered.
334*f4b54213SHuang Borong 	 * If the interrupt file is M-level, continue traversing.
335*f4b54213SHuang Borong 	 * If it is S-level, return directly.
336*f4b54213SHuang Borong 	 */
337*f4b54213SHuang Borong 	node = fdt_node_offset_by_compatible(fdt, -1, IMSIC_COMPATIBLE);
338*f4b54213SHuang Borong 	while (node != -FDT_ERR_NOTFOUND) {
339*f4b54213SHuang Borong 		res = imisc_parse_fdt_node(fdt, node, imsic);
340*f4b54213SHuang Borong 		if (res) {
341*f4b54213SHuang Borong 			EMSG("Parse IMSIC node failed");
342*f4b54213SHuang Borong 			return res;
343*f4b54213SHuang Borong 		}
344*f4b54213SHuang Borong 		if (!imsic->targets_mmode)
345*f4b54213SHuang Borong 			return TEE_SUCCESS;
346*f4b54213SHuang Borong 		node = fdt_node_offset_by_compatible(fdt, node,
347*f4b54213SHuang Borong 						     IMSIC_COMPATIBLE);
348*f4b54213SHuang Borong 	}
349*f4b54213SHuang Borong 
350*f4b54213SHuang Borong 	return TEE_ERROR_ITEM_NOT_FOUND;
351*f4b54213SHuang Borong }
352*f4b54213SHuang Borong 
imsic_it_handle(void)353*f4b54213SHuang Borong void imsic_it_handle(void)
354*f4b54213SHuang Borong {
355*f4b54213SHuang Borong 	struct imsic_data *imsic = &imsic_data;
356*f4b54213SHuang Borong 	uint32_t id = imsic_claim_interrupt();
357*f4b54213SHuang Borong 
358*f4b54213SHuang Borong 	if (id == IMSIC_IPI_ID)
359*f4b54213SHuang Borong 		DMSG("Interprocessor interrupt");
360*f4b54213SHuang Borong 
361*f4b54213SHuang Borong 	if (id > IMSIC_IPI_ID && id <= imsic->num_ids)
362*f4b54213SHuang Borong 		interrupt_call_handlers(&imsic->chip, id);
363*f4b54213SHuang Borong 	else
364*f4b54213SHuang Borong 		DMSG("ignoring interrupt %" PRIu32, id);
365*f4b54213SHuang Borong }
366*f4b54213SHuang Borong 
imsic_init_per_hart(void)367*f4b54213SHuang Borong void imsic_init_per_hart(void)
368*f4b54213SHuang Borong {
369*f4b54213SHuang Borong 	struct imsic_data *imsic = &imsic_data;
370*f4b54213SHuang Borong 
371*f4b54213SHuang Borong 	imsic_local_eix_update(1, imsic->num_ids, false, false);
372*f4b54213SHuang Borong 	imsic_enable_interrupt_threshold();
373*f4b54213SHuang Borong 	imsic_enable_interrupt_delivery();
374*f4b54213SHuang Borong }
375*f4b54213SHuang Borong 
imsic_init(paddr_t imsic_base_pa)376*f4b54213SHuang Borong void imsic_init(paddr_t imsic_base_pa)
377*f4b54213SHuang Borong {
378*f4b54213SHuang Borong 	struct imsic_data *imsic = &imsic_data;
379*f4b54213SHuang Borong 	TEE_Result res = TEE_ERROR_GENERIC;
380*f4b54213SHuang Borong 
381*f4b54213SHuang Borong 	if (IS_ENABLED(CFG_DT)) {
382*f4b54213SHuang Borong 		res = imsic_init_from_device_tree(imsic);
383*f4b54213SHuang Borong 		if (res)
384*f4b54213SHuang Borong 			panic();
385*f4b54213SHuang Borong 	} else {
386*f4b54213SHuang Borong 		imsic_init_base_addr(imsic_base_pa);
387*f4b54213SHuang Borong 	}
388*f4b54213SHuang Borong 
389*f4b54213SHuang Borong 	imsic->chip.ops = &imsic_ops;
390*f4b54213SHuang Borong 
391*f4b54213SHuang Borong 	imsic_init_per_hart();
392*f4b54213SHuang Borong 
393*f4b54213SHuang Borong 	imsic->aplic_chip = interrupt_get_main_chip();
394*f4b54213SHuang Borong 
395*f4b54213SHuang Borong 	interrupt_main_init(&imsic->chip);
396*f4b54213SHuang Borong }
397*f4b54213SHuang Borong 
imsic_dump_state(void)398*f4b54213SHuang Borong void imsic_dump_state(void)
399*f4b54213SHuang Borong {
400*f4b54213SHuang Borong }
401