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

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

Updated ASM330LHH driver for HAL 1.0/2.0



Updated driver to support decimal ODRs (CTS/VTS requirement)
and new timestamp management with alignemt of samples timestamp
to AP timestamp.

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


STMems_ASM330LHH_IIO_HAL_Driver.git.

Change-Id: I5224aef722449ee1030b40d7e4b43089cf585ba2
Signed-off-by: default avatarPuneet Yatnal <puneet@codeaurora.org>
parent da2faffc
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -21,6 +21,18 @@ config IIO_ST_ASM330LHH_SPI
	tristate
	depends on IIO_ST_ASM330LHH

config IIO_ST_ASM330LHH_MAY_WAKEUP
	bool "Enable wake-up irq"
	depends on IIO_ST_ASM330LHH
	help
	  Enable wake-up irq on interrupt line

config IIO_ST_ASM330LHH_EN_TEMPERATURE_FIFO
	bool "Enable internal temperature sensor in FIFO"
	depends on IIO_ST_ASM330LHH
	help
          Enable internal temperature sensor channel in FIFO

config ENABLE_ASM_ACC_GYRO_BUFFERING
        bool "Enable accel & gyro  boot time sensor sample buffering"
        depends on IIO_ST_ASM330LHH
+209 −40
Original line number Diff line number Diff line
/*
 * STMicroelectronics st_asm330lhh sensor driver
 *
 * Copyright 2018 STMicroelectronics Inc.
 * Copyright 2020 STMicroelectronics Inc.
 *
 * Lorenzo Bianconi <lorenzo.bianconi@st.com>
 *
@@ -13,35 +13,105 @@

#include <linux/device.h>
#include <linux/iio/iio.h>
#include <linux/delay.h>
#include <linux/input.h>
#include <linux/ktime.h>
#include <linux/slab.h>

#define ST_ASM330LHH_REVISION			"2.0.1"
#define ST_ASM330LHH_PATCH		"2"
#define ST_ASM330LHH_PATCH			"4"

#define ST_ASM330LHH_VERSION			"v"	\
	ST_ASM330LHH_REVISION				\
	"-"						\
	ST_ASM330LHH_PATCH

#define ST_ASM330LHH_MAX_ODR			833
#define ST_ASM330LHH_ODR_LIST_SIZE		8
#define ST_ASM330LHH_ODR_EXPAND(odr, uodr)	((odr * 1000000) + uodr)

#define ST_ASM330LHH_DEV_NAME			"asm330lhh"

#define ST_ASM330LHH_SAMPLE_SIZE	6
#define ST_ASM330LHH_TS_SAMPLE_SIZE	4
#define ST_ASM330LHH_TAG_SIZE		1
#define ST_ASM330LHH_FIFO_SAMPLE_SIZE	(ST_ASM330LHH_SAMPLE_SIZE + \
					 ST_ASM330LHH_TAG_SIZE)
#define ST_ASM330LHH_MAX_FIFO_DEPTH	416
#define ST_ASM330LHH_DEFAULT_XL_FS_INDEX	2
#define ST_ASM330LHH_DEFAULT_XL_ODR_INDEX	1
#define ST_ASM330LHH_DEFAULT_G_FS_INDEX		3
#define ST_ASM330LHH_DEFAULT_G_ODR_INDEX	1
#define ST_ASM330LHH_DEFAULT_T_FS_INDEX		0
#define ST_ASM330LHH_DEFAULT_T_ODR_INDEX	1

#define ST_ASM330LHH_REG_FIFO_CTRL1_ADDR	0x07
#define ST_ASM330LHH_REG_FIFO_CTRL2_ADDR	0x08
#define ST_ASM330LHH_REG_FIFO_WTM_MASK		GENMASK(8, 0)
#define ST_ASM330LHH_REG_FIFO_WTM8_MASK		BIT(0)
#define ST_ASM330LHH_REG_FIFO_STATUS_DIFF	GENMASK(9, 0)

#define ST_ASM330LHH_REG_FIFO_CTRL3_ADDR	0x09
#define ST_ASM330LHH_REG_BDR_XL_MASK		GENMASK(3, 0)
#define ST_ASM330LHH_REG_BDR_GY_MASK		GENMASK(7, 4)

#define ST_ASM330LHH_REG_FIFO_BATCH_ADDR	0x09
#define ST_ASM330LHH_REG_FIFO_CTRL4_ADDR	0x0a
#define ST_ASM330LHH_REG_FIFO_MODE_MASK		GENMASK(2, 0)
#define ST_ASM330LHH_REG_DEC_TS_MASK		GENMASK(7, 6)
#define ST_ASM330LHH_REG_ODR_T_BATCH_MASK	GENMASK(5, 4)

#define ST_ASM330LHH_REG_INT1_CTRL_ADDR		0x0d
#define ST_ASM330LHH_REG_INT2_CTRL_ADDR		0x0e
#define ST_ASM330LHH_REG_INT_FIFO_TH_MASK	BIT(3)

#define ST_ASM330LHH_REG_WHOAMI_ADDR		0x0f
#define ST_ASM330LHH_WHOAMI_VAL			0x6b

#define ST_ASM330LHH_CTRL1_XL_ADDR		0x10
#define ST_ASM330LHH_CTRL2_G_ADDR		0x11

#define ST_ASM330LHH_REG_CTRL3_C_ADDR		0x12
#define ST_ASM330LHH_REG_SW_RESET_MASK		BIT(0)
#define ST_ASM330LHH_REG_PP_OD_MASK		BIT(4)
#define ST_ASM330LHH_REG_H_LACTIVE_MASK		BIT(5)
#define ST_ASM330LHH_REG_BDU_MASK		BIT(6)
#define ST_ASM330LHH_REG_BOOT_MASK		BIT(7)

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

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

#define ST_ASM330LHH_REG_CTRL9_XL_ADDR		0x18
#define ST_ASM330LHH_REG_DEVICE_CONF_MASK	BIT(1)

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

#define ST_ASM330LHH_REG_STATUS_ADDR		0x1e
#define ST_ASM330LHH_REG_STATUS_TDA		BIT(2)

#define ST_ASM330LHH_REG_OUT_TEMP_L_ADDR	0x20
#define ST_ASM330LHH_REG_OUT_TEMP_H_ADDR	0x21

#define ST_ASM330LHH_MAX_ODR			416
#define ST_ASM330LHH_REG_OUTX_L_A_ADDR		0x28
#define ST_ASM330LHH_REG_OUTY_L_A_ADDR		0x2a
#define ST_ASM330LHH_REG_OUTZ_L_A_ADDR		0x2c

#define ST_ASM330LHH_REG_OUTX_L_G_ADDR		0x22
#define ST_ASM330LHH_REG_OUTY_L_G_ADDR		0x24
#define ST_ASM330LHH_REG_OUTZ_L_G_ADDR		0x26

#define ST_ASM330LHH_REG_TAP_CFG0_ADDR		0x56
#define ST_ASM330LHH_REG_LIR_MASK		BIT(0)

#define ST_ASM330LHH_REG_THS_6D_ADDR		0x59
#define ST_ASM330LHH_SIXD_THS_MASK		GENMASK(6, 5)

#define ST_ASM330LHH_REG_WAKE_UP_THS_ADDR	0x5b
#define ST_ASM330LHH_WAKE_UP_THS_MASK		GENMASK(5, 0)

#define ST_ASM330LHH_REG_WAKE_UP_DUR_ADDR	0x5c
#define ST_ASM330LHH_WAKE_UP_DUR_MASK		GENMASK(6, 5)

#define ST_ASM330LHH_REG_FREE_FALL_ADDR		0x5d
#define ST_ASM330LHH_FF_THS_MASK		GENMASK(2, 0)

#define ST_ASM330LHH_INTERNAL_FREQ_FINE		0x63

/* Timestamp Tick 25us/LSB */
#define ST_ASM330LHH_TS_DELTA_NS		25000ULL
@@ -51,7 +121,21 @@
#define CUSTOM_IIO_EV_DIR_FIFO_DATA (IIO_EV_DIR_NONE + 2)
#define CUSTOM_IIO_EV_TYPE_FIFO_FLUSH (IIO_EV_TYPE_CHANGE + 1)

