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