]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
iio: light: vl6180: Added Interrupt support for single shot access
authorAbhash Jha <abhashkumarjha123@gmail.com>
Mon, 7 Oct 2024 15:22:22 +0000 (20:52 +0530)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Tue, 15 Oct 2024 17:59:51 +0000 (18:59 +0100)
The interrupts are serviced in the `vl6180_measure` function when the
irq_handler signals that the reading is complete. We now can read
asynchronously if `client->irq` is set.

Signed-off-by: Abhash Jha <abhashkumarjha123@gmail.com>
Link: https://patch.msgid.link/20241007152223.59008-3-abhashkumarjha123@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/light/vl6180.c

index 67aa2f101598f90e53185bd700e8578fb0ece645..0801071774b81e5944c38dbdcee9d6ef13696035 100644 (file)
@@ -86,6 +86,7 @@
 struct vl6180_data {
        struct i2c_client *client;
        struct mutex lock;
+       struct completion completion;
        unsigned int als_gain_milli;
        unsigned int als_it_ms;
        unsigned int als_meas_rate;
@@ -211,29 +212,40 @@ static int vl6180_write_word(struct i2c_client *client, u16 cmd, u16 val)
 static int vl6180_measure(struct vl6180_data *data, int addr)
 {
        struct i2c_client *client = data->client;
+       unsigned long time_left;
        int tries = 20, ret;
        u16 value;
 
        mutex_lock(&data->lock);
+       reinit_completion(&data->completion);
+
        /* Start single shot measurement */
        ret = vl6180_write_byte(client,
                vl6180_chan_regs_table[addr].start_reg, VL6180_STARTSTOP);
        if (ret < 0)
                goto fail;
 
-       while (tries--) {
-               ret = vl6180_read_byte(client, VL6180_INTR_STATUS);
-               if (ret < 0)
+       if (client->irq) {
+               time_left = wait_for_completion_timeout(&data->completion, HZ / 10);
+               if (time_left == 0) {
+                       ret = -ETIMEDOUT;
                        goto fail;
+               }
+       } else {
+               while (tries--) {
+                       ret = vl6180_read_byte(client, VL6180_INTR_STATUS);
+                       if (ret < 0)
+                               goto fail;
+
+                       if (ret & vl6180_chan_regs_table[addr].drdy_mask)
+                               break;
+                       msleep(20);
+               }
 
-               if (ret & vl6180_chan_regs_table[addr].drdy_mask)
-                       break;
-               msleep(20);
-       }
-
-       if (tries < 0) {
-               ret = -EIO;
-               goto fail;
+               if (tries < 0) {
+                       ret = -EIO;
+                       goto fail;
+               }
        }
 
        /* Read result value from appropriate registers */
@@ -484,6 +496,15 @@ static int vl6180_write_raw(struct iio_dev *indio_dev,
        }
 }
 
+static irqreturn_t vl6180_threaded_irq(int irq, void *priv)
+{
+       struct iio_dev *indio_dev = priv;
+       struct vl6180_data *data = iio_priv(indio_dev);
+
+       complete(&data->completion);
+       return IRQ_HANDLED;
+}
+
 static const struct iio_info vl6180_info = {
        .read_raw = vl6180_read_raw,
        .write_raw = vl6180_write_raw,
@@ -583,6 +604,17 @@ static int vl6180_probe(struct i2c_client *client)
        if (ret < 0)
                return ret;
 
+       if (client->irq) {
+               ret = devm_request_threaded_irq(&client->dev, client->irq,
+                                               NULL, vl6180_threaded_irq,
+                                               IRQF_ONESHOT,
+                                               indio_dev->name, indio_dev);
+               if (ret)
+                       return dev_err_probe(&client->dev, ret, "devm_request_irq error \n");
+
+               init_completion(&data->completion);
+       }
+
        return devm_iio_device_register(&client->dev, indio_dev);
 }