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;
}