1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2021, 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 10*91f16700Schasinglulu #include <arch_helpers.h> 11*91f16700Schasinglulu #include <lib/psci/psci.h> 12*91f16700Schasinglulu #include <lib/spinlock.h> 13*91f16700Schasinglulu 14*91f16700Schasinglulu #include <mt_cpu_pm_cpc.h> 15*91f16700Schasinglulu #include <mt_lp_irqremain.h> 16*91f16700Schasinglulu #include <mt_lp_rm.h> 17*91f16700Schasinglulu #include <mt_mcdi.h> 18*91f16700Schasinglulu #include <plat_mtk_lpm.h> 19*91f16700Schasinglulu #include <plat_pm.h> 20*91f16700Schasinglulu 21*91f16700Schasinglulu DEFINE_SYSREG_RW_FUNCS(dbgprcr_el1); 22*91f16700Schasinglulu 23*91f16700Schasinglulu static int plat_mt_lp_cpu_rc; 24*91f16700Schasinglulu 25*91f16700Schasinglulu static int pwr_state_prompt(unsigned int cpu, const psci_power_state_t *state) 26*91f16700Schasinglulu { 27*91f16700Schasinglulu return 0; 28*91f16700Schasinglulu } 29*91f16700Schasinglulu 30*91f16700Schasinglulu static int pwr_state_reflect(unsigned int cpu, const psci_power_state_t *state) 31*91f16700Schasinglulu { 32*91f16700Schasinglulu mtk_cpc_core_on_hint_clr(cpu); 33*91f16700Schasinglulu 34*91f16700Schasinglulu if (IS_SYSTEM_SUSPEND_STATE(state)) { 35*91f16700Schasinglulu mtk_cpc_time_sync(); 36*91f16700Schasinglulu } 37*91f16700Schasinglulu 38*91f16700Schasinglulu return 0; 39*91f16700Schasinglulu } 40*91f16700Schasinglulu 41*91f16700Schasinglulu static int pwr_cpu_pwron(unsigned int cpu, const psci_power_state_t *state) 42*91f16700Schasinglulu { 43*91f16700Schasinglulu return 0; 44*91f16700Schasinglulu } 45*91f16700Schasinglulu 46*91f16700Schasinglulu static int pwr_cpu_pwrdwn(unsigned int cpu, const psci_power_state_t *state) 47*91f16700Schasinglulu { 48*91f16700Schasinglulu /* clear DBGPRCR.CORENPDRQ to allow CPU power down */ 49*91f16700Schasinglulu write_dbgprcr_el1(0ULL); 50*91f16700Schasinglulu 51*91f16700Schasinglulu return 0; 52*91f16700Schasinglulu } 53*91f16700Schasinglulu 54*91f16700Schasinglulu static int pwr_cluster_pwron(unsigned int cpu, const psci_power_state_t *state) 55*91f16700Schasinglulu { 56*91f16700Schasinglulu return 0; 57*91f16700Schasinglulu } 58*91f16700Schasinglulu 59*91f16700Schasinglulu static int pwr_cluster_pwrdwn(unsigned int cpu, const psci_power_state_t *state) 60*91f16700Schasinglulu { 61*91f16700Schasinglulu return 0; 62*91f16700Schasinglulu } 63*91f16700Schasinglulu 64*91f16700Schasinglulu static int pwr_mcusys_pwron(unsigned int cpu, const psci_power_state_t *state) 65*91f16700Schasinglulu { 66*91f16700Schasinglulu if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) { 67*91f16700Schasinglulu return -1; 68*91f16700Schasinglulu } 69*91f16700Schasinglulu 70*91f16700Schasinglulu mtk_cpc_mcusys_off_reflect(); 71*91f16700Schasinglulu 72*91f16700Schasinglulu return 0; 73*91f16700Schasinglulu } 74*91f16700Schasinglulu 75*91f16700Schasinglulu static int pwr_mcusys_pwron_finished(unsigned int cpu, 76*91f16700Schasinglulu const psci_power_state_t *state) 77*91f16700Schasinglulu { 78*91f16700Schasinglulu int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS]; 79*91f16700Schasinglulu 80*91f16700Schasinglulu if (!IS_MCUSYS_OFF_STATE(state) || (plat_mt_lp_cpu_rc < 0)) { 81*91f16700Schasinglulu return -1; 82*91f16700Schasinglulu } 83*91f16700Schasinglulu 84*91f16700Schasinglulu mt_lp_rm_reset_constraint(plat_mt_lp_cpu_rc, cpu, state_id); 85*91f16700Schasinglulu mt_lp_irqremain_release(); 86*91f16700Schasinglulu 87*91f16700Schasinglulu return 0; 88*91f16700Schasinglulu } 89*91f16700Schasinglulu 90*91f16700Schasinglulu static int pwr_mcusys_pwrdwn(unsigned int cpu, const psci_power_state_t *state) 91*91f16700Schasinglulu { 92*91f16700Schasinglulu int state_id = state->pwr_domain_state[MTK_AFFLVL_MCUSYS]; 93*91f16700Schasinglulu 94*91f16700Schasinglulu if (!IS_MCUSYS_OFF_STATE(state)) { 95*91f16700Schasinglulu goto mt_pwr_mcusysoff_break; 96*91f16700Schasinglulu } 97*91f16700Schasinglulu 98*91f16700Schasinglulu if (mcdi_try_init() != 0) { /* not ready to process mcusys-off */ 99*91f16700Schasinglulu goto mt_pwr_mcusysoff_break; 100*91f16700Schasinglulu } 101*91f16700Schasinglulu 102*91f16700Schasinglulu if (mtk_cpc_mcusys_off_prepare() != CPC_SUCCESS) { 103*91f16700Schasinglulu goto mt_pwr_mcusysoff_break; 104*91f16700Schasinglulu } 105*91f16700Schasinglulu 106*91f16700Schasinglulu plat_mt_lp_cpu_rc = 107*91f16700Schasinglulu mt_lp_rm_find_and_run_constraint(0, cpu, state_id, NULL); 108*91f16700Schasinglulu 109*91f16700Schasinglulu if (plat_mt_lp_cpu_rc < 0) { 110*91f16700Schasinglulu goto mt_pwr_mcusysoff_reflect; 111*91f16700Schasinglulu } 112*91f16700Schasinglulu 113*91f16700Schasinglulu mt_lp_irqremain_aquire(); 114*91f16700Schasinglulu 115*91f16700Schasinglulu return 0; 116*91f16700Schasinglulu 117*91f16700Schasinglulu mt_pwr_mcusysoff_reflect: 118*91f16700Schasinglulu mtk_cpc_mcusys_off_reflect(); 119*91f16700Schasinglulu 120*91f16700Schasinglulu mt_pwr_mcusysoff_break: 121*91f16700Schasinglulu plat_mt_lp_cpu_rc = -1; 122*91f16700Schasinglulu 123*91f16700Schasinglulu return -1; 124*91f16700Schasinglulu } 125*91f16700Schasinglulu 126*91f16700Schasinglulu static const struct mt_lpm_tz plat_pm = { 127*91f16700Schasinglulu .pwr_prompt = pwr_state_prompt, 128*91f16700Schasinglulu .pwr_reflect = pwr_state_reflect, 129*91f16700Schasinglulu .pwr_cpu_on = pwr_cpu_pwron, 130*91f16700Schasinglulu .pwr_cpu_dwn = pwr_cpu_pwrdwn, 131*91f16700Schasinglulu .pwr_cluster_on = pwr_cluster_pwron, 132*91f16700Schasinglulu .pwr_cluster_dwn = pwr_cluster_pwrdwn, 133*91f16700Schasinglulu .pwr_mcusys_dwn = pwr_mcusys_pwrdwn, 134*91f16700Schasinglulu .pwr_mcusys_on = pwr_mcusys_pwron, 135*91f16700Schasinglulu .pwr_mcusys_on_finished = pwr_mcusys_pwron_finished 136*91f16700Schasinglulu }; 137*91f16700Schasinglulu 138*91f16700Schasinglulu const struct mt_lpm_tz *mt_plat_cpu_pm_init(void) 139*91f16700Schasinglulu { 140*91f16700Schasinglulu mtk_cpc_init(); 141*91f16700Schasinglulu 142*91f16700Schasinglulu if (mcdi_try_init() == 0) { 143*91f16700Schasinglulu INFO("MCDI init done.\n"); 144*91f16700Schasinglulu } 145*91f16700Schasinglulu 146*91f16700Schasinglulu mt_lp_irqremain_init(); 147*91f16700Schasinglulu 148*91f16700Schasinglulu return &plat_pm; 149*91f16700Schasinglulu } 150