power: pm8921-bms: remember soc between restarts
Currently the code does not have a mechanism to remember the soc
reported just before shutting down and upon restarting the new
soc reported is off from the previous soc value reported.
This change introduces
- a method to save soc in an unused coincell back register: ssbi address
0x107 is not used on 8921 and serves the purpose of storing the soc.
The driver reads this value and uses it to scale the reported soc.
- a method to detect that a battery was removed and perhaps replaced by a
different one. If the battery is found replaced the driver is notified
of the change and it disregards the soc value it read from the backup
register. The charger driver has a battery backed bit (force vref
therm) which it sets in its initialization sequence. Once set the
value remains between restarts, unless the battery is removed. The
default value of this bit is 0. Hence if a zero is detected before
writing to it, battery was removed between restarts - this mechanism
is used to notify the BMS to disregard the soc read from the backup
register.
Note that for this to work correctly the bootloader needs to be updated to
not overwrite register 0x107 upon restart.
CRs-Fixed: 370287
Change-Id: If7d098552d36eb27a396ee7d37f78d3629861f6e
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index a1561f0..a2eb39e 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -3296,13 +3296,29 @@
}
}
+#define VREF_BATT_THERM_FORCE_ON BIT(7)
+static void detect_battery_removal(struct pm8921_chg_chip *chip)
+{
+ u8 temp;
+
+ pm8xxx_readb(chip->dev->parent, CHG_CNTRL, &temp);
+ pr_debug("upon restart CHG_CNTRL = 0x%x\n", temp);
+
+ if (!(temp & VREF_BATT_THERM_FORCE_ON))
+ /*
+ * batt therm force on bit is battery backed and is default 0
+ * The charger sets this bit at init time. If this bit is found
+ * 0 that means the battery was removed. Tell the bms about it
+ */
+ pm8921_bms_invalidate_shutdown_soc();
+}
+
#define ENUM_TIMER_STOP_BIT BIT(1)
#define BOOT_DONE_BIT BIT(6)
#define CHG_BATFET_ON_BIT BIT(3)
#define CHG_VCP_EN BIT(0)
#define CHG_BAT_TEMP_DIS_BIT BIT(2)
#define SAFE_CURRENT_MA 1500
-#define VREF_BATT_THERM_FORCE_ON BIT(7)
static int __devinit pm8921_chg_hw_init(struct pm8921_chg_chip *chip)
{
int rc;
@@ -3311,6 +3327,8 @@
/* forcing 19p2mhz before accessing any charger registers */
pm8921_chg_force_19p2mhz_clk(chip);
+ detect_battery_removal(chip);
+
rc = pm_chg_masked_write(chip, SYS_CONFIG_2,
BOOT_DONE_BIT, BOOT_DONE_BIT);
if (rc) {