xref: /rk3399_ARM-atf/plat/mediatek/drivers/spm/mt8189/mt_spm.c (revision 05d22c3045e2e972c2262b9ccd6c82cb7545bf83)
1 /*
2  * Copyright (c) 2025, Mediatek Inc. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <stddef.h>
9 #include <stdio.h>
10 #include <string.h>
11 
12 #include <arch.h>
13 #include <common/debug.h>
14 #include <drivers/console.h>
15 #include <lib/bakery_lock.h>
16 #include <lib/mmio.h>
17 #include <lib/utils_def.h>
18 
19 #include <constraints/mt_spm_rc_api.h>
20 #include <constraints/mt_spm_rc_internal.h>
21 #include <drivers/spm/mt_spm_resource_req.h>
22 #include <lib/mtk_init/mtk_init.h>
23 #include <lib/pm/mtk_pm.h>
24 #include <lpm_v2/mt_lp_rm.h>
25 #include <lpm_v2/mt_lp_rqm.h>
26 #include <lpm_v2/mt_lpm_smc.h>
27 #include <mt_cirq.h>
28 #include <mt_gic_v3.h>
29 #include <mt_plat_spm_setting.h>
30 #include <mt_spm.h>
31 #include <mt_spm_common.h>
32 #include <mt_spm_conservation.h>
33 #include <mt_spm_constraint.h>
34 #include <mt_spm_dispatcher.h>
35 #include <mt_spm_hwreq.h>
36 #include <mt_spm_idle.h>
37 #include <mt_spm_internal.h>
38 #include <mt_spm_reg.h>
39 #include <mt_spm_suspend.h>
40 #include <mtk_mmap_pool.h>
41 #include <platform_def.h>
42 #include <sleep_def.h>
43 
44 #ifdef MT_SPM_USING_BAKERY_LOCK
45 DEFINE_BAKERY_LOCK(spm_lock);
46 #define plat_spm_lock_init() bakery_lock_init(&spm_lock)
47 #else
48 spinlock_t spm_lock;
49 #define plat_spm_lock_init()
50 #endif
51 
52 static uint32_t spm_irq_num;
53 
54 void spm_set_sysclk_settle(void)
55 {
56 	uint32_t settle;
57 
58 	mmio_write_32(SPM_CLK_SETTLE, SPM_SYSCLK_SETTLE);
59 	settle = mmio_read_32(SPM_CLK_SETTLE);
60 
61 	INFO("md_settle = %u, settle = %u\n", SPM_SYSCLK_SETTLE, settle);
62 }
63 
64 void spm_set_irq_num(uint32_t num)
65 {
66 	spm_irq_num = num;
67 }
68 
69 void spm_irq0_handler(uint64_t x1, uint64_t x2)
70 {
71 	if (x2 == 0) {
72 		mmio_setbits_32(SPM_IRQ_MASK, ISRM_ALL_EXC_TWAM);
73 		mmio_write_32(SPM_IRQ_STA, x1);
74 		mmio_write_32(SPM_SWINT_CLR, PCM_SW_INT0);
75 	}
76 }
77 
78 static int spm_ap_mdsrc_ack(void)
79 {
80 	int ack, md_state = 0;
81 
82 	/* Check ap_mdsrc_ack = 1'b1, for md internal resource on ack */
83 	ack = !!(mmio_read_32(AP_MDSRC_REQ) & AP_MDSMSRC_ACK_LSB);
84 
85 	if (!ack) {
86 		/* Check md_apsrc_req = 1'b0, for md state 0:sleep, 1:wakeup */
87 		md_state = !!(mmio_read_32(SPM_REQ_STA_9) & MD_APSRC_REQ_LSB);
88 
89 		ERROR("[SPM] error: md_sleep = %d\n", md_state);
90 		ERROR("%s can not get AP_MDSRC_ACK\n", __func__);
91 		return -1;
92 	}
93 	return 0;
94 }
95 
96 static void spm_ap_mdsrc_req(int set)
97 {
98 	spm_lock_get();
99 
100 	if (set)
101 		mmio_setbits_32(AP_MDSRC_REQ, AP_MDSMSRC_REQ_LSB);
102 	else
103 		mmio_clrbits_32(AP_MDSRC_REQ, AP_MDSMSRC_REQ_LSB);
104 
105 	spm_lock_release();
106 }
107 
108 static int spm_is_md_sleep(void *priv)
109 {
110 	int md_state = 0;
111 	int *sleep = (int *)priv;
112 
113 	if (!priv)
114 		return -1;
115 
116 	/* Check md_apsrc_req = 1'b0, for md state 0:sleep, 1:wakeup */
117 	md_state = !!(mmio_read_32(SPM_REQ_STA_9) & MD_APSRC_REQ_LSB);
118 
119 	if (md_state == 0)
120 		*sleep = 1;
121 	else
122 		*sleep = 0;
123 
124 	return 0;
125 }
126 
127 static void spm_ap_gpueb_pll_control(int set)
128 {
129 	spm_lock_get();
130 
131 	if (set)
132 		mmio_setbits_32(SPM2GPUPM_CON, SC_MFG_PLL_EN_LSB);
133 	else
134 		mmio_clrbits_32(SPM2GPUPM_CON, SC_MFG_PLL_EN_LSB);
135 
136 	spm_lock_release();
137 }
138 
139 static uint32_t spm_ap_gpueb_get_pwr_status(void)
140 {
141 	uint32_t ret;
142 
143 	ret = mmio_read_32(XPU_PWR_STATUS);
144 
145 	return ret;
146 }
147 
148 static uint32_t spm_ap_gpueb_get_mfg0_pwr_con(void)
149 {
150 	uint32_t ret;
151 
152 	ret = mmio_read_32(MFG0_PWR_CON);
153 
154 	return ret;
155 }
156 
157 #ifndef MTK_PLAT_SPM_UNSUPPORT
158 struct mt_lp_res_req rq_xo_fpm = {
159 	.res_id = MT_LP_RQ_XO_FPM,
160 	.res_rq = MT_SPM_XO_FPM,
161 	.res_usage = 0,
162 };
163 
164 struct mt_lp_res_req rq_26m = {
165 	.res_id = MT_LP_RQ_26M,
166 	.res_rq = MT_SPM_26M,
167 	.res_usage = 0,
168 };
169 
170 struct mt_lp_res_req rq_infra = {
171 	.res_id = MT_LP_RQ_INFRA,
172 	.res_rq = MT_SPM_INFRA,
173 	.res_usage = 0,
174 };
175 
176 struct mt_lp_res_req rq_syspll = {
177 	.res_id = MT_LP_RQ_SYSPLL,
178 	.res_rq = MT_SPM_SYSPLL,
179 	.res_usage = 0,
180 };
181 
182 struct mt_lp_res_req rq_dram_s0 = {
183 	.res_id = MT_LP_RQ_DRAM,
184 	.res_rq = MT_SPM_DRAM_S0,
185 	.res_usage = 0,
186 };
187 
188 struct mt_lp_res_req rq_dram_s1 = {
189 	.res_id = MT_LP_RQ_DRAM,
190 	.res_rq = MT_SPM_DRAM_S1,
191 	.res_usage = 0,
192 };
193 
194 struct mt_lp_res_req rq_vcore = {
195 	.res_id = MT_LP_RQ_VCORE,
196 	.res_rq = MT_SPM_VCORE,
197 	.res_usage = 0,
198 };
199 
200 struct mt_lp_res_req rq_emi = {
201 	.res_id = MT_LP_RQ_EMI,
202 	.res_rq = MT_SPM_EMI,
203 	.res_usage = 0,
204 };
205 
206 struct mt_lp_res_req rq_pmic = {
207 	.res_id = MT_LP_RQ_PMIC,
208 	.res_rq = MT_SPM_PMIC,
209 	.res_usage = 0,
210 };
211 
212 struct mt_lp_res_req *spm_resources[] = {
213 	&rq_xo_fpm,  &rq_26m,	&rq_infra, &rq_syspll, &rq_dram_s0,
214 	&rq_dram_s1, &rq_vcore, &rq_emi,   &rq_pmic,   NULL,
215 };
216 
217 struct mt_resource_req_manager plat_mt8189_rq = {
218 	.res = spm_resources,
219 };
220 
221 struct mt_resource_constraint plat_constraint_vcore = {
222 	.is_valid = spm_is_valid_rc_vcore,
223 	.update = spm_update_rc_vcore,
224 	.allow = spm_allow_rc_vcore,
225 	.run = spm_run_rc_vcore,
226 	.reset = spm_reset_rc_vcore,
227 	.get_status = spm_get_status_rc_vcore,
228 };
229 
230 struct mt_resource_constraint plat_constraint_bus26m = {
231 	.is_valid = spm_is_valid_rc_bus26m,
232 	.update = spm_update_rc_bus26m,
233 	.allow = spm_allow_rc_bus26m,
234 	.run = spm_run_rc_bus26m,
235 	.reset = spm_reset_rc_bus26m,
236 	.get_status = spm_get_status_rc_bus26m,
237 };
238 struct mt_resource_constraint plat_constraint_syspll = {
239 	.is_valid = spm_is_valid_rc_syspll,
240 	.update = spm_update_rc_syspll,
241 	.allow = spm_allow_rc_syspll,
242 	.run = spm_run_rc_syspll,
243 	.reset = spm_reset_rc_syspll,
244 	.get_status = spm_get_status_rc_syspll,
245 };
246 
247 struct mt_resource_constraint *plat_constraints[] = {
248 	&plat_constraint_vcore,
249 	&plat_constraint_bus26m,
250 	&plat_constraint_syspll,
251 	NULL,
252 };
253 #endif
254 
255 int mt_spm_hwctrl(uint32_t type, int set, void *priv)
256 {
257 	int ret = 0;
258 
259 	switch (type) {
260 	case PLAT_AP_MDSRC_REQ:
261 		spm_ap_mdsrc_req(set);
262 		break;
263 	case PLAT_AP_MDSRC_ACK:
264 		ret = spm_ap_mdsrc_ack();
265 		break;
266 	case PLAT_AP_IS_MD_SLEEP:
267 		ret = spm_is_md_sleep(priv);
268 		break;
269 	case PLAT_AP_MDSRC_SETTLE:
270 		if (!priv)
271 			return -1;
272 		*(int *)priv = AP_MDSRC_REQ_MD_26M_SETTLE;
273 		break;
274 	case PLAT_AP_GPUEB_PLL_CONTROL:
275 		spm_ap_gpueb_pll_control(set);
276 		break;
277 	case PLAT_AP_GPUEB_PWR_STATUS:
278 		if (!priv)
279 			return -1;
280 		*(uint32_t *)priv = spm_ap_gpueb_get_pwr_status();
281 		break;
282 	case PLAT_AP_GPUEB_MFG0_PWR_CON:
283 		if (!priv)
284 			return -1;
285 		*(uint32_t *)priv = spm_ap_gpueb_get_mfg0_pwr_con();
286 		break;
287 	case PLAT_AP_ASSERT_SPM_IRQ:
288 		mt_irq_set_pending(spm_irq_num);
289 		break;
290 	case PLAT_AP_SPM_RESOURCE_REQUEST_UPDATE:
291 		struct spm_lp_scen *spmlp;
292 
293 #if defined(MT_SPM_FEATURE_SUPPORT)
294 		mt_spm_idle_generic_get_spm_lp(&spmlp);
295 #endif
296 		if (!spmlp)
297 			return -1;
298 		__spm_set_power_control(spmlp->pwrctrl, *(uint32_t *)priv);
299 		ret = __spm_wait_spm_request_ack(*(uint32_t *)priv, SPM_ACK_TIMEOUT_US);
300 		break;
301 	default:
302 		/* not supported type */
303 		ret = -1;
304 		break;
305 	}
306 
307 	return ret;
308 }
309 
310 #ifndef MTK_PLAT_SPM_UNSUPPORT
311 struct mt_resource_manager plat_mt8189_rm = {
312 	.update = NULL,
313 	.hwctrl = mt_spm_hwctrl,
314 	.consts = plat_constraints,
315 };
316 #else
317 struct mt_resource_manager plat_mt8189_rm = {
318 	.hwctrl = mt_spm_hwctrl,
319 };
320 #endif
321 
322 /* Determine for spm sw resource user */
323 static struct mt_lp_resource_user spm_res_user;
324 
325 struct mt_lp_resource_user *get_spm_res_user(void)
326 {
327 	return &spm_res_user;
328 }
329 
330 int spm_boot_init(void)
331 {
332 	plat_spm_lock_init();
333 
334 #if defined(MT_SPM_FEATURE_SUPPORT)
335 	plat_spm_pmic_wrap_init();
336 #endif
337 	plat_spm_cond_init();
338 
339 	mt_lp_rm_register(&plat_mt8189_rm);
340 
341 /* If spm service won't run when spm not ready */
342 #ifndef MTK_PLAT_SPM_UNSUPPORT
343 	mt_lp_resource_request_manager_register(&plat_mt8189_rq);
344 	mt_lp_resource_user_register("SPM", &spm_res_user);
345 	mt_spm_dispatcher_init();
346 #endif
347 #if defined(MT_SPM_FEATURE_SUPPORT)
348 	spm_hwreq_init();
349 #endif
350 
351 	INFO("[%s:%d] - spm finished\n", __func__, __LINE__);
352 	return 0;
353 }
354 MTK_ARCH_INIT(spm_boot_init);
355