diff options
| author | Subbaraman Narayanamurthy <subbaram@codeaurora.org> | 2016-09-22 19:36:39 -0700 |
|---|---|---|
| committer | Subbaraman Narayanamurthy <subbaram@codeaurora.org> | 2016-10-10 09:44:05 -0700 |
| commit | 0edd25653c344358c440dc8a4f97134adfe65e88 (patch) | |
| tree | 04d20dd0c1838f911551f124a9db9404f8ee5d34 | |
| parent | bd811f3afde01a284c8892dba5a7acecdf56975f (diff) | |
qpnp-fg-gen3: add support to restart fuel gauge
Add a module parameter "fg_restart" to restart the fuel gauge
without loading the battery profile. This will be useful in
geting a fresh SOC estimate whenever required.
Change-Id: I0c054ad523a0eab72f777d010807bb3a55f63f7e
Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
| -rw-r--r-- | drivers/power/qcom-charger/fg-core.h | 2 | ||||
| -rw-r--r-- | drivers/power/qcom-charger/qpnp-fg-gen3.c | 119 |
2 files changed, 97 insertions, 24 deletions
diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h index e4715fd6fb39..091b8f49ee09 100644 --- a/drivers/power/qcom-charger/fg-core.h +++ b/drivers/power/qcom-charger/fg-core.h @@ -237,9 +237,11 @@ struct fg_chip { int nom_cap_uah; int status; int prev_status; + int last_soc; bool profile_available; bool profile_loaded; bool battery_missing; + bool fg_restarting; struct completion soc_update; struct completion soc_ready; struct delayed_work profile_load_work; diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c index 76c26ca7c800..eda0efa312e2 100644 --- a/drivers/power/qcom-charger/qpnp-fg-gen3.c +++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c @@ -279,6 +279,7 @@ module_param_named( sram_dump, fg_sram_dump, bool, S_IRUSR | S_IWUSR ); +static int fg_restart; /* All getters HERE */ @@ -999,12 +1000,57 @@ static bool is_profile_load_required(struct fg_chip *chip) } #define SOC_READY_WAIT_MS 2000 +static int __fg_restart(struct fg_chip *chip) +{ + int rc, msoc; + bool tried_again = false; + + rc = fg_get_prop_capacity(chip, &msoc); + if (rc < 0) { + pr_err("Error in getting capacity, rc=%d\n", rc); + return rc; + } + + chip->last_soc = msoc; + chip->fg_restarting = true; + reinit_completion(&chip->soc_ready); + rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, + RESTART_GO_BIT); + if (rc < 0) { + pr_err("Error in writing to %04x, rc=%d\n", + BATT_SOC_RESTART(chip), rc); + goto out; + } + +wait: + rc = wait_for_completion_interruptible_timeout(&chip->soc_ready, + msecs_to_jiffies(SOC_READY_WAIT_MS)); + + /* If we were interrupted wait again one more time. */ + if (rc == -ERESTARTSYS && !tried_again) { + tried_again = true; + goto wait; + } else if (rc <= 0) { + pr_err("wait for soc_ready timed out rc=%d\n", rc); + goto out; + } + + rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, 0); + if (rc < 0) { + pr_err("Error in writing to %04x, rc=%d\n", + BATT_SOC_RESTART(chip), rc); + goto out; + } +out: + chip->fg_restarting = false; + return rc; +} + static void profile_load_work(struct work_struct *work) { struct fg_chip *chip = container_of(work, struct fg_chip, profile_load_work.work); - bool tried_again = false; u8 buf[2], val; int rc; @@ -1029,24 +1075,9 @@ static void profile_load_work(struct work_struct *work) goto out; } - rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, - RESTART_GO_BIT); + rc = __fg_restart(chip); if (rc < 0) { - pr_err("Error in writing to %04x, rc=%d\n", - BATT_SOC_RESTART(chip), rc); - goto out; - } - -wait: - rc = wait_for_completion_interruptible_timeout(&chip->soc_ready, - msecs_to_jiffies(SOC_READY_WAIT_MS)); - - /* If we were interrupted wait again one more time. */ - if (rc == -ERESTARTSYS && !tried_again) { - tried_again = true; - goto wait; - } else if (rc <= 0) { - pr_err("wait for soc_ready timed out rc=%d\n", rc); + pr_err("Error in restarting FG, rc=%d\n", rc); goto out; } @@ -1061,7 +1092,6 @@ wait: goto out; } - fg_dbg(chip, FG_STATUS, "profile loaded successfully"); done: rc = fg_sram_read(chip, NOM_CAP_WORD, NOM_CAP_OFFSET, buf, 2, FG_IMA_DEFAULT); @@ -1073,14 +1103,52 @@ done: chip->nom_cap_uah = (int)(buf[0] | buf[1] << 8) * 1000; chip->profile_loaded = true; + fg_dbg(chip, FG_STATUS, "profile loaded successfully"); out: vote(chip->awake_votable, PROFILE_LOAD, false, 0); - rc = fg_masked_write(chip, BATT_SOC_RESTART(chip), RESTART_GO_BIT, 0); - if (rc < 0) - pr_err("Error in writing to %04x, rc=%d\n", - BATT_SOC_RESTART(chip), rc); } +static int fg_restart_sysfs(const char *val, const struct kernel_param *kp) +{ + int rc; + struct power_supply *bms_psy; + struct fg_chip *chip; + + rc = param_set_int(val, kp); + if (rc) { + pr_err("Unable to set fg_restart: %d\n", rc); + return rc; + } + + if (fg_restart != 1) { + pr_err("Bad value %d\n", fg_restart); + return -EINVAL; + } + + bms_psy = power_supply_get_by_name("bms"); + if (!bms_psy) { + pr_err("bms psy not found\n"); + return 0; + } + + chip = power_supply_get_drvdata(bms_psy); + rc = __fg_restart(chip); + if (rc < 0) { + pr_err("Error in restarting FG, rc=%d\n", rc); + return rc; + } + + pr_info("FG restart done\n"); + return rc; +} + +static struct kernel_param_ops fg_restart_ops = { + .set = fg_restart_sysfs, + .get = param_get_int, +}; + +module_param_cb(restart, &fg_restart_ops, &fg_restart, 0644); + /* PSY CALLBACKS STAY HERE */ static int fg_psy_get_property(struct power_supply *psy, @@ -1092,7 +1160,10 @@ static int fg_psy_get_property(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_CAPACITY: - rc = fg_get_prop_capacity(chip, &pval->intval); + if (chip->fg_restarting) + pval->intval = chip->last_soc; + else + rc = fg_get_prop_capacity(chip, &pval->intval); break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: rc = fg_get_battery_voltage(chip, &pval->intval); |
