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