Contributors: 1
Author Tokens Token Proportion Commits Commit Proportion
Remi Buisson 1096 100.00% 4 100.00%
Total 1096 4


/* SPDX-License-Identifier: GPL-2.0-or-later */
/* Copyright (C) 2025 Invensense, Inc. */

#ifndef INV_ICM45600_H_
#define INV_ICM45600_H_

#include <linux/bits.h>
#include <linux/limits.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/sizes.h>
#include <linux/types.h>

#include <linux/iio/common/inv_sensors_timestamp.h>
#include <linux/iio/iio.h>

#include "inv_icm45600_buffer.h"

#define INV_ICM45600_REG_BANK_MASK	GENMASK(15, 8)
#define INV_ICM45600_REG_ADDR_MASK	GENMASK(7, 0)

enum inv_icm45600_sensor_mode {
	INV_ICM45600_SENSOR_MODE_OFF,
	INV_ICM45600_SENSOR_MODE_STANDBY,
	INV_ICM45600_SENSOR_MODE_LOW_POWER,
	INV_ICM45600_SENSOR_MODE_LOW_NOISE,
	INV_ICM45600_SENSOR_MODE_MAX
};

/* gyroscope fullscale values */
enum inv_icm45600_gyro_fs {
	INV_ICM45600_GYRO_FS_2000DPS,
	INV_ICM45600_GYRO_FS_1000DPS,
	INV_ICM45600_GYRO_FS_500DPS,
	INV_ICM45600_GYRO_FS_250DPS,
	INV_ICM45600_GYRO_FS_125DPS,
	INV_ICM45600_GYRO_FS_62_5DPS,
	INV_ICM45600_GYRO_FS_31_25DPS,
	INV_ICM45600_GYRO_FS_15_625DPS,
	INV_ICM45600_GYRO_FS_MAX
};

enum inv_icm45686_gyro_fs {
	INV_ICM45686_GYRO_FS_4000DPS,
	INV_ICM45686_GYRO_FS_2000DPS,
	INV_ICM45686_GYRO_FS_1000DPS,
	INV_ICM45686_GYRO_FS_500DPS,
	INV_ICM45686_GYRO_FS_250DPS,
	INV_ICM45686_GYRO_FS_125DPS,
	INV_ICM45686_GYRO_FS_62_5DPS,
	INV_ICM45686_GYRO_FS_31_25DPS,
	INV_ICM45686_GYRO_FS_15_625DPS,
	INV_ICM45686_GYRO_FS_MAX
};

/* accelerometer fullscale values */
enum inv_icm45600_accel_fs {
	INV_ICM45600_ACCEL_FS_16G,
	INV_ICM45600_ACCEL_FS_8G,
	INV_ICM45600_ACCEL_FS_4G,
	INV_ICM45600_ACCEL_FS_2G,
	INV_ICM45600_ACCEL_FS_MAX
};

enum inv_icm45686_accel_fs {
	INV_ICM45686_ACCEL_FS_32G,
	INV_ICM45686_ACCEL_FS_16G,
	INV_ICM45686_ACCEL_FS_8G,
	INV_ICM45686_ACCEL_FS_4G,
	INV_ICM45686_ACCEL_FS_2G,
	INV_ICM45686_ACCEL_FS_MAX
};

/* ODR suffixed by LN or LP are Low-Noise or Low-Power mode only */
enum inv_icm45600_odr {
	INV_ICM45600_ODR_6400HZ_LN = 0x03,
	INV_ICM45600_ODR_3200HZ_LN,
	INV_ICM45600_ODR_1600HZ_LN,
	INV_ICM45600_ODR_800HZ_LN,
	INV_ICM45600_ODR_400HZ,
	INV_ICM45600_ODR_200HZ,
	INV_ICM45600_ODR_100HZ,
	INV_ICM45600_ODR_50HZ,
	INV_ICM45600_ODR_25HZ,
	INV_ICM45600_ODR_12_5HZ,
	INV_ICM45600_ODR_6_25HZ_LP,
	INV_ICM45600_ODR_3_125HZ_LP,
	INV_ICM45600_ODR_1_5625HZ_LP,
	INV_ICM45600_ODR_MAX
};

