Ejemplo n.º 1
0
static int qpnp_get_battery_current(int *current_ua)
{
	struct qpnp_iadc_result i_result;
	int ret;

	if (qpnp_iadc_is_ready()) {
		pr_err("%s: qpnp iadc is not ready!\n", __func__);
		*current_ua = 0;
		return 0;
	}

	ret = qpnp_iadc_read(EXTERNAL_RSENSE, &i_result);
	if (ret) {
		pr_err("%s: failed to read iadc\n", __func__);
		*current_ua = 0;
		return ret;
	}

	*current_ua = -i_result.result_ua;

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

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