hwmon: qpnp-adc-current: Perform trim update after init

Perform calibration to update trim immediately after
initialization to utilize interrupts as opposed to
performing it as part of driver initialization and
rely on polling. This improves the boot time. Also
add additional checks to ensure driver is initialized
before reading from rsense.

Change-Id: Ibfea3aa67abf86559830d85cb70a722168848a84
Signed-off-by: Siddartha Mohanadoss <smohanad@codeaurora.org>
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 3fdc68f..e4a9e30 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -131,7 +131,6 @@
 	struct qpnp_adc_drv			*adc;
 	int32_t					rsense;
 	struct device				*iadc_hwmon;
-	bool					iadc_init_calib;
 	bool					iadc_initialized;
 	int64_t					die_temp_calib_offset;
 	struct delayed_work			iadc_work;
@@ -413,6 +412,8 @@
 	uint16_t raw_data;
 	uint32_t mode_sel = 0;
 
+	mutex_lock(&iadc->adc->adc_lock);
+
 	rc = qpnp_iadc_configure(GAIN_CALIBRATION_17P857MV,
 						&raw_data, mode_sel);
 	if (rc < 0) {
@@ -469,6 +470,7 @@
 		goto fail;
 	}
 fail:
+	mutex_unlock(&iadc->adc->adc_lock);
 	return rc;
 }
 
@@ -477,16 +479,12 @@
 	struct qpnp_iadc_drv *iadc = qpnp_iadc;
 	int rc = 0;
 
-	mutex_lock(&iadc->adc->adc_lock);
-
 	rc = qpnp_iadc_calibrate_for_trim();
 	if (rc) {
 		pr_err("periodic IADC calibration failed\n");
 		iadc->iadc_err_cnt++;
 	}
 
-	mutex_unlock(&iadc->adc->adc_lock);
-
 	if (iadc->iadc_err_cnt < QPNP_IADC_ERR_CHK_RATELIMIT)
 		schedule_delayed_work(&iadc->iadc_work,
 			round_jiffies_relative(msecs_to_jiffies
@@ -527,9 +525,13 @@
 
 int32_t qpnp_iadc_get_rsense(int32_t *rsense)
 {
+	struct qpnp_iadc_drv *iadc = qpnp_iadc;
 	uint8_t	rslt_rsense;
 	int32_t	rc, sign_bit = 0;
 
+	if (!iadc || !iadc->iadc_initialized)
+		return -EPROBE_DEFER;
+
 	rc = qpnp_iadc_read_reg(QPNP_IADC_NOMINAL_RSENSE, &rslt_rsense);
 	if (rc < 0) {
 		pr_err("qpnp adc rsense read failed with %d\n", rc);
@@ -552,7 +554,7 @@
 }
 EXPORT_SYMBOL(qpnp_iadc_get_rsense);
 
-int32_t qpnp_check_pmic_temp(void)
+static int32_t qpnp_check_pmic_temp(void)
 {
 	struct qpnp_iadc_drv *iadc = qpnp_iadc;
 	struct qpnp_vadc_result result_pmic_therm;
@@ -565,13 +567,9 @@
 	if (((uint64_t) (result_pmic_therm.physical -
 				iadc->die_temp_calib_offset))
 			> QPNP_IADC_DIE_TEMP_CALIB_OFFSET) {
-		mutex_lock(&iadc->adc->adc_lock);
-
 		rc = qpnp_iadc_calibrate_for_trim();
 		if (rc)
 			pr_err("periodic IADC calibration failed\n");
-
-		mutex_unlock(&iadc->adc->adc_lock);
 	}
 
 	return 0;
@@ -818,7 +816,6 @@
 	} else
 		enable_irq_wake(iadc->adc->adc_irq_eoc);
 
-	iadc->iadc_init_calib = false;
 	dev_set_drvdata(&spmi->dev, iadc);
 	qpnp_iadc = iadc;
 
@@ -835,20 +832,17 @@
 		goto fail;
 	}
 
-	rc = qpnp_iadc_calibrate_for_trim();
-	if (rc) {
-		dev_err(&spmi->dev, "failed to calibrate for USR trim\n");
-		goto fail;
-	}
-	iadc->iadc_init_calib = true;
-	INIT_DELAYED_WORK(&iadc->iadc_work, qpnp_iadc_work);
-	schedule_delayed_work(&iadc->iadc_work,
-			round_jiffies_relative(msecs_to_jiffies
-					(QPNP_IADC_CALIB_SECONDS)));
 	mutex_init(&iadc->iadc_vadc_lock);
+	INIT_DELAYED_WORK(&iadc->iadc_work, qpnp_iadc_work);
 	iadc->iadc_err_cnt = 0;
 	iadc->iadc_initialized = true;
 
+	rc = qpnp_iadc_calibrate_for_trim();
+	if (rc)
+		dev_err(&spmi->dev, "failed to calibrate for USR trim\n");
+	schedule_delayed_work(&iadc->iadc_work,
+			round_jiffies_relative(msecs_to_jiffies
+					(QPNP_IADC_CALIB_SECONDS)));
 	return 0;
 fail:
 	qpnp_iadc = NULL;
@@ -862,6 +856,7 @@
 	struct device_node *child;
 	int i = 0;
 
+	cancel_delayed_work(&iadc->iadc_work);
 	mutex_destroy(&iadc->iadc_vadc_lock);
 	for_each_child_of_node(node, child) {
 		device_remove_file(&spmi->dev,