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>
This commit is contained in:
parent
9435c04228
commit
bd811f3afd
3 changed files with 72 additions and 13 deletions
|
@ -146,6 +146,13 @@ First Level Node - FG Gen3 device
|
|||
Value type: <bool>
|
||||
Definition: Enables the cycle counter feature.
|
||||
|
||||
- qcom,fg-force-load-profile
|
||||
Usage: optional
|
||||
Value type: <bool>
|
||||
Definition: If set, battery profile will be force loaded if the profile
|
||||
loaded earlier by bootloader doesn't match with the profile
|
||||
available in the device tree.
|
||||
|
||||
==========================================================
|
||||
Second Level Nodes - Peripherals managed by FG Gen3 driver
|
||||
==========================================================
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue