summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBhanu Prakash Maiya <bhanumaiya@google.com>2021-06-22 21:33:33 -0700
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-08-31 02:41:13 +0000
commite32c8af4f94bb584c65b56d8ec48607e686bac13 (patch)
tree7c8b3dcade15952d7e36309fd3b066f3001a7a04
parent85baaa1b82cd56d2274b5650938488fca7a3fefe (diff)
downloadchrome-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.mk1
-rw-r--r--driver/accel_bma422.h16
-rw-r--r--driver/accel_bma4xx.c269
-rw-r--r--driver/accel_bma4xx.h153
-rw-r--r--driver/build.mk1
-rw-r--r--include/config.h2
-rw-r--r--include/ec_commands.h1
-rw-r--r--zephyr/shim/include/config_chip.h5
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, &reg_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