Loading drivers/hwmon/qpnp-adc-common.c +151 −119 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -789,14 +790,24 @@ 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); /* Convert to Kelvin and account for voltage to be written as 2mV/K */ low_output = (param->low_temp + KELVINMIL_DEGMIL) * 2; /* Convert to Kelvin and account for voltage to be written as 2mV/K */ high_output = (param->high_temp + KELVINMIL_DEGMIL) * 2; 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 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) { Loading @@ -809,8 +820,6 @@ int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(struct qpnp_vadc_chip *chip, 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) { Loading @@ -821,9 +830,11 @@ int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(struct qpnp_vadc_chip *chip, 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, Loading Loading @@ -1079,8 +1090,18 @@ 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; int negative_offset = 0; 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 { qpnp_get_vadc_gain_and_offset(chip, ¶m1, CALIB_RATIOMETRIC); adc_voltage = (reg - param1.adc_gnd) * param1.adc_vref; Loading @@ -1091,17 +1112,12 @@ int32_t qpnp_adc_tm_scale_voltage_therm_pu2(struct qpnp_vadc_chip *chip, do_div(adc_voltage, param1.dy); if (adc_properties->adc_hc) qpnp_adc_map_voltage_temp(adcmap_100k_104ef_104fb_1875_vref, ARRAY_SIZE(adcmap_100k_104ef_104fb_1875_vref), adc_voltage, result); else 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; } return 0; } Loading @@ -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, ¶m1, CALIB_RATIOMETRIC); if (adc_properties->adc_hc) { rc = qpnp_adc_map_temp_voltage( adcmap_100k_104ef_104fb_1875_vref, Loading @@ -1123,13 +1137,25 @@ int32_t qpnp_adc_tm_scale_therm_voltage_pu2(struct qpnp_vadc_chip *chip, param->low_thr_temp, ¶m->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, ¶m->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, ¶m1, CALIB_RATIOMETRIC); rc = qpnp_adc_map_temp_voltage(adcmap_100k_104ef_104fb, ARRAY_SIZE(adcmap_100k_104ef_104fb), param->low_thr_temp, ¶m->low_thr_voltage); if (rc) return rc; } param->low_thr_voltage *= param1.dy; do_div(param->low_thr_voltage, param1.adc_vref); Loading @@ -1144,6 +1170,7 @@ int32_t qpnp_adc_tm_scale_therm_voltage_pu2(struct qpnp_vadc_chip *chip, param->high_thr_voltage *= param1.dy; do_div(param->high_thr_voltage, param1.adc_vref); param->high_thr_voltage += param1.adc_gnd; } return 0; } Loading Loading @@ -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) { Loading @@ -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 (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; low_thr = (((param->low_thr/param->gain_den) - QPNP_ADC_625_UV) * vbatt_param.dy); 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); 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; } pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr, param->low_thr); Loading @@ -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, Loading Loading @@ -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, Loading Loading @@ -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, Loading Loading @@ -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, Loading Loading @@ -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, Loading drivers/hwmon/qpnp-adc-voltage.c +5 −1 Original line number Diff line number Diff line Loading @@ -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); 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 = Loading drivers/thermal/qpnp-adc-tm.c +245 −162 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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) || Loading Loading @@ -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) { Loading @@ -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) { Loading @@ -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; } } Loading @@ -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) { Loading @@ -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, Loading @@ -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; } Loading Loading @@ -2096,35 +2103,15 @@ 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; uint32_t btm_chan_num = 0; struct qpnp_adc_thr_client_info *client_info = NULL; struct list_head *thr_list; if (qpnp_adc_tm_is_valid(chip)) return -ENODEV; mutex_lock(&chip->adc->adc_lock); if (!chip->adc_tm_hc) { rc = qpnp_adc_tm_req_sts_check(chip); if (rc) { pr_err("adc-tm-tm req sts check failed with %d\n", rc); goto fail; } } 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++; } 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", Loading @@ -2132,8 +2119,10 @@ static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip) 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 */ /* * 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, Loading @@ -2141,13 +2130,24 @@ static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip) if (rc < 0 || !notify_check) { pr_debug("Calib recheck re-armed rc=%d\n", rc); chip->th_info.adc_tm_high_enable = 0; goto fail; return rc; } } else { /* Uses the thermal sysfs registered device to disable the corresponding high voltage threshold which is triggered by low temp */ /* * 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, Loading @@ -2164,33 +2164,64 @@ static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip) 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; } 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++; 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 */ /* * 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, ¬ify_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; return rc; } sensor_mask = 1 << sensor_num; rc = qpnp_adc_tm_reg_update(chip, Loading @@ -2198,12 +2229,15 @@ static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip) sensor_mask, false); if (rc < 0) { pr_err("low threshold int read failed\n"); goto fail; return rc; } } else { /* Uses the thermal sysfs registered device to disable the corresponding low voltage threshold which is triggered by high temp */ /* * 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, Loading @@ -2211,15 +2245,13 @@ static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip) THERMAL_TRIP_ACTIVATION_DISABLED); if (rc < 0) { pr_err("notify error:%d\n", sensor_num); goto fail; 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) { /* 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 == Loading @@ -2231,27 +2263,23 @@ static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip) ADC_TM_LOW_THR_DISABLE; } } } 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; return rc; } } else { rc = qpnp_adc_tm_reg_update(chip, QPNP_BTM_Mn_EN(sensor_mask), QPNP_BTM_Mn_EN(sensor_num), QPNP_BTM_Mn_MEAS_EN, false); if (rc < 0) { pr_err("multi meas disable failed\n"); goto fail; return rc; } } Loading @@ -2260,16 +2288,62 @@ static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip) pr_err("re-enabling measurement failed\n"); return rc; } } else pr_debug("No threshold status enable %d for high/low??\n", sensor_mask); 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) { rc = qpnp_adc_tm_req_sts_check(chip); if (rc) { pr_err("adc-tm-tm req sts check failed with %d\n", rc); goto fail; } } 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; } chip->sensor[sensor_num].high_thr_triggered = false; } 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; } sensor_num++; } 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); Loading @@ -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"); Loading Loading @@ -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"); Loading Loading @@ -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; Loading Loading @@ -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) && Loading Loading @@ -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; } } Loading Loading @@ -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; Loading @@ -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; } Loading Loading @@ -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; Loading include/linux/qpnp/qpnp-adc.h +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading @@ -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; Loading Loading
drivers/hwmon/qpnp-adc-common.c +151 −119 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -789,14 +790,24 @@ 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); /* Convert to Kelvin and account for voltage to be written as 2mV/K */ low_output = (param->low_temp + KELVINMIL_DEGMIL) * 2; /* Convert to Kelvin and account for voltage to be written as 2mV/K */ high_output = (param->high_temp + KELVINMIL_DEGMIL) * 2; 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 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) { Loading @@ -809,8 +820,6 @@ int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(struct qpnp_vadc_chip *chip, 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) { Loading @@ -821,9 +830,11 @@ int32_t qpnp_adc_scale_millidegc_pmic_voltage_thr(struct qpnp_vadc_chip *chip, 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, Loading Loading @@ -1079,8 +1090,18 @@ 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; int negative_offset = 0; 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 { qpnp_get_vadc_gain_and_offset(chip, ¶m1, CALIB_RATIOMETRIC); adc_voltage = (reg - param1.adc_gnd) * param1.adc_vref; Loading @@ -1091,17 +1112,12 @@ int32_t qpnp_adc_tm_scale_voltage_therm_pu2(struct qpnp_vadc_chip *chip, do_div(adc_voltage, param1.dy); if (adc_properties->adc_hc) qpnp_adc_map_voltage_temp(adcmap_100k_104ef_104fb_1875_vref, ARRAY_SIZE(adcmap_100k_104ef_104fb_1875_vref), adc_voltage, result); else 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; } return 0; } Loading @@ -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, ¶m1, CALIB_RATIOMETRIC); if (adc_properties->adc_hc) { rc = qpnp_adc_map_temp_voltage( adcmap_100k_104ef_104fb_1875_vref, Loading @@ -1123,13 +1137,25 @@ int32_t qpnp_adc_tm_scale_therm_voltage_pu2(struct qpnp_vadc_chip *chip, param->low_thr_temp, ¶m->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, ¶m->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, ¶m1, CALIB_RATIOMETRIC); rc = qpnp_adc_map_temp_voltage(adcmap_100k_104ef_104fb, ARRAY_SIZE(adcmap_100k_104ef_104fb), param->low_thr_temp, ¶m->low_thr_voltage); if (rc) return rc; } param->low_thr_voltage *= param1.dy; do_div(param->low_thr_voltage, param1.adc_vref); Loading @@ -1144,6 +1170,7 @@ int32_t qpnp_adc_tm_scale_therm_voltage_pu2(struct qpnp_vadc_chip *chip, param->high_thr_voltage *= param1.dy; do_div(param->high_thr_voltage, param1.adc_vref); param->high_thr_voltage += param1.adc_gnd; } return 0; } Loading Loading @@ -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) { Loading @@ -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 (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; low_thr = (((param->low_thr/param->gain_den) - QPNP_ADC_625_UV) * vbatt_param.dy); 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); 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; } pr_debug("high_volt:%d, low_volt:%d\n", param->high_thr, param->low_thr); Loading @@ -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, Loading Loading @@ -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, Loading Loading @@ -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, Loading Loading @@ -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, Loading Loading @@ -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, Loading
drivers/hwmon/qpnp-adc-voltage.c +5 −1 Original line number Diff line number Diff line Loading @@ -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); 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 = Loading
drivers/thermal/qpnp-adc-tm.c +245 −162 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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) || Loading Loading @@ -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) { Loading @@ -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) { Loading @@ -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; } } Loading @@ -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) { Loading @@ -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, Loading @@ -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; } Loading Loading @@ -2096,35 +2103,15 @@ 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; uint32_t btm_chan_num = 0; struct qpnp_adc_thr_client_info *client_info = NULL; struct list_head *thr_list; if (qpnp_adc_tm_is_valid(chip)) return -ENODEV; mutex_lock(&chip->adc->adc_lock); if (!chip->adc_tm_hc) { rc = qpnp_adc_tm_req_sts_check(chip); if (rc) { pr_err("adc-tm-tm req sts check failed with %d\n", rc); goto fail; } } 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++; } 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", Loading @@ -2132,8 +2119,10 @@ static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip) 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 */ /* * 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, Loading @@ -2141,13 +2130,24 @@ static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip) if (rc < 0 || !notify_check) { pr_debug("Calib recheck re-armed rc=%d\n", rc); chip->th_info.adc_tm_high_enable = 0; goto fail; return rc; } } else { /* Uses the thermal sysfs registered device to disable the corresponding high voltage threshold which is triggered by low temp */ /* * 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, Loading @@ -2164,33 +2164,64 @@ static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip) 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; } 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++; 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 */ /* * 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, ¬ify_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; return rc; } sensor_mask = 1 << sensor_num; rc = qpnp_adc_tm_reg_update(chip, Loading @@ -2198,12 +2229,15 @@ static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip) sensor_mask, false); if (rc < 0) { pr_err("low threshold int read failed\n"); goto fail; return rc; } } else { /* Uses the thermal sysfs registered device to disable the corresponding low voltage threshold which is triggered by high temp */ /* * 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, Loading @@ -2211,15 +2245,13 @@ static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip) THERMAL_TRIP_ACTIVATION_DISABLED); if (rc < 0) { pr_err("notify error:%d\n", sensor_num); goto fail; 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) { /* 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 == Loading @@ -2231,27 +2263,23 @@ static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip) ADC_TM_LOW_THR_DISABLE; } } } 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; return rc; } } else { rc = qpnp_adc_tm_reg_update(chip, QPNP_BTM_Mn_EN(sensor_mask), QPNP_BTM_Mn_EN(sensor_num), QPNP_BTM_Mn_MEAS_EN, false); if (rc < 0) { pr_err("multi meas disable failed\n"); goto fail; return rc; } } Loading @@ -2260,16 +2288,62 @@ static int qpnp_adc_tm_read_status(struct qpnp_adc_tm_chip *chip) pr_err("re-enabling measurement failed\n"); return rc; } } else pr_debug("No threshold status enable %d for high/low??\n", sensor_mask); 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) { rc = qpnp_adc_tm_req_sts_check(chip); if (rc) { pr_err("adc-tm-tm req sts check failed with %d\n", rc); goto fail; } } 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; } chip->sensor[sensor_num].high_thr_triggered = false; } 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; } sensor_num++; } 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); Loading @@ -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"); Loading Loading @@ -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"); Loading Loading @@ -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; Loading Loading @@ -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) && Loading Loading @@ -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; } } Loading Loading @@ -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; Loading @@ -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; } Loading Loading @@ -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; Loading
include/linux/qpnp/qpnp-adc.h +3 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading @@ -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; Loading