Loading drivers/power/qpnp-fg.c +96 −50 Original line number Diff line number Diff line Loading @@ -400,6 +400,7 @@ struct fg_chip { struct completion sram_access_granted; struct completion sram_access_revoked; struct completion batt_id_avail; struct completion first_soc_done; struct power_supply bms_psy; struct mutex rw_lock; struct mutex sysfs_restart_lock; Loading Loading @@ -427,6 +428,7 @@ struct fg_chip { bool first_profile_loaded; struct fg_wakeup_source update_temp_wakeup_source; struct fg_wakeup_source update_sram_wakeup_source; bool fg_restarting; bool profile_loaded; bool use_otp_profile; bool battery_missing; Loading Loading @@ -1926,6 +1928,9 @@ static void update_sram_data(struct fg_chip *chip, int *resched_ms) int battid_valid = fg_is_batt_id_valid(chip); fg_stay_awake(&chip->update_sram_wakeup_source); if (chip->fg_restarting) goto resched; fg_mem_lock(chip); for (i = 1; i < FG_DATA_MAX; i++) { if (chip->profile_loaded && i >= FG_DATA_BATT_ID) Loading Loading @@ -1994,6 +1999,7 @@ static void update_sram_data(struct fg_chip *chip, int *resched_ms) if (!rc) get_current_time(&chip->last_sram_update_time); resched: if (battid_valid) { complete_all(&chip->batt_id_avail); *resched_ms = fg_sram_update_period_ms; Loading Loading @@ -2055,6 +2061,9 @@ static void update_temp_data(struct work_struct *work) struct fg_chip, update_temp_work.work); if (chip->fg_restarting) goto resched; fg_stay_awake(&chip->update_temp_wakeup_source); if (chip->sw_rbias_ctrl) { rc = fg_mem_masked_write(chip, EXTERNAL_SENSE_SELECT, Loading Loading @@ -2110,10 +2119,12 @@ out: if (rc) pr_err("failed to write BATT_TEMP_OFF rc=%d\n", rc); } fg_relax(&chip->update_temp_wakeup_source); resched: schedule_delayed_work( &chip->update_temp_work, msecs_to_jiffies(TEMP_PERIOD_UPDATE_MS)); fg_relax(&chip->update_temp_wakeup_source); } static void update_jeita_setting(struct work_struct *work) Loading Loading @@ -2555,6 +2566,11 @@ static int fg_power_get_property(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_BATTERY_TYPE: if (chip->battery_missing) val->strval = missing_batt_type; else if (chip->fg_restarting) val->strval = loading_batt_type; else val->strval = chip->batt_type; break; case POWER_SUPPLY_PROP_CAPACITY: Loading Loading @@ -3662,7 +3678,7 @@ static irqreturn_t fg_batt_missing_irq_handler(int irq, void *_chip) if (batt_missing) { chip->battery_missing = true; chip->profile_loaded = false; chip->batt_type = missing_batt_type; chip->batt_type = default_batt_type; mutex_lock(&chip->cyc_ctr.lock); if (fg_debug_mask & FG_IRQS) pr_info("battery missing, clearing cycle counters\n"); Loading @@ -3687,6 +3703,7 @@ static irqreturn_t fg_batt_missing_irq_handler(int irq, void *_chip) if (chip->power_supply_registered) power_supply_changed(&chip->bms_psy); complete_all(&chip->first_soc_done); return IRQ_HANDLED; } Loading Loading @@ -4142,14 +4159,32 @@ static void update_cc_cv_setpoint(struct fg_chip *chip) #define FIRST_EST_DONE_BIT BIT(5) #define MAX_TRIES_FIRST_EST 3 #define FIRST_EST_WAIT_MS 2000 #define PROFILE_LOAD_TIMEOUT_MS 5000 static int fg_do_restart(struct fg_chip *chip, bool write_profile) { int rc; int tries = 0; u8 reg = 0; u8 buf[2]; if (fg_debug_mask & FG_STATUS) pr_info("restarting fuel gauge...\n"); chip->fg_restarting = true; /* * save the temperature if the sw rbias control is active so that there * is no gap of time when there is no valid temperature read after the * restart */ if (chip->sw_rbias_ctrl) { rc = fg_mem_read(chip, buf, fg_data[FG_DATA_BATT_TEMP].address, fg_data[FG_DATA_BATT_TEMP].len, fg_data[FG_DATA_BATT_TEMP].offset, 0); if (rc) { pr_err("failed to read batt temp rc=%d\n", rc); goto sub_and_fail; } } /* * release the sram access and configure the correct settings * before re-requesting access. Loading Loading @@ -4246,18 +4281,18 @@ static int fg_do_restart(struct fg_chip *chip, bool write_profile) } /* wait for the first estimate to complete */ for (tries = 0; tries < MAX_TRIES_FIRST_EST; tries++) { msleep(FIRST_EST_WAIT_MS); rc = wait_for_completion_interruptible_timeout(&chip->first_soc_done, msecs_to_jiffies(PROFILE_LOAD_TIMEOUT_MS)); if (rc <= 0) { pr_err("transaction timed out rc=%d\n", rc); rc = -ETIMEDOUT; goto fail; } rc = fg_read(chip, ®, INT_RT_STS(chip->soc_base), 1); if (rc) { pr_err("spmi read failed: addr=%03X, rc=%d\n", INT_RT_STS(chip->soc_base), rc); } if (reg & FIRST_EST_DONE_BIT) break; if (fg_debug_mask & FG_STATUS) pr_info("waiting for est, tries = %d\n", tries); goto fail; } if ((reg & FIRST_EST_DONE_BIT) == 0) pr_err("Battery profile reloading failed, no first estimate\n"); Loading @@ -4277,6 +4312,22 @@ static int fg_do_restart(struct fg_chip *chip, bool write_profile) goto fail; } /* restore the battery temperature reading here */ if (chip->sw_rbias_ctrl) { if (fg_debug_mask & FG_STATUS) pr_info("reloaded 0x%02x%02x into batt temp", buf[0], buf[1]); rc = fg_mem_write(chip, buf, fg_data[FG_DATA_BATT_TEMP].address, fg_data[FG_DATA_BATT_TEMP].len, fg_data[FG_DATA_BATT_TEMP].offset, 0); if (rc) { pr_err("failed to write batt temp rc=%d\n", rc); goto fail; } } chip->fg_restarting = false; if (fg_debug_mask & FG_STATUS) pr_info("done!\n"); return 0; Loading @@ -4288,10 +4339,10 @@ sub_and_fail: fg_release_access_if_necessary(chip); goto fail; fail: chip->fg_restarting = false; return -EINVAL; } #define PROFILE_LOAD_TIMEOUT_MS 5000 #define FG_PROFILE_LEN 128 #define PROFILE_COMPARE_LEN 32 #define THERMAL_COEFF_ADDR 0x444 Loading @@ -4302,7 +4353,7 @@ static int fg_batt_profile_init(struct fg_chip *chip) int len; struct device_node *node = chip->spmi->dev.of_node; struct device_node *batt_node, *profile_node; const char *data, *batt_type_str, *old_batt_type; const char *data, *batt_type_str; bool tried_again = false, vbat_in_range, profiles_same; u8 reg = 0; Loading Loading @@ -4335,9 +4386,8 @@ wait: fg_batt_type); if (!profile_node) { pr_err("couldn't find profile handle\n"); old_batt_type = default_batt_type; rc = -ENODATA; goto fail; goto no_profile; } /* read rslow compensation values if they're available */ Loading Loading @@ -4387,29 +4437,6 @@ wait: &chip->cc_cv_threshold_mv); } /* * Only configure from profile if thermal-coefficients is not * defined in the FG device node. */ if (!of_find_property(chip->spmi->dev.of_node, "qcom,thermal-coefficients", NULL)) { data = of_get_property(profile_node, "qcom,thermal-coefficients", &len); if (data && len == THERMAL_COEFF_N_BYTES) { memcpy(chip->thermal_coefficients, data, len); rc = fg_mem_write(chip, chip->thermal_coefficients, THERMAL_COEFF_ADDR, THERMAL_COEFF_N_BYTES, THERMAL_COEFF_OFFSET, 0); if (rc) { pr_err("spmi write failed addr:%03x, ret:%d\n", THERMAL_COEFF_ADDR, rc); goto fail; } else { pr_debug("Battery thermal coefficients changed\n"); } } } data = of_get_property(profile_node, "qcom,fg-profile-data", &len); if (!data) { pr_err("no battery profile loaded\n"); Loading @@ -4420,7 +4447,7 @@ wait: if (len != FG_PROFILE_LEN) { pr_err("battery profile incorrect size: %d\n", len); rc = -EINVAL; goto fail; goto no_profile; } rc = of_property_read_string(profile_node, "qcom,battery-type", Loading Loading @@ -4487,8 +4514,6 @@ wait: DUMP_PREFIX_NONE, 16, 1, chip->batt_profile, len, false); } old_batt_type = chip->batt_type; chip->batt_type = loading_batt_type; if (chip->power_supply_registered) power_supply_changed(&chip->bms_psy); Loading @@ -4504,7 +4529,28 @@ wait: rc = fg_do_restart(chip, true); if (rc) { pr_err("restart failed: %d\n", rc); goto fail; goto no_profile; } /* * Only configure from profile if thermal-coefficients is not * defined in the FG device node. */ if (!of_find_property(chip->spmi->dev.of_node, "qcom,thermal-coefficients", NULL)) { data = of_get_property(profile_node, "qcom,thermal-coefficients", &len); if (data && len == THERMAL_COEFF_N_BYTES) { memcpy(chip->thermal_coefficients, data, len); rc = fg_mem_write(chip, chip->thermal_coefficients, THERMAL_COEFF_ADDR, THERMAL_COEFF_N_BYTES, THERMAL_COEFF_OFFSET, 0); if (rc) pr_err("spmi write failed addr:%03x, ret:%d\n", THERMAL_COEFF_ADDR, rc); else if (fg_debug_mask & FG_STATUS) pr_info("Battery thermal coefficients changed\n"); } } done: Loading @@ -4529,11 +4575,9 @@ done: fg_relax(&chip->profile_wakeup_source); pr_info("Battery SOC: %d\n", get_prop_capacity(chip)); return rc; fail: chip->batt_type = old_batt_type; no_profile: if (chip->power_supply_registered) power_supply_changed(&chip->bms_psy); no_profile: fg_relax(&chip->profile_wakeup_source); return rc; } Loading Loading @@ -6022,6 +6066,8 @@ static int fg_probe(struct spmi_device *spmi) init_completion(&chip->sram_access_revoked); complete_all(&chip->sram_access_revoked); init_completion(&chip->batt_id_avail); init_completion(&chip->first_soc_done); complete_all(&chip->first_soc_done); dev_set_drvdata(&spmi->dev, chip); spmi_for_each_container_dev(spmi_resource, spmi) { Loading Loading
drivers/power/qpnp-fg.c +96 −50 Original line number Diff line number Diff line Loading @@ -400,6 +400,7 @@ struct fg_chip { struct completion sram_access_granted; struct completion sram_access_revoked; struct completion batt_id_avail; struct completion first_soc_done; struct power_supply bms_psy; struct mutex rw_lock; struct mutex sysfs_restart_lock; Loading Loading @@ -427,6 +428,7 @@ struct fg_chip { bool first_profile_loaded; struct fg_wakeup_source update_temp_wakeup_source; struct fg_wakeup_source update_sram_wakeup_source; bool fg_restarting; bool profile_loaded; bool use_otp_profile; bool battery_missing; Loading Loading @@ -1926,6 +1928,9 @@ static void update_sram_data(struct fg_chip *chip, int *resched_ms) int battid_valid = fg_is_batt_id_valid(chip); fg_stay_awake(&chip->update_sram_wakeup_source); if (chip->fg_restarting) goto resched; fg_mem_lock(chip); for (i = 1; i < FG_DATA_MAX; i++) { if (chip->profile_loaded && i >= FG_DATA_BATT_ID) Loading Loading @@ -1994,6 +1999,7 @@ static void update_sram_data(struct fg_chip *chip, int *resched_ms) if (!rc) get_current_time(&chip->last_sram_update_time); resched: if (battid_valid) { complete_all(&chip->batt_id_avail); *resched_ms = fg_sram_update_period_ms; Loading Loading @@ -2055,6 +2061,9 @@ static void update_temp_data(struct work_struct *work) struct fg_chip, update_temp_work.work); if (chip->fg_restarting) goto resched; fg_stay_awake(&chip->update_temp_wakeup_source); if (chip->sw_rbias_ctrl) { rc = fg_mem_masked_write(chip, EXTERNAL_SENSE_SELECT, Loading Loading @@ -2110,10 +2119,12 @@ out: if (rc) pr_err("failed to write BATT_TEMP_OFF rc=%d\n", rc); } fg_relax(&chip->update_temp_wakeup_source); resched: schedule_delayed_work( &chip->update_temp_work, msecs_to_jiffies(TEMP_PERIOD_UPDATE_MS)); fg_relax(&chip->update_temp_wakeup_source); } static void update_jeita_setting(struct work_struct *work) Loading Loading @@ -2555,6 +2566,11 @@ static int fg_power_get_property(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_BATTERY_TYPE: if (chip->battery_missing) val->strval = missing_batt_type; else if (chip->fg_restarting) val->strval = loading_batt_type; else val->strval = chip->batt_type; break; case POWER_SUPPLY_PROP_CAPACITY: Loading Loading @@ -3662,7 +3678,7 @@ static irqreturn_t fg_batt_missing_irq_handler(int irq, void *_chip) if (batt_missing) { chip->battery_missing = true; chip->profile_loaded = false; chip->batt_type = missing_batt_type; chip->batt_type = default_batt_type; mutex_lock(&chip->cyc_ctr.lock); if (fg_debug_mask & FG_IRQS) pr_info("battery missing, clearing cycle counters\n"); Loading @@ -3687,6 +3703,7 @@ static irqreturn_t fg_batt_missing_irq_handler(int irq, void *_chip) if (chip->power_supply_registered) power_supply_changed(&chip->bms_psy); complete_all(&chip->first_soc_done); return IRQ_HANDLED; } Loading Loading @@ -4142,14 +4159,32 @@ static void update_cc_cv_setpoint(struct fg_chip *chip) #define FIRST_EST_DONE_BIT BIT(5) #define MAX_TRIES_FIRST_EST 3 #define FIRST_EST_WAIT_MS 2000 #define PROFILE_LOAD_TIMEOUT_MS 5000 static int fg_do_restart(struct fg_chip *chip, bool write_profile) { int rc; int tries = 0; u8 reg = 0; u8 buf[2]; if (fg_debug_mask & FG_STATUS) pr_info("restarting fuel gauge...\n"); chip->fg_restarting = true; /* * save the temperature if the sw rbias control is active so that there * is no gap of time when there is no valid temperature read after the * restart */ if (chip->sw_rbias_ctrl) { rc = fg_mem_read(chip, buf, fg_data[FG_DATA_BATT_TEMP].address, fg_data[FG_DATA_BATT_TEMP].len, fg_data[FG_DATA_BATT_TEMP].offset, 0); if (rc) { pr_err("failed to read batt temp rc=%d\n", rc); goto sub_and_fail; } } /* * release the sram access and configure the correct settings * before re-requesting access. Loading Loading @@ -4246,18 +4281,18 @@ static int fg_do_restart(struct fg_chip *chip, bool write_profile) } /* wait for the first estimate to complete */ for (tries = 0; tries < MAX_TRIES_FIRST_EST; tries++) { msleep(FIRST_EST_WAIT_MS); rc = wait_for_completion_interruptible_timeout(&chip->first_soc_done, msecs_to_jiffies(PROFILE_LOAD_TIMEOUT_MS)); if (rc <= 0) { pr_err("transaction timed out rc=%d\n", rc); rc = -ETIMEDOUT; goto fail; } rc = fg_read(chip, ®, INT_RT_STS(chip->soc_base), 1); if (rc) { pr_err("spmi read failed: addr=%03X, rc=%d\n", INT_RT_STS(chip->soc_base), rc); } if (reg & FIRST_EST_DONE_BIT) break; if (fg_debug_mask & FG_STATUS) pr_info("waiting for est, tries = %d\n", tries); goto fail; } if ((reg & FIRST_EST_DONE_BIT) == 0) pr_err("Battery profile reloading failed, no first estimate\n"); Loading @@ -4277,6 +4312,22 @@ static int fg_do_restart(struct fg_chip *chip, bool write_profile) goto fail; } /* restore the battery temperature reading here */ if (chip->sw_rbias_ctrl) { if (fg_debug_mask & FG_STATUS) pr_info("reloaded 0x%02x%02x into batt temp", buf[0], buf[1]); rc = fg_mem_write(chip, buf, fg_data[FG_DATA_BATT_TEMP].address, fg_data[FG_DATA_BATT_TEMP].len, fg_data[FG_DATA_BATT_TEMP].offset, 0); if (rc) { pr_err("failed to write batt temp rc=%d\n", rc); goto fail; } } chip->fg_restarting = false; if (fg_debug_mask & FG_STATUS) pr_info("done!\n"); return 0; Loading @@ -4288,10 +4339,10 @@ sub_and_fail: fg_release_access_if_necessary(chip); goto fail; fail: chip->fg_restarting = false; return -EINVAL; } #define PROFILE_LOAD_TIMEOUT_MS 5000 #define FG_PROFILE_LEN 128 #define PROFILE_COMPARE_LEN 32 #define THERMAL_COEFF_ADDR 0x444 Loading @@ -4302,7 +4353,7 @@ static int fg_batt_profile_init(struct fg_chip *chip) int len; struct device_node *node = chip->spmi->dev.of_node; struct device_node *batt_node, *profile_node; const char *data, *batt_type_str, *old_batt_type; const char *data, *batt_type_str; bool tried_again = false, vbat_in_range, profiles_same; u8 reg = 0; Loading Loading @@ -4335,9 +4386,8 @@ wait: fg_batt_type); if (!profile_node) { pr_err("couldn't find profile handle\n"); old_batt_type = default_batt_type; rc = -ENODATA; goto fail; goto no_profile; } /* read rslow compensation values if they're available */ Loading Loading @@ -4387,29 +4437,6 @@ wait: &chip->cc_cv_threshold_mv); } /* * Only configure from profile if thermal-coefficients is not * defined in the FG device node. */ if (!of_find_property(chip->spmi->dev.of_node, "qcom,thermal-coefficients", NULL)) { data = of_get_property(profile_node, "qcom,thermal-coefficients", &len); if (data && len == THERMAL_COEFF_N_BYTES) { memcpy(chip->thermal_coefficients, data, len); rc = fg_mem_write(chip, chip->thermal_coefficients, THERMAL_COEFF_ADDR, THERMAL_COEFF_N_BYTES, THERMAL_COEFF_OFFSET, 0); if (rc) { pr_err("spmi write failed addr:%03x, ret:%d\n", THERMAL_COEFF_ADDR, rc); goto fail; } else { pr_debug("Battery thermal coefficients changed\n"); } } } data = of_get_property(profile_node, "qcom,fg-profile-data", &len); if (!data) { pr_err("no battery profile loaded\n"); Loading @@ -4420,7 +4447,7 @@ wait: if (len != FG_PROFILE_LEN) { pr_err("battery profile incorrect size: %d\n", len); rc = -EINVAL; goto fail; goto no_profile; } rc = of_property_read_string(profile_node, "qcom,battery-type", Loading Loading @@ -4487,8 +4514,6 @@ wait: DUMP_PREFIX_NONE, 16, 1, chip->batt_profile, len, false); } old_batt_type = chip->batt_type; chip->batt_type = loading_batt_type; if (chip->power_supply_registered) power_supply_changed(&chip->bms_psy); Loading @@ -4504,7 +4529,28 @@ wait: rc = fg_do_restart(chip, true); if (rc) { pr_err("restart failed: %d\n", rc); goto fail; goto no_profile; } /* * Only configure from profile if thermal-coefficients is not * defined in the FG device node. */ if (!of_find_property(chip->spmi->dev.of_node, "qcom,thermal-coefficients", NULL)) { data = of_get_property(profile_node, "qcom,thermal-coefficients", &len); if (data && len == THERMAL_COEFF_N_BYTES) { memcpy(chip->thermal_coefficients, data, len); rc = fg_mem_write(chip, chip->thermal_coefficients, THERMAL_COEFF_ADDR, THERMAL_COEFF_N_BYTES, THERMAL_COEFF_OFFSET, 0); if (rc) pr_err("spmi write failed addr:%03x, ret:%d\n", THERMAL_COEFF_ADDR, rc); else if (fg_debug_mask & FG_STATUS) pr_info("Battery thermal coefficients changed\n"); } } done: Loading @@ -4529,11 +4575,9 @@ done: fg_relax(&chip->profile_wakeup_source); pr_info("Battery SOC: %d\n", get_prop_capacity(chip)); return rc; fail: chip->batt_type = old_batt_type; no_profile: if (chip->power_supply_registered) power_supply_changed(&chip->bms_psy); no_profile: fg_relax(&chip->profile_wakeup_source); return rc; } Loading Loading @@ -6022,6 +6066,8 @@ static int fg_probe(struct spmi_device *spmi) init_completion(&chip->sram_access_revoked); complete_all(&chip->sram_access_revoked); init_completion(&chip->batt_id_avail); init_completion(&chip->first_soc_done); complete_all(&chip->first_soc_done); dev_set_drvdata(&spmi->dev, chip); spmi_for_each_container_dev(spmi_resource, spmi) { Loading