Re: [PATCH v7 6/7] iio: dac: ad5686: add triggered buffer support
David Lechner <[email protected]>
| Newsgroups | org.kernel.vger.linux-hardening,org.kernel.vger.linux-devicetree,org.kernel.vger.linux-iio,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
On 7/10/26 6:20 AM, Rodrigo Alencar via B4 Relay wrote: > From: Rodrigo Alencar <[email protected]> > > Implement trigger handler by leveraging the LDAC gpio to update all DAC > channels at once when it is available. Also, the multiple channel writes > can be flushed at once with the sync() operation. > > Signed-off-by: Rodrigo Alencar <[email protected]> > --- > drivers/iio/dac/Kconfig | 2 ++ > drivers/iio/dac/ad5686.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 68 insertions(+) > > diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig > index 17529509da9d..d6d560c09e25 100644 > --- a/drivers/iio/dac/Kconfig > +++ b/drivers/iio/dac/Kconfig > @@ -243,6 +243,8 @@ config LTC2688 > > config AD5686 > tristate > + select IIO_BUFFER > + select IIO_TRIGGERED_BUFFER > > config AD5686_SPI > tristate "Analog Devices AD5686 and similar multi-channel DACs (SPI)" > diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c > index df32f46db81e..eeeff5c6cf38 100644 > --- a/drivers/iio/dac/ad5686.c > +++ b/drivers/iio/dac/ad5686.c > @@ -21,7 +21,11 @@ > #include <linux/sysfs.h> > #include <linux/wordpart.h> > > +#include <linux/iio/buffer.h> > #include <linux/iio/iio.h> > +#include <linux/iio/trigger.h> > +#include <linux/iio/trigger_consumer.h> > +#include <linux/iio/triggered_buffer.h> > > #include "ad5686.h" > > @@ -243,6 +247,7 @@ static const struct iio_chan_spec_ext_info ad5686_ext_info[] = { > .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ > .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\ > .address = addr, \ > + .scan_index = chan, \ > .scan_type = { \ > .sign = 'u', \ > .realbits = (bits), \ > @@ -467,6 +472,60 @@ const struct ad5686_chip_info ad5679r_chip_info = { > }; > EXPORT_SYMBOL_NS_GPL(ad5679r_chip_info, "IIO_AD5686"); > > +static void do_ad5686_trigger_handler(struct iio_dev *indio_dev) > +{ > + struct iio_buffer *buffer = indio_dev->buffer; Only used once and doesn't save a line wrap, so no need for a local variable. > + struct ad5686_state *st = iio_priv(indio_dev); > + u16 val[AD5686_MAX_CHANNELS] = { }; > + unsigned int scan_count, ch, i; > + bool async_update; > + u8 cmd; > + > + if (iio_pop_from_buffer(buffer, val)) > + return; > + > + guard(mutex)(&st->lock); > + > + scan_count = bitmap_weight(indio_dev->active_scan_mask, > + iio_get_masklength(indio_dev)); > + async_update = st->ldac_gpio && scan_count > 1; > + if (async_update) { > + /* use LDAC to update all channels simultaneously */ > + cmd = AD5686_CMD_WRITE_INPUT_N; > + gpiod_set_value_cansleep(st->ldac_gpio, 0); > + } else { > + cmd = AD5686_CMD_WRITE_INPUT_N_UPDATE_N; > + } > + > + i = 0; > + iio_for_each_active_channel(indio_dev, ch) { > + if (st->ops->write(st, cmd, indio_dev->channels[ch].address, val[i++])) > + break; > + } > + > + /* > + * If sync() is available, it is called here regardless of write > + * failure to allow bus implementation to reset. In that case, partial > + * writes are unlikely as the write operations would just queue up > + * the transfers. > + */ > + if (st->ops->sync) > + st->ops->sync(st); > + > + if (async_update) > + gpiod_set_value_cansleep(st->ldac_gpio, 1); > +} > +