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 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 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 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 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 89 void mt_gic_pcpu_init(void) 90 { 91 gicv3_rdistif_init(plat_my_core_pos()); 92 } 93 94 void mt_gic_distif_save(void) 95 { 96 /* Save the GIC Distributor context */ 97 gicv3_distif_save(&dist_ctx); 98 } 99 100 void mt_gic_distif_restore(void) 101 { 102 /* Restore the GIC Distributor context */ 103 gicv3_distif_init_restore(&dist_ctx); 104 } 105 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 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 132 void mt_gic_redistif_on(void) 133 { 134 gicv3_rdistif_on(plat_my_core_pos()); 135 } 136 137 void mt_gic_redistif_off(void) 138 { 139 gicv3_rdistif_off(plat_my_core_pos()); 140 } 141 142 void mt_gic_redistif_init(void) 143 { 144 gicv3_rdistif_init(plat_my_core_pos()); 145 } 146 147 void mt_gic_cpuif_enable(void) 148 { 149 gicv3_cpuif_enable(plat_my_core_pos()); 150 } 151 152 void mt_gic_cpuif_disable(void) 153 { 154 gicv3_cpuif_disable(plat_my_core_pos()); 155 } 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 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 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