1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2022-2023, 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 <lib/spinlock.h> 11*91f16700Schasinglulu 12*91f16700Schasinglulu #include <lib/mtk_init/mtk_init.h> 13*91f16700Schasinglulu #include <lib/pm/mtk_pm.h> 14*91f16700Schasinglulu #include <lpm/mt_lp_rm.h> 15*91f16700Schasinglulu #include "mt_cpu_pm.h" 16*91f16700Schasinglulu #include "mt_cpu_pm_cpc.h" 17*91f16700Schasinglulu #include "mt_cpu_pm_mbox.h" 18*91f16700Schasinglulu #include "mt_smp.h" 19*91f16700Schasinglulu #include <mtk_mmap_pool.h> 20*91f16700Schasinglulu #include <platform_def.h> 21*91f16700Schasinglulu 22*91f16700Schasinglulu /* 23*91f16700Schasinglulu * The locker must use the bakery locker when cache turns off. 24*91f16700Schasinglulu * Using spin_lock will gain better performance. 25*91f16700Schasinglulu */ 26*91f16700Schasinglulu #ifdef MT_CPU_PM_USING_BAKERY_LOCK 27*91f16700Schasinglulu DEFINE_BAKERY_LOCK(mt_cpu_pm_lock); 28*91f16700Schasinglulu #define plat_cpu_pm_lock_init() bakery_lock_init(&mt_cpu_pm_lock) 29*91f16700Schasinglulu #define plat_cpu_pm_lock() bakery_lock_get(&mt_cpu_pm_lock) 30*91f16700Schasinglulu #define plat_cpu_pm_unlock() bakery_lock_release(&mt_cpu_pm_lock) 31*91f16700Schasinglulu #else 32*91f16700Schasinglulu spinlock_t mt_cpu_pm_lock; 33*91f16700Schasinglulu #define plat_cpu_pm_lock_init() 34*91f16700Schasinglulu #define plat_cpu_pm_lock() spin_lock(&mt_cpu_pm_lock) 35*91f16700Schasinglulu #define plat_cpu_pm_unlock() spin_unlock(&mt_cpu_pm_lock) 36*91f16700Schasinglulu #endif 37*91f16700Schasinglulu 38*91f16700Schasinglulu enum mt_pwr_node { 39*91f16700Schasinglulu MT_PWR_NONMCUSYS = 0, 40*91f16700Schasinglulu MT_PWR_MCUSYS_PDN, 41*91f16700Schasinglulu MT_PWR_SUSPEND, 42*91f16700Schasinglulu MT_PWR_SYSTEM_MEM, 43*91f16700Schasinglulu MT_PWR_SYSTEM_PLL, 44*91f16700Schasinglulu MT_PWR_SYSTEM_BUS, 45*91f16700Schasinglulu MT_PWR_MAX, 46*91f16700Schasinglulu }; 47*91f16700Schasinglulu 48*91f16700Schasinglulu #define CPU_PM_DEPD_INIT BIT(0) 49*91f16700Schasinglulu #define CPU_PM_DEPD_READY BIT(1) 50*91f16700Schasinglulu #define CPU_PM_PLAT_READY BIT(2) 51*91f16700Schasinglulu 52*91f16700Schasinglulu #ifdef CPU_PM_TINYSYS_SUPPORT 53*91f16700Schasinglulu #define CPU_PM_INIT_READY (CPU_PM_DEPD_INIT | CPU_PM_DEPD_READY) 54*91f16700Schasinglulu #define CPU_PM_LP_READY (CPU_PM_INIT_READY | CPU_PM_PLAT_READY) 55*91f16700Schasinglulu #else 56*91f16700Schasinglulu #define CPU_PM_LP_READY (CPU_PM_PLAT_READY) 57*91f16700Schasinglulu #endif 58*91f16700Schasinglulu 59*91f16700Schasinglulu #if CONFIG_MTK_PM_SUPPORT 60*91f16700Schasinglulu 61*91f16700Schasinglulu #if CONFIG_MTK_CPU_SUSPEND_EN || CONFIG_MTK_SMP_EN 62*91f16700Schasinglulu static void cpupm_cpu_resume_common(const struct mtk_cpupm_pwrstate *state) 63*91f16700Schasinglulu { 64*91f16700Schasinglulu CPU_PM_ASSERT(state != NULL); 65*91f16700Schasinglulu mtk_cpc_core_on_hint_clr(state->info.cpuid); 66*91f16700Schasinglulu } 67*91f16700Schasinglulu #endif 68*91f16700Schasinglulu 69*91f16700Schasinglulu #if CONFIG_MTK_SMP_EN 70*91f16700Schasinglulu static int cpupm_cpu_pwr_on_prepare(unsigned int cpu, uintptr_t entry) 71*91f16700Schasinglulu { 72*91f16700Schasinglulu struct cpu_pwr_ctrl pwr_ctrl; 73*91f16700Schasinglulu 74*91f16700Schasinglulu PER_CPU_PWR_CTRL(pwr_ctrl, cpu); 75*91f16700Schasinglulu mt_smp_core_bootup_address_set(&pwr_ctrl, entry); 76*91f16700Schasinglulu mt_smp_core_init_arch(0, cpu, 1, &pwr_ctrl); 77*91f16700Schasinglulu 78*91f16700Schasinglulu return mt_smp_power_core_on(cpu, &pwr_ctrl); 79*91f16700Schasinglulu } 80*91f16700Schasinglulu 81*91f16700Schasinglulu static void cpupm_cpu_resume_smp(const struct mtk_cpupm_pwrstate *state) 82*91f16700Schasinglulu { 83*91f16700Schasinglulu CPU_PM_ASSERT(state != NULL); 84*91f16700Schasinglulu 85*91f16700Schasinglulu plat_cpu_pm_lock(); 86*91f16700Schasinglulu mmio_clrbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, 87*91f16700Schasinglulu GIC_WAKEUP_IGNORE(state->info.cpuid)); 88*91f16700Schasinglulu plat_cpu_pm_unlock(); 89*91f16700Schasinglulu cpupm_cpu_resume_common(state); 90*91f16700Schasinglulu } 91*91f16700Schasinglulu 92*91f16700Schasinglulu static void cpupm_cpu_suspend_smp(const struct mtk_cpupm_pwrstate *state) 93*91f16700Schasinglulu { 94*91f16700Schasinglulu struct cpu_pwr_ctrl pwr_ctrl; 95*91f16700Schasinglulu 96*91f16700Schasinglulu CPU_PM_ASSERT(state != NULL); 97*91f16700Schasinglulu 98*91f16700Schasinglulu PER_CPU_PWR_CTRL(pwr_ctrl, state->info.cpuid); 99*91f16700Schasinglulu mt_smp_power_core_off(&pwr_ctrl); 100*91f16700Schasinglulu mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, 101*91f16700Schasinglulu GIC_WAKEUP_IGNORE(state->info.cpuid)); 102*91f16700Schasinglulu } 103*91f16700Schasinglulu 104*91f16700Schasinglulu static void cpupm_smp_init(unsigned int cpu, uintptr_t sec_entrypoint) 105*91f16700Schasinglulu { 106*91f16700Schasinglulu unsigned int reg; 107*91f16700Schasinglulu struct mtk_cpupm_pwrstate state = { 108*91f16700Schasinglulu .info = { 109*91f16700Schasinglulu .cpuid = cpu, 110*91f16700Schasinglulu .mode = MTK_CPU_PM_SMP, 111*91f16700Schasinglulu }, 112*91f16700Schasinglulu .pwr = { 113*91f16700Schasinglulu .afflv = 0, 114*91f16700Schasinglulu .state_id = 0, 115*91f16700Schasinglulu }, 116*91f16700Schasinglulu }; 117*91f16700Schasinglulu 118*91f16700Schasinglulu reg = mmio_read_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG); 119*91f16700Schasinglulu if ((reg & CPC_MCUSYS_CPC_RESET_PWR_ON_EN) != 0) { 120*91f16700Schasinglulu INFO("[%s:%d][CPU_PM] reset pwr on is enabled then clear it!\n", 121*91f16700Schasinglulu __func__, __LINE__); 122*91f16700Schasinglulu mmio_clrbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, CPC_MCUSYS_CPC_RESET_PWR_ON_EN); 123*91f16700Schasinglulu } 124*91f16700Schasinglulu 125*91f16700Schasinglulu cpupm_cpu_pwr_on_prepare(cpu, sec_entrypoint); 126*91f16700Schasinglulu cpupm_cpu_resume_smp(&state); 127*91f16700Schasinglulu } 128*91f16700Schasinglulu 129*91f16700Schasinglulu static struct mtk_cpu_smp_ops cpcv3_2_cpu_smp = { 130*91f16700Schasinglulu .init = cpupm_smp_init, 131*91f16700Schasinglulu .cpu_pwr_on_prepare = cpupm_cpu_pwr_on_prepare, 132*91f16700Schasinglulu .cpu_on = cpupm_cpu_resume_smp, 133*91f16700Schasinglulu .cpu_off = cpupm_cpu_suspend_smp, 134*91f16700Schasinglulu }; 135*91f16700Schasinglulu 136*91f16700Schasinglulu #endif /* CONFIG_MTK_SMP_EN */ 137*91f16700Schasinglulu 138*91f16700Schasinglulu #if CONFIG_MTK_CPU_SUSPEND_EN 139*91f16700Schasinglulu #define CPUPM_READY_MS (40000) 140*91f16700Schasinglulu #define CPUPM_ARCH_TIME_MS(ms) (ms * 1000 * SYS_COUNTER_FREQ_IN_MHZ) 141*91f16700Schasinglulu #define CPUPM_BOOTUP_TIME_THR CPUPM_ARCH_TIME_MS(CPUPM_READY_MS) 142*91f16700Schasinglulu 143*91f16700Schasinglulu static int mt_pwr_nodes[MT_PWR_MAX]; 144*91f16700Schasinglulu static int plat_mt_lp_cpu_rc; 145*91f16700Schasinglulu static unsigned int cpu_pm_status; 146*91f16700Schasinglulu static unsigned int plat_prev_stateid; 147*91f16700Schasinglulu 148*91f16700Schasinglulu static int mcusys_prepare_suspend(const struct mtk_cpupm_pwrstate *state) 149*91f16700Schasinglulu { 150*91f16700Schasinglulu unsigned int stateid = state->pwr.state_id; 151*91f16700Schasinglulu 152*91f16700Schasinglulu if (mtk_cpc_mcusys_off_prepare() != CPC_SUCCESS) { 153*91f16700Schasinglulu goto mt_pwr_mcusysoff_break; 154*91f16700Schasinglulu } 155*91f16700Schasinglulu 156*91f16700Schasinglulu if (!IS_PLAT_SUSPEND_ID(stateid)) { 157*91f16700Schasinglulu if (mt_pwr_nodes[MT_PWR_SYSTEM_MEM] != 0) { 158*91f16700Schasinglulu stateid = MT_PLAT_PWR_STATE_SYSTEM_MEM; 159*91f16700Schasinglulu } else if (mt_pwr_nodes[MT_PWR_SYSTEM_PLL] != 0) { 160*91f16700Schasinglulu stateid = MT_PLAT_PWR_STATE_SYSTEM_PLL; 161*91f16700Schasinglulu } else if (mt_pwr_nodes[MT_PWR_SYSTEM_BUS] != 0) { 162*91f16700Schasinglulu stateid = MT_PLAT_PWR_STATE_SYSTEM_BUS; 163*91f16700Schasinglulu } else if (mt_pwr_nodes[MT_PWR_SUSPEND] != 0) { 164*91f16700Schasinglulu stateid = MT_PLAT_PWR_STATE_SUSPEND; 165*91f16700Schasinglulu } else { 166*91f16700Schasinglulu stateid = MT_PLAT_PWR_STATE_MCUSYS; 167*91f16700Schasinglulu } 168*91f16700Schasinglulu } 169*91f16700Schasinglulu 170*91f16700Schasinglulu plat_prev_stateid = stateid; 171*91f16700Schasinglulu plat_mt_lp_cpu_rc = mt_lp_rm_find_and_run_constraint(0, state->info.cpuid, stateid, NULL); 172*91f16700Schasinglulu 173*91f16700Schasinglulu if (plat_mt_lp_cpu_rc < 0) { 174*91f16700Schasinglulu goto mt_pwr_mcusysoff_reflect; 175*91f16700Schasinglulu } 176*91f16700Schasinglulu 177*91f16700Schasinglulu #ifdef CPU_PM_TINYSYS_SUPPORT 178*91f16700Schasinglulu mtk_set_cpu_pm_preffered_cpu(state->info.cpuid); 179*91f16700Schasinglulu #endif 180*91f16700Schasinglulu return MTK_CPUPM_E_OK; 181*91f16700Schasinglulu 182*91f16700Schasinglulu mt_pwr_mcusysoff_reflect: 183*91f16700Schasinglulu mtk_cpc_mcusys_off_reflect(); 184*91f16700Schasinglulu mt_pwr_mcusysoff_break: 185*91f16700Schasinglulu plat_mt_lp_cpu_rc = -1; 186*91f16700Schasinglulu 187*91f16700Schasinglulu return MTK_CPUPM_E_FAIL; 188*91f16700Schasinglulu } 189*91f16700Schasinglulu 190*91f16700Schasinglulu static int mcusys_prepare_resume(const struct mtk_cpupm_pwrstate *state) 191*91f16700Schasinglulu { 192*91f16700Schasinglulu if (plat_mt_lp_cpu_rc < 0) { 193*91f16700Schasinglulu return MTK_CPUPM_E_FAIL; 194*91f16700Schasinglulu } 195*91f16700Schasinglulu 196*91f16700Schasinglulu mt_lp_rm_reset_constraint(plat_mt_lp_cpu_rc, state->info.cpuid, plat_prev_stateid); 197*91f16700Schasinglulu mtk_cpc_mcusys_off_reflect(); 198*91f16700Schasinglulu return MTK_CPUPM_E_OK; 199*91f16700Schasinglulu } 200*91f16700Schasinglulu 201*91f16700Schasinglulu static unsigned int cpupm_do_pstate_off(const mtk_pstate_type psci_state, 202*91f16700Schasinglulu const struct mtk_cpupm_pwrstate *state) 203*91f16700Schasinglulu { 204*91f16700Schasinglulu unsigned int pstate = MT_CPUPM_PWR_DOMAIN_CORE; 205*91f16700Schasinglulu 206*91f16700Schasinglulu if (!state || (state->pwr.afflv > PLAT_MAX_PWR_LVL)) { 207*91f16700Schasinglulu CPU_PM_ASSERT(0); 208*91f16700Schasinglulu } 209*91f16700Schasinglulu 210*91f16700Schasinglulu switch (state->pwr.state_id) { 211*91f16700Schasinglulu case MT_PLAT_PWR_STATE_SYSTEM_MEM: 212*91f16700Schasinglulu mt_pwr_nodes[MT_PWR_SYSTEM_MEM] += 1; 213*91f16700Schasinglulu break; 214*91f16700Schasinglulu case MT_PLAT_PWR_STATE_SYSTEM_PLL: 215*91f16700Schasinglulu mt_pwr_nodes[MT_PWR_SYSTEM_PLL] += 1; 216*91f16700Schasinglulu break; 217*91f16700Schasinglulu case MT_PLAT_PWR_STATE_SYSTEM_BUS: 218*91f16700Schasinglulu mt_pwr_nodes[MT_PWR_SYSTEM_BUS] += 1; 219*91f16700Schasinglulu break; 220*91f16700Schasinglulu case MT_PLAT_PWR_STATE_SUSPEND: 221*91f16700Schasinglulu mt_pwr_nodes[MT_PWR_SUSPEND] += 1; 222*91f16700Schasinglulu break; 223*91f16700Schasinglulu default: 224*91f16700Schasinglulu if (!IS_MT_PLAT_PWR_STATE_MCUSYS(state->pwr.state_id) && 225*91f16700Schasinglulu !IS_PLAT_SYSTEM_SUSPEND(state->pwr.afflv)) { 226*91f16700Schasinglulu plat_cpu_pm_lock(); 227*91f16700Schasinglulu mt_pwr_nodes[MT_PWR_NONMCUSYS] += 1; 228*91f16700Schasinglulu flush_dcache_range((uintptr_t)&mt_pwr_nodes[MT_PWR_NONMCUSYS], 229*91f16700Schasinglulu sizeof(mt_pwr_nodes[MT_PWR_NONMCUSYS])); 230*91f16700Schasinglulu plat_cpu_pm_unlock(); 231*91f16700Schasinglulu } 232*91f16700Schasinglulu break; 233*91f16700Schasinglulu } 234*91f16700Schasinglulu 235*91f16700Schasinglulu if ((mt_pwr_nodes[MT_PWR_NONMCUSYS] == 0) && IS_PLAT_MCUSYSOFF_AFFLV(state->pwr.afflv)) { 236*91f16700Schasinglulu /* Prepare to power down mcusys */ 237*91f16700Schasinglulu if (mcusys_prepare_suspend(state) == MTK_CPUPM_E_OK) { 238*91f16700Schasinglulu mt_pwr_nodes[MT_PWR_MCUSYS_PDN] += 1; 239*91f16700Schasinglulu flush_dcache_range((uintptr_t)&mt_pwr_nodes[MT_PWR_MCUSYS_PDN], 240*91f16700Schasinglulu sizeof(mt_pwr_nodes[MT_PWR_MCUSYS_PDN])); 241*91f16700Schasinglulu pstate |= (MT_CPUPM_PWR_DOMAIN_MCUSYS | MT_CPUPM_PWR_DOMAIN_CLUSTER); 242*91f16700Schasinglulu } 243*91f16700Schasinglulu } 244*91f16700Schasinglulu 245*91f16700Schasinglulu if (state->pwr.afflv >= PLAT_MT_CPU_SUSPEND_CLUSTER) { 246*91f16700Schasinglulu pstate |= MT_CPUPM_PWR_DOMAIN_CLUSTER; 247*91f16700Schasinglulu } 248*91f16700Schasinglulu 249*91f16700Schasinglulu if (psci_get_pstate_pwrlvl(psci_state) >= PLAT_MT_CPU_SUSPEND_CLUSTER) { 250*91f16700Schasinglulu pstate |= MT_CPUPM_PWR_DOMAIN_PERCORE_DSU; 251*91f16700Schasinglulu } 252*91f16700Schasinglulu 253*91f16700Schasinglulu return pstate; 254*91f16700Schasinglulu } 255*91f16700Schasinglulu 256*91f16700Schasinglulu static unsigned int cpupm_do_pstate_on(const mtk_pstate_type psci_state, 257*91f16700Schasinglulu const struct mtk_cpupm_pwrstate *state) 258*91f16700Schasinglulu { 259*91f16700Schasinglulu unsigned int pstate = MT_CPUPM_PWR_DOMAIN_CORE; 260*91f16700Schasinglulu 261*91f16700Schasinglulu CPU_PM_ASSERT(state != NULL); 262*91f16700Schasinglulu 263*91f16700Schasinglulu if (state->pwr.afflv > PLAT_MAX_PWR_LVL) { 264*91f16700Schasinglulu CPU_PM_ASSERT(0); 265*91f16700Schasinglulu } 266*91f16700Schasinglulu 267*91f16700Schasinglulu if (mt_pwr_nodes[MT_PWR_MCUSYS_PDN] != 0) { 268*91f16700Schasinglulu mt_pwr_nodes[MT_PWR_MCUSYS_PDN] = 0; 269*91f16700Schasinglulu flush_dcache_range((uintptr_t)&mt_pwr_nodes[MT_PWR_MCUSYS_PDN], 270*91f16700Schasinglulu sizeof(mt_pwr_nodes[MT_PWR_MCUSYS_PDN])); 271*91f16700Schasinglulu pstate |= (MT_CPUPM_PWR_DOMAIN_MCUSYS | MT_CPUPM_PWR_DOMAIN_CLUSTER); 272*91f16700Schasinglulu mcusys_prepare_resume(state); 273*91f16700Schasinglulu } 274*91f16700Schasinglulu 275*91f16700Schasinglulu if (state->pwr.afflv >= PLAT_MT_CPU_SUSPEND_CLUSTER) { 276*91f16700Schasinglulu pstate |= MT_CPUPM_PWR_DOMAIN_CLUSTER; 277*91f16700Schasinglulu } 278*91f16700Schasinglulu 279*91f16700Schasinglulu switch (state->pwr.state_id) { 280*91f16700Schasinglulu case MT_PLAT_PWR_STATE_SYSTEM_MEM: 281*91f16700Schasinglulu mt_pwr_nodes[MT_PWR_SYSTEM_MEM] -= 1; 282*91f16700Schasinglulu CPU_PM_ASSERT(mt_pwr_nodes[MT_PWR_SYSTEM_MEM] >= 0); 283*91f16700Schasinglulu break; 284*91f16700Schasinglulu case MT_PLAT_PWR_STATE_SYSTEM_PLL: 285*91f16700Schasinglulu mt_pwr_nodes[MT_PWR_SYSTEM_PLL] -= 1; 286*91f16700Schasinglulu CPU_PM_ASSERT(mt_pwr_nodes[MT_PWR_SYSTEM_PLL] >= 0); 287*91f16700Schasinglulu break; 288*91f16700Schasinglulu case MT_PLAT_PWR_STATE_SYSTEM_BUS: 289*91f16700Schasinglulu mt_pwr_nodes[MT_PWR_SYSTEM_BUS] -= 1; 290*91f16700Schasinglulu CPU_PM_ASSERT(mt_pwr_nodes[MT_PWR_SYSTEM_BUS] >= 0); 291*91f16700Schasinglulu break; 292*91f16700Schasinglulu case MT_PLAT_PWR_STATE_SUSPEND: 293*91f16700Schasinglulu mt_pwr_nodes[MT_PWR_SUSPEND] -= 1; 294*91f16700Schasinglulu CPU_PM_ASSERT(mt_pwr_nodes[MT_PWR_SUSPEND] >= 0); 295*91f16700Schasinglulu break; 296*91f16700Schasinglulu default: 297*91f16700Schasinglulu if (!IS_MT_PLAT_PWR_STATE_MCUSYS(state->pwr.state_id) && 298*91f16700Schasinglulu !IS_PLAT_SYSTEM_SUSPEND(state->pwr.afflv)) { 299*91f16700Schasinglulu plat_cpu_pm_lock(); 300*91f16700Schasinglulu mt_pwr_nodes[MT_PWR_NONMCUSYS] -= 1; 301*91f16700Schasinglulu flush_dcache_range((uintptr_t)&mt_pwr_nodes[MT_PWR_NONMCUSYS], 302*91f16700Schasinglulu sizeof(mt_pwr_nodes[MT_PWR_NONMCUSYS])); 303*91f16700Schasinglulu plat_cpu_pm_unlock(); 304*91f16700Schasinglulu } 305*91f16700Schasinglulu break; 306*91f16700Schasinglulu } 307*91f16700Schasinglulu 308*91f16700Schasinglulu if (IS_PLAT_SYSTEM_SUSPEND(state->pwr.afflv) || 309*91f16700Schasinglulu (IS_PLAT_SYSTEM_RETENTION(state->pwr.afflv) && (mt_pwr_nodes[MT_PWR_SUSPEND] > 0))) { 310*91f16700Schasinglulu mtk_cpc_time_sync(); 311*91f16700Schasinglulu } 312*91f16700Schasinglulu 313*91f16700Schasinglulu if (mt_pwr_nodes[MT_PWR_NONMCUSYS] < 0) { 314*91f16700Schasinglulu CPU_PM_ASSERT(0); 315*91f16700Schasinglulu } 316*91f16700Schasinglulu 317*91f16700Schasinglulu pstate |= MT_CPUPM_PWR_DOMAIN_PERCORE_DSU; 318*91f16700Schasinglulu 319*91f16700Schasinglulu return pstate; 320*91f16700Schasinglulu } 321*91f16700Schasinglulu 322*91f16700Schasinglulu static void cpupm_cpu_resume(const struct mtk_cpupm_pwrstate *state) 323*91f16700Schasinglulu { 324*91f16700Schasinglulu cpupm_cpu_resume_common(state); 325*91f16700Schasinglulu } 326*91f16700Schasinglulu 327*91f16700Schasinglulu static void cpupm_mcusys_resume(const struct mtk_cpupm_pwrstate *state) 328*91f16700Schasinglulu { 329*91f16700Schasinglulu assert(state != NULL); 330*91f16700Schasinglulu } 331*91f16700Schasinglulu 332*91f16700Schasinglulu static void cpupm_mcusys_suspend(const struct mtk_cpupm_pwrstate *state) 333*91f16700Schasinglulu { 334*91f16700Schasinglulu assert(state != NULL); 335*91f16700Schasinglulu } 336*91f16700Schasinglulu 337*91f16700Schasinglulu static unsigned int cpupm_get_pstate(enum mt_cpupm_pwr_domain domain, 338*91f16700Schasinglulu const mtk_pstate_type psci_state, 339*91f16700Schasinglulu const struct mtk_cpupm_pwrstate *state) 340*91f16700Schasinglulu { 341*91f16700Schasinglulu unsigned int pstate = 0; 342*91f16700Schasinglulu 343*91f16700Schasinglulu if (state == NULL) { 344*91f16700Schasinglulu return 0; 345*91f16700Schasinglulu } 346*91f16700Schasinglulu 347*91f16700Schasinglulu if (state->info.mode == MTK_CPU_PM_SMP) { 348*91f16700Schasinglulu pstate = MT_CPUPM_PWR_DOMAIN_CORE; 349*91f16700Schasinglulu } else { 350*91f16700Schasinglulu if (domain == CPUPM_PWR_OFF) { 351*91f16700Schasinglulu pstate = cpupm_do_pstate_off(psci_state, state); 352*91f16700Schasinglulu } else if (domain == CPUPM_PWR_ON) { 353*91f16700Schasinglulu pstate = cpupm_do_pstate_on(psci_state, state); 354*91f16700Schasinglulu } else { 355*91f16700Schasinglulu INFO("[%s:%d][CPU_PM] unknown pwr domain :%d\n", 356*91f16700Schasinglulu __func__, __LINE__, domain); 357*91f16700Schasinglulu assert(0); 358*91f16700Schasinglulu } 359*91f16700Schasinglulu } 360*91f16700Schasinglulu return pstate; 361*91f16700Schasinglulu } 362*91f16700Schasinglulu 363*91f16700Schasinglulu static int cpupm_init(void) 364*91f16700Schasinglulu { 365*91f16700Schasinglulu int ret = MTK_CPUPM_E_OK; 366*91f16700Schasinglulu 367*91f16700Schasinglulu #ifdef CPU_PM_TINYSYS_SUPPORT 368*91f16700Schasinglulu int status; 369*91f16700Schasinglulu 370*91f16700Schasinglulu if ((cpu_pm_status & CPU_PM_INIT_READY) == CPU_PM_INIT_READY) { 371*91f16700Schasinglulu return MTK_CPUPM_E_OK; 372*91f16700Schasinglulu } 373*91f16700Schasinglulu 374*91f16700Schasinglulu if (!(cpu_pm_status & CPU_PM_DEPD_INIT)) { 375*91f16700Schasinglulu status = mtk_lp_depd_condition(CPUPM_MBOX_WAIT_DEV_INIT); 376*91f16700Schasinglulu if (status == 0) { 377*91f16700Schasinglulu plat_cpu_pm_lock(); 378*91f16700Schasinglulu cpu_pm_status |= CPU_PM_DEPD_INIT; 379*91f16700Schasinglulu plat_cpu_pm_unlock(); 380*91f16700Schasinglulu } 381*91f16700Schasinglulu } 382*91f16700Schasinglulu 383*91f16700Schasinglulu if ((cpu_pm_status & CPU_PM_DEPD_INIT) && !(cpu_pm_status & CPU_PM_DEPD_READY)) { 384*91f16700Schasinglulu status = mtk_lp_depd_condition(CPUPM_MBOX_WAIT_TASK_READY); 385*91f16700Schasinglulu if (status == 0) { 386*91f16700Schasinglulu plat_cpu_pm_lock(); 387*91f16700Schasinglulu cpu_pm_status |= CPU_PM_DEPD_READY; 388*91f16700Schasinglulu plat_cpu_pm_unlock(); 389*91f16700Schasinglulu } 390*91f16700Schasinglulu } 391*91f16700Schasinglulu 392*91f16700Schasinglulu ret = ((cpu_pm_status & CPU_PM_INIT_READY) == CPU_PM_INIT_READY) ? 393*91f16700Schasinglulu MTK_CPUPM_E_OK : MTK_CPUPM_E_FAIL; 394*91f16700Schasinglulu #endif 395*91f16700Schasinglulu return ret; 396*91f16700Schasinglulu } 397*91f16700Schasinglulu 398*91f16700Schasinglulu static int cpupm_pwr_state_valid(unsigned int afflv, unsigned int state) 399*91f16700Schasinglulu { 400*91f16700Schasinglulu if (cpu_pm_status == CPU_PM_LP_READY) { 401*91f16700Schasinglulu return MTK_CPUPM_E_OK; 402*91f16700Schasinglulu } 403*91f16700Schasinglulu 404*91f16700Schasinglulu if (cpupm_init() != MTK_CPUPM_E_OK) { 405*91f16700Schasinglulu return MTK_CPUPM_E_FAIL; 406*91f16700Schasinglulu } 407*91f16700Schasinglulu 408*91f16700Schasinglulu if (read_cntpct_el0() >= (uint64_t)CPUPM_BOOTUP_TIME_THR) { 409*91f16700Schasinglulu plat_cpu_pm_lock(); 410*91f16700Schasinglulu cpu_pm_status |= CPU_PM_PLAT_READY; 411*91f16700Schasinglulu plat_cpu_pm_unlock(); 412*91f16700Schasinglulu } 413*91f16700Schasinglulu 414*91f16700Schasinglulu if (!IS_PLAT_SYSTEM_SUSPEND(afflv) && (cpu_pm_status & CPU_PM_PLAT_READY) == 0) { 415*91f16700Schasinglulu return MTK_CPUPM_E_FAIL; 416*91f16700Schasinglulu } 417*91f16700Schasinglulu 418*91f16700Schasinglulu return MTK_CPUPM_E_OK; 419*91f16700Schasinglulu } 420*91f16700Schasinglulu 421*91f16700Schasinglulu static struct mtk_cpu_pm_ops cpcv3_2_mcdi = { 422*91f16700Schasinglulu .get_pstate = cpupm_get_pstate, 423*91f16700Schasinglulu .pwr_state_valid = cpupm_pwr_state_valid, 424*91f16700Schasinglulu .cpu_resume = cpupm_cpu_resume, 425*91f16700Schasinglulu .mcusys_suspend = cpupm_mcusys_suspend, 426*91f16700Schasinglulu .mcusys_resume = cpupm_mcusys_resume, 427*91f16700Schasinglulu }; 428*91f16700Schasinglulu #endif /* CONFIG_MTK_CPU_SUSPEND_EN */ 429*91f16700Schasinglulu 430*91f16700Schasinglulu #endif /* CONFIG_MTK_PM_SUPPORT */ 431*91f16700Schasinglulu 432*91f16700Schasinglulu /* 433*91f16700Schasinglulu * Depend on mtk pm methodology, the psci op init must 434*91f16700Schasinglulu * be invoked after cpu pm to avoid initialization fail. 435*91f16700Schasinglulu */ 436*91f16700Schasinglulu int mt_plat_cpu_pm_init(void) 437*91f16700Schasinglulu { 438*91f16700Schasinglulu plat_cpu_pm_lock_init(); 439*91f16700Schasinglulu 440*91f16700Schasinglulu mtk_cpc_init(); 441*91f16700Schasinglulu #if CONFIG_MTK_PM_SUPPORT 442*91f16700Schasinglulu 443*91f16700Schasinglulu #if CONFIG_MTK_CPU_SUSPEND_EN 444*91f16700Schasinglulu register_cpu_pm_ops(CPU_PM_FN, &cpcv3_2_mcdi); 445*91f16700Schasinglulu #endif /* CONFIG_MTK_CPU_SUSPEND_EN */ 446*91f16700Schasinglulu 447*91f16700Schasinglulu #if CONFIG_MTK_SMP_EN 448*91f16700Schasinglulu register_cpu_smp_ops(CPU_PM_FN, &cpcv3_2_cpu_smp); 449*91f16700Schasinglulu #endif /* CONFIG_MTK_SMP_EN */ 450*91f16700Schasinglulu 451*91f16700Schasinglulu #endif /* CONFIG_MTK_PM_SUPPORT */ 452*91f16700Schasinglulu 453*91f16700Schasinglulu INFO("[%s:%d] - CPU PM INIT finished\n", __func__, __LINE__); 454*91f16700Schasinglulu return 0; 455*91f16700Schasinglulu } 456*91f16700Schasinglulu MTK_ARCH_INIT(mt_plat_cpu_pm_init); 457*91f16700Schasinglulu 458*91f16700Schasinglulu static const mmap_region_t cpu_pm_mmap[] MTK_MMAP_SECTION = { 459*91f16700Schasinglulu #ifdef CPU_PM_TINYSYS_SUPPORT 460*91f16700Schasinglulu #if CONFIG_MTK_PM_SUPPORT && CONFIG_MTK_CPU_SUSPEND_EN 461*91f16700Schasinglulu MAP_REGION_FLAT(CPU_EB_TCM_BASE, CPU_EB_TCM_SIZE, MT_DEVICE | MT_RW | MT_SECURE), 462*91f16700Schasinglulu #endif 463*91f16700Schasinglulu #endif 464*91f16700Schasinglulu {0} 465*91f16700Schasinglulu }; 466*91f16700Schasinglulu DECLARE_MTK_MMAP_REGIONS(cpu_pm_mmap); 467