From: Jonathan Cameron <jic23@kernel.org>
To: Andrei Stancovici via B4 Relay
<devnull+andrei.stancovici.analog.com@kernel.org>
Cc: andrei.stancovici@analog.com, "Nuno Sá" <nuno.sa@analog.com>,
"Michael Hennerich" <Michael.Hennerich@analog.com>,
"David Lechner" <dlechner@baylibre.com>,
"Andy Shevchenko" <andy@kernel.org>,
"Rob Herring" <robh@kernel.org>,
"Krzysztof Kozlowski" <krzk+dt@kernel.org>,
"Conor Dooley" <conor+dt@kernel.org>,
"Liam Beguin" <liambeguin@gmail.com>,
linux@analog.com, linux-iio@vger.kernel.org,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 5/6] iio: adc: ltc2497: add FA/FB line-frequency rejection selection
Date: Sun, 18 Oct 2026 04:28:54 +0100 [thread overview]
Message-ID: <20261018042854.00c0d6a1@jic23-hlaptop> (raw)
In-Reply-To: <20261009-submission-ltc2493-support-v1-v1-5-3dad1d4b152a@analog.com>
On Fri, 09 Oct 2026 11:43:38 +0300
Andrei Stancovici via B4 Relay <devnull+andrei.stancovici.analog.com@kernel.org> wrote:
> From: Andrei Stancovici <andrei.stancovici@analog.com>
>
> The LTC2499 can suppress mains interference at 50Hz, 60Hz, or
> simultaneously at both (the power-up default). Expose it through
> filter_mode and filter_mode_available on the voltage channels.
>
> The conversion time also depends on the rejection mode: 50Hz-only is the
> longest at 163.5 ms (1x). The previous 150 ms budget was 13.5 ms short,
> risking a mid-conversion reprogram in 50Hz-only 1x mode.
>
> Tested on live LTC2499 hardware connected through an IIO network backend:
> all three modes are selectable and readable; voltage reads succeed in each
> mode; conversion times are respected; temperature reads honour the
> rejection selection.
>
> Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/2499fa.pdf
> Signed-off-by: Andrei Stancovici <andrei.stancovici@analog.com>
> ---
> drivers/iio/adc/ltc2497-core.c | 159 +++++++++++++++++++++++++++++++++--------
> drivers/iio/adc/ltc2497.c | 50 +++++++++----
> drivers/iio/adc/ltc2497.h | 44 +++++++++---
> 3 files changed, 200 insertions(+), 53 deletions(-)
>
> diff --git a/drivers/iio/adc/ltc2497-core.c b/drivers/iio/adc/ltc2497-core.c
> index 816312bf0e90..e5a8ab568128 100644
> --- a/drivers/iio/adc/ltc2497-core.c
> +++ b/drivers/iio/adc/ltc2497-core.c
> +
> +static int ltc2497core_set_filter_mode(struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan,
> + unsigned int val)
> +{
> + struct ltc2497core_driverdata *ddata = iio_priv(indio_dev);
> +
> + mutex_lock(&ddata->lock);
Can use a guard() here as well as below.
Maybe look more generally at making use of that newer stuff
in the driver (not as part of this series though!)
> + ddata->rejection = val;
> + /*
> + * The new rejection mode only takes effect once the second command byte
> + * is reprogrammed, so force the next read to reprogram rather than reuse
> + * the value already latched for this address. LTC2497_CONFIG_DEFAULT is
> + * not a valid channel/temperature address, so it is a safe re-arm
> + * sentinel (as used at probe).
> + *
> + * A conversion started under the old rejection mode may still be in
> + * flight; its own duration (conv_time_prev), not the new mode's, still
> + * gates the next reprogram, so the timing state is left untouched here.
> + */
> + ddata->addr_prev = LTC2497_CONFIG_DEFAULT;
> + mutex_unlock(&ddata->lock);
> +
> + return 0;
> +}
> +
> +static int ltc2497core_get_filter_mode(struct iio_dev *indio_dev,
> + const struct iio_chan_spec *chan)
> +{
> + struct ltc2497core_driverdata *ddata = iio_priv(indio_dev);
> + enum ltc2497_rejection rejection;
> +
> + mutex_lock(&ddata->lock);
Consider if worth doing:
guard(mutex)(&data->lock);
return ddata->rejection;
Trade off is looks different from existing code (unless you fancy
updating that as well).
> + rejection = ddata->rejection;
> + mutex_unlock(&ddata->lock);
> +
> + return rejection;
> +}
> #define LTC2497_CHAN(_chan, _addr, _ds_name, _extra_mask) { \
> .type = IIO_VOLTAGE, \
> .indexed = 1, \
> @@ -404,6 +484,27 @@ int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev)
> if (!ddata->chip_info->has_temp)
> indio_dev->num_channels--;
>
> + if (ddata->chip_info->has_rejection_mode) {
> + struct iio_chan_spec *channels;
> + unsigned int i;
> +
> + /*
> + * Rejection applies to every channel; ext_info is attached at
> + * probe because a const table would expose filter_mode on all
> + * parts unconditionally.
You could have a bonus set of channels to pick instead of using a copy
and update approach. As such I'd drop this comment as somewhat confusing.
The implementation is fine.
> + */
> + channels = devm_kmemdup(dev, indio_dev->channels,
> + indio_dev->num_channels * sizeof(*channels),
> + GFP_KERNEL);
> + if (!channels)
> + return -ENOMEM;
> +
> + for (i = 0; i < indio_dev->num_channels; i++)
> + channels[i].ext_info = ltc2497core_ext_info;
> +
> + indio_dev->channels = channels;
> + }
> diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c
> index a655b04e2454..0df2ad9b3243 100644
> --- a/drivers/iio/adc/ltc2497.c
> +++ b/drivers/iio/adc/ltc2497.c
> @@ -38,6 +38,23 @@ struct ltc2497_driverdata {
> } data __aligned(IIO_DMA_MINALIGN);
> };
>
> +/*
> + * The reserved FA = FB = 1 combination is not reachable: the enum has no
> + * enumerator for it.
> + */
> +static u8 ltc2497_rejection_bits(enum ltc2497_rejection rejection)
> +{
> + switch (rejection) {
> + case LTC2499_REJECT_50:
> + return LTC2499_FB;
> + case LTC2499_REJECT_60:
> + return LTC2499_FA;
As mentioned below, I'd use values 0 1 and 2 rather than the bit
values. That avoids the oddity of REJECT_50_60 not being b11 which
you'd expect if the bits were independent things.
> + case LTC2499_REJECT_50_60:
> + default:
> + return 0;
> + }
> +}
> diff --git a/drivers/iio/adc/ltc2497.h b/drivers/iio/adc/ltc2497.h
> index 219f7d49854b..34ea62c2a4bc 100644
> --- a/drivers/iio/adc/ltc2497.h
> +++ b/drivers/iio/adc/ltc2497.h
> /*
> * Sentinel passed as `address` to result_and_measure() to request a
> @@ -24,13 +28,29 @@
> /* Second config-byte bits (LTC2499 / LTC2493 only) */
> #define LTC2499_EN2 BIT(7) /* enable second config byte */
> #define LTC2499_IM BIT(6) /* 1 = measure internal temp sensor */
> +#define LTC2499_FA BIT(5) /* line-rejection select bit A */
> +#define LTC2499_FB BIT(4) /* line-rejection select bit B */
Hmm. Next to each other. Given reject both is b00 I'd just make these
a 2 bit field and have the values as 0, 1, 2
> #define LTC2499_SPD BIT(3) /* 1 = 2x output rate (offset cal off) */
>
> +/*
> + * Line-frequency rejection modes selected by FA/FB in the second config byte.
> + * The datasheet's fourth combination (FA = FB = 1) is reserved, so it is not
> + * given an enumerator and is unreachable through this driver.
I'd drop this bit. Not a detail we need to call out in the driver. If anyone
wonders, they can go look at the datasheet. If we called out every reserved
value we'd end up with a lot of boring docs!
> Applies to both
> + * voltage and temperature conversions (unlike SPD, which the part ignores while
> + * measuring temperature).
> + */
> +enum ltc2497_rejection {
> + LTC2499_REJECT_50_60, /* FA=0 FB=0: simultaneous 50/60Hz (default) */
> + LTC2499_REJECT_50, /* FA=0 FB=1: 50Hz only */
> + LTC2499_REJECT_60, /* FA=1 FB=0: 60Hz only */
> +};
>
> @@ -41,8 +61,14 @@ struct ltc2497core_driverdata {
> struct mutex lock;
> const struct ltc2497_chip_info *chip_info;
> u8 addr_prev;
> - bool speed_2x; /* SPD: false = 1x (default), true = 2x */
> - /* Conversion time (ms) of the conversion currently in flight. */
> + bool speed_2x; /* SPD: false = 1x (default), true = 2x */
I'm not seeing a clear advantage in changing that indent. So put it back
to reduce the noise in the patch.
> + enum ltc2497_rejection rejection; /* FA/FB line-rejection select */
> + /*
> + * Conversion time (ms) of the conversion currently in flight. It is
> + * fixed by the mode active when that conversion was started, which
> + * differs from the newly selected mode for the first read after a
> + * sampling_frequency or filter_mode change.
> + */
> unsigned int conv_time_prev;
> int (*result_and_measure)(struct ltc2497core_driverdata *ddata,
> u8 address, int *val);
>
next prev parent reply other threads:[~2026-10-18 3:29 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-09 8:43 [PATCH 0/6] iio: adc: ltc2497: add LTC2493 support and line-frequency rejection Andrei Stancovici via B4 Relay
2026-10-09 8:43 ` [PATCH 1/6] dt-bindings: iio: adc: lltc,ltc2497: add LTC2493 support Andrei Stancovici via B4 Relay
2026-10-09 12:06 ` Joshua Crofts
2026-10-09 14:45 ` Conor Dooley
2026-10-13 13:15 ` Nuno Sá
2026-10-09 8:43 ` [PATCH 2/6] iio: adc: ltc2497: " Andrei Stancovici via B4 Relay
2026-10-10 7:05 ` Joshua Crofts
2026-10-18 3:13 ` Jonathan Cameron
2026-10-09 8:43 ` [PATCH 3/6] iio: adc: ltc2497: add LTC2493 internal temperature channel Andrei Stancovici via B4 Relay
2026-10-13 13:15 ` Nuno Sá
2026-10-09 8:43 ` [PATCH 4/6] iio: adc: ltc2497: add 2x speed mode support for the LTC2493 Andrei Stancovici via B4 Relay
2026-10-09 8:43 ` [PATCH 5/6] iio: adc: ltc2497: add FA/FB line-frequency rejection selection Andrei Stancovici via B4 Relay
2026-10-18 3:28 ` Jonathan Cameron [this message]
2026-10-09 8:43 ` [PATCH 6/6] iio: adc: ltc2497: enable line-frequency rejection on LTC2493 Andrei Stancovici via B4 Relay
2026-10-18 3:30 ` Jonathan Cameron
2026-10-13 13:15 ` [PATCH 0/6] iio: adc: ltc2497: add LTC2493 support and line-frequency rejection Nuno Sá
2026-10-13 13:58 ` Andy Shevchenko
2026-10-13 15:09 ` Nuno Sá
2026-10-13 15:20 ` Andy Shevchenko
2026-10-18 3:17 ` Jonathan Cameron
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=20261018042854.00c0d6a1@jic23-hlaptop \
--to=jic23@kernel.org \
--cc=Michael.Hennerich@analog.com \
--cc=andrei.stancovici@analog.com \
--cc=andy@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=devnull+andrei.stancovici.analog.com@kernel.org \
--cc=dlechner@baylibre.com \
--cc=krzk+dt@kernel.org \
--cc=liambeguin@gmail.com \
--cc=linux-iio@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@analog.com \
--cc=nuno.sa@analog.com \
--cc=robh@kernel.org \
/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
all inboxes | Powered by JetHome®