Commit 7762902c authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Jonathan Cameron

iio: imu: st_lsm6dsx: fix read misalignment on untagged FIFO

st_lsm6dsx suffers of a read misalignment on untagged FIFO when
all 3 supported sensors (accel, gyro and ext device) are running
at different ODRs (the use-case is reported in the LSM6DSM Application
Note at pag 100).
Fix the issue taking into account decimation factor reading the FIFO
pattern.

Fixes: e485e2a2 ("iio: imu: st_lsm6dsx: enable sensor-hub support for lsm6dsm")
Signed-off-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent e2042d29
...@@ -337,6 +337,7 @@ enum st_lsm6dsx_fifo_mode { ...@@ -337,6 +337,7 @@ enum st_lsm6dsx_fifo_mode {
* @gain: Configured sensor sensitivity. * @gain: Configured sensor sensitivity.
* @odr: Output data rate of the sensor [Hz]. * @odr: Output data rate of the sensor [Hz].
* @watermark: Sensor watermark level. * @watermark: Sensor watermark level.
* @decimator: Sensor decimation factor.
* @sip: Number of samples in a given pattern. * @sip: Number of samples in a given pattern.
* @ts_ref: Sensor timestamp reference for hw one. * @ts_ref: Sensor timestamp reference for hw one.
* @ext_info: Sensor settings if it is connected to i2c controller * @ext_info: Sensor settings if it is connected to i2c controller
...@@ -350,6 +351,7 @@ struct st_lsm6dsx_sensor { ...@@ -350,6 +351,7 @@ struct st_lsm6dsx_sensor {
u32 odr; u32 odr;
u16 watermark; u16 watermark;
u8 decimator;
u8 sip; u8 sip;
s64 ts_ref; s64 ts_ref;
......
...@@ -93,6 +93,7 @@ st_lsm6dsx_get_decimator_val(struct st_lsm6dsx_sensor *sensor, u32 max_odr) ...@@ -93,6 +93,7 @@ st_lsm6dsx_get_decimator_val(struct st_lsm6dsx_sensor *sensor, u32 max_odr)
break; break;
} }
sensor->decimator = decimator;
return i == max_size ? 0 : st_lsm6dsx_decimator_table[i].val; return i == max_size ? 0 : st_lsm6dsx_decimator_table[i].val;
} }
...@@ -337,7 +338,7 @@ static inline int st_lsm6dsx_read_block(struct st_lsm6dsx_hw *hw, u8 addr, ...@@ -337,7 +338,7 @@ static inline int st_lsm6dsx_read_block(struct st_lsm6dsx_hw *hw, u8 addr,
int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
{ {
struct st_lsm6dsx_sensor *acc_sensor, *gyro_sensor, *ext_sensor = NULL; struct st_lsm6dsx_sensor *acc_sensor, *gyro_sensor, *ext_sensor = NULL;
int err, acc_sip, gyro_sip, ts_sip, ext_sip, read_len, offset; int err, sip, acc_sip, gyro_sip, ts_sip, ext_sip, read_len, offset;
u16 fifo_len, pattern_len = hw->sip * ST_LSM6DSX_SAMPLE_SIZE; u16 fifo_len, pattern_len = hw->sip * ST_LSM6DSX_SAMPLE_SIZE;
u16 fifo_diff_mask = hw->settings->fifo_ops.fifo_diff.mask; u16 fifo_diff_mask = hw->settings->fifo_ops.fifo_diff.mask;
u8 gyro_buff[ST_LSM6DSX_IIO_BUFF_SIZE]; u8 gyro_buff[ST_LSM6DSX_IIO_BUFF_SIZE];
...@@ -399,19 +400,20 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) ...@@ -399,19 +400,20 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
acc_sip = acc_sensor->sip; acc_sip = acc_sensor->sip;
ts_sip = hw->ts_sip; ts_sip = hw->ts_sip;
offset = 0; offset = 0;
sip = 0;
while (acc_sip > 0 || gyro_sip > 0 || ext_sip > 0) { while (acc_sip > 0 || gyro_sip > 0 || ext_sip > 0) {
if (gyro_sip > 0) { if (gyro_sip > 0 && !(sip % gyro_sensor->decimator)) {
memcpy(gyro_buff, &hw->buff[offset], memcpy(gyro_buff, &hw->buff[offset],
ST_LSM6DSX_SAMPLE_SIZE); ST_LSM6DSX_SAMPLE_SIZE);
offset += ST_LSM6DSX_SAMPLE_SIZE; offset += ST_LSM6DSX_SAMPLE_SIZE;
} }
if (acc_sip > 0) { if (acc_sip > 0 && !(sip % acc_sensor->decimator)) {
memcpy(acc_buff, &hw->buff[offset], memcpy(acc_buff, &hw->buff[offset],
ST_LSM6DSX_SAMPLE_SIZE); ST_LSM6DSX_SAMPLE_SIZE);
offset += ST_LSM6DSX_SAMPLE_SIZE; offset += ST_LSM6DSX_SAMPLE_SIZE;
} }
if (ext_sip > 0) { if (ext_sip > 0 && !(sip % ext_sensor->decimator)) {
memcpy(ext_buff, &hw->buff[offset], memcpy(ext_buff, &hw->buff[offset],
ST_LSM6DSX_SAMPLE_SIZE); ST_LSM6DSX_SAMPLE_SIZE);
offset += ST_LSM6DSX_SAMPLE_SIZE; offset += ST_LSM6DSX_SAMPLE_SIZE;
...@@ -441,18 +443,25 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw) ...@@ -441,18 +443,25 @@ int st_lsm6dsx_read_fifo(struct st_lsm6dsx_hw *hw)
offset += ST_LSM6DSX_SAMPLE_SIZE; offset += ST_LSM6DSX_SAMPLE_SIZE;
} }
if (gyro_sip-- > 0) if (gyro_sip > 0 && !(sip % gyro_sensor->decimator)) {
iio_push_to_buffers_with_timestamp( iio_push_to_buffers_with_timestamp(
hw->iio_devs[ST_LSM6DSX_ID_GYRO], hw->iio_devs[ST_LSM6DSX_ID_GYRO],
gyro_buff, gyro_sensor->ts_ref + ts); gyro_buff, gyro_sensor->ts_ref + ts);
if (acc_sip-- > 0) gyro_sip--;
}
if (acc_sip > 0 && !(sip % acc_sensor->decimator)) {
iio_push_to_buffers_with_timestamp( iio_push_to_buffers_with_timestamp(
hw->iio_devs[ST_LSM6DSX_ID_ACC], hw->iio_devs[ST_LSM6DSX_ID_ACC],
acc_buff, acc_sensor->ts_ref + ts); acc_buff, acc_sensor->ts_ref + ts);
if (ext_sip-- > 0) acc_sip--;
}
if (ext_sip > 0 && !(sip % ext_sensor->decimator)) {
iio_push_to_buffers_with_timestamp( iio_push_to_buffers_with_timestamp(
hw->iio_devs[ST_LSM6DSX_ID_EXT0], hw->iio_devs[ST_LSM6DSX_ID_EXT0],
ext_buff, ext_sensor->ts_ref + ts); ext_buff, ext_sensor->ts_ref + ts);
ext_sip--;
}
sip++;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment