Skip to content

Commit bf8367b

Browse files
jmaneyrol-invnjic23
authored andcommitted
iio: invensense: fix timestamp glitches when switching frequency
When a sensor is running and there is a FIFO frequency change due to another sensor turned on/off, there are glitches on timestamp. Fix that by using only interrupt timestamp when there is the corresponding sensor data in the FIFO. Delete FIFO period handling and simplify internal functions. Update integration inside inv_mpu6050 and inv_icm42600 drivers. Fixes: 0ecc363 ("iio: make invensense timestamp module generic") Cc: Stable@vger.kernel.org Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com> Link: https://lore.kernel.org/r/20240426094835.138389-1-inv.git-commit@tdk.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent 0340dc4 commit bf8367b

4 files changed

Lines changed: 21 additions & 28 deletions

File tree

drivers/iio/common/inv_sensors/inv_sensors_timestamp.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -70,29 +70,29 @@ int inv_sensors_timestamp_update_odr(struct inv_sensors_timestamp *ts,
7070
}
7171
EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_update_odr, IIO_INV_SENSORS_TIMESTAMP);
7272

73-
static bool inv_validate_period(struct inv_sensors_timestamp *ts, uint32_t period, uint32_t mult)
73+
static bool inv_validate_period(struct inv_sensors_timestamp *ts, uint32_t period)
7474
{
7575
uint32_t period_min, period_max;
7676

7777
/* check that period is acceptable */
78-
period_min = ts->min_period * mult;
79-
period_max = ts->max_period * mult;
78+
period_min = ts->min_period * ts->mult;
79+
period_max = ts->max_period * ts->mult;
8080
if (period > period_min && period < period_max)
8181
return true;
8282
else
8383
return false;
8484
}
8585

8686
static bool inv_update_chip_period(struct inv_sensors_timestamp *ts,
87-
uint32_t mult, uint32_t period)
87+
uint32_t period)
8888
{
8989
uint32_t new_chip_period;
9090

91-
if (!inv_validate_period(ts, period, mult))
91+
if (!inv_validate_period(ts, period))
9292
return false;
9393

9494
/* update chip internal period estimation */
95-
new_chip_period = period / mult;
95+
new_chip_period = period / ts->mult;
9696
inv_update_acc(&ts->chip_period, new_chip_period);
9797
ts->period = ts->mult * ts->chip_period.val;
9898

@@ -125,16 +125,14 @@ static void inv_align_timestamp_it(struct inv_sensors_timestamp *ts)
125125
}
126126

127127
void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts,
128-
uint32_t fifo_period, size_t fifo_nb,
129-
size_t sensor_nb, int64_t timestamp)
128+
size_t sample_nb, int64_t timestamp)
130129
{
131130
struct inv_sensors_timestamp_interval *it;
132131
int64_t delta, interval;
133-
const uint32_t fifo_mult = fifo_period / ts->chip.clock_period;
134132
uint32_t period;
135133
bool valid = false;
136134

137-
if (fifo_nb == 0)
135+
if (sample_nb == 0)
138136
return;
139137

140138
/* update interrupt timestamp and compute chip and sensor periods */
@@ -144,14 +142,14 @@ void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts,
144142
delta = it->up - it->lo;
145143
if (it->lo != 0) {
146144
/* compute period: delta time divided by number of samples */
147-
period = div_s64(delta, fifo_nb);
148-
valid = inv_update_chip_period(ts, fifo_mult, period);
145+
period = div_s64(delta, sample_nb);
146+
valid = inv_update_chip_period(ts, period);
149147
}
150148

151149
/* no previous data, compute theoritical value from interrupt */
152150
if (ts->timestamp == 0) {
153151
/* elapsed time: sensor period * sensor samples number */
154-
interval = (int64_t)ts->period * (int64_t)sensor_nb;
152+
interval = (int64_t)ts->period * (int64_t)sample_nb;
155153
ts->timestamp = it->up - interval;
156154
return;
157155
}

drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -512,20 +512,20 @@ int inv_icm42600_buffer_fifo_parse(struct inv_icm42600_state *st)
512512
return 0;
513513

514514
/* handle gyroscope timestamp and FIFO data parsing */
515-
ts = &gyro_st->ts;
516-
inv_sensors_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total,
517-
st->fifo.nb.gyro, st->timestamp.gyro);
518515
if (st->fifo.nb.gyro > 0) {
516+
ts = &gyro_st->ts;
517+
inv_sensors_timestamp_interrupt(ts, st->fifo.nb.gyro,
518+
st->timestamp.gyro);
519519
ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro);
520520
if (ret)
521521
return ret;
522522
}
523523

524524
/* handle accelerometer timestamp and FIFO data parsing */
525-
ts = &accel_st->ts;
526-
inv_sensors_timestamp_interrupt(ts, st->fifo.period, st->fifo.nb.total,
527-
st->fifo.nb.accel, st->timestamp.accel);
528525
if (st->fifo.nb.accel > 0) {
526+
ts = &accel_st->ts;
527+
inv_sensors_timestamp_interrupt(ts, st->fifo.nb.accel,
528+
st->timestamp.accel);
529529
ret = inv_icm42600_accel_parse_fifo(st->indio_accel);
530530
if (ret)
531531
return ret;
@@ -555,19 +555,15 @@ int inv_icm42600_buffer_hwfifo_flush(struct inv_icm42600_state *st,
555555

556556
if (st->fifo.nb.gyro > 0) {
557557
ts = &gyro_st->ts;
558-
inv_sensors_timestamp_interrupt(ts, st->fifo.period,
559-
st->fifo.nb.total, st->fifo.nb.gyro,
560-
gyro_ts);
558+
inv_sensors_timestamp_interrupt(ts, st->fifo.nb.gyro, gyro_ts);
561559
ret = inv_icm42600_gyro_parse_fifo(st->indio_gyro);
562560
if (ret)
563561
return ret;
564562
}
565563

566564
if (st->fifo.nb.accel > 0) {
567565
ts = &accel_st->ts;
568-
inv_sensors_timestamp_interrupt(ts, st->fifo.period,
569-
st->fifo.nb.total, st->fifo.nb.accel,
570-
accel_ts);
566+
inv_sensors_timestamp_interrupt(ts, st->fifo.nb.accel, accel_ts);
571567
ret = inv_icm42600_accel_parse_fifo(st->indio_accel);
572568
if (ret)
573569
return ret;

drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
100100
goto end_session;
101101
/* Each FIFO data contains all sensors, so same number for FIFO and sensor data */
102102
fifo_period = NSEC_PER_SEC / INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider);
103-
inv_sensors_timestamp_interrupt(&st->timestamp, fifo_period, nb, nb, pf->timestamp);
103+
inv_sensors_timestamp_interrupt(&st->timestamp, nb, pf->timestamp);
104104
inv_sensors_timestamp_apply_odr(&st->timestamp, fifo_period, nb, 0);
105105

106106
/* clear internal data buffer for avoiding kernel data leak */

include/linux/iio/common/inv_sensors_timestamp.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ int inv_sensors_timestamp_update_odr(struct inv_sensors_timestamp *ts,
7171
uint32_t period, bool fifo);
7272

7373
void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts,
74-
uint32_t fifo_period, size_t fifo_nb,
75-
size_t sensor_nb, int64_t timestamp);
74+
size_t sample_nb, int64_t timestamp);
7675

7776
static inline int64_t inv_sensors_timestamp_pop(struct inv_sensors_timestamp *ts)
7877
{

0 commit comments

Comments
 (0)