Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 547c2f50 authored by mario tesi's avatar mario tesi Committed by Gerrit - the friendly Code Review server
Browse files

drivers: iio: imu: Updated sample timestamp management for jitter reduction



Updated ASM330 timestamp management function of sensor to reduce
jitter in output.

Signed-off-by: default avatarmario tesi <mario.tesi@st.com>
(cherry picked from commit 03e7a797fb900a6f6da0ace769b80a1e34e278f2)
Git-commit: 03e7a797fb900a6f6da0ace769b80a1e34e278f2
Git-Repo: https://github.com/STMicroelectronics/


STMems_ASM330LHH_IIO_HAL_Driver.git.

Change-Id: I5bcf67dfea9faaccd4de068b446612ad54a233fa
Signed-off-by: default avatarPuneet Yatnal <puneet@codeaurora.org>
parent a2ead32b
Loading
Loading
Loading
Loading
+38 −12
Original line number Diff line number Diff line
@@ -43,6 +43,9 @@

#define ST_ASM330LHH_MAX_ODR			416

/* Timestamp Tick 25us/LSB */
#define ST_ASM330LHH_TS_DELTA_NS		25000ULL

/* Define Custom events for FIFO flush */
#define CUSTOM_IIO_EV_DIR_FIFO_EMPTY (IIO_EV_DIR_NONE + 1)
#define CUSTOM_IIO_EV_DIR_FIFO_DATA (IIO_EV_DIR_NONE + 2)
@@ -82,8 +85,8 @@ static const struct iio_event_spec st_asm330lhh_flush_event = {
	.num_event_specs = 1,				\
}

#define ST_ASM330LHH_RX_MAX_LENGTH	8
#define ST_ASM330LHH_TX_MAX_LENGTH	8
#define ST_ASM330LHH_RX_MAX_LENGTH	64
#define ST_ASM330LHH_TX_MAX_LENGTH	16

