xref: /rk3399_ARM-atf/plat/mediatek/drivers/spm/mt8196/mt_spm.c (revision a24b53e0e581cde7b5c43607ab76ded8336dc353)
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