| /* 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 "driver/accelgyro_bmi260.h" |
| #include "mag_bmm150.h" |
| |
| #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 BIT(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(v) (BMI160_ACC_X_L_G + \ |
| (v) * (BMI260_ACC_X_L_G - BMI160_ACC_X_L_G)) |
| #define BMI_GYR_DATA(v) (BMI160_GYR_X_L_G + \ |
| (v) * (BMI260_GYR_X_L_G - BMI160_GYR_X_L_G)) |
| #define BMI_AUX_DATA(v) (BMI160_MAG_X_L_G + \ |
| (v) * (BMI260_AUX_X_L_G - BMI160_MAG_X_L_G)) |
| |
| #define BMI_FIFO_CONFIG_0(v) (BMI160_FIFO_CONFIG_0 + \ |
| (v) * (BMI260_FIFO_CONFIG_0 - BMI160_FIFO_CONFIG_0)) |
| #define BMI_FIFO_CONFIG_1(v) (BMI160_FIFO_CONFIG_1 + \ |
| (v) * (BMI260_FIFO_CONFIG_1 - BMI160_FIFO_CONFIG_1)) |
| #define BMI_FIFO_SENSOR_EN(v, _sensor) (BMI160_FIFO_SENSOR_EN(_sensor) + \ |
| (v) * (BMI260_FIFO_SENSOR_EN(_sensor) - BMI160_FIFO_SENSOR_EN(_sensor))) |
| |
| #define BMI_TEMPERATURE_0(v) (BMI160_TEMPERATURE_0 + \ |
| (v) * (BMI260_TEMPERATURE_0 - BMI160_TEMPERATURE_0)) |
| #define BMI_INVALID_TEMP 0x8000 |
| |
| #define BMI_STATUS(v) (BMI160_STATUS + \ |
| (v) * (BMI260_STATUS - BMI160_STATUS)) |
| #define BMI_DRDY_OFF(_sensor) (7 - (_sensor)) |
| #define BMI_DRDY_MASK(_sensor) (1 << BMI160_DRDY_OFF(_sensor)) |
| |
| #define BMI_OFFSET_ACC70(v) (BMI160_OFFSET_ACC70 + \ |
| (v) * (BMI260_OFFSET_ACC70 - BMI160_OFFSET_ACC70)) |
| #define BMI_OFFSET_GYR70(v) (BMI160_OFFSET_GYR70 + \ |
| (v) * (BMI260_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(v) (BMI160_OFFSET_EN_GYR98 + \ |
| (v) * (BMI260_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(v) (BMI160_FIFO_LENGTH_0 + \ |
| (v) * (BMI260_FIFO_LENGTH_0 - BMI160_FIFO_LENGTH_0)) |
| #define BMI_FIFO_LENGTH_MASK(v) (BMI160_FIFO_LENGTH_MASK + \ |
| (v) * (BMI260_FIFO_LENGTH_MASK - BMI160_FIFO_LENGTH_MASK)) |
| #define BMI_FIFO_DATA(v) (BMI160_FIFO_DATA + \ |
| (v) * (BMI260_FIFO_DATA - BMI160_FIFO_DATA)) |
| |
| #define BMI_CMD_REG(v) (BMI160_CMD_REG + \ |
| (v) * (BMI260_CMD_REG - BMI160_CMD_REG)) |
| #define BMI_CMD_FIFO_FLUSH 0xb0 |
| |
| #define BMI_ACCEL_RMS_NOISE_100HZ(v) (BMI160_ACCEL_RMS_NOISE_100HZ + \ |
| (v) * (BMI260_ACCEL_RMS_NOISE_100HZ - BMI160_ACCEL_RMS_NOISE_100HZ)) |
| #define BMI_ACCEL_100HZ 100 |
| |
| /* |
| * 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); |
| |
| #ifdef CONFIG_BODY_DETECTION |
| int bmi_get_rms_noise(const struct motion_sensor_t *s); |
| #endif |
| |
| 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 */ |