power: pm8921-bms: disable ocv updates for flat portion of the curve

An issue is observed when an OCV is updated while the device is
sleeping. When it wakes up the SOC calculations are run on the new OCV
which result in a drastically different SOC than previously reported.
The root cause of this issue is PON OCV likely was unsettled.

Provide a feature where OCV updates can be disabled between certain
SOC range.

Change-Id: I54a75a7e9d05ff2c8ccd484850f02a0190d6a3b7
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 981fde6..de656fc 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -162,6 +162,9 @@
 	int			low_voltage_calc_ms;
 	int			imax_ua;
 	struct wake_lock	soc_wake_lock;
+	int			disable_flat_portion_ocv;
+	int			ocv_dis_high_soc;
+	int			ocv_dis_low_soc;
 };
 
 /*
@@ -748,7 +751,7 @@
 		pr_err("BMS driver has not been initialized yet!\n");
 		return -EINVAL;
 	}
-	pr_debug("stopping ocv updates\n");
+	pr_debug("starting ocv updates\n");
 	return pm_bms_masked_write(the_chip, BMS_TOLERANCES,
 			OCV_TOL_MASK, OCV_TOL_DEFAULT);
 }
@@ -2154,6 +2157,15 @@
 	calculated_soc = new_calculated_soc;
 	firsttime = 0;
 	get_current_time(&chip->last_recalc_time);
+
+	if (chip->disable_flat_portion_ocv) {
+		if (is_between(chip->ocv_dis_high_soc, chip->ocv_dis_low_soc,
+					calculated_soc)) {
+			pm8921_bms_stop_ocv_updates();
+		} else {
+			pm8921_bms_start_ocv_updates();
+		}
+	}
 	return calculated_soc;
 }
 
@@ -3130,6 +3142,10 @@
 	chip->revision = pm8xxx_get_revision(chip->dev->parent);
 	chip->enable_fcc_learning = pdata->enable_fcc_learning;
 
+	chip->disable_flat_portion_ocv = pdata->disable_flat_portion_ocv;
+	chip->ocv_dis_high_soc = pdata->ocv_dis_high_soc;
+	chip->ocv_dis_low_soc = pdata->ocv_dis_low_soc;
+
 	mutex_init(&chip->calib_mutex);
 	INIT_WORK(&chip->calib_hkadc_work, calibrate_hkadc_work);
 
diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h
index 12214d9..d670732 100644
--- a/include/linux/mfd/pm8xxx/pm8921-bms.h
+++ b/include/linux/mfd/pm8xxx/pm8921-bms.h
@@ -41,6 +41,9 @@
  *				voltage higher than cutoff voltage
  * @low_voltage_calc_ms:	The period of soc calculation in ms when battery
  *				voltage is near cutoff voltage
+ * @disable_flat_portion_ocv:	feature to disable ocv updates while in sleep
+ * @ocv_dis_high_soc:		the high soc percent when ocv should be disabled
+ * @ocv_dis_low_soc:		the low soc percent when ocv should be enabled
  */
 struct pm8921_bms_platform_data {
 	struct pm8xxx_bms_core_data	bms_cdata;
@@ -57,6 +60,9 @@
 	int				chg_term_ua;
 	int				normal_voltage_calc_ms;
 	int				low_voltage_calc_ms;
+	int				disable_flat_portion_ocv;
+	int				ocv_dis_high_soc;
+	int				ocv_dis_low_soc;
 };
 
 #if defined(CONFIG_PM8921_BMS) || defined(CONFIG_PM8921_BMS_MODULE)