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

iio: st_lsm6dsx: Fixed calibrated timestamp calculation

The calibrated timestamp is calculated from the nominal value using the
formula:
ts_gain[ns] ≈ ts_sensitivity - (ts_trim_coeff * val) / 1000.

The values of ts_sensitivity and ts_trim_coeff are not the same for all
devices, so it is necessary to differentiate them based on the part name.
For the correct values please consult the relevant AN.

Fixes: cb3b6b8e1bc0 ("iio: imu: st_lsm6dsx: add odr calibration feature")
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>

authored by

Mario Tesi and committed by
Jonathan Cameron
8abbf45f cb372b4f

+26 -11
+18
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
··· 192 192 * @fifo_en: Hw timer FIFO enable register info (addr + mask). 193 193 * @decimator: Hw timer FIFO decimator register info (addr + mask). 194 194 * @freq_fine: Difference in % of ODR with respect to the typical. 195 + * @ts_sensitivity: Nominal timestamp sensitivity. 196 + * @ts_trim_coeff: Coefficient for calculating the calibrated timestamp gain. 197 + * This coefficient comes into play when linearizing the formula 198 + * used to calculate the calibrated timestamp (please see the 199 + * relevant formula in the AN for the specific IMU). 200 + * For example, in the case of LSM6DSO we have: 201 + * 202 + * 1 / (1 + x) ~= 1 - x (Taylor’s Series) 203 + * ttrim[s] = 1 / (40000 * (1 + 0.0015 * val)) (from AN5192) 204 + * ttrim[ns] ~= 25000 - 37.5 * val 205 + * ttrim[ns] ~= 25000 - (37500 * val) / 1000 206 + * 207 + * so, replacing ts_sensitivity = 25000 and 208 + * ts_trim_coeff = 37500 209 + * 210 + * ttrim[ns] ~= ts_sensitivity - (ts_trim_coeff * val) / 1000 195 211 */ 196 212 struct st_lsm6dsx_hw_ts_settings { 197 213 struct st_lsm6dsx_reg timer_en; ··· 215 199 struct st_lsm6dsx_reg fifo_en; 216 200 struct st_lsm6dsx_reg decimator; 217 201 u8 freq_fine; 202 + u16 ts_sensitivity; 203 + u16 ts_trim_coeff; 218 204 }; 219 205 220 206 /**
+8 -11
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
··· 94 94 95 95 #define ST_LSM6DSX_REG_WHOAMI_ADDR 0x0f 96 96 97 - #define ST_LSM6DSX_TS_SENSITIVITY 25000UL /* 25us */ 98 - 99 97 static const struct iio_chan_spec st_lsm6dsx_acc_channels[] = { 100 98 ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x28, IIO_MOD_X, 0), 101 99 ST_LSM6DSX_CHANNEL_ACC(IIO_ACCEL, 0x2a, IIO_MOD_Y, 1), ··· 981 983 .mask = GENMASK(7, 6), 982 984 }, 983 985 .freq_fine = 0x63, 986 + .ts_sensitivity = 25000, 987 + .ts_trim_coeff = 37500, 984 988 }, 985 989 .shub_settings = { 986 990 .page_mux = { ··· 1196 1196 .mask = GENMASK(7, 6), 1197 1197 }, 1198 1198 .freq_fine = 0x63, 1199 + .ts_sensitivity = 25000, 1200 + .ts_trim_coeff = 37500, 1199 1201 }, 1200 1202 .event_settings = { 1201 1203 .enable_reg = { ··· 1373 1371 .mask = GENMASK(7, 6), 1374 1372 }, 1375 1373 .freq_fine = 0x4f, 1374 + .ts_sensitivity = 21701, 1375 + .ts_trim_coeff = 28212, 1376 1376 }, 1377 1377 .shub_settings = { 1378 1378 .page_mux = { ··· 2252 2248 } 2253 2249 2254 2250 /* calibrate timestamp sensitivity */ 2255 - hw->ts_gain = ST_LSM6DSX_TS_SENSITIVITY; 2251 + hw->ts_gain = ts_settings->ts_sensitivity; 2256 2252 if (ts_settings->freq_fine) { 2257 2253 err = regmap_read(hw->regmap, ts_settings->freq_fine, &val); 2258 2254 if (err < 0) 2259 2255 return err; 2260 2256 2261 - /* 2262 - * linearize the AN5192 formula: 2263 - * 1 / (1 + x) ~= 1 - x (Taylor’s Series) 2264 - * ttrim[s] = 1 / (40000 * (1 + 0.0015 * val)) 2265 - * ttrim[ns] ~= 25000 - 37.5 * val 2266 - * ttrim[ns] ~= 25000 - (37500 * val) / 1000 2267 - */ 2268 - hw->ts_gain -= ((s8)val * 37500) / 1000; 2257 + hw->ts_gain -= ((s8)val * ts_settings->ts_trim_coeff) / 1000; 2269 2258 } 2270 2259 2271 2260 return 0;