Loading drivers/power/supply/qcom/qg-core.h +3 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ struct qg_dt { bool fvss_enable; bool multi_profile_load; bool tcss_enable; bool bass_enable; }; struct qg_esr_data { Loading Loading @@ -138,6 +139,7 @@ struct qpnp_qg { bool force_soc; bool fvss_active; bool tcss_active; bool bass_active; int charge_status; int charge_type; int chg_iterm_ma; Loading @@ -154,6 +156,7 @@ struct qpnp_qg { int soc_tcss; int tcss_entry_count; int max_fcc_limit_ma; int bsoc_bass_entry; u32 fifo_done_count; u32 wa_flags; u32 seq_no; Loading drivers/power/supply/qcom/qg-soc.c +121 −9 Original line number Diff line number Diff line Loading @@ -20,11 +20,38 @@ #include "qg-profile-lib.h" #include "qg-soc.h" enum soc_scaling_feature { QG_FVSS = BIT(0), QG_TCSS = BIT(1), QG_BASS = BIT(2), }; #define DEFAULT_UPDATE_TIME_MS 64000 #define SOC_SCALE_HYST_MS 2000 #define VBAT_LOW_HYST_UV 50000 #define FULL_SOC 100 static int qg_ss_feature; static ssize_t qg_ss_feature_show(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "0x%4x\n", qg_ss_feature); } static ssize_t qg_ss_feature_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int val; if (kstrtos32(buf, 0, &val)) return -EINVAL; qg_ss_feature = val; return count; } DEVICE_ATTR_RW(qg_ss_feature); static int qg_delta_soc_interval_ms = 20000; static ssize_t soc_interval_ms_show(struct device *dev, struct device_attribute *attr, char *buf) Loading @@ -47,9 +74,25 @@ static ssize_t soc_interval_ms_store(struct device *dev, DEVICE_ATTR_RW(soc_interval_ms); static int qg_fvss_delta_soc_interval_ms = 10000; module_param_named( fvss_soc_interval_ms, qg_fvss_delta_soc_interval_ms, int, 0600 ); static ssize_t fvss_delta_soc_interval_ms_show(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", qg_fvss_delta_soc_interval_ms); } static ssize_t fvss_delta_soc_interval_ms_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int val; if (kstrtos32(buf, 0, &val)) return -EINVAL; qg_fvss_delta_soc_interval_ms = val; return count; } DEVICE_ATTR_RW(fvss_delta_soc_interval_ms); static int qg_delta_soc_cold_interval_ms = 4000; static ssize_t soc_cold_interval_ms_show(struct device *dev, Loading Loading @@ -95,16 +138,32 @@ DEVICE_ATTR_RW(maint_soc_update_ms); /* FVSS scaling only based on VBAT */ static int qg_fvss_vbat_scaling = 1; module_param_named( fvss_vbat_scaling, qg_fvss_vbat_scaling, int, 0600 ); static ssize_t fvss_vbat_scaling_show(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", qg_fvss_vbat_scaling); } static ssize_t fvss_vbat_scaling_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int val; if (kstrtos32(buf, 0, &val)) return -EINVAL; qg_fvss_vbat_scaling = val; return count; } DEVICE_ATTR_RW(fvss_vbat_scaling); static int qg_process_fvss_soc(struct qpnp_qg *chip, int sys_soc) { int rc, vbat_uv = 0, vbat_cutoff_uv = chip->dt.vbatt_cutoff_mv * 1000; int soc_vbat = 0, wt_vbat = 0, wt_sys = 0, soc_fvss = 0; if (!chip->dt.fvss_enable) if (!chip->dt.fvss_enable && !(qg_ss_feature & QG_FVSS)) goto exit_soc_scale; if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) Loading Loading @@ -180,7 +239,7 @@ static int qg_process_tcss_soc(struct qpnp_qg *chip, int sys_soc) int soc_ibat, wt_ibat, wt_sys; union power_supply_propval prop = {0, }; if (!chip->dt.tcss_enable) if (!chip->dt.tcss_enable && !(qg_ss_feature & QG_TCSS)) goto exit_soc_scale; if (chip->sys_soc < (chip->dt.tcss_entry_soc * 100)) Loading Loading @@ -262,12 +321,60 @@ static int qg_process_tcss_soc(struct qpnp_qg *chip, int sys_soc) chip->tcss_entry_count = 0; skip_entry_count: chip->tcss_active = false; if (chip->dt.tcss_enable || (qg_ss_feature & QG_TCSS)) qg_dbg(chip, QG_DEBUG_SOC, "TCSS: Quit - enabled=%d sys_soc=%d tcss_entry_count=%d fifo_i_ua=%d\n", chip->dt.tcss_enable, sys_soc, chip->tcss_entry_count, chip->last_fifo_i_ua); return sys_soc; } #define BASS_SYS_MSOC_DELTA 2 static int qg_process_bass_soc(struct qpnp_qg *chip, int sys_soc) { int bass_soc = sys_soc, msoc = chip->msoc; int batt_soc = CAP(0, 100, DIV_ROUND_CLOSEST(chip->batt_soc, 100)); if (!chip->dt.bass_enable && !(qg_ss_feature & QG_BASS)) goto exit_soc_scale; qg_dbg(chip, QG_DEBUG_SOC, "BASS Entry: fifo_i=%d sys_soc=%d msoc=%d batt_soc=%d fvss_active=%d\n", chip->last_fifo_i_ua, sys_soc, msoc, batt_soc, chip->fvss_active); /* Skip BASS if FVSS is active */ if (chip->fvss_active) goto exit_soc_scale; if (((sys_soc - msoc) < BASS_SYS_MSOC_DELTA) || chip->last_fifo_i_ua <= 0) goto exit_soc_scale; if (!chip->bass_active) { chip->bass_active = true; chip->bsoc_bass_entry = batt_soc; } /* Drop the sys_soc by 1% if batt_soc has dropped */ if ((chip->bsoc_bass_entry - batt_soc) >= 1) { bass_soc = (msoc > 0) ? msoc - 1 : 0; chip->bass_active = false; } qg_dbg(chip, QG_DEBUG_SOC, "BASS Exit: fifo_i_ua=%d sys_soc=%d msoc=%d bsoc_bass_entry=%d batt_soc=%d bass_soc=%d\n", chip->last_fifo_i_ua, sys_soc, msoc, chip->bsoc_bass_entry, chip->batt_soc, bass_soc); return bass_soc; exit_soc_scale: chip->bass_active = false; if (chip->dt.bass_enable || (qg_ss_feature & QG_BASS)) qg_dbg(chip, QG_DEBUG_SOC, "BASS Quit: enabled=%d fifo_i_ua=%d sys_soc=%d msoc=%d batt_soc=%d\n", chip->dt.bass_enable, chip->last_fifo_i_ua, sys_soc, msoc, chip->batt_soc); return sys_soc; } int qg_adjust_sys_soc(struct qpnp_qg *chip) { int soc, vbat_uv, rc; Loading @@ -275,6 +382,7 @@ int qg_adjust_sys_soc(struct qpnp_qg *chip) chip->sys_soc = CAP(QG_MIN_SOC, QG_MAX_SOC, chip->sys_soc); /* TCSS */ chip->sys_soc = qg_process_tcss_soc(chip, chip->sys_soc); if (chip->sys_soc <= 50) { /* 0.5% */ Loading @@ -299,8 +407,12 @@ int qg_adjust_sys_soc(struct qpnp_qg *chip) qg_dbg(chip, QG_DEBUG_SOC, "sys_soc=%d adjusted sys_soc=%d\n", chip->sys_soc, soc); /* FVSS */ soc = qg_process_fvss_soc(chip, soc); /* BASS */ soc = qg_process_bass_soc(chip, soc); chip->last_adj_ssoc = soc; return soc; Loading drivers/power/supply/qcom/qg-soc.h +3 −0 Original line number Diff line number Diff line Loading @@ -14,5 +14,8 @@ int qg_adjust_sys_soc(struct qpnp_qg *chip); extern struct device_attribute dev_attr_soc_interval_ms; extern struct device_attribute dev_attr_soc_cold_interval_ms; extern struct device_attribute dev_attr_maint_soc_update_ms; extern struct device_attribute dev_attr_fvss_delta_soc_interval_ms; extern struct device_attribute dev_attr_fvss_vbat_scaling; extern struct device_attribute dev_attr_qg_ss_feature; #endif /* __QG_SOC_H__ */ drivers/power/supply/qcom/qpnp-qg.c +5 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,9 @@ static struct attribute *qg_attrs[] = { &dev_attr_soc_interval_ms.attr, &dev_attr_soc_cold_interval_ms.attr, &dev_attr_maint_soc_update_ms.attr, &dev_attr_fvss_delta_soc_interval_ms.attr, &dev_attr_fvss_vbat_scaling.attr, &dev_attr_qg_ss_feature.attr, NULL, }; ATTRIBUTE_GROUPS(qg); Loading Loading @@ -4280,6 +4283,8 @@ static int qg_parse_dt(struct qpnp_qg *chip) chip->dt.tcss_entry_soc = temp; } chip->dt.bass_enable = of_property_read_bool(node, "qcom,bass-enable"); chip->dt.multi_profile_load = of_property_read_bool(node, "qcom,multi-profile-load"); Loading Loading
drivers/power/supply/qcom/qg-core.h +3 −0 Original line number Diff line number Diff line Loading @@ -72,6 +72,7 @@ struct qg_dt { bool fvss_enable; bool multi_profile_load; bool tcss_enable; bool bass_enable; }; struct qg_esr_data { Loading Loading @@ -138,6 +139,7 @@ struct qpnp_qg { bool force_soc; bool fvss_active; bool tcss_active; bool bass_active; int charge_status; int charge_type; int chg_iterm_ma; Loading @@ -154,6 +156,7 @@ struct qpnp_qg { int soc_tcss; int tcss_entry_count; int max_fcc_limit_ma; int bsoc_bass_entry; u32 fifo_done_count; u32 wa_flags; u32 seq_no; Loading
drivers/power/supply/qcom/qg-soc.c +121 −9 Original line number Diff line number Diff line Loading @@ -20,11 +20,38 @@ #include "qg-profile-lib.h" #include "qg-soc.h" enum soc_scaling_feature { QG_FVSS = BIT(0), QG_TCSS = BIT(1), QG_BASS = BIT(2), }; #define DEFAULT_UPDATE_TIME_MS 64000 #define SOC_SCALE_HYST_MS 2000 #define VBAT_LOW_HYST_UV 50000 #define FULL_SOC 100 static int qg_ss_feature; static ssize_t qg_ss_feature_show(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "0x%4x\n", qg_ss_feature); } static ssize_t qg_ss_feature_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int val; if (kstrtos32(buf, 0, &val)) return -EINVAL; qg_ss_feature = val; return count; } DEVICE_ATTR_RW(qg_ss_feature); static int qg_delta_soc_interval_ms = 20000; static ssize_t soc_interval_ms_show(struct device *dev, struct device_attribute *attr, char *buf) Loading @@ -47,9 +74,25 @@ static ssize_t soc_interval_ms_store(struct device *dev, DEVICE_ATTR_RW(soc_interval_ms); static int qg_fvss_delta_soc_interval_ms = 10000; module_param_named( fvss_soc_interval_ms, qg_fvss_delta_soc_interval_ms, int, 0600 ); static ssize_t fvss_delta_soc_interval_ms_show(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", qg_fvss_delta_soc_interval_ms); } static ssize_t fvss_delta_soc_interval_ms_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int val; if (kstrtos32(buf, 0, &val)) return -EINVAL; qg_fvss_delta_soc_interval_ms = val; return count; } DEVICE_ATTR_RW(fvss_delta_soc_interval_ms); static int qg_delta_soc_cold_interval_ms = 4000; static ssize_t soc_cold_interval_ms_show(struct device *dev, Loading Loading @@ -95,16 +138,32 @@ DEVICE_ATTR_RW(maint_soc_update_ms); /* FVSS scaling only based on VBAT */ static int qg_fvss_vbat_scaling = 1; module_param_named( fvss_vbat_scaling, qg_fvss_vbat_scaling, int, 0600 ); static ssize_t fvss_vbat_scaling_show(struct device *dev, struct device_attribute *attr, char *buf) { return snprintf(buf, PAGE_SIZE, "%d\n", qg_fvss_vbat_scaling); } static ssize_t fvss_vbat_scaling_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int val; if (kstrtos32(buf, 0, &val)) return -EINVAL; qg_fvss_vbat_scaling = val; return count; } DEVICE_ATTR_RW(fvss_vbat_scaling); static int qg_process_fvss_soc(struct qpnp_qg *chip, int sys_soc) { int rc, vbat_uv = 0, vbat_cutoff_uv = chip->dt.vbatt_cutoff_mv * 1000; int soc_vbat = 0, wt_vbat = 0, wt_sys = 0, soc_fvss = 0; if (!chip->dt.fvss_enable) if (!chip->dt.fvss_enable && !(qg_ss_feature & QG_FVSS)) goto exit_soc_scale; if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) Loading Loading @@ -180,7 +239,7 @@ static int qg_process_tcss_soc(struct qpnp_qg *chip, int sys_soc) int soc_ibat, wt_ibat, wt_sys; union power_supply_propval prop = {0, }; if (!chip->dt.tcss_enable) if (!chip->dt.tcss_enable && !(qg_ss_feature & QG_TCSS)) goto exit_soc_scale; if (chip->sys_soc < (chip->dt.tcss_entry_soc * 100)) Loading Loading @@ -262,12 +321,60 @@ static int qg_process_tcss_soc(struct qpnp_qg *chip, int sys_soc) chip->tcss_entry_count = 0; skip_entry_count: chip->tcss_active = false; if (chip->dt.tcss_enable || (qg_ss_feature & QG_TCSS)) qg_dbg(chip, QG_DEBUG_SOC, "TCSS: Quit - enabled=%d sys_soc=%d tcss_entry_count=%d fifo_i_ua=%d\n", chip->dt.tcss_enable, sys_soc, chip->tcss_entry_count, chip->last_fifo_i_ua); return sys_soc; } #define BASS_SYS_MSOC_DELTA 2 static int qg_process_bass_soc(struct qpnp_qg *chip, int sys_soc) { int bass_soc = sys_soc, msoc = chip->msoc; int batt_soc = CAP(0, 100, DIV_ROUND_CLOSEST(chip->batt_soc, 100)); if (!chip->dt.bass_enable && !(qg_ss_feature & QG_BASS)) goto exit_soc_scale; qg_dbg(chip, QG_DEBUG_SOC, "BASS Entry: fifo_i=%d sys_soc=%d msoc=%d batt_soc=%d fvss_active=%d\n", chip->last_fifo_i_ua, sys_soc, msoc, batt_soc, chip->fvss_active); /* Skip BASS if FVSS is active */ if (chip->fvss_active) goto exit_soc_scale; if (((sys_soc - msoc) < BASS_SYS_MSOC_DELTA) || chip->last_fifo_i_ua <= 0) goto exit_soc_scale; if (!chip->bass_active) { chip->bass_active = true; chip->bsoc_bass_entry = batt_soc; } /* Drop the sys_soc by 1% if batt_soc has dropped */ if ((chip->bsoc_bass_entry - batt_soc) >= 1) { bass_soc = (msoc > 0) ? msoc - 1 : 0; chip->bass_active = false; } qg_dbg(chip, QG_DEBUG_SOC, "BASS Exit: fifo_i_ua=%d sys_soc=%d msoc=%d bsoc_bass_entry=%d batt_soc=%d bass_soc=%d\n", chip->last_fifo_i_ua, sys_soc, msoc, chip->bsoc_bass_entry, chip->batt_soc, bass_soc); return bass_soc; exit_soc_scale: chip->bass_active = false; if (chip->dt.bass_enable || (qg_ss_feature & QG_BASS)) qg_dbg(chip, QG_DEBUG_SOC, "BASS Quit: enabled=%d fifo_i_ua=%d sys_soc=%d msoc=%d batt_soc=%d\n", chip->dt.bass_enable, chip->last_fifo_i_ua, sys_soc, msoc, chip->batt_soc); return sys_soc; } int qg_adjust_sys_soc(struct qpnp_qg *chip) { int soc, vbat_uv, rc; Loading @@ -275,6 +382,7 @@ int qg_adjust_sys_soc(struct qpnp_qg *chip) chip->sys_soc = CAP(QG_MIN_SOC, QG_MAX_SOC, chip->sys_soc); /* TCSS */ chip->sys_soc = qg_process_tcss_soc(chip, chip->sys_soc); if (chip->sys_soc <= 50) { /* 0.5% */ Loading @@ -299,8 +407,12 @@ int qg_adjust_sys_soc(struct qpnp_qg *chip) qg_dbg(chip, QG_DEBUG_SOC, "sys_soc=%d adjusted sys_soc=%d\n", chip->sys_soc, soc); /* FVSS */ soc = qg_process_fvss_soc(chip, soc); /* BASS */ soc = qg_process_bass_soc(chip, soc); chip->last_adj_ssoc = soc; return soc; Loading
drivers/power/supply/qcom/qg-soc.h +3 −0 Original line number Diff line number Diff line Loading @@ -14,5 +14,8 @@ int qg_adjust_sys_soc(struct qpnp_qg *chip); extern struct device_attribute dev_attr_soc_interval_ms; extern struct device_attribute dev_attr_soc_cold_interval_ms; extern struct device_attribute dev_attr_maint_soc_update_ms; extern struct device_attribute dev_attr_fvss_delta_soc_interval_ms; extern struct device_attribute dev_attr_fvss_vbat_scaling; extern struct device_attribute dev_attr_qg_ss_feature; #endif /* __QG_SOC_H__ */
drivers/power/supply/qcom/qpnp-qg.c +5 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,9 @@ static struct attribute *qg_attrs[] = { &dev_attr_soc_interval_ms.attr, &dev_attr_soc_cold_interval_ms.attr, &dev_attr_maint_soc_update_ms.attr, &dev_attr_fvss_delta_soc_interval_ms.attr, &dev_attr_fvss_vbat_scaling.attr, &dev_attr_qg_ss_feature.attr, NULL, }; ATTRIBUTE_GROUPS(qg); Loading Loading @@ -4280,6 +4283,8 @@ static int qg_parse_dt(struct qpnp_qg *chip) chip->dt.tcss_entry_soc = temp; } chip->dt.bass_enable = of_property_read_bool(node, "qcom,bass-enable"); chip->dt.multi_profile_load = of_property_read_bool(node, "qcom,multi-profile-load"); Loading