#define ST_ASM330LHH_CHANNEL(chan_type, addr, mod, ch2, scan_idx,	\
/* Temperature in uC */
#define ST_ASM330LHH_TEMP_GAIN			256
#define ST_ASM330LHH_TEMP_FS_GAIN		(1000000 / \
						ST_ASM330LHH_TEMP_GAIN)
#define ST_ASM330LHH_TEMP_OFFSET		6400

/* FIFO simple size and depth */
#define ST_ASM330LHH_SAMPLE_SIZE		6
#define ST_ASM330LHH_TS_SAMPLE_SIZE		4
#define ST_ASM330LHH_TAG_SIZE			1
#define ST_ASM330LHH_FIFO_SAMPLE_SIZE		(ST_ASM330LHH_SAMPLE_SIZE + \
						 ST_ASM330LHH_TAG_SIZE)
#define ST_ASM330LHH_MAX_FIFO_DEPTH		416

#define ST_ASM330LHH_DATA_CHANNEL(chan_type, addr, mod, ch2, scan_idx,	\
				rb, sb, sg)				\
{									\
	.type = chan_type,						\
@@ -75,9 +159,9 @@ static const struct iio_event_spec st_asm330lhh_flush_event = {
	.dir = IIO_EV_DIR_EITHER,
};

#define ST_ASM330LHH_FLUSH_CHANNEL(dtype)		\
#define ST_ASM330LHH_EVENT_CHANNEL(ctype, etype)	\
{							\
	.type = dtype,					\
	.type = ctype,					\
	.modified = 0,					\
	.scan_index = -1,				\
	.indexed = -1,					\
@@ -105,43 +189,89 @@ struct st_asm330lhh_transfer_buffer {

struct st_asm330lhh_transfer_function {
	int (*read)(struct device *dev, u8 addr, int len, u8 *data);
	int (*write)(struct device *dev, u8 addr, int len, u8 *data);
	int (*write)(struct device *dev, u8 addr, int len, const u8 *data);
};

/**
 * struct st_asm330lhh_reg - Generic sensor register description (addr + mask)
 * @addr: Address of register.
 * @mask: Bitmask register for proper usage.
 */
struct st_asm330lhh_reg {
	u8 addr;
	u8 mask;
};

/**
 * struct st_asm330lhh_odr - Single ODR entry
 * @hz: Most significant part of the sensor ODR (Hz).
 * @uhz: Less significant part of the sensor ODR (micro Hz).
 * @val: ODR register value.
 * @batch_val: Batching ODR register value.
 */
struct st_asm330lhh_odr {
	u16 hz;
	u32 uhz;
	u8 val;
	u8 batch_val;
};

#define ST_ASM330LHH_ODR_LIST_SIZE	7
/**
 * struct st_asm330lhh_odr_table_entry - Sensor ODR table
 * @size: Size of ODR table.
 * @reg: ODR register.
 * @batching_reg: ODR register for batching on fifo.
 * @odr_avl: Array of supported ODR value.
 */
struct st_asm330lhh_odr_table_entry {
	u8 size;
	struct st_asm330lhh_reg reg;
	struct st_asm330lhh_reg batching_reg;
	struct st_asm330lhh_odr odr_avl[ST_ASM330LHH_ODR_LIST_SIZE];
};

/**
 * struct st_asm330lhh_fs - Full Scale sensor table entry
 * @reg: Register description for FS settings.
 * @gain: Sensor sensitivity (mdps/LSB, mg/LSB and uC/LSB).
 * @val: FS register value.
 */
struct st_asm330lhh_fs {
	struct st_asm330lhh_reg reg;
	u32 gain;
	u8 val;
};

#define ST_ASM330LHH_FS_LIST_SIZE		6
#define ST_ASM330LHH_FS_ACC_LIST_SIZE		4
#define ST_ASM330LHH_FS_GYRO_LIST_SIZE		6
#define ST_ASM330LHH_FS_TEMP_LIST_SIZE		1
#define ST_ASM330LHH_FS_LIST_SIZE		6

/**
 * struct st_asm330lhh_fs_table_entry - Full Scale sensor table
 * @size: Full Scale sensor table size.
 * @fs_avl: Full Scale list entries.
 */
struct st_asm330lhh_fs_table_entry {
	u32 size;
	struct st_asm330lhh_reg reg;
	u8 size;
	struct st_asm330lhh_fs fs_avl[ST_ASM330LHH_FS_LIST_SIZE];
};

#define ST_ASM330LHH_ACC_FS_2G_GAIN	IIO_G_TO_M_S_2(61)
#define ST_ASM330LHH_ACC_FS_4G_GAIN	IIO_G_TO_M_S_2(122)
#define ST_ASM330LHH_ACC_FS_8G_GAIN	IIO_G_TO_M_S_2(244)
#define ST_ASM330LHH_ACC_FS_16G_GAIN	IIO_G_TO_M_S_2(488)

#define ST_ASM330LHH_GYRO_FS_125_GAIN	IIO_DEGREE_TO_RAD(4375)
#define ST_ASM330LHH_GYRO_FS_250_GAIN	IIO_DEGREE_TO_RAD(8750)
#define ST_ASM330LHH_GYRO_FS_500_GAIN	IIO_DEGREE_TO_RAD(17500)
#define ST_ASM330LHH_GYRO_FS_1000_GAIN	IIO_DEGREE_TO_RAD(35000)
#define ST_ASM330LHH_GYRO_FS_2000_GAIN	IIO_DEGREE_TO_RAD(70000)
#define ST_ASM330LHH_GYRO_FS_4000_GAIN	IIO_DEGREE_TO_RAD(140000)

enum st_asm330lhh_sensor_id {
	ST_ASM330LHH_ID_GYRO = 0,
	ST_ASM330LHH_ID_ACC,
	ST_ASM330LHH_ID_GYRO,
	ST_ASM330LHH_ID_TEMP,
	ST_ASM330LHH_ID_MAX,
};
@@ -163,24 +293,24 @@ enum {
 * @gain: Configured sensor sensitivity.
 * @odr: Output data rate of the sensor [Hz].
 * @watermark: Sensor watermark level.
 * @batch_mask: Sensor mask for FIFO batching register
 * @last_fifo_timestamp: Store last sample timestamp in FIFO, used by flush
 */
struct st_asm330lhh_sensor {
	enum st_asm330lhh_sensor_id id;
	struct st_asm330lhh_hw *hw;
	struct iio_trigger *trig;

	u32 gain;
	u16 odr;
	u32 offset;

	__le16 old_data;

	u8 std_samples;
	u8 std_level;
	int odr;
	int uodr;

	u16 max_watermark;
	u16 watermark;
	u8 batch_mask;
	u8 batch_addr;
	s64 last_fifo_timestamp;
#ifdef CONFIG_ENABLE_ASM_ACC_GYRO_BUFFERING
	bool read_boot_sample;
	int bufsample_cnt;
@@ -216,6 +346,7 @@ struct st_asm330lhh_sensor {
 * @tsample: Timestamp for each sensor sample.
 * @delta_ts: Delta time between two consecutive interrupts.
 * @ts: Latest timestamp from irq handler.
 * @odr_table_entry: Sensors ODR table.
 * @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.
@@ -223,6 +354,7 @@ struct st_asm330lhh_sensor {
struct st_asm330lhh_hw {
	struct device *dev;
	int irq;
	int int_pin;

	struct mutex lock;
	struct mutex fifo_lock;
@@ -230,7 +362,7 @@ struct st_asm330lhh_hw {

	enum st_asm330lhh_fifo_mode fifo_mode;
	unsigned long state;
	u8 enable_mask;
	u32 enable_mask;

	s64 ts_offset;
	u64 ts_delta_ns;
@@ -240,12 +372,14 @@ struct st_asm330lhh_hw {
	s64 tsample;
	s64 delta_ts;
	s64 ts;
	const struct st_asm330lhh_odr_table_entry *odr_table_entry;
	struct iio_dev *iio_devs[ST_ASM330LHH_ID_MAX];

	const struct st_asm330lhh_transfer_function *tf;
	struct st_asm330lhh_transfer_buffer tb;
	struct regulator *vdd;
	struct regulator *vio;
	struct iio_mount_matrix orientation;
	int enable_gpio;
	bool asm330_hrtimer;
	struct hrtimer st_asm330lhh_hrtimer;
@@ -265,14 +399,47 @@ static inline int st_asm330lhh_read_atomic(struct st_asm330lhh_hw *hw, u8 addr,
	return err;
}

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

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

	return err;
}

int __st_asm330lhh_write_with_mask(struct st_asm330lhh_hw *hw, u8 addr, u8 mask,
				 u8 val);
static inline int st_asm330lhh_write_with_mask(struct st_asm330lhh_hw *hw,
		u8 addr, u8 mask, u8 val)
{
	int err;

	mutex_lock(&hw->page_lock);
	err = __st_asm330lhh_write_with_mask(hw, addr, mask, val);
	mutex_unlock(&hw->page_lock);

	return err;
}

static inline bool st_asm330lhh_is_fifo_enabled(struct st_asm330lhh_hw *hw)
{
	return hw->enable_mask & (BIT(ST_ASM330LHH_ID_GYRO) |
				  BIT(ST_ASM330LHH_ID_ACC));
}

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,
				   bool enable);
int st_asm330lhh_fifo_setup(struct st_asm330lhh_hw *hw);
int st_asm330lhh_write_with_mask(struct st_asm330lhh_hw *hw, u8 addr, u8 mask,
				 u8 val);
int st_asm330lhh_get_odr_val(enum st_asm330lhh_sensor_id id, u16 odr, u8 *val);
int st_asm330lhh_buffers_setup(struct st_asm330lhh_hw *hw);
int st_asm330lhh_get_batch_val(struct st_asm330lhh_sensor *sensor, int odr,
			       int uodr, u8 *val);
int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor,
				  u16 watermark);
ssize_t st_asm330lhh_flush_fifo(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t size);
@@ -283,11 +450,13 @@ ssize_t st_asm330lhh_get_watermark(struct device *dev,
ssize_t st_asm330lhh_set_watermark(struct device *dev,
				   struct device_attribute *attr,
				   const char *buf, size_t size);
int st_asm330lhh_suspend_fifo(struct st_asm330lhh_hw *hw);
int st_asm330lhh_set_fifo_mode(struct st_asm330lhh_hw *hw,
			       enum st_asm330lhh_fifo_mode fifo_mode);
int st_asm330lhh_suspend_fifo(struct st_asm330lhh_hw *hw);
int st_asm330lhh_update_watermark(struct st_asm330lhh_sensor *sensor,
					u16 watermark);
int __st_asm330lhh_set_sensor_batching_odr(struct st_asm330lhh_sensor *sensor,
					   bool enable);
int st_asm330lhh_update_batching(struct iio_dev *iio_dev, bool enable);
int st_asm330lhh_reset_hwts(struct st_asm330lhh_hw *hw);
int st_asm330lhh_update_fifo(struct iio_dev *iio_dev, bool enable);
int asm330_check_acc_gyro_early_buff_enable_flag(
		struct st_asm330lhh_sensor *sensor);
+173 −87

File changed.

Preview size limit exceeded, changes collapsed.

+483 −239

File changed.

Preview size limit exceeded, changes collapsed.

+4 −3
Original line number Diff line number Diff line
/*
 * STMicroelectronics st_asm330lhh i2c driver
 *
 * Copyright 2018 STMicroelectronics Inc.
 * Copyright 2020 STMicroelectronics Inc.
 *
 * Lorenzo Bianconi <lorenzo.bianconi@st.com>
 *
@@ -45,7 +45,8 @@ static int st_asm330lhh_i2c_read(struct device *dev, u8 addr, int len, u8 *data)
	return ret;
}

static int st_asm330lhh_i2c_write(struct device *dev, u8 addr, int len, u8 *data)
static int st_asm330lhh_i2c_write(struct device *dev, u8 addr, int len,
				const u8 *data)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct i2c_msg msg;
@@ -100,7 +101,7 @@ static struct i2c_driver st_asm330lhh_driver = {
	.driver = {
		.name = "st_asm330lhh_i2c",
		.pm = &st_asm330lhh_pm_ops,
		.of_match_table = of_match_ptr(st_asm330lhh_i2c_of_match),
		.of_match_table = st_asm330lhh_i2c_of_match,
	},
	.probe = st_asm330lhh_i2c_probe,
	.id_table = st_asm330lhh_i2c_id_table,
Loading