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