]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
iio: chemical: bme680: add power management
authorVasileios Amoiridis <vassilisamir@gmail.com>
Mon, 2 Dec 2024 19:23:41 +0000 (20:23 +0100)
committerJonathan Cameron <Jonathan.Cameron@huawei.com>
Wed, 11 Dec 2024 19:20:49 +0000 (19:20 +0000)
Add runtime power management to the device.

Signed-off-by: Vasileios Amoiridis <vassilisamir@gmail.com>
Link: https://patch.msgid.link/20241202192341.33187-4-vassilisamir@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
drivers/iio/chemical/bme680.h
drivers/iio/chemical/bme680_core.c
drivers/iio/chemical/bme680_i2c.c
drivers/iio/chemical/bme680_spi.c

index 00ab89b3138b4fe072e829d652abffebaa06b741..7d86ed8b02e6b54cdda0802fd73bdfdf1d09e43a 100644 (file)
@@ -2,6 +2,7 @@
 #ifndef BME680_H_
 #define BME680_H_
 
+#include <linux/pm.h>
 #include <linux/regmap.h>
 
 #define BME680_REG_CHIP_ID                     0xD0
@@ -80,6 +81,7 @@
 #define BME680_CALIB_RANGE_3_LEN               5
 
 extern const struct regmap_config bme680_regmap_config;
+extern const struct dev_pm_ops bme680_dev_pm_ops;
 
 int bme680_core_probe(struct device *dev, struct regmap *regmap,
                      const char *name);
index 0fb13e36462f726a114ad60f6f6f7a39dbed3135..26eb0fa77a43d232f09b4284bab7d1fa3ed673dc 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/device.h>
 #include <linux/log2.h>
 #include <linux/module.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 
@@ -820,9 +822,9 @@ static int bme680_read_gas(struct bme680_data *data, int *comp_gas_res)
        return 0;
 }
 
-static int bme680_read_raw(struct iio_dev *indio_dev,
-                          struct iio_chan_spec const *chan,
-                          int *val, int *val2, long mask)
+static int __bme680_read_raw(struct iio_dev *indio_dev,
+                            struct iio_chan_spec const *chan,
+                            int *val, int *val2, long mask)
 {
        struct bme680_data *data = iio_priv(indio_dev);
        int chan_val, ret;
@@ -935,14 +937,33 @@ static int bme680_read_raw(struct iio_dev *indio_dev,
        }
 }
 
+static int bme680_read_raw(struct iio_dev *indio_dev,
+                          struct iio_chan_spec const *chan,
+                          int *val, int *val2, long mask)
+{
+       struct bme680_data *data = iio_priv(indio_dev);
+       struct device *dev = regmap_get_device(data->regmap);
+       int ret;
+
+       ret = pm_runtime_resume_and_get(dev);
+       if (ret)
+               return ret;
+
+       ret = __bme680_read_raw(indio_dev, chan, val, val2, mask);
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+
+       return ret;
+}
+
 static bool bme680_is_valid_oversampling(int rate)
 {
        return (rate > 0 && rate <= 16 && is_power_of_2(rate));
 }
 
-static int bme680_write_raw(struct iio_dev *indio_dev,
-                           struct iio_chan_spec const *chan,
-                           int val, int val2, long mask)
+static int __bme680_write_raw(struct iio_dev *indio_dev,
+                             struct iio_chan_spec const *chan,
+                             int val, int val2, long mask)
 {
        struct bme680_data *data = iio_priv(indio_dev);
 
@@ -987,6 +1008,25 @@ static int bme680_write_raw(struct iio_dev *indio_dev,
        }
 }
 
+static int bme680_write_raw(struct iio_dev *indio_dev,
+                           struct iio_chan_spec const *chan,
+                           int val, int val2, long mask)
+{
+       struct bme680_data *data = iio_priv(indio_dev);
+       struct device *dev = regmap_get_device(data->regmap);
+       int ret;
+
+       ret = pm_runtime_resume_and_get(dev);
+       if (ret)
+               return ret;
+
+       ret = __bme680_write_raw(indio_dev, chan, val, val2, mask);
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+
+       return ret;
+}
+
 static const char bme680_oversampling_ratio_show[] = "1 2 4 8 16";
 
 static IIO_CONST_ATTR(oversampling_ratio_available,
@@ -1087,6 +1127,29 @@ out:
        return IRQ_HANDLED;
 }
 
