Loading arch/arm/boot/dts/qcom/msm-pmi8994.dtsi +2 −1 Original line number Diff line number Diff line Loading @@ -306,6 +306,7 @@ qcom,cycle-counter-high-soc = <85>; qcom,capacity-learning-on; qcom,fg-cc-cv-threshold-mv = <4340>; qcom,pmic-revid = <&pmi8994_revid>; qcom,fg-soc@4000 { status = "okay"; Loading Loading @@ -455,7 +456,7 @@ qcom,qpnp-lab-switching-clock-frequency = <1600>; qcom,qpnp-lab-limit-maximum-current = <800>; qcom,qpnp-lab-limit-max-current-enable; qcom,qpnp-lab-ps-threshold = <40>; qcom,qpnp-lab-ps-threshold = <20>; qcom,qpnp-lab-ps-enable; qcom,qpnp-lab-nfet-size = <100>; qcom,qpnp-lab-pfet-size = <100>; Loading drivers/platform/msm/qpnp-revid.c +2 −2 Original line number Diff line number Diff line /* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -208,7 +208,7 @@ static void __exit qpnp_revid_exit(void) return spmi_driver_unregister(&qpnp_revid_driver); } module_init(qpnp_revid_init); subsys_initcall(qpnp_revid_init); module_exit(qpnp_revid_exit); MODULE_DESCRIPTION("QPNP REVID DRIVER"); Loading drivers/power/power_supply_sysfs.c +1 −0 Original line number Diff line number Diff line Loading @@ -234,6 +234,7 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(charge_done), POWER_SUPPLY_ATTR(allow_detection), POWER_SUPPLY_ATTR(flash_active), POWER_SUPPLY_ATTR(force_tlim), /* Local extensions of type int64_t */ POWER_SUPPLY_ATTR(charge_counter_ext), /* Properties of type `const char *' */ Loading drivers/power/qpnp-fg.c +376 −160 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include <linux/of_batterydata.h> #include <linux/string_helpers.h> #include <linux/alarmtimer.h> #include <linux/qpnp/qpnp-revid.h> /* Register offsets */ Loading Loading @@ -92,6 +93,11 @@ enum dig_major { DIG_REV_8950_3 = 0x3, }; enum pmic_subtype { PMI8994 = 10, PMI8950 = 17, }; struct fg_mem_setting { u16 address; u8 offset; Loading Loading @@ -229,6 +235,7 @@ module_param_named( ); static int fg_sense_type = -EINVAL; static int fg_restart; static int fg_est_dump; module_param_named( Loading @@ -240,6 +247,11 @@ module_param_named( battery_type, fg_batt_type, charp, S_IRUSR | S_IWUSR ); static int fg_sram_update_period_ms = 30000; module_param_named( sram_update_period_ms, fg_sram_update_period_ms, int, S_IRUSR | S_IWUSR ); struct fg_irq { int irq; unsigned long disabled; Loading Loading @@ -341,6 +353,7 @@ static void fg_relax(struct fg_wakeup_source *source) struct fg_chip { struct device *dev; struct spmi_device *spmi; u8 pmic_subtype; u8 revision[4]; u16 soc_base; u16 batt_base; Loading @@ -358,6 +371,7 @@ struct fg_chip { struct power_supply bms_psy; struct mutex rw_lock; struct mutex cyc_ctr_lock; struct mutex sysfs_restart_lock; struct work_struct batt_profile_init; struct work_struct dump_sram; struct work_struct status_change_work; Loading @@ -366,6 +380,7 @@ struct fg_chip { struct work_struct update_esr_work; struct work_struct set_resume_soc_work; struct work_struct rslow_comp_work; struct work_struct sysfs_restart_work; struct power_supply *batt_psy; struct power_supply *usb_psy; struct power_supply *dc_psy; Loading Loading @@ -1835,7 +1850,6 @@ static int64_t twos_compliment_extend(int64_t val, int nbytes) #define LSB_8B 9800 #define TEMP_LSB_16B 625 #define DECIKELVIN 2730 #define SRAM_PERIOD_UPDATE_MS 30000 #define SRAM_PERIOD_NO_ID_UPDATE_MS 100 #define FULL_PERCENT_28BIT 0xFFFFFFF static void update_sram_data(struct fg_chip *chip, int *resched_ms) Loading Loading @@ -1916,22 +1930,39 @@ static void update_sram_data(struct fg_chip *chip, int *resched_ms) if (battid_valid) { complete_all(&chip->batt_id_avail); *resched_ms = SRAM_PERIOD_UPDATE_MS; *resched_ms = fg_sram_update_period_ms; } else { *resched_ms = SRAM_PERIOD_NO_ID_UPDATE_MS; } fg_relax(&chip->update_sram_wakeup_source); } #define SRAM_TIMEOUT_MS 3000 static void update_sram_data_work(struct work_struct *work) { struct fg_chip *chip = container_of(work, struct fg_chip, update_sram_data.work); int resched_ms; int resched_ms, ret; bool tried_again = false; wait: /* Wait for MEMIF access revoked */ ret = wait_for_completion_interruptible_timeout( &chip->sram_access_revoked, msecs_to_jiffies(SRAM_TIMEOUT_MS)); /* If we were interrupted wait again one more time. */ if (ret == -ERESTARTSYS && !tried_again) { tried_again = true; goto wait; } else if (ret <= 0) { pr_err("transaction timed out ret=%d\n", ret); goto out; } update_sram_data(chip, &resched_ms); out: schedule_delayed_work( &chip->update_sram_data, msecs_to_jiffies(resched_ms)); Loading @@ -1955,7 +1986,6 @@ static void update_temp_data(struct work_struct *work) fg_stay_awake(&chip->update_temp_wakeup_source); if (chip->sw_rbias_ctrl) { reinit_completion(&chip->sram_access_revoked); rc = fg_mem_masked_write(chip, EXTERNAL_SENSE_SELECT, BATT_TEMP_CNTRL_MASK, BATT_TEMP_ON, Loading Loading @@ -3145,6 +3175,7 @@ static irqreturn_t fg_mem_avail_irq_handler(int irq, void *_chip) if ((fg_debug_mask & FG_IRQS) & (FG_MEM_DEBUG_READS | FG_MEM_DEBUG_WRITES)) pr_info("sram access granted\n"); reinit_completion(&chip->sram_access_revoked); complete_all(&chip->sram_access_granted); } else { if ((fg_debug_mask & FG_IRQS) Loading Loading @@ -3560,24 +3591,175 @@ static void update_cc_cv_setpoint(struct fg_chip *chip) tmp[0], tmp[1], CC_CV_SETPOINT_REG); } #define V_PREDICTED_ADDR 0x540 #define V_CURRENT_PREDICTED_OFFSET 0 #define LOW_LATENCY BIT(6) #define PROFILE_LOAD_TIMEOUT_MS 5000 #define BATT_PROFILE_OFFSET 0x4C0 #define PROFILE_INTEGRITY_REG 0x53C #define PROFILE_INTEGRITY_BIT BIT(0) #define FIRST_EST_DONE_BIT BIT(5) #define MAX_TRIES_FIRST_EST 3 #define FIRST_EST_WAIT_MS 2000 static int fg_do_restart(struct fg_chip *chip, bool write_profile) { int rc; int tries = 0; u8 reg = 0; if (fg_debug_mask & FG_STATUS) pr_info("restarting fuel gauge...\n"); /* * release the sram access and configure the correct settings * before re-requesting access. */ mutex_lock(&chip->rw_lock); fg_release_access(chip); rc = fg_masked_write(chip, chip->soc_base + SOC_BOOT_MOD, NO_OTP_PROF_RELOAD, 0, 1); if (rc) { pr_err("failed to set no otp reload bit\n"); goto unlock_and_fail; } /* unset the restart bits so the fg doesn't continuously restart */ reg = REDO_FIRST_ESTIMATE | RESTART_GO; rc = fg_masked_write(chip, chip->soc_base + SOC_RESTART, reg, 0, 1); if (rc) { pr_err("failed to unset fg restart: %d\n", rc); goto unlock_and_fail; } rc = fg_masked_write(chip, MEM_INTF_CFG(chip), LOW_LATENCY, LOW_LATENCY, 1); if (rc) { pr_err("failed to set low latency access bit\n"); goto unlock_and_fail; } mutex_unlock(&chip->rw_lock); /* read once to get a fg cycle in */ rc = fg_mem_read(chip, ®, PROFILE_INTEGRITY_REG, 1, 0, 0); if (rc) { pr_err("failed to read profile integrity rc=%d\n", rc); goto fail; } /* * If this is not the first time a profile has been loaded, sleep for * 3 seconds to make sure the NO_OTP_RELOAD is cleared in memory */ if (chip->first_profile_loaded) msleep(3000); mutex_lock(&chip->rw_lock); fg_release_access(chip); rc = fg_masked_write(chip, MEM_INTF_CFG(chip), LOW_LATENCY, 0, 1); if (rc) { pr_err("failed to set low latency access bit\n"); goto unlock_and_fail; } atomic_add_return(1, &chip->memif_user_cnt); mutex_unlock(&chip->rw_lock); if (write_profile) { /* write the battery profile */ rc = fg_mem_write(chip, chip->batt_profile, BATT_PROFILE_OFFSET, chip->batt_profile_len, 0, 1); if (rc) { pr_err("failed to write profile rc=%d\n", rc); goto sub_and_fail; } /* write the integrity bits and release access */ rc = fg_mem_masked_write(chip, PROFILE_INTEGRITY_REG, PROFILE_INTEGRITY_BIT, PROFILE_INTEGRITY_BIT, 0); if (rc) { pr_err("failed to write profile rc=%d\n", rc); goto sub_and_fail; } } /* decrement the user count so that memory access can be released */ fg_release_access_if_necessary(chip); /* * set the restart bits so that the next fg cycle will not reload * the profile */ rc = fg_masked_write(chip, chip->soc_base + SOC_BOOT_MOD, NO_OTP_PROF_RELOAD, NO_OTP_PROF_RELOAD, 1); if (rc) { pr_err("failed to set no otp reload bit\n"); goto fail; } reg = REDO_FIRST_ESTIMATE | RESTART_GO; rc = fg_masked_write(chip, chip->soc_base + SOC_RESTART, reg, reg, 1); if (rc) { pr_err("failed to set fg restart: %d\n", rc); goto fail; } /* wait for the first estimate to complete */ for (tries = 0; tries < MAX_TRIES_FIRST_EST; tries++) { msleep(FIRST_EST_WAIT_MS); 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); } if ((reg & FIRST_EST_DONE_BIT) == 0) pr_err("Battery profile reloading failed, no first estimate\n"); rc = fg_masked_write(chip, chip->soc_base + SOC_BOOT_MOD, NO_OTP_PROF_RELOAD, 0, 1); if (rc) { pr_err("failed to set no otp reload bit\n"); goto fail; } /* unset the restart bits so the fg doesn't continuously restart */ reg = REDO_FIRST_ESTIMATE | RESTART_GO; rc = fg_masked_write(chip, chip->soc_base + SOC_RESTART, reg, 0, 1); if (rc) { pr_err("failed to unset fg restart: %d\n", rc); goto fail; } if (fg_debug_mask & FG_STATUS) pr_info("done!\n"); return 0; unlock_and_fail: mutex_unlock(&chip->rw_lock); goto fail; sub_and_fail: fg_release_access_if_necessary(chip); goto fail; fail: return -EINVAL; } #define V_PREDICTED_ADDR 0x540 #define V_CURRENT_PREDICTED_OFFSET 0 #define PROFILE_LOAD_TIMEOUT_MS 5000 #define FG_PROFILE_LEN 128 #define PROFILE_COMPARE_LEN 32 static int fg_batt_profile_init(struct fg_chip *chip) { int rc = 0, ret; int len, tries; 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; bool tried_again = false, vbat_in_range; bool tried_again = false, vbat_in_range, profiles_same; u8 reg = 0; wait: Loading Loading @@ -3654,6 +3836,12 @@ wait: goto no_profile; } if (len != FG_PROFILE_LEN) { pr_err("battery profile incorrect size: %d\n", len); rc = -EINVAL; goto fail; } rc = of_property_read_string(profile_node, "qcom,battery-type", &batt_type_str); if (rc) { Loading Loading @@ -3688,11 +3876,13 @@ wait: vbat_in_range = abs(fg_data[FG_DATA_VOLTAGE].value - fg_data[FG_DATA_CPRED_VOLTAGE].value) < settings[FG_MEM_VBAT_EST_DIFF].value * 1000; profiles_same = memcmp(chip->batt_profile, data, PROFILE_COMPARE_LEN) == 0; if (reg & PROFILE_INTEGRITY_BIT) fg_cap_learning_load_data(chip); if ((reg & PROFILE_INTEGRITY_BIT) && vbat_in_range && !fg_is_batt_empty(chip) && memcmp(chip->batt_profile, data, len - 4) == 0) { && profiles_same) { if (fg_debug_mask & FG_STATUS) pr_info("Battery profiles same, using default\n"); if (fg_est_dump) Loading @@ -3707,6 +3897,8 @@ wait: fg_data[FG_DATA_VOLTAGE].value); if ((fg_debug_mask & FG_STATUS) && fg_is_batt_empty(chip)) pr_info("battery empty\n"); if ((fg_debug_mask & FG_STATUS) && !profiles_same) pr_info("profiles differ\n"); if (fg_debug_mask & FG_STATUS) { pr_info("Using new profile\n"); print_hex_dump(KERN_INFO, "FG: loaded profile: ", Loading @@ -3727,131 +3919,12 @@ wait: DUMP_PREFIX_NONE, 16, 1, chip->batt_profile, chip->batt_profile_len, false); /* * release the sram access and configure the correct settings * before re-requesting access. */ mutex_lock(&chip->rw_lock); fg_release_access(chip); rc = fg_masked_write(chip, chip->soc_base + SOC_BOOT_MOD, NO_OTP_PROF_RELOAD, 0, 1); rc = fg_do_restart(chip, true); if (rc) { pr_err("failed to set no otp reload bit\n"); goto unlock_and_fail; } /* unset the restart bits so the fg doesn't continuously restart */ reg = REDO_FIRST_ESTIMATE | RESTART_GO; rc = fg_masked_write(chip, chip->soc_base + SOC_RESTART, reg, 0, 1); if (rc) { pr_err("failed to unset fg restart: %d\n", rc); goto unlock_and_fail; } rc = fg_masked_write(chip, MEM_INTF_CFG(chip), LOW_LATENCY, LOW_LATENCY, 1); if (rc) { pr_err("failed to set low latency access bit\n"); goto unlock_and_fail; } mutex_unlock(&chip->rw_lock); /* read once to get a fg cycle in */ rc = fg_mem_read(chip, ®, PROFILE_INTEGRITY_REG, 1, 0, 0); if (rc) { pr_err("failed to read profile integrity rc=%d\n", rc); pr_err("restart failed: %d\n", rc); goto fail; } /* * If this is not the first time a profile has been loaded, sleep for * 3 seconds to make sure the NO_OTP_RELOAD is cleared in memory */ if (chip->first_profile_loaded) msleep(3000); mutex_lock(&chip->rw_lock); fg_release_access(chip); rc = fg_masked_write(chip, MEM_INTF_CFG(chip), LOW_LATENCY, 0, 1); if (rc) { pr_err("failed to set low latency access bit\n"); goto unlock_and_fail; } atomic_add_return(1, &chip->memif_user_cnt); mutex_unlock(&chip->rw_lock); /* write the battery profile */ rc = fg_mem_write(chip, chip->batt_profile, BATT_PROFILE_OFFSET, chip->batt_profile_len, 0, 1); if (rc) { pr_err("failed to write profile rc=%d\n", rc); goto sub_and_fail; } /* write the integrity bits and release access */ rc = fg_mem_masked_write(chip, PROFILE_INTEGRITY_REG, PROFILE_INTEGRITY_BIT, PROFILE_INTEGRITY_BIT, 0); if (rc) { pr_err("failed to write profile rc=%d\n", rc); goto sub_and_fail; } /* decrement the user count so that memory access can be released */ fg_release_access_if_necessary(chip); /* * set the restart bits so that the next fg cycle will reload * the profile */ rc = fg_masked_write(chip, chip->soc_base + SOC_BOOT_MOD, NO_OTP_PROF_RELOAD, NO_OTP_PROF_RELOAD, 1); if (rc) { pr_err("failed to set no otp reload bit\n"); goto fail; } reg = REDO_FIRST_ESTIMATE | RESTART_GO; rc = fg_masked_write(chip, chip->soc_base + SOC_RESTART, reg, reg, 1); if (rc) { pr_err("failed to set fg restart: %d\n", rc); goto fail; } /* wait for the first estimate to complete */ for (tries = 0; tries < MAX_TRIES_FIRST_EST; tries++) { msleep(FIRST_EST_WAIT_MS); 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; else if (fg_debug_mask & FG_STATUS) pr_info("waiting for est, tries = %d\n", tries); } if ((reg & FIRST_EST_DONE_BIT) == 0) pr_err("Battery profile reloading failed, no first estimate\n"); rc = fg_masked_write(chip, chip->soc_base + SOC_BOOT_MOD, NO_OTP_PROF_RELOAD, 0, 1); if (rc) { pr_err("failed to set no otp reload bit\n"); goto fail; } /* unset the restart bits so the fg doesn't continuously restart */ reg = REDO_FIRST_ESTIMATE | RESTART_GO; rc = fg_masked_write(chip, chip->soc_base + SOC_RESTART, reg, 0, 1); if (rc) { pr_err("failed to unset fg restart: %d\n", rc); goto fail; } done: if (fg_batt_type) chip->batt_type = fg_batt_type; Loading @@ -3873,12 +3946,6 @@ done: power_supply_changed(&chip->bms_psy); fg_relax(&chip->profile_wakeup_source); return rc; unlock_and_fail: mutex_unlock(&chip->rw_lock); goto fail; sub_and_fail: fg_release_access_if_necessary(chip); goto fail; fail: chip->batt_type = old_batt_type; if (chip->power_supply_registered) Loading Loading @@ -3914,6 +3981,21 @@ static void batt_profile_init(struct work_struct *work) pr_err("failed to initialize profile\n"); } static void sysfs_restart_work(struct work_struct *work) { struct fg_chip *chip = container_of(work, struct fg_chip, sysfs_restart_work); int rc; rc = fg_do_restart(chip, false); if (rc) pr_err("fg restart failed: %d\n", rc); mutex_lock(&chip->sysfs_restart_lock); fg_restart = 0; mutex_unlock(&chip->sysfs_restart_lock); } static void update_bcl_thresholds(struct fg_chip *chip) { u8 data[4]; Loading Loading @@ -4327,9 +4409,13 @@ static int fg_remove(struct spmi_device *spmi) cancel_work_sync(&chip->status_change_work); cancel_work_sync(&chip->cycle_count_work); cancel_work_sync(&chip->update_esr_work); cancel_work_sync(&chip->sysfs_restart_work); power_supply_unregister(&chip->bms_psy); mutex_destroy(&chip->rslow_comp.lock); mutex_destroy(&chip->rw_lock); mutex_destroy(&chip->cyc_ctr_lock); mutex_destroy(&chip->learning_data.learning_lock); mutex_destroy(&chip->sysfs_restart_lock); wakeup_source_trash(&chip->resume_soc_wakeup_source.source); wakeup_source_trash(&chip->empty_check_wakeup_source.source); wakeup_source_trash(&chip->memif_wakeup_source.source); Loading Loading @@ -4805,27 +4891,16 @@ static int bcl_trim_workaround(struct fg_chip *chip) #define FG_ADC_CONFIG_REG 0x4B8 #define FG_BCL_CONFIG_OFFSET 0x3 #define BCL_FORCED_HPM_IN_CHARGE BIT(2) static int fg_hw_init(struct fg_chip *chip) static int fg_common_hw_init(struct fg_chip *chip) { int rc; u8 resume_soc; u8 data[4]; u64 esr_value; int rc = 0; update_iterm(chip); update_cutoff_voltage(chip); update_irq_volt_empty(chip); update_bcl_thresholds(chip); rc = fg_mem_masked_write(chip, EXTERNAL_SENSE_SELECT, PATCH_NEG_CURRENT_BIT, PATCH_NEG_CURRENT_BIT, EXTERNAL_SENSE_OFFSET); if (rc) { pr_err("failed to write patch current bit rc=%d\n", rc); return rc; } resume_soc = settings[FG_MEM_RESUME_SOC].value; if (resume_soc > 0) { resume_soc = resume_soc * 255 / 100; Loading Loading @@ -4879,6 +4954,30 @@ static int fg_hw_init(struct fg_chip *chip) return rc; } if (chip->use_thermal_coefficients) { fg_mem_write(chip, chip->thermal_coefficients, THERMAL_COEFF_ADDR, THERMAL_COEFF_N_BYTES, THERMAL_COEFF_OFFSET, 0); } return 0; } static int fg_8994_hw_init(struct fg_chip *chip) { int rc = 0; u8 data[4]; u64 esr_value; rc = fg_mem_masked_write(chip, EXTERNAL_SENSE_SELECT, PATCH_NEG_CURRENT_BIT, PATCH_NEG_CURRENT_BIT, EXTERNAL_SENSE_OFFSET); if (rc) { pr_err("failed to write patch current bit rc=%d\n", rc); return rc; } rc = bcl_trim_workaround(chip); if (rc) { pr_err("failed to redo bcl trim rc=%d\n", rc); Loading @@ -4894,12 +4993,6 @@ static int fg_hw_init(struct fg_chip *chip) return rc; } if (chip->use_thermal_coefficients) { fg_mem_write(chip, chip->thermal_coefficients, THERMAL_COEFF_ADDR, THERMAL_COEFF_N_BYTES, THERMAL_COEFF_OFFSET, 0); } fg_mem_masked_write(chip, FG_ALG_SYSCTL_1, I_TERM_QUAL_BIT, 0, 0); data[0] = 0xA2; Loading Loading @@ -4935,6 +5028,45 @@ static int fg_hw_init(struct fg_chip *chip) return 0; } static int fg_8950_hw_init(struct fg_chip *chip) { int rc; rc = fg_mem_masked_write(chip, FG_ADC_CONFIG_REG, BCL_FORCED_HPM_IN_CHARGE, BCL_FORCED_HPM_IN_CHARGE, FG_BCL_CONFIG_OFFSET); if (rc) pr_err("failed to force hpm in charge rc=%d\n", rc); return rc; } static int fg_hw_init(struct fg_chip *chip) { int rc = 0; rc = fg_common_hw_init(chip); if (rc) { pr_err("Unable to initialize FG HW rc=%d\n", rc); return rc; } /* add PMIC specific hw init */ switch (chip->pmic_subtype) { case PMI8994: rc = fg_8994_hw_init(chip); break; case PMI8950: rc = fg_8950_hw_init(chip); break; } if (rc) pr_err("Unable to initialize PMIC specific FG HW rc=%d\n", rc); return rc; } #define DIG_MINOR 0x0 #define DIG_MAJOR 0x1 #define ANA_MINOR 0x2 Loading Loading @@ -4983,6 +5115,44 @@ static int fg_setup_memif_offset(struct fg_chip *chip) return 0; } static int fg_detect_pmic_type(struct fg_chip *chip) { struct pmic_revid_data *pmic_rev_id; struct device_node *revid_dev_node; revid_dev_node = of_parse_phandle(chip->spmi->dev.of_node, "qcom,pmic-revid", 0); if (!revid_dev_node) { pr_err("Missing qcom,pmic-revid property - driver failed\n"); return -EINVAL; } pmic_rev_id = get_revid_data(revid_dev_node); if (IS_ERR(pmic_rev_id)) { pr_err("Unable to get pmic_revid rc=%ld\n", PTR_ERR(pmic_rev_id)); /* * the revid peripheral must be registered, any failure * here only indicates that the rev-id module has not * probed yet. */ return -EPROBE_DEFER; } switch (pmic_rev_id->pmic_subtype) { case PMI8994: case PMI8950: chip->pmic_subtype = pmic_rev_id->pmic_subtype; break; default: pr_err("PMIC subtype %d not supported\n", pmic_rev_id->pmic_subtype); return -EINVAL; } return 0; } #define INIT_JEITA_DELAY_MS 1000 static int fg_probe(struct spmi_device *spmi) { Loading Loading @@ -5028,6 +5198,7 @@ static int fg_probe(struct spmi_device *spmi) mutex_init(&chip->cyc_ctr_lock); mutex_init(&chip->learning_data.learning_lock); mutex_init(&chip->rslow_comp.lock); mutex_init(&chip->sysfs_restart_lock); INIT_DELAYED_WORK(&chip->update_jeita_setting, update_jeita_setting); INIT_DELAYED_WORK(&chip->update_sram_data, update_sram_data_work); INIT_DELAYED_WORK(&chip->update_temp_work, update_temp_data); Loading @@ -5041,10 +5212,12 @@ static int fg_probe(struct spmi_device *spmi) INIT_WORK(&chip->battery_age_work, battery_age_work); INIT_WORK(&chip->update_esr_work, update_esr_value); INIT_WORK(&chip->set_resume_soc_work, set_resume_soc_work); INIT_WORK(&chip->sysfs_restart_work, sysfs_restart_work); alarm_init(&chip->fg_cap_learning_alarm, ALARM_BOOTTIME, fg_cap_learning_alarm_cb); init_completion(&chip->sram_access_granted); init_completion(&chip->sram_access_revoked); complete_all(&chip->sram_access_revoked); init_completion(&chip->batt_id_avail); dev_set_drvdata(&spmi->dev, chip); Loading Loading @@ -5101,6 +5274,12 @@ static int fg_probe(struct spmi_device *spmi) } } rc = fg_detect_pmic_type(chip); if (rc) { pr_err("Unable to detect PMIC type rc=%d\n", rc); return rc; } rc = fg_setup_memif_offset(chip); if (rc) { pr_err("Unable to setup mem_if offsets rc=%d\n", rc); Loading Loading @@ -5184,9 +5363,10 @@ static int fg_probe(struct spmi_device *spmi) if (!chip->use_otp_profile) schedule_work(&chip->batt_profile_init); pr_info("FG Probe success - FG Revision DIG:%d.%d ANA:%d.%d\n", pr_info("FG Probe success - FG Revision DIG:%d.%d ANA:%d.%d PMIC subtype=%d\n", chip->revision[DIG_MAJOR], chip->revision[DIG_MINOR], chip->revision[ANA_MAJOR], chip->revision[ANA_MINOR]); chip->revision[ANA_MAJOR], chip->revision[ANA_MINOR], chip->pmic_subtype); return rc; Loading @@ -5206,11 +5386,13 @@ cancel_work: cancel_work_sync(&chip->cycle_count_work); cancel_work_sync(&chip->update_esr_work); cancel_work_sync(&chip->rslow_comp_work); cancel_work_sync(&chip->sysfs_restart_work); of_init_fail: mutex_destroy(&chip->rslow_comp.lock); mutex_destroy(&chip->rw_lock); mutex_destroy(&chip->cyc_ctr_lock); mutex_destroy(&chip->learning_data.learning_lock); mutex_destroy(&chip->sysfs_restart_lock); wakeup_source_trash(&chip->resume_soc_wakeup_source.source); wakeup_source_trash(&chip->empty_check_wakeup_source.source); wakeup_source_trash(&chip->memif_wakeup_source.source); Loading Loading @@ -5238,7 +5420,7 @@ static void check_and_update_sram_data(struct fg_chip *chip) &chip->update_temp_work, msecs_to_jiffies(time_left * 1000)); next_update_time = chip->last_sram_update_time + (SRAM_PERIOD_UPDATE_MS / 1000); + (fg_sram_update_period_ms / 1000); if (next_update_time > current_time) time_left = next_update_time - current_time; Loading Loading @@ -5318,6 +5500,40 @@ static struct kernel_param_ops fg_sense_type_ops = { module_param_cb(sense_type, &fg_sense_type_ops, &fg_sense_type, 0644); static int fg_restart_set(const char *val, const struct kernel_param *kp) { struct power_supply *bms_psy; struct fg_chip *chip; bms_psy = power_supply_get_by_name("bms"); if (!bms_psy) { pr_err("bms psy not found\n"); return 0; } chip = container_of(bms_psy, struct fg_chip, bms_psy); mutex_lock(&chip->sysfs_restart_lock); if (fg_restart != 0) { mutex_unlock(&chip->sysfs_restart_lock); return 0; } fg_restart = 1; mutex_unlock(&chip->sysfs_restart_lock); if (fg_debug_mask & FG_STATUS) pr_info("fuel gauge restart initiated from sysfs...\n"); schedule_work(&chip->sysfs_restart_work); return 0; } static struct kernel_param_ops fg_restart_ops = { .set = fg_restart_set, .get = param_get_int, }; module_param_cb(restart, &fg_restart_ops, &fg_restart, 0644); static struct spmi_driver fg_driver = { .driver = { .name = QPNP_FG_DEV_NAME, Loading Loading
arch/arm/boot/dts/qcom/msm-pmi8994.dtsi +2 −1 Original line number Diff line number Diff line Loading @@ -306,6 +306,7 @@ qcom,cycle-counter-high-soc = <85>; qcom,capacity-learning-on; qcom,fg-cc-cv-threshold-mv = <4340>; qcom,pmic-revid = <&pmi8994_revid>; qcom,fg-soc@4000 { status = "okay"; Loading Loading @@ -455,7 +456,7 @@ qcom,qpnp-lab-switching-clock-frequency = <1600>; qcom,qpnp-lab-limit-maximum-current = <800>; qcom,qpnp-lab-limit-max-current-enable; qcom,qpnp-lab-ps-threshold = <40>; qcom,qpnp-lab-ps-threshold = <20>; qcom,qpnp-lab-ps-enable; qcom,qpnp-lab-nfet-size = <100>; qcom,qpnp-lab-pfet-size = <100>; Loading
drivers/platform/msm/qpnp-revid.c +2 −2 Original line number Diff line number Diff line /* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -208,7 +208,7 @@ static void __exit qpnp_revid_exit(void) return spmi_driver_unregister(&qpnp_revid_driver); } module_init(qpnp_revid_init); subsys_initcall(qpnp_revid_init); module_exit(qpnp_revid_exit); MODULE_DESCRIPTION("QPNP REVID DRIVER"); Loading
drivers/power/power_supply_sysfs.c +1 −0 Original line number Diff line number Diff line Loading @@ -234,6 +234,7 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(charge_done), POWER_SUPPLY_ATTR(allow_detection), POWER_SUPPLY_ATTR(flash_active), POWER_SUPPLY_ATTR(force_tlim), /* Local extensions of type int64_t */ POWER_SUPPLY_ATTR(charge_counter_ext), /* Properties of type `const char *' */ Loading
drivers/power/qpnp-fg.c +376 −160 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include <linux/of_batterydata.h> #include <linux/string_helpers.h> #include <linux/alarmtimer.h> #include <linux/qpnp/qpnp-revid.h> /* Register offsets */ Loading Loading @@ -92,6 +93,11 @@ enum dig_major { DIG_REV_8950_3 = 0x3, }; enum pmic_subtype { PMI8994 = 10, PMI8950 = 17, }; struct fg_mem_setting { u16 address; u8 offset; Loading Loading @@ -229,6 +235,7 @@ module_param_named( ); static int fg_sense_type = -EINVAL; static int fg_restart; static int fg_est_dump; module_param_named( Loading @@ -240,6 +247,11 @@ module_param_named( battery_type, fg_batt_type, charp, S_IRUSR | S_IWUSR ); static int fg_sram_update_period_ms = 30000; module_param_named( sram_update_period_ms, fg_sram_update_period_ms, int, S_IRUSR | S_IWUSR ); struct fg_irq { int irq; unsigned long disabled; Loading Loading @@ -341,6 +353,7 @@ static void fg_relax(struct fg_wakeup_source *source) struct fg_chip { struct device *dev; struct spmi_device *spmi; u8 pmic_subtype; u8 revision[4]; u16 soc_base; u16 batt_base; Loading @@ -358,6 +371,7 @@ struct fg_chip { struct power_supply bms_psy; struct mutex rw_lock; struct mutex cyc_ctr_lock; struct mutex sysfs_restart_lock; struct work_struct batt_profile_init; struct work_struct dump_sram; struct work_struct status_change_work; Loading @@ -366,6 +380,7 @@ struct fg_chip { struct work_struct update_esr_work; struct work_struct set_resume_soc_work; struct work_struct rslow_comp_work; struct work_struct sysfs_restart_work; struct power_supply *batt_psy; struct power_supply *usb_psy; struct power_supply *dc_psy; Loading Loading @@ -1835,7 +1850,6 @@ static int64_t twos_compliment_extend(int64_t val, int nbytes) #define LSB_8B 9800 #define TEMP_LSB_16B 625 #define DECIKELVIN 2730 #define SRAM_PERIOD_UPDATE_MS 30000 #define SRAM_PERIOD_NO_ID_UPDATE_MS 100 #define FULL_PERCENT_28BIT 0xFFFFFFF static void update_sram_data(struct fg_chip *chip, int *resched_ms) Loading Loading @@ -1916,22 +1930,39 @@ static void update_sram_data(struct fg_chip *chip, int *resched_ms) if (battid_valid) { complete_all(&chip->batt_id_avail); *resched_ms = SRAM_PERIOD_UPDATE_MS; *resched_ms = fg_sram_update_period_ms; } else { *resched_ms = SRAM_PERIOD_NO_ID_UPDATE_MS; } fg_relax(&chip->update_sram_wakeup_source); } #define SRAM_TIMEOUT_MS 3000 static void update_sram_data_work(struct work_struct *work) { struct fg_chip *chip = container_of(work, struct fg_chip, update_sram_data.work); int resched_ms; int resched_ms, ret; bool tried_again = false; wait: /* Wait for MEMIF access revoked */ ret = wait_for_completion_interruptible_timeout( &chip->sram_access_revoked, msecs_to_jiffies(SRAM_TIMEOUT_MS)); /* If we were interrupted wait again one more time. */ if (ret == -ERESTARTSYS && !tried_again) { tried_again = true; goto wait; } else if (ret <= 0) { pr_err("transaction timed out ret=%d\n", ret); goto out; } update_sram_data(chip, &resched_ms); out: schedule_delayed_work( &chip->update_sram_data, msecs_to_jiffies(resched_ms)); Loading @@ -1955,7 +1986,6 @@ static void update_temp_data(struct work_struct *work) fg_stay_awake(&chip->update_temp_wakeup_source); if (chip->sw_rbias_ctrl) { reinit_completion(&chip->sram_access_revoked); rc = fg_mem_masked_write(chip, EXTERNAL_SENSE_SELECT, BATT_TEMP_CNTRL_MASK, BATT_TEMP_ON, Loading Loading @@ -3145,6 +3175,7 @@ static irqreturn_t fg_mem_avail_irq_handler(int irq, void *_chip) if ((fg_debug_mask & FG_IRQS) & (FG_MEM_DEBUG_READS | FG_MEM_DEBUG_WRITES)) pr_info("sram access granted\n"); reinit_completion(&chip->sram_access_revoked); complete_all(&chip->sram_access_granted); } else { if ((fg_debug_mask & FG_IRQS) Loading Loading @@ -3560,24 +3591,175 @@ static void update_cc_cv_setpoint(struct fg_chip *chip) tmp[0], tmp[1], CC_CV_SETPOINT_REG); } #define V_PREDICTED_ADDR 0x540 #define V_CURRENT_PREDICTED_OFFSET 0 #define LOW_LATENCY BIT(6) #define PROFILE_LOAD_TIMEOUT_MS 5000 #define BATT_PROFILE_OFFSET 0x4C0 #define PROFILE_INTEGRITY_REG 0x53C #define PROFILE_INTEGRITY_BIT BIT(0) #define FIRST_EST_DONE_BIT BIT(5) #define MAX_TRIES_FIRST_EST 3 #define FIRST_EST_WAIT_MS 2000 static int fg_do_restart(struct fg_chip *chip, bool write_profile) { int rc; int tries = 0; u8 reg = 0; if (fg_debug_mask & FG_STATUS) pr_info("restarting fuel gauge...\n"); /* * release the sram access and configure the correct settings * before re-requesting access. */ mutex_lock(&chip->rw_lock); fg_release_access(chip); rc = fg_masked_write(chip, chip->soc_base + SOC_BOOT_MOD, NO_OTP_PROF_RELOAD, 0, 1); if (rc) { pr_err("failed to set no otp reload bit\n"); goto unlock_and_fail; } /* unset the restart bits so the fg doesn't continuously restart */ reg = REDO_FIRST_ESTIMATE | RESTART_GO; rc = fg_masked_write(chip, chip->soc_base + SOC_RESTART, reg, 0, 1); if (rc) { pr_err("failed to unset fg restart: %d\n", rc); goto unlock_and_fail; } rc = fg_masked_write(chip, MEM_INTF_CFG(chip), LOW_LATENCY, LOW_LATENCY, 1); if (rc) { pr_err("failed to set low latency access bit\n"); goto unlock_and_fail; } mutex_unlock(&chip->rw_lock); /* read once to get a fg cycle in */ rc = fg_mem_read(chip, ®, PROFILE_INTEGRITY_REG, 1, 0, 0); if (rc) { pr_err("failed to read profile integrity rc=%d\n", rc); goto fail; } /* * If this is not the first time a profile has been loaded, sleep for * 3 seconds to make sure the NO_OTP_RELOAD is cleared in memory */ if (chip->first_profile_loaded) msleep(3000); mutex_lock(&chip->rw_lock); fg_release_access(chip); rc = fg_masked_write(chip, MEM_INTF_CFG(chip), LOW_LATENCY, 0, 1); if (rc) { pr_err("failed to set low latency access bit\n"); goto unlock_and_fail; } atomic_add_return(1, &chip->memif_user_cnt); mutex_unlock(&chip->rw_lock); if (write_profile) { /* write the battery profile */ rc = fg_mem_write(chip, chip->batt_profile, BATT_PROFILE_OFFSET, chip->batt_profile_len, 0, 1); if (rc) { pr_err("failed to write profile rc=%d\n", rc); goto sub_and_fail; } /* write the integrity bits and release access */ rc = fg_mem_masked_write(chip, PROFILE_INTEGRITY_REG, PROFILE_INTEGRITY_BIT, PROFILE_INTEGRITY_BIT, 0); if (rc) { pr_err("failed to write profile rc=%d\n", rc); goto sub_and_fail; } } /* decrement the user count so that memory access can be released */ fg_release_access_if_necessary(chip); /* * set the restart bits so that the next fg cycle will not reload * the profile */ rc = fg_masked_write(chip, chip->soc_base + SOC_BOOT_MOD, NO_OTP_PROF_RELOAD, NO_OTP_PROF_RELOAD, 1); if (rc) { pr_err("failed to set no otp reload bit\n"); goto fail; } reg = REDO_FIRST_ESTIMATE | RESTART_GO; rc = fg_masked_write(chip, chip->soc_base + SOC_RESTART, reg, reg, 1); if (rc) { pr_err("failed to set fg restart: %d\n", rc); goto fail; } /* wait for the first estimate to complete */ for (tries = 0; tries < MAX_TRIES_FIRST_EST; tries++) { msleep(FIRST_EST_WAIT_MS); 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); } if ((reg & FIRST_EST_DONE_BIT) == 0) pr_err("Battery profile reloading failed, no first estimate\n"); rc = fg_masked_write(chip, chip->soc_base + SOC_BOOT_MOD, NO_OTP_PROF_RELOAD, 0, 1); if (rc) { pr_err("failed to set no otp reload bit\n"); goto fail; } /* unset the restart bits so the fg doesn't continuously restart */ reg = REDO_FIRST_ESTIMATE | RESTART_GO; rc = fg_masked_write(chip, chip->soc_base + SOC_RESTART, reg, 0, 1); if (rc) { pr_err("failed to unset fg restart: %d\n", rc); goto fail; } if (fg_debug_mask & FG_STATUS) pr_info("done!\n"); return 0; unlock_and_fail: mutex_unlock(&chip->rw_lock); goto fail; sub_and_fail: fg_release_access_if_necessary(chip); goto fail; fail: return -EINVAL; } #define V_PREDICTED_ADDR 0x540 #define V_CURRENT_PREDICTED_OFFSET 0 #define PROFILE_LOAD_TIMEOUT_MS 5000 #define FG_PROFILE_LEN 128 #define PROFILE_COMPARE_LEN 32 static int fg_batt_profile_init(struct fg_chip *chip) { int rc = 0, ret; int len, tries; 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; bool tried_again = false, vbat_in_range; bool tried_again = false, vbat_in_range, profiles_same; u8 reg = 0; wait: Loading Loading @@ -3654,6 +3836,12 @@ wait: goto no_profile; } if (len != FG_PROFILE_LEN) { pr_err("battery profile incorrect size: %d\n", len); rc = -EINVAL; goto fail; } rc = of_property_read_string(profile_node, "qcom,battery-type", &batt_type_str); if (rc) { Loading Loading @@ -3688,11 +3876,13 @@ wait: vbat_in_range = abs(fg_data[FG_DATA_VOLTAGE].value - fg_data[FG_DATA_CPRED_VOLTAGE].value) < settings[FG_MEM_VBAT_EST_DIFF].value * 1000; profiles_same = memcmp(chip->batt_profile, data, PROFILE_COMPARE_LEN) == 0; if (reg & PROFILE_INTEGRITY_BIT) fg_cap_learning_load_data(chip); if ((reg & PROFILE_INTEGRITY_BIT) && vbat_in_range && !fg_is_batt_empty(chip) && memcmp(chip->batt_profile, data, len - 4) == 0) { && profiles_same) { if (fg_debug_mask & FG_STATUS) pr_info("Battery profiles same, using default\n"); if (fg_est_dump) Loading @@ -3707,6 +3897,8 @@ wait: fg_data[FG_DATA_VOLTAGE].value); if ((fg_debug_mask & FG_STATUS) && fg_is_batt_empty(chip)) pr_info("battery empty\n"); if ((fg_debug_mask & FG_STATUS) && !profiles_same) pr_info("profiles differ\n"); if (fg_debug_mask & FG_STATUS) { pr_info("Using new profile\n"); print_hex_dump(KERN_INFO, "FG: loaded profile: ", Loading @@ -3727,131 +3919,12 @@ wait: DUMP_PREFIX_NONE, 16, 1, chip->batt_profile, chip->batt_profile_len, false); /* * release the sram access and configure the correct settings * before re-requesting access. */ mutex_lock(&chip->rw_lock); fg_release_access(chip); rc = fg_masked_write(chip, chip->soc_base + SOC_BOOT_MOD, NO_OTP_PROF_RELOAD, 0, 1); rc = fg_do_restart(chip, true); if (rc) { pr_err("failed to set no otp reload bit\n"); goto unlock_and_fail; } /* unset the restart bits so the fg doesn't continuously restart */ reg = REDO_FIRST_ESTIMATE | RESTART_GO; rc = fg_masked_write(chip, chip->soc_base + SOC_RESTART, reg, 0, 1); if (rc) { pr_err("failed to unset fg restart: %d\n", rc); goto unlock_and_fail; } rc = fg_masked_write(chip, MEM_INTF_CFG(chip), LOW_LATENCY, LOW_LATENCY, 1); if (rc) { pr_err("failed to set low latency access bit\n"); goto unlock_and_fail; } mutex_unlock(&chip->rw_lock); /* read once to get a fg cycle in */ rc = fg_mem_read(chip, ®, PROFILE_INTEGRITY_REG, 1, 0, 0); if (rc) { pr_err("failed to read profile integrity rc=%d\n", rc); pr_err("restart failed: %d\n", rc); goto fail; } /* * If this is not the first time a profile has been loaded, sleep for * 3 seconds to make sure the NO_OTP_RELOAD is cleared in memory */ if (chip->first_profile_loaded) msleep(3000); mutex_lock(&chip->rw_lock); fg_release_access(chip); rc = fg_masked_write(chip, MEM_INTF_CFG(chip), LOW_LATENCY, 0, 1); if (rc) { pr_err("failed to set low latency access bit\n"); goto unlock_and_fail; } atomic_add_return(1, &chip->memif_user_cnt); mutex_unlock(&chip->rw_lock); /* write the battery profile */ rc = fg_mem_write(chip, chip->batt_profile, BATT_PROFILE_OFFSET, chip->batt_profile_len, 0, 1); if (rc) { pr_err("failed to write profile rc=%d\n", rc); goto sub_and_fail; } /* write the integrity bits and release access */ rc = fg_mem_masked_write(chip, PROFILE_INTEGRITY_REG, PROFILE_INTEGRITY_BIT, PROFILE_INTEGRITY_BIT, 0); if (rc) { pr_err("failed to write profile rc=%d\n", rc); goto sub_and_fail; } /* decrement the user count so that memory access can be released */ fg_release_access_if_necessary(chip); /* * set the restart bits so that the next fg cycle will reload * the profile */ rc = fg_masked_write(chip, chip->soc_base + SOC_BOOT_MOD, NO_OTP_PROF_RELOAD, NO_OTP_PROF_RELOAD, 1); if (rc) { pr_err("failed to set no otp reload bit\n"); goto fail; } reg = REDO_FIRST_ESTIMATE | RESTART_GO; rc = fg_masked_write(chip, chip->soc_base + SOC_RESTART, reg, reg, 1); if (rc) { pr_err("failed to set fg restart: %d\n", rc); goto fail; } /* wait for the first estimate to complete */ for (tries = 0; tries < MAX_TRIES_FIRST_EST; tries++) { msleep(FIRST_EST_WAIT_MS); 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; else if (fg_debug_mask & FG_STATUS) pr_info("waiting for est, tries = %d\n", tries); } if ((reg & FIRST_EST_DONE_BIT) == 0) pr_err("Battery profile reloading failed, no first estimate\n"); rc = fg_masked_write(chip, chip->soc_base + SOC_BOOT_MOD, NO_OTP_PROF_RELOAD, 0, 1); if (rc) { pr_err("failed to set no otp reload bit\n"); goto fail; } /* unset the restart bits so the fg doesn't continuously restart */ reg = REDO_FIRST_ESTIMATE | RESTART_GO; rc = fg_masked_write(chip, chip->soc_base + SOC_RESTART, reg, 0, 1); if (rc) { pr_err("failed to unset fg restart: %d\n", rc); goto fail; } done: if (fg_batt_type) chip->batt_type = fg_batt_type; Loading @@ -3873,12 +3946,6 @@ done: power_supply_changed(&chip->bms_psy); fg_relax(&chip->profile_wakeup_source); return rc; unlock_and_fail: mutex_unlock(&chip->rw_lock); goto fail; sub_and_fail: fg_release_access_if_necessary(chip); goto fail; fail: chip->batt_type = old_batt_type; if (chip->power_supply_registered) Loading Loading @@ -3914,6 +3981,21 @@ static void batt_profile_init(struct work_struct *work) pr_err("failed to initialize profile\n"); } static void sysfs_restart_work(struct work_struct *work) { struct fg_chip *chip = container_of(work, struct fg_chip, sysfs_restart_work); int rc; rc = fg_do_restart(chip, false); if (rc) pr_err("fg restart failed: %d\n", rc); mutex_lock(&chip->sysfs_restart_lock); fg_restart = 0; mutex_unlock(&chip->sysfs_restart_lock); } static void update_bcl_thresholds(struct fg_chip *chip) { u8 data[4]; Loading Loading @@ -4327,9 +4409,13 @@ static int fg_remove(struct spmi_device *spmi) cancel_work_sync(&chip->status_change_work); cancel_work_sync(&chip->cycle_count_work); cancel_work_sync(&chip->update_esr_work); cancel_work_sync(&chip->sysfs_restart_work); power_supply_unregister(&chip->bms_psy); mutex_destroy(&chip->rslow_comp.lock); mutex_destroy(&chip->rw_lock); mutex_destroy(&chip->cyc_ctr_lock); mutex_destroy(&chip->learning_data.learning_lock); mutex_destroy(&chip->sysfs_restart_lock); wakeup_source_trash(&chip->resume_soc_wakeup_source.source); wakeup_source_trash(&chip->empty_check_wakeup_source.source); wakeup_source_trash(&chip->memif_wakeup_source.source); Loading Loading @@ -4805,27 +4891,16 @@ static int bcl_trim_workaround(struct fg_chip *chip) #define FG_ADC_CONFIG_REG 0x4B8 #define FG_BCL_CONFIG_OFFSET 0x3 #define BCL_FORCED_HPM_IN_CHARGE BIT(2) static int fg_hw_init(struct fg_chip *chip) static int fg_common_hw_init(struct fg_chip *chip) { int rc; u8 resume_soc; u8 data[4]; u64 esr_value; int rc = 0; update_iterm(chip); update_cutoff_voltage(chip); update_irq_volt_empty(chip); update_bcl_thresholds(chip); rc = fg_mem_masked_write(chip, EXTERNAL_SENSE_SELECT, PATCH_NEG_CURRENT_BIT, PATCH_NEG_CURRENT_BIT, EXTERNAL_SENSE_OFFSET); if (rc) { pr_err("failed to write patch current bit rc=%d\n", rc); return rc; } resume_soc = settings[FG_MEM_RESUME_SOC].value; if (resume_soc > 0) { resume_soc = resume_soc * 255 / 100; Loading Loading @@ -4879,6 +4954,30 @@ static int fg_hw_init(struct fg_chip *chip) return rc; } if (chip->use_thermal_coefficients) { fg_mem_write(chip, chip->thermal_coefficients, THERMAL_COEFF_ADDR, THERMAL_COEFF_N_BYTES, THERMAL_COEFF_OFFSET, 0); } return 0; } static int fg_8994_hw_init(struct fg_chip *chip) { int rc = 0; u8 data[4]; u64 esr_value; rc = fg_mem_masked_write(chip, EXTERNAL_SENSE_SELECT, PATCH_NEG_CURRENT_BIT, PATCH_NEG_CURRENT_BIT, EXTERNAL_SENSE_OFFSET); if (rc) { pr_err("failed to write patch current bit rc=%d\n", rc); return rc; } rc = bcl_trim_workaround(chip); if (rc) { pr_err("failed to redo bcl trim rc=%d\n", rc); Loading @@ -4894,12 +4993,6 @@ static int fg_hw_init(struct fg_chip *chip) return rc; } if (chip->use_thermal_coefficients) { fg_mem_write(chip, chip->thermal_coefficients, THERMAL_COEFF_ADDR, THERMAL_COEFF_N_BYTES, THERMAL_COEFF_OFFSET, 0); } fg_mem_masked_write(chip, FG_ALG_SYSCTL_1, I_TERM_QUAL_BIT, 0, 0); data[0] = 0xA2; Loading Loading @@ -4935,6 +5028,45 @@ static int fg_hw_init(struct fg_chip *chip) return 0; } static int fg_8950_hw_init(struct fg_chip *chip) { int rc; rc = fg_mem_masked_write(chip, FG_ADC_CONFIG_REG, BCL_FORCED_HPM_IN_CHARGE, BCL_FORCED_HPM_IN_CHARGE, FG_BCL_CONFIG_OFFSET); if (rc) pr_err("failed to force hpm in charge rc=%d\n", rc); return rc; } static int fg_hw_init(struct fg_chip *chip) { int rc = 0; rc = fg_common_hw_init(chip); if (rc) { pr_err("Unable to initialize FG HW rc=%d\n", rc); return rc; } /* add PMIC specific hw init */ switch (chip->pmic_subtype) { case PMI8994: rc = fg_8994_hw_init(chip); break; case PMI8950: rc = fg_8950_hw_init(chip); break; } if (rc) pr_err("Unable to initialize PMIC specific FG HW rc=%d\n", rc); return rc; } #define DIG_MINOR 0x0 #define DIG_MAJOR 0x1 #define ANA_MINOR 0x2 Loading Loading @@ -4983,6 +5115,44 @@ static int fg_setup_memif_offset(struct fg_chip *chip) return 0; } static int fg_detect_pmic_type(struct fg_chip *chip) { struct pmic_revid_data *pmic_rev_id; struct device_node *revid_dev_node; revid_dev_node = of_parse_phandle(chip->spmi->dev.of_node, "qcom,pmic-revid", 0); if (!revid_dev_node) { pr_err("Missing qcom,pmic-revid property - driver failed\n"); return -EINVAL; } pmic_rev_id = get_revid_data(revid_dev_node); if (IS_ERR(pmic_rev_id)) { pr_err("Unable to get pmic_revid rc=%ld\n", PTR_ERR(pmic_rev_id)); /* * the revid peripheral must be registered, any failure * here only indicates that the rev-id module has not * probed yet. */ return -EPROBE_DEFER; } switch (pmic_rev_id->pmic_subtype) { case PMI8994: case PMI8950: chip->pmic_subtype = pmic_rev_id->pmic_subtype; break; default: pr_err("PMIC subtype %d not supported\n", pmic_rev_id->pmic_subtype); return -EINVAL; } return 0; } #define INIT_JEITA_DELAY_MS 1000 static int fg_probe(struct spmi_device *spmi) { Loading Loading @@ -5028,6 +5198,7 @@ static int fg_probe(struct spmi_device *spmi) mutex_init(&chip->cyc_ctr_lock); mutex_init(&chip->learning_data.learning_lock); mutex_init(&chip->rslow_comp.lock); mutex_init(&chip->sysfs_restart_lock); INIT_DELAYED_WORK(&chip->update_jeita_setting, update_jeita_setting); INIT_DELAYED_WORK(&chip->update_sram_data, update_sram_data_work); INIT_DELAYED_WORK(&chip->update_temp_work, update_temp_data); Loading @@ -5041,10 +5212,12 @@ static int fg_probe(struct spmi_device *spmi) INIT_WORK(&chip->battery_age_work, battery_age_work); INIT_WORK(&chip->update_esr_work, update_esr_value); INIT_WORK(&chip->set_resume_soc_work, set_resume_soc_work); INIT_WORK(&chip->sysfs_restart_work, sysfs_restart_work); alarm_init(&chip->fg_cap_learning_alarm, ALARM_BOOTTIME, fg_cap_learning_alarm_cb); init_completion(&chip->sram_access_granted); init_completion(&chip->sram_access_revoked); complete_all(&chip->sram_access_revoked); init_completion(&chip->batt_id_avail); dev_set_drvdata(&spmi->dev, chip); Loading Loading @@ -5101,6 +5274,12 @@ static int fg_probe(struct spmi_device *spmi) } } rc = fg_detect_pmic_type(chip); if (rc) { pr_err("Unable to detect PMIC type rc=%d\n", rc); return rc; } rc = fg_setup_memif_offset(chip); if (rc) { pr_err("Unable to setup mem_if offsets rc=%d\n", rc); Loading Loading @@ -5184,9 +5363,10 @@ static int fg_probe(struct spmi_device *spmi) if (!chip->use_otp_profile) schedule_work(&chip->batt_profile_init); pr_info("FG Probe success - FG Revision DIG:%d.%d ANA:%d.%d\n", pr_info("FG Probe success - FG Revision DIG:%d.%d ANA:%d.%d PMIC subtype=%d\n", chip->revision[DIG_MAJOR], chip->revision[DIG_MINOR], chip->revision[ANA_MAJOR], chip->revision[ANA_MINOR]); chip->revision[ANA_MAJOR], chip->revision[ANA_MINOR], chip->pmic_subtype); return rc; Loading @@ -5206,11 +5386,13 @@ cancel_work: cancel_work_sync(&chip->cycle_count_work); cancel_work_sync(&chip->update_esr_work); cancel_work_sync(&chip->rslow_comp_work); cancel_work_sync(&chip->sysfs_restart_work); of_init_fail: mutex_destroy(&chip->rslow_comp.lock); mutex_destroy(&chip->rw_lock); mutex_destroy(&chip->cyc_ctr_lock); mutex_destroy(&chip->learning_data.learning_lock); mutex_destroy(&chip->sysfs_restart_lock); wakeup_source_trash(&chip->resume_soc_wakeup_source.source); wakeup_source_trash(&chip->empty_check_wakeup_source.source); wakeup_source_trash(&chip->memif_wakeup_source.source); Loading Loading @@ -5238,7 +5420,7 @@ static void check_and_update_sram_data(struct fg_chip *chip) &chip->update_temp_work, msecs_to_jiffies(time_left * 1000)); next_update_time = chip->last_sram_update_time + (SRAM_PERIOD_UPDATE_MS / 1000); + (fg_sram_update_period_ms / 1000); if (next_update_time > current_time) time_left = next_update_time - current_time; Loading Loading @@ -5318,6 +5500,40 @@ static struct kernel_param_ops fg_sense_type_ops = { module_param_cb(sense_type, &fg_sense_type_ops, &fg_sense_type, 0644); static int fg_restart_set(const char *val, const struct kernel_param *kp) { struct power_supply *bms_psy; struct fg_chip *chip; bms_psy = power_supply_get_by_name("bms"); if (!bms_psy) { pr_err("bms psy not found\n"); return 0; } chip = container_of(bms_psy, struct fg_chip, bms_psy); mutex_lock(&chip->sysfs_restart_lock); if (fg_restart != 0) { mutex_unlock(&chip->sysfs_restart_lock); return 0; } fg_restart = 1; mutex_unlock(&chip->sysfs_restart_lock); if (fg_debug_mask & FG_STATUS) pr_info("fuel gauge restart initiated from sysfs...\n"); schedule_work(&chip->sysfs_restart_work); return 0; } static struct kernel_param_ops fg_restart_ops = { .set = fg_restart_set, .get = param_get_int, }; module_param_cb(restart, &fg_restart_ops, &fg_restart, 0644); static struct spmi_driver fg_driver = { .driver = { .name = QPNP_FG_DEV_NAME, Loading