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/pmic_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 <mt_spm_reg.h>
18
19 /* SPMI_M: 6363, SPMI_P: 6373/6316 */
20 /* SPMI_M: 6363, SPMI_P: 6373/6316 */
21 static struct lp_pmic_cfg {
22 uint8_t slave;
23 uint8_t master;
24 char *name;
25 } pmics[] = {
26 [LP_MT6363] = {MT6363_SLAVE, SPMI_MASTER_1, "MT6363"},
27 [LP_MT6373] = {MT6373_SLAVE, SPMI_MASTER_P_1, "MT6373"},
28 [LP_MT6316_1] = {MT6316_S8_SLAVE, SPMI_MASTER_P_1, "MT6316_S8"},
29 [LP_MT6316_2] = {MT6316_S6_SLAVE, SPMI_MASTER_P_1, "MT6316_S6"},
30 [LP_MT6316_3] = {MT6316_S7_SLAVE, SPMI_MASTER_P_1, "MT6316_S7"},
31 [LP_MT6316_4] = {MT6316_S15_SLAVE, SPMI_MASTER_P_1, "MT6316_S15"},
32 };
33
34 #ifdef MTK_SPM_PMIC_GS_DUMP
35 static struct pmic_gs_info pmic_gs_dump_info;
36 static char *pmic_str[] = {
37 [LP_MT6363] = "MT6363",
38 [LP_MT6373] = "MT6373",
39 [LP_MT6316_1] = "MT6316_1",
40 [LP_MT6316_2] = "MT6316_2",
41 [LP_MT6316_3] = "MT6316_3",
42 [LP_MT6316_4] = "MT6316_4",
43 };
44 #endif
45 struct spmi_device *lp_sdev[LP_PMIC_SLAVE_NUM];
46
47 #define VSRAM_CORE_0_35V 56
48 #define VSRAM_CORE_0_55V 88
49 #define VSRAM_CORE_0_75V 120
50
51 /* VSRAM_CORE Low bound */
52 #ifdef MTK_AGING_FLAVOR_LOAD
53 #define SUSPEND_AGING_VAL_SHIFT 3
54 #define SUSPEND_AGING_VAL_DEFAULT 85
55 #define VSRAM_CORE_LOWBOUND (74 - SUSPEND_AGING_VAL_SHIFT)
56 #else
57 #define VSRAM_CORE_LOWBOUND 74
58 #endif
59 #define MT6363_LP_REG 0x1687
60 #define MT6363_VIO18_SWITCH 0x53
61 #define MT6373_VIO18_SWITCH 0x58
62
63 static uint32_t vcore_sram_suspend_vol = VSRAM_CORE_0_55V;
64 static bool vcore_sram_lp_enable = true;
65 static bool vcore_lp_enable = true;
66
get_vcore_sram_suspend_vol(void)67 static uint32_t get_vcore_sram_suspend_vol(void)
68 {
69 uint8_t value;
70 /* Set vcore_sram to 0.55V by default */
71 value = VSRAM_CORE_0_55V;
72
73 #ifdef MTK_AGING_FLAVOR_LOAD
74 value -= SUSPEND_AGING_VAL_SHIFT;
75 if (value > SUSPEND_AGING_VAL_DEFAULT)
76 value = SUSPEND_AGING_VAL_DEFAULT;
77 INFO("%s(%d) enable aging with value: %u\n",
78 __func__, __LINE__, value);
79 #endif
80 return value;
81 }
82
83 #ifdef MTK_SPM_PMIC_GS_DUMP
mt_spm_dump_pmic_gs(uint32_t cmd)84 static void mt_spm_dump_pmic_gs(uint32_t cmd)
85 {
86 #ifdef MTK_SPM_PMIC_GS_DUMP_SUSPEND
87 if (cmd & MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND) { /* Suspend enter */
88 mt_spm_pmic_gs_dump(SUSPEND, LP_MT6363);
89 mt_spm_pmic_gs_dump(SUSPEND, LP_MT6373);
90 }
91 #endif
92 if (cmd & MT_RM_CONSTRAINT_ALLOW_VCORE_LP) {
93 if (cmd & MT_RM_CONSTRAINT_ALLOW_BUS26M_OFF) { /* SODI3 */
94 #ifdef MTK_SPM_PMIC_GS_DUMP_SODI3
95 mt_spm_pmic_gs_dump(SODI3, LP_MT6363);
96 mt_spm_pmic_gs_dump(SODI3, LP_MT6373);
97 #endif
98 } else { /* DPIDLE enter */
99 #ifdef MTK_SPM_PMIC_GS_DUMP_DPIDLE
100 mt_spm_pmic_gs_dump(DPIDLE, LP_MT6363);
101 mt_spm_pmic_gs_dump(DPIDLE, LP_MT6373);
102 #endif
103 }
104 }
105 }
106 #endif
107
spm_lp_setting_init(void)108 int spm_lp_setting_init(void)
109 {
110 uint8_t i, slvid, spmi_master;
111
112 for (i = 0; i < ARRAY_SIZE(pmics); i++) {
113 slvid = pmics[i].slave;
114 spmi_master = pmics[i].master;
115 lp_sdev[i] = get_spmi_device(spmi_master, slvid);
116 if (!lp_sdev[i])
117 return -ENODEV;
118 }
119
120 PMIC_SLVID_BUCK_SET_LP(MT6316, S8, VBUCK1, RC8,
121 false, OP_MODE_LP, HW_OFF);
122
123 /* Get suspend case vcore_sram sleep voltage */
124 vcore_sram_suspend_vol = get_vcore_sram_suspend_vol();
125
126 #ifdef MTK_SPM_PMIC_GS_DUMP
127 pmic_gs_dump_info.lp_sdev = lp_sdev;
128 pmic_gs_dump_info.pmic_str = pmic_str;
129 pmic_gs_dump_info.pmic_num = LP_PMIC_SLAVE_NUM;
130 #ifdef MTK_SPM_PMIC_GS_DUMP_SUSPEND
131 pmic_gs_dump_info.scen_gs[SUSPEND].data = pmic_gs_suspend;
132 #endif
133 #ifdef MTK_SPM_PMIC_GS_DUMP_SODI3
134 pmic_gs_dump_info.scen_gs[SODI3].data = pmic_gs_sodi3;
135 #endif
136 #ifdef MTK_SPM_PMIC_GS_DUMP_DPIDLE
137 pmic_gs_dump_info.scen_gs[DPIDLE].data = pmic_gs_dpidle;
138 #endif
139 return register_pmic_gs_info(&pmic_gs_dump_info);
140 #else
141 return 0;
142 #endif
143 }
144
145 #ifdef MTK_SPM_PMIC_LP_SUPPORT
146 MTK_PLAT_SETUP_0_INIT(spm_lp_setting_init);
147 #endif
148
set_vcore_lp_enable(bool enable)149 void set_vcore_lp_enable(bool enable)
150 {
151 vcore_lp_enable = enable;
152 }
153
get_vcore_lp_enable(void)154 bool get_vcore_lp_enable(void)
155 {
156 return vcore_lp_enable;
157 }
158
set_vsram_lp_enable(bool enable)159 void set_vsram_lp_enable(bool enable)
160 {
161 vcore_sram_lp_enable = enable;
162 }
163
get_vsram_lp_enable(void)164 bool get_vsram_lp_enable(void)
165 {
166 return vcore_sram_lp_enable;
167 }
168
set_vsram_lp_volt(uint32_t volt)169 void set_vsram_lp_volt(uint32_t volt)
170 {
171 /* Allow 0.35V ~ 0.75V */
172 if (volt < VSRAM_CORE_0_35V || volt > VSRAM_CORE_0_75V)
173 return;
174 vcore_sram_suspend_vol = volt;
175 }
176
get_vsram_lp_volt(void)177 uint32_t get_vsram_lp_volt(void)
178 {
179 return vcore_sram_suspend_vol;
180 }
181
pmic_lp_setting(uint8_t data)182 static int pmic_lp_setting(uint8_t data)
183 {
184 int ret;
185
186 if (data != 0x0 && data != 0x1)
187 return -ENODEV;
188 /* SUSPEND:VS1 HW2&RC9 normal mode */
189 PMIC_BUCK_SET_LP(MT6363, VS1, HW2,
190 false, OP_MODE_LP, HW_LP);
191 PMIC_BUCK_SET_LP(MT6363, VS1, RC9,
192 false, OP_MODE_MU, HW_ON);
193 PMIC_LDO_SET_LP(MT6363, VIO18, HW2,
194 false, OP_MODE_LP, HW_LP);
195 PMIC_LDO_SET_LP(MT6363, VIO18, RC9,
196 false, OP_MODE_MU, HW_ON);
197
198 /* Switch DIG18 to VIO18 for power saving */
199 ret = spmi_ext_register_writel(lp_sdev[LP_MT6363], MT6363_VIO18_SWITCH, &data, 1);
200 if (ret)
201 INFO("MT6363 RG_VIO18 spmi failed\n");
202
203 ret = spmi_ext_register_writel(lp_sdev[LP_MT6373], MT6373_VIO18_SWITCH, &data, 1);
204 if (ret)
205 INFO("MT6373 RG_VIO18 spmi failed\n");
206 return ret;
207 }
208
do_spm_low_power(enum SPM_PWR_TYPE type,uint32_t cmd)209 int do_spm_low_power(enum SPM_PWR_TYPE type, uint32_t cmd)
210 {
211 int ret;
212 uint8_t value;
213 bool enter_suspend, vcore_sram_lp = false;
214
215 if (type == SPM_LP_ENTER) {
216 enter_suspend = true;
217 vcore_sram_lp = vcore_sram_lp_enable;
218
219 if (cmd & MT_RM_CONSTRAINT_ALLOW_AP_PLAT_SUSPEND) {
220 value = vcore_sram_suspend_vol;
221 if (value < VSRAM_CORE_LOWBOUND ||
222 value > VSRAM_CORE_0_75V) {
223 INFO("Vsram_core voltage wrong\n");
224 panic();
225 }
226 } else {
227 value = VSRAM_CORE_0_55V;
228 }
229 } else {
230 enter_suspend = false;
231 vcore_sram_lp = false;
232 value = VSRAM_CORE_0_75V;
233 }
234 /* Enable VA12_2/VSRAM_CPUL HW_LP for suspend/idle */
235 PMIC_LDO_SET_LP(MT6363, VA12_2, HW2, enter_suspend, OP_MODE_LP, HW_LP);
236 PMIC_LDO_SET_LP(MT6363, VSRAM_CPUL, HW2,
237 enter_suspend, OP_MODE_LP, HW_LP);
238
239 if (!(cmd & MT_RM_CONSTRAINT_ALLOW_AP_SUSPEND))
240 return 0;
241 PMIC_SLVID_BUCK_SET_LP(MT6316, S8, VBUCK1, HW2, vcore_lp_enable,
242 OP_MODE_LP, HW_LP);
243 PMIC_BUCK_SET_LP(MT6363, VBUCK4, HW0, vcore_sram_lp,
244 OP_MODE_LP, HW_LP);
245 PMIC_BUCK_SET_LP(MT6363, VBUCK4, HW2, !enter_suspend,
246 OP_MODE_LP, HW_LP);
247 ret = spmi_ext_register_writel(lp_sdev[LP_MT6363], MT6363_LP_REG, &value, 1);
248 if (ret)
249 INFO("BUCK(VSRAM_CORE) spmi write failed\n");
250
251 if (cmd & MT_RM_CONSTRAINT_ALLOW_AP_PLAT_SUSPEND)
252 pmic_lp_setting(enter_suspend ? 1 : 0);
253
254 return 0;
255 }
256