1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <stdint.h> 9*91f16700Schasinglulu #include <stdio.h> 10*91f16700Schasinglulu 11*91f16700Schasinglulu #include "../drivers/arm/gic/v3/gicv3_private.h" 12*91f16700Schasinglulu #include <bl31/interrupt_mgmt.h> 13*91f16700Schasinglulu #include <common/bl_common.h> 14*91f16700Schasinglulu #include <common/debug.h> 15*91f16700Schasinglulu #include <lib/mtk_init/mtk_init.h> 16*91f16700Schasinglulu #include <mt_gic_v3.h> 17*91f16700Schasinglulu #include <mtk_plat_common.h> 18*91f16700Schasinglulu #include <plat/common/platform.h> 19*91f16700Schasinglulu #include <plat_private.h> 20*91f16700Schasinglulu #include <platform_def.h> 21*91f16700Schasinglulu 22*91f16700Schasinglulu #define SGI_MASK 0xffff 23*91f16700Schasinglulu 24*91f16700Schasinglulu uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; 25*91f16700Schasinglulu static uint32_t rdist_has_saved[PLATFORM_CORE_COUNT]; 26*91f16700Schasinglulu 27*91f16700Schasinglulu /* we save and restore the GICv3 context on system suspend */ 28*91f16700Schasinglulu gicv3_dist_ctx_t dist_ctx; 29*91f16700Schasinglulu 30*91f16700Schasinglulu static unsigned int mt_mpidr_to_core_pos(u_register_t mpidr) 31*91f16700Schasinglulu { 32*91f16700Schasinglulu return plat_core_pos_by_mpidr(mpidr); 33*91f16700Schasinglulu } 34*91f16700Schasinglulu 35*91f16700Schasinglulu gicv3_driver_data_t mt_gicv3_data = { 36*91f16700Schasinglulu .gicd_base = MT_GIC_BASE, 37*91f16700Schasinglulu .gicr_base = MT_GIC_RDIST_BASE, 38*91f16700Schasinglulu .rdistif_num = PLATFORM_CORE_COUNT, 39*91f16700Schasinglulu .rdistif_base_addrs = rdistif_base_addrs, 40*91f16700Schasinglulu .mpidr_to_core_pos = mt_mpidr_to_core_pos, 41*91f16700Schasinglulu }; 42*91f16700Schasinglulu 43*91f16700Schasinglulu struct gic_chip_data { 44*91f16700Schasinglulu /* All cores share the same configuration */ 45*91f16700Schasinglulu unsigned int saved_ctlr; 46*91f16700Schasinglulu unsigned int saved_group; 47*91f16700Schasinglulu unsigned int saved_enable; 48*91f16700Schasinglulu unsigned int saved_conf0; 49*91f16700Schasinglulu unsigned int saved_conf1; 50*91f16700Schasinglulu unsigned int saved_grpmod; 51*91f16700Schasinglulu unsigned int saved_ispendr; 52*91f16700Schasinglulu unsigned int saved_isactiver; 53*91f16700Schasinglulu unsigned int saved_nsacr; 54*91f16700Schasinglulu /* Per-core sgi */ 55*91f16700Schasinglulu unsigned int saved_sgi[PLATFORM_CORE_COUNT]; 56*91f16700Schasinglulu /* Per-core priority */ 57*91f16700Schasinglulu unsigned int saved_prio[PLATFORM_CORE_COUNT][GICR_NUM_REGS(IPRIORITYR)]; 58*91f16700Schasinglulu }; 59*91f16700Schasinglulu 60*91f16700Schasinglulu static struct gic_chip_data gic_data; 61*91f16700Schasinglulu 62*91f16700Schasinglulu void mt_gic_driver_init(void) 63*91f16700Schasinglulu { 64*91f16700Schasinglulu gicv3_driver_init(&mt_gicv3_data); 65*91f16700Schasinglulu } 66*91f16700Schasinglulu 67*91f16700Schasinglulu void mt_gic_set_pending(uint32_t irq) 68*91f16700Schasinglulu { 69*91f16700Schasinglulu gicv3_set_interrupt_pending(irq, plat_my_core_pos()); 70*91f16700Schasinglulu } 71*91f16700Schasinglulu 72*91f16700Schasinglulu void mt_gic_distif_save(void) 73*91f16700Schasinglulu { 74*91f16700Schasinglulu gicv3_distif_save(&dist_ctx); 75*91f16700Schasinglulu } 76*91f16700Schasinglulu 77*91f16700Schasinglulu void mt_gic_distif_restore(void) 78*91f16700Schasinglulu { 79*91f16700Schasinglulu gicv3_distif_init_restore(&dist_ctx); 80*91f16700Schasinglulu } 81*91f16700Schasinglulu 82*91f16700Schasinglulu void mt_gic_rdistif_init(void) 83*91f16700Schasinglulu { 84*91f16700Schasinglulu unsigned int proc_num; 85*91f16700Schasinglulu unsigned int index; 86*91f16700Schasinglulu uintptr_t gicr_base; 87*91f16700Schasinglulu 88*91f16700Schasinglulu proc_num = plat_my_core_pos(); 89*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 90*91f16700Schasinglulu 91*91f16700Schasinglulu /* set all SGI/PPI as non-secure GROUP1 by default */ 92*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_IGROUPR0, ~0U); 93*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_IGRPMODR0, 0x0); 94*91f16700Schasinglulu 95*91f16700Schasinglulu /* setup the default PPI/SGI priorities */ 96*91f16700Schasinglulu for (index = 0; index < TOTAL_PCPU_INTR_NUM; index += 4U) 97*91f16700Schasinglulu gicr_write_ipriorityr(gicr_base, index, 98*91f16700Schasinglulu GICD_IPRIORITYR_DEF_VAL); 99*91f16700Schasinglulu } 100*91f16700Schasinglulu 101*91f16700Schasinglulu void mt_gic_rdistif_save(void) 102*91f16700Schasinglulu { 103*91f16700Schasinglulu unsigned int i, proc_num; 104*91f16700Schasinglulu uintptr_t gicr_base; 105*91f16700Schasinglulu 106*91f16700Schasinglulu proc_num = plat_my_core_pos(); 107*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 108*91f16700Schasinglulu 109*91f16700Schasinglulu /* 110*91f16700Schasinglulu * Wait for any write to GICR_CTLR to complete before trying to save any 111*91f16700Schasinglulu * state. 112*91f16700Schasinglulu */ 113*91f16700Schasinglulu gicr_wait_for_pending_write(gicr_base); 114*91f16700Schasinglulu 115*91f16700Schasinglulu gic_data.saved_ctlr = mmio_read_32(gicr_base + GICR_CTLR); 116*91f16700Schasinglulu gic_data.saved_group = mmio_read_32(gicr_base + GICR_IGROUPR0); 117*91f16700Schasinglulu gic_data.saved_enable = mmio_read_32(gicr_base + GICR_ISENABLER0); 118*91f16700Schasinglulu gic_data.saved_conf0 = mmio_read_32(gicr_base + GICR_ICFGR0); 119*91f16700Schasinglulu gic_data.saved_conf1 = mmio_read_32(gicr_base + GICR_ICFGR1); 120*91f16700Schasinglulu gic_data.saved_grpmod = mmio_read_32(gicr_base + GICR_IGRPMODR0); 121*91f16700Schasinglulu gic_data.saved_ispendr = mmio_read_32(gicr_base + GICR_ISPENDR0); 122*91f16700Schasinglulu gic_data.saved_isactiver = mmio_read_32(gicr_base + GICR_ISACTIVER0); 123*91f16700Schasinglulu gic_data.saved_nsacr = mmio_read_32(gicr_base + GICR_NSACR); 124*91f16700Schasinglulu 125*91f16700Schasinglulu for (i = 0U; i < 8U; ++i) 126*91f16700Schasinglulu gic_data.saved_prio[proc_num][i] = gicr_ipriorityr_read(gicr_base, i); 127*91f16700Schasinglulu 128*91f16700Schasinglulu rdist_has_saved[proc_num] = 1; 129*91f16700Schasinglulu } 130*91f16700Schasinglulu 131*91f16700Schasinglulu void mt_gic_rdistif_restore(void) 132*91f16700Schasinglulu { 133*91f16700Schasinglulu unsigned int i, proc_num; 134*91f16700Schasinglulu uintptr_t gicr_base; 135*91f16700Schasinglulu 136*91f16700Schasinglulu proc_num = plat_my_core_pos(); 137*91f16700Schasinglulu if (rdist_has_saved[proc_num] == 1) { 138*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 139*91f16700Schasinglulu 140*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group); 141*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_IGRPMODR0, gic_data.saved_grpmod); 142*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_NSACR, gic_data.saved_nsacr); 143*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0); 144*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1); 145*91f16700Schasinglulu 146*91f16700Schasinglulu for (i = 0U; i < 8U; ++i) 147*91f16700Schasinglulu gicr_ipriorityr_write(gicr_base, i, gic_data.saved_prio[proc_num][i]); 148*91f16700Schasinglulu 149*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_ISPENDR0, gic_data.saved_ispendr); 150*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_ISACTIVER0, gic_data.saved_isactiver); 151*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_ISENABLER0, gic_data.saved_enable); 152*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_CTLR, gic_data.saved_ctlr); 153*91f16700Schasinglulu 154*91f16700Schasinglulu gicr_wait_for_pending_write(gicr_base); 155*91f16700Schasinglulu } 156*91f16700Schasinglulu } 157*91f16700Schasinglulu 158*91f16700Schasinglulu void mt_gic_rdistif_restore_all(void) 159*91f16700Schasinglulu { 160*91f16700Schasinglulu unsigned int i, proc_num; 161*91f16700Schasinglulu uintptr_t gicr_base; 162*91f16700Schasinglulu 163*91f16700Schasinglulu for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) { 164*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 165*91f16700Schasinglulu 166*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group); 167*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_IGRPMODR0, gic_data.saved_grpmod); 168*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_NSACR, gic_data.saved_nsacr); 169*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0); 170*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1); 171*91f16700Schasinglulu 172*91f16700Schasinglulu for (i = 0U; i < 8U; ++i) 173*91f16700Schasinglulu gicr_ipriorityr_write(gicr_base, i, gic_data.saved_prio[proc_num][i]); 174*91f16700Schasinglulu 175*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_ISPENDR0, gic_data.saved_ispendr); 176*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_ISACTIVER0, gic_data.saved_isactiver); 177*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_ISENABLER0, gic_data.saved_enable); 178*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_CTLR, gic_data.saved_ctlr); 179*91f16700Schasinglulu 180*91f16700Schasinglulu gicr_wait_for_pending_write(gicr_base); 181*91f16700Schasinglulu } 182*91f16700Schasinglulu } 183*91f16700Schasinglulu 184*91f16700Schasinglulu void gic_sgi_save_all(void) 185*91f16700Schasinglulu { 186*91f16700Schasinglulu unsigned int proc_num; 187*91f16700Schasinglulu uintptr_t gicr_base; 188*91f16700Schasinglulu 189*91f16700Schasinglulu for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) { 190*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 191*91f16700Schasinglulu gic_data.saved_sgi[proc_num] = 192*91f16700Schasinglulu mmio_read_32(gicr_base + GICR_ISPENDR0) & SGI_MASK; 193*91f16700Schasinglulu } 194*91f16700Schasinglulu } 195*91f16700Schasinglulu 196*91f16700Schasinglulu void gic_sgi_restore_all(void) 197*91f16700Schasinglulu { 198*91f16700Schasinglulu unsigned int proc_num; 199*91f16700Schasinglulu uintptr_t gicr_base; 200*91f16700Schasinglulu 201*91f16700Schasinglulu for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) { 202*91f16700Schasinglulu gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 203*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_ICPENDR0, SGI_MASK); 204*91f16700Schasinglulu mmio_write_32(gicr_base + GICR_ISPENDR0, 205*91f16700Schasinglulu gic_data.saved_sgi[proc_num] & SGI_MASK); 206*91f16700Schasinglulu } 207*91f16700Schasinglulu } 208*91f16700Schasinglulu 209*91f16700Schasinglulu void mt_gic_init(void) 210*91f16700Schasinglulu { 211*91f16700Schasinglulu gicv3_distif_init(); 212*91f16700Schasinglulu gicv3_rdistif_init(plat_my_core_pos()); 213*91f16700Schasinglulu gicv3_cpuif_enable(plat_my_core_pos()); 214*91f16700Schasinglulu } 215*91f16700Schasinglulu 216*91f16700Schasinglulu uint32_t mt_irq_get_pending(uint32_t irq) 217*91f16700Schasinglulu { 218*91f16700Schasinglulu uint32_t val; 219*91f16700Schasinglulu 220*91f16700Schasinglulu val = mmio_read_32(BASE_GICD_BASE + GICD_ISPENDR + 221*91f16700Schasinglulu irq / 32 * 4); 222*91f16700Schasinglulu val = (val >> (irq % 32)) & 1U; 223*91f16700Schasinglulu return val; 224*91f16700Schasinglulu } 225*91f16700Schasinglulu 226*91f16700Schasinglulu 227*91f16700Schasinglulu void mt_irq_set_pending(uint32_t irq) 228*91f16700Schasinglulu { 229*91f16700Schasinglulu uint32_t bit = 1U << (irq % 32); 230*91f16700Schasinglulu 231*91f16700Schasinglulu mmio_write_32(BASE_GICD_BASE + GICD_ISPENDR + 232*91f16700Schasinglulu irq / 32 * 4, bit); 233*91f16700Schasinglulu } 234*91f16700Schasinglulu 235*91f16700Schasinglulu int mt_gic_one_init(void) 236*91f16700Schasinglulu { 237*91f16700Schasinglulu INFO("[%s] GIC initialization\n", __func__); 238*91f16700Schasinglulu 239*91f16700Schasinglulu /* Initialize the GIC driver, CPU and distributor interfaces */ 240*91f16700Schasinglulu mt_gic_driver_init(); 241*91f16700Schasinglulu mt_gic_init(); 242*91f16700Schasinglulu 243*91f16700Schasinglulu return 0; 244*91f16700Schasinglulu } 245*91f16700Schasinglulu MTK_PLAT_SETUP_0_INIT(mt_gic_one_init); 246