13374752fSBo-Chen Chen /* 23374752fSBo-Chen Chen * Copyright (c) 2020-2022, MediaTek Inc. All rights reserved. 33374752fSBo-Chen Chen * 43374752fSBo-Chen Chen * SPDX-License-Identifier: BSD-3-Clause 53374752fSBo-Chen Chen */ 63374752fSBo-Chen Chen 73374752fSBo-Chen Chen #include <assert.h> 83374752fSBo-Chen Chen #include <stdint.h> 93374752fSBo-Chen Chen #include <stdio.h> 103374752fSBo-Chen Chen 113374752fSBo-Chen Chen #include "../drivers/arm/gic/v3/gicv3_private.h" 123374752fSBo-Chen Chen #include <bl31/interrupt_mgmt.h> 133374752fSBo-Chen Chen #include <common/bl_common.h> 143374752fSBo-Chen Chen #include <common/debug.h> 15*cfb0516fSRex-BC Chen #include <lib/mtk_init/mtk_init.h> 163374752fSBo-Chen Chen #include <mt_gic_v3.h> 173374752fSBo-Chen Chen #include <mtk_plat_common.h> 183374752fSBo-Chen Chen #include <plat/common/platform.h> 193374752fSBo-Chen Chen #include <plat_private.h> 203374752fSBo-Chen Chen #include <platform_def.h> 213374752fSBo-Chen Chen 223374752fSBo-Chen Chen #define SGI_MASK 0xffff 233374752fSBo-Chen Chen 243374752fSBo-Chen Chen uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; 253374752fSBo-Chen Chen static uint32_t rdist_has_saved[PLATFORM_CORE_COUNT]; 263374752fSBo-Chen Chen 273374752fSBo-Chen Chen /* we save and restore the GICv3 context on system suspend */ 283374752fSBo-Chen Chen gicv3_dist_ctx_t dist_ctx; 293374752fSBo-Chen Chen 303374752fSBo-Chen Chen static unsigned int mt_mpidr_to_core_pos(u_register_t mpidr) 313374752fSBo-Chen Chen { 323374752fSBo-Chen Chen return plat_core_pos_by_mpidr(mpidr); 333374752fSBo-Chen Chen } 343374752fSBo-Chen Chen 353374752fSBo-Chen Chen gicv3_driver_data_t mt_gicv3_data = { 363374752fSBo-Chen Chen .gicd_base = MT_GIC_BASE, 373374752fSBo-Chen Chen .gicr_base = MT_GIC_RDIST_BASE, 383374752fSBo-Chen Chen .rdistif_num = PLATFORM_CORE_COUNT, 393374752fSBo-Chen Chen .rdistif_base_addrs = rdistif_base_addrs, 403374752fSBo-Chen Chen .mpidr_to_core_pos = mt_mpidr_to_core_pos, 413374752fSBo-Chen Chen }; 423374752fSBo-Chen Chen 433374752fSBo-Chen Chen struct gic_chip_data { 443374752fSBo-Chen Chen /* All cores share the same configuration */ 453374752fSBo-Chen Chen unsigned int saved_group; 463374752fSBo-Chen Chen unsigned int saved_enable; 473374752fSBo-Chen Chen unsigned int saved_conf0; 483374752fSBo-Chen Chen unsigned int saved_conf1; 493374752fSBo-Chen Chen unsigned int saved_grpmod; 503374752fSBo-Chen Chen /* Per-core sgi */ 513374752fSBo-Chen Chen unsigned int saved_sgi[PLATFORM_CORE_COUNT]; 523374752fSBo-Chen Chen }; 533374752fSBo-Chen Chen 543374752fSBo-Chen Chen static struct gic_chip_data gic_data; 553374752fSBo-Chen Chen 563374752fSBo-Chen Chen void mt_gic_driver_init(void) 573374752fSBo-Chen Chen { 583374752fSBo-Chen Chen gicv3_driver_init(&mt_gicv3_data); 593374752fSBo-Chen Chen } 603374752fSBo-Chen Chen 613374752fSBo-Chen Chen void mt_gic_set_pending(uint32_t irq) 623374752fSBo-Chen Chen { 633374752fSBo-Chen Chen gicv3_set_interrupt_pending(irq, plat_my_core_pos()); 643374752fSBo-Chen Chen } 653374752fSBo-Chen Chen 663374752fSBo-Chen Chen void mt_gic_distif_save(void) 673374752fSBo-Chen Chen { 683374752fSBo-Chen Chen gicv3_distif_save(&dist_ctx); 693374752fSBo-Chen Chen } 703374752fSBo-Chen Chen 713374752fSBo-Chen Chen void mt_gic_distif_restore(void) 723374752fSBo-Chen Chen { 733374752fSBo-Chen Chen gicv3_distif_init_restore(&dist_ctx); 743374752fSBo-Chen Chen } 753374752fSBo-Chen Chen 763374752fSBo-Chen Chen void mt_gic_rdistif_init(void) 773374752fSBo-Chen Chen { 783374752fSBo-Chen Chen unsigned int proc_num; 793374752fSBo-Chen Chen unsigned int index; 803374752fSBo-Chen Chen uintptr_t gicr_base; 813374752fSBo-Chen Chen 823374752fSBo-Chen Chen proc_num = plat_my_core_pos(); 833374752fSBo-Chen Chen gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 843374752fSBo-Chen Chen 853374752fSBo-Chen Chen /* set all SGI/PPI as non-secure GROUP1 by default */ 863374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_IGROUPR0, ~0U); 873374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_IGRPMODR0, 0x0); 883374752fSBo-Chen Chen 893374752fSBo-Chen Chen /* setup the default PPI/SGI priorities */ 903374752fSBo-Chen Chen for (index = 0; index < TOTAL_PCPU_INTR_NUM; index += 4U) 913374752fSBo-Chen Chen gicr_write_ipriorityr(gicr_base, index, 923374752fSBo-Chen Chen GICD_IPRIORITYR_DEF_VAL); 933374752fSBo-Chen Chen } 943374752fSBo-Chen Chen 953374752fSBo-Chen Chen void mt_gic_rdistif_save(void) 963374752fSBo-Chen Chen { 973374752fSBo-Chen Chen unsigned int proc_num; 983374752fSBo-Chen Chen uintptr_t gicr_base; 993374752fSBo-Chen Chen 1003374752fSBo-Chen Chen proc_num = plat_my_core_pos(); 1013374752fSBo-Chen Chen gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 1023374752fSBo-Chen Chen 1033374752fSBo-Chen Chen gic_data.saved_group = mmio_read_32(gicr_base + GICR_IGROUPR0); 1043374752fSBo-Chen Chen gic_data.saved_enable = mmio_read_32(gicr_base + GICR_ISENABLER0); 1053374752fSBo-Chen Chen gic_data.saved_conf0 = mmio_read_32(gicr_base + GICR_ICFGR0); 1063374752fSBo-Chen Chen gic_data.saved_conf1 = mmio_read_32(gicr_base + GICR_ICFGR1); 1073374752fSBo-Chen Chen gic_data.saved_grpmod = mmio_read_32(gicr_base + GICR_IGRPMODR0); 1083374752fSBo-Chen Chen 1093374752fSBo-Chen Chen rdist_has_saved[proc_num] = 1; 1103374752fSBo-Chen Chen } 1113374752fSBo-Chen Chen 1123374752fSBo-Chen Chen void mt_gic_rdistif_restore(void) 1133374752fSBo-Chen Chen { 1143374752fSBo-Chen Chen unsigned int proc_num; 1153374752fSBo-Chen Chen uintptr_t gicr_base; 1163374752fSBo-Chen Chen 1173374752fSBo-Chen Chen proc_num = plat_my_core_pos(); 1183374752fSBo-Chen Chen if (rdist_has_saved[proc_num] == 1) { 1193374752fSBo-Chen Chen gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 1203374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group); 1213374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_ISENABLER0, 1223374752fSBo-Chen Chen gic_data.saved_enable); 1233374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0); 1243374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1); 1253374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_IGRPMODR0, 1263374752fSBo-Chen Chen gic_data.saved_grpmod); 1273374752fSBo-Chen Chen } 1283374752fSBo-Chen Chen } 1293374752fSBo-Chen Chen 1303374752fSBo-Chen Chen void mt_gic_rdistif_restore_all(void) 1313374752fSBo-Chen Chen { 1323374752fSBo-Chen Chen unsigned int proc_num; 1333374752fSBo-Chen Chen uintptr_t gicr_base; 1343374752fSBo-Chen Chen 1353374752fSBo-Chen Chen for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) { 1363374752fSBo-Chen Chen gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 1373374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group); 1383374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_ISENABLER0, 1393374752fSBo-Chen Chen gic_data.saved_enable); 1403374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0); 1413374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1); 1423374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_IGRPMODR0, 1433374752fSBo-Chen Chen gic_data.saved_grpmod); 1443374752fSBo-Chen Chen } 1453374752fSBo-Chen Chen } 1463374752fSBo-Chen Chen 1473374752fSBo-Chen Chen void gic_sgi_save_all(void) 1483374752fSBo-Chen Chen { 1493374752fSBo-Chen Chen unsigned int proc_num; 1503374752fSBo-Chen Chen uintptr_t gicr_base; 1513374752fSBo-Chen Chen 1523374752fSBo-Chen Chen for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) { 1533374752fSBo-Chen Chen gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 1543374752fSBo-Chen Chen gic_data.saved_sgi[proc_num] = 1553374752fSBo-Chen Chen mmio_read_32(gicr_base + GICR_ISPENDR0) & SGI_MASK; 1563374752fSBo-Chen Chen } 1573374752fSBo-Chen Chen } 1583374752fSBo-Chen Chen 1593374752fSBo-Chen Chen void gic_sgi_restore_all(void) 1603374752fSBo-Chen Chen { 1613374752fSBo-Chen Chen unsigned int proc_num; 1623374752fSBo-Chen Chen uintptr_t gicr_base; 1633374752fSBo-Chen Chen 1643374752fSBo-Chen Chen for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) { 1653374752fSBo-Chen Chen gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; 1663374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_ICPENDR0, SGI_MASK); 1673374752fSBo-Chen Chen mmio_write_32(gicr_base + GICR_ISPENDR0, 1683374752fSBo-Chen Chen gic_data.saved_sgi[proc_num] & SGI_MASK); 1693374752fSBo-Chen Chen } 1703374752fSBo-Chen Chen } 1713374752fSBo-Chen Chen 1723374752fSBo-Chen Chen void mt_gic_init(void) 1733374752fSBo-Chen Chen { 1743374752fSBo-Chen Chen gicv3_distif_init(); 1753374752fSBo-Chen Chen gicv3_rdistif_init(plat_my_core_pos()); 1763374752fSBo-Chen Chen gicv3_cpuif_enable(plat_my_core_pos()); 1773374752fSBo-Chen Chen } 1783374752fSBo-Chen Chen 1793374752fSBo-Chen Chen uint32_t mt_irq_get_pending(uint32_t irq) 1803374752fSBo-Chen Chen { 1813374752fSBo-Chen Chen uint32_t val; 1823374752fSBo-Chen Chen 1833374752fSBo-Chen Chen val = mmio_read_32(BASE_GICD_BASE + GICD_ISPENDR + 1843374752fSBo-Chen Chen irq / 32 * 4); 1853374752fSBo-Chen Chen val = (val >> (irq % 32)) & 1U; 1863374752fSBo-Chen Chen return val; 1873374752fSBo-Chen Chen } 1883374752fSBo-Chen Chen 1893374752fSBo-Chen Chen 1903374752fSBo-Chen Chen void mt_irq_set_pending(uint32_t irq) 1913374752fSBo-Chen Chen { 1923374752fSBo-Chen Chen uint32_t bit = 1U << (irq % 32); 1933374752fSBo-Chen Chen 1943374752fSBo-Chen Chen mmio_write_32(BASE_GICD_BASE + GICD_ISPENDR + 1953374752fSBo-Chen Chen irq / 32 * 4, bit); 1963374752fSBo-Chen Chen } 197*cfb0516fSRex-BC Chen 198*cfb0516fSRex-BC Chen int mt_gic_one_init(void) 199*cfb0516fSRex-BC Chen { 200*cfb0516fSRex-BC Chen INFO("[%s] GIC initialization\n", __func__); 201*cfb0516fSRex-BC Chen 202*cfb0516fSRex-BC Chen /* Initialize the GIC driver, CPU and distributor interfaces */ 203*cfb0516fSRex-BC Chen mt_gic_driver_init(); 204*cfb0516fSRex-BC Chen mt_gic_init(); 205*cfb0516fSRex-BC Chen 206*cfb0516fSRex-BC Chen return 0; 207*cfb0516fSRex-BC Chen } 208*cfb0516fSRex-BC Chen MTK_PLAT_SETUP_0_INIT(mt_gic_one_init); 209