Commit 1e60a654 authored by Vasileios Amoiridis's avatar Vasileios Amoiridis Committed by Jonathan Cameron
Browse files

iio: chemical: bme680: add power management

parent 601f7269
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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);
+102 −7
Original line number Diff line number Diff line
@@ -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,7 +822,7 @@ 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,
static int __bme680_read_raw(struct iio_dev *indio_dev,
			     struct iio_chan_spec const *chan,
			     int *val, int *val2, long mask)
{
@@ -935,12 +937,31 @@ 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,
static int __bme680_write_raw(struct iio_dev *indio_dev,
			      struct iio_chan_spec const *chan,
			      int val, int val2, long mask)
{
@@ -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 @@ static irqreturn_t bme680_trigger_handler(int irq, void *p)
	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");
+1 −0
Original line number Diff line number Diff line
@@ -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,
+1 −0
Original line number Diff line number Diff line
@@ -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,