Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Lorenzo Bianconi and committed by
Jonathan Cameron
bce0d57d df4d737e

+19 -8
+2
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
··· 271 271 * @conf_lock: Mutex to prevent concurrent FIFO configuration update. 272 272 * @page_lock: Mutex to prevent concurrent memory page configuration. 273 273 * @fifo_mode: FIFO operating mode supported by the device. 274 + * @suspend_mask: Suspended sensor bitmask. 274 275 * @enable_mask: Enabled sensor bitmask. 275 276 * @ts_sip: Total number of timestamp samples in a given pattern. 276 277 * @sip: Total number of samples (acc/gyro/ts) in a given pattern. ··· 289 288 struct mutex page_lock; 290 289 291 290 enum st_lsm6dsx_fifo_mode fifo_mode; 291 + u8 suspend_mask; 292 292 u8 enable_mask; 293 293 u8 ts_sip; 294 294 u8 sip;
+17 -8
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
··· 1110 1110 { 1111 1111 struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev); 1112 1112 struct st_lsm6dsx_sensor *sensor; 1113 - const struct st_lsm6dsx_reg *reg; 1114 - unsigned int data; 1115 1113 int i, err = 0; 1116 1114 1117 1115 for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { ··· 1120 1122 if (!(hw->enable_mask & BIT(sensor->id))) 1121 1123 continue; 1122 1124 1123 - reg = &st_lsm6dsx_odr_table[sensor->id].reg; 1124 - data = ST_LSM6DSX_SHIFT_VAL(0, reg->mask); 1125 - err = st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, 1126 - data); 1125 + if (sensor->id == ST_LSM6DSX_ID_EXT0 || 1126 + sensor->id == ST_LSM6DSX_ID_EXT1 || 1127 + sensor->id == ST_LSM6DSX_ID_EXT2) 1128 + err = st_lsm6dsx_shub_set_enable(sensor, false); 1129 + else 1130 + err = st_lsm6dsx_sensor_set_enable(sensor, false); 1127 1131 if (err < 0) 1128 1132 return err; 1133 + 1134 + hw->suspend_mask |= BIT(sensor->id); 1129 1135 } 1130 1136 1131 1137 if (hw->fifo_mode != ST_LSM6DSX_FIFO_BYPASS) ··· 1149 1147 continue; 1150 1148 1151 1149 sensor = iio_priv(hw->iio_devs[i]); 1152 - if (!(hw->enable_mask & BIT(sensor->id))) 1150 + if (!(hw->suspend_mask & BIT(sensor->id))) 1153 1151 continue; 1154 1152 1155 - err = st_lsm6dsx_set_odr(sensor, sensor->odr); 1153 + if (sensor->id == ST_LSM6DSX_ID_EXT0 || 1154 + sensor->id == ST_LSM6DSX_ID_EXT1 || 1155 + sensor->id == ST_LSM6DSX_ID_EXT2) 1156 + err = st_lsm6dsx_shub_set_enable(sensor, true); 1157 + else 1158 + err = st_lsm6dsx_sensor_set_enable(sensor, true); 1156 1159 if (err < 0) 1157 1160 return err; 1161 + 1162 + hw->suspend_mask &= ~BIT(sensor->id); 1158 1163 } 1159 1164 1160 1165 if (hw->enable_mask)