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