iio: adc: ad4695: Fix call ordering in offload buffer postenable

ad4695_enter_advanced_sequencer_mode() was called after
spi_offload_trigger_enable(). That is wrong because
ad4695_enter_advanced_sequencer_mode() issues regular SPI transfers to
put the ADC into advanced sequencer mode, and not all SPI offload capable
controllers support regular SPI transfers while offloading is enabled.

Fix this by calling ad4695_enter_advanced_sequencer_mode() before
spi_offload_trigger_enable(), so the ADC is fully configured before the
first CNV pulse can occur. This is consistent with the same constraint
that already applies to the BUSY_GP_EN write above it.

Update the error unwind labels accordingly: add err_exit_conversion_mode
so that a failure of spi_offload_trigger_enable() correctly exits
conversion mode before clearing BUSY_GP_EN.

Fixes: f09f140e3e ("iio: adc: ad4695: Add support for SPI offload")
Reviewed-by: Nuno Sá <nuno.sa@analog.com>
Reviewed-by: David Lechner <dlechner@baylibre.com>
Signed-off-by: Radu Sabau <radu.sabau@analog.com>
Cc: Stable@vger.kernel.org
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
Radu Sabau 2026-04-08 13:32:13 +03:00 committed by Jonathan Cameron
parent b66f922f6a
commit 1a77271931

View File

@ -876,14 +876,14 @@ static int ad4695_offload_buffer_postenable(struct iio_dev *indio_dev)
if (ret)
goto err_unoptimize_message;
ret = spi_offload_trigger_enable(st->offload, st->offload_trigger,
&config);
ret = ad4695_enter_advanced_sequencer_mode(st, num_slots);
if (ret)
goto err_disable_busy_output;
ret = ad4695_enter_advanced_sequencer_mode(st, num_slots);
ret = spi_offload_trigger_enable(st->offload, st->offload_trigger,
&config);
if (ret)
goto err_offload_trigger_disable;
goto err_exit_conversion_mode;
mutex_lock(&st->cnv_pwm_lock);
pwm_get_state(st->cnv_pwm, &state);
@ -895,23 +895,16 @@ static int ad4695_offload_buffer_postenable(struct iio_dev *indio_dev)
ret = pwm_apply_might_sleep(st->cnv_pwm, &state);
mutex_unlock(&st->cnv_pwm_lock);
if (ret)
goto err_offload_exit_conversion_mode;
goto err_offload_trigger_disable;
return 0;
err_offload_exit_conversion_mode:
/*
* We have to unwind in a different order to avoid triggering offload.
* ad4695_exit_conversion_mode() triggers a conversion, so it has to be
* done after spi_offload_trigger_disable().
*/
spi_offload_trigger_disable(st->offload, st->offload_trigger);
ad4695_exit_conversion_mode(st);
goto err_disable_busy_output;
err_offload_trigger_disable:
spi_offload_trigger_disable(st->offload, st->offload_trigger);
err_exit_conversion_mode:
ad4695_exit_conversion_mode(st);
err_disable_busy_output:
regmap_clear_bits(st->regmap, AD4695_REG_GP_MODE,
AD4695_REG_GP_MODE_BUSY_GP_EN);