From: Olivier MOYSAN <olivier.moysan@foss.st.com>
To: David Lechner <dlechner@baylibre.com>,
Jonathan Cameron <jic23@kernel.org>,
Lars-Peter Clausen <lars@metafoo.de>,
Maxime Coquelin <mcoquelin.stm32@gmail.com>,
Alexandre Torgue <alexandre.torgue@foss.st.com>
Cc: Fabrice Gasnier <fabrice.gasnier@foss.st.com>,
<linux-iio@vger.kernel.org>,
<linux-stm32@st-md-mailman.stormreply.com>,
<linux-arm-kernel@lists.infradead.org>,
<linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v2] iio: adc: stm32: add oversampling support
Date: Mon, 7 Apr 2025 18:07:17 +0200 [thread overview]
Message-ID: <6d12b6fe-85fb-4345-bf32-02c0fbb1a27a@foss.st.com> (raw)
In-Reply-To: <25b34e60-5392-4bfb-b994-49212dfbdb22@baylibre.com>
Hi David,
Thanks for reviewing,
On 4/4/25 18:15, David Lechner wrote:
> On 4/3/25 11:23 AM, Olivier Moysan wrote:
>> Add oversampling support for STM32H7, STM32MP15 & STM32MP13.
>> STM32F4 ADC has no oversampling feature.
>>
>> The current support of the oversampling feature aims at increasing
>> the data SNR, without changing the data resolution.
>> As the oversampling by itself increases data resolution,
>> a right shift is applied to keep initial resolution.
>
> Why do we not want the extra bits too? I guess if we wanted the extra bits
> in the future we could make the in_voltage_scale attribute writable to
> select the resolution.
>
Yes, I agree that the oversampling feature could could be further
exploited. It could also be used to increase the data resolution.
This additional feature can be managed as a separate patch later.
The main logic here was to keep the resolution aligned with the one
requested in the DT, through the "assigned-resolution-bits" property.
>> Only the oversampling ratio corresponding to a power of two are
>> supported here, to get a direct link between right shift and
>> oversampling ratio. (2exp(n) ratio <=> n right shift)
>>
>> The oversampling ratio is shared by all channels, whatever channel type.
>> (e.g. single ended or differential).
>>
>> Oversampling can be configured using IIO ABI:
>> - in_voltage_oversampling_ratio_available
>> - in_voltage_oversampling_ratio
>
> This would require info_mask_shared_by_type but the patch uses
> info_mask_shared_by_all, so the attributes will be:
>
> - oversampling_ratio
> - oversampling_ratio_available
>
> I guess currently it doesn't matter which one gets used if there are only
> voltage channels, but it could make a difference, e.g. if a temperature
> channel was ever added.
>
> In any case, the description should match what is actually implemented.
>
The oversampling configuration is shared by all the channels of a given
ADC instance. So, it makes sense to use info_mask_shared_by_all here.
What is the most relevant is to change the commit message to
"- oversampling_ratio
- oversampling_ratio_available"
which are the attributes actually exposed.
>>
>> Signed-off-by: Fabrice Gasnier <fabrice.gasnier@foss.st.com>
>> Signed-off-by: Olivier Moysan <olivier.moysan@foss.st.com>
>>
>> ---
>> Changes in v2:
>> - Remove useless header files
>> - Use FIELD_PREP macro
>> - Reorder stm32_adc_write_raw() function
>
> Link to v1? (for the lazy reviewer :-p)
>
>> ---
>> drivers/iio/adc/stm32-adc-core.h | 14 ++++
>> drivers/iio/adc/stm32-adc.c | 137 +++++++++++++++++++++++++++++++
>> 2 files changed, 151 insertions(+)
>>
>> diff --git a/drivers/iio/adc/stm32-adc-core.h b/drivers/iio/adc/stm32-adc-core.h
>> index 73b2c2e91c08..bfd42c5456bf 100644
>> --- a/drivers/iio/adc/stm32-adc-core.h
>> +++ b/drivers/iio/adc/stm32-adc-core.h
>> @@ -91,6 +91,7 @@
>> #define STM32H7_ADC_IER 0x04
>> #define STM32H7_ADC_CR 0x08
>> #define STM32H7_ADC_CFGR 0x0C
>> +#define STM32H7_ADC_CFGR2 0x10
>> #define STM32H7_ADC_SMPR1 0x14
>> #define STM32H7_ADC_SMPR2 0x18
>> #define STM32H7_ADC_PCSEL 0x1C
>> @@ -160,6 +161,13 @@
>> #define STM32H7_DMNGT_SHIFT 0
>> #define STM32H7_DMNGT_MASK GENMASK(1, 0)
>>
>> +/* STM32H7_ADC_CFGR2 bit fields */
>> +#define STM32H7_OVSR_MASK GENMASK(25, 16) /* Correspond to OSVR field in datasheet */
>
> nit: Comment seems obvious and can be left out.
>
Oversampling bit name is "OSVR" in datasheet H7, while oversampling
shift is "OVSS". For naming consistency, I used OVSR instead of OSVR,
and highlighted it with a comment. As an alternative, STM32H7_OVSR could
be renamed, but I would rather keep it unchanged.
>> +#define STM32H7_OVSR(v) FIELD_PREP(STM32H7_OVSR_MASK, v)
>> +#define STM32H7_OVSS_MASK GENMASK(8, 5)
>> +#define STM32H7_OVSS(v) FIELD_PREP(STM32H7_OVSS_MASK, v)
>> +#define STM32H7_ROVSE BIT(0)
>> +
>
> ...
>
>> +static const unsigned int stm32h7_adc_oversampling_avail[] = {
>> +1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024
>
> Normal style is to have 1 tab indent here.
>
ok
>> +};
>> +
>> +static const unsigned int stm32mp13_adc_oversampling_avail[] = {
>> +1, 2, 4, 8, 16, 32, 64, 128, 256
>
> And here.
>
ok
>> };
>>
>
> ...
>
>> @@ -889,6 +912,41 @@ static void stm32mp13_adc_start_conv(struct iio_dev *indio_dev, bool dma)
>> stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTART);
>> }
>>
>> +static void stm32h7_adc_set_ovs(struct iio_dev *indio_dev, u32 ovs_idx)
>> +{
>> + struct stm32_adc *adc = iio_priv(indio_dev);
>> + u32 ovsr_bits, bits, msk;
>> +
>> + msk = STM32H7_ROVSE | STM32H7_OVSR_MASK | STM32H7_OVSS_MASK;
>> + stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR2, msk);
>> +
>> + if (!ovs_idx)
>> + return;
>> +
>> + ovsr_bits = (1 << ovs_idx) - 1;
>> + bits = STM32H7_ROVSE | STM32H7_OVSS(ovs_idx) | STM32H7_OVSR(ovsr_bits);
>> +
>> + stm32_adc_set_bits(adc, STM32H7_ADC_CFGR2, bits & msk);
>> +}
>> +
>> +static void stm32mp13_adc_set_ovs(struct iio_dev *indio_dev, u32 ovs_idx)
>> +{
>> + struct stm32_adc *adc = iio_priv(indio_dev);
>> + u32 bits, msk;
>> +
>> + msk = STM32H7_ROVSE | STM32MP13_OVSR_MASK | STM32MP13_OVSS_MASK;
>> + stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR2, msk);
>> +
>> + if (!ovs_idx)
>> + return;
>> +
>> + bits = STM32H7_ROVSE | STM32MP13_OVSS(ovs_idx);
>> + if (ovs_idx - 1)
>> + bits |= STM32MP13_OVSR(ovs_idx - 1);
>> +
>> + stm32_adc_set_bits(adc, STM32H7_ADC_CFGR2, bits & msk);
>> +}
>
>
> Some comments in these functions could be useful to avoid needing the
> datasheet to understand all the different things that are happening here
> and more importantly, why it was decided to do it this way when there are
> many other possibilities (i.e. repeat the bit from commit message about
> always using 12-bit output).
>
ok, I will add some comments here.
>> @@ -1461,6 +1519,69 @@ static int stm32_adc_single_conv(struct iio_dev *indio_dev,
>> return ret;
>> }
>>
>> +static int stm32_adc_write_raw(struct iio_dev *indio_dev,
>> + struct iio_chan_spec const *chan,
>> + int val, int val2, long mask)
>> +{
>> + struct stm32_adc *adc = iio_priv(indio_dev);
>> + struct device *dev = indio_dev->dev.parent;
>> + int nb = adc->cfg->adc_info->num_ovs;
>> + u32 idx;
>> + int ret;
>> +
>> + switch (mask) {
>> + case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
>> + if (val2)
>> + return -EINVAL;
>> +
>> + for (idx = 0; idx < nb; idx++)
>> + if (adc->cfg->adc_info->oversampling[idx] == val)
>> + break;
>> +
>> + if (idx >= nb)
>> + return -EINVAL;
>> +
>> + ret = iio_device_claim_direct_mode(indio_dev);
>> + if (ret)
>> + return ret;
>
> We've been replacing this everywhere with:
>
> if (!iio_device_claim_direct(indio_dev))
> return -EBUSY;
>
> See: https://lore.kernel.org/linux-iio/20250331121317.1694135-1-jic23@kernel.org/
>
ok
>> +
>> + ret = pm_runtime_resume_and_get(dev);
>> + if (ret < 0)
>> + goto err;
>> +
>> + adc->cfg->set_ovs(indio_dev, idx);
>> +
>> + pm_runtime_mark_last_busy(dev);
>> + pm_runtime_put_autosuspend(dev);
>> +
>> + adc->ovs_idx = idx;
>> +
>> +err:
>> + iio_device_release_direct_mode(indio_dev);
>
> iio_device_release_direct(indio_dev);
>
>> +
>> + return ret;
>> + default:
>> + return -EINVAL;
>> + }
>> +}
BRs
Olivier
next prev parent reply other threads:[~2025-04-07 16:09 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-03 16:23 [PATCH v2] iio: adc: stm32: add oversampling support Olivier Moysan
2025-04-04 16:15 ` David Lechner
2025-04-07 16:07 ` Olivier MOYSAN [this message]
2025-04-08 14:43 ` David Lechner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=6d12b6fe-85fb-4345-bf32-02c0fbb1a27a@foss.st.com \
--to=olivier.moysan@foss.st.com \
--cc=alexandre.torgue@foss.st.com \
--cc=dlechner@baylibre.com \
--cc=fabrice.gasnier@foss.st.com \
--cc=jic23@kernel.org \
--cc=lars@metafoo.de \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-iio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-stm32@st-md-mailman.stormreply.com \
--cc=mcoquelin.stm32@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox