summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGwendal Grignou <gwendal@chromium.org>2018-07-07 22:25:58 -0700
committerChromeOS Commit Bot <chromeos-commit-bot@chromium.org>2018-07-16 18:22:51 +0000
commitcbee5325d37f012cb279f42640921c22d84ed168 (patch)
tree398463b06f0752f509a535e881e0662e37149590
parent17ab2d23d3794e8ffd7c1da5de155491f5fa29b0 (diff)
downloadchrome-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.c91
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 */