Loading drivers/power/supply/qcom/qg-core.h +8 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ struct qg_dt { int min_sleep_time_secs; int sys_min_volt_mv; int fvss_vbat_mv; int tcss_entry_soc; bool hold_soc_while_full; bool linearize_soc; bool cl_disable; Loading @@ -70,6 +71,7 @@ struct qg_dt { bool qg_fast_chg_cfg; bool fvss_enable; bool multi_profile_load; bool tcss_enable; }; struct qg_esr_data { Loading Loading @@ -135,6 +137,7 @@ struct qpnp_qg { bool charge_full; bool force_soc; bool fvss_active; bool tcss_active; int charge_status; int charge_type; int chg_iterm_ma; Loading @@ -145,6 +148,11 @@ struct qpnp_qg { int soc_reporting_ready; int last_fifo_v_uv; int last_fifo_i_ua; int prev_fifo_i_ua; int soc_tcss_entry; int ibat_tcss_entry; int soc_tcss; int tcss_entry_count; u32 fifo_done_count; u32 wa_flags; u32 seq_no; Loading drivers/power/supply/qcom/qg-soc.c +99 −0 Original line number Diff line number Diff line Loading @@ -171,6 +171,103 @@ static int qg_process_fvss_soc(struct qpnp_qg *chip, int sys_soc) return sys_soc; } #define IBAT_HYST_PC 10 #define TCSS_ENTRY_COUNT 2 static int qg_process_tcss_soc(struct qpnp_qg *chip, int sys_soc) { int rc, ibatt_diff = 0, ibat_inc_hyst = 0; int qg_iterm_ua = (-1 * chip->dt.iterm_ma * 1000); int soc_ibat, wt_ibat, wt_sys; union power_supply_propval prop = {0, }; if (!chip->dt.tcss_enable) goto exit_soc_scale; if (chip->sys_soc < (chip->dt.tcss_entry_soc * 100)) goto exit_soc_scale; if (chip->sys_soc >= QG_MAX_SOC && chip->soc_tcss >= QG_MAX_SOC) goto exit_soc_scale; rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH, &prop); if (!rc && (prop.intval == POWER_SUPPLY_HEALTH_COOL || prop.intval == POWER_SUPPLY_HEALTH_WARM)) goto exit_soc_scale; if (chip->last_fifo_i_ua >= 0) goto exit_soc_scale; else if (++chip->tcss_entry_count < TCSS_ENTRY_COUNT) goto skip_entry_count; if (!chip->tcss_active) { chip->soc_tcss = sys_soc; chip->soc_tcss_entry = sys_soc; chip->ibat_tcss_entry = min(chip->last_fifo_i_ua, qg_iterm_ua); chip->prev_fifo_i_ua = chip->last_fifo_i_ua; chip->tcss_active = true; } rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED, &prop); if (!rc && prop.intval) { qg_dbg(chip, QG_DEBUG_SOC, "Input limited sys_soc=%d soc_tcss=%d\n", sys_soc, chip->soc_tcss); if (chip->soc_tcss > sys_soc) sys_soc = chip->soc_tcss; goto exit_soc_scale; } ibatt_diff = chip->last_fifo_i_ua - chip->prev_fifo_i_ua; if (ibatt_diff > 0) { /* * if the battery charge current has suddendly dropped, allow it * to decrease only by a small fraction to avoid a SOC jump. */ ibat_inc_hyst = (chip->prev_fifo_i_ua * IBAT_HYST_PC) / 100; if (ibatt_diff > abs(ibat_inc_hyst)) chip->prev_fifo_i_ua -= ibat_inc_hyst; else chip->prev_fifo_i_ua = chip->last_fifo_i_ua; } chip->prev_fifo_i_ua = min(chip->prev_fifo_i_ua, qg_iterm_ua); soc_ibat = qg_linear_interpolate(chip->soc_tcss_entry, chip->ibat_tcss_entry, QG_MAX_SOC, qg_iterm_ua, chip->prev_fifo_i_ua); soc_ibat = CAP(QG_MIN_SOC, QG_MAX_SOC, soc_ibat); wt_ibat = qg_linear_interpolate(1, chip->soc_tcss_entry, 10000, 10000, soc_ibat); wt_ibat = CAP(QG_MIN_SOC, QG_MAX_SOC, wt_ibat); wt_sys = 10000 - wt_ibat; chip->soc_tcss = DIV_ROUND_CLOSEST((soc_ibat * wt_ibat) + (wt_sys * sys_soc), 10000); chip->soc_tcss = CAP(QG_MIN_SOC, QG_MAX_SOC, chip->soc_tcss); qg_dbg(chip, QG_DEBUG_SOC, "TCSS: fifo_i=%d prev_fifo_i=%d ibatt_tcss_entry=%d qg_term=%d soc_tcss_entry=%d sys_soc=%d soc_ibat=%d wt_ibat=%d wt_sys=%d soc_tcss=%d\n", chip->last_fifo_i_ua, chip->prev_fifo_i_ua, chip->ibat_tcss_entry, qg_iterm_ua, chip->soc_tcss_entry, sys_soc, soc_ibat, wt_ibat, wt_sys, chip->soc_tcss); return chip->soc_tcss; exit_soc_scale: chip->tcss_entry_count = 0; skip_entry_count: chip->tcss_active = false; 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; } int qg_adjust_sys_soc(struct qpnp_qg *chip) { int soc, vbat_uv, rc; Loading @@ -178,6 +275,8 @@ int qg_adjust_sys_soc(struct qpnp_qg *chip) chip->sys_soc = CAP(QG_MIN_SOC, QG_MAX_SOC, chip->sys_soc); chip->sys_soc = qg_process_tcss_soc(chip, chip->sys_soc); if (chip->sys_soc <= 50) { /* 0.5% */ /* Hold SOC to 1% of VBAT has not dropped below cutoff */ rc = qg_get_battery_voltage(chip, &vbat_uv); Loading drivers/power/supply/qcom/qpnp-qg.c +13 −0 Original line number Diff line number Diff line Loading @@ -4006,6 +4006,7 @@ static int qg_parse_cl_dt(struct qpnp_qg *chip) #define DEFAULT_SLEEP_TIME_SECS 1800 /* 30 mins */ #define DEFAULT_SYS_MIN_VOLT_MV 2800 #define DEFAULT_FVSS_VBAT_MV 3500 #define DEFAULT_TCSS_ENTRY_SOC 90 static int qg_parse_dt(struct qpnp_qg *chip) { int rc = 0; Loading Loading @@ -4249,6 +4250,18 @@ static int qg_parse_dt(struct qpnp_qg *chip) chip->dt.fvss_vbat_mv = temp; } if (of_property_read_bool(node, "qcom,tcss-enable")) { chip->dt.tcss_enable = true; rc = of_property_read_u32(node, "qcom,tcss-entry-soc", &temp); if (rc < 0) chip->dt.tcss_entry_soc = DEFAULT_TCSS_ENTRY_SOC; else chip->dt.tcss_entry_soc = temp; } chip->dt.multi_profile_load = of_property_read_bool(node, "qcom,multi-profile-load"); Loading Loading
drivers/power/supply/qcom/qg-core.h +8 −0 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ struct qg_dt { int min_sleep_time_secs; int sys_min_volt_mv; int fvss_vbat_mv; int tcss_entry_soc; bool hold_soc_while_full; bool linearize_soc; bool cl_disable; Loading @@ -70,6 +71,7 @@ struct qg_dt { bool qg_fast_chg_cfg; bool fvss_enable; bool multi_profile_load; bool tcss_enable; }; struct qg_esr_data { Loading Loading @@ -135,6 +137,7 @@ struct qpnp_qg { bool charge_full; bool force_soc; bool fvss_active; bool tcss_active; int charge_status; int charge_type; int chg_iterm_ma; Loading @@ -145,6 +148,11 @@ struct qpnp_qg { int soc_reporting_ready; int last_fifo_v_uv; int last_fifo_i_ua; int prev_fifo_i_ua; int soc_tcss_entry; int ibat_tcss_entry; int soc_tcss; int tcss_entry_count; u32 fifo_done_count; u32 wa_flags; u32 seq_no; Loading
drivers/power/supply/qcom/qg-soc.c +99 −0 Original line number Diff line number Diff line Loading @@ -171,6 +171,103 @@ static int qg_process_fvss_soc(struct qpnp_qg *chip, int sys_soc) return sys_soc; } #define IBAT_HYST_PC 10 #define TCSS_ENTRY_COUNT 2 static int qg_process_tcss_soc(struct qpnp_qg *chip, int sys_soc) { int rc, ibatt_diff = 0, ibat_inc_hyst = 0; int qg_iterm_ua = (-1 * chip->dt.iterm_ma * 1000); int soc_ibat, wt_ibat, wt_sys; union power_supply_propval prop = {0, }; if (!chip->dt.tcss_enable) goto exit_soc_scale; if (chip->sys_soc < (chip->dt.tcss_entry_soc * 100)) goto exit_soc_scale; if (chip->sys_soc >= QG_MAX_SOC && chip->soc_tcss >= QG_MAX_SOC) goto exit_soc_scale; rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_HEALTH, &prop); if (!rc && (prop.intval == POWER_SUPPLY_HEALTH_COOL || prop.intval == POWER_SUPPLY_HEALTH_WARM)) goto exit_soc_scale; if (chip->last_fifo_i_ua >= 0) goto exit_soc_scale; else if (++chip->tcss_entry_count < TCSS_ENTRY_COUNT) goto skip_entry_count; if (!chip->tcss_active) { chip->soc_tcss = sys_soc; chip->soc_tcss_entry = sys_soc; chip->ibat_tcss_entry = min(chip->last_fifo_i_ua, qg_iterm_ua); chip->prev_fifo_i_ua = chip->last_fifo_i_ua; chip->tcss_active = true; } rc = power_supply_get_property(chip->batt_psy, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED, &prop); if (!rc && prop.intval) { qg_dbg(chip, QG_DEBUG_SOC, "Input limited sys_soc=%d soc_tcss=%d\n", sys_soc, chip->soc_tcss); if (chip->soc_tcss > sys_soc) sys_soc = chip->soc_tcss; goto exit_soc_scale; } ibatt_diff = chip->last_fifo_i_ua - chip->prev_fifo_i_ua; if (ibatt_diff > 0) { /* * if the battery charge current has suddendly dropped, allow it * to decrease only by a small fraction to avoid a SOC jump. */ ibat_inc_hyst = (chip->prev_fifo_i_ua * IBAT_HYST_PC) / 100; if (ibatt_diff > abs(ibat_inc_hyst)) chip->prev_fifo_i_ua -= ibat_inc_hyst; else chip->prev_fifo_i_ua = chip->last_fifo_i_ua; } chip->prev_fifo_i_ua = min(chip->prev_fifo_i_ua, qg_iterm_ua); soc_ibat = qg_linear_interpolate(chip->soc_tcss_entry, chip->ibat_tcss_entry, QG_MAX_SOC, qg_iterm_ua, chip->prev_fifo_i_ua); soc_ibat = CAP(QG_MIN_SOC, QG_MAX_SOC, soc_ibat); wt_ibat = qg_linear_interpolate(1, chip->soc_tcss_entry, 10000, 10000, soc_ibat); wt_ibat = CAP(QG_MIN_SOC, QG_MAX_SOC, wt_ibat); wt_sys = 10000 - wt_ibat; chip->soc_tcss = DIV_ROUND_CLOSEST((soc_ibat * wt_ibat) + (wt_sys * sys_soc), 10000); chip->soc_tcss = CAP(QG_MIN_SOC, QG_MAX_SOC, chip->soc_tcss); qg_dbg(chip, QG_DEBUG_SOC, "TCSS: fifo_i=%d prev_fifo_i=%d ibatt_tcss_entry=%d qg_term=%d soc_tcss_entry=%d sys_soc=%d soc_ibat=%d wt_ibat=%d wt_sys=%d soc_tcss=%d\n", chip->last_fifo_i_ua, chip->prev_fifo_i_ua, chip->ibat_tcss_entry, qg_iterm_ua, chip->soc_tcss_entry, sys_soc, soc_ibat, wt_ibat, wt_sys, chip->soc_tcss); return chip->soc_tcss; exit_soc_scale: chip->tcss_entry_count = 0; skip_entry_count: chip->tcss_active = false; 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; } int qg_adjust_sys_soc(struct qpnp_qg *chip) { int soc, vbat_uv, rc; Loading @@ -178,6 +275,8 @@ int qg_adjust_sys_soc(struct qpnp_qg *chip) chip->sys_soc = CAP(QG_MIN_SOC, QG_MAX_SOC, chip->sys_soc); chip->sys_soc = qg_process_tcss_soc(chip, chip->sys_soc); if (chip->sys_soc <= 50) { /* 0.5% */ /* Hold SOC to 1% of VBAT has not dropped below cutoff */ rc = qg_get_battery_voltage(chip, &vbat_uv); Loading
drivers/power/supply/qcom/qpnp-qg.c +13 −0 Original line number Diff line number Diff line Loading @@ -4006,6 +4006,7 @@ static int qg_parse_cl_dt(struct qpnp_qg *chip) #define DEFAULT_SLEEP_TIME_SECS 1800 /* 30 mins */ #define DEFAULT_SYS_MIN_VOLT_MV 2800 #define DEFAULT_FVSS_VBAT_MV 3500 #define DEFAULT_TCSS_ENTRY_SOC 90 static int qg_parse_dt(struct qpnp_qg *chip) { int rc = 0; Loading Loading @@ -4249,6 +4250,18 @@ static int qg_parse_dt(struct qpnp_qg *chip) chip->dt.fvss_vbat_mv = temp; } if (of_property_read_bool(node, "qcom,tcss-enable")) { chip->dt.tcss_enable = true; rc = of_property_read_u32(node, "qcom,tcss-entry-soc", &temp); if (rc < 0) chip->dt.tcss_entry_soc = DEFAULT_TCSS_ENTRY_SOC; else chip->dt.tcss_entry_soc = temp; } chip->dt.multi_profile_load = of_property_read_bool(node, "qcom,multi-profile-load"); Loading