1*a24b53e0SWenzhen Yu /* 2*a24b53e0SWenzhen Yu * Copyright (c) 2025, Mediatek Inc. All rights reserved. 3*a24b53e0SWenzhen Yu * 4*a24b53e0SWenzhen Yu * SPDX-License-Identifier: BSD-3-Clause 5*a24b53e0SWenzhen Yu */ 6*a24b53e0SWenzhen Yu 7*a24b53e0SWenzhen Yu #include <assert.h> 8*a24b53e0SWenzhen Yu #include <stddef.h> 9*a24b53e0SWenzhen Yu #include <stdio.h> 10*a24b53e0SWenzhen Yu #include <string.h> 11*a24b53e0SWenzhen Yu 12*a24b53e0SWenzhen Yu #include <arch.h> 13*a24b53e0SWenzhen Yu #include <common/debug.h> 14*a24b53e0SWenzhen Yu #include <drivers/console.h> 15*a24b53e0SWenzhen Yu #include <drivers/delay_timer.h> 16*a24b53e0SWenzhen Yu #include <drivers/gpio.h> 17*a24b53e0SWenzhen Yu #include <lib/bakery_lock.h> 18*a24b53e0SWenzhen Yu #include <lib/mmio.h> 19*a24b53e0SWenzhen Yu #include <lib/utils_def.h> 20*a24b53e0SWenzhen Yu #include <platform_def.h> 21*a24b53e0SWenzhen Yu 22*a24b53e0SWenzhen Yu #include <constraints/mt_spm_rc_api.h> 23*a24b53e0SWenzhen Yu #include <constraints/mt_spm_rc_internal.h> 24*a24b53e0SWenzhen Yu #include <drivers/spm/mt_spm_resource_req.h> 25*a24b53e0SWenzhen Yu #include <lib/mtk_init/mtk_init.h> 26*a24b53e0SWenzhen Yu #include <lib/pm/mtk_pm.h> 27*a24b53e0SWenzhen Yu #include <lpm_v2/mt_lp_rm.h> 28*a24b53e0SWenzhen Yu #include <lpm_v2/mt_lp_rqm.h> 29*a24b53e0SWenzhen Yu #include <lpm_v2/mt_lpm_smc.h> 30*a24b53e0SWenzhen Yu #include <mt_plat_spm_setting.h> 31*a24b53e0SWenzhen Yu #include <mt_spm.h> 32*a24b53e0SWenzhen Yu #include <mt_spm_common.h> 33*a24b53e0SWenzhen Yu #include <mt_spm_conservation.h> 34*a24b53e0SWenzhen Yu #include <mt_spm_constraint.h> 35*a24b53e0SWenzhen Yu #include <mt_spm_dispatcher.h> 36*a24b53e0SWenzhen Yu #include <mt_spm_hwreq.h> 37*a24b53e0SWenzhen Yu #include <mt_spm_idle.h> 38*a24b53e0SWenzhen Yu #include <mt_spm_internal.h> 39*a24b53e0SWenzhen Yu #include <mt_spm_reg.h> 40*a24b53e0SWenzhen Yu #include <mt_spm_suspend.h> 41*a24b53e0SWenzhen Yu #include <mtk_mmap_pool.h> 42*a24b53e0SWenzhen Yu #include <sleep_def.h> 43*a24b53e0SWenzhen Yu 44*a24b53e0SWenzhen Yu #ifdef MT_SPM_USING_BAKERY_LOCK 45*a24b53e0SWenzhen Yu DEFINE_BAKERY_LOCK(spm_lock); 46*a24b53e0SWenzhen Yu #define plat_spm_lock_init() \ 47*a24b53e0SWenzhen Yu bakery_lock_init(&spm_lock) 48*a24b53e0SWenzhen Yu #else 49*a24b53e0SWenzhen Yu spinlock_t spm_lock; 50*a24b53e0SWenzhen Yu #define plat_spm_lock_init() 51*a24b53e0SWenzhen Yu #endif 52*a24b53e0SWenzhen Yu 53*a24b53e0SWenzhen Yu uint32_t mt_spm_version; 54*a24b53e0SWenzhen Yu 55*a24b53e0SWenzhen Yu static uint32_t spm_irq_num; 56*a24b53e0SWenzhen Yu 57*a24b53e0SWenzhen Yu void spm_set_sysclk_settle(void) 58*a24b53e0SWenzhen Yu { 59*a24b53e0SWenzhen Yu uint32_t settle; 60*a24b53e0SWenzhen Yu 61*a24b53e0SWenzhen Yu mmio_write_32(SPM_CLK_SETTLE, SPM_SYSCLK_SETTLE); 62*a24b53e0SWenzhen Yu settle = mmio_read_32(SPM_CLK_SETTLE); 63*a24b53e0SWenzhen Yu 64*a24b53e0SWenzhen Yu INFO("md_settle = %u, settle = %u\n", SPM_SYSCLK_SETTLE, settle); 65*a24b53e0SWenzhen Yu } 66*a24b53e0SWenzhen Yu 67*a24b53e0SWenzhen Yu void spm_set_irq_num(uint32_t num) 68*a24b53e0SWenzhen Yu { 69*a24b53e0SWenzhen Yu spm_irq_num = num; 70*a24b53e0SWenzhen Yu } 71*a24b53e0SWenzhen Yu 72*a24b53e0SWenzhen Yu void spm_irq0_handler(uint64_t x1, uint64_t x2) 73*a24b53e0SWenzhen Yu { 74*a24b53e0SWenzhen Yu if (x2 == 0) { 75*a24b53e0SWenzhen Yu mmio_setbits_32(SPM_IRQ_MASK, ISRM_ALL_EXC_TWAM); 76*a24b53e0SWenzhen Yu mmio_write_32(SPM_IRQ_STA, x1); 77*a24b53e0SWenzhen Yu mmio_write_32(SPM_SWINT_CLR, PCM_SW_INT0); 78*a24b53e0SWenzhen Yu } 79*a24b53e0SWenzhen Yu } 80*a24b53e0SWenzhen Yu 81*a24b53e0SWenzhen Yu static int spm_ap_mdsrc_ack(void) 82*a24b53e0SWenzhen Yu { 83*a24b53e0SWenzhen Yu int ack, md_state = 0; 84*a24b53e0SWenzhen Yu 85*a24b53e0SWenzhen Yu /* Check ap_mdsrc_ack = 1'b1, for md internal resource on ack */ 86*a24b53e0SWenzhen Yu ack = !!(mmio_read_32(AP_MDSRC_REQ) & AP_MDSMSRC_ACK_LSB); 87*a24b53e0SWenzhen Yu 88*a24b53e0SWenzhen Yu if (!ack) { 89*a24b53e0SWenzhen Yu /* Check md_apsrc_req = 1'b0, for md state 0:sleep, 1:wakeup */ 90*a24b53e0SWenzhen Yu md_state = !!(mmio_read_32(SPM_REQ_STA_10) 91*a24b53e0SWenzhen Yu & MD_APSRC_REQ_LSB); 92*a24b53e0SWenzhen Yu 93*a24b53e0SWenzhen Yu ERROR("[SPM] error: md_sleep = %d\n", md_state); 94*a24b53e0SWenzhen Yu ERROR("%s can not get AP_MDSRC_ACK\n", __func__); 95*a24b53e0SWenzhen Yu return -1; 96*a24b53e0SWenzhen Yu } 97*a24b53e0SWenzhen Yu return 0; 98*a24b53e0SWenzhen Yu } 99*a24b53e0SWenzhen Yu 100*a24b53e0SWenzhen Yu static void spm_ap_mdsrc_req(int set) 101*a24b53e0SWenzhen Yu { 102*a24b53e0SWenzhen Yu spm_lock_get(); 103*a24b53e0SWenzhen Yu 104*a24b53e0SWenzhen Yu if (set) 105*a24b53e0SWenzhen Yu mmio_setbits_32(AP_MDSRC_REQ, AP_MDSMSRC_REQ_LSB); 106*a24b53e0SWenzhen Yu else 107*a24b53e0SWenzhen Yu mmio_clrbits_32(AP_MDSRC_REQ, AP_MDSMSRC_REQ_LSB); 108*a24b53e0SWenzhen Yu 109*a24b53e0SWenzhen Yu spm_lock_release(); 110*a24b53e0SWenzhen Yu } 111*a24b53e0SWenzhen Yu 112*a24b53e0SWenzhen Yu static int spm_is_md_sleep(void *priv) 113*a24b53e0SWenzhen Yu { 114*a24b53e0SWenzhen Yu int md_state = 0; 115*a24b53e0SWenzhen Yu int *sleep = (int *)priv; 116*a24b53e0SWenzhen Yu 117*a24b53e0SWenzhen Yu if (!priv) 118*a24b53e0SWenzhen Yu return -1; 119*a24b53e0SWenzhen Yu 120*a24b53e0SWenzhen Yu /* Check md_apsrc_req = 1'b0, for md state 0:sleep, 1:wakeup */ 121*a24b53e0SWenzhen Yu md_state = !!(mmio_read_32(SPM_REQ_STA_10) 122*a24b53e0SWenzhen Yu & MD_APSRC_REQ_LSB); 123*a24b53e0SWenzhen Yu 124*a24b53e0SWenzhen Yu if (md_state == 0) 125*a24b53e0SWenzhen Yu *sleep = 1; 126*a24b53e0SWenzhen Yu else 127*a24b53e0SWenzhen Yu *sleep = 0; 128*a24b53e0SWenzhen Yu 129*a24b53e0SWenzhen Yu return 0; 130*a24b53e0SWenzhen Yu } 131*a24b53e0SWenzhen Yu 132*a24b53e0SWenzhen Yu static void spm_ap_gpueb_pll_control(int set) 133*a24b53e0SWenzhen Yu { 134*a24b53e0SWenzhen Yu spm_lock_get(); 135*a24b53e0SWenzhen Yu 136*a24b53e0SWenzhen Yu if (set) 137*a24b53e0SWenzhen Yu mmio_setbits_32(SPM2GPUPM_CON, SC_MFG_PLL_EN_LSB); 138*a24b53e0SWenzhen Yu else 139*a24b53e0SWenzhen Yu mmio_clrbits_32(SPM2GPUPM_CON, SC_MFG_PLL_EN_LSB); 140*a24b53e0SWenzhen Yu 141*a24b53e0SWenzhen Yu spm_lock_release(); 142*a24b53e0SWenzhen Yu } 143*a24b53e0SWenzhen Yu 144*a24b53e0SWenzhen Yu static uint32_t spm_ap_gpueb_get_pwr_status(void) 145*a24b53e0SWenzhen Yu { 146*a24b53e0SWenzhen Yu uint32_t ret; 147*a24b53e0SWenzhen Yu 148*a24b53e0SWenzhen Yu ret = mmio_read_32(XPU_PWR_STATUS); 149*a24b53e0SWenzhen Yu 150*a24b53e0SWenzhen Yu return ret; 151*a24b53e0SWenzhen Yu } 152*a24b53e0SWenzhen Yu 153*a24b53e0SWenzhen Yu static uint32_t spm_ap_gpueb_get_mfg0_pwr_con(void) 154*a24b53e0SWenzhen Yu { 155*a24b53e0SWenzhen Yu uint32_t ret; 156*a24b53e0SWenzhen Yu 157*a24b53e0SWenzhen Yu ret = mmio_read_32(MFG0_PWR_CON); 158*a24b53e0SWenzhen Yu 159*a24b53e0SWenzhen Yu return ret; 160*a24b53e0SWenzhen Yu } 161*a24b53e0SWenzhen Yu 162*a24b53e0SWenzhen Yu #ifndef MTK_PLAT_SPM_UNSUPPORT 163*a24b53e0SWenzhen Yu struct mt_lp_res_req rq_xo_fpm = { 164*a24b53e0SWenzhen Yu .res_id = MT_LP_RQ_XO_FPM, 165*a24b53e0SWenzhen Yu .res_rq = MT_SPM_XO_FPM, 166*a24b53e0SWenzhen Yu .res_usage = 0, 167*a24b53e0SWenzhen Yu }; 168*a24b53e0SWenzhen Yu 169*a24b53e0SWenzhen Yu struct mt_lp_res_req rq_26m = { 170*a24b53e0SWenzhen Yu .res_id = MT_LP_RQ_26M, 171*a24b53e0SWenzhen Yu .res_rq = MT_SPM_26M, 172*a24b53e0SWenzhen Yu .res_usage = 0, 173*a24b53e0SWenzhen Yu }; 174*a24b53e0SWenzhen Yu 175*a24b53e0SWenzhen Yu struct mt_lp_res_req rq_infra = { 176*a24b53e0SWenzhen Yu .res_id = MT_LP_RQ_INFRA, 177*a24b53e0SWenzhen Yu .res_rq = MT_SPM_INFRA, 178*a24b53e0SWenzhen Yu .res_usage = 0, 179*a24b53e0SWenzhen Yu }; 180*a24b53e0SWenzhen Yu 181*a24b53e0SWenzhen Yu struct mt_lp_res_req rq_syspll = { 182*a24b53e0SWenzhen Yu .res_id = MT_LP_RQ_SYSPLL, 183*a24b53e0SWenzhen Yu .res_rq = MT_SPM_SYSPLL, 184*a24b53e0SWenzhen Yu .res_usage = 0, 185*a24b53e0SWenzhen Yu }; 186*a24b53e0SWenzhen Yu 187*a24b53e0SWenzhen Yu struct mt_lp_res_req rq_dram_s0 = { 188*a24b53e0SWenzhen Yu .res_id = MT_LP_RQ_DRAM, 189*a24b53e0SWenzhen Yu .res_rq = MT_SPM_DRAM_S0, 190*a24b53e0SWenzhen Yu .res_usage = 0, 191*a24b53e0SWenzhen Yu }; 192*a24b53e0SWenzhen Yu 193*a24b53e0SWenzhen Yu struct mt_lp_res_req rq_dram_s1 = { 194*a24b53e0SWenzhen Yu .res_id = MT_LP_RQ_DRAM, 195*a24b53e0SWenzhen Yu .res_rq = MT_SPM_DRAM_S1, 196*a24b53e0SWenzhen Yu .res_usage = 0, 197*a24b53e0SWenzhen Yu }; 198*a24b53e0SWenzhen Yu 199*a24b53e0SWenzhen Yu struct mt_lp_res_req rq_vcore = { 200*a24b53e0SWenzhen Yu .res_id = MT_LP_RQ_VCORE, 201*a24b53e0SWenzhen Yu .res_rq = MT_SPM_VCORE, 202*a24b53e0SWenzhen Yu .res_usage = 0, 203*a24b53e0SWenzhen Yu }; 204*a24b53e0SWenzhen Yu 205*a24b53e0SWenzhen Yu struct mt_lp_res_req rq_emi = { 206*a24b53e0SWenzhen Yu .res_id = MT_LP_RQ_EMI, 207*a24b53e0SWenzhen Yu .res_rq = MT_SPM_EMI, 208*a24b53e0SWenzhen Yu .res_usage = 0, 209*a24b53e0SWenzhen Yu }; 210*a24b53e0SWenzhen Yu 211*a24b53e0SWenzhen Yu struct mt_lp_res_req rq_pmic = { 212*a24b53e0SWenzhen Yu .res_id = MT_LP_RQ_PMIC, 213*a24b53e0SWenzhen Yu .res_rq = MT_SPM_PMIC, 214*a24b53e0SWenzhen Yu .res_usage = 0, 215*a24b53e0SWenzhen Yu }; 216*a24b53e0SWenzhen Yu 217*a24b53e0SWenzhen Yu struct mt_lp_res_req *spm_resources[] = { 218*a24b53e0SWenzhen Yu &rq_xo_fpm, 219*a24b53e0SWenzhen Yu &rq_26m, 220*a24b53e0SWenzhen Yu &rq_infra, 221*a24b53e0SWenzhen Yu &rq_syspll, 222*a24b53e0SWenzhen Yu &rq_dram_s0, 223*a24b53e0SWenzhen Yu &rq_dram_s1, 224*a24b53e0SWenzhen Yu &rq_vcore, 225*a24b53e0SWenzhen Yu &rq_emi, 226*a24b53e0SWenzhen Yu &rq_pmic, 227*a24b53e0SWenzhen Yu NULL, 228*a24b53e0SWenzhen Yu }; 229*a24b53e0SWenzhen Yu 230*a24b53e0SWenzhen Yu struct mt_resource_req_manager plat_mt8196_rq = { 231*a24b53e0SWenzhen Yu .res = spm_resources, 232*a24b53e0SWenzhen Yu }; 233*a24b53e0SWenzhen Yu 234*a24b53e0SWenzhen Yu struct mt_resource_constraint plat_constraint_vcore = { 235*a24b53e0SWenzhen Yu .is_valid = spm_is_valid_rc_vcore, 236*a24b53e0SWenzhen Yu .update = spm_update_rc_vcore, 237*a24b53e0SWenzhen Yu .allow = spm_allow_rc_vcore, 238*a24b53e0SWenzhen Yu .run = spm_run_rc_vcore, 239*a24b53e0SWenzhen Yu .reset = spm_reset_rc_vcore, 240*a24b53e0SWenzhen Yu .get_status = spm_get_status_rc_vcore, 241*a24b53e0SWenzhen Yu }; 242*a24b53e0SWenzhen Yu 243*a24b53e0SWenzhen Yu struct mt_resource_constraint plat_constraint_bus26m = { 244*a24b53e0SWenzhen Yu .is_valid = spm_is_valid_rc_bus26m, 245*a24b53e0SWenzhen Yu .update = spm_update_rc_bus26m, 246*a24b53e0SWenzhen Yu .allow = spm_allow_rc_bus26m, 247*a24b53e0SWenzhen Yu .run = spm_run_rc_bus26m, 248*a24b53e0SWenzhen Yu .reset = spm_reset_rc_bus26m, 249*a24b53e0SWenzhen Yu .get_status = spm_get_status_rc_bus26m, 250*a24b53e0SWenzhen Yu }; 251*a24b53e0SWenzhen Yu 252*a24b53e0SWenzhen Yu struct mt_resource_constraint plat_constraint_syspll = { 253*a24b53e0SWenzhen Yu .is_valid = spm_is_valid_rc_syspll, 254*a24b53e0SWenzhen Yu .update = spm_update_rc_syspll, 255*a24b53e0SWenzhen Yu .allow = spm_allow_rc_syspll, 256*a24b53e0SWenzhen Yu .run = spm_run_rc_syspll, 257*a24b53e0SWenzhen Yu .reset = spm_reset_rc_syspll, 258*a24b53e0SWenzhen Yu .get_status = spm_get_status_rc_syspll, 259*a24b53e0SWenzhen Yu }; 260*a24b53e0SWenzhen Yu 261*a24b53e0SWenzhen Yu struct mt_resource_constraint *plat_constraints[] = { 262*a24b53e0SWenzhen Yu &plat_constraint_vcore, 263*a24b53e0SWenzhen Yu &plat_constraint_bus26m, 264*a24b53e0SWenzhen Yu &plat_constraint_syspll, 265*a24b53e0SWenzhen Yu NULL, 266*a24b53e0SWenzhen Yu }; 267*a24b53e0SWenzhen Yu #endif 268*a24b53e0SWenzhen Yu 269*a24b53e0SWenzhen Yu int mt_spm_hwctrl(uint32_t type, int set, void *priv) 270*a24b53e0SWenzhen Yu { 271*a24b53e0SWenzhen Yu int ret = 0; 272*a24b53e0SWenzhen Yu 273*a24b53e0SWenzhen Yu if (type == PLAT_AP_MDSRC_REQ) { 274*a24b53e0SWenzhen Yu spm_ap_mdsrc_req(set); 275*a24b53e0SWenzhen Yu } else if (type == PLAT_AP_MDSRC_ACK) { 276*a24b53e0SWenzhen Yu ret = spm_ap_mdsrc_ack(); 277*a24b53e0SWenzhen Yu } else if (type == PLAT_AP_IS_MD_SLEEP) { 278*a24b53e0SWenzhen Yu ret = spm_is_md_sleep(priv); 279*a24b53e0SWenzhen Yu } else if (type == PLAT_AP_MDSRC_SETTLE) { 280*a24b53e0SWenzhen Yu if (!priv) 281*a24b53e0SWenzhen Yu return -1; 282*a24b53e0SWenzhen Yu *(int *)priv = AP_MDSRC_REQ_MD_26M_SETTLE; 283*a24b53e0SWenzhen Yu } else if (type == PLAT_AP_GPUEB_PLL_CONTROL) { 284*a24b53e0SWenzhen Yu spm_ap_gpueb_pll_control(set); 285*a24b53e0SWenzhen Yu } else if (type == PLAT_AP_GPUEB_PWR_STATUS) { 286*a24b53e0SWenzhen Yu if (!priv) 287*a24b53e0SWenzhen Yu return -1; 288*a24b53e0SWenzhen Yu *(uint32_t *)priv = spm_ap_gpueb_get_pwr_status(); 289*a24b53e0SWenzhen Yu } else if (type == PLAT_AP_GPUEB_MFG0_PWR_CON) { 290*a24b53e0SWenzhen Yu if (!priv) 291*a24b53e0SWenzhen Yu return -1; 292*a24b53e0SWenzhen Yu *(uint32_t *)priv = spm_ap_gpueb_get_mfg0_pwr_con(); 293*a24b53e0SWenzhen Yu } else if (type == PLAT_AP_SPM_RESOURCE_REQUEST_UPDATE) { 294*a24b53e0SWenzhen Yu struct spm_lp_scen *spmlp = NULL; 295*a24b53e0SWenzhen Yu 296*a24b53e0SWenzhen Yu #ifdef MT_SPM_COMMON_SODI_SUPPORT 297*a24b53e0SWenzhen Yu mt_spm_common_sodi_get_spm_lp(&spmlp); 298*a24b53e0SWenzhen Yu #else 299*a24b53e0SWenzhen Yu #if defined(MT_SPM_FEATURE_SUPPORT) 300*a24b53e0SWenzhen Yu mt_spm_idle_generic_get_spm_lp(&spmlp); 301*a24b53e0SWenzhen Yu #endif 302*a24b53e0SWenzhen Yu #endif 303*a24b53e0SWenzhen Yu if (!spmlp) 304*a24b53e0SWenzhen Yu return -1; 305*a24b53e0SWenzhen Yu __spm_set_power_control(spmlp->pwrctrl, *(uint32_t *)priv); 306*a24b53e0SWenzhen Yu ret = __spm_wait_spm_request_ack(*(uint32_t *)priv, 307*a24b53e0SWenzhen Yu SPM_ACK_TIMEOUT_US); 308*a24b53e0SWenzhen Yu } else if (type == PLAT_AP_SPM_WDT_TRIGGER) { 309*a24b53e0SWenzhen Yu mmio_write_32(PCM_WDT_VAL, 0x1); 310*a24b53e0SWenzhen Yu mmio_setbits_32(PCM_CON1, SPM_REGWR_CFG_KEY | 311*a24b53e0SWenzhen Yu REG_PCM_WDT_EN_LSB | REG_PCM_WDT_WAKE_LSB); 312*a24b53e0SWenzhen Yu } else { 313*a24b53e0SWenzhen Yu /* Not supported type */ 314*a24b53e0SWenzhen Yu return -1; 315*a24b53e0SWenzhen Yu } 316*a24b53e0SWenzhen Yu 317*a24b53e0SWenzhen Yu return ret; 318*a24b53e0SWenzhen Yu } 319*a24b53e0SWenzhen Yu 320*a24b53e0SWenzhen Yu #ifndef MTK_PLAT_SPM_UNSUPPORT 321*a24b53e0SWenzhen Yu struct mt_resource_manager plat_mt8196_rm = { 322*a24b53e0SWenzhen Yu .update = NULL, 323*a24b53e0SWenzhen Yu .hwctrl = mt_spm_hwctrl, 324*a24b53e0SWenzhen Yu .consts = plat_constraints, 325*a24b53e0SWenzhen Yu }; 326*a24b53e0SWenzhen Yu #else 327*a24b53e0SWenzhen Yu struct mt_resource_manager plat_mt8196_rm = { 328*a24b53e0SWenzhen Yu .hwctrl = mt_spm_hwctrl, 329*a24b53e0SWenzhen Yu }; 330*a24b53e0SWenzhen Yu #endif 331*a24b53e0SWenzhen Yu 332*a24b53e0SWenzhen Yu /* Determine for spm sw resource user */ 333*a24b53e0SWenzhen Yu static struct mt_lp_resource_user spm_res_user; 334*a24b53e0SWenzhen Yu 335*a24b53e0SWenzhen Yu struct mt_lp_resource_user *get_spm_res_user(void) 336*a24b53e0SWenzhen Yu { 337*a24b53e0SWenzhen Yu return &spm_res_user; 338*a24b53e0SWenzhen Yu } 339*a24b53e0SWenzhen Yu 340*a24b53e0SWenzhen Yu #ifdef MT_SPM_COMMON_SODI_SUPPORT 341*a24b53e0SWenzhen Yu int mt_spm_common_sodi_get_spm_pcm_flag(uint32_t *lp, uint32_t idx) 342*a24b53e0SWenzhen Yu { 343*a24b53e0SWenzhen Yu struct spm_lp_scen *spmlp; 344*a24b53e0SWenzhen Yu struct pwr_ctrl *pwrctrl; 345*a24b53e0SWenzhen Yu 346*a24b53e0SWenzhen Yu mt_spm_common_sodi_get_spm_lp(&spmlp); 347*a24b53e0SWenzhen Yu 348*a24b53e0SWenzhen Yu pwrctrl = spmlp->pwrctrl; 349*a24b53e0SWenzhen Yu 350*a24b53e0SWenzhen Yu if (!lp || idx > 1) 351*a24b53e0SWenzhen Yu return -1; 352*a24b53e0SWenzhen Yu 353*a24b53e0SWenzhen Yu switch (idx) { 354*a24b53e0SWenzhen Yu case 0: 355*a24b53e0SWenzhen Yu *lp = pwrctrl->pcm_flags; 356*a24b53e0SWenzhen Yu break; 357*a24b53e0SWenzhen Yu case 1: 358*a24b53e0SWenzhen Yu *lp = pwrctrl->pcm_flags; 359*a24b53e0SWenzhen Yu break; 360*a24b53e0SWenzhen Yu default: 361*a24b53e0SWenzhen Yu return -1; 362*a24b53e0SWenzhen Yu } 363*a24b53e0SWenzhen Yu return 0; 364*a24b53e0SWenzhen Yu } 365*a24b53e0SWenzhen Yu 366*a24b53e0SWenzhen Yu void mt_spm_common_sodi_en(bool en) 367*a24b53e0SWenzhen Yu { 368*a24b53e0SWenzhen Yu struct spm_lp_scen *spmlp; 369*a24b53e0SWenzhen Yu struct pwr_ctrl *pwrctrl; 370*a24b53e0SWenzhen Yu 371*a24b53e0SWenzhen Yu mt_spm_common_sodi_get_spm_lp(&spmlp); 372*a24b53e0SWenzhen Yu pwrctrl = spmlp->pwrctrl; 373*a24b53e0SWenzhen Yu #if defined(CONFIG_MTK_VCOREDVFS_SUPPORT) 374*a24b53e0SWenzhen Yu __spm_sync_vcore_dvfs_pcm_flags(&pwrctrl->pcm_flags, 375*a24b53e0SWenzhen Yu &__spm_vcorefs.pwrctrl->pcm_flags); 376*a24b53e0SWenzhen Yu #endif 377*a24b53e0SWenzhen Yu if (en) 378*a24b53e0SWenzhen Yu pwrctrl->pcm_flags |= SPM_FLAG_ENABLE_COMMON_SODI5; 379*a24b53e0SWenzhen Yu else 380*a24b53e0SWenzhen Yu pwrctrl->pcm_flags &= (~SPM_FLAG_ENABLE_COMMON_SODI5); 381*a24b53e0SWenzhen Yu 382*a24b53e0SWenzhen Yu /* Set PCM flags */ 383*a24b53e0SWenzhen Yu __spm_set_pcm_flags(pwrctrl); 384*a24b53e0SWenzhen Yu 385*a24b53e0SWenzhen Yu __spm_send_cpu_wakeup_event(); 386*a24b53e0SWenzhen Yu } 387*a24b53e0SWenzhen Yu 388*a24b53e0SWenzhen Yu int mt_spm_common_sodi_get_spm_lp(struct spm_lp_scen **lp) 389*a24b53e0SWenzhen Yu { 390*a24b53e0SWenzhen Yu if (!lp) 391*a24b53e0SWenzhen Yu return -1; 392*a24b53e0SWenzhen Yu 393*a24b53e0SWenzhen Yu *lp = &__spm_common_sodi; 394*a24b53e0SWenzhen Yu return 0; 395*a24b53e0SWenzhen Yu } 396*a24b53e0SWenzhen Yu 397*a24b53e0SWenzhen Yu void mt_spm_set_common_sodi_pwrctr(void) 398*a24b53e0SWenzhen Yu { 399*a24b53e0SWenzhen Yu struct resource_req_status common_sodi_spm_resource_req = { 400*a24b53e0SWenzhen Yu .id = MT_LP_RQ_ID_ALL_USAGE, 401*a24b53e0SWenzhen Yu .val = 0, 402*a24b53e0SWenzhen Yu }; 403*a24b53e0SWenzhen Yu struct spm_lp_scen *spmlp; 404*a24b53e0SWenzhen Yu 405*a24b53e0SWenzhen Yu mt_lp_rq_get_status(PLAT_RQ_REQ_USAGE, 406*a24b53e0SWenzhen Yu &common_sodi_spm_resource_req); 407*a24b53e0SWenzhen Yu mt_spm_common_sodi_get_spm_lp(&spmlp); 408*a24b53e0SWenzhen Yu 409*a24b53e0SWenzhen Yu __spm_set_power_control(spmlp->pwrctrl, 410*a24b53e0SWenzhen Yu common_sodi_spm_resource_req.val); 411*a24b53e0SWenzhen Yu } 412*a24b53e0SWenzhen Yu 413*a24b53e0SWenzhen Yu void mt_spm_set_common_sodi_pcm_flags(void) 414*a24b53e0SWenzhen Yu { 415*a24b53e0SWenzhen Yu struct spm_lp_scen *spmlp; 416*a24b53e0SWenzhen Yu struct pwr_ctrl *pwrctrl; 417*a24b53e0SWenzhen Yu 418*a24b53e0SWenzhen Yu mt_spm_common_sodi_get_spm_lp(&spmlp); 419*a24b53e0SWenzhen Yu pwrctrl = spmlp->pwrctrl; 420*a24b53e0SWenzhen Yu #if defined(CONFIG_MTK_VCOREDVFS_SUPPORT) 421*a24b53e0SWenzhen Yu /* Set PCM flags */ 422*a24b53e0SWenzhen Yu __spm_sync_vcore_dvfs_pcm_flags(&pwrctrl->pcm_flags, 423*a24b53e0SWenzhen Yu &__spm_vcorefs.pwrctrl->pcm_flags); 424*a24b53e0SWenzhen Yu #endif 425*a24b53e0SWenzhen Yu __spm_set_pcm_flags(pwrctrl); 426*a24b53e0SWenzhen Yu 427*a24b53e0SWenzhen Yu __spm_send_cpu_wakeup_event(); 428*a24b53e0SWenzhen Yu 429*a24b53e0SWenzhen Yu } 430*a24b53e0SWenzhen Yu #endif 431*a24b53e0SWenzhen Yu 432*a24b53e0SWenzhen Yu static void spm_gpio_init(void) 433*a24b53e0SWenzhen Yu { 434*a24b53e0SWenzhen Yu gpio_set_direction(EC_SUSPEND_PIN, GPIO_DIR_OUT); 435*a24b53e0SWenzhen Yu gpio_set_value(EC_SUSPEND_PIN, GPIO_LEVEL_HIGH); 436*a24b53e0SWenzhen Yu } 437*a24b53e0SWenzhen Yu 438*a24b53e0SWenzhen Yu int spm_boot_init(void) 439*a24b53e0SWenzhen Yu { 440*a24b53e0SWenzhen Yu plat_spm_lock_init(); 441*a24b53e0SWenzhen Yu 442*a24b53e0SWenzhen Yu #if defined(MT_SPM_FEATURE_SUPPORT) 443*a24b53e0SWenzhen Yu plat_spm_pmic_wrap_init(); 444*a24b53e0SWenzhen Yu #endif 445*a24b53e0SWenzhen Yu mt_lp_rm_register(&plat_mt8196_rm); 446*a24b53e0SWenzhen Yu 447*a24b53e0SWenzhen Yu #ifndef MTK_PLAT_SPM_UNSUPPORT 448*a24b53e0SWenzhen Yu mt_lp_resource_request_manager_register(&plat_mt8196_rq); 449*a24b53e0SWenzhen Yu mt_lp_resource_user_register("SPM", &spm_res_user); 450*a24b53e0SWenzhen Yu mt_spm_dispatcher_init(); 451*a24b53e0SWenzhen Yu #endif 452*a24b53e0SWenzhen Yu #if defined(MT_SPM_FEATURE_SUPPORT) 453*a24b53e0SWenzhen Yu spm_hwreq_init(); 454*a24b53e0SWenzhen Yu #endif 455*a24b53e0SWenzhen Yu spm_gpio_init(); 456*a24b53e0SWenzhen Yu 457*a24b53e0SWenzhen Yu spm_irq_num = 0xFFFFFFFF; 458*a24b53e0SWenzhen Yu 459*a24b53e0SWenzhen Yu INFO("[%s:%d] - spm finished, version = %u, PC = 0x%x\n", 460*a24b53e0SWenzhen Yu __func__, __LINE__, 461*a24b53e0SWenzhen Yu mt_spm_version, mmio_read_32(MD32PCM_PC)); 462*a24b53e0SWenzhen Yu return 0; 463*a24b53e0SWenzhen Yu } 464*a24b53e0SWenzhen Yu MTK_PLAT_SETUP_1_INIT(spm_boot_init); 465