diff options
author | Gwendal Grignou <gwendal@chromium.org> | 2018-07-07 22:25:58 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-07-14 01:03:44 -0700 |
commit | 77ff16475d8408d087943f836a53675a675b5847 (patch) | |
tree | a83751d8f6b2d33f6906352d1380fbbee1c4a7aa /driver | |
parent | fd5cbe7392f1b9abd2bcec8aeac012ef777de719 (diff) | |
download | chrome-ec-77ff16475d8408d087943f836a53675a675b5847.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/1128554
Commit-Ready: Alexandru M Stan <amstan@chromium.org>
Tested-by: Alexandru M Stan <amstan@chromium.org>
Reviewed-by: Alexandru M Stan <amstan@chromium.org>
Diffstat (limited to 'driver')
-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 0e765e5d5e..c46862d8a9 100644 --- a/driver/accelgyro_bmi160.c +++ b/driver/accelgyro_bmi160.c @@ -990,16 +990,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 */ @@ -1047,46 +1044,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: @@ -1109,11 +1078,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 */ |