struct inv_icm45600_sensor_conf {
	u8 mode;
	u8 fs;
	u8 odr;
	u8 filter;
};

#define INV_ICM45600_SENSOR_CONF_KEEP_VALUES { U8_MAX, U8_MAX, U8_MAX, U8_MAX }

struct inv_icm45600_conf {
	struct inv_icm45600_sensor_conf gyro;
	struct inv_icm45600_sensor_conf accel;
};

struct inv_icm45600_suspended {
	enum inv_icm45600_sensor_mode gyro;
	enum inv_icm45600_sensor_mode accel;
};

struct inv_icm45600_chip_info {
	u8 whoami;
	const char *name;
	const struct inv_icm45600_conf *conf;
	const int *accel_scales;
	const int accel_scales_len;
	const int *gyro_scales;
	const int gyro_scales_len;
};

extern const struct inv_icm45600_chip_info inv_icm45605_chip_info;
extern const struct inv_icm45600_chip_info inv_icm45606_chip_info;
extern const struct inv_icm45600_chip_info inv_icm45608_chip_info;
extern const struct inv_icm45600_chip_info inv_icm45634_chip_info;
extern const struct inv_icm45600_chip_info inv_icm45686_chip_info;
extern const struct inv_icm45600_chip_info inv_icm45687_chip_info;
extern const struct inv_icm45600_chip_info inv_icm45688p_chip_info;
extern const struct inv_icm45600_chip_info inv_icm45689_chip_info;

extern const int inv_icm45600_accel_scale[][2];
extern const int inv_icm45686_accel_scale[][2];
extern const int inv_icm45600_gyro_scale[][2];
extern const int inv_icm45686_gyro_scale[][2];

/**
 *  struct inv_icm45600_state - driver state variables
 *  @lock:		lock for serializing multiple registers access.
 *  @map:		regmap pointer.
 *  @vddio_supply:	I/O voltage regulator for the chip.
 *  @orientation:	sensor chip orientation relative to main hardware.
 *  @conf:		chip sensors configurations.
 *  @suspended:		suspended sensors configuration.
 *  @indio_gyro:	gyroscope IIO device.
 *  @indio_accel:	accelerometer IIO device.
 *  @chip_info:		chip driver data.
 *  @timestamp:		interrupt timestamps.
 *  @fifo:		FIFO management structure.
 *  @buffer:		data transfer buffer aligned for DMA.
 */
struct inv_icm45600_state {
	struct mutex lock;
	struct regmap *map;
	struct regulator *vddio_supply;
	struct iio_mount_matrix orientation;
	struct inv_icm45600_conf conf;
	struct inv_icm45600_suspended suspended;
	struct iio_dev *indio_gyro;
	struct iio_dev *indio_accel;
	const struct inv_icm45600_chip_info *chip_info;
	struct {
		s64 gyro;
		s64 accel;
	} timestamp;
	struct inv_icm45600_fifo fifo;
	union {
		u8 buff[2];
		__le16 u16;
		u8 ireg[3];
	} buffer __aligned(IIO_DMA_MINALIGN);
};

/**
 * struct inv_icm45600_sensor_state - sensor state variables
 * @scales:		table of scales.
 * @scales_len:		length (nb of items) of the scales table.
 * @power_mode:		sensor requested power mode (for common frequencies)
 * @ts:			timestamp module states.
 */
struct inv_icm45600_sensor_state {
	const int *scales;
	size_t scales_len;
	enum inv_icm45600_sensor_mode power_mode;
	struct inv_sensors_timestamp ts;
};

/* Virtual register addresses: @bank on MSB (16 bits), @address on LSB */

/* Indirect register access */
#define INV_ICM45600_REG_IREG_ADDR			0x7C
#define INV_ICM45600_REG_IREG_DATA			0x7E

