summaryrefslogtreecommitdiff
path: root/drivers/power
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-10-10 18:28:21 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-10-10 18:28:21 -0700
commitdb5b016bf7e964d6f42819844e72863bf5488378 (patch)
treea4116f75053a5ae8dc70fc9b6f88b3ff26d9f8c0 /drivers/power
parentd610af945362876ee99e73c41585c72a7a321c0b (diff)
parent0edd25653c344358c440dc8a4f97134adfe65e88 (diff)
Merge "qpnp-fg-gen3: add support to restart fuel gauge"
Diffstat (limited to 'drivers/power')
-rw-r--r--drivers/power/qcom-charger/fg-core.h2
-rw-r--r--drivers/power/qcom-charger/qpnp-fg-gen3.c119
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);