hwmon: qpnp-adc-tm: Optimize and add more TM channel support

The change adds 3 additional channels and run-time
detects the supported number of channels to allow
clients to set threshold notification.

To support this, optimize the kernel api used to configure
and start a threshold monitoring request to include multiple
clients thus avoiding the need to have seperate kernel api's
for different clients. Changes are made to avoid the driver
depending on the order in which the VADC_TM DT channel
nodes should be added. Support is now included to
monitor DIE temperature for reading the pmic_therm, VBATT
and msm_thermistor scaling functions.

The change also disables the bank when an interrupt is
received or any changes are to be made in the settings,
make sure no measurements are in the queue, settings updated
and the bank is re-enabled.

Change-Id: I7a7c03857c86127dd6f1055df17099ecff4bb2f7
Signed-off-by: Siddartha Mohanadoss <smohanad@codeaurora.org>
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index ecd4bbb..2fdf791 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -367,7 +367,42 @@
 }
 EXPORT_SYMBOL_GPL(qpnp_adc_scale_pmic_therm);
 
-/* Scales the ADC code to 0.001 degrees C using the map
+int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(
+		struct qpnp_adc_tm_btm_param *param,
+		uint32_t *low_threshold, uint32_t *high_threshold)
+{
+	struct qpnp_vadc_linear_graph btm_param;
+	int64_t *low_output = 0, *high_output = 0;
+	int rc = 0;
+
+	rc = qpnp_get_vadc_gain_and_offset(&btm_param, CALIB_ABSOLUTE);
+	if (rc < 0) {
+		pr_err("Could not acquire gain and offset\n");
+		return rc;
+	}
+
+	/* Convert to Kelvin and account for voltage to be written as 2mV/K */
+	*low_output = (param->low_temp + KELVINMIL_DEGMIL) * 2;
+	/* Convert to voltage threshold */
+	*low_output *= btm_param.dy;
+	do_div(*low_output, btm_param.adc_vref);
+	*low_output += btm_param.adc_gnd;
+
+	/* Convert to Kelvin and account for voltage to be written as 2mV/K */
+	*high_output = (param->high_temp + KELVINMIL_DEGMIL) * 2;
+	/* Convert to voltage threshold */
+	*high_output *= btm_param.dy;
+	do_div(*high_output, btm_param.adc_vref);
+	*high_output += btm_param.adc_gnd;
+
+	low_threshold = (uint32_t *) low_output;
+	high_threshold = (uint32_t *) high_output;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(qpnp_adc_scale_millidegc_pmic_voltage_thr);
+
+/* Scales the ADC code to degC using the mapping
  * table for the XO thermistor.
  */
 int32_t qpnp_adc_tdkntcg_therm(int32_t adc_code,
@@ -577,7 +612,8 @@
 }
 EXPORT_SYMBOL_GPL(qpnp_adc_scale_default);
 
-int32_t qpnp_adc_usb_scaler(struct qpnp_adc_tm_usbid_param *param,
+/* Converts millivolts to ADC high/low threshold code */
+int32_t qpnp_adc_usb_scaler(struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold)
 {
 	struct qpnp_vadc_linear_graph usb_param;
@@ -592,10 +628,34 @@
 	do_div(*high_threshold, usb_param.adc_vref);
 	*high_threshold += usb_param.adc_gnd;
 
+	pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
+				param->low_thr);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(qpnp_adc_usb_scaler);
 
+int32_t qpnp_adc_vbatt_rscaler(struct qpnp_adc_tm_btm_param *param,
+		uint32_t *low_threshold, uint32_t *high_threshold)
+{
+	struct qpnp_vadc_linear_graph vbatt_param;
+
+	qpnp_get_vadc_gain_and_offset(&vbatt_param, CALIB_ABSOLUTE);
+
+	*low_threshold = param->low_thr * vbatt_param.dy;
+	do_div(*low_threshold, vbatt_param.adc_vref);
+	*low_threshold += vbatt_param.adc_gnd;
+
+	*high_threshold = param->high_thr * vbatt_param.dy;
+	do_div(*high_threshold, vbatt_param.adc_vref);
+	*high_threshold += vbatt_param.adc_gnd;
+
+	pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
+				param->low_thr);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(qpnp_adc_vbatt_rscaler);
+
+/* Converts decidegreesC to voltage based on the mapping table */
 int32_t qpnp_adc_btm_scaler(struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold)
 {
@@ -625,6 +685,8 @@
 	if (rc)
 		return rc;
 
+	pr_debug("warm_temp:%d and cool_temp:%d\n", param->high_temp,
+				param->low_temp);
 	*high_output *= btm_param.dy;
 	do_div(*high_output, btm_param.adc_vref);
 	*high_output += btm_param.adc_gnd;
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 180ca0d..6cd6d5b 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -1353,7 +1353,7 @@
 	}
 
 	/* re-arm ADC interrupt */
-	qpnp_adc_tm_btm_configure(&chip->adc_param);
+	qpnp_adc_tm_channel_measure(&chip->adc_param);
 }
 
 static int
@@ -2005,8 +2005,8 @@
 		chip->adc_param.btm_ctx = chip;
 		chip->adc_param.threshold_notification =
 						qpnp_chg_adc_notification;
