]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
iio: light: bh1750: Add hardware reset support via GPIO
authorSergio Perez <sergio@pereznus.es>
Mon, 24 Mar 2025 13:59:20 +0000 (14:59 +0100)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Tue, 22 Apr 2025 18:09:51 +0000 (19:09 +0100)
Some BH1750 sensors require a hardware reset before they can be
detected on the I2C bus. This implementation adds support for an
optional reset GPIO that can be specified in the device tree.

The reset sequence pulls the GPIO low and then high before initializing
the sensor, which enables proper detection with tools like i2cdetect.
This is particularly important for sensors that power on in an
undefined state.

Signed-off-by: Sergio Perez <sergio@pereznus.es>
Link: https://patch.msgid.link/20250324135920.6802-2-sergio@pereznus.es
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/light/bh1750.c

index 4b869fa9e5b17ed179b2c357fff1cb244e9172f2..764f88826fcbc2c14ed7093eaaf18a70808b54a6 100644 (file)
 #include <linux/iio/iio.h>
 #include <linux/iio/sysfs.h>
 #include <linux/module.h>
+#include <linux/gpio/consumer.h>
 
 #define BH1750_POWER_DOWN              0x00
 #define BH1750_ONE_TIME_H_RES_MODE     0x20 /* auto-mode for BH1721 */
 #define BH1750_CHANGE_INT_TIME_H_BIT   0x40
 #define BH1750_CHANGE_INT_TIME_L_BIT   0x60
 
+/* Define the reset delay time in microseconds */
+#define BH1750_RESET_DELAY_US 10000 /* 10ms */
+
 enum {
        BH1710,
        BH1721,
@@ -40,6 +44,7 @@ struct bh1750_data {
        struct mutex lock;
        const struct bh1750_chip_info *chip_info;
        u16 mtreg;
+       struct gpio_desc *reset_gpio;
 };
 
 struct bh1750_chip_info {
@@ -248,6 +253,25 @@ static int bh1750_probe(struct i2c_client *client)
        data->client = client;
        data->chip_info = &bh1750_chip_info_tbl[id->driver_data];
 
+       /* Get reset GPIO from device tree */
+       data->reset_gpio = devm_gpiod_get_optional(&client->dev,
+                                                  "reset", GPIOD_OUT_HIGH);
+
+       if (IS_ERR(data->reset_gpio))
+               return dev_err_probe(&client->dev, PTR_ERR(data->reset_gpio),
+                                    "Failed to get reset GPIO\n");
+
+       /* Perform hardware reset if GPIO is provided */
+       if (data->reset_gpio) {
+               /* Perform reset sequence: low-high */
+               gpiod_set_value_cansleep(data->reset_gpio, 1);
+               fsleep(BH1750_RESET_DELAY_US);
+               gpiod_set_value_cansleep(data->reset_gpio, 0);
+               fsleep(BH1750_RESET_DELAY_US);
+
+               dev_dbg(&client->dev, "BH1750 reset completed via GPIO\n");
+       }
+
        usec = data->chip_info->mtreg_to_usec * data->chip_info->mtreg_default;
        ret = bh1750_change_int_time(data, usec);
        if (ret < 0)