Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e2a77e0e authored by Siddartha Mohanadoss's avatar Siddartha Mohanadoss Committed by Matt Wagantall
Browse files

hwmon: qpnp-adc: Add support to vote for a regulator



Add support to vote for HKADC LDO and HKADC LDO ok signal
if needed.

Change-Id: I92dcb8bf0495e93a8eaedabfbd82c3cc9a527f7c
Signed-off-by: default avatarSiddartha Mohanadoss <smohanad@codeaurora.org>
parent d92c6fed
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -37,7 +37,8 @@ Optional properties:
			   to set temperature thresholds and receive notification when the temperature
			   crosses a set threshold, read temperature and enable/set trip types supported
			   by the thermal framework.

- hkadc_ldo-supply : Add this property if VADC needs to perform a Software Vote for the HKADC.
- hkadc_ok-supply : Add this property if the VADC needs to perform a Software vote for the HKADC VREG_OK.

Client required property:
- qcom,<consumer name>-vadc : The phandle to the corresponding vadc device.
+2 −0
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@ Optional properties:
		1 : Select Timer 2 for a measurement polling interval of 1 second.
		2 : Select Timer 3 for a measurement polling interval of 4 seconds.
- qcom,adc-tm-recalib-check: Add this property to check if recalibration required due to inaccuracy.
- hkadc_ldo-supply : Add this property if VADC needs to perform a Software Vote for the HKADC.
- hkadc_ok-supply : Add this property if the VADC needs to perform a Software vote for the HKADC VREG_OK.

Client required property:
- qcom,<consumer name>-adc_tm : The phandle to the corresponding adc_tm device.
+91 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -35,6 +35,10 @@
/* Max ADC code represents full-scale range of 1.8V */
#define QPNP_VADC_MAX_ADC_CODE			0xA800
#define KELVINMIL_DEGMIL	273160
#define QPNP_VADC_LDO_VOLTAGE_MIN	1800000
#define QPNP_VADC_LDO_VOLTAGE_MAX	1800000
#define QPNP_VADC_OK_VOLTAGE_MIN	1000000
#define QPNP_VADC_OK_VOLTAGE_MAX	1000000

