/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2019 MediaTek Inc. */ #include #include #include #if defined(CONFIG_REGULATOR_MT6315) #include #endif #include #include #include "include/pmic.h" #include "include/pmic_api_buck.h" #include "include/regulator_codegen.h" #if defined(CONFIG_MFD_MT6362) #include #endif /* VRFDIG use VPU of MT6359+ in MT6885 */ static unsigned int g_vrfdig_vosel; void record_md_vosel(void) { g_vrfdig_vosel = pmic_get_register_value(PMIC_RG_BUCK_VPU_VOSEL); pr_info("[%s] vrfdig=0x%x\n", __func__, g_vrfdig_vosel); } /* [Export API] */ void vmd1_pmic_setting_on(void) { #if defined(CONFIG_REGULATOR_MT6315) mt6315_vmd1_pmic_setting_on(); #elif defined(CONFIG_MFD_MT6362) mt6362_vmd1_pmic_setting_on(); #endif /* 1.Call PMIC driver API configure VMODEM voltage */ if (g_vrfdig_vosel != 0) { pmic_set_register_value(PMIC_RG_BUCK_VPU_VOSEL, g_vrfdig_vosel); pr_info("[%s] set vrfdig=0x%x\n", __func__, g_vrfdig_vosel); } else { pr_notice("[%s] vmodem vosel has not recorded!\n", __func__); record_md_vosel(); } } void vmd1_pmic_setting_off(void) { PMICLOG("%s\n", __func__); } void pmic_enable_smart_reset(unsigned char smart_en, unsigned char smart_sdn_en) { pr_notice("[%s] powerkey: %s, count=%d(ms) JUST_SMART_RST:%d\n" , __func__ , pmic_get_register_value(PMIC_PWRKEY_DEB)?"released":"pressed" , pmic_get_register_value(PMIC_PWRKEY_LONG_PRESS_COUNT) << 5 , pmic_get_register_value(PMIC_JUST_SMART_RST)); pmic_set_register_value(PMIC_RG_CPS_W_KEY, 0x4729); pmic_set_register_value(PMIC_RG_SMART_RST_MODE, smart_en); pmic_set_register_value(PMIC_RG_SMART_RST_SDN_EN, smart_sdn_en); pmic_set_register_value(PMIC_RG_CPS_W_KEY, 0); pr_info("[%s] smart_en:%d, smart_sdn_en:%d\n", __func__, smart_en, smart_sdn_en); } void enable_bat_temp_det(bool en) { pmic_set_register_value(PMIC_AUXADC_BAT_TEMP_FROZE_EN, !en); } static unsigned int pmic_scp_set_regulator(struct mtk_regulator mt_reg, enum PMU_FLAGS_LIST vosel_reg, unsigned int voltage, bool is_sleep_vol) { unsigned int min_uV = mt_reg.desc.min_uV; unsigned int uV_step = mt_reg.desc.uV_step; unsigned int n_voltages = mt_reg.desc.n_voltages; unsigned short set_step = 0; unsigned short get_step = 0; set_step = (voltage - min_uV) / uV_step; if (voltage < min_uV || set_step >= n_voltages) { pr_notice("[%s] SSHUB_%s Set Wrong voltage=%duV is unsupportable range %d-%duV\n" , __func__ , mt_reg.desc.name , voltage , min_uV , (n_voltages * uV_step + min_uV)); return voltage; } pr_info("SSHUB_%s Expected %svolt step = %d\n", mt_reg.desc.name, is_sleep_vol?"sleep ":"", set_step); pmic_set_register_value(vosel_reg, set_step); udelay(220); get_step = pmic_get_register_value(vosel_reg); if (get_step != set_step) { pr_notice("[%s] Set SSHUB_%s Voltage fail with step = %d, read voltage = %duV\n" , __func__, mt_reg.desc.name, set_step , (get_step * uV_step + min_uV)); return voltage; } pr_info("Set SSHUB_%s %sVoltage to %duV pass\n", mt_reg.desc.name, is_sleep_vol?"sleep ":"", voltage); return 0; } /* * SCP enable VCORE/VSRAM control, return 0 if success */ int pmic_scp_ctrl_enable(bool vcore_en, bool vsram_en, bool is_pmrc_mode) { int ret = 0; pmic_set_register_value(PMIC_RG_BUCK_VGPU11_SSHUB_EN, vcore_en); pmic_set_register_value(PMIC_RG_LDO_VSRAM_OTHERS_SSHUB_EN, vsram_en); pmic_set_register_value(PMIC_RG_VR_SSHUB_MODE, is_pmrc_mode); pr_info("[%s] vcore_en:%d vsram_en:%d is_pmic_mode:%d\n", __func__, vcore_en, vsram_en, is_pmrc_mode); return ret; } /* * SCP set VCORE voltage, return 0 if success, * otherwise return set voltage(uV) */ unsigned int pmic_scp_set_vcore(unsigned int voltage) { return pmic_scp_set_regulator( mt_bucks[MT6359_POWER_BUCK_VGPU11], PMIC_RG_BUCK_VGPU11_SSHUB_VOSEL, voltage, false); } /* * SCP set VSRAM_CORE(VSRAM_OTHERS) voltage, return 0 if success, * otherwise return set voltage(uV) */ unsigned int pmic_scp_set_vsram_vcore(unsigned int voltage) { return pmic_scp_set_regulator( mt_ldos[MT6359_POWER_LDO_VSRAM_OTHERS], PMIC_RG_LDO_VSRAM_OTHERS_SSHUB_VOSEL, voltage, false); } unsigned int pmic_scp_set_vsram_vcore_sleep(unsigned int voltage) { return pmic_scp_set_regulator( mt_ldos[MT6359_POWER_LDO_VSRAM_OTHERS], PMIC_RG_LDO_VSRAM_OTHERS_SSHUB_VOSEL_SLEEP, voltage, true); } /***************************************************************************** * PMIC charger detection ******************************************************************************/ unsigned int upmu_get_rgs_chrdet(void) { unsigned int val = 0; val = pmic_get_register_value(PMIC_RGS_CHRDET); PMICLOG("[%s] CHRDET status = %d\n", __func__, val); return val; } int is_ext_vbat_boost_exist(void) { return 0; } int is_ext_swchr_exist(void) { return 0; } /***************************************************************************** * Enternal BUCK status ******************************************************************************/ int is_ext_buck_gpio_exist(void) { return pmic_get_register_value(PMIC_RG_STRUP_EXT_PMIC_EN); } MODULE_AUTHOR("Jeter Chen"); MODULE_DESCRIPTION("MT PMIC Device Driver"); MODULE_LICENSE("GPL");