Loading Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt +14 −0 Original line number Diff line number Diff line Loading @@ -404,6 +404,20 @@ First Level Node - QGAUGE device 'qcom,qg-fast-chg-config' is enabled. The default value if not specified is 1. - qcom,fvss-enable Usage: optional Value type: bool Definition: Enable Filtered Voltage based SOC scaling. This logic enables SOC scaling to report 0 at the cutoff voltage. - qcom,fvss-vbatt-mv Usage: optional Value type: <u32> Definition: Battery voltage threshold at which FVSS is enabled. Applicable only if 'qcom,fvss-enable' is set. ========================================================== Second Level Nodes - Peripherals managed by QGAUGE driver ========================================================== Loading drivers/power/supply/qcom/qg-core.h +7 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ struct qg_dt { int shutdown_soc_threshold; int min_sleep_time_secs; int sys_min_volt_mv; int fvss_vbat_mv; bool hold_soc_while_full; bool linearize_soc; bool cl_disable; Loading @@ -73,6 +74,7 @@ struct qg_dt { bool use_s7_ocv; bool qg_sleep_config; bool qg_fast_chg_cfg; bool fvss_enable; }; struct qg_esr_data { Loading Loading @@ -134,6 +136,7 @@ struct qpnp_qg { bool dc_present; bool charge_full; bool force_soc; bool fvss_active; int charge_status; int charge_type; int chg_iterm_ma; Loading @@ -142,6 +145,8 @@ struct qpnp_qg { int esr_nominal; int soh; int soc_reporting_ready; int last_fifo_v_uv; int last_fifo_i_ua; u32 fifo_done_count; u32 wa_flags; u32 seq_no; Loading @@ -150,6 +155,8 @@ struct qpnp_qg { u32 esr_last; u32 s2_state; u32 s2_state_mask; u32 soc_fvss_entry; u32 vbat_fvss_entry; ktime_t last_user_update_time; ktime_t last_fifo_update_time; unsigned long last_maint_soc_update_time; Loading drivers/power/supply/qcom/qg-soc.c +91 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include "qg-reg.h" #include "qg-util.h" #include "qg-defs.h" #include "qg-profile-lib.h" #include "qg-soc.h" #define DEFAULT_UPDATE_TIME_MS 64000 Loading @@ -36,6 +37,11 @@ module_param_named( soc_interval_ms, qg_delta_soc_interval_ms, int, 0600 ); 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 int qg_delta_soc_cold_interval_ms = 4000; module_param_named( soc_cold_interval_ms, qg_delta_soc_cold_interval_ms, int, 0600 Loading @@ -46,6 +52,84 @@ module_param_named( maint_soc_update_ms, qg_maint_soc_update_ms, int, 0600 ); /* 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 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) return 0; if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) goto exit_soc_scale; rc = qg_get_battery_voltage(chip, &vbat_uv); if (rc < 0) goto exit_soc_scale; if (!chip->last_fifo_v_uv) chip->last_fifo_v_uv = vbat_uv; if (chip->last_fifo_v_uv > (chip->dt.fvss_vbat_mv * 1000)) { qg_dbg(chip, QG_DEBUG_SOC, "FVSS: last_fifo_v=%d fvss_entry_uv=%d - exit\n", chip->last_fifo_v_uv, chip->dt.fvss_vbat_mv * 1000); goto exit_soc_scale; } /* Enter FVSS */ if (!chip->fvss_active) { chip->vbat_fvss_entry = CAP(vbat_cutoff_uv, chip->dt.fvss_vbat_mv * 1000, chip->last_fifo_v_uv); chip->soc_fvss_entry = sys_soc; chip->fvss_active = true; } else if (chip->last_fifo_v_uv > chip->vbat_fvss_entry) { /* VBAT has gone beyond the entry voltage */ chip->vbat_fvss_entry = chip->last_fifo_v_uv; chip->soc_fvss_entry = sys_soc; } soc_vbat = qg_linear_interpolate(chip->soc_fvss_entry, chip->vbat_fvss_entry, 0, vbat_cutoff_uv, chip->last_fifo_v_uv); soc_vbat = CAP(0, 100, soc_vbat); if (qg_fvss_vbat_scaling) { wt_vbat = 100; wt_sys = 0; } else { wt_sys = qg_linear_interpolate(100, chip->soc_fvss_entry, 0, 0, sys_soc); wt_sys = CAP(0, 100, wt_sys); wt_vbat = 100 - wt_sys; } soc_fvss = ((soc_vbat * wt_vbat) + (sys_soc * wt_sys)) / 100; soc_fvss = CAP(0, 100, soc_fvss); qg_dbg(chip, QG_DEBUG_SOC, "FVSS: vbat_fvss_entry=%d soc_fvss_entry=%d cutoff_uv=%d vbat_uv=%d fifo_avg_v=%d soc_vbat=%d sys_soc=%d wt_vbat=%d wt_sys=%d soc_fvss=%d\n", chip->vbat_fvss_entry, chip->soc_fvss_entry, vbat_cutoff_uv, vbat_uv, chip->last_fifo_v_uv, soc_vbat, sys_soc, wt_vbat, wt_sys, soc_fvss); return soc_fvss; exit_soc_scale: chip->fvss_active = false; return sys_soc; } int qg_adjust_sys_soc(struct qpnp_qg *chip) { int soc, vbat_uv, rc; Loading @@ -72,8 +156,11 @@ int qg_adjust_sys_soc(struct qpnp_qg *chip) soc = DIV_ROUND_CLOSEST(chip->sys_soc, 100); } qg_dbg(chip, QG_DEBUG_SOC, "last_adj_sys_soc=%d adj_sys_soc=%d\n", chip->last_adj_ssoc, soc); qg_dbg(chip, QG_DEBUG_SOC, "sys_soc=%d adjusted sys_soc=%d\n", chip->sys_soc, soc); soc = qg_process_fvss_soc(chip, soc); chip->last_adj_ssoc = soc; return soc; Loading Loading @@ -103,6 +190,8 @@ static void get_next_update_time(struct qpnp_qg *chip) else if (chip->maint_soc > 0 && chip->maint_soc >= chip->recharge_soc) /* if in maintenance mode scale slower */ min_delta_soc_interval_ms = qg_maint_soc_update_ms; else if (chip->fvss_active) min_delta_soc_interval_ms = qg_fvss_delta_soc_interval_ms; if (!min_delta_soc_interval_ms) min_delta_soc_interval_ms = 1000; /* 1 second */ Loading drivers/power/supply/qcom/qpnp-qg.c +23 −0 Original line number Diff line number Diff line Loading @@ -460,6 +460,9 @@ static int qg_process_fifo(struct qpnp_qg *chip, u32 fifo_length) chip->kdata.fifo[j].interval = sample_interval; chip->kdata.fifo[j].count = sample_count; chip->last_fifo_v_uv = chip->kdata.fifo[j].v; chip->last_fifo_i_ua = chip->kdata.fifo[j].i; qg_dbg(chip, QG_DEBUG_FIFO, "FIFO %d raw_v=%d uV=%d raw_i=%d uA=%d interval=%d count=%d\n", j, fifo_v, chip->kdata.fifo[j].v, Loading Loading @@ -524,6 +527,9 @@ static int qg_process_accumulator(struct qpnp_qg *chip) if (chip->kdata.fifo_length == MAX_FIFO_LENGTH) chip->kdata.fifo_length = MAX_FIFO_LENGTH - 1; chip->last_fifo_v_uv = chip->kdata.fifo[index].v; chip->last_fifo_i_ua = chip->kdata.fifo[index].i; if (chip->kdata.fifo_length == 1) /* Only accumulator data */ chip->kdata.seq_no = chip->seq_no++ % U32_MAX; Loading Loading @@ -2068,6 +2074,9 @@ static int qg_psy_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_POWER_AVG: rc = qg_get_power(chip, &pval->intval, true); break; case POWER_SUPPLY_PROP_SCALE_MODE_EN: pval->intval = chip->fvss_active; break; default: pr_debug("Unsupported property %d\n", psp); break; Loading Loading @@ -2126,6 +2135,7 @@ static enum power_supply_property qg_psy_props[] = { POWER_SUPPLY_PROP_VOLTAGE_AVG, POWER_SUPPLY_PROP_POWER_AVG, POWER_SUPPLY_PROP_POWER_NOW, POWER_SUPPLY_PROP_SCALE_MODE_EN, }; static const struct power_supply_desc qg_psy_desc = { Loading Loading @@ -3601,6 +3611,7 @@ static int qg_alg_init(struct qpnp_qg *chip) #define DEFAULT_SLEEP_TIME_SECS 1800 /* 30 mins */ #define DEFAULT_SYS_MIN_VOLT_MV 2800 #define DEFAULT_FAST_CHG_S2_FIFO_LENGTH 1 #define DEFAULT_FVSS_VBAT_MV 3500 static int qg_parse_dt(struct qpnp_qg *chip) { int rc = 0; Loading Loading @@ -3895,6 +3906,18 @@ static int qg_parse_dt(struct qpnp_qg *chip) else chip->dt.min_sleep_time_secs = temp; if (of_property_read_bool(node, "qcom,fvss-enable")) { chip->dt.fvss_enable = true; rc = of_property_read_u32(node, "qcom,fvss-vbatt-mv", &temp); if (rc < 0) chip->dt.fvss_vbat_mv = DEFAULT_FVSS_VBAT_MV; else chip->dt.fvss_vbat_mv = temp; } /* Capacity learning params*/ if (!chip->dt.cl_disable) { chip->dt.cl_feedback_on = of_property_read_bool(node, Loading Loading
Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt +14 −0 Original line number Diff line number Diff line Loading @@ -404,6 +404,20 @@ First Level Node - QGAUGE device 'qcom,qg-fast-chg-config' is enabled. The default value if not specified is 1. - qcom,fvss-enable Usage: optional Value type: bool Definition: Enable Filtered Voltage based SOC scaling. This logic enables SOC scaling to report 0 at the cutoff voltage. - qcom,fvss-vbatt-mv Usage: optional Value type: <u32> Definition: Battery voltage threshold at which FVSS is enabled. Applicable only if 'qcom,fvss-enable' is set. ========================================================== Second Level Nodes - Peripherals managed by QGAUGE driver ========================================================== Loading
drivers/power/supply/qcom/qg-core.h +7 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,7 @@ struct qg_dt { int shutdown_soc_threshold; int min_sleep_time_secs; int sys_min_volt_mv; int fvss_vbat_mv; bool hold_soc_while_full; bool linearize_soc; bool cl_disable; Loading @@ -73,6 +74,7 @@ struct qg_dt { bool use_s7_ocv; bool qg_sleep_config; bool qg_fast_chg_cfg; bool fvss_enable; }; struct qg_esr_data { Loading Loading @@ -134,6 +136,7 @@ struct qpnp_qg { bool dc_present; bool charge_full; bool force_soc; bool fvss_active; int charge_status; int charge_type; int chg_iterm_ma; Loading @@ -142,6 +145,8 @@ struct qpnp_qg { int esr_nominal; int soh; int soc_reporting_ready; int last_fifo_v_uv; int last_fifo_i_ua; u32 fifo_done_count; u32 wa_flags; u32 seq_no; Loading @@ -150,6 +155,8 @@ struct qpnp_qg { u32 esr_last; u32 s2_state; u32 s2_state_mask; u32 soc_fvss_entry; u32 vbat_fvss_entry; ktime_t last_user_update_time; ktime_t last_fifo_update_time; unsigned long last_maint_soc_update_time; Loading
drivers/power/supply/qcom/qg-soc.c +91 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include "qg-reg.h" #include "qg-util.h" #include "qg-defs.h" #include "qg-profile-lib.h" #include "qg-soc.h" #define DEFAULT_UPDATE_TIME_MS 64000 Loading @@ -36,6 +37,11 @@ module_param_named( soc_interval_ms, qg_delta_soc_interval_ms, int, 0600 ); 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 int qg_delta_soc_cold_interval_ms = 4000; module_param_named( soc_cold_interval_ms, qg_delta_soc_cold_interval_ms, int, 0600 Loading @@ -46,6 +52,84 @@ module_param_named( maint_soc_update_ms, qg_maint_soc_update_ms, int, 0600 ); /* 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 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) return 0; if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) goto exit_soc_scale; rc = qg_get_battery_voltage(chip, &vbat_uv); if (rc < 0) goto exit_soc_scale; if (!chip->last_fifo_v_uv) chip->last_fifo_v_uv = vbat_uv; if (chip->last_fifo_v_uv > (chip->dt.fvss_vbat_mv * 1000)) { qg_dbg(chip, QG_DEBUG_SOC, "FVSS: last_fifo_v=%d fvss_entry_uv=%d - exit\n", chip->last_fifo_v_uv, chip->dt.fvss_vbat_mv * 1000); goto exit_soc_scale; } /* Enter FVSS */ if (!chip->fvss_active) { chip->vbat_fvss_entry = CAP(vbat_cutoff_uv, chip->dt.fvss_vbat_mv * 1000, chip->last_fifo_v_uv); chip->soc_fvss_entry = sys_soc; chip->fvss_active = true; } else if (chip->last_fifo_v_uv > chip->vbat_fvss_entry) { /* VBAT has gone beyond the entry voltage */ chip->vbat_fvss_entry = chip->last_fifo_v_uv; chip->soc_fvss_entry = sys_soc; } soc_vbat = qg_linear_interpolate(chip->soc_fvss_entry, chip->vbat_fvss_entry, 0, vbat_cutoff_uv, chip->last_fifo_v_uv); soc_vbat = CAP(0, 100, soc_vbat); if (qg_fvss_vbat_scaling) { wt_vbat = 100; wt_sys = 0; } else { wt_sys = qg_linear_interpolate(100, chip->soc_fvss_entry, 0, 0, sys_soc); wt_sys = CAP(0, 100, wt_sys); wt_vbat = 100 - wt_sys; } soc_fvss = ((soc_vbat * wt_vbat) + (sys_soc * wt_sys)) / 100; soc_fvss = CAP(0, 100, soc_fvss); qg_dbg(chip, QG_DEBUG_SOC, "FVSS: vbat_fvss_entry=%d soc_fvss_entry=%d cutoff_uv=%d vbat_uv=%d fifo_avg_v=%d soc_vbat=%d sys_soc=%d wt_vbat=%d wt_sys=%d soc_fvss=%d\n", chip->vbat_fvss_entry, chip->soc_fvss_entry, vbat_cutoff_uv, vbat_uv, chip->last_fifo_v_uv, soc_vbat, sys_soc, wt_vbat, wt_sys, soc_fvss); return soc_fvss; exit_soc_scale: chip->fvss_active = false; return sys_soc; } int qg_adjust_sys_soc(struct qpnp_qg *chip) { int soc, vbat_uv, rc; Loading @@ -72,8 +156,11 @@ int qg_adjust_sys_soc(struct qpnp_qg *chip) soc = DIV_ROUND_CLOSEST(chip->sys_soc, 100); } qg_dbg(chip, QG_DEBUG_SOC, "last_adj_sys_soc=%d adj_sys_soc=%d\n", chip->last_adj_ssoc, soc); qg_dbg(chip, QG_DEBUG_SOC, "sys_soc=%d adjusted sys_soc=%d\n", chip->sys_soc, soc); soc = qg_process_fvss_soc(chip, soc); chip->last_adj_ssoc = soc; return soc; Loading Loading @@ -103,6 +190,8 @@ static void get_next_update_time(struct qpnp_qg *chip) else if (chip->maint_soc > 0 && chip->maint_soc >= chip->recharge_soc) /* if in maintenance mode scale slower */ min_delta_soc_interval_ms = qg_maint_soc_update_ms; else if (chip->fvss_active) min_delta_soc_interval_ms = qg_fvss_delta_soc_interval_ms; if (!min_delta_soc_interval_ms) min_delta_soc_interval_ms = 1000; /* 1 second */ Loading
drivers/power/supply/qcom/qpnp-qg.c +23 −0 Original line number Diff line number Diff line Loading @@ -460,6 +460,9 @@ static int qg_process_fifo(struct qpnp_qg *chip, u32 fifo_length) chip->kdata.fifo[j].interval = sample_interval; chip->kdata.fifo[j].count = sample_count; chip->last_fifo_v_uv = chip->kdata.fifo[j].v; chip->last_fifo_i_ua = chip->kdata.fifo[j].i; qg_dbg(chip, QG_DEBUG_FIFO, "FIFO %d raw_v=%d uV=%d raw_i=%d uA=%d interval=%d count=%d\n", j, fifo_v, chip->kdata.fifo[j].v, Loading Loading @@ -524,6 +527,9 @@ static int qg_process_accumulator(struct qpnp_qg *chip) if (chip->kdata.fifo_length == MAX_FIFO_LENGTH) chip->kdata.fifo_length = MAX_FIFO_LENGTH - 1; chip->last_fifo_v_uv = chip->kdata.fifo[index].v; chip->last_fifo_i_ua = chip->kdata.fifo[index].i; if (chip->kdata.fifo_length == 1) /* Only accumulator data */ chip->kdata.seq_no = chip->seq_no++ % U32_MAX; Loading Loading @@ -2068,6 +2074,9 @@ static int qg_psy_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_POWER_AVG: rc = qg_get_power(chip, &pval->intval, true); break; case POWER_SUPPLY_PROP_SCALE_MODE_EN: pval->intval = chip->fvss_active; break; default: pr_debug("Unsupported property %d\n", psp); break; Loading Loading @@ -2126,6 +2135,7 @@ static enum power_supply_property qg_psy_props[] = { POWER_SUPPLY_PROP_VOLTAGE_AVG, POWER_SUPPLY_PROP_POWER_AVG, POWER_SUPPLY_PROP_POWER_NOW, POWER_SUPPLY_PROP_SCALE_MODE_EN, }; static const struct power_supply_desc qg_psy_desc = { Loading Loading @@ -3601,6 +3611,7 @@ static int qg_alg_init(struct qpnp_qg *chip) #define DEFAULT_SLEEP_TIME_SECS 1800 /* 30 mins */ #define DEFAULT_SYS_MIN_VOLT_MV 2800 #define DEFAULT_FAST_CHG_S2_FIFO_LENGTH 1 #define DEFAULT_FVSS_VBAT_MV 3500 static int qg_parse_dt(struct qpnp_qg *chip) { int rc = 0; Loading Loading @@ -3895,6 +3906,18 @@ static int qg_parse_dt(struct qpnp_qg *chip) else chip->dt.min_sleep_time_secs = temp; if (of_property_read_bool(node, "qcom,fvss-enable")) { chip->dt.fvss_enable = true; rc = of_property_read_u32(node, "qcom,fvss-vbatt-mv", &temp); if (rc < 0) chip->dt.fvss_vbat_mv = DEFAULT_FVSS_VBAT_MV; else chip->dt.fvss_vbat_mv = temp; } /* Capacity learning params*/ if (!chip->dt.cl_disable) { chip->dt.cl_feedback_on = of_property_read_bool(node, Loading