summaryrefslogtreecommitdiff
path: root/driver
diff options
context:
space:
mode:
authorNick Vaccaro <nvaccaro@chromium.org>2017-05-26 12:29:14 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-08-08 17:34:11 -0700
commite656b970e204309c1a665f154a5972ed85305911 (patch)
tree58ed84ec4144caf71a4953bae780ec60dd62037e /driver
parent8bfde69fdd9b5feb4c47c8c714416c17afe00f78 (diff)
downloadchrome-ec-e656b970e204309c1a665f154a5972ed85305911.tar.gz
sensors: add bmi160 & kionix orientation driver
BRANCH=none BUG=chromium:718919 TEST=make buildall -j works, orientation works when enabled on gru and scarlet. Change-Id: I16dcfa5d9dea39c082d98190fa1bb6e496168b17 Signed-off-by: Nick Vaccaro <nvaccaro@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/540124 Tested-by: Nick Vaccaro <nvaccaro@google.com> Reviewed-by: Gwendal Grignou <gwendal@chromium.org>
Diffstat (limited to 'driver')
-rw-r--r--driver/accel_kionix.c60
-rw-r--r--driver/accel_kionix.h21
-rw-r--r--driver/accel_kx022.h11
-rw-r--r--driver/accelgyro_bmi160.c49
-rw-r--r--driver/accelgyro_bmi160.h39
5 files changed, 178 insertions, 2 deletions
diff --git a/driver/accel_kionix.c b/driver/accel_kionix.c
index 7323abf6f0..8697a17d66 100644
--- a/driver/accel_kionix.c
+++ b/driver/accel_kionix.c
@@ -253,6 +253,12 @@ static int enable_sensor(const struct motion_sensor_t *s, int reg_val)
if (ret != EC_SUCCESS)
continue;
+#ifdef CONFIG_KX022_ORIENTATION_SENSOR
+ /* Enable tilt orientation mode if lid sensor */
+ if ((s->location == MOTIONSENSE_LOC_LID) && (V(s) == 0))
+ reg_val |= KX022_CNTL1_TPE;
+#endif
+
/* Enable accelerometer based on reg_val value. */
ret = raw_write8(s->port, s->addr, reg,
reg_val | pc1_field);
@@ -394,6 +400,55 @@ static int get_offset(const struct motion_sensor_t *s, int16_t *offset,
return EC_SUCCESS;
}
+#ifdef CONFIG_KX022_ORIENTATION_SENSOR
+static enum motionsensor_orientation kx022_convert_orientation(
+ const struct motion_sensor_t *s,
+ int orientation)
+{
+ enum motionsensor_orientation res = MOTIONSENSE_ORIENTATION_UNKNOWN;
+
+ switch (orientation) {
+ case KX022_ORIENT_PORTRAIT:
+ res = MOTIONSENSE_ORIENTATION_PORTRAIT;
+ break;
+ case KX022_ORIENT_INVERT_PORTRAIT:
+ res = MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_PORTRAIT;
+ break;
+ case KX022_ORIENT_LANDSCAPE:
+ res = MOTIONSENSE_ORIENTATION_LANDSCAPE;
+ break;
+ case KX022_ORIENT_INVERT_LANDSCAPE:
+ res = MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_LANDSCAPE;
+ break;
+ default:
+ break;
+ }
+ res = motion_sense_remap_orientation(s, res);
+ return res;
+}
+
+static int check_orientation_locked(const struct motion_sensor_t *s)
+{
+ struct kionix_accel_data *data = s->drv_data;
+ int orientation, raw_orientation;
+ int ret;
+
+ ret = raw_read8(s->port, s->addr,
+ KX022_TSCP, &raw_orientation);
+ if (ret != EC_SUCCESS)
+ return ret;
+
+ /* mask off up and down events, we don't care about those */
+ raw_orientation &= KX022_ORIENT_MASK;
+ if (raw_orientation && (raw_orientation != data->raw_orientation)) {
+ data->raw_orientation = raw_orientation;
+ orientation = kx022_convert_orientation(s, raw_orientation);
+ SET_ORIENTATION(s, orientation);
+ }
+ return ret;
+}
+#endif
+
static int read(const struct motion_sensor_t *s, vector_3_t v)
{
uint8_t acc[6];
@@ -405,6 +460,11 @@ static int read(const struct motion_sensor_t *s, vector_3_t v)
reg = KIONIX_XOUT_L(V(s));
mutex_lock(s->mutex);
ret = raw_read_multi(s->port, s->addr, reg, acc, 6);
+#ifdef CONFIG_KX022_ORIENTATION_SENSOR
+ if ((s->location == MOTIONSENSE_LOC_LID) && (V(s) == 0) &&
+ (ret == EC_SUCCESS))
+ ret = check_orientation_locked(s);
+#endif
mutex_unlock(s->mutex);
if (ret != EC_SUCCESS)
diff --git a/driver/accel_kionix.h b/driver/accel_kionix.h
index aeac666039..79d6374917 100644
--- a/driver/accel_kionix.h
+++ b/driver/accel_kionix.h
@@ -30,6 +30,11 @@ struct kionix_accel_data {
/* Current resolution of accelerometer. */
int sensor_resolution;
int16_t offset[3];
+#ifdef CONFIG_KX022_ORIENTATION_SENSOR
+ int8_t raw_orientation;
+ enum motionsensor_orientation orientation;
+ enum motionsensor_orientation last_orientation;
+#endif
};
extern const struct accelgyro_drv kionix_accel_drv;
@@ -77,4 +82,20 @@ extern const struct accelgyro_drv kionix_accel_drv;
extern struct i2c_stress_test_dev kionix_i2c_stress_test_dev;
#endif
+#ifdef CONFIG_KX022_ORIENTATION_SENSOR
+#define ORIENTATION_CHANGED(_sensor) \
+ (((struct kionix_accel_data *)(_sensor->drv_data))->orientation != \
+ ((struct kionix_accel_data *)(_sensor->drv_data))->last_orientation)
+
+#define GET_ORIENTATION(_sensor) \
+ (((struct kionix_accel_data *)(_sensor->drv_data))->orientation)
+
+#define SET_ORIENTATION(_sensor, _val) \
+ (((struct kionix_accel_data *)(_sensor->drv_data))->orientation = _val)
+
+#define SET_ORIENTATION_UPDATED(_sensor) \
+ (((struct kionix_accel_data *)(_sensor->drv_data))->last_orientation = \
+ ((struct kionix_accel_data *)(_sensor->drv_data))->orientation)
+#endif
+
#endif /* __CROS_EC_ACCEL_KIONIX_H */
diff --git a/driver/accel_kx022.h b/driver/accel_kx022.h
index 7b1ea89c43..7fd7508395 100644
--- a/driver/accel_kx022.h
+++ b/driver/accel_kx022.h
@@ -74,6 +74,17 @@
#define KX022_CNTL1_PC1 (1 << 7)
#define KX022_CNTL1_WUFE (1 << 1)
+#define KX022_CNTL1_TPE (1 << 0)
+
+/* TSCP orientations */
+#define KX022_ORIENT_PORTRAIT (1 << 2)
+#define KX022_ORIENT_INVERT_PORTRAIT (1 << 3)
+#define KX022_ORIENT_LANDSCAPE (1 << 4)
+#define KX022_ORIENT_INVERT_LANDSCAPE (1 << 5)
+#define KX022_ORIENT_MASK (KX022_ORIENT_PORTRAIT | \
+ KX022_ORIENT_INVERT_PORTRAIT | \
+ KX022_ORIENT_LANDSCAPE | \
+ KX022_ORIENT_INVERT_LANDSCAPE)
#define KX022_CNTL2_SRST (1 << 7)
diff --git a/driver/accelgyro_bmi160.c b/driver/accelgyro_bmi160.c
index e63aefcb34..dcba2ae17f 100644
--- a/driver/accelgyro_bmi160.c
+++ b/driver/accelgyro_bmi160.c
@@ -796,6 +796,16 @@ static int config_interrupt(const struct motion_sensor_t *s)
ret = raw_write8(s->port, s->addr, BMI160_INT_TAP_1,
BMI160_TAP_TH(s, CONFIG_GESTURE_TAP_THRES_MG));
#endif
+#ifdef CONFIG_BMI160_ORIENTATION_SENSOR
+ /* only use orientation sensor on the lid sensor */
+ if (s->location == MOTIONSENSE_LOC_LID) {
+ ret = raw_write8(s->port, s->addr, BMI160_INT_ORIENT_0,
+ BMI160_INT_ORIENT_0_INIT_VAL);
+ ret = raw_write8(s->port, s->addr, BMI160_INT_ORIENT_1,
+ BMI160_INT_ORIENT_1_INIT_VAL);
+ }
+#endif
+
/*
* Set a 5ms latch to be sure the EC can read the interrupt register
* properly, even when it is running more slowly.
@@ -820,6 +830,11 @@ static int config_interrupt(const struct motion_sensor_t *s)
#ifdef CONFIG_GESTURE_SENSOR_BATTERY_TAP
tmp |= BMI160_INT_D_TAP;
#endif
+#ifdef CONFIG_BMI160_ORIENTATION_SENSOR
+ /* enable orientation interrupt for lid sensor only */
+ if (s->location == MOTIONSENSE_LOC_LID)
+ tmp |= BMI160_INT_ORIENT;
+#endif
ret = raw_write8(s->port, s->addr, BMI160_INT_MAP_REG(1), tmp);
#ifdef CONFIG_ACCEL_FIFO
@@ -859,6 +874,9 @@ static int config_interrupt(const struct motion_sensor_t *s)
static int irq_handler(struct motion_sensor_t *s, uint32_t *event)
{
int interrupt;
+#ifdef CONFIG_BMI160_ORIENTATION_SENSOR
+ int shifted_masked_orientation;
+#endif
if ((s->type != MOTIONSENSE_TYPE_ACCEL) ||
(!(*event & CONFIG_ACCELGYRO_BMI160_INT_EVENT)))
@@ -874,6 +892,37 @@ static int irq_handler(struct motion_sensor_t *s, uint32_t *event)
if (interrupt & BMI160_SIGMOT_INT)
*event |= CONFIG_GESTURE_SIGMO_EVENT;
#endif
+#ifdef CONFIG_BMI160_ORIENTATION_SENSOR
+ shifted_masked_orientation = (interrupt >> 24) & BMI160_ORIENT_XY_MASK;
+ if (BMI160_GET_DATA(s)->raw_orientation != shifted_masked_orientation) {
+ enum motionsensor_orientation orientation =
+ MOTIONSENSE_ORIENTATION_UNKNOWN;
+
+ BMI160_GET_DATA(s)->raw_orientation =
+ shifted_masked_orientation;
+
+ switch (shifted_masked_orientation) {
+ case BMI160_ORIENT_PORTRAIT:
+ orientation = MOTIONSENSE_ORIENTATION_PORTRAIT;
+ break;
+ case BMI160_ORIENT_PORTRAIT_INVERT:
+ orientation =
+ MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_PORTRAIT;
+ break;
+ case BMI160_ORIENT_LANDSCAPE:
+ orientation = MOTIONSENSE_ORIENTATION_LANDSCAPE;
+ break;
+ case BMI160_ORIENT_LANDSCAPE_INVERT:
+ orientation =
+ MOTIONSENSE_ORIENTATION_UPSIDE_DOWN_LANDSCAPE;
+ break;
+ default:
+ break;
+ }
+ orientation = motion_sense_remap_orientation(s, orientation);
+ SET_ORIENTATION(s, orientation);
+ }
+#endif
/*
* No need to read the FIFO here, motion sense task is
* doing it on every interrupt.
diff --git a/driver/accelgyro_bmi160.h b/driver/accelgyro_bmi160.h
index bc31186344..0682d03171 100644
--- a/driver/accelgyro_bmi160.h
+++ b/driver/accelgyro_bmi160.h
@@ -99,6 +99,12 @@
#define BMI160_S_TAP_INT (1 << 5)
#define BMI160_ORIENT_INT (1 << 6)
#define BMI160_FLAT_INT (1 << 7)
+#define BMI160_ORIENT_XY_MASK 0x30
+#define BMI160_ORIENT_PORTRAIT (0 << 4)
+#define BMI160_ORIENT_PORTRAIT_INVERT (1 << 4)
+#define BMI160_ORIENT_LANDSCAPE (2 << 4)
+#define BMI160_ORIENT_LANDSCAPE_INVERT (3 << 4)
+
#define BMI160_INT_STATUS_1 0x1d
#define BMI160_HIGHG_INT (1 << (2 + 8))
@@ -333,8 +339,15 @@ enum fifo_header {
#define BMI160_TAP_TH(_s, _mg) \
(MIN(((_mg) * 1000) / ((_s)->drv->get_range(_s) * 31250), 0x1f))
-#define BMI160_INT_ORIENT_0 0x65
-#define BMI160_INT_ORIENT_1 0x66
+#define BMI160_INT_ORIENT_0 0x65
+
+/* No hysterisis, theta block, int on slope > 0.2 or axis > 1.5, symmetrical */
+#define BMI160_INT_ORIENT_0_INIT_VAL 0x48
+
+#define BMI160_INT_ORIENT_1 0x66
+
+/* no axes remap, no int on up/down, no blocking angle */
+#define BMI160_INT_ORIENT_1_INIT_VAL 0x00
#define BMI160_INT_FLAT_0 0x67
#define BMI160_INT_FLAT_1 0x68
@@ -449,6 +462,12 @@ struct bmi160_drv_data_t {
#ifdef CONFIG_MAG_BMI160_BMM150
struct bmm150_private_data compass;
#endif
+#ifdef CONFIG_BMI160_ORIENTATION_SENSOR
+ uint8_t raw_orientation;
+ enum motionsensor_orientation orientation;
+ enum motionsensor_orientation last_orientation;
+#endif
+
};
#define BMI160_GET_DATA(_s) \
@@ -456,6 +475,22 @@ struct bmi160_drv_data_t {
#define BMI160_GET_SAVED_DATA(_s) \
(&BMI160_GET_DATA(_s)->saved_data[(_s)->type])
+#ifdef CONFIG_BMI160_ORIENTATION_SENSOR
+#define ORIENTATION_CHANGED(_sensor) \
+ (BMI160_GET_DATA(_sensor)->orientation != \
+ BMI160_GET_DATA(_sensor)->last_orientation)
+
+#define GET_ORIENTATION(_sensor) \
+ (BMI160_GET_DATA(_sensor)->orientation)
+
+#define SET_ORIENTATION(_sensor, _val) \
+ (BMI160_GET_DATA(_sensor)->orientation = _val)
+
+#define SET_ORIENTATION_UPDATED(_sensor) \
+ (BMI160_GET_DATA(_sensor)->last_orientation = \
+ BMI160_GET_DATA(_sensor)->orientation)
+#endif
+
void bmi160_interrupt(enum gpio_signal signal);
#ifdef CONFIG_MAG_BMI160_BMM150