-
-		rc = qpnp_adc_tm_btm_configure(&chip->adc_param);
+		chip->adc_param.channel = LR_MUX1_BATT_THERM;
+		rc = qpnp_adc_tm_channel_measure(&chip->adc_param);
 		if (rc) {
 			pr_err("request ADC error %d\n", rc);
 			goto fail_chg_enable;
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index 17ae34f..e84220f 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -35,6 +35,8 @@
 #include <linux/platform_device.h>
 
 /* QPNP VADC TM register definition */
+#define QPNP_REVISION3					0x3
+#define QPNP_REVISION_EIGHT_CHANNEL_SUPPORT		2
 #define QPNP_STATUS1					0x8
 #define QPNP_STATUS1_OP_MODE				4
 #define QPNP_STATUS1_MEAS_INTERVAL_EN_STS		BIT(2)
@@ -79,22 +81,41 @@
 #define QPNP_M0_LOW_THR_MSB				0x5d
 #define QPNP_M0_HIGH_THR_LSB				0x5e
 #define QPNP_M0_HIGH_THR_MSB				0x5f
+#define QPNP_M1_ADC_CH_SEL_CTL				0x68
 #define QPNP_M1_LOW_THR_LSB				0x69
 #define QPNP_M1_LOW_THR_MSB				0x6a
 #define QPNP_M1_HIGH_THR_LSB				0x6b
 #define QPNP_M1_HIGH_THR_MSB				0x6c
+#define QPNP_M2_ADC_CH_SEL_CTL				0x70
 #define QPNP_M2_LOW_THR_LSB				0x71
 #define QPNP_M2_LOW_THR_MSB				0x72
 #define QPNP_M2_HIGH_THR_LSB				0x7b
 #define QPNP_M2_HIGH_THR_MSB				0x7c
+#define QPNP_M3_ADC_CH_SEL_CTL				0x78
 #define QPNP_M3_LOW_THR_LSB				0x79
 #define QPNP_M3_LOW_THR_MSB				0x7a
 #define QPNP_M3_HIGH_THR_LSB				0x7b
 #define QPNP_M3_HIGH_THR_MSB				0x7c
+#define QPNP_M4_ADC_CH_SEL_CTL				0x80
 #define QPNP_M4_LOW_THR_LSB				0x81
 #define QPNP_M4_LOW_THR_MSB				0x82
 #define QPNP_M4_HIGH_THR_LSB				0x83
 #define QPNP_M4_HIGH_THR_MSB				0x84
+#define QPNP_M5_ADC_CH_SEL_CTL				0x88
+#define QPNP_M5_LOW_THR_LSB				0x89
+#define QPNP_M5_LOW_THR_MSB				0x8a
+#define QPNP_M5_HIGH_THR_LSB				0x8b
+#define QPNP_M5_HIGH_THR_MSB				0x8c
+#define QPNP_M6_ADC_CH_SEL_CTL				0x90
+#define QPNP_M6_LOW_THR_LSB				0x91
+#define QPNP_M6_LOW_THR_MSB				0x92
+#define QPNP_M6_HIGH_THR_LSB				0x93
+#define QPNP_M6_HIGH_THR_MSB				0x94
+#define QPNP_M7_ADC_CH_SEL_CTL				0x98
+#define QPNP_M7_LOW_THR_LSB				0x99
+#define QPNP_M7_LOW_THR_MSB				0x9a
+#define QPNP_M7_HIGH_THR_LSB				0x9b
+#define QPNP_M7_HIGH_THR_MSB				0x9c
 
 #define QPNP_ADC_TM_MULTI_MEAS_EN			0x41
 #define QPNP_ADC_TM_MULTI_MEAS_EN_M0			BIT(0)
@@ -102,24 +123,36 @@
 #define QPNP_ADC_TM_MULTI_MEAS_EN_M2			BIT(2)
 #define QPNP_ADC_TM_MULTI_MEAS_EN_M3			BIT(3)
 #define QPNP_ADC_TM_MULTI_MEAS_EN_M4			BIT(4)
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M5			BIT(5)
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M6			BIT(6)
+#define QPNP_ADC_TM_MULTI_MEAS_EN_M7			BIT(7)
 #define QPNP_ADC_TM_LOW_THR_INT_EN			0x42
 #define QPNP_ADC_TM_LOW_THR_INT_EN_M0			BIT(0)
 #define QPNP_ADC_TM_LOW_THR_INT_EN_M1			BIT(1)
 #define QPNP_ADC_TM_LOW_THR_INT_EN_M2			BIT(2)
 #define QPNP_ADC_TM_LOW_THR_INT_EN_M3			BIT(3)
 #define QPNP_ADC_TM_LOW_THR_INT_EN_M4			BIT(4)
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M5			BIT(5)
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M6			BIT(6)
+#define QPNP_ADC_TM_LOW_THR_INT_EN_M7			BIT(7)
 #define QPNP_ADC_TM_HIGH_THR_INT_EN			0x43
 #define QPNP_ADC_TM_HIGH_THR_INT_EN_M0			BIT(0)
 #define QPNP_ADC_TM_HIGH_THR_INT_EN_M1			BIT(1)
 #define QPNP_ADC_TM_HIGH_THR_INT_EN_M2			BIT(2)
 #define QPNP_ADC_TM_HIGH_THR_INT_EN_M3			BIT(3)
 #define QPNP_ADC_TM_HIGH_THR_INT_EN_M4			BIT(4)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M5			BIT(5)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M6			BIT(6)
+#define QPNP_ADC_TM_HIGH_THR_INT_EN_M7			BIT(7)
 
-#define QPNP_ADC_TM_M0_MEAS_INTERVAL_CTL			0x57
+#define QPNP_ADC_TM_M0_MEAS_INTERVAL_CTL			0x59
 #define QPNP_ADC_TM_M1_MEAS_INTERVAL_CTL			0x6d
 #define QPNP_ADC_TM_M2_MEAS_INTERVAL_CTL			0x75
 #define QPNP_ADC_TM_M3_MEAS_INTERVAL_CTL			0x7d
 #define QPNP_ADC_TM_M4_MEAS_INTERVAL_CTL			0x85
+#define QPNP_ADC_TM_M5_MEAS_INTERVAL_CTL			0x8d
+#define QPNP_ADC_TM_M6_MEAS_INTERVAL_CTL			0x95
+#define QPNP_ADC_TM_M7_MEAS_INTERVAL_CTL			0x9d
 #define QPNP_ADC_TM_STATUS1				0x8
 #define QPNP_ADC_TM_STATUS_LOW				0xa
 #define QPNP_ADC_TM_STATUS_HIGH				0xb
@@ -131,6 +164,9 @@
 #define QPNP_ADC_TM_THR_LSB_MASK(val)			(val & 0xff)
 #define QPNP_ADC_TM_THR_MSB_MASK(val)			((val & 0xff00) >> 8)
 
+#define QPNP_MIN_TIME			2000
+#define QPNP_MAX_TIME			2100
+
 struct qpnp_adc_tm_sensor {
 	struct thermal_zone_device	*tz_dev;
 	enum thermal_device_mode	mode;
@@ -140,16 +176,18 @@
 	uint32_t			low_thr;
 	uint32_t			high_thr;
 	uint32_t			btm_channel_num;
+	uint32_t			vadc_channel_num;
 	struct work_struct		work;
+	struct qpnp_adc_tm_btm_param	*btm_param;
+	bool				thermal_node;
+	bool				low_thr_notify;
+	bool				high_thr_notify;
 };
 
 struct qpnp_adc_tm_drv {
 	struct qpnp_adc_drv		*adc;
-	struct qpnp_adc_tm_usbid_param	*usb_id_param;
-	struct work_struct		usbid_work;
-	struct qpnp_adc_tm_btm_param	*battery_param;
-	struct work_struct		batt_work;
 	bool				adc_tm_initialized;
+	int				max_channels_available;
 	struct qpnp_adc_tm_sensor	sensor[0];
 };
 
@@ -163,29 +201,57 @@
 	u8 multi_meas_en;
 	u8 low_thr_int_chan_en;
 	u8 high_thr_int_chan_en;
+	u8 meas_interval_ctl;
 };
 
 static struct qpnp_adc_tm_trip_reg_type adc_tm_data[] = {
 	[QPNP_ADC_TM_M0_ADC_CH_SEL_CTL] = {QPNP_M0_LOW_THR_LSB,
 		QPNP_M0_LOW_THR_MSB, QPNP_M0_HIGH_THR_LSB,
 		QPNP_M0_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M0,
-		QPNP_ADC_TM_LOW_THR_INT_EN_M0, QPNP_ADC_TM_HIGH_THR_INT_EN_M0},
+		QPNP_ADC_TM_LOW_THR_INT_EN_M0, QPNP_ADC_TM_HIGH_THR_INT_EN_M0,
+		QPNP_ADC_TM_M0_MEAS_INTERVAL_CTL},
 	[QPNP_ADC_TM_M1_ADC_CH_SEL_CTL] = {QPNP_M1_LOW_THR_LSB,
 		QPNP_M1_LOW_THR_MSB, QPNP_M1_HIGH_THR_LSB,
 		QPNP_M1_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M1,
-		QPNP_ADC_TM_LOW_THR_INT_EN_M1, QPNP_ADC_TM_HIGH_THR_INT_EN_M1},
+		QPNP_ADC_TM_LOW_THR_INT_EN_M1, QPNP_ADC_TM_HIGH_THR_INT_EN_M1,
+		QPNP_ADC_TM_M1_MEAS_INTERVAL_CTL},
 	[QPNP_ADC_TM_M2_ADC_CH_SEL_CTL] = {QPNP_M2_LOW_THR_LSB,
 		QPNP_M2_LOW_THR_MSB, QPNP_M2_HIGH_THR_LSB,
 		QPNP_M2_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M2,
-		QPNP_ADC_TM_LOW_THR_INT_EN_M2, QPNP_ADC_TM_HIGH_THR_INT_EN_M2},
+		QPNP_ADC_TM_LOW_THR_INT_EN_M2, QPNP_ADC_TM_HIGH_THR_INT_EN_M2,
+		QPNP_ADC_TM_M2_MEAS_INTERVAL_CTL},
 	[QPNP_ADC_TM_M3_ADC_CH_SEL_CTL] = {QPNP_M3_LOW_THR_LSB,
 		QPNP_M3_LOW_THR_MSB, QPNP_M3_HIGH_THR_LSB,
 		QPNP_M3_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M3,
-		QPNP_ADC_TM_LOW_THR_INT_EN_M3, QPNP_ADC_TM_HIGH_THR_INT_EN_M3},
+		QPNP_ADC_TM_LOW_THR_INT_EN_M3, QPNP_ADC_TM_HIGH_THR_INT_EN_M3,
+		QPNP_ADC_TM_M3_MEAS_INTERVAL_CTL},
 	[QPNP_ADC_TM_M4_ADC_CH_SEL_CTL] = {QPNP_M4_LOW_THR_LSB,
 		QPNP_M4_LOW_THR_MSB, QPNP_M4_HIGH_THR_LSB,
 		QPNP_M4_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M4,
-		QPNP_ADC_TM_LOW_THR_INT_EN_M4, QPNP_ADC_TM_HIGH_THR_INT_EN_M4},
+		QPNP_ADC_TM_LOW_THR_INT_EN_M4, QPNP_ADC_TM_HIGH_THR_INT_EN_M4,
+		QPNP_ADC_TM_M4_MEAS_INTERVAL_CTL},
+	[QPNP_ADC_TM_M5_ADC_CH_SEL_CTL] = {QPNP_M5_LOW_THR_LSB,
+		QPNP_M5_LOW_THR_MSB, QPNP_M5_HIGH_THR_LSB,
+		QPNP_M5_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M5,
+		QPNP_ADC_TM_LOW_THR_INT_EN_M5, QPNP_ADC_TM_HIGH_THR_INT_EN_M5,
+		QPNP_ADC_TM_M5_MEAS_INTERVAL_CTL},
+	[QPNP_ADC_TM_M6_ADC_CH_SEL_CTL] = {QPNP_M6_LOW_THR_LSB,
+		QPNP_M6_LOW_THR_MSB, QPNP_M6_HIGH_THR_LSB,
+		QPNP_M6_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M6,
+		QPNP_ADC_TM_LOW_THR_INT_EN_M6, QPNP_ADC_TM_HIGH_THR_INT_EN_M6,
+		QPNP_ADC_TM_M6_MEAS_INTERVAL_CTL},
+	[QPNP_ADC_TM_M7_ADC_CH_SEL_CTL] = {QPNP_M7_LOW_THR_LSB,
+		QPNP_M7_LOW_THR_MSB, QPNP_M7_HIGH_THR_LSB,
+		QPNP_M7_HIGH_THR_MSB, QPNP_ADC_TM_MULTI_MEAS_EN_M7,
+		QPNP_ADC_TM_LOW_THR_INT_EN_M7, QPNP_ADC_TM_HIGH_THR_INT_EN_M7,
+		QPNP_ADC_TM_M7_MEAS_INTERVAL_CTL},
+};
+
+static struct qpnp_adc_tm_reverse_scale_fn adc_tm_rscale_fn[] = {
+	[SCALE_R_VBATT] = {qpnp_adc_vbatt_rscaler},
+	[SCALE_RBATT_THERM] = {qpnp_adc_btm_scaler},
+	[SCALE_R_USB_ID] = {qpnp_adc_usb_scaler},
+	[SCALE_RPMIC_THERM] = {qpnp_adc_scale_millidegc_pmic_voltage_thr},
 };
 
 static int32_t qpnp_adc_tm_read_reg(int16_t reg, u8 *data)
@@ -217,40 +283,63 @@
 	return rc;
 }
 
-static int32_t qpnp_adc_tm_enable(bool state)
+static int32_t qpnp_adc_tm_enable(void)
 {
 	int rc = 0;
-	u8 data = 0, enable_check = 0;
+	u8 data = 0;
 
-	if (state) {
-		data = QPNP_ADC_TM_EN;
-		rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1,
-					data);
-		if (rc < 0)
-			pr_err("adc-tm enable failed\n");
-	} else {
-		rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_MULTI_MEAS_EN,
-					&enable_check);
+	data = QPNP_ADC_TM_EN;
+	rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1, data);
+	if (rc < 0)
+		pr_err("adc-tm enable failed\n");
+
+	return rc;
+}
+
+static int32_t qpnp_adc_tm_disable(void)
+{
+	u8 data = 0;
+	int rc = 0;
+
+	rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1, data);
+	if (rc < 0)
+		pr_err("adc-tm disable failed\n");
+
+	return rc;
+}
+
+static int32_t qpnp_adc_tm_enable_if_channel_meas(void)
+{
+	u8 adc_tm_meas_en = 0;
+	int rc = 0;
+
+	/* Check if a measurement request is still required */
+	rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_MULTI_MEAS_EN,
+							&adc_tm_meas_en);
+	if (rc) {
+		pr_err("adc-tm-tm read status high failed with %d\n", rc);
+		return rc;
+	}
+
+	/* Enable only if there are pending measurement requests */
+	if (adc_tm_meas_en) {
+		qpnp_adc_tm_enable();
+
+		/* Request conversion */
+		rc = qpnp_adc_tm_write_reg(QPNP_CONV_REQ, QPNP_CONV_REQ_SET);
 		if (rc < 0) {
-			pr_err("multi measurement read failed\n");
+			pr_err("adc-tm request conversion failed\n");
 			return rc;
 		}
-
-		if (!enable_check) {
-			data = 0;
-			rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1, data);
-			if (rc < 0)
-				pr_err("adc-tm disable failed\n");
-		}
 	}
 
 	return rc;
 }
 
