summaryrefslogtreecommitdiff
path: root/driver/accelgyro_bmi_common.h
blob: 27e4978ab5817b4b45075dca109f694fb4702379 (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
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
/* 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.
 */
/* BMI accelerometer and gyro common definitions for Chrome EC */

#ifndef __CROS_EC_ACCELGYRO_BMI_COMMON_H
#define __CROS_EC_ACCELGYRO_BMI_COMMON_H

#include "accelgyro.h"
#include "driver/accelgyro_bmi160.h"
#include "mag_bmm150.h"

/*
 * The addr field of motion_sensor support both SPI and I2C:
 *
 * +-------------------------------+---+
 * |    7 bit i2c address          | 0 |
 * +-------------------------------+---+
 * Or
 * +-------------------------------+---+
 * |    SPI device ID              | 1 |
 * +-------------------------------+---+
 */
#define BMI_SET_SPI_ADDRESS(_addr) (((_addr) << 1) | 1)
#define BMI_IS_SPI(_addr)        ((_addr) & 1)
#define BMI_SPI_ADDRESS(_addr)   ((_addr) >> 1)
#define BMI_I2C_ADDRESS(_addr)   (_addr)

#define BMI_CONF_REG(_sensor)      (0x40 + 2 * (_sensor))
#define BMI_RANGE_REG(_sensor)     (0x41 + 2 * (_sensor))

#define BMI_ODR_MASK         0x0F
/* odr = 100 / (1 << (8 - reg)) , within limit */
#define BMI_ODR_0_78HZ       0x01
#define BMI_ODR_100HZ        0x08

#define BMI_REG_TO_ODR(_regval) \
	((_regval) < BMI_ODR_100HZ ? 100000 / (1 << (8 - (_regval))) : \
					100000 * (1 << ((_regval) - 8)))
#define BMI_ODR_TO_REG(_odr) \
	((_odr) < 100000 ? (__builtin_clz(100000 / ((_odr) + 1)) - 24) : \
			   (39 - __builtin_clz((_odr) / 100000)))

enum fifo_header {
	BMI_FH_EMPTY = 0x80,
	BMI_FH_SKIP = 0x40,
	BMI_FH_TIME = 0x44,
	BMI_FH_CONFIG = 0x48
};

#define BMI_FH_MODE_MASK     0xc0
#define BMI_FH_PARM_OFFSET       2
#define BMI_FH_PARM_MASK         (0x7 << BMI_FH_PARM_OFFSET)
#define BMI_FH_EXT_MASK      0x03

/* Sensor resolution in number of bits. This sensor has fixed resolution. */
#define BMI_RESOLUTION      16
/* Min and Max sampling frequency in mHz */
#define BMI_ACCEL_MIN_FREQ 12500
#define BMI_ACCEL_MAX_FREQ MOTION_MAX_SENSOR_FREQUENCY(1600000, 100000)
#define BMI_GYRO_MIN_FREQ  25000
#define BMI_GYRO_MAX_FREQ MOTION_MAX_SENSOR_FREQUENCY(3200000, 100000)

enum bmi_running_mode {
	STANDARD_UI_9DOF_FIFO          = 0,
	STANDARD_UI_IMU_FIFO           = 1,
	STANDARD_UI_IMU                = 2,
	STANDARD_UI_ADVANCEPOWERSAVE   = 3,
	ACCEL_PEDOMETER                = 4,
	APPLICATION_HEAD_TRACKING      = 5,
	APPLICATION_NAVIGATION         = 6,
	APPLICATION_REMOTE_CONTROL     = 7,
	APPLICATION_INDOOR_NAVIGATION  = 8,
};

#define BMI_FLAG_SEC_I2C_ENABLED    (1 << 0)
#define BMI_FIFO_FLAG_OFFSET        4
#define BMI_FIFO_ALL_MASK           7

struct bmi_drv_data_t {
	struct accelgyro_saved_data_t saved_data[3];
	uint8_t              flags;
	uint8_t              enabled_activities;
	uint8_t              disabled_activities;
#ifdef CONFIG_MAG_BMI_BMM150
	struct bmm150_private_data compass;
#endif
#ifdef CONFIG_BMI_ORIENTATION_SENSOR
	uint8_t raw_orientation;
	enum motionsensor_orientation orientation;
	enum motionsensor_orientation last_orientation;
#endif

};

#define BMI_GET_DATA(_s) \
	((struct bmi_drv_data_t *)(_s)->drv_data)
#define BMI_GET_SAVED_DATA(_s) \
	(&BMI_GET_DATA(_s)->saved_data[(_s)->type])

#ifdef CONFIG_BMI_ORIENTATION_SENSOR
#define ORIENTATION_CHANGED(_sensor) \
	(BMI_GET_DATA(_sensor)->orientation != \
	BMI_GET_DATA(_sensor)->last_orientation)

#define GET_ORIENTATION(_sensor) \
	(BMI_GET_DATA(_sensor)->orientation)

#define SET_ORIENTATION(_sensor, _val) \
	(BMI_GET_DATA(_sensor)->orientation = _val)

#define SET_ORIENTATION_UPDATED(_sensor) \
	(BMI_GET_DATA(_sensor)->last_orientation = \
	BMI_GET_DATA(_sensor)->orientation)
#endif

#define BMI_ACC_DATA BMI160_ACC_X_L_G
#define BMI_GYR_DATA BMI160_GYR_X_L_G
#define BMI_AUX_DATA BMI160_MAG_X_L_G

#define BMI_FIFO_CONFIG_0 BMI160_FIFO_CONFIG_0
#define BMI_FIFO_CONFIG_1 BMI160_FIFO_CONFIG_1
#define BMI_FIFO_SENSOR_EN(_sensor) BMI160_FIFO_SENSOR_EN(_sensor)

#define BMI_TEMPERATURE_0 BMI160_TEMPERATURE_0
#define BMI_INVALID_TEMP     0x8000

#define BMI_STATUS BMI160_STATUS
#define BMI_DRDY_OFF(_sensor)   (7 - (_sensor))
#define BMI_DRDY_MASK(_sensor)  (1 << BMI160_DRDY_OFF(_sensor))

#define BMI_OFFSET_ACC70 BMI160_OFFSET_ACC70
#define BMI_OFFSET_GYR70 BMI160_OFFSET_GYR70
/*
 * There is some bits in this register that differ between BMI160 and BMI260
 * Only use this macro for gyro offset 9:8 (BMI_OFFSET_EN_GYR98 5:0).
 */
#define BMI_OFFSET_EN_GYR98 BMI160_OFFSET_EN_GYR98
#define BMI_OFFSET_GYR98_MASK     (BIT(6) - 1)
#define BMI_OFFSET_ACC_MULTI_MG   (3900 * 1024)
#define BMI_OFFSET_ACC_DIV_MG     1000000
#define BMI_OFFSET_GYRO_MULTI_MDS (61 * 1024)
#define BMI_OFFSET_GYRO_DIV_MDS   1000

#define BMI_FIFO_LENGTH_0 BMI160_FIFO_LENGTH_0
#define BMI_FIFO_LENGTH_MASK BMI160_FIFO_LENGTH_MASK
#define BMI_FIFO_DATA BMI160_FIFO_DATA

#define BMI_CMD_REG BMI160_CMD_REG
#define BMI_CMD_FIFO_FLUSH 0xb0



/*
 * Struct for pairing an engineering value with the register value for a
 * parameter.
 */
struct bmi_accel_param_pair {
	int val; /* Value in engineering units. */
	int reg_val; /* Corresponding register value. */
};

int bmi_get_xyz_reg(const struct motion_sensor_t *s);

/**
 * @param type   Accel/Gyro
 * @param psize  Size of the table
 *
 * @return       Range table of the type.
 */
const struct bmi_accel_param_pair *bmi_get_range_table(
		const struct motion_sensor_t *s, int *psize);

/**
 * @return reg value that matches the given engineering value passed in.
 * The round_up flag is used to specify whether to round up or down.
 * Note, this function always returns a valid reg value. If the request is
 * outside the range of values, it returns the closest valid reg value.
 */
int bmi_get_reg_val(const int eng_val, const int round_up,
		const struct bmi_accel_param_pair *pairs, const int size);

/**
 * @return engineering value that matches the given reg val
 */
int bmi_get_engineering_val(const int reg_val,
		const struct bmi_accel_param_pair *pairs, const int size);

#ifdef CONFIG_SPI_ACCEL_PORT
int bmi_spi_raw_read(const int addr, const uint8_t reg,
		     uint8_t *data, const int len);
#endif

/**
 * Read 8bit register from accelerometer.
 */
int bmi_read8(const int port, const uint16_t i2c_spi_addr_flags,
	      const int reg, int *data_ptr);

/**
 * Write 8bit register from accelerometer.
 */
int bmi_write8(const int port, const uint16_t i2c_spi_addr_flags,
	       const int reg, int data);

/**
 * Read 16bit register from accelerometer.
 */
int bmi_read16(const int port, const uint16_t i2c_spi_addr_flags,
	       const uint8_t reg, int *data_ptr);

/**
 * Write 16bit register from accelerometer.
 */
int bmi_write16(const int port, const uint16_t i2c_spi_addr_flags,
		const int reg, int data);

/**
 * Read 32bit register from accelerometer.
 */
int bmi_read32(const int port, const uint16_t i2c_spi_addr_flags,
	       const uint8_t reg, int *data_ptr);

/**
 * Read n bytes from accelerometer.
 */
int bmi_read_n(const int port, const uint16_t i2c_spi_addr_flags,
	       const uint8_t reg, uint8_t *data_ptr, const int len);

/**
 * Write n bytes from accelerometer.
 */
int bmi_write_n(const int port, const uint16_t i2c_spi_addr_flags,
		const uint8_t reg, const uint8_t *data_ptr, const int len);

/*
 * Enable/Disable specific bit set of a 8-bit reg.
 */
int bmi_enable_reg8(const struct motion_sensor_t *s,
		    int reg, uint8_t bits, int enable);

/*
 * Set specific bit set to certain value of a 8-bit reg.
 */
int bmi_set_reg8(const struct motion_sensor_t *s, int reg,
		 uint8_t bits, int mask);

/*
 * @s: base sensor.
 * @v: output vector.
 * @input: 6-bits array input.
 */
void bmi_normalize(const struct motion_sensor_t *s, intv3_t v, uint8_t *input);

/*
 * Decode the header from the fifo.
 * Return 0 if we need further processing.
 * Sensor mutex must be held during processing, to protect the fifos.
 *
 * @accel: base sensor
 * @hdr: the header to decode
 * @last_ts: the last timestamp of fifo interrupt.
 * @bp: current pointer in the buffer, updated when processing the header.
 * @ep: pointer to the end of the valid data in the buffer.
 */
int bmi_decode_header(struct motion_sensor_t *accel,
		      enum fifo_header hdr, uint32_t last_ts,
		      uint8_t **bp, uint8_t *ep);
/**
 * Retrieve hardware FIFO from sensor,
 * - put data in Sensor Hub fifo.
 * - update sensor raw_xyz vector with the last information.
 * We put raw data in hub fifo and process data from there.
 * @s: Pointer to sensor data.
 * @last_ts: The last timestamp of fifo interrupt.
 *
 * Read only up to  bmi_buffer. If more reads are needed, we will be called
 * again by the interrupt routine.
 *
 * NOTE: If a new driver supports this function, be sure to add a check
 * for spoof_mode in order to load the sensor stack with the spoofed
 * data.  See accelgyro_bmi260.c::load_fifo for an example.
 */
int bmi_load_fifo(struct motion_sensor_t *s, uint32_t last_ts);

int bmi_set_range(const struct motion_sensor_t *s, int range, int rnd);

int bmi_get_range(const struct motion_sensor_t *s);

int bmi_get_data_rate(const struct motion_sensor_t *s);


int bmi_get_offset(const struct motion_sensor_t *s,
		   int16_t *offset, int16_t *temp);

int bmi_get_resolution(const struct motion_sensor_t *s);

int bmi_set_scale(const struct motion_sensor_t *s,
		  const uint16_t *scale, int16_t temp);

int bmi_get_scale(const struct motion_sensor_t *s,
		  uint16_t *scale, int16_t *temp);

/* Start/Stop the FIFO collecting events */
int bmi_enable_fifo(const struct motion_sensor_t *s, int enable);

/* Read the xyz data of accel/gyro */
int bmi_read(const struct motion_sensor_t *s, intv3_t v);

/* Read temperature of sensor s */
int bmi_read_temp(const struct motion_sensor_t *s, int *temp_ptr);

/* Read temperature of sensor idx */
int bmi_get_sensor_temp(int idx, int *temp_ptr);

/*
 * Get the normalized rate according to input rate and input rnd
 * @rate: input rate
 * @rnd: round up
 * @normalized_rate_ptr: normalized rate pointer for output
 * @reg_val_ptr: pointer to the actual register value of normalized rate for
 *               output.
 */
int bmi_get_normalized_rate(const struct motion_sensor_t *s, int rate, int rnd,
			    int *normalized_rate_ptr, uint8_t *reg_val_ptr);

/* Get the accelerometer offset */
void bmi_accel_get_offset(const struct motion_sensor_t *accel, intv3_t v);

/* Get the gyroscope offset */
void bmi_gyro_get_offset(const struct motion_sensor_t *gyro, intv3_t v);

/* Set the accelerometer offset */
void bmi_set_accel_offset(const struct motion_sensor_t *accel, intv3_t v);

/* Set the gyroscope offset */
void bmi_set_gyro_offset(const struct motion_sensor_t *gyro, intv3_t v,
			 int *val98_ptr);

#endif /* __CROS_EC_ACCELGYRO_BMI_COMMON_H */