xref: /rk3399_ARM-atf/plat/mediatek/drivers/gicv3/mt_gic_v3.c (revision d905b3df300c1a822e666c5d8bd903ce16f5d507)
1*d905b3dfSRunyang Chen /*
2*d905b3dfSRunyang Chen  * Copyright (c) 2025, MediaTek Inc. All rights reserved.
3*d905b3dfSRunyang Chen  *
4*d905b3dfSRunyang Chen  * SPDX-License-Identifier: BSD-3-Clause
5*d905b3dfSRunyang Chen  */
6*d905b3dfSRunyang Chen 
7*d905b3dfSRunyang Chen #include <assert.h>
8*d905b3dfSRunyang Chen #include <stdint.h>
9*d905b3dfSRunyang Chen #include <stdio.h>
10*d905b3dfSRunyang Chen 
11*d905b3dfSRunyang Chen #include <bl31/interrupt_mgmt.h>
12*d905b3dfSRunyang Chen #include <common/bl_common.h>
13*d905b3dfSRunyang Chen #include <common/debug.h>
14*d905b3dfSRunyang Chen #include <gicv3_private.h>
15*d905b3dfSRunyang Chen #include <plat/common/common_def.h>
16*d905b3dfSRunyang Chen #include <plat/common/platform.h>
17*d905b3dfSRunyang Chen #include <platform_def.h>
18*d905b3dfSRunyang Chen 
19*d905b3dfSRunyang Chen #include <lib/mtk_init/mtk_init.h>
20*d905b3dfSRunyang Chen #include <mt_gic_v3.h>
21*d905b3dfSRunyang Chen #include <mtk_plat_common.h>
22*d905b3dfSRunyang Chen #include <plat_private.h>
23*d905b3dfSRunyang Chen 
24*d905b3dfSRunyang Chen uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
25*d905b3dfSRunyang Chen 
26*d905b3dfSRunyang Chen static gicv3_redist_ctx_t rdist_ctx;
27*d905b3dfSRunyang Chen static gicv3_dist_ctx_t dist_ctx;
28*d905b3dfSRunyang Chen 
29*d905b3dfSRunyang Chen /* Configure Secure IRQs */
30*d905b3dfSRunyang Chen static const interrupt_prop_t mt_interrupt_props[] = {
31*d905b3dfSRunyang Chen 	PLATFORM_G1S_PROPS(INTR_GROUP1S)
32*d905b3dfSRunyang Chen };
33*d905b3dfSRunyang Chen 
34*d905b3dfSRunyang Chen static unsigned int mt_mpidr_to_core_pos(u_register_t mpidr)
35*d905b3dfSRunyang Chen {
36*d905b3dfSRunyang Chen 	return plat_core_pos_by_mpidr(mpidr);
37*d905b3dfSRunyang Chen }
38*d905b3dfSRunyang Chen 
39*d905b3dfSRunyang Chen gicv3_driver_data_t mt_gicv3_data = {
40*d905b3dfSRunyang Chen 	.gicd_base = MT_GIC_BASE,
41*d905b3dfSRunyang Chen 	.gicr_base = MT_GIC_RDIST_BASE,
42*d905b3dfSRunyang Chen 	.rdistif_num = PLATFORM_CORE_COUNT,
43*d905b3dfSRunyang Chen 	.rdistif_base_addrs = rdistif_base_addrs,
44*d905b3dfSRunyang Chen 	.mpidr_to_core_pos = mt_mpidr_to_core_pos,
45*d905b3dfSRunyang Chen 	.interrupt_props = mt_interrupt_props,
46*d905b3dfSRunyang Chen 	.interrupt_props_num = ARRAY_SIZE(mt_interrupt_props),
47*d905b3dfSRunyang Chen };
48*d905b3dfSRunyang Chen 
49*d905b3dfSRunyang Chen int32_t mt_irq_get_pending(uint32_t irq)
50*d905b3dfSRunyang Chen {
51*d905b3dfSRunyang Chen 	uint32_t val;
52*d905b3dfSRunyang Chen 
53*d905b3dfSRunyang Chen 	if (!IS_SPI(irq))
54*d905b3dfSRunyang Chen 		return -EINVAL;
55*d905b3dfSRunyang Chen 
56*d905b3dfSRunyang Chen 	val = mmio_read_32(BASE_GICD_BASE + GICD_ISPENDR +
57*d905b3dfSRunyang Chen 		irq / 32 * 4);
58*d905b3dfSRunyang Chen 	val = (val >> (irq % 32)) & 1U;
59*d905b3dfSRunyang Chen 
60*d905b3dfSRunyang Chen 	return (int32_t)val;
61*d905b3dfSRunyang Chen }
62*d905b3dfSRunyang Chen 
63*d905b3dfSRunyang Chen int32_t mt_irq_set_pending(uint32_t irq)
64*d905b3dfSRunyang Chen {
65*d905b3dfSRunyang Chen 	uint32_t bit = 1U << (irq % 32);
66*d905b3dfSRunyang Chen 
67*d905b3dfSRunyang Chen 	if (!IS_SPI(irq))
68*d905b3dfSRunyang Chen 		return -EINVAL;
69*d905b3dfSRunyang Chen 
70*d905b3dfSRunyang Chen 	mmio_write_32(BASE_GICD_BASE + GICD_ISPENDR +
71*d905b3dfSRunyang Chen 		irq / 32 * 4, bit);
72*d905b3dfSRunyang Chen 
73*d905b3dfSRunyang Chen 	return 0;
74*d905b3dfSRunyang Chen }
75*d905b3dfSRunyang Chen 
76*d905b3dfSRunyang Chen uint32_t gicr_get_sgi_pending(void)
77*d905b3dfSRunyang Chen {
78*d905b3dfSRunyang Chen 	uint32_t result = 0, ispendr0, proc_num;
79*d905b3dfSRunyang Chen 
80*d905b3dfSRunyang Chen 	for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) {
81*d905b3dfSRunyang Chen 		ispendr0 =
82*d905b3dfSRunyang Chen 			gicr_read_ispendr0(MT_GIC_RDIST_BASE + proc_num * SZ_64K * 2);
83*d905b3dfSRunyang Chen 		result |= ((ispendr0 & SGI_MASK) ? 1 : 0) << proc_num;
84*d905b3dfSRunyang Chen 	}
85*d905b3dfSRunyang Chen 
86*d905b3dfSRunyang Chen 	return result;
87*d905b3dfSRunyang Chen }
88*d905b3dfSRunyang Chen 
89*d905b3dfSRunyang Chen void mt_gic_pcpu_init(void)
90*d905b3dfSRunyang Chen {
91*d905b3dfSRunyang Chen 	gicv3_rdistif_init(plat_my_core_pos());
92*d905b3dfSRunyang Chen }
93*d905b3dfSRunyang Chen 
94*d905b3dfSRunyang Chen void mt_gic_distif_save(void)
95*d905b3dfSRunyang Chen {
96*d905b3dfSRunyang Chen 	/* Save the GIC Distributor context */
97*d905b3dfSRunyang Chen 	gicv3_distif_save(&dist_ctx);
98*d905b3dfSRunyang Chen }
99*d905b3dfSRunyang Chen 
100*d905b3dfSRunyang Chen void mt_gic_distif_restore(void)
101*d905b3dfSRunyang Chen {
102*d905b3dfSRunyang Chen 	/* Restore the GIC Distributor context */
103*d905b3dfSRunyang Chen 	gicv3_distif_init_restore(&dist_ctx);
104*d905b3dfSRunyang Chen }
105*d905b3dfSRunyang Chen 
106*d905b3dfSRunyang Chen void mt_gic_rdistif_save(void)
107*d905b3dfSRunyang Chen {
108*d905b3dfSRunyang Chen 	uint32_t cpu;
109*d905b3dfSRunyang Chen 
110*d905b3dfSRunyang Chen 	/*
111*d905b3dfSRunyang Chen 	 * For all cores, save the GIC Redistributors and ITS contexts
112*d905b3dfSRunyang Chen 	 * before the Distributor context.
113*d905b3dfSRunyang Chen 	 */
114*d905b3dfSRunyang Chen 	for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
115*d905b3dfSRunyang Chen 		gicv3_rdistif_save(cpu, &rdist_ctx);
116*d905b3dfSRunyang Chen }
117*d905b3dfSRunyang Chen 
118*d905b3dfSRunyang Chen void mt_gic_rdistif_restore(void)
119*d905b3dfSRunyang Chen {
120*d905b3dfSRunyang Chen 	uint32_t cpu;
121*d905b3dfSRunyang Chen 
122*d905b3dfSRunyang Chen 	/*
123*d905b3dfSRunyang Chen 	 * Restore the GIC Redistributor and ITS contexts after the
124*d905b3dfSRunyang Chen 	 * Distributor context. As we only handle SYSTEM SUSPEND API,
125*d905b3dfSRunyang Chen 	 * we only need to restore the context of the CPU that issued
126*d905b3dfSRunyang Chen 	 * the SYSTEM SUSPEND call.
127*d905b3dfSRunyang Chen 	 */
128*d905b3dfSRunyang Chen 	for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++)
129*d905b3dfSRunyang Chen 		gicv3_rdistif_init_restore(cpu, &rdist_ctx);
130*d905b3dfSRunyang Chen }
131*d905b3dfSRunyang Chen 
132*d905b3dfSRunyang Chen void mt_gic_redistif_on(void)
133*d905b3dfSRunyang Chen {
134*d905b3dfSRunyang Chen 	gicv3_rdistif_on(plat_my_core_pos());
135*d905b3dfSRunyang Chen }
136*d905b3dfSRunyang Chen 
137*d905b3dfSRunyang Chen void mt_gic_redistif_off(void)
138*d905b3dfSRunyang Chen {
139*d905b3dfSRunyang Chen 	gicv3_rdistif_off(plat_my_core_pos());
140*d905b3dfSRunyang Chen }
141*d905b3dfSRunyang Chen 
142*d905b3dfSRunyang Chen void mt_gic_redistif_init(void)
143*d905b3dfSRunyang Chen {
144*d905b3dfSRunyang Chen 	gicv3_rdistif_init(plat_my_core_pos());
145*d905b3dfSRunyang Chen }
146*d905b3dfSRunyang Chen 
147*d905b3dfSRunyang Chen void mt_gic_cpuif_enable(void)
148*d905b3dfSRunyang Chen {
149*d905b3dfSRunyang Chen 	gicv3_cpuif_enable(plat_my_core_pos());
150*d905b3dfSRunyang Chen }
151*d905b3dfSRunyang Chen 
152*d905b3dfSRunyang Chen void mt_gic_cpuif_disable(void)
153*d905b3dfSRunyang Chen {
154*d905b3dfSRunyang Chen 	gicv3_cpuif_disable(plat_my_core_pos());
155*d905b3dfSRunyang Chen }
156*d905b3dfSRunyang Chen void mt_gic_driver_init(void)
157*d905b3dfSRunyang Chen {
158*d905b3dfSRunyang Chen 	/*
159*d905b3dfSRunyang Chen 	 * The GICv3 driver is initialized in EL3 and does not need
160*d905b3dfSRunyang Chen 	 * to be initialized again in SEL1. This is because the S-EL1
161*d905b3dfSRunyang Chen 	 * can use GIC system registers to manage interrupts and does
162*d905b3dfSRunyang Chen 	 * not need GIC interface base addresses to be configured.
163*d905b3dfSRunyang Chen 	 */
164*d905b3dfSRunyang Chen #if (!defined(__aarch64__) && defined(IMAGE_BL32)) || \
165*d905b3dfSRunyang Chen 	(defined(__aarch64__) && defined(IMAGE_BL31))
166*d905b3dfSRunyang Chen 	gicv3_driver_init(&mt_gicv3_data);
167*d905b3dfSRunyang Chen #endif
168*d905b3dfSRunyang Chen }
169*d905b3dfSRunyang Chen 
170*d905b3dfSRunyang Chen void mt_gic_init(void)
171*d905b3dfSRunyang Chen {
172*d905b3dfSRunyang Chen 	gicv3_distif_init();
173*d905b3dfSRunyang Chen 	gicv3_rdistif_init(plat_my_core_pos());
174*d905b3dfSRunyang Chen 	gicv3_cpuif_enable(plat_my_core_pos());
175*d905b3dfSRunyang Chen }
176*d905b3dfSRunyang Chen 
177*d905b3dfSRunyang Chen int mt_gic_one_init(void)
178*d905b3dfSRunyang Chen {
179*d905b3dfSRunyang Chen 	INFO("[%s] GIC initialization\n", __func__);
180*d905b3dfSRunyang Chen 
181*d905b3dfSRunyang Chen 	mt_gic_driver_init();
182*d905b3dfSRunyang Chen 	mt_gic_init();
183*d905b3dfSRunyang Chen 
184*d905b3dfSRunyang Chen 	return 0;
185*d905b3dfSRunyang Chen }
186*d905b3dfSRunyang Chen 
187*d905b3dfSRunyang Chen MTK_PLAT_SETUP_0_INIT(mt_gic_one_init);
188