summaryrefslogtreecommitdiff
path: root/driver/accelgyro_bmi160.c
diff options
context:
space:
mode:
Diffstat (limited to 'driver/accelgyro_bmi160.c')
-rw-r--r--driver/accelgyro_bmi160.c345
1 files changed, 166 insertions, 179 deletions
diff --git a/driver/accelgyro_bmi160.c b/driver/accelgyro_bmi160.c
index cad62df246..96eea09844 100644
--- a/driver/accelgyro_bmi160.c
+++ b/driver/accelgyro_bmi160.c
@@ -759,6 +759,169 @@ int list_activities(const struct motion_sensor_t *s,
#endif
#ifdef CONFIG_ACCEL_INTERRUPTS
+/**
+ * bmi160_interrupt - called when the sensor activates the interrupt line.
+ *
+ * This is a "top half" interrupt handler, it just asks motion sense ask
+ * to schedule the "bottom half", ->irq_handler().
+ */
+void bmi160_interrupt(enum gpio_signal signal)
+{
+ task_set_event(TASK_ID_MOTIONSENSE,
+ CONFIG_ACCELGYRO_BMI160_INT_EVENT, 0);
+}
+
+
+static int config_interrupt(const struct motion_sensor_t *s)
+{
+ int ret, tmp;
+
+ if (s->type != MOTIONSENSE_TYPE_ACCEL)
+ return EC_SUCCESS;
+
+ mutex_lock(s->mutex);
+ raw_write8(s->port, s->addr, BMI160_CMD_REG, BMI160_CMD_FIFO_FLUSH);
+ raw_write8(s->port, s->addr, BMI160_CMD_REG, BMI160_CMD_INT_RESET);
+
+#ifdef CONFIG_GESTURE_SENSOR_BATTERY_TAP
+ raw_write8(s->port, s->addr, BMI160_INT_TAP_0,
+ BMI160_TAP_DUR(s, CONFIG_GESTURE_TAP_MAX_INTERSTICE_T));
+ 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.
+ */
+#ifdef CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT
+ ret = raw_write8(s->port, s->addr, BMI160_INT_LATCH, BMI160_LATCH_5MS);
+#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);
+#endif
+
+ /* configure int1 as an interrupt */
+ ret = raw_write8(s->port, s->addr, BMI160_INT_OUT_CTRL,
+ BMI160_INT_CTRL(1, OUTPUT_EN));
+
+ /* Map activity interrupt to int 1 */
+ tmp = 0;
+#ifdef CONFIG_GESTURE_SIGMO
+ tmp |= BMI160_INT_ANYMOTION;
+#endif
+#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
+ /* map fifo water mark to int 1 */
+ ret = raw_write8(s->port, s->addr, BMI160_INT_FIFO_MAP,
+ BMI160_INT_MAP(1, FWM) |
+ BMI160_INT_MAP(1, FFULL));
+
+ /* configure fifo watermark to int whenever there's any data in there */
+ ret = raw_write8(s->port, s->addr, BMI160_FIFO_CONFIG_0, 1);
+#ifdef CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT
+ ret = raw_write8(s->port, s->addr, BMI160_FIFO_CONFIG_1,
+ BMI160_FIFO_HEADER_EN);
+#else
+ ret = raw_write8(s->port, s->addr, BMI160_FIFO_CONFIG_1,
+ BMI160_FIFO_TAG_INT2_EN |
+ BMI160_FIFO_HEADER_EN);
+#endif
+
+ /* Set fifo*/
+ ret = raw_read8(s->port, s->addr, BMI160_INT_EN_1, &tmp);
+ tmp |= BMI160_INT_FWM_EN | BMI160_INT_FFUL_EN;
+ ret = raw_write8(s->port, s->addr, BMI160_INT_EN_1, tmp);
+#endif
+ mutex_unlock(s->mutex);
+ 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_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.
+ */
+ return EC_SUCCESS;
+}
+#endif /* CONFIG_ACCEL_INTERRUPTS */
#ifdef CONFIG_ACCEL_FIFO
enum fifo_state {
@@ -823,17 +986,6 @@ static int bmi160_decode_header(struct motion_sensor_t *s,
}
}
-/**
- * Retrieve hardware FIFO from sensor,
- * - put data in Sensor Hub fifo.
- * - update sensor raw_xyz vector with the last information.
- * We put raw data in hub fifo and process data from there.
- * @s Pointer to sensor data.
- *
- * NOTE: If a new driver supports this function, be sure to add a check
- * for spoof_mode in order to load the sensor stack with the spoofed
- * data. See accelgyro_bmi160.c::load_fifo for an example.
- */
static int load_fifo(struct motion_sensor_t *s)
{
int done = 0;
@@ -940,174 +1092,6 @@ static int load_fifo(struct motion_sensor_t *s)
}
#endif /* CONFIG_ACCEL_FIFO */
-/**
- * bmi160_interrupt - called when the sensor activates the interrupt line.
- *
- * This is a "top half" interrupt handler, it just asks motion sense ask
- * to schedule the "bottom half", ->irq_handler().
- */
-void bmi160_interrupt(enum gpio_signal signal)
-{
- task_set_event(TASK_ID_MOTIONSENSE,
- CONFIG_ACCELGYRO_BMI160_INT_EVENT, 0);
-}
-
-
-static int config_interrupt(const struct motion_sensor_t *s)
-{
- int ret, tmp;
-
- if (s->type != MOTIONSENSE_TYPE_ACCEL)
- return EC_SUCCESS;
-
- mutex_lock(s->mutex);
- raw_write8(s->port, s->addr, BMI160_CMD_REG, BMI160_CMD_FIFO_FLUSH);
- raw_write8(s->port, s->addr, BMI160_CMD_REG, BMI160_CMD_INT_RESET);
-
-#ifdef CONFIG_GESTURE_SENSOR_BATTERY_TAP
- raw_write8(s->port, s->addr, BMI160_INT_TAP_0,
- BMI160_TAP_DUR(s, CONFIG_GESTURE_TAP_MAX_INTERSTICE_T));
- 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.
- */
-#ifdef CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT
- ret = raw_write8(s->port, s->addr, BMI160_INT_LATCH, BMI160_LATCH_5MS);
-#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);
-#endif
-
- /* configure int1 as an interrupt */
- ret = raw_write8(s->port, s->addr, BMI160_INT_OUT_CTRL,
- BMI160_INT_CTRL(1, OUTPUT_EN));
-
- /* Map activity interrupt to int 1 */
- tmp = 0;
-#ifdef CONFIG_GESTURE_SIGMO
- tmp |= BMI160_INT_ANYMOTION;
-#endif
-#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
- /* map fifo water mark to int 1 */
- ret = raw_write8(s->port, s->addr, BMI160_INT_FIFO_MAP,
- BMI160_INT_MAP(1, FWM) |
- BMI160_INT_MAP(1, FFULL));
-
- /* configure fifo watermark to int whenever there's any data in there */
- ret = raw_write8(s->port, s->addr, BMI160_FIFO_CONFIG_0, 1);
-#ifdef CONFIG_ACCELGYRO_BMI160_INT2_OUTPUT
- ret = raw_write8(s->port, s->addr, BMI160_FIFO_CONFIG_1,
- BMI160_FIFO_HEADER_EN);
-#else
- ret = raw_write8(s->port, s->addr, BMI160_FIFO_CONFIG_1,
- BMI160_FIFO_TAG_INT2_EN |
- BMI160_FIFO_HEADER_EN);
-#endif
-
- /* Set fifo*/
- ret = raw_read8(s->port, s->addr, BMI160_INT_EN_1, &tmp);
- tmp |= BMI160_INT_FWM_EN | BMI160_INT_FFUL_EN;
- ret = raw_write8(s->port, s->addr, BMI160_INT_EN_1, tmp);
-#endif
- mutex_unlock(s->mutex);
- 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;
- 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.
- */
- return EC_SUCCESS;
-}
-#endif /* CONFIG_ACCEL_INTERRUPTS */
-
static int read(const struct motion_sensor_t *s, vector_3_t v)
{
@@ -1301,6 +1285,9 @@ const struct accelgyro_drv bmi160_drv = {
#ifdef CONFIG_ACCEL_INTERRUPTS
.irq_handler = irq_handler,
#endif
+#ifdef CONFIG_ACCEL_FIFO
+ .load_fifo = load_fifo,
+#endif
#ifdef CONFIG_GESTURE_HOST_DETECTION
.manage_activity = manage_activity,
.list_activities = list_activities,