summaryrefslogtreecommitdiff
path: root/driver/accelgyro_bmi_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/accelgyro_bmi_common.c')
-rw-r--r--driver/accelgyro_bmi_common.c902
1 files changed, 0 insertions, 902 deletions
diff --git a/driver/accelgyro_bmi_common.c b/driver/accelgyro_bmi_common.c
deleted file mode 100644
index 2da407427e..0000000000
--- a/driver/accelgyro_bmi_common.c
+++ /dev/null
@@ -1,902 +0,0 @@
-/* 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 module for Chrome EC
- * 3D digital accelerometer & 3D digital gyroscope
- */
-
-
-#include "accelgyro.h"
-#include "console.h"
-#include "accelgyro_bmi_common.h"
-#include "mag_bmm150.h"
-#include "mag_lis2mdl.h"
-#include "i2c.h"
-#include "math_util.h"
-#include "motion_sense_fifo.h"
-#include "spi.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)
-
-#if !defined(CONFIG_ACCELGYRO_BMI160) && !defined(CONFIG_ACCELGYRO_BMI260) \
-&& !defined(CONFIG_ACCELGYRO_BMI3XX)
-#error "Must use following sensors BMI160 BMI260 BMI3XX"
-#endif
-
-#if defined(CONFIG_ACCELGYRO_BMI260) && !defined(CONFIG_ACCELGYRO_BMI160)
-#define V(s_) 1
-#elif defined(CONFIG_ACCELGYRO_BMI160) && !defined(CONFIG_ACCELGYRO_BMI260)
-#define V(s_) 0
-#else
-#define V(s_) ((s_)->chip == MOTIONSENSE_CHIP_BMI260)
-#endif
-/* Index for which table to use. */
-#if !defined(CONFIG_ACCELGYRO_BMI160) || !defined(CONFIG_ACCELGYRO_BMI260)
-#define T(s_) 0
-#else
-#define T(s_) V(s_)
-#endif
-
-/* List of range values in +/-G's and their associated register values. */
-const struct bmi_accel_param_pair g_ranges[][4] = {
-#ifdef CONFIG_ACCELGYRO_BMI160
- { {2, BMI160_GSEL_2G},
- {4, BMI160_GSEL_4G},
- {8, BMI160_GSEL_8G},
- {16, BMI160_GSEL_16G} },
-#endif
-#ifdef CONFIG_ACCELGYRO_BMI260
- { {2, BMI260_GSEL_2G},
- {4, BMI260_GSEL_4G},
- {8, BMI260_GSEL_8G},
- {16, BMI260_GSEL_16G} },
-#endif
-};
-
-/*
- * List of angular rate range values in +/-dps's
- * and their associated register values.
- */
-const struct bmi_accel_param_pair dps_ranges[][5] = {
-#ifdef CONFIG_ACCELGYRO_BMI160
- { {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} },
-#endif
-#ifdef CONFIG_ACCELGYRO_BMI260
- { {125, BMI260_DPS_SEL_125},
- {250, BMI260_DPS_SEL_250},
- {500, BMI260_DPS_SEL_500},
- {1000, BMI260_DPS_SEL_1000},
- {2000, BMI260_DPS_SEL_2000} },
-#endif
-};
-
-int bmi_get_xyz_reg(const struct motion_sensor_t *s)
-{
- switch (s->type) {
- case MOTIONSENSE_TYPE_ACCEL:
- return BMI_ACC_DATA(V(s));
- case MOTIONSENSE_TYPE_GYRO:
- return BMI_GYR_DATA(V(s));
- case MOTIONSENSE_TYPE_MAG:
- return BMI_AUX_DATA(V(s));
- default:
- return -1;
- }
-}
-
-const struct bmi_accel_param_pair *bmi_get_range_table(
- const struct motion_sensor_t *s, int *psize)
-{
- if (s->type == MOTIONSENSE_TYPE_ACCEL) {
- if (psize)
- *psize = ARRAY_SIZE(g_ranges[T(s)]);
- return g_ranges[T(s)];
- }
- if (psize)
- *psize = ARRAY_SIZE(dps_ranges[T(s)]);
- return dps_ranges[T(s)];
-}
-
-/**
- * @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)
-{
- 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
- */
-int bmi_get_engineering_val(const int reg_val,
- const struct bmi_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_ACCELGYRO_BMI_COMM_SPI
-static int bmi_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.
- */
-int bmi_read8(const int port, const uint16_t i2c_spi_addr_flags,
- const int reg, int *data_ptr)
-{
- int rv;
-
-#ifdef CONFIG_ACCELGYRO_BMI_COMM_SPI
- {
- uint8_t val;
-
- rv = bmi_spi_raw_read(ACCEL_GET_SPI_ADDR(i2c_spi_addr_flags),
- reg, &val, 1);
- if (rv == EC_SUCCESS)
- *data_ptr = val;
- }
-#else
- rv = i2c_read8(port, i2c_spi_addr_flags, reg, data_ptr);
-#endif
- return rv;
-}
-
-/**
- * Write 8bit register from accelerometer.
- */
-int bmi_write8(const int port, const uint16_t i2c_spi_addr_flags,
- const int reg, int data)
-{
- int rv;
-
-#ifdef CONFIG_ACCELGYRO_BMI_COMM_SPI
- {
- uint8_t cmd[2] = { reg, data };
-
- rv = spi_transaction(
- &spi_devices[ACCEL_GET_SPI_ADDR(i2c_spi_addr_flags)],
- cmd, 2, NULL, 0);
- }
-#else
- rv = i2c_write8(port, i2c_spi_addr_flags, reg, data);
-#endif
- /*
- * From Bosch: BMI 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 unconditionally.
- */
- msleep(1);
-
- return rv;
-}
-
-/**
- * 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)
-{
-#ifdef CONFIG_ACCELGYRO_BMI_COMM_SPI
- return bmi_spi_raw_read(ACCEL_GET_SPI_ADDR(i2c_spi_addr_flags), reg,
- (uint8_t *)data_ptr, 2);
-#else
- return i2c_read16(port, i2c_spi_addr_flags, reg, data_ptr);
-#endif
-}
-
-/**
- * Write 16bit register from accelerometer.
- */
-int bmi_write16(const int port, const uint16_t i2c_spi_addr_flags,
- const int reg, int data)
-{
- int rv = -EC_ERROR_PARAM1;
-
-#ifdef CONFIG_ACCELGYRO_BMI_COMM_SPI
- CPRINTS("%s() spi part is not implemented", __func__);
-#else
- rv = i2c_write16(port, i2c_spi_addr_flags, reg, data);
-#endif
- /*
- * From Bosch: BMI 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 unconditionally.
- */
- msleep(1);
- return rv;
-}
-
-/**
- * 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)
-{
-#ifdef CONFIG_ACCELGYRO_BMI_COMM_SPI
- return bmi_spi_raw_read(ACCEL_GET_SPI_ADDR(i2c_spi_addr_flags), reg,
- (uint8_t *)data_ptr, 4);
-#else
- return i2c_read32(port, i2c_spi_addr_flags, reg, data_ptr);
-#endif
-}
-
-/**
- * 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)
-{
-#ifdef CONFIG_ACCELGYRO_BMI_COMM_SPI
- return bmi_spi_raw_read(ACCEL_GET_SPI_ADDR(i2c_spi_addr_flags), reg,
- data_ptr, len);
-#else
- return i2c_read_block(port, i2c_spi_addr_flags, reg, data_ptr, len);
-#endif
-}
-
-/**
- * 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)
-{
- int rv = -EC_ERROR_PARAM1;
-
-#ifdef CONFIG_ACCELGYRO_BMI_COMM_SPI
- CPRINTS("%s() spi part is not implemented", __func__);
-#else
- rv = i2c_write_block(port, i2c_spi_addr_flags, reg, data_ptr, len);
-#endif
- /*
- * From Bosch: BMI 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 unconditionally.
- */
- msleep(1);
-
- return rv;
-}
-/*
- * 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)
-{
- if (enable)
- return bmi_set_reg8(s, reg, bits, 0);
- return bmi_set_reg8(s, reg, 0, bits);
-}
-
-/*
- * 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)
-{
- int ret, val;
-
- ret = bmi_read8(s->port, s->i2c_spi_addr_flags, reg, &val);
- if (ret)
- return ret;
- val = (val & ~mask) | bits;
- ret = bmi_write8(s->port, s->i2c_spi_addr_flags, reg, val);
- return ret;
-}
-
-void bmi_normalize(const struct motion_sensor_t *s, intv3_t v, uint8_t *input)
-{
- int i;
- struct accelgyro_saved_data_t *data = BMI_GET_SAVED_DATA(s);
-
- if (IS_ENABLED(CONFIG_MAG_BMI_BMM150) &&
- (s->type == MOTIONSENSE_TYPE_MAG)) {
- bmm150_normalize(s, v, input);
- } else if (IS_ENABLED(CONFIG_MAG_BMI_LIS2MDL) &&
- (s->type == MOTIONSENSE_TYPE_MAG)) {
- lis2mdl_normalize(s, v, input);
- } else {
- 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]);
-}
-
-int bmi_decode_header(struct motion_sensor_t *accel, enum fifo_header hdr,
- uint32_t last_ts, uint8_t **bp, uint8_t *ep)
-{
- if ((hdr & BMI_FH_MODE_MASK) == BMI_FH_EMPTY &&
- (hdr & BMI_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 + BMI_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 + BMI_FH_PARM_OFFSET))) {
- struct ec_response_motion_sensor_data vector;
- int *v = s->raw_xyz;
-
- vector.flags = 0;
- bmi_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;
- }
-}
-
-enum fifo_state {
- FIFO_HEADER,
- FIFO_DATA_SKIP,
- FIFO_DATA_TIME,
- FIFO_DATA_CONFIG,
-};
-
-#define BMI_FIFO_BUFFER 64
-static uint8_t bmi_buffer[BMI_FIFO_BUFFER];
-
-int bmi_load_fifo(struct motion_sensor_t *s, uint32_t last_ts)
-{
- struct bmi_drv_data_t *data = BMI_GET_DATA(s);
- uint16_t length;
- enum fifo_state state = FIFO_HEADER;
- uint8_t *bp = bmi_buffer;
- uint8_t *ep;
- uint32_t beginning;
-
- if (s->type != MOTIONSENSE_TYPE_ACCEL)
- return EC_SUCCESS;
-
- if (!(data->flags & (BMI_FIFO_ALL_MASK << BMI_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.
- */
- bmi_write8(s->port, s->i2c_spi_addr_flags, BMI_CMD_REG(V(s)),
- BMI_CMD_FIFO_FLUSH);
- return EC_SUCCESS;
- }
-
- bmi_read_n(s->port, s->i2c_spi_addr_flags, BMI_FIFO_LENGTH_0(V(s)),
- (uint8_t *)&length, sizeof(length));
- length &= BMI_FIFO_LENGTH_MASK(V(s));
-
- /*
- * We have not requested timestamp, no extra frame to read.
- * if we have too much to read, read the whole buffer.
- */
- if (length == 0) {
- /*
- * Disable this message on BMI260, due to this seems to always
- * happen after we complete to read the data.
- * TODO(chingkang): check why this happen on BMI260.
- */
- if (V(s) == 0)
- CPRINTS("unexpected empty FIFO");
- return EC_SUCCESS;
- }
-
- /* Add one byte to get an empty FIFO frame.*/
- length++;
-
- if (length > sizeof(bmi_buffer))
- CPRINTS("unexpected large FIFO: %d", length);
- length = MIN(length, sizeof(bmi_buffer));
-
- bmi_read_n(s->port, s->i2c_spi_addr_flags, BMI_FIFO_DATA(V(s)),
- bmi_buffer, length);
- beginning = *(uint32_t *)bmi_buffer;
- ep = bmi_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),
- BMI_GET_SAVED_DATA(s)->odr, beginning);
- return EC_SUCCESS;
- }
-
- while (bp < ep) {
- switch (state) {
- case FIFO_HEADER: {
- enum fifo_header hdr = *bp++;
-
- if (bmi_decode_header(s, hdr, last_ts, &bp, ep))
- continue;
- /* Other cases */
- hdr &= 0xdc;
- switch (hdr) {
- case BMI_FH_EMPTY:
- return EC_SUCCESS;
- case BMI_FH_SKIP:
- state = FIFO_DATA_SKIP;
- break;
- case BMI_FH_TIME:
- state = FIFO_DATA_TIME;
- break;
- case BMI_FH_CONFIG:
- state = FIFO_DATA_CONFIG;
- break;
- default:
- CPRINTS("Unknown header: 0x%02x @ %zd", hdr,
- bp - bmi_buffer);
- bmi_write8(s->port, s->i2c_spi_addr_flags,
- BMI_CMD_REG(V(s)),
- BMI_CMD_FIFO_FLUSH);
- return EC_ERROR_NOT_HANDLED;
- }
- break;
- }
- case FIFO_DATA_SKIP:
- CPRINTS("@ %zd - %d, skipped %d frames",
- bp - bmi_buffer, length, *bp);
- bp++;
- state = FIFO_HEADER;
- break;
- case FIFO_DATA_CONFIG:
- CPRINTS("@ %zd - %d, config change: 0x%02x",
- bp - bmi_buffer, length, *bp);
- bp++;
- if (V(s))
- state = FIFO_DATA_TIME;
- else
- 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;
-}
-
-int bmi_set_range(struct motion_sensor_t *s, int range, int rnd)
-{
- int ret, range_tbl_size;
- uint8_t reg_val, ctrl_reg;
- const struct bmi_accel_param_pair *ranges;
-
- if (s->type == MOTIONSENSE_TYPE_MAG) {
- s->current_range = range;
- return EC_SUCCESS;
- }
-
- ctrl_reg = BMI_RANGE_REG(s->type);
- ranges = bmi_get_range_table(s, &range_tbl_size);
- reg_val = bmi_get_reg_val(range, rnd, ranges, range_tbl_size);
-
- ret = bmi_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)
- s->current_range = bmi_get_engineering_val(reg_val, ranges,
- range_tbl_size);
- return ret;
-}
-
-int bmi_get_data_rate(const struct motion_sensor_t *s)
-{
- struct accelgyro_saved_data_t *data = BMI_GET_SAVED_DATA(s);
-
- return data->odr;
-}
-
-int bmi_get_offset(const struct motion_sensor_t *s, int16_t *offset,
- int16_t *temp)
-{
- int i, ret = EC_SUCCESS;
- 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.
- */
- ret = bmi_accel_get_offset(s, v);
- break;
- case MOTIONSENSE_TYPE_GYRO:
- /*
- * 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
- */
- ret = bmi_gyro_get_offset(s, v);
- break;
-#ifdef CONFIG_MAG_BMI_BMM150
- case MOTIONSENSE_TYPE_MAG:
- ret = bmm150_get_offset(s, v);
- break;
-#endif /* defined(CONFIG_MAG_BMI_BMM150) */
- default:
- for (i = X; i <= Z; i++)
- v[i] = 0;
- }
-
- if (ret != EC_SUCCESS)
- return ret;
-
- 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;
-}
-
-#ifdef CONFIG_BODY_DETECTION
-int bmi_get_rms_noise(const struct motion_sensor_t *s)
-{
- int ret;
- fp_t noise_100hz, rate, sqrt_rate_ratio;
-
- switch (s->type) {
- case MOTIONSENSE_TYPE_ACCEL:
- /* change unit of ODR to Hz to prevent INT_TO_FP() overflow */
- rate = INT_TO_FP(bmi_get_data_rate(s) / 1000);
- /*
- * Since the noise is proportional to sqrt(ODR) in BMI, and we
- * have rms noise in 100 Hz, we multiply it with the sqrt(ratio
- * of ODR to 100Hz) to get current noise.
- */
- noise_100hz = INT_TO_FP(BMI_ACCEL_RMS_NOISE_100HZ(V(s)));
- sqrt_rate_ratio =
- fp_sqrtf(fp_div(rate, INT_TO_FP(BMI_ACCEL_100HZ)));
- ret = FP_TO_INT(fp_mul(noise_100hz, sqrt_rate_ratio));
- break;
- default:
- CPRINTS("%s with gyro/mag is not implemented", __func__);
- return 0;
- }
- return ret;
-}
-#endif
-
-int bmi_get_resolution(const struct motion_sensor_t *s)
-{
- return BMI_RESOLUTION;
-}
-
-int bmi_set_scale(const struct motion_sensor_t *s, const uint16_t *scale,
- int16_t temp)
-{
- struct accelgyro_saved_data_t *data = BMI_GET_SAVED_DATA(s);
-
- data->scale[X] = scale[X];
- data->scale[Y] = scale[Y];
- data->scale[Z] = scale[Z];
- return EC_SUCCESS;
-}
-
-int bmi_get_scale(const struct motion_sensor_t *s, uint16_t *scale,
- int16_t *temp)
-{
- struct accelgyro_saved_data_t *data = BMI_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;
-}
-
-int bmi_enable_fifo(const struct motion_sensor_t *s, int enable)
-{
- struct bmi_drv_data_t *data = BMI_GET_DATA(s);
- int ret;
-
- /* FIFO start/stop collecting events */
- ret = bmi_enable_reg8(s, BMI_FIFO_CONFIG_1(V(s)),
- BMI_FIFO_SENSOR_EN(V(s), s->type), enable);
- if (ret)
- return ret;
-
- if (enable)
- data->flags |= 1 << (s->type + BMI_FIFO_FLAG_OFFSET);
- else
- data->flags &= ~(1 << (s->type + BMI_FIFO_FLAG_OFFSET));
-
- return ret;
-}
-
-int bmi_read(const struct motion_sensor_t *s, intv3_t v)
-{
- uint8_t data[6];
- int ret, status = 0;
-
- ret = bmi_read8(s->port, s->i2c_spi_addr_flags, BMI_STATUS(V(s)),
- &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 & BMI_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 = bmi_read_n(s->port, s->i2c_spi_addr_flags, bmi_get_xyz_reg(s),
- data, 6);
-
- if (ret != EC_SUCCESS) {
- CPRINTS("%s: type:0x%X RD XYZ Error %d", s->name, s->type, ret);
- return ret;
- }
- bmi_normalize(s, v, data);
- return EC_SUCCESS;
-}
-
-int bmi_read_temp(const struct motion_sensor_t *s, int *temp_ptr)
-{
- return bmi_get_sensor_temp(s - motion_sensors, temp_ptr);
-}
-
-int bmi_get_sensor_temp(int idx, int *temp_ptr)
-{
- struct motion_sensor_t *s = &motion_sensors[idx];
- int16_t temp;
- int ret;
-
- ret = bmi_read_n(s->port, s->i2c_spi_addr_flags,
- BMI_TEMPERATURE_0(V(s)), (uint8_t *)&temp,
- sizeof(temp));
-
- if (ret || temp == (int16_t)BMI_INVALID_TEMP)
- return EC_ERROR_NOT_POWERED;
-
- *temp_ptr = C_TO_K(23 + ((temp + 256) >> 9));
- return 0;
-}
-
-int bmi_get_normalized_rate(const struct motion_sensor_t *s, int rate, int rnd,
- int *normalized_rate_ptr, uint8_t *reg_val_ptr)
-{
- *reg_val_ptr = BMI_ODR_TO_REG(rate);
- *normalized_rate_ptr = BMI_REG_TO_ODR(*reg_val_ptr);
- if (rnd && (*normalized_rate_ptr < rate)) {
- (*reg_val_ptr)++;
- *normalized_rate_ptr = BMI_REG_TO_ODR(*reg_val_ptr);
- }
-
- switch (s->type) {
- case MOTIONSENSE_TYPE_ACCEL:
- if (*normalized_rate_ptr > BMI_ACCEL_MAX_FREQ ||
- *normalized_rate_ptr < BMI_ACCEL_MIN_FREQ)
- return EC_RES_INVALID_PARAM;
- break;
- case MOTIONSENSE_TYPE_GYRO:
- if (*normalized_rate_ptr > BMI_GYRO_MAX_FREQ ||
- *normalized_rate_ptr < BMI_GYRO_MIN_FREQ)
- return EC_RES_INVALID_PARAM;
- break;
-#ifdef CONFIG_MAG_BMI_BMM150
- case MOTIONSENSE_TYPE_MAG:
- /* We use the regular preset we can go about 100Hz */
- if (*reg_val_ptr > BMI_ODR_100HZ ||
- *reg_val_ptr < BMI_ODR_0_78HZ)
- return EC_RES_INVALID_PARAM;
- break;
-#endif
-
- default:
- return EC_RES_INVALID_PARAM;
- }
- return EC_SUCCESS;
-}
-
-int bmi_accel_get_offset(const struct motion_sensor_t *accel, intv3_t v)
-{
- int i, val, ret;
-
- for (i = X; i <= Z; i++) {
- ret = bmi_read8(accel->port, accel->i2c_spi_addr_flags,
- BMI_OFFSET_ACC70(V(accel)) + i, &val);
- if (ret != EC_SUCCESS)
- return ret;
-
- if (val > 0x7f)
- val = -256 + val;
- v[i] = round_divide((int64_t)val * BMI_OFFSET_ACC_MULTI_MG,
- BMI_OFFSET_ACC_DIV_MG);
- }
-
- return EC_SUCCESS;
-}
-
-int bmi_gyro_get_offset(const struct motion_sensor_t *gyro, intv3_t v)
-{
- int i, val, val98, ret;
-
- /* Read the MSB first */
- ret = bmi_read8(gyro->port, gyro->i2c_spi_addr_flags,
- BMI_OFFSET_EN_GYR98(V(gyro)), &val98);
- if (ret != EC_SUCCESS)
- return ret;
-
- for (i = X; i <= Z; i++) {
- ret = bmi_read8(gyro->port, gyro->i2c_spi_addr_flags,
- BMI_OFFSET_GYR70(V(gyro)) + i, &val);
- if (ret != EC_SUCCESS)
- return ret;
-
- val |= ((val98 >> (2 * i)) & 0x3) << 8;
- if (val > 0x1ff)
- val = -1024 + val;
- v[i] = round_divide((int64_t)val * BMI_OFFSET_GYRO_MULTI_MDS,
- BMI_OFFSET_GYRO_DIV_MDS);
- }
-
- return EC_SUCCESS;
-}
-
-int bmi_set_accel_offset(const struct motion_sensor_t *accel, intv3_t v)
-{
- int i, val, ret;
-
- for (i = X; i <= Z; ++i) {
- val = round_divide((int64_t)v[i] * BMI_OFFSET_ACC_DIV_MG,
- BMI_OFFSET_ACC_MULTI_MG);
- if (val > 127)
- val = 127;
- if (val < -128)
- val = -128;
- if (val < 0)
- val = 256 + val;
- ret = bmi_write8(accel->port, accel->i2c_spi_addr_flags,
- BMI_OFFSET_ACC70(V(accel)) + i, val);
- if (ret != EC_SUCCESS)
- return ret;
- }
-
- return EC_SUCCESS;
-}
-
-int bmi_set_gyro_offset(const struct motion_sensor_t *gyro, intv3_t v,
- int *val98_ptr)
-{
- int i, val, ret;
-
- for (i = X; i <= Z; i++) {
- val = round_divide((int64_t)v[i] * BMI_OFFSET_GYRO_DIV_MDS,
- BMI_OFFSET_GYRO_MULTI_MDS);
- if (val > 511)
- val = 511;
- if (val < -512)
- val = -512;
- if (val < 0)
- val = 1024 + val;
- ret = bmi_write8(gyro->port, gyro->i2c_spi_addr_flags,
- BMI_OFFSET_GYR70(V(gyro)) + i, val & 0xFF);
- if (ret != EC_SUCCESS)
- return ret;
-
- *val98_ptr &= ~(0x3 << (2 * i));
- *val98_ptr |= (val >> 8) << (2 * i);
- }
-
- return EC_SUCCESS;
-}
-
-#ifdef CONFIG_BMI_ORIENTATION_SENSOR
-bool motion_orientation_changed(const struct motion_sensor_t *s)
-{
- return BMI_GET_DATA(s)->orientation !=
- BMI_GET_DATA(s)->last_orientation;
-}
-
-enum motionsensor_orientation *
-motion_orientation_ptr(const struct motion_sensor_t *s)
-{
- return &BMI_GET_DATA(s)->orientation;
-}
-
-void motion_orientation_update(const struct motion_sensor_t *s)
-{
- BMI_GET_DATA(s)->last_orientation = BMI_GET_DATA(s)->orientation;
-}
-#endif
-
-int bmi_list_activities(const struct motion_sensor_t *s,
- uint32_t *enabled,
- uint32_t *disabled)
-{
- struct bmi_drv_data_t *data = BMI_GET_DATA(s);
- *enabled = data->enabled_activities;
- *disabled = data->disabled_activities;
- return EC_RES_SUCCESS;
-}