/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2016 MediaTek Inc. */ #include #include #include #include #include #include "include/pmic.h" #include "include/regulator_codegen.h" #if defined(CONFIG_MACH_MT6781) #include static unsigned int g_is_new_power_grid; unsigned int is_pmic_new_power_grid(void) { return g_is_new_power_grid; } void record_is_pmic_new_power_grid(struct platform_device *pdev) { unsigned int GPIO200_idx = 0; GPIO200_idx = of_get_named_gpio(pdev->dev.of_node, "pmic,init_gpio", 0); if (gpio_get_value(GPIO200_idx)) g_is_new_power_grid = 1; pr_info("[PMIC] (GPIO200)(%d) = %d\n", GPIO200_idx, g_is_new_power_grid); } #endif void record_md_vosel(void) { g_vmodem_vosel = pmic_get_register_value(PMIC_RG_BUCK_VMODEM_VOSEL); pr_info("[%s] vmodem_vosel = 0x%x\n", __func__, g_vmodem_vosel); } /* [Export API] */ #if defined(CONFIG_MACH_MT6781) void vmd1_pmic_setting_on(void) { unsigned int vsram_md_vosel = 0x4F; /*993750*/ /* 1.Call PMIC driver API configure VMODEM voltage */ if (g_vmodem_vosel != 0) { if (is_pmic_new_power_grid()) pmic_config_interface(PMIC_RG_LDO_VSRAM_CORE_VOSEL_ADDR, vsram_md_vosel, PMIC_RG_LDO_VSRAM_CORE_VOSEL_MASK, PMIC_RG_LDO_VSRAM_CORE_VOSEL_SHIFT); else pmic_set_register_value(PMIC_RG_LDO_VSRAM_OTHERS_VOSEL, vsram_md_vosel); pmic_set_register_value(PMIC_RG_BUCK_VMODEM_VOSEL, g_vmodem_vosel); pr_info("[%s] set vmodem=0x%x vsram_md=0x%x\n" , __func__, g_vmodem_vosel, vsram_md_vosel); } else { pr_notice("[%s] vmodem vosel has not recorded!\n", __func__); record_md_vosel(); } } #else void vmd1_pmic_setting_on(void) { /* 1.Call PMIC driver API configure VMODEM voltage */ if (g_vmodem_vosel != 0) { pmic_set_register_value(PMIC_RG_BUCK_VMODEM_VOSEL, g_vmodem_vosel); } else { pr_notice("[%s] vmodem vosel has not recorded!\n", __func__); g_vmodem_vosel = pmic_get_register_value(PMIC_RG_BUCK_VMODEM_VOSEL); pr_info("[%s] vmodem_vosel = 0x%x\n", __func__, g_vmodem_vosel); } if (pmic_get_register_value(PMIC_DA_VMODEM_VOSEL) != g_vmodem_vosel) pr_notice("[%s] vmodem vosel = 0x%x, da_vosel = 0x%x", __func__, pmic_get_register_value(PMIC_RG_BUCK_VMODEM_VOSEL), pmic_get_register_value(PMIC_DA_VMODEM_VOSEL)); } #endif 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] pwrkey %s, JUST_SMART_RST:%d\n", __func__, pmic_get_register_value(PMIC_PWRKEY_DEB)?"released":"pressed", pmic_get_register_value(PMIC_JUST_SMART_RST)); pmic_set_register_value(PMIC_RG_SMART_RST_MODE, smart_en); pmic_set_register_value(PMIC_RG_SMART_RST_SDN_EN, smart_sdn_en); pr_info("[%s] smart_en:%d, smart_sdn_en:%d\n", __func__, smart_en, smart_sdn_en); } void wk_pmic_enable_sdn_delay(void) { pmic_set_register_value(PMIC_TMA_KEY, 0x9CA7); pmic_set_register_value(PMIC_RG_SDN_DLY_ENB, 0); pmic_set_register_value(PMIC_TMA_KEY, 0); } 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 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[MT6358_POWER_BUCK_VCORE], PMIC_RG_BUCK_VCORE_SSHUB_VOSEL, voltage, false); } unsigned int pmic_scp_set_vcore_sleep(unsigned int voltage) { return pmic_scp_set_regulator( mt_bucks[MT6358_POWER_BUCK_VCORE], PMIC_RG_BUCK_VCORE_SSHUB_VOSEL_SLEEP, voltage, true); } /* * 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[MT6358_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[MT6358_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");