public inbox for linux-iio@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] iio: adc: ad_sigma_delta: fix CS held asserted after single conversion
@ 2026-04-28 13:45 Radu Sabau via B4 Relay
  2026-04-28 16:41 ` Uwe Kleine-König
  0 siblings, 1 reply; 2+ messages in thread
From: Radu Sabau via B4 Relay @ 2026-04-28 13:45 UTC (permalink / raw)
  To: Lars-Peter Clausen, Michael Hennerich, Jonathan Cameron,
	David Lechner, Nuno Sá, Andy Shevchenko,
	Uwe Kleine-König
  Cc: linux-iio, linux-kernel, Jonathan Cameron, Radu Sabau

From: Radu Sabau <radu.sabau@analog.com>

Commit 132d44dc6966 ("iio: adc: ad_sigma_delta: Check for previous
ready signals") introduced a new out_unlock: label for an early-exit
path and moved sigma_delta->keep_cs_asserted = false there.
Unfortunately it left ad_sigma_delta_disable_one() in the out: block
above that label, so disable_one()'s SPI write is issued while
keep_cs_asserted is still true.  keep_cs_asserted feeds directly into
the cs_change field of the spi_transfer, so the final write to the
device carries cs_change=1.  The SPI framework only calls spi_set_cs()
to deassert CS as part of message teardown when cs_change is not set on
the last transfer; with cs_change=1, that teardown is skipped and CS
stays physically asserted.  No further transfer to the device is made,
so the driver never deasserts CS.  The framework provides no automatic
CS deassert on bus unlock or when switching to another device, so CS
remains stuck low until the next SPI operation to that same device.

On a shared SPI bus this is problematic: with CS stuck low the ADC
remains selected and subsequent SPI traffic intended for another device
is interpreted as commands by the ADC.  Devices like the AD7124 that
multiplex /RDY onto the MISO line will start spurious conversions and
pull MISO low, corrupting reads from the other device and causing a
deadlock.

Fix by moving ad_sigma_delta_disable_one() into the out_unlock: block,
after keep_cs_asserted is cleared.  The final SPI write now carries
cs_change=0, so the SPI framework deasserts CS as part of normal
message teardown.

As a side effect this also calls disable_one() on the early-exit path
when ad_sigma_delta_clear_pending_event() fails.  That path already had
ad_sigma_delta_set_channel() called, so calling disable_one() to undo
it is the right thing to do and is consistent with ad_sd_calibrate().

Fixes: 132d44dc6966 ("iio: adc: ad_sigma_delta: Check for previous ready signals")
Signed-off-by: Radu Sabau <radu.sabau@analog.com>
---
 drivers/iio/adc/ad_sigma_delta.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index a955556f9ec8..43aa296922c6 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -442,10 +442,10 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev,
 	ad_sd_disable_irq(sigma_delta);
 
 	ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE);
-	ad_sigma_delta_disable_one(sigma_delta, chan->address);
 
 out_unlock:
 	sigma_delta->keep_cs_asserted = false;
+	ad_sigma_delta_disable_one(sigma_delta, chan->address);
 	sigma_delta->bus_locked = false;
 	spi_bus_unlock(sigma_delta->spi->controller);
 out_release:

---
base-commit: 3b3bea6d4b9c162f9e555905d96b8c1da67ecd5b
change-id: 20260428-ad_sigma_delta-fix-bb65d56ccbb0

Best regards,
-- 
Radu Sabau <radu.sabau@analog.com>



^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-04-28 16:41 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-28 13:45 [PATCH] iio: adc: ad_sigma_delta: fix CS held asserted after single conversion Radu Sabau via B4 Relay
2026-04-28 16:41 ` Uwe Kleine-König

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox