summaryrefslogtreecommitdiff
path: root/driver/accelgyro_icm426xx.h
blob: 0c1949e3f0a26fb71db6359f5af6bc4c62ee5ffd (plain)
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
/* Copyright 2020 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/* ICM-426xx accelerometer and gyroscope for Chrome EC */

#ifndef __CROS_EC_ACCELGYRO_ICM426XX_H
#define __CROS_EC_ACCELGYRO_ICM426XX_H

#include "accelgyro.h"
#include "common.h"

/*
 * 8-bit address is 110100X0b. Where 'X' is determined
 * by the logic level on pin AP_AD0.
 */
#define ICM426XX_ADDR0_FLAGS		(0x68 << 1)
#define ICM426XX_ADDR1_FLAGS		(0x69 << 1)

/* Min and Max sampling frequency in mHz */
#define ICM426XX_ACCEL_MIN_FREQ	3125
#define ICM426XX_ACCEL_MAX_FREQ	100000
#define ICM426XX_GYRO_MIN_FREQ	12500
#define ICM426XX_GYRO_MAX_FREQ	100000
/* Min and Max Accel FS in G */
#define ICM426XX_ACCEL_FS_MIN_VAL	2
#define ICM426XX_ACCEL_FS_MAX_VAL	16

/* Min and Max Gyro FS in dps */
#define ICM426XX_GYRO_FS_MIN_VAL	125
#define ICM426XX_GYRO_FS_MAX_VAL	2000

/* accel stabilization time in us */
#define ICM426XX_ACCEL_START_TIME	20000
#define ICM426XX_ACCEL_STOP_TIME	0

/* gyro stabilization time in us */
#define ICM426XX_GYRO_START_TIME	60000
#define ICM426XX_GYRO_STOP_TIME		150000

/* Reg value from Accel FS in G */
#define ICM426XX_ACCEL_FS_TO_REG(_fs)	((_fs) < 2 ? 3 : \
					(_fs) > 16 ? 0 : \
					3 - __fls((_fs) / 2))

/* Accel FSR in G from Reg value */
#define ICM426XX_ACCEL_REG_TO_FS(_reg)	((1 << (3 - (_reg))) * 2)

/* Reg value from Gyro FS in dps */
#define ICM426XX_GYRO_FS_TO_REG(_fs)	((_fs) < 125 ? 4 : \
					(_fs) > 2000 ? 0 : \
					4 - __fls((_fs) / 125))

/* Gyro FSR in dps from Reg value */
#define ICM426XX_GYRO_REG_TO_FS(_reg)	((1 << (4 - (_reg))) * 125)

/* Reg value from ODR in mHz */
#define ICM426XX_ODR_TO_REG(_odr)	((_odr) <= 200000 ? \
					13 - __fls((_odr) / 3125) : \
					(_odr) < 500000 ? 7 : \
					(_odr) < 1000000 ? 15 : \
					6 - __fls((_odr) / 1000000))

/* ODR in mHz from Reg value */
#define ICM426XX_REG_TO_ODR(_reg)	((_reg) == 15 ? 500000 : \
					(_reg) >= 7 ? \
					(1 << (13 - (_reg))) * 3125 : \
					(1 << (6 - (_reg))) * 1000000)

/* Reg value for the next higher ODR */
#define ICM426XX_ODR_REG_UP(_reg)	((_reg) == 15 ? 6 : \
					(_reg) == 7 ? 15 : \
					(_reg) - 1)

/*
 * Register addresses are virtual address on 16 bits.
 * MSB is coding register bank and LSB real register address.
 * ex: bank 4, register 1F => 0x041F
 */
#define ICM426XX_REG_DEVICE_CONFIG	0x0011
#define ICM426XX_SOFT_RESET_CONFIG	BIT(0)

enum icm426xx_slew_rate {
	ICM426XX_SLEW_RATE_20NS_60NS,
	ICM426XX_SLEW_RATE_12NS_36NS,
	ICM426XX_SLEW_RATE_6NS_18NS,
	ICM426XX_SLEW_RATE_4NS_12NS,
	ICM426XX_SLEW_RATE_2NS_6NS,
	ICM426XX_SLEW_RATE_INF_2NS,
};
#define ICM426XX_REG_DRIVE_CONFIG	0x0013
#define ICM426XX_DRIVE_CONFIG_MASK	GENMASK(5, 0)
#define ICM426XX_I2C_SLEW_RATE(_s)	(((_s) & 0x07) << 3)
#define ICM426XX_SPI_SLEW_RATE(_s)	((_s) & 0x07)

/* default int configuration is pulsed mode, open drain, and active low */
#define ICM426XX_REG_INT_CONFIG		0x0014
#define ICM426XX_INT2_LATCHED		BIT(5)
#define ICM426XX_INT2_PUSH_PULL		BIT(4)
#define ICM426XX_INT2_ACTIVE_HIGH	BIT(3)
#define ICM426XX_INT1_LATCHED		BIT(2)
#define ICM426XX_INT1_PUSH_PULL		BIT(1)
#define ICM426XX_INT1_ACTIVE_HIGH	BIT(0)

