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