summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSubbaraman Narayanamurthy <subbaram@codeaurora.org>2016-09-21 12:36:03 -0700
committerSubbaraman Narayanamurthy <subbaram@codeaurora.org>2016-10-10 09:44:04 -0700
commitbd811f3afde01a284c8892dba5a7acecdf56975f (patch)
tree35459dbd4be292878f40ce1af16172ae0a27d191 /drivers
parent9435c04228a8117f7acba15169820e27dc8ed398 (diff)
qpnp-fg-gen3: Add support to configure force battery profile loading
Currently, FG_GEN3 driver loads the battery profile if it finds out the profile loaded earlier doesn't match with the available profile. This will be done when the profile integrity bit is set already. Make this force profile loading as a configurable parameter through a device tree property. While at it, add a module parameter to dump the profile contents conditionally. This will be helpful in debugging. Change-Id: Ibaff55aa5434ee283e6d597485d193e9e52bb74e Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/power/qcom-charger/fg-core.h1
-rw-r--r--drivers/power/qcom-charger/qpnp-fg-gen3.c77
2 files changed, 65 insertions, 13 deletions
diff --git a/drivers/power/qcom-charger/fg-core.h b/drivers/power/qcom-charger/fg-core.h
index 24ab83565fc9..e4715fd6fb39 100644
--- a/drivers/power/qcom-charger/fg-core.h
+++ b/drivers/power/qcom-charger/fg-core.h
@@ -181,6 +181,7 @@ struct fg_dt_props {
int esr_timer_charging;
int esr_timer_awake;
int esr_timer_asleep;
+ bool force_load_profile;
};
/* parameters from battery profile */
diff --git a/drivers/power/qcom-charger/qpnp-fg-gen3.c b/drivers/power/qcom-charger/qpnp-fg-gen3.c
index ac24ad9486d9..76c26ca7c800 100644
--- a/drivers/power/qcom-charger/qpnp-fg-gen3.c
+++ b/drivers/power/qcom-charger/qpnp-fg-gen3.c
@@ -274,6 +274,12 @@ module_param_named(
sram_update_period_ms, fg_sram_update_period_ms, int, S_IRUSR | S_IWUSR
);
+static bool fg_sram_dump;
+module_param_named(
+ sram_dump, fg_sram_dump, bool, S_IRUSR | S_IWUSR
+);
+
+
/* All getters HERE */
static int fg_decode_value_16b(struct fg_sram_param *sp,
@@ -929,40 +935,82 @@ static int fg_get_cycle_count(struct fg_chip *chip)
return count;
}
-#define SOC_READY_WAIT_MS 2000
-static void profile_load_work(struct work_struct *work)
+static void dump_sram(u8 *buf, int len)
+{
+ int i;
+ char str[16];
+
+ for (i = 0; i < len; i += 4) {
+ str[0] = '\0';
+ fill_string(str, sizeof(str), buf + i, 4);
+ pr_info("%03d %s\n", PROFILE_LOAD_WORD + (i / 4), str);
+ }
+}
+
+static bool is_profile_load_required(struct fg_chip *chip)
{
- struct fg_chip *chip = container_of(work,
- struct fg_chip,
- profile_load_work.work);
- int rc;
u8 buf[PROFILE_COMP_LEN], val;
- bool tried_again = false, profiles_same = false;
+ bool profiles_same = false;
+ int rc;
rc = fg_sram_read(chip, PROFILE_INTEGRITY_WORD,
PROFILE_INTEGRITY_OFFSET, &val, 1, FG_IMA_DEFAULT);
if (rc < 0) {
pr_err("failed to read profile integrity rc=%d\n", rc);
- return;
+ return false;
}
- vote(chip->awake_votable, PROFILE_LOAD, true, 0);
+ /* Check if integrity bit is set */
if (val == 0x01) {
fg_dbg(chip, FG_STATUS, "Battery profile integrity bit is set\n");
rc = fg_sram_read(chip, PROFILE_LOAD_WORD, PROFILE_LOAD_OFFSET,
buf, PROFILE_COMP_LEN, FG_IMA_DEFAULT);
if (rc < 0) {
pr_err("Error in reading battery profile, rc:%d\n", rc);
- goto out;
+ return false;
}
profiles_same = memcmp(chip->batt_profile, buf,
PROFILE_COMP_LEN) == 0;
if (profiles_same) {
- fg_dbg(chip, FG_STATUS, "Battery profile is same\n");
- goto done;
+ fg_dbg(chip, FG_STATUS, "Battery profile is same, not loading it\n");
+ return false;
+ }
+
+ if (!chip->dt.force_load_profile) {
+ pr_warn("Profiles doesn't match, skipping loading it since force_load_profile is disabled\n");
+ if (fg_sram_dump) {
+ pr_info("FG: loaded profile:\n");
+ dump_sram(buf, PROFILE_COMP_LEN);
+ pr_info("FG: available profile:\n");
+ dump_sram(chip->batt_profile, PROFILE_LEN);
+ }
+ return false;
+ }
+
+ fg_dbg(chip, FG_STATUS, "Profiles are different, loading the correct one\n");
+ } else {
+ fg_dbg(chip, FG_STATUS, "Profile integrity bit is not set\n");
+ if (fg_sram_dump) {
+ pr_info("FG: profile to be loaded:\n");
+ dump_sram(chip->batt_profile, PROFILE_LEN);
}
- fg_dbg(chip, FG_STATUS, "profiles are different?\n");
}
+ return true;
+}
+
+#define SOC_READY_WAIT_MS 2000
+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;
+
+ vote(chip->awake_votable, PROFILE_LOAD, true, 0);
+ if (!is_profile_load_required(chip))
+ goto done;
clear_cycle_counter(chip);
fg_dbg(chip, FG_STATUS, "profile loading started\n");
@@ -1783,6 +1831,9 @@ static int fg_parse_dt(struct fg_chip *chip)
if (chip->cyc_ctr.en)
chip->cyc_ctr.id = 1;
+ chip->dt.force_load_profile = of_property_read_bool(node,
+ "qcom,fg-force-load-profile");
+
return 0;
}