[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