diff options
author | Gwendal Grignou <gwendal@chromium.org> | 2018-07-07 22:25:58 -0700 |
---|---|---|
committer | ChromeOS Commit Bot <chromeos-commit-bot@chromium.org> | 2018-07-16 18:22:51 +0000 |
commit | cbee5325d37f012cb279f42640921c22d84ed168 (patch) | |
tree | 398463b06f0752f509a535e881e0662e37149590 | |
parent | 17ab2d23d3794e8ffd7c1da5de155491f5fa29b0 (diff) | |
download | chrome-ec-cbee5325d37f012cb279f42640921c22d84ed168.tar.gz |
driver: bmi160: harden interrupt and fifo processing
During cts test with CL:938146, the BMI160 would not send any interrupts
and FIFO got un processed.
- Latch IRQ events forever: the motion_sense task will kick in and read
the interrupt source sometimes, even after 5ms.
- Retest irq bits in irq_handler. If more events are posted, we will
collect them right away, avoiding a task wake up round trip.
We assume the BMI160 adds events too fast and force the motion task into
a infinite loop.
BUG=b:73557414,b:80284952
BRANCH=scarlet,poppy
TEST=Without that code, BMI160 would get unprocessed:
android.hardware.cts.SensorIntegrationTests#testSensorsWithSeveralClients
fail: ... Iteration 0 failed: "WaitForEvents |i
sensor='CrosEC Accelerometer', samplingPeriod=0us, maxReportLatency=0us |
requested=100, received=0,
With it, the 25 iterations pass.
Change-Id: I0f94b811ac0dbf60dcfa24c899682a2b5eb69de7
Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1137442
Commit-Queue: Alexandru M Stan <amstan@chromium.org>
Commit-Queue: Philip Chen <philipchen@chromium.org>
Tested-by: Alexandru M Stan <amstan@chromium.org>
Tested-by: Philip Chen <philipchen@chromium.org>
Trybot-Ready: Alexandru M Stan <amstan@chromium.org>
Reviewed-by: Philip Chen <philipchen@chromium.org>
-rw-r--r-- | driver/accelgyro_bmi160.c | 91 |
1 files changed, 46 insertions, 45 deletions
diff --git a/driver/accelgyro_bmi160.c b/driver/accelgyro_bmi160.c index 72b8b2a902..443937ba59 100644 --- a/driver/accelgyro_bmi160.c +++ b/driver/accelgyro_bmi160.c @@ -996,16 +996,13 @@ static int config_interrupt(const struct motion_sensor_t *s) } #endif - /* - * Set a 5ms latch to be sure the EC can read the interrupt register - * properly, even when it is running more slowly. - */ #ifdef CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT - ret = raw_write8(s->port, s->addr, BMI160_INT_LATCH, BMI160_LATCH_5MS); + ret = raw_write8(s->port, s->addr, BMI160_INT_LATCH, + BMI160_LATCH_FOREVER); #else /* Also, configure int2 as an external input. */ ret = raw_write8(s->port, s->addr, BMI160_INT_LATCH, - BMI160_INT2_INPUT_EN | BMI160_LATCH_5MS); + BMI160_INT2_INPUT_EN | BMI160_LATCH_FOREVER); #endif /* configure int1 as an interrupt */ @@ -1053,46 +1050,18 @@ static int config_interrupt(const struct motion_sensor_t *s) return ret; } -/** - * irq_handler - bottom half of the interrupt stack. - * Ran from the motion_sense task, finds the events that raised the interrupt. - * - * For now, we just print out. We should set a bitmask motion sense code will - * act upon. - */ -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))) - return EC_ERROR_NOT_HANDLED; - - raw_read32(s->port, s->addr, BMI160_INT_STATUS_0, &interrupt); - -#ifdef CONFIG_GESTURE_SENSOR_BATTERY_TAP - if (interrupt & BMI160_D_TAP_INT) - *event |= CONFIG_GESTURE_TAP_EVENT; -#endif -#ifdef CONFIG_GESTURE_SIGMO - if (interrupt & BMI160_SIGMOT_INT) - *event |= CONFIG_GESTURE_SIGMO_EVENT; -#endif -#ifdef CONFIG_ACCEL_FIFO - if (interrupt & (BMI160_FWM_INT | BMI160_FFULL_INT)) - load_fifo(s); -#endif -#ifdef CONFIG_BMI160_ORIENTATION_SENSOR - shifted_masked_orientation = (interrupt >> 24) & BMI160_ORIENT_XY_MASK; +static void irq_set_orientation(struct motion_sensor_t *s, + int interrupt) +{ + int 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; + MOTIONSENSE_ORIENTATION_UNKNOWN; BMI160_GET_DATA(s)->raw_orientation = - shifted_masked_orientation; + shifted_masked_orientation; switch (shifted_masked_orientation) { case BMI160_ORIENT_PORTRAIT: @@ -1115,11 +1084,43 @@ static int irq_handler(struct motion_sensor_t *s, uint32_t *event) 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. - */ +/** + * irq_handler - bottom half of the interrupt stack. + * Ran from the motion_sense task, finds the events that raised the interrupt. + * + * For now, we just print out. We should set a bitmask motion sense code will + * act upon. + */ +static int irq_handler(struct motion_sensor_t *s, uint32_t *event) +{ + int interrupt; + + if ((s->type != MOTIONSENSE_TYPE_ACCEL) || + (!(*event & CONFIG_ACCELGYRO_BMI160_INT_EVENT))) + return EC_ERROR_NOT_HANDLED; + + do { + raw_read32(s->port, s->addr, BMI160_INT_STATUS_0, &interrupt); + +#ifdef CONFIG_GESTURE_SENSOR_BATTERY_TAP + if (interrupt & BMI160_D_TAP_INT) + *event |= CONFIG_GESTURE_TAP_EVENT; +#endif +#ifdef CONFIG_GESTURE_SIGMO + if (interrupt & BMI160_SIGMOT_INT) + *event |= CONFIG_GESTURE_SIGMO_EVENT; +#endif +#ifdef CONFIG_ACCEL_FIFO + if (interrupt & (BMI160_FWM_INT | BMI160_FFULL_INT)) + load_fifo(s); +#endif +#ifdef CONFIG_BMI160_ORIENTATION_SENSOR + irq_set_orientation(s, interrupt); +#endif + } while (interrupt != 0); + return EC_SUCCESS; } #endif /* CONFIG_ACCEL_INTERRUPTS */ |