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

iio: imu: st_lsm6dsx: discard samples during filters settling time

During digital filters settling time the driver is expected to drop
samples since they can be corrupted. Introduce the capability to drop
a given number of samples according to the configured ODR.
Add sample_to_discard for LSM6DSM-like sensors since new generation
devices (e.g. LSM6DSO) support DRDY mask where corrupted samples are
masked in hw with values greather than 0x7ffd so the driver can easily
discard them.
I have not added sample_to_discard support for LSM6DS3 or LSM6DS3H since
I do not have any sample for testing at the moment.

Reported-by: Philippe De Muyter <phdm@macqel.be>
Tested-by: Philippe De Muyter <phdm@macqel.be>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://lore.kernel.org/r/21dcd94935c147ef9b1da4984b3da6264ee9609e.1677496295.git.lorenzo@kernel.org
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Lorenzo Bianconi and committed by
Jonathan Cameron
db3c4905 accb9d05

+78 -8
+11
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
··· 137 137 int odr_len; 138 138 }; 139 139 140 + struct st_lsm6dsx_samples_to_discard { 141 + struct { 142 + u32 milli_hz; 143 + u16 samples; 144 + } val[ST_LSM6DSX_ODR_LIST_SIZE]; 145 + }; 146 + 140 147 struct st_lsm6dsx_fs { 141 148 u32 gain; 142 149 u8 val; ··· 298 291 * @irq_config: interrupts related registers. 299 292 * @drdy_mask: register info for data-ready mask (addr + mask). 300 293 * @odr_table: Hw sensors odr table (Hz + val). 294 + * @samples_to_discard: Number of samples to discard for filters settling time. 301 295 * @fs_table: Hw sensors gain table (gain + val). 302 296 * @decimator: List of decimator register info (addr + mask). 303 297 * @batch: List of FIFO batching register info (addr + mask). ··· 331 323 } irq_config; 332 324 struct st_lsm6dsx_reg drdy_mask; 333 325 struct st_lsm6dsx_odr_table_entry odr_table[2]; 326 + struct st_lsm6dsx_samples_to_discard samples_to_discard[2]; 334 327 struct st_lsm6dsx_fs_table_entry fs_table[2]; 335 328 struct st_lsm6dsx_reg decimator[ST_LSM6DSX_MAX_ID]; 336 329 struct st_lsm6dsx_reg batch[ST_LSM6DSX_MAX_ID]; ··· 362 353 * @hw: Pointer to instance of struct st_lsm6dsx_hw. 363 354 * @gain: Configured sensor sensitivity. 364 355 * @odr: Output data rate of the sensor [Hz]. 356 + * @samples_to_discard: Number of samples to discard for filters settling time. 365 357 * @watermark: Sensor watermark level. 366 358 * @decimator: Sensor decimation factor. 367 359 * @sip: Number of samples in a given pattern. ··· 377 367 u32 gain; 378 368 u32 odr; 379 369 370 + u16 samples_to_discard; 380 371 u16 watermark; 381 372 u8 decimator; 382 373 u8 sip;
+49 -8
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
··· 457 457 } 458 458 459 459 if (gyro_sip > 0 && !(sip % gyro_sensor->decimator)) { 460 - iio_push_to_buffers_with_timestamp( 461 - hw->iio_devs[ST_LSM6DSX_ID_GYRO], 462 - &hw->scan[ST_LSM6DSX_ID_GYRO], 463 - gyro_sensor->ts_ref + ts); 460 + /* 461 + * We need to discards gyro samples during 462 + * filters settling time 463 + */ 464 + if (gyro_sensor->samples_to_discard > 0) 465 + gyro_sensor->samples_to_discard--; 466 + else 467 + iio_push_to_buffers_with_timestamp( 468 + hw->iio_devs[ST_LSM6DSX_ID_GYRO], 469 + &hw->scan[ST_LSM6DSX_ID_GYRO], 470 + gyro_sensor->ts_ref + ts); 464 471 gyro_sip--; 465 472 } 466 473 if (acc_sip > 0 && !(sip % acc_sensor->decimator)) { 467 - iio_push_to_buffers_with_timestamp( 468 - hw->iio_devs[ST_LSM6DSX_ID_ACC], 469 - &hw->scan[ST_LSM6DSX_ID_ACC], 470 - acc_sensor->ts_ref + ts); 474 + /* 475 + * We need to discards accel samples during 476 + * filters settling time 477 + */ 478 + if (acc_sensor->samples_to_discard > 0) 479 + acc_sensor->samples_to_discard--; 480 + else 481 + iio_push_to_buffers_with_timestamp( 482 + hw->iio_devs[ST_LSM6DSX_ID_ACC], 483 + &hw->scan[ST_LSM6DSX_ID_ACC], 484 + acc_sensor->ts_ref + ts); 471 485 acc_sip--; 472 486 } 473 487 if (ext_sip > 0 && !(sip % ext_sensor->decimator)) { ··· 668 654 return err; 669 655 } 670 656 657 + static void 658 + st_lsm6dsx_update_samples_to_discard(struct st_lsm6dsx_sensor *sensor) 659 + { 660 + const struct st_lsm6dsx_samples_to_discard *data; 661 + struct st_lsm6dsx_hw *hw = sensor->hw; 662 + int i; 663 + 664 + if (sensor->id != ST_LSM6DSX_ID_GYRO && 665 + sensor->id != ST_LSM6DSX_ID_ACC) 666 + return; 667 + 668 + /* check if drdy mask is supported in hw */ 669 + if (hw->settings->drdy_mask.addr) 670 + return; 671 + 672 + data = &hw->settings->samples_to_discard[sensor->id]; 673 + for (i = 0; i < ST_LSM6DSX_ODR_LIST_SIZE; i++) { 674 + if (data->val[i].milli_hz == sensor->odr) { 675 + sensor->samples_to_discard = data->val[i].samples; 676 + return; 677 + } 678 + } 679 + } 680 + 671 681 int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable) 672 682 { 673 683 struct st_lsm6dsx_hw *hw = sensor->hw; ··· 710 672 if (err < 0) 711 673 goto out; 712 674 } 675 + 676 + if (enable) 677 + st_lsm6dsx_update_samples_to_discard(sensor); 713 678 714 679 err = st_lsm6dsx_device_set_enable(sensor, enable); 715 680 if (err < 0)
+18
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
··· 634 634 .fs_len = 4, 635 635 }, 636 636 }, 637 + .samples_to_discard = { 638 + [ST_LSM6DSX_ID_ACC] = { 639 + .val[0] = { 12500, 1 }, 640 + .val[1] = { 26000, 1 }, 641 + .val[2] = { 52000, 1 }, 642 + .val[3] = { 104000, 2 }, 643 + .val[4] = { 208000, 2 }, 644 + .val[5] = { 416000, 2 }, 645 + }, 646 + [ST_LSM6DSX_ID_GYRO] = { 647 + .val[0] = { 12500, 2 }, 648 + .val[1] = { 26000, 5 }, 649 + .val[2] = { 52000, 7 }, 650 + .val[3] = { 104000, 12 }, 651 + .val[4] = { 208000, 20 }, 652 + .val[5] = { 416000, 36 }, 653 + }, 654 + }, 637 655 .irq_config = { 638 656 .irq1 = { 639 657 .addr = 0x0d,