xref: /rk3399_ARM-atf/plat/mediatek/drivers/spm/mt8196/mt_spm.c (revision 0715f858b69e629ac8abf36c5e9f15de5cac4c6e)
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 
spm_set_sysclk_settle(void)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 
spm_set_irq_num(uint32_t num)65a24b53e0SWenzhen Yu void spm_set_irq_num(uint32_t num)
66a24b53e0SWenzhen Yu {
67a24b53e0SWenzhen Yu 	spm_irq_num = num;
68a24b53e0SWenzhen Yu }
69a24b53e0SWenzhen Yu 
spm_irq0_handler(uint64_t x1,uint64_t x2)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 
spm_ap_mdsrc_ack(void)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 
spm_ap_mdsrc_req(int set)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 
spm_is_md_sleep(void * priv)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 
spm_ap_gpueb_pll_control(int set)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 
spm_ap_gpueb_get_pwr_status(void)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 
spm_ap_gpueb_get_mfg0_pwr_con(void)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 
mt_spm_hwctrl(uint32_t type,int set,void * priv)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 
get_spm_res_user(void)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
mt_spm_common_sodi_get_spm_pcm_flag(uint32_t * lp,uint32_t idx)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 
mt_spm_common_sodi_en(bool en)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 
mt_spm_common_sodi_get_spm_lp(struct spm_lp_scen ** lp)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 
mt_spm_set_common_sodi_pwrctr(void)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 
mt_spm_set_common_sodi_pcm_flags(void)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 
spm_boot_init(void)430a24b53e0SWenzhen Yu int spm_boot_init(void)
431a24b53e0SWenzhen Yu {
432a24b53e0SWenzhen Yu 	plat_spm_lock_init();
433a24b53e0SWenzhen Yu 
434a24b53e0SWenzhen Yu #if defined(MT_SPM_FEATURE_SUPPORT)
435a24b53e0SWenzhen Yu 	plat_spm_pmic_wrap_init();
436a24b53e0SWenzhen Yu #endif
437a24b53e0SWenzhen Yu 	mt_lp_rm_register(&plat_mt8196_rm);
438a24b53e0SWenzhen Yu 
439a24b53e0SWenzhen Yu #ifndef MTK_PLAT_SPM_UNSUPPORT
440a24b53e0SWenzhen Yu 	mt_lp_resource_request_manager_register(&plat_mt8196_rq);
441a24b53e0SWenzhen Yu 	mt_lp_resource_user_register("SPM", &spm_res_user);
442a24b53e0SWenzhen Yu 	mt_spm_dispatcher_init();
443a24b53e0SWenzhen Yu #endif
444a24b53e0SWenzhen Yu #if defined(MT_SPM_FEATURE_SUPPORT)
445a24b53e0SWenzhen Yu 	spm_hwreq_init();
446a24b53e0SWenzhen Yu #endif
447a24b53e0SWenzhen Yu 	spm_irq_num = 0xFFFFFFFF;
448a24b53e0SWenzhen Yu 
449*ee2e99c3SWenzhen Yu 	INFO("[%s], PC = 0x%x\n", __func__, mmio_read_32(MD32PCM_PC));
450a24b53e0SWenzhen Yu 	return 0;
451a24b53e0SWenzhen Yu }
452a24b53e0SWenzhen Yu MTK_PLAT_SETUP_1_INIT(spm_boot_init);
453