power: pm8921-bms: adjust rbatt and ocv both for shutdown soc
When ocv (open circuit voltage of the battery) is adjusted to match a
specific soc, rbatt (the battery resistance) changes too. This is because
rbatt is dependent on the remaining charge which changes as the ocv
changes.
The issue we observed with this changing rbatt was the unusable charge
changes which causes the soc to move away from the soc the algorithm
attempts to match.
To get around this issue adjust both the rbatt and ocv when we want to
match a soc for a specific soc.
Change-Id: Ifa8efe1e37b9982d6d67730f911e47e369e9b4ff
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index ad5ee04..d4852f6 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -1526,16 +1526,22 @@
}
EXPORT_SYMBOL(pm8921_bms_invalidate_shutdown_soc);
-static int adjust_remaining_charge_for_shutdown_soc(
+static void adjust_rc_and_uuc_for_shutdown_soc(
struct pm8921_bms_chip *chip,
int batt_temp,
int chargecycles,
int fcc_uah,
int uuc_uah,
int cc_uah,
- int remaining_charge_uah)
+ int remaining_charge_uah,
+ int rbatt,
+ int *ret_rc,
+ int *ret_uuc,
+ int *ret_rbatt)
{
- s64 rc;
+ s64 new_rc;
+ int new_uuc;
+ int new_rbatt;
int pc;
int ocv, ocv_uv;
int batt_temp_degc = batt_temp / 10;
@@ -1548,18 +1554,13 @@
* value of zero means the shutdown soc should not be used, the battery
* was removed for extended period, the coincell capacitor could have
* drained
- */
- if (shutdown_soc == 0) {
- rc = remaining_charge_uah;
- goto out;
- }
-
- /*
* shutdown_soc_invalid means the shutdown soc should not be used,
* the battery was removed for a small period
*/
- if (shutdown_soc_invalid) {
- rc = remaining_charge_uah;
+ if (shutdown_soc == 0 || shutdown_soc_invalid) {
+ new_rc = remaining_charge_uah;
+ new_uuc = uuc_uah;
+ new_rbatt = rbatt;
goto out;
}
@@ -1569,15 +1570,47 @@
pr_debug("shutdown_soc = %d forcing it now\n", shutdown_soc);
- rc = (s64)shutdown_soc * (fcc_uah - uuc_uah);
- rc = div_s64(rc, 100) + cc_uah + uuc_uah;
- pc = DIV_ROUND_CLOSEST((int)rc * 100, fcc_uah);
+ /* step 1 get to a reasonable rbatt */
+ if (chip->last_ocv_uv < chip->v_cutoff * 1000) {
+ int new_pc_for_rbatt;
+ int iavg_ua;
+ int iavg_ma;
+ int soc_for_rbatt;
+
+ new_pc_for_rbatt = calculate_pc(chip, chip->v_cutoff * 1000,
+ batt_temp, chargecycles);
+
+ soc_for_rbatt
+ = (new_pc_for_rbatt * fcc_uah - cc_uah * 100) / fcc_uah;
+ new_rbatt = get_rbatt(chip, soc_for_rbatt, batt_temp);
+
+ pm8921_bms_get_battery_current(&iavg_ua);
+ iavg_ma = iavg_ua / 1000;
+ if (iavg_ma < 0)
+ iavg_ma = CHARGING_IAVG_MA;
+
+ new_uuc = calculate_uuc_uah_at_given_current(chip,
+ batt_temp, chargecycles,
+ new_rbatt, fcc_uah, iavg_ma);
+
+ pr_debug("new pc = %d, soc_rbatt = %d, new_rbatt = %d,\n",
+ new_pc_for_rbatt, soc_for_rbatt, new_rbatt);
+ pr_debug("iavg_ma = %d, new_uuc = %d\n", iavg_ma, new_uuc);
+ } else {
+ new_rbatt = rbatt;
+ new_uuc = uuc_uah;
+ }
+
+ /* step 2 adjust rc using the new uuc */
+ new_rc = (s64)shutdown_soc * (fcc_uah - new_uuc);
+ new_rc = div_s64(new_rc, 100) + cc_uah + new_uuc;
+ pc = DIV_ROUND_CLOSEST((int)new_rc * 100, fcc_uah);
pc = clamp(pc, 0, 100);
ocv = interpolate_ocv(chip, batt_temp_degc, pc);
- pr_debug("To force shutdown_soc = %d, rc = %d, pc = %d, ocv mv = %d\n",
- shutdown_soc, (int)rc, pc, ocv);
+ pr_debug("To force shutdown_soc = %d, new_rc = %d, pc = %d, ocv mv = %d\n",
+ shutdown_soc, (int)new_rc, pc, ocv);
new_pc = interpolate_pc(chip, batt_temp_degc, ocv);
pr_debug("test revlookup pc = %d for ocv = %d\n", new_pc, ocv);
@@ -1597,8 +1630,10 @@
chip->pon_ocv_uv = chip->last_ocv_uv;
chip->last_ocv_uv = ocv_uv;
out:
+ *ret_rbatt = new_rbatt;
+ *ret_rc = (int)new_rc;
+ *ret_uuc = new_uuc;
mutex_unlock(&soc_invalidation_mutex);
- return (int)rc;
}
#define SOC_CATCHUP_SEC_MAX 600
@@ -1676,6 +1711,9 @@
int rbatt;
int iavg_ua;
int delta_time_us;
+ int new_rc_uah;
+ int new_ucc_uah;
+ int new_rbatt;
calculate_soc_params(chip, raw, batt_temp, chargecycles,
&fcc_uah,
@@ -1686,16 +1724,24 @@
&iavg_ua,
&delta_time_us);
- if (delta_time_us == 0)
+ if (delta_time_us == 0) {
/*
* soc for the first time - use shutdown soc
* to adjust pon ocv
*/
- remaining_charge_uah = adjust_remaining_charge_for_shutdown_soc(
+ adjust_rc_and_uuc_for_shutdown_soc(
chip,
batt_temp, chargecycles,
fcc_uah, unusable_charge_uah,
- cc_uah, remaining_charge_uah);
+ cc_uah, remaining_charge_uah,
+ rbatt,
+ &new_rc_uah, &new_ucc_uah,
+ &new_rbatt);
+
+ remaining_charge_uah = new_rc_uah;
+ unusable_charge_uah = new_ucc_uah;
+ rbatt = new_rbatt;
+ }
/* calculate remaining usable charge */
remaining_usable_charge_uah = remaining_charge_uah