From 244435314b449b331fea963c6ab6a0ce4ce6ade1 Mon Sep 17 00:00:00 2001 From: Lukasz Madej Date: Mon, 8 Apr 2024 11:48:45 +0200 Subject: [PATCH] drivers: adc: adc_ad559x: improve adc read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use information encoded in conversion result value to validate it. Check if MSB bit is set to zero. Check if channel number included in the result matches channel number selected for conversion. Use bitmask to extract converted value instead of math calculations. (cherry picked from commit 71e7a77e99c320e1078f711076c513f0b37b2215) Original-Signed-off-by: Lukasz Madej GitOrigin-RevId: 71e7a77e99c320e1078f711076c513f0b37b2215 Change-Id: I023f3ecd1127f41df288e0ee89512b571cb14f5f Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/zephyr/+/5488598 Commit-Queue: Dawid Niedźwiecki Reviewed-by: Dawid Niedźwiecki Tested-by: ChromeOS Prod (Robot) Tested-by: Dawid Niedźwiecki --- drivers/adc/adc_ad559x.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/drivers/adc/adc_ad559x.c b/drivers/adc/adc_ad559x.c index 50a3d866290..21ee1e62e18 100644 --- a/drivers/adc/adc_ad559x.c +++ b/drivers/adc/adc_ad559x.c @@ -23,6 +23,10 @@ LOG_MODULE_REGISTER(adc_ad559x, CONFIG_ADC_LOG_LEVEL); #define AD559X_ADC_RESOLUTION 12U #define AD559X_ADC_VREF_MV 2500U +#define AD559X_ADC_RES_IND_BIT BIT(15) +#define AD559X_ADC_RES_CHAN_MASK GENMASK(14, 12) +#define AD559X_ADC_RES_VAL_MASK GENMASK(11, 0) + struct adc_ad559x_config { const struct device *mfd_dev; }; @@ -103,6 +107,7 @@ static int adc_ad559x_read_channel(const struct device *dev, uint8_t channel, ui { const struct adc_ad559x_config *config = dev->config; uint16_t val; + uint8_t conv_channel; int ret; /* Select channel */ @@ -142,11 +147,27 @@ static int adc_ad559x_read_channel(const struct device *dev, uint8_t channel, ui } val = sys_be16_to_cpu(val); - if (channel >= 1) { - val -= channel * BIT(AD559X_ADC_RESOLUTION); + + /* + * Invalid data: + * See "ADC section" in "Theory of operation" chapter. + * Valid ADC result has MSB bit set to 0. + */ + if ((val & AD559X_ADC_RES_IND_BIT) != 0) { + return -EAGAIN; + } + + /* + * Invalid channel converted: + * See "ADC section" in "Theory of operation" chapter. + * Conversion result contains channel number which should match requested channel. + */ + conv_channel = FIELD_GET(AD559X_ADC_RES_CHAN_MASK, val); + if (conv_channel != channel) { + return -EIO; } - *result = val; + *result = val & AD559X_ADC_RES_VAL_MASK; } return 0;