* [PATCH v4 1/5] iio: adc: ad7380: do not use iio_device_claim_direct_scoped anymore
2025-01-08 12:49 [PATCH v4 0/5] iio: adc: ad7380: add alert support Julien Stephan
@ 2025-01-08 12:49 ` Julien Stephan
2025-01-12 16:29 ` Andy Shevchenko
2025-01-08 12:49 ` [PATCH v4 2/5] iio: adc: ad7380: enable regmap cache Julien Stephan
` (4 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Julien Stephan @ 2025-01-08 12:49 UTC (permalink / raw)
To: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
David Lechner, Jonathan Cameron, Jonathan Corbet
Cc: linux-iio, linux-kernel, linux-doc, Julien Stephan
Conditionnal scoped handlers are turning out to be a real pain:
readability issues, compiler and linker handling issues among others so
rollback and remove the scoped version of iio_dvice_claim_direct_mode.
To impove code readability factorize code to set oversampling ratio.
Signed-off-by: Julien Stephan <jstephan@baylibre.com>
---
drivers/iio/adc/ad7380.c | 110 +++++++++++++++++++++++++++++------------------
1 file changed, 67 insertions(+), 43 deletions(-)
diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c
index 4f32cb22f140442b831dc9a4f275e88e4ab2388e..bc7d58850a3e2a84a241d81377e3dc14c43fc101 100644
--- a/drivers/iio/adc/ad7380.c
+++ b/drivers/iio/adc/ad7380.c
@@ -675,15 +675,21 @@ static const struct regmap_config ad7380_regmap_config = {
static int ad7380_debugfs_reg_access(struct iio_dev *indio_dev, u32 reg,
u32 writeval, u32 *readval)
{
- iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
- struct ad7380_state *st = iio_priv(indio_dev);
+ struct ad7380_state *st = iio_priv(indio_dev);
+ int ret;
- if (readval)
- return regmap_read(st->regmap, reg, readval);
- else
- return regmap_write(st->regmap, reg, writeval);
- }
- unreachable();
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ if (readval)
+ ret = regmap_read(st->regmap, reg, readval);
+ else
+ ret = regmap_write(st->regmap, reg, writeval);
+
+ iio_device_release_direct_mode(indio_dev);
+
+ return ret;
}
/*
@@ -920,6 +926,7 @@ static int ad7380_read_raw(struct iio_dev *indio_dev,
{
struct ad7380_state *st = iio_priv(indio_dev);
const struct iio_scan_type *scan_type;
+ int ret;
scan_type = iio_get_current_scan_type(indio_dev, chan);
@@ -928,11 +935,16 @@ static int ad7380_read_raw(struct iio_dev *indio_dev,
switch (info) {
case IIO_CHAN_INFO_RAW:
- iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
- return ad7380_read_direct(st, chan->scan_index,
- scan_type, val);
- }
- unreachable();
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = ad7380_read_direct(st, chan->scan_index,
+ scan_type, val);
+
+ iio_device_release_direct_mode(indio_dev);
+
+ return ret;
case IIO_CHAN_INFO_SCALE:
/*
* According to the datasheet, the LSB size is:
@@ -1008,47 +1020,59 @@ static int ad7380_osr_to_regval(int ratio)
return -EINVAL;
}
+static int ad7380_set_oversampling_ratio(struct ad7380_state *st, int val)
+{
+ int ret, osr, boost;
+
+ osr = ad7380_osr_to_regval(val);
+ if (osr < 0)
+ return osr;
+
+ /* always enable resolution boost when oversampling is enabled */
+ boost = osr > 0 ? 1 : 0;
+
+ ret = regmap_update_bits(st->regmap,
+ AD7380_REG_ADDR_CONFIG1,
+ AD7380_CONFIG1_OSR | AD7380_CONFIG1_RES,
+ FIELD_PREP(AD7380_CONFIG1_OSR, osr) |
+ FIELD_PREP(AD7380_CONFIG1_RES, boost));
+
+ if (ret)
+ return ret;
+
+ st->oversampling_ratio = val;
+ st->resolution_boost_enabled = boost;
+
+ /*
+ * Perform a soft reset. This will flush the oversampling
+ * block and FIFO but will maintain the content of the
+ * configurable registers.
+ */
+ ret = regmap_update_bits(st->regmap,
+ AD7380_REG_ADDR_CONFIG2,
+ AD7380_CONFIG2_RESET,
+ FIELD_PREP(AD7380_CONFIG2_RESET,
+ AD7380_CONFIG2_RESET_SOFT));
+ return ret;
+}
static int ad7380_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan, int val,
int val2, long mask)
{
struct ad7380_state *st = iio_priv(indio_dev);
- int ret, osr, boost;
+ int ret;
switch (mask) {
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
- osr = ad7380_osr_to_regval(val);
- if (osr < 0)
- return osr;
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
- /* always enable resolution boost when oversampling is enabled */
- boost = osr > 0 ? 1 : 0;
+ ret = ad7380_set_oversampling_ratio(st, val);
- iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
- ret = regmap_update_bits(st->regmap,
- AD7380_REG_ADDR_CONFIG1,
- AD7380_CONFIG1_OSR | AD7380_CONFIG1_RES,
- FIELD_PREP(AD7380_CONFIG1_OSR, osr) |
- FIELD_PREP(AD7380_CONFIG1_RES, boost));
+ iio_device_release_direct_mode(indio_dev);
- if (ret)
- return ret;
-
- st->oversampling_ratio = val;
- st->resolution_boost_enabled = boost;
-
- /*
- * Perform a soft reset. This will flush the oversampling
- * block and FIFO but will maintain the content of the
- * configurable registers.
- */
- return regmap_update_bits(st->regmap,
- AD7380_REG_ADDR_CONFIG2,
- AD7380_CONFIG2_RESET,
- FIELD_PREP(AD7380_CONFIG2_RESET,
- AD7380_CONFIG2_RESET_SOFT));
- }
- unreachable();
+ return ret;
default:
return -EINVAL;
}
--
2.47.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH v4 1/5] iio: adc: ad7380: do not use iio_device_claim_direct_scoped anymore
2025-01-08 12:49 ` [PATCH v4 1/5] iio: adc: ad7380: do not use iio_device_claim_direct_scoped anymore Julien Stephan
@ 2025-01-12 16:29 ` Andy Shevchenko
2025-01-12 16:42 ` Jonathan Cameron
0 siblings, 1 reply; 13+ messages in thread
From: Andy Shevchenko @ 2025-01-12 16:29 UTC (permalink / raw)
To: Julien Stephan
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
David Lechner, Jonathan Cameron, Jonathan Corbet, linux-iio,
linux-kernel, linux-doc
Wed, Jan 08, 2025 at 01:49:33PM +0100, Julien Stephan kirjoitti:
> Conditionnal scoped handlers are turning out to be a real pain:
> readability issues, compiler and linker handling issues among others so
> rollback and remove the scoped version of iio_dvice_claim_direct_mode.
Is it IIO level decision or you as a contributor to/maintainer of this driver?
If the former? can you add a Link to the discussion?
Otherwise, I would like to understand the common approach / practices in IIO
WRT individual drivers to deviate the common approaches. Jonathan?
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 1/5] iio: adc: ad7380: do not use iio_device_claim_direct_scoped anymore
2025-01-12 16:29 ` Andy Shevchenko
@ 2025-01-12 16:42 ` Jonathan Cameron
2025-01-12 20:19 ` Andy Shevchenko
0 siblings, 1 reply; 13+ messages in thread
From: Jonathan Cameron @ 2025-01-12 16:42 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Julien Stephan, Lars-Peter Clausen, Michael Hennerich,
Nuno Sá, David Lechner, Jonathan Corbet, linux-iio,
linux-kernel, linux-doc
On Sun, 12 Jan 2025 18:29:42 +0200
Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
> Wed, Jan 08, 2025 at 01:49:33PM +0100, Julien Stephan kirjoitti:
> > Conditionnal scoped handlers are turning out to be a real pain:
> > readability issues, compiler and linker handling issues among others so
> > rollback and remove the scoped version of iio_dvice_claim_direct_mode.
>
> Is it IIO level decision or you as a contributor to/maintainer of this driver?
> If the former? can you add a Link to the discussion?
IIO. Agreed a link would have been sensible here.
>
> Otherwise, I would like to understand the common approach / practices in IIO
> WRT individual drivers to deviate the common approaches. Jonathan?
Patch series on list ripping the whole lot out that has some more explanation
and links. Basically we never found a way to overcome the short comings of
conditional scoped guards.
https://lore.kernel.org/linux-iio/20250105172613.1204781-1-jic23@kernel.org/
Jonathan
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v4 1/5] iio: adc: ad7380: do not use iio_device_claim_direct_scoped anymore
2025-01-12 16:42 ` Jonathan Cameron
@ 2025-01-12 20:19 ` Andy Shevchenko
0 siblings, 0 replies; 13+ messages in thread
From: Andy Shevchenko @ 2025-01-12 20:19 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Julien Stephan, Lars-Peter Clausen, Michael Hennerich,
Nuno Sá, David Lechner, Jonathan Corbet, linux-iio,
linux-kernel, linux-doc
On Sun, Jan 12, 2025 at 6:42 PM Jonathan Cameron <jic23@kernel.org> wrote:
>
> On Sun, 12 Jan 2025 18:29:42 +0200
> Andy Shevchenko <andy.shevchenko@gmail.com> wrote:
>
> > Wed, Jan 08, 2025 at 01:49:33PM +0100, Julien Stephan kirjoitti:
> > > Conditionnal scoped handlers are turning out to be a real pain:
> > > readability issues, compiler and linker handling issues among others so
> > > rollback and remove the scoped version of iio_dvice_claim_direct_mode.
> >
> > Is it IIO level decision or you as a contributor to/maintainer of this driver?
> > If the former? can you add a Link to the discussion?
>
>
> IIO. Agreed a link would have been sensible here.
>
> >
> > Otherwise, I would like to understand the common approach / practices in IIO
> > WRT individual drivers to deviate the common approaches. Jonathan?
>
> Patch series on list ripping the whole lot out that has some more explanation
> and links. Basically we never found a way to overcome the short comings of
> conditional scoped guards.
>
> https://lore.kernel.org/linux-iio/20250105172613.1204781-1-jic23@kernel.org/
Thanks, it was an interesting dive into "how did I spend my holidays?" essay.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v4 2/5] iio: adc: ad7380: enable regmap cache
2025-01-08 12:49 [PATCH v4 0/5] iio: adc: ad7380: add alert support Julien Stephan
2025-01-08 12:49 ` [PATCH v4 1/5] iio: adc: ad7380: do not use iio_device_claim_direct_scoped anymore Julien Stephan
@ 2025-01-08 12:49 ` Julien Stephan
2025-01-08 12:49 ` [PATCH v4 3/5] iio: adc: ad7380: do not store osr in private data structure Julien Stephan
` (3 subsequent siblings)
5 siblings, 0 replies; 13+ messages in thread
From: Julien Stephan @ 2025-01-08 12:49 UTC (permalink / raw)
To: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
David Lechner, Jonathan Cameron, Jonathan Corbet
Cc: linux-iio, linux-kernel, linux-doc, Julien Stephan
Enable regmap cache, to avoid useless access on spi bus.
Reviewed-by: David Lechner <dlechner@baylibre.com>
Signed-off-by: Julien Stephan <jstephan@baylibre.com>
---
drivers/iio/adc/ad7380.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c
index bc7d58850a3e2a84a241d81377e3dc14c43fc101..b97d2978289e92ad502cd6a67de43d2b51cdab56 100644
--- a/drivers/iio/adc/ad7380.c
+++ b/drivers/iio/adc/ad7380.c
@@ -663,6 +663,20 @@ static int ad7380_regmap_reg_read(void *context, unsigned int reg,
return 0;
}
+static const struct reg_default ad7380_reg_defaults[] = {
+ { AD7380_REG_ADDR_ALERT_LOW_TH, 0x800 },
+ { AD7380_REG_ADDR_ALERT_HIGH_TH, 0x7FF },
+};
+
+static const struct regmap_range ad7380_volatile_reg_ranges[] = {
+ regmap_reg_range(AD7380_REG_ADDR_CONFIG2, AD7380_REG_ADDR_ALERT),
+};
+
+static const struct regmap_access_table ad7380_volatile_regs = {
+ .yes_ranges = ad7380_volatile_reg_ranges,
+ .n_yes_ranges = ARRAY_SIZE(ad7380_volatile_reg_ranges),
+};
+
static const struct regmap_config ad7380_regmap_config = {
.reg_bits = 3,
.val_bits = 12,
@@ -670,6 +684,10 @@ static const struct regmap_config ad7380_regmap_config = {
.reg_write = ad7380_regmap_reg_write,
.max_register = AD7380_REG_ADDR_ALERT_HIGH_TH,
.can_sleep = true,
+ .reg_defaults = ad7380_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(ad7380_reg_defaults),
+ .volatile_table = &ad7380_volatile_regs,
+ .cache_type = REGCACHE_MAPLE,
};
static int ad7380_debugfs_reg_access(struct iio_dev *indio_dev, u32 reg,
--
2.47.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* [PATCH v4 3/5] iio: adc: ad7380: do not store osr in private data structure
2025-01-08 12:49 [PATCH v4 0/5] iio: adc: ad7380: add alert support Julien Stephan
2025-01-08 12:49 ` [PATCH v4 1/5] iio: adc: ad7380: do not use iio_device_claim_direct_scoped anymore Julien Stephan
2025-01-08 12:49 ` [PATCH v4 2/5] iio: adc: ad7380: enable regmap cache Julien Stephan
@ 2025-01-08 12:49 ` Julien Stephan
2025-01-12 16:31 ` Andy Shevchenko
2025-01-08 12:49 ` [PATCH v4 4/5] iio: adc: ad7380: add alert support Julien Stephan
` (2 subsequent siblings)
5 siblings, 1 reply; 13+ messages in thread
From: Julien Stephan @ 2025-01-08 12:49 UTC (permalink / raw)
To: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
David Lechner, Jonathan Cameron, Jonathan Corbet
Cc: linux-iio, linux-kernel, linux-doc, Julien Stephan
Since regmap cache is now enabled, we don't need to store the
oversampling ratio in the private data structure.
Reviewed-by: David Lechner <dlechner@baylibre.com>
Signed-off-by: Julien Stephan <jstephan@baylibre.com>
---
drivers/iio/adc/ad7380.c | 79 +++++++++++++++++++++++++++++++++++++++---------
1 file changed, 65 insertions(+), 14 deletions(-)
diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c
index b97d2978289e92ad502cd6a67de43d2b51cdab56..a532de4422082df8503454d66fc49f75b52cff68 100644
--- a/drivers/iio/adc/ad7380.c
+++ b/drivers/iio/adc/ad7380.c
@@ -582,7 +582,6 @@ struct ad7380_state {
const struct ad7380_chip_info *chip_info;
struct spi_device *spi;
struct regmap *regmap;
- unsigned int oversampling_ratio;
bool resolution_boost_enabled;
unsigned int ch;
bool seq;
@@ -710,6 +709,36 @@ static int ad7380_debugfs_reg_access(struct iio_dev *indio_dev, u32 reg,
return ret;
}
+/**
+ * ad7380_regval_to_osr - convert OSR register value to ratio
+ * @regval: register value to check
+ *
+ * Returns: the ratio corresponding to the OSR register. If regval is not in
+ * bound, return 1 (oversampling disabled)
+ *
+ */
+static int ad7380_regval_to_osr(unsigned int regval)
+{
+ if (regval >= ARRAY_SIZE(ad7380_oversampling_ratios))
+ return 1;
+
+ return ad7380_oversampling_ratios[regval];
+}
+
+static int ad7380_get_osr(struct ad7380_state *st, int *val)
+{
+ u32 tmp;
+ int ret;
+
+ ret = regmap_read(st->regmap, AD7380_REG_ADDR_CONFIG1, &tmp);
+ if (ret)
+ return ret;
+
+ *val = ad7380_regval_to_osr(FIELD_GET(AD7380_CONFIG1_OSR, tmp));
+
+ return 0;
+}
+
/*
* When switching channel, the ADC require an additional settling time.
* According to the datasheet, data is value on the third CS low. We already
@@ -725,11 +754,15 @@ static int ad7380_set_ch(struct ad7380_state *st, unsigned int ch)
.unit = SPI_DELAY_UNIT_NSECS,
}
};
- int ret;
+ int oversampling_ratio, ret;
if (st->ch == ch)
return 0;
+ ret = ad7380_get_osr(st, &oversampling_ratio);
+ if (ret)
+ return ret;
+
ret = regmap_update_bits(st->regmap,
AD7380_REG_ADDR_CONFIG1,
AD7380_CONFIG1_CH,
@@ -740,9 +773,9 @@ static int ad7380_set_ch(struct ad7380_state *st, unsigned int ch)
st->ch = ch;
- if (st->oversampling_ratio > 1)
+ if (oversampling_ratio > 1)
xfer.delay.value = T_CONVERT_0_NS +
- T_CONVERT_X_NS * (st->oversampling_ratio - 1) *
+ T_CONVERT_X_NS * (oversampling_ratio - 1) *
st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES;
return spi_sync_transfer(st->spi, &xfer, 1);
@@ -753,20 +786,25 @@ static int ad7380_set_ch(struct ad7380_state *st, unsigned int ch)
* @st: device instance specific state
* @scan_type: current scan type
*/
-static void ad7380_update_xfers(struct ad7380_state *st,
+static int ad7380_update_xfers(struct ad7380_state *st,
const struct iio_scan_type *scan_type)
{
struct spi_transfer *xfer = st->seq ? st->seq_xfer : st->normal_xfer;
unsigned int t_convert = T_CONVERT_NS;
+ int oversampling_ratio, ret;
/*
* In the case of oversampling, conversion time is higher than in normal
* mode. Technically T_CONVERT_X_NS is lower for some chips, but we use
* the maximum value for simplicity for now.
*/
- if (st->oversampling_ratio > 1)
+ ret = ad7380_get_osr(st, &oversampling_ratio);
+ if (ret)
+ return ret;
+
+ if (oversampling_ratio > 1)
t_convert = T_CONVERT_0_NS + T_CONVERT_X_NS *
- (st->oversampling_ratio - 1) *
+ (oversampling_ratio - 1) *
st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES;
if (st->seq) {
@@ -779,7 +817,7 @@ static void ad7380_update_xfers(struct ad7380_state *st,
st->chip_info->num_simult_channels;
xfer[3].rx_buf = xfer[2].rx_buf + xfer[2].len;
/* Additional delay required here when oversampling is enabled */
- if (st->oversampling_ratio > 1)
+ if (oversampling_ratio > 1)
xfer[2].delay.value = t_convert;
else
xfer[2].delay.value = 0;
@@ -791,6 +829,8 @@ static void ad7380_update_xfers(struct ad7380_state *st,
xfer[1].len = BITS_TO_BYTES(scan_type->storagebits) *
st->chip_info->num_simult_channels;
}
+
+ return 0;
}
static int ad7380_triggered_buffer_preenable(struct iio_dev *indio_dev)
@@ -798,6 +838,7 @@ static int ad7380_triggered_buffer_preenable(struct iio_dev *indio_dev)
struct ad7380_state *st = iio_priv(indio_dev);
const struct iio_scan_type *scan_type;
struct spi_message *msg = &st->normal_msg;
+ int ret;
/*
* Currently, we always read all channels at the same time. The scan_type
@@ -809,7 +850,6 @@ static int ad7380_triggered_buffer_preenable(struct iio_dev *indio_dev)
if (st->chip_info->has_mux) {
unsigned int index;
- int ret;
/*
* Depending on the requested scan_mask and current state,
@@ -840,7 +880,9 @@ static int ad7380_triggered_buffer_preenable(struct iio_dev *indio_dev)
}
- ad7380_update_xfers(st, scan_type);
+ ret = ad7380_update_xfers(st, scan_type);
+ if (ret)
+ return ret;
return spi_optimize_message(st->spi, msg);
}
@@ -913,7 +955,9 @@ static int ad7380_read_direct(struct ad7380_state *st, unsigned int scan_index,
return ret;
}
- ad7380_update_xfers(st, scan_type);
+ ret = ad7380_update_xfers(st, scan_type);
+ if (ret)
+ return ret;
ret = spi_sync(st->spi, &st->normal_msg);
if (ret < 0)
@@ -991,7 +1035,16 @@ static int ad7380_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
- *val = st->oversampling_ratio;
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = ad7380_get_osr(st, val);
+
+ iio_device_release_direct_mode(indio_dev);
+
+ if (ret)
+ return ret;
return IIO_VAL_INT;
default:
@@ -1058,7 +1111,6 @@ static int ad7380_set_oversampling_ratio(struct ad7380_state *st, int val)
if (ret)
return ret;
- st->oversampling_ratio = val;
st->resolution_boost_enabled = boost;
/*
@@ -1134,7 +1186,6 @@ static int ad7380_init(struct ad7380_state *st, bool external_ref_en)
}
/* This is the default value after reset. */
- st->oversampling_ratio = 1;
st->ch = 0;
st->seq = false;
--
2.47.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH v4 3/5] iio: adc: ad7380: do not store osr in private data structure
2025-01-08 12:49 ` [PATCH v4 3/5] iio: adc: ad7380: do not store osr in private data structure Julien Stephan
@ 2025-01-12 16:31 ` Andy Shevchenko
0 siblings, 0 replies; 13+ messages in thread
From: Andy Shevchenko @ 2025-01-12 16:31 UTC (permalink / raw)
To: Julien Stephan
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
David Lechner, Jonathan Cameron, Jonathan Corbet, linux-iio,
linux-kernel, linux-doc
Wed, Jan 08, 2025 at 01:49:35PM +0100, Julien Stephan kirjoitti:
> Since regmap cache is now enabled, we don't need to store the
> oversampling ratio in the private data structure.
...
> +/**
> + * ad7380_regval_to_osr - convert OSR register value to ratio
> + * @regval: register value to check
> + *
> + * Returns: the ratio corresponding to the OSR register. If regval is not in
> + * bound, return 1 (oversampling disabled)
> + *
Redundant blank line.
> + */
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v4 4/5] iio: adc: ad7380: add alert support
2025-01-08 12:49 [PATCH v4 0/5] iio: adc: ad7380: add alert support Julien Stephan
` (2 preceding siblings ...)
2025-01-08 12:49 ` [PATCH v4 3/5] iio: adc: ad7380: do not store osr in private data structure Julien Stephan
@ 2025-01-08 12:49 ` Julien Stephan
2025-01-08 15:17 ` David Lechner
2025-01-08 12:49 ` [PATCH v4 5/5] docs: iio: " Julien Stephan
2025-01-12 11:51 ` [PATCH v4 0/5] iio: adc: " Jonathan Cameron
5 siblings, 1 reply; 13+ messages in thread
From: Julien Stephan @ 2025-01-08 12:49 UTC (permalink / raw)
To: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
David Lechner, Jonathan Cameron, Jonathan Corbet
Cc: linux-iio, linux-kernel, linux-doc, Julien Stephan
The alert functionality is an out of range indicator and can be used as
an early indicator of an out of bounds conversion result.
ALERT_LOW_THRESHOLD and ALERT_HIGH_THRESHOLD registers are common to all
channels.
When using 1 SDO line (only mode supported by the driver right now), i.e
data outputs only on SDOA, SDOB (or SDOD for 4 channels variants) is
used as an alert pin. The alert pin is updated at the end of the
conversion (set to low if an alert occurs) and is cleared on a falling
edge of CS.
The ALERT register contains information about the exact alert status:
channel and direction. ALERT register can be accessed using debugfs if
enabled.
User can set high/low thresholds and enable alert detection using the
regular iio events attributes:
events/in_thresh_falling_value events/in_thresh_rising_value
events/thresh_either_en
In most use cases, user will hardwire the alert pin to trigger a shutdown.
In theory, we could generate userspace IIO events for alerts, but this
is not implemented yet for several reasons [1]. This can be implemented
later if a real use case actually requires it.
Signed-off-by: Julien Stephan <jstephan@baylibre.com>
[1] https://lore.kernel.org/all/4be16272-5197-4fa1-918c-c4cdfcaee02e@baylibre.com/
---
drivers/iio/adc/ad7380.c | 197 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 197 insertions(+)
diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c
index a532de4422082df8503454d66fc49f75b52cff68..cedd45556ee38b3197f8dd7edea162c3f4ba1563 100644
--- a/drivers/iio/adc/ad7380.c
+++ b/drivers/iio/adc/ad7380.c
@@ -34,6 +34,7 @@
#include <linux/util_macros.h>
#include <linux/iio/buffer.h>
+#include <linux/iio/events.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
@@ -112,6 +113,24 @@ struct ad7380_chip_info {
const struct ad7380_timing_specs *timing_specs;
};
+static const struct iio_event_spec ad7380_events[] = {
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_RISING,
+ .mask_shared_by_dir = BIT(IIO_EV_INFO_VALUE),
+ },
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_FALLING,
+ .mask_shared_by_dir = BIT(IIO_EV_INFO_VALUE),
+ },
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_EITHER,
+ .mask_shared_by_all = BIT(IIO_EV_INFO_ENABLE),
+ },
+};
+
enum {
AD7380_SCAN_TYPE_NORMAL,
AD7380_SCAN_TYPE_RESOLUTION_BOOST,
@@ -214,6 +233,8 @@ static const struct iio_scan_type ad7380_scan_type_16_u[] = {
.has_ext_scan_type = 1, \
.ext_scan_type = ad7380_scan_type_##bits##_##sign, \
.num_ext_scan_type = ARRAY_SIZE(ad7380_scan_type_##bits##_##sign), \
+ .event_spec = ad7380_events, \
+ .num_event_specs = ARRAY_SIZE(ad7380_events), \
}
#define AD7380_CHANNEL(index, bits, diff, sign) \
@@ -1157,12 +1178,188 @@ static int ad7380_get_current_scan_type(const struct iio_dev *indio_dev,
: AD7380_SCAN_TYPE_NORMAL;
}
+static int ad7380_read_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct ad7380_state *st = iio_priv(indio_dev);
+ int tmp, ret;
+
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(st->regmap, AD7380_REG_ADDR_CONFIG1, &tmp);
+
+ iio_device_release_direct_mode(indio_dev);
+
+ if (ret)
+ return ret;
+
+ return FIELD_GET(AD7380_CONFIG1_ALERTEN, tmp);
+}
+
+static int ad7380_write_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ bool state)
+{
+ struct ad7380_state *st = iio_priv(indio_dev);
+ int ret;
+
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(st->regmap,
+ AD7380_REG_ADDR_CONFIG1,
+ AD7380_CONFIG1_ALERTEN,
+ FIELD_PREP(AD7380_CONFIG1_ALERTEN, state));
+
+ iio_device_release_direct_mode(indio_dev);
+
+ return ret;
+}
+
+static int ad7380_get_alert_th(struct ad7380_state *st,
+ enum iio_event_direction dir,
+ int *val)
+{
+ int ret, tmp;
+
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ ret = regmap_read(st->regmap,
+ AD7380_REG_ADDR_ALERT_HIGH_TH,
+ &tmp);
+ if (ret)
+ return ret;
+
+ *val = FIELD_GET(AD7380_ALERT_HIGH_TH, tmp);
+ ret = IIO_VAL_INT;
+ break;
+ case IIO_EV_DIR_FALLING:
+ ret = regmap_read(st->regmap,
+ AD7380_REG_ADDR_ALERT_LOW_TH,
+ &tmp);
+ if (ret)
+ return ret;
+
+ *val = FIELD_GET(AD7380_ALERT_LOW_TH, tmp);
+ ret = IIO_VAL_INT;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ return ret;
+}
+
+static int ad7380_read_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int *val, int *val2)
+{
+ struct ad7380_state *st = iio_priv(indio_dev);
+ int ret;
+
+ switch (info) {
+ case IIO_EV_INFO_VALUE:
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = ad7380_get_alert_th(st, dir, val);
+
+ iio_device_release_direct_mode(indio_dev);
+ return ret;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad7380_set_alert_th(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_direction dir,
+ int val)
+{
+ struct ad7380_state *st = iio_priv(indio_dev);
+ const struct iio_scan_type *scan_type;
+ u16 th;
+
+ /*
+ * According to the datasheet,
+ * AD7380_REG_ADDR_ALERT_HIGH_TH[11:0] are the 12 MSB of the
+ * 16-bits internal alert high register. LSB are set to 0xf.
+ * AD7380_REG_ADDR_ALERT_LOW_TH[11:0] are the 12 MSB of the
+ * 16 bits internal alert low register. LSB are set to 0x0.
+ *
+ * When alert is enabled the conversion from the adc is compared
+ * immediately to the alert high/low thresholds, before any
+ * oversampling. This means that the thresholds are the same for
+ * normal mode and oversampling mode.
+ */
+
+ /* Extract the 12 MSB of val */
+ scan_type = iio_get_current_scan_type(indio_dev, chan);
+ if (IS_ERR(scan_type))
+ return PTR_ERR(scan_type);
+
+ th = val >> (scan_type->realbits - 12);
+
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ return regmap_write(st->regmap,
+ AD7380_REG_ADDR_ALERT_HIGH_TH,
+ th);
+ case IIO_EV_DIR_FALLING:
+ return regmap_write(st->regmap,
+ AD7380_REG_ADDR_ALERT_LOW_TH,
+ th);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad7380_write_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int val, int val2)
+{
+ int ret;
+
+ switch (info) {
+ case IIO_EV_INFO_VALUE:
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = ad7380_set_alert_th(indio_dev, chan, dir, val);
+
+ iio_device_release_direct_mode(indio_dev);
+ return ret;
+ default:
+ return -EINVAL;
+ }
+}
+
static const struct iio_info ad7380_info = {
.read_raw = &ad7380_read_raw,
.read_avail = &ad7380_read_avail,
.write_raw = &ad7380_write_raw,
.get_current_scan_type = &ad7380_get_current_scan_type,
.debugfs_reg_access = &ad7380_debugfs_reg_access,
+ .read_event_config = &ad7380_read_event_config,
+ .write_event_config = &ad7380_write_event_config,
+ .read_event_value = &ad7380_read_event_value,
+ .write_event_value = &ad7380_write_event_value,
};
static int ad7380_init(struct ad7380_state *st, bool external_ref_en)
--
2.47.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH v4 4/5] iio: adc: ad7380: add alert support
2025-01-08 12:49 ` [PATCH v4 4/5] iio: adc: ad7380: add alert support Julien Stephan
@ 2025-01-08 15:17 ` David Lechner
2025-01-12 11:49 ` Jonathan Cameron
0 siblings, 1 reply; 13+ messages in thread
From: David Lechner @ 2025-01-08 15:17 UTC (permalink / raw)
To: Julien Stephan, Lars-Peter Clausen, Michael Hennerich,
Nuno Sá, Jonathan Cameron, Jonathan Corbet
Cc: linux-iio, linux-kernel, linux-doc
On 1/8/25 6:49 AM, Julien Stephan wrote:
> The alert functionality is an out of range indicator and can be used as
> an early indicator of an out of bounds conversion result.
>
...
> +static int ad7380_get_alert_th(struct ad7380_state *st,
> + enum iio_event_direction dir,
> + int *val)
> +{
> + int ret, tmp;
> +
> + switch (dir) {
> + case IIO_EV_DIR_RISING:
> + ret = regmap_read(st->regmap,
> + AD7380_REG_ADDR_ALERT_HIGH_TH,
> + &tmp);
> + if (ret)
> + return ret;
> +
> + *val = FIELD_GET(AD7380_ALERT_HIGH_TH, tmp);
> + ret = IIO_VAL_INT;
> + break;
> + case IIO_EV_DIR_FALLING:
> + ret = regmap_read(st->regmap,
> + AD7380_REG_ADDR_ALERT_LOW_TH,
> + &tmp);
> + if (ret)
> + return ret;
> +
> + *val = FIELD_GET(AD7380_ALERT_LOW_TH, tmp);
> + ret = IIO_VAL_INT;
> + break;
> + default:
> + ret = -EINVAL;
> + break;
> + }
> +
> + return ret;
We can just return directly in each case instead of using break (preferred
style in IIO).
> +}
> +
Reviewed-by: David Lechner <dlechner@baylibre.com>
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH v4 4/5] iio: adc: ad7380: add alert support
2025-01-08 15:17 ` David Lechner
@ 2025-01-12 11:49 ` Jonathan Cameron
0 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron @ 2025-01-12 11:49 UTC (permalink / raw)
To: David Lechner
Cc: Julien Stephan, Lars-Peter Clausen, Michael Hennerich,
Nuno Sá, Jonathan Corbet, linux-iio, linux-kernel, linux-doc
On Wed, 8 Jan 2025 09:17:32 -0600
David Lechner <dlechner@baylibre.com> wrote:
> On 1/8/25 6:49 AM, Julien Stephan wrote:
> > The alert functionality is an out of range indicator and can be used as
> > an early indicator of an out of bounds conversion result.
> >
>
> ...
>
> > +static int ad7380_get_alert_th(struct ad7380_state *st,
> > + enum iio_event_direction dir,
> > + int *val)
> > +{
> > + int ret, tmp;
> > +
> > + switch (dir) {
> > + case IIO_EV_DIR_RISING:
> > + ret = regmap_read(st->regmap,
> > + AD7380_REG_ADDR_ALERT_HIGH_TH,
> > + &tmp);
> > + if (ret)
> > + return ret;
> > +
> > + *val = FIELD_GET(AD7380_ALERT_HIGH_TH, tmp);
> > + ret = IIO_VAL_INT;
> > + break;
> > + case IIO_EV_DIR_FALLING:
> > + ret = regmap_read(st->regmap,
> > + AD7380_REG_ADDR_ALERT_LOW_TH,
> > + &tmp);
> > + if (ret)
> > + return ret;
> > +
> > + *val = FIELD_GET(AD7380_ALERT_LOW_TH, tmp);
> > + ret = IIO_VAL_INT;
> > + break;
> > + default:
> > + ret = -EINVAL;
> > + break;
> > + }
> > +
> > + return ret;
>
> We can just return directly in each case instead of using break (preferred
> style in IIO).
>
> > +}
> > +
>
> Reviewed-by: David Lechner <dlechner@baylibre.com>
>
I tweaked it whilst applying.
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v4 5/5] docs: iio: ad7380: add alert support
2025-01-08 12:49 [PATCH v4 0/5] iio: adc: ad7380: add alert support Julien Stephan
` (3 preceding siblings ...)
2025-01-08 12:49 ` [PATCH v4 4/5] iio: adc: ad7380: add alert support Julien Stephan
@ 2025-01-08 12:49 ` Julien Stephan
2025-01-12 11:51 ` [PATCH v4 0/5] iio: adc: " Jonathan Cameron
5 siblings, 0 replies; 13+ messages in thread
From: Julien Stephan @ 2025-01-08 12:49 UTC (permalink / raw)
To: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
David Lechner, Jonathan Cameron, Jonathan Corbet
Cc: linux-iio, linux-kernel, linux-doc, Julien Stephan
Add a section for alert support, explaining how user can use iio events
attributes to enable alert and set thresholds.
Reviewed-by: David Lechner <dlechner@baylibre.com>
Signed-off-by: Julien Stephan <jstephan@baylibre.com>
---
Documentation/iio/ad7380.rst | 33 ++++++++++++++++++++++++++++++++-
1 file changed, 32 insertions(+), 1 deletion(-)
diff --git a/Documentation/iio/ad7380.rst b/Documentation/iio/ad7380.rst
index c46127700e14ca9ec3cac0bd5776b6702f2659e2..cff688bcc2d9601a9faf42d5e9c217486639ca66 100644
--- a/Documentation/iio/ad7380.rst
+++ b/Documentation/iio/ad7380.rst
@@ -92,6 +92,38 @@ must restart iiod using the following command:
root:~# systemctl restart iiod
+Alert
+-----
+
+2 channels variants of the ad738x family, can use the SDOB line as an alert pin
+when configured in 1 SDO line mode. 4 channels variants, can use SDOD as an
+alert pin when configured in 1 or 2 SDO line(s) mode, although only 1 SDO line
+mode is currently supported by the driver (see `SPI wiring modes`_).
+
+At the end of a conversion the active-low alert pin gets asserted if the
+conversion result exceeds the alert high limit or falls below the alert low
+limit. It is cleared, on a falling edge of CS. The alert pin is common to all
+channels.
+
+User can enable alert using the regular iio events attribute:
+
+.. code-block:: bash
+
+ events/thresh_either_en
+
+The high and low thresholds are common to all channels and can also be set using
+regular iio events attributes:
+
+.. code-block:: bash
+
+ events/in_thresh_falling_value
+ events/in_thresh_rising_value
+
+If debugfs is available, user can read the ALERT register to determine the
+faulty channel and direction.
+
+In most use cases, user will hardwire the alert pin to trigger a shutdown.
+
Channel selection and sequencer (single-end chips only)
-------------------------------------------------------
@@ -144,7 +176,6 @@ Unimplemented features
- Rolling average oversampling
- Power down mode
- CRC indication
-- Alert
Device buffers
--
2.47.1
^ permalink raw reply related [flat|nested] 13+ messages in thread* Re: [PATCH v4 0/5] iio: adc: ad7380: add alert support
2025-01-08 12:49 [PATCH v4 0/5] iio: adc: ad7380: add alert support Julien Stephan
` (4 preceding siblings ...)
2025-01-08 12:49 ` [PATCH v4 5/5] docs: iio: " Julien Stephan
@ 2025-01-12 11:51 ` Jonathan Cameron
5 siblings, 0 replies; 13+ messages in thread
From: Jonathan Cameron @ 2025-01-12 11:51 UTC (permalink / raw)
To: Julien Stephan
Cc: Lars-Peter Clausen, Michael Hennerich, Nuno Sá,
David Lechner, Jonathan Corbet, linux-iio, linux-kernel,
linux-doc
On Wed, 08 Jan 2025 13:49:32 +0100
Julien Stephan <jstephan@baylibre.com> wrote:
> Hello,
>
> The ad738x family includes a built-in alert mechanism for early
> detection of out-of-bounds conversion results. This series introduces
> this functionality to the ad7380 family.
>
> This is the first non RFC version of the series (RFC available at [1] and [2]).
>
> Given the fact that the main use case is to hardwire the interrupt line
> and according to discussions in V2 about interrupts, I think the best is
> to not generate events, at least while we don't have a reasonable way to
> correctly and efficiently handle interrupts.
>
> Events attributes are still populated to allow user to set a threshold
> and enable alert detection, so alert pin can be hardwired.
>
> Userspace event can still be added later if needed.
>
> [1]: https://lore.kernel.org/r/20241029-ad7380-add-aleyyrt-support-v1-1-d0359401b788@baylibre.com
> [2]: https://lore.kernel.org/r/20241224-ad7380-add-alert-support-v2-0-7c89b2bf7cb3@baylibre.com
>
> Signed-off-by: Julien Stephan <jstephan@baylibre.com>
Series applied to the to testing branch of iio.git.
Unless the release is delayed for some reason, we are now too late to make
the merge window, so this is next cycle material.
I'll be rebasing the tree on rc1 once available and pushing out as togreg
only once that is done.
Thanks
Jonathan
> ---
> Changes in v4:
> - docs: fix some nitpicks from David Lechner
> - driver: fix some nitpicks from David Lechner and use helper functions
> to get/set the thresholds
> - driver: fix reading the low threshold value
> - add Reviewed-by tag from David Lechner
> - Link to v3: https://lore.kernel.org/r/20250107-ad7380-add-alert-support-v3-0-bce10afd656b@baylibre.com
>
> Changes in v3:
> - split regmap cache commit in two
> - remove interrupt handling completely, updating commit messages,
> driver, and doc
> - fix minor comments from v2 review
> - improve commit message for iio_device_claim_direct_scoped removal
> - Link to v2: https://lore.kernel.org/r/20241224-ad7380-add-alert-support-v2-0-7c89b2bf7cb3@baylibre.com
>
> Changes in v2:
> - fix read/write high/low thresholds
> - add reset_timeout mechanism for buffered reads
> - implement regcache
> - add cleanup patch to remove iio_device_claim_direct_scoped calls
> - add alert section in the Documentation page
> - Link to v1: https://lore.kernel.org/r/20241029-ad7380-add-aleyyrt-support-v1-1-d0359401b788@baylibre.com
>
> ---
> Julien Stephan (5):
> iio: adc: ad7380: do not use iio_device_claim_direct_scoped anymore
> iio: adc: ad7380: enable regmap cache
> iio: adc: ad7380: do not store osr in private data structure
> iio: adc: ad7380: add alert support
> docs: iio: ad7380: add alert support
>
> Documentation/iio/ad7380.rst | 33 +++-
> drivers/iio/adc/ad7380.c | 402 +++++++++++++++++++++++++++++++++++++------
> 2 files changed, 378 insertions(+), 57 deletions(-)
> ---
> base-commit: 5ab39233382c621d3271cc274d1534e1b687f4d3
> change-id: 20241029-ad7380-add-alert-support-4d0dd6cea8cd
>
> Best regards,
^ permalink raw reply [flat|nested] 13+ messages in thread