power: qpnp-bms: restrict soc decrease to one percent

The calculated soc could decrease up to 3% within one
calculation period. This will happen when UUC and CC increase
by 1% percent while the adjusting algorithm reduces the OCV
to cause RC to decrease by 1%.

Update the reporting side of the code to restrict the decrease
of soc by 1%. There will be ample time to catch up to calculated
soc.

Importantly, when the device is resumed after a long time, we don't
want to restrict the soc decrease. So when the device resumes and
the BMS sleeps for longer than the SoC calculation period, unrestrict
the next soc.

Change-Id: I8dda42735df3608b42ab94f42f22a892ee61df20
Signed-off-by: Xiaozhe Shi <xiaozhes@codeaurora.org>
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 3af5b9a..fd42c47 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -175,6 +175,7 @@
 	struct timespec			t_soc_queried;
 	int				last_soc;
 	int				last_soc_est;
+	int				last_soc_unbound;
 
 	int				charge_time_us;
 	int				catch_up_time_us;
@@ -1898,9 +1899,18 @@
 		soc = scale_soc_while_chg(chip, delta_time_us,
 						soc, chip->last_soc);
 
+	if (chip->last_soc_unbound)
+		chip->last_soc_unbound = false;
+	else if (chip->last_soc != -EINVAL) {
+		if (soc < chip->last_soc && soc != 0)
+			soc = chip->last_soc - 1;
+		if (soc > chip->last_soc && soc != 100)
+			soc = chip->last_soc + 1;
+	}
+
 	pr_debug("last_soc = %d, calculated_soc = %d, soc = %d\n",
 			chip->last_soc, chip->calculated_soc, soc);
-	chip->last_soc = soc;
+	chip->last_soc = bound_soc(soc);
 	backup_soc_and_iavg(chip, batt_temp, chip->last_soc);
 	pr_debug("Reported SOC = %d\n", chip->last_soc);
 	chip->t_soc_queried = now;
@@ -2571,6 +2581,11 @@
 	if (rc) {
 		pr_err("Could not read current time: %d\n", rc);
 	} else if (tm_now_sec > chip->last_recalc_time) {
+		/*
+		 * unbind the last soc so that the next
+		 * recalculation is not limited to changing by 1%
+		 */
+		chip->last_soc_unbound = true;
 		time_since_last_recalc = tm_now_sec - chip->last_recalc_time;
 		pr_debug("Time since last recalc: %lu\n",
 				time_since_last_recalc);