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 <lib/mmio.h>
11
12 #include <drivers/pmic/mt6359p_set_lowpower.h>
13 #include <drivers/spmi/spmi_common.h>
14 #include <lib/mtk_init/mtk_init.h>
15 #include <mt_spm_constraint.h>
16 #include <mt_spm_pmic_lp.h>
17 #include <pmic_wrap_init_common.h>
18
19 #ifdef MTK_SPM_PMIC_GS_DUMP
20 static struct pmic_gs_info pmic_gs_dump_info;
21 static char *pmic_str[] = {
22 [LP_MT6365] = "MT6365",
23 [LP_MT6319_S7] = "MT6319",
24 };
25 #endif
26
27 struct spmi_device *lp_sdev[LP_PMIC_SLAVE_NUM];
28
29 #define VCORE_BASE_UV 40000
30 #define VCORE_TO_PMIC_VAL(volt) (((volt) - VCORE_BASE_UV + 625 - 1) / 625)
31 #define PMIC_VAL_TO_VCORE(pmic) (((pmic) * 625) + VCORE_BASE_UV)
32
33 #define VCORE_0_45V VCORE_TO_PMIC_VAL(45000)
34 #define VCORE_0_55V VCORE_TO_PMIC_VAL(55000)
35 #define VCORE_0_75V VCORE_TO_PMIC_VAL(75000)
36
37 #define VSRAM_CORE_BASE_UV 40000
38 #define VSRAM_CORE_TO_PMIC_VAL(volt) (((volt) - VSRAM_CORE_BASE_UV + 625 - 1) / 625)
39 #define PMIC_VAL_TO_VSRAM_CORE(pmic) (((pmic) * 625) + VSRAM_CORE_BASE_UV)
40
41 #define VSRAM_CORE_0_40V VSRAM_CORE_TO_PMIC_VAL(40000)
42 #define VSRAM_CORE_0_55V VSRAM_CORE_TO_PMIC_VAL(55000)
43 #define VSRAM_CORE_0_75V VSRAM_CORE_TO_PMIC_VAL(75000)
44
45 static uint32_t vcore_sram_suspend_vol = VSRAM_CORE_0_55V;
46 static uint32_t vcore_suspend_vol = VCORE_0_55V;
47 static bool vcore_sram_lp_enable = true;
48 static bool vcore_lp_enable = true;
49
get_vcore_sram_suspend_vol(void)50 static uint32_t get_vcore_sram_suspend_vol(void)
51 {
52 uint8_t value = VSRAM_CORE_0_55V;
53 #ifdef MTK_SUSPEND_VOL_BIN_SUPPORT
54 static const uint32_t vlp_vb_efuse_val_arr[] = { 24, 24, 24, 24, 24, 24,
55 22, 21, 20, 19, 18, 17,
56 16, 15, 14, 13 };
57 uint32_t volbin_efuse_reg;
58
59 volbin_efuse_reg = mmio_read_32(SOC_VB_REG);
60 INFO("11#@# %s(%d) enable voltage bin support with efuse value: 0x%x\n",
61 __func__, __LINE__, volbin_efuse_reg);
62 volbin_efuse_reg = (volbin_efuse_reg >> SUSPEND_VB_USE_SHIFT) &
63 SUSPEND_VB_USE_MASK;
64
65 if (volbin_efuse_reg < ARRAY_SIZE(vlp_vb_efuse_val_arr))
66 value = vlp_vb_efuse_val_arr[volbin_efuse_reg];
67 #endif
68 #ifdef MTK_AGING_FLAVOR_LOAD
69 value -= SUSPEND_AGING_VAL_SHIFT;
70 if (value > SUSPEND_AGING_VAL_DEFAULT)
71 value = SUSPEND_AGING_VAL_DEFAULT;
72 INFO("11#@# %s(%d) enable aging with value: %d\n", __func__, __LINE__,
73 value);
74 #endif
75 #ifdef MTK_AGING_HV_FLAVOR_LOAD
76 /* ignore binning and configure as sign off + 5% */
77 value = SUSPEND_AGING_HV_VAL_DEFAULT;
78 INFO("11#@# %s(%d) enable aging hv with value: %d\n", __func__,
79 __LINE__, value);
80 #endif
81 return value;
82 }
83
84 #ifdef MTK_SPM_PMIC_GS_DUMP
mt_spm_dump_pmic_gs(uint32_t cmd)85 static void mt_spm_dump_pmic_gs(uint32_t cmd)
86 {
87 #ifdef MTK_SPM_PMIC_GS_DUMP_SUSPEND
88 if (cmd & MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND) { /*Suspend enter*/
89 mt_spm_pmic_gs_dump(SUSPEND, LP_MT6365);
90 }
91 #endif
92 if (cmd & MT_RM_CONSTRAINT_ALLOW_VCORE_LP) {
93 if (cmd & MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF) { /*SODI3 enter*/
94 #ifdef MTK_SPM_PMIC_GS_DUMP_SODI3
95 mt_spm_pmic_gs_dump(SODI3, LP_MT6365);
96 #endif
97 } else { /*DPIDLE enter*/
98 #ifdef MTK_SPM_PMIC_GS_DUMP_DPIDLE
99 mt_spm_pmic_gs_dump(DPIDLE, LP_MT6365);
100 #endif
101 }
102 }
103 }
104 #endif
105
spm_lp_setting_init(void)106 int spm_lp_setting_init(void)
107 {
108 /* AOC2.5: VCORE O0 OFF */
109 PMIC_BUCK_SET_LP(MT6359P, VPROC2, HW0, true, OP_MODE_LP, HW_OFF);
110
111 /* AOC2.5 : VSRAM_CORE O0 HW:LP */
112 PMIC_BUCK_SET_LP(MT6359P, VGPU11, HW0, true, OP_MODE_LP, HW_LP);
113
114 /* Get suspend case VSRAM_CORE sleep voltage */
115 vcore_sram_suspend_vol = get_vcore_sram_suspend_vol();
116 /* Set VCORE LP default 0.55V */
117 vcore_suspend_vol = VCORE_0_55V;
118
119 #ifdef MTK_SPM_PMIC_GS_DUMP
120 pmic_gs_dump_info.lp_sdev = lp_sdev;
121 pmic_gs_dump_info.pmic_str = pmic_str;
122 pmic_gs_dump_info.pmic_num = LP_PMIC_SLAVE_NUM;
123 #ifdef MTK_SPM_PMIC_GS_DUMP_SUSPEND
124 pmic_gs_dump_info.scen_gs[SUSPEND].data = pmic_gs_suspend;
125 #endif
126 #ifdef MTK_SPM_PMIC_GS_DUMP_SODI3
127 pmic_gs_dump_info.scen_gs[SODI3].data = pmic_gs_sodi3;
128 #endif
129 #ifdef MTK_SPM_PMIC_GS_DUMP_DPIDLE
130 pmic_gs_dump_info.scen_gs[DPIDLE].data = pmic_gs_dpidle;
131 #endif
132 return register_pmic_gs_info(&pmic_gs_dump_info);
133 #else
134 return 0;
135 #endif
136 }
137
138 MTK_PLAT_SETUP_0_INIT(spm_lp_setting_init);
139
set_vcore_lp_enable(bool enable)140 void set_vcore_lp_enable(bool enable)
141 {
142 vcore_lp_enable = enable;
143 }
144
get_vcore_lp_enable(void)145 bool get_vcore_lp_enable(void)
146 {
147 return vcore_lp_enable;
148 }
149
set_vcore_lp_volt(uint32_t volt)150 void set_vcore_lp_volt(uint32_t volt)
151 {
152 /* allow 0.45V ~ 0.75V */
153 if (volt < VCORE_0_45V)
154 return;
155 if (volt > VCORE_0_75V)
156 return;
157 vcore_suspend_vol = volt;
158 }
159
get_vcore_lp_volt(void)160 uint32_t get_vcore_lp_volt(void)
161 {
162 return vcore_suspend_vol;
163 }
164
set_vsram_lp_enable(bool enable)165 void set_vsram_lp_enable(bool enable)
166 {
167 vcore_sram_lp_enable = enable;
168 }
169
get_vsram_lp_enable(void)170 bool get_vsram_lp_enable(void)
171 {
172 return vcore_sram_lp_enable;
173 }
174
set_vsram_lp_volt(uint32_t volt)175 void set_vsram_lp_volt(uint32_t volt)
176 {
177 /* allow 0.40V ~ 0.75V */
178 if (volt > VSRAM_CORE_0_75V)
179 return;
180 vcore_sram_suspend_vol = volt;
181 }
182
get_vsram_lp_volt(void)183 uint32_t get_vsram_lp_volt(void)
184 {
185 return vcore_sram_suspend_vol;
186 }
187
do_spm_low_power(enum SPM_PWR_TYPE type,uint32_t cmd)188 int do_spm_low_power(enum SPM_PWR_TYPE type, uint32_t cmd)
189 {
190 int ret = 0;
191 uint8_t value = 0;
192 uint32_t reg = 0;
193 bool vproc2_lp_enable = false;
194 bool vgpu11_hw0_lp_enable = false;
195 bool vgpu11_hw2_lp_enable = false;
196
197 if (!(cmd & MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND))
198 return 0;
199
200 if (type == SPM_LP_ENTER) {
201 /* SUSPEND enter */
202 vproc2_lp_enable = vcore_lp_enable;
203 vgpu11_hw0_lp_enable = vcore_sram_lp_enable;
204 vgpu11_hw2_lp_enable = false;
205 reg = 0x158E; /* LDO_VSRAM_CORE_VOSEL0 */
206
207 if (cmd & MT_RM_CONSTRAINT_ALLOW_AP_PLAT_SUSPEND)
208 value = vcore_sram_suspend_vol; /* SUSPEND: VSRAM_CORE 0.55V */
209 else
210 value = VSRAM_CORE_0_55V; /* SODI5.0: VSRAM_CORE 0.55V */
211 } else {
212 /* SUSPEND leave (SODI3/DPIDLE) */
213 vproc2_lp_enable = true;
214 vgpu11_hw0_lp_enable = true;
215 vgpu11_hw2_lp_enable = true;
216 reg = 0x15b4; /* LDO_VSRAM_CORE_VOSEL0 */
217 value = VSRAM_CORE_0_75V; /* 0.75V SODI3/DPIDLE */
218 }
219
220 PMIC_BUCK_SET_LP(MT6359P, VPROC2, HW0, vproc2_lp_enable, OP_MODE_LP, HW_OFF);
221 PMIC_BUCK_SET_LP(MT6359P, VGPU11, HW0, vgpu11_hw0_lp_enable, OP_MODE_LP, HW_LP);
222 PMIC_BUCK_SET_LP(MT6359P, VGPU11, HW2, vgpu11_hw2_lp_enable, OP_MODE_LP, HW_LP);
223
224 ret = pwrap_write_field(reg, value, 0xff, 0);
225 if (ret) {
226 if (type == SPM_LP_ENTER)
227 INFO("LDO_VSRAM_CORE_VOSEL0(VSRAM_CORE) spmi write failed\n");
228 else
229 INFO("BUCK_VBUCK4_CON1(VSRAM_CORE) spmi write failed\n");
230 }
231
232 #ifdef MTK_SPM_PMIC_GS_DUMP
233 if (type == SPM_LP_ENTER)
234 mt_spm_dump_pmic_gs(cmd);
235 #endif
236
237 return 0;
238 }
239