/* Direct acces registers */
#define INV_ICM45600_REG_MISC2				0x007F
#define INV_ICM45600_MISC2_SOFT_RESET			BIT(1)

#define INV_ICM45600_REG_DRIVE_CONFIG0			0x0032
#define INV_ICM45600_DRIVE_CONFIG0_SPI_MASK		GENMASK(3, 1)
#define INV_ICM45600_SPI_SLEW_RATE_0_5NS		6
#define INV_ICM45600_SPI_SLEW_RATE_4NS			5
#define INV_ICM45600_SPI_SLEW_RATE_5NS			4
#define INV_ICM45600_SPI_SLEW_RATE_7NS			3
#define INV_ICM45600_SPI_SLEW_RATE_10NS			2
#define INV_ICM45600_SPI_SLEW_RATE_14NS			1
#define INV_ICM45600_SPI_SLEW_RATE_38NS			0

#define INV_ICM45600_REG_INT1_CONFIG2			0x0018
#define INV_ICM45600_INT1_CONFIG2_PUSH_PULL		BIT(2)
#define INV_ICM45600_INT1_CONFIG2_LATCHED		BIT(1)
#define INV_ICM45600_INT1_CONFIG2_ACTIVE_HIGH		BIT(0)
#define INV_ICM45600_INT1_CONFIG2_ACTIVE_LOW		0x00

#define INV_ICM45600_REG_FIFO_CONFIG0			0x001D
#define INV_ICM45600_FIFO_CONFIG0_MODE_MASK		GENMASK(7, 6)
#define INV_ICM45600_FIFO_CONFIG0_MODE_BYPASS		0
#define INV_ICM45600_FIFO_CONFIG0_MODE_STREAM		1
#define INV_ICM45600_FIFO_CONFIG0_MODE_STOP_ON_FULL	2
#define INV_ICM45600_FIFO_CONFIG0_FIFO_DEPTH_MASK	GENMASK(5, 0)
#define INV_ICM45600_FIFO_CONFIG0_FIFO_DEPTH_MAX	0x1F

#define INV_ICM45600_REG_FIFO_CONFIG2			0x0020
#define INV_ICM45600_REG_FIFO_CONFIG2_FIFO_FLUSH	BIT(7)
#define INV_ICM45600_REG_FIFO_CONFIG2_WM_GT_TH		BIT(3)

#define INV_ICM45600_REG_FIFO_CONFIG3			0x0021
#define INV_ICM45600_FIFO_CONFIG3_ES1_EN		BIT(5)
#define INV_ICM45600_FIFO_CONFIG3_ES0_EN		BIT(4)
#define INV_ICM45600_FIFO_CONFIG3_HIRES_EN		BIT(3)
#define INV_ICM45600_FIFO_CONFIG3_GYRO_EN		BIT(2)
#define INV_ICM45600_FIFO_CONFIG3_ACCEL_EN		BIT(1)
#define INV_ICM45600_FIFO_CONFIG3_IF_EN			BIT(0)

#define INV_ICM45600_REG_FIFO_CONFIG4			0x0022
#define INV_ICM45600_FIFO_CONFIG4_COMP_EN		BIT(2)
#define INV_ICM45600_FIFO_CONFIG4_TMST_FSYNC_EN		BIT(1)
#define INV_ICM45600_FIFO_CONFIG4_ES0_9B		BIT(0)

/* all sensor data are 16 bits (2 registers wide) in big-endian */
#define INV_ICM45600_REG_TEMP_DATA			0x000C
#define INV_ICM45600_REG_ACCEL_DATA_X			0x0000
#define INV_ICM45600_REG_ACCEL_DATA_Y			0x0002
#define INV_ICM45600_REG_ACCEL_DATA_Z			0x0004
#define INV_ICM45600_REG_GYRO_DATA_X			0x0006
#define INV_ICM45600_REG_GYRO_DATA_Y			0x0008
#define INV_ICM45600_REG_GYRO_DATA_Z			0x000A

