diff options
-rw-r--r-- | driver/build.mk | 1 | ||||
-rw-r--r-- | driver/sync.c | 120 | ||||
-rw-r--r-- | driver/sync.h | 18 | ||||
-rw-r--r-- | include/config.h | 12 |
4 files changed, 151 insertions, 0 deletions
diff --git a/driver/build.mk b/driver/build.mk index 597b055de9..4fa26af667 100644 --- a/driver/build.mk +++ b/driver/build.mk @@ -15,6 +15,7 @@ driver-$(CONFIG_ACCELGYRO_BMI160)+=accelgyro_bmi160.o driver-$(CONFIG_MAG_BMI160_BMM150)+=mag_bmm150.o driver-$(CONFIG_ACCELGYRO_LSM6DSM)+=accelgyro_lsm6dsm.o driver-$(CONFIG_ACCEL_LIS2DH)+=accel_lis2dh.o stm_mems_common.o +driver-$(CONFIG_SYNC)+=sync.o # BC1.2 Charger Detection Devices driver-$(CONFIG_BC12_DETECT_BQ24392)+=bc12/bq24392.o diff --git a/driver/sync.c b/driver/sync.c new file mode 100644 index 0000000000..bbf0b7f0d8 --- /dev/null +++ b/driver/sync.c @@ -0,0 +1,120 @@ +/* Copyright 2017 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Sync event driver. + * Useful for recording the exact time a gpio interrupt happened in the + * context of sensors. Originally created for a camera vsync signal. + */ + +#include "accelgyro.h" +#include "config.h" +#include "console.h" +#include "driver/sync.h" +#include "hwtimer.h" +#include "task.h" + +#define CPRINTS(format, args...) cprints(CC_MOTION_SENSE, format, ## args) +#define CPRINTF(format, args...) cprintf(CC_MOTION_SENSE, format, ## args) + +#ifndef CONFIG_ACCEL_FIFO +#error This driver needs CONFIG_ACCEL_FIFO +#endif + +#ifndef CONFIG_ACCEL_INTERRUPTS +#error This driver needs CONFIG_ACCEL_INTERRUPTS +#endif + +static uint32_t previous_interrupt_timestamp, last_interrupt_timestamp; +static int event_counter; +struct ec_response_motion_sensor_data vector = {.flags = 0, .data = {0, 0, 0} }; +int sync_enabled; + +static int sync_read(const struct motion_sensor_t *s, vector_3_t v) +{ + v[0] = event_counter; + return EC_SUCCESS; +} + +/* + * Since there's no such thing as data rate for this sensor, but the framework + * still depends on being able to set this to 0 to disable it, we'll just use + * non 0 rate values as an enable boolean. + */ +static int sync_set_data_rate(const struct motion_sensor_t *s, + int rate, int roundup) +{ + sync_enabled = !!rate; + CPRINTF("sync event driver enabling=%d\n", sync_enabled); + return EC_SUCCESS; +} + +static int sync_get_data_rate(const struct motion_sensor_t *s) +{ + return sync_enabled; +} + +/* Upper half of the irq handler */ +void sync_interrupt(enum gpio_signal signal) +{ + uint32_t timestamp = __hw_clock_source_read(); + + if (!sync_enabled) + return; + + last_interrupt_timestamp = timestamp; + event_counter++; + + task_set_event(TASK_ID_MOTIONSENSE, CONFIG_SYNC_INT_EVENT, 0); +} + +/* Bottom half of the irq handler */ +static int motion_irq_handler(struct motion_sensor_t *s, uint32_t *event) +{ + uint32_t timestamp; + + if (!(*event & CONFIG_SYNC_INT_EVENT)) + return EC_ERROR_NOT_HANDLED; + + /* this should be the atomic read */ + timestamp = last_interrupt_timestamp; + + if (previous_interrupt_timestamp == timestamp) + return EC_ERROR_NOT_HANDLED; /* nothing new yet */ + previous_interrupt_timestamp = timestamp; + + vector.flags = MOTIONSENSE_SENSOR_FLAG_WAKEUP; + vector.data[X] = event_counter; + motion_sense_fifo_add_data(&vector, s, 1, timestamp); + return EC_SUCCESS; +} + +static int sync_init(const struct motion_sensor_t *s) +{ + last_interrupt_timestamp = __hw_clock_source_read(); + previous_interrupt_timestamp = last_interrupt_timestamp; + event_counter = 0; + vector.sensor_num = s - motion_sensors; + sync_enabled = 0; + return 0; +} + +#ifdef CONFIG_SYNC_COMMAND +static int command_sync(int argc, char **argv) +{ + sync_interrupt(GPIO_SYNC_INT); + return EC_SUCCESS; +} +DECLARE_CONSOLE_COMMAND(sync, command_sync, + NULL, + "Simulates a sync event"); +#endif + +const struct accelgyro_drv sync_drv = { + .init = sync_init, + .read = sync_read, + .set_data_rate = sync_set_data_rate, + .get_data_rate = sync_get_data_rate, + .irq_handler = motion_irq_handler, +}; + diff --git a/driver/sync.h b/driver/sync.h new file mode 100644 index 0000000000..1f6115a086 --- /dev/null +++ b/driver/sync.h @@ -0,0 +1,18 @@ +/* Copyright 2017 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Sync event driver. + * Useful for recording the exact time a gpio interrupt happened in the + * context of sensors. Originally created for a camera vsync signal. + */ + +#ifndef __CROS_EC_VSYNC_H +#define __CROS_EC_VSYNC_H + +extern const struct accelgyro_drv sync_drv; + +void sync_interrupt(enum gpio_signal signal); + +#endif /* __CROS_EC_VSYNC_H */ + diff --git a/include/config.h b/include/config.h index 31c2972b15..a9ba707b97 100644 --- a/include/config.h +++ b/include/config.h @@ -121,6 +121,18 @@ */ #undef CONFIG_ACCEL_LIS2DH_INT_EVENT +/* Sync event driver */ +#undef CONFIG_SYNC + +/* Simulate command for sync */ +#undef CONFIG_SYNC_COMMAND + +/* + * Define the event to raise when the sync event happens. + * Must be within TASK_EVENT_MOTION_INTERRUPT_MASK. + */ +#undef CONFIG_SYNC_INT_EVENT + /* Compile chip support for analog-to-digital convertor */ #undef CONFIG_ADC |