diff options
author | Subbaraman Narayanamurthy <subbaram@codeaurora.org> | 2017-03-15 13:15:31 -0700 |
---|---|---|
committer | Subbaraman Narayanamurthy <subbaram@codeaurora.org> | 2017-03-23 16:45:35 -0700 |
commit | b3dd099154f7b98b1761d004c51e0e70ff0cab68 (patch) | |
tree | 7e3b6ea22ce189c7a441d2dabf6e3147bd68e9b6 /drivers | |
parent | e0e09f71900ba7d43aa5ce29a2d616482b0dfe58 (diff) |
qpnp-fg-gen3: prime CC_SOC_SW when capacity learning begins
CC_SOC_SW can accumulate error over time and get saturated high
during capacity learning. Prime it to a value based on battery
SOC when capacity learning begins. This way, it can be ensured
that CC_SOC_SW doesn't saturate in a capacity learning cycle.
Change-Id: I2866ed6dadee84e84bf28fb08dc3a5a0ae353852
Signed-off-by: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/power/supply/qcom/qpnp-fg-gen3.c | 49 |
1 files changed, 28 insertions, 21 deletions
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c index d0e1340456a0..5ce74dab9aab 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen3.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c @@ -525,7 +525,7 @@ static int fg_get_sram_prop(struct fg_chip *chip, enum fg_sram_param_id id, } #define CC_SOC_30BIT GENMASK(29, 0) -static int fg_get_cc_soc(struct fg_chip *chip, int *val) +static int fg_get_charge_raw(struct fg_chip *chip, int *val) { int rc, cc_soc; @@ -539,7 +539,7 @@ static int fg_get_cc_soc(struct fg_chip *chip, int *val) return 0; } -static int fg_get_cc_soc_sw(struct fg_chip *chip, int *val) +static int fg_get_charge_counter(struct fg_chip *chip, int *val) { int rc, cc_soc; @@ -1241,7 +1241,7 @@ static void fg_cap_learning_post_process(struct fg_chip *chip) chip->cl.final_cc_uah, old_cap, chip->cl.learned_cc_uah); } -static int fg_cap_learning_process_full_data(struct fg_chip *chip) +static int fg_cap_learning_process_full_data(struct fg_chip *chip) { int rc, cc_soc_sw, cc_soc_delta_pct; int64_t delta_cc_uah; @@ -1263,30 +1263,39 @@ static int fg_cap_learning_process_full_data(struct fg_chip *chip) return 0; } -static int fg_cap_learning_begin(struct fg_chip *chip, int batt_soc) +#define BATT_SOC_32BIT GENMASK(31, 0) +static int fg_cap_learning_begin(struct fg_chip *chip, u32 batt_soc) { - int rc, cc_soc_sw; + int rc, cc_soc_sw, batt_soc_msb; - if (DIV_ROUND_CLOSEST(batt_soc * 100, FULL_SOC_RAW) > + batt_soc_msb = batt_soc >> 24; + if (DIV_ROUND_CLOSEST(batt_soc_msb * 100, FULL_SOC_RAW) > chip->dt.cl_start_soc) { fg_dbg(chip, FG_CAP_LEARN, "Battery SOC %d is high!, not starting\n", - batt_soc); + batt_soc_msb); return -EINVAL; } - chip->cl.init_cc_uah = div64_s64(chip->cl.learned_cc_uah * batt_soc, + chip->cl.init_cc_uah = div64_s64(chip->cl.learned_cc_uah * batt_soc_msb, FULL_SOC_RAW); - rc = fg_get_sram_prop(chip, FG_SRAM_CC_SOC_SW, &cc_soc_sw); + + /* Prime cc_soc_sw with battery SOC when capacity learning begins */ + cc_soc_sw = div64_s64((int64_t)batt_soc * CC_SOC_30BIT, + BATT_SOC_32BIT); + rc = fg_sram_write(chip, chip->sp[FG_SRAM_CC_SOC_SW].addr_word, + chip->sp[FG_SRAM_CC_SOC_SW].addr_byte, (u8 *)&cc_soc_sw, + chip->sp[FG_SRAM_CC_SOC_SW].len, FG_IMA_ATOMIC); if (rc < 0) { - pr_err("Error in getting CC_SOC_SW, rc=%d\n", rc); - return rc; + pr_err("Error in writing cc_soc_sw, rc=%d\n", rc); + goto out; } chip->cl.init_cc_soc_sw = cc_soc_sw; chip->cl.active = true; fg_dbg(chip, FG_CAP_LEARN, "Capacity learning started @ battery SOC %d init_cc_soc_sw:%d\n", - batt_soc, chip->cl.init_cc_soc_sw); - return 0; + batt_soc_msb, chip->cl.init_cc_soc_sw); +out: + return rc; } static int fg_cap_learning_done(struct fg_chip *chip) @@ -1318,7 +1327,7 @@ out: #define FULL_SOC_RAW 255 static void fg_cap_learning_update(struct fg_chip *chip) { - int rc, batt_soc; + int rc, batt_soc, batt_soc_msb; mutex_lock(&chip->cl.lock); @@ -1337,11 +1346,9 @@ static void fg_cap_learning_update(struct fg_chip *chip) goto out; } - /* We need only the most significant byte here */ - batt_soc = (u32)batt_soc >> 24; - + batt_soc_msb = (u32)batt_soc >> 24; fg_dbg(chip, FG_CAP_LEARN, "Chg_status: %d cl_active: %d batt_soc: %d\n", - chip->charge_status, chip->cl.active, batt_soc); + chip->charge_status, chip->cl.active, batt_soc_msb); /* Initialize the starting point of learning capacity */ if (!chip->cl.active) { @@ -1363,7 +1370,7 @@ static void fg_cap_learning_update(struct fg_chip *chip) if (chip->charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING) { fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n", - batt_soc); + batt_soc_msb); chip->cl.active = false; chip->cl.init_cc_uah = 0; } @@ -2821,7 +2828,7 @@ static int fg_psy_get_property(struct power_supply *psy, pval->intval = chip->cyc_ctr.id; break; case POWER_SUPPLY_PROP_CHARGE_NOW_RAW: - rc = fg_get_cc_soc(chip, &pval->intval); + rc = fg_get_charge_raw(chip, &pval->intval); break; case POWER_SUPPLY_PROP_CHARGE_NOW: pval->intval = chip->cl.init_cc_uah; @@ -2830,7 +2837,7 @@ static int fg_psy_get_property(struct power_supply *psy, pval->intval = chip->cl.learned_cc_uah; break; case POWER_SUPPLY_PROP_CHARGE_COUNTER: - rc = fg_get_cc_soc_sw(chip, &pval->intval); + rc = fg_get_charge_counter(chip, &pval->intval); break; case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: rc = fg_get_time_to_full(chip, &pval->intval); |