-static int32_t qpnp_adc_tm_enable_req_sts_check(void)
+static int32_t qpnp_adc_tm_req_sts_check(void)
 {
 	u8 status1;
-	int rc;
+	int rc, count = 0;
 
 	/* The VADC_TM bank needs to be disabled for new conversion request */
 	rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS1, &status1);
@@ -260,19 +349,45 @@
 	}
 
 	/* Disable the bank if a conversion is occuring */
-	if (status1 & QPNP_STATUS1_REQ_STS) {
-		rc = qpnp_adc_tm_write_reg(QPNP_EN_CTL1, 0);
+	while ((status1 & QPNP_STATUS1_REQ_STS) && (count < 5)) {
+		rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS1, &status1);
 		if (rc < 0)
 			pr_err("adc-tm disable failed\n");
+		/* Wait time is based on the optimum sampling rate
+		 * and adding enough time buffer to account for ADC conversions
+		 * occuring on different peripheral banks */
+		usleep_range(QPNP_MIN_TIME, QPNP_MAX_TIME);
+		count++;
 	}
 
 	return rc;
 }
 
+static int32_t qpnp_adc_tm_check_revision(uint32_t btm_chan_num)
+{
+	u8 rev;
+	int rc = 0;
+
+	rc = qpnp_adc_tm_read_reg(QPNP_REVISION3, &rev);
+	if (rc) {
+		pr_err("adc-tm revision read failed\n");
+		return rc;
+	}
+
+	if ((rev < QPNP_REVISION_EIGHT_CHANNEL_SUPPORT) &&
+		(btm_chan_num > QPNP_ADC_TM_M4_ADC_CH_SEL_CTL)) {
+		pr_debug("Version does not support more than 5 channels\n");
+		return -EINVAL;
+	}
+
+	return rc;
+}
 static int32_t qpnp_adc_tm_mode_select(u8 mode_ctl)
 {
 	int rc;
 
+	mode_ctl |= (QPNP_ADC_TRIM_EN | QPNP_AMUX_TRIM_EN);
+
 	/* VADC_BTM current sets mode to recurring measurements */
 	rc = qpnp_adc_tm_write_reg(QPNP_MODE_CTL, mode_ctl);
 	if (rc < 0)
@@ -281,13 +396,13 @@
 	return rc;
 }
 
-static int32_t qpnp_adc_tm_timer_interval_select(
+static int32_t qpnp_adc_tm_timer_interval_select(uint32_t btm_chan,
 		struct qpnp_vadc_chan_properties *chan_prop)
 {
 	int rc;
 	u8 meas_interval_timer2 = 0;
 
-	/* Configure USB_ID to timer1, batt_therm to timer2 */
+	/* Configure kernel clients to timer1 */
 	switch (chan_prop->timer_select) {
 	case ADC_MEAS_TIMER_SELECT1:
 		rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_MEAS_INTERVAL_CTL,
@@ -298,6 +413,7 @@
 		}
 	break;
 	case ADC_MEAS_TIMER_SELECT2:
+		/* Thermal channels uses timer2, default to 1 second */
 		rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
 				&meas_interval_timer2);
 		if (rc < 0) {
@@ -315,7 +431,6 @@
 		}
 	break;
 	case ADC_MEAS_TIMER_SELECT3:
-		/* Thermal channels uses timer3, default to 1 second */
 		rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_MEAS_INTERVAL_CTL2,
 				&meas_interval_timer2);
 		if (rc < 0) {
@@ -336,29 +451,35 @@
 		return -EINVAL;
 	}
 
+	/* Select the timer to use for the corresponding channel */
+	adc_tm_data[btm_chan].meas_interval_ctl = chan_prop->timer_select;
+
 	return rc;
 }
 
-static int32_t qpnp_adc_tm_meas_int_update(uint16_t reg_addr_src,
-		u8 reg_addr_dst, bool state)
+static int32_t qpnp_adc_tm_meas_int_update(uint16_t addr,
+		u8 mask, bool state)
 {
-	u8 bit_mask_check = 0;
+	u8 reg_value = 0;
 	int rc = 0;
 
-	rc = qpnp_adc_tm_read_reg(reg_addr_src, &bit_mask_check);
+	rc = qpnp_adc_tm_read_reg(addr, &reg_value);
 	if (rc < 0) {
-		pr_err("read failed for addr:%x\n", reg_addr_src);
+		pr_err("read failed for addr:0x%x\n", addr);
 		return rc;
 	}
 
+	reg_value = reg_value & ~mask;
 	if (state)
-		bit_mask_check |= reg_addr_dst;
-	else
-		bit_mask_check &= ~reg_addr_dst;
+		reg_value |= mask;
 
-	rc = qpnp_adc_tm_write_reg(reg_addr_src, bit_mask_check);
-	if (rc < 0)
-		pr_err("write failed for addr:%x\n", reg_addr_src);
+	pr_debug("state:%d, reg:0x%x with bits:0x%x and mask:0x%x\n",
+					state, addr, reg_value, ~mask);
+	rc = qpnp_adc_tm_write_reg(addr, reg_value);
+	if (rc < 0) {
+		pr_err("write failed for addr:%x\n", addr);
+		return rc;
+	}
 
 	return rc;
 }
@@ -398,6 +519,9 @@
 	if (rc < 0)
 		pr_err("high threshold msb setting failed\n");
 
+	pr_debug("client requested high:%d and low:%d\n",
+		chan_prop->low_thr, chan_prop->high_thr);
+
 	return rc;
 }
 
@@ -405,11 +529,27 @@
 			struct qpnp_vadc_chan_properties *chan_prop,
 			uint32_t amux_channel)
 {
-	int rc = 0;
+	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
+	int rc = 0, i = 0, chan_idx = 0;
+	bool chan_found = false;
+	u8 sensor_mask = 0;
 
-	switch (btm_chan) {
-	case QPNP_ADC_TM_M0_ADC_CH_SEL_CTL:
-	case QPNP_ADC_TM_M1_ADC_CH_SEL_CTL:
+	while (i < adc_tm->max_channels_available) {
+		if (adc_tm->sensor[i].btm_channel_num == btm_chan) {
+			chan_idx = i;
+			chan_found = true;
+			i++;
+		} else
+			i++;
+	}
+
+	if ((i == adc_tm->max_channels_available) && (!chan_found)) {
+		pr_err("Channel not found\n");
+		return -EINVAL;
+	}
+
+	sensor_mask = 1 << chan_idx;
+	if (!adc_tm->sensor[chan_idx].thermal_node) {
 		/* Update low and high notification thresholds */
 		rc = qpnp_adc_tm_usbid_btm_thr_en(btm_chan,
 				chan_prop);
@@ -422,11 +562,11 @@
 					ADC_TM_LOW_THR_ENABLE) ||
 			(chan_prop->state_request ==
 					ADC_TM_HIGH_LOW_THR_ENABLE)) {
+			pr_debug("low sensor mask:%x with state:%d\n",
+					sensor_mask, chan_prop->state_request);
 			/* Enable low threshold's interrupt */
 			rc = qpnp_adc_tm_meas_int_update(
-				QPNP_ADC_TM_LOW_THR_INT_EN,
-				adc_tm_data[btm_chan].low_thr_int_chan_en,
-				true);
+				QPNP_ADC_TM_LOW_THR_INT_EN, sensor_mask, true);
 			if (rc < 0) {
 				pr_err("low thr enable err:%d\n", btm_chan);
 				return rc;
@@ -438,37 +578,22 @@
 			(chan_prop->state_request ==
 					ADC_TM_HIGH_LOW_THR_ENABLE)) {
 			/* Enable high threshold's interrupt */
+			pr_debug("high sensor mask:%x\n", sensor_mask);
 			rc = qpnp_adc_tm_meas_int_update(
-				QPNP_ADC_TM_HIGH_THR_INT_EN,
-				adc_tm_data[btm_chan].high_thr_int_chan_en,
-				true);
+				QPNP_ADC_TM_HIGH_THR_INT_EN, sensor_mask, true);
 			if (rc < 0) {
 				pr_err("high thr enable err:%d\n", btm_chan);
 				return rc;
 			}
 		}
-	/* intention fall through to configure common chan meas */
-	case QPNP_ADC_TM_M2_ADC_CH_SEL_CTL:
-	case QPNP_ADC_TM_M3_ADC_CH_SEL_CTL:
-	case QPNP_ADC_TM_M4_ADC_CH_SEL_CTL:
-		/* Configure AMUX control register for channel selection */
-		rc = qpnp_adc_tm_write_reg(btm_chan, amux_channel);
-		if (rc < 0) {
-			pr_err("btm_chan:%d selection failed\n", btm_chan);
-			return rc;
-		}
+	}
 
-		/* Enable corresponding BTM channel measurement */
-		rc = qpnp_adc_tm_meas_int_update(
-			QPNP_ADC_TM_MULTI_MEAS_EN,
-			adc_tm_data[btm_chan].multi_meas_en, true);
-		if (rc < 0) {
-			pr_err("multi measurement en failed\n");
-			return rc;
-		}
-	break;
-	default:
-		return -EINVAL;
+	/* Enable corresponding BTM channel measurement */
+	rc = qpnp_adc_tm_meas_int_update(
+		QPNP_ADC_TM_MULTI_MEAS_EN, sensor_mask, true);
+	if (rc < 0) {
+		pr_err("multi measurement en failed\n");
+		return rc;
 	}
 
 	return rc;
