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

iio: imu: inv_mpu6050: use the common inv_sensors timestamp module

Replace timestamping by the new common inv_sensors timestamp
module. The principle behind is the same but the implementation in
the new module is far better providing less jitter and a better
estimation.

Signed-off-by: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Link: https://lore.kernel.org/r/20230606162147.79667-5-inv.git-commit@tdk.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Jean-Baptiste Maneyrol and committed by
Jonathan Cameron
111e1abd 0ecc363c

+46 -94
+1
drivers/iio/imu/inv_mpu6050/Kconfig
··· 7 7 tristate 8 8 select IIO_BUFFER 9 9 select IIO_TRIGGERED_BUFFER 10 + select IIO_INV_SENSORS_TIMESTAMP 10 11 11 12 config INV_MPU6050_I2C 12 13 tristate "Invensense MPU6050 devices (I2C)"
+23 -7
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
··· 12 12 #include <linux/jiffies.h> 13 13 #include <linux/irq.h> 14 14 #include <linux/interrupt.h> 15 - #include <linux/iio/iio.h> 16 15 #include <linux/acpi.h> 17 16 #include <linux/platform_device.h> 18 17 #include <linux/regulator/consumer.h> 19 18 #include <linux/pm.h> 20 19 #include <linux/pm_runtime.h> 20 + 21 + #include <linux/iio/common/inv_sensors_timestamp.h> 22 + #include <linux/iio/iio.h> 23 + 21 24 #include "inv_mpu_iio.h" 22 25 #include "inv_mpu_magn.h" 23 26 ··· 524 521 int result; 525 522 u8 d; 526 523 struct inv_mpu6050_state *st = iio_priv(indio_dev); 524 + struct inv_sensors_timestamp_chip timestamp; 527 525 528 526 result = inv_mpu6050_set_gyro_fsr(st, st->chip_config.fsr); 529 527 if (result) ··· 548 544 if (result) 549 545 return result; 550 546 551 - /* 552 - * Internal chip period is 1ms (1kHz). 553 - * Let's use at the beginning the theorical value before measuring 554 - * with interrupt timestamps. 555 - */ 556 - st->chip_period = NSEC_PER_MSEC; 547 + /* clock jitter is +/- 2% */ 548 + timestamp.clock_period = NSEC_PER_SEC / INV_MPU6050_INTERNAL_FREQ_HZ; 549 + timestamp.jitter = 20; 550 + timestamp.init_period = 551 + NSEC_PER_SEC / INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider); 552 + inv_sensors_timestamp_init(&st->timestamp, &timestamp); 557 553 558 554 /* magn chip init, noop if not present in the chip */ 559 555 result = inv_mpu_magn_probe(st); ··· 940 936 const char *buf, size_t count) 941 937 { 942 938 int fifo_rate; 939 + u32 fifo_period; 940 + bool fifo_on; 943 941 u8 d; 944 942 int result; 945 943 struct iio_dev *indio_dev = dev_to_iio_dev(dev); ··· 958 952 d = INV_MPU6050_FIFO_RATE_TO_DIVIDER(fifo_rate); 959 953 /* compute back the fifo rate to handle truncation cases */ 960 954 fifo_rate = INV_MPU6050_DIVIDER_TO_FIFO_RATE(d); 955 + fifo_period = NSEC_PER_SEC / fifo_rate; 961 956 962 957 mutex_lock(&st->lock); 963 958 if (d == st->chip_config.divider) { 964 959 result = 0; 965 960 goto fifo_rate_fail_unlock; 966 961 } 962 + 963 + fifo_on = st->chip_config.accl_fifo_enable || 964 + st->chip_config.gyro_fifo_enable || 965 + st->chip_config.magn_fifo_enable; 966 + result = inv_sensors_timestamp_update_odr(&st->timestamp, fifo_period, fifo_on); 967 + if (result) 968 + goto fifo_rate_fail_unlock; 969 + 967 970 result = pm_runtime_resume_and_get(pdev); 968 971 if (result) 969 972 goto fifo_rate_fail_unlock; ··· 1800 1785 MODULE_AUTHOR("Invensense Corporation"); 1801 1786 MODULE_DESCRIPTION("Invensense device MPU6050 driver"); 1802 1787 MODULE_LICENSE("GPL"); 1788 + MODULE_IMPORT_NS(IIO_INV_SENSORS_TIMESTAMP);
+8 -10
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
··· 9 9 #include <linux/i2c.h> 10 10 #include <linux/i2c-mux.h> 11 11 #include <linux/mutex.h> 12 - #include <linux/iio/iio.h> 13 - #include <linux/iio/buffer.h> 12 + #include <linux/platform_data/invensense_mpu6050.h> 14 13 #include <linux/regmap.h> 15 - #include <linux/iio/sysfs.h> 14 + 15 + #include <linux/iio/buffer.h> 16 + #include <linux/iio/common/inv_sensors_timestamp.h> 17 + #include <linux/iio/iio.h> 16 18 #include <linux/iio/kfifo_buf.h> 17 19 #include <linux/iio/trigger.h> 18 20 #include <linux/iio/triggered_buffer.h> 19 21 #include <linux/iio/trigger_consumer.h> 20 - #include <linux/platform_data/invensense_mpu6050.h> 22 + #include <linux/iio/sysfs.h> 21 23 22 24 /** 23 25 * struct inv_mpu6050_reg_map - Notable registers. ··· 172 170 * @map regmap pointer. 173 171 * @irq interrupt number. 174 172 * @irq_mask the int_pin_cfg mask to configure interrupt type. 175 - * @chip_period: chip internal period estimation (~1kHz). 176 - * @it_timestamp: timestamp from previous interrupt. 177 - * @data_timestamp: timestamp for next data sample. 173 + * @timestamp: timestamping module 178 174 * @vdd_supply: VDD voltage regulator for the chip. 179 175 * @vddio_supply I/O voltage regulator for the chip. 180 176 * @magn_disabled: magnetometer disabled for backward compatibility reason. ··· 196 196 int irq; 197 197 u8 irq_mask; 198 198 unsigned skip_samples; 199 - s64 chip_period; 200 - s64 it_timestamp; 201 - s64 data_timestamp; 199 + struct inv_sensors_timestamp timestamp; 202 200 struct regulator *vdd_supply; 203 201 struct regulator *vddio_supply; 204 202 bool magn_disabled;
+9 -76
drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
··· 13 13 #include <linux/interrupt.h> 14 14 #include <linux/poll.h> 15 15 #include <linux/math64.h> 16 + 17 + #include <linux/iio/common/inv_sensors_timestamp.h> 18 + 16 19 #include "inv_mpu_iio.h" 17 - 18 - /** 19 - * inv_mpu6050_update_period() - Update chip internal period estimation 20 - * 21 - * @st: driver state 22 - * @timestamp: the interrupt timestamp 23 - * @nb: number of data set in the fifo 24 - * 25 - * This function uses interrupt timestamps to estimate the chip period and 26 - * to choose the data timestamp to come. 27 - */ 28 - static void inv_mpu6050_update_period(struct inv_mpu6050_state *st, 29 - s64 timestamp, size_t nb) 30 - { 31 - /* Period boundaries for accepting timestamp */ 32 - const s64 period_min = 33 - (NSEC_PER_MSEC * (100 - INV_MPU6050_TS_PERIOD_JITTER)) / 100; 34 - const s64 period_max = 35 - (NSEC_PER_MSEC * (100 + INV_MPU6050_TS_PERIOD_JITTER)) / 100; 36 - const s32 divider = INV_MPU6050_FREQ_DIVIDER(st); 37 - s64 delta, interval; 38 - bool use_it_timestamp = false; 39 - 40 - if (st->it_timestamp == 0) { 41 - /* not initialized, forced to use it_timestamp */ 42 - use_it_timestamp = true; 43 - } else if (nb == 1) { 44 - /* 45 - * Validate the use of it timestamp by checking if interrupt 46 - * has been delayed. 47 - * nb > 1 means interrupt was delayed for more than 1 sample, 48 - * so it's obviously not good. 49 - * Compute the chip period between 2 interrupts for validating. 50 - */ 51 - delta = div_s64(timestamp - st->it_timestamp, divider); 52 - if (delta > period_min && delta < period_max) { 53 - /* update chip period and use it timestamp */ 54 - st->chip_period = (st->chip_period + delta) / 2; 55 - use_it_timestamp = true; 56 - } 57 - } 58 - 59 - if (use_it_timestamp) { 60 - /* 61 - * Manage case of multiple samples in the fifo (nb > 1): 62 - * compute timestamp corresponding to the first sample using 63 - * estimated chip period. 64 - */ 65 - interval = (nb - 1) * st->chip_period * divider; 66 - st->data_timestamp = timestamp - interval; 67 - } 68 - 69 - /* save it timestamp */ 70 - st->it_timestamp = timestamp; 71 - } 72 - 73 - /** 74 - * inv_mpu6050_get_timestamp() - Return the current data timestamp 75 - * 76 - * @st: driver state 77 - * @return: current data timestamp 78 - * 79 - * This function returns the current data timestamp and prepares for next one. 80 - */ 81 - static s64 inv_mpu6050_get_timestamp(struct inv_mpu6050_state *st) 82 - { 83 - s64 ts; 84 - 85 - /* return current data timestamp and increment */ 86 - ts = st->data_timestamp; 87 - st->data_timestamp += st->chip_period * INV_MPU6050_FREQ_DIVIDER(st); 88 - 89 - return ts; 90 - } 91 20 92 21 static int inv_reset_fifo(struct iio_dev *indio_dev) 93 22 { ··· 50 121 size_t bytes_per_datum; 51 122 int result; 52 123 u16 fifo_count; 124 + u32 fifo_period; 53 125 s64 timestamp; 54 126 int int_status; 55 127 size_t i, nb; ··· 107 177 108 178 /* compute and process all complete datum */ 109 179 nb = fifo_count / bytes_per_datum; 110 - inv_mpu6050_update_period(st, pf->timestamp, nb); 180 + /* Each FIFO data contains all sensors, so same number for FIFO and sensor data */ 181 + fifo_period = NSEC_PER_SEC / INV_MPU6050_DIVIDER_TO_FIFO_RATE(st->chip_config.divider); 182 + inv_sensors_timestamp_interrupt(&st->timestamp, fifo_period, nb, nb, pf->timestamp); 183 + inv_sensors_timestamp_apply_odr(&st->timestamp, fifo_period, nb, 0); 111 184 for (i = 0; i < nb; ++i) { 112 185 result = regmap_noinc_read(st->map, st->reg->fifo_r_w, 113 186 st->data, bytes_per_datum); ··· 121 188 st->skip_samples--; 122 189 continue; 123 190 } 124 - timestamp = inv_mpu6050_get_timestamp(st); 191 + timestamp = inv_sensors_timestamp_pop(&st->timestamp); 125 192 iio_push_to_buffers_with_timestamp(indio_dev, st->data, timestamp); 126 193 } 127 194
+5 -1
drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
··· 4 4 */ 5 5 6 6 #include <linux/pm_runtime.h> 7 + 8 + #include <linux/iio/common/inv_sensors_timestamp.h> 9 + 7 10 #include "inv_mpu_iio.h" 8 11 9 12 static unsigned int inv_scan_query_mpu6050(struct iio_dev *indio_dev) ··· 109 106 int ret; 110 107 111 108 if (enable) { 112 - st->it_timestamp = 0; 109 + /* reset timestamping */ 110 + inv_sensors_timestamp_reset(&st->timestamp); 113 111 /* reset FIFO */ 114 112 d = st->chip_config.user_ctrl | INV_MPU6050_BIT_FIFO_RST; 115 113 ret = regmap_write(st->map, st->reg->user_ctrl, d);