diff options
author | Tomasz Michalec <tm@semihalf.com> | 2021-06-22 11:09:31 +0200 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-07-14 21:24:50 +0000 |
commit | 3d41adc1d1d13a76b68f7927caa37315ed90977e (patch) | |
tree | ec679e13f5ec35281fea6e852fa38783ccc5fbad /include | |
parent | 58e9704c8f823bebbf2ae426567dd95a8eef6d50 (diff) | |
download | chrome-ec-3d41adc1d1d13a76b68f7927caa37315ed90977e.tar.gz |
zephyr: Add BMI160 emulator
Add BMI emulator which is emulated device on i2c bus. Emulated
accelerometer and gyroscope properties are defined through device tree,
but they can be changed in runtime through BMI emulator API. It allows
to set custom handlers for write and read messages to emulate more
complex scenarios or malfunctioning device.
BMI emulator is designed to implement support for different BMI models
as an extension to common emulator code.
BUG=b:184856157
BRANCH=none
TEST=none
Signed-off-by: Tomasz Michalec <tm@semihalf.com>
Change-Id: I63e9d3aca98c8923372437f7a66257a4c82817f2
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2977559
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Jeremy Bettis <jbettis@chromium.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/driver/accelgyro_bmi160.h | 394 | ||||
-rw-r--r-- | include/driver/accelgyro_bmi260.h | 324 | ||||
-rw-r--r-- | include/driver/accelgyro_bmi_common.h | 316 | ||||
-rw-r--r-- | include/driver/mag_bmm150.h | 150 |
4 files changed, 1184 insertions, 0 deletions
diff --git a/include/driver/accelgyro_bmi160.h b/include/driver/accelgyro_bmi160.h new file mode 100644 index 0000000000..c916576130 --- /dev/null +++ b/include/driver/accelgyro_bmi160.h @@ -0,0 +1,394 @@ +/* Copyright 2015 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. + */ + +/* BMI160 accelerometer and gyro and BMM150 compass module for Chrome EC */ + +#ifndef __CROS_EC_ACCELGYRO_BMI160_H +#define __CROS_EC_ACCELGYRO_BMI160_H + +#include "accelgyro.h" +#include "driver/accelgyro_bmi160_public.h" +#include "mag_bmm150.h" + +#define BMI160_CHIP_ID 0x00 +#define BMI160_CHIP_ID_MAJOR 0xd1 +#define BMI168_CHIP_ID_MAJOR 0xd2 + +#define BMI160_SPEC_ACC_STARTUP_TIME_MS 10 +#define BMI160_SPEC_GYR_STARTUP_TIME_MS 80 +#define BMI160_SPEC_MAG_STARTUP_TIME_MS 60 + + +#define BMI160_ERR_REG 0x02 +#define BMI160_PMU_STATUS 0x03 +#define BMI160_PMU_MAG_OFFSET 0 +#define BMI160_PMU_GYR_OFFSET 2 +#define BMI160_PMU_ACC_OFFSET 4 +#define BMI160_PMU_SENSOR_STATUS(_sensor_type, _val) \ + (((_val) >> (4 - 2 * (_sensor_type))) & 0x3) +#define BMI160_PMU_SUSPEND 0 +#define BMI160_PMU_NORMAL 1 +#define BMI160_PMU_LOW_POWER 2 +#define BMI160_PMU_FAST_STARTUP 3 + +#define BMI160_MAG_X_L_G 0x04 +#define BMI160_MAG_X_H_G 0x05 +#define BMI160_MAG_Y_L_G 0x06 +#define BMI160_MAG_Y_H_G 0x07 +#define BMI160_MAG_Z_L_G 0x08 +#define BMI160_MAG_Z_H_G 0x09 +#define BMI160_RHALL_L_G 0x0a +#define BMI160_RHALL_H_G 0x0b +#define BMI160_GYR_X_L_G 0x0c +#define BMI160_GYR_X_H_G 0x0d +#define BMI160_GYR_Y_L_G 0x0e +#define BMI160_GYR_Y_H_G 0x0f +#define BMI160_GYR_Z_L_G 0x10 +#define BMI160_GYR_Z_H_G 0x11 +#define BMI160_ACC_X_L_G 0x12 +#define BMI160_ACC_X_H_G 0x13 +#define BMI160_ACC_Y_L_G 0x14 +#define BMI160_ACC_Y_H_G 0x15 +#define BMI160_ACC_Z_L_G 0x16 +#define BMI160_ACC_Z_H_G 0x17 + +#define BMI160_SENSORTIME_0 0x18 +#define BMI160_SENSORTIME_1 0x19 +#define BMI160_SENSORTIME_2 0x1a + +#define BMI160_STATUS 0x1b +#define BMI160_POR_DETECTED BIT(0) +#define BMI160_GYR_SLF_TST BIT(1) +#define BMI160_MAG_MAN_OP BIT(2) +#define BMI160_FOC_RDY BIT(3) +#define BMI160_NVM_RDY BIT(4) +#define BMI160_DRDY_MAG BIT(5) +#define BMI160_DRDY_GYR BIT(6) +#define BMI160_DRDY_ACC BIT(7) +#define BMI160_DRDY_OFF(_sensor) (7 - (_sensor)) +#define BMI160_DRDY_MASK(_sensor) (1 << BMI160_DRDY_OFF(_sensor)) + +/* first 2 bytes are the interrupt reasons, next 2 some qualifier */ +#define BMI160_INT_STATUS_0 0x1c +#define BMI160_STEP_INT BIT(0) +#define BMI160_SIGMOT_INT BIT(1) +#define BMI160_ANYM_INT BIT(2) +#define BMI160_PMU_TRIGGER_INT BIT(3) +#define BMI160_D_TAP_INT BIT(4) +#define BMI160_S_TAP_INT BIT(5) +#define BMI160_ORIENT_INT BIT(6) +#define BMI160_FLAT_INT BIT(7) +#define BMI160_ORIENT_XY_MASK 0x30 +#define BMI160_ORIENT_PORTRAIT (0 << 4) +#define BMI160_ORIENT_PORTRAIT_INVERT BIT(4) +#define BMI160_ORIENT_LANDSCAPE (2 << 4) +#define BMI160_ORIENT_LANDSCAPE_INVERT (3 << 4) + + +#define BMI160_INT_STATUS_1 0x1d +#define BMI160_HIGHG_INT (1 << (2 + 8)) +#define BMI160_LOWG_INT (1 << (3 + 8)) +#define BMI160_DRDY_INT (1 << (4 + 8)) +#define BMI160_FFULL_INT (1 << (5 + 8)) +#define BMI160_FWM_INT (1 << (6 + 8)) +#define BMI160_NOMO_INT (1 << (7 + 8)) + +#define BMI160_INT_MASK 0xFFFF + +#define BMI160_INT_STATUS_2 0x1e +#define BMI160_INT_STATUS_3 0x1f +#define BMI160_FIRST_X (1 << (0 + 16)) +#define BMI160_FIRST_Y (1 << (1 + 16)) +#define BMI160_FIRST_Z (1 << (2 + 16)) +#define BMI160_SIGN (1 << (3 + 16)) +#define BMI160_ANYM_OFFSET 0 +#define BMI160_TAP_OFFSET 4 +#define BMI160_HIGH_OFFSET 8 +#define BMI160_INT_INFO(_type, _data) \ +(CONCAT2(BMI160_, _data) << CONCAT3(BMI160_, _type, _OFFSET)) + +#define BMI160_ORIENT_Z (1 << (6 + 24)) +#define BMI160_FLAT (1 << (7 + 24)) + +#define BMI160_TEMPERATURE_0 0x20 +#define BMI160_TEMPERATURE_1 0x21 + + +#define BMI160_FIFO_LENGTH_0 0x22 +#define BMI160_FIFO_LENGTH_1 0x23 +#define BMI160_FIFO_LENGTH_MASK (BIT(11) - 1) +#define BMI160_FIFO_DATA 0x24 + +#define BMI160_ACC_CONF 0x40 +#define BMI160_ACC_BW_OFFSET 4 +#define BMI160_ACC_BW_MASK (0x7 << BMI160_ACC_BW_OFFSET) + +#define BMI160_ACC_RANGE 0x41 +#define BMI160_GSEL_2G 0x03 +#define BMI160_GSEL_4G 0x05 +#define BMI160_GSEL_8G 0x08 +#define BMI160_GSEL_16G 0x0c + +#define BMI160_GYR_CONF 0x42 +#define BMI160_GYR_BW_OFFSET 4 +#define BMI160_GYR_BW_MASK (0x3 << BMI160_GYR_BW_OFFSET) + +#define BMI160_GYR_RANGE 0x43 +#define BMI160_DPS_SEL_2000 0x00 +#define BMI160_DPS_SEL_1000 0x01 +#define BMI160_DPS_SEL_500 0x02 +#define BMI160_DPS_SEL_250 0x03 +#define BMI160_DPS_SEL_125 0x04 + +#define BMI160_MAG_CONF 0x44 + +#define BMI160_FIFO_DOWNS 0x45 +#define BMI160_FIFO_CONFIG_0 0x46 +#define BMI160_FIFO_CONFIG_1 0x47 +#define BMI160_FIFO_TAG_TIME_EN BIT(1) +#define BMI160_FIFO_TAG_INT2_EN BIT(2) +#define BMI160_FIFO_TAG_INT1_EN BIT(3) +#define BMI160_FIFO_HEADER_EN BIT(4) +#define BMI160_FIFO_MAG_EN BIT(5) +#define BMI160_FIFO_ACC_EN BIT(6) +#define BMI160_FIFO_GYR_EN BIT(7) +#define BMI160_FIFO_TARG_INT(_i) CONCAT3(BMI160_FIFO_TAG_INT, _i, _EN) +#define BMI160_FIFO_SENSOR_EN(_sensor) \ + ((_sensor) == MOTIONSENSE_TYPE_ACCEL ? BMI160_FIFO_ACC_EN : \ + ((_sensor) == MOTIONSENSE_TYPE_GYRO ? BMI160_FIFO_GYR_EN : \ + BMI160_FIFO_MAG_EN)) + +#define BMI160_MAG_IF_0 0x4b +#define BMI160_MAG_I2C_ADDRESS BMI160_MAG_IF_0 +#define BMI160_MAG_IF_1 0x4c +#define BMI160_MAG_I2C_CONTROL BMI160_MAG_IF_1 +#define BMI160_MAG_READ_BURST_MASK 3 +#define BMI160_MAG_READ_BURST_1 0 +#define BMI160_MAG_READ_BURST_2 1 +#define BMI160_MAG_READ_BURST_6 2 +#define BMI160_MAG_READ_BURST_8 3 +#define BMI160_MAG_OFFSET_OFF 3 +#define BMI160_MAG_OFFSET_MASK (0xf << BMI160_MAG_OFFSET_OFF) +#define BMI160_MAG_MANUAL_EN BIT(7) + +#define BMI160_MAG_IF_2 0x4d +#define BMI160_MAG_I2C_READ_ADDR BMI160_MAG_IF_2 +#define BMI160_MAG_IF_3 0x4e +#define BMI160_MAG_I2C_WRITE_ADDR BMI160_MAG_IF_3 +#define BMI160_MAG_IF_4 0x4f +#define BMI160_MAG_I2C_WRITE_DATA BMI160_MAG_IF_4 +#define BMI160_MAG_I2C_READ_DATA BMI160_MAG_X_L_G + +#define BMI160_INT_EN_0 0x50 +#define BMI160_INT_ANYMO_X_EN BIT(0) +#define BMI160_INT_ANYMO_Y_EN BIT(1) +#define BMI160_INT_ANYMO_Z_EN BIT(2) +#define BMI160_INT_D_TAP_EN BIT(4) +#define BMI160_INT_S_TAP_EN BIT(5) +#define BMI160_INT_ORIENT_EN BIT(6) +#define BMI160_INT_FLAT_EN BIT(7) +#define BMI160_INT_EN_1 0x51 +#define BMI160_INT_HIGHG_X_EN BIT(0) +#define BMI160_INT_HIGHG_Y_EN BIT(1) +#define BMI160_INT_HIGHG_Z_EN BIT(2) +#define BMI160_INT_LOW_EN BIT(3) +#define BMI160_INT_DRDY_EN BIT(4) +#define BMI160_INT_FFUL_EN BIT(5) +#define BMI160_INT_FWM_EN BIT(6) +#define BMI160_INT_EN_2 0x52 +#define BMI160_INT_NOMOX_EN BIT(0) +#define BMI160_INT_NOMOY_EN BIT(1) +#define BMI160_INT_NOMOZ_EN BIT(2) +#define BMI160_INT_STEP_DET_EN BIT(3) + +#define BMI160_INT_OUT_CTRL 0x53 +#define BMI160_INT_EDGE_CTRL BIT(0) +#define BMI160_INT_LVL_CTRL BIT(1) +#define BMI160_INT_OD BIT(2) +#define BMI160_INT_OUTPUT_EN BIT(3) +#define BMI160_INT1_CTRL_OFFSET 0 +#define BMI160_INT2_CTRL_OFFSET 4 +#define BMI160_INT_CTRL(_i, _bit) \ +(CONCAT2(BMI160_INT_, _bit) << CONCAT3(BMI160_INT, _i, _CTRL_OFFSET)) + +#define BMI160_INT_LATCH 0x54 +#define BMI160_INT1_INPUT_EN BIT(4) +#define BMI160_INT2_INPUT_EN BIT(5) +#define BMI160_LATCH_MASK 0xf +#define BMI160_LATCH_NONE 0 +#define BMI160_LATCH_5MS 5 +#define BMI160_LATCH_FOREVER 0xf + +#define BMI160_INT_MAP_0 0x55 +#define BMI160_INT_LOWG_STEP BIT(0) +#define BMI160_INT_HIGHG BIT(1) +#define BMI160_INT_ANYMOTION BIT(2) +#define BMI160_INT_NOMOTION BIT(3) +#define BMI160_INT_D_TAP BIT(4) +#define BMI160_INT_S_TAP BIT(5) +#define BMI160_INT_ORIENT BIT(6) +#define BMI160_INT_FLAT BIT(7) + +#define BMI160_INT_MAP_1 0x56 +#define BMI160_INT_PMU_TRIG BIT(0) +#define BMI160_INT_FFULL BIT(1) +#define BMI160_INT_FWM BIT(2) +#define BMI160_INT_DRDY BIT(3) +#define BMI160_INT1_MAP_OFFSET 4 +#define BMI160_INT2_MAP_OFFSET 0 +#define BMI160_INT_MAP(_i, _bit) \ +(CONCAT2(BMI160_INT_, _bit) << CONCAT3(BMI160_INT, _i, _MAP_OFFSET)) +#define BMI160_INT_FIFO_MAP BMI160_INT_MAP_1 + +#define BMI160_INT_MAP_2 0x57 + +#define BMI160_INT_MAP_INT_1 BMI160_INT_MAP_0 +#define BMI160_INT_MAP_INT_2 BMI160_INT_MAP_2 +#define BMI160_INT_MAP_REG(_i) CONCAT2(BMI160_INT_MAP_INT_, _i) + +#define BMI160_INT_DATA_0 0x58 +#define BMI160_INT_DATA_1 0x59 + +#define BMI160_INT_LOW_HIGH_0 0x5a +#define BMI160_INT_LOW_HIGH_1 0x5b +#define BMI160_INT_LOW_HIGH_2 0x5c +#define BMI160_INT_LOW_HIGH_3 0x5d +#define BMI160_INT_LOW_HIGH_4 0x5e + +#define BMI160_INT_MOTION_0 0x5f +#define BMI160_INT_MOTION_1 0x60 +/* + * The formula is defined in 2.11.25 (any motion interrupt [1]). + * + * if we want threshold at a (in mg), the register should be x, where + * x * 7.81mg = a, assuming a range of 4G, which is + * x * 4 * 1.953 = a so + * x = a * 1000 / range * 1953 + */ +#define BMI160_MOTION_TH(_s, _mg) \ + (MIN(((_mg) * 1000) / ((_s)->current_range * 1953), 0xff)) +#define BMI160_INT_MOTION_2 0x61 +#define BMI160_INT_MOTION_3 0x62 +#define BMI160_MOTION_NO_MOT_SEL BIT(0) +#define BMI160_MOTION_SIG_MOT_SEL BIT(1) +#define BMI160_MOTION_SKIP_OFF 2 +#define BMI160_MOTION_SKIP_MASK 0x3 +#define BMI160_MOTION_SKIP_TIME(_ms) \ + (MIN(__fls((_ms) / 1500), BMI160_MOTION_SKIP_MASK)) +#define BMI160_MOTION_PROOF_OFF 4 +#define BMI160_MOTION_PROOF_MASK 0x3 +#define BMI160_MOTION_PROOF_TIME(_ms) \ + (MIN(__fls((_ms) / 250), BMI160_MOTION_PROOF_MASK)) + +#define BMI160_INT_TAP_0 0x63 +#define BMI160_TAP_DUR(_s, _ms) \ + ((_ms) <= 250 ? MAX((_ms), 50) / 50 - 1 : \ + (_ms) <= 500 ? 4 + ((_ms) - 250) / 125 : \ + (_ms) < 700 ? 6 : 7) + +#define BMI160_INT_TAP_1 0x64 +#define BMI160_TAP_TH(_s, _mg) \ + (MIN(((_mg) * 1000) / ((_s)->current_range * 31250), 0x1f)) + +#define BMI160_INT_ORIENT_0 0x65 + +/* No hysterisis, theta block, int on slope > 0.2 or axis > 1.5, symmetrical */ +#define BMI160_INT_ORIENT_0_INIT_VAL 0x48 + +#define BMI160_INT_ORIENT_1 0x66 + +/* no axes remap, no int on up/down, no blocking angle */ +#define BMI160_INT_ORIENT_1_INIT_VAL 0x00 + +#define BMI160_INT_FLAT_0 0x67 +#define BMI160_INT_FLAT_1 0x68 + +#define BMI160_FOC_CONF 0x69 +#define BMI160_FOC_GYRO_EN BIT(6) +#define BMI160_FOC_ACC_PLUS_1G 1 +#define BMI160_FOC_ACC_MINUS_1G 2 +#define BMI160_FOC_ACC_0G 3 +#define BMI160_FOC_ACC_Z_OFFSET 0 +#define BMI160_FOC_ACC_Y_OFFSET 2 +#define BMI160_FOC_ACC_X_OFFSET 4 + +#define BMI160_CONF 0x6a +#define BMI160_IF_CONF 0x6b +#define BMI160_IF_MODE_OFF 4 +#define BMI160_IF_MODE_MASK 3 +#define BMI160_IF_MODE_AUTO_OFF 0 +#define BMI160_IF_MODE_I2C_IOS 1 +#define BMI160_IF_MODE_AUTO_I2C 2 + +#define BMI160_PMU_TRIGGER 0x6c +#define BMI160_SELF_TEST 0x6d + +#define BMI160_NV_CONF 0x70 + +#define BMI160_OFFSET_ACC70 0x71 +#define BMI160_OFFSET_GYR70 0x74 +#define BMI160_OFFSET_EN_GYR98 0x77 +#define BMI160_OFFSET_ACC_EN BIT(6) +#define BMI160_OFFSET_GYRO_EN BIT(7) + +#define BMI160_STEP_CNT_0 0x78 +#define BMI160_STEP_CNT_1 0x79 +#define BMI160_STEP_CONF_0 0x7a +#define BMI160_STEP_CONF_1 0x7b + +#define BMI160_CMD_REG 0x7e +#define BMI160_CMD_SOFT_RESET 0xb6 +#define BMI160_CMD_NOOP 0x00 +#define BMI160_CMD_START_FOC 0x03 +#define BMI160_CMD_ACC_MODE_OFFSET 0x10 +#define BMI160_CMD_ACC_MODE_SUSP 0x10 +#define BMI160_CMD_ACC_MODE_NORMAL 0x11 +#define BMI160_CMD_ACC_MODE_LOWPOWER 0x12 +#define BMI160_CMD_GYR_MODE_SUSP 0x14 +#define BMI160_CMD_GYR_MODE_NORMAL 0x15 +#define BMI160_CMD_GYR_MODE_FAST_STARTUP 0x17 +#define BMI160_CMD_MAG_MODE_SUSP 0x18 +#define BMI160_CMD_MAG_MODE_NORMAL 0x19 +#define BMI160_CMD_MAG_MODE_LOWPOWER 0x1a +#define BMI160_CMD_MODE_SUSPEND(_sensor_type) \ + (BMI160_CMD_ACC_MODE_OFFSET | (_sensor_type) << 2 | BMI160_PMU_SUSPEND) +#define BMI160_CMD_MODE_NORMAL(_sensor_type) \ + (BMI160_CMD_ACC_MODE_OFFSET | (_sensor_type) << 2 | BMI160_PMU_NORMAL) + +#define BMI160_CMD_FIFO_FLUSH 0xb0 +#define BMI160_CMD_INT_RESET 0xb1 +#define BMI160_CMD_SOFT_RESET 0xb6 +#define BMI160_CMD_EXT_MODE_EN_B0 0x37 +#define BMI160_CMD_EXT_MODE_EN_B1 0x9a +#define BMI160_CMD_EXT_MODE_EN_B2 0xc0 + +#define BMI160_CMD_EXT_MODE_ADDR 0x7f +#define BMI160_CMD_PAGING_EN BIT(7) +#define BMI160_CMD_TARGET_PAGE BIT(4) +#define BMI160_COM_C_TRIM_ADDR 0x85 +#define BMI160_COM_C_TRIM (3 << 4) + +#define BMI160_CMD_TGT_PAGE 0 +#define BMI160_CMD_TGT_PAGE_COM 1 +#define BMI160_CMD_TGT_PAGE_ACC 2 +#define BMI160_CMD_TGT_PAGE_GYR 3 + +#define BMI160_FF_FRAME_LEN_TS 4 +#define BMI160_FF_DATA_LEN_ACC 6 +#define BMI160_FF_DATA_LEN_GYR 6 +#define BMI160_FF_DATA_LEN_MAG 8 + +/* Root mean square noise of 100 Hz accelerometer, units: ug */ +#define BMI160_ACCEL_RMS_NOISE_100HZ 1300 + +#ifdef CONFIG_BMI_SEC_I2C +/* Functions to access the secondary device through the accel/gyro. */ +int bmi160_sec_raw_read8(const int port, const uint16_t addr_flags, + const uint8_t reg, int *data_ptr); +int bmi160_sec_raw_write8(const int port, const uint16_t addr_flags, + const uint8_t reg, int data); +#endif + +#endif /* __CROS_EC_ACCELGYRO_BMI160_H */ diff --git a/include/driver/accelgyro_bmi260.h b/include/driver/accelgyro_bmi260.h new file mode 100644 index 0000000000..9f39dd568a --- /dev/null +++ b/include/driver/accelgyro_bmi260.h @@ -0,0 +1,324 @@ +/* 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. + */ + +/* BMI260 accelerometer and gyro for Chrome EC */ + +#ifndef __CROS_EC_ACCELGYRO_BMI260_H +#define __CROS_EC_ACCELGYRO_BMI260_H + +#include "accelgyro.h" +#include "common.h" +#include "mag_bmm150.h" +#include "driver/accelgyro_bmi260_public.h" + +#define BMI260_CHIP_ID 0x00 +#define BMI260_CHIP_ID_MAJOR 0x27 + +#define BMI260_ERR_REG 0x02 + +#define BMI260_STATUS 0x03 +#define BMI260_AUX_BUSY BIT(2) +#define BMI260_CMD_RDY BIT(4) +#define BMI260_DRDY_AUX BIT(5) +#define BMI260_DRDY_GYR BIT(6) +#define BMI260_DRDY_ACC BIT(7) +#define BMI260_DRDY_OFF(_sensor) (7 - (_sensor)) +#define BMI260_DRDY_MASK(_sensor) (1 << BMI260_DRDY_OFF(_sensor)) + +#define BMI260_AUX_X_L_G 0x04 +#define BMI260_AUX_X_H_G 0x05 +#define BMI260_AUX_Y_L_G 0x06 +#define BMI260_AUX_Y_H_G 0x07 +#define BMI260_AUX_Z_L_G 0x08 +#define BMI260_AUX_Z_H_G 0x09 +#define BMI260_AUX_R_L_G 0x0a +#define BMI260_AUX_R_H_G 0x0b +#define BMI260_ACC_X_L_G 0x0c +#define BMI260_ACC_X_H_G 0x0d +#define BMI260_ACC_Y_L_G 0x0e +#define BMI260_ACC_Y_H_G 0x0f +#define BMI260_ACC_Z_L_G 0x10 +#define BMI260_ACC_Z_H_G 0x11 +#define BMI260_GYR_X_L_G 0x12 +#define BMI260_GYR_X_H_G 0x13 +#define BMI260_GYR_Y_L_G 0x14 +#define BMI260_GYR_Y_H_G 0x15 +#define BMI260_GYR_Z_L_G 0x16 +#define BMI260_GYR_Z_H_G 0x17 + +#define BMI260_SENSORTIME_0 0x18 +#define BMI260_SENSORTIME_1 0x19 +#define BMI260_SENSORTIME_2 0x1a + +#define BMI260_EVENT 0x1b + +/* 2 bytes interrupt reasons*/ +#define BMI260_INT_STATUS_0 0x1c +#define BMI260_SIG_MOTION_OUT BIT(0) +#define BMI260_STEP_COUNTER_OUT BIT(1) +#define BMI260_HIGH_LOW_G_OUT BIT(2) +#define BMI260_TAP_OUT BIT(3) +#define BMI260_FLAT_OUT BIT(4) +#define BMI260_NO_MOTION_OUT BIT(5) +#define BMI260_ANY_MOTION_OUT BIT(6) +#define BMI260_ORIENTATION_OUT BIT(7) + +#define BMI260_INT_STATUS_1 0x1d +#define BMI260_FFULL_INT BIT(0 + 8) +#define BMI260_FWM_INT BIT(1 + 8) +#define BMI260_ERR_INT BIT(2 + 8) +#define BMI260_AUX_DRDY_INT BIT(5 + 8) +#define BMI260_GYR_DRDY_INT BIT(6 + 8) +#define BMI260_ACC_DRDY_INT BIT(7 + 8) + +#define BMI260_INT_MASK 0xFFFF + +#define BMI260_SC_OUT_0 0x1e +#define BMI260_SC_OUT_1 0x1f + +#define BMI260_ORIENT_ACT 0x20 + +#define BMI260_INTERNAL_STATUS 0X21 +#define BMI260_MESSAGE_MASK 0xf +#define BMI260_NOT_INIT 0x00 +#define BMI260_INIT_OK 0x01 +#define BMI260_INIT_ERR 0x02 +#define BMI260_DRV_ERR 0x03 +#define BMI260_SNS_STOP 0x04 +#define BMI260_NVM_ERROR 0x05 +#define BMI260_START_UP_ERROR 0x06 +#define BMI260_COMPAT_ERROR 0x07 + +#define BMI260_TEMPERATURE_0 0x22 +#define BMI260_TEMPERATURE_1 0x23 + +#define BMI260_FIFO_LENGTH_0 0x24 +#define BMI260_FIFO_LENGTH_1 0x25 +#define BMI260_FIFO_LENGTH_MASK (BIT(14) - 1) +#define BMI260_FIFO_DATA 0x26 + +#define BMI260_FEAT_PAGE 0x2f +/* + * The register of feature page should be read/write as 16-bit register + * Otherwise, there can be invalid data + */ +/* Features page 0 */ +#define BMI260_ORIENT_OUT 0x36 +#define BMI260_ORIENT_OUT_PORTRAIT_LANDSCAPE_MASK 3 +#define BMI260_ORIENT_PORTRAIT 0x0 +#define BMI260_ORIENT_LANDSCAPE 0x1 +#define BMI260_ORIENT_PORTRAIT_INVERT 0x2 +#define BMI260_ORIENT_LANDSCAPE_INVERT 0x3 + +/* Features page 1 */ +#define BMI260_GEN_SET_1 0x34 +#define BMI260_GYR_SELF_OFF BIT(9) + +#define BMI260_TAP_1 0x3e +#define BMI260_TAP_1_EN BIT(0) +#define BMI260_TAP_1_SENSITIVITY_OFFSET 1 +#define BMI260_TAP_1_SENSITIVITY_MASK \ + (0x7 << BMI260_TAP_1_SENSITIVITY_OFFSET) + +/* Features page 2 */ +#define BMI260_ORIENT_1 0x30 +#define BMI260_ORIENT_1_EN BIT(0) +#define BMI260_ORIENT_1_UD_EN BIT(1) +#define BMI260_ORIENT_1_MODE_OFFSET 2 +#define BMI260_ORIENT_1_MODE_MASK (0x3 << BMI260_ORIENT_1_MODE_OFFSET) +#define BMI260_ORIENT_1_BLOCK_OFFSET 4 +#define BMI260_ORIENT_1_BLOCK_MASK (0x3 << BMI260_ORIENT_1_BLOCK_OFFSET) +#define BMI260_ORIENT_1_THETA_OFFSET 6 +#define BMI260_ORIENT_1_THETA_MASK \ + ((BIT(6) - 1) << BMI260_ORIENT_1_THETA_OFFSET) + +#define BMI260_ORIENT_2 0x32 +/* hysteresis(10...0) range is 0~1g, default is 128 (0.0625g) */ +#define BMI260_ORIENT_2_HYSTERESIS_MASK (BIT(11) - 1) + +#define BMI260_ACC_CONF 0x40 +#define BMI260_ACC_BW_OFFSET 4 +#define BMI260_ACC_BW_MASK (0x7 << BMI260_ACC_BW_OFFSET) +#define BMI260_FILTER_PERF BIT(7) +#define BMI260_ULP 0x0 +#define BMI260_HP 0x1 + +#define BMI260_ACC_RANGE 0x41 +#define BMI260_GSEL_2G 0x00 +#define BMI260_GSEL_4G 0x01 +#define BMI260_GSEL_8G 0x02 +#define BMI260_GSEL_16G 0x03 + +/* The max positvie value of accel data is 0x7FFF, equal to range(g) */ +/* So, in order to get +1g, divide the 0x7FFF by range */ +#define BMI260_ACC_DATA_PLUS_1G(range) (0x7FFF / (range)) +#define BMI260_ACC_DATA_MINUS_1G(range) (-BMI260_ACC_DATA_PLUS_1G(range)) + +#define BMI260_GYR_CONF 0x42 +#define BMI260_GYR_BW_OFFSET 4 +#define BMI260_GYR_BW_MASK (0x3 << BMI260_GYR_BW_OFFSET) +#define BMI260_GYR_NOISE_PERF BIT(6) + +#define BMI260_GYR_RANGE 0x43 +#define BMI260_DPS_SEL_2000 0x00 +#define BMI260_DPS_SEL_1000 0x01 +#define BMI260_DPS_SEL_500 0x02 +#define BMI260_DPS_SEL_250 0x03 +#define BMI260_DPS_SEL_125 0x04 + +#define BMI260_AUX_CONF 0x44 + +#define BMI260_FIFO_DOWNS 0x45 + +#define BMI260_FIFO_WTM_0 0x46 +#define BMI260_FIFO_WTM_1 0x47 + +#define BMI260_FIFO_CONFIG_0 0x48 +#define BMI260_FIFO_STOP_ON_FULL BIT(0) +#define BMI260_FIFO_TIME_EN BIT(1) + +#define BMI260_FIFO_CONFIG_1 0x49 +#define BMI260_FIFO_TAG_INT1_EN_OFFSET 0 +#define BMI260_FIFO_TAG_INT1_EN_MASK (0x3 << BMI260_FIFO_TAG_INT1_EN_OFFSET) +#define BMI260_FIFO_TAG_INT2_EN_OFFSET 2 +#define BMI260_FIFO_TAG_INT2_EN_MASK (0x3 << BMI260_FIFO_TAG_INT2_EN_OFFSET) +#define BMI260_FIFO_TAG_INT_EDGE 0x0 +#define BMI260_FIFO_TAG_INT_LEVEL 0x1 +#define BMI260_FIFO_TAG_ACC_SAT 0x2 +#define BMI260_FIFO_TAG_GYR_SAT 0x3 +#define BMI260_FIFO_HEADER_EN BIT(4) +#define BMI260_FIFO_AUX_EN BIT(5) +#define BMI260_FIFO_ACC_EN BIT(6) +#define BMI260_FIFO_GYR_EN BIT(7) +#define BMI260_FIFO_SENSOR_EN(_sensor) \ + ((_sensor) == MOTIONSENSE_TYPE_ACCEL ? BMI260_FIFO_ACC_EN : \ + ((_sensor) == MOTIONSENSE_TYPE_GYRO ? BMI260_FIFO_GYR_EN : \ + BMI260_FIFO_AUX_EN)) + +#define BMI260_AUX_DEV_ID 0x4b +#define BMI260_AUX_I2C_ADDRESS BMI260_AUX_DEV_ID + +#define BMI260_AUX_IF_CONF 0x4c +#define BMI260_AUX_I2C_CONTROL BMI260_AUX_IF_CONF +#define BMI260_AUX_READ_BURST_MASK 3 +#define BMI260_AUX_MAN_READ_BURST_OFF 2 +#define BMI260_AUX_MAN_READ_BURST_MASK (0x3 << BMI280_AUX_MAN_READ_BURST_OFF) +#define BMI260_AUX_READ_BURST_1 0 +#define BMI260_AUX_READ_BURST_2 1 +#define BMI260_AUX_READ_BURST_6 2 +#define BMI260_AUX_READ_BURST_8 3 +#define BMI260_AUX_FCU_WRITE_EN BIT(6) +#define BMI260_AUX_MANUAL_EN BIT(7) + +#define BMI260_AUX_RD_ADDR 0x4d +#define BMI260_AUX_I2C_READ_ADDR BMI260_AUX_RD_ADDR +#define BMI260_AUX_WR_ADDR 0x4e +#define BMI260_AUX_I2C_WRITE_ADDR BMI260_AUX_WR_ADDR +#define BMI260_AUX_WR_DATA 0x4f +#define BMI260_AUX_I2C_WRITE_DATA BMI260_AUX_WR_DATA +#define BMI260_AUX_I2C_READ_DATA BMI260_AUX_X_L_G + +#define BMI260_ERR_REG_MSK 0x52 +#define BMI260_FATAL_ERR BIT(0) +#define BMI260_INTERNAL_ERR_OFF 1 +#define BMI260_INTERNAL_ERR_MASK (0xf << BMI260_INTERNAL_ERR_OFF) +#define BMI260_FIFO_ERR BIT(6) +#define BMI260_AUX_ERR BIT(7) + +#define BMI260_INT1_IO_CTRL 0x53 +#define BMI260_INT1_LVL BIT(1) +#define BMI260_INT1_OD BIT(2) +#define BMI260_INT1_OUTPUT_EN BIT(3) +#define BMI260_INT1_INPUT_EN BIT(4) + +#define BMI260_INT2_IO_CTRL 0x54 +#define BMI260_INT2_LVL BIT(1) +#define BMI260_INT2_OD BIT(2) +#define BMI260_INT2_OUTPUT_EN BIT(3) +#define BMI260_INT2_INPUT_EN BIT(4) + +#define BMI260_INT_LATCH 0x55 +#define BMI260_INT_LATCH_EN BIT(0) + +#define BMI260_INT1_MAP_FEAT 0x56 +#define BMI260_INT2_MAP_FEAT 0x57 +#define BMI260_MAP_SIG_MOTION_OUT BIT(0) +#define BMI260_MAP_STEP_COUNTER_OUT BIT(1) +#define BMI260_MAP_HIGH_LOW_G_OUT BIT(2) +#define BMI260_MAP_TAP_OUT BIT(3) +#define BMI260_MAP_FLAT_OUT BIT(4) +#define BMI260_MAP_NO_MOTION_OUT BIT(5) +#define BMI260_MAP_ANY_MOTION_OUT BIT(6) +#define BMI260_MAP_ORIENTAION_OUT BIT(7) + +#define BMI260_INT_MAP_DATA 0x58 +#define BMI260_MAP_FFULL_INT BIT(0) +#define BMI260_MAP_FWM_INT BIT(1) +#define BMI260_MAP_DRDY_INT BIT(2) +#define BMI260_MAP_ERR_INT BIT(3) +#define BMI260_INT_MAP_DATA_INT1_OFFSET 0 +#define BMI260_INT_MAP_DATA_INT2_OFFSET 4 +#define BMI260_INT_MAP_DATA_REG(_i, _bit) \ + (CONCAT3(BMI260_MAP_, _bit, _INT) << \ + CONCAT3(BMI260_INT_MAP_DATA_INT, _i, _OFFSET)) + +#define BMI260_INIT_CTRL 0x59 +#define BMI260_INIT_ADDR_0 0x5b +#define BMI260_INIT_ADDR_1 0x5c +#define BMI260_INIT_DATA 0x5e +#define BMI260_INTERNAL_ERROR 0x5f +#define BMI260_INT_ERR_1 BIT(1) +#define BMI260_INT_ERR_2 BIT(2) +#define BMI260_FEAT_ENG_DISABLED BIT(4) + +#define BMI260_AUX_IF_TRIM 0x68 +#define BMI260_GYR_CRT_CONF 0x69 + +#define BMI260_NVM_CONF 0x6a +#define BMI260_NVM_PROG_EN BIT(1) + +#define BMI260_IF_CONF 0x6b +#define BMI260_IF_SPI3 BIT(0) +#define BMI260_IF_SPI3_OIS BIT(1) +#define BMI260_IF_OIS_EN BIT(4) +#define BMI260_IF_AUX_EN BIT(5) + +#define BMI260_DRV 0x6c +#define BMI260_ACC_SELF_TEST 0x6d + +#define BMI260_NV_CONF 0x70 +#define BMI260_ACC_OFFSET_EN BIT(3) + +#define BMI260_OFFSET_ACC70 0x71 +#define BMI260_OFFSET_GYR70 0x74 +#define BMI260_OFFSET_EN_GYR98 0x77 +#define BMI260_OFFSET_GYRO_EN BIT(6) +#define BMI260_GYR_GAIN_EN BIT(7) + +#define BMI260_PWR_CONF 0x7c +#define BMI260_ADV_POWER_SAVE BIT(0) +#define BMI260_FIFO_SELF_WAKE_UP BIT(1) +#define BMI260_FUP_EN BIT(2) + +#define BMI260_PWR_CTRL 0x7d +#define BMI260_AUX_EN BIT(0) +#define BMI260_GYR_EN BIT(1) +#define BMI260_ACC_EN BIT(2) +#define BMI260_PWR_EN(_sensor_type) BIT(2 - _sensor_type) +#define BMI260_TEMP_EN BIT(3) + +#define BMI260_CMD_REG 0x7e +#define BMI260_CMD_FIFO_FLUSH 0xb0 +#define BMI260_CMD_SOFT_RESET 0xb6 + +#define BMI260_FF_FRAME_LEN_TS 4 +#define BMI260_FF_DATA_LEN_ACC 6 +#define BMI260_FF_DATA_LEN_GYR 6 +#define BMI260_FF_DATA_LEN_MAG 8 + +/* Root mean square noise of 100Hz accelerometer, units: ug */ +#define BMI260_ACCEL_RMS_NOISE_100HZ 1060 + +#endif /* __CROS_EC_ACCELGYRO_BMI260_H */ diff --git a/include/driver/accelgyro_bmi_common.h b/include/driver/accelgyro_bmi_common.h new file mode 100644 index 0000000000..398f04dc42 --- /dev/null +++ b/include/driver/accelgyro_bmi_common.h @@ -0,0 +1,316 @@ +/* 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 "accelgyro_bmi160.h" +#include "accelgyro_bmi260.h" +#include "mag_bmm150.h" +#include "accelgyro_bmi_common_public.h" + +#if !defined(CONFIG_ACCELGYRO_BMI_COMM_SPI) && \ + !defined(CONFIG_ACCELGYRO_BMI_COMM_I2C) +#error "BMI must use either SPI or I2C communication" +#endif + +#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 + +#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]) + +#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); + +/** + * 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(struct motion_sensor_t *s, int range, int rnd); + +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 */ diff --git a/include/driver/mag_bmm150.h b/include/driver/mag_bmm150.h new file mode 100644 index 0000000000..9f517f8097 --- /dev/null +++ b/include/driver/mag_bmm150.h @@ -0,0 +1,150 @@ +/* Copyright 2015 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. + */ + +/* BMM150 magnetometer definition */ + +#ifndef __CROS_EC_MAG_BMM150_H +#define __CROS_EC_MAG_BMM150_H + +#include "accelgyro.h" +#include "mag_cal.h" + +#define BMM150_ADDR0_FLAGS 0x10 +#define BMM150_ADDR1_FLAGS 0x11 +#define BMM150_ADDR2_FLAGS 0x12 +#define BMM150_ADDR3_FLAGS 0x13 + +#define BMM150_CHIP_ID 0x40 +#define BMM150_CHIP_ID_MAJOR 0x32 + +#define BMM150_BASE_DATA 0x42 + +#define BMM150_INT_STATUS 0x4a +#define BMM150_PWR_CTRL 0x4b +#define BMM150_SRST (BIT(7) | BIT(1)) +#define BMM150_PWR_ON BIT(0) + +#define BMM150_OP_CTRL 0x4c +#define BMM150_OP_MODE_OFFSET 1 +#define BMM150_OP_MODE_MASK 3 +#define BMM150_OP_MODE_NORMAL 0x00 +#define BMM150_OP_MODE_FORCED 0x01 +#define BMM150_OP_MODE_SLEEP 0x03 + +#define BMM150_INT_CTRL 0x4d + +#define BMM150_REPXY 0x51 +#define BMM150_LOW_POWER_nXY 3 +#define BMM150_REGULAR_nXY 9 +#define BMM150_ENHANCED_nXY 15 +#define BMM150_HIGH_ACCURACY_nXY 47 +#define BMM150_SPECIAL_nXY 75 +#define BMM150_REPZ 0x52 +#define BMM150_LOW_POWER_nZ 3 +#define BMM150_REGULAR_nZ 15 +#define BMM150_ENHANCED_nZ 27 +#define BMM150_HIGH_ACCURACY_nZ 83 +#define BMM150_SPECIAL_nZ 27 + +#define BMM150_REP(_preset, _axis) CONCAT4(BMM150_, _preset, _n, _axis) + +/* Hidden registers for RHALL calculation */ +#define BMM150_REGA_DIG_X1 0x5d +#define BMM150_REGA_DIG_Y1 0x5e +#define BMM150_REGA_DIG_Z4_LSB 0x62 +#define BMM150_REGA_DIG_Z4_MSB 0x63 +#define BMM150_REGA_DIG_X2 0x64 +#define BMM150_REGA_DIG_Y2 0x65 +#define BMM150_REGA_DIG_Z2_LSB 0x68 +#define BMM150_REGA_DIG_Z2_MSB 0x69 +#define BMM150_REGA_DIG_Z1_LSB 0x6a +#define BMM150_REGA_DIG_Z1_MSB 0x6b +#define BMM150_REGA_DIG_XYZ1_LSB 0x6c +#define BMM150_REGA_DIG_XYZ1_MSB 0x6d +#define BMM150_REGA_DIG_Z3_LSB 0x6e +#define BMM150_REGA_DIG_Z3_MSB 0x6f +#define BMM150_REGA_DIG_XY2 0x70 +#define BMM150_REGA_DIG_XY1 0x71 + +/* Overflow */ + +#define BMM150_FLIP_OVERFLOW_ADCVAL (-4096) +#define BMM150_HALL_OVERFLOW_ADCVAL (-16384) +#define BMM150_OVERFLOW_OUTPUT (0x8000) + +/* Min and Max sampling frequency in mHz */ +#define BMM150_MAG_MIN_FREQ 781 + +/* + * From Section 4.2.4, max frequency depends on the preset. + * + * Fmax ~= 1 / (145us * nXY + 500us * nZ + 980us) + * + * To be safe, declare only 75% of the value. + */ +#define __BMM150_MAG_MAX_FREQ(_preset) (750000000 / \ + (145 * BMM150_REP(_preset, XY) + 500 * BMM150_REP(_preset, Z) + 980)) + +#if (__BMM150_MAG_MAX_FREQ(SPECIAL) > CONFIG_EC_MAX_SENSOR_FREQ_MILLIHZ) +#error "EC too slow for magnetometer" +#endif + +struct bmm150_comp_registers { + /* Local copy of the compensation registers. */ + int8_t dig1[2]; + int8_t dig2[2]; + + uint16_t dig_z1; + int16_t dig_z2; + int16_t dig_z3; + int16_t dig_z4; + + uint8_t dig_xy1; + int8_t dig_xy2; + + uint16_t dig_xyz1; +}; + +struct bmm150_private_data { + /* lsm6dsm_data union requires cal be first element */ + struct mag_cal_t cal; + struct bmm150_comp_registers comp; +}; + +#ifdef CONFIG_MAG_BMI_BMM150 +#include "accelgyro_bmi_common.h" + +#define BMM150_COMP_REG(_s) \ + (&BMI_GET_DATA(_s)->compass.comp) + +#define BMM150_CAL(_s) \ + (&BMI_GET_DATA(_s)->compass.cal) +/* + * Behind a BMI, the BMM150 is in forced mode. Be sure to choose a frequency + * compatible with BMI. + */ +#define BMM150_MAG_MAX_FREQ(_preset) \ + BMI_REG_TO_ODR(BMI_ODR_TO_REG(__BMM150_MAG_MAX_FREQ(_preset))) +#else +#define BMM150_COMP_REG(_s) NULL +#define BMM150_CAL(_s) NULL +#define BMM150_MAG_MAX_FREQ(_preset) __BMM150_MAG_MAX_FREQ(_preset) +#endif + +/* Specific initialization of BMM150 when behing BMI160 */ +int bmm150_init(struct motion_sensor_t *s); + +/* Command to normalize and apply temperature compensation */ +void bmm150_normalize(const struct motion_sensor_t *s, + intv3_t v, + uint8_t *data); + +int bmm150_set_offset(const struct motion_sensor_t *s, + const intv3_t offset); + +int bmm150_get_offset(const struct motion_sensor_t *s, + intv3_t offset); + +#endif /* __CROS_EC_MAG_BMM150_H */ |