Loading Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt +14 −0 Original line number Diff line number Diff line Loading @@ -245,6 +245,20 @@ First Level Node - FG Gen4 device capacity learning cycle. If this is not specified, then the default value is 0. Unit is in decipercentage. - qcom,cl-min-delta-batt-soc Usage: optional Value type: <u32> Definition: Minimum change in battery SOC to qualify for capacity learning. If this is not specified, then the default value is 10. Unit is in percentage. - qcom,cl-wt-enable Usage: optional Value type: <empty> Definition: A boolean property to enable weighted capacity learning based on change in battery SOC during a charging cycle. If this is specified "qcom,cl-start-capacity" is not used. - qcom,hold-soc-while-full Usage: optional Value type: <empty> Loading Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt +15 −0 Original line number Diff line number Diff line Loading @@ -262,6 +262,21 @@ First Level Node - QGAUGE device capacity learning cycle. If this is not specified, then the default value is 0. Unit is in decipercentage. - qcom,cl-min-delta-batt-soc Usage: optional Value type: <u32> Definition: Minimum change in battery SOC to qualify for capacity learning. If this is not specified, then the default value is 10. Unit is in percentage. - qcom,cl-wt-enable Usage: optional Value type: <empty> Definition: A boolean property to enable weighted capacity learning based on change in battery SOC during a charging cycle. If this is specified, then "qcom,cl-min-start-soc" and "qcom,cl-max-start-soc" is not used. - qcom,esr-disable Usage: optional Value type: <bool> Loading drivers/power/supply/qcom/fg-alg.c +107 −20 Original line number Diff line number Diff line Loading @@ -369,17 +369,63 @@ static void cap_learning_post_process(struct cap_learning *cl) cl->final_cap_uah, old_cap, cl->learned_cap_uah); } /** * cap_wt_learning_process_full_data - * @cl: Capacity learning object * @batt_soc_pct: Battery State of Charge in percent * @cc_soc_delta_pct: percentage change in cc_soc * @delta_batt_soc_pct: percentage change in battery State of Charge * * Calculates the final learnt capacity when * weighted capacity learning is enabled. * */ static int cap_wt_learning_process_full_data(struct cap_learning *cl, int batt_soc_pct, int cc_soc_delta_pct, int delta_batt_soc_pct) { int64_t delta_cap_uah, del_cap_uah, total_cap_uah, res_cap_uah, wt_learnt_cap_uah; /* If the delta is < 10%, then skip processing full data */ if (delta_batt_soc_pct < cl->dt.min_delta_batt_soc) { pr_debug("batt_soc_delta_pct: %d\n", delta_batt_soc_pct); return -ERANGE; } delta_cap_uah = div64_s64(cl->learned_cap_uah * cc_soc_delta_pct, 100); /* Learnt Capacity from end Battery SOC to 100 % */ res_cap_uah = div64_s64(cl->learned_cap_uah * (100 - batt_soc_pct), 100); total_cap_uah = cl->init_cap_uah + delta_cap_uah + res_cap_uah; /* * difference in capacity learnt in this * charge cycle and previous learnt capacity */ del_cap_uah = total_cap_uah - cl->learned_cap_uah; /* Applying weight based on change in battery SOC */ wt_learnt_cap_uah = div64_s64(del_cap_uah * delta_batt_soc_pct, 100); cl->final_cap_uah = cl->learned_cap_uah + wt_learnt_cap_uah; pr_debug("cc_soc_delta_pct=%d total_cap_uah=%lld\n", cc_soc_delta_pct, cl->final_cap_uah); return 0; } /** * cap_learning_process_full_data - * @cl: Capacity learning object * @batt_soc_msb: Most significant byte of Battery State of Charge * * Processes the coulomb counter during charge termination and calculates the * delta w.r.to the coulomb counter obtained earlier when the learning begun. * */ static int cap_learning_process_full_data(struct cap_learning *cl) static int cap_learning_process_full_data(struct cap_learning *cl, int batt_soc_msb) { int rc, cc_soc_sw, cc_soc_delta_pct; int rc, cc_soc_sw, cc_soc_delta_pct, delta_batt_soc_pct, batt_soc_pct; int64_t delta_cap_uah; rc = cl->get_cc_soc(cl->data, &cc_soc_sw); Loading @@ -388,10 +434,19 @@ static int cap_learning_process_full_data(struct cap_learning *cl) return rc; } batt_soc_pct = DIV_ROUND_CLOSEST(batt_soc_msb * 100, FULL_SOC_RAW); delta_batt_soc_pct = batt_soc_pct - cl->init_batt_soc; cc_soc_delta_pct = div64_s64((int64_t)(cc_soc_sw - cl->init_cc_soc_sw) * 100, cl->cc_soc_max); if (cl->dt.cl_wt_enable) { rc = cap_wt_learning_process_full_data(cl, batt_soc_pct, cc_soc_delta_pct, delta_batt_soc_pct); return rc; } /* If the delta is < 50%, then skip processing full data */ if (cc_soc_delta_pct < 50) { pr_err("cc_soc_delta_pct: %d\n", cc_soc_delta_pct); Loading Loading @@ -422,12 +477,14 @@ static int cap_learning_begin(struct cap_learning *cl, u32 batt_soc) batt_soc_msb = batt_soc >> 24; batt_soc_pct = DIV_ROUND_CLOSEST(batt_soc_msb * 100, FULL_SOC_RAW); if (!cl->dt.cl_wt_enable) { if (batt_soc_pct > cl->dt.max_start_soc || batt_soc_pct < cl->dt.min_start_soc) { pr_debug("Battery SOC %d is high/low, not starting\n", batt_soc_pct); return -EINVAL; } } cl->init_cap_uah = div64_s64(cl->learned_cap_uah * batt_soc_msb, FULL_SOC_RAW); Loading @@ -451,6 +508,7 @@ static int cap_learning_begin(struct cap_learning *cl, u32 batt_soc) } cl->init_cc_soc_sw = cc_soc_sw; cl->init_batt_soc = batt_soc_pct; pr_debug("Capacity learning started @ battery SOC %d init_cc_soc_sw:%d\n", batt_soc_msb, cl->init_cc_soc_sw); out: Loading @@ -460,18 +518,19 @@ static int cap_learning_begin(struct cap_learning *cl, u32 batt_soc) /** * cap_learning_done - * @cl: Capacity learning object * @batt_soc_msb: Most significant byte of battery State of Charge * * Top level function for getting coulomb counter and post processing the * data once the capacity learning is complete after charge termination. * */ static int cap_learning_done(struct cap_learning *cl) static int cap_learning_done(struct cap_learning *cl, int batt_soc_msb) { int rc; rc = cap_learning_process_full_data(cl); rc = cap_learning_process_full_data(cl, batt_soc_msb); if (rc < 0) { pr_err("Error in processing cap learning full data, rc=%d\n", pr_debug("Error in processing cap learning full data, rc=%d\n", rc); goto out; } Loading @@ -490,6 +549,30 @@ static int cap_learning_done(struct cap_learning *cl) return rc; } /** * cap_wt_learning_update - * @cl: Capacity learning object * @batt_soc_msb: Most significant byte of battery State of Charge * @input_present: Indicator for input presence * * Called by cap_learning_update when weighted learning is enabled * */ static void cap_wt_learning_update(struct cap_learning *cl, int batt_soc_msb, bool input_present) { int rc; if (!input_present) { rc = cap_learning_done(cl, batt_soc_msb); if (rc < 0) pr_debug("Error in completing capacity learning, rc=%d\n", rc); cl->active = false; cl->init_cap_uah = 0; } } /** * cap_learning_update - * @cl: Capacity learning object Loading Loading @@ -526,6 +609,10 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, pr_debug("Charge_status: %d active: %d batt_soc: %d\n", charge_status, cl->active, batt_soc_msb); if (cl->active && cl->dt.cl_wt_enable) cap_wt_learning_update(cl, batt_soc_msb, input_present); /* Initialize the starting point of learning capacity */ if (!cl->active) { if (charge_status == POWER_SUPPLY_STATUS_CHARGING) { Loading @@ -538,7 +625,7 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, } } else { if (charge_done) { rc = cap_learning_done(cl); rc = cap_learning_done(cl, batt_soc_msb); if (rc < 0) pr_err("Error in completing capacity learning, rc=%d\n", rc); Loading @@ -547,17 +634,17 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, cl->init_cap_uah = 0; } if (charge_status == POWER_SUPPLY_STATUS_DISCHARGING) { if (!input_present) { if (charge_status == POWER_SUPPLY_STATUS_DISCHARGING && !input_present) { pr_debug("Capacity learning aborted @ battery SOC %d\n", batt_soc_msb); cl->active = false; cl->init_cap_uah = 0; prime_cc = true; } } if (charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING) { if (charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING && !cl->dt.cl_wt_enable) { if (qnovo_en && input_present) { /* * Don't abort the capacity learning when qnovo Loading drivers/power/supply/qcom/fg-alg.h +3 −0 Original line number Diff line number Diff line Loading @@ -48,12 +48,15 @@ struct cl_params { int max_cap_limit; int min_cap_limit; int skew_decipct; int min_delta_batt_soc; bool cl_wt_enable; }; struct cap_learning { void *data; int init_cc_soc_sw; int cc_soc_max; int init_batt_soc; int64_t nom_cap_uah; int64_t init_cap_uah; int64_t final_cap_uah; Loading drivers/power/supply/qcom/qpnp-fg-gen4.c +9 −0 Original line number Diff line number Diff line Loading @@ -4363,6 +4363,7 @@ static int fg_parse_esr_cal_params(struct fg_dev *fg) #define DEFAULT_CL_MAX_DEC_DECIPERC 100 #define DEFAULT_CL_MIN_LIM_DECIPERC 0 #define DEFAULT_CL_MAX_LIM_DECIPERC 0 #define DEFAULT_CL_DELTA_BATT_SOC 10 #define BTEMP_DELTA_LOW 0 #define BTEMP_DELTA_HIGH 3 #define DEFAULT_ESR_PULSE_THRESH_MA 47 Loading Loading @@ -4529,6 +4530,14 @@ static int fg_gen4_parse_dt(struct fg_gen4_chip *chip) else chip->cl->dt.max_start_soc = temp; chip->cl->dt.min_delta_batt_soc = DEFAULT_CL_DELTA_BATT_SOC; /* read from DT property and update, if value exists */ of_property_read_u32(node, "qcom,cl-min-delta-batt-soc", &chip->cl->dt.min_delta_batt_soc); chip->cl->dt.cl_wt_enable = of_property_read_bool(node, "qcom,cl-wt-enable"); rc = of_property_read_u32(node, "qcom,cl-min-temp", &temp); if (rc < 0) chip->cl->dt.min_temp = DEFAULT_CL_MIN_TEMP_DECIDEGC; Loading Loading
Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt +14 −0 Original line number Diff line number Diff line Loading @@ -245,6 +245,20 @@ First Level Node - FG Gen4 device capacity learning cycle. If this is not specified, then the default value is 0. Unit is in decipercentage. - qcom,cl-min-delta-batt-soc Usage: optional Value type: <u32> Definition: Minimum change in battery SOC to qualify for capacity learning. If this is not specified, then the default value is 10. Unit is in percentage. - qcom,cl-wt-enable Usage: optional Value type: <empty> Definition: A boolean property to enable weighted capacity learning based on change in battery SOC during a charging cycle. If this is specified "qcom,cl-start-capacity" is not used. - qcom,hold-soc-while-full Usage: optional Value type: <empty> Loading
Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt +15 −0 Original line number Diff line number Diff line Loading @@ -262,6 +262,21 @@ First Level Node - QGAUGE device capacity learning cycle. If this is not specified, then the default value is 0. Unit is in decipercentage. - qcom,cl-min-delta-batt-soc Usage: optional Value type: <u32> Definition: Minimum change in battery SOC to qualify for capacity learning. If this is not specified, then the default value is 10. Unit is in percentage. - qcom,cl-wt-enable Usage: optional Value type: <empty> Definition: A boolean property to enable weighted capacity learning based on change in battery SOC during a charging cycle. If this is specified, then "qcom,cl-min-start-soc" and "qcom,cl-max-start-soc" is not used. - qcom,esr-disable Usage: optional Value type: <bool> Loading
drivers/power/supply/qcom/fg-alg.c +107 −20 Original line number Diff line number Diff line Loading @@ -369,17 +369,63 @@ static void cap_learning_post_process(struct cap_learning *cl) cl->final_cap_uah, old_cap, cl->learned_cap_uah); } /** * cap_wt_learning_process_full_data - * @cl: Capacity learning object * @batt_soc_pct: Battery State of Charge in percent * @cc_soc_delta_pct: percentage change in cc_soc * @delta_batt_soc_pct: percentage change in battery State of Charge * * Calculates the final learnt capacity when * weighted capacity learning is enabled. * */ static int cap_wt_learning_process_full_data(struct cap_learning *cl, int batt_soc_pct, int cc_soc_delta_pct, int delta_batt_soc_pct) { int64_t delta_cap_uah, del_cap_uah, total_cap_uah, res_cap_uah, wt_learnt_cap_uah; /* If the delta is < 10%, then skip processing full data */ if (delta_batt_soc_pct < cl->dt.min_delta_batt_soc) { pr_debug("batt_soc_delta_pct: %d\n", delta_batt_soc_pct); return -ERANGE; } delta_cap_uah = div64_s64(cl->learned_cap_uah * cc_soc_delta_pct, 100); /* Learnt Capacity from end Battery SOC to 100 % */ res_cap_uah = div64_s64(cl->learned_cap_uah * (100 - batt_soc_pct), 100); total_cap_uah = cl->init_cap_uah + delta_cap_uah + res_cap_uah; /* * difference in capacity learnt in this * charge cycle and previous learnt capacity */ del_cap_uah = total_cap_uah - cl->learned_cap_uah; /* Applying weight based on change in battery SOC */ wt_learnt_cap_uah = div64_s64(del_cap_uah * delta_batt_soc_pct, 100); cl->final_cap_uah = cl->learned_cap_uah + wt_learnt_cap_uah; pr_debug("cc_soc_delta_pct=%d total_cap_uah=%lld\n", cc_soc_delta_pct, cl->final_cap_uah); return 0; } /** * cap_learning_process_full_data - * @cl: Capacity learning object * @batt_soc_msb: Most significant byte of Battery State of Charge * * Processes the coulomb counter during charge termination and calculates the * delta w.r.to the coulomb counter obtained earlier when the learning begun. * */ static int cap_learning_process_full_data(struct cap_learning *cl) static int cap_learning_process_full_data(struct cap_learning *cl, int batt_soc_msb) { int rc, cc_soc_sw, cc_soc_delta_pct; int rc, cc_soc_sw, cc_soc_delta_pct, delta_batt_soc_pct, batt_soc_pct; int64_t delta_cap_uah; rc = cl->get_cc_soc(cl->data, &cc_soc_sw); Loading @@ -388,10 +434,19 @@ static int cap_learning_process_full_data(struct cap_learning *cl) return rc; } batt_soc_pct = DIV_ROUND_CLOSEST(batt_soc_msb * 100, FULL_SOC_RAW); delta_batt_soc_pct = batt_soc_pct - cl->init_batt_soc; cc_soc_delta_pct = div64_s64((int64_t)(cc_soc_sw - cl->init_cc_soc_sw) * 100, cl->cc_soc_max); if (cl->dt.cl_wt_enable) { rc = cap_wt_learning_process_full_data(cl, batt_soc_pct, cc_soc_delta_pct, delta_batt_soc_pct); return rc; } /* If the delta is < 50%, then skip processing full data */ if (cc_soc_delta_pct < 50) { pr_err("cc_soc_delta_pct: %d\n", cc_soc_delta_pct); Loading Loading @@ -422,12 +477,14 @@ static int cap_learning_begin(struct cap_learning *cl, u32 batt_soc) batt_soc_msb = batt_soc >> 24; batt_soc_pct = DIV_ROUND_CLOSEST(batt_soc_msb * 100, FULL_SOC_RAW); if (!cl->dt.cl_wt_enable) { if (batt_soc_pct > cl->dt.max_start_soc || batt_soc_pct < cl->dt.min_start_soc) { pr_debug("Battery SOC %d is high/low, not starting\n", batt_soc_pct); return -EINVAL; } } cl->init_cap_uah = div64_s64(cl->learned_cap_uah * batt_soc_msb, FULL_SOC_RAW); Loading @@ -451,6 +508,7 @@ static int cap_learning_begin(struct cap_learning *cl, u32 batt_soc) } cl->init_cc_soc_sw = cc_soc_sw; cl->init_batt_soc = batt_soc_pct; pr_debug("Capacity learning started @ battery SOC %d init_cc_soc_sw:%d\n", batt_soc_msb, cl->init_cc_soc_sw); out: Loading @@ -460,18 +518,19 @@ static int cap_learning_begin(struct cap_learning *cl, u32 batt_soc) /** * cap_learning_done - * @cl: Capacity learning object * @batt_soc_msb: Most significant byte of battery State of Charge * * Top level function for getting coulomb counter and post processing the * data once the capacity learning is complete after charge termination. * */ static int cap_learning_done(struct cap_learning *cl) static int cap_learning_done(struct cap_learning *cl, int batt_soc_msb) { int rc; rc = cap_learning_process_full_data(cl); rc = cap_learning_process_full_data(cl, batt_soc_msb); if (rc < 0) { pr_err("Error in processing cap learning full data, rc=%d\n", pr_debug("Error in processing cap learning full data, rc=%d\n", rc); goto out; } Loading @@ -490,6 +549,30 @@ static int cap_learning_done(struct cap_learning *cl) return rc; } /** * cap_wt_learning_update - * @cl: Capacity learning object * @batt_soc_msb: Most significant byte of battery State of Charge * @input_present: Indicator for input presence * * Called by cap_learning_update when weighted learning is enabled * */ static void cap_wt_learning_update(struct cap_learning *cl, int batt_soc_msb, bool input_present) { int rc; if (!input_present) { rc = cap_learning_done(cl, batt_soc_msb); if (rc < 0) pr_debug("Error in completing capacity learning, rc=%d\n", rc); cl->active = false; cl->init_cap_uah = 0; } } /** * cap_learning_update - * @cl: Capacity learning object Loading Loading @@ -526,6 +609,10 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, pr_debug("Charge_status: %d active: %d batt_soc: %d\n", charge_status, cl->active, batt_soc_msb); if (cl->active && cl->dt.cl_wt_enable) cap_wt_learning_update(cl, batt_soc_msb, input_present); /* Initialize the starting point of learning capacity */ if (!cl->active) { if (charge_status == POWER_SUPPLY_STATUS_CHARGING) { Loading @@ -538,7 +625,7 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, } } else { if (charge_done) { rc = cap_learning_done(cl); rc = cap_learning_done(cl, batt_soc_msb); if (rc < 0) pr_err("Error in completing capacity learning, rc=%d\n", rc); Loading @@ -547,17 +634,17 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, cl->init_cap_uah = 0; } if (charge_status == POWER_SUPPLY_STATUS_DISCHARGING) { if (!input_present) { if (charge_status == POWER_SUPPLY_STATUS_DISCHARGING && !input_present) { pr_debug("Capacity learning aborted @ battery SOC %d\n", batt_soc_msb); cl->active = false; cl->init_cap_uah = 0; prime_cc = true; } } if (charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING) { if (charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING && !cl->dt.cl_wt_enable) { if (qnovo_en && input_present) { /* * Don't abort the capacity learning when qnovo Loading
drivers/power/supply/qcom/fg-alg.h +3 −0 Original line number Diff line number Diff line Loading @@ -48,12 +48,15 @@ struct cl_params { int max_cap_limit; int min_cap_limit; int skew_decipct; int min_delta_batt_soc; bool cl_wt_enable; }; struct cap_learning { void *data; int init_cc_soc_sw; int cc_soc_max; int init_batt_soc; int64_t nom_cap_uah; int64_t init_cap_uah; int64_t final_cap_uah; Loading
drivers/power/supply/qcom/qpnp-fg-gen4.c +9 −0 Original line number Diff line number Diff line Loading @@ -4363,6 +4363,7 @@ static int fg_parse_esr_cal_params(struct fg_dev *fg) #define DEFAULT_CL_MAX_DEC_DECIPERC 100 #define DEFAULT_CL_MIN_LIM_DECIPERC 0 #define DEFAULT_CL_MAX_LIM_DECIPERC 0 #define DEFAULT_CL_DELTA_BATT_SOC 10 #define BTEMP_DELTA_LOW 0 #define BTEMP_DELTA_HIGH 3 #define DEFAULT_ESR_PULSE_THRESH_MA 47 Loading Loading @@ -4529,6 +4530,14 @@ static int fg_gen4_parse_dt(struct fg_gen4_chip *chip) else chip->cl->dt.max_start_soc = temp; chip->cl->dt.min_delta_batt_soc = DEFAULT_CL_DELTA_BATT_SOC; /* read from DT property and update, if value exists */ of_property_read_u32(node, "qcom,cl-min-delta-batt-soc", &chip->cl->dt.min_delta_batt_soc); chip->cl->dt.cl_wt_enable = of_property_read_bool(node, "qcom,cl-wt-enable"); rc = of_property_read_u32(node, "qcom,cl-min-temp", &temp); if (rc < 0) chip->cl->dt.min_temp = DEFAULT_CL_MIN_TEMP_DECIDEGC; Loading