@@ -477,12 +602,17 @@
 static int32_t qpnp_adc_tm_configure(
 			struct qpnp_adc_amux_properties *chan_prop)
 {
-	u8 decimation = 0;
+	u8 decimation = 0, op_cntrl = 0;
 	int rc = 0;
 	uint32_t btm_chan = 0;
 
+	/* Disable bank */
+	rc = qpnp_adc_tm_disable();
+	if (rc)
+		return rc;
+
 	/* Check if a conversion is in progress */
-	rc = qpnp_adc_tm_enable_req_sts_check();
+	rc = qpnp_adc_tm_req_sts_check();
 	if (rc < 0) {
 		pr_err("adc-tm req_sts check failed\n");
 		return rc;
@@ -495,9 +625,9 @@
 		return rc;
 	}
 
-	/* Configure AMUX channel */
-	rc = qpnp_adc_tm_write_reg(QPNP_ADC_CH_SEL_CTL,
-				chan_prop->amux_channel);
+	/* Configure AMUX channel select for the corresponding BTM channel*/
+	btm_chan = chan_prop->chan_prop->tm_channel_select;
+	rc = qpnp_adc_tm_write_reg(btm_chan, chan_prop->amux_channel);
 	if (rc < 0) {
 		pr_err("adc-tm channel selection err\n");
 		return rc;
@@ -529,14 +659,14 @@
 	}
 
 	/* Measurement interval setup */
-	rc = qpnp_adc_tm_timer_interval_select(chan_prop->chan_prop);
+	rc = qpnp_adc_tm_timer_interval_select(btm_chan,
+						chan_prop->chan_prop);
 	if (rc < 0) {
 		pr_err("adc-tm timer select failed\n");
 		return rc;
 	}
 
 	/* Channel configuration setup */
-	btm_chan = chan_prop->chan_prop->tm_channel_select;
 	rc = qpnp_adc_tm_channel_configure(btm_chan, chan_prop->chan_prop,
 					chan_prop->amux_channel);
 	if (rc < 0) {
@@ -544,19 +674,21 @@
 		return rc;
 	}
 
-	/* Enable bank */
-	rc = qpnp_adc_tm_enable(true);
-	if (rc)
-		return rc;
-
 	/* Recurring interval measurement enable */
+	rc = qpnp_adc_tm_read_reg(QPNP_ADC_MEAS_INTERVAL_OP_CTL, &op_cntrl);
+	op_cntrl |= QPNP_ADC_MEAS_INTERVAL_OP;
 	rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_MEAS_INTERVAL_OP_CTL,
-			QPNP_ADC_MEAS_INTERVAL_OP, true);
+			op_cntrl, true);
 	if (rc < 0) {
 		pr_err("adc-tm meas interval op configure failed\n");
 		return rc;
 	}
 
+	/* Enable bank */
+	rc = qpnp_adc_tm_enable();
+	if (rc)
+		return rc;
+
 	/* Request conversion */
 	rc = qpnp_adc_tm_write_reg(QPNP_CONV_REQ, QPNP_CONV_REQ_SET);
 	if (rc < 0) {
@@ -570,12 +702,13 @@
 static int qpnp_adc_tm_get_mode(struct thermal_zone_device *thermal,
 			      enum thermal_device_mode *mode)
 {
-	struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
+	struct qpnp_adc_tm_sensor *adc_tm_sensor = thermal->devdata;
 
-	if (!adc_tm || !mode)
+	if (!adc_tm_sensor || qpnp_adc_tm_check_revision(
+			adc_tm_sensor->btm_channel_num) || !mode)
 		return -EINVAL;
 
-	*mode = adc_tm->mode;
+	*mode = adc_tm_sensor->mode;
 
 	return 0;
 }
@@ -586,12 +719,14 @@
 	struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
 	struct qpnp_adc_tm_drv *adc_drv = qpnp_adc_tm;
 	int rc = 0, channel;
+	u8 sensor_mask = 0;
 
-	if (!adc_tm)
+	if (!adc_tm || qpnp_adc_tm_check_revision(adc_tm->btm_channel_num))
 		return -EINVAL;
 
 	if (mode == THERMAL_DEVICE_ENABLED) {
-		adc_drv->adc->amux_prop->amux_channel = adc_tm->sensor_num;
+		adc_drv->adc->amux_prop->amux_channel =
+					adc_tm->vadc_channel_num;
 		channel = adc_tm->sensor_num;
 		adc_drv->adc->amux_prop->decimation =
 			adc_drv->adc->adc_channels[channel].adc_decimation;
@@ -616,17 +751,31 @@
 			return -EINVAL;
 		}
 	} else if (mode == THERMAL_DEVICE_DISABLED) {
+		sensor_mask = 1 << adc_tm->sensor_num;
+		/* Disable bank */
+		rc = qpnp_adc_tm_disable();
+		if (rc < 0) {
+			pr_err("adc-tm disable failed\n");
+			return rc;
+		}
+
+		/* Check if a conversion is in progress */
+		rc = qpnp_adc_tm_req_sts_check();
+		if (rc < 0) {
+			pr_err("adc-tm req_sts check failed\n");
+			return rc;
+		}
+
 		rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_MULTI_MEAS_EN,
-			adc_tm_data[adc_tm->btm_channel_num].multi_meas_en,
-			false);
+			sensor_mask, false);
 		if (rc < 0) {
 			pr_err("multi measurement update failed\n");
 			return rc;
 		}
 
-		rc = qpnp_adc_tm_enable(false);
+		rc = qpnp_adc_tm_enable_if_channel_meas();
 		if (rc < 0) {
-			pr_err("adc-tm disable failed\n");
+			pr_err("re-enabling measurement failed\n");
 			return rc;
 		}
 	}
