Skip to content

Commit 31c24c1

Browse files
jmaneyrol-invnjic23
authored andcommitted
iio: imu: inv_icm42600: add core of new inv_icm42600 driver
Core component of a new driver for InvenSense ICM-426xx devices. It includes registers definition, main probe/setup, and device utility functions. ICM-426xx devices are latest generation of 6-axis IMU, gyroscope+accelerometer and temperature sensor. This device includes a 2K FIFO, supports I2C/I3C/SPI, and provides intelligent motion features like pedometer, tilt detection, and tap detection. Signed-off-by: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com> Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
1 parent 8f52a15 commit 31c24c1

File tree

2 files changed

+1006
-0
lines changed

2 files changed

+1006
-0
lines changed
Lines changed: 372 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,372 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
/*
3+
* Copyright (C) 2020 Invensense, Inc.
4+
*/
5+
6+
#ifndef INV_ICM42600_H_
7+
#define INV_ICM42600_H_
8+
9+
#include <linux/bits.h>
10+
#include <linux/bitfield.h>
11+
#include <linux/regmap.h>
12+
#include <linux/mutex.h>
13+
#include <linux/regulator/consumer.h>
14+
#include <linux/pm.h>
15+
#include <linux/iio/iio.h>
16+
17+
enum inv_icm42600_chip {
18+
INV_CHIP_ICM42600,
19+
INV_CHIP_ICM42602,
20+
INV_CHIP_ICM42605,
21+
INV_CHIP_ICM42622,
22+
INV_CHIP_NB,
23+
};
24+
25+
/* serial bus slew rates */
26+
enum inv_icm42600_slew_rate {
27+
INV_ICM42600_SLEW_RATE_20_60NS,
28+
INV_ICM42600_SLEW_RATE_12_36NS,
29+
INV_ICM42600_SLEW_RATE_6_18NS,
30+
INV_ICM42600_SLEW_RATE_4_12NS,
31+
INV_ICM42600_SLEW_RATE_2_6NS,
32+
INV_ICM42600_SLEW_RATE_INF_2NS,
33+
};
34+
35+
enum inv_icm42600_sensor_mode {
36+
INV_ICM42600_SENSOR_MODE_OFF,
37+
INV_ICM42600_SENSOR_MODE_STANDBY,
38+
INV_ICM42600_SENSOR_MODE_LOW_POWER,
39+
INV_ICM42600_SENSOR_MODE_LOW_NOISE,
40+
INV_ICM42600_SENSOR_MODE_NB,
41+
};
42+
43+
/* gyroscope fullscale values */
44+
enum inv_icm42600_gyro_fs {
45+
INV_ICM42600_GYRO_FS_2000DPS,
46+
INV_ICM42600_GYRO_FS_1000DPS,
47+
INV_ICM42600_GYRO_FS_500DPS,
48+
INV_ICM42600_GYRO_FS_250DPS,
49+
INV_ICM42600_GYRO_FS_125DPS,
50+
INV_ICM42600_GYRO_FS_62_5DPS,
51+
INV_ICM42600_GYRO_FS_31_25DPS,
52+
INV_ICM42600_GYRO_FS_15_625DPS,
53+
INV_ICM42600_GYRO_FS_NB,
54+
};
55+
56+
/* accelerometer fullscale values */
57+
enum inv_icm42600_accel_fs {
58+
INV_ICM42600_ACCEL_FS_16G,
59+
INV_ICM42600_ACCEL_FS_8G,
60+
INV_ICM42600_ACCEL_FS_4G,
61+
INV_ICM42600_ACCEL_FS_2G,
62+
INV_ICM42600_ACCEL_FS_NB,
63+
};
64+
65+
/* ODR suffixed by LN or LP are Low-Noise or Low-Power mode only */
66+
enum inv_icm42600_odr {
67+
INV_ICM42600_ODR_8KHZ_LN = 3,
68+
INV_ICM42600_ODR_4KHZ_LN,
69+
INV_ICM42600_ODR_2KHZ_LN,
70+
INV_ICM42600_ODR_1KHZ_LN,
71+
INV_ICM42600_ODR_200HZ,
72+
INV_ICM42600_ODR_100HZ,
73+
INV_ICM42600_ODR_50HZ,
74+
INV_ICM42600_ODR_25HZ,
75+
INV_ICM42600_ODR_12_5HZ,
76+
INV_ICM42600_ODR_6_25HZ_LP,
77+
INV_ICM42600_ODR_3_125HZ_LP,
78+
INV_ICM42600_ODR_1_5625HZ_LP,
79+
INV_ICM42600_ODR_500HZ,
80+
INV_ICM42600_ODR_NB,
81+
};
82+
83+
enum inv_icm42600_filter {
84+
/* Low-Noise mode sensor data filter (3rd order filter by default) */
85+
INV_ICM42600_FILTER_BW_ODR_DIV_2,
86+
87+
/* Low-Power mode sensor data filter (averaging) */
88+
INV_ICM42600_FILTER_AVG_1X = 1,
89+
INV_ICM42600_FILTER_AVG_16X = 6,
90+
};
91+
92+
struct inv_icm42600_sensor_conf {
93+
int mode;
94+
int fs;
95+
int odr;
96+
int filter;
97+
};
98+
#define INV_ICM42600_SENSOR_CONF_INIT {-1, -1, -1, -1}
99+
100+
struct inv_icm42600_conf {
101+
struct inv_icm42600_sensor_conf gyro;
102+
struct inv_icm42600_sensor_conf accel;
103+
bool temp_en;
104+
};
105+
106+
struct inv_icm42600_suspended {
107+
enum inv_icm42600_sensor_mode gyro;
108+
enum inv_icm42600_sensor_mode accel;
109+
bool temp;
110+
};
111+
112+
/**
113+
* struct inv_icm42600_state - driver state variables
114+
* @lock: lock for serializing multiple registers access.
115+
* @chip: chip identifier.
116+
* @name: chip name.
117+
* @map: regmap pointer.
118+
* @vdd_supply: VDD voltage regulator for the chip.
119+
* @vddio_supply: I/O voltage regulator for the chip.
120+
* @orientation: sensor chip orientation relative to main hardware.
121+
* @conf: chip sensors configurations.
122+
* @suspended: suspended sensors configuration.
123+
*/
124+
struct inv_icm42600_state {
125+
struct mutex lock;
126+
enum inv_icm42600_chip chip;
127+
const char *name;
128+
struct regmap *map;
129+
struct regulator *vdd_supply;
130+
struct regulator *vddio_supply;
131+
struct iio_mount_matrix orientation;
132+
struct inv_icm42600_conf conf;
133+
struct inv_icm42600_suspended suspended;
134+
};
135+
136+
/* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
137+
138+
/* Bank selection register, available in all banks */
139+
#define INV_ICM42600_REG_BANK_SEL 0x76
140+
#define INV_ICM42600_BANK_SEL_MASK GENMASK(2, 0)
141+
142+
/* User bank 0 (MSB 0x00) */
143+
#define INV_ICM42600_REG_DEVICE_CONFIG 0x0011
144+
#define INV_ICM42600_DEVICE_CONFIG_SOFT_RESET BIT(0)
145+
146+
#define INV_ICM42600_REG_DRIVE_CONFIG 0x0013
147+
#define INV_ICM42600_DRIVE_CONFIG_I2C_MASK GENMASK(5, 3)
148+
#define INV_ICM42600_DRIVE_CONFIG_I2C(_rate) \
149+
FIELD_PREP(INV_ICM42600_DRIVE_CONFIG_I2C_MASK, (_rate))
150+
#define INV_ICM42600_DRIVE_CONFIG_SPI_MASK GENMASK(2, 0)
151+
#define INV_ICM42600_DRIVE_CONFIG_SPI(_rate) \
152+
FIELD_PREP(INV_ICM42600_DRIVE_CONFIG_SPI_MASK, (_rate))
153+
154+
#define INV_ICM42600_REG_INT_CONFIG 0x0014
155+
#define INV_ICM42600_INT_CONFIG_INT2_LATCHED BIT(5)
156+
#define INV_ICM42600_INT_CONFIG_INT2_PUSH_PULL BIT(4)
157+
#define INV_ICM42600_INT_CONFIG_INT2_ACTIVE_HIGH BIT(3)
158+
#define INV_ICM42600_INT_CONFIG_INT2_ACTIVE_LOW 0x00
159+
#define INV_ICM42600_INT_CONFIG_INT1_LATCHED BIT(2)
160+
#define INV_ICM42600_INT_CONFIG_INT1_PUSH_PULL BIT(1)
161+
#define INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH BIT(0)
162+
#define INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW 0x00
163+
164+
#define INV_ICM42600_REG_FIFO_CONFIG 0x0016
165+
#define INV_ICM42600_FIFO_CONFIG_MASK GENMASK(7, 6)
166+
#define INV_ICM42600_FIFO_CONFIG_BYPASS \
167+
FIELD_PREP(INV_ICM42600_FIFO_CONFIG_MASK, 0)
168+
#define INV_ICM42600_FIFO_CONFIG_STREAM \
169+
FIELD_PREP(INV_ICM42600_FIFO_CONFIG_MASK, 1)
170+
#define INV_ICM42600_FIFO_CONFIG_STOP_ON_FULL \
171+
FIELD_PREP(INV_ICM42600_FIFO_CONFIG_MASK, 2)
172+
173+
/* all sensor data are 16 bits (2 registers wide) in big-endian */
174+
#define INV_ICM42600_REG_TEMP_DATA 0x001D
175+
#define INV_ICM42600_REG_ACCEL_DATA_X 0x001F
176+
#define INV_ICM42600_REG_ACCEL_DATA_Y 0x0021
177+
#define INV_ICM42600_REG_ACCEL_DATA_Z 0x0023
178+
#define INV_ICM42600_REG_GYRO_DATA_X 0x0025
179+
#define INV_ICM42600_REG_GYRO_DATA_Y 0x0027
180+
#define INV_ICM42600_REG_GYRO_DATA_Z 0x0029
181+
#define INV_ICM42600_DATA_INVALID -32768
182+
183+
#define INV_ICM42600_REG_INT_STATUS 0x002D
184+
#define INV_ICM42600_INT_STATUS_UI_FSYNC BIT(6)
185+
#define INV_ICM42600_INT_STATUS_PLL_RDY BIT(5)
186+
#define INV_ICM42600_INT_STATUS_RESET_DONE BIT(4)
187+
#define INV_ICM42600_INT_STATUS_DATA_RDY BIT(3)
188+
#define INV_ICM42600_INT_STATUS_FIFO_THS BIT(2)
189+
#define INV_ICM42600_INT_STATUS_FIFO_FULL BIT(1)
190+
#define INV_ICM42600_INT_STATUS_AGC_RDY BIT(0)
191+
192+
/*
193+
* FIFO access registers
194+
* FIFO count is 16 bits (2 registers) big-endian
195+
* FIFO data is a continuous read register to read FIFO content
196+
*/
197+
#define INV_ICM42600_REG_FIFO_COUNT 0x002E
198+
#define INV_ICM42600_REG_FIFO_DATA 0x0030
199+
200+
#define INV_ICM42600_REG_SIGNAL_PATH_RESET 0x004B
201+
#define INV_ICM42600_SIGNAL_PATH_RESET_DMP_INIT_EN BIT(6)
202+
#define INV_ICM42600_SIGNAL_PATH_RESET_DMP_MEM_RESET BIT(5)
203+
#define INV_ICM42600_SIGNAL_PATH_RESET_RESET BIT(3)
204+
#define INV_ICM42600_SIGNAL_PATH_RESET_TMST_STROBE BIT(2)
205+
#define INV_ICM42600_SIGNAL_PATH_RESET_FIFO_FLUSH BIT(1)
206+
207+
/* default configuration: all data big-endian and fifo count in bytes */
208+
#define INV_ICM42600_REG_INTF_CONFIG0 0x004C
209+
#define INV_ICM42600_INTF_CONFIG0_FIFO_HOLD_LAST_DATA BIT(7)
210+
#define INV_ICM42600_INTF_CONFIG0_FIFO_COUNT_REC BIT(6)
211+
#define INV_ICM42600_INTF_CONFIG0_FIFO_COUNT_ENDIAN BIT(5)
212+
#define INV_ICM42600_INTF_CONFIG0_SENSOR_DATA_ENDIAN BIT(4)
213+
#define INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK GENMASK(1, 0)
214+
#define INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS \
215+
FIELD_PREP(INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK, 2)
216+
#define INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS \
217+
FIELD_PREP(INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK, 3)
218+
219+
#define INV_ICM42600_REG_INTF_CONFIG1 0x004D
220+
#define INV_ICM42600_INTF_CONFIG1_ACCEL_LP_CLK_RC BIT(3)
221+
222+
#define INV_ICM42600_REG_PWR_MGMT0 0x004E
223+
#define INV_ICM42600_PWR_MGMT0_TEMP_DIS BIT(5)
224+
#define INV_ICM42600_PWR_MGMT0_IDLE BIT(4)
225+
#define INV_ICM42600_PWR_MGMT0_GYRO(_mode) \
226+
FIELD_PREP(GENMASK(3, 2), (_mode))
227+
#define INV_ICM42600_PWR_MGMT0_ACCEL(_mode) \
228+
FIELD_PREP(GENMASK(1, 0), (_mode))
229+
230+
#define INV_ICM42600_REG_GYRO_CONFIG0 0x004F
231+
#define INV_ICM42600_GYRO_CONFIG0_FS(_fs) \
232+
FIELD_PREP(GENMASK(7, 5), (_fs))
233+
#define INV_ICM42600_GYRO_CONFIG0_ODR(_odr) \
234+
FIELD_PREP(GENMASK(3, 0), (_odr))
235+
236+
#define INV_ICM42600_REG_ACCEL_CONFIG0 0x0050
237+
#define INV_ICM42600_ACCEL_CONFIG0_FS(_fs) \
238+
FIELD_PREP(GENMASK(7, 5), (_fs))
239+
#define INV_ICM42600_ACCEL_CONFIG0_ODR(_odr) \
240+
FIELD_PREP(GENMASK(3, 0), (_odr))
241+
242+
#define INV_ICM42600_REG_GYRO_ACCEL_CONFIG0 0x0052
243+
#define INV_ICM42600_GYRO_ACCEL_CONFIG0_ACCEL_FILT(_f) \
244+
FIELD_PREP(GENMASK(7, 4), (_f))
245+
#define INV_ICM42600_GYRO_ACCEL_CONFIG0_GYRO_FILT(_f) \
246+
FIELD_PREP(GENMASK(3, 0), (_f))
247+
248+
#define INV_ICM42600_REG_TMST_CONFIG 0x0054
249+
#define INV_ICM42600_TMST_CONFIG_MASK GENMASK(4, 0)
250+
#define INV_ICM42600_TMST_CONFIG_TMST_TO_REGS_EN BIT(4)
251+
#define INV_ICM42600_TMST_CONFIG_TMST_RES_16US BIT(3)
252+
#define INV_ICM42600_TMST_CONFIG_TMST_DELTA_EN BIT(2)
253+
#define INV_ICM42600_TMST_CONFIG_TMST_FSYNC_EN BIT(1)
254+
#define INV_ICM42600_TMST_CONFIG_TMST_EN BIT(0)
255+
256+
#define INV_ICM42600_REG_FIFO_CONFIG1 0x005F
257+
#define INV_ICM42600_FIFO_CONFIG1_RESUME_PARTIAL_RD BIT(6)
258+
#define INV_ICM42600_FIFO_CONFIG1_WM_GT_TH BIT(5)
259+
#define INV_ICM42600_FIFO_CONFIG1_TMST_FSYNC_EN BIT(3)
260+
#define INV_ICM42600_FIFO_CONFIG1_TEMP_EN BIT(2)
261+
#define INV_ICM42600_FIFO_CONFIG1_GYRO_EN BIT(1)
262+
#define INV_ICM42600_FIFO_CONFIG1_ACCEL_EN BIT(0)
263+
264+
/* FIFO watermark is 16 bits (2 registers wide) in little-endian */
265+
#define INV_ICM42600_REG_FIFO_WATERMARK 0x0060
266+
#define INV_ICM42600_FIFO_WATERMARK_VAL(_wm) \
267+
cpu_to_le16((_wm) & GENMASK(11, 0))
268+
/* FIFO is 2048 bytes, let 12 samples for reading latency */
269+
#define INV_ICM42600_FIFO_WATERMARK_MAX (2048 - 12 * 16)
270+
271+
#define INV_ICM42600_REG_INT_CONFIG1 0x0064
272+
#define INV_ICM42600_INT_CONFIG1_TPULSE_DURATION BIT(6)
273+
#define INV_ICM42600_INT_CONFIG1_TDEASSERT_DISABLE BIT(5)
274+
#define INV_ICM42600_INT_CONFIG1_ASYNC_RESET BIT(4)
275+
276+
#define INV_ICM42600_REG_INT_SOURCE0 0x0065
277+
#define INV_ICM42600_INT_SOURCE0_UI_FSYNC_INT1_EN BIT(6)
278+
#define INV_ICM42600_INT_SOURCE0_PLL_RDY_INT1_EN BIT(5)
279+
#define INV_ICM42600_INT_SOURCE0_RESET_DONE_INT1_EN BIT(4)
280+
#define INV_ICM42600_INT_SOURCE0_UI_DRDY_INT1_EN BIT(3)
281+
#define INV_ICM42600_INT_SOURCE0_FIFO_THS_INT1_EN BIT(2)
282+
#define INV_ICM42600_INT_SOURCE0_FIFO_FULL_INT1_EN BIT(1)
283+
#define INV_ICM42600_INT_SOURCE0_UI_AGC_RDY_INT1_EN BIT(0)
284+
285+
#define INV_ICM42600_REG_WHOAMI 0x0075
286+
#define INV_ICM42600_WHOAMI_ICM42600 0x40
287+
#define INV_ICM42600_WHOAMI_ICM42602 0x41
288+
#define INV_ICM42600_WHOAMI_ICM42605 0x42
289+
#define INV_ICM42600_WHOAMI_ICM42622 0x46
290+
291+
/* User bank 1 (MSB 0x10) */
292+
#define INV_ICM42600_REG_SENSOR_CONFIG0 0x1003
293+
#define INV_ICM42600_SENSOR_CONFIG0_ZG_DISABLE BIT(5)
294+
#define INV_ICM42600_SENSOR_CONFIG0_YG_DISABLE BIT(4)
295+
#define INV_ICM42600_SENSOR_CONFIG0_XG_DISABLE BIT(3)
296+
#define INV_ICM42600_SENSOR_CONFIG0_ZA_DISABLE BIT(2)
297+
#define INV_ICM42600_SENSOR_CONFIG0_YA_DISABLE BIT(1)
298+
#define INV_ICM42600_SENSOR_CONFIG0_XA_DISABLE BIT(0)
299+
300+
/* Timestamp value is 20 bits (3 registers) in little-endian */
301+
#define INV_ICM42600_REG_TMSTVAL 0x1062
302+
#define INV_ICM42600_TMSTVAL_MASK GENMASK(19, 0)
303+
304+
#define INV_ICM42600_REG_INTF_CONFIG4 0x107A
305+
#define INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY BIT(6)
306+
#define INV_ICM42600_INTF_CONFIG4_SPI_AP_4WIRE BIT(1)
307+
308+
#define INV_ICM42600_REG_INTF_CONFIG6 0x107C
309+
#define INV_ICM42600_INTF_CONFIG6_MASK GENMASK(4, 0)
310+
#define INV_ICM42600_INTF_CONFIG6_I3C_EN BIT(4)
311+
#define INV_ICM42600_INTF_CONFIG6_I3C_IBI_BYTE_EN BIT(3)
312+
#define INV_ICM42600_INTF_CONFIG6_I3C_IBI_EN BIT(2)
313+
#define INV_ICM42600_INTF_CONFIG6_I3C_DDR_EN BIT(1)
314+
#define INV_ICM42600_INTF_CONFIG6_I3C_SDR_EN BIT(0)
315+
316+
/* User bank 4 (MSB 0x40) */
317+
#define INV_ICM42600_REG_INT_SOURCE8 0x404F
318+
#define INV_ICM42600_INT_SOURCE8_FSYNC_IBI_EN BIT(5)
319+
#define INV_ICM42600_INT_SOURCE8_PLL_RDY_IBI_EN BIT(4)
320+
#define INV_ICM42600_INT_SOURCE8_UI_DRDY_IBI_EN BIT(3)
321+
#define INV_ICM42600_INT_SOURCE8_FIFO_THS_IBI_EN BIT(2)
322+
#define INV_ICM42600_INT_SOURCE8_FIFO_FULL_IBI_EN BIT(1)
323+
#define INV_ICM42600_INT_SOURCE8_AGC_RDY_IBI_EN BIT(0)
324+
325+
#define INV_ICM42600_REG_OFFSET_USER0 0x4077
326+
#define INV_ICM42600_REG_OFFSET_USER1 0x4078
327+
#define INV_ICM42600_REG_OFFSET_USER2 0x4079
328+
#define INV_ICM42600_REG_OFFSET_USER3 0x407A
329+
#define INV_ICM42600_REG_OFFSET_USER4 0x407B
330+
#define INV_ICM42600_REG_OFFSET_USER5 0x407C
331+
#define INV_ICM42600_REG_OFFSET_USER6 0x407D
332+
#define INV_ICM42600_REG_OFFSET_USER7 0x407E
333+
#define INV_ICM42600_REG_OFFSET_USER8 0x407F
334+
335+
/* Sleep times required by the driver */
336+
#define INV_ICM42600_POWER_UP_TIME_MS 100
337+
#define INV_ICM42600_RESET_TIME_MS 1
338+
#define INV_ICM42600_ACCEL_STARTUP_TIME_MS 20
339+
#define INV_ICM42600_GYRO_STARTUP_TIME_MS 60
340+
#define INV_ICM42600_GYRO_STOP_TIME_MS 150
341+
#define INV_ICM42600_TEMP_STARTUP_TIME_MS 14
342+
#define INV_ICM42600_SUSPEND_DELAY_MS 2000
343+
344+
typedef int (*inv_icm42600_bus_setup)(struct inv_icm42600_state *);
345+
346+
extern const struct regmap_config inv_icm42600_regmap_config;
347+
extern const struct dev_pm_ops inv_icm42600_pm_ops;
348+
349+
const struct iio_mount_matrix *
350+
inv_icm42600_get_mount_matrix(const struct iio_dev *indio_dev,
351+
const struct iio_chan_spec *chan);
352+
353+
uint32_t inv_icm42600_odr_to_period(enum inv_icm42600_odr odr);
354+
355+
int inv_icm42600_set_accel_conf(struct inv_icm42600_state *st,
356+
struct inv_icm42600_sensor_conf *conf,
357+
unsigned int *sleep_ms);
358+
359+
int inv_icm42600_set_gyro_conf(struct inv_icm42600_state *st,
360+
struct inv_icm42600_sensor_conf *conf,
361+
unsigned int *sleep_ms);
362+
363+
int inv_icm42600_set_temp_conf(struct inv_icm42600_state *st, bool enable,
364+
unsigned int *sleep_ms);
365+
366+
int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg,
367+
unsigned int writeval, unsigned int *readval);
368+
369+
int inv_icm42600_core_probe(struct regmap *regmap, int chip,
370+
inv_icm42600_bus_setup bus_setup);
371+
372+
#endif

0 commit comments

Comments
 (0)