1*3374752fSBo-Chen Chen /* 2*3374752fSBo-Chen Chen * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved. 3*3374752fSBo-Chen Chen * 4*3374752fSBo-Chen Chen * SPDX-License-Identifier: BSD-3-Clause 5*3374752fSBo-Chen Chen */ 6*3374752fSBo-Chen Chen 7*3374752fSBo-Chen Chen #include <assert.h> 8*3374752fSBo-Chen Chen #include <stdint.h> 9*3374752fSBo-Chen Chen #include <stdio.h> 10*3374752fSBo-Chen Chen 11*3374752fSBo-Chen Chen #include "../drivers/arm/gic/v3/gicv3_private.h" 12*3374752fSBo-Chen Chen #include <bl31/interrupt_mgmt.h> 13*3374752fSBo-Chen Chen #include <common/bl_common.h> 14*3374752fSBo-Chen Chen #include <common/debug.h> 15*3374752fSBo-Chen Chen 16*3374752fSBo-Chen Chen #include <mt_gic_v3.h> 17*3374752fSBo-Chen Chen #include <mtk_plat_common.h> 18*3374752fSBo-Chen Chen #include <plat/common/platform.h> 19*3374752fSBo-Chen Chen #include <plat_private.h> 20*3374752fSBo-Chen Chen #include <platform_def.h> 21*3374752fSBo-Chen Chen 22*3374752fSBo-Chen Chen #define SGI_MASK 0xffff 23*3374752fSBo-Chen Chen 24*3374752fSBo-Chen Chen uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; 25*3374752fSBo-Chen Chen static uint32_t rdist_has_saved[PLATFORM_CORE_COUNT]; 26*3374752fSBo-Chen Chen 27*3374752fSBo-Chen Chen /* we save and restore the GICv3 context on system suspend */ 28*3374752fSBo-Chen Chen gicv3_dist_ctx_t dist_ctx; 29*3374752fSBo-Chen Chen 30*3374752fSBo-Chen Chen static unsigned int mt_mpidr_to_core_pos(u_register_t mpidr) 31*3374752fSBo-Chen Chen { 32*3374752fSBo-Chen Chen return plat_core_pos_by_mpidr(mpidr); 33*3374752fSBo-Chen Chen } 34*3374752fSBo-Chen Chen 35*3374752fSBo-Chen Chen gicv3_driver_data_t mt_gicv3_data = { 36*3374752fSBo-Chen Chen .gicd_base = MT_GIC_BASE, 37*3374752fSBo-Chen Chen .gicr_base = MT_GIC_RDIST_BASE, 38*3374752fSBo-Chen Chen .rdistif_num = PLATFORM_CORE_COUNT, 39*3374752fSBo-Chen Chen .rdistif_base_addrs = rdistif_base_addrs, 40*3374752fSBo-Chen Chen .mpidr_to_core_pos = mt_mpidr_to_core_pos, 41*3374752fSBo-Chen Chen }; 42*3374752fSBo-Chen Chen 43*3374752fSBo-Chen Chen struct gic_chip_data { 44*3374752fSBo-Chen Chen /* All cores share the same configuration */ 45*3374752fSBo-Chen Chen unsigned int saved_group; 46*3374752fSBo-Chen Chen unsigned int saved_enable; 47*3374752fSBo-Chen Chen unsigned int saved_conf0; 48*3374752fSBo-Chen Chen unsigned int saved_conf1; 49*3374752fSBo-Chen Chen unsigned int saved_grpmod; 50*3374752fSBo-Chen Chen /* Per-core sgi */ 51*3374752fSBo-Chen Chen unsigned int saved_sgi[PLATFORM_CORE_COUNT]; 52*3374752fSBo-Chen Chen }; 53*3374752fSBo-Chen Chen 54*3374752fSBo-Chen Chen static struct gic_chip_data gic_data; 55*3374752fSBo-Chen Chen 56*3374752fSBo-Chen Chen void mt_gic_driver_init(void) 57*3374752fSBo-Chen Chen { 58*3374752fSBo-Chen Chen gicv3_driver_init(&mt_gicv3_data); 59*3374752fSBo-Chen Chen } 60*3374752fSBo-Chen Chen 61*3374752fSBo-Chen Chen void mt_gic_set_pending(uint32_t irq) 62*3374752fSBo-Chen Chen { 63*3374752fSBo-Chen Chen gicv3_set_interrupt_pending(irq, plat_my_core_pos()); 64*3374752fSBo-Chen Chen } 65*3374752fSBo-Chen Chen 66*3374752fSBo-Chen Chen void mt_gic_distif_save(void) 67*3374752fSBo-Chen Chen { 68*3374752fSBo-Chen Chen gicv3_distif_save(&dist_ctx); 69*3374752fSBo-Chen Chen } 70*3374752fSBo-Chen Chen 71*3374752fSBo-Chen Chen void mt_gic_distif_restore(void) 72*3374752fSBo-Chen Chen { 73*3374752fSBo-Chen Chen gicv3_distif_init_restore(&dist_ctx); 74*3374752fSBo-Chen Chen } 75*3374752fSBo-Chen Chen 76*3374752fSBo-Chen Chen void mt_gic_rdistif_init(void) 77*3374752fSBo-Chen Chen { 78*3374752fSBo-Chen Chen unsigned int proc_num; 79*3374752fSBo-Chen Chen unsigned int index; 80*3374752fSBo-Chen Chen uintptr_t gicr_base; 81*3374752fSBo-Chen Chen 82*3374752fSBo-Chen Chen proc_num = plat_my_core_pos(); 83*3374752fSBo-Chen Chen gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 84*3374752fSBo-Chen Chen 85*3374752fSBo-Chen Chen /* set all SGI/PPI as non-secure GROUP1 by default */ 86*3374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_IGROUPR0, ~0U); 87*3374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_IGRPMODR0, 0x0); 88*3374752fSBo-Chen Chen 89*3374752fSBo-Chen Chen /* setup the default PPI/SGI priorities */ 90*3374752fSBo-Chen Chen for (index = 0; index < TOTAL_PCPU_INTR_NUM; index += 4U) 91*3374752fSBo-Chen Chen gicr_write_ipriorityr(gicr_base, index, 92*3374752fSBo-Chen Chen GICD_IPRIORITYR_DEF_VAL); 93*3374752fSBo-Chen Chen } 94*3374752fSBo-Chen Chen 95*3374752fSBo-Chen Chen void mt_gic_rdistif_save(void) 96*3374752fSBo-Chen Chen { 97*3374752fSBo-Chen Chen unsigned int proc_num; 98*3374752fSBo-Chen Chen uintptr_t gicr_base; 99*3374752fSBo-Chen Chen 100*3374752fSBo-Chen Chen proc_num = plat_my_core_pos(); 101*3374752fSBo-Chen Chen gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 102*3374752fSBo-Chen Chen 103*3374752fSBo-Chen Chen gic_data.saved_group = mmio_read_32(gicr_base + GICR_IGROUPR0); 104*3374752fSBo-Chen Chen gic_data.saved_enable = mmio_read_32(gicr_base + GICR_ISENABLER0); 105*3374752fSBo-Chen Chen gic_data.saved_conf0 = mmio_read_32(gicr_base + GICR_ICFGR0); 106*3374752fSBo-Chen Chen gic_data.saved_conf1 = mmio_read_32(gicr_base + GICR_ICFGR1); 107*3374752fSBo-Chen Chen gic_data.saved_grpmod = mmio_read_32(gicr_base + GICR_IGRPMODR0); 108*3374752fSBo-Chen Chen 109*3374752fSBo-Chen Chen rdist_has_saved[proc_num] = 1; 110*3374752fSBo-Chen Chen } 111*3374752fSBo-Chen Chen 112*3374752fSBo-Chen Chen void mt_gic_rdistif_restore(void) 113*3374752fSBo-Chen Chen { 114*3374752fSBo-Chen Chen unsigned int proc_num; 115*3374752fSBo-Chen Chen uintptr_t gicr_base; 116*3374752fSBo-Chen Chen 117*3374752fSBo-Chen Chen proc_num = plat_my_core_pos(); 118*3374752fSBo-Chen Chen if (rdist_has_saved[proc_num] == 1) { 119*3374752fSBo-Chen Chen gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 120*3374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group); 121*3374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_ISENABLER0, 122*3374752fSBo-Chen Chen gic_data.saved_enable); 123*3374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0); 124*3374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1); 125*3374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_IGRPMODR0, 126*3374752fSBo-Chen Chen gic_data.saved_grpmod); 127*3374752fSBo-Chen Chen } 128*3374752fSBo-Chen Chen } 129*3374752fSBo-Chen Chen 130*3374752fSBo-Chen Chen void mt_gic_rdistif_restore_all(void) 131*3374752fSBo-Chen Chen { 132*3374752fSBo-Chen Chen unsigned int proc_num; 133*3374752fSBo-Chen Chen uintptr_t gicr_base; 134*3374752fSBo-Chen Chen 135*3374752fSBo-Chen Chen for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) { 136*3374752fSBo-Chen Chen gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 137*3374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group); 138*3374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_ISENABLER0, 139*3374752fSBo-Chen Chen gic_data.saved_enable); 140*3374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0); 141*3374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1); 142*3374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_IGRPMODR0, 143*3374752fSBo-Chen Chen gic_data.saved_grpmod); 144*3374752fSBo-Chen Chen } 145*3374752fSBo-Chen Chen } 146*3374752fSBo-Chen Chen 147*3374752fSBo-Chen Chen void gic_sgi_save_all(void) 148*3374752fSBo-Chen Chen { 149*3374752fSBo-Chen Chen unsigned int proc_num; 150*3374752fSBo-Chen Chen uintptr_t gicr_base; 151*3374752fSBo-Chen Chen 152*3374752fSBo-Chen Chen for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) { 153*3374752fSBo-Chen Chen gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 154*3374752fSBo-Chen Chen gic_data.saved_sgi[proc_num] = 155*3374752fSBo-Chen Chen mmio_read_32(gicr_base + GICR_ISPENDR0) & SGI_MASK; 156*3374752fSBo-Chen Chen } 157*3374752fSBo-Chen Chen } 158*3374752fSBo-Chen Chen 159*3374752fSBo-Chen Chen void gic_sgi_restore_all(void) 160*3374752fSBo-Chen Chen { 161*3374752fSBo-Chen Chen unsigned int proc_num; 162*3374752fSBo-Chen Chen uintptr_t gicr_base; 163*3374752fSBo-Chen Chen 164*3374752fSBo-Chen Chen for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) { 165*3374752fSBo-Chen Chen gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 166*3374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_ICPENDR0, SGI_MASK); 167*3374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_ISPENDR0, 168*3374752fSBo-Chen Chen gic_data.saved_sgi[proc_num] & SGI_MASK); 169*3374752fSBo-Chen Chen } 170*3374752fSBo-Chen Chen } 171*3374752fSBo-Chen Chen 172*3374752fSBo-Chen Chen void mt_gic_init(void) 173*3374752fSBo-Chen Chen { 174*3374752fSBo-Chen Chen gicv3_distif_init(); 175*3374752fSBo-Chen Chen gicv3_rdistif_init(plat_my_core_pos()); 176*3374752fSBo-Chen Chen gicv3_cpuif_enable(plat_my_core_pos()); 177*3374752fSBo-Chen Chen } 178*3374752fSBo-Chen Chen 179*3374752fSBo-Chen Chen uint32_t mt_irq_get_pending(uint32_t irq) 180*3374752fSBo-Chen Chen { 181*3374752fSBo-Chen Chen uint32_t val; 182*3374752fSBo-Chen Chen 183*3374752fSBo-Chen Chen val = mmio_read_32(BASE_GICD_BASE + GICD_ISPENDR + 184*3374752fSBo-Chen Chen irq / 32 * 4); 185*3374752fSBo-Chen Chen val = (val >> (irq % 32)) & 1U; 186*3374752fSBo-Chen Chen return val; 187*3374752fSBo-Chen Chen } 188*3374752fSBo-Chen Chen 189*3374752fSBo-Chen Chen 190*3374752fSBo-Chen Chen void mt_irq_set_pending(uint32_t irq) 191*3374752fSBo-Chen Chen { 192*3374752fSBo-Chen Chen uint32_t bit = 1U << (irq % 32); 193*3374752fSBo-Chen Chen 194*3374752fSBo-Chen Chen mmio_write_32(BASE_GICD_BASE + GICD_ISPENDR + 195*3374752fSBo-Chen Chen irq / 32 * 4, bit); 196*3374752fSBo-Chen Chen } 197