@@ -641,7 +790,8 @@
 {
 	struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
 
-	if (!adc_tm || !type || type < 0)
+	if (!adc_tm || qpnp_adc_tm_check_revision(adc_tm->btm_channel_num)
+						|| !type || type < 0)
 		return -EINVAL;
 
 	switch (trip) {
@@ -669,7 +819,8 @@
 	uint16_t reg_low_thr_lsb, reg_low_thr_msb;
 	uint16_t reg_high_thr_lsb, reg_high_thr_msb;
 
-	if (!adc_tm)
+	if (!adc_tm || qpnp_adc_tm_check_revision(
+					adc_tm_sensor->btm_channel_num))
 		return -EINVAL;
 
 	btm_channel_num = adc_tm_sensor->btm_channel_num;
@@ -733,10 +884,11 @@
 	uint16_t reg_high_thr_lsb, reg_high_thr_msb;
 	int rc = 0, btm_channel_num;
 
-	if (!adc_tm)
+	if (!adc_tm || qpnp_adc_tm_check_revision(
+				adc_tm_sensor->btm_channel_num))
 		return -EINVAL;
 
-	tm_config.channel = adc_tm_sensor->sensor_num;
+	tm_config.channel = adc_tm_sensor->vadc_channel_num;
 	switch (trip) {
 	case ADC_TM_TRIP_HIGH_WARM:
 		tm_config.high_thr_temp = temp;
@@ -748,6 +900,8 @@
 		return -EINVAL;
 	}
 
+	pr_debug("requested a high - %d and low - %d with trip - %d\n",
+			tm_config.high_thr_temp, tm_config.low_thr_temp, trip);
 	rc = qpnp_adc_tm_scale_therm_voltage_pu2(&tm_config);
 	if (rc < 0) {
 		pr_err("Failed to lookup the adc-tm thresholds\n");
@@ -801,131 +955,70 @@
 	return 0;
 }
 
-static void notify_uspace_qpnp_adc_tm_fn(struct work_struct *work)
+static void notify_adc_tm_fn(struct work_struct *work)
 {
 	struct qpnp_adc_tm_sensor *adc_tm = container_of(work,
 		struct qpnp_adc_tm_sensor, work);
 
-	sysfs_notify(&adc_tm->tz_dev->device.kobj,
+	if (adc_tm->thermal_node) {
+		sysfs_notify(&adc_tm->tz_dev->device.kobj,
 					NULL, "btm");
-}
+		pr_debug("notifying uspace client\n");
+	} else {
+		if (adc_tm->btm_param->threshold_notification != NULL) {
+			if (adc_tm->low_thr_notify) {
+				pr_debug("notify kernel with low state\n");
+				adc_tm->btm_param->threshold_notification(
+				ADC_TM_LOW_STATE, adc_tm->btm_param->btm_ctx);
+				adc_tm->low_thr_notify = false;
+			}
 
-static void notify_usb_fn(struct work_struct *work)
-{
-	struct qpnp_adc_tm_drv *adc_tm = container_of(work,
-		struct qpnp_adc_tm_drv, usbid_work);
-	int rc;
-	u8 status_low, status_high;
-
-	if (adc_tm->usb_id_param->threshold_notification != NULL) {
-		rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_LOW,
-							&status_low);
-		if (rc) {
-			pr_err("adc-tm read low status failed\n");
-			return;
+			if (adc_tm->high_thr_notify) {
+				pr_debug("notify kernel with high state\n");
+				adc_tm->btm_param->threshold_notification(
+				ADC_TM_HIGH_STATE, adc_tm->btm_param->btm_ctx);
+				adc_tm->high_thr_notify = false;
+			}
 		}
-
-		rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_HIGH,
-							&status_high);
-		if (rc) {
-			pr_err("adc-tm read high status failed\n");
-			return;
-		}
-
-		if (status_low & 1)
-			adc_tm->usb_id_param->threshold_notification(
-			ADC_TM_LOW_STATE, adc_tm->usb_id_param->usbid_ctx);
-		else if (status_high & 1)
-			adc_tm->usb_id_param->threshold_notification(
-			ADC_TM_HIGH_STATE, adc_tm->usb_id_param->usbid_ctx);
 	}
 
 	return;
 }
 
-static void notify_batt_fn(struct work_struct *work)
-{
-	struct qpnp_adc_tm_drv *adc_tm = container_of(work,
-		struct qpnp_adc_tm_drv, batt_work);
-	int rc;
-	u8 status_low, status_high;
-
-	if (adc_tm->battery_param->threshold_notification != NULL) {
-		rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_LOW,
-							&status_low);
-		if (rc) {
-			pr_err("adc-tm read low status failed\n");
-			return;
-		}
-
-		rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_HIGH,
-							&status_high);
-		if (rc) {
-			pr_err("adc-tm read high status failed\n");
-			return;
-		}
-
-		if (status_low & QPNP_ADC_TM_LOW_THR_INT_EN_M1)
-			adc_tm->battery_param->threshold_notification(
-			ADC_TM_LOW_STATE, adc_tm->battery_param->btm_ctx);
-		else if (status_high & QPNP_ADC_TM_HIGH_THR_INT_EN_M1)
-			adc_tm->battery_param->threshold_notification(
-			ADC_TM_HIGH_STATE, adc_tm->battery_param->btm_ctx);
-	}
-
-	return;
-}
-
-static int qpnp_adc_tm_activate_trip_type_fn(uint32_t btm_channel_num,
-	enum thermal_trip_activation_mode mode, u8 *data, uint32_t reg)
-{
-	u8 thr_int = 0;
-	int rc = 0;
-
-	rc = qpnp_adc_tm_read_reg(reg, &thr_int);
-	if (rc) {
-		pr_err("multi meas read failed\n");
-		return rc;
-	}
-
-	thr_int = adc_tm_data[btm_channel_num].low_thr_int_chan_en;
-
-	if (mode == THERMAL_TRIP_ACTIVATION_ENABLED)
-		thr_int |= *data;
-	else
-		thr_int &= ~*data;
-
-	rc = qpnp_adc_tm_write_reg(reg, thr_int);
-	if (rc)
-		pr_err("multi meas write failed\n");
-
-	return rc;
-}
-
 static int qpnp_adc_tm_activate_trip_type(struct thermal_zone_device *thermal,
 			int trip, enum thermal_trip_activation_mode mode)
 {
 	struct qpnp_adc_tm_sensor *adc_tm = thermal->devdata;
-	int rc = 0;
+	int rc = 0, sensor_mask = 0;
 	u8 thr_int_en = 0;
+	bool state = false;
 
-	if (!adc_tm)
+	if (!adc_tm || qpnp_adc_tm_check_revision(adc_tm->btm_channel_num))
 		return -EINVAL;
 
+	if (mode == THERMAL_TRIP_ACTIVATION_ENABLED)
+		state = true;
+
+	sensor_mask = 1 << adc_tm->sensor_num;
+
+	pr_debug("Sensor number:%x with state:%d\n", adc_tm->sensor_num, state);
+
 	switch (trip) {
 	case ADC_TM_TRIP_HIGH_WARM:
+		/* low_thr (lower voltage) for higher temp */
 		thr_int_en = adc_tm_data[adc_tm->btm_channel_num].
 							low_thr_int_chan_en;
-		rc = qpnp_adc_tm_activate_trip_type_fn(adc_tm->btm_channel_num,
-				mode, &thr_int_en, QPNP_ADC_TM_LOW_THR_INT_EN);
+		rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_LOW_THR_INT_EN,
+				sensor_mask, state);
 		if (rc)
 			pr_err("channel:%x failed\n", adc_tm->btm_channel_num);
 	break;
 	case ADC_TM_TRIP_LOW_COOL:
+		/* high_thr (higher voltage) for cooler temp */
 		thr_int_en = adc_tm_data[adc_tm->btm_channel_num].
 							high_thr_int_chan_en;
-		rc = qpnp_adc_tm_activate_trip_type_fn(adc_tm->btm_channel_num,
-				mode, &thr_int_en, QPNP_ADC_TM_HIGH_THR_INT_EN);
+		rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_HIGH_THR_INT_EN,
+				sensor_mask, state);
 		if (rc)
 			pr_err("channel:%x failed\n", adc_tm->btm_channel_num);
 	break;
@@ -941,12 +1034,20 @@
 	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
 	u8 status_low = 0, status_high = 0, qpnp_adc_tm_meas_en = 0;
 	u8 adc_tm_low_enable = 0, adc_tm_high_enable = 0;
-	u8 thr_int_disable = 0;
-	int rc = 0, sensor_notify_num = 0;
+	u8 sensor_mask = 0;
+	int rc = 0, sensor_notify_num = 0, i = 0, sensor_num = 0, btm_chan_num;
 
 	if (!adc_tm || !adc_tm->adc_tm_initialized)
 		return -ENODEV;
 
+	mutex_lock(&adc_tm->adc->adc_lock);
+
+	rc = qpnp_adc_tm_req_sts_check();
+	if (rc) {
+		pr_err("adc-tm-tm req sts check failed with %d\n", rc);
+		goto fail;
+	}
+
 	rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_LOW, &status_low);
 	if (rc) {
 		pr_err("adc-tm-tm read status low failed with %d\n", rc);
@@ -972,100 +1073,100 @@
 	adc_tm_high_enable = qpnp_adc_tm_meas_en & status_high;
 
 	if (adc_tm_high_enable) {
-		sensor_notify_num = (adc_tm_high_enable >> 3);
-		switch (adc_tm_high_enable) {
-		case 1:
-		case 2:
-		{
-			if (adc_tm_high_enable == 1)
-				thr_int_disable =
-					QPNP_ADC_TM_HIGH_THR_INT_EN_M0;
-			else if (adc_tm_high_enable == 2)
-				thr_int_disable =
-					QPNP_ADC_TM_HIGH_THR_INT_EN_M1;
+		sensor_notify_num = adc_tm_high_enable;
+		while (i < adc_tm->max_channels_available) {
+			if ((sensor_notify_num & 0x1) == 1)
+				sensor_num = i;
+			sensor_notify_num >>= 1;
+			i++;
+		}
 
+		btm_chan_num = adc_tm->sensor[sensor_num].btm_channel_num;
+		pr_debug("high:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
+			sensor_num, adc_tm_high_enable, adc_tm_low_enable,
+			qpnp_adc_tm_meas_en);
+		if (!adc_tm->sensor[sensor_num].thermal_node) {
+			/* For non thermal registered clients
+				such as usb_id, vbatt, pmic_therm */
+			sensor_mask = 1 << sensor_num;
+			pr_debug("non thermal node - mask:%x\n", sensor_mask);
 			rc = qpnp_adc_tm_meas_int_update(
 				QPNP_ADC_TM_HIGH_THR_INT_EN,
-				thr_int_disable, false);
+				sensor_mask, false);
 			if (rc < 0) {
 				pr_err("high threshold int read failed\n");
 				goto fail;
 			}
-
-			if (adc_tm_high_enable == 1)
-				schedule_work(&adc_tm->usbid_work);
-			else if (adc_tm_high_enable == 2)
-				schedule_work(&adc_tm->batt_work);
-		}
-		break;
-		case 4:
-		case 8:
-		case 16:
-		{
-			/* High voltage threshold is triggered by low temp */
+			adc_tm->sensor[sensor_num].high_thr_notify = true;
+		} else {
+			/* Uses the thermal sysfs registered device to disable
+				the corresponding high voltage threshold which
+				 is triggered by low temp */
+			pr_debug("thermal node with mask:%x\n", sensor_mask);
 			rc = qpnp_adc_tm_activate_trip_type(
-				adc_tm->sensor[sensor_notify_num].tz_dev,
+				adc_tm->sensor[sensor_num].tz_dev,
 				ADC_TM_TRIP_LOW_COOL,
 				THERMAL_TRIP_ACTIVATION_DISABLED);
 			if (rc < 0) {
-				pr_err("notify error:%d\n", sensor_notify_num);
+				pr_err("notify error:%d\n", sensor_num);
 				goto fail;
 			}
-			schedule_work(&adc_tm->sensor[sensor_notify_num].work);
-		}
-		break;
-		default:
-			rc = -EINVAL;
 		}
 	}
 
 	if (adc_tm_low_enable) {
-		sensor_notify_num = (adc_tm_low_enable >> 3);
-		switch (adc_tm_low_enable) {
-		case 1:
-		case 2:
-		{
-			if (adc_tm_low_enable == 1)
-				thr_int_disable = QPNP_ADC_TM_LOW_THR_INT_EN_M0;
-			else if (adc_tm_low_enable == 2)
-				thr_int_disable = QPNP_ADC_TM_LOW_THR_INT_EN_M1;
+		sensor_notify_num = adc_tm_low_enable;
+		i = 0;
+		while (i < adc_tm->max_channels_available) {
+			if ((sensor_notify_num & 0x1) == 1)
+				sensor_num = i;
+			sensor_notify_num >>= 1;
+			i++;
+		}
 
+		btm_chan_num = adc_tm->sensor[sensor_num].btm_channel_num;
+		pr_debug("low:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
+			sensor_num, adc_tm_high_enable, adc_tm_low_enable,
+			qpnp_adc_tm_meas_en);
+		if (!adc_tm->sensor[sensor_num].thermal_node) {
+			/* For non thermal registered clients
+				such as usb_id, vbatt, pmic_therm */
+			pr_debug("non thermal node - mask:%x\n", sensor_mask);
+			sensor_mask = 1 << sensor_num;
 			rc = qpnp_adc_tm_meas_int_update(
 				QPNP_ADC_TM_LOW_THR_INT_EN,
-				thr_int_disable, false);
+				sensor_mask, false);
 			if (rc < 0) {
-				pr_err("low threshold int disable failed\n");
+				pr_err("low threshold int read failed\n");
 				goto fail;
 			}
-
-			if (adc_tm_low_enable == 1)
-				schedule_work(&adc_tm->usbid_work);
-			else if (adc_tm_low_enable == 2)
-				schedule_work(&adc_tm->batt_work);
-		}
-		break;
-		case 4:
-		case 8:
-		case 16:
-		{
-			/* Low voltage threshold is triggered by high temp */
+			adc_tm->sensor[sensor_num].low_thr_notify = true;
+		} else {
+			/* Uses the thermal sysfs registered device to disable
+				the corresponding low voltage threshold which
+				 is triggered by high temp */
+			pr_debug("thermal node with mask:%x\n", sensor_mask);
 			rc = qpnp_adc_tm_activate_trip_type(
-				adc_tm->sensor[sensor_notify_num].tz_dev,
+				adc_tm->sensor[sensor_num].tz_dev,
 				ADC_TM_TRIP_HIGH_WARM,
 				THERMAL_TRIP_ACTIVATION_DISABLED);
 			if (rc < 0) {
-				pr_err("notify error:%d\n", sensor_notify_num);
+				pr_err("notify error:%d\n", sensor_num);
 				goto fail;
 			}
-			schedule_work(&adc_tm->sensor[sensor_notify_num].work);
-		}
-		break;
-		default:
-			rc = -EINVAL;
 		}
 	}
 
+	rc = qpnp_adc_tm_enable_if_channel_meas();
+	if (rc < 0) {
+		pr_err("re-enabling measurement failed\n");
+		return rc;
+	}
 fail:
+	mutex_unlock(&adc_tm->adc->adc_lock);
+
+	schedule_work(&adc_tm->sensor[sensor_num].work);
+
 	return rc;
 }
 
@@ -1074,6 +1175,8 @@
 	int rc;
 
 	rc = qpnp_adc_tm_read_status();
+	if (rc < 0)
+		pr_err("adc-tm high thr work failed\n");
 
 	return;
 }
@@ -1082,6 +1185,8 @@
 
 static irqreturn_t qpnp_adc_tm_high_thr_isr(int irq, void *data)
 {
+	qpnp_adc_tm_disable();
+
 	schedule_work(&trigger_completion_adc_tm_high_thr_work);
 
 	return IRQ_HANDLED;
@@ -1092,6 +1197,8 @@
 	int rc;
 
 	rc = qpnp_adc_tm_read_status();
+	if (rc < 0)
+		pr_err("adc-tm low thr work failed\n");
 
 	return;
 }
