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