Loading Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt +8 −0 Original line number Diff line number Diff line Loading @@ -397,6 +397,14 @@ First Level Node - FG Gen4 device five pin battery is used. Based on this, time to full calculations would use the Rbatt calculated properly. - qcom,multi-profile-load Usage: optional Value type: <empty> Definition: A boolean property that when specified indicates that multiple profile loading needs to be enabled. This requires multiple battery profiles to be specified for a battery for proper functionality. ========================================================== Second Level Nodes - Peripherals managed by FG Gen4 driver ========================================================== Loading drivers/power/supply/qcom/qpnp-fg-gen4.c +150 −60 Original line number Diff line number Diff line Loading @@ -116,6 +116,8 @@ #define RCONN_OFFSET 0 #define ACT_BATT_CAP_WORD 285 #define ACT_BATT_CAP_OFFSET 0 #define BATT_AGE_LEVEL_WORD 288 #define BATT_AGE_LEVEL_OFFSET 0 #define CYCLE_COUNT_WORD 291 #define CYCLE_COUNT_OFFSET 0 #define PROFILE_INTEGRITY_WORD 299 Loading Loading @@ -190,6 +192,7 @@ struct fg_dt_props { bool linearize_soc; bool rapid_soc_dec_en; bool five_pin_battery; bool multi_profile_load; int cutoff_volt_mv; int empty_volt_mv; int cutoff_curr_ma; Loading Loading @@ -249,6 +252,8 @@ struct fg_gen4_chip { int esr_nominal; int soh; int esr_soh_cycle_count; int batt_age_level; int last_batt_age_level; bool first_profile_load; bool ki_coeff_dischg_en; bool slope_limit_en; Loading Loading @@ -1323,7 +1328,7 @@ static int fg_gen4_get_batt_profile(struct fg_dev *fg) struct device_node *node = fg->dev->of_node; struct device_node *batt_node, *profile_node; const char *data; int rc, len, i, tuple_len; int rc, len, i, tuple_len, avail_age_level = 0; batt_node = of_find_node_by_name(node, "qcom,battery-data"); if (!batt_node) { Loading @@ -1331,6 +1336,11 @@ static int fg_gen4_get_batt_profile(struct fg_dev *fg) return -ENXIO; } if (chip->dt.multi_profile_load) profile_node = of_batterydata_get_best_aged_profile(batt_node, fg->batt_id_ohms / 1000, chip->batt_age_level, &avail_age_level); else profile_node = of_batterydata_get_best_profile(batt_node, fg->batt_id_ohms / 1000, NULL); if (IS_ERR(profile_node)) Loading @@ -1341,6 +1351,13 @@ static int fg_gen4_get_batt_profile(struct fg_dev *fg) return -ENODATA; } if (chip->dt.multi_profile_load && chip->batt_age_level != avail_age_level) { fg_dbg(fg, FG_STATUS, "Batt_age_level %d doesn't exist, using %d\n", chip->batt_age_level, avail_age_level); chip->batt_age_level = avail_age_level; } rc = of_property_read_string(profile_node, "qcom,battery-type", &fg->bp.batt_type_str); if (rc < 0) { Loading Loading @@ -1687,6 +1704,10 @@ static bool is_profile_load_required(struct fg_gen4_chip *chip) FIRST_PROFILE_LOAD_BIT, }; if (chip->dt.multi_profile_load && (chip->batt_age_level != chip->last_batt_age_level)) return true; rc = fg_sram_read(fg, PROFILE_INTEGRITY_WORD, PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT); if (rc < 0) { Loading Loading @@ -1756,47 +1777,29 @@ static bool is_profile_load_required(struct fg_gen4_chip *chip) } #define SOC_READY_WAIT_TIME_MS 1000 static void profile_load_work(struct work_struct *work) static int qpnp_fg_gen4_load_profile(struct fg_gen4_chip *chip) { struct fg_dev *fg = container_of(work, struct fg_dev, profile_load_work.work); struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); int64_t nom_cap_uah; struct fg_dev *fg = &chip->fg; u8 val, mask, buf[2]; int rc; bool normal_profile_load = false; vote(fg->awake_votable, PROFILE_LOAD, true, 0); rc = fg_gen4_get_batt_id(chip); if (rc < 0) { pr_err("Error in getting battery id, rc:%d\n", rc); goto out; } rc = fg_gen4_get_batt_profile(fg); if (rc < 0) { fg->profile_load_status = PROFILE_MISSING; pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n", fg->batt_id_ohms / 1000, rc); goto out; } if (!fg->profile_available) goto out; if (!is_profile_load_required(chip)) goto done; clear_cycle_count(chip->counter); fg_dbg(fg, FG_STATUS, "profile loading started\n"); rc = fg_masked_write(fg, BATT_SOC_RESTART(fg), RESTART_GO_BIT, 0); /* * This is used to determine if the profile is loaded normally i.e. * either multi profile loading is disabled OR if it is enabled, then * only loading the profile with battery age level 0 is considered. */ normal_profile_load = !chip->dt.multi_profile_load || (chip->dt.multi_profile_load && chip->batt_age_level == 0); if (normal_profile_load) { rc = fg_masked_write(fg, BATT_SOC_RESTART(fg), RESTART_GO_BIT, 0); if (rc < 0) { pr_err("Error in writing to %04x, rc=%d\n", BATT_SOC_RESTART(fg), rc); goto out; return rc; } } /* load battery profile */ Loading @@ -1804,25 +1807,30 @@ static void profile_load_work(struct work_struct *work) chip->batt_profile, PROFILE_LEN, FG_IMA_ATOMIC); if (rc < 0) { pr_err("Error in writing battery profile, rc:%d\n", rc); goto out; return rc; } if (normal_profile_load) { /* Enable side loading for voltage and current */ val = mask = BIT(0); rc = fg_sram_masked_write(fg, SYS_CONFIG_WORD, SYS_CONFIG_OFFSET, mask, val, FG_IMA_DEFAULT); if (rc < 0) { pr_err("Error in setting SYS_CONFIG_WORD[0], rc=%d\n", rc); goto out; pr_err("Error in setting SYS_CONFIG_WORD[0], rc=%d\n", rc); return rc; } /* Clear first logged main current ADC values */ buf[0] = buf[1] = 0; rc = fg_sram_write(fg, FIRST_LOG_CURRENT_v2_WORD, FIRST_LOG_CURRENT_v2_OFFSET, buf, 2, FG_IMA_DEFAULT); FIRST_LOG_CURRENT_v2_OFFSET, buf, 2, FG_IMA_DEFAULT); if (rc < 0) { pr_err("Error in clearing FIRST_LOG_CURRENT rc=%d\n", rc); goto out; pr_err("Error in clearing FIRST_LOG_CURRENT rc=%d\n", rc); return rc; } } /* Set the profile integrity bit */ Loading @@ -1831,13 +1839,24 @@ static void profile_load_work(struct work_struct *work) PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT); if (rc < 0) { pr_err("failed to write profile integrity rc=%d\n", rc); goto out; return rc; } if (chip->dt.multi_profile_load && chip->batt_age_level >= 0) { val = (u8)chip->batt_age_level; rc = fg_sram_write(fg, BATT_AGE_LEVEL_WORD, BATT_AGE_LEVEL_OFFSET, &val, 1, FG_IMA_ATOMIC); if (rc < 0) { pr_err("Error in writing batt_age_level, rc:%d\n", rc); return rc; } } if (normal_profile_load) { rc = fg_restart(fg, SOC_READY_WAIT_TIME_MS); if (rc < 0) { pr_err("Error in restarting FG, rc=%d\n", rc); goto out; return rc; } /* Clear side loading for voltage and current */ Loading @@ -1846,10 +1865,57 @@ static void profile_load_work(struct work_struct *work) rc = fg_sram_masked_write(fg, SYS_CONFIG_WORD, SYS_CONFIG_OFFSET, mask, val, FG_IMA_DEFAULT); if (rc < 0) { pr_err("Error in clearing SYS_CONFIG_WORD[0], rc=%d\n", rc); pr_err("Error in clearing SYS_CONFIG_WORD[0], rc=%d\n", rc); return rc; } } return 0; } static void profile_load_work(struct work_struct *work) { struct fg_dev *fg = container_of(work, struct fg_dev, profile_load_work.work); struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); int64_t nom_cap_uah; u8 val, buf[2]; int rc; vote(fg->awake_votable, PROFILE_LOAD, true, 0); rc = fg_gen4_get_batt_id(chip); if (rc < 0) { pr_err("Error in getting battery id, rc:%d\n", rc); goto out; } rc = fg_gen4_get_batt_profile(fg); if (rc < 0) { fg->profile_load_status = PROFILE_MISSING; pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n", fg->batt_id_ohms / 1000, rc); goto out; } if (!fg->profile_available) goto out; if (!is_profile_load_required(chip)) goto done; if (!chip->dt.multi_profile_load) clear_cycle_count(chip->counter); fg_dbg(fg, FG_STATUS, "profile loading started\n"); rc = qpnp_fg_gen4_load_profile(chip); if (rc < 0) goto out; fg_dbg(fg, FG_STATUS, "SOC is ready\n"); fg->profile_load_status = PROFILE_LOADED; Loading Loading @@ -1900,6 +1966,8 @@ static void profile_load_work(struct work_struct *work) schedule_delayed_work(&chip->ttf->ttf_work, msecs_to_jiffies(10000)); fg_dbg(fg, FG_STATUS, "profile loaded successfully"); out: if (chip->dt.multi_profile_load && rc < 0) chip->batt_age_level = chip->last_batt_age_level; fg->soc_reporting_ready = true; vote(fg->awake_votable, ESR_FCC_VOTER, true, 0); schedule_delayed_work(&chip->pl_enable_work, msecs_to_jiffies(5000)); Loading Loading @@ -3511,6 +3579,9 @@ static int fg_psy_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CC_STEP_SEL: pval->intval = chip->ttf->cc_step.sel; break; case POWER_SUPPLY_PROP_BATT_AGE_LEVEL: pval->intval = chip->batt_age_level; break; default: pr_err("unsupported property %d\n", psp); rc = -EINVAL; Loading Loading @@ -3592,6 +3663,14 @@ static int fg_psy_set_property(struct power_supply *psy, chip->first_profile_load = false; } break; case POWER_SUPPLY_PROP_BATT_AGE_LEVEL: if (!chip->dt.multi_profile_load || pval->intval < 0 || chip->batt_age_level == pval->intval) return -EINVAL; chip->last_batt_age_level = chip->batt_age_level; chip->batt_age_level = pval->intval; schedule_delayed_work(&fg->profile_load_work, 0); break; default: break; } Loading @@ -3610,6 +3689,7 @@ static int fg_property_is_writeable(struct power_supply *psy, case POWER_SUPPLY_PROP_ESR_NOMINAL: case POWER_SUPPLY_PROP_SOH: case POWER_SUPPLY_PROP_CLEAR_SOH: case POWER_SUPPLY_PROP_BATT_AGE_LEVEL: return 1; default: break; Loading Loading @@ -3646,6 +3726,7 @@ static enum power_supply_property fg_psy_props[] = { POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, POWER_SUPPLY_PROP_CC_STEP, POWER_SUPPLY_PROP_CC_STEP_SEL, POWER_SUPPLY_PROP_BATT_AGE_LEVEL, }; static const struct power_supply_desc fg_psy_desc = { Loading Loading @@ -4220,6 +4301,13 @@ static int fg_gen4_hw_init(struct fg_gen4_chip *chip) return rc; } chip->batt_age_level = chip->last_batt_age_level = -EINVAL; if (chip->dt.multi_profile_load) { rc = fg_sram_read(fg, BATT_AGE_LEVEL_WORD, BATT_AGE_LEVEL_OFFSET, &val, 1, FG_IMA_DEFAULT); if (!rc) chip->batt_age_level = chip->last_batt_age_level = val; } return 0; } Loading Loading @@ -4701,6 +4789,8 @@ static int fg_gen4_parse_dt(struct fg_gen4_chip *chip) chip->dt.five_pin_battery = of_property_read_bool(node, "qcom,five-pin-battery"); chip->dt.multi_profile_load = of_property_read_bool(node, "qcom,multi-profile-load"); return 0; } Loading Loading
Documentation/devicetree/bindings/power/supply/qcom/qpnp-fg-gen4.txt +8 −0 Original line number Diff line number Diff line Loading @@ -397,6 +397,14 @@ First Level Node - FG Gen4 device five pin battery is used. Based on this, time to full calculations would use the Rbatt calculated properly. - qcom,multi-profile-load Usage: optional Value type: <empty> Definition: A boolean property that when specified indicates that multiple profile loading needs to be enabled. This requires multiple battery profiles to be specified for a battery for proper functionality. ========================================================== Second Level Nodes - Peripherals managed by FG Gen4 driver ========================================================== Loading
drivers/power/supply/qcom/qpnp-fg-gen4.c +150 −60 Original line number Diff line number Diff line Loading @@ -116,6 +116,8 @@ #define RCONN_OFFSET 0 #define ACT_BATT_CAP_WORD 285 #define ACT_BATT_CAP_OFFSET 0 #define BATT_AGE_LEVEL_WORD 288 #define BATT_AGE_LEVEL_OFFSET 0 #define CYCLE_COUNT_WORD 291 #define CYCLE_COUNT_OFFSET 0 #define PROFILE_INTEGRITY_WORD 299 Loading Loading @@ -190,6 +192,7 @@ struct fg_dt_props { bool linearize_soc; bool rapid_soc_dec_en; bool five_pin_battery; bool multi_profile_load; int cutoff_volt_mv; int empty_volt_mv; int cutoff_curr_ma; Loading Loading @@ -249,6 +252,8 @@ struct fg_gen4_chip { int esr_nominal; int soh; int esr_soh_cycle_count; int batt_age_level; int last_batt_age_level; bool first_profile_load; bool ki_coeff_dischg_en; bool slope_limit_en; Loading Loading @@ -1323,7 +1328,7 @@ static int fg_gen4_get_batt_profile(struct fg_dev *fg) struct device_node *node = fg->dev->of_node; struct device_node *batt_node, *profile_node; const char *data; int rc, len, i, tuple_len; int rc, len, i, tuple_len, avail_age_level = 0; batt_node = of_find_node_by_name(node, "qcom,battery-data"); if (!batt_node) { Loading @@ -1331,6 +1336,11 @@ static int fg_gen4_get_batt_profile(struct fg_dev *fg) return -ENXIO; } if (chip->dt.multi_profile_load) profile_node = of_batterydata_get_best_aged_profile(batt_node, fg->batt_id_ohms / 1000, chip->batt_age_level, &avail_age_level); else profile_node = of_batterydata_get_best_profile(batt_node, fg->batt_id_ohms / 1000, NULL); if (IS_ERR(profile_node)) Loading @@ -1341,6 +1351,13 @@ static int fg_gen4_get_batt_profile(struct fg_dev *fg) return -ENODATA; } if (chip->dt.multi_profile_load && chip->batt_age_level != avail_age_level) { fg_dbg(fg, FG_STATUS, "Batt_age_level %d doesn't exist, using %d\n", chip->batt_age_level, avail_age_level); chip->batt_age_level = avail_age_level; } rc = of_property_read_string(profile_node, "qcom,battery-type", &fg->bp.batt_type_str); if (rc < 0) { Loading Loading @@ -1687,6 +1704,10 @@ static bool is_profile_load_required(struct fg_gen4_chip *chip) FIRST_PROFILE_LOAD_BIT, }; if (chip->dt.multi_profile_load && (chip->batt_age_level != chip->last_batt_age_level)) return true; rc = fg_sram_read(fg, PROFILE_INTEGRITY_WORD, PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT); if (rc < 0) { Loading Loading @@ -1756,47 +1777,29 @@ static bool is_profile_load_required(struct fg_gen4_chip *chip) } #define SOC_READY_WAIT_TIME_MS 1000 static void profile_load_work(struct work_struct *work) static int qpnp_fg_gen4_load_profile(struct fg_gen4_chip *chip) { struct fg_dev *fg = container_of(work, struct fg_dev, profile_load_work.work); struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); int64_t nom_cap_uah; struct fg_dev *fg = &chip->fg; u8 val, mask, buf[2]; int rc; bool normal_profile_load = false; vote(fg->awake_votable, PROFILE_LOAD, true, 0); rc = fg_gen4_get_batt_id(chip); if (rc < 0) { pr_err("Error in getting battery id, rc:%d\n", rc); goto out; } rc = fg_gen4_get_batt_profile(fg); if (rc < 0) { fg->profile_load_status = PROFILE_MISSING; pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n", fg->batt_id_ohms / 1000, rc); goto out; } if (!fg->profile_available) goto out; if (!is_profile_load_required(chip)) goto done; clear_cycle_count(chip->counter); fg_dbg(fg, FG_STATUS, "profile loading started\n"); rc = fg_masked_write(fg, BATT_SOC_RESTART(fg), RESTART_GO_BIT, 0); /* * This is used to determine if the profile is loaded normally i.e. * either multi profile loading is disabled OR if it is enabled, then * only loading the profile with battery age level 0 is considered. */ normal_profile_load = !chip->dt.multi_profile_load || (chip->dt.multi_profile_load && chip->batt_age_level == 0); if (normal_profile_load) { rc = fg_masked_write(fg, BATT_SOC_RESTART(fg), RESTART_GO_BIT, 0); if (rc < 0) { pr_err("Error in writing to %04x, rc=%d\n", BATT_SOC_RESTART(fg), rc); goto out; return rc; } } /* load battery profile */ Loading @@ -1804,25 +1807,30 @@ static void profile_load_work(struct work_struct *work) chip->batt_profile, PROFILE_LEN, FG_IMA_ATOMIC); if (rc < 0) { pr_err("Error in writing battery profile, rc:%d\n", rc); goto out; return rc; } if (normal_profile_load) { /* Enable side loading for voltage and current */ val = mask = BIT(0); rc = fg_sram_masked_write(fg, SYS_CONFIG_WORD, SYS_CONFIG_OFFSET, mask, val, FG_IMA_DEFAULT); if (rc < 0) { pr_err("Error in setting SYS_CONFIG_WORD[0], rc=%d\n", rc); goto out; pr_err("Error in setting SYS_CONFIG_WORD[0], rc=%d\n", rc); return rc; } /* Clear first logged main current ADC values */ buf[0] = buf[1] = 0; rc = fg_sram_write(fg, FIRST_LOG_CURRENT_v2_WORD, FIRST_LOG_CURRENT_v2_OFFSET, buf, 2, FG_IMA_DEFAULT); FIRST_LOG_CURRENT_v2_OFFSET, buf, 2, FG_IMA_DEFAULT); if (rc < 0) { pr_err("Error in clearing FIRST_LOG_CURRENT rc=%d\n", rc); goto out; pr_err("Error in clearing FIRST_LOG_CURRENT rc=%d\n", rc); return rc; } } /* Set the profile integrity bit */ Loading @@ -1831,13 +1839,24 @@ static void profile_load_work(struct work_struct *work) PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT); if (rc < 0) { pr_err("failed to write profile integrity rc=%d\n", rc); goto out; return rc; } if (chip->dt.multi_profile_load && chip->batt_age_level >= 0) { val = (u8)chip->batt_age_level; rc = fg_sram_write(fg, BATT_AGE_LEVEL_WORD, BATT_AGE_LEVEL_OFFSET, &val, 1, FG_IMA_ATOMIC); if (rc < 0) { pr_err("Error in writing batt_age_level, rc:%d\n", rc); return rc; } } if (normal_profile_load) { rc = fg_restart(fg, SOC_READY_WAIT_TIME_MS); if (rc < 0) { pr_err("Error in restarting FG, rc=%d\n", rc); goto out; return rc; } /* Clear side loading for voltage and current */ Loading @@ -1846,10 +1865,57 @@ static void profile_load_work(struct work_struct *work) rc = fg_sram_masked_write(fg, SYS_CONFIG_WORD, SYS_CONFIG_OFFSET, mask, val, FG_IMA_DEFAULT); if (rc < 0) { pr_err("Error in clearing SYS_CONFIG_WORD[0], rc=%d\n", rc); pr_err("Error in clearing SYS_CONFIG_WORD[0], rc=%d\n", rc); return rc; } } return 0; } static void profile_load_work(struct work_struct *work) { struct fg_dev *fg = container_of(work, struct fg_dev, profile_load_work.work); struct fg_gen4_chip *chip = container_of(fg, struct fg_gen4_chip, fg); int64_t nom_cap_uah; u8 val, buf[2]; int rc; vote(fg->awake_votable, PROFILE_LOAD, true, 0); rc = fg_gen4_get_batt_id(chip); if (rc < 0) { pr_err("Error in getting battery id, rc:%d\n", rc); goto out; } rc = fg_gen4_get_batt_profile(fg); if (rc < 0) { fg->profile_load_status = PROFILE_MISSING; pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n", fg->batt_id_ohms / 1000, rc); goto out; } if (!fg->profile_available) goto out; if (!is_profile_load_required(chip)) goto done; if (!chip->dt.multi_profile_load) clear_cycle_count(chip->counter); fg_dbg(fg, FG_STATUS, "profile loading started\n"); rc = qpnp_fg_gen4_load_profile(chip); if (rc < 0) goto out; fg_dbg(fg, FG_STATUS, "SOC is ready\n"); fg->profile_load_status = PROFILE_LOADED; Loading Loading @@ -1900,6 +1966,8 @@ static void profile_load_work(struct work_struct *work) schedule_delayed_work(&chip->ttf->ttf_work, msecs_to_jiffies(10000)); fg_dbg(fg, FG_STATUS, "profile loaded successfully"); out: if (chip->dt.multi_profile_load && rc < 0) chip->batt_age_level = chip->last_batt_age_level; fg->soc_reporting_ready = true; vote(fg->awake_votable, ESR_FCC_VOTER, true, 0); schedule_delayed_work(&chip->pl_enable_work, msecs_to_jiffies(5000)); Loading Loading @@ -3511,6 +3579,9 @@ static int fg_psy_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CC_STEP_SEL: pval->intval = chip->ttf->cc_step.sel; break; case POWER_SUPPLY_PROP_BATT_AGE_LEVEL: pval->intval = chip->batt_age_level; break; default: pr_err("unsupported property %d\n", psp); rc = -EINVAL; Loading Loading @@ -3592,6 +3663,14 @@ static int fg_psy_set_property(struct power_supply *psy, chip->first_profile_load = false; } break; case POWER_SUPPLY_PROP_BATT_AGE_LEVEL: if (!chip->dt.multi_profile_load || pval->intval < 0 || chip->batt_age_level == pval->intval) return -EINVAL; chip->last_batt_age_level = chip->batt_age_level; chip->batt_age_level = pval->intval; schedule_delayed_work(&fg->profile_load_work, 0); break; default: break; } Loading @@ -3610,6 +3689,7 @@ static int fg_property_is_writeable(struct power_supply *psy, case POWER_SUPPLY_PROP_ESR_NOMINAL: case POWER_SUPPLY_PROP_SOH: case POWER_SUPPLY_PROP_CLEAR_SOH: case POWER_SUPPLY_PROP_BATT_AGE_LEVEL: return 1; default: break; Loading Loading @@ -3646,6 +3726,7 @@ static enum power_supply_property fg_psy_props[] = { POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, POWER_SUPPLY_PROP_CC_STEP, POWER_SUPPLY_PROP_CC_STEP_SEL, POWER_SUPPLY_PROP_BATT_AGE_LEVEL, }; static const struct power_supply_desc fg_psy_desc = { Loading Loading @@ -4220,6 +4301,13 @@ static int fg_gen4_hw_init(struct fg_gen4_chip *chip) return rc; } chip->batt_age_level = chip->last_batt_age_level = -EINVAL; if (chip->dt.multi_profile_load) { rc = fg_sram_read(fg, BATT_AGE_LEVEL_WORD, BATT_AGE_LEVEL_OFFSET, &val, 1, FG_IMA_DEFAULT); if (!rc) chip->batt_age_level = chip->last_batt_age_level = val; } return 0; } Loading Loading @@ -4701,6 +4789,8 @@ static int fg_gen4_parse_dt(struct fg_gen4_chip *chip) chip->dt.five_pin_battery = of_property_read_bool(node, "qcom,five-pin-battery"); chip->dt.multi_profile_load = of_property_read_bool(node, "qcom,multi-profile-load"); return 0; } Loading