/* Units for temperature below (on x axis) is in 0.1DegC as
   required by the battery driver. Note the resolution used
@@ -1543,6 +1547,51 @@ int32_t qpnp_vadc_check_result(int32_t *data, bool recalib_check)
}
EXPORT_SYMBOL(qpnp_vadc_check_result);

int32_t qpnp_adc_enable_voltage(struct qpnp_adc_drv *adc)
{
	int rc = 0;

	if (adc->hkadc_ldo) {
		rc = regulator_enable(adc->hkadc_ldo);
		if (rc < 0) {
			pr_err("Failed to enable hkadc ldo\n");
			return rc;
		}
	}

	if (adc->hkadc_ldo_ok) {
		rc = regulator_enable(adc->hkadc_ldo_ok);
		if (rc < 0) {
			pr_err("Failed to enable hkadc ok signal\n");
			return rc;
		}
	}

	return rc;
}
EXPORT_SYMBOL(qpnp_adc_enable_voltage);

void qpnp_adc_disable_voltage(struct qpnp_adc_drv *adc)
{
	if (adc->hkadc_ldo)
		regulator_disable(adc->hkadc_ldo);

	if (adc->hkadc_ldo_ok)
		regulator_disable(adc->hkadc_ldo_ok);

}
EXPORT_SYMBOL(qpnp_adc_disable_voltage);

void qpnp_adc_free_voltage_resource(struct qpnp_adc_drv *adc)
{
	if (adc->hkadc_ldo)
		regulator_put(adc->hkadc_ldo);

	if (adc->hkadc_ldo_ok)
		regulator_put(adc->hkadc_ldo_ok);
}
EXPORT_SYMBOL(qpnp_adc_free_voltage_resource);

int qpnp_adc_get_revid_version(struct device *dev)
{
	struct pmic_revid_data *revid_data;
@@ -1826,6 +1875,47 @@ int32_t qpnp_adc_get_devicetree_data(struct spmi_device *spmi,

	init_completion(&adc_qpnp->adc_rslt_completion);

	if (of_get_property(node, "hkadc_ldo-supply", NULL)) {
		adc_qpnp->hkadc_ldo = regulator_get(&spmi->dev,
				"hkadc_ldo");
		if (IS_ERR(adc_qpnp->hkadc_ldo)) {
			pr_err("hkadc_ldo-supply node not found\n");
			return -EINVAL;
		}

		rc = regulator_set_voltage(adc_qpnp->hkadc_ldo,
				QPNP_VADC_LDO_VOLTAGE_MIN,
				QPNP_VADC_LDO_VOLTAGE_MAX);
		if (rc < 0) {
			pr_err("setting voltage for hkadc_ldo failed\n");
			return rc;
		}

		rc = regulator_set_optimum_mode(adc_qpnp->hkadc_ldo,
				100000);
		if (rc < 0) {
			pr_err("hkadc_ldo optimum mode failed%d\n", rc);
			return rc;
		}
	}

	if (of_get_property(node, "hkadc_ok-supply", NULL)) {
		adc_qpnp->hkadc_ldo_ok = regulator_get(&spmi->dev,
				"hkadc_ok");
		if (IS_ERR(adc_qpnp->hkadc_ldo_ok)) {
			pr_err("hkadc_ok node not found\n");
			return -EINVAL;
		}

		rc = regulator_set_voltage(adc_qpnp->hkadc_ldo_ok,
				QPNP_VADC_OK_VOLTAGE_MIN,
				QPNP_VADC_OK_VOLTAGE_MAX);
		if (rc < 0) {
			pr_err("setting voltage for hkadc-ldo-ok failed\n");
			return rc;
		}
	}

	return 0;
}
EXPORT_SYMBOL(qpnp_adc_get_devicetree_data);
+14 −1
Original line number Diff line number Diff line
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -267,6 +267,14 @@ static int32_t qpnp_vadc_enable(struct qpnp_vadc_chip *vadc, bool state)

	data = QPNP_VADC_EN;
	if (state) {
		if (vadc->adc->hkadc_ldo && vadc->adc->hkadc_ldo_ok) {
			rc = qpnp_adc_enable_voltage(vadc->adc);
			if (rc) {
				pr_err("failed enabling VADC LDO\n");
				return rc;
			}
		}

		rc = qpnp_vadc_write_reg(vadc, QPNP_VADC_EN_CTL1,
					data);
		if (rc < 0) {
@@ -280,6 +288,9 @@ static int32_t qpnp_vadc_enable(struct qpnp_vadc_chip *vadc, bool state)
			pr_err("VADC disable failed\n");
			return rc;
		}

		if (vadc->adc->hkadc_ldo && vadc->adc->hkadc_ldo_ok)
			qpnp_adc_disable_voltage(vadc->adc);
	}

	return 0;
@@ -2376,6 +2387,8 @@ static int qpnp_vadc_remove(struct spmi_device *spmi)
	}
	hwmon_device_unregister(vadc->vadc_hwmon);
	list_del(&vadc->list);
	if (vadc->adc->hkadc_ldo && vadc->adc->hkadc_ldo_ok)
		qpnp_adc_free_voltage_resource(vadc->adc);
	dev_set_drvdata(&spmi->dev, NULL);

	return 0;
+70 −5
Original line number Diff line number Diff line
/* Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -169,7 +169,7 @@

#define QPNP_MIN_TIME			2000
#define QPNP_MAX_TIME			2100
#define QPNP_RETRY			25
#define QPNP_RETRY			1000

struct qpnp_adc_thr_client_info {
	struct list_head		list;
@@ -215,6 +215,7 @@ struct qpnp_adc_tm_chip {
	struct workqueue_struct		*low_thr_wq;
	struct work_struct		trigger_high_thr_work;
	struct work_struct		trigger_low_thr_work;
	bool				adc_vote_enable;
	struct qpnp_adc_tm_sensor	sensor[0];
};

@@ -350,11 +351,35 @@ static int32_t qpnp_adc_tm_fast_avg_en(struct qpnp_adc_tm_chip *chip,
	return rc;
}

static int qpnp_adc_tm_check_vreg_vote(struct qpnp_adc_tm_chip *chip)
{
	int rc = 0;

	if (!chip->adc_vote_enable) {
		if (chip->adc->hkadc_ldo && chip->adc->hkadc_ldo_ok) {
			rc = qpnp_adc_enable_voltage(chip->adc);
			if (rc) {
				pr_err("failed enabling VADC LDO\n");
				return rc;
			}
			chip->adc_vote_enable = true;
		}
	}

	return rc;
}

static int32_t qpnp_adc_tm_enable(struct qpnp_adc_tm_chip *chip)
{
	int rc = 0;
	u8 data = 0;

	rc = qpnp_adc_tm_check_vreg_vote(chip);
	if (rc) {
		pr_err("ADC TM VREG enable failed:%d\n", rc);
		return rc;
	}

	data = QPNP_ADC_TM_EN;
	rc = qpnp_adc_tm_write_reg(chip, QPNP_EN_CTL1, data);
	if (rc < 0)
@@ -369,8 +394,10 @@ static int32_t qpnp_adc_tm_disable(struct qpnp_adc_tm_chip *chip)
	int rc = 0;

	rc = qpnp_adc_tm_write_reg(chip, QPNP_EN_CTL1, data);
	if (rc < 0)
	if (rc < 0) {
		pr_err("adc-tm disable failed\n");
		return rc;
	}

	return rc;
}
@@ -389,7 +416,7 @@ static int qpnp_adc_tm_is_valid(struct qpnp_adc_tm_chip *chip)
static int32_t qpnp_adc_tm_enable_if_channel_meas(
					struct qpnp_adc_tm_chip *chip)
{
	u8 adc_tm_meas_en = 0;
	u8 adc_tm_meas_en = 0, status_low = 0, status_high = 0;
	int rc = 0;

	/* Check if a measurement request is still required */
