diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c index 3ebd84f06e366..f25df7f32ac8e 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -30,6 +30,7 @@ #include #include /* For irq_get_irq_data() */ #include +#include #include "bmp280.h" @@ -336,6 +337,7 @@ static int bmp280_read_raw(struct iio_dev *indio_dev, int ret; struct bmp280_data *data = iio_priv(indio_dev); + pm_runtime_get_sync(data->dev); mutex_lock(&data->lock); switch (mask) { @@ -380,6 +382,8 @@ static int bmp280_read_raw(struct iio_dev *indio_dev, } mutex_unlock(&data->lock); + pm_runtime_mark_last_busy(data->dev); + pm_runtime_put_autosuspend(data->dev); return ret; } @@ -444,6 +448,7 @@ static int bmp280_write_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_OVERSAMPLING_RATIO: + pm_runtime_get_sync(data->dev); mutex_lock(&data->lock); switch (chan->type) { case IIO_HUMIDITYRELATIVE: @@ -460,6 +465,8 @@ static int bmp280_write_raw(struct iio_dev *indio_dev, break; } mutex_unlock(&data->lock); + pm_runtime_mark_last_busy(data->dev); + pm_runtime_put_autosuspend(data->dev); break; default: return -EINVAL; @@ -1021,12 +1028,29 @@ int bmp280_common_probe(struct device *dev, goto out_disable_vdda; } + /* Enable runtime PM */ + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + /* + * Set autosuspend to two orders of magnitude larger than the + * start-up time. + */ + pm_runtime_set_autosuspend_delay(dev, data->start_up_time *100); + pm_runtime_use_autosuspend(dev); + pm_runtime_put(dev); + ret = iio_device_register(indio_dev); if (ret) - goto out_disable_vdda; + goto out_runtime_pm_disable; + return 0; +out_runtime_pm_disable: + pm_runtime_get_sync(data->dev); + pm_runtime_put_noidle(data->dev); + pm_runtime_disable(data->dev); out_disable_vdda: regulator_disable(data->vdda); out_disable_vddd: @@ -1041,12 +1065,51 @@ int bmp280_common_remove(struct device *dev) struct bmp280_data *data = iio_priv(indio_dev); iio_device_unregister(indio_dev); + pm_runtime_get_sync(data->dev); + pm_runtime_put_noidle(data->dev); + pm_runtime_disable(data->dev); regulator_disable(data->vdda); regulator_disable(data->vddd); return 0; } EXPORT_SYMBOL(bmp280_common_remove); +#ifdef CONFIG_PM +static int bmp280_runtime_suspend(struct device *dev) +{ + struct bmp280_data *data = dev_get_drvdata(dev); + int ret; + + ret = regulator_disable(data->vdda); + if (ret) + return ret; + return regulator_disable(data->vddd); +} + +static int bmp280_runtime_resume(struct device *dev) +{ + struct bmp280_data *data = dev_get_drvdata(dev); + int ret; + + ret = regulator_enable(data->vddd); + if (ret) + return ret; + ret = regulator_enable(data->vdda); + if (ret) + return ret; + msleep(data->start_up_time); + return data->chip_info->chip_config(data); +} +#endif /* CONFIG_PM */ + +const struct dev_pm_ops bmp280_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) + SET_RUNTIME_PM_OPS(bmp280_runtime_suspend, + bmp280_runtime_resume, NULL) +}; +EXPORT_SYMBOL(bmp280_dev_pm_ops); + MODULE_AUTHOR("Vlad Dogaru "); MODULE_DESCRIPTION("Driver for Bosch Sensortec BMP180/BMP280 pressure and temperature sensor"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c index 8cf8a900bdaab..03742b15b72a4 100644 --- a/drivers/iio/pressure/bmp280-i2c.c +++ b/drivers/iio/pressure/bmp280-i2c.c @@ -78,6 +78,7 @@ static struct i2c_driver bmp280_i2c_driver = { .name = "bmp280", .acpi_match_table = ACPI_PTR(bmp280_acpi_i2c_match), .of_match_table = of_match_ptr(bmp280_of_i2c_match), + .pm = &bmp280_dev_pm_ops, }, .probe = bmp280_i2c_probe, .remove = bmp280_i2c_remove, diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c index cd365ba74b68f..17bc95586f9e2 100644 --- a/drivers/iio/pressure/bmp280-spi.c +++ b/drivers/iio/pressure/bmp280-spi.c @@ -113,6 +113,7 @@ static struct spi_driver bmp280_spi_driver = { .driver = { .name = "bmp280", .of_match_table = bmp280_of_spi_match, + .pm = &bmp280_dev_pm_ops, }, .id_table = bmp280_spi_id, .probe = bmp280_spi_probe, diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h index 573334b8e93b6..2c770e13be0e4 100644 --- a/drivers/iio/pressure/bmp280.h +++ b/drivers/iio/pressure/bmp280.h @@ -107,3 +107,6 @@ int bmp280_common_probe(struct device *dev, const char *name, int irq); int bmp280_common_remove(struct device *dev); + +/* PM ops */ +extern const struct dev_pm_ops bmp280_dev_pm_ops;