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 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 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 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 140 void set_vcore_lp_enable(bool enable) 141 { 142 vcore_lp_enable = enable; 143 } 144 145 bool get_vcore_lp_enable(void) 146 { 147 return vcore_lp_enable; 148 } 149 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 160 uint32_t get_vcore_lp_volt(void) 161 { 162 return vcore_suspend_vol; 163 } 164 165 void set_vsram_lp_enable(bool enable) 166 { 167 vcore_sram_lp_enable = enable; 168 } 169 170 bool get_vsram_lp_enable(void) 171 { 172 return vcore_sram_lp_enable; 173 } 174 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 183 uint32_t get_vsram_lp_volt(void) 184 { 185 return vcore_sram_suspend_vol; 186 } 187 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