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