1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
|
/* 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
|