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

Commit cdc861b1 authored by Subbaraman Narayanamurthy's avatar Subbaraman Narayanamurthy
Browse files

iio: qcom-spmi-adc5: Handle EOC properly



Currently, when an ADC7 channel is read, there is a wait time of
10 ms where an EOC (end of conversion) interrupt should happen
thereby completing the wait for ADC conversion. However, if this
wait times out, it is not handled and stale data can be read. Add
error logs to print when this wait times out as well as if EOC
bit is not set and return an error.

Also, this 10 ms wait time for EOC after requesting for a channel
conversion is not sufficient. As per the hardware recommendation
when multiple subsystems requests PMIC HW arbiter to read same
or different channels on different PMICs simultaneously, it could
take 15 ms for a good case i.e. where all the conversion requests
went through successfully. However, for a worst case where this
conversion request times out, it could take up to 500 ms before
an EOC interrupt is sent by PBS to SW. Hence, increase conversion
wait time to 501 ms so that no other channel reads can be made in
the worst case. Also print a warning when the wait time for EOC
is more than 15 ms.

Change-Id: I69eeade3e85f740af10cd7a3d668e67f67f6617d
Signed-off-by: default avatarSubbaraman Narayanamurthy <subbaram@codeaurora.org>
parent 522ef887
Loading
Loading
Loading
Loading
+34 −4
Original line number Diff line number Diff line
@@ -87,7 +87,7 @@
/* For PMIC7 */
#define ADC_APP_SID				0x40
#define ADC_APP_SID_MASK			0xf
#define ADC7_CONV_TIMEOUT			msecs_to_jiffies(10)
#define ADC7_CONV_TIMEOUT_MS			501

enum adc5_cal_method {
	ADC5_NO_CAL = 0,
@@ -427,6 +427,8 @@ static int adc7_do_conversion(struct adc5_chip *adc,
			u16 *data_volt, u16 *data_cur)
{
	int ret;
	unsigned long rc;
	unsigned int time_pending_ms;
	u8 status = 0;

	mutex_lock(&adc->lock);
@@ -438,15 +440,43 @@ static int adc7_do_conversion(struct adc5_chip *adc,
	}

	/* No support for polling mode at present*/
	wait_for_completion_timeout(&adc->complete,
					ADC7_CONV_TIMEOUT);
	rc = wait_for_completion_timeout(&adc->complete,
					msecs_to_jiffies(ADC7_CONV_TIMEOUT_MS));
	if (!rc) {
		pr_err("Reading ADC channel %s timed out\n",
			prop->datasheet_name);
		ret = -ETIMEDOUT;
		goto unlock;
	}

	/*
	 * As per the hardware documentation, EOC should happen within 15 ms
	 * in a good case where there could be multiple conversion requests
	 * going through PMIC HW arbiter for reading ADC channels. However, if
	 * for some reason, one of the conversion request fails and times out,
	 * worst possible delay can be 500 ms. Hence print a warning when we
	 * see EOC completion happened more than 15 ms.
	 */
	time_pending_ms = jiffies_to_msecs(rc);
	if (time_pending_ms < ADC7_CONV_TIMEOUT_MS &&
	    (ADC7_CONV_TIMEOUT_MS - time_pending_ms) > 15)
		pr_warn("ADC channel %s EOC took %u ms\n", prop->datasheet_name,
			ADC7_CONV_TIMEOUT_MS - time_pending_ms);

	ret = adc5_read(adc, ADC5_USR_STATUS1, &status, 1);
	if (ret < 0)
		goto unlock;

	if (status & ADC5_USR_STATUS1_CONV_FAULT) {
		pr_err("Unexpected conversion fault\n");
		pr_err("ADC channel %s unexpected conversion fault\n",
			prop->datasheet_name);
		ret = -EIO;
		goto unlock;
	}

	if (!(status & ADC5_USR_STATUS1_EOC)) {
		pr_err("ADC channel %s EOC bit not set, status=%#x\n",
			prop->datasheet_name, status);
		ret = -EIO;
		goto unlock;
	}