iio: adc: mcp3911: add reset management
authorMarcus Folkesson <marcus.folkesson@gmail.com>
Mon, 28 Apr 2025 06:54:13 +0000 (08:54 +0200)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Wed, 21 May 2025 13:20:30 +0000 (14:20 +0100)
Add support for optional HW reset.
If specified, a reset will be asserted during driver probe.

Co-developed-by: Lukas Rauber <lukas.rauber@janitza.de>
Signed-off-by: Lukas Rauber <lukas.rauber@janitza.de>
Signed-off-by: Marcus Folkesson <marcus.folkesson@gmail.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Link: https://patch.msgid.link/20250428-mcp3911-fixes-v2-3-406e39330c3d@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/adc/mcp3911.c

index 622d425..a6f2179 100644 (file)
@@ -10,7 +10,9 @@
 #include <linux/cleanup.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/dev_printk.h>
 #include <linux/err.h>
+#include <linux/gpio/consumer.h>
 #include <linux/module.h>
 #include <linux/mod_devicetable.h>
 #include <linux/property.h>
@@ -706,6 +708,7 @@ static const struct iio_trigger_ops mcp3911_trigger_ops = {
 static int mcp3911_probe(struct spi_device *spi)
 {
        struct device *dev = &spi->dev;
+       struct gpio_desc *gpio_reset;
        struct iio_dev *indio_dev;
        struct mcp3911 *adc;
        bool external_vref;
@@ -750,6 +753,22 @@ static int mcp3911_probe(struct spi_device *spi)
        }
        dev_dbg(dev, "use device address %i\n", adc->dev_addr);
 
+       gpio_reset = devm_gpiod_get_optional(&spi->dev, "reset", GPIOD_OUT_HIGH);
+       if (IS_ERR(gpio_reset))
+               return dev_err_probe(dev, PTR_ERR(gpio_reset),
+                                    "Cannot get reset GPIO\n");
+
+       if (gpio_reset) {
+               gpiod_set_value_cansleep(gpio_reset, 0);
+
+               /*
+                * Settling time after Hard Reset Mode (determined experimentally):
+                * 330 micro-seconds are too few; 470 micro-seconds are sufficient.
+                * Just in case, we add some safety factor...
+                */
+               fsleep(600);
+       }
+
        ret = adc->chip->config(adc, external_vref);
        if (ret)
                return ret;