@@ -1099,6 +1206,8 @@
 
 static irqreturn_t qpnp_adc_tm_low_thr_isr(int irq, void *data)
 {
+	qpnp_adc_tm_disable();
+
 	schedule_work(&trigger_completion_adc_tm_low_thr_work);
 
 	return IRQ_HANDLED;
@@ -1120,7 +1229,7 @@
 	struct qpnp_vadc_result result;
 	int rc = 0;
 
-	rc = qpnp_vadc_read(adc_tm_sensor->sensor_num, &result);
+	rc = qpnp_vadc_read(adc_tm_sensor->vadc_channel_num, &result);
 	if (rc)
 		return rc;
 
@@ -1139,24 +1248,47 @@
 	.set_trip_temp = qpnp_adc_tm_set_trip_temp,
 };
 
-int32_t qpnp_adc_tm_usbid_configure(struct qpnp_adc_tm_usbid_param *param)
+int32_t qpnp_adc_tm_channel_measure(struct qpnp_adc_tm_btm_param *param)
 {
 	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
-	uint32_t channel;
+	uint32_t channel, dt_index = 0, scale_type = 0;
 	int rc = 0;
 
 	if (!adc_tm || !adc_tm->adc_tm_initialized)
 		return -ENODEV;
 
 	if (param->threshold_notification == NULL) {
-		pr_err("No USB_ID high/low voltage notificaton??\n");
+		pr_err("No notification for high/low temp??\n");
 		return -EINVAL;
 	}
 
 	mutex_lock(&adc_tm->adc->adc_lock);
 
-	adc_tm->adc->amux_prop->amux_channel = LR_MUX10_PU2_AMUX_USB_ID_LV;
-	channel = LR_MUX10_PU2_AMUX_USB_ID_LV;
+	channel = param->channel;
+	while ((adc_tm->adc->adc_channels[dt_index].channel_num
+		!= channel) && (dt_index < adc_tm->max_channels_available))
+		dt_index++;
+
+	if (dt_index >= adc_tm->max_channels_available) {
+		pr_err("not a valid ADC_TM channel\n");
+		rc = -EINVAL;
+		goto fail_unlock;
+	}
+
+	rc = qpnp_adc_tm_check_revision(
+			adc_tm->sensor[dt_index].btm_channel_num);
+	if (rc < 0)
+		goto fail_unlock;
+
+	scale_type = adc_tm->adc->adc_channels[dt_index].adc_scale_fn;
+	if (scale_type >= SCALE_RSCALE_NONE) {
+		rc = -EBADF;
+		goto fail_unlock;
+	}
+
+	pr_debug("channel:%d, scale_type:%d, dt_idx:%d",
+					channel, scale_type, dt_index);
+	adc_tm->adc->amux_prop->amux_channel = channel;
 	adc_tm->adc->amux_prop->decimation =
 			adc_tm->adc->adc_channels[channel].adc_decimation;
 	adc_tm->adc->amux_prop->hw_settle_time =
@@ -1167,10 +1299,11 @@
 		ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
 	adc_tm->adc->amux_prop->chan_prop->meas_interval1 =
 						ADC_MEAS1_INTERVAL_1S;
-	qpnp_adc_usb_scaler(param, &adc_tm->adc->amux_prop->chan_prop->low_thr,
+	adc_tm_rscale_fn[scale_type].chan(param,
+			&adc_tm->adc->amux_prop->chan_prop->low_thr,
 			&adc_tm->adc->amux_prop->chan_prop->high_thr);
 	adc_tm->adc->amux_prop->chan_prop->tm_channel_select =
-					QPNP_ADC_TM_M0_ADC_CH_SEL_CTL;
+				adc_tm->sensor[dt_index].btm_channel_num;
 	adc_tm->adc->amux_prop->chan_prop->timer_select =
 					ADC_MEAS_TIMER_SELECT1;
 	adc_tm->adc->amux_prop->chan_prop->state_request =
@@ -1181,144 +1314,102 @@
 		goto fail_unlock;
 	}
 
-	adc_tm->usb_id_param = param;
+	adc_tm->sensor[dt_index].btm_param = param;
 
 fail_unlock:
 	mutex_unlock(&adc_tm->adc->adc_lock);
 
 	return rc;
 }
-EXPORT_SYMBOL(qpnp_adc_tm_usbid_configure);
+EXPORT_SYMBOL(qpnp_adc_tm_channel_measure);
 
-static int32_t qpnp_adc_tm_chan_usbid_chan_btm_end(
-				uint32_t btm_chan_num)
+int32_t qpnp_adc_tm_disable_chan_meas(struct qpnp_adc_tm_btm_param *param)
 {
-	int32_t rc = 0;
+	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
+	uint32_t channel, dt_index = 0, btm_chan_num;
+	u8 sensor_mask = 0;
+	int rc = 0;
+
+	if (!adc_tm || !adc_tm->adc_tm_initialized)
+		return -ENODEV;
+
+	mutex_lock(&adc_tm->adc->adc_lock);
+
+	/* Disable bank */
+	rc = qpnp_adc_tm_disable();
+	if (rc < 0) {
+		pr_err("adc-tm disable failed\n");
+		goto fail;
+	}
+
+	/* Check if a conversion is in progress */
+	rc = qpnp_adc_tm_req_sts_check();
+	if (rc < 0) {
+		pr_err("adc-tm req_sts check failed\n");
+		goto fail;
+	}
+
+	channel = param->channel;
+	while ((adc_tm->adc->adc_channels[dt_index].channel_num
+		!= channel) && (dt_index < adc_tm->max_channels_available))
+		dt_index++;
+
+	if (dt_index >= adc_tm->max_channels_available) {
+		pr_err("not a valid ADC_TMN channel\n");
+		rc = -EINVAL;
+		goto fail;
+	}
+
+	btm_chan_num = adc_tm->sensor[dt_index].btm_channel_num;
+	sensor_mask = 1 << adc_tm->sensor[dt_index].sensor_num;
 
 	rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_LOW_THR_INT_EN,
-		adc_tm_data[btm_chan_num].low_thr_int_chan_en,
-		false);
+		sensor_mask, false);
 	if (rc < 0) {
 		pr_err("low threshold int write failed\n");
-		return rc;
+		goto fail;
 	}
 
 	rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_HIGH_THR_INT_EN,
-		adc_tm_data[btm_chan_num].high_thr_int_chan_en,
-		false);
+		sensor_mask, false);
 	if (rc < 0) {
 		pr_err("high threshold int enable failed\n");
-		return rc;
+		goto fail;
 	}
 
 	rc = qpnp_adc_tm_meas_int_update(QPNP_ADC_TM_MULTI_MEAS_EN,
-		adc_tm_data[btm_chan_num].multi_meas_en,
-		false);
+		sensor_mask, false);
 	if (rc < 0) {
 		pr_err("multi measurement en failed\n");
-		return rc;
+		goto fail;
 	}
 
-	rc = qpnp_adc_tm_enable(false);
+	rc = qpnp_adc_tm_enable_if_channel_meas();
 	if (rc < 0)
-		pr_err("TM disable failed\n");
+		pr_err("re-enabling measurement failed\n");
+
+fail:
+	mutex_unlock(&adc_tm->adc->adc_lock);
 
 	return rc;
 }
+EXPORT_SYMBOL(qpnp_adc_tm_disable_chan_meas);
+
+int32_t qpnp_adc_tm_usbid_configure(struct qpnp_adc_tm_btm_param *param)
+{
+	param->channel = LR_MUX10_PU2_AMUX_USB_ID_LV;
+	return qpnp_adc_tm_channel_measure(param);
+}
+EXPORT_SYMBOL(qpnp_adc_tm_usbid_configure);
 
 int32_t qpnp_adc_tm_usbid_end(void)
 {
-	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
-	int rc = 0;
+	struct qpnp_adc_tm_btm_param param;
 
-	if (!adc_tm || !adc_tm->adc_tm_initialized)
-		return -ENODEV;
-
-	mutex_lock(&adc_tm->adc->adc_lock);
-
-	rc = qpnp_adc_tm_chan_usbid_chan_btm_end(
-				QPNP_ADC_TM_M0_ADC_CH_SEL_CTL);
-	if (rc < 0)
-		pr_err("disabling thresholds for usb channel failed\n");
-
-	mutex_unlock(&adc_tm->adc->adc_lock);
-
-	return rc;
+	return qpnp_adc_tm_disable_chan_meas(&param);
 }
 EXPORT_SYMBOL(qpnp_adc_tm_usbid_end);
 
