| From 80e527fc5ae59c6931efe7107710c18655beb068 Mon Sep 17 00:00:00 2001 |
| From: Gwendal Grignou <gwendal@chromium.org> |
| Date: Tue, 8 Oct 2019 10:19:11 -0700 |
| Subject: [PATCH] CHROMIUM: iio: cros_ec: Add synchronization sensor |
| |
| EC returns a counter when there is an event on a interrupt line. |
| Use to synchronise gyroscope and camera. |
| |
| BUG=b:67743747 |
| TEST=On cyan, create a pseudo sensor in EC, see its events through |
| sysfs. |
| |
| Original-Change-Id: I3e2bc154866a28d33b8773bdcdebf67410130483 |
| Reviewed-on: https://chromium-review.googlesource.com/851418 |
| Commit-Ready: ChromeOS CL Exonerator Bot |
| <chromiumos-cl-exonerator@appspot.gserviceaccount.com> |
| Reviewed-by: Alexandru M Stan <amstan@chromium.org> |
| |
| [rebase419(groeck): Kernel API changes] |
| Signed-off-by: Guenter Roeck <groeck@chromium.org> |
| [rebase54(gwendal): Counter subsystem is gone, only timestamp channel, |
| moved to common/cros_ec_sensors.] |
| [rebase510(gwendal): Use FIFO, squash with: |
| 9eefe65b2748 ("CHROMIUM: iio: cros_ec: Expose sync sampling frequencies")] |
| |
| Signed-off-by: Gwendal Grignou <gwendal@chromium.org> |
| --- |
| drivers/iio/common/cros_ec_sensors/Kconfig | 9 ++ |
| drivers/iio/common/cros_ec_sensors/Makefile | 1 + |
| .../cros_ec_sensors/cros_ec_sensors_core.c | 9 ++ |
| .../cros_ec_sensors/cros_ec_sensors_sync.c | 150 ++++++++++++++++++ |
| 4 files changed, 169 insertions(+) |
| create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_sync.c |
| |
| diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig b/drivers/iio/common/cros_ec_sensors/Kconfig |
| --- a/drivers/iio/common/cros_ec_sensors/Kconfig |
| +++ b/drivers/iio/common/cros_ec_sensors/Kconfig |
| @@ -41,3 +41,12 @@ config IIO_CROS_EC_ACTIVITY |
| They are being reported by physical devices or the EC itself. |
| Creates an IIO device to manage all activities. |
| |
| +config IIO_CROS_EC_SENSORS_SYNC |
| + tristate "ChromeOS EC Counter Sensors" |
| + depends on IIO_CROS_EC_SENSORS_CORE |
| + help |
| + Module to handle synchronisation sensors presented by the ChromeOS EC |
| + Sensor hub. |
| + Synchronisation sensors are counter sensors that are triggered when |
| + events occurs from other subsystems. They are use to synchronised |
| + those subsystem with existing MEMS sensors, like gyroscope. |
| diff --git a/drivers/iio/common/cros_ec_sensors/Makefile b/drivers/iio/common/cros_ec_sensors/Makefile |
| --- a/drivers/iio/common/cros_ec_sensors/Makefile |
| +++ b/drivers/iio/common/cros_ec_sensors/Makefile |
| @@ -7,3 +7,4 @@ obj-$(CONFIG_IIO_CROS_EC_ACTIVITY) += cros_ec_activity.o |
| obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.o |
| obj-$(CONFIG_IIO_CROS_EC_SENSORS) += cros_ec_sensors.o |
| obj-$(CONFIG_IIO_CROS_EC_SENSORS_LID_ANGLE) += cros_ec_lid_angle.o |
| +obj-$(CONFIG_IIO_CROS_EC_SENSORS_SYNC) += cros_ec_sensors_sync.o |
| diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c |
| --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c |
| +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c |
| @@ -32,6 +32,7 @@ |
| static char *cros_ec_loc[] = { |
| [MOTIONSENSE_LOC_BASE] = "base", |
| [MOTIONSENSE_LOC_LID] = "lid", |
| + [MOTIONSENSE_LOC_CAMERA] = "camera", |
| [MOTIONSENSE_LOC_MAX] = "unknown", |
| }; |
| |
| @@ -93,6 +94,14 @@ static void get_default_min_max_freq(enum motionsensor_type type, |
| *min_freq = 250; |
| *max_freq = 20000; |
| break; |
| + case MOTIONSENSE_TYPE_SYNC: |
| + /* |
| + * Frequency for sync/counter sensors is overloaded for |
| + * enable/disable. |
| + */ |
| + *min_freq = 0; |
| + *max_freq = 1; |
| + break; |
| case MOTIONSENSE_TYPE_ACTIVITY: |
| default: |
| *min_freq = 0; |
| diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_sync.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_sync.c |
| new file mode 100644 |
| --- /dev/null |
| +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_sync.c |
| @@ -0,0 +1,150 @@ |
| +/* |
| + * cros_ec_sensors_sync - Driver for synchronisation sensor behind CrOS EC. |
| + * |
| + * Copyright 2018 Google, Inc |
| + * |
| + * This software is licensed under the terms of the GNU General Public |
| + * License version 2, as published by the Free Software Foundation, and |
| + * may be copied, distributed, and modified under those terms. |
| + * |
| + * This program is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + * GNU General Public License for more details. |
| + * |
| + * This driver uses the cros-ec interface to communicate with the Chrome OS |
| + * EC about counter sensors. Counters are presented through |
| + * iio sysfs. |
| + */ |
| + |
| +#include <linux/delay.h> |
| +#include <linux/device.h> |
| +#include <linux/iio/buffer.h> |
| +#include <linux/iio/common/cros_ec_sensors_core.h> |
| +#include <linux/iio/iio.h> |
| +#include <linux/iio/kfifo_buf.h> |
| +#include <linux/iio/trigger.h> |
| +#include <linux/iio/triggered_buffer.h> |
| +#include <linux/iio/trigger_consumer.h> |
| +#include <linux/kernel.h> |
| +#include <linux/module.h> |
| +#include <linux/platform_data/cros_ec_commands.h> |
| +#include <linux/platform_data/cros_ec_proto.h> |
| +#include <linux/platform_device.h> |
| +#include <linux/slab.h> |
| + |
| +/* |
| + * One channel for timestamp. |
| + */ |
| +#define MAX_CHANNELS 1 |
| + |
| +/* State data for ec_sensors iio driver. */ |
| +struct cros_ec_sensors_sync_state { |
| + /* Shared by all sensors */ |
| + struct cros_ec_sensors_core_state core; |
| + |
| + struct iio_chan_spec channels[MAX_CHANNELS]; |
| +}; |
| + |
| +static int cros_ec_sensors_sync_read(struct iio_dev *indio_dev, |
| + struct iio_chan_spec const *chan, |
| + int *val, int *val2, long mask) |
| +{ |
| + struct cros_ec_sensors_sync_state *st = iio_priv(indio_dev); |
| + int ret; |
| + |
| + mutex_lock(&st->core.cmd_lock); |
| + ret = cros_ec_sensors_core_read(&st->core, chan, val, val2, mask); |
| + mutex_unlock(&st->core.cmd_lock); |
| + return ret; |
| +} |
| + |
| +static int cros_ec_sensors_write(struct iio_dev *indio_dev, |
| + struct iio_chan_spec const *chan, |
| + int val, int val2, long mask) |
| +{ |
| + struct cros_ec_sensors_sync_state *st = iio_priv(indio_dev); |
| + int ret; |
| + |
| + mutex_lock(&st->core.cmd_lock); |
| + |
| + ret = cros_ec_sensors_core_write( |
| + &st->core, chan, val, val2, mask); |
| + |
| + mutex_unlock(&st->core.cmd_lock); |
| + return ret; |
| +} |
| + |
| +static const struct iio_info cros_ec_sensors_sync_info = { |
| + .read_raw = &cros_ec_sensors_sync_read, |
| + .write_raw = &cros_ec_sensors_write, |
| + .read_avail = &cros_ec_sensors_core_read_avail, |
| +}; |
| + |
| +static int cros_ec_sensors_sync_probe(struct platform_device *pdev) |
| +{ |
| + struct device *dev = &pdev->dev; |
| + struct iio_dev *indio_dev; |
| + struct cros_ec_sensors_sync_state *state; |
| + struct iio_chan_spec *channel; |
| + int ret; |
| + |
| + indio_dev = devm_iio_device_alloc(dev, sizeof(*state)); |
| + if (!indio_dev) |
| + return -ENOMEM; |
| + |
| + ret = cros_ec_sensors_core_init(pdev, indio_dev, true, |
| + cros_ec_sensors_capture, cros_ec_sensors_push_data, false); |
| + if (ret) |
| + return ret; |
| + |
| + indio_dev->info = &cros_ec_sensors_sync_info; |
| + state = iio_priv(indio_dev); |
| + /* |
| + * Sync sensor notion of frequencies is either on or off. |
| + * EC reports min and max as 1, that would translate in 1 mHz. |
| + * Force it to 1 (..HZ), more readable. |
| + * For the EC, any frequencies different from 0 means the sync sensor is |
| + * enabled. |
| + */ |
| + state->core.frequencies[2] = state->core.frequencies[4] = 1; |
| + state->core.frequencies[3] = state->core.frequencies[5] = 0; |
| + |
| + channel = state->channels; |
| + channel->info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ); |
| + channel->info_mask_shared_by_all_available = |
| + BIT(IIO_CHAN_INFO_SAMP_FREQ); |
| + channel->type = IIO_TIMESTAMP; |
| + channel->channel = -1; |
| + channel->scan_index = 1; |
| + channel->scan_type.sign = 's'; |
| + channel->scan_type.realbits = 64; |
| + channel->scan_type.storagebits = 64; |
| + |
| + indio_dev->channels = state->channels; |
| + indio_dev->num_channels = MAX_CHANNELS; |
| + |
| + state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd; |
| + |
| + return devm_iio_device_register(dev, indio_dev); |
| +} |
| + |
| +static const struct platform_device_id cros_ec_sensors_sync_ids[] = { |
| + { |
| + .name = "cros-ec-sync", |
| + }, |
| + { /* sentinel */ } |
| +}; |
| +MODULE_DEVICE_TABLE(platform, cros_ec_sensors_sync_ids); |
| + |
| +static struct platform_driver cros_ec_sensors_sync_platform_driver = { |
| + .driver = { |
| + .name = "cros-ec-sync", |
| + }, |
| + .probe = cros_ec_sensors_sync_probe, |
| + .id_table = cros_ec_sensors_sync_ids, |
| +}; |
| +module_platform_driver(cros_ec_sensors_sync_platform_driver); |
| + |
| +MODULE_DESCRIPTION("ChromeOS EC synchronisation sensor driver"); |
| +MODULE_LICENSE("GPL v2"); |
| -- |
| 2.33.0.rc2.250.ged5fa647cd-goog |
| |