hwmon: qpnp-vadc: Set peripheral warm reset

It is seen on certain conditions during bootup the end
of conversion interrupt is latched and this causes the
VADC to never receive the end of conversion interrupt.
This causes the clients to experience delays when requesting
an ADC request and on certain scenario during a soft reset
condition delays bootup.

qpnp-int expects the peripheral interrupt registers to be
in a known state. If an interrupt occured and is not
handled correctly it could lead to the interrupt being
latched and subsequent interrupts are never handled.

Each qpnp peripheral has an option to reset the peripheral
when a warm reset occurs to reset the peripheral to its
power on reset state. Set the VADC peripheral reset register
to enable resetting the peripheral during a warm reset.

Change-Id: Ic59726d327bf93900011d6f7051b2967ed0eae87
Signed-off-by: Siddartha Mohanadoss <smohanad@codeaurora.org>
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index b3b3b5e..4306b1d 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -83,6 +83,14 @@
 #define QPNP_VADC_M1_LOW_THR_MSB					0x6a
 #define QPNP_VADC_M1_HIGH_THR_LSB				0x6b
 #define QPNP_VADC_M1_HIGH_THR_MSB				0x6c
+#define QPNP_VADC_ACCESS					0xd0
+#define QPNP_VADC_ACCESS_DATA					0xa5
+#define QPNP_VADC_PERH_RESET_CTL3				0xda
+#define QPNP_FOLLOW_OTST2_RB					BIT(3)
+#define QPNP_FOLLOW_WARM_RB					BIT(2)
+#define QPNP_FOLLOW_SHUTDOWN1_RB				BIT(1)
+#define QPNP_FOLLOW_SHUTDOWN2_RB				BIT(0)
+
 #define QPNP_INT_TEST_VAL					0xE1
 
 #define QPNP_VADC_DATA0						0x60
@@ -150,6 +158,40 @@
 	return 0;
 }
 
+static int32_t qpnp_vadc_warm_rst_configure(void)
+{
+	int rc = 0;
+	u8 data = 0;
+
+	rc = qpnp_vadc_write_reg(QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
+	if (rc < 0) {
+		pr_err("VADC write access failed\n");
+		return rc;
+	}
+
+	rc = qpnp_vadc_read_reg(QPNP_VADC_PERH_RESET_CTL3, &data);
+	if (rc < 0) {
+		pr_err("VADC perh reset ctl3 read failed\n");
+		return rc;
+	}
+
+	rc = qpnp_vadc_write_reg(QPNP_VADC_ACCESS, QPNP_VADC_ACCESS_DATA);
+	if (rc < 0) {
+		pr_err("VADC write access failed\n");
+		return rc;
+	}
+
+	data |= QPNP_FOLLOW_WARM_RB;
+
+	rc = qpnp_vadc_write_reg(QPNP_VADC_PERH_RESET_CTL3, data);
+	if (rc < 0) {
+		pr_err("VADC perh reset ctl3 write failed\n");
+		return rc;
+	}
+
+	return 0;
+}
+
 static int32_t qpnp_vadc_enable(bool state)
 {
 	int rc = 0;
@@ -1126,6 +1168,12 @@
 	}
 	vadc->id = fab_id;
 
+	rc = qpnp_vadc_warm_rst_configure();
+	if (rc < 0) {
+		pr_err("Setting perp reset on warm reset failed %d\n", rc);
+		return rc;
+	}
+
 	vadc->vadc_initialized = true;
 	vadc->vadc_iadc_sync_lock = false;