summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorKarthikeyan Ramasubramanian <kramasub@chromium.org>2018-10-01 14:26:17 -0600
committerchrome-bot <chrome-bot@chromium.org>2018-10-19 15:07:41 -0700
commitb1753218caff75713e8a5ddf58344bf4cec21941 (patch)
tree869d5d3d9ce1815f967db05fdb8b7c53f4b73aeb /driver
parent58f4737ae117f0bd5e2a3a7ea35ef26791bdd146 (diff)
downloadchrome-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.mk1
-rw-r--r--driver/mag_lis2mdl.c143
-rw-r--r--driver/mag_lis2mdl.h36
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 */
+