#define ICM426XX_REG_FIFO_CONFIG	0x0016
#define ICM426XX_FIFO_MODE_BYPASS	(0x00 << 6)
#define ICM426XX_FIFO_MODE_STREAM	(0x01 << 6)
#define ICM426XX_FIFO_MODE_STOP_FULL	(0x02 << 6)

/* data are 16 bits */
#define ICM426XX_REG_TEMP_DATA		0x001D
/* X + Y + Z: 3 * 16 bits */
#define ICM426XX_REG_ACCEL_DATA_XYZ	0x001F
#define ICM426XX_REG_GYRO_DATA_XYZ	0x0025

#define ICM426XX_INVALID_DATA		-32768

#define ICM426XX_REG_INT_STATUS		0x002D
#define ICM426XX_UI_FSYNC_INT		BIT(6)
#define ICM426XX_PLL_RDY_INT		BIT(5)
#define ICM426XX_RESET_DONE_INT		BIT(4)
#define ICM426XX_DATA_RDY_INT		BIT(3)
#define ICM426XX_FIFO_THS_INT		BIT(2)
#define ICM426XX_FIFO_FULL_INT		BIT(1)
#define ICM426XX_AGC_RDY_INT		BIT(0)

/* FIFO count is 16 bits */
#define ICM426XX_REG_FIFO_COUNT		0x002E
#define ICM426XX_REG_FIFO_DATA		0x0030

#define ICM426XX_REG_SIGNAL_PATH_RESET	0x004B
#define ICM426XX_ABORT_AND_RESET	BIT(3)
#define ICM426XX_TMST_STROBE		BIT(2)
#define ICM426XX_FIFO_FLUSH		BIT(1)

#define ICM426XX_REG_INTF_CONFIG0	0x004C
#define ICM426XX_DATA_CONF_MASK		GENMASK(7, 4)
#define ICM426XX_FIFO_HOLD_LAST_DATA	BIT(7)
#define ICM426XX_FIFO_COUNT_REC		BIT(6)
#define ICM426XX_FIFO_COUNT_BE		BIT(5)
#define ICM426XX_SENSOR_DATA_BE		BIT(4)
#define ICM426XX_UI_SIFS_CFG_MASK	GENMASK(1, 0)
#define ICM426XX_UI_SIFS_CFG_SPI_DIS	0x02
#define ICM426XX_UI_SIFS_CFG_I2C_DIS	0x03

#define ICM426XX_REG_INTF_CONFIG1	0x004D
#define ICM426XX_ACCEL_LP_CLK_SEL	BIT(3)

enum icm426xx_sensor_mode {
	ICM426XX_MODE_OFF,
	ICM426XX_MODE_STANDBY,
	ICM426XX_MODE_LOW_POWER,
	ICM426XX_MODE_LOW_NOISE,
};
#define ICM426XX_REG_PWR_MGMT0		0x004E
#define ICM426XX_TEMP_DIS		BIT(5)
#define ICM426XX_IDLE			BIT(4)
#define ICM426XX_GYRO_MODE_MASK		GENMASK(3, 2)
#define ICM426XX_GYRO_MODE(_m)		(((_m) & 0x03) << 2)
#define ICM426XX_ACCEL_MODE_MASK	GENMASK(1, 0)
#define ICM426XX_ACCEL_MODE(_m)		((_m) & 0x03)

#define ICM426XX_REG_GYRO_CONFIG0	0x004F
#define ICM426XX_REG_ACCEL_CONFIG0	0x0050
#define ICM426XX_FS_MASK		GENMASK(7, 5)
#define ICM426XX_FS_SEL(_fs)		(((_fs) & 0x07) << 5)
#define ICM426XX_ODR_MASK		GENMASK(3, 0)
#define ICM426XX_ODR(_odr)		((_odr) & 0x0F)

enum icm426xx_filter_bw {
	/* low noise mode */
	ICM426XX_FILTER_BW_ODR_DIV_2 = 0,

	/* low power mode */
	ICM426XX_FILTER_BW_AVG_1X = 1,
	ICM426XX_FILTER_BW_AVG_16X = 6,
};

#define ICM426XX_REG_GYRO_ACCEL_CONFIG0	0x0052
#define ICM426XX_ACCEL_UI_FILT_MASK	GENMASK(7, 4)
#define ICM426XX_ACCEL_UI_FILT_BW(_f)	(((_f) & 0x0F) << 4)
#define ICM426XX_GYRO_UI_FILT_MASK	GENMASK(3, 0)
#define ICM426XX_GYRO_UI_FILT_BW(_f)	((_f) & 0x0F)

