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: Subbaraman Narayanamurthy <subbaram@codeaurora.org>
This commit is contained in:
Subbaraman Narayanamurthy 2020-09-14 14:42:07 -07:00 committed by David Collins
parent 81fe95c85f
commit 5104aa0d97

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2018, 2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
*/
#include <linux/bitops.h>
@ -88,7 +88,7 @@
/* For PMIC7 */
#define ADC_APP_SID 0x40
#define ADC_APP_SID_MASK GENMASK(3, 0)
#define ADC7_CONV_TIMEOUT msecs_to_jiffies(10)
#define ADC7_CONV_TIMEOUT_MS 501
enum adc5_cal_method {
ADC5_NO_CAL = 0,
@ -365,6 +365,8 @@ static int adc7_do_conversion(struct adc5_chip *adc,
{
int ret;
u8 status;
unsigned long rc;
unsigned int time_pending_ms;
mutex_lock(&adc->lock);
@ -375,14 +377,44 @@ 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) {
dev_err(adc->dev, "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)
dev_warn(adc->dev, "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)
goto unlock;
if (status & ADC5_USR_STATUS1_CONV_FAULT) {
dev_err(adc->dev, "Unexpected conversion fault\n");
dev_err(adc->dev, "ADC channel %s unexpected conversion fault\n",
prop->datasheet_name);
ret = -EIO;
goto unlock;
}
if (!(status & ADC5_USR_STATUS1_EOC)) {
dev_err(adc->dev, "ADC channel %s EOC bit not set, status=%#x\n",
prop->datasheet_name, status);
ret = -EIO;
goto unlock;
}