summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/hwmon/qpnp-adc-common.c270
-rw-r--r--drivers/hwmon/qpnp-adc-voltage.c6
-rw-r--r--drivers/thermal/qpnp-adc-tm.c407
-rw-r--r--include/linux/qpnp/qpnp-adc.h3
4 files changed, 404 insertions, 282 deletions
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index ba54e7bde795..3776e748647e 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -38,6 +38,7 @@
#define PMI_CHG_SCALE_1 -138890
#define PMI_CHG_SCALE_2 391750000000
#define QPNP_VADC_HC_VREF_CODE 0x4000
+#define QPNP_VADC_HC_VDD_REFERENCE_MV 1875
/* Units for temperature below (on x axis) is in 0.1DegC as
required by the battery driver. Note the resolution used
@@ -789,41 +790,51 @@ int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(struct qpnp_vadc_chip *chip,
int64_t low_output = 0, high_output = 0;
int rc = 0, sign = 0;
- rc = qpnp_get_vadc_gain_and_offset(chip, &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 = (low_output - QPNP_ADC_625_UV) * btm_param.dy;
- if (low_output < 0) {
- sign = 1;
- low_output = -low_output;
- }
- do_div(low_output, QPNP_ADC_625_UV);
- if (sign)
- low_output = -low_output;
- low_output += btm_param.adc_gnd;
-
- sign = 0;
/* 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 = (high_output - QPNP_ADC_625_UV) * btm_param.dy;
- if (high_output < 0) {
- sign = 1;
- high_output = -high_output;
+
+ if (param->adc_tm_hc) {
+ low_output *= QPNP_VADC_HC_VREF_CODE;
+ do_div(low_output, (QPNP_VADC_HC_VDD_REFERENCE_MV * 1000));
+ high_output *= QPNP_VADC_HC_VREF_CODE;
+ do_div(high_output, (QPNP_VADC_HC_VDD_REFERENCE_MV * 1000));
+ } else {
+ rc = qpnp_get_vadc_gain_and_offset(chip, &btm_param,
+ CALIB_ABSOLUTE);
+ if (rc < 0) {
+ pr_err("Could not acquire gain and offset\n");
+ return rc;
+ }
+
+ /* Convert to voltage threshold */
+ low_output = (low_output - QPNP_ADC_625_UV) * btm_param.dy;
+ if (low_output < 0) {
+ sign = 1;
+ low_output = -low_output;
+ }
+ do_div(low_output, QPNP_ADC_625_UV);
+ if (sign)
+ low_output = -low_output;
+ low_output += btm_param.adc_gnd;
+
+ sign = 0;
+ /* Convert to voltage threshold */
+ high_output = (high_output - QPNP_ADC_625_UV) * btm_param.dy;
+ if (high_output < 0) {
+ sign = 1;
+ high_output = -high_output;
+ }
+ do_div(high_output, QPNP_ADC_625_UV);
+ if (sign)
+ high_output = -high_output;
+ high_output += btm_param.adc_gnd;
}
- do_div(high_output, QPNP_ADC_625_UV);
- if (sign)
- high_output = -high_output;
- high_output += btm_param.adc_gnd;
*low_threshold = (uint32_t) low_output;
*high_threshold = (uint32_t) high_output;
+
pr_debug("high_temp:%d, low_temp:%d\n", param->high_temp,
param->low_temp);
pr_debug("adc_code_high:%x, adc_code_low:%x\n", *high_threshold,
@@ -1079,29 +1090,34 @@ int32_t qpnp_adc_tm_scale_voltage_therm_pu2(struct qpnp_vadc_chip *chip,
{
int64_t adc_voltage = 0;
struct qpnp_vadc_linear_graph param1;
- int negative_offset;
-
- qpnp_get_vadc_gain_and_offset(chip, &param1, CALIB_RATIOMETRIC);
+ int negative_offset = 0;
- adc_voltage = (reg - param1.adc_gnd) * param1.adc_vref;
- if (adc_voltage < 0) {
- negative_offset = 1;
- adc_voltage = -adc_voltage;
- }
-
- do_div(adc_voltage, param1.dy);
-
- if (adc_properties->adc_hc)
+ if (adc_properties->adc_hc) {
+ /* (ADC code * vref_vadc (1.875V)) / 0x4000 */
+ adc_voltage = (int64_t) reg;
+ adc_voltage *= QPNP_VADC_HC_VDD_REFERENCE_MV;
+ adc_voltage = div64_s64(adc_voltage,
+ QPNP_VADC_HC_VREF_CODE);
qpnp_adc_map_voltage_temp(adcmap_100k_104ef_104fb_1875_vref,
ARRAY_SIZE(adcmap_100k_104ef_104fb_1875_vref),
adc_voltage, result);
- else
+ } else {
+ qpnp_get_vadc_gain_and_offset(chip, &param1, CALIB_RATIOMETRIC);
+
+ adc_voltage = (reg - param1.adc_gnd) * param1.adc_vref;
+ if (adc_voltage < 0) {
+ negative_offset = 1;
+ adc_voltage = -adc_voltage;
+ }
+
+ do_div(adc_voltage, param1.dy);
+
qpnp_adc_map_voltage_temp(adcmap_100k_104ef_104fb,
ARRAY_SIZE(adcmap_100k_104ef_104fb),
adc_voltage, result);
-
- if (negative_offset)
- adc_voltage = -adc_voltage;
+ if (negative_offset)
+ adc_voltage = -adc_voltage;
+ }
return 0;
}
@@ -1114,8 +1130,6 @@ int32_t qpnp_adc_tm_scale_therm_voltage_pu2(struct qpnp_vadc_chip *chip,
struct qpnp_vadc_linear_graph param1;
int rc;
- qpnp_get_vadc_gain_and_offset(chip, &param1, CALIB_RATIOMETRIC);
-
if (adc_properties->adc_hc) {
rc = qpnp_adc_map_temp_voltage(
adcmap_100k_104ef_104fb_1875_vref,
@@ -1123,27 +1137,40 @@ int32_t qpnp_adc_tm_scale_therm_voltage_pu2(struct qpnp_vadc_chip *chip,
param->low_thr_temp, &param->low_thr_voltage);
if (rc)
return rc;
+ param->low_thr_voltage *= QPNP_VADC_HC_VREF_CODE;
+ do_div(param->low_thr_voltage, QPNP_VADC_HC_VDD_REFERENCE_MV);
+
+ rc = qpnp_adc_map_temp_voltage(
+ adcmap_100k_104ef_104fb_1875_vref,
+ ARRAY_SIZE(adcmap_100k_104ef_104fb_1875_vref),
+ param->high_thr_temp, &param->high_thr_voltage);
+ if (rc)
+ return rc;
+ param->high_thr_voltage *= QPNP_VADC_HC_VREF_CODE;
+ do_div(param->high_thr_voltage, QPNP_VADC_HC_VDD_REFERENCE_MV);
} else {
+ qpnp_get_vadc_gain_and_offset(chip, &param1, CALIB_RATIOMETRIC);
+
rc = qpnp_adc_map_temp_voltage(adcmap_100k_104ef_104fb,
ARRAY_SIZE(adcmap_100k_104ef_104fb),
param->low_thr_temp, &param->low_thr_voltage);
if (rc)
return rc;
- }
- param->low_thr_voltage *= param1.dy;
- do_div(param->low_thr_voltage, param1.adc_vref);
- param->low_thr_voltage += param1.adc_gnd;
+ param->low_thr_voltage *= param1.dy;
+ do_div(param->low_thr_voltage, param1.adc_vref);
+ param->low_thr_voltage += param1.adc_gnd;
- rc = qpnp_adc_map_temp_voltage(adcmap_100k_104ef_104fb,
- ARRAY_SIZE(adcmap_100k_104ef_104fb),
- param->high_thr_temp, &param->high_thr_voltage);
- if (rc)
- return rc;
+ rc = qpnp_adc_map_temp_voltage(adcmap_100k_104ef_104fb,
+ ARRAY_SIZE(adcmap_100k_104ef_104fb),
+ param->high_thr_temp, &param->high_thr_voltage);
+ if (rc)
+ return rc;
- param->high_thr_voltage *= param1.dy;
- do_div(param->high_thr_voltage, param1.adc_vref);
- param->high_thr_voltage += param1.adc_gnd;
+ param->high_thr_voltage *= param1.dy;
+ do_div(param->high_thr_voltage, param1.adc_vref);
+ param->high_thr_voltage += param1.adc_gnd;
+ }
return 0;
}
@@ -1251,7 +1278,7 @@ int32_t qpnp_adc_usb_scaler(struct qpnp_vadc_chip *chip,
}
EXPORT_SYMBOL(qpnp_adc_usb_scaler);
-int32_t qpnp_adc_vbatt_rscaler(struct qpnp_vadc_chip *chip,
+int32_t qpnp_adc_absolute_rthr(struct qpnp_vadc_chip *chip,
struct qpnp_adc_tm_btm_param *param,
uint32_t *low_threshold, uint32_t *high_threshold)
{
@@ -1259,32 +1286,49 @@ int32_t qpnp_adc_vbatt_rscaler(struct qpnp_vadc_chip *chip,
int rc = 0, sign = 0;
int64_t low_thr = 0, high_thr = 0;
- rc = qpnp_get_vadc_gain_and_offset(chip, &vbatt_param, CALIB_ABSOLUTE);
- if (rc < 0)
- return rc;
-
- low_thr = (((param->low_thr/param->gain_den) - QPNP_ADC_625_UV) *
- vbatt_param.dy);
- if (low_thr < 0) {
- sign = 1;
- low_thr = -low_thr;
- }
- do_div(low_thr, QPNP_ADC_625_UV);
- if (sign)
- low_thr = -low_thr;
- *low_threshold = low_thr + vbatt_param.adc_gnd;
+ if (param->adc_tm_hc) {
+ low_thr = (param->low_thr/param->gain_den);
+ low_thr *= param->gain_num;
+ low_thr *= QPNP_VADC_HC_VREF_CODE;
+ do_div(low_thr, (QPNP_VADC_HC_VDD_REFERENCE_MV * 1000));
+ *low_threshold = low_thr;
+
+ high_thr = (param->high_thr/param->gain_den);
+ high_thr *= param->gain_num;
+ high_thr *= QPNP_VADC_HC_VREF_CODE;
+ do_div(high_thr, (QPNP_VADC_HC_VDD_REFERENCE_MV * 1000));
+ *high_threshold = high_thr;
+ } else {
+ rc = qpnp_get_vadc_gain_and_offset(chip, &vbatt_param,
+ CALIB_ABSOLUTE);
+ if (rc < 0)
+ return rc;
- sign = 0;
- high_thr = (((param->high_thr/param->gain_den) - QPNP_ADC_625_UV) *
- vbatt_param.dy);
- if (high_thr < 0) {
- sign = 1;
- high_thr = -high_thr;
+ low_thr = (((param->low_thr/param->gain_den) -
+ QPNP_ADC_625_UV) * vbatt_param.dy);
+ if (low_thr < 0) {
+ sign = 1;
+ low_thr = -low_thr;
+ }
+ low_thr = low_thr * param->gain_num;
+ do_div(low_thr, QPNP_ADC_625_UV);
+ if (sign)
+ low_thr = -low_thr;
+ *low_threshold = low_thr + vbatt_param.adc_gnd;
+
+ sign = 0;
+ high_thr = (((param->high_thr/param->gain_den) -
+ QPNP_ADC_625_UV) * vbatt_param.dy);
+ if (high_thr < 0) {
+ sign = 1;
+ high_thr = -high_thr;
+ }
+ high_thr = high_thr * param->gain_num;
+ do_div(high_thr, QPNP_ADC_625_UV);
+ if (sign)
+ high_thr = -high_thr;
+ *high_threshold = high_thr + vbatt_param.adc_gnd;
}
- do_div(high_thr, QPNP_ADC_625_UV);
- if (sign)
- high_thr = -high_thr;
- *high_threshold = high_thr + vbatt_param.adc_gnd;
pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
param->low_thr);
@@ -1292,48 +1336,16 @@ int32_t qpnp_adc_vbatt_rscaler(struct qpnp_vadc_chip *chip,
*low_threshold);
return 0;
}
-EXPORT_SYMBOL(qpnp_adc_vbatt_rscaler);
+EXPORT_SYMBOL(qpnp_adc_absolute_rthr);
-int32_t qpnp_adc_absolute_rthr(struct qpnp_vadc_chip *chip,
+int32_t qpnp_adc_vbatt_rscaler(struct qpnp_vadc_chip *chip,
struct qpnp_adc_tm_btm_param *param,
uint32_t *low_threshold, uint32_t *high_threshold)
{
- struct qpnp_vadc_linear_graph vbatt_param;
- int rc = 0, sign = 0;
- int64_t low_thr = 0, high_thr = 0;
-
- rc = qpnp_get_vadc_gain_and_offset(chip, &vbatt_param, CALIB_ABSOLUTE);
- if (rc < 0)
- return rc;
-
- low_thr = (((param->low_thr) - QPNP_ADC_625_UV) * vbatt_param.dy);
- if (low_thr < 0) {
- sign = 1;
- low_thr = -low_thr;
- }
- do_div(low_thr, QPNP_ADC_625_UV);
- if (sign)
- low_thr = -low_thr;
- *low_threshold = low_thr + vbatt_param.adc_gnd;
-
- sign = 0;
- high_thr = (((param->high_thr) - QPNP_ADC_625_UV) * vbatt_param.dy);
- if (high_thr < 0) {
- sign = 1;
- high_thr = -high_thr;
- }
- do_div(high_thr, QPNP_ADC_625_UV);
- if (sign)
- high_thr = -high_thr;
- *high_threshold = high_thr + vbatt_param.adc_gnd;
-
- pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr,
- param->low_thr);
- pr_debug("adc_code_high:%x, adc_code_low:%x\n", *high_threshold,
- *low_threshold);
- return 0;
+ return qpnp_adc_absolute_rthr(chip, param, low_threshold,
+ high_threshold);
}
-EXPORT_SYMBOL(qpnp_adc_absolute_rthr);
+EXPORT_SYMBOL(qpnp_adc_vbatt_rscaler);
int32_t qpnp_vadc_absolute_rthr(struct qpnp_vadc_chip *chip,
const struct qpnp_vadc_chan_properties *chan_prop,
@@ -1393,6 +1405,11 @@ int32_t qpnp_adc_btm_scaler(struct qpnp_vadc_chip *chip,
int64_t low_output = 0, high_output = 0;
int rc = 0;
+ if (param->adc_tm_hc) {
+ pr_err("Update scaling for VADC_TM_HC\n");
+ return -EINVAL;
+ }
+
qpnp_get_vadc_gain_and_offset(chip, &btm_param, CALIB_RATIOMETRIC);
pr_debug("warm_temp:%d and cool_temp:%d\n", param->high_temp,
@@ -1446,6 +1463,11 @@ int32_t qpnp_adc_qrd_skuh_btm_scaler(struct qpnp_vadc_chip *chip,
int64_t low_output = 0, high_output = 0;
int rc = 0;
+ if (param->adc_tm_hc) {
+ pr_err("Update scaling for VADC_TM_HC\n");
+ return -EINVAL;
+ }
+
qpnp_get_vadc_gain_and_offset(chip, &btm_param, CALIB_RATIOMETRIC);
pr_debug("warm_temp:%d and cool_temp:%d\n", param->high_temp,
@@ -1499,6 +1521,11 @@ int32_t qpnp_adc_qrd_skut1_btm_scaler(struct qpnp_vadc_chip *chip,
int64_t low_output = 0, high_output = 0;
int rc = 0;
+ if (param->adc_tm_hc) {
+ pr_err("Update scaling for VADC_TM_HC\n");
+ return -EINVAL;
+ }
+
qpnp_get_vadc_gain_and_offset(chip, &btm_param, CALIB_RATIOMETRIC);
pr_debug("warm_temp:%d and cool_temp:%d\n", param->high_temp,
@@ -1552,6 +1579,11 @@ int32_t qpnp_adc_smb_btm_rscaler(struct qpnp_vadc_chip *chip,
int64_t low_output = 0, high_output = 0;
int rc = 0;
+ if (param->adc_tm_hc) {
+ pr_err("Update scaling for VADC_TM_HC\n");
+ return -EINVAL;
+ }
+
qpnp_get_vadc_gain_and_offset(chip, &btm_param, CALIB_RATIOMETRIC);
pr_debug("warm_temp:%d and cool_temp:%d\n", param->high_temp,
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index f36bb933a03e..6ed947e5603b 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -1642,8 +1642,12 @@ static int32_t qpnp_vadc_calib_device(struct qpnp_vadc_chip *vadc)
vadc->adc->amux_prop->chan_prop->adc_graph[calib_type].dy =
(calib_read_1 - calib_read_2);
- vadc->adc->amux_prop->chan_prop->adc_graph[calib_type].dx
+ if (calib_type == CALIB_ABSOLUTE)
+ vadc->adc->amux_prop->chan_prop->adc_graph[calib_type].dx
= QPNP_ADC_625_UV;
+ else if (calib_type == ADC_HC_ABS_CAL)
+ vadc->adc->amux_prop->chan_prop->adc_graph[calib_type].dx
+ = QPNP_ADC_1P25_UV;
vadc->adc->amux_prop->chan_prop->adc_graph[calib_type].adc_vref =
calib_read_1;
vadc->adc->amux_prop->chan_prop->adc_graph[calib_type].adc_gnd =
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index 500d47d4ffdf..84ab45fde4ae 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -250,6 +250,8 @@ struct qpnp_adc_tm_sensor {
bool thermal_node;
uint32_t scale_type;
struct list_head thr_list;
+ bool high_thr_triggered;
+ bool low_thr_triggered;
};
struct qpnp_adc_tm_chip {
@@ -501,8 +503,8 @@ static int32_t qpnp_adc_tm_rc_check_channel_en(struct qpnp_adc_tm_chip *chip)
}
adc_tm_ctl &= QPNP_BTM_Mn_MEAS_EN;
- status_low &= QPNP_BTM_Mn_LOW_THR_INT_EN;
- status_high &= QPNP_BTM_Mn_HIGH_THR_INT_EN;
+ status_low = adc_tm_ctl & QPNP_BTM_Mn_LOW_THR_INT_EN;
+ status_high = adc_tm_ctl & QPNP_BTM_Mn_HIGH_THR_INT_EN;
/* Enable only if there are pending measurement requests */
if ((adc_tm_ctl && status_high) ||
@@ -1497,11 +1499,13 @@ static int qpnp_adc_tm_set_mode(struct thermal_zone_device *thermal,
if (qpnp_adc_tm_check_revision(chip, adc_tm->btm_channel_num))
return -EINVAL;
+ mutex_lock(&chip->adc->adc_lock);
+
btm_chan = adc_tm->btm_channel_num;
rc = qpnp_adc_tm_get_btm_idx(chip, btm_chan, &btm_chan_idx);
if (rc < 0) {
pr_err("Invalid btm channel idx\n");
- return rc;
+ goto fail;
}
if (mode == THERMAL_DEVICE_ENABLED) {
@@ -1527,14 +1531,14 @@ static int qpnp_adc_tm_set_mode(struct thermal_zone_device *thermal,
rc = qpnp_adc_tm_configure(chip, chip->adc->amux_prop);
if (rc) {
pr_err("adc-tm configure failed with %d\n", rc);
- return -EINVAL;
+ goto fail;
}
} else {
rc = qpnp_adc_tm_hc_configure(chip,
chip->adc->amux_prop);
if (rc) {
pr_err("hc configure failed with %d\n", rc);
- return -EINVAL;
+ goto fail;
}
}
} else if (mode == THERMAL_DEVICE_DISABLED) {
@@ -1545,7 +1549,7 @@ static int qpnp_adc_tm_set_mode(struct thermal_zone_device *thermal,
rc = qpnp_adc_tm_mode_select(chip, mode_ctl);
if (rc < 0) {
pr_err("adc-tm single mode select failed\n");
- return rc;
+ goto fail;
}
}
@@ -1553,7 +1557,7 @@ static int qpnp_adc_tm_set_mode(struct thermal_zone_device *thermal,
rc = qpnp_adc_tm_disable(chip);
if (rc < 0) {
pr_err("adc-tm disable failed\n");
- return rc;
+ goto fail;
}
if (!chip->adc_tm_hc) {
@@ -1561,14 +1565,14 @@ static int qpnp_adc_tm_set_mode(struct thermal_zone_device *thermal,
rc = qpnp_adc_tm_req_sts_check(chip);
if (rc < 0) {
pr_err("adc-tm req_sts check failed\n");
- return rc;
+ goto fail;
}
rc = qpnp_adc_tm_reg_update(chip,
QPNP_ADC_TM_MULTI_MEAS_EN, sensor_mask, false);
if (rc < 0) {
pr_err("multi measurement update failed\n");
- return rc;
+ goto fail;
}
} else {
rc = qpnp_adc_tm_reg_update(chip,
@@ -1576,19 +1580,22 @@ static int qpnp_adc_tm_set_mode(struct thermal_zone_device *thermal,
QPNP_BTM_Mn_MEAS_EN, false);
if (rc < 0) {
pr_err("multi measurement disable failed\n");
- return rc;
+ goto fail;
}
}
rc = qpnp_adc_tm_enable_if_channel_meas(chip);
if (rc < 0) {
pr_err("re-enabling measurement failed\n");
- return rc;
+ goto fail;
}
}
adc_tm->mode = mode;
+fail:
+ mutex_unlock(&chip->adc->adc_lock);
+
return 0;
}
@@ -2096,17 +2103,207 @@ fail:
return rc;
}
-static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip)
+static int qpnp_adc_tm_disable_rearm_high_thresholds(
+ struct qpnp_adc_tm_chip *chip, int sensor_num)
{
- u8 sensor_mask = 0, notify_check = 0;
- int rc = 0, sensor_notify_num = 0, i = 0, sensor_num = 0;
+
+ struct qpnp_adc_thr_client_info *client_info = NULL;
+ struct list_head *thr_list;
uint32_t btm_chan_num = 0;
+ u8 sensor_mask = 0, notify_check = 0;
+ int rc = 0;
+
+ btm_chan_num = chip->sensor[sensor_num].btm_channel_num;
+ pr_debug("high:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
+ sensor_num, chip->th_info.adc_tm_high_enable,
+ chip->th_info.adc_tm_low_enable,
+ chip->th_info.qpnp_adc_tm_meas_en);
+ if (!chip->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_recalib_request_check(chip,
+ sensor_num, true, &notify_check);
+ if (rc < 0 || !notify_check) {
+ pr_debug("Calib recheck re-armed rc=%d\n", rc);
+ chip->th_info.adc_tm_high_enable = 0;
+ return rc;
+ }
+ } else {
+ /*
+ * Uses the thermal sysfs registered device to disable
+ * the corresponding high voltage threshold which
+ * is triggered by low temp
+ */
+ sensor_mask = 1 << sensor_num;
+ pr_debug("thermal node with mask:%x\n", sensor_mask);
+ rc = qpnp_adc_tm_activate_trip_type(
+ chip->sensor[sensor_num].tz_dev,
+ ADC_TM_TRIP_LOW_COOL,
+ THERMAL_TRIP_ACTIVATION_DISABLED);
+ if (rc < 0) {
+ pr_err("notify error:%d\n", sensor_num);
+ return rc;
+ }
+ }
+ list_for_each(thr_list, &chip->sensor[sensor_num].thr_list) {
+ client_info = list_entry(thr_list,
+ struct qpnp_adc_thr_client_info, list);
+ if (client_info->high_thr_set) {
+ client_info->high_thr_set = false;
+ client_info->notify_high_thr = true;
+ if (client_info->state_req_copy ==
+ ADC_TM_HIGH_LOW_THR_ENABLE)
+ client_info->state_req_copy =
+ ADC_TM_LOW_THR_ENABLE;
+ else
+ client_info->state_req_copy =
+ ADC_TM_HIGH_THR_DISABLE;
+ }
+ }
+ qpnp_adc_tm_manage_thresholds(chip, sensor_num, btm_chan_num);
+
+ if (!chip->adc_tm_hc) {
+ rc = qpnp_adc_tm_reg_update(chip,
+ QPNP_ADC_TM_MULTI_MEAS_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("multi meas disable failed\n");
+ return rc;
+ }
+ } else {
+ rc = qpnp_adc_tm_reg_update(chip,
+ QPNP_BTM_Mn_EN(sensor_num),
+ QPNP_BTM_Mn_MEAS_EN, false);
+ if (rc < 0) {
+ pr_err("multi meas disable failed\n");
+ return rc;
+ }
+ }
+
+ rc = qpnp_adc_tm_enable_if_channel_meas(chip);
+ if (rc < 0) {
+ pr_err("re-enabling measurement failed\n");
+ return rc;
+ }
+
+ queue_work(chip->sensor[sensor_num].req_wq,
+ &chip->sensor[sensor_num].work);
+
+ return rc;
+}
+
+static int qpnp_adc_tm_disable_rearm_low_thresholds(
+ struct qpnp_adc_tm_chip *chip, int sensor_num)
+{
struct qpnp_adc_thr_client_info *client_info = NULL;
struct list_head *thr_list;
+ uint32_t btm_chan_num = 0;
+ u8 sensor_mask = 0, notify_check = 0;
+ int rc = 0;
+
+ btm_chan_num = chip->sensor[sensor_num].btm_channel_num;
+ pr_debug("low:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
+ sensor_num, chip->th_info.adc_tm_high_enable,
+ chip->th_info.adc_tm_low_enable,
+ chip->th_info.qpnp_adc_tm_meas_en);
+ if (!chip->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);
+ rc = qpnp_adc_tm_recalib_request_check(chip,
+ sensor_num, false, &notify_check);
+ if (rc < 0 || !notify_check) {
+ pr_debug("Calib recheck re-armed rc=%d\n", rc);
+ chip->th_info.adc_tm_low_enable = 0;
+ return rc;
+ }
+ sensor_mask = 1 << sensor_num;
+ rc = qpnp_adc_tm_reg_update(chip,
+ QPNP_ADC_TM_LOW_THR_INT_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("low threshold int read failed\n");
+ return rc;
+ }
+ } else {
+ /*
+ * Uses the thermal sysfs registered device to disable
+ * the corresponding high voltage threshold which
+ * is triggered by low temp
+ */
+ sensor_mask = 1 << sensor_num;
+ pr_debug("thermal node with mask:%x\n", sensor_mask);
+ rc = qpnp_adc_tm_activate_trip_type(
+ chip->sensor[sensor_num].tz_dev,
+ ADC_TM_TRIP_HIGH_WARM,
+ THERMAL_TRIP_ACTIVATION_DISABLED);
+ if (rc < 0) {
+ pr_err("notify error:%d\n", sensor_num);
+ return rc;
+ }
+ }
+ list_for_each(thr_list, &chip->sensor[sensor_num].thr_list) {
+ client_info = list_entry(thr_list,
+ struct qpnp_adc_thr_client_info, list);
+ if (client_info->low_thr_set) {
+ client_info->low_thr_set = false;
+ client_info->notify_low_thr = true;
+ if (client_info->state_req_copy ==
+ ADC_TM_HIGH_LOW_THR_ENABLE)
+ client_info->state_req_copy =
+ ADC_TM_HIGH_THR_ENABLE;
+ else
+ client_info->state_req_copy =
+ ADC_TM_LOW_THR_DISABLE;
+ }
+ }
+ qpnp_adc_tm_manage_thresholds(chip, sensor_num, btm_chan_num);
+
+ if (!chip->adc_tm_hc) {
+ rc = qpnp_adc_tm_reg_update(chip,
+ QPNP_ADC_TM_MULTI_MEAS_EN,
+ sensor_mask, false);
+ if (rc < 0) {
+ pr_err("multi meas disable failed\n");
+ return rc;
+ }
+ } else {
+ rc = qpnp_adc_tm_reg_update(chip,
+ QPNP_BTM_Mn_EN(sensor_num),
+ QPNP_BTM_Mn_MEAS_EN, false);
+ if (rc < 0) {
+ pr_err("multi meas disable failed\n");
+ return rc;
+ }
+ }
+
+ rc = qpnp_adc_tm_enable_if_channel_meas(chip);
+ if (rc < 0) {
+ pr_err("re-enabling measurement failed\n");
+ return rc;
+ }
+
+ queue_work(chip->sensor[sensor_num].req_wq,
+ &chip->sensor[sensor_num].work);
+
+ return rc;
+}
+
+static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip)
+{
+ int rc = 0, sensor_num = 0;
if (qpnp_adc_tm_is_valid(chip))
return -ENODEV;
+ pr_debug("%s\n", __func__);
+
mutex_lock(&chip->adc->adc_lock);
if (!chip->adc_tm_hc) {
@@ -2117,159 +2314,36 @@ static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip)
}
}
- if (chip->th_info.adc_tm_high_enable) {
- sensor_notify_num = chip->th_info.adc_tm_high_enable;
- while (i < chip->max_channels_available) {
- if ((sensor_notify_num & 0x1) == 1)
- sensor_num = i;
- sensor_notify_num >>= 1;
- i++;
- }
-
- btm_chan_num = chip->sensor[sensor_num].btm_channel_num;
- pr_debug("high:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
- sensor_num, chip->th_info.adc_tm_high_enable,
- chip->th_info.adc_tm_low_enable,
- chip->th_info.qpnp_adc_tm_meas_en);
- if (!chip->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_recalib_request_check(chip,
- sensor_num, true, &notify_check);
- if (rc < 0 || !notify_check) {
- pr_debug("Calib recheck re-armed rc=%d\n", rc);
- chip->th_info.adc_tm_high_enable = 0;
+ while (sensor_num < chip->max_channels_available) {
+ if (chip->sensor[sensor_num].high_thr_triggered) {
+ rc = qpnp_adc_tm_disable_rearm_high_thresholds(
+ chip, sensor_num);
+ if (rc) {
+ pr_err("rearm threshold failed\n");
goto fail;
}
- } 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);
- }
- list_for_each(thr_list, &chip->sensor[sensor_num].thr_list) {
- client_info = list_entry(thr_list,
- struct qpnp_adc_thr_client_info, list);
- if (client_info->high_thr_set) {
- client_info->high_thr_set = false;
- client_info->notify_high_thr = true;
- if (client_info->state_req_copy ==
- ADC_TM_HIGH_LOW_THR_ENABLE)
- client_info->state_req_copy =
- ADC_TM_LOW_THR_ENABLE;
- else
- client_info->state_req_copy =
- ADC_TM_HIGH_THR_DISABLE;
- }
+ chip->sensor[sensor_num].high_thr_triggered = false;
}
+ sensor_num++;
}
- if (chip->th_info.adc_tm_low_enable) {
- sensor_notify_num = chip->th_info.adc_tm_low_enable;
- i = 0;
- while (i < chip->max_channels_available) {
- if ((sensor_notify_num & 0x1) == 1)
- sensor_num = i;
- sensor_notify_num >>= 1;
- i++;
- }
-
- btm_chan_num = chip->sensor[sensor_num].btm_channel_num;
- pr_debug("low:sen:%d, hs:0x%x, ls:0x%x, meas_en:0x%x\n",
- sensor_num, chip->th_info.adc_tm_high_enable,
- chip->th_info.adc_tm_low_enable,
- chip->th_info.qpnp_adc_tm_meas_en);
- if (!chip->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);
- rc = qpnp_adc_tm_recalib_request_check(chip,
- sensor_num, false, &notify_check);
- if (rc < 0 || !notify_check) {
- pr_debug("Calib recheck re-armed rc=%d\n", rc);
- chip->th_info.adc_tm_low_enable = 0;
- goto fail;
- }
- sensor_mask = 1 << sensor_num;
- rc = qpnp_adc_tm_reg_update(chip,
- QPNP_ADC_TM_LOW_THR_INT_EN,
- sensor_mask, false);
- if (rc < 0) {
- pr_err("low threshold int read failed\n");
- goto fail;
- }
- } 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(
- chip->sensor[sensor_num].tz_dev,
- ADC_TM_TRIP_HIGH_WARM,
- THERMAL_TRIP_ACTIVATION_DISABLED);
- if (rc < 0) {
- pr_err("notify error:%d\n", sensor_num);
+ sensor_num = 0;
+ while (sensor_num < chip->max_channels_available) {
+ if (chip->sensor[sensor_num].low_thr_triggered) {
+ rc = qpnp_adc_tm_disable_rearm_low_thresholds(
+ chip, sensor_num);
+ if (rc) {
+ pr_err("rearm threshold failed\n");
goto fail;
}
+ chip->sensor[sensor_num].low_thr_triggered = false;
}
- list_for_each(thr_list, &chip->sensor[sensor_num].thr_list) {
- client_info = list_entry(thr_list,
- struct qpnp_adc_thr_client_info, list);
- if (client_info->low_thr_set) {
- /* mark the corresponding clients threshold
- as not set */
- client_info->low_thr_set = false;
- client_info->notify_low_thr = true;
- if (client_info->state_req_copy ==
- ADC_TM_HIGH_LOW_THR_ENABLE)
- client_info->state_req_copy =
- ADC_TM_HIGH_THR_ENABLE;
- else
- client_info->state_req_copy =
- ADC_TM_LOW_THR_DISABLE;
- }
- }
+ sensor_num++;
}
- qpnp_adc_tm_manage_thresholds(chip, sensor_num, btm_chan_num);
-
- if (chip->th_info.adc_tm_high_enable ||
- chip->th_info.adc_tm_low_enable) {
- if (!chip->adc_tm_hc) {
- rc = qpnp_adc_tm_reg_update(chip,
- QPNP_ADC_TM_MULTI_MEAS_EN,
- sensor_mask, false);
- if (rc < 0) {
- pr_err("multi meas disable failed\n");
- goto fail;
- }
- } else {
- rc = qpnp_adc_tm_reg_update(chip,
- QPNP_BTM_Mn_EN(sensor_mask),
- QPNP_BTM_Mn_MEAS_EN, false);
- if (rc < 0) {
- pr_err("multi meas disable failed\n");
- goto fail;
- }
- }
-
- rc = qpnp_adc_tm_enable_if_channel_meas(chip);
- if (rc < 0) {
- pr_err("re-enabling measurement failed\n");
- return rc;
- }
- } else
- pr_debug("No threshold status enable %d for high/low??\n",
- sensor_mask);
-
fail:
mutex_unlock(&chip->adc->adc_lock);
- if (chip->th_info.adc_tm_high_enable || chip->th_info.adc_tm_low_enable)
- queue_work(chip->sensor[sensor_num].req_wq,
- &chip->sensor[sensor_num].work);
if (rc < 0 || (!chip->th_info.adc_tm_high_enable &&
!chip->th_info.adc_tm_low_enable))
atomic_dec(&chip->wq_cnt);
@@ -2290,6 +2364,8 @@ static void qpnp_adc_tm_high_thr_work(struct work_struct *work)
chip->adc_vote_enable = false;
}
+ pr_debug("thr:0x%x\n", chip->th_info.adc_tm_high_enable);
+
rc = qpnp_adc_tm_read_status(chip);
if (rc < 0)
pr_err("adc-tm high thr work failed\n");
@@ -2393,6 +2469,8 @@ static void qpnp_adc_tm_low_thr_work(struct work_struct *work)
chip->adc_vote_enable = false;
}
+ pr_debug("thr:0x%x\n", chip->th_info.adc_tm_low_enable);
+
rc = qpnp_adc_tm_read_status(chip);
if (rc < 0)
pr_err("adc-tm low thr work failed\n");
@@ -2483,7 +2561,7 @@ static irqreturn_t qpnp_adc_tm_low_thr_isr(int irq, void *data)
static int qpnp_adc_tm_rc_check_sensor_trip(struct qpnp_adc_tm_chip *chip,
u8 status_low, u8 status_high, int i,
- int sensor_low_notify_num, int sensor_high_notify_num)
+ int *sensor_low_notify_num, int *sensor_high_notify_num)
{
int rc = 0;
u8 ctl = 0, sensor_mask = 0;
@@ -2523,7 +2601,8 @@ static int qpnp_adc_tm_rc_check_sensor_trip(struct qpnp_adc_tm_chip *chip,
return IRQ_HANDLED;
}
}
- sensor_low_notify_num |= (status_low & 0x1);
+ *sensor_low_notify_num |= (status_low & 0x1);
+ chip->sensor[i].low_thr_triggered = true;
}
if ((status_high & 0x1) && (ctl & QPNP_BTM_Mn_MEAS_EN) &&
@@ -2553,7 +2632,8 @@ static int qpnp_adc_tm_rc_check_sensor_trip(struct qpnp_adc_tm_chip *chip,
return IRQ_HANDLED;
}
}
- sensor_high_notify_num |= (status_high & 0x1);
+ *sensor_high_notify_num |= (status_high & 0x1);
+ chip->sensor[i].high_thr_triggered = true;
}
}
@@ -2590,7 +2670,8 @@ static irqreturn_t qpnp_adc_tm_rc_thr_isr(int irq, void *data)
while (i < chip->max_channels_available) {
rc = qpnp_adc_tm_rc_check_sensor_trip(chip,
status_low, status_high, i,
- sensor_low_notify_num, sensor_high_notify_num);
+ &sensor_low_notify_num,
+ &sensor_high_notify_num);
if (rc) {
pr_err("Sensor trip read failed\n");
return IRQ_HANDLED;
@@ -2600,14 +2681,15 @@ static irqreturn_t qpnp_adc_tm_rc_thr_isr(int irq, void *data)
i++;
}
- if (sensor_low_notify_num || sensor_high_notify_num)
+ if (sensor_low_notify_num) {
atomic_inc(&chip->wq_cnt);
-
- if (sensor_low_notify_num)
queue_work(chip->low_thr_wq, &chip->trigger_low_thr_work);
+ }
- if (sensor_high_notify_num)
+ if (sensor_high_notify_num) {
+ atomic_inc(&chip->wq_cnt);
queue_work(chip->high_thr_wq, &chip->trigger_high_thr_work);
+ }
return IRQ_HANDLED;
}
@@ -2710,6 +2792,7 @@ int32_t qpnp_adc_tm_channel_measure(struct qpnp_adc_tm_chip *chip,
channel, scale_type, dt_index);
param->gain_num = qpnp_vadc_amux_scaling_ratio[amux_prescaling].num;
param->gain_den = qpnp_vadc_amux_scaling_ratio[amux_prescaling].den;
+ param->adc_tm_hc = chip->adc_tm_hc;
chip->adc->amux_prop->amux_channel = channel;
chip->adc->amux_prop->decimation =
chip->adc->adc_channels[dt_index].adc_decimation;
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index 8d51ddcd4246..af25f0c01369 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -242,6 +242,7 @@ enum qpnp_iadc_channels {
#define QPNP_ADC_HWMON_NAME_LENGTH 64
#define QPNP_MAX_PROP_NAME_LEN 32
#define QPNP_THERMALNODE_NAME_LENGTH 25
+#define QPNP_ADC_1P25_UV 1250000
/* Structure device for qpnp vadc */
struct qpnp_vadc_chip;
@@ -950,6 +951,7 @@ enum qpnp_state_request {
* @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.
+ * @adc_tm_hc: Represents the refreshed BTM register design.
* @state_request: Enable/disable the corresponding high and low temperature
* thresholds.
* @timer_interval1: Select polling rate from qpnp_adc_meas_timer_1 type.
@@ -972,6 +974,7 @@ struct qpnp_adc_tm_btm_param {
int32_t low_thr;
int32_t gain_num;
int32_t gain_den;
+ bool adc_tm_hc;
enum qpnp_vadc_channels channel;
enum qpnp_state_request state_request;
enum qpnp_adc_meas_timer_1 timer_interval;