Skip to content

Commit ba0f923

Browse files
ukleineknunojsa
authored andcommitted
iio: adc: ad_sigma_delta: Add support for reading irq status using a GPIO
Some of the ADCs by Analog signal their irq condition on the MISO line. So typically that line is connected to an SPI controller and a GPIO. The GPIO is used as input and the respective interrupt is enabled when the last SPI transfer is completed. Depending on the GPIO controller the toggling MISO line might make the interrupt pending even while it's masked. In that case the irq handler is called immediately after irq_enable() and so before the device actually pulls that line low which results in non-sense values being reported to the upper layers. The only way to find out if the line was actually pulled low is to read the GPIO. (There is a flag in AD7124's status register that also signals if an interrupt was asserted, but reading that register toggles the MISO line and so might trigger another spurious interrupt.) Add the possibility to specify an interrupt GPIO in the machine description in addition to the plain interrupt. This GPIO is used then to check if the irq line is actually active in the irq handler. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com> Link: https://patch.msgid.link/5be9a4cc4dc600ec384c88db01dd661a21506b9c.1733504533.git.u.kleine-koenig@baylibre.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> Origin: next-20241216~37^2~22, commit:a87ef09b1fdf75fdc2d6b386ff23a35589173055
1 parent a080219 commit ba0f923

File tree

2 files changed

+35
-5
lines changed

2 files changed

+35
-5
lines changed

drivers/iio/adc/ad_sigma_delta.c

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -600,12 +600,29 @@ static irqreturn_t ad_sd_data_rdy_trig_poll(int irq, void *private)
600600
{
601601
struct ad_sigma_delta *sigma_delta = private;
602602

603-
complete(&sigma_delta->completion);
604-
disable_irq_nosync(irq);
605-
sigma_delta->irq_dis = true;
606-
iio_trigger_poll(sigma_delta->trig);
603+
/*
604+
* AD7124 and a few others use the same physical line for interrupt
605+
* reporting (R̅D̅Y̅) and MISO.
606+
* As MISO toggles when reading a register, this likely results in a
607+
* pending interrupt. This has two consequences: a) The irq might
608+
* trigger immediately after it's enabled even though the conversion
609+
* isn't done yet; and b) checking the STATUS register's R̅D̅Y̅ flag is
610+
* off-limits as reading that would trigger another irq event.
611+
*
612+
* So read the MOSI line as GPIO (if available) and only trigger the irq
613+
* if the line is active. Without such a GPIO assume this is a valid
614+
* interrupt.
615+
*/
616+
if (!sigma_delta->rdy_gpiod || gpiod_get_value(sigma_delta->rdy_gpiod)) {
617+
complete(&sigma_delta->completion);
618+
disable_irq_nosync(irq);
619+
sigma_delta->irq_dis = true;
620+
iio_trigger_poll(sigma_delta->trig);
607621

608-
return IRQ_HANDLED;
622+
return IRQ_HANDLED;
623+
}
624+
625+
return IRQ_NONE;
609626
}
610627

611628
/**
@@ -738,6 +755,17 @@ int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
738755
else
739756
sigma_delta->irq_line = spi->irq;
740757

758+
sigma_delta->rdy_gpiod = devm_gpiod_get_optional(&spi->dev, "rdy", GPIOD_IN);
759+
if (IS_ERR(sigma_delta->rdy_gpiod))
760+
return dev_err_probe(&spi->dev, PTR_ERR(sigma_delta->rdy_gpiod),
761+
"Failed to find rdy gpio\n");
762+
763+
if (sigma_delta->rdy_gpiod && !sigma_delta->irq_line) {
764+
sigma_delta->irq_line = gpiod_to_irq(sigma_delta->rdy_gpiod);
765+
if (sigma_delta->irq_line < 0)
766+
return sigma_delta->irq_line;
767+
}
768+
741769
iio_device_set_drvdata(indio_dev, sigma_delta);
742770

743771
return 0;

include/linux/iio/adc/ad_sigma_delta.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ struct ad_sd_calib_data {
2727

2828
struct ad_sigma_delta;
2929
struct device;
30+
struct gpio_desc;
3031
struct iio_dev;
3132

3233
/**
@@ -94,6 +95,7 @@ struct ad_sigma_delta {
9495
unsigned int active_slots;
9596
unsigned int current_slot;
9697
unsigned int num_slots;
98+
struct gpio_desc *rdy_gpiod;
9799
int irq_line;
98100
bool status_appended;
99101
/* map slots to channels in order to know what to expect from devices */

0 commit comments

Comments
 (0)