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 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 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 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 149 void set_vcore_lp_enable(bool enable) 150 { 151 vcore_lp_enable = enable; 152 } 153 154 bool get_vcore_lp_enable(void) 155 { 156 return vcore_lp_enable; 157 } 158 159 void set_vsram_lp_enable(bool enable) 160 { 161 vcore_sram_lp_enable = enable; 162 } 163 164 bool get_vsram_lp_enable(void) 165 { 166 return vcore_sram_lp_enable; 167 } 168 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 177 uint32_t get_vsram_lp_volt(void) 178 { 179 return vcore_sram_suspend_vol; 180 } 181 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 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