aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio/imu/st_lsm6dsx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iio/imu/st_lsm6dsx')
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h5
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c20
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c52
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c1
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c1
5 files changed, 76 insertions, 3 deletions
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
index 4839db7b9690..46352c7bff43 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
@@ -135,6 +135,8 @@ struct st_lsm6dsx_hw {
#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,
const struct st_lsm6dsx_transfer_function *tf_ops);
int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor);
@@ -144,5 +146,8 @@ int st_lsm6dsx_write_with_mask(struct st_lsm6dsx_hw *hw, u8 addr, u8 mask,
u8 val);
int st_lsm6dsx_update_watermark(struct st_lsm6dsx_sensor *sensor,
u16 watermark);
+int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw);
+int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw,
+ enum st_lsm6dsx_fifo_mode fifo_mode);
#endif /* ST_LSM6DSX_H */
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
index c8e5cfd0ef0b..2a72acc6e049 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
@@ -37,6 +37,8 @@
#define ST_LSM6DSX_REG_FIFO_THH_ADDR 0x07
#define ST_LSM6DSX_FIFO_TH_MASK GENMASK(11, 0)
#define ST_LSM6DSX_REG_FIFO_DEC_GXL_ADDR 0x08
+#define ST_LSM6DSX_REG_HLACTIVE_ADDR 0x12
+#define ST_LSM6DSX_REG_HLACTIVE_MASK BIT(5)
#define ST_LSM6DSX_REG_FIFO_MODE_ADDR 0x0a
#define ST_LSM6DSX_FIFO_MODE_MASK GENMASK(2, 0)
#define ST_LSM6DSX_FIFO_ODR_MASK GENMASK(6, 3)
@@ -130,8 +132,8 @@ static int st_lsm6dsx_update_decimators(struct st_lsm6dsx_hw *hw)
return 0;
}
-static int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw,
- enum st_lsm6dsx_fifo_mode fifo_mode)
+int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw,
+ enum st_lsm6dsx_fifo_mode fifo_mode)
{
u8 data;
int err;
@@ -303,7 +305,7 @@ static int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
return read_len;
}
-static int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw)
+int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw)
{
int err;
@@ -417,6 +419,7 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
{
struct iio_buffer *buffer;
unsigned long irq_type;
+ bool irq_active_low;
int i, err;
irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
@@ -424,12 +427,23 @@ int st_lsm6dsx_fifo_setup(struct st_lsm6dsx_hw *hw)
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
+ irq_active_low = false;
+ break;
+ case IRQF_TRIGGER_LOW:
+ case IRQF_TRIGGER_FALLING:
+ irq_active_low = true;
break;
default:
dev_info(hw->dev, "mode %lx unsupported\n", irq_type);
return -EINVAL;
}
+ err = st_lsm6dsx_write_with_mask(hw, ST_LSM6DSX_REG_HLACTIVE_ADDR,
+ ST_LSM6DSX_REG_HLACTIVE_MASK,
+ irq_active_low);
+ if (err < 0)
+ return err;
+
err = devm_request_threaded_irq(hw->dev, hw->irq,
st_lsm6dsx_handler_irq,
st_lsm6dsx_handler_thread,
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
index 462a27b70453..b485540da89e 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -36,6 +36,7 @@
#include <linux/delay.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/pm.h>
#include <linux/platform_data/st_sensors_pdata.h>
@@ -731,6 +732,57 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name,
}
EXPORT_SYMBOL(st_lsm6dsx_probe);
+static int __maybe_unused 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 __maybe_unused 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;
+}
+
+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("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx driver");
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
index 09a51cfb9b5e..305fec712ab0 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
@@ -98,6 +98,7 @@ MODULE_DEVICE_TABLE(i2c, st_lsm6dsx_i2c_id_table);
static struct i2c_driver st_lsm6dsx_driver = {
.driver = {
.name = "st_lsm6dsx_i2c",
+ .pm = &st_lsm6dsx_pm_ops,
.of_match_table = of_match_ptr(st_lsm6dsx_i2c_of_match),
},
.probe = st_lsm6dsx_i2c_probe,
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
index f765a5058488..95472f153ad2 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
@@ -115,6 +115,7 @@ MODULE_DEVICE_TABLE(spi, st_lsm6dsx_spi_id_table);
static struct spi_driver st_lsm6dsx_driver = {
.driver = {
.name = "st_lsm6dsx_spi",
+ .pm = &st_lsm6dsx_pm_ops,
.of_match_table = of_match_ptr(st_lsm6dsx_spi_of_match),
},
.probe = st_lsm6dsx_spi_probe,