#ifdef CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING
#define ASM_MAXSAMPLE        4000
@@ -197,6 +200,7 @@ struct st_asm330lhh_sensor {
 * @irq: Device interrupt line (I2C or SPI).
 * @lock: Mutex to protect read and write operations.
 * @fifo_lock: Mutex to prevent concurrent access to the hw FIFO.
 * @page_lock: Mutex to prevent concurrent memory page configuration.
 * @fifo_mode: FIFO operating mode supported by the device.
 * @state: hw operational state.
 * @enable_mask: Enabled sensor bitmask.
@@ -204,6 +208,13 @@ struct st_asm330lhh_sensor {
 * @hw_ts: Latest hw timestamp from the sensor.
 * @ts: Latest timestamp from irq handler.
 * @delta_ts: Delta time between two consecutive interrupts.
 * @ts_delta_ns: Calibrate delta time tick.
 * @hw_ts: Latest hw timestamp from the sensor.
 * @val_ts_old: Hold hw timestamp for timer rollover.
 * @hw_ts_high: Save MSB hw timestamp.
 * @tsample: Timestamp for each sensor sample.
 * @delta_ts: Delta time between two consecutive interrupts.
 * @ts: Latest timestamp from irq handler.
 * @iio_devs: Pointers to acc/gyro iio_dev instances.
 * @tf: Transfer function structure used by I/O operations.
 * @tb: Transfer buffers used by SPI I/O operations.
@@ -214,25 +225,20 @@ struct st_asm330lhh_hw {

	struct mutex lock;
	struct mutex fifo_lock;
	struct mutex page_lock;

	enum st_asm330lhh_fifo_mode fifo_mode;
	unsigned long state;
	u8 enable_mask;

	s64 ts_offset;
	u32 hw_val;
	u32 hw_val_old;
	u64 ts_delta_ns;
	s64 hw_ts;
	s64 hw_ts_high;
	u32 val_ts_old;
	u32 hw_ts_high;
	s64 tsample;
	s64 delta_ts;
	s64 ts;
	s64 tsample;
	s64 hw_ts_old;
	s64 delta_hw_ts;

	/* Timestamp sample ODR */
	u16 odr;

	struct iio_dev *iio_devs[ST_ASM330LHH_ID_MAX];

	const struct st_asm330lhh_transfer_function *tf;
@@ -242,6 +248,26 @@ struct st_asm330lhh_hw {

extern const struct dev_pm_ops st_asm330lhh_pm_ops;

static inline int st_asm330lhh_read_atomic(struct st_asm330lhh_hw *hw, u8 addr,
					 int len, u8 *data)
{
	int err;

	mutex_lock(&hw->page_lock);
	err = hw->tf->read(hw->dev, addr, len, data);
	mutex_unlock(&hw->page_lock);

	return err;
}

static inline s64 st_asm330lhh_get_time_ns(void)
{
	struct timespec ts;

	get_monotonic_boottime(&ts);
	return timespec_to_ns(&ts);
}

int st_asm330lhh_probe(struct device *dev, int irq,
		       const struct st_asm330lhh_transfer_function *tf_ops);
int st_asm330lhh_sensor_set_enable(struct st_asm330lhh_sensor *sensor,
+125 −142
Original line number Diff line number Diff line
/*
 * STMicroelectronics st_asm330lhh FIFO buffer library driver
 *
 * Copyright 2018 STMicroelectronics Inc.
 * Copyright 2020 STMicroelectronics Inc.
 *
 * Lorenzo Bianconi <lorenzo.bianconi@st.com>
 *
@@ -10,41 +10,41 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/iio/iio.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/iio/events.h>
#include <asm/unaligned.h>
#include <linux/iio/buffer.h>
#include <linux/of.h>

#include "st_asm330lhh.h"

#define ST_ASM330LHH_REG_FIFO_THL_ADDR		0x07
#define ST_ASM330LHH_REG_FIFO_LEN_MASK		GENMASK(8, 0)
#define ST_ASM330LHH_REG_FIFO_STATUS_DIFF	GENMASK(9, 0)
#define ST_ASM330LHH_REG_FIFO_MODE_MASK		GENMASK(2, 0)
#define ST_ASM330LHH_REG_DEC_TS_MASK		GENMASK(7, 6)
#define ST_ASM330LHH_REG_HLACTIVE_ADDR		0x12
#define ST_ASM330LHH_REG_HLACTIVE_MASK		BIT(5)
#define ST_ASM330LHH_REG_PP_OD_ADDR		0x12
#define ST_ASM330LHH_REG_PP_OD_MASK		BIT(4)
#define ST_ASM330LHH_REG_FIFO_DIFFL_ADDR	0x3a
#define ST_ASM330LHH_REG_FIFO_STATUS1_ADDR	0x3a
#define ST_ASM330LHH_REG_TS0_ADDR		0x40
#define ST_ASM330LHH_REG_TS2_ADDR		0x42
#define ST_ASM330LHH_REG_FIFO_OUT_TAG_ADDR	0x78
#define ST_ASM330LHH_GYRO_TAG			0x01
#define ST_ASM330LHH_ACC_TAG			0x02
#define ST_ASM330LHH_TS_TAG			0x04

#define ST_ASM330LHH_TS_DELTA_NS		25000ULL /* 25us/LSB */

static inline s64 st_asm330lhh_get_time_ns(void)
{
	struct timespec ts;

	get_monotonic_boottime(&ts);
	return timespec_to_ns(&ts);
}
#define ST_ASM330LHH_SAMPLE_DISCHARD		0x7ffd

/* Timestamp convergence filter parameter */
#define ST_ASM330LHH_EWMA_LEVEL			120
#define ST_ASM330LHH_EWMA_DIV			128

enum {
	ST_ASM330LHH_GYRO_TAG = 0x01,
	ST_ASM330LHH_ACC_TAG = 0x02,
	ST_ASM330LHH_TS_TAG = 0x04,
};

static inline s64 st_asm330lhh_ewma(s64 old, s64 new, int weight)
{
	s64 diff, incr;
@@ -62,10 +62,9 @@ static inline int st_asm330lhh_reset_hwts(struct st_asm330lhh_hw *hw)

	hw->ts = st_asm330lhh_get_time_ns();
	hw->ts_offset = hw->ts;
	hw->hw_ts_old = 0ull;
	hw->val_ts_old = 0;
	hw->hw_ts_high = 0;
	hw->tsample = 0ull;
	hw->hw_ts_high = 0ull;
	hw->hw_val_old = 0ull;

	return hw->tf->write(hw->dev, ST_ASM330LHH_REG_TS2_ADDR, sizeof(data),
			     &data);
@@ -84,6 +83,11 @@ int st_asm330lhh_set_fifo_mode(struct st_asm330lhh_hw *hw,

	hw->fifo_mode = fifo_mode;

	if (fifo_mode == ST_ASM330LHH_FIFO_BYPASS)
		clear_bit(ST_ASM330LHH_HW_OPERATIONAL, &hw->state);
	else
		set_bit(ST_ASM330LHH_HW_OPERATIONAL, &hw->state);

	return 0;
}

@@ -105,24 +109,6 @@ static int st_asm330lhh_set_sensor_batching_odr(struct st_asm330lhh_sensor *sens
					    sensor->batch_mask, data);
}

static u16 st_asm330lhh_ts_odr(struct st_asm330lhh_hw *hw)
{
	struct st_asm330lhh_sensor *sensor;
	u16 odr = 0;
	u8 i;

	for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) {
		if (!hw->iio_devs[i])
			continue;

		sensor = iio_priv(hw->iio_devs[i]);
		if (hw->enable_mask & BIT(sensor->id))
			odr = max_t(u16, odr, sensor->odr);
	}

	return odr;
}

int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor,
					 u16 watermark)
{
@@ -134,6 +120,9 @@ int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor,
	u8 data;

	for (i = 0; i < ST_ASM330LHH_ID_MAX; i++) {
		if (!hw->iio_devs[i])
			continue;

		cur_sensor = iio_priv(hw->iio_devs[i]);

		if (!(hw->enable_mask & BIT(cur_sensor->id)))
@@ -146,6 +135,7 @@ int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor,
	}

	fifo_watermark = max_t(u16, fifo_watermark, 2);

	mutex_lock(&hw->lock);

	err = hw->tf->read(hw->dev, ST_ASM330LHH_REG_FIFO_THL_ADDR + 1,
@@ -165,14 +155,6 @@ int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor,
	return err < 0 ? err : 0;
}

static inline void st_asm330lhh_sync_hw_ts(struct st_asm330lhh_hw *hw, s64 ts)
{
	s64 delta = ts - hw->hw_ts;

	hw->ts_offset = st_asm330lhh_ewma(hw->ts_offset, delta,
					  ST_ASM330LHH_EWMA_LEVEL);
}

static struct iio_dev *st_asm330lhh_get_iiodev_from_tag(struct st_asm330lhh_hw *hw,
							u8 tag)
{
@@ -248,37 +230,51 @@ static void store_acc_gyro_boot_sample(struct st_asm330lhh_sensor *sensor,
}
#endif

static inline void st_asm330lhh_sync_hw_ts(struct st_asm330lhh_hw *hw, s64 ts)
{
	s64 delta = ts - hw->hw_ts;

	hw->ts_offset = st_asm330lhh_ewma(hw->ts_offset, delta,
					  ST_ASM330LHH_EWMA_LEVEL);
}

static int st_asm330lhh_read_fifo(struct st_asm330lhh_hw *hw)
{
	u8 iio_buf[ALIGN(ST_ASM330LHH_SAMPLE_SIZE, sizeof(s64)) + sizeof(s64)];
	u8 buf[30 * ST_ASM330LHH_FIFO_SAMPLE_SIZE], tag, *ptr;
	s64 ts_delta_hw_ts = 0, ts_irq;
	s64 ts_delta_offs;
	int i, err, read_len, word_len, fifo_len;
	struct st_asm330lhh_sensor *sensor;
	int i, err, word_len, fifo_len, read_len;
	struct iio_dev *iio_dev;
	struct st_asm330lhh_sensor *sensor;
	s64 ts_irq, hw_ts_old;
	__le16 fifo_status;
	u16 fifo_depth;
	int ts_processed = 0;
	s64 hw_ts = 0ull, delta_hw_ts, cpu_timestamp;
	s16 drdymask;
	u32 val;

	/* return if FIFO is already disabled */
	if (!test_bit(ST_ASM330LHH_HW_OPERATIONAL, &hw->state)) {
		dev_warn(hw->dev, "%s: FIFO in bypass mode\n", __func__);

		return 0;
	}

	ts_irq = hw->ts - hw->delta_ts;

	do {
		err = hw->tf->read(hw->dev, ST_ASM330LHH_REG_FIFO_DIFFL_ADDR,
	err = st_asm330lhh_read_atomic(hw, ST_ASM330LHH_REG_FIFO_STATUS1_ADDR,
				     sizeof(fifo_status), (u8 *)&fifo_status);
	if (err < 0)
		return err;

		fifo_depth = le16_to_cpu(fifo_status) & ST_ASM330LHH_REG_FIFO_LEN_MASK;
	fifo_depth = le16_to_cpu(fifo_status) &
		ST_ASM330LHH_REG_FIFO_STATUS_DIFF;
	if (!fifo_depth)
		return 0;

		read_len = 0;
	fifo_len = fifo_depth * ST_ASM330LHH_FIFO_SAMPLE_SIZE;
	read_len = 0;
	while (read_len < fifo_len) {
		word_len = min_t(int, fifo_len - read_len, sizeof(buf));
			err = hw->tf->read(hw->dev,
		err = st_asm330lhh_read_atomic(hw,
					     ST_ASM330LHH_REG_FIFO_OUT_TAG_ADDR,
					     word_len, buf);
		if (err < 0)
@@ -289,54 +285,54 @@ static int st_asm330lhh_read_fifo(struct st_asm330lhh_hw *hw)
			tag = buf[i] >> 3;

			if (tag == ST_ASM330LHH_TS_TAG) {
					hw->hw_val = get_unaligned_le32(ptr);
				val = get_unaligned_le32(ptr);

					/* check for timer rollover */
					if (hw->hw_val < hw->hw_val_old)
				if (hw->val_ts_old > val)
					hw->hw_ts_high++;
					hw->hw_ts =
					(hw->hw_val + (hw->hw_ts_high << 32))
						* ST_ASM330LHH_TS_DELTA_NS;
					ts_delta_hw_ts = hw->hw_ts - hw->hw_ts_old;
					hw_ts += ts_delta_hw_ts;
					ts_delta_offs =
						div_s64(hw->delta_hw_ts * ST_ASM330LHH_MAX_ODR, hw->odr);

					hw->ts_offset = st_asm330lhh_ewma(hw->ts_offset, ts_irq -
						hw->hw_ts + ts_delta_offs, ST_ASM330LHH_EWMA_LEVEL);

					ts_irq += (hw->hw_ts + ts_delta_offs);
					hw->hw_ts_old = hw->hw_ts;
					hw->hw_val_old = hw->hw_val;
					ts_processed++;

				hw_ts_old = hw->hw_ts;

				/* check hw rollover */
				hw->val_ts_old = val;
				hw->hw_ts = (val + ((s64)hw->hw_ts_high <<
							32)) * hw->ts_delta_ns;
				hw->ts_offset = st_asm330lhh_ewma(hw->ts_offset,
						ts_irq - hw->hw_ts,
						ST_ASM330LHH_EWMA_LEVEL);

				if (!test_bit(ST_ASM330LHH_HW_FLUSH,
							&hw->state))
					/* sync ap timestamp and sensor one */
					st_asm330lhh_sync_hw_ts(hw, ts_irq);

				ts_irq += hw->hw_ts;

				if (!hw->tsample)
						hw->tsample =
							hw->ts_offset + (hw->hw_ts + ts_delta_offs);
					hw->tsample = hw->ts_offset + hw->hw_ts;
				else
						hw->tsample =
							hw->tsample + (ts_delta_hw_ts + ts_delta_offs);
					hw->tsample = hw->tsample +
						hw->hw_ts - hw_ts_old;
			} else {
					iio_dev = st_asm330lhh_get_iiodev_from_tag(hw, tag);
				iio_dev = st_asm330lhh_get_iiodev_from_tag(hw,
						tag);
				if (!iio_dev)
					continue;

				sensor = iio_priv(iio_dev);
					if (sensor->std_samples < sensor->std_level) {
						sensor->std_samples++;

				/* skip samples if not ready */
				drdymask = (s16)le16_to_cpu(
						get_unaligned_le16(ptr));
				if (unlikely(drdymask
					>= ST_ASM330LHH_SAMPLE_DISCHARD)) {
					continue;
				}

					sensor = iio_priv(iio_dev);

					/* Check if timestamp is in the future. */
					cpu_timestamp = st_asm330lhh_get_time_ns();
				memcpy(iio_buf, ptr, ST_ASM330LHH_SAMPLE_SIZE);

					/* Avoid samples in the future. */
					if (hw->tsample > cpu_timestamp)
						hw->tsample = cpu_timestamp;
				hw->tsample = min_t(s64,
						    hw->ts,
						    hw->tsample);

					memcpy(iio_buf, ptr, ST_ASM330LHH_SAMPLE_SIZE);
				iio_push_to_buffers_with_timestamp(iio_dev,
								   iio_buf,
								   hw->tsample);
@@ -347,13 +343,6 @@ static int st_asm330lhh_read_fifo(struct st_asm330lhh_hw *hw)
		read_len += word_len;
	}

		delta_hw_ts = div_s64(hw->delta_ts - hw_ts, ts_processed);
		delta_hw_ts = div_s64(delta_hw_ts * hw->odr, ST_ASM330LHH_MAX_ODR);
		hw->delta_hw_ts = st_asm330lhh_ewma(hw->delta_hw_ts,
							delta_hw_ts,
							ST_ASM330LHH_EWMA_LEVEL);
	} while(read_len);

	return read_len;
}

@@ -412,8 +401,9 @@ ssize_t st_asm330lhh_flush_fifo(struct device *dev,
	struct iio_dev *iio_dev = dev_get_drvdata(dev);
	struct st_asm330lhh_sensor *sensor = iio_priv(iio_dev);
	struct st_asm330lhh_hw *hw = sensor->hw;
	s64 type, event;
	s64 event;
	int count;
	s64 type;
	s64 ts;

	mutex_lock(&hw->fifo_lock);
@@ -421,9 +411,7 @@ ssize_t st_asm330lhh_flush_fifo(struct device *dev,
	hw->delta_ts = ts - hw->ts;
	hw->ts = ts;
	set_bit(ST_ASM330LHH_HW_FLUSH, &hw->state);

	count = st_asm330lhh_read_fifo(hw);

	mutex_unlock(&hw->fifo_lock);

	type = count > 0 ? CUSTOM_IIO_EV_DIR_FIFO_DATA : CUSTOM_IIO_EV_DIR_FIFO_EMPTY;
@@ -439,10 +427,8 @@ int st_asm330lhh_suspend_fifo(struct st_asm330lhh_hw *hw)
	int err;

	mutex_lock(&hw->fifo_lock);

	st_asm330lhh_read_fifo(hw);
	err = st_asm330lhh_set_fifo_mode(hw, ST_ASM330LHH_FIFO_BYPASS);

	mutex_unlock(&hw->fifo_lock);

	return err;
@@ -468,8 +454,6 @@ int st_asm330lhh_update_fifo(struct iio_dev *iio_dev, bool enable)
	if (err < 0)
		goto out;

	hw->odr = st_asm330lhh_ts_odr(hw);

	if (enable && hw->fifo_mode == ST_ASM330LHH_FIFO_BYPASS) {
		st_asm330lhh_reset_hwts(hw);
		err = st_asm330lhh_set_fifo_mode(hw, ST_ASM330LHH_FIFO_CONT);
@@ -499,10 +483,8 @@ static irqreturn_t st_asm330lhh_handler_thread(int irq, void *private)
	struct st_asm330lhh_hw *hw = (struct st_asm330lhh_hw *)private;

	mutex_lock(&hw->fifo_lock);

	st_asm330lhh_read_fifo(hw);
	clear_bit(ST_ASM330LHH_HW_FLUSH, &hw->state);

	mutex_unlock(&hw->fifo_lock);

	return IRQ_HANDLED;
@@ -548,6 +530,8 @@ int st_asm330lhh_fifo_setup(struct st_asm330lhh_hw *hw)
	int i, err;

	irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
	if (irq_type == IRQF_TRIGGER_NONE)
		irq_type = IRQF_TRIGGER_HIGH;

	switch (irq_type) {
	case IRQF_TRIGGER_HIGH:
@@ -605,4 +589,3 @@ int st_asm330lhh_fifo_setup(struct st_asm330lhh_hw *hw)

	return st_asm330lhh_fifo_init(hw);
}
+45 −2
Original line number Diff line number Diff line
@@ -26,18 +26,24 @@
#define ST_ASM330LHH_REG_INT2_ADDR		0x0e
#define ST_ASM330LHH_REG_FIFO_CTRL4_ADDR	0x0a
#define ST_ASM330LHH_REG_FIFO_FTH_IRQ_MASK	BIT(3)

#define ST_ASM330LHH_REG_WHOAMI_ADDR		0x0f
#define ST_ASM330LHH_WHOAMI_VAL			0x6b
#define ST_ASM330LHH_REG_CTRL1_XL_ADDR		0x10
#define ST_ASM330LHH_REG_CTRL2_G_ADDR		0x11

#define ST_ASM330LHH_REG_RESET_ADDR		0x12
#define ST_ASM330LHH_REG_RESET_MASK		BIT(0)

#define ST_ASM330LHH_REG_BDU_ADDR		0x12
#define ST_ASM330LHH_REG_BDU_MASK		BIT(6)
#define ST_ASM330LHH_REG_INT2_ON_INT1_ADDR	0x13
#define ST_ASM330LHH_REG_INT2_ON_INT1_MASK	BIT(5)

#define ST_ASM330LHH_REG_CTRL4_C_ADDR		0x13
#define ST_ASM330LHH_REG_DRDY_MASK		BIT(3)

#define ST_ASM330LHH_REG_ROUNDING_ADDR		0x14
#define ST_ASM330LHH_REG_ROUNDING_MASK		GENMASK(6, 5)

#define ST_ASM330LHH_REG_TIMESTAMP_EN_ADDR	0x19
#define ST_ASM330LHH_REG_TIMESTAMP_EN_MASK	BIT(5)

@@ -64,6 +70,8 @@
#define ST_ASM330LHH_GYRO_FS_2000_GAIN		IIO_DEGREE_TO_RAD(70000)
#define ST_ASM330LHH_GYRO_FS_4000_GAIN		IIO_DEGREE_TO_RAD(140000)

#define ST_ASM330LHH_INTERNAL_FREQ_FINE		0x63

/* Temperature in uC */
#define ST_ASM330LHH_TEMP_GAIN			256
#define ST_ASM330LHH_TEMP_FS_GAIN		(1000000 / ST_ASM330LHH_TEMP_GAIN)
@@ -230,6 +238,30 @@ static int st_asm330lhh_check_whoami(struct st_asm330lhh_hw *hw)
	return 0;
}

static int st_asm330lhh_get_odr_calibration(struct st_asm330lhh_hw *hw)
{
	s64 odr_calib;
	int err;
	s8 data;

	err = hw->tf->read(hw->dev,
			   ST_ASM330LHH_INTERNAL_FREQ_FINE,
			   sizeof(data), (u8 *)&data);
	if (err < 0) {
		dev_err(hw->dev, "failed to read %d register\n",
				ST_ASM330LHH_INTERNAL_FREQ_FINE);
		return err;
	}

	odr_calib = (data * 37500) / 1000;
	hw->ts_delta_ns = ST_ASM330LHH_TS_DELTA_NS - odr_calib;

	dev_info(hw->dev, "Freq Fine %lld (ts %lld)\n",
			odr_calib, hw->ts_delta_ns);

	return 0;
}

static int st_asm330lhh_set_full_scale(struct st_asm330lhh_sensor *sensor,
				       u32 gain)
{
@@ -775,6 +807,12 @@ static int st_asm330lhh_init_device(struct st_asm330lhh_hw *hw)
	if (err < 0)
		return err;

	/* enable DRDY MASK for filters settling time */
	err = st_asm330lhh_write_with_mask(hw, ST_ASM330LHH_REG_CTRL4_C_ADDR,
					 ST_ASM330LHH_REG_DRDY_MASK, 1);
	if (err < 0)
		return err;

	/* enable FIFO watermak interrupt */
	err = st_asm330lhh_get_drdy_reg(hw, &drdy_int_reg);
	if (err < 0)
@@ -1043,6 +1081,7 @@ int st_asm330lhh_probe(struct device *dev, int irq,

	mutex_init(&hw->lock);
	mutex_init(&hw->fifo_lock);
	mutex_init(&hw->page_lock);

	hw->dev = dev;
	hw->irq = irq;
@@ -1067,6 +1106,10 @@ int st_asm330lhh_probe(struct device *dev, int irq,
	if (err < 0)
		return err;

	err = st_asm330lhh_get_odr_calibration(hw);
	if (err < 0)
		return err;

	err = st_asm330lhh_init_device(hw);
	if (err < 0)
		return err;