[PATCH v2 2/2] iio: light: vcnl4000: add shared IRQ support

Tsz Shan Chan <[email protected]>
Newsgroups org.kernel.vger.linux-iio,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
The INT output of vcnl4010/4020 and vcnl4040/4200 is open drain active
low which can be shared with other devices.
Add IRQF_SHARED and switch the trigger type from IRQF_TRIGGER_FALLING to
IRQF_TRIGGER_LOW. Edge triggering can miss interrupts on a shared line.

Return IRQ_NONE from the irq handler when read fails or when none of the
interrupt source bits handled by the driver are set. This prevents
claiming interrupts from other devices on a shared line.

Signed-off-by: Tsz Shan Chan <[email protected]>
---
 drivers/iio/light/vcnl4000.c | 16 +++++++++++-----
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index 663e623da833..8a723eaadbb6 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -1470,7 +1470,11 @@ static irqreturn_t vcnl4040_irq_thread(int irq, void *p)
 
 	ret = i2c_smbus_read_word_data(data->client, data->chip_spec->int_reg);
 	if (ret < 0)
-		return IRQ_HANDLED;
+		return IRQ_NONE;
+
+	if (!(ret & (VCNL4040_PS_IF_CLOSE | VCNL4040_PS_IF_AWAY |
+		     VCNL4040_ALS_FALLING | VCNL4040_ALS_RISING)))
+		return IRQ_NONE;
 
 	if (ret & VCNL4040_PS_IF_CLOSE) {
 		iio_push_event(indio_dev,
@@ -1526,7 +1530,10 @@ static irqreturn_t vcnl4010_irq_thread(int irq, void *p)
 
 	ret = i2c_smbus_read_byte_data(data->client, VCNL4010_ISR);
 	if (ret < 0)
-		goto end;
+		return IRQ_NONE;
+
+	if (!(ret & (VCNL4010_INT_THR | VCNL4010_INT_DRDY)))
+		return IRQ_NONE;
 
 	isr = ret;
 
@@ -1558,7 +1565,6 @@ static irqreturn_t vcnl4010_irq_thread(int irq, void *p)
 	if (isr & VCNL4010_INT_DRDY && iio_buffer_enabled(indio_dev))
 		iio_trigger_poll_nested(indio_dev->trig);
 
-end:
 	return IRQ_HANDLED;
 }
 
@@ -1981,8 +1987,8 @@ static int vcnl4000_probe(struct i2c_client *client)
 	if (client->irq && data->chip_spec->irq_thread) {
 		ret = devm_request_threaded_irq(dev, client->irq, NULL,
 						data->chip_spec->irq_thread,
-						IRQF_TRIGGER_FALLING |
-						IRQF_ONESHOT,
+						IRQF_TRIGGER_LOW |
+						IRQF_ONESHOT | IRQF_SHARED,
 						"vcnl4000_irq",
 						indio_dev);
 		if (ret < 0)

-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.