From a84c7ca320ad9bdc07b25a2d863c0034da418660 Mon Sep 17 00:00:00 2001 From: Hiroyuki Ishii Date: Tue, 12 Oct 2021 11:30:05 +0900 Subject: [PATCH] imu: st_lsm6dsx: tentative: Fix invalid value read from asm330lhh With respect to ASM330LHH's datasheet, we need to wait between enabling accelerometer and reading value for designated samples depend on frequency and/or other configurations. Current implementation intends to wait for more than 1 sample and less than 2 samples but it's obviously incompliant against the spec and results to read of invalid-value (-32764) from sensors occasionally. As mentioned above we need complicated control actually, however, it looks enough to wait for 3 samples for all availavle configurations currently supported, so that we do it as of now. Signed-off-by: Hiroyuki Ishii --- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c | 18 ++++++++++++++++-- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c | 18 ++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c index 057a4b010010..a706ab883bdb 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c @@ -1078,7 +1078,7 @@ static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor, u8 addr, int *val) { struct st_lsm6dsx_hw *hw = sensor->hw; - int err, delay; + int err, delay, additional_delay = 0; __le16 data; err = st_lsm6dsx_sensor_set_enable(sensor, true); @@ -1086,7 +1086,21 @@ static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor, return err; delay = 1000000 / sensor->odr; - usleep_range(delay, 2 * delay); + if (!strncmp(sensor->name, "asm330lhh_", 10)) { + /* + * FIXME: With respect to ASM330LHH's datasheet, we need to wait between + * enabling sensors and reading value for designated samples depend on + * frequency and/or other configurations. However it looks enough to wait + * for 3 samples for all availavle configurations currently supported, so + * that we do it as of now. + * And also we need additional 70ms delay for gyro. + */ + if (!strcmp(sensor->name, "asm330lhh_gyro")) + additional_delay = 70000; + usleep_range(3 * delay + additional_delay, 3 * delay + additional_delay + 100); + } else { + usleep_range(delay, 2 * delay); + } err = st_lsm6dsx_read_locked(hw, addr, &data, sizeof(data)); if (err < 0) diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c index ea472cf6db7b..6f946557a52c 100644 --- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c +++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_shub.c @@ -433,7 +433,7 @@ st_lsm6dsx_shub_read_oneshot(struct st_lsm6dsx_sensor *sensor, struct iio_chan_spec const *ch, int *val) { - int err, delay, len; + int err, delay, len, additional_delay = 0; u8 data[4]; err = st_lsm6dsx_shub_set_enable(sensor, true); @@ -441,7 +441,21 @@ st_lsm6dsx_shub_read_oneshot(struct st_lsm6dsx_sensor *sensor, return err; delay = 1000000 / sensor->odr; - usleep_range(delay, 2 * delay); + if (!strncmp(sensor->name, "asm330lhh_", 10)) { + /* + * FIXME: With respect to ASM330LHH's datasheet, we need to wait between + * enabling sensors and reading value for designated samples depend on + * frequency and/or other configurations. However it looks enough to wait + * for 3 samples for all availavle configurations currently supported, so + * that we do it as of now. + * And also we need additional 70ms delay for gyro. + */ + if (!strcmp(sensor->name, "asm330lhh_gyro")) + additional_delay = 70000; + usleep_range(3 * delay + additional_delay, 3 * delay + additional_delay + 100); + } else { + usleep_range(delay, 2 * delay); + } len = min_t(int, sizeof(data), ch->scan_type.realbits >> 3); err = st_lsm6dsx_shub_read(sensor, ch->address, data, len); -- 2.25.1