diff options
author | Karthikeyan Ramasubramanian <kramasub@chromium.org> | 2018-10-01 14:26:17 -0600 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-10-19 15:07:41 -0700 |
commit | b1753218caff75713e8a5ddf58344bf4cec21941 (patch) | |
tree | 869d5d3d9ce1815f967db05fdb8b7c53f4b73aeb /driver | |
parent | 58f4737ae117f0bd5e2a3a7ea35ef26791bdd146 (diff) | |
download | chrome-ec-b1753218caff75713e8a5ddf58344bf4cec21941.tar.gz |
driver/mag_lis2mdl: Add LIS2MDL magnetometer module
Add support for LIS2MDL magnetometer module in cascade mode to LSM6DSM
accelerometer module.
BRANCH=none
BUG=b:115587004
TEST=Collect magnetometer readings through ectool motionsense
Change-Id: I06d11777543f14a557ebe6524f7ede15440f1f1e
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1257504
Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-by: Jett Rink <jettrink@chromium.org>
Diffstat (limited to 'driver')
-rw-r--r-- | driver/build.mk | 1 | ||||
-rw-r--r-- | driver/mag_lis2mdl.c | 143 | ||||
-rw-r--r-- | driver/mag_lis2mdl.h | 36 |
3 files changed, 180 insertions, 0 deletions
diff --git a/driver/build.mk b/driver/build.mk index a9f266ba16..5d48edb242 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -15,6 +15,7 @@ driver-$(CONFIG_ACCELGYRO_BMI160)+=accelgyro_bmi160.o driver-$(CONFIG_MAG_BMI160_BMM150)+=mag_bmm150.o driver-$(CONFIG_ACCELGYRO_LSM6DSM)+=accelgyro_lsm6dsm.o stm_mems_common.o driver-$(CONFIG_ACCEL_LIS2D_COMMON)+=accel_lis2dh.o stm_mems_common.o +driver-$(CONFIG_MAG_LIS2MDL)+=mag_lis2mdl.o driver-$(CONFIG_SENSORHUB_LSM6DSM)+=sensorhub_lsm6dsm.o driver-$(CONFIG_SYNC)+=sync.o diff --git a/driver/mag_lis2mdl.c b/driver/mag_lis2mdl.c new file mode 100644 index 0000000000..de0650cd38 --- /dev/null +++ b/driver/mag_lis2mdl.c @@ -0,0 +1,143 @@ +/* Copyright 2018 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. + */ + +/** + * LIS2MDL magnetometer module for Chrome EC. + * This driver supports LIS2MDL magnetometer in cascade with LSM6DSx (x stands + * for L or M) accel/gyro module. + */ + +#include "common.h" +#include "driver/mag_lis2mdl.h" +#include "driver/sensorhub_lsm6dsm.h" +#include "driver/stm_mems_common.h" +#include "task.h" + +#ifndef CONFIG_SENSORHUB_LSM6DSM +#error "Need Sensor Hub LSM6DSM support" +#endif + +static int irq_handler(struct motion_sensor_t *s, uint32_t *event) +{ + if (!s->parent) { + /* Sensor is not supported in direct connection/slave mode */ + return EC_ERROR_UNIMPLEMENTED; + } + /* + * Magnetometer in cascade mode. The main sensor should take + * care of interrupt situation. + */ + return EC_SUCCESS; +} + +static int set_data_rate(const struct motion_sensor_t *s, int rate, int rnd) +{ + int ret = EC_ERROR_UNIMPLEMENTED; + /* + * Since 'stprivate_data a_data;' is the first member of lsm6dsm_data, + * the address of lsm6dsm_data is the same as a_data's. Using this + * fact, we can do the following conversion. This conversion is equal + * to: + * struct lsm6dsm_data *lsm_data = s->drv_data; + * struct stprivate_data *data = &lsm_data->a_data; + */ + struct stprivate_data *data = s->drv_data; + + if (!s->parent) + return ret; + + mutex_lock(s->mutex); + ret = sensorhub_set_ext_data_rate(s->parent, rate, rnd, + &data->base.odr); + mutex_unlock(s->mutex); + + return ret; +} + +static int set_range(const struct motion_sensor_t *s, int range, int rnd) +{ + struct stprivate_data *data = s->drv_data; + + if (range != LIS2MDL_RANGE) + return EC_ERROR_INVAL; + + /* Range is fixed to LIS2MDL_RANGE by hardware */ + data->base.range = LIS2MDL_RANGE; + return EC_SUCCESS; +} + +static int get_range(const struct motion_sensor_t *s) +{ + struct stprivate_data *data = s->drv_data; + + return data->base.range; +} + +static int read(const struct motion_sensor_t *s, intv3_t v) +{ + int ret = EC_ERROR_UNIMPLEMENTED; + + if (!s->parent) + return ret; + + mutex_lock(s->mutex); + ret = sensorhub_slv0_data_read(s->parent, v); + mutex_unlock(s->mutex); + + return ret; +} + +static int init(const struct motion_sensor_t *s) +{ + int ret = EC_ERROR_UNIMPLEMENTED; + struct stprivate_data *data = s->drv_data; + + if (!s->parent) + return ret; + + mutex_lock(s->mutex); + /* Magnetometer in cascade mode */ + ret = sensorhub_check_and_rst(s->parent, s->addr, + LIS2MDL_WHO_AM_I_REG, LIS2MDL_WHO_AM_I, + LIS2MDL_CFG_REG_A_ADDR, LIS2MDL_SW_RESET); + if (ret != EC_SUCCESS) + goto err_unlock; + + ret = sensorhub_config_ext_reg(s->parent, s->addr, + LIS2MDL_CFG_REG_A_ADDR, + LIS2MDL_ODR_100HZ | LIS2MDL_CONT_MODE); + if (ret != EC_SUCCESS) + goto err_unlock; + + ret = sensorhub_config_slv0_read(s->parent, s->addr, + LIS2MDL_OUT_REG, OUT_XYZ_SIZE); + if (ret != EC_SUCCESS) + goto err_unlock; + + /* Set default resolution to 16 bit */ + data->resol = LIS2MDL_RESOLUTION; + /* Range is fixed to LIS2MDL_RANGE by hardware */ + data->base.range = LIS2MDL_RANGE; + mutex_unlock(s->mutex); + + return sensor_init_done(s); + +err_unlock: + mutex_unlock(s->mutex); + return ret; +} + +const struct accelgyro_drv lis2mdl_drv = { + .init = init, + .read = read, + .set_range = set_range, + .get_range = get_range, + .get_resolution = st_get_resolution, + .set_data_rate = set_data_rate, + .get_data_rate = st_get_data_rate, + .set_offset = st_set_offset, + .get_offset = st_get_offset, + .irq_handler = irq_handler, +}; diff --git a/driver/mag_lis2mdl.h b/driver/mag_lis2mdl.h new file mode 100644 index 0000000000..ae7907c225 --- /dev/null +++ b/driver/mag_lis2mdl.h @@ -0,0 +1,36 @@ +/* Copyright 2018 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. + */ + +/* LIS2MSL magnetometer module for Chrome EC */ + +#ifndef __CROS_EC_MAG_LIS2MDL_H +#define __CROS_EC_MAG_LIS2MDL_H + +#define LIS2MDL_I2C_ADDR(__x) (__x << 1) + +#define LIS2MDL_ADDR0 LIS2MDL_I2C_ADDR(0x1e) +#define LIS2MDL_ADDR1 LIS2MDL_I2C_ADDR(0x1f) + +#define LIS2MDL_WHO_AM_I_REG 0x4f +#define LIS2MDL_WHO_AM_I 0x40 + +#define LIS2MDL_CFG_REG_A_ADDR 0x60 +#define LIS2MDL_SW_RESET 0x20 +#define LIS2MDL_ODR_100HZ 0xc +#define LIS2MDL_CONT_MODE 0x0 + +#define LIS2MDL_STATUS_REG 0x67 +#define LIS2MDL_OUT_REG 0x68 + +#define LIS2MDL_RANGE 4915 +#define LIS2MDL_RESOLUTION 16 + +#define LIS2MDL_ODR_MIN_VAL 10000 +#define LIS2MDL_ODR_MAX_VAL 100000 + +extern const struct accelgyro_drv lis2mdl_drv; + +#endif /* __CROS_EC_MAG_LIS2MDL_H */ + |