#define INV_ICM45600_REG_INT_STATUS			0x0019
#define INV_ICM45600_INT_STATUS_RESET_DONE		BIT(7)
#define INV_ICM45600_INT_STATUS_AUX1_AGC_RDY		BIT(6)
#define INV_ICM45600_INT_STATUS_AP_AGC_RDY		BIT(5)
#define INV_ICM45600_INT_STATUS_AP_FSYNC		BIT(4)
#define INV_ICM45600_INT_STATUS_AUX1_DRDY		BIT(3)
#define INV_ICM45600_INT_STATUS_DATA_RDY		BIT(2)
#define INV_ICM45600_INT_STATUS_FIFO_THS		BIT(1)
#define INV_ICM45600_INT_STATUS_FIFO_FULL		BIT(0)

/*
 * FIFO access registers
 * FIFO count is 16 bits (2 registers)
 * FIFO data is a continuous read register to read FIFO content
 */
#define INV_ICM45600_REG_FIFO_COUNT			0x0012
#define INV_ICM45600_REG_FIFO_DATA			0x0014

#define INV_ICM45600_REG_PWR_MGMT0			0x0010
#define INV_ICM45600_PWR_MGMT0_GYRO_MODE_MASK		GENMASK(3, 2)
#define INV_ICM45600_PWR_MGMT0_ACCEL_MODE_MASK		GENMASK(1, 0)

#define INV_ICM45600_REG_ACCEL_CONFIG0			0x001B
#define INV_ICM45600_ACCEL_CONFIG0_FS_MASK		GENMASK(6, 4)
#define INV_ICM45600_ACCEL_CONFIG0_ODR_MASK		GENMASK(3, 0)
#define INV_ICM45600_REG_GYRO_CONFIG0			0x001C
#define INV_ICM45600_GYRO_CONFIG0_FS_MASK		GENMASK(7, 4)
#define INV_ICM45600_GYRO_CONFIG0_ODR_MASK		GENMASK(3, 0)

#define INV_ICM45600_REG_SMC_CONTROL_0			0xA258
#define INV_ICM45600_SMC_CONTROL_0_ACCEL_LP_CLK_SEL	BIT(4)
#define INV_ICM45600_SMC_CONTROL_0_TMST_EN		BIT(0)

/* FIFO watermark is 16 bits (2 registers wide) in little-endian */
#define INV_ICM45600_REG_FIFO_WATERMARK			0x001E

/* FIFO is configured for 8kb */
#define INV_ICM45600_FIFO_SIZE_MAX			SZ_8K

#define INV_ICM45600_REG_INT1_CONFIG0			0x0016
#define INV_ICM45600_INT1_CONFIG0_RESET_DONE_EN		BIT(7)
#define INV_ICM45600_INT1_CONFIG0_AUX1_AGC_RDY_EN	BIT(6)
#define INV_ICM45600_INT1_CONFIG0_AP_AGC_RDY_EN		BIT(5)
#define INV_ICM45600_INT1_CONFIG0_AP_FSYNC_EN		BIT(4)
#define INV_ICM45600_INT1_CONFIG0_AUX1_DRDY_EN		BIT(3)
#define INV_ICM45600_INT1_CONFIG0_DRDY_EN		BIT(2)
#define INV_ICM45600_INT1_CONFIG0_FIFO_THS_EN		BIT(1)
#define INV_ICM45600_INT1_CONFIG0_FIFO_FULL_EN		BIT(0)

#define INV_ICM45600_REG_WHOAMI				0x0072
#define INV_ICM45600_WHOAMI_ICM45605			0xE5
#define INV_ICM45600_WHOAMI_ICM45686			0xE9
#define INV_ICM45600_WHOAMI_ICM45688P			0xE7
#define INV_ICM45600_WHOAMI_ICM45608			0x81
#define INV_ICM45600_WHOAMI_ICM45634			0x82
#define INV_ICM45600_WHOAMI_ICM45689			0x83
#define INV_ICM45600_WHOAMI_ICM45606			0x84
#define INV_ICM45600_WHOAMI_ICM45687			0x85

