diff --git a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c index 2aaaa8df6d03..88a82d1370c5 100644 --- a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c +++ b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c @@ -16,6 +16,9 @@ #define INV_SENSORS_TIMESTAMP_MAX(_val, _jitter) \ (((_val) * (1000 + (_jitter))) / 1000) +/* minimum timestamp delta between 2 interrupts for measuring period (20ms) */ +#define INV_SENSORS_MIN_IT_DELTA (20 * NSEC_PER_MSEC) + /* Add a new value inside an accumulator and update the estimate value */ static void inv_update_acc(struct inv_sensors_timestamp_acc *acc, u32 val) { @@ -122,7 +125,7 @@ void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts, size_t sample_nb, s64 timestamp) { struct inv_sensors_timestamp_interval *it; - s64 delta, interval; + s64 delta, delta_threshold, interval; u32 period; bool valid = false; @@ -136,15 +139,32 @@ void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts, ts->timestamp = timestamp - interval; } + /* update delta timestamps and estimated period */ + it = &ts->delta; + ts->delta_counter += sample_nb; + delta = timestamp - it->up; + delta_threshold = INV_SENSORS_TIMESTAMP_MIN(INV_SENSORS_MIN_IT_DELTA, ts->chip.jitter); + if (delta >= delta_threshold) { + it->lo = it->up; + it->up = timestamp; + if (it->lo != 0) { + /* compute period: delta time divided by number of samples */ + delta = it->up - it->lo; + period = div_s64(delta, ts->delta_counter); + inv_update_chip_period(ts, period); + } + ts->delta_counter = 0; + } + /* update interrupt timestamp and compute chip and sensor periods */ it = &ts->it; it->lo = it->up; it->up = timestamp; delta = it->up - it->lo; if (it->lo != 0) { - /* compute period: delta time divided by number of samples */ + /* compute period and check validity */ period = div_s64(delta, sample_nb); - valid = inv_update_chip_period(ts, period); + valid = inv_validate_period(ts, period); } /* if interrupt interval is valid, sync with interrupt timestamp */ diff --git a/include/linux/iio/common/inv_sensors_timestamp.h b/include/linux/iio/common/inv_sensors_timestamp.h index e4e720e6f4b7..4f08204ede3b 100644 --- a/include/linux/iio/common/inv_sensors_timestamp.h +++ b/include/linux/iio/common/inv_sensors_timestamp.h @@ -46,6 +46,8 @@ struct inv_sensors_timestamp_acc { * @min_period: minimal acceptable clock period * @max_period: maximal acceptable clock period * @it: interrupts interval timestamps + * @delta: interval timestamps between several interrupts + * @delta_counter: number of data samples in the delta interval * @timestamp: store last timestamp for computing next data timestamp * @mult: current internal period multiplier * @new_mult: new set internal period multiplier (not yet effective) @@ -57,6 +59,8 @@ struct inv_sensors_timestamp { u32 min_period; u32 max_period; struct inv_sensors_timestamp_interval it; + struct inv_sensors_timestamp_interval delta; + u32 delta_counter; s64 timestamp; u32 mult; u32 new_mult; @@ -88,6 +92,8 @@ static inline void inv_sensors_timestamp_reset(struct inv_sensors_timestamp *ts) const struct inv_sensors_timestamp_interval interval_init = {0LL, 0LL}; ts->it = interval_init; + ts->delta = interval_init; + ts->delta_counter = 0; ts->timestamp = 0; }