Loading drivers/power/supply/qcom/fg-alg.c +58 −46 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #define FULL_SOC_RAW 255 #define CAPACITY_DELTA_DECIPCT 500 #define CENTI_FULL_SOC 10000 #define CENTI_ICORRECT_C0 105 #define CENTI_ICORRECT_C1 20 Loading Loading @@ -366,7 +367,7 @@ static void cap_learning_post_process(struct cap_learning *cl) * cap_wt_learning_process_full_data - * @cl: Capacity learning object * @delta_batt_soc_pct: percentage change in battery State of Charge * @batt_soc_msb: MSB of battery State of Charge * @batt_soc_cp: Battery State of Charge in centi-percentage * * Calculates the final learnt capacity when * weighted capacity learning is enabled. Loading @@ -374,11 +375,11 @@ static void cap_learning_post_process(struct cap_learning *cl) */ static int cap_wt_learning_process_full_data(struct cap_learning *cl, int delta_batt_soc_pct, int batt_soc_msb) int batt_soc_cp) { int64_t del_cap_uah, total_cap_uah, res_cap_uah, wt_learnt_cap_uah; int delta_batt_soc_msb, res_batt_soc_msb; int delta_batt_soc_cp, res_batt_soc_cp; /* If the delta is < 10%, then skip processing full data */ if (delta_batt_soc_pct < cl->dt.min_delta_batt_soc) { Loading @@ -386,11 +387,11 @@ static int cap_wt_learning_process_full_data(struct cap_learning *cl, return -ERANGE; } delta_batt_soc_msb = batt_soc_msb - cl->init_batt_soc_msb; res_batt_soc_msb = FULL_SOC_RAW - batt_soc_msb; /* Learnt Capacity from end Battery SOC MSB to FULL_SOC_RAW */ delta_batt_soc_cp = batt_soc_cp - cl->init_batt_soc_cp; res_batt_soc_cp = CENTI_FULL_SOC - batt_soc_cp; /* Learnt Capacity from end Battery SOC to CENTI_FULL_SOC */ res_cap_uah = div64_s64(cl->learned_cap_uah * res_batt_soc_msb, FULL_SOC_RAW); res_batt_soc_cp, CENTI_FULL_SOC); total_cap_uah = cl->init_cap_uah + cl->delta_cap_uah + res_cap_uah; /* * difference in capacity learnt in this Loading @@ -398,8 +399,8 @@ static int cap_wt_learning_process_full_data(struct cap_learning *cl, */ del_cap_uah = total_cap_uah - cl->learned_cap_uah; /* Applying weight based on change in battery SOC MSB */ wt_learnt_cap_uah = div64_s64(del_cap_uah * delta_batt_soc_msb, FULL_SOC_RAW); wt_learnt_cap_uah = div64_s64(del_cap_uah * delta_batt_soc_cp, CENTI_FULL_SOC); cl->final_cap_uah = cl->learned_cap_uah + wt_learnt_cap_uah; pr_debug("wt_learnt_cap_uah=%lld, del_cap_uah=%lld\n", Loading @@ -413,14 +414,14 @@ static int cap_wt_learning_process_full_data(struct cap_learning *cl, /** * cap_learning_process_full_data - * @cl: Capacity learning object * @batt_soc_msb: Most significant byte of Battery State of Charge * @batt_soc_cp: Battery State of Charge in centi-percentage * * 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, int batt_soc_msb) int batt_soc_cp) { int rc, cc_soc_sw, cc_soc_delta_pct, delta_batt_soc_pct, batt_soc_pct, cc_soc_fraction; Loading @@ -432,7 +433,7 @@ 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); batt_soc_pct = DIV_ROUND_CLOSEST(batt_soc_cp, 100); delta_batt_soc_pct = batt_soc_pct - cl->init_batt_soc; cc_soc_delta_pct = div_s64_rem((int64_t)(cc_soc_sw - cl->init_cc_soc_sw) * 100, Loading @@ -446,7 +447,7 @@ static int cap_learning_process_full_data(struct cap_learning *cl, if (cl->dt.cl_wt_enable) { rc = cap_wt_learning_process_full_data(cl, delta_batt_soc_pct, batt_soc_msb); batt_soc_cp); return rc; } Loading @@ -465,38 +466,47 @@ static int cap_learning_process_full_data(struct cap_learning *cl, /** * cap_learning_begin - * @cl: Capacity learning object * @batt_soc: Battery State of Charge (SOC) * @batt_soc_cp: Battery State of Charge in centi-percentage * * Gets the coulomb counter from FG/QG when the conditions are suitable for * beginning capacity learning. Also, primes the coulomb counter based on * battery SOC if required. * */ static int cap_learning_begin(struct cap_learning *cl, u32 batt_soc) #define BATT_SOC_32BIT GENMASK(31, 0) static int cap_learning_begin(struct cap_learning *cl, u32 batt_soc_cp) { int rc, cc_soc_sw, batt_soc_msb, batt_soc_pct; int rc, cc_soc_sw, batt_soc_pct; u32 batt_soc_prime; if (cl->ok_to_begin && !cl->ok_to_begin(cl->data)) { pr_debug("Not OK to begin\n"); return -EINVAL; } batt_soc_msb = batt_soc >> 24; batt_soc_pct = DIV_ROUND_CLOSEST(batt_soc_msb * 100, FULL_SOC_RAW); batt_soc_pct = DIV_ROUND_CLOSEST(batt_soc_cp, 100); if (!cl->dt.cl_wt_enable) { if (batt_soc_pct > cl->dt.max_start_soc || batt_soc_pct < cl->dt.min_start_soc) { if ((cl->dt.max_start_soc != -EINVAL && batt_soc_pct > cl->dt.max_start_soc) || (cl->dt.min_start_soc != -EINVAL && 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); cl->init_cap_uah = div64_s64(cl->learned_cap_uah * batt_soc_cp, CENTI_FULL_SOC); if (cl->prime_cc_soc) { /* * Prime cc_soc_sw with battery SOC when capacity learning * begins. */ rc = cl->prime_cc_soc(cl->data, batt_soc); batt_soc_prime = div64_u64( (uint64_t)batt_soc_cp * BATT_SOC_32BIT, CENTI_FULL_SOC); rc = cl->prime_cc_soc(cl->data, batt_soc_prime); if (rc < 0) { pr_err("Error in writing cc_soc_sw, rc=%d\n", rc); goto out; Loading @@ -511,9 +521,9 @@ 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; cl->init_batt_soc_msb = batt_soc_msb; cl->init_batt_soc_cp = batt_soc_cp; pr_debug("Capacity learning started @ battery SOC %d init_cc_soc_sw:%d\n", batt_soc_msb, cl->init_cc_soc_sw); batt_soc_cp, cl->init_cc_soc_sw); out: return rc; } Loading @@ -521,17 +531,17 @@ 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 * @batt_soc_cp: Battery State of Charge in centi-percentage * * 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, int batt_soc_msb) static int cap_learning_done(struct cap_learning *cl, int batt_soc_cp) { int rc; rc = cap_learning_process_full_data(cl, batt_soc_msb); rc = cap_learning_process_full_data(cl, batt_soc_cp); if (rc < 0) { pr_debug("Error in processing cap learning full data, rc=%d\n", rc); Loading @@ -555,19 +565,19 @@ static int cap_learning_done(struct cap_learning *cl, int batt_soc_msb) /** * cap_wt_learning_update - * @cl: Capacity learning object * @batt_soc_msb: Most significant byte of battery State of Charge * @batt_soc_cp: Battery State of Charge in centi-percentage * @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, static void cap_wt_learning_update(struct cap_learning *cl, int batt_soc_cp, bool input_present) { int rc; if (!input_present) { rc = cap_learning_done(cl, batt_soc_msb); rc = cap_learning_done(cl, batt_soc_cp); if (rc < 0) pr_debug("Error in completing capacity learning, rc=%d\n", rc); Loading @@ -590,10 +600,11 @@ static void cap_wt_learning_update(struct cap_learning *cl, int batt_soc_msb, * */ void cap_learning_update(struct cap_learning *cl, int batt_temp, int batt_soc, int charge_status, bool charge_done, int batt_soc_cp, int charge_status, bool charge_done, bool input_present, bool qnovo_en) { int rc, batt_soc_msb, batt_soc_prime; int rc; u32 batt_soc_prime; bool prime_cc = false; if (!cl) Loading @@ -608,18 +619,16 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, goto out; } batt_soc_msb = (u32)batt_soc >> 24; pr_debug("Charge_status: %d active: %d batt_soc: %d\n", charge_status, cl->active, batt_soc_msb); charge_status, cl->active, batt_soc_cp); if (cl->active && cl->dt.cl_wt_enable) cap_wt_learning_update(cl, batt_soc_msb, input_present); cap_wt_learning_update(cl, batt_soc_cp, input_present); /* Initialize the starting point of learning capacity */ if (!cl->active) { if (charge_status == POWER_SUPPLY_STATUS_CHARGING) { rc = cap_learning_begin(cl, batt_soc); rc = cap_learning_begin(cl, batt_soc_cp); cl->active = (rc == 0); } else { if (charge_status == POWER_SUPPLY_STATUS_DISCHARGING || Loading @@ -628,7 +637,7 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, } } else { if (charge_done) { rc = cap_learning_done(cl, batt_soc_msb); rc = cap_learning_done(cl, batt_soc_cp); if (rc < 0) pr_err("Error in completing capacity learning, rc=%d\n", rc); Loading @@ -640,7 +649,7 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, if (charge_status == POWER_SUPPLY_STATUS_DISCHARGING && !input_present) { pr_debug("Capacity learning aborted @ battery SOC %d\n", batt_soc_msb); batt_soc_cp); cl->active = false; cl->init_cap_uah = 0; prime_cc = true; Loading @@ -657,7 +666,7 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, */ } else { pr_debug("Capacity learning aborted @ battery SOC %d\n", batt_soc_msb); batt_soc_cp); cl->active = false; cl->init_cap_uah = 0; prime_cc = true; Loading @@ -671,10 +680,13 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, */ if (prime_cc && cl->prime_cc_soc) { /* pass 32-bit batt_soc to the priming logic */ if (charge_done) batt_soc_prime = cl->cc_soc_max; else batt_soc_prime = batt_soc; batt_soc_prime = div64_u64( (uint64_t)batt_soc_cp * BATT_SOC_32BIT, CENTI_FULL_SOC); rc = cl->prime_cc_soc(cl->data, batt_soc_prime); if (rc < 0) Loading drivers/power/supply/qcom/fg-alg.h +2 −1 Original line number Diff line number Diff line Loading @@ -51,7 +51,7 @@ struct cap_learning { int init_cc_soc_sw; int cc_soc_max; int init_batt_soc; int init_batt_soc_msb; int init_batt_soc_cp; int64_t nom_cap_uah; int64_t init_cap_uah; int64_t final_cap_uah; Loading @@ -60,6 +60,7 @@ struct cap_learning { bool active; struct mutex lock; struct cl_params dt; bool (*ok_to_begin)(void *data); int (*get_learned_capacity)(void *data, int64_t *learned_cap_uah); int (*store_learned_capacity)(void *data, int64_t learned_cap_uah); int (*get_cc_soc)(void *data, int *cc_soc_sw); Loading drivers/power/supply/qcom/qg-soc.c +3 −6 Original line number Diff line number Diff line Loading @@ -306,7 +306,7 @@ static bool maint_soc_timeout(struct qpnp_qg *chip) static void update_msoc(struct qpnp_qg *chip) { int rc = 0, sdam_soc, batt_temp = 0, batt_soc_32bit = 0; int rc = 0, sdam_soc, batt_temp = 0; bool input_present = is_input_present(chip); if (chip->catch_up_soc > chip->msoc) { Loading Loading @@ -345,11 +345,8 @@ static void update_msoc(struct qpnp_qg *chip) rc = qg_get_battery_temp(chip, &batt_temp); if (rc < 0) { pr_err("Failed to read BATT_TEMP rc=%d\n", rc); } else { batt_soc_32bit = div64_u64( chip->batt_soc * BATT_SOC_32BIT, QG_SOC_FULL); cap_learning_update(chip->cl, batt_temp, batt_soc_32bit, } else if (chip->batt_soc >= 0) { cap_learning_update(chip->cl, batt_temp, chip->batt_soc, chip->charge_status, chip->charge_done, input_present, false); } Loading drivers/power/supply/qcom/qpnp-fg-gen4.c +20 −7 Original line number Diff line number Diff line Loading @@ -3595,12 +3595,14 @@ static irqreturn_t fg_delta_bsoc_irq_handler(int irq, void *data) return IRQ_HANDLED; } #define CENTI_FULL_SOC 10000 static irqreturn_t fg_delta_msoc_irq_handler(int irq, void *data) { struct fg_dev *fg = data; struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); int rc, batt_soc, batt_temp, msoc_raw; bool input_present = is_input_present(fg); u32 batt_soc_cp; rc = fg_get_msoc_raw(fg, &msoc_raw); if (!rc) Loading @@ -3620,10 +3622,14 @@ static irqreturn_t fg_delta_msoc_irq_handler(int irq, void *data) if (rc < 0) { pr_err("Failed to read battery temp rc: %d\n", rc); } else { if (chip->cl->active) cap_learning_update(chip->cl, batt_temp, batt_soc, if (chip->cl->active) { batt_soc_cp = div64_u64( (u64)(u32)batt_soc * CENTI_FULL_SOC, BATT_SOC_32BIT); cap_learning_update(chip->cl, batt_temp, batt_soc_cp, fg->charge_status, fg->charge_done, input_present, is_qnovo_en(fg)); } rc = fg_gen4_slope_limit_config(chip, batt_temp); if (rc < 0) Loading Loading @@ -4059,6 +4065,7 @@ static void status_change_work(struct work_struct *work) struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); int rc, batt_soc, batt_temp; bool input_present, qnovo_en; u32 batt_soc_cp; if (fg->battery_missing) { pm_relax(fg->dev); Loading Loading @@ -4103,10 +4110,13 @@ static void status_change_work(struct work_struct *work) cycle_count_update(chip->counter, (u32)batt_soc >> 24, fg->charge_status, fg->charge_done, input_present); if (fg->charge_status != fg->prev_charge_status) cap_learning_update(chip->cl, batt_temp, batt_soc, if (fg->charge_status != fg->prev_charge_status) { batt_soc_cp = div64_u64((u64)(u32)batt_soc * CENTI_FULL_SOC, BATT_SOC_32BIT); cap_learning_update(chip->cl, batt_temp, batt_soc_cp, fg->charge_status, fg->charge_done, input_present, qnovo_en); } rc = fg_gen4_charge_full_update(fg); if (rc < 0) Loading Loading @@ -5691,9 +5701,6 @@ static void fg_gen4_parse_cl_params_dt(struct fg_gen4_chip *chip) 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"); chip->cl->dt.min_temp = DEFAULT_CL_MIN_TEMP_DECIDEGC; of_property_read_u32(node, "qcom,cl-min-temp", &chip->cl->dt.min_temp); Loading @@ -5717,6 +5724,12 @@ static void fg_gen4_parse_cl_params_dt(struct fg_gen4_chip *chip) &chip->cl->dt.max_cap_limit); of_property_read_u32(node, "qcom,cl-skew", &chip->cl->dt.skew_decipct); if (of_property_read_bool(node, "qcom,cl-wt-enable")) { chip->cl->dt.cl_wt_enable = true; chip->cl->dt.max_start_soc = -EINVAL; chip->cl->dt.min_start_soc = -EINVAL; } } static int fg_gen4_parse_revid_dt(struct fg_gen4_chip *chip) Loading drivers/power/supply/qcom/qpnp-qg.c +9 −8 Original line number Diff line number Diff line Loading @@ -2553,7 +2553,7 @@ static void qg_status_change_work(struct work_struct *work) struct qpnp_qg *chip = container_of(work, struct qpnp_qg, qg_status_change_work); union power_supply_propval prop = {0, }; int rc = 0, batt_temp = 0, batt_soc_32b = 0; int rc = 0, batt_temp = 0; bool input_present = false; if (!is_batt_available(chip)) { Loading Loading @@ -2609,11 +2609,8 @@ static void qg_status_change_work(struct work_struct *work) rc = qg_get_battery_temp(chip, &batt_temp); if (rc < 0) { pr_err("Failed to read BATT_TEMP at PON rc=%d\n", rc); } else { batt_soc_32b = div64_u64( chip->batt_soc * BATT_SOC_32BIT, QG_SOC_FULL); cap_learning_update(chip->cl, batt_temp, batt_soc_32b, } else if (chip->batt_soc >= 0) { cap_learning_update(chip->cl, batt_temp, chip->batt_soc, chip->charge_status, chip->charge_done, input_present, false); } Loading Loading @@ -3895,6 +3892,7 @@ static int qg_parse_s2_dt(struct qpnp_qg *chip) #define DEFAULT_CL_MIN_LIM_DECIPERC 500 #define DEFAULT_CL_MAX_LIM_DECIPERC 100 #define DEFAULT_CL_DELTA_BATT_SOC 10 #define DEFAULT_CL_WT_START_SOC 15 static int qg_parse_cl_dt(struct qpnp_qg *chip) { int rc; Loading Loading @@ -3962,8 +3960,11 @@ static int qg_parse_cl_dt(struct qpnp_qg *chip) 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"); if (of_property_read_bool(node, "qcom,cl-wt-enable")) { chip->cl->dt.cl_wt_enable = true; chip->cl->dt.min_start_soc = DEFAULT_CL_WT_START_SOC; chip->cl->dt.max_start_soc = -EINVAL; } qg_dbg(chip, QG_DEBUG_PON, "DT: cl_min_start_soc=%d cl_max_start_soc=%d cl_min_temp=%d cl_max_temp=%d chip->cl->dt.cl_wt_enable=%d\n", chip->cl->dt.min_start_soc, chip->cl->dt.max_start_soc, Loading Loading
drivers/power/supply/qcom/fg-alg.c +58 −46 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ #define FULL_SOC_RAW 255 #define CAPACITY_DELTA_DECIPCT 500 #define CENTI_FULL_SOC 10000 #define CENTI_ICORRECT_C0 105 #define CENTI_ICORRECT_C1 20 Loading Loading @@ -366,7 +367,7 @@ static void cap_learning_post_process(struct cap_learning *cl) * cap_wt_learning_process_full_data - * @cl: Capacity learning object * @delta_batt_soc_pct: percentage change in battery State of Charge * @batt_soc_msb: MSB of battery State of Charge * @batt_soc_cp: Battery State of Charge in centi-percentage * * Calculates the final learnt capacity when * weighted capacity learning is enabled. Loading @@ -374,11 +375,11 @@ static void cap_learning_post_process(struct cap_learning *cl) */ static int cap_wt_learning_process_full_data(struct cap_learning *cl, int delta_batt_soc_pct, int batt_soc_msb) int batt_soc_cp) { int64_t del_cap_uah, total_cap_uah, res_cap_uah, wt_learnt_cap_uah; int delta_batt_soc_msb, res_batt_soc_msb; int delta_batt_soc_cp, res_batt_soc_cp; /* If the delta is < 10%, then skip processing full data */ if (delta_batt_soc_pct < cl->dt.min_delta_batt_soc) { Loading @@ -386,11 +387,11 @@ static int cap_wt_learning_process_full_data(struct cap_learning *cl, return -ERANGE; } delta_batt_soc_msb = batt_soc_msb - cl->init_batt_soc_msb; res_batt_soc_msb = FULL_SOC_RAW - batt_soc_msb; /* Learnt Capacity from end Battery SOC MSB to FULL_SOC_RAW */ delta_batt_soc_cp = batt_soc_cp - cl->init_batt_soc_cp; res_batt_soc_cp = CENTI_FULL_SOC - batt_soc_cp; /* Learnt Capacity from end Battery SOC to CENTI_FULL_SOC */ res_cap_uah = div64_s64(cl->learned_cap_uah * res_batt_soc_msb, FULL_SOC_RAW); res_batt_soc_cp, CENTI_FULL_SOC); total_cap_uah = cl->init_cap_uah + cl->delta_cap_uah + res_cap_uah; /* * difference in capacity learnt in this Loading @@ -398,8 +399,8 @@ static int cap_wt_learning_process_full_data(struct cap_learning *cl, */ del_cap_uah = total_cap_uah - cl->learned_cap_uah; /* Applying weight based on change in battery SOC MSB */ wt_learnt_cap_uah = div64_s64(del_cap_uah * delta_batt_soc_msb, FULL_SOC_RAW); wt_learnt_cap_uah = div64_s64(del_cap_uah * delta_batt_soc_cp, CENTI_FULL_SOC); cl->final_cap_uah = cl->learned_cap_uah + wt_learnt_cap_uah; pr_debug("wt_learnt_cap_uah=%lld, del_cap_uah=%lld\n", Loading @@ -413,14 +414,14 @@ static int cap_wt_learning_process_full_data(struct cap_learning *cl, /** * cap_learning_process_full_data - * @cl: Capacity learning object * @batt_soc_msb: Most significant byte of Battery State of Charge * @batt_soc_cp: Battery State of Charge in centi-percentage * * 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, int batt_soc_msb) int batt_soc_cp) { int rc, cc_soc_sw, cc_soc_delta_pct, delta_batt_soc_pct, batt_soc_pct, cc_soc_fraction; Loading @@ -432,7 +433,7 @@ 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); batt_soc_pct = DIV_ROUND_CLOSEST(batt_soc_cp, 100); delta_batt_soc_pct = batt_soc_pct - cl->init_batt_soc; cc_soc_delta_pct = div_s64_rem((int64_t)(cc_soc_sw - cl->init_cc_soc_sw) * 100, Loading @@ -446,7 +447,7 @@ static int cap_learning_process_full_data(struct cap_learning *cl, if (cl->dt.cl_wt_enable) { rc = cap_wt_learning_process_full_data(cl, delta_batt_soc_pct, batt_soc_msb); batt_soc_cp); return rc; } Loading @@ -465,38 +466,47 @@ static int cap_learning_process_full_data(struct cap_learning *cl, /** * cap_learning_begin - * @cl: Capacity learning object * @batt_soc: Battery State of Charge (SOC) * @batt_soc_cp: Battery State of Charge in centi-percentage * * Gets the coulomb counter from FG/QG when the conditions are suitable for * beginning capacity learning. Also, primes the coulomb counter based on * battery SOC if required. * */ static int cap_learning_begin(struct cap_learning *cl, u32 batt_soc) #define BATT_SOC_32BIT GENMASK(31, 0) static int cap_learning_begin(struct cap_learning *cl, u32 batt_soc_cp) { int rc, cc_soc_sw, batt_soc_msb, batt_soc_pct; int rc, cc_soc_sw, batt_soc_pct; u32 batt_soc_prime; if (cl->ok_to_begin && !cl->ok_to_begin(cl->data)) { pr_debug("Not OK to begin\n"); return -EINVAL; } batt_soc_msb = batt_soc >> 24; batt_soc_pct = DIV_ROUND_CLOSEST(batt_soc_msb * 100, FULL_SOC_RAW); batt_soc_pct = DIV_ROUND_CLOSEST(batt_soc_cp, 100); if (!cl->dt.cl_wt_enable) { if (batt_soc_pct > cl->dt.max_start_soc || batt_soc_pct < cl->dt.min_start_soc) { if ((cl->dt.max_start_soc != -EINVAL && batt_soc_pct > cl->dt.max_start_soc) || (cl->dt.min_start_soc != -EINVAL && 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); cl->init_cap_uah = div64_s64(cl->learned_cap_uah * batt_soc_cp, CENTI_FULL_SOC); if (cl->prime_cc_soc) { /* * Prime cc_soc_sw with battery SOC when capacity learning * begins. */ rc = cl->prime_cc_soc(cl->data, batt_soc); batt_soc_prime = div64_u64( (uint64_t)batt_soc_cp * BATT_SOC_32BIT, CENTI_FULL_SOC); rc = cl->prime_cc_soc(cl->data, batt_soc_prime); if (rc < 0) { pr_err("Error in writing cc_soc_sw, rc=%d\n", rc); goto out; Loading @@ -511,9 +521,9 @@ 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; cl->init_batt_soc_msb = batt_soc_msb; cl->init_batt_soc_cp = batt_soc_cp; pr_debug("Capacity learning started @ battery SOC %d init_cc_soc_sw:%d\n", batt_soc_msb, cl->init_cc_soc_sw); batt_soc_cp, cl->init_cc_soc_sw); out: return rc; } Loading @@ -521,17 +531,17 @@ 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 * @batt_soc_cp: Battery State of Charge in centi-percentage * * 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, int batt_soc_msb) static int cap_learning_done(struct cap_learning *cl, int batt_soc_cp) { int rc; rc = cap_learning_process_full_data(cl, batt_soc_msb); rc = cap_learning_process_full_data(cl, batt_soc_cp); if (rc < 0) { pr_debug("Error in processing cap learning full data, rc=%d\n", rc); Loading @@ -555,19 +565,19 @@ static int cap_learning_done(struct cap_learning *cl, int batt_soc_msb) /** * cap_wt_learning_update - * @cl: Capacity learning object * @batt_soc_msb: Most significant byte of battery State of Charge * @batt_soc_cp: Battery State of Charge in centi-percentage * @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, static void cap_wt_learning_update(struct cap_learning *cl, int batt_soc_cp, bool input_present) { int rc; if (!input_present) { rc = cap_learning_done(cl, batt_soc_msb); rc = cap_learning_done(cl, batt_soc_cp); if (rc < 0) pr_debug("Error in completing capacity learning, rc=%d\n", rc); Loading @@ -590,10 +600,11 @@ static void cap_wt_learning_update(struct cap_learning *cl, int batt_soc_msb, * */ void cap_learning_update(struct cap_learning *cl, int batt_temp, int batt_soc, int charge_status, bool charge_done, int batt_soc_cp, int charge_status, bool charge_done, bool input_present, bool qnovo_en) { int rc, batt_soc_msb, batt_soc_prime; int rc; u32 batt_soc_prime; bool prime_cc = false; if (!cl) Loading @@ -608,18 +619,16 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, goto out; } batt_soc_msb = (u32)batt_soc >> 24; pr_debug("Charge_status: %d active: %d batt_soc: %d\n", charge_status, cl->active, batt_soc_msb); charge_status, cl->active, batt_soc_cp); if (cl->active && cl->dt.cl_wt_enable) cap_wt_learning_update(cl, batt_soc_msb, input_present); cap_wt_learning_update(cl, batt_soc_cp, input_present); /* Initialize the starting point of learning capacity */ if (!cl->active) { if (charge_status == POWER_SUPPLY_STATUS_CHARGING) { rc = cap_learning_begin(cl, batt_soc); rc = cap_learning_begin(cl, batt_soc_cp); cl->active = (rc == 0); } else { if (charge_status == POWER_SUPPLY_STATUS_DISCHARGING || Loading @@ -628,7 +637,7 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, } } else { if (charge_done) { rc = cap_learning_done(cl, batt_soc_msb); rc = cap_learning_done(cl, batt_soc_cp); if (rc < 0) pr_err("Error in completing capacity learning, rc=%d\n", rc); Loading @@ -640,7 +649,7 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, if (charge_status == POWER_SUPPLY_STATUS_DISCHARGING && !input_present) { pr_debug("Capacity learning aborted @ battery SOC %d\n", batt_soc_msb); batt_soc_cp); cl->active = false; cl->init_cap_uah = 0; prime_cc = true; Loading @@ -657,7 +666,7 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, */ } else { pr_debug("Capacity learning aborted @ battery SOC %d\n", batt_soc_msb); batt_soc_cp); cl->active = false; cl->init_cap_uah = 0; prime_cc = true; Loading @@ -671,10 +680,13 @@ void cap_learning_update(struct cap_learning *cl, int batt_temp, */ if (prime_cc && cl->prime_cc_soc) { /* pass 32-bit batt_soc to the priming logic */ if (charge_done) batt_soc_prime = cl->cc_soc_max; else batt_soc_prime = batt_soc; batt_soc_prime = div64_u64( (uint64_t)batt_soc_cp * BATT_SOC_32BIT, CENTI_FULL_SOC); rc = cl->prime_cc_soc(cl->data, batt_soc_prime); if (rc < 0) Loading
drivers/power/supply/qcom/fg-alg.h +2 −1 Original line number Diff line number Diff line Loading @@ -51,7 +51,7 @@ struct cap_learning { int init_cc_soc_sw; int cc_soc_max; int init_batt_soc; int init_batt_soc_msb; int init_batt_soc_cp; int64_t nom_cap_uah; int64_t init_cap_uah; int64_t final_cap_uah; Loading @@ -60,6 +60,7 @@ struct cap_learning { bool active; struct mutex lock; struct cl_params dt; bool (*ok_to_begin)(void *data); int (*get_learned_capacity)(void *data, int64_t *learned_cap_uah); int (*store_learned_capacity)(void *data, int64_t learned_cap_uah); int (*get_cc_soc)(void *data, int *cc_soc_sw); Loading
drivers/power/supply/qcom/qg-soc.c +3 −6 Original line number Diff line number Diff line Loading @@ -306,7 +306,7 @@ static bool maint_soc_timeout(struct qpnp_qg *chip) static void update_msoc(struct qpnp_qg *chip) { int rc = 0, sdam_soc, batt_temp = 0, batt_soc_32bit = 0; int rc = 0, sdam_soc, batt_temp = 0; bool input_present = is_input_present(chip); if (chip->catch_up_soc > chip->msoc) { Loading Loading @@ -345,11 +345,8 @@ static void update_msoc(struct qpnp_qg *chip) rc = qg_get_battery_temp(chip, &batt_temp); if (rc < 0) { pr_err("Failed to read BATT_TEMP rc=%d\n", rc); } else { batt_soc_32bit = div64_u64( chip->batt_soc * BATT_SOC_32BIT, QG_SOC_FULL); cap_learning_update(chip->cl, batt_temp, batt_soc_32bit, } else if (chip->batt_soc >= 0) { cap_learning_update(chip->cl, batt_temp, chip->batt_soc, chip->charge_status, chip->charge_done, input_present, false); } Loading
drivers/power/supply/qcom/qpnp-fg-gen4.c +20 −7 Original line number Diff line number Diff line Loading @@ -3595,12 +3595,14 @@ static irqreturn_t fg_delta_bsoc_irq_handler(int irq, void *data) return IRQ_HANDLED; } #define CENTI_FULL_SOC 10000 static irqreturn_t fg_delta_msoc_irq_handler(int irq, void *data) { struct fg_dev *fg = data; struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); int rc, batt_soc, batt_temp, msoc_raw; bool input_present = is_input_present(fg); u32 batt_soc_cp; rc = fg_get_msoc_raw(fg, &msoc_raw); if (!rc) Loading @@ -3620,10 +3622,14 @@ static irqreturn_t fg_delta_msoc_irq_handler(int irq, void *data) if (rc < 0) { pr_err("Failed to read battery temp rc: %d\n", rc); } else { if (chip->cl->active) cap_learning_update(chip->cl, batt_temp, batt_soc, if (chip->cl->active) { batt_soc_cp = div64_u64( (u64)(u32)batt_soc * CENTI_FULL_SOC, BATT_SOC_32BIT); cap_learning_update(chip->cl, batt_temp, batt_soc_cp, fg->charge_status, fg->charge_done, input_present, is_qnovo_en(fg)); } rc = fg_gen4_slope_limit_config(chip, batt_temp); if (rc < 0) Loading Loading @@ -4059,6 +4065,7 @@ static void status_change_work(struct work_struct *work) struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); int rc, batt_soc, batt_temp; bool input_present, qnovo_en; u32 batt_soc_cp; if (fg->battery_missing) { pm_relax(fg->dev); Loading Loading @@ -4103,10 +4110,13 @@ static void status_change_work(struct work_struct *work) cycle_count_update(chip->counter, (u32)batt_soc >> 24, fg->charge_status, fg->charge_done, input_present); if (fg->charge_status != fg->prev_charge_status) cap_learning_update(chip->cl, batt_temp, batt_soc, if (fg->charge_status != fg->prev_charge_status) { batt_soc_cp = div64_u64((u64)(u32)batt_soc * CENTI_FULL_SOC, BATT_SOC_32BIT); cap_learning_update(chip->cl, batt_temp, batt_soc_cp, fg->charge_status, fg->charge_done, input_present, qnovo_en); } rc = fg_gen4_charge_full_update(fg); if (rc < 0) Loading Loading @@ -5691,9 +5701,6 @@ static void fg_gen4_parse_cl_params_dt(struct fg_gen4_chip *chip) 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"); chip->cl->dt.min_temp = DEFAULT_CL_MIN_TEMP_DECIDEGC; of_property_read_u32(node, "qcom,cl-min-temp", &chip->cl->dt.min_temp); Loading @@ -5717,6 +5724,12 @@ static void fg_gen4_parse_cl_params_dt(struct fg_gen4_chip *chip) &chip->cl->dt.max_cap_limit); of_property_read_u32(node, "qcom,cl-skew", &chip->cl->dt.skew_decipct); if (of_property_read_bool(node, "qcom,cl-wt-enable")) { chip->cl->dt.cl_wt_enable = true; chip->cl->dt.max_start_soc = -EINVAL; chip->cl->dt.min_start_soc = -EINVAL; } } static int fg_gen4_parse_revid_dt(struct fg_gen4_chip *chip) Loading
drivers/power/supply/qcom/qpnp-qg.c +9 −8 Original line number Diff line number Diff line Loading @@ -2553,7 +2553,7 @@ static void qg_status_change_work(struct work_struct *work) struct qpnp_qg *chip = container_of(work, struct qpnp_qg, qg_status_change_work); union power_supply_propval prop = {0, }; int rc = 0, batt_temp = 0, batt_soc_32b = 0; int rc = 0, batt_temp = 0; bool input_present = false; if (!is_batt_available(chip)) { Loading Loading @@ -2609,11 +2609,8 @@ static void qg_status_change_work(struct work_struct *work) rc = qg_get_battery_temp(chip, &batt_temp); if (rc < 0) { pr_err("Failed to read BATT_TEMP at PON rc=%d\n", rc); } else { batt_soc_32b = div64_u64( chip->batt_soc * BATT_SOC_32BIT, QG_SOC_FULL); cap_learning_update(chip->cl, batt_temp, batt_soc_32b, } else if (chip->batt_soc >= 0) { cap_learning_update(chip->cl, batt_temp, chip->batt_soc, chip->charge_status, chip->charge_done, input_present, false); } Loading Loading @@ -3895,6 +3892,7 @@ static int qg_parse_s2_dt(struct qpnp_qg *chip) #define DEFAULT_CL_MIN_LIM_DECIPERC 500 #define DEFAULT_CL_MAX_LIM_DECIPERC 100 #define DEFAULT_CL_DELTA_BATT_SOC 10 #define DEFAULT_CL_WT_START_SOC 15 static int qg_parse_cl_dt(struct qpnp_qg *chip) { int rc; Loading Loading @@ -3962,8 +3960,11 @@ static int qg_parse_cl_dt(struct qpnp_qg *chip) 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"); if (of_property_read_bool(node, "qcom,cl-wt-enable")) { chip->cl->dt.cl_wt_enable = true; chip->cl->dt.min_start_soc = DEFAULT_CL_WT_START_SOC; chip->cl->dt.max_start_soc = -EINVAL; } qg_dbg(chip, QG_DEBUG_PON, "DT: cl_min_start_soc=%d cl_max_start_soc=%d cl_min_temp=%d cl_max_temp=%d chip->cl->dt.cl_wt_enable=%d\n", chip->cl->dt.min_start_soc, chip->cl->dt.max_start_soc, Loading