/* Gyro USER offset */
#define INV_ICM45600_IPREG_SYS1_REG_42			0xA42A
#define INV_ICM45600_IPREG_SYS1_REG_56			0xA438
#define INV_ICM45600_IPREG_SYS1_REG_70			0xA446
#define INV_ICM45600_GYRO_OFFUSER_MASK			GENMASK(13, 0)
/* Gyro Averaging filter */
#define INV_ICM45600_IPREG_SYS1_REG_170			0xA4AA
#define INV_ICM45600_IPREG_SYS1_170_GYRO_LP_AVG_MASK	GENMASK(4, 1)
#define INV_ICM45600_GYRO_LP_AVG_SEL_8X			5
#define INV_ICM45600_GYRO_LP_AVG_SEL_2X			1
/* Accel USER offset */
#define INV_ICM45600_IPREG_SYS2_REG_24			0xA518
#define INV_ICM45600_IPREG_SYS2_REG_32			0xA520
#define INV_ICM45600_IPREG_SYS2_REG_40			0xA528
#define INV_ICM45600_ACCEL_OFFUSER_MASK			GENMASK(13, 0)
/* Accel averaging filter */
#define INV_ICM45600_IPREG_SYS2_REG_129			0xA581
#define INV_ICM45600_ACCEL_LP_AVG_SEL_1X		0x0000
#define INV_ICM45600_ACCEL_LP_AVG_SEL_4X		0x0002

/* Sleep times required by the driver */
#define INV_ICM45600_ACCEL_STARTUP_TIME_MS	60
#define INV_ICM45600_GYRO_STARTUP_TIME_MS	60
#define INV_ICM45600_GYRO_STOP_TIME_MS		150
#define INV_ICM45600_IREG_DELAY_US		4

typedef int (*inv_icm45600_bus_setup)(struct inv_icm45600_state *);

extern const struct dev_pm_ops inv_icm45600_pm_ops;

const struct iio_mount_matrix *
inv_icm45600_get_mount_matrix(const struct iio_dev *indio_dev,
			      const struct iio_chan_spec *chan);

#define INV_ICM45600_TEMP_CHAN(_index)					\
	{								\
		.type = IIO_TEMP,					\
		.info_mask_separate =					\
			BIT(IIO_CHAN_INFO_RAW) |			\
			BIT(IIO_CHAN_INFO_OFFSET) |			\
			BIT(IIO_CHAN_INFO_SCALE),			\
		.scan_index = _index,					\
		.scan_type = {						\
			.sign = 's',					\
			.realbits = 16,					\
			.storagebits = 16,				\
			.endianness = IIO_LE,				\
		},							\
	}

int inv_icm45600_temp_read_raw(struct iio_dev *indio_dev,
			       struct iio_chan_spec const *chan,
			       int *val, int *val2, long mask);

u32 inv_icm45600_odr_to_period(enum inv_icm45600_odr odr);

int inv_icm45600_set_accel_conf(struct inv_icm45600_state *st,
				struct inv_icm45600_sensor_conf *conf,
				unsigned int *sleep_ms);

int inv_icm45600_set_gyro_conf(struct inv_icm45600_state *st,
			       struct inv_icm45600_sensor_conf *conf,
			       unsigned int *sleep_ms);

int inv_icm45600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg,
			     unsigned int writeval, unsigned int *readval);

int inv_icm45600_core_probe(struct regmap *regmap,
				const struct inv_icm45600_chip_info *chip_info,
				bool reset, inv_icm45600_bus_setup bus_setup);

struct iio_dev *inv_icm45600_gyro_init(struct inv_icm45600_state *st);

int inv_icm45600_gyro_parse_fifo(struct iio_dev *indio_dev);

struct iio_dev *inv_icm45600_accel_init(struct inv_icm45600_state *st);

int inv_icm45600_accel_parse_fifo(struct iio_dev *indio_dev);

#endif