diff --git a/plat/mediatek/mt8183/include/mt_gic_v3.h b/plat/mediatek/mt8183/include/mt_gic_v3.h index 9d78ddb..b6fc29b 100644 --- a/plat/mediatek/mt8183/include/mt_gic_v3.h +++ b/plat/mediatek/mt8183/include/mt_gic_v3.h @@ -15,15 +15,19 @@ #define GIC500_ACTIVE_CPU_SHIFT 16 #define GIC500_ACTIVE_CPU_MASK (0xff << GIC500_ACTIVE_CPU_SHIFT) +#define NR_INT_POL_CTL 20 + void mt_gic_driver_init(void); void mt_gic_init(void); void mt_gic_set_pending(uint32_t irq); uint32_t mt_gic_get_pending(uint32_t irq); void mt_gic_cpuif_enable(void); void mt_gic_cpuif_disable(void); -void mt_gic_pcpu_init(void); -void mt_gic_irq_save(void); -void mt_gic_irq_restore(void); +void mt_gic_rdistif_init(void); +void mt_gic_distif_save(void); +void mt_gic_distif_restore(void); +void mt_gic_rdistif_save(void); +void mt_gic_rdistif_restore(void); void mt_gic_sync_dcm_enable(void); void mt_gic_sync_dcm_disable(void); diff --git a/plat/mediatek/mt8183/plat_mt_gic.c b/plat/mediatek/mt8183/plat_mt_gic.c index ccb72be..35792b2 100644 --- a/plat/mediatek/mt8183/plat_mt_gic.c +++ b/plat/mediatek/mt8183/plat_mt_gic.c @@ -11,18 +11,17 @@ #include #include #include +#include "../drivers/arm/gic/v3/gicv3_private.h" #include "plat_private.h" #include #include #include #include -#define NR_INT_POL_CTL 20 - uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; +static uint32_t rdist_has_saved[PLATFORM_CORE_COUNT]; /* we save and restore the GICv3 context on system suspend */ -gicv3_redist_ctx_t rdist_ctx; gicv3_dist_ctx_t dist_ctx; static unsigned int mt_mpidr_to_core_pos(u_register_t mpidr) @@ -38,6 +37,16 @@ .mpidr_to_core_pos = mt_mpidr_to_core_pos, }; +struct gic_chip_data { + unsigned int saved_group; + unsigned int saved_enable; + unsigned int saved_conf0; + unsigned int saved_conf1; + unsigned int saved_grpmod; +}; + +static struct gic_chip_data gic_data; + void clear_sec_pol_ctl_en(void) { unsigned int i; @@ -54,15 +63,6 @@ gicv3_driver_init(&mt_gicv3_data); } -void mt_gic_init(void) -{ - gicv3_distif_init(); - gicv3_rdistif_init(plat_my_core_pos()); - gicv3_cpuif_enable(plat_my_core_pos()); - - clear_sec_pol_ctl_en(); -} - void mt_gic_set_pending(uint32_t irq) { gicv3_set_interrupt_pending(irq, plat_my_core_pos()); @@ -78,35 +78,83 @@ gicv3_cpuif_disable(plat_my_core_pos()); } -void mt_gic_pcpu_init(void) +void mt_gic_rdistif_init(void) { - gicv3_rdistif_init(plat_my_core_pos()); + unsigned int proc_num; + unsigned int index; + uintptr_t gicr_base; + + proc_num = plat_my_core_pos(); + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + + /* set all SGI/PPI as non-secure GROUP1 by default */ + mmio_write_32(gicr_base + GICR_IGROUPR0, ~0U); + mmio_write_32(gicr_base + GICR_IGRPMODR0, 0x0); + + /* setup the default PPI/SGI priorities */ + for (index = 0; index < TOTAL_PCPU_INTR_NUM; index += 4U) + gicr_write_ipriorityr(gicr_base, index, + GICD_IPRIORITYR_DEF_VAL); } -void mt_gic_irq_save(void) +void mt_gic_distif_save(void) { - gicv3_rdistif_save(plat_my_core_pos(), &rdist_ctx); gicv3_distif_save(&dist_ctx); } -void mt_gic_irq_restore(void) +void mt_gic_distif_restore(void) { gicv3_distif_init_restore(&dist_ctx); - gicv3_rdistif_init_restore(plat_my_core_pos(), &rdist_ctx); +} + +void mt_gic_rdistif_save(void) +{ + unsigned int proc_num; + uintptr_t gicr_base; + + proc_num = plat_my_core_pos(); + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + + gic_data.saved_group = mmio_read_32(gicr_base + GICR_IGROUPR0); + gic_data.saved_enable = mmio_read_32(gicr_base + GICR_ISENABLER0); + gic_data.saved_conf0 = mmio_read_32(gicr_base + GICR_ICFGR0); + gic_data.saved_conf1 = mmio_read_32(gicr_base + GICR_ICFGR1); + gic_data.saved_grpmod = mmio_read_32(gicr_base + GICR_IGRPMODR0); + + rdist_has_saved[proc_num] = 1; +} + +void mt_gic_rdistif_restore(void) +{ + unsigned int proc_num; + uintptr_t gicr_base; + + proc_num = plat_my_core_pos(); + if (rdist_has_saved[proc_num] == 1) { + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group); + mmio_write_32(gicr_base + GICR_ISENABLER0, gic_data.saved_enable); + mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0); + mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1); + mmio_write_32(gicr_base + GICR_IGRPMODR0, gic_data.saved_grpmod); + } } void mt_gic_sync_dcm_enable(void) { - unsigned int val = mmio_read_32(GIC_SYNC_DCM); - - val &= ~GIC_SYNC_DCM_MASK; - mmio_write_32(GIC_SYNC_DCM, val | GIC_SYNC_DCM_ON); + mmio_clrsetbits_32(GIC_SYNC_DCM, GIC_SYNC_DCM_MASK, GIC_SYNC_DCM_ON); } void mt_gic_sync_dcm_disable(void) { - unsigned int val = mmio_read_32(GIC_SYNC_DCM); + mmio_clrsetbits_32(GIC_SYNC_DCM, GIC_SYNC_DCM_MASK, GIC_SYNC_DCM_OFF); +} - val &= ~GIC_SYNC_DCM_MASK; - mmio_write_32(GIC_SYNC_DCM, val | GIC_SYNC_DCM_OFF); +void mt_gic_init(void) +{ + gicv3_distif_init(); + gicv3_cpuif_enable(plat_my_core_pos()); + mt_gic_rdistif_init(); + + clear_sec_pol_ctl_en(); } diff --git a/plat/mediatek/mt8183/plat_pm.c b/plat/mediatek/mt8183/plat_pm.c index 555b389..efa30f6 100644 --- a/plat/mediatek/mt8183/plat_pm.c +++ b/plat/mediatek/mt8183/plat_pm.c @@ -152,6 +152,21 @@ return !(on_stat & (cpu_mask[cluster] & ~BIT(my_idx))); } +static void plat_cpu_pwrdwn_common(void) +{ + /* Prevent interrupts from spuriously waking up this cpu */ + mt_gic_rdistif_save(); + mt_gic_cpuif_disable(); +} + +static void plat_cpu_pwron_common(void) +{ + /* Enable the gic cpu interface */ + mt_gic_cpuif_enable(); + mt_gic_rdistif_init(); + mt_gic_rdistif_restore(); +} + static void plat_cluster_pwrdwn_common(uint64_t mpidr, int cluster) { if (cluster > 0) @@ -312,7 +327,7 @@ bool cluster_off = (HP_CLUSTER_OFF && afflvl1 && clst_single_on(cluster, cpu)); - mt_gic_cpuif_disable(); + plat_cpu_pwrdwn_common(); if (cluster_off) plat_cluster_pwrdwn_common(mpidr, cluster); @@ -332,8 +347,7 @@ if (afflvl1) plat_cluster_pwron_common(mpidr, cluster); - mt_gic_pcpu_init(); - mt_gic_cpuif_enable(); + plat_cpu_pwron_common(); hotplug_ctrl_cpu_on_finish(cluster, cpu); } @@ -352,8 +366,8 @@ mcucfg_init_archstate(cluster, cpu, 1); mcucfg_set_bootaddr(cluster, cpu, secure_entrypoint); - mt_gic_cpuif_disable(); - mt_gic_irq_save(); + plat_cpu_pwrdwn_common(); + plat_dcm_mcsi_a_backup(); if (cluster_off || afflvl2) @@ -376,6 +390,8 @@ if (MCDI_SSPM) while (sspm_ipi_recv_non_blocking(IPI_ID_SUSPEND, d, l)) ; + + mt_gic_distif_save(); } else { mcdi_ctrl_cluster_cpu_off(cluster, cpu, cluster_off); } @@ -394,7 +410,9 @@ uint32_t l = sizeof(spm_d) / sizeof(uint32_t); mt_gic_init(); - mt_gic_irq_restore(); + mt_gic_distif_restore(); + mt_gic_rdistif_restore(); + mmio_write_32(EMI_WFIFO, 0xf); if (MCDI_SSPM) @@ -407,6 +425,8 @@ ; mcdi_ctrl_resume(); + } else { + plat_cpu_pwron_common(); } plat_cluster_pwron_common(mpidr, cluster);