diff options
author | Nick Vaccaro <nvaccaro@chromium.org> | 2017-05-26 12:29:14 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2017-08-08 17:34:11 -0700 |
commit | e656b970e204309c1a665f154a5972ed85305911 (patch) | |
tree | 58ed84ec4144caf71a4953bae780ec60dd62037e /driver | |
parent | 8bfde69fdd9b5feb4c47c8c714416c17afe00f78 (diff) | |
download | chrome-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.c | 60 | ||||
-rw-r--r-- | driver/accel_kionix.h | 21 | ||||
-rw-r--r-- | driver/accel_kx022.h | 11 | ||||
-rw-r--r-- | driver/accelgyro_bmi160.c | 49 | ||||
-rw-r--r-- | driver/accelgyro_bmi160.h | 39 |
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 |