#define ICM426XX_REG_FIFO_CONFIG1	0x005F
#define ICM426XX_FIFO_PARTIAL_READ	BIT(6)
#define ICM426XX_FIFO_WM_GT_TH		BIT(5)
#define ICM426XX_FIFO_EN_MASK		GENMASK(3, 0)
#define ICM426XX_FIFO_TMST_FSYNC_EN	BIT(3)
#define ICM426XX_FIFO_TEMP_EN		BIT(2)
#define ICM426XX_FIFO_GYRO_EN		BIT(1)
#define ICM426XX_FIFO_ACCEL_EN		BIT(0)

/* FIFO watermark value is 16 bits little endian */
#define ICM426XX_REG_FIFO_WATERMARK	0x0060

#define ICM426XX_REG_INT_CONFIG1	0x0064
#define ICM426XX_INT_PULSE_DURATION	BIT(6)
#define ICM426XX_INT_TDEASSERT_DIS	BIT(5)
#define ICM426XX_INT_ASYNC_RESET	BIT(4)

#define ICM426XX_REG_INT_SOURCE0	0x0065
#define ICM426XX_UI_FSYNC_INT1_EN	BIT(6)
#define ICM426XX_PLL_RDY_INT1_EN	BIT(5)
#define ICM426XX_RESET_DONE_INT1_EN	BIT(4)
#define ICM426XX_UI_DRDY_INT1_EN	BIT(3)
#define ICM426XX_FIFO_THS_INT1_EN	BIT(2)
#define ICM426XX_FIFO_FULL_INT1_EN	BIT(1)
#define ICM426XX_UI_AGC_RDY_INT1_EN	BIT(0)

#define ICM426XX_REG_INT_SOURCE3	0x0068
#define ICM426XX_UI_FSYNC_INT2_EN	BIT(6)
#define ICM426XX_PLL_RDY_INT2_EN	BIT(5)
#define ICM426XX_RESET_DONE_INT2_EN	BIT(4)
#define ICM426XX_UI_DRDY_INT2_EN	BIT(3)
#define ICM426XX_FIFO_THS_INT2_EN	BIT(2)
#define ICM426XX_FIFO_FULL_INT2_EN	BIT(1)
#define ICM426XX_UI_AGC_RDY_INT2_EN	BIT(0)

#define ICM426XX_REG_WHO_AM_I		0x0075
#define ICM426XX_CHIP_ICM40608		0x39
#define ICM426XX_CHIP_ICM42605		0x42

#define ICM426XX_REG_BANK_SEL		0x0076
#define ICM426XX_BANK_SEL(_b)		((_b) & 0x07)

#define ICM426XX_REG_INTF_CONFIG4	0x017A
#define ICM426XX_I3C_BUS_MODE		BIT(6)
#define ICM426XX_SPI_AP_4WIRE		BIT(1)

#define ICM426XX_REG_INTF_CONFIG5	0x017B
#define ICM426XX_PIN9_FUNC_INT2		(0x00 << 1)
#define ICM426XX_PIN9_FUNC_FSYNC	(0x01 << 1)

#define ICM426XX_REG_INTF_CONFIG6	0x017C
#define ICM426XX_INTF_CONFIG6_MASK	GENMASK(4, 0)
#define ICM426XX_I3C_EN			BIT(4)
#define ICM426XX_I3C_IBI_BYTE_EN	BIT(3)
#define ICM426XX_I3C_IBI_EN		BIT(2)
#define ICM426XX_I3C_DDR_EN		BIT(1)
#define ICM426XX_I3C_SDR_EN		BIT(0)

#define ICM426XX_REG_INT_SOURCE8	0x044F
#define ICM426XX_FSYNC_IBI_EN		BIT(5)
#define ICM426XX_PLL_RDY_IBI_EN		BIT(4)
#define ICM426XX_UI_DRDY_IBI_EN		BIT(3)
#define ICM426XX_FIFO_THS_IBI_EN	BIT(2)
#define ICM426XX_FIFO_FULL_IBI_EN	BIT(1)
#define ICM426XX_AGC_RDY_IBI_EN		BIT(0)

#define ICM426XX_REG_OFFSET_USER0	0x0477
#define ICM426XX_REG_OFFSET_USER1	0x0478
#define ICM426XX_REG_OFFSET_USER2	0x0479
#define ICM426XX_REG_OFFSET_USER3	0x047A
#define ICM426XX_REG_OFFSET_USER4	0x047B
#define ICM426XX_REG_OFFSET_USER5	0x047C
#define ICM426XX_REG_OFFSET_USER6	0x047D
#define ICM426XX_REG_OFFSET_USER7	0x047E
#define ICM426XX_REG_OFFSET_USER8	0x047F

extern const struct accelgyro_drv icm426xx_drv;

void icm426xx_interrupt(enum gpio_signal signal);

#endif /* __CROS_EC_ACCELGYRO_ICM426XX_H */