Re: [PATCH v2 2/2] iio: light: vcnl4000: add shared IRQ support
Jonathan Cameron <[email protected]>
| Newsgroups | org.kernel.vger.linux-iio,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <20260822032550.31a0fa9e@jic23-huawei> |
On Fri, 14 Aug 2026 14:30:43 +1000 Tsz Shan Chan <[email protected]> wrote: > 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. Fairly low risk change but I guess we'll see. It used to be annoyingly common for interrupt controllers to support only edge based interrupts, but hopefully that silliness is a thing of the past. So crossed fingers, I'll apply this and see if we get anyone shouting. I think we'll get away with it Thanks, Jonathan > > 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) >