+static int bme680_buffer_preenable(struct iio_dev *indio_dev)
+{
+       struct bme680_data *data = iio_priv(indio_dev);
+       struct device *dev = regmap_get_device(data->regmap);
+
+       return pm_runtime_resume_and_get(dev);
+}
+
+static int bme680_buffer_postdisable(struct iio_dev *indio_dev)
+{
+       struct bme680_data *data = iio_priv(indio_dev);
+       struct device *dev = regmap_get_device(data->regmap);
+
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
+       return 0;
+}
+
+static const struct iio_buffer_setup_ops bme680_buffer_setup_ops = {
+       .preenable = bme680_buffer_preenable,
+       .postdisable = bme680_buffer_postdisable,
+};
+
 int bme680_core_probe(struct device *dev, struct regmap *regmap,
                      const char *name)
 {
@@ -1160,15 +1223,47 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap,
        ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
                                              iio_pollfunc_store_time,
                                              bme680_trigger_handler,
-                                             NULL);
+                                             &bme680_buffer_setup_ops);
        if (ret)
                return dev_err_probe(dev, ret,
                                     "iio triggered buffer setup failed\n");
 
+       /* Enable runtime PM */
+       pm_runtime_set_autosuspend_delay(dev, BME680_STARTUP_TIME_US);
+       pm_runtime_use_autosuspend(dev);
+       pm_runtime_set_active(dev);
+       ret = devm_pm_runtime_enable(dev);
+       if (ret)
+               return ret;
+
        return devm_iio_device_register(dev, indio_dev);
 }
 EXPORT_SYMBOL_NS_GPL(bme680_core_probe, "IIO_BME680");
 
+static int bme680_runtime_suspend(struct device *dev)
+{
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct bme680_data *data = iio_priv(indio_dev);
+
+       return bme680_set_mode(data, BME680_MODE_SLEEP);
+}
+
+static int bme680_runtime_resume(struct device *dev)
+{
+       struct iio_dev *indio_dev = dev_get_drvdata(dev);
+       struct bme680_data *data = iio_priv(indio_dev);
+       int ret;
+
+       ret = bme680_chip_config(data);
+       if (ret)
+               return ret;
+
+       return bme680_gas_config(data);
+}
+
+EXPORT_RUNTIME_DEV_PM_OPS(bme680_dev_pm_ops, bme680_runtime_suspend,
+                         bme680_runtime_resume, NULL);
+
 MODULE_AUTHOR("Himanshu Jha <himanshujha199640@gmail.com>");
 MODULE_DESCRIPTION("Bosch BME680 Driver");
 MODULE_LICENSE("GPL v2");
index 7a949228b4a614a4e4c09553a4e640784cff0e2a..ac7763f98a6ab3e95bec342414f50728b1f9443b 100644 (file)
@@ -51,6 +51,7 @@ static struct i2c_driver bme680_i2c_driver = {
        .driver = {
                .name                   = "bme680_i2c",
                .of_match_table         = bme680_of_i2c_match,
+               .pm = pm_ptr(&bme680_dev_pm_ops),
        },
        .probe = bme680_i2c_probe,
        .id_table = bme680_i2c_id,
index 3916a51ba68e1712d79ed245432b8b40c80e0a00..ecb24ba0ebc9a75b530056e12dee9b641329f38b 100644 (file)
@@ -154,6 +154,7 @@ static struct spi_driver bme680_spi_driver = {
        .driver = {
                .name                   = "bme680_spi",
                .of_match_table         = bme680_of_spi_match,
+               .pm = pm_ptr(&bme680_dev_pm_ops),
        },
        .probe = bme680_spi_probe,
        .id_table = bme680_spi_id,