diff options
author | Bhanu Prakash Maiya <bhanumaiya@google.com> | 2021-06-22 21:33:33 -0700 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2022-08-31 02:41:13 +0000 |
commit | e32c8af4f94bb584c65b56d8ec48607e686bac13 (patch) | |
tree | 7c8b3dcade15952d7e36309fd3b066f3001a7a04 | |
parent | 85baaa1b82cd56d2274b5650938488fca7a3fefe (diff) | |
download | chrome-ec-e32c8af4f94bb584c65b56d8ec48607e686bac13.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 Pazquel360
EC commands:
> accelinfo
> accelread
Signed-off-by: Bhanu Prakash Maiya <bhanumaiya@chromium.org>
Change-Id: I8117283e54980379989fb01f68c29b7d6c501eca
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2981465
Reviewed-by: Rob Barnes <robbarnes@google.com>
Commit-Queue: Rob Barnes <robbarnes@google.com>
(cherry picked from commit 1d235e9f8e6dbc5588a32f2b0f563f11a74bfe04)
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3858895
Reviewed-by: Tang Qijun <qijun.tang@ecs.corp-partner.google.com>
Tested-by: Tang Qijun <qijun.tang@ecs.corp-partner.google.com>
Reviewed-by: Wai-Hong Tam <waihong@google.com>
Reviewed-by: Chao Gui <chaogui@google.com>
Commit-Queue: Tang Qijun <qijun.tang@ecs.corp-partner.google.com>
-rw-r--r-- | common/build.mk | 1 | ||||
-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 | ||||
-rw-r--r-- | include/config.h | 2 | ||||
-rw-r--r-- | include/ec_commands.h | 1 | ||||
-rw-r--r-- | zephyr/shim/include/config_chip.h | 5 |
8 files changed, 448 insertions, 0 deletions
diff --git a/common/build.mk b/common/build.mk index afb44107ed..2ed1e8c3e0 100644 --- a/common/build.mk +++ b/common/build.mk @@ -21,6 +21,7 @@ common-$(CONFIG_ACCELGYRO_LSM6DSM)+=math_util.o common-$(CONFIG_ACCELGYRO_LSM6DSO)+=math_util.o common-$(CONFIG_ACCEL_FIFO)+=motion_sense_fifo.o common-$(CONFIG_ACCEL_BMA255)+=math_util.o +common-$(CONFIG_ACCEL_BMA4XX)+=math_util.o common-$(CONFIG_ACCEL_LIS2DW12)+=math_util.o common-$(CONFIG_ACCEL_LIS2DH)+=math_util.o common-$(CONFIG_ACCEL_LIS2DS)+=math_util.o diff --git a/driver/accel_bma422.h b/driver/accel_bma422.h new file mode 100644 index 0000000000..f838c884f5 --- /dev/null +++ b/driver/accel_bma422.h @@ -0,0 +1,16 @@ +/* Copyright 2022 The ChromiumOS Authors. + * 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..d2b82867fb --- /dev/null +++ b/driver/accel_bma4xx.c @@ -0,0 +1,269 @@ +/* Copyright 2022 The ChromiumOS Authors. + * 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..c8a5db4752 --- /dev/null +++ b/driver/accel_bma4xx.h @@ -0,0 +1,153 @@ +/* Copyright 2022 The ChromiumOS Authors. + * 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 856d779ff9..2e394c2ac0 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 diff --git a/include/config.h b/include/config.h index 6f6942b7d7..7241e63190 100644 --- a/include/config.h +++ b/include/config.h @@ -79,8 +79,10 @@ /* Specify type of accelerometers attached. */ #undef CONFIG_ACCEL_BMA255 +#undef CONFIG_ACCEL_BMA4XX #undef CONFIG_ACCEL_KXCJ9 #undef CONFIG_ACCEL_KX022 + /* * lis2dh/lis2de/lng2dm have the same register interface but different * supported resolution. In normal mode, lis2dh works in 10-bit resolution, diff --git a/include/ec_commands.h b/include/ec_commands.h index 18a9fb0842..675dfcb4ec 100644 --- a/include/ec_commands.h +++ b/include/ec_commands.h @@ -2601,6 +2601,7 @@ enum motionsensor_chip { MOTIONSENSE_CHIP_BMI260 = 24, MOTIONSENSE_CHIP_ICM426XX = 25, MOTIONSENSE_CHIP_ICM42607 = 26, + MOTIONSENSE_CHIP_BMA422 = 27, MOTIONSENSE_CHIP_MAX, }; diff --git a/zephyr/shim/include/config_chip.h b/zephyr/shim/include/config_chip.h index e673630cb6..b637960060 100644 --- a/zephyr/shim/include/config_chip.h +++ b/zephyr/shim/include/config_chip.h @@ -82,6 +82,11 @@ #endif /* CONFIG_PLATFORM_EC_TIMER */ +#undef CONFIG_ACCEL_BMA4XX +#ifdef CONFIG_PLATFORM_EC_ACCEL_BMA4XX +#define CONFIG_ACCEL_BMA4XX +#endif + /* eSPI signals */ #ifdef CONFIG_PLATFORM_EC_ESPI_VW_SLP_S3 #define CONFIG_HOSTCMD_ESPI_VW_SLP_S3 |