diff options
author | Bhanu Prakash Maiya <bhanumaiya@google.com> | 2021-06-22 21:33:33 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2021-06-28 23:31:49 +0000 |
commit | 1d235e9f8e6dbc5588a32f2b0f563f11a74bfe04 (patch) | |
tree | 12114cac072f6b1d87534c87dcfdcdd3eed361ea /driver | |
parent | bca2d153c7710465541b19610d98f00dba39b44e (diff) | |
download | chrome-ec-1d235e9f8e6dbc5588a32f2b0f563f11a74bfe04.tar.gz |
driver: bma4xx: Add support for BMA422 sensor
BMA422 is one of BMA4XX series accel sensor series.
Adding defines, driver from Bosch APIs based initial patches
submitted by Bosch team members in crrev/c/2894333.
Reference code can be found on
https://github.com/BoschSensortec/BMA423-Sensor-API.
BRANCH=none
BUG=b:178400750
TEST=Accel implementation tested on Guybrush
EC commands:
> accelinfo
> acceldata
Signed-off-by: Bhanu Prakash Maiya <bhanumaiya@chromium.org>
Change-Id: I8117283e54980379989fb01f68c29b7d6c501eca
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2981465
Tested-by: Bhanu Prakash Maiya <bhanumaiya@google.com>
Auto-Submit: Bhanu Prakash Maiya <bhanumaiya@google.com>
Commit-Queue: Rob Barnes <robbarnes@google.com>
Reviewed-by: Rob Barnes <robbarnes@google.com>
Diffstat (limited to 'driver')
-rw-r--r-- | driver/accel_bma422.h | 16 | ||||
-rw-r--r-- | driver/accel_bma4xx.c | 269 | ||||
-rw-r--r-- | driver/accel_bma4xx.h | 153 | ||||
-rw-r--r-- | driver/build.mk | 1 |
4 files changed, 439 insertions, 0 deletions
diff --git a/driver/accel_bma422.h b/driver/accel_bma422.h new file mode 100644 index 0000000000..0ab580235c --- /dev/null +++ b/driver/accel_bma422.h @@ -0,0 +1,16 @@ +/* Copyright 2021 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. + */ + +/* BMA422 gsensor module for Chrome EC */ + +#ifndef __CROS_EC_ACCEL_BMA422_H +#define __CROS_EC_ACCEL_BMA422_H + +#include "accel_bma4xx.h" + +/* Chip ID of BMA422 */ +#define BMA422_CHIP_ID 0x12 + +#endif /* __CROS_EC_ACCEL_BMA422_H */ diff --git a/driver/accel_bma4xx.c b/driver/accel_bma4xx.c new file mode 100644 index 0000000000..13e174b93c --- /dev/null +++ b/driver/accel_bma4xx.c @@ -0,0 +1,269 @@ +/* Copyright 2021 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. + */ + +/* + * Bosch Accelerometer driver for Chrome EC + * + * Supported: BMA422 + */ + +#include "accelgyro.h" +#include "accel_bma422.h" +#include "common.h" +#include "console.h" +#include "i2c.h" +#include "math_util.h" +#include "spi.h" +#include "task.h" +#include "util.h" + +#define CPUTS(outstr) cputs(CC_ACCEL, outstr) +#define CPRINTF(format, args...) cprintf(CC_ACCEL, format, ## args) + +/** + * Read 8bit register from accelerometer. + */ +static inline int bma4_read8(const struct motion_sensor_t *s, const int reg, + int *data_ptr) +{ + return i2c_read8(s->port, s->i2c_spi_addr_flags, reg, data_ptr); +} + +/** + * Write 8bit register from accelerometer. + */ +static inline int bma4_write8(const struct motion_sensor_t *s, const int reg, + int data) +{ + int ret; + + ret = i2c_write8(s->port, s->i2c_spi_addr_flags, reg, data); + + /* + * From Bosch: BMA 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. + */ + usleep(450); + + return ret; +} + +/* + * Set specific bit set to certain value of a 8-bit reg. + */ +static inline int bma4_set_reg8(const struct motion_sensor_t *s, int reg, + uint8_t bits, int mask) +{ + int val; + + RETURN_ERROR(bma4_read8(s, reg, &val)); + + val = (val & ~mask) | bits; + + return bma4_write8(s, reg, val); +} + +static int set_range(struct motion_sensor_t *s, int range, int round) +{ + int ret, range_reg_val; + + range_reg_val = BMA4_RANGE_TO_REG(range); + + /* + * If rounding flag is set then set the range_val to nearest + * valid value. + */ + if ((BMA4_REG_TO_RANGE(range_reg_val) < range) && round) + range_reg_val = BMA4_RANGE_TO_REG(range * 2); + + mutex_lock(s->mutex); + + /* Determine the new value of control reg and attempt to write it. */ + ret = bma4_set_reg8(s, BMA4_ACCEL_RANGE_ADDR, range_reg_val, + BMA4_ACCEL_RANGE_MSK); + + /* If successfully written, then save the range. */ + if (ret == EC_SUCCESS) + s->current_range = BMA4_REG_TO_RANGE(range_reg_val); + + mutex_unlock(s->mutex); + + return ret; +} + +static int get_resolution(const struct motion_sensor_t *s) +{ + return BMA4_12_BIT_RESOLUTION; +} + +static int set_data_rate(const struct motion_sensor_t *s, int rate, int round) +{ + int ret, odr_reg_val; + struct accelgyro_saved_data_t *data = s->drv_data; + + odr_reg_val = BMA4_ODR_TO_REG(rate); + + if ((BMA4_REG_TO_ODR(odr_reg_val) < rate) && round) + odr_reg_val = BMA4_ODR_TO_REG(rate * 2); + + mutex_lock(s->mutex); + + /* Determine the new value of control reg and attempt to write it. */ + ret = bma4_set_reg8(s, BMA4_ACCEL_CONFIG_ADDR, odr_reg_val, + BMA4_ACCEL_ODR_MSK); + + /* If successfully written, then save the new data rate. */ + if (ret == EC_SUCCESS) + data->odr = BMA4_REG_TO_ODR(odr_reg_val); + + mutex_unlock(s->mutex); + + return ret; +} + +static int get_data_rate(const struct motion_sensor_t *s) +{ + struct accelgyro_saved_data_t *data = s->drv_data; + + return data->odr; +} + +static int set_offset(const struct motion_sensor_t *s, const int16_t *offset, + int16_t temp) +{ + int i, ret; + intv3_t v = { offset[X], offset[Y], offset[Z] }; + + rotate_inv(v, *s->rot_standard_ref, v); + + mutex_lock(s->mutex); + + /* Offset from host is in 1/1024g, 1/128g internally. */ + for (i = X; i <= Z; i++) { + ret = bma4_write8(s, BMA4_OFFSET_0_ADDR + i, v[i] / 8); + + if (ret) { + mutex_unlock(s->mutex); + return ret; + } + } + + mutex_unlock(s->mutex); + + return ret; +} + +static int get_offset(const struct motion_sensor_t *s, int16_t *offset, + int16_t *temp) +{ + int i, val, ret; + intv3_t v; + + mutex_lock(s->mutex); + + for (i = X; i <= Z; i++) { + ret = bma4_read8(s, BMA4_OFFSET_0_ADDR + i, &val); + + if (ret) { + mutex_unlock(s->mutex); + return ret; + } + + v[i] = (int8_t)val * 8; + } + + mutex_unlock(s->mutex); + + rotate(v, *s->rot_standard_ref, v); + offset[X] = v[X]; + offset[Y] = v[Y]; + offset[Z] = v[Z]; + + *temp = EC_MOTION_SENSE_INVALID_CALIB_TEMP; + + return EC_SUCCESS; +} + +static int read(const struct motion_sensor_t *s, intv3_t v) +{ + uint8_t acc[6]; + int ret, i; + + mutex_lock(s->mutex); + + /* Read 6 bytes starting at X_AXIS_LSB. */ + ret = i2c_read_block(s->port, s->i2c_spi_addr_flags, + BMA4_DATA_8_ADDR, acc, 6); + + mutex_unlock(s->mutex); + + if (ret) + return ret; + + /* + * Convert acceleration to a signed 16-bit number. Note, based on + * the order of the registers: + * + * acc[0] = X_AXIS_LSB -> bit 7~4 for value, bit 0 for new data bit + * acc[1] = X_AXIS_MSB + * acc[2] = Y_AXIS_LSB -> bit 7~4 for value, bit 0 for new data bit + * acc[3] = Y_AXIS_MSB + * acc[4] = Z_AXIS_LSB -> bit 7~4 for value, bit 0 for new data bit + * acc[5] = Z_AXIS_MSB + */ + for (i = X; i <= Z; i++) + v[i] = (((int8_t)acc[i * 2 + 1]) << 8) | (acc[i * 2] & 0xf0); + + rotate(v, *s->rot_standard_ref, v); + + return EC_SUCCESS; +} + +static int perform_calib(struct motion_sensor_t *s, int enable) +{ + /* TODO */ + return EC_ERROR_UNIMPLEMENTED; +} + +static int init(struct motion_sensor_t *s) +{ + int ret = 0, reg_val; + + /* This driver requires a mutex. Assert if mutex is not supplied. */ + ASSERT(s->mutex); + + /* Read accelerometer's CHID ID */ + RETURN_ERROR(bma4_read8(s, BMA4_CHIP_ID_ADDR, ®_val)); + + if (s->chip != MOTIONSENSE_CHIP_BMA422 || reg_val != BMA422_CHIP_ID) + return EC_ERROR_HW_INTERNAL; + + mutex_lock(s->mutex); + + /* Enable accelerometer */ + ret = bma4_set_reg8(s, BMA4_POWER_CTRL_ADDR, BMA4_POWER_ACC_EC_MASK, + BMA4_POWER_ACC_EC_MASK); + + mutex_unlock(s->mutex); + + if (ret) + return ret; + + return sensor_init_done(s); +} + +const struct accelgyro_drv bma4_accel_drv = { + .init = init, + .read = read, + .set_range = set_range, + .get_resolution = get_resolution, + .set_data_rate = set_data_rate, + .get_data_rate = get_data_rate, + .set_offset = set_offset, + .get_offset = get_offset, + .perform_calib = perform_calib, +}; diff --git a/driver/accel_bma4xx.h b/driver/accel_bma4xx.h new file mode 100644 index 0000000000..72c8265241 --- /dev/null +++ b/driver/accel_bma4xx.h @@ -0,0 +1,153 @@ +/* Copyright 2021 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. + */ + +/* BMA4XX gsensor module for Chrome EC */ + +#ifndef __CROS_EC_ACCEL_BMA4XX_H +#define __CROS_EC_ACCEL_BMA4XX_H + +#define BMA4_I2C_ADDR_PRIMARY 0x18 +#define BMA4_I2C_ADDR_SECONDARY 0x19 +#define BMA4_I2C_BMM150_ADDR 0x10 + +/* Chip-specific registers */ +#define BMA4_CHIP_ID_ADDR 0x00 +#define BMA4_CHIP_ID_MIN 0x10 +#define BMA4_CHIP_ID_MAX 0x15 + +#define BMA4_ERROR_ADDR 0x02 +#define BMA4_FATAL_ERR_MSK 0x01 +#define BMA4_CMD_ERR_POS 1 +#define BMA4_CMD_ERR_MSK 0x02 +#define BMA4_ERR_CODE_POS 2 +#define BMA4_ERR_CODE_MSK 0x1C +#define BMA4_FIFO_ERR_POS 6 +#define BMA4_FIFO_ERR_MSK 0x40 +#define BMA4_AUX_ERR_POS 7 +#define BMA4_AUX_ERR_MSK 0x80 + +#define BMA4_STATUS_ADDR 0x03 +#define BMA4_STAT_DATA_RDY_ACCEL_POS 7 +#define BMA4_STAT_DATA_RDY_ACCEL_MSK 0x80 + +#define BMA4_DATA_0_ADDR 0x0A +#define BMA4_DATA_8_ADDR 0x12 + +#define BMA4_SENSORTIME_0_ADDR 0x18 +#define BMA4_INT_STAT_0_ADDR 0x1C +#define BMA4_INT_STAT_1_ADDR 0x1D +#define BMA4_STEP_CNT_OUT_0_ADDR 0x1E +#define BMA4_HIGH_G_OUT_ADDR 0x1F +#define BMA4_TEMPERATURE_ADDR 0x22 + +#define BMA4_FIFO_LENGTH_0_ADDR 0x24 +#define BMA4_FIFO_DATA_ADDR 0x26 +#define BMA4_ACTIVITY_OUT_ADDR 0x27 +#define BMA4_ORIENTATION_OUT_ADDR 0x28 + +#define BMA4_INTERNAL_STAT 0x2A +#define BMA4_ASIC_INITIALIZED 0x01 + +#define BMA4_ACCEL_CONFIG_ADDR 0x40 +#define BMA4_ACCEL_ODR_MSK 0x0F +#define BMA4_ACCEL_BW_POS 4 +#define BMA4_ACCEL_BW_MSK 0x70 +#define BMA4_ACCEL_PERFMODE_POS 7 +#define BMA4_ACCEL_PERFMODE_MSK 0x80 +#define BMA4_OUTPUT_DATA_RATE_0_78HZ 0x01 +#define BMA4_OUTPUT_DATA_RATE_1_56HZ 0x02 +#define BMA4_OUTPUT_DATA_RATE_3_12HZ 0x03 +#define BMA4_OUTPUT_DATA_RATE_6_25HZ 0x04 +#define BMA4_OUTPUT_DATA_RATE_12_5HZ 0x05 +#define BMA4_OUTPUT_DATA_RATE_25HZ 0x06 +#define BMA4_OUTPUT_DATA_RATE_50HZ 0x07 +#define BMA4_OUTPUT_DATA_RATE_100HZ 0x08 +#define BMA4_OUTPUT_DATA_RATE_200HZ 0x09 +#define BMA4_OUTPUT_DATA_RATE_400HZ 0x0A +#define BMA4_OUTPUT_DATA_RATE_800HZ 0x0B +#define BMA4_OUTPUT_DATA_RATE_1600HZ 0x0C +#define BMA4_ACCEL_OSR4_AVG1 0 +#define BMA4_ACCEL_OSR2_AVG2 1 +#define BMA4_ACCEL_NORMAL_AVG4 2 +#define BMA4_ACCEL_CIC_AVG8 3 +#define BMA4_ACCEL_RES_AVG16 4 +#define BMA4_ACCEL_RES_AVG32 5 +#define BMA4_ACCEL_RES_AVG64 6 +#define BMA4_ACCEL_RES_AVG128 7 +#define BMA4_CIC_AVG_MODE 0 +#define BMA4_CONTINUOUS_MODE 1 + +#define BMA4_ACCEL_RANGE_ADDR 0x41 +#define BMA4_ACCEL_RANGE_MSK 0x03 +#define BMA4_ACCEL_RANGE_2G 0 +#define BMA4_ACCEL_RANGE_4G 1 +#define BMA4_ACCEL_RANGE_8G 2 +#define BMA4_ACCEL_RANGE_16G 3 + +#define BMA4_RESERVED_REG_5B_ADDR 0x5B +#define BMA4_RESERVED_REG_5C_ADDR 0x5C +#define BMA4_FEATURE_CONFIG_ADDR 0x5E +#define BMA4_INTERNAL_ERROR 0x5F +#define BMA4_IF_CONFIG_ADDR 0x6B +#define BMA4_FOC_ACC_CONF_VAL 0xB7 + +#define BMA4_NV_CONFIG_ADDR 0x70 +#define BMA4_NV_ACCEL_OFFSET_POS 3 +#define BMA4_NV_ACCEL_OFFSET_MSK 0x08 + +#define BMA4_OFFSET_0_ADDR 0x71 +#define BMA4_OFFSET_1_ADDR 0x72 +#define BMA4_OFFSET_2_ADDR 0x73 + +#define BMA4_POWER_CONF_ADDR 0x7C +#define BMA4_ADVANCE_POWER_SAVE_MSK 0x01 + +#define BMA4_POWER_CTRL_ADDR 0x7D +#define BMA4_ACCEL_ENABLE_POS 2 +#define BMA4_ACCEL_ENABLE_MSK 0x04 +#define BMA4_ENABLE 0x01 +#define BMA4_DISABLE 0x00 + +#define BMA4_POWER_ACC_EC_MASK 0x4 + +#define BMA4_CMD_ADDR 0x7E +#define BMA4_NVM_PROG 0xA0 +#define BMA4_FIFO_FLUSH 0xB0 +#define BMA4_SOFT_RESET 0xB6 + +/* Other definitions */ +#define BMA4_X_AXIS 0 +#define BMA4_Y_AXIS 1 +#define BMA4_Z_AXIS 2 + +#define BMA4_12_BIT_RESOLUTION 12 +#define BMA4_14_BIT_RESOLUTION 14 +#define BMA4_16_BIT_RESOLUTION 16 + +/* Min and Max sampling frequency in mHz */ +#define BMA4_ACCEL_MIN_FREQ 12500 +#define BMA4_ACCEL_MAX_FREQ MOTION_MAX_SENSOR_FREQUENCY(1600000, 6250) + +#define BMA4_RANGE_TO_REG(_range) \ + ((_range) < 8 ? BMA4_ACCEL_RANGE_2G + ((_range) / 4) : \ + BMA4_ACCEL_RANGE_8G + ((_range) / 16)) + +#define BMA4_REG_TO_RANGE(_reg) \ + ((_reg) < BMA4_ACCEL_RANGE_8G ? 2 + (_reg) * 2 : \ + 8 + ((_reg) - BMA4_ACCEL_RANGE_8G) * 8) + +#define BMA4_ODR_TO_REG(_odr) \ + ((_odr) < 125000 ? \ + BMA4_OUTPUT_DATA_RATE_0_78HZ + __fls(((_odr) * 10) / 7800) : \ + BMA4_OUTPUT_DATA_RATE_25HZ + __fls((_odr) / 25000)) + +#define BMA4_REG_TO_ODR(_reg) \ + ((_reg) < BMA4_OUTPUT_DATA_RATE_25HZ ? \ + (7800 << ((_reg) - BMA4_OUTPUT_DATA_RATE_0_78HZ)) / 10 : \ + 25000 << ((_reg) - BMA4_OUTPUT_DATA_RATE_25HZ)) + +extern const struct accelgyro_drv bma4_accel_drv; + +#endif /* __CROS_EC_ACCEL_BMA4XX_H */ diff --git a/driver/build.mk b/driver/build.mk index 2c04dad6ad..3df8ecc102 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -16,6 +16,7 @@ driver-$(CONFIG_ACCEL_KX022)+=accel_kionix.o driver-$(CONFIG_ACCELGYRO_LSM6DS0)+=accelgyro_lsm6ds0.o driver-$(CONFIG_ACCELGYRO_BMI160)+=accelgyro_bmi160.o accelgyro_bmi_common.o driver-$(CONFIG_ACCELGYRO_BMI260)+=accelgyro_bmi260.o accelgyro_bmi_common.o +driver-$(CONFIG_ACCEL_BMA4XX)+=accel_bma4xx.o driver-$(CONFIG_MAG_BMI_BMM150)+=mag_bmm150.o driver-$(CONFIG_ACCELGYRO_LSM6DSM)+=accelgyro_lsm6dsm.o stm_mems_common.o driver-$(CONFIG_ACCELGYRO_LSM6DSO)+=accelgyro_lsm6dso.o stm_mems_common.o |