[RESEND PATCH 14/14] iio: adc: at91_adc: poll the enabled trigger from interrupt handler

From: Jonathan Cameron

Date: Sun Nov 08 2026 - 23:34:58 EST


From: Jonathan Cameron <jonathan.cameron@xxxxxxxxxxxxxxxx>

The driver registers several hardware triggers, any of which may be
selected. The end of conversion interrupt is only enabled for buffered
capture by the set_trigger_state() callback of the trigger being
enabled, and handle_adc_eoc_trigger() then polls indio_dev->trig.

Record the trigger in at91_adc_configure_trigger() before enabling the
interrupt and poll that instead. It is not cleared on disable so that
an interrupt still in flight polls the same trigger as before rather
than dereferencing NULL.

Also use the trigger passed to at91_adc_configure_trigger() to look up
its configuration rather than indio_dev->trig, which is the same
trigger.

This removes the driver's dependencies on the trig field of struct
iio_dev, which is to become private to the IIO core.

Signed-off-by: Jonathan Cameron <jonathan.cameron@xxxxxxxxxxxxxxxx>
---
drivers/iio/adc/at91_adc.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 0ac74ad92fca..49e7fb2d39f2 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -229,6 +229,7 @@ struct at91_adc_state {
u8 sample_hold_time;
bool sleep_mode;
struct iio_trigger **trig;
+ struct iio_trigger *cur_trig; /* last enabled of trig[] */
bool use_external;
u32 vref_mv;
u32 res; /* resolution used for conversions */
@@ -294,7 +295,7 @@ static void handle_adc_eoc_trigger(int irq, struct iio_dev *idev)

if (iio_buffer_enabled(idev)) {
disable_irq_nosync(irq);
- iio_trigger_poll(idev->trig);
+ iio_trigger_poll(st->cur_trig);
} else {
st->last_value = at91_adc_readl(st, AT91_ADC_CHAN(st, st->chnb));
/* Needed to ACK the DRDY interruption */
@@ -562,7 +563,7 @@ static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)

value = at91_adc_get_trigger_value_by_name(idev,
st->caps->triggers,
- idev->trig->name);
+ trig->name);
if (value < 0)
return value;

@@ -581,6 +582,7 @@ static int at91_adc_configure_trigger(struct iio_trigger *trig, bool state)
AT91_ADC_CH(chan->channel));
}

+ st->cur_trig = trig;
at91_adc_writel(st, AT91_ADC_IER, reg->drdy_mask);

} else {
--
2.56.0