diff options
author | Mario Tesi <mario.tesi@st.com> | 2019-10-07 15:56:26 +0200 |
---|---|---|
committer | Jonathan Cameron <Jonathan.Cameron@huawei.com> | 2019-10-15 21:11:06 +0100 |
commit | cb3b6b8e1bc0456d15a40a4bc3f95ad214340fed (patch) | |
tree | 15a80b71bfe3839f4c2542f076765d2d1ec35870 /drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | |
parent | 960506ed2c69a87a2004556624c8f702391b2e43 (diff) | |
download | linux-cb3b6b8e1bc0456d15a40a4bc3f95ad214340fed.tar.bz2 |
iio: imu: st_lsm6dsx: add odr calibration feature
On LSM6DSO/LSM6DSR/LSM6DSOX/ASM330LHH and ISH330DHCX
devices it is possible to trim the hardware timestamp
resolution through the FREQ_FINE[7:0] bits of the
INTERNAL_FREQ_FINE register, which contains the difference
in percentage of the effective ODR (and timestamp rate)
with respect to the typical value.
The formula for calculating the effective ODR reported
in the application notes has been linearized to the first
order to simplify the calculation (pls. see note on source
code).
This change may be useful in the outcome of CTS
tests regarding the SingleSensorTests and the
SensorTest#testSensorTimeStamps for high ODRs
Signed-off-by: Mario Tesi <mario.tesi@st.com>
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Diffstat (limited to 'drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c')
-rw-r--r-- | drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 4f2a787f63f4..b0f525066237 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -63,6 +63,8 @@ #define ST_LSM6DSX_REG_WHOAMI_ADDR 0x0f +#define ST_LSM6DSX_TS_SENSITIVITY 25000UL /* 25us */ + static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x28, IIO_MOD_X, 0), ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1), @@ -843,6 +845,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x0a, .mask = GENMASK(7, 6), }, + .freq_fine = 0x63, }, .shub_settings = { .page_mux = { @@ -1037,6 +1040,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x0a, .mask = GENMASK(7, 6), }, + .freq_fine = 0x63, }, .event_settings = { .enable_reg = { @@ -1208,6 +1212,7 @@ static const struct st_lsm6dsx_settings st_lsm6dsx_sensor_settings[] = { .addr = 0x0a, .mask = GENMASK(7, 6), }, + .freq_fine = 0x63, }, .shub_settings = { .page_mux = { @@ -1893,6 +1898,24 @@ static int st_lsm6dsx_init_hw_timer(struct st_lsm6dsx_hw *hw) if (err < 0) return err; } + + /* calibrate timestamp sensitivity */ + hw->ts_gain = ST_LSM6DSX_TS_SENSITIVITY; + if (ts_settings->freq_fine) { + err = regmap_read(hw->regmap, ts_settings->freq_fine, &val); + if (err < 0) + return err; + + /* + * linearize the AN5192 formula: + * 1 / (1 + x) ~= 1 - x (Taylor’s Series) + * ttrim[s] = 1 / (40000 * (1 + 0.0015 * val)) + * ttrim[ns] ~= 25000 - 37.5 * val + * ttrim[ns] ~= 25000 - (37500 * val) / 1000 + */ + hw->ts_gain -= ((s8)val * 37500) / 1000; + } + return 0; } |