1*532ac057SKun Lu /* 2*532ac057SKun Lu * Copyright (c) 2025, Mediatek Inc. All rights reserved. 3*532ac057SKun Lu * 4*532ac057SKun Lu * SPDX-License-Identifier: BSD-3-Clause 5*532ac057SKun Lu */ 6*532ac057SKun Lu 7*532ac057SKun Lu #include <lib/mmio.h> 8*532ac057SKun Lu #include <platform_def.h> 9*532ac057SKun Lu 10*532ac057SKun Lu #include <lpm_v2/mt_lpm_dispatch.h> 11*532ac057SKun Lu #include <lpm_v2/mt_lpm_smc.h> 12*532ac057SKun Lu #include <mt_spm_conservation.h> 13*532ac057SKun Lu #include <mt_spm_dispatcher.h> 14*532ac057SKun Lu #include <mt_spm_internal.h> 15*532ac057SKun Lu #include <mt_spm_reg.h> 16*532ac057SKun Lu #include <mt_spm_smc.h> 17*532ac057SKun Lu #include <mt_spm_suspend.h> 18*532ac057SKun Lu #include <pcm_def.h> 19*532ac057SKun Lu 20*532ac057SKun Lu #define SPM_FW_BASE_SIZE 0x100000 21*532ac057SKun Lu 22*532ac057SKun Lu static void mt_spm_pcm_wdt(int enable, uint64_t time) 23*532ac057SKun Lu { 24*532ac057SKun Lu mmio_write_32(PCM_TIMER_VAL, time); 25*532ac057SKun Lu __spm_set_pcm_wdt(enable); 26*532ac057SKun Lu } 27*532ac057SKun Lu 28*532ac057SKun Lu static uint32_t mt_spm_phypll_mode_check(void) 29*532ac057SKun Lu { 30*532ac057SKun Lu uint32_t val = mmio_read_32(SPM_POWER_ON_VAL0); 31*532ac057SKun Lu 32*532ac057SKun Lu return val; 33*532ac057SKun Lu } 34*532ac057SKun Lu 35*532ac057SKun Lu static uint64_t mt_spm_compatible_smc_id(uint64_t lp_id) 36*532ac057SKun Lu { 37*532ac057SKun Lu switch (lp_id) { 38*532ac057SKun Lu case MT_LPM_SPMC_COMPAT_LK_FW_INIT: 39*532ac057SKun Lu lp_id = MT_SPM_SMC_UID_FW_INIT; 40*532ac057SKun Lu break; 41*532ac057SKun Lu default: 42*532ac057SKun Lu break; 43*532ac057SKun Lu } 44*532ac057SKun Lu return lp_id; 45*532ac057SKun Lu } 46*532ac057SKun Lu 47*532ac057SKun Lu uint64_t mt_spm_dispatcher(u_register_t lp_id, u_register_t act, 48*532ac057SKun Lu u_register_t arg1, u_register_t arg2, 49*532ac057SKun Lu void *handle, struct smccc_res *smccc_ret) 50*532ac057SKun Lu { 51*532ac057SKun Lu uint64_t ret = 0; 52*532ac057SKun Lu 53*532ac057SKun Lu if (act & MT_LPM_SMC_ACT_COMPAT) { 54*532ac057SKun Lu lp_id = mt_spm_compatible_smc_id(lp_id); 55*532ac057SKun Lu act &= ~(MT_LPM_SMC_ACT_COMPAT); 56*532ac057SKun Lu } 57*532ac057SKun Lu 58*532ac057SKun Lu switch (lp_id) { 59*532ac057SKun Lu case MT_SPM_SMC_UID_STATUS: 60*532ac057SKun Lu if (!(arg2 & MT_SPM_STATUS_SUSPEND_SLEEP)) 61*532ac057SKun Lu break; 62*532ac057SKun Lu if (act & MT_LPM_SMC_ACT_SET) 63*532ac057SKun Lu /* Legacy audio check from kernel */ 64*532ac057SKun Lu mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SLEEP, NULL); 65*532ac057SKun Lu else if (act & MT_LPM_SMC_ACT_CLR) 66*532ac057SKun Lu mt_spm_suspend_mode_set(MT_SPM_SUSPEND_SYSTEM_PDN, 67*532ac057SKun Lu NULL); 68*532ac057SKun Lu break; 69*532ac057SKun Lu case MT_SPM_SMC_UID_PCM_WDT: 70*532ac057SKun Lu if (act & MT_LPM_SMC_ACT_SET) 71*532ac057SKun Lu mt_spm_pcm_wdt(1, arg2); 72*532ac057SKun Lu else if (act & MT_LPM_SMC_ACT_CLR) 73*532ac057SKun Lu mt_spm_pcm_wdt(0, arg2); 74*532ac057SKun Lu break; 75*532ac057SKun Lu case MT_SPM_SMC_UID_PHYPLL_MODE: 76*532ac057SKun Lu if (act & MT_LPM_SMC_ACT_GET) 77*532ac057SKun Lu ret = mt_spm_phypll_mode_check(); 78*532ac057SKun Lu break; 79*532ac057SKun Lu case MT_SPM_SMC_UID_SET_PENDING_IRQ_INIT: 80*532ac057SKun Lu spm_set_irq_num((uint32_t)arg1); 81*532ac057SKun Lu break; 82*532ac057SKun Lu default: 83*532ac057SKun Lu break; 84*532ac057SKun Lu } 85*532ac057SKun Lu return ret; 86*532ac057SKun Lu } 87*532ac057SKun Lu 88*532ac057SKun Lu int mt_spm_dispatcher_init(void) 89*532ac057SKun Lu { 90*532ac057SKun Lu mt_lpm_dispatcher_registry(MT_LPM_SMC_USER_SPM, 91*532ac057SKun Lu mt_spm_dispatcher); 92*532ac057SKun Lu return 0; 93*532ac057SKun Lu } 94