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
mt_spm_pcm_wdt(int enable,uint64_t time)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
mt_spm_phypll_mode_check(void)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
mt_spm_compatible_smc_id(uint64_t lp_id)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
mt_spm_dispatcher(u_register_t lp_id,u_register_t act,u_register_t arg1,u_register_t arg2,void * handle,struct smccc_res * smccc_ret)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
mt_spm_dispatcher_init(void)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