[PATCH v3 5/5] iio: light: vcnl4000: add shared IRQ support
From: Tsz Shan Chan
Date: Thu Sep 03 2026 - 00:55:00 EST
Change the interrupt trigger to IRQF_TRIGGER_LOW and add IRQF_SHARED to
allow the sensor to share an interrupt 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.
The datasheets confirm that the INT pin is open drain active low, and
the interrupts are latched:
- vcnl4010/4020: The INT pin is open drain. It is pulled low
while a status bit is 1, and it stays low until the driver writes
a 1 to clear it.
- vcnl4040/4200: The INT pin is pulled low when a flag triggers. It
resets to high only after the driver reads the INT_Flag register.
Signed-off-by: Tsz Shan Chan <tchan@xxxxxxxxxxxxxx>
---
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 df929eab2bef..9855c2954429 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -1517,7 +1517,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,
@@ -1573,7 +1577,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;
@@ -1610,7 +1617,6 @@ static irqreturn_t vcnl4010_irq_thread(int irq, void *p)
isr & VCNL4010_INT_DRDY);
}
-end:
return IRQ_HANDLED;
}
@@ -2047,8 +2053,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