static int32_t qpnp_iadc_init_calib(void)
{
	struct qpnp_iadc_drv *iadc = qpnp_iadc;
	int32_t rc = 0, result;

	rc = qpnp_iadc_configure(GAIN_CALIBRATION_25MV, &result);
	if (rc < 0) {
		pr_err("qpnp adc result read failed with %d\n", rc);
		goto fail;
	}

	iadc->adc->calib.gain = result;

	rc = qpnp_iadc_configure(OFFSET_CALIBRATION_SHORT_CADC_LEADS,
								&result);
	if (rc < 0) {
		pr_err("qpnp adc result read failed with %d\n", rc);
		goto fail;
	}

	iadc->adc->calib.offset = result;

fail:
	return rc;
}
int32_t qpnp_iadc_read(enum qpnp_iadc_channels channel,
						int32_t *result)
{
	struct qpnp_iadc_drv *iadc = qpnp_iadc;
	int32_t vsense_mv = 0, rc;

	mutex_lock(&iadc->adc->adc_lock);

	if (!iadc->iadc_init_calib) {
		rc = qpnp_iadc_init_calib();
		if (!rc) {
			pr_err("Calibration failed\n");
			goto fail;
		} else
			iadc->iadc_init_calib = true;
	}

	rc = qpnp_iadc_configure(channel, result);
	if (rc < 0) {
		pr_err("qpnp adc result read failed with %d\n", rc);
		goto fail;
	}

	vsense_mv = ((*result - iadc->adc->calib.offset)/
			(iadc->adc->calib.gain - iadc->adc->calib.offset))
			* QPNP_ADC_GAIN_CALCULATION;

	*result = (vsense_mv/qpnp_iadc->rsense);

fail:
	mutex_unlock(&iadc->adc->adc_lock);

	return rc;
}
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_calibrate_for_trim(struct qpnp_iadc_chip *iadc,
                                     bool batfet_closed)
{
    uint8_t rslt_lsb, rslt_msb;
    int32_t rc = 0, version = 0;
    uint16_t raw_data;
    uint32_t mode_sel = 0;
    bool iadc_offset_ch_batfet_check;

    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->adc->amux_prop->decimation = DECIMATION_TYPE1;
    iadc->adc->amux_prop->fast_avg_setup = ADC_FAST_AVG_SAMPLE_1;

    rc = qpnp_iadc_configure(iadc, GAIN_CALIBRATION_17P857MV,
                             &raw_data, mode_sel);
    if (rc < 0) {
        pr_err("qpnp adc result read failed with %d\n", rc);
        goto fail;
    }

    iadc->adc->calib.gain_raw = raw_data;

    /*
     * there is a features on PM8941 in the BMS where if the batfet is
     * opened the BMS reads from INTERNAL_RSENSE (channel 0) actually go to
     * OFFSET_CALIBRATION_CSP_CSN (channel 5). Hence if batfet is opened
     * we have to calibrate based on OFFSET_CALIBRATION_CSP_CSN even for
     * internal rsense.
     */
    version = qpnp_adc_get_revid_version(iadc->dev);
    if ((version == QPNP_REV_ID_8941_3_1) ||
            (version == QPNP_REV_ID_8941_3_0) ||
            (version == QPNP_REV_ID_8941_2_0))
        iadc_offset_ch_batfet_check = true;
    else
        iadc_offset_ch_batfet_check = false;

    if ((iadc_offset_ch_batfet_check && !batfet_closed) ||
            (iadc->external_rsense)) {
        /* external offset calculation */
        rc = qpnp_iadc_configure(iadc, OFFSET_CALIBRATION_CSP_CSN,
                                 &raw_data, mode_sel);
        if (rc < 0) {
            pr_err("qpnp adc result read failed with %d\n", rc);
            goto fail;
        }
    } else {
        /* internal offset calculation */
        rc = qpnp_iadc_configure(iadc, OFFSET_CALIBRATION_CSP2_CSN2,
                                 &raw_data, mode_sel);
        if (rc < 0) {
            pr_err("qpnp adc result read failed with %d\n", rc);
            goto fail;
        }
    }

    iadc->adc->calib.offset_raw = raw_data;
    if (rc < 0) {
        pr_err("qpnp adc offset/gain calculation failed\n");
        goto fail;
    }

    if (iadc->iadc_comp.revision_dig_major == QPNP_IADC_PM8026_2_REV2
            && iadc->iadc_comp.revision_ana_minor ==
            QPNP_IADC_PM8026_2_REV3)
        iadc->adc->calib.gain_raw =
            iadc->adc->calib.offset_raw + IADC_IDEAL_RAW_GAIN;

    pr_debug("raw gain:0x%x, raw offset:0x%x\n",
             iadc->adc->calib.gain_raw, iadc->adc->calib.offset_raw);

    rc = qpnp_convert_raw_offset_voltage(iadc);
    if (rc < 0) {
        pr_err("qpnp raw_voltage conversion failed\n");
        goto fail;
    }

    rslt_msb = (raw_data & QPNP_RAW_CODE_16_BIT_MSB_MASK) >>
               QPNP_BIT_SHIFT_8;
    rslt_lsb = raw_data & QPNP_RAW_CODE_16_BIT_LSB_MASK;

    pr_debug("trim values:lsb:0x%x and msb:0x%x\n", rslt_lsb, rslt_msb);

    rc = qpnp_iadc_write_reg(iadc, QPNP_IADC_SEC_ACCESS,
                             QPNP_IADC_SEC_ACCESS_DATA);
    if (rc < 0) {
        pr_err("qpnp iadc configure error for sec access\n");
        goto fail;
    }

    rc = qpnp_iadc_write_reg(iadc, QPNP_IADC_MSB_OFFSET,
                             rslt_msb);
    if (rc < 0) {
        pr_err("qpnp iadc configure error for MSB write\n");
        goto fail;
    }

    rc = qpnp_iadc_write_reg(iadc, QPNP_IADC_SEC_ACCESS,
                             QPNP_IADC_SEC_ACCESS_DATA);
    if (rc < 0) {
        pr_err("qpnp iadc configure error for sec access\n");
        goto fail;
    }

    rc = qpnp_iadc_write_reg(iadc, QPNP_IADC_LSB_OFFSET,
                             rslt_lsb);
    if (rc < 0) {
        pr_err("qpnp iadc configure error for LSB write\n");
        goto fail;
    }
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;
}
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;
}
int32_t qpnp_iadc_calibrate_for_trim(struct qpnp_iadc_chip *iadc,
							bool batfet_closed)
{
	uint8_t rslt_lsb, rslt_msb;
	int32_t rc = 0, version = 0;
	uint16_t raw_data;
	uint32_t mode_sel = 0;
	bool iadc_offset_ch_batfet_check;

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

	rc = qpnp_iadc_configure(iadc, GAIN_CALIBRATION_17P857MV,
						&raw_data, mode_sel);
	if (rc < 0) {
		pr_err("qpnp adc result read failed with %d\n", rc);
		goto fail;
	}

	iadc->adc->calib.gain_raw = raw_data;

	version = qpnp_adc_get_revid_version(iadc->dev);
	if ((version == QPNP_REV_ID_8941_3_1) ||
			(version == QPNP_REV_ID_8941_3_0) ||
			(version == QPNP_REV_ID_8941_2_0))
		iadc_offset_ch_batfet_check = true;
	else
		iadc_offset_ch_batfet_check = false;

	if ((iadc_offset_ch_batfet_check && !batfet_closed) ||
						(iadc->external_rsense)) {
		
		rc = qpnp_iadc_configure(iadc, OFFSET_CALIBRATION_CSP_CSN,
						&raw_data, mode_sel);
		if (rc < 0) {
			pr_err("qpnp adc result read failed with %d\n", rc);
			goto fail;
		}
	} else {
		
		rc = qpnp_iadc_configure(iadc, OFFSET_CALIBRATION_CSP2_CSN2,
						&raw_data, mode_sel);
		if (rc < 0) {
			pr_err("qpnp adc result read failed with %d\n", rc);
			goto fail;
		}
	}

	iadc->adc->calib.offset_raw = raw_data;
	if (rc < 0) {
		pr_err("qpnp adc offset/gain calculation failed\n");
		goto fail;
	}

	if (iadc->iadc_comp.revision_dig_major == QPNP_IADC_PM8026_2_REV2
		&& iadc->iadc_comp.revision_ana_minor ==
						QPNP_IADC_PM8026_2_REV3)
		iadc->adc->calib.gain_raw =
			iadc->adc->calib.offset_raw + IADC_IDEAL_RAW_GAIN;

	pr_debug("raw gain:0x%x, raw offset:0x%x\n",
		iadc->adc->calib.gain_raw, iadc->adc->calib.offset_raw);

	rc = qpnp_convert_raw_offset_voltage(iadc);
	if (rc < 0) {
		pr_err("qpnp raw_voltage conversion failed\n");
		goto fail;
	}

	rslt_msb = (raw_data & QPNP_RAW_CODE_16_BIT_MSB_MASK) >>
							QPNP_BIT_SHIFT_8;
	rslt_lsb = raw_data & QPNP_RAW_CODE_16_BIT_LSB_MASK;

	pr_debug("trim values:lsb:0x%x and msb:0x%x\n", rslt_lsb, rslt_msb);

	rc = qpnp_iadc_write_reg(iadc, QPNP_IADC_SEC_ACCESS,
					QPNP_IADC_SEC_ACCESS_DATA);
	if (rc < 0) {
		pr_err("qpnp iadc configure error for sec access\n");
		goto fail;
	}

	rc = qpnp_iadc_write_reg(iadc, QPNP_IADC_MSB_OFFSET,
						rslt_msb);
	if (rc < 0) {
		pr_err("qpnp iadc configure error for MSB write\n");
		goto fail;
	}

	rc = qpnp_iadc_write_reg(iadc, QPNP_IADC_SEC_ACCESS,
					QPNP_IADC_SEC_ACCESS_DATA);
	if (rc < 0) {
		pr_err("qpnp iadc configure error for sec access\n");
		goto fail;
	}

	rc = qpnp_iadc_write_reg(iadc, QPNP_IADC_LSB_OFFSET,
						rslt_lsb);
	if (rc < 0) {
		pr_err("qpnp iadc configure error for LSB write\n");
		goto fail;
	}
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;
}
int32_t qpnp_iadc_calibrate_for_trim(void)
{
	struct qpnp_iadc_drv *iadc = qpnp_iadc;
	uint8_t rslt_lsb, rslt_msb;
	int32_t rc = 0;
	uint16_t raw_data;
	uint32_t mode_sel = 0;

	if (!iadc || !iadc->iadc_initialized)
		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);
	}

	/* Exported symbol may be called from outside this driver.
	 * Ensure this driver is ready (probed) before supporting
	 * calibration.
	 */
	rc = qpnp_iadc_is_ready();
	if (rc < 0)
		goto fail;

	rc = qpnp_iadc_configure(GAIN_CALIBRATION_17P857MV,
					&raw_data, mode_sel);
	if (rc < 0) {
		pr_err("qpnp adc result read failed with %d\n", rc);
		goto fail;
	}

	iadc->adc->calib.gain_raw = raw_data;

	if (iadc->external_rsense) {
		/* external offset calculation */
		rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP_CSN,
						&raw_data, mode_sel);
		if (rc < 0) {
			pr_err("qpnp adc result read failed with %d\n", rc);
			goto fail;
		}
	} else {
		/* internal offset calculation */
		rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP2_CSN2,
						&raw_data, mode_sel);
		if (rc < 0) {
			pr_err("qpnp adc result read failed with %d\n", rc);
			goto fail;
		}
	}

	iadc->adc->calib.offset_raw = raw_data;
	if (rc < 0) {
		pr_err("qpnp adc offset/gain calculation failed\n");
		goto fail;
	}

	pr_debug("raw gain:0x%x, raw offset:0x%x\n",
		iadc->adc->calib.gain_raw, iadc->adc->calib.offset_raw);

	rc = qpnp_convert_raw_offset_voltage();
	if (rc < 0) {
		pr_err("qpnp raw_voltage conversion failed\n");
		goto fail;
	}

	rslt_msb = (raw_data & QPNP_RAW_CODE_16_BIT_MSB_MASK) >>
							QPNP_BIT_SHIFT_8;
	rslt_lsb = raw_data & QPNP_RAW_CODE_16_BIT_LSB_MASK;

	pr_debug("trim values:lsb:0x%x and msb:0x%x\n", rslt_lsb, rslt_msb);

	rc = qpnp_iadc_write_reg(QPNP_IADC_SEC_ACCESS,
					QPNP_IADC_SEC_ACCESS_DATA);
	if (rc < 0) {
		pr_err("qpnp iadc configure error for sec access\n");
		goto fail;
	}

	rc = qpnp_iadc_write_reg(QPNP_IADC_MSB_OFFSET,
						rslt_msb);
	if (rc < 0) {
		pr_err("qpnp iadc configure error for MSB write\n");
		goto fail;
	}

	rc = qpnp_iadc_write_reg(QPNP_IADC_SEC_ACCESS,
					QPNP_IADC_SEC_ACCESS_DATA);
	if (rc < 0) {
		pr_err("qpnp iadc configure error for sec access\n");
		goto fail;
	}

	rc = qpnp_iadc_write_reg(QPNP_IADC_LSB_OFFSET,
						rslt_lsb);
	if (rc < 0) {
		pr_err("qpnp iadc configure error for LSB write\n");
		goto fail;
	}
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;
}
Пример #10
0
int32_t qpnp_iadc_calibrate_for_trim(void)
{
	struct qpnp_iadc_drv *iadc = qpnp_iadc;
	uint8_t rslt_lsb, rslt_msb;
	int32_t rc = 0;
	uint16_t raw_data;
	uint32_t mode_sel = 0;

	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(GAIN_CALIBRATION_17P857MV,
						&raw_data, mode_sel);
	if (rc < 0) {
		pr_err("qpnp adc result read failed with %d\n", rc);
		goto fail;
	}

	iadc->adc->calib.gain_raw = raw_data;

	rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP2_CSN2,
						&raw_data, mode_sel);
	if (rc < 0) {
		pr_err("qpnp adc result read failed with %d\n", rc);
		goto fail;
	}

	iadc->adc->calib.offset_raw = raw_data;
	if (rc < 0) {
		pr_err("qpnp adc offset/gain calculation failed\n");
		goto fail;
	}

	pr_debug("raw gain:0x%x, raw offset:0x%x\n",
		iadc->adc->calib.gain_raw, iadc->adc->calib.offset_raw);

	rc = qpnp_convert_raw_offset_voltage();
	if (rc < 0) {
		pr_err("qpnp raw_voltage conversion failed\n");
		goto fail;
	}

	rslt_msb = (raw_data & QPNP_RAW_CODE_16_BIT_MSB_MASK) >>
							QPNP_BIT_SHIFT_8;
	rslt_lsb = raw_data & QPNP_RAW_CODE_16_BIT_LSB_MASK;

	pr_debug("trim values:lsb:0x%x and msb:0x%x\n", rslt_lsb, rslt_msb);

	rc = qpnp_iadc_write_reg(QPNP_IADC_SEC_ACCESS,
					QPNP_IADC_SEC_ACCESS_DATA);
	if (rc < 0) {
		pr_err("qpnp iadc configure error for sec access\n");
		goto fail;
	}

	rc = qpnp_iadc_write_reg(QPNP_IADC_MSB_OFFSET,
						rslt_msb);
	if (rc < 0) {
		pr_err("qpnp iadc configure error for MSB write\n");
		goto fail;
	}

	rc = qpnp_iadc_write_reg(QPNP_IADC_SEC_ACCESS,
					QPNP_IADC_SEC_ACCESS_DATA);
	if (rc < 0) {
		pr_err("qpnp iadc configure error for sec access\n");
		goto fail;
	}

	rc = qpnp_iadc_write_reg(QPNP_IADC_LSB_OFFSET,
						rslt_lsb);
	if (rc < 0) {
		pr_err("qpnp iadc configure error for LSB write\n");
		goto fail;
	}
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;
}
Пример #11
0
static int32_t qpnp_iadc_calibrate_for_trim(void)
{
	struct qpnp_iadc_drv *iadc = qpnp_iadc;
	uint8_t rslt_lsb, rslt_msb;
	int32_t rc = 0;
	uint16_t raw_data;
	uint32_t mode_sel = 0;

	rc = qpnp_iadc_configure(GAIN_CALIBRATION_17P857MV,
						&raw_data, mode_sel);
	if (rc < 0) {
		pr_err("qpnp adc result read failed with %d\n", rc);
		goto fail;
	}

	iadc->adc->calib.gain_raw = raw_data;

	rc = qpnp_iadc_configure(OFFSET_CALIBRATION_CSP2_CSN2,
						&raw_data, mode_sel);
	if (rc < 0) {
		pr_err("qpnp adc result read failed with %d\n", rc);
		goto fail;
	}

	iadc->adc->calib.offset_raw = raw_data;
	if (rc < 0) {
		pr_err("qpnp adc offset/gain calculation failed\n");
		goto fail;
	}

	rc = qpnp_convert_raw_offset_voltage();

	rslt_msb = (raw_data & QPNP_RAW_CODE_16_BIT_MSB_MASK) >>
							QPNP_BIT_SHIFT_8;
	rslt_lsb = raw_data & QPNP_RAW_CODE_16_BIT_LSB_MASK;

	rc = qpnp_iadc_write_reg(QPNP_IADC_SEC_ACCESS,
					QPNP_IADC_SEC_ACCESS_DATA);
	if (rc < 0) {
		pr_err("qpnp iadc configure error for sec access\n");
		goto fail;
	}

	rc = qpnp_iadc_write_reg(QPNP_IADC_MSB_OFFSET,
						rslt_msb);
	if (rc < 0) {
		pr_err("qpnp iadc configure error for MSB write\n");
		goto fail;
	}

	rc = qpnp_iadc_write_reg(QPNP_IADC_SEC_ACCESS,
					QPNP_IADC_SEC_ACCESS_DATA);
	if (rc < 0) {
		pr_err("qpnp iadc configure error for sec access\n");
		goto fail;
	}

	rc = qpnp_iadc_write_reg(QPNP_IADC_LSB_OFFSET,
						rslt_lsb);
	if (rc < 0) {
		pr_err("qpnp iadc configure error for LSB write\n");
		goto fail;
	}
fail:
	return rc;
}