-int32_t qpnp_adc_tm_btm_configure(struct qpnp_adc_tm_btm_param *param)
-{
-	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
-	uint32_t channel;
-	int rc = 0;
-
-	if (!adc_tm || !adc_tm->adc_tm_initialized)
-		return -ENODEV;
-
-	if (param->threshold_notification == NULL) {
-		pr_err("No battery high/low temp notificaton??\n");
-		return -EINVAL;
-	}
-
-	mutex_lock(&adc_tm->adc->adc_lock);
-
-	adc_tm->adc->amux_prop->amux_channel = LR_MUX1_BATT_THERM;
-	channel = LR_MUX1_BATT_THERM;
-	adc_tm->adc->amux_prop->decimation =
-			adc_tm->adc->adc_channels[channel].adc_decimation;
-	adc_tm->adc->amux_prop->hw_settle_time =
-			adc_tm->adc->adc_channels[channel].hw_settle_time;
-	adc_tm->adc->amux_prop->fast_avg_setup =
-			adc_tm->adc->adc_channels[channel].fast_avg_setup;
-	adc_tm->adc->amux_prop->mode_sel =
-		ADC_OP_MEASUREMENT_INTERVAL << QPNP_OP_MODE_SHIFT;
-	adc_tm->adc->amux_prop->chan_prop->meas_interval2 =
-						ADC_MEAS2_INTERVAL_1S;
-	qpnp_adc_btm_scaler(param, &adc_tm->adc->amux_prop->chan_prop->low_thr,
-			&adc_tm->adc->amux_prop->chan_prop->high_thr);
-	adc_tm->adc->amux_prop->chan_prop->tm_channel_select =
-					QPNP_ADC_TM_M1_ADC_CH_SEL_CTL;
-	adc_tm->adc->amux_prop->chan_prop->timer_select =
-					ADC_MEAS_TIMER_SELECT2;
-	adc_tm->adc->amux_prop->chan_prop->state_request =
-					param->state_request;
-	rc = qpnp_adc_tm_configure(adc_tm->adc->amux_prop);
-	if (rc) {
-		pr_err("adc-tm configure failed with %d\n", rc);
-		goto fail_unlock;
-	}
-
-	adc_tm->battery_param = param;
-
-fail_unlock:
-	mutex_unlock(&adc_tm->adc->adc_lock);
-
-	return rc;
-}
-EXPORT_SYMBOL(qpnp_adc_tm_btm_configure);
-
-int32_t qpnp_adc_tm_btm_end(void)
-{
-	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
-	int rc = 0;
-
-	if (!adc_tm || !adc_tm->adc_tm_initialized)
-		return -ENODEV;
-
-	mutex_lock(&adc_tm->adc->adc_lock);
-
-	rc = qpnp_adc_tm_chan_usbid_chan_btm_end(
-				QPNP_ADC_TM_M1_ADC_CH_SEL_CTL);
-	if (rc < 0)
-		pr_err("disabling thresholds for batt channel failed\n");
-
-	mutex_unlock(&adc_tm->adc->adc_lock);
-
-	return rc;
-}
-EXPORT_SYMBOL(qpnp_adc_tm_btm_end);
-
 int32_t qpnp_adc_tm_is_ready(void)
 {
 	struct qpnp_adc_tm_drv *adc_tm = qpnp_adc_tm;
@@ -1335,7 +1426,7 @@
 	struct device_node *node = spmi->dev.of_node, *child;
 	struct qpnp_adc_tm_drv *adc_tm;
 	struct qpnp_adc_drv *adc_qpnp;
-	int32_t count_adc_channel_list = 0, rc, i = 0, j = 0;
+	int32_t count_adc_channel_list = 0, rc, sen_idx = 0;
 	u8 thr_init = 0;
 
 	if (!node)
@@ -1363,6 +1454,7 @@
 		return -ENOMEM;
 	}
 
+	qpnp_adc_tm = adc_tm;
 	adc_qpnp = devm_kzalloc(&spmi->dev, sizeof(struct qpnp_adc_drv),
 			GFP_KERNEL);
 	if (!adc_qpnp) {
@@ -1430,41 +1522,43 @@
 	for_each_child_of_node(node, child) {
 		char name[25];
 		int btm_channel_num;
+		bool thermal_node = false;
+
 		rc = of_property_read_u32(child,
 				"qcom,btm-channel-number", &btm_channel_num);
 		if (rc) {
 			pr_err("Invalid btm channel number\n");
 			goto fail;
 		}
-
-		if ((btm_channel_num != QPNP_ADC_TM_M0_ADC_CH_SEL_CTL) &&
-			(btm_channel_num != QPNP_ADC_TM_M1_ADC_CH_SEL_CTL)) {
+		adc_tm->sensor[sen_idx].btm_channel_num = btm_channel_num;
+		adc_tm->sensor[sen_idx].vadc_channel_num =
+				adc_tm->adc->adc_channels[sen_idx].channel_num;
+		adc_tm->sensor[sen_idx].sensor_num = sen_idx;
+		if (thermal_node) {
 			/* Register with the thermal zone */
-			adc_tm->sensor[i].mode = THERMAL_DEVICE_DISABLED;
-			snprintf(name, sizeof(name), "qpnp_adc_tm_sensor%d", i);
-			adc_tm->sensor[i].sensor_num =
-				adc_tm->adc->adc_channels[j].channel_num;
-			adc_tm->sensor[i].btm_channel_num = btm_channel_num;
-			adc_tm->sensor[i].meas_interval =
+			pr_debug("thermal node%x\n", btm_channel_num);
+			adc_tm->sensor[sen_idx].mode = THERMAL_DEVICE_DISABLED;
+			adc_tm->sensor[sen_idx].thermal_node = true;
+			snprintf(name, sizeof(name),
+				adc_tm->adc->adc_channels[sen_idx].name);
+			adc_tm->sensor[sen_idx].meas_interval =
 				QPNP_ADC_TM_MEAS_INTERVAL;
-			adc_tm->sensor[i].low_thr = QPNP_ADC_TM_M0_LOW_THR;
-			adc_tm->sensor[i].high_thr = QPNP_ADC_TM_M0_HIGH_THR;
-			adc_tm->sensor[i].tz_dev =
+			adc_tm->sensor[sen_idx].low_thr =
+						QPNP_ADC_TM_M0_LOW_THR;
+			adc_tm->sensor[sen_idx].high_thr =
+						QPNP_ADC_TM_M0_HIGH_THR;
+			adc_tm->sensor[sen_idx].tz_dev =
 				thermal_zone_device_register(name,
 				ADC_TM_TRIP_NUM,
-				&adc_tm->sensor[i],
+				&adc_tm->sensor[sen_idx],
 				&qpnp_adc_tm_thermal_ops, 0, 0, 0, 0);
-			if (IS_ERR(adc_tm->sensor[i].tz_dev))
+			if (IS_ERR(adc_tm->sensor[sen_idx].tz_dev))
 				pr_err("thermal device register failed.\n");
-				INIT_WORK(&adc_tm->sensor[i].work,
-					notify_uspace_qpnp_adc_tm_fn);
-			i++;
 		}
-		j++;
+		INIT_WORK(&adc_tm->sensor[sen_idx].work, notify_adc_tm_fn);
+		sen_idx++;
 	}
-	INIT_WORK(&adc_tm->usbid_work, notify_usb_fn);
-	INIT_WORK(&adc_tm->batt_work, notify_batt_fn);
-	qpnp_adc_tm = adc_tm;
+	adc_tm->max_channels_available = count_adc_channel_list;
 	dev_set_drvdata(&spmi->dev, adc_tm);
 	rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_HIGH_THR_INT_EN, thr_init);
 	if (rc < 0) {
@@ -1486,6 +1580,7 @@
 
 	adc_tm->adc_tm_initialized = true;
 
+	pr_debug("OK\n");
 	return 0;
 fail:
 	qpnp_adc_tm = NULL;
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 4710110..64ef2db 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -188,7 +188,7 @@
 	enum usb_chg_state	chg_state;
 	int			pmic_id_irq;
 	struct work_struct	id_work;
-	struct qpnp_adc_tm_usbid_param	adc_param;
+	struct qpnp_adc_tm_btm_param	adc_param;
 	struct delayed_work	init_adc_work;
 	bool			id_adc_detect;
 	u8			dcd_retries;
@@ -2159,7 +2159,7 @@
 	mdwc->adc_param.high_thr = adc_high_threshold;
 	mdwc->adc_param.timer_interval = adc_meas_interval;
 	mdwc->adc_param.state_request = ADC_TM_HIGH_LOW_THR_ENABLE;
-	mdwc->adc_param.usbid_ctx = mdwc;
+	mdwc->adc_param.btm_ctx = mdwc;
 	mdwc->adc_param.threshold_notification = dwc3_adc_notification;
 
 	ret = qpnp_adc_tm_usbid_configure(&mdwc->adc_param);
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index 05d75ce..a853aff 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -195,7 +195,7 @@
 };
 
 /**
- * enum qpnp_adc_scale_fn_type - Scaling function for pm8921 pre calibrated
+ * enum qpnp_adc_scale_fn_type - Scaling function for pm8941 pre calibrated
  *				   digital data relative to ADC reference.
  * %ADC_SCALE_DEFAULT: Default scaling to convert raw adc code to voltage.
  * %ADC_SCALE_BATT_THERM: Conversion to temperature based on btm parameters.
@@ -217,6 +217,26 @@
 	SCALE_NONE,
 };
 
+
+/**
+ * enum qpnp_adc_tm_rscale_fn_type - Scaling function used to convert the
+ *	channels input voltage/temperature to corresponding ADC code that is
+ *	applied for thresholds. Check the corresponding channels scaling to
+ *	determine the appropriate temperature/voltage units that are passed
+ *	to the scaling function. Example battery follows the power supply
+ *	framework that needs its units to be in decidegreesC so it passes
+ *	deci-degreesC. PA_THERM clients pass the temperature in degrees.
+ *	The order below should match the one in the driver for
+ *	adc_tm_rscale_fn[].
+ */
+enum qpnp_adc_tm_rscale_fn_type {
+	SCALE_R_VBATT = 0,
+	SCALE_RBATT_THERM,
+	SCALE_R_USB_ID,
+	SCALE_RPMIC_THERM,
+	SCALE_RSCALE_NONE,
+};
+
 /**
  * enum qpnp_adc_fast_avg_ctl - Provides ability to obtain single result
  *		from the ADC that is an average of multiple measurement
@@ -560,16 +580,11 @@
 };
 
 /**
- * Channel selection registers for each of the 5 configurable measurements
- * Channels allotment is fixed for the given channels below.
- * The USB_ID and BATT_THERM channels are used only by the kernel space
- * USB and Battery drivers.
+ * Channel selection registers for each of the configurable measurements
+ * Channels allotment is set at device config for a channel.
+ * The USB_ID, BATT_THERM, PMIC_THERM and VBAT channels are used by the
+ * kernel space USB, Battery and IADC drivers.
  * The other 3 channels are configurable for use by userspace clients.
- * USB_ID uses QPNP_ADC_TM_M0_ADC_CH_SEL_CTL
- * BATT_TEMP uses QPNP_ADC_TM_M1_ADC_CH_SEL_CTL
- * PA_THERM1 uses QPNP_ADC_TM_M2_ADC_CH_SEL_CTL
- * PA_THERM2 uses QPNP_ADC_TM_M3_ADC_CH_SEL_CTL
- * EMMC_THERM uses QPNP_ADC_TM_M4_ADC_CH_SEL_CTL
  */
 enum qpnp_adc_tm_channel_select	{
 	QPNP_ADC_TM_M0_ADC_CH_SEL_CTL = 0x48,
@@ -577,6 +592,9 @@
 	QPNP_ADC_TM_M2_ADC_CH_SEL_CTL = 0x70,
 	QPNP_ADC_TM_M3_ADC_CH_SEL_CTL = 0x78,
 	QPNP_ADC_TM_M4_ADC_CH_SEL_CTL = 0x80,
+	QPNP_ADC_TM_M5_ADC_CH_SEL_CTL = 0x88,
+	QPNP_ADC_TM_M6_ADC_CH_SEL_CTL = 0x90,
+	QPNP_ADC_TM_M7_ADC_CH_SEL_CTL = 0x98,
 	QPNP_ADC_TM_CH_SELECT_NONE
 };
 
@@ -652,42 +670,37 @@
 };
 
 /**
- * struct qpnp_adc_tm_usbid_param - Represent USB_ID threshold
- *				monitoring configuration.
- * @high_thr: High voltage threshold for which notification is requested.
- * @low_thr: Low voltage threshold for which notification is requested.
- * @state_request: Enable/disable the corresponding high and low voltage
- *		thresholds.
- * @timer_interval: Select polling rate from qpnp_adc_meas_timer_1 type.
- * @threshold_notification: Notification callback once threshold are crossed.
- * @usbid_ctx: A context of void type.
- */
-struct qpnp_adc_tm_usbid_param {
-	int32_t					high_thr;
-	int32_t					low_thr;
-	enum qpnp_state_request			state_request;
-	enum qpnp_adc_meas_timer_1		timer_interval;
-	void					*usbid_ctx;
-	void	(*threshold_notification) (enum qpnp_tm_state state,
-				void *ctx);
-};
-
-/**
  * struct qpnp_adc_tm_btm_param - Represent Battery temperature threshold
  *				monitoring configuration.
  * @high_temp: High temperature threshold for which notification is requested.
  * @low_temp: Low temperature threshold for which notification is requested.
+ * @high_thr_voltage: High voltage for which notification is requested.
+ * @low_thr_voltage: Low voltage for which notification is requested.
  * @state_request: Enable/disable the corresponding high and low temperature
  *		thresholds.
- * @timer_interval: Select polling rate from qpnp_adc_meas_timer_2 type.
+ * @timer_interval1: Select polling rate from qpnp_adc_meas_timer_1 type.
+ * @timer_interval2: Select polling rate from qpnp_adc_meas_timer_2 type.
+ * @timer_interval3: Select polling rate from qpnp_adc_meas_timer_3 type.
  * @btmid_ctx: A context of void type.
  * @threshold_notification: Notification callback once threshold are crossed.
+ * units to be used for High/Low temperature and voltage notification -
+ * This depends on the clients usage. Check the rscaling function
+ * for the appropriate channel nodes.
+ * @Batt therm clients temperature units is decidegreesCentigrate.
+ * @USB_ID inputs the voltage units in milli-volts.
+ * @PA_THERM inputs the units in degC.
+ * @PMIC_THERM inputs the units in millidegC.
  */
 struct qpnp_adc_tm_btm_param {
 	int32_t					high_temp;
 	int32_t					low_temp;
+	int32_t					high_thr;
+	int32_t					low_thr;
+	enum qpnp_vadc_channels			channel;
 	enum qpnp_state_request			state_request;
-	enum qpnp_adc_meas_timer_2		timer_interval;
+	enum qpnp_adc_meas_timer_1		timer_interval;
+	enum qpnp_adc_meas_timer_2		timer_interval2;
+	enum qpnp_adc_meas_timer_3		timer_interval3;
 	void					*btm_ctx;
 	void	(*threshold_notification) (enum qpnp_tm_state state,
 						void *ctx);
@@ -841,6 +854,17 @@
 };
 
 /**
+ * struct qpnp_adc_tm_reverse_scale_fn - Reverse scaling prototype
+ * @chan: Function pointer to one of the scaling functions
+ *	which takes the adc properties, channel properties,
+ *	and returns the physical result
+ */
+struct qpnp_adc_tm_reverse_scale_fn {
+	int32_t (*chan) (struct qpnp_adc_tm_btm_param *,
+		uint32_t *, uint32_t *);
+};
+
+/**
  * struct qpnp_iadc_calib - IADC channel calibration structure.
  * @channel - Channel for which the historical offset and gain is
  *	      calculated. Available channels are internal rsense,
@@ -1107,6 +1131,21 @@
 int32_t qpnp_get_vadc_gain_and_offset(struct qpnp_vadc_linear_graph *param,
 			enum qpnp_adc_calib_type calib_type);
 /**
+ * qpnp_adc_scale_millidegc_pmic_voltage_thr() - Performs reverse calibration
+ *		on the low/high temperature threshold values passed by the
+ *		client. The function coverts milldegC to voltage threshold
+ *		and accounts for the corresponding channels scaling as (2mV/K).
+ * @param:	The input parameters that contain the low/high temperature
+ *		values.
+ * @low_threshold: The low threshold value that needs to be updated with
+ *		the above calibrated voltage value.
+ * @high_threshold: The low threshold value that needs to be updated with
+ *		the above calibrated voltage value.
+ */
+int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(
+		struct qpnp_adc_tm_btm_param *param,
+		uint32_t *low_threshold, uint32_t *high_threshold);
+/**
  * qpnp_adc_btm_scaler() - Performs reverse calibration on the low/high
  *		temperature threshold values passed by the client.
  *		The function maps the temperature to voltage and applies
@@ -1147,7 +1186,21 @@
  * @high_threshold: The low threshold value that needs to be updated with
  *		the above calibrated voltage value.
  */
