iio: imu: st_lsm6dsx: add system power management support
Add system sleep power management support to st_lsm6dsx driver. In particular during suspend phase each sensor is disabled and hw fifo is configured in bypass in order to avoid subsequent I/O operations. The patch has been tested on HiKey board device Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@st.com> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
This commit is contained in:
parent
535de397b2
commit
d3f770582a
|
@ -135,6 +135,8 @@ struct st_lsm6dsx_hw {
|
||||||
#endif /* CONFIG_SPI_MASTER */
|
#endif /* CONFIG_SPI_MASTER */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern const struct dev_pm_ops st_lsm6dsx_pm_ops;
|
||||||
|
|
||||||
int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name,
|
int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name,
|
||||||
const struct st_lsm6dsx_transfer_function *tf_ops);
|
const struct st_lsm6dsx_transfer_function *tf_ops);
|
||||||
int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor);
|
int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor);
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/iio/iio.h>
|
#include <linux/iio/iio.h>
|
||||||
#include <linux/iio/sysfs.h>
|
#include <linux/iio/sysfs.h>
|
||||||
|
#include <linux/pm.h>
|
||||||
|
|
||||||
#include <linux/platform_data/st_sensors_pdata.h>
|
#include <linux/platform_data/st_sensors_pdata.h>
|
||||||
|
|
||||||
|
@ -731,6 +732,59 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(st_lsm6dsx_probe);
|
EXPORT_SYMBOL(st_lsm6dsx_probe);
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
static int st_lsm6dsx_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev);
|
||||||
|
struct st_lsm6dsx_sensor *sensor;
|
||||||
|
int i, err = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
|
||||||
|
sensor = iio_priv(hw->iio_devs[i]);
|
||||||
|
if (!(hw->enable_mask & BIT(sensor->id)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
err = st_lsm6dsx_write_with_mask(hw,
|
||||||
|
st_lsm6dsx_odr_table[sensor->id].reg.addr,
|
||||||
|
st_lsm6dsx_odr_table[sensor->id].reg.mask, 0);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hw->fifo_mode != ST_LSM6DSX_FIFO_BYPASS)
|
||||||
|
err = st_lsm6dsx_flush_fifo(hw);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int st_lsm6dsx_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev);
|
||||||
|
struct st_lsm6dsx_sensor *sensor;
|
||||||
|
int i, err = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) {
|
||||||
|
sensor = iio_priv(hw->iio_devs[i]);
|
||||||
|
if (!(hw->enable_mask & BIT(sensor->id)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
err = st_lsm6dsx_set_odr(sensor, sensor->odr);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hw->enable_mask)
|
||||||
|
err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_PM */
|
||||||
|
|
||||||
|
const struct dev_pm_ops st_lsm6dsx_pm_ops = {
|
||||||
|
SET_SYSTEM_SLEEP_PM_OPS(st_lsm6dsx_suspend, st_lsm6dsx_resume)
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL(st_lsm6dsx_pm_ops);
|
||||||
|
|
||||||
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
|
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
|
||||||
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
|
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
|
||||||
MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx driver");
|
MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx driver");
|
||||||
|
|
|
@ -98,6 +98,7 @@ MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table);
|
||||||
static struct i2c_driver st_lsm6dsx_driver = {
|
static struct i2c_driver st_lsm6dsx_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "st_lsm6dsx_i2c",
|
.name = "st_lsm6dsx_i2c",
|
||||||
|
.pm = &st_lsm6dsx_pm_ops,
|
||||||
.of_match_table = of_match_ptr(st_lsm6dsx_i2c_of_match),
|
.of_match_table = of_match_ptr(st_lsm6dsx_i2c_of_match),
|
||||||
},
|
},
|
||||||
.probe = st_lsm6dsx_i2c_probe,
|
.probe = st_lsm6dsx_i2c_probe,
|
||||||
|
|
|
@ -115,6 +115,7 @@ MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table);
|
||||||
static struct spi_driver st_lsm6dsx_driver = {
|
static struct spi_driver st_lsm6dsx_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "st_lsm6dsx_spi",
|
.name = "st_lsm6dsx_spi",
|
||||||
|
.pm = &st_lsm6dsx_pm_ops,
|
||||||
.of_match_table = of_match_ptr(st_lsm6dsx_spi_of_match),
|
.of_match_table = of_match_ptr(st_lsm6dsx_spi_of_match),
|
||||||
},
|
},
|
||||||
.probe = st_lsm6dsx_spi_probe,
|
.probe = st_lsm6dsx_spi_probe,
|
||||||
|
|
Loading…
Reference in New Issue