xref: /rk3399_ARM-atf/plat/mediatek/drivers/spm/mt8196/mt_vcore_dvfsrc_plat.c (revision cf2df874cd09305ac7282fadb0fef6be597dfffb)
1 /*
2  * Copyright (c) 2025, MediaTek Inc. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <errno.h>
8 
9 #include <common/debug.h>
10 #include <drivers/delay_timer.h>
11 #include <lib/mmio.h>
12 
13 #include <drivers/dbgtop.h>
14 #include <drivers/dramc.h>
15 #include <drivers/spmi/spmi_common.h>
16 #include <drivers/spmi_api.h>
17 #include <drivers/sramrc.h>
18 #include <lib/mtk_init/mtk_init.h>
19 #include <mt_plat_spm_setting.h>
20 #include <mt_spm.h>
21 #include <mt_spm_reg.h>
22 #include <mt_spm_vcorefs.h>
23 #include <mt_spm_vcorefs_common.h>
24 #include <mt_spm_vcorefs_ext.h>
25 #include <mt_spm_vcorefs_reg.h>
26 #include <mt_vcore_dvfsrc_plat_def.h>
27 #include <mtk_mmap_pool.h>
28 #include <mtk_sip_svc.h>
29 #include <pmic_wrap/inc/mt_spm_pmic_wrap.h>
30 #include <sleep_def.h>
31 
32 #define VCORE_SPM_INIT_PCM_FLAG	 (SPM_FLAG_RUN_COMMON_SCENARIO | \
33 				  SPM_FLAG_DISABLE_VLP_PDN)
34 
35 #define V_VB_EN			BIT(5)
36 #define V_DRM_ENABLE		BIT(31)
37 #define V_B0_EN_SHIFT		BIT(23)
38 
39 #define V_VMODE_SHIFT		0
40 #define V_VMODE_MASK		0x3
41 #define V_OPP_TYPE_SHIFT	20
42 #define V_OPP_TYPE_SHIFT_MASK	0x3
43 
44 #define DVFSRC_DISABLE_DVS	0x1
45 #define DVFSRC_DISABLE_DFS	0x2
46 
47 #define CFG_DVFSRC_BW_ASYM_ENABLE
48 
49 #ifdef MT8196_VCORE_SUPPORT
50 #define VCORE_MAX_OPP		6
51 #define DRAM_MAX_OPP		11
52 
53 #define VCORE_OPP0_UV		850000
54 #define VCORE_OPP1_UV		750000
55 #define VCORE_OPP2_UV		675000
56 #define VCORE_OPP3_UV		625000
57 #define VCORE_OPP4_UV		600000
58 
59 static unsigned int v_opp_uv[VCORE_MAX_OPP] = {
60 	VCORE_OPP0_UV,
61 	VCORE_OPP0_UV,
62 	VCORE_OPP1_UV,
63 	VCORE_OPP2_UV,
64 	VCORE_OPP3_UV,
65 	VCORE_OPP4_UV
66 };
67 
68 #else
69 #define VCORE_MAX_OPP		6
70 #define DRAM_MAX_OPP		11
71 
72 #define VCORE_OPP0_UV		875000
73 #define VCORE_OPP1_UV		825000
74 #define VCORE_OPP2_UV		725000
75 #define VCORE_OPP3_UV		650000
76 #define VCORE_OPP4_UV		600000
77 #define VCORE_OPP5_UV		575000
78 
79 static unsigned int v_opp_uv[VCORE_MAX_OPP] = {
80 	VCORE_OPP0_UV,
81 	VCORE_OPP1_UV,
82 	VCORE_OPP2_UV,
83 	VCORE_OPP3_UV,
84 	VCORE_OPP4_UV,
85 	VCORE_OPP5_UV,
86 };
87 
88 static unsigned int v_opp_df_uv[VCORE_MAX_OPP] = {
89 	VCORE_OPP0_UV,
90 	VCORE_OPP1_UV,
91 	VCORE_OPP2_UV,
92 	VCORE_OPP3_UV,
93 	VCORE_OPP4_UV,
94 	VCORE_OPP5_UV,
95 };
96 #endif
97 
98 #ifdef CONFIG_MTK_VCOREDVFS_SUPPORT
99 static int opp_type;
100 static unsigned int b0_en;
101 
v_roundup(unsigned int x,unsigned int y)102 static unsigned int v_roundup(unsigned int x, unsigned int y)
103 {
104 	return round_up(x, y);
105 }
106 
v_rounddown(unsigned int x,unsigned int y)107 static unsigned int v_rounddown(unsigned int x, unsigned int y)
108 {
109 	return round_down(x, y);
110 }
111 
spm_vcorefs_pwarp_cmd(uint64_t cmd,uint64_t val)112 static void spm_vcorefs_pwarp_cmd(uint64_t cmd, uint64_t val)
113 {
114 	if (cmd < NR_IDX_ALL)
115 		mt_spm_pmic_wrap_set_cmd(PMIC_WRAP_PHASE_ALLINONE, cmd, val);
116 	else
117 		INFO("cmd out of range!\n");
118 }
119 
dvfsrc_init(void)120 static void dvfsrc_init(void)
121 {
122 	int i;
123 	static int dvfs_enable_done;
124 
125 	if (dvfs_enable_done)
126 		return;
127 
128 	for (i = 0; i < ARRAY_SIZE(dvfsrc_init_configs); i++)
129 		mmio_write_32(dvfsrc_init_configs[i].offset,
130 			      dvfsrc_init_configs[i].val);
131 
132 #ifdef MT8196_VCORE_SUPPORT
133 		for (i = 0; i < ARRAY_SIZE(lp5_8533_init_configs_auto); i++)
134 			mmio_write_32(lp5_8533_init_configs_auto[i].offset,
135 				      lp5_8533_init_configs_auto[i].val);
136 #endif
137 
138 	if (opp_type == 2) {
139 		for (i = 0; i < ARRAY_SIZE(lp5_7500_init_configs); i++)
140 			mmio_write_32(lp5_7500_init_configs[i].offset,
141 				      lp5_7500_init_configs[i].val);
142 	} else if (opp_type == 0) {
143 		for (i = 0; i < ARRAY_SIZE(lp5_8533_init_configs); i++)
144 			mmio_write_32(lp5_8533_init_configs[i].offset,
145 				      lp5_8533_init_configs[i].val);
146 	} else if (opp_type == 3) {
147 		for (i = 0; i < ARRAY_SIZE(lp5_10677_init_configs); i++)
148 			mmio_write_32(lp5_10677_init_configs[i].offset,
149 				      lp5_10677_init_configs[i].val);
150 	}
151 #ifdef CFG_DVFSRC_BW_ASYM_ENABLE
152 	if (b0_en) {
153 		mmio_write_32(DVFSRC_LEVEL_LABEL_210_211, 0x20100000);
154 		mmio_write_32(DVFSRC_LEVEL_LABEL_212_213, 0x00504030);
155 		mmio_write_32(DVFSRC_LEVEL_LABEL_220_221, 0x00400000);
156 		mmio_write_32(DVFSRC_LEVEL_LABEL_224_225, 0x00000050);
157 		mmio_write_32(DVFSRC_LEVEL_LABEL_226_227, 0x00300000);
158 		mmio_write_32(DVFSRC_LEVEL_LABEL_252_253, 0x000040F5);
159 		mmio_write_32(DVFSRC_LEVEL_LABEL_248_249, 0x30450000);
160 		mmio_write_32(DVFSRC_LEVEL_LABEL_246_247, 0x00002065);
161 		mmio_write_32(DVFSRC_LEVEL_LABEL_242_243, 0x10960000);
162 		mmio_write_32(DVFSRC_LEVEL_LABEL_202_203, 0x00010040);
163 		mmio_write_32(DVFSRC_LEVEL_LABEL_200_201, 0xE0420030);
164 	}
165 #endif
166 
167 	mmio_write_32(DVFSRC_SW_REQ4, 0x00000030);
168 	/* ENABLE */
169 	mmio_write_32(DVFSRC_CURRENT_FORCE_4, 0x00000001);
170 #ifdef MT8196_VCORE_SUPPORT
171 	mmio_write_32(DVFSRC_BASIC_CONTROL, 0xD460213B);
172 	mmio_write_32(DVFSRC_BASIC_CONTROL, 0xD46001BB);
173 #else
174 	mmio_write_32(DVFSRC_BASIC_CONTROL, 0xD560213B);
175 	mmio_write_32(DVFSRC_BASIC_CONTROL, 0xD56001BB);
176 #endif
177 	mmio_write_32(DVFSRC_CURRENT_FORCE_4, 0x00000000);
178 
179 #ifdef CONFIG_MTK_DBGTOP
180 	mtk_dbgtop_cfg_dvfsrc(1);
181 #endif
182 	dvfs_enable_done = 1;
183 }
184 
spm_vcorefs_vcore_setting(void)185 static void spm_vcorefs_vcore_setting(void)
186 {
187 	int i;
188 	uint32_t dvfs_v_mode, dvfsrc_rsrv;
189 #ifndef MT8196_VCORE_SUPPORT
190 	uint32_t rsrv0, rsrv1;
191 
192 	rsrv0 = mmio_read_32(DVFSRC_RSRV_0);
193 	rsrv1 = mmio_read_32(DVFSRC_RSRV_1);
194 #endif
195 	dvfsrc_rsrv = mmio_read_32(DVFSRC_RSRV_4);
196 	dvfs_v_mode = (dvfsrc_rsrv >> V_VMODE_SHIFT) & V_VMODE_MASK;
197 
198 	if (dvfs_v_mode == 3) {	/* LV */
199 		for (i = 0; i < VCORE_MAX_OPP; i++)
200 			v_opp_uv[i] =
201 				v_rounddown((v_opp_uv[i] * 95) / 100,
202 					    VCORE_STEP_UV);
203 	} else if (dvfs_v_mode == 1) {	/* HV */
204 		for (i = 0; i < VCORE_MAX_OPP; i++)
205 			v_opp_uv[i] =
206 				v_roundup((v_opp_uv[i] * 105) / 100,
207 					   VCORE_STEP_UV);
208 	}
209 #ifndef MT8196_VCORE_SUPPORT
210 	else if (dvfsrc_rsrv & V_VB_EN) { /* NV & AVS1.0 */
211 		v_opp_uv[5] = VCORE_PMIC_TO_UV(((rsrv1 >> 24) & 0xFF) + 7);
212 		v_opp_uv[4] = VCORE_PMIC_TO_UV(((rsrv1 >> 16) & 0xFF) + 5);
213 		v_opp_uv[3] = VCORE_PMIC_TO_UV(((rsrv1 >> 8) & 0xFF) + 4);
214 		v_opp_uv[2] = VCORE_PMIC_TO_UV(((rsrv0 >> 24) & 0xFF) + 4);
215 		v_opp_uv[1] = VCORE_PMIC_TO_UV(((rsrv0 >> 16) & 0xFF) + 3);
216 		v_opp_uv[0] = VCORE_PMIC_TO_UV((rsrv0 & 0xFF) + 3);
217 		for (i = 0; i < VCORE_MAX_OPP; i++)
218 			v_opp_uv[i] = v_min(v_opp_uv[i], v_opp_df_uv[i]);
219 	}
220 #endif
221 #ifdef MT8196_VCORE_SUPPORT
222 	spm_vcorefs_pwarp_cmd(CMD_0, VCORE_UV_TO_PMIC(v_opp_uv[5]));
223 	spm_vcorefs_pwarp_cmd(CMD_1, VCORE_UV_TO_PMIC(v_opp_uv[5]));
224 	spm_vcorefs_pwarp_cmd(CMD_2, VCORE_UV_TO_PMIC(v_opp_uv[4]));
225 	spm_vcorefs_pwarp_cmd(CMD_3, VCORE_UV_TO_PMIC(v_opp_uv[3]));
226 	spm_vcorefs_pwarp_cmd(CMD_4, VCORE_UV_TO_PMIC(v_opp_uv[2]));
227 	spm_vcorefs_pwarp_cmd(CMD_5, VCORE_UV_TO_PMIC(v_opp_uv[2]));
228 	spm_vcorefs_pwarp_cmd(CMD_6, VCORE_UV_TO_PMIC(v_opp_uv[1]));
229 	spm_vcorefs_pwarp_cmd(CMD_7, VCORE_UV_TO_PMIC(v_opp_uv[1]));
230 	spm_vcorefs_pwarp_cmd(CMD_8, VCORE_UV_TO_PMIC(v_opp_uv[0]));
231 
232 	spm_vcorefs_pwarp_cmd(CMD_9, VCORE_UV_TO_PMIC(v_opp_uv[5]));
233 	spm_vcorefs_pwarp_cmd(CMD_10, VCORE_UV_TO_PMIC(v_opp_uv[4]));
234 	spm_vcorefs_pwarp_cmd(CMD_11, VCORE_UV_TO_PMIC(v_opp_uv[3]));
235 	spm_vcorefs_pwarp_cmd(CMD_12, VCORE_UV_TO_PMIC(v_opp_uv[2]));
236 	spm_vcorefs_pwarp_cmd(CMD_13, VCORE_UV_TO_PMIC(v_opp_uv[1]));
237 	spm_vcorefs_pwarp_cmd(CMD_14, VCORE_UV_TO_PMIC(v_opp_uv[0]));
238 #else
239 	spm_vcorefs_pwarp_cmd(CMD_9, VCORE_UV_TO_PMIC(v_opp_uv[5]));
240 	spm_vcorefs_pwarp_cmd(CMD_10, VCORE_UV_TO_PMIC(v_opp_uv[4]));
241 	spm_vcorefs_pwarp_cmd(CMD_11, VCORE_UV_TO_PMIC(v_opp_uv[3]));
242 	spm_vcorefs_pwarp_cmd(CMD_12, VCORE_UV_TO_PMIC(v_opp_uv[2]));
243 	spm_vcorefs_pwarp_cmd(CMD_13, VCORE_UV_TO_PMIC(v_opp_uv[1]));
244 	spm_vcorefs_pwarp_cmd(CMD_14, VCORE_UV_TO_PMIC(v_opp_uv[0]));
245 #endif
246 }
247 
spm_vcorefs_plat_init(uint32_t dvfsrc_flag,uint32_t dvfsrc_vmode,uint32_t * dram_type)248 int spm_vcorefs_plat_init(uint32_t dvfsrc_flag,
249 			  uint32_t dvfsrc_vmode, uint32_t *dram_type)
250 {
251 	uint64_t spm_flags = VCORE_SPM_INIT_PCM_FLAG;
252 	uint32_t dvfsrc_rsrv = 0;
253 
254 	if (mmio_read_32(MD32PCM_PC) == 0)
255 		return MTK_SIP_E_NOT_SUPPORTED;
256 	/* set high opp */
257 	mmio_write_32(DVFSRC_SW_BW_9, 0x3FF);
258 	spm_dvfsfw_init(0, 0);
259 	spm_vcorefs_vcore_setting();
260 	dvfsrc_rsrv = mmio_read_32(DVFSRC_RSRV_4);
261 	opp_type = (dvfsrc_rsrv >> V_OPP_TYPE_SHIFT) & V_OPP_TYPE_SHIFT_MASK;
262 	b0_en = dvfsrc_rsrv & V_B0_EN_SHIFT;
263 
264 	if (dvfsrc_flag & DVFSRC_DISABLE_DVS)
265 		spm_flags |= SPM_FLAG_DISABLE_VCORE_DVS;
266 
267 	if (dvfsrc_flag & DVFSRC_DISABLE_DFS) {
268 		spm_flags |= (SPM_FLAG_DISABLE_DDR_DFS |
269 			      SPM_FLAG_DISABLE_EMI_DFS |
270 			      SPM_FLAG_DISABLE_BUS_DFS);
271 		mmio_write_32(DVFSRC_SW_BW_8, 0x3FF);
272 	}
273 
274 	if (dvfsrc_rsrv & V_DRM_ENABLE) {
275 		spm_flags |= (SPM_FLAG_DISABLE_VCORE_DVS |
276 			      SPM_FLAG_DISABLE_DDR_DFS |
277 			      SPM_FLAG_DISABLE_EMI_DFS |
278 			      SPM_FLAG_DISABLE_BUS_DFS);
279 		return MTK_SIP_E_NOT_SUPPORTED;
280 	}
281 
282 	spm_go_to_vcorefs(spm_flags);
283 	dvfsrc_init();
284 	*dram_type = 0;
285 
286 	return VCOREFS_SUCCESS;
287 }
288 
spm_vcorefs_plat_kick(void)289 int spm_vcorefs_plat_kick(void)
290 {
291 	/* release high opp if not in drm mode*/
292 	if (!(mmio_read_32(DVFSRC_RSRV_4) & V_DRM_ENABLE))
293 		mmio_write_32(DVFSRC_SW_BW_9, 0);
294 
295 	mmio_write_32(DVFSRC_AVS_RETRY, 1);
296 	mmio_write_32(DVFSRC_AVS_RETRY, 0);
297 
298 	return VCOREFS_SUCCESS;
299 }
300 
spm_vcorefs_plat_suspend(void)301 void spm_vcorefs_plat_suspend(void)
302 {
303 	mmio_write_32(DVFSRC_MD_TURBO, 0x1FFF0000);
304 }
305 
spm_vcorefs_plat_resume(void)306 void spm_vcorefs_plat_resume(void)
307 {
308 	mmio_write_32(DVFSRC_MD_TURBO, 0x00000000);
309 }
310 
311 #else
spm_vcorefs_plat_kick(void)312 int spm_vcorefs_plat_kick(void)
313 {
314 	return MTK_SIP_E_NOT_SUPPORTED;
315 }
316 
spm_vcorefs_plat_init(uint32_t dvfsrc_flag,uint32_t dvfsrc_vmode,uint32_t * dram_type)317 int spm_vcorefs_plat_init(uint32_t dvfsrc_flag,
318 			  uint32_t dvfsrc_vmode, uint32_t *dram_type)
319 {
320 	return MTK_SIP_E_NOT_SUPPORTED;
321 }
322 
spm_vcorefs_plat_suspend(void)323 void spm_vcorefs_plat_suspend(void)
324 {
325 }
326 
spm_vcorefs_plat_resume(void)327 void spm_vcorefs_plat_resume(void)
328 {
329 }
330 #endif
331 
spm_vcorefs_get_vcore_uv(uint32_t gear,uint32_t * val)332 int spm_vcorefs_get_vcore_uv(uint32_t gear, uint32_t *val)
333 {
334 	if (gear < VCORE_MAX_OPP)
335 		*val = v_opp_uv[VCORE_MAX_OPP - gear - 1];
336 	else
337 		*val = 0;
338 
339 	return VCOREFS_SUCCESS;
340 }
341 
spm_vcorefs_get_dram_freq(uint32_t gear,uint32_t * val)342 int spm_vcorefs_get_dram_freq(uint32_t gear, uint32_t *val)
343 {
344 #ifdef CONFIG_MTK_DRAMC
345 	if (gear < DRAM_MAX_OPP)
346 		*val = get_dram_step_freq((DRAM_MAX_OPP - gear - 1)) * 1000;
347 	else
348 		*val = 0;
349 #else
350 	*val = 0;
351 #endif
352 	return VCOREFS_SUCCESS;
353 }
354 
spm_vcorefs_get_vcore_opp_num(uint32_t * val)355 int spm_vcorefs_get_vcore_opp_num(uint32_t *val)
356 {
357 	*val = VCORE_MAX_OPP;
358 
359 	return VCOREFS_SUCCESS;
360 }
361 
spm_vcorefs_get_dram_opp_num(uint32_t * val)362 int spm_vcorefs_get_dram_opp_num(uint32_t *val)
363 {
364 	*val = DRAM_MAX_OPP;
365 
366 	return VCOREFS_SUCCESS;
367 }
368 
spm_vcorefs_get_opp_type(uint32_t * val)369 int spm_vcorefs_get_opp_type(uint32_t *val)
370 {
371 	*val = 0;
372 
373 	return VCOREFS_SUCCESS;
374 }
375 
spm_vcorefs_get_fw_type(uint32_t * val)376 int spm_vcorefs_get_fw_type(uint32_t *val)
377 {
378 	*val = 0;
379 
380 	return VCOREFS_SUCCESS;
381 }
382 
spm_vcorefs_get_vcore_info(uint32_t idx,uint32_t * data)383 int spm_vcorefs_get_vcore_info(uint32_t idx, uint32_t *data)
384 {
385 	if (idx == 0)
386 		*data = mmio_read_32(VCORE_VB_INFO0);
387 	else if (idx == 1)
388 		*data = mmio_read_32(VCORE_VB_INFO1);
389 	else if (idx == 2)
390 		*data = mmio_read_32(VCORE_VB_INFO2);
391 	else
392 		*data = 0;
393 
394 	return VCOREFS_SUCCESS;
395 }
396 
397 #define MMPC_FLAG 0x3333
spm_vcorefs_qos_mode(uint32_t data)398 int spm_vcorefs_qos_mode(uint32_t data)
399 {
400 #ifdef CFG_DVFSRC_BW_ASYM_ENABLE
401 	uint32_t mode, value;
402 	bool mm_flag;
403 
404 	mm_flag = (mmio_read_32(DVFSRC_VCORE_QOS7) == 0xFFFFFE);
405 	mode = data >> 16;
406 
407 	if ((mode == 0x3333) && b0_en && mm_flag) {
408 		value = data & 0xFFFF;
409 		if (value == 1)
410 			mmio_write_32(DVFSRC_QOS_EN, 0x00F3007C);
411 		else
412 			mmio_write_32(DVFSRC_QOS_EN, 0x20F1007C);
413 		return VCOREFS_SUCCESS;
414 	}
415 #endif
416 
417 	return MTK_SIP_E_NOT_SUPPORTED;
418 
419 }
420 
spm_vcorefs_pause_enable(uint32_t enable)421 int spm_vcorefs_pause_enable(uint32_t enable)
422 {
423 #ifdef CONFIG_MTK_DBGTOP
424 	mtk_dbgtop_dfd_pause_dvfsrc(1);
425 #endif
426 
427 	return VCOREFS_SUCCESS;
428 }
429 
430 #ifdef MTK_VCORE_DVFS_RES_MEM
vcorefs_rsc_ctrl(unsigned int rsc,bool hold)431 static int vcorefs_rsc_ctrl(unsigned int rsc, bool hold)
432 {
433 	static struct mt_lp_resource_user vcorefs_res_user;
434 	int ret = -1;
435 
436 	if (!vcorefs_res_user.uid) {
437 		ret = mt_lp_resource_user_register("VCOREFS",
438 						    &vcorefs_res_user);
439 		if (ret) {
440 			WARN("%s: register lp resource failed", __func__);
441 			return ret;
442 		}
443 	}
444 
445 	if (hold)
446 		ret = vcorefs_res_user.request(&vcorefs_res_user, rsc);
447 	else
448 		ret = vcorefs_res_user.release(&vcorefs_res_user);
449 
450 	if (ret)
451 		WARN("%s: RSC_%d %s failed",
452 		     __func__, rsc, hold ? "req" : "rel");
453 
454 	return ret;
455 }
456 
spm_vcorefs_rsc_mem_req(bool request)457 int spm_vcorefs_rsc_mem_req(bool request)
458 {
459 	vcorefs_rsc_ctrl(MT_LP_RQ_DRAM, request);
460 
461 	return VCOREFS_SUCCESS;
462 }
463 #endif
464