blob: 574421b2488765d5664aa5c5c842c42056d4b76c [file] [log] [blame]
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