summaryrefslogtreecommitdiff
path: root/driver/accelgyro_lsm6dso.h
blob: ccc1fa0e84436f4a1ad0c6b2539175defa422926 (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
/* Copyright 2019 The ChromiumOS Authors
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

/* LSM6DSO Accel and Gyro driver for Chrome EC */

#ifndef __CROS_EC_ACCELGYRO_LSM6DSO_H
#define __CROS_EC_ACCELGYRO_LSM6DSO_H

#include "driver/accelgyro_lsm6dso_public.h"
#include "stm_mems_common.h"

/* Access to embedded sensor hub register bank */
#define LSM6DSO_FUNC_CFG_ACC_ADDR 0x01
#define LSM6DSO_FUNC_CFG_EN 0x80

/* Who Am I */
#define LSM6DSO_WHO_AM_I_REG 0x0f
#define LSM6DSO_WHO_AM_I 0x6c

/* Common defines for Acc and Gyro sensors */
#define LSM6DSO_EN_BIT 0x01
#define LSM6DSO_DIS_BIT 0x00

#define LSM6DSO_GYRO_OUT_X_L_ADDR 0x22
#define LSM6DSO_ACCEL_OUT_X_L_ADDR 0x28

#define LSM6DSO_CTRL1_ADDR 0x10
#define LSM6DSO_CTRL2_ADDR 0x11
#define LSM6DSO_CTRL3_ADDR 0x12
#define LSM6DSO_SW_RESET 0x01
#define LSM6DSO_IF_INC 0x04
#define LSM6DSO_PP_OD 0x10
#define LSM6DSO_H_L_ACTIVE 0x20
#define LSM6DSO_BDU 0x40

#define LSM6DSO_CTRL4_ADDR 0x13
#define LSM6DSO_INT2_ON_INT1_MASK 0x20

#define LSM6DSO_CTRL5_ADDR 0x14
#define LSM6DSO_CTRL6_ADDR 0x15
#define LSM6DSO_CTRL7_ADDR 0x16
#define LSM6DSO_CTRL8_ADDR 0x17
#define LSM6DSO_CTRL9_ADDR 0x18

#define LSM6DSO_CTRL10_ADDR 0x19
#define LSM6DSO_TIMESTAMP_EN 0x20

#define LSM6DSO_STATUS_REG 0x1e

/* Output data rate registers and masks */
#define LSM6DSO_ODR_REG(_sensor) (LSM6DSO_CTRL1_ADDR + (_sensor))
#define LSM6DSO_ODR_MASK 0xf0

/* FIFO decimator registers and bitmask */
#define LSM6DSO_FIFO_CTRL1_ADDR 0x07
#define LSM6DSO_FIFO_CTRL2_ADDR 0x08

#define LSM6DSO_FIFO_CTRL3_ADDR 0x09
#define LSM6DSO_FIFO_ODR_XL_MASK 0x0f
#define LSM6DSO_FIFO_ODR_G_MASK 0xf0

#define LSM6DSO_FIFO_CTRL4_ADDR 0x0a
#define LSM6DSO_FIFO_MODE_MASK 0x07

#define LSM6DSO_INT1_CTRL 0x0d
#define LSM6DSO_INT2_CTRL 0x0e
#define LSM6DSO_INT_FIFO_TH 0x08
#define LSM6DSO_INT_FIFO_OVR 0x10
#define LSM6DSO_INT_FIFO_FULL 0x20

#define LSM6DSO_FIFO_STS1_ADDR 0x3a
#define LSM6DSO_FIFO_STS2_ADDR 0x3b
#define LSM6DSO_FIFO_DIFF_MASK 0x07ff
#define LSM6DSO_FIFO_FULL 0x2000
#define LSM6DSO_FIFO_DATA_OVR 0x4000
#define LSM6DSO_FIFO_WATERMARK 0x8000

/* Out FIFO data register */
#define LSM6DSO_FIFO_DATA_ADDR_TAG 0x78

/* Registers value for supported FIFO mode */
#define LSM6DSO_FIFO_MODE_BYPASS_VAL 0x00
#define LSM6DSO_FIFO_MODE_CONTINUOUS_VAL 0x06

/* Define device available in FIFO pattern */
enum lsm6dso_dev_fifo {
	LSM6DSO_FIFO_DEV_INVALID = -1,
	LSM6DSO_FIFO_DEV_GYRO = 0,
	LSM6DSO_FIFO_DEV_ACCEL,
	LSM6DSO_FIFO_DEV_NUM,
};

/* Define FIFO data pattern, tag and len */
#define LSM6DSO_TAG_SIZE 1
#define LSM6DSO_FIFO_SAMPLE_SIZE (OUT_XYZ_SIZE + LSM6DSO_TAG_SIZE)

enum lsm6dso_tag_fifo {
	LSM6DSO_GYRO_TAG = 0x01,
	LSM6DSO_ACC_TAG = 0x02,
};

struct lsm6dso_fstatus {
	uint16_t len;
	uint16_t pattern;
};

/* ODR reg value from selected data rate in mHz */
#define LSM6DSO_ODR_TO_REG(_odr) (__fls(_odr / LSM6DSO_ODR_MIN_VAL) + 1)

#define LSM6DSO_FIFO_ODR_MASK(_s)                                        \
	(_s->type == MOTIONSENSE_TYPE_ACCEL ? LSM6DSO_FIFO_ODR_XL_MASK : \
					      LSM6DSO_FIFO_ODR_G_MASK)

/* Normalized ODR values from selected data rate in mHz */
#define LSM6DSO_REG_TO_ODR(_reg) (LSM6DSO_ODR_MIN_VAL << (_reg - 1))

/* Full Scale ranges value and gain for Acc */
#define LSM6DSO_FS_LIST_NUM 4

#define LSM6DSO_ACCEL_FS_ADDR 0x10
#define LSM6DSO_ACCEL_FS_MASK 0x0c

#define LSM6DSO_ACCEL_FS_2G_VAL 0x00
#define LSM6DSO_ACCEL_FS_4G_VAL 0x02
#define LSM6DSO_ACCEL_FS_8G_VAL 0x03
#define LSM6DSO_ACCEL_FS_16G_VAL 0x01

#define LSM6DSO_ACCEL_FS_MAX_VAL 16

/* Accel reg value from Full Scale range */
static inline uint8_t lsm6dso_accel_fs_reg(int fs)
{
	uint8_t ret;

	switch (fs) {
	case 2:
		ret = LSM6DSO_ACCEL_FS_2G_VAL;
		break;
	case 16:
		ret = LSM6DSO_ACCEL_FS_16G_VAL;
		break;
	default:
		ret = __fls(fs);
		break;
	}

	return ret;
}

/* Accel normalized FS value from Full Scale */
#define LSM6DSO_ACCEL_NORMALIZE_FS(_fs) (1 << __fls(_fs))

/* Full Scale range value and gain for Gyro */
#define LSM6DSO_GYRO_FS_ADDR 0x11
#define LSM6DSO_GYRO_FS_MASK 0x0c

/* Minimal Gyro range in mDPS */
#define LSM6DSO_GYRO_FS_MIN_VAL_MDPS ((8750 << 15) / 1000)
#define LSM6DSO_GYRO_FS_MAX_REG_VAL 3

/* Gyro reg value for Full Scale selection in DPS */
#define LSM6DSO_GYRO_FS_REG(_fs) \
	__fls(MAX(1, (_fs * 1000) / LSM6DSO_GYRO_FS_MIN_VAL_MDPS))

/* Gyro normalized FS value (in DPS) from Full Scale register */
#define LSM6DSO_GYRO_NORMALIZE_FS(_reg) \
	((LSM6DSO_GYRO_FS_MIN_VAL_MDPS << (_reg)) / 1000)

/* FS register address/mask for Acc/Gyro sensors */
#define LSM6DSO_RANGE_REG(_sensor) (LSM6DSO_ACCEL_FS_ADDR + (_sensor))
#define LSM6DSO_RANGE_MASK 0x0c

/* Status register bit for Acc/Gyro data ready */
enum lsm6dso_status {
	LSM6DSO_STS_DOWN = 0x00,
	LSM6DSO_STS_XLDA_UP = 0x01,
	LSM6DSO_STS_GDA_UP = 0x02
};

/* Status register bitmask for Acc/Gyro data ready */
#define LSM6DSO_STS_XLDA_MASK 0x01
#define LSM6DSO_STS_GDA_MASK 0x02

/* Sensor resolution in number of bits: fixed 16 bit */
#define LSM6DSO_RESOLUTION 16

/* Aggregate private data for all supported sensor (Acc, Gyro) */
struct lsm6dso_data {
	struct stprivate_data st_data[LSM6DSO_FIFO_DEV_NUM];
};

/*
 * Note: The specific number of samples to discard depends on the filters
 * configured for the chip, as well as the ODR being set. For most of our
 * allowed ODRs, 3 should suffice.
 * See: ST's LSM6DSO application notes (AN5192) Tables 12 and 18 for details
 */
#define LSM6DSO_DISCARD_SAMPLES 3

/* Macro to initialize motion_sensors structure */
#define LSM6DSO_ST_DATA(g, type) (&((g).st_data[type]))

extern const struct accelgyro_drv lsm6dso_drv;

void lsm6dso_interrupt(enum gpio_signal signal);

#if defined(CONFIG_ZEPHYR)
#if DT_NODE_EXISTS(DT_ALIAS(lsm6dso_int))
/* Get the motion sensor ID of the LSM6DSO sensor that generates the
 * interrupt. The interrupt is converted to the event and transferred to
 * motion sense task that actually handles the interrupt.
 *
 * Here we use an alias (lsm6dso_int) to get the motion sensor ID. This alias
 * MUST be defined for this driver to work.
 * aliases {
 *   lsm6dso-int = &lid_accel;
 * };
 */
#define CONFIG_ACCEL_LSM6DSO_INT_EVENT \
	TASK_EVENT_MOTION_SENSOR_INTERRUPT(SENSOR_ID(DT_ALIAS(lsm6dso_int)))
#endif
#endif /* CONFIG_ZEPHYR */

#endif /* __CROS_EC_ACCELGYRO_LSM6DSO_H */