diff options
| author | Lorenzo Bianconi <lorenzo@kernel.org> | 2019-05-19 04:58:23 -0400 |
|---|---|---|
| committer | Jonathan Cameron <Jonathan.Cameron@huawei.com> | 2019-05-27 05:52:30 -0400 |
| commit | bce0d57db388cdb1c1931d0aa7d31c77b590e0f0 (patch) | |
| tree | 8a8ce83f462f52f59bd5724095bb9a958e2e3036 | |
| parent | df4d737ee4d7205aaa6275158aeebff87fd14488 (diff) | |
iio: imu: st_lsm6dsx: fix PM support for st_lsm6dsx i2c controller
Properly suspend/resume i2c slaves connected to st_lsm6dsx master
controller if the CPU goes in suspended state
Fixes: c91c1c844ebd ("imu: st_lsm6dsx: add i2c embedded controller support")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
| -rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | 2 | ||||
| -rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 25 |
2 files changed, 19 insertions, 8 deletions
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h index 004a8a1a0027..6ef3577234a0 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h | |||
| @@ -271,6 +271,7 @@ struct st_lsm6dsx_sensor { | |||
| 271 | * @conf_lock: Mutex to prevent concurrent FIFO configuration update. | 271 | * @conf_lock: Mutex to prevent concurrent FIFO configuration update. |
| 272 | * @page_lock: Mutex to prevent concurrent memory page configuration. | 272 | * @page_lock: Mutex to prevent concurrent memory page configuration. |
| 273 | * @fifo_mode: FIFO operating mode supported by the device. | 273 | * @fifo_mode: FIFO operating mode supported by the device. |
| 274 | * @suspend_mask: Suspended sensor bitmask. | ||
| 274 | * @enable_mask: Enabled sensor bitmask. | 275 | * @enable_mask: Enabled sensor bitmask. |
| 275 | * @ts_sip: Total number of timestamp samples in a given pattern. | 276 | * @ts_sip: Total number of timestamp samples in a given pattern. |
| 276 | * @sip: Total number of samples (acc/gyro/ts) in a given pattern. | 277 | * @sip: Total number of samples (acc/gyro/ts) in a given pattern. |
| @@ -288,6 +289,7 @@ struct st_lsm6dsx_hw { | |||
| 288 | struct mutex page_lock; | 289 | struct mutex page_lock; |
| 289 | 290 | ||
| 290 | enum st_lsm6dsx_fifo_mode fifo_mode; | 291 | enum st_lsm6dsx_fifo_mode fifo_mode; |
| 292 | u8 suspend_mask; | ||
| 291 | u8 enable_mask; | 293 | u8 enable_mask; |
| 292 | u8 ts_sip; | 294 | u8 ts_sip; |
| 293 | u8 sip; | 295 | u8 sip; |
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index cf82c9049945..be5c87c8266d 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | |||
| @@ -1110,8 +1110,6 @@ static int __maybe_unused st_lsm6dsx_suspend(struct device *dev) | |||
| 1110 | { | 1110 | { |
| 1111 | struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev); | 1111 | struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev); |
| 1112 | struct st_lsm6dsx_sensor *sensor; | 1112 | struct st_lsm6dsx_sensor *sensor; |
| 1113 | const struct st_lsm6dsx_reg *reg; | ||
| 1114 | unsigned int data; | ||
| 1115 | int i, err = 0; | 1113 | int i, err = 0; |
| 1116 | 1114 | ||
| 1117 | for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { | 1115 | for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { |
| @@ -1122,12 +1120,16 @@ static int __maybe_unused st_lsm6dsx_suspend(struct device *dev) | |||
| 1122 | if (!(hw->enable_mask & BIT(sensor->id))) | 1120 | if (!(hw->enable_mask & BIT(sensor->id))) |
| 1123 | continue; | 1121 | continue; |
| 1124 | 1122 | ||
| 1125 | reg = &st_lsm6dsx_odr_table[sensor->id].reg; | 1123 | if (sensor->id == ST_LSM6DSX_ID_EXT0 || |
| 1126 | data = ST_LSM6DSX_SHIFT_VAL(0, reg->mask); | 1124 | sensor->id == ST_LSM6DSX_ID_EXT1 || |
| 1127 | err = st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, | 1125 | sensor->id == ST_LSM6DSX_ID_EXT2) |
| 1128 | data); | 1126 | err = st_lsm6dsx_shub_set_enable(sensor, false); |
| 1127 | else | ||
| 1128 | err = st_lsm6dsx_sensor_set_enable(sensor, false); | ||
| 1129 | if (err < 0) | 1129 | if (err < 0) |
| 1130 | return err; | 1130 | return err; |
| 1131 | |||
| 1132 | hw->suspend_mask |= BIT(sensor->id); | ||
| 1131 | } | 1133 | } |
| 1132 | 1134 | ||
| 1133 | if (hw->fifo_mode != ST_LSM6DSX_FIFO_BYPASS) | 1135 | if (hw->fifo_mode != ST_LSM6DSX_FIFO_BYPASS) |
| @@ -1147,12 +1149,19 @@ static int __maybe_unused st_lsm6dsx_resume(struct device *dev) | |||
| 1147 | continue; | 1149 | continue; |
| 1148 | 1150 | ||
| 1149 | sensor = iio_priv(hw->iio_devs[i]); | 1151 | sensor = iio_priv(hw->iio_devs[i]); |
| 1150 | if (!(hw->enable_mask & BIT(sensor->id))) | 1152 | if (!(hw->suspend_mask & BIT(sensor->id))) |
| 1151 | continue; | 1153 | continue; |
| 1152 | 1154 | ||
| 1153 | err = st_lsm6dsx_set_odr(sensor, sensor->odr); | 1155 | if (sensor->id == ST_LSM6DSX_ID_EXT0 || |
| 1156 | sensor->id == ST_LSM6DSX_ID_EXT1 || | ||
| 1157 | sensor->id == ST_LSM6DSX_ID_EXT2) | ||
| 1158 | err = st_lsm6dsx_shub_set_enable(sensor, true); | ||
| 1159 | else | ||
| 1160 | err = st_lsm6dsx_sensor_set_enable(sensor, true); | ||
| 1154 | if (err < 0) | 1161 | if (err < 0) |
| 1155 | return err; | 1162 | return err; |
| 1163 | |||
| 1164 | hw->suspend_mask &= ~BIT(sensor->id); | ||
| 1156 | } | 1165 | } |
| 1157 | 1166 | ||
| 1158 | if (hw->enable_mask) | 1167 | if (hw->enable_mask) |