-int32_t qpnp_adc_usb_scaler(struct qpnp_adc_tm_usbid_param *param,
+int32_t qpnp_adc_usb_scaler(struct qpnp_adc_tm_btm_param *param,
+		uint32_t *low_threshold, uint32_t *high_threshold);
+/**
+ * qpnp_adc_vbatt_rscaler() - Performs reverse calibration on the low/high
+ *		voltage threshold values passed by the client.
+ *		The function applies ratiometric calibration on the
+ *		voltage values.
+ * @param:	The input parameters that contain the low/high voltage
+ *		threshold values.
+ * @low_threshold: The low threshold value that needs to be updated with
+ *		the above calibrated voltage value.
+ * @high_threshold: The low threshold value that needs to be updated with
+ *		the above calibrated voltage value.
+ */
+int32_t qpnp_adc_vbatt_rscaler(struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold);
 /**
  * qpnp_vadc_iadc_sync_request() - Performs Voltage ADC read and
@@ -1217,13 +1270,21 @@
 			enum qpnp_adc_calib_type calib_type)
 { return -ENXIO; }
 static inline int32_t qpnp_adc_usb_scaler(
-		struct qpnp_adc_tm_usbid_param *param,
+		struct qpnp_adc_tm_btm_param *param,
+		uint32_t *low_threshold, uint32_t *high_threshold)
+{ return -ENXIO; }
+static inline int32_t qpnp_adc_vbatt_rscaler(
+		struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold)
 { return -ENXIO; }
 static inline int32_t qpnp_adc_btm_scaler(
 		struct qpnp_adc_tm_btm_param *param,
 		uint32_t *low_threshold, uint32_t *high_threshold)
 { return -ENXIO; }
+static inline int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(
+		struct qpnp_adc_tm_btm_param *param,
+		uint32_t *low_threshold, uint32_t *high_threshold)
+{ return -ENXIO; }
 static inline int32_t qpnp_adc_tm_scale_therm_voltage_pu2(
 				struct qpnp_adc_tm_config *param)
 { return -ENXIO; }
@@ -1314,7 +1375,7 @@
  *		Clients pass the low/high voltage along with the threshold
  *		notification callback.
  */
-int32_t qpnp_adc_tm_usbid_configure(struct qpnp_adc_tm_usbid_param *param);
+int32_t qpnp_adc_tm_usbid_configure(struct qpnp_adc_tm_btm_param *param);
 /**
  * qpnp_adc_tm_usbid_end() - Disables the monitoring of channel 0 thats
  *		assigned for monitoring USB_ID. Disables the low/high
@@ -1323,23 +1384,25 @@
  */
 int32_t qpnp_adc_tm_usbid_end(void);
 /**
- * qpnp_adc_tm_usbid_configure() - Configures Channel 1 of VADC_BTM to
- *		monitor batt_therm channel using 100k internal pull-up.
- *		Battery driver passes the high/low voltage threshold along
+ * qpnp_adc_tm_channel_measure() - Configures kernel clients a channel to
+ *		monitor the corresponding ADC channel for threshold detection.
+ *		Driver passes the high/low voltage threshold along
  *		with the notification callback once the set thresholds
  *		are crossed.
  * @param:	Structure pointer of qpnp_adc_tm_btm_param type.
  *		Clients pass the low/high temperature along with the threshold
  *		notification callback.
  */
-int32_t qpnp_adc_tm_btm_configure(struct qpnp_adc_tm_btm_param *param);
+int32_t qpnp_adc_tm_channel_measure(struct qpnp_adc_tm_btm_param *param);
 /**
- * qpnp_adc_tm_btm_end() - Disables the monitoring of channel 1 thats
- *		assigned for monitoring batt_therm. Disables the low/high
- *		threshold activation for channel 1 as well.
- * @param:	none.
+ * qpnp_adc_tm_disable_chan_meas() - Disables the monitoring of channel thats
+ *		assigned for monitoring kernel clients. Disables the low/high
+ *		threshold activation for the corresponding channel.
+ * @param:	Structure pointer of qpnp_adc_tm_btm_param type.
+ *		This is used to identify the channel for which the corresponding
+ *		channels high/low threshold notification will be disabled.
  */
-int32_t qpnp_adc_tm_btm_end(void);
+int32_t qpnp_adc_tm_disable_chan_meas(struct qpnp_adc_tm_btm_param *param);
 /**
  * qpnp_adc_tm_is_ready() - Clients can use this API to check if the
  *			  device is ready to use.
@@ -1349,14 +1412,14 @@
 int32_t	qpnp_adc_tm_is_ready(void);
 #else
 static inline int32_t qpnp_adc_tm_usbid_configure(
-			struct qpnp_adc_tm_usbid_param *param)
+			struct qpnp_adc_tm_btm_param *param)
 { return -ENXIO; }
 static inline int32_t qpnp_adc_tm_usbid_end(void)
 { return -ENXIO; }
-static inline int32_t qpnp_adc_tm_btm_configure(
+static inline int32_t qpnp_adc_tm_channel_measure(
 		struct qpnp_adc_tm_btm_param *param)
 { return -ENXIO; }
-static inline int32_t qpnp_adc_tm_btm_end(void)
+static inline int32_t qpnp_adc_tm_disable_chan_meas(void)
 { return -ENXIO; }
 static inline int32_t qpnp_adc_tm_is_ready(void)
 { return -ENXIO; }