Re: [PATCH v5 11/12] iio: dac: ad5686: add triggered buffer support

From: Jonathan Cameron

Date: Mon Jun 29 2026 - 19:38:42 EST


On Sun, 28 Jun 2026 15:08:18 +0100
Rodrigo Alencar via B4 Relay <devnull+rodrigo.alencar.analog.com@xxxxxxxxxx> wrote:

> From: Rodrigo Alencar <rodrigo.alencar@xxxxxxxxxx>
>
> 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 <rodrigo.alencar@xxxxxxxxxx>
I may well have forgotten an earlier discussion about this (assuming Sashiko
found it before now) but the masking of the stuff from the ring buffer
does look necessary to me (at first glance anyway!)

> diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
> index db175e77b0b7..3120e6983d9e 100644
> --- a/drivers/iio/dac/ad5686.c
> +++ b/drivers/iio/dac/ad5686.c

> };
> 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;
> + 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))

The Sashiko comment is that the data in val is controlled by
userspace so might include stuff in the bits where the
_CMD() macros are placing the cmd. I think we need masking
somewhere and I think it should be in the ad5686_write()
rather than here as that is where the per device macros
are applied.

> + 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;
> + }