summaryrefslogtreecommitdiff
path: root/driver/accelgyro_bmi160.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/accelgyro_bmi160.c')
-rw-r--r--driver/accelgyro_bmi160.c1488
1 files changed, 0 insertions, 1488 deletions
diff --git a/driver/accelgyro_bmi160.c b/driver/accelgyro_bmi160.c
deleted file mode 100644
index e46a367b6a..0000000000
--- a/driver/accelgyro_bmi160.c
+++ /dev/null
@@ -1,1488 +0,0 @@
-/* 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 module for Chrome EC
- * 3D digital accelerometer & 3D digital gyroscope
- */
-
-#include "accelgyro.h"
-#include "common.h"
-#include "console.h"
-#include "driver/accelgyro_bmi160.h"
-#include "driver/mag_bmm150.h"
-#include "hooks.h"
-#include "hwtimer.h"
-#include "i2c.h"
-#include "math_util.h"
-#include "motion_sense_fifo.h"
-#include "spi.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-
-#define CPUTS(outstr) cputs(CC_ACCEL, outstr)
-#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args)
-#define CPRINTS(format, args...) cprints(CC_ACCEL, format, ## args)
-
-STATIC_IF(CONFIG_ACCEL_FIFO) volatile uint32_t last_interrupt_timestamp;
-
-/*
- * Struct for pairing an engineering value with the register value for a
- * parameter.
- */
-struct accel_param_pair {
- int val; /* Value in engineering units. */
- int reg_val; /* Corresponding register value. */
-};
-
-/* List of range values in +/-G's and their associated register values. */
-static const struct accel_param_pair g_ranges[] = {
- {2, BMI160_GSEL_2G},
- {4, BMI160_GSEL_4G},
- {8, BMI160_GSEL_8G},
- {16, BMI160_GSEL_16G}
-};
-
-/*
- * List of angular rate range values in +/-dps's
- * and their associated register values.
- */
-const struct accel_param_pair dps_ranges[] = {
- {125, BMI160_DPS_SEL_125},
- {250, BMI160_DPS_SEL_250},
- {500, BMI160_DPS_SEL_500},
- {1000, BMI160_DPS_SEL_1000},
- {2000, BMI160_DPS_SEL_2000}
-};
-
-static int wakeup_time[] = {
- [MOTIONSENSE_TYPE_ACCEL] = 4,
- [MOTIONSENSE_TYPE_GYRO] = 80,
- [MOTIONSENSE_TYPE_MAG] = 1
-};
-
-static inline const struct accel_param_pair *get_range_table(
- enum motionsensor_type type, int *psize)
-{
- if (MOTIONSENSE_TYPE_ACCEL == type) {
- if (psize)
- *psize = ARRAY_SIZE(g_ranges);
- return g_ranges;
- } else {
- if (psize)
- *psize = ARRAY_SIZE(dps_ranges);
- return dps_ranges;
- }
-}
-
-static inline int get_xyz_reg(enum motionsensor_type type)
-{
- switch (type) {
- case MOTIONSENSE_TYPE_ACCEL:
- return BMI160_ACC_X_L_G;
- case MOTIONSENSE_TYPE_GYRO:
- return BMI160_GYR_X_L_G;
- case MOTIONSENSE_TYPE_MAG:
- return BMI160_MAG_X_L_G;
- default:
- return -1;
- }
-}
-
-/**
- * @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.
- */
-static int get_reg_val(const int eng_val, const int round_up,
- const struct accel_param_pair *pairs, const int size)
-{
- int i;
-
- for (i = 0; i < size - 1; i++) {
- if (eng_val <= pairs[i].val)
- break;
-
- if (eng_val < pairs[i+1].val) {
- if (round_up)
- i += 1;
- break;
- }
- }
- return pairs[i].reg_val;
-}
-
-/**
- * @return engineering value that matches the given reg val
- */
-static int get_engineering_val(const int reg_val,
- const struct accel_param_pair *pairs, const int size)
-{
- int i;
-
- for (i = 0; i < size; i++) {
- if (reg_val == pairs[i].reg_val)
- break;
- }
- return pairs[i].val;
-}
-
-#ifdef CONFIG_SPI_ACCEL_PORT
-static inline int spi_raw_read(const int addr, const uint8_t reg,
- uint8_t *data, const int len)
-{
- uint8_t cmd = 0x80 | reg;
-
- return spi_transaction(&spi_devices[addr], &cmd, 1, data, len);
-}
-#endif
-/**
- * Read 8bit register from accelerometer.
- */
-static int raw_read8(const int port,
- const uint16_t i2c_spi_addr_flags,
- const int reg, int *data_ptr)
-{
- int rv = -EC_ERROR_PARAM1;
-
- if (SLAVE_IS_SPI(i2c_spi_addr_flags)) {
-#ifdef CONFIG_SPI_ACCEL_PORT
- uint8_t val;
- rv = spi_raw_read(SLAVE_GET_SPI_ADDR(i2c_spi_addr_flags),
- reg, &val, 1);
- if (rv == EC_SUCCESS)
- *data_ptr = val;
-#endif
- } else {
-#ifdef I2C_PORT_ACCEL
- rv = i2c_read8(port, i2c_spi_addr_flags,
- reg, data_ptr);
-#endif
- }
- return rv;
-}
-
-/**
- * Write 8bit register from accelerometer.
- */
-static int raw_write8(const int port,
- const uint16_t i2c_spi_addr_flags,
- const int reg, int data)
-{
- int rv = -EC_ERROR_PARAM1;
-
- if (SLAVE_IS_SPI(i2c_spi_addr_flags)) {
-#ifdef CONFIG_SPI_ACCEL_PORT
- uint8_t cmd[2] = { reg, data };
- rv = spi_transaction(
- &spi_devices[SLAVE_GET_SPI_ADDR(i2c_spi_addr_flags)],
- cmd, 2, NULL, 0);
-#endif
- } else {
-#ifdef I2C_PORT_ACCEL
- rv = i2c_write8(port, i2c_spi_addr_flags,
- reg, data);
-#endif
- }
- /*
- * From Bosch: BMI160 needs a delay of 450us after each write if it
- * is in suspend mode, otherwise the operation may be ignored by
- * the sensor. Given we are only doing write during init, add
- * the delay inconditionally.
- */
- msleep(1);
- return rv;
-}
-
-#ifdef CONFIG_ACCEL_INTERRUPTS
-/**
- * Read 32bit register from accelerometer.
- */
-static int raw_read32(const int port,
- const uint16_t i2c_spi_addr_flags,
- const uint8_t reg, int *data_ptr)
-{
- int rv = -EC_ERROR_PARAM1;
- if (SLAVE_IS_SPI(i2c_spi_addr_flags)) {
-#ifdef CONFIG_SPI_ACCEL_PORT
- rv = spi_raw_read(SLAVE_GET_SPI_ADDR(i2c_spi_addr_flags),
- reg, (uint8_t *)data_ptr, 4);
-#endif
- } else {
-#ifdef I2C_PORT_ACCEL
- rv = i2c_read32(port, i2c_spi_addr_flags,
- reg, data_ptr);
-#endif
- }
- return rv;
-}
-#endif /* defined(CONFIG_ACCEL_INTERRUPTS) */
-
-/**
- * Read n bytes from accelerometer.
- */
-static int raw_read_n(const int port,
- const uint16_t i2c_spi_addr_flags,
- const uint8_t reg, uint8_t *data_ptr, const int len)
-{
- int rv = -EC_ERROR_PARAM1;
-
- if (SLAVE_IS_SPI(i2c_spi_addr_flags)) {
-#ifdef CONFIG_SPI_ACCEL_PORT
- rv = spi_raw_read(SLAVE_GET_SPI_ADDR(i2c_spi_addr_flags),
- reg, data_ptr, len);
-#endif
- } else {
-#ifdef I2C_PORT_ACCEL
- rv = i2c_read_block(port, i2c_spi_addr_flags,
- reg, data_ptr, len);
-#endif
- }
- return rv;
-}
-
-#ifdef CONFIG_BMI160_SEC_I2C
-/**
- * Control access to the compass on the secondary i2c interface:
- * enable values are:
- * 1: manual access, we can issue i2c to the compass
- * 0: data access: BMI160 gather data periodically from the compass.
- */
-static int bmi160_sec_access_ctrl(const int port,
- const uint16_t i2c_spi_addr_flags,
- const int enable)
-{
- int mag_if_ctrl;
- raw_read8(port, i2c_spi_addr_flags,
- BMI160_MAG_IF_1, &mag_if_ctrl);
- if (enable) {
- mag_if_ctrl |= BMI160_MAG_MANUAL_EN;
- mag_if_ctrl &= ~BMI160_MAG_READ_BURST_MASK;
- mag_if_ctrl |= BMI160_MAG_READ_BURST_1;
- } else {
- mag_if_ctrl &= ~BMI160_MAG_MANUAL_EN;
- mag_if_ctrl &= ~BMI160_MAG_READ_BURST_MASK;
- mag_if_ctrl |= BMI160_MAG_READ_BURST_8;
- }
- return raw_write8(port, i2c_spi_addr_flags,
- BMI160_MAG_IF_1, mag_if_ctrl);
-}
-
-/**
- * Read register from compass.
- * Assuming we are in manual access mode, read compass i2c register.
- */
-int bmi160_sec_raw_read8(const int port,
- const uint16_t i2c_spi_addr_flags,
- const uint8_t reg, int *data_ptr)
-{
- /* Only read 1 bytes */
- raw_write8(port, i2c_spi_addr_flags,
- BMI160_MAG_I2C_READ_ADDR, reg);
- return raw_read8(port, i2c_spi_addr_flags,
- BMI160_MAG_I2C_READ_DATA, data_ptr);
-}
-
-/**
- * Write register from compass.
- * Assuming we are in manual access mode, write to compass i2c register.
- */
-int bmi160_sec_raw_write8(const int port,
- const uint16_t i2c_spi_addr_flags,
- const uint8_t reg, int data)
-{
- raw_write8(port, i2c_spi_addr_flags,
- BMI160_MAG_I2C_WRITE_DATA, data);
- return raw_write8(port, i2c_spi_addr_flags,
- BMI160_MAG_I2C_WRITE_ADDR, reg);
-}
-#endif
-
-static int enable_fifo(const struct motion_sensor_t *s, int enable)
-{
- struct bmi160_drv_data_t *data = BMI160_GET_DATA(s);
- int ret, val;
-
- if (enable) {
- /* FIFO start collecting events */
- ret = raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_FIFO_CONFIG_1, &val);
- val |= BMI160_FIFO_SENSOR_EN(s->type);
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_FIFO_CONFIG_1, val);
- if (ret == EC_SUCCESS)
- data->flags |= 1 << (s->type + BMI160_FIFO_FLAG_OFFSET);
-
- } else {
- /* FIFO stop collecting events */
- ret = raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_FIFO_CONFIG_1, &val);
- val &= ~BMI160_FIFO_SENSOR_EN(s->type);
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_FIFO_CONFIG_1, val);
- if (ret == EC_SUCCESS)
- data->flags &=
- ~(1 << (s->type + BMI160_FIFO_FLAG_OFFSET));
- }
- return ret;
-}
-
-static int set_range(const struct motion_sensor_t *s,
- int range,
- int rnd)
-{
- int ret, range_tbl_size;
- uint8_t reg_val, ctrl_reg;
- const struct accel_param_pair *ranges;
- struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s);
-
- if (s->type == MOTIONSENSE_TYPE_MAG) {
- data->range = range;
- return EC_SUCCESS;
- }
-
- ctrl_reg = BMI160_RANGE_REG(s->type);
- ranges = get_range_table(s->type, &range_tbl_size);
- reg_val = get_reg_val(range, rnd, ranges, range_tbl_size);
-
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- ctrl_reg, reg_val);
- /* Now that we have set the range, update the driver's value. */
- if (ret == EC_SUCCESS)
- data->range = get_engineering_val(reg_val, ranges,
- range_tbl_size);
- return ret;
-}
-
-static int get_range(const struct motion_sensor_t *s)
-{
- struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s);
-
- return data->range;
-}
-
-static int get_resolution(const struct motion_sensor_t *s)
-{
- return BMI160_RESOLUTION;
-}
-
-static int set_data_rate(const struct motion_sensor_t *s,
- int rate,
- int rnd)
-{
- int ret, val, normalized_rate;
- uint8_t ctrl_reg, reg_val;
- struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s);
-#ifdef CONFIG_MAG_BMI160_BMM150
- struct mag_cal_t *moc = BMM150_CAL(s);
-#endif
-
- if (rate == 0) {
- /* FIFO stop collecting events */
- if (IS_ENABLED(CONFIG_ACCEL_FIFO))
- enable_fifo(s, 0);
-
- /* go to suspend mode */
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_REG,
- BMI160_CMD_MODE_SUSPEND(s->type));
- msleep(3);
- data->odr = 0;
-#ifdef CONFIG_MAG_BMI160_BMM150
- if (s->type == MOTIONSENSE_TYPE_MAG)
- moc->batch_size = 0;
-#endif
- return ret;
- } else if (data->odr == 0) {
- /* back from suspend mode. */
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_REG,
- BMI160_CMD_MODE_NORMAL(s->type));
- msleep(wakeup_time[s->type]);
- }
- ctrl_reg = BMI160_CONF_REG(s->type);
- reg_val = BMI160_ODR_TO_REG(rate);
- normalized_rate = BMI160_REG_TO_ODR(reg_val);
- if (rnd && (normalized_rate < rate)) {
- reg_val++;
- normalized_rate = BMI160_REG_TO_ODR(reg_val);
- }
-
- switch (s->type) {
- case MOTIONSENSE_TYPE_ACCEL:
- if (normalized_rate > BMI160_ACCEL_MAX_FREQ ||
- normalized_rate < BMI160_ACCEL_MIN_FREQ)
- return EC_RES_INVALID_PARAM;
- break;
- case MOTIONSENSE_TYPE_GYRO:
- if (normalized_rate > BMI160_GYRO_MAX_FREQ ||
- normalized_rate < BMI160_GYRO_MIN_FREQ)
- return EC_RES_INVALID_PARAM;
- break;
-#ifdef CONFIG_MAG_BMI160_BMM150
- case MOTIONSENSE_TYPE_MAG:
- /* We use the regular preset we can go about 100Hz */
- if (reg_val > BMI160_ODR_100HZ || reg_val < BMI160_ODR_0_78HZ)
- return EC_RES_INVALID_PARAM;
- break;
-#endif
-
- default:
- return EC_RES_INVALID_PARAM;
- }
-
- /*
- * Lock accel resource to prevent another task from attempting
- * to write accel parameters until we are done.
- */
- mutex_lock(s->mutex);
-
- ret = raw_read8(s->port, s->i2c_spi_addr_flags, ctrl_reg, &val);
- if (ret != EC_SUCCESS)
- goto accel_cleanup;
-
- val = (val & ~BMI160_ODR_MASK) | reg_val;
- ret = raw_write8(s->port, s->i2c_spi_addr_flags, ctrl_reg, val);
- if (ret != EC_SUCCESS)
- goto accel_cleanup;
-
- /* Now that we have set the odr, update the driver's value. */
- data->odr = normalized_rate;
-
-#ifdef CONFIG_MAG_BMI160_BMM150
- if (s->type == MOTIONSENSE_TYPE_MAG) {
- /* Reset the calibration */
- init_mag_cal(moc);
- /*
- * We need at least MIN_BATCH_SIZE amd we must have collected
- * for at least MIN_BATCH_WINDOW_US.
- * Given odr is in mHz, multiply by 1000x
- */
- moc->batch_size = MAX(
- MAG_CAL_MIN_BATCH_SIZE,
- (data->odr * 1000) / (MAG_CAL_MIN_BATCH_WINDOW_US));
- CPRINTS("Batch size: %d", moc->batch_size);
- }
-#endif
-
- /*
- * FIFO start collecting events.
- * They will be discarded if AP does not want them.
- */
- if (IS_ENABLED(CONFIG_ACCEL_FIFO))
- enable_fifo(s, 1);
-
-accel_cleanup:
- mutex_unlock(s->mutex);
- return ret;
-}
-
-static int get_data_rate(const struct motion_sensor_t *s)
-{
- struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s);
-
- return data->odr;
-}
-static int get_offset(const struct motion_sensor_t *s,
- int16_t *offset,
- int16_t *temp)
-{
- int i, val, val98;
- intv3_t v;
-
- switch (s->type) {
- case MOTIONSENSE_TYPE_ACCEL:
- /*
- * The offset of the accelerometer off_acc_[xyz] is a 8 bit
- * two-complement number in units of 3.9 mg independent of the
- * range selected for the accelerometer.
- */
- for (i = X; i <= Z; i++) {
- raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_OFFSET_ACC70 + i, &val);
- if (val > 0x7f)
- val = -256 + val;
- v[i] = val * BMI160_OFFSET_ACC_MULTI_MG /
- BMI160_OFFSET_ACC_DIV_MG;
- }
- break;
- case MOTIONSENSE_TYPE_GYRO:
- /* Read the MSB first */
- raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_OFFSET_EN_GYR98, &val98);
- /*
- * The offset of the gyroscope off_gyr_[xyz] is a 10 bit
- * two-complement number in units of 0.061 °/s.
- * Therefore a maximum range that can be compensated is
- * -31.25 °/s to +31.25 °/s
- */
- for (i = X; i <= Z; i++) {
- raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_OFFSET_GYR70 + i, &val);
- val |= ((val98 >> (2 * i)) & 0x3) << 8;
- if (val > 0x1ff)
- val = -1024 + val;
- v[i] = val * BMI160_OFFSET_GYRO_MULTI_MDS /
- BMI160_OFFSET_GYRO_DIV_MDS;
- }
- break;
-#ifdef CONFIG_MAG_BMI160_BMM150
- case MOTIONSENSE_TYPE_MAG:
- bmm150_get_offset(s, v);
- break;
-#endif /* defined(CONFIG_MAG_BMI160_BMM150) */
- default:
- for (i = X; i <= Z; i++)
- v[i] = 0;
- }
- rotate(v, *s->rot_standard_ref, v);
- offset[X] = v[X];
- offset[Y] = v[Y];
- offset[Z] = v[Z];
- /* Saving temperature at calibration not supported yet */
- *temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP;
- return EC_SUCCESS;
-}
-
-static int set_offset(const struct motion_sensor_t *s,
- const int16_t *offset,
- int16_t temp)
-{
- int ret, i, val, val98;
- intv3_t v = { offset[X], offset[Y], offset[Z] };
-
- rotate_inv(v, *s->rot_standard_ref, v);
-
- ret = raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_OFFSET_EN_GYR98, &val98);
- if (ret != 0)
- return ret;
-
- switch (s->type) {
- case MOTIONSENSE_TYPE_ACCEL:
- for (i = X; i <= Z; i++) {
- val = v[i] * BMI160_OFFSET_ACC_DIV_MG /
- BMI160_OFFSET_ACC_MULTI_MG;
- if (val > 127)
- val = 127;
- if (val < -128)
- val = -128;
- if (val < 0)
- val = 256 + val;
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_OFFSET_ACC70 + i, val);
- }
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_OFFSET_EN_GYR98,
- val98 | BMI160_OFFSET_ACC_EN);
- break;
- case MOTIONSENSE_TYPE_GYRO:
- for (i = X; i <= Z; i++) {
- val = v[i] * BMI160_OFFSET_GYRO_DIV_MDS /
- BMI160_OFFSET_GYRO_MULTI_MDS;
- if (val > 511)
- val = 511;
- if (val < -512)
- val = -512;
- if (val < 0)
- val = 1024 + val;
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_OFFSET_GYR70 + i, val & 0xFF);
- val98 &= ~(0x3 << (2 * i));
- val98 |= (val >> 8) << (2 * i);
- }
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_OFFSET_EN_GYR98,
- val98 | BMI160_OFFSET_GYRO_EN);
- break;
-#ifdef CONFIG_MAG_BMI160_BMM150
- case MOTIONSENSE_TYPE_MAG:
- ret = bmm150_set_offset(s, v);
- break;
-#endif /* defined(CONFIG_MAG_BMI160) */
- default:
- ret = EC_RES_INVALID_PARAM;
- }
- return ret;
-}
-
-int set_scale(const struct motion_sensor_t *s,
- const uint16_t *scale, int16_t temp)
-{
- struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s);
-
- data->scale[X] = scale[X];
- data->scale[Y] = scale[Y];
- data->scale[Z] = scale[Z];
- return EC_SUCCESS;
-}
-
-int get_scale(const struct motion_sensor_t *s,
- uint16_t *scale, int16_t *temp)
-{
- struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s);
-
- scale[X] = data->scale[X];
- scale[Y] = data->scale[Y];
- scale[Z] = data->scale[Z];
- *temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP;
- return EC_SUCCESS;
-}
-
-static int perform_calib(const struct motion_sensor_t *s, int enable)
-{
- int ret, val, en_flag, status, rate;
- timestamp_t deadline;
-
- if (!enable)
- return EC_SUCCESS;
-
- rate = get_data_rate(s);
- /*
- * Temporary set frequency to 100Hz to get enough data in a short
- * period of time.
- */
- set_data_rate(s, 100000, 0);
-
- switch (s->type) {
- case MOTIONSENSE_TYPE_ACCEL:
- /* We assume the device is laying flat for calibration */
- if (s->rot_standard_ref == NULL ||
- (*s->rot_standard_ref)[2][2] > INT_TO_FP(0))
- val = BMI160_FOC_ACC_PLUS_1G;
- else
- val = BMI160_FOC_ACC_MINUS_1G;
- val = (BMI160_FOC_ACC_0G << BMI160_FOC_ACC_X_OFFSET) |
- (BMI160_FOC_ACC_0G << BMI160_FOC_ACC_Y_OFFSET) |
- (val << BMI160_FOC_ACC_Z_OFFSET);
- en_flag = BMI160_OFFSET_ACC_EN;
- break;
- case MOTIONSENSE_TYPE_GYRO:
- val = BMI160_FOC_GYRO_EN;
- en_flag = BMI160_OFFSET_GYRO_EN;
- break;
- default:
- /* Not supported on Magnetometer */
- ret = EC_RES_INVALID_PARAM;
- goto end_perform_calib;
- }
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_FOC_CONF, val);
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_REG, BMI160_CMD_START_FOC);
- deadline.val = get_time().val + 400 * MSEC;
- do {
- if (timestamp_expired(deadline, NULL)) {
- ret = EC_RES_TIMEOUT;
- goto end_perform_calib;
- }
- msleep(50);
- ret = raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_STATUS, &status);
- if (ret != EC_SUCCESS)
- goto end_perform_calib;
- } while ((status & BMI160_FOC_RDY) == 0);
-
- /* Calibration is successful, and loaded, use the result */
- ret = raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_OFFSET_EN_GYR98, &val);
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_OFFSET_EN_GYR98, val | en_flag);
-end_perform_calib:
- set_data_rate(s, rate, 0);
- return ret;
-}
-
-void normalize(const struct motion_sensor_t *s, intv3_t v, uint8_t *input)
-{
- int i;
- struct accelgyro_saved_data_t *data = BMI160_GET_SAVED_DATA(s);
-
-#ifdef CONFIG_MAG_BMI160_BMM150
- if (s->type == MOTIONSENSE_TYPE_MAG)
- bmm150_normalize(s, v, input);
- else
-#endif
-#ifdef CONFIG_MAG_BMI160_LIS2MDL
- if (s->type == MOTIONSENSE_TYPE_MAG)
- lis2mdl_normalize(s, v, data);
- else
-#endif
- {
- v[0] = ((int16_t)((input[1] << 8) | input[0]));
- v[1] = ((int16_t)((input[3] << 8) | input[2]));
- v[2] = ((int16_t)((input[5] << 8) | input[4]));
- }
- rotate(v, *s->rot_standard_ref, v);
- for (i = X; i <= Z; i++)
- v[i] = SENSOR_APPLY_SCALE(v[i], data->scale[i]);
-}
-
-/*
- * Manage gesture recognition.
- * Defined even if host interface is not defined, to enable double tap even
- * when the host does not deal with gesture.
- */
-int manage_activity(const struct motion_sensor_t *s,
- enum motionsensor_activity activity,
- int enable,
- const struct ec_motion_sense_activity *param)
-{
- int ret;
- struct bmi160_drv_data_t *data = BMI160_GET_DATA(s);
-
- switch (activity) {
-#ifdef CONFIG_GESTURE_SIGMO
- case MOTIONSENSE_ACTIVITY_SIG_MOTION: {
- int tmp;
- ret = raw_read8(s->port, s->addr, BMI160_INT_EN_0, &tmp);
- if (ret)
- return ret;
- if (enable) {
- /* We should use parameters from caller */
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_MOTION_3,
- BMI160_MOTION_PROOF_TIME(
- CONFIG_GESTURE_SIGMO_PROOF_MS) <<
- BMI160_MOTION_PROOF_OFF |
- BMI160_MOTION_SKIP_TIME(
- CONFIG_GESTURE_SIGMO_SKIP_MS) <<
- BMI160_MOTION_SKIP_OFF |
- BMI160_MOTION_SIG_MOT_SEL);
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_MOTION_1,
- BMI160_MOTION_TH(s,
- CONFIG_GESTURE_SIGMO_THRES_MG));
- tmp |= BMI160_INT_ANYMO_X_EN |
- BMI160_INT_ANYMO_Y_EN |
- BMI160_INT_ANYMO_Z_EN;
- } else {
- tmp &= ~(BMI160_INT_ANYMO_X_EN |
- BMI160_INT_ANYMO_Y_EN |
- BMI160_INT_ANYMO_Z_EN);
- }
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_EN_0, tmp);
- if (ret)
- ret = EC_RES_UNAVAILABLE;
- break;
- }
-#endif
-#ifdef CONFIG_GESTURE_SENSOR_DOUBLE_TAP
- case MOTIONSENSE_ACTIVITY_DOUBLE_TAP: {
- int tmp;
- /* Set double tap interrupt */
- ret = raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_EN_0, &tmp);
- if (ret)
- return ret;
- if (enable)
- tmp |= BMI160_INT_D_TAP_EN;
- else
- tmp &= ~BMI160_INT_D_TAP_EN;
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_EN_0, tmp);
- if (ret)
- ret = EC_RES_UNAVAILABLE;
- break;
- }
-#endif
- default:
- ret = EC_RES_INVALID_PARAM;
- }
- if (ret == EC_RES_SUCCESS) {
- if (enable) {
- data->enabled_activities |= 1 << activity;
- data->disabled_activities &= ~BIT(activity);
- } else {
- data->enabled_activities &= ~BIT(activity);
- data->disabled_activities |= 1 << activity;
- }
- }
- return ret;
-}
-
-#ifdef CONFIG_GESTURE_HOST_DETECTION
-int list_activities(const struct motion_sensor_t *s,
- uint32_t *enabled,
- uint32_t *disabled)
-{
- struct bmi160_drv_data_t *data = BMI160_GET_DATA(s);
- *enabled = data->enabled_activities;
- *disabled = data->disabled_activities;
- return EC_RES_SUCCESS;
-}
-#endif
-
-#ifdef CONFIG_ACCEL_INTERRUPTS
-
-enum fifo_state {
- FIFO_HEADER,
- FIFO_DATA_SKIP,
- FIFO_DATA_TIME,
- FIFO_DATA_CONFIG,
-};
-
-
-#define BMI160_FIFO_BUFFER 64
-static uint8_t bmi160_buffer[BMI160_FIFO_BUFFER];
-/*
- * Decode the header from the fifo.
- * Return 0 if we need further processing.
- * Sensor mutex must be held during processing, to protect the fifos.
- *
- * @s: base sensor
- * @hdr: the header to decode
- * @bp: current pointer in the buffer, updated when processing the header.
- * @ep: pointer to the end of the valid data in the buffer.
- */
-static int bmi160_decode_header(struct motion_sensor_t *accel,
- enum fifo_header hdr, uint32_t last_ts,
- uint8_t **bp, uint8_t *ep)
-{
- if ((hdr & BMI160_FH_MODE_MASK) == BMI160_EMPTY &&
- (hdr & BMI160_FH_PARM_MASK) != 0) {
- int i, size = 0;
- /* Check if there is enough space for the data frame */
- for (i = MOTIONSENSE_TYPE_MAG; i >= MOTIONSENSE_TYPE_ACCEL;
- i--) {
- if (hdr & (1 << (i + BMI160_FH_PARM_OFFSET)))
- size += (i == MOTIONSENSE_TYPE_MAG ? 8 : 6);
- }
- if (*bp + size > ep) {
- /* frame is not complete, it will be retransmitted. */
- *bp = ep;
- return 1;
- }
- for (i = MOTIONSENSE_TYPE_MAG; i >= MOTIONSENSE_TYPE_ACCEL;
- i--) {
- struct motion_sensor_t *s = accel + i;
-
- if (hdr & (1 << (i + BMI160_FH_PARM_OFFSET))) {
- struct ec_response_motion_sensor_data vector;
- int *v = s->raw_xyz;
- vector.flags = 0;
- normalize(s, v, *bp);
- if (IS_ENABLED(CONFIG_ACCEL_SPOOF_MODE) &&
- s->flags & MOTIONSENSE_FLAG_IN_SPOOF_MODE)
- v = s->spoof_xyz;
- vector.data[X] = v[X];
- vector.data[Y] = v[Y];
- vector.data[Z] = v[Z];
- vector.sensor_num = s - motion_sensors;
- motion_sense_fifo_stage_data(&vector, s, 3,
- last_ts);
- *bp += (i == MOTIONSENSE_TYPE_MAG ? 8 : 6);
- }
- }
- return 1;
- } else {
- return 0;
- }
-}
-
-/**
- * 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.
- *
- * Read only up to bmi160_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_bmi160.c::load_fifo for an example.
- */
-static int load_fifo(struct motion_sensor_t *s, uint32_t last_ts)
-{
- struct bmi160_drv_data_t *data = BMI160_GET_DATA(s);
- uint16_t length;
- enum fifo_state state = FIFO_HEADER;
- uint8_t *bp = bmi160_buffer;
- uint8_t *ep;
- uint32_t beginning;
-
-
- if (s->type != MOTIONSENSE_TYPE_ACCEL)
- return EC_SUCCESS;
-
- if (!(data->flags &
- (BMI160_FIFO_ALL_MASK << BMI160_FIFO_FLAG_OFFSET))) {
- /*
- * The FIFO was disabled while we were processing it.
- *
- * Flush potential left over:
- * When sensor is resumed, we won't read old data.
- */
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_REG, BMI160_CMD_FIFO_FLUSH);
- return EC_SUCCESS;
- }
-
- raw_read_n(s->port, s->i2c_spi_addr_flags,
- BMI160_FIFO_LENGTH_0,
- (uint8_t *)&length, sizeof(length));
- length &= BMI160_FIFO_LENGTH_MASK;
-
- /*
- * We have not requested timestamp, no extra frame to read.
- * if we have too much to read, read the whole buffer.
- */
- if (length == 0) {
- CPRINTS("unexpected empty FIFO");
- return EC_SUCCESS;
- }
-
- /* Add one byte to get an empty FIFO frame.*/
- length++;
-
- if (length > sizeof(bmi160_buffer))
- CPRINTS("unexpected large FIFO: %d", length);
- length = MIN(length, sizeof(bmi160_buffer));
-
-
- raw_read_n(s->port, s->i2c_spi_addr_flags,
- BMI160_FIFO_DATA, bmi160_buffer, length);
- beginning = *(uint32_t *)bmi160_buffer;
- ep = bmi160_buffer + length;
- /*
- * FIFO is invalid when reading while the sensors are all
- * suspended.
- * Instead of returning the empty frame, it can return a
- * pattern that looks like a valid header: 84 or 40.
- * If we see those, assume the sensors have been disabled
- * while this thread was running.
- */
- if (beginning == 0x84848484 ||
- (beginning & 0xdcdcdcdc) == 0x40404040) {
- CPRINTS("Suspended FIFO: accel ODR/rate: %d/%d: 0x%08x",
- BASE_ODR(s->config[SENSOR_CONFIG_AP].odr),
- get_data_rate(s),
- beginning);
- return EC_SUCCESS;
- }
-
- while (bp < ep) {
- switch (state) {
- case FIFO_HEADER: {
- enum fifo_header hdr = *bp++;
-
- if (bmi160_decode_header(s, hdr, last_ts, &bp, ep))
- continue;
- /* Other cases */
- hdr &= 0xdc;
- switch (hdr) {
- case BMI160_EMPTY:
- return EC_SUCCESS;
- case BMI160_SKIP:
- state = FIFO_DATA_SKIP;
- break;
- case BMI160_TIME:
- state = FIFO_DATA_TIME;
- break;
- case BMI160_CONFIG:
- state = FIFO_DATA_CONFIG;
- break;
- default:
- CPRINTS("Unknown header: 0x%02x @ %zd",
- hdr, bp - bmi160_buffer);
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_REG,
- BMI160_CMD_FIFO_FLUSH);
- return EC_ERROR_NOT_HANDLED;
- }
- break;
- }
- case FIFO_DATA_SKIP:
- CPRINTS("@ %zd - %d, skipped %d frames",
- bp - bmi160_buffer, length, *bp);
- bp++;
- state = FIFO_HEADER;
- break;
- case FIFO_DATA_CONFIG:
- CPRINTS("@ %zd - %d, config change: 0x%02x",
- bp - bmi160_buffer, length, *bp);
- bp++;
- state = FIFO_HEADER;
- break;
- case FIFO_DATA_TIME:
- if (bp + 3 > ep) {
- bp = ep;
- continue;
- }
- /* We are not requesting timestamp */
- CPRINTS("timestamp %d", (bp[2] << 16) |
- (bp[1] << 8) | bp[0]);
- state = FIFO_HEADER;
- bp += 3;
- break;
- default:
- CPRINTS("Unknown data: 0x%02x", *bp++);
- state = FIFO_HEADER;
- }
- }
- return EC_SUCCESS;
-}
-
-/**
- * bmi160_interrupt - called when the sensor activates the interrupt line.
- *
- * This is a "top half" interrupt handler, it just asks motion sense ask
- * to schedule the "bottom half", ->irq_handler().
- */
-void bmi160_interrupt(enum gpio_signal signal)
-{
- if (IS_ENABLED(CONFIG_ACCEL_FIFO))
- last_interrupt_timestamp = __hw_clock_source_read();
-
- task_set_event(TASK_ID_MOTIONSENSE,
- CONFIG_ACCELGYRO_BMI160_INT_EVENT, 0);
-}
-
-
-static int config_interrupt(const struct motion_sensor_t *s)
-{
- int ret, tmp;
-
- if (s->type != MOTIONSENSE_TYPE_ACCEL)
- return EC_SUCCESS;
-
- mutex_lock(s->mutex);
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_REG, BMI160_CMD_FIFO_FLUSH);
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_REG, BMI160_CMD_INT_RESET);
-
-#ifdef CONFIG_GESTURE_SENSOR_DOUBLE_TAP
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_TAP_0,
- BMI160_TAP_DUR(s, CONFIG_GESTURE_TAP_MAX_INTERSTICE_T));
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_TAP_1,
- BMI160_TAP_TH(s, CONFIG_GESTURE_TAP_THRES_MG));
-#endif
-#ifdef CONFIG_BMI160_ORIENTATION_SENSOR
- /* only use orientation sensor on the lid sensor */
- if (s->location == MOTIONSENSE_LOC_LID) {
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_ORIENT_0,
- BMI160_INT_ORIENT_0_INIT_VAL);
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_ORIENT_1,
- BMI160_INT_ORIENT_1_INIT_VAL);
- }
-#endif
-
-#ifdef CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_LATCH, BMI160_LATCH_5MS);
-#else
- /* Also, configure int2 as an external input. */
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_LATCH,
- BMI160_INT2_INPUT_EN | BMI160_LATCH_5MS);
-#endif
-
- /* configure int1 as an interrupt */
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_OUT_CTRL,
- BMI160_INT_CTRL(1, OUTPUT_EN));
-
- /* Map activity interrupt to int 1 */
- tmp = 0;
-#ifdef CONFIG_GESTURE_SIGMO
- tmp |= BMI160_INT_ANYMOTION;
-#endif
-#ifdef CONFIG_GESTURE_SENSOR_DOUBLE_TAP
- tmp |= BMI160_INT_D_TAP;
-#endif
-#ifdef CONFIG_BMI160_ORIENTATION_SENSOR
- /* enable orientation interrupt for lid sensor only */
- if (s->location == MOTIONSENSE_LOC_LID)
- tmp |= BMI160_INT_ORIENT;
-#endif
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_MAP_REG(1), tmp);
-
- if (IS_ENABLED(CONFIG_ACCEL_FIFO)) {
- /* map fifo water mark to int 1 */
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_FIFO_MAP,
- BMI160_INT_MAP(1, FWM) |
- BMI160_INT_MAP(1, FFULL));
-
- /*
- * Configure fifo watermark to int whenever there's any data in
- * there
- */
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_FIFO_CONFIG_0, 1);
-#ifdef CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_FIFO_CONFIG_1,
- BMI160_FIFO_HEADER_EN);
-#else
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_FIFO_CONFIG_1,
- BMI160_FIFO_TAG_INT2_EN |
- BMI160_FIFO_HEADER_EN);
-#endif
-
- /* Set fifo*/
- ret = raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_EN_1, &tmp);
- tmp |= BMI160_INT_FWM_EN | BMI160_INT_FFUL_EN;
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_EN_1, tmp);
- }
- mutex_unlock(s->mutex);
- return ret;
-}
-
-#ifdef CONFIG_BMI160_ORIENTATION_SENSOR
-static void irq_set_orientation(struct motion_sensor_t *s,
- int interrupt)
-{
- int shifted_masked_orientation =
- (interrupt >> 24) & BMI160_ORIENT_XY_MASK;
- if (BMI160_GET_DATA(s)->raw_orientation != shifted_masked_orientation) {
- enum motionsensor_orientation orientation =
- MOTIONSENSE_ORIENTATION_UNKNOWN;
-
- BMI160_GET_DATA(s)->raw_orientation =
- shifted_masked_orientation;
-
- switch (shifted_masked_orientation) {
- case BMI160_ORIENT_PORTRAIT:
- orientation = MOTIONSENSE_ORIENTATION_PORTRAIT;
- break;
- case BMI160_ORIENT_PORTRAIT_INVERT:
- orientation =
- MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_PORTRAIT;
- break;
- case BMI160_ORIENT_LANDSCAPE:
- orientation = MOTIONSENSE_ORIENTATION_LANDSCAPE;
- break;
- case BMI160_ORIENT_LANDSCAPE_INVERT:
- orientation =
- MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_LANDSCAPE;
- break;
- default:
- break;
- }
- orientation = motion_sense_remap_orientation(s, orientation);
- SET_ORIENTATION(s, orientation);
- }
-}
-#endif
-/**
- * irq_handler - bottom half of the interrupt stack.
- * Ran from the motion_sense task, finds the events that raised the interrupt.
- *
- * For now, we just print out. We should set a bitmask motion sense code will
- * act upon.
- */
-static int irq_handler(struct motion_sensor_t *s, uint32_t *event)
-{
- uint32_t interrupt;
- int8_t has_read_fifo = 0;
- int rv;
-
- if ((s->type != MOTIONSENSE_TYPE_ACCEL) ||
- (!(*event & CONFIG_ACCELGYRO_BMI160_INT_EVENT)))
- return EC_ERROR_NOT_HANDLED;
-
- do {
- rv = raw_read32(s->port, s->i2c_spi_addr_flags,
- BMI160_INT_STATUS_0, &interrupt);
- /*
- * Bail out of this loop there was an error reading the register
- */
- if (rv)
- return rv;
-
-#ifdef CONFIG_GESTURE_SENSOR_DOUBLE_TAP
- if (interrupt & BMI160_D_TAP_INT)
- *event |= TASK_EVENT_MOTION_ACTIVITY_INTERRUPT(
- MOTIONSENSE_ACTIVITY_DOUBLE_TAP);
-#endif
-#ifdef CONFIG_GESTURE_SIGMO
- if (interrupt & BMI160_SIGMOT_INT)
- *event |= TASK_EVENT_MOTION_ACTIVITY_INTERRUPT(
- MOTIONSENSE_ACTIVITY_SIG_MOTION);
-#endif
- if (IS_ENABLED(CONFIG_ACCEL_FIFO) &&
- interrupt & (BMI160_FWM_INT | BMI160_FFULL_INT)) {
- load_fifo(s, last_interrupt_timestamp);
- has_read_fifo = 1;
- }
-#ifdef CONFIG_BMI160_ORIENTATION_SENSOR
- irq_set_orientation(s, interrupt);
-#endif
- } while (interrupt != 0);
-
- if (IS_ENABLED(CONFIG_ACCEL_FIFO) && has_read_fifo)
- motion_sense_fifo_commit_data();
-
- return EC_SUCCESS;
-}
-#endif /* CONFIG_ACCEL_INTERRUPTS */
-
-
-static int read(const struct motion_sensor_t *s, intv3_t v)
-{
- uint8_t data[6];
- int ret, status = 0;
-
- ret = raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_STATUS, &status);
- if (ret != EC_SUCCESS)
- return ret;
-
- /*
- * If sensor data is not ready, return the previous read data.
- * Note: return success so that motion senor task can read again
- * to get the latest updated sensor data quickly.
- */
- if (!(status & BMI160_DRDY_MASK(s->type))) {
- if (v != s->raw_xyz)
- memcpy(v, s->raw_xyz, sizeof(s->raw_xyz));
- return EC_SUCCESS;
- }
-
- /* Read 6 bytes starting at xyz_reg */
- ret = raw_read_n(s->port, s->i2c_spi_addr_flags,
- get_xyz_reg(s->type), data, 6);
-
- if (ret != EC_SUCCESS) {
- CPRINTS("%s: type:0x%X RD XYZ Error %d", s->name, s->type, ret);
- return ret;
- }
- normalize(s, v, data);
- return EC_SUCCESS;
-}
-
-static int init(const struct motion_sensor_t *s)
-{
- int ret = 0, tmp, i;
- struct accelgyro_saved_data_t *saved_data = BMI160_GET_SAVED_DATA(s);
-
- ret = raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_CHIP_ID, &tmp);
- if (ret)
- return EC_ERROR_UNKNOWN;
-
- if (tmp != BMI160_CHIP_ID_MAJOR && tmp != BMI168_CHIP_ID_MAJOR) {
- /* The device may be lock on paging mode. Try to unlock it. */
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_REG, BMI160_CMD_EXT_MODE_EN_B0);
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_REG, BMI160_CMD_EXT_MODE_EN_B1);
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_REG, BMI160_CMD_EXT_MODE_EN_B2);
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_EXT_MODE_ADDR, BMI160_CMD_PAGING_EN);
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_EXT_MODE_ADDR, 0);
- return EC_ERROR_ACCESS_DENIED;
- }
-
-
- if (s->type == MOTIONSENSE_TYPE_ACCEL) {
- struct bmi160_drv_data_t *data = BMI160_GET_DATA(s);
-
- /* Reset the chip to be in a good state */
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_REG, BMI160_CMD_SOFT_RESET);
- msleep(1);
- data->flags &= ~(BMI160_FLAG_SEC_I2C_ENABLED |
- (BMI160_FIFO_ALL_MASK <<
- BMI160_FIFO_FLAG_OFFSET));
-#ifdef CONFIG_GESTURE_HOST_DETECTION
- data->enabled_activities = 0;
- data->disabled_activities = 0;
-#ifdef CONFIG_GESTURE_SIGMO
- data->disabled_activities |=
- 1 << MOTIONSENSE_ACTIVITY_SIG_MOTION;
-#endif
-#ifdef CONFIG_GESTURE_SENSOR_DOUBLE_TAP
- data->disabled_activities |=
- 1 << MOTIONSENSE_ACTIVITY_DOUBLE_TAP;
-#endif
-#endif
- /* To avoid gyro wakeup */
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_PMU_TRIGGER, 0);
- }
-
-#ifdef CONFIG_BMI160_SEC_I2C
- if (s->type == MOTIONSENSE_TYPE_MAG) {
- struct bmi160_drv_data_t *data = BMI160_GET_DATA(s);
-
- /*
- * To be able to configure the real magnetometer, we must set
- * the BMI160 magnetometer part (a pass through) in normal mode.
- */
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_REG, BMI160_CMD_MODE_NORMAL(s->type));
- msleep(wakeup_time[s->type]);
-
- if ((data->flags & BMI160_FLAG_SEC_I2C_ENABLED) == 0) {
- int ext_page_reg, pullup_reg;
- /* Enable secondary interface */
- /*
- * This is not part of the normal configuration but from
- * code on Bosh github repo:
- * https://github.com/BoschSensortec/BMI160_driver
- *
- * Magic command sequences
- */
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_REG, BMI160_CMD_EXT_MODE_EN_B0);
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_REG, BMI160_CMD_EXT_MODE_EN_B1);
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_REG, BMI160_CMD_EXT_MODE_EN_B2);
-
- /*
- * Change the register page to target mode, to change
- * the internal pull ups of the secondary interface.
- */
- raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_EXT_MODE_ADDR, &ext_page_reg);
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_EXT_MODE_ADDR,
- ext_page_reg | BMI160_CMD_TARGET_PAGE);
- raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_EXT_MODE_ADDR, &ext_page_reg);
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_EXT_MODE_ADDR,
- ext_page_reg | BMI160_CMD_PAGING_EN);
- raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_COM_C_TRIM_ADDR, &pullup_reg);
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_COM_C_TRIM_ADDR,
- pullup_reg | BMI160_COM_C_TRIM);
- raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_EXT_MODE_ADDR, &ext_page_reg);
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_EXT_MODE_ADDR,
- ext_page_reg & ~BMI160_CMD_TARGET_PAGE);
- raw_read8(s->port, s->i2c_spi_addr_flags,
- BMI160_CMD_EXT_MODE_ADDR, &ext_page_reg);
-
- /* Set the i2c address of the compass */
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_MAG_IF_0,
- I2C_GET_ADDR(
- CONFIG_ACCELGYRO_SEC_ADDR_FLAGS)
- << 1);
-
- /* Enable the secondary interface as I2C */
- ret = raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_IF_CONF,
- BMI160_IF_MODE_AUTO_I2C <<
- BMI160_IF_MODE_OFF);
- data->flags |= BMI160_FLAG_SEC_I2C_ENABLED;
- }
-
-
- bmi160_sec_access_ctrl(s->port, s->i2c_spi_addr_flags, 1);
-
- ret = bmm150_init(s);
- if (ret)
- /* Leave the compass open for tinkering. */
- return ret;
-
- /* Leave the address for reading the data */
- raw_write8(s->port, s->i2c_spi_addr_flags,
- BMI160_MAG_I2C_READ_ADDR, BMM150_BASE_DATA);
- /*
- * Put back the secondary interface in normal mode.
- * BMI160 will poll based on the configure ODR.
- */
- bmi160_sec_access_ctrl(s->port, s->i2c_spi_addr_flags, 0);
-
- /*
- * Clean interrupt event that may have occurred while the
- * BMI160 was in management mode.
- */
- task_set_event(TASK_ID_MOTIONSENSE,
- CONFIG_ACCELGYRO_BMI160_INT_EVENT, 0);
- }
-#endif
-
- for (i = X; i <= Z; i++)
- saved_data->scale[i] = MOTION_SENSE_DEFAULT_SCALE;
- /*
- * The sensor is in Suspend mode at init,
- * so set data rate to 0.
- */
- saved_data->odr = 0;
- set_range(s, s->default_range, 0);
-
- if (s->type == MOTIONSENSE_TYPE_ACCEL) {
-#ifdef CONFIG_ACCEL_INTERRUPTS
- ret = config_interrupt(s);
-#endif
- }
-
- return sensor_init_done(s);
-}
-
-const struct accelgyro_drv bmi160_drv = {
- .init = init,
- .read = read,
- .set_range = set_range,
- .get_range = get_range,
- .get_resolution = get_resolution,
- .set_data_rate = set_data_rate,
- .get_data_rate = get_data_rate,
- .set_offset = set_offset,
- .get_scale = get_scale,
- .set_scale = set_scale,
- .get_offset = get_offset,
- .perform_calib = perform_calib,
-#ifdef CONFIG_ACCEL_INTERRUPTS
- .irq_handler = irq_handler,
-#endif
-#ifdef CONFIG_GESTURE_HOST_DETECTION
- .manage_activity = manage_activity,
- .list_activities = list_activities,
-#endif
-};
-
-#ifdef CONFIG_CMD_I2C_STRESS_TEST_ACCEL
-struct i2c_stress_test_dev bmi160_i2c_stress_test_dev = {
- .reg_info = {
- .read_reg = BMI160_CHIP_ID,
- .read_val = BMI160_CHIP_ID_MAJOR,
- .write_reg = BMI160_PMU_TRIGGER,
- },
- .i2c_read = &raw_read8,
- .i2c_write = &raw_write8,
-};
-#endif /* CONFIG_CMD_I2C_STRESS_TEST_ACCEL */
-
-int bmi160_get_sensor_temp(int idx, int *temp_ptr)
-{
- struct motion_sensor_t *s = &motion_sensors[idx];
- int16_t temp;
- int ret;
-
- ret = raw_read_n(s->port, s->i2c_spi_addr_flags,
- BMI160_TEMPERATURE_0,
- (uint8_t *)&temp, sizeof(temp));
-
- if (ret || temp == BMI160_INVALID_TEMP)
- return EC_ERROR_NOT_POWERED;
-
- *temp_ptr = C_TO_K(23 + ((temp + 256) >> 9));
- return 0;
-}