int32_t qpnp_iadc_read(enum qpnp_iadc_channels channel, struct qpnp_iadc_result *result) { struct qpnp_iadc_drv *iadc = qpnp_iadc; int32_t rc, rsense_n_ohms, sign = 0, num, mode_sel = 0; int32_t rsense_u_ohms = 0; int64_t result_current; uint16_t raw_data; if (!iadc || !iadc->iadc_initialized) return -EPROBE_DEFER; if (!iadc->iadc_mode_sel) { rc = qpnp_check_pmic_temp(); if (rc) { pr_err("Error checking pmic therm temp\n"); return rc; } } mutex_lock(&iadc->adc->adc_lock); rc = qpnp_iadc_configure(channel, &raw_data, mode_sel); if (rc < 0) { pr_err("qpnp adc result read failed with %d\n", rc); goto fail; } rc = qpnp_iadc_get_rsense(&rsense_n_ohms); pr_debug("current raw:0%x and rsense:%d\n", raw_data, rsense_n_ohms); rsense_u_ohms = rsense_n_ohms/1000; num = raw_data - iadc->adc->calib.offset_raw; if (num < 0) { sign = 1; num = -num; } result->result_uv = (num * QPNP_ADC_GAIN_NV)/ (iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw); result_current = result->result_uv; result_current *= QPNP_IADC_NANO_VOLTS_FACTOR; do_div(result_current, rsense_u_ohms); if (sign) { result->result_uv = -result->result_uv; result_current = -result_current; } result->result_ua = (int32_t) result_current; fail: mutex_unlock(&iadc->adc->adc_lock); return rc; }
int32_t qpnp_iadc_vadc_sync_read(struct qpnp_iadc_chip *iadc, enum qpnp_iadc_channels i_channel, struct qpnp_iadc_result *i_result, enum qpnp_vadc_channels v_channel, struct qpnp_vadc_result *v_result) { int rc = 0, mode_sel = 0, num = 0, rsense_n_ohms = 0, sign = 0; int dt_index = 0; uint16_t raw_data; int32_t rsense_u_ohms = 0; int64_t result_current; if (qpnp_iadc_is_valid(iadc) < 0) return -EPROBE_DEFER; if ((iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw) == 0) { pr_err("raw offset errors! run iadc calibration again\n"); return -EINVAL; } mutex_lock(&iadc->adc->adc_lock); if (iadc->iadc_poll_eoc) { pr_debug("acquiring iadc eoc wakelock\n"); pm_stay_awake(iadc->dev); } iadc->iadc_mode_sel = true; rc = qpnp_vadc_iadc_sync_request(iadc->vadc_dev, v_channel); if (rc) { pr_err("Configuring VADC failed\n"); goto fail; } while (((enum qpnp_iadc_channels) iadc->adc->adc_channels[dt_index].channel_num != i_channel) && (dt_index < iadc->max_channels_available)) dt_index++; if (dt_index >= iadc->max_channels_available) { pr_err("not a valid IADC channel\n"); rc = -EINVAL; goto fail; } iadc->adc->amux_prop->decimation = iadc->adc->adc_channels[dt_index].adc_decimation; iadc->adc->amux_prop->fast_avg_setup = iadc->adc->adc_channels[dt_index].fast_avg_setup; rc = qpnp_iadc_configure(iadc, i_channel, &raw_data, mode_sel); if (rc < 0) { pr_err("qpnp adc result read failed with %d\n", rc); goto fail_release_vadc; } rc = qpnp_iadc_get_rsense(iadc, &rsense_n_ohms); pr_debug("current raw:0%x and rsense:%d\n", raw_data, rsense_n_ohms); rsense_u_ohms = rsense_n_ohms/1000; num = raw_data - iadc->adc->calib.offset_raw; if (num < 0) { sign = 1; num = -num; } i_result->result_uv = (num * QPNP_ADC_GAIN_NV)/ (iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw); result_current = i_result->result_uv; result_current *= QPNP_IADC_NANO_VOLTS_FACTOR; /* Intentional fall through. Process the result w/o comp */ if (!rsense_u_ohms) { pr_err("rsense error=%d\n", rsense_u_ohms); goto fail_release_vadc; } do_div(result_current, rsense_u_ohms); if (sign) { i_result->result_uv = -i_result->result_uv; result_current = -result_current; } result_current *= -1; rc = qpnp_iadc_comp_result(iadc, &result_current); if (rc < 0) pr_err("Error during compensating the IADC\n"); rc = 0; result_current *= -1; i_result->result_ua = (int32_t) result_current; fail_release_vadc: rc = qpnp_vadc_iadc_sync_complete_request(iadc->vadc_dev, v_channel, v_result); if (rc) pr_err("Releasing VADC failed\n"); fail: iadc->iadc_mode_sel = false; if (iadc->iadc_poll_eoc) { pr_debug("releasing iadc eoc wakelock\n"); pm_relax(iadc->dev); } mutex_unlock(&iadc->adc->adc_lock); return rc; }
int32_t qpnp_iadc_vadc_sync_read(struct qpnp_iadc_chip *iadc, enum qpnp_iadc_channels i_channel, struct qpnp_iadc_result *i_result, enum qpnp_vadc_channels v_channel, struct qpnp_vadc_result *v_result) { int rc = 0, mode_sel = 0, num = 0, rsense_n_ohms = 0, sign = 0; uint16_t raw_data; int32_t rsense_u_ohms = 0; int64_t result_current; if (qpnp_iadc_is_valid(iadc) < 0) return -EPROBE_DEFER; mutex_lock(&iadc->adc->adc_lock); if (iadc->iadc_poll_eoc) { pr_debug("acquiring iadc eoc wakelock\n"); pm_stay_awake(iadc->dev); } iadc->iadc_mode_sel = true; rc = qpnp_vadc_iadc_sync_request(iadc->vadc_dev, v_channel); if (rc) { pr_err("Configuring VADC failed\n"); goto fail; } rc = qpnp_iadc_configure(iadc, i_channel, &raw_data, mode_sel); if (rc < 0) { pr_err("qpnp adc result read failed with %d\n", rc); goto fail_release_vadc; } rc = qpnp_iadc_get_rsense(iadc, &rsense_n_ohms); pr_debug("current raw:0%x and rsense:%d\n", raw_data, rsense_n_ohms); rsense_u_ohms = rsense_n_ohms/1000; num = raw_data - iadc->adc->calib.offset_raw; if (num < 0) { sign = 1; num = -num; } i_result->result_uv = (num * QPNP_ADC_GAIN_NV)/ (iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw); result_current = i_result->result_uv; result_current *= QPNP_IADC_NANO_VOLTS_FACTOR; /* Intentional fall through. Process the result w/o comp */ do_div(result_current, rsense_u_ohms); if (sign) { i_result->result_uv = -i_result->result_uv; result_current = -result_current; } result_current *= -1; rc = qpnp_iadc_comp_result(iadc, &result_current); if (rc < 0) pr_err("Error during compensating the IADC\n"); rc = 0; result_current *= -1; i_result->result_ua = (int32_t) result_current; fail_release_vadc: rc = qpnp_vadc_iadc_sync_complete_request(iadc->vadc_dev, v_channel, v_result); if (rc) pr_err("Releasing VADC failed\n"); fail: iadc->iadc_mode_sel = false; if (iadc->iadc_poll_eoc) { pr_debug("releasing iadc eoc wakelock\n"); pm_relax(iadc->dev); } mutex_unlock(&iadc->adc->adc_lock); return rc; }
int32_t qpnp_iadc_read(struct qpnp_iadc_chip *iadc, enum qpnp_iadc_channels channel, struct qpnp_iadc_result *result) { int32_t rc, rsense_n_ohms, sign = 0, num, mode_sel = 0; int32_t rsense_u_ohms = 0; int64_t result_current; uint16_t raw_data; if (qpnp_iadc_is_valid(iadc) < 0) return -EPROBE_DEFER; if ((iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw) == 0) { pr_err("raw offset errors! run iadc calibration again\n"); return -EINVAL; } rc = qpnp_check_pmic_temp(iadc); if (rc) { pr_err("Error checking pmic therm temp\n"); return rc; } mutex_lock(&iadc->adc->adc_lock); if (iadc->iadc_poll_eoc) { pr_debug("acquiring iadc eoc wakelock\n"); pm_stay_awake(iadc->dev); } rc = qpnp_iadc_configure(iadc, channel, &raw_data, mode_sel); if (rc < 0) { pr_err("qpnp adc result read failed with %d\n", rc); goto fail; } rc = qpnp_iadc_get_rsense(iadc, &rsense_n_ohms); pr_debug("current raw:0%x and rsense:%d\n", raw_data, rsense_n_ohms); rsense_u_ohms = rsense_n_ohms/1000; num = raw_data - iadc->adc->calib.offset_raw; if (num < 0) { sign = 1; num = -num; } result->result_uv = (num * QPNP_ADC_GAIN_NV)/ (iadc->adc->calib.gain_raw - iadc->adc->calib.offset_raw); result_current = result->result_uv; result_current *= QPNP_IADC_NANO_VOLTS_FACTOR; /* Intentional fall through. Process the result w/o comp */ do_div(result_current, rsense_u_ohms); if (sign) { result->result_uv = -result->result_uv; result_current = -result_current; } result_current *= -1; rc = qpnp_iadc_comp_result(iadc, &result_current); if (rc < 0) pr_err("Error during compensating the IADC\n"); rc = 0; result_current *= -1; result->result_ua = (int32_t) result_current; fail: if (iadc->iadc_poll_eoc) { pr_debug("releasing iadc eoc wakelock\n"); pm_relax(iadc->dev); } mutex_unlock(&iadc->adc->adc_lock); return rc; }