128a773efSkenny liang /*
2f992b960Skenny liang * Copyright (c) 2019, MediaTek Inc. All rights reserved.
328a773efSkenny liang *
428a773efSkenny liang * SPDX-License-Identifier: BSD-3-Clause
528a773efSkenny liang */
628a773efSkenny liang
7f992b960Skenny liang #include <assert.h>
828a773efSkenny liang #include <common/bl_common.h>
928a773efSkenny liang #include <common/debug.h>
1028a773efSkenny liang #include <drivers/arm/gicv3.h>
1128a773efSkenny liang #include <bl31/interrupt_mgmt.h>
1228a773efSkenny liang #include <mt_gic_v3.h>
1328a773efSkenny liang #include <mtk_plat_common.h>
14*4450a518Skenny liang #include "../drivers/arm/gic/v3/gicv3_private.h"
1528a773efSkenny liang #include "plat_private.h"
1628a773efSkenny liang #include <plat/common/platform.h>
1728a773efSkenny liang #include <platform_def.h>
1828a773efSkenny liang #include <stdint.h>
1928a773efSkenny liang #include <stdio.h>
2028a773efSkenny liang
2128a773efSkenny liang uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
22*4450a518Skenny liang static uint32_t rdist_has_saved[PLATFORM_CORE_COUNT];
2328a773efSkenny liang
24f992b960Skenny liang /* we save and restore the GICv3 context on system suspend */
25f992b960Skenny liang gicv3_dist_ctx_t dist_ctx;
2628a773efSkenny liang
mt_mpidr_to_core_pos(u_register_t mpidr)2728a773efSkenny liang static unsigned int mt_mpidr_to_core_pos(u_register_t mpidr)
2828a773efSkenny liang {
2928a773efSkenny liang return plat_core_pos_by_mpidr(mpidr);
3028a773efSkenny liang }
3128a773efSkenny liang
3228a773efSkenny liang gicv3_driver_data_t mt_gicv3_data = {
3328a773efSkenny liang .gicd_base = MT_GIC_BASE,
3428a773efSkenny liang .gicr_base = MT_GIC_RDIST_BASE,
3528a773efSkenny liang .rdistif_num = PLATFORM_CORE_COUNT,
3628a773efSkenny liang .rdistif_base_addrs = rdistif_base_addrs,
3728a773efSkenny liang .mpidr_to_core_pos = mt_mpidr_to_core_pos,
3828a773efSkenny liang };
3928a773efSkenny liang
40*4450a518Skenny liang struct gic_chip_data {
41*4450a518Skenny liang unsigned int saved_group;
42*4450a518Skenny liang unsigned int saved_enable;
43*4450a518Skenny liang unsigned int saved_conf0;
44*4450a518Skenny liang unsigned int saved_conf1;
45*4450a518Skenny liang unsigned int saved_grpmod;
46*4450a518Skenny liang };
47*4450a518Skenny liang
48*4450a518Skenny liang static struct gic_chip_data gic_data;
49*4450a518Skenny liang
clear_sec_pol_ctl_en(void)5028a773efSkenny liang void clear_sec_pol_ctl_en(void)
5128a773efSkenny liang {
5228a773efSkenny liang unsigned int i;
5328a773efSkenny liang
5428a773efSkenny liang /* total 19 polarity ctrl registers */
5528a773efSkenny liang for (i = 0; i <= NR_INT_POL_CTL - 1; i++) {
5628a773efSkenny liang mmio_write_32((SEC_POL_CTL_EN0 + (i * 4)), 0);
5728a773efSkenny liang }
5828a773efSkenny liang dsb();
5928a773efSkenny liang }
6028a773efSkenny liang
mt_gic_driver_init(void)6128a773efSkenny liang void mt_gic_driver_init(void)
6228a773efSkenny liang {
6328a773efSkenny liang gicv3_driver_init(&mt_gicv3_data);
6428a773efSkenny liang }
6528a773efSkenny liang
mt_gic_set_pending(uint32_t irq)6628a773efSkenny liang void mt_gic_set_pending(uint32_t irq)
6728a773efSkenny liang {
6828a773efSkenny liang gicv3_set_interrupt_pending(irq, plat_my_core_pos());
6928a773efSkenny liang }
7028a773efSkenny liang
mt_gic_cpuif_enable(void)7128a773efSkenny liang void mt_gic_cpuif_enable(void)
7228a773efSkenny liang {
7328a773efSkenny liang gicv3_cpuif_enable(plat_my_core_pos());
7428a773efSkenny liang }
7528a773efSkenny liang
mt_gic_cpuif_disable(void)7628a773efSkenny liang void mt_gic_cpuif_disable(void)
7728a773efSkenny liang {
7828a773efSkenny liang gicv3_cpuif_disable(plat_my_core_pos());
7928a773efSkenny liang }
8028a773efSkenny liang
mt_gic_rdistif_init(void)81*4450a518Skenny liang void mt_gic_rdistif_init(void)
8228a773efSkenny liang {
83*4450a518Skenny liang unsigned int proc_num;
84*4450a518Skenny liang unsigned int index;
85*4450a518Skenny liang uintptr_t gicr_base;
86*4450a518Skenny liang
87*4450a518Skenny liang proc_num = plat_my_core_pos();
88*4450a518Skenny liang gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
89*4450a518Skenny liang
90*4450a518Skenny liang /* set all SGI/PPI as non-secure GROUP1 by default */
91*4450a518Skenny liang mmio_write_32(gicr_base + GICR_IGROUPR0, ~0U);
92*4450a518Skenny liang mmio_write_32(gicr_base + GICR_IGRPMODR0, 0x0);
93*4450a518Skenny liang
94*4450a518Skenny liang /* setup the default PPI/SGI priorities */
95*4450a518Skenny liang for (index = 0; index < TOTAL_PCPU_INTR_NUM; index += 4U)
96*4450a518Skenny liang gicr_write_ipriorityr(gicr_base, index,
97*4450a518Skenny liang GICD_IPRIORITYR_DEF_VAL);
9828a773efSkenny liang }
9928a773efSkenny liang
mt_gic_distif_save(void)100*4450a518Skenny liang void mt_gic_distif_save(void)
10128a773efSkenny liang {
10228a773efSkenny liang gicv3_distif_save(&dist_ctx);
10328a773efSkenny liang }
10428a773efSkenny liang
mt_gic_distif_restore(void)105*4450a518Skenny liang void mt_gic_distif_restore(void)
10628a773efSkenny liang {
10728a773efSkenny liang gicv3_distif_init_restore(&dist_ctx);
108*4450a518Skenny liang }
109*4450a518Skenny liang
mt_gic_rdistif_save(void)110*4450a518Skenny liang void mt_gic_rdistif_save(void)
111*4450a518Skenny liang {
112*4450a518Skenny liang unsigned int proc_num;
113*4450a518Skenny liang uintptr_t gicr_base;
114*4450a518Skenny liang
115*4450a518Skenny liang proc_num = plat_my_core_pos();
116*4450a518Skenny liang gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
117*4450a518Skenny liang
118*4450a518Skenny liang gic_data.saved_group = mmio_read_32(gicr_base + GICR_IGROUPR0);
119*4450a518Skenny liang gic_data.saved_enable = mmio_read_32(gicr_base + GICR_ISENABLER0);
120*4450a518Skenny liang gic_data.saved_conf0 = mmio_read_32(gicr_base + GICR_ICFGR0);
121*4450a518Skenny liang gic_data.saved_conf1 = mmio_read_32(gicr_base + GICR_ICFGR1);
122*4450a518Skenny liang gic_data.saved_grpmod = mmio_read_32(gicr_base + GICR_IGRPMODR0);
123*4450a518Skenny liang
124*4450a518Skenny liang rdist_has_saved[proc_num] = 1;
125*4450a518Skenny liang }
126*4450a518Skenny liang
mt_gic_rdistif_restore(void)127*4450a518Skenny liang void mt_gic_rdistif_restore(void)
128*4450a518Skenny liang {
129*4450a518Skenny liang unsigned int proc_num;
130*4450a518Skenny liang uintptr_t gicr_base;
131*4450a518Skenny liang
132*4450a518Skenny liang proc_num = plat_my_core_pos();
133*4450a518Skenny liang if (rdist_has_saved[proc_num] == 1) {
134*4450a518Skenny liang gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
135*4450a518Skenny liang mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group);
136*4450a518Skenny liang mmio_write_32(gicr_base + GICR_ISENABLER0, gic_data.saved_enable);
137*4450a518Skenny liang mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0);
138*4450a518Skenny liang mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1);
139*4450a518Skenny liang mmio_write_32(gicr_base + GICR_IGRPMODR0, gic_data.saved_grpmod);
140*4450a518Skenny liang }
14128a773efSkenny liang }
14228a773efSkenny liang
mt_gic_sync_dcm_enable(void)14328a773efSkenny liang void mt_gic_sync_dcm_enable(void)
14428a773efSkenny liang {
145*4450a518Skenny liang mmio_clrsetbits_32(GIC_SYNC_DCM, GIC_SYNC_DCM_MASK, GIC_SYNC_DCM_ON);
14628a773efSkenny liang }
14728a773efSkenny liang
mt_gic_sync_dcm_disable(void)14828a773efSkenny liang void mt_gic_sync_dcm_disable(void)
14928a773efSkenny liang {
150*4450a518Skenny liang mmio_clrsetbits_32(GIC_SYNC_DCM, GIC_SYNC_DCM_MASK, GIC_SYNC_DCM_OFF);
151*4450a518Skenny liang }
15228a773efSkenny liang
mt_gic_init(void)153*4450a518Skenny liang void mt_gic_init(void)
154*4450a518Skenny liang {
155*4450a518Skenny liang gicv3_distif_init();
156*4450a518Skenny liang gicv3_cpuif_enable(plat_my_core_pos());
157*4450a518Skenny liang mt_gic_rdistif_init();
158*4450a518Skenny liang
159*4450a518Skenny liang clear_sec_pol_ctl_en();
16028a773efSkenny liang }
161