@@ -400,8 +427,22 @@ static int32_t qpnp_adc_tm_enable_if_channel_meas(
		return rc;
	}

	rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_LOW_THR_INT_EN,
							&status_low);
	if (rc) {
		pr_err("adc-tm-tm read status low failed with %d\n", rc);
		return rc;
	}

	rc = qpnp_adc_tm_read_reg(chip, QPNP_ADC_TM_HIGH_THR_INT_EN,
							&status_high);
	if (rc) {
		pr_err("adc-tm-tm read status high failed with %d\n", rc);
		return rc;
	}

	/* Enable only if there are pending measurement requests */
	if (adc_tm_meas_en) {
	if ((adc_tm_meas_en && status_high) || (adc_tm_meas_en && status_low)) {
		qpnp_adc_tm_enable(chip);

		/* Request conversion */
@@ -411,6 +452,13 @@ static int32_t qpnp_adc_tm_enable_if_channel_meas(
			pr_err("adc-tm request conversion failed\n");
			return rc;
		}
	} else {
		/* disable the vote if applicable */
		if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
					chip->adc->hkadc_ldo_ok) {
			qpnp_adc_disable_voltage(chip->adc);
			chip->adc_vote_enable = false;
		}
	}

	return rc;
@@ -1871,6 +1919,13 @@ static void qpnp_adc_tm_high_thr_work(struct work_struct *work)
			struct qpnp_adc_tm_chip, trigger_high_thr_work);
	int rc;

	/* disable the vote if applicable */
	if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
					chip->adc->hkadc_ldo_ok) {
		qpnp_adc_disable_voltage(chip->adc);
		chip->adc_vote_enable = false;
	}

	rc = qpnp_adc_tm_read_status(chip);
	if (rc < 0)
		pr_err("adc-tm high thr work failed\n");
@@ -1901,6 +1956,13 @@ static void qpnp_adc_tm_low_thr_work(struct work_struct *work)
			struct qpnp_adc_tm_chip, trigger_low_thr_work);
	int rc;

	/* disable the vote if applicable */
	if (chip->adc_vote_enable && chip->adc->hkadc_ldo &&
					chip->adc->hkadc_ldo_ok) {
		qpnp_adc_disable_voltage(chip->adc);
		chip->adc_vote_enable = false;
	}

	rc = qpnp_adc_tm_read_status(chip);
	if (rc < 0)
		pr_err("adc-tm low thr work failed\n");
@@ -2355,6 +2417,7 @@ static int qpnp_adc_tm_probe(struct spmi_device *spmi)
		enable_irq_wake(chip->adc->adc_low_thr_irq);
	}

	chip->adc_vote_enable = false;
	dev_set_drvdata(&spmi->dev, chip);
	list_add(&chip->list, &qpnp_adc_tm_device_list);

@@ -2401,6 +2464,8 @@ static int qpnp_adc_tm_remove(struct spmi_device *spmi)
		destroy_workqueue(chip->high_thr_wq);
	if (chip->low_thr_wq)
		destroy_workqueue(chip->low_thr_wq);
	if (chip->adc->hkadc_ldo && chip->adc->hkadc_ldo_ok)
		qpnp_adc_free_voltage_resource(chip->adc);
	dev_set_drvdata(&spmi->dev, NULL);

	return 0;
Loading