All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/4] Add support for cros-ec-sensors
@ 2016-08-01  9:54 Enric Balletbo i Serra
  2016-08-01  9:54 ` [PATCH v4 1/4] iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC Sensor Hub Enric Balletbo i Serra
                   ` (5 more replies)
  0 siblings, 6 replies; 30+ messages in thread
From: Enric Balletbo i Serra @ 2016-08-01  9:54 UTC (permalink / raw)
  To: linux-kernel, linux-iio
  Cc: Olof Johansson, Lee Jones, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Guenter Roeck,
	Gwendal Grignou

Hi,

This is the four patchset to add support for the sensors behind the ChromeOS
Embedded Controller.

This version has only the patches to support common functions and 3d
contiguous sensors like Accelerometers, Gyroscope and Magnetometer that are
presented by the ChromeOS EC Sensor hub. The patches were tested on an Oak board.

The code was checked out from the ChromeOS v3.18 tree and forward ported to
mainline solving all the conflicts and build issues. I splitted the code in
single patches that have sense by themselves in order to avoid the chances
to fail.

Note that the patches depends on this [1] to apply and work.

[1] https://lkml.org/lkml/2016/7/1/188

Waiting for your reviews and feedback.

Changes since v3 (requested by Guenter Roeck)
  - Convert structure to a simple array
  - Remove PM declarations
  - Remove unnecessary initializations
  - cros_ec_sensors_cmd_read_u16: Conversion should only be done if ret >= 0
  - Remove unnecessary else
  - Add Reviewed-by tag for two last patches.

Changes since v2 (requested by Guenter Roeck and Jonhatan Cameron)
  - Rebased and fix build error.
  - Include a list of possible values in the description of location attr.
  - Fix some typos.
  - Remove id sysfs entry.
  - Skip filling by zero structure parameters that already zero'd.
  - Order includes alphabetically.
  - Propagate error codes.

Changes since v1 (requested by Peter Meerwald-Stadler and Jonhatan Cameron)
  - Check kernel-doc documentation and 
  - Bring some patches together.
  - Fix some spelling mistakes.
  - Include ABI documentation.
  - Be more careful with buffer sizes (sprintf -> snprintf)
  - Add cros_ec_sensors prefix to all function.
  - Check return values on some functions.

Best regards,

Enric Balletbo i Serra (3):
  iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC
    Sensor Hub.
  iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver
  platform/chrome: cros_ec_dev - Register cros-ec sensors

Vincent Palatin (1):
  platform/chrome: Introduce a new function to check EC features.

 Documentation/ABI/testing/sysfs-bus-iio-cros-ec    |  18 +
 drivers/iio/common/Kconfig                         |   1 +
 drivers/iio/common/Makefile                        |   1 +
 drivers/iio/common/cros_ec_sensors/Kconfig         |  22 +
 drivers/iio/common/cros_ec_sensors/Makefile        |   6 +
 .../iio/common/cros_ec_sensors/cros_ec_sensors.c   | 322 +++++++++++++++
 .../common/cros_ec_sensors/cros_ec_sensors_core.c  | 450 +++++++++++++++++++++
 .../common/cros_ec_sensors/cros_ec_sensors_core.h  | 175 ++++++++
 drivers/platform/chrome/cros_ec_dev.c              | 159 ++++++++
 include/linux/mfd/cros_ec.h                        |  10 +
 include/linux/mfd/cros_ec_commands.h               | 183 ++++++++-
 11 files changed, 1342 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-cros-ec
 create mode 100644 drivers/iio/common/cros_ec_sensors/Kconfig
 create mode 100644 drivers/iio/common/cros_ec_sensors/Makefile
 create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
 create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
 create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h

-- 
2.1.0

^ permalink raw reply	[flat|nested] 30+ messages in thread

* [PATCH v4 1/4] iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC Sensor Hub.
  2016-08-01  9:54 [PATCH v4 0/4] Add support for cros-ec-sensors Enric Balletbo i Serra
@ 2016-08-01  9:54 ` Enric Balletbo i Serra
  2016-08-01 16:57   ` Guenter Roeck
  2016-08-15 15:28   ` Jonathan Cameron
  2016-08-01  9:54 ` [PATCH v4 2/4] iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver Enric Balletbo i Serra
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 30+ messages in thread
From: Enric Balletbo i Serra @ 2016-08-01  9:54 UTC (permalink / raw)
  To: linux-kernel, linux-iio
  Cc: Olof Johansson, Lee Jones, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Guenter Roeck,
	Gwendal Grignou

Add the core functions to be able to support the sensors attached behind
the ChromeOS Embedded Controller and used by other IIO cros-ec sensor
drivers.

The cros_ec_sensor_core driver matches with current driver in ChromeOS
4.4 tree, so it includes all the fixes at the moment. The support for
this driver was made by Gwendal Grignou. The original patch and all the
fixes has been squashed and rebased on top of mainline.

Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
[eballetbo: split, squash and rebase on top of mainline the patches
found in ChromeOS tree]
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
---

Changes since v3:
  - Convert structure to a simple array
  - Remove PM declarations
  - Remove unnecessary initializations
  - cros_ec_sensors_cmd_read_u16: Conversion should only be done if ret >= 0
  - Remove unnecessary else

Changes since v2:
  - Rebased and fix build error.
  - Include a list of possible values in the description of location attr.
  - Fix some typos.
  - Remove id sysfs entry.

Changes since v1:
  - Check kernel-doc documentation.
  - Bring this in as an when you need it in the rest of the series.
  - Fix some spelling mistakes.
  - Include ABI documentation.
  - Be more careful with buffer sizes (sprintf -> snprintf)
  - Add cros_ec_sensors prefix to all function.
  - Check return values on some functions.

 Documentation/ABI/testing/sysfs-bus-iio-cros-ec    |  18 +
 drivers/iio/common/Kconfig                         |   1 +
 drivers/iio/common/Makefile                        |   1 +
 drivers/iio/common/cros_ec_sensors/Kconfig         |  14 +
 drivers/iio/common/cros_ec_sensors/Makefile        |   5 +
 .../common/cros_ec_sensors/cros_ec_sensors_core.c  | 450 +++++++++++++++++++++
 .../common/cros_ec_sensors/cros_ec_sensors_core.h  | 175 ++++++++
 include/linux/mfd/cros_ec.h                        |   9 +
 include/linux/mfd/cros_ec_commands.h               |  99 ++++-
 9 files changed, 767 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-cros-ec
 create mode 100644 drivers/iio/common/cros_ec_sensors/Kconfig
 create mode 100644 drivers/iio/common/cros_ec_sensors/Makefile
 create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
 create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h

diff --git a/Documentation/ABI/testing/sysfs-bus-iio-cros-ec b/Documentation/ABI/testing/sysfs-bus-iio-cros-ec
new file mode 100644
index 0000000..297b972
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-iio-cros-ec
@@ -0,0 +1,18 @@
+What:		/sys/bus/iio/devices/iio:deviceX/calibrate
+Date:		July 2015
+KernelVersion:	4.7
+Contact:	linux-iio@vger.kernel.org
+Description:
+		Writing '1' will perform a FOC (Fast Online Calibration). The
+                corresponding calibration offsets can be read from *_calibbias
+                entries.
+
+What:		/sys/bus/iio/devices/iio:deviceX/location
+Date:		July 2015
+KernelVersion:	4.7
+Contact:	linux-iio@vger.kernel.org
+Description:
+		This attribute returns a string with the physical location where
+                the motion sensor is placed. For example, in a laptop a motion
+                sensor can be located on the base or on the lid. Current valid
+		values are 'base' and 'lid'.
diff --git a/drivers/iio/common/Kconfig b/drivers/iio/common/Kconfig
index 26a6026..e108996 100644
--- a/drivers/iio/common/Kconfig
+++ b/drivers/iio/common/Kconfig
@@ -2,6 +2,7 @@
 # IIO common modules
 #
 
+source "drivers/iio/common/cros_ec_sensors/Kconfig"
 source "drivers/iio/common/hid-sensors/Kconfig"
 source "drivers/iio/common/ms_sensors/Kconfig"
 source "drivers/iio/common/ssp_sensors/Kconfig"
diff --git a/drivers/iio/common/Makefile b/drivers/iio/common/Makefile
index 585da6a..6fa760e 100644
--- a/drivers/iio/common/Makefile
+++ b/drivers/iio/common/Makefile
@@ -7,6 +7,7 @@
 #
 
 # When adding new entries keep the list in alphabetical order
+obj-y += cros_ec_sensors/
 obj-y += hid-sensors/
 obj-y += ms_sensors/
 obj-y += ssp_sensors/
diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig b/drivers/iio/common/cros_ec_sensors/Kconfig
new file mode 100644
index 0000000..24743be
--- /dev/null
+++ b/drivers/iio/common/cros_ec_sensors/Kconfig
@@ -0,0 +1,14 @@
+#
+# Chrome OS Embedded Controller managed sensors library
+#
+config IIO_CROS_EC_SENSORS_CORE
+	tristate "ChromeOS EC Sensors Core"
+	depends on SYSFS && MFD_CROS_EC
+	select IIO_BUFFER
+	select IIO_TRIGGERED_BUFFER
+	help
+	  Base module for the ChromeOS EC Sensors module.
+	  Contains core functions used by other IIO CrosEC sensor
+	  drivers.
+	  Define common attributes and sysfs interrupt handler.
+
diff --git a/drivers/iio/common/cros_ec_sensors/Makefile b/drivers/iio/common/cros_ec_sensors/Makefile
new file mode 100644
index 0000000..95b6901
--- /dev/null
+++ b/drivers/iio/common/cros_ec_sensors/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for sensors seen through the ChromeOS EC sensor hub.
+#
+
+obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.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
new file mode 100644
index 0000000..a3be799
--- /dev/null
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -0,0 +1,450 @@
+/*
+ * cros_ec_sensors_core - Common function for Chrome OS EC sensor driver.
+ *
+ * Copyright (C) 2016 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/kernel.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+#include <linux/platform_device.h>
+
+#include "cros_ec_sensors_core.h"
+
+static char *cros_ec_loc[] = {
+	[MOTIONSENSE_LOC_BASE] = "base",
+	[MOTIONSENSE_LOC_LID] = "lid",
+	[MOTIONSENSE_LOC_MAX] = "unknown",
+};
+
+int cros_ec_sensors_core_init(struct platform_device *pdev,
+			      struct iio_dev *indio_dev,
+			      bool physical_device)
+{
+	struct device *dev = &pdev->dev;
+	struct cros_ec_sensors_core_state *state = iio_priv(indio_dev);
+	struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent);
+	struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
+
+	platform_set_drvdata(pdev, indio_dev);
+
+	state->ec = ec->ec_dev;
+	state->msg = devm_kzalloc(&pdev->dev,
+				max((u16)sizeof(struct ec_params_motion_sense),
+				state->ec->max_response), GFP_KERNEL);
+	if (!state->msg)
+		return -ENOMEM;
+
+	state->resp = (struct ec_response_motion_sense *)state->msg->data;
+
+	mutex_init(&state->cmd_lock);
+
+	/* Set up the host command structure. */
+	state->msg->version = 2;
+	state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
+	state->msg->outsize = sizeof(struct ec_params_motion_sense);
+
+	indio_dev->dev.parent = &pdev->dev;
+	indio_dev->name = pdev->name;
+
+	if (physical_device) {
+		indio_dev->modes = INDIO_DIRECT_MODE;
+
+		state->param.cmd = MOTIONSENSE_CMD_INFO;
+		state->param.info.sensor_num = sensor_platform->sensor_num;
+		if (cros_ec_motion_send_host_cmd(state, 0)) {
+			dev_warn(dev, "Can not access sensor info\n");
+			return -EIO;
+		}
+		state->type = state->resp->info.type;
+		state->loc = state->resp->info.location;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init);
+
+int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *state,
+				 u16 opt_length)
+{
+	int ret;
+
+	if (opt_length)
+		state->msg->insize = min(opt_length, state->ec->max_response);
+	else
+		state->msg->insize = state->ec->max_response;
+
+	memcpy(state->msg->data, &state->param, sizeof(state->param));
+
+	ret = cros_ec_cmd_xfer_status(state->ec, state->msg);
+	if (ret < 0)
+		return -EIO;
+
+	if (ret &&
+	    state->resp != (struct ec_response_motion_sense *)state->msg->data)
+		memcpy(state->resp, state->msg->data, ret);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cros_ec_motion_send_host_cmd);
+
+static ssize_t cros_ec_sensors_calibrate(struct iio_dev *indio_dev,
+		uintptr_t private, const struct iio_chan_spec *chan,
+		const char *buf, size_t len)
+{
+	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+	int ret, i;
+	bool calibrate;
+
+	ret = strtobool(buf, &calibrate);
+	if (ret < 0)
+		return ret;
+	if (!calibrate)
+		return -EINVAL;
+
+	mutex_lock(&st->cmd_lock);
+	st->param.cmd = MOTIONSENSE_CMD_PERFORM_CALIB;
+	ret = cros_ec_motion_send_host_cmd(st, 0);
+	if (ret != 0) {
+		dev_warn(&indio_dev->dev, "Unable to calibrate sensor\n");
+	} else {
+		/* Save values */
+		for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
+			st->calib[i] = st->resp->perform_calib.offset[i];
+	}
+	mutex_unlock(&st->cmd_lock);
+
+	return ret ? ret : len;
+}
+
+static ssize_t cros_ec_sensors_loc(struct iio_dev *indio_dev,
+		uintptr_t private, const struct iio_chan_spec *chan,
+		char *buf)
+{
+	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", cros_ec_loc[st->loc]);
+}
+
+const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[] = {
+	{
+		.name = "calibrate",
+		.shared = IIO_SHARED_BY_ALL,
+		.write = cros_ec_sensors_calibrate
+	},
+	{
+		.name = "location",
+		.shared = IIO_SHARED_BY_ALL,
+		.read = cros_ec_sensors_loc
+	},
+	{ },
+};
+EXPORT_SYMBOL_GPL(cros_ec_sensors_ext_info);
+
+/**
+ * cros_ec_sensors_idx_to_reg - convert index into offset in shared memory
+ * @st:		pointer to state information for device
+ * @idx:	sensor index (should be element of enum sensor_index)
+ *
+ * Return:	address to read at
+ */
+static unsigned int cros_ec_sensors_idx_to_reg(
+					struct cros_ec_sensors_core_state *st,
+					unsigned int idx)
+{
+	/*
+	 * When using LPC interface, only space for 2 Accel and one Gyro.
+	 * First halfword of MOTIONSENSE_TYPE_ACCEL is used by angle.
+	 */
+	if (st->type == MOTIONSENSE_TYPE_ACCEL)
+		return EC_MEMMAP_ACC_DATA + sizeof(u16) *
+			(1 + idx + st->param.info.sensor_num *
+			 CROS_EC_SENSOR_MAX_AXIS);
+
+	return EC_MEMMAP_GYRO_DATA + sizeof(u16) * idx;
+}
+
+static int cros_ec_sensors_cmd_read_u8(struct cros_ec_device *ec,
+				       unsigned int offset, u8 *dest)
+{
+	return ec->cmd_readmem(ec, offset, 1, dest);
+}
+
+static int cros_ec_sensors_cmd_read_u16(struct cros_ec_device *ec,
+					 unsigned int offset, u16 *dest)
+{
+	__le16 tmp;
+	int ret = ec->cmd_readmem(ec, offset, 2, &tmp);
+
+	if (ret >= 0)
+		*dest = le16_to_cpu(tmp);
+
+	return ret;
+}
+
+/**
+ * cros_ec_sensors_read_until_not_busy() - read until is not busy
+ *
+ * @st:	pointer to state information for device
+ *
+ * Read from EC status byte until it reads not busy.
+ * Return: 8-bit status if ok, -errno on failure.
+ */
+static int cros_ec_sensors_read_until_not_busy(
+					struct cros_ec_sensors_core_state *st)
+{
+	struct cros_ec_device *ec = st->ec;
+	u8 status;
+	int ret, attempts = 0;
+
+	ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status);
+	if (ret < 0)
+		return ret;
+
+	while (status & EC_MEMMAP_ACC_STATUS_BUSY_BIT) {
+		/* Give up after enough attempts, return error. */
+		if (attempts++ >= 50)
+			return -EIO;
+
+		/* Small delay every so often. */
+		if (attempts % 5 == 0)
+			msleep(25);
+
+		ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS,
+						  &status);
+		if (ret < 0)
+			return ret;
+	}
+
+	return status;
+}
+
+/**
+ * read_ec_sensors_data_unsafe() - read acceleration data from EC shared memory
+ * @indio_dev:	pointer to IIO device
+ * @scan_mask:	bitmap of the sensor indices to scan
+ * @data:	location to store data
+ *
+ * This is the unsafe function for reading the EC data. It does not guarantee
+ * that the EC will not modify the data as it is being read in.
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+static int cros_ec_sensors_read_data_unsafe(struct iio_dev *indio_dev,
+			 unsigned long scan_mask, s16 *data)
+{
+	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+	struct cros_ec_device *ec = st->ec;
+	unsigned int i;
+	int ret;
+
+	/* Read all sensors enabled in scan_mask. Each value is 2 bytes. */
+	for_each_set_bit(i, &scan_mask, indio_dev->masklength) {
+		ret = cros_ec_sensors_cmd_read_u16(ec,
+					     cros_ec_sensors_idx_to_reg(st, i),
+					     data);
+		if (ret < 0)
+			return ret;
+
+		data++;
+	}
+
+	return 0;
+}
+
+int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev,
+			     unsigned long scan_mask, s16 *data)
+{
+	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+	struct cros_ec_device *ec = st->ec;
+	u8 samp_id = 0xff, status = 0;
+	int ret, attempts = 0;
+
+	/*
+	 * Continually read all data from EC until the status byte after
+	 * all reads reflects that the EC is not busy and the sample id
+	 * matches the sample id from before all reads. This guarantees
+	 * that data read in was not modified by the EC while reading.
+	 */
+	while ((status & (EC_MEMMAP_ACC_STATUS_BUSY_BIT |
+			  EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK)) != samp_id) {
+		/* If we have tried to read too many times, return error. */
+		if (attempts++ >= 5)
+			return -EIO;
+
+		/* Read status byte until EC is not busy. */
+		status = cros_ec_sensors_read_until_not_busy(st);
+		if (status < 0)
+			return status;
+
+		/*
+		 * Store the current sample id so that we can compare to the
+		 * sample id after reading the data.
+		 */
+		samp_id = status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK;
+
+		/* Read all EC data, format it, and store it into data. */
+		ret = cros_ec_sensors_read_data_unsafe(indio_dev, scan_mask,
+						       data);
+		if (ret < 0)
+			return ret;
+
+		/* Read status byte. */
+		ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS,
+						  &status);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cros_ec_sensors_read_lpc);
+
+int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev,
+			     unsigned long scan_mask, s16 *data)
+{
+	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+	int ret;
+	unsigned int i;
+
+	/* Read all sensor data through a command. */
+	st->param.cmd = MOTIONSENSE_CMD_DATA;
+	ret = cros_ec_motion_send_host_cmd(st, sizeof(st->resp->data));
+	if (ret != 0) {
+		dev_warn(&indio_dev->dev, "Unable to read sensor data\n");
+		return ret;
+	}
+
+	for_each_set_bit(i, &scan_mask, indio_dev->masklength) {
+		*data = st->resp->data.data[i];
+		data++;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(cros_ec_sensors_read_cmd);
+
+irqreturn_t cros_ec_sensors_capture(int irq, void *p)
+{
+	struct iio_poll_func *pf = p;
+	struct iio_dev *indio_dev = pf->indio_dev;
+	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&st->cmd_lock);
+
+	/* Clear capture data. */
+	memset(st->samples, 0, indio_dev->scan_bytes);
+
+	/* Read data based on which channels are enabled in scan mask. */
+	ret = st->read_ec_sensors_data(indio_dev,
+				       *(indio_dev->active_scan_mask),
+				       (s16 *)st->samples);
+	if (ret < 0)
+		goto done;
+
+	iio_push_to_buffers_with_timestamp(indio_dev, st->samples,
+					   iio_get_time_ns(indio_dev));
+
+done:
+	/*
+	 * Tell the core we are done with this trigger and ready for the
+	 * next one.
+	 */
+	iio_trigger_notify_done(indio_dev->trig);
+
+	mutex_unlock(&st->cmd_lock);
+
+	return IRQ_HANDLED;
+}
+EXPORT_SYMBOL_GPL(cros_ec_sensors_capture);
+
+int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st,
+			  struct iio_chan_spec const *chan,
+			  int *val, int *val2, long mask)
+{
+	int ret = IIO_VAL_INT;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
+		st->param.ec_rate.data =
+			EC_MOTION_SENSE_NO_VALUE;
+
+		if (cros_ec_motion_send_host_cmd(st, 0))
+			ret = -EIO;
+		else
+			*val = st->resp->ec_rate.ret;
+		break;
+	case IIO_CHAN_INFO_FREQUENCY:
+		st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
+		st->param.sensor_odr.data =
+			EC_MOTION_SENSE_NO_VALUE;
+
+		if (cros_ec_motion_send_host_cmd(st, 0))
+			ret = -EIO;
+		else
+			*val = st->resp->sensor_odr.ret;
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read);
+
+int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
+			       struct iio_chan_spec const *chan,
+			       int val, int val2, long mask)
+{
+	int ret = 0;
+
+	switch (mask) {
+	case IIO_CHAN_INFO_FREQUENCY:
+		st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
+		st->param.sensor_odr.data = val;
+
+		/* Always roundup, so caller gets at least what it asks for. */
+		st->param.sensor_odr.roundup = 1;
+
+		if (cros_ec_motion_send_host_cmd(st, 0))
+			ret = -EIO;
+		break;
+	case IIO_CHAN_INFO_SAMP_FREQ:
+		st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
+		st->param.ec_rate.data = val;
+
+		if (cros_ec_motion_send_host_cmd(st, 0))
+			ret = -EIO;
+		else
+			st->curr_sampl_freq = val;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+EXPORT_SYMBOL_GPL(cros_ec_sensors_core_write);
+
+MODULE_DESCRIPTION("ChromeOS EC sensor hub core functions");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
new file mode 100644
index 0000000..8bc2ca3
--- /dev/null
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
@@ -0,0 +1,175 @@
+/*
+ * ChromeOS EC sensor hub
+ *
+ * Copyright (C) 2016 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.
+ */
+
+#ifndef __CROS_EC_SENSORS_CORE_H
+#define __CROS_EC_SENSORS_CORE_H
+
+#include <linux/irqreturn.h>
+
+enum {
+	CROS_EC_SENSOR_X,
+	CROS_EC_SENSOR_Y,
+	CROS_EC_SENSOR_Z,
+	CROS_EC_SENSOR_MAX_AXIS,
+};
+
+/* EC returns sensor values using signed 16 bit registers */
+#define CROS_EC_SENSOR_BITS 16
+
+/*
+ * 4 16 bit channels are allowed.
+ * Good enough for current sensors, they use up to 3 16 bit vectors.
+ */
+#define CROS_EC_SAMPLE_SIZE  (sizeof(s64) * 2)
+
+/* Minimum sampling period to use when device is suspending */
+#define CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY 1000  /* 1 second */
+
+/**
+ * struct cros_ec_sensors_core_state - state data for EC sensors IIO driver
+ * @ec:				cros EC device structure
+ * @cmd_lock:			lock used to prevent simultaneous access to the
+ *				commands.
+ * @msg:			cros EC command structure
+ * @param:			motion sensor parameters structure
+ * @resp:			motion sensor response structure
+ * @type:			type of motion sensor
+ * @loc:			location where the motion sensor is placed
+ * @calib:			calibration parameters. Note that trigger
+ *				captured data will always provide the calibrated
+ *				data
+ * @samples:			static array to hold data from a single capture.
+ *				For each channel we need 2 bytes, except for
+ *				the timestamp. The timestamp is always last and
+ *				is always 8-byte aligned.
+ * @read_ec_sensors_data:	function used for accessing sensors values
+ * @cuur_sampl_freq:		current sampling period
+ */
+struct cros_ec_sensors_core_state {
+	struct cros_ec_device *ec;
+	struct mutex cmd_lock;
+
+	struct cros_ec_command *msg;
+	struct ec_params_motion_sense param;
+	struct ec_response_motion_sense *resp;
+
+	enum motionsensor_type type;
+	enum motionsensor_location loc;
+
+	s16 calib[CROS_EC_SENSOR_MAX_AXIS];
+
+	u8 samples[CROS_EC_SAMPLE_SIZE];
+
+	int (*read_ec_sensors_data)(struct iio_dev *indio_dev,
+				    unsigned long scan_mask, s16 *data);
+
+	int curr_sampl_freq;
+};
+
+/**
+ * cros_ec_sensors_read_lpc() - retrieve data from EC shared memory
+ * @indio_dev:	pointer to IIO device
+ * @scan_mask:	bitmap of the sensor indices to scan
+ * @data:	location to store data
+ *
+ * This is the safe function for reading the EC data. It guarantees that the
+ * data sampled was not modified by the EC while being read.
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev, unsigned long scan_mask,
+			     s16 *data);
+
+/**
+ * cros_ec_sensors_read_cmd() - retrieve data using the EC command protocol
+ * @indio_dev:	pointer to IIO device
+ * @scan_mask:	bitmap of the sensor indices to scan
+ * @data:	location to store data
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, unsigned long scan_mask,
+			     s16 *data);
+
+/**
+ * cros_ec_sensors_core_init() - basic initialization of the core structure
+ * @pdev:		platform device created for the sensors
+ * @indio_dev:		iio device structure of the device
+ * @physical_device:	true if the device refers to a physical device
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+int cros_ec_sensors_core_init(struct platform_device *pdev,
+			      struct iio_dev *indio_dev, bool physical_device);
+
+/**
+ * cros_ec_sensors_capture() - the trigger handler function
+ * @irq:	the interrupt number.
+ * @p:		a pointer to the poll function.
+ *
+ * On a trigger event occurring, if the pollfunc is attached then this
+ * handler is called as a threaded interrupt (and hence may sleep). It
+ * is responsible for grabbing data from the device and pushing it into
+ * the associated buffer.
+ *
+ * Return: IRQ_HANDLED
+ */
+irqreturn_t cros_ec_sensors_capture(int irq, void *p);
+
+/**
+ * cros_ec_motion_send_host_cmd() - send motion sense host command
+ * @st:		pointer to state information for device
+ * @opt_length:	optional length to reduce the response size, useful on the data
+ *		path. Otherwise, the maximal allowed response size is used
+ *
+ * When called, the sub-command is assumed to be set in param->cmd.
+ *
+ * Return: 0 on success, -errno on failure.
+ */
+int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *st,
+				 u16 opt_length);
+
+/**
+ * cros_ec_sensors_core_read() - function to request a value from the sensor
+ * @st:		pointer to state information for device
+ * @chan:	channel specification structure table
+ * @val:	will contain one element making up the returned value
+ * @val2:	will contain another element making up the returned value
+ * @mask:	specifies which values to be requested
+ *
+ * Return:	the type of value returned by the device
+ */
+int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st,
+			      struct iio_chan_spec const *chan,
+			      int *val, int *val2, long mask);
+
+/**
+ * cros_ec_sensors_core_write() - function to write a value to the sensor
+ * @st:		pointer to state information for device
+ * @chan:	channel specification structure table
+ * @val:	first part of value to write
+ * @val2:	second part of value to write
+ * @mask:	specifies which values to write
+ *
+ * Return:	the type of value returned by the device
+ */
+int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
+			       struct iio_chan_spec const *chan,
+			       int val, int val2, long mask);
+
+/* List of extended channel specification for all sensors */
+extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[];
+
+#endif  /* __CROS_EC_SENSORS_CORE_H */
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index d6539c1..7769ea6 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -151,6 +151,15 @@ struct cros_ec_device {
 	int event_size;
 };
 
+/**
+ * struct cros_ec_sensor_platform - ChromeOS EC sensor platform information
+ *
+ * @sensor_num: Id of the sensor, as reported by the EC.
+ */
+struct cros_ec_sensor_platform {
+	u8 sensor_num;
+};
+
 /* struct cros_ec_platform - ChromeOS EC platform information
  *
  * @ec_name: name of EC device (e.g. 'cros-ec', 'cros-pd', ...)
diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h
index 76728ff..8826e0f 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -1315,6 +1315,24 @@ enum motionsense_command {
 	 */
 	MOTIONSENSE_CMD_KB_WAKE_ANGLE = 5,
 
+	/*
+	 * Returns a single sensor data.
+	 */
+	MOTIONSENSE_CMD_DATA = 6,
+
+	/*
+	 * Perform low level calibration.. On sensors that support it, ask to
+	 * do offset calibration.
+	 */
+	MOTIONSENSE_CMD_PERFORM_CALIB = 10,
+
+	/*
+	 * Sensor Offset command is a setter/getter command for the offset used
+	 * for calibration. The offsets can be calculated by the host, or via
+	 * PERFORM_CALIB command.
+	 */
+	MOTIONSENSE_CMD_SENSOR_OFFSET = 11,
+
 	/* Number of motionsense sub-commands. */
 	MOTIONSENSE_NUM_CMDS
 };
@@ -1335,12 +1353,18 @@ enum motionsensor_id {
 enum motionsensor_type {
 	MOTIONSENSE_TYPE_ACCEL = 0,
 	MOTIONSENSE_TYPE_GYRO = 1,
+	MOTIONSENSE_TYPE_MAG = 2,
+	MOTIONSENSE_TYPE_PROX = 3,
+	MOTIONSENSE_TYPE_LIGHT = 4,
+	MOTIONSENSE_TYPE_ACTIVITY = 5,
+	MOTIONSENSE_TYPE_MAX
 };
 
 /* List of motion sensor locations. */
 enum motionsensor_location {
 	MOTIONSENSE_LOC_BASE = 0,
 	MOTIONSENSE_LOC_LID = 1,
+	MOTIONSENSE_LOC_MAX,
 };
 
 /* List of motion sensor chips. */
@@ -1361,6 +1385,31 @@ enum motionsensor_chip {
  */
 #define EC_MOTION_SENSE_NO_VALUE -1
 
+#define EC_MOTION_SENSE_INVALID_CALIB_TEMP 0x8000
+
+/* Set Calibration information */
+#define MOTION_SENSE_SET_OFFSET	1
+
+struct ec_response_motion_sensor_data {
+	/* Flags for each sensor. */
+	uint8_t flags;
+	/* Sensor number the data comes from */
+	uint8_t sensor_num;
+	/* Each sensor is up to 3-axis. */
+	union {
+		int16_t             data[3];
+		struct {
+			uint16_t    rsvd;
+			uint32_t    timestamp;
+		} __packed;
+		struct {
+			uint8_t     activity; /* motionsensor_activity */
+			uint8_t     state;
+			int16_t     add_info[2];
+		};
+	};
+} __packed;
+
 struct ec_params_motion_sense {
 	uint8_t cmd;
 	union {
@@ -1378,9 +1427,37 @@ struct ec_params_motion_sense {
 			int16_t data;
 		} ec_rate, kb_wake_angle;
 
+		/* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */
+		struct {
+			uint8_t sensor_num;
+
+			/*
+			 * bit 0: If set (MOTION_SENSE_SET_OFFSET), set
+			 * the calibration information in the EC.
+			 * If unset, just retrieve calibration information.
+			 */
+			uint16_t flags;
+
+			/*
+			 * Temperature at calibration, in units of 0.01 C
+			 * 0x8000: invalid / unknown.
+			 * 0x0: 0C
+			 * 0x7fff: +327.67C
+			 */
+			int16_t temp;
+
+			/*
+			 * Offset for calibration.
+			 * Unit:
+			 * Accelerometer: 1/1024 g
+			 * Gyro:          1/1024 deg/s
+			 * Compass:       1/16 uT
+			 */
+			int16_t offset[3];
+		} __packed sensor_offset;
+
 		/* Used for MOTIONSENSE_CMD_INFO. */
 		struct {
-			/* Should be element of enum motionsensor_id. */
 			uint8_t sensor_num;
 		} info;
 
@@ -1410,11 +1487,14 @@ struct ec_response_motion_sense {
 			/* Flags representing the motion sensor module. */
 			uint8_t module_flags;
 
-			/* Flags for each sensor in enum motionsensor_id. */
-			uint8_t sensor_flags[EC_MOTION_SENSOR_COUNT];
+			/* Number of sensors managed directly by the EC. */
+			uint8_t sensor_count;
 
-			/* Array of all sensor data. Each sensor is 3-axis. */
-			int16_t data[3*EC_MOTION_SENSOR_COUNT];
+			/*
+			 * Sensor data is truncated if response_max is too small
+			 * for holding all the data.
+			 */
+			struct ec_response_motion_sensor_data sensor[0];
 		} dump;
 
 		/* Used for MOTIONSENSE_CMD_INFO. */
@@ -1429,6 +1509,9 @@ struct ec_response_motion_sense {
 			uint8_t chip;
 		} info;
 
+		/* Used for MOTIONSENSE_CMD_DATA */
+		struct ec_response_motion_sensor_data data;
+
 		/*
 		 * Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR,
 		 * MOTIONSENSE_CMD_SENSOR_RANGE, and
@@ -1438,6 +1521,12 @@ struct ec_response_motion_sense {
 			/* Current value of the parameter queried. */
 			int32_t ret;
 		} ec_rate, sensor_odr, sensor_range, kb_wake_angle;
+
+		/* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */
+		struct {
+			int16_t temp;
+			int16_t offset[3];
+		} sensor_offset, perform_calib;
 	};
 } __packed;
 
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v4 2/4] iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver
  2016-08-01  9:54 [PATCH v4 0/4] Add support for cros-ec-sensors Enric Balletbo i Serra
  2016-08-01  9:54 ` [PATCH v4 1/4] iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC Sensor Hub Enric Balletbo i Serra
@ 2016-08-01  9:54 ` Enric Balletbo i Serra
  2016-08-15 15:28   ` Jonathan Cameron
  2016-08-01  9:54 ` [PATCH v4 3/4] platform/chrome: Introduce a new function to check EC features Enric Balletbo i Serra
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 30+ messages in thread
From: Enric Balletbo i Serra @ 2016-08-01  9:54 UTC (permalink / raw)
  To: linux-kernel, linux-iio
  Cc: Olof Johansson, Lee Jones, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Guenter Roeck,
	Gwendal Grignou

Handle 3d contiguous sensors like Accelerometers, Gyroscope and
Magnetometer that are presented by the ChromeOS EC Sensor hub.

Signed-off-by: Guenter Roeck <groeck@chromium.org>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
---

Changes since v3:
  - Remove some useless initialitzations as always overwritten.
  - Convert calib structure to a simple array.
Changes since v2:
  - Fix some typos
  - Skip filling by zero structure parameters that already zero'd.
  - Order includes alphabetically.
  - Propagate error codes.
Changes since v1:
  - Fixup multiline comments.
  - Fix some spelling mistakes.
  - Blank line before return statements.
  - Add CROS_EC_SENSORS_ prefix.

 drivers/iio/common/cros_ec_sensors/Kconfig         |   8 +
 drivers/iio/common/cros_ec_sensors/Makefile        |   1 +
 .../iio/common/cros_ec_sensors/cros_ec_sensors.c   | 322 +++++++++++++++++++++
 3 files changed, 331 insertions(+)
 create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c

diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig b/drivers/iio/common/cros_ec_sensors/Kconfig
index 24743be..980bea2 100644
--- a/drivers/iio/common/cros_ec_sensors/Kconfig
+++ b/drivers/iio/common/cros_ec_sensors/Kconfig
@@ -12,3 +12,11 @@ config IIO_CROS_EC_SENSORS_CORE
 	  drivers.
 	  Define common attributes and sysfs interrupt handler.
 
+config IIO_CROS_EC_SENSORS
+	tristate "ChromeOS EC Contiguous Sensors"
+	select IIO_CROS_EC_SENSORS_CORE
+	help
+	  Module to handle 3d contiguous sensors like
+	  Accelerometers, Gyroscope and Magnetometer that are
+	  presented by the ChromeOS EC Sensor hub.
+	  Creates an IIO device for each functions.
diff --git a/drivers/iio/common/cros_ec_sensors/Makefile b/drivers/iio/common/cros_ec_sensors/Makefile
index 95b6901..ec716ff 100644
--- a/drivers/iio/common/cros_ec_sensors/Makefile
+++ b/drivers/iio/common/cros_ec_sensors/Makefile
@@ -3,3 +3,4 @@
 #
 
 obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.o
+obj-$(CONFIG_IIO_CROS_EC_SENSORS) += cros_ec_sensors.o
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
new file mode 100644
index 0000000..48edeba
--- /dev/null
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -0,0 +1,322 @@
+/*
+ * cros_ec_sensors - Driver for Chrome OS Embedded Controller sensors.
+ *
+ * Copyright (C) 2016 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 sensors data. Data access is presented through iio sysfs.
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/kfifo_buf.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/kernel.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+
+#include "cros_ec_sensors_core.h"
+
+#define CROS_EC_SENSORS_MAX_CHANNELS 4
+
+/* State data for ec_sensors iio driver. */
+struct cros_ec_sensors_state {
+	/* Shared by all sensors */
+	struct cros_ec_sensors_core_state core;
+
+	struct iio_chan_spec channels[CROS_EC_SENSORS_MAX_CHANNELS];
+};
+
+static int cros_ec_sensors_read(struct iio_dev *indio_dev,
+			  struct iio_chan_spec const *chan,
+			  int *val, int *val2, long mask)
+{
+	struct cros_ec_sensors_state *st = iio_priv(indio_dev);
+	s16 data = 0;
+	s64 val64;
+	int i;
+	int ret = IIO_VAL_INT;
+	int idx = chan->scan_index;
+
+	mutex_lock(&st->core.cmd_lock);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_RAW:
+		ret = st->core.read_ec_sensors_data(indio_dev, 1 << idx, &data);
+		if (ret < 0)
+			break;
+
+		*val = data;
+		break;
+	case IIO_CHAN_INFO_CALIBBIAS:
+		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
+		st->core.param.sensor_offset.flags = 0;
+
+		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+		if (ret < 0)
+			break;
+
+		/* Save values */
+		for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
+			st->core.calib[i] =
+				st->core.resp->sensor_offset.offset[i];
+
+		*val = st->core.calib[idx];
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
+		st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE;
+
+		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+		if (ret < 0)
+			break;
+
+		val64 = st->core.resp->sensor_range.ret;
+		switch (st->core.type) {
+		case MOTIONSENSE_TYPE_ACCEL:
+			/*
+			 * EC returns data in g, iio exepects m/s^2.
+			 * Do not use IIO_G_TO_M_S_2 to avoid precision loss.
+			 */
+			*val = div_s64(val64 * 980665, 10);
+			*val2 = 10000 << (CROS_EC_SENSOR_BITS - 1);
+			ret = IIO_VAL_FRACTIONAL;
+			break;
+		case MOTIONSENSE_TYPE_GYRO:
+			/*
+			 * EC returns data in dps, iio expects rad/s.
+			 * Do not use IIO_DEGREE_TO_RAD to avoid precision
+			 * loss. Round to the nearest integer.
+			 */
+			*val = div_s64(val64 * 314159 + 9000000ULL, 1000);
+			*val2 = 18000 << (CROS_EC_SENSOR_BITS - 1);
+			ret = IIO_VAL_FRACTIONAL;
+			break;
+		case MOTIONSENSE_TYPE_MAG:
+			/*
+			 * EC returns data in 16LSB / uT,
+			 * iio expects Gauss
+			 */
+			*val = val64;
+			*val2 = 100 << (CROS_EC_SENSOR_BITS - 1);
+			ret = IIO_VAL_FRACTIONAL;
+			break;
+		default:
+			ret = -EINVAL;
+		}
+		break;
+	default:
+		ret = cros_ec_sensors_core_read(&st->core, chan, val, val2,
+						mask);
+		break;
+	}
+	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_state *st = iio_priv(indio_dev);
+	int i;
+	int ret = 0;
+	int idx = chan->scan_index;
+
+	mutex_lock(&st->core.cmd_lock);
+
+	switch (mask) {
+	case IIO_CHAN_INFO_CALIBBIAS:
+		st->core.calib[idx] = val;
+
+		/* Send to EC for each axis, even if not complete */
+		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
+		st->core.param.sensor_offset.flags =
+			MOTION_SENSE_SET_OFFSET;
+		for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
+			st->core.param.sensor_offset.offset[i] =
+				st->core.calib[i];
+		st->core.param.sensor_offset.temp =
+			EC_MOTION_SENSE_INVALID_CALIB_TEMP;
+
+		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+		break;
+	case IIO_CHAN_INFO_SCALE:
+		if (st->core.type == MOTIONSENSE_TYPE_MAG) {
+			ret = -EINVAL;
+			break;
+		}
+		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
+		st->core.param.sensor_range.data = val;
+
+		/* Always roundup, so caller gets at least what it asks for. */
+		st->core.param.sensor_range.roundup = 1;
+
+		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+		break;
+	default:
+		ret = cros_ec_sensors_core_write(
+				&st->core, chan, val, val2, mask);
+		break;
+	}
+
+	mutex_unlock(&st->core.cmd_lock);
+
+	return ret;
+}
+
+static const struct iio_info ec_sensors_info = {
+	.read_raw = &cros_ec_sensors_read,
+	.write_raw = &cros_ec_sensors_write,
+	.driver_module = THIS_MODULE,
+};
+
+static int cros_ec_sensors_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
+	struct cros_ec_device *ec_device;
+	struct iio_dev *indio_dev;
+	struct cros_ec_sensors_state *state;
+	struct iio_chan_spec *channel;
+	int ret, i;
+
+	if (!ec_dev || !ec_dev->ec_dev) {
+		dev_warn(&pdev->dev, "No CROS EC device found.\n");
+		return -EINVAL;
+	}
+	ec_device = ec_dev->ec_dev;
+
+	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state));
+	if (!indio_dev)
+		return -ENOMEM;
+
+	ret = cros_ec_sensors_core_init(pdev, indio_dev, true);
+	if (ret)
+		return ret;
+
+	indio_dev->info = &ec_sensors_info;
+	state = iio_priv(indio_dev);
+	for (channel = state->channels, i = CROS_EC_SENSOR_X;
+	     i < CROS_EC_SENSOR_MAX_AXIS; i++, channel++) {
+		/* Common part */
+		channel->info_mask_separate =
+			BIT(IIO_CHAN_INFO_RAW) |
+			BIT(IIO_CHAN_INFO_CALIBBIAS);
+		channel->info_mask_shared_by_all =
+			BIT(IIO_CHAN_INFO_SCALE) |
+			BIT(IIO_CHAN_INFO_FREQUENCY) |
+			BIT(IIO_CHAN_INFO_SAMP_FREQ);
+		channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
+		channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
+		channel->scan_index = i;
+		channel->ext_info = cros_ec_sensors_ext_info;
+		channel->modified = 1;
+		channel->channel2 = IIO_MOD_X + i;
+		channel->scan_type.sign = 's';
+
+		/* Sensor specific */
+		switch (state->core.type) {
+		case MOTIONSENSE_TYPE_ACCEL:
+			channel->type = IIO_ACCEL;
+			break;
+		case MOTIONSENSE_TYPE_GYRO:
+			channel->type = IIO_ANGL_VEL;
+			break;
+		case MOTIONSENSE_TYPE_MAG:
+			channel->type = IIO_MAGN;
+			break;
+		default:
+			dev_err(&pdev->dev, "Unknown motion sensor\n");
+			return -EINVAL;
+		}
+	}
+
+	/* Timestamp */
+	channel->type = IIO_TIMESTAMP;
+	channel->channel = -1;
+	channel->scan_index = CROS_EC_SENSOR_MAX_AXIS;
+	channel->scan_type.sign = 's';
+	channel->scan_type.realbits = 64;
+	channel->scan_type.storagebits = 64;
+
+	indio_dev->channels = state->channels;
+	indio_dev->num_channels = CROS_EC_SENSORS_MAX_CHANNELS;
+
+	/* There is only enough room for accel and gyro in the io space */
+	if ((state->core.ec->cmd_readmem != NULL) &&
+	    (state->core.type != MOTIONSENSE_TYPE_MAG))
+		state->core.read_ec_sensors_data = cros_ec_sensors_read_lpc;
+	else
+		state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;
+
+	ret = iio_triggered_buffer_setup(indio_dev, NULL,
+					 cros_ec_sensors_capture, NULL);
+	if (ret)
+		return ret;
+
+	ret = iio_device_register(indio_dev);
+	if (ret)
+		goto error_uninit_buffer;
+
+	return 0;
+
+error_uninit_buffer:
+	iio_triggered_buffer_cleanup(indio_dev);
+
+	return ret;
+}
+
+static int cros_ec_sensors_remove(struct platform_device *pdev)
+{
+	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+
+	iio_device_unregister(indio_dev);
+	iio_triggered_buffer_cleanup(indio_dev);
+
+	return 0;
+}
+
+static const struct platform_device_id cros_ec_sensors_ids[] = {
+	{
+		.name = "cros-ec-accel",
+	},
+	{
+		.name = "cros-ec-gyro",
+	},
+	{
+		.name = "cros-ec-mag",
+	},
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids);
+
+static struct platform_driver cros_ec_sensors_platform_driver = {
+	.driver = {
+		.name	= "cros-ec-sensors",
+	},
+	.probe		= cros_ec_sensors_probe,
+	.remove		= cros_ec_sensors_remove,
+	.id_table	= cros_ec_sensors_ids,
+};
+module_platform_driver(cros_ec_sensors_platform_driver);
+
+MODULE_DESCRIPTION("ChromeOS EC 3-axis sensors driver");
+MODULE_LICENSE("GPL v2");
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v4 3/4] platform/chrome: Introduce a new function to check EC features.
  2016-08-01  9:54 [PATCH v4 0/4] Add support for cros-ec-sensors Enric Balletbo i Serra
  2016-08-01  9:54 ` [PATCH v4 1/4] iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC Sensor Hub Enric Balletbo i Serra
  2016-08-01  9:54 ` [PATCH v4 2/4] iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver Enric Balletbo i Serra
@ 2016-08-01  9:54 ` Enric Balletbo i Serra
  2016-08-09 13:59   ` Lee Jones
  2016-08-01  9:54 ` [PATCH v4 4/4] platform/chrome: cros_ec_dev - Register cros-ec sensors Enric Balletbo i Serra
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 30+ messages in thread
From: Enric Balletbo i Serra @ 2016-08-01  9:54 UTC (permalink / raw)
  To: linux-kernel, linux-iio
  Cc: Olof Johansson, Lee Jones, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Guenter Roeck,
	Gwendal Grignou, Vincent Palatin, Tomeu Vizoso

From: Vincent Palatin <vpalatin@chromium.org>

Use the EC_CMD_GET_FEATURES message to check the supported features for
each MCU.

Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
[tomeu: adapted to changes in mainline]
Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
[enric: remove references to USB PD feature and do it more generic]
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Reviewed-by: Guenter Roeck <groeck@chromium.org>
---

Changes since v3:
 - Add Reviewed-by tag.

 drivers/platform/chrome/cros_ec_dev.c | 37 +++++++++++++++
 include/linux/mfd/cros_ec.h           |  1 +
 include/linux/mfd/cros_ec_commands.h  | 84 +++++++++++++++++++++++++++++++++++
 3 files changed, 122 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c
index 8abd80d..7eb5307 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -87,6 +87,41 @@ exit:
 	return ret;
 }
 
+static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
+{
+	struct cros_ec_command *msg;
+	int ret;
+
+	if (ec->features[0] == -1U && ec->features[1] == -1U) {
+		/* features bitmap not read yet */
+
+		msg = kmalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL);
+		if (!msg)
+			return -ENOMEM;
+
+		msg->version = 0;
+		msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset;
+		msg->insize = sizeof(ec->features);
+		msg->outsize = 0;
+
+		ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+		if (ret < 0 || msg->result != EC_RES_SUCCESS) {
+			dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
+				 ret, msg->result);
+			memset(ec->features, 0, sizeof(ec->features));
+		}
+
+		memcpy(ec->features, msg->data, sizeof(ec->features));
+
+		dev_dbg(ec->dev, "EC features %08x %08x\n",
+			ec->features[0], ec->features[1]);
+
+		kfree(msg);
+	}
+
+	return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature);
+}
+
 /* Device file ops */
 static int ec_device_open(struct inode *inode, struct file *filp)
 {
@@ -245,6 +280,8 @@ static int ec_device_probe(struct platform_device *pdev)
 	ec->ec_dev = dev_get_drvdata(dev->parent);
 	ec->dev = dev;
 	ec->cmd_offset = ec_platform->cmd_offset;
+	ec->features[0] = -1U; /* Not cached yet */
+	ec->features[1] = -1U; /* Not cached yet */
 	device_initialize(&ec->class_dev);
 	cdev_init(&ec->cdev, &fops);
 
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 7769ea6..7f039b2 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -187,6 +187,7 @@ struct cros_ec_dev {
 	struct cros_ec_device *ec_dev;
 	struct device *dev;
 	u16 cmd_offset;
+	u32 features[2];
 };
 
 /**
diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h
index 8826e0f..1683003 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -713,6 +713,90 @@ struct ec_response_get_set_value {
 /* More than one command can use these structs to get/set paramters. */
 #define EC_CMD_GSV_PAUSE_IN_S5	0x0c
 
+/*****************************************************************************/
+/* List the features supported by the firmware */
+#define EC_CMD_GET_FEATURES  0x0d
+
+/* Supported features */
+enum ec_feature_code {
+	/*
+	 * This image contains a limited set of features. Another image
+	 * in RW partition may support more features.
+	 */
+	EC_FEATURE_LIMITED = 0,
+	/*
+	 * Commands for probing/reading/writing/erasing the flash in the
+	 * EC are present.
+	 */
+	EC_FEATURE_FLASH = 1,
+	/*
+	 * Can control the fan speed directly.
+	 */
+	EC_FEATURE_PWM_FAN = 2,
+	/*
+	 * Can control the intensity of the keyboard backlight.
+	 */
+	EC_FEATURE_PWM_KEYB = 3,
+	/*
+	 * Support Google lightbar, introduced on Pixel.
+	 */
+	EC_FEATURE_LIGHTBAR = 4,
+	/* Control of LEDs  */
+	EC_FEATURE_LED = 5,
+	/* Exposes an interface to control gyro and sensors.
+	 * The host goes through the EC to access these sensors.
+	 * In addition, the EC may provide composite sensors, like lid angle.
+	 */
+	EC_FEATURE_MOTION_SENSE = 6,
+	/* The keyboard is controlled by the EC */
+	EC_FEATURE_KEYB = 7,
+	/* The AP can use part of the EC flash as persistent storage. */
+	EC_FEATURE_PSTORE = 8,
+	/* The EC monitors BIOS port 80h, and can return POST codes. */
+	EC_FEATURE_PORT80 = 9,
+	/*
+	 * Thermal management: include TMP specific commands.
+	 * Higher level than direct fan control.
+	 */
+	EC_FEATURE_THERMAL = 10,
+	/* Can switch the screen backlight on/off */
+	EC_FEATURE_BKLIGHT_SWITCH = 11,
+	/* Can switch the wifi module on/off */
+	EC_FEATURE_WIFI_SWITCH = 12,
+	/* Monitor host events, through for example SMI or SCI */
+	EC_FEATURE_HOST_EVENTS = 13,
+	/* The EC exposes GPIO commands to control/monitor connected devices. */
+	EC_FEATURE_GPIO = 14,
+	/* The EC can send i2c messages to downstream devices. */
+	EC_FEATURE_I2C = 15,
+	/* Command to control charger are included */
+	EC_FEATURE_CHARGER = 16,
+	/* Simple battery support. */
+	EC_FEATURE_BATTERY = 17,
+	/*
+	 * Support Smart battery protocol
+	 * (Common Smart Battery System Interface Specification)
+	 */
+	EC_FEATURE_SMART_BATTERY = 18,
+	/* EC can dectect when the host hangs. */
+	EC_FEATURE_HANG_DETECT = 19,
+	/* Report power information, for pit only */
+	EC_FEATURE_PMU = 20,
+	/* Another Cros EC device is present downstream of this one */
+	EC_FEATURE_SUB_MCU = 21,
+	/* Support USB Power delivery (PD) commands */
+	EC_FEATURE_USB_PD = 22,
+	/* Control USB multiplexer, for audio through USB port for instance. */
+	EC_FEATURE_USB_MUX = 23,
+	/* Motion Sensor code has an internal software FIFO */
+	EC_FEATURE_MOTION_SENSE_FIFO = 24,
+};
+
+#define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32))
+#define EC_FEATURE_MASK_1(event_code) (1UL << (event_code - 32))
+struct ec_response_get_features {
+	uint32_t flags[2];
+} __packed;
 
 /*****************************************************************************/
 /* Flash commands */
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH v4 4/4] platform/chrome: cros_ec_dev - Register cros-ec sensors
  2016-08-01  9:54 [PATCH v4 0/4] Add support for cros-ec-sensors Enric Balletbo i Serra
                   ` (2 preceding siblings ...)
  2016-08-01  9:54 ` [PATCH v4 3/4] platform/chrome: Introduce a new function to check EC features Enric Balletbo i Serra
@ 2016-08-01  9:54 ` Enric Balletbo i Serra
  2016-08-15 15:31   ` Jonathan Cameron
  2016-08-15 15:24 ` [PATCH v4 0/4] Add support for cros-ec-sensors Jonathan Cameron
  2016-10-22 18:47 ` Jonathan Cameron
  5 siblings, 1 reply; 30+ messages in thread
From: Enric Balletbo i Serra @ 2016-08-01  9:54 UTC (permalink / raw)
  To: linux-kernel, linux-iio
  Cc: Olof Johansson, Lee Jones, Jonathan Cameron, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Guenter Roeck,
	Gwendal Grignou

Check whether the ChromeOS Embedded Controller is a sensor hub and in
such case issue a command to get the number of sensors and register them
all.

Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Reviewed-by: Guenter Roeck <groeck@chromium.org>
---

Changes since v3:
 - Remove Unnecessary ( ) around 'ret < 0'.
 - Add Reviewed-by tag

 .../iio/common/cros_ec_sensors/cros_ec_sensors.c   |   4 +-
 drivers/platform/chrome/cros_ec_dev.c              | 122 +++++++++++++++++++++
 2 files changed, 124 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
index 48edeba..d6c372b 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -51,7 +51,7 @@ static int cros_ec_sensors_read(struct iio_dev *indio_dev,
 	s16 data = 0;
 	s64 val64;
 	int i;
-	int ret = IIO_VAL_INT;
+	int ret;
 	int idx = chan->scan_index;
 
 	mutex_lock(&st->core.cmd_lock);
@@ -137,7 +137,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
 {
 	struct cros_ec_sensors_state *st = iio_priv(indio_dev);
 	int i;
-	int ret = 0;
+	int ret;
 	int idx = chan->scan_index;
 
 	mutex_lock(&st->core.cmd_lock);
diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c
index 7eb5307..47268ec 100644
--- a/drivers/platform/chrome/cros_ec_dev.c
+++ b/drivers/platform/chrome/cros_ec_dev.c
@@ -18,6 +18,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/mfd/core.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -265,6 +266,123 @@ static void __remove(struct device *dev)
 	kfree(ec);
 }
 
+static void cros_ec_sensors_register(struct cros_ec_dev *ec)
+{
+	/*
+	 * Issue a command to get the number of sensor reported.
+	 * Build an array of sensors driver and register them all.
+	 */
+	int ret, i, id, sensor_num;
+	struct mfd_cell *sensor_cells;
+	struct cros_ec_sensor_platform *sensor_platforms;
+	int sensor_type[MOTIONSENSE_TYPE_MAX];
+	struct ec_params_motion_sense *params;
+	struct ec_response_motion_sense *resp;
+	struct cros_ec_command *msg;
+
+	msg = kzalloc(sizeof(struct cros_ec_command) +
+		      max(sizeof(*params), sizeof(*resp)), GFP_KERNEL);
+	if (msg == NULL)
+		return;
+
+	msg->version = 2;
+	msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
+	msg->outsize = sizeof(*params);
+	msg->insize = sizeof(*resp);
+
+	params = (struct ec_params_motion_sense *)msg->data;
+	params->cmd = MOTIONSENSE_CMD_DUMP;
+
+	ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+	if (ret < 0 || msg->result != EC_RES_SUCCESS) {
+		dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n",
+			 ret, msg->result);
+		goto error;
+	}
+
+	resp = (struct ec_response_motion_sense *)msg->data;
+	sensor_num = resp->dump.sensor_count;
+	/* Allocate 2 extra sensors in case lid angle or FIFO are needed */
+	sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 2),
+			       GFP_KERNEL);
+	if (sensor_cells == NULL)
+		goto error;
+
+	sensor_platforms = kzalloc(sizeof(struct cros_ec_sensor_platform) *
+		  (sensor_num + 1), GFP_KERNEL);
+	if (sensor_platforms == NULL)
+		goto error_platforms;
+
+	memset(sensor_type, 0, sizeof(sensor_type));
+	id = 0;
+	for (i = 0; i < sensor_num; i++) {
+		params->cmd = MOTIONSENSE_CMD_INFO;
+		params->info.sensor_num = i;
+		ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
+		if (ret < 0 || msg->result != EC_RES_SUCCESS) {
+			dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n",
+				 i, ret, msg->result);
+			continue;
+		}
+		switch (resp->info.type) {
+		case MOTIONSENSE_TYPE_ACCEL:
+			sensor_cells[id].name = "cros-ec-accel";
+			break;
+		case MOTIONSENSE_TYPE_GYRO:
+			sensor_cells[id].name = "cros-ec-gyro";
+			break;
+		case MOTIONSENSE_TYPE_MAG:
+			sensor_cells[id].name = "cros-ec-mag";
+			break;
+		case MOTIONSENSE_TYPE_PROX:
+			sensor_cells[id].name = "cros-ec-prox";
+			break;
+		case MOTIONSENSE_TYPE_LIGHT:
+			sensor_cells[id].name = "cros-ec-light";
+			break;
+		case MOTIONSENSE_TYPE_ACTIVITY:
+			sensor_cells[id].name = "cros-ec-activity";
+			break;
+		default:
+			dev_warn(ec->dev, "unknown type %d\n", resp->info.type);
+			continue;
+		}
+		sensor_platforms[id].sensor_num = i;
+		sensor_cells[id].id = sensor_type[resp->info.type];
+		sensor_cells[id].platform_data = &sensor_platforms[id];
+		sensor_cells[id].pdata_size =
+			sizeof(struct cros_ec_sensor_platform);
+
+		sensor_type[resp->info.type]++;
+		id++;
+	}
+	if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) {
+		sensor_platforms[id].sensor_num = sensor_num;
+
+		sensor_cells[id].name = "cros-ec-angle";
+		sensor_cells[id].id = 0;
+		sensor_cells[id].platform_data = &sensor_platforms[id];
+		sensor_cells[id].pdata_size =
+			sizeof(struct cros_ec_sensor_platform);
+		id++;
+	}
+	if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
+		sensor_cells[id].name = "cros-ec-ring";
+		id++;
+	}
+
+	ret = mfd_add_devices(ec->dev, 0, sensor_cells, id,
+			      NULL, 0, NULL);
+	if (ret)
+		dev_err(ec->dev, "failed to add EC sensors\n");
+
+	kfree(sensor_platforms);
+error_platforms:
+	kfree(sensor_cells);
+error:
+	kfree(msg);
+}
+
 static int ec_device_probe(struct platform_device *pdev)
 {
 	int retval = -ENOMEM;
@@ -319,6 +437,10 @@ static int ec_device_probe(struct platform_device *pdev)
 		goto dev_reg_failed;
 	}
 
+	/* check whether this EC is a sensor hub. */
+	if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
+		cros_ec_sensors_register(ec);
+
 	return 0;
 
 dev_reg_failed:
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 1/4] iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC Sensor Hub.
  2016-08-01  9:54 ` [PATCH v4 1/4] iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC Sensor Hub Enric Balletbo i Serra
@ 2016-08-01 16:57   ` Guenter Roeck
  2016-08-15 15:28   ` Jonathan Cameron
  1 sibling, 0 replies; 30+ messages in thread
From: Guenter Roeck @ 2016-08-01 16:57 UTC (permalink / raw)
  To: Enric Balletbo i Serra
  Cc: linux-kernel, linux-iio, Olof Johansson, Lee Jones,
	Jonathan Cameron, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Guenter Roeck, Gwendal Grignou

On Mon, Aug 1, 2016 at 2:54 AM, Enric Balletbo i Serra
<enric.balletbo@collabora.com> wrote:
> Add the core functions to be able to support the sensors attached behind
> the ChromeOS Embedded Controller and used by other IIO cros-ec sensor
> drivers.
>
> The cros_ec_sensor_core driver matches with current driver in ChromeOS
> 4.4 tree, so it includes all the fixes at the moment. The support for
> this driver was made by Gwendal Grignou. The original patch and all the
> fixes has been squashed and rebased on top of mainline.
>
> Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
> Signed-off-by: Guenter Roeck <groeck@chromium.org>
> [eballetbo: split, squash and rebase on top of mainline the patches
> found in ChromeOS tree]
> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>

Nitpick below. Please only address if you need to resend for a different reason.

Reviewed-by: Guenter Roeck <linux@roeck-us.net>

> ---
>
[ ... ]

> --- /dev/null
> +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
> @@ -0,0 +1,450 @@
> +/*
> + * cros_ec_sensors_core - Common function for Chrome OS EC sensor driver.
> + *
> + * Copyright (C) 2016 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.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/kfifo_buf.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/kernel.h>
> +#include <linux/mfd/cros_ec.h>
> +#include <linux/mfd/cros_ec_commands.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/sysfs.h>
> +#include <linux/platform_device.h>

Alphabetic oder.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 3/4] platform/chrome: Introduce a new function to check EC features.
  2016-08-01  9:54 ` [PATCH v4 3/4] platform/chrome: Introduce a new function to check EC features Enric Balletbo i Serra
@ 2016-08-09 13:59   ` Lee Jones
  2016-10-25 17:14     ` Jonathan Cameron
  0 siblings, 1 reply; 30+ messages in thread
From: Lee Jones @ 2016-08-09 13:59 UTC (permalink / raw)
  To: Enric Balletbo i Serra
  Cc: linux-kernel, linux-iio, Olof Johansson, Jonathan Cameron,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Guenter Roeck, Gwendal Grignou, Vincent Palatin, Tomeu Vizoso

On Mon, 01 Aug 2016, Enric Balletbo i Serra wrote:

> From: Vincent Palatin <vpalatin@chromium.org>
> 
> Use the EC_CMD_GET_FEATURES message to check the supported features for
> each MCU.
> 
> Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
> [tomeu: adapted to changes in mainline]
> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
> [enric: remove references to USB PD feature and do it more generic]
> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> Reviewed-by: Guenter Roeck <groeck@chromium.org>
> ---
> 
> Changes since v3:
>  - Add Reviewed-by tag.
> 
>  drivers/platform/chrome/cros_ec_dev.c | 37 +++++++++++++++
>  include/linux/mfd/cros_ec.h           |  1 +
>  include/linux/mfd/cros_ec_commands.h  | 84 +++++++++++++++++++++++++++++++++++

For the MFD changes:
  Acked-by: Lee Jones <lee.jones@linaro.org>

>  3 files changed, 122 insertions(+)
> 
> diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c
> index 8abd80d..7eb5307 100644
> --- a/drivers/platform/chrome/cros_ec_dev.c
> +++ b/drivers/platform/chrome/cros_ec_dev.c
> @@ -87,6 +87,41 @@ exit:
>  	return ret;
>  }
>  
> +static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
> +{
> +	struct cros_ec_command *msg;
> +	int ret;
> +
> +	if (ec->features[0] == -1U && ec->features[1] == -1U) {
> +		/* features bitmap not read yet */
> +
> +		msg = kmalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL);
> +		if (!msg)
> +			return -ENOMEM;
> +
> +		msg->version = 0;
> +		msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset;
> +		msg->insize = sizeof(ec->features);
> +		msg->outsize = 0;
> +
> +		ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
> +		if (ret < 0 || msg->result != EC_RES_SUCCESS) {
> +			dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
> +				 ret, msg->result);
> +			memset(ec->features, 0, sizeof(ec->features));
> +		}
> +
> +		memcpy(ec->features, msg->data, sizeof(ec->features));
> +
> +		dev_dbg(ec->dev, "EC features %08x %08x\n",
> +			ec->features[0], ec->features[1]);
> +
> +		kfree(msg);
> +	}
> +
> +	return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature);
> +}
> +
>  /* Device file ops */
>  static int ec_device_open(struct inode *inode, struct file *filp)
>  {
> @@ -245,6 +280,8 @@ static int ec_device_probe(struct platform_device *pdev)
>  	ec->ec_dev = dev_get_drvdata(dev->parent);
>  	ec->dev = dev;
>  	ec->cmd_offset = ec_platform->cmd_offset;
> +	ec->features[0] = -1U; /* Not cached yet */
> +	ec->features[1] = -1U; /* Not cached yet */
>  	device_initialize(&ec->class_dev);
>  	cdev_init(&ec->cdev, &fops);
>  
> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
> index 7769ea6..7f039b2 100644
> --- a/include/linux/mfd/cros_ec.h
> +++ b/include/linux/mfd/cros_ec.h
> @@ -187,6 +187,7 @@ struct cros_ec_dev {
>  	struct cros_ec_device *ec_dev;
>  	struct device *dev;
>  	u16 cmd_offset;
> +	u32 features[2];
>  };
>  
>  /**
> diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h
> index 8826e0f..1683003 100644
> --- a/include/linux/mfd/cros_ec_commands.h
> +++ b/include/linux/mfd/cros_ec_commands.h
> @@ -713,6 +713,90 @@ struct ec_response_get_set_value {
>  /* More than one command can use these structs to get/set paramters. */
>  #define EC_CMD_GSV_PAUSE_IN_S5	0x0c
>  
> +/*****************************************************************************/
> +/* List the features supported by the firmware */
> +#define EC_CMD_GET_FEATURES  0x0d
> +
> +/* Supported features */
> +enum ec_feature_code {
> +	/*
> +	 * This image contains a limited set of features. Another image
> +	 * in RW partition may support more features.
> +	 */
> +	EC_FEATURE_LIMITED = 0,
> +	/*
> +	 * Commands for probing/reading/writing/erasing the flash in the
> +	 * EC are present.
> +	 */
> +	EC_FEATURE_FLASH = 1,
> +	/*
> +	 * Can control the fan speed directly.
> +	 */
> +	EC_FEATURE_PWM_FAN = 2,
> +	/*
> +	 * Can control the intensity of the keyboard backlight.
> +	 */
> +	EC_FEATURE_PWM_KEYB = 3,
> +	/*
> +	 * Support Google lightbar, introduced on Pixel.
> +	 */
> +	EC_FEATURE_LIGHTBAR = 4,
> +	/* Control of LEDs  */
> +	EC_FEATURE_LED = 5,
> +	/* Exposes an interface to control gyro and sensors.
> +	 * The host goes through the EC to access these sensors.
> +	 * In addition, the EC may provide composite sensors, like lid angle.
> +	 */
> +	EC_FEATURE_MOTION_SENSE = 6,
> +	/* The keyboard is controlled by the EC */
> +	EC_FEATURE_KEYB = 7,
> +	/* The AP can use part of the EC flash as persistent storage. */
> +	EC_FEATURE_PSTORE = 8,
> +	/* The EC monitors BIOS port 80h, and can return POST codes. */
> +	EC_FEATURE_PORT80 = 9,
> +	/*
> +	 * Thermal management: include TMP specific commands.
> +	 * Higher level than direct fan control.
> +	 */
> +	EC_FEATURE_THERMAL = 10,
> +	/* Can switch the screen backlight on/off */
> +	EC_FEATURE_BKLIGHT_SWITCH = 11,
> +	/* Can switch the wifi module on/off */
> +	EC_FEATURE_WIFI_SWITCH = 12,
> +	/* Monitor host events, through for example SMI or SCI */
> +	EC_FEATURE_HOST_EVENTS = 13,
> +	/* The EC exposes GPIO commands to control/monitor connected devices. */
> +	EC_FEATURE_GPIO = 14,
> +	/* The EC can send i2c messages to downstream devices. */
> +	EC_FEATURE_I2C = 15,
> +	/* Command to control charger are included */
> +	EC_FEATURE_CHARGER = 16,
> +	/* Simple battery support. */
> +	EC_FEATURE_BATTERY = 17,
> +	/*
> +	 * Support Smart battery protocol
> +	 * (Common Smart Battery System Interface Specification)
> +	 */
> +	EC_FEATURE_SMART_BATTERY = 18,
> +	/* EC can dectect when the host hangs. */
> +	EC_FEATURE_HANG_DETECT = 19,
> +	/* Report power information, for pit only */
> +	EC_FEATURE_PMU = 20,
> +	/* Another Cros EC device is present downstream of this one */
> +	EC_FEATURE_SUB_MCU = 21,
> +	/* Support USB Power delivery (PD) commands */
> +	EC_FEATURE_USB_PD = 22,
> +	/* Control USB multiplexer, for audio through USB port for instance. */
> +	EC_FEATURE_USB_MUX = 23,
> +	/* Motion Sensor code has an internal software FIFO */
> +	EC_FEATURE_MOTION_SENSE_FIFO = 24,
> +};
> +
> +#define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32))
> +#define EC_FEATURE_MASK_1(event_code) (1UL << (event_code - 32))
> +struct ec_response_get_features {
> +	uint32_t flags[2];
> +} __packed;
>  
>  /*****************************************************************************/
>  /* Flash commands */

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 0/4] Add support for cros-ec-sensors
  2016-08-01  9:54 [PATCH v4 0/4] Add support for cros-ec-sensors Enric Balletbo i Serra
                   ` (3 preceding siblings ...)
  2016-08-01  9:54 ` [PATCH v4 4/4] platform/chrome: cros_ec_dev - Register cros-ec sensors Enric Balletbo i Serra
@ 2016-08-15 15:24 ` Jonathan Cameron
  2016-08-16 12:49   ` Lee Jones
  2016-10-22 18:47 ` Jonathan Cameron
  5 siblings, 1 reply; 30+ messages in thread
From: Jonathan Cameron @ 2016-08-15 15:24 UTC (permalink / raw)
  To: Enric Balletbo i Serra, linux-kernel, linux-iio
  Cc: Olof Johansson, Lee Jones, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Guenter Roeck, Gwendal Grignou

On 01/08/16 10:54, Enric Balletbo i Serra wrote:
> Hi,
> 
> This is the four patchset to add support for the sensors behind the ChromeOS
> Embedded Controller.
> 
> This version has only the patches to support common functions and 3d
> contiguous sensors like Accelerometers, Gyroscope and Magnetometer that are
> presented by the ChromeOS EC Sensor hub. The patches were tested on an Oak board.
> 
> The code was checked out from the ChromeOS v3.18 tree and forward ported to
> mainline solving all the conflicts and build issues. I splitted the code in
> single patches that have sense by themselves in order to avoid the chances
> to fail.
> 
> Note that the patches depends on this [1] to apply and work.
> 
> [1] https://lkml.org/lkml/2016/7/1/188
Given this dependency I'm assuming the best route for these is via
the MFD tree...

Lee, shout if you want them to go a different route.

Jonathan
> 
> Waiting for your reviews and feedback.
> 
> Changes since v3 (requested by Guenter Roeck)
>   - Convert structure to a simple array
>   - Remove PM declarations
>   - Remove unnecessary initializations
>   - cros_ec_sensors_cmd_read_u16: Conversion should only be done if ret >= 0
>   - Remove unnecessary else
>   - Add Reviewed-by tag for two last patches.
> 
> Changes since v2 (requested by Guenter Roeck and Jonhatan Cameron)
>   - Rebased and fix build error.
>   - Include a list of possible values in the description of location attr.
>   - Fix some typos.
>   - Remove id sysfs entry.
>   - Skip filling by zero structure parameters that already zero'd.
>   - Order includes alphabetically.
>   - Propagate error codes.
> 
> Changes since v1 (requested by Peter Meerwald-Stadler and Jonhatan Cameron)
>   - Check kernel-doc documentation and 
>   - Bring some patches together.
>   - Fix some spelling mistakes.
>   - Include ABI documentation.
>   - Be more careful with buffer sizes (sprintf -> snprintf)
>   - Add cros_ec_sensors prefix to all function.
>   - Check return values on some functions.
> 
> Best regards,
> 
> Enric Balletbo i Serra (3):
>   iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC
>     Sensor Hub.
>   iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver
>   platform/chrome: cros_ec_dev - Register cros-ec sensors
> 
> Vincent Palatin (1):
>   platform/chrome: Introduce a new function to check EC features.
> 
>  Documentation/ABI/testing/sysfs-bus-iio-cros-ec    |  18 +
>  drivers/iio/common/Kconfig                         |   1 +
>  drivers/iio/common/Makefile                        |   1 +
>  drivers/iio/common/cros_ec_sensors/Kconfig         |  22 +
>  drivers/iio/common/cros_ec_sensors/Makefile        |   6 +
>  .../iio/common/cros_ec_sensors/cros_ec_sensors.c   | 322 +++++++++++++++
>  .../common/cros_ec_sensors/cros_ec_sensors_core.c  | 450 +++++++++++++++++++++
>  .../common/cros_ec_sensors/cros_ec_sensors_core.h  | 175 ++++++++
>  drivers/platform/chrome/cros_ec_dev.c              | 159 ++++++++
>  include/linux/mfd/cros_ec.h                        |  10 +
>  include/linux/mfd/cros_ec_commands.h               | 183 ++++++++-
>  11 files changed, 1342 insertions(+), 5 deletions(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-cros-ec
>  create mode 100644 drivers/iio/common/cros_ec_sensors/Kconfig
>  create mode 100644 drivers/iio/common/cros_ec_sensors/Makefile
>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 1/4] iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC Sensor Hub.
  2016-08-01  9:54 ` [PATCH v4 1/4] iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC Sensor Hub Enric Balletbo i Serra
  2016-08-01 16:57   ` Guenter Roeck
@ 2016-08-15 15:28   ` Jonathan Cameron
  2016-09-03 17:07     ` Jonathan Cameron
  1 sibling, 1 reply; 30+ messages in thread
From: Jonathan Cameron @ 2016-08-15 15:28 UTC (permalink / raw)
  To: Enric Balletbo i Serra, linux-kernel, linux-iio
  Cc: Olof Johansson, Lee Jones, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Guenter Roeck, Gwendal Grignou

On 01/08/16 10:54, Enric Balletbo i Serra wrote:
> Add the core functions to be able to support the sensors attached behind
> the ChromeOS Embedded Controller and used by other IIO cros-ec sensor
> drivers.
> 
> The cros_ec_sensor_core driver matches with current driver in ChromeOS
> 4.4 tree, so it includes all the fixes at the moment. The support for
> this driver was made by Gwendal Grignou. The original patch and all the
> fixes has been squashed and rebased on top of mainline.
> 
> Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
> Signed-off-by: Guenter Roeck <groeck@chromium.org>
> [eballetbo: split, squash and rebase on top of mainline the patches
> found in ChromeOS tree]
> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Reviewed-by: Jonathan Cameron <jic23@kernel.org>

Thanks,

Jonathan
> ---
> 
> Changes since v3:
>   - Convert structure to a simple array
>   - Remove PM declarations
>   - Remove unnecessary initializations
>   - cros_ec_sensors_cmd_read_u16: Conversion should only be done if ret >= 0
>   - Remove unnecessary else
> 
> Changes since v2:
>   - Rebased and fix build error.
>   - Include a list of possible values in the description of location attr.
>   - Fix some typos.
>   - Remove id sysfs entry.
> 
> Changes since v1:
>   - Check kernel-doc documentation.
>   - Bring this in as an when you need it in the rest of the series.
>   - Fix some spelling mistakes.
>   - Include ABI documentation.
>   - Be more careful with buffer sizes (sprintf -> snprintf)
>   - Add cros_ec_sensors prefix to all function.
>   - Check return values on some functions.
> 
>  Documentation/ABI/testing/sysfs-bus-iio-cros-ec    |  18 +
>  drivers/iio/common/Kconfig                         |   1 +
>  drivers/iio/common/Makefile                        |   1 +
>  drivers/iio/common/cros_ec_sensors/Kconfig         |  14 +
>  drivers/iio/common/cros_ec_sensors/Makefile        |   5 +
>  .../common/cros_ec_sensors/cros_ec_sensors_core.c  | 450 +++++++++++++++++++++
>  .../common/cros_ec_sensors/cros_ec_sensors_core.h  | 175 ++++++++
>  include/linux/mfd/cros_ec.h                        |   9 +
>  include/linux/mfd/cros_ec_commands.h               |  99 ++++-
>  9 files changed, 767 insertions(+), 5 deletions(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-cros-ec
>  create mode 100644 drivers/iio/common/cros_ec_sensors/Kconfig
>  create mode 100644 drivers/iio/common/cros_ec_sensors/Makefile
>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-cros-ec b/Documentation/ABI/testing/sysfs-bus-iio-cros-ec
> new file mode 100644
> index 0000000..297b972
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-bus-iio-cros-ec
> @@ -0,0 +1,18 @@
> +What:		/sys/bus/iio/devices/iio:deviceX/calibrate
> +Date:		July 2015
> +KernelVersion:	4.7
> +Contact:	linux-iio@vger.kernel.org
> +Description:
> +		Writing '1' will perform a FOC (Fast Online Calibration). The
> +                corresponding calibration offsets can be read from *_calibbias
> +                entries.
> +
> +What:		/sys/bus/iio/devices/iio:deviceX/location
> +Date:		July 2015
> +KernelVersion:	4.7
> +Contact:	linux-iio@vger.kernel.org
> +Description:
> +		This attribute returns a string with the physical location where
> +                the motion sensor is placed. For example, in a laptop a motion
> +                sensor can be located on the base or on the lid. Current valid
> +		values are 'base' and 'lid'.
> diff --git a/drivers/iio/common/Kconfig b/drivers/iio/common/Kconfig
> index 26a6026..e108996 100644
> --- a/drivers/iio/common/Kconfig
> +++ b/drivers/iio/common/Kconfig
> @@ -2,6 +2,7 @@
>  # IIO common modules
>  #
>  
> +source "drivers/iio/common/cros_ec_sensors/Kconfig"
>  source "drivers/iio/common/hid-sensors/Kconfig"
>  source "drivers/iio/common/ms_sensors/Kconfig"
>  source "drivers/iio/common/ssp_sensors/Kconfig"
> diff --git a/drivers/iio/common/Makefile b/drivers/iio/common/Makefile
> index 585da6a..6fa760e 100644
> --- a/drivers/iio/common/Makefile
> +++ b/drivers/iio/common/Makefile
> @@ -7,6 +7,7 @@
>  #
>  
>  # When adding new entries keep the list in alphabetical order
> +obj-y += cros_ec_sensors/
>  obj-y += hid-sensors/
>  obj-y += ms_sensors/
>  obj-y += ssp_sensors/
> diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig b/drivers/iio/common/cros_ec_sensors/Kconfig
> new file mode 100644
> index 0000000..24743be
> --- /dev/null
> +++ b/drivers/iio/common/cros_ec_sensors/Kconfig
> @@ -0,0 +1,14 @@
> +#
> +# Chrome OS Embedded Controller managed sensors library
> +#
> +config IIO_CROS_EC_SENSORS_CORE
> +	tristate "ChromeOS EC Sensors Core"
> +	depends on SYSFS && MFD_CROS_EC
> +	select IIO_BUFFER
> +	select IIO_TRIGGERED_BUFFER
> +	help
> +	  Base module for the ChromeOS EC Sensors module.
> +	  Contains core functions used by other IIO CrosEC sensor
> +	  drivers.
> +	  Define common attributes and sysfs interrupt handler.
> +
> diff --git a/drivers/iio/common/cros_ec_sensors/Makefile b/drivers/iio/common/cros_ec_sensors/Makefile
> new file mode 100644
> index 0000000..95b6901
> --- /dev/null
> +++ b/drivers/iio/common/cros_ec_sensors/Makefile
> @@ -0,0 +1,5 @@
> +#
> +# Makefile for sensors seen through the ChromeOS EC sensor hub.
> +#
> +
> +obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.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
> new file mode 100644
> index 0000000..a3be799
> --- /dev/null
> +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
> @@ -0,0 +1,450 @@
> +/*
> + * cros_ec_sensors_core - Common function for Chrome OS EC sensor driver.
> + *
> + * Copyright (C) 2016 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.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/kfifo_buf.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/kernel.h>
> +#include <linux/mfd/cros_ec.h>
> +#include <linux/mfd/cros_ec_commands.h>
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/sysfs.h>
> +#include <linux/platform_device.h>
> +
> +#include "cros_ec_sensors_core.h"
> +
> +static char *cros_ec_loc[] = {
> +	[MOTIONSENSE_LOC_BASE] = "base",
> +	[MOTIONSENSE_LOC_LID] = "lid",
> +	[MOTIONSENSE_LOC_MAX] = "unknown",
> +};
> +
> +int cros_ec_sensors_core_init(struct platform_device *pdev,
> +			      struct iio_dev *indio_dev,
> +			      bool physical_device)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct cros_ec_sensors_core_state *state = iio_priv(indio_dev);
> +	struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent);
> +	struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
> +
> +	platform_set_drvdata(pdev, indio_dev);
> +
> +	state->ec = ec->ec_dev;
> +	state->msg = devm_kzalloc(&pdev->dev,
> +				max((u16)sizeof(struct ec_params_motion_sense),
> +				state->ec->max_response), GFP_KERNEL);
> +	if (!state->msg)
> +		return -ENOMEM;
> +
> +	state->resp = (struct ec_response_motion_sense *)state->msg->data;
> +
> +	mutex_init(&state->cmd_lock);
> +
> +	/* Set up the host command structure. */
> +	state->msg->version = 2;
> +	state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
> +	state->msg->outsize = sizeof(struct ec_params_motion_sense);
> +
> +	indio_dev->dev.parent = &pdev->dev;
> +	indio_dev->name = pdev->name;
> +
> +	if (physical_device) {
> +		indio_dev->modes = INDIO_DIRECT_MODE;
> +
> +		state->param.cmd = MOTIONSENSE_CMD_INFO;
> +		state->param.info.sensor_num = sensor_platform->sensor_num;
> +		if (cros_ec_motion_send_host_cmd(state, 0)) {
> +			dev_warn(dev, "Can not access sensor info\n");
> +			return -EIO;
> +		}
> +		state->type = state->resp->info.type;
> +		state->loc = state->resp->info.location;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init);
> +
> +int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *state,
> +				 u16 opt_length)
> +{
> +	int ret;
> +
> +	if (opt_length)
> +		state->msg->insize = min(opt_length, state->ec->max_response);
> +	else
> +		state->msg->insize = state->ec->max_response;
> +
> +	memcpy(state->msg->data, &state->param, sizeof(state->param));
> +
> +	ret = cros_ec_cmd_xfer_status(state->ec, state->msg);
> +	if (ret < 0)
> +		return -EIO;
> +
> +	if (ret &&
> +	    state->resp != (struct ec_response_motion_sense *)state->msg->data)
> +		memcpy(state->resp, state->msg->data, ret);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(cros_ec_motion_send_host_cmd);
> +
> +static ssize_t cros_ec_sensors_calibrate(struct iio_dev *indio_dev,
> +		uintptr_t private, const struct iio_chan_spec *chan,
> +		const char *buf, size_t len)
> +{
> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
> +	int ret, i;
> +	bool calibrate;
> +
> +	ret = strtobool(buf, &calibrate);
> +	if (ret < 0)
> +		return ret;
> +	if (!calibrate)
> +		return -EINVAL;
> +
> +	mutex_lock(&st->cmd_lock);
> +	st->param.cmd = MOTIONSENSE_CMD_PERFORM_CALIB;
> +	ret = cros_ec_motion_send_host_cmd(st, 0);
> +	if (ret != 0) {
> +		dev_warn(&indio_dev->dev, "Unable to calibrate sensor\n");
> +	} else {
> +		/* Save values */
> +		for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
> +			st->calib[i] = st->resp->perform_calib.offset[i];
> +	}
> +	mutex_unlock(&st->cmd_lock);
> +
> +	return ret ? ret : len;
> +}
> +
> +static ssize_t cros_ec_sensors_loc(struct iio_dev *indio_dev,
> +		uintptr_t private, const struct iio_chan_spec *chan,
> +		char *buf)
> +{
> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
> +
> +	return snprintf(buf, PAGE_SIZE, "%s\n", cros_ec_loc[st->loc]);
> +}
> +
> +const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[] = {
> +	{
> +		.name = "calibrate",
> +		.shared = IIO_SHARED_BY_ALL,
> +		.write = cros_ec_sensors_calibrate
> +	},
> +	{
> +		.name = "location",
> +		.shared = IIO_SHARED_BY_ALL,
> +		.read = cros_ec_sensors_loc
> +	},
> +	{ },
> +};
> +EXPORT_SYMBOL_GPL(cros_ec_sensors_ext_info);
> +
> +/**
> + * cros_ec_sensors_idx_to_reg - convert index into offset in shared memory
> + * @st:		pointer to state information for device
> + * @idx:	sensor index (should be element of enum sensor_index)
> + *
> + * Return:	address to read at
> + */
> +static unsigned int cros_ec_sensors_idx_to_reg(
> +					struct cros_ec_sensors_core_state *st,
> +					unsigned int idx)
> +{
> +	/*
> +	 * When using LPC interface, only space for 2 Accel and one Gyro.
> +	 * First halfword of MOTIONSENSE_TYPE_ACCEL is used by angle.
> +	 */
> +	if (st->type == MOTIONSENSE_TYPE_ACCEL)
> +		return EC_MEMMAP_ACC_DATA + sizeof(u16) *
> +			(1 + idx + st->param.info.sensor_num *
> +			 CROS_EC_SENSOR_MAX_AXIS);
> +
> +	return EC_MEMMAP_GYRO_DATA + sizeof(u16) * idx;
> +}
> +
> +static int cros_ec_sensors_cmd_read_u8(struct cros_ec_device *ec,
> +				       unsigned int offset, u8 *dest)
> +{
> +	return ec->cmd_readmem(ec, offset, 1, dest);
> +}
> +
> +static int cros_ec_sensors_cmd_read_u16(struct cros_ec_device *ec,
> +					 unsigned int offset, u16 *dest)
> +{
> +	__le16 tmp;
> +	int ret = ec->cmd_readmem(ec, offset, 2, &tmp);
> +
> +	if (ret >= 0)
> +		*dest = le16_to_cpu(tmp);
> +
> +	return ret;
> +}
> +
> +/**
> + * cros_ec_sensors_read_until_not_busy() - read until is not busy
> + *
> + * @st:	pointer to state information for device
> + *
> + * Read from EC status byte until it reads not busy.
> + * Return: 8-bit status if ok, -errno on failure.
> + */
> +static int cros_ec_sensors_read_until_not_busy(
> +					struct cros_ec_sensors_core_state *st)
> +{
> +	struct cros_ec_device *ec = st->ec;
> +	u8 status;
> +	int ret, attempts = 0;
> +
> +	ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status);
> +	if (ret < 0)
> +		return ret;
> +
> +	while (status & EC_MEMMAP_ACC_STATUS_BUSY_BIT) {
> +		/* Give up after enough attempts, return error. */
> +		if (attempts++ >= 50)
> +			return -EIO;
> +
> +		/* Small delay every so often. */
> +		if (attempts % 5 == 0)
> +			msleep(25);
> +
> +		ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS,
> +						  &status);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	return status;
> +}
> +
> +/**
> + * read_ec_sensors_data_unsafe() - read acceleration data from EC shared memory
> + * @indio_dev:	pointer to IIO device
> + * @scan_mask:	bitmap of the sensor indices to scan
> + * @data:	location to store data
> + *
> + * This is the unsafe function for reading the EC data. It does not guarantee
> + * that the EC will not modify the data as it is being read in.
> + *
> + * Return: 0 on success, -errno on failure.
> + */
> +static int cros_ec_sensors_read_data_unsafe(struct iio_dev *indio_dev,
> +			 unsigned long scan_mask, s16 *data)
> +{
> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
> +	struct cros_ec_device *ec = st->ec;
> +	unsigned int i;
> +	int ret;
> +
> +	/* Read all sensors enabled in scan_mask. Each value is 2 bytes. */
> +	for_each_set_bit(i, &scan_mask, indio_dev->masklength) {
> +		ret = cros_ec_sensors_cmd_read_u16(ec,
> +					     cros_ec_sensors_idx_to_reg(st, i),
> +					     data);
> +		if (ret < 0)
> +			return ret;
> +
> +		data++;
> +	}
> +
> +	return 0;
> +}
> +
> +int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev,
> +			     unsigned long scan_mask, s16 *data)
> +{
> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
> +	struct cros_ec_device *ec = st->ec;
> +	u8 samp_id = 0xff, status = 0;
> +	int ret, attempts = 0;
> +
> +	/*
> +	 * Continually read all data from EC until the status byte after
> +	 * all reads reflects that the EC is not busy and the sample id
> +	 * matches the sample id from before all reads. This guarantees
> +	 * that data read in was not modified by the EC while reading.
> +	 */
> +	while ((status & (EC_MEMMAP_ACC_STATUS_BUSY_BIT |
> +			  EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK)) != samp_id) {
> +		/* If we have tried to read too many times, return error. */
> +		if (attempts++ >= 5)
> +			return -EIO;
> +
> +		/* Read status byte until EC is not busy. */
> +		status = cros_ec_sensors_read_until_not_busy(st);
> +		if (status < 0)
> +			return status;
> +
> +		/*
> +		 * Store the current sample id so that we can compare to the
> +		 * sample id after reading the data.
> +		 */
> +		samp_id = status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK;
> +
> +		/* Read all EC data, format it, and store it into data. */
> +		ret = cros_ec_sensors_read_data_unsafe(indio_dev, scan_mask,
> +						       data);
> +		if (ret < 0)
> +			return ret;
> +
> +		/* Read status byte. */
> +		ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS,
> +						  &status);
> +		if (ret < 0)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(cros_ec_sensors_read_lpc);
> +
> +int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev,
> +			     unsigned long scan_mask, s16 *data)
> +{
> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
> +	int ret;
> +	unsigned int i;
> +
> +	/* Read all sensor data through a command. */
> +	st->param.cmd = MOTIONSENSE_CMD_DATA;
> +	ret = cros_ec_motion_send_host_cmd(st, sizeof(st->resp->data));
> +	if (ret != 0) {
> +		dev_warn(&indio_dev->dev, "Unable to read sensor data\n");
> +		return ret;
> +	}
> +
> +	for_each_set_bit(i, &scan_mask, indio_dev->masklength) {
> +		*data = st->resp->data.data[i];
> +		data++;
> +	}
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(cros_ec_sensors_read_cmd);
> +
> +irqreturn_t cros_ec_sensors_capture(int irq, void *p)
> +{
> +	struct iio_poll_func *pf = p;
> +	struct iio_dev *indio_dev = pf->indio_dev;
> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
> +	int ret;
> +
> +	mutex_lock(&st->cmd_lock);
> +
> +	/* Clear capture data. */
> +	memset(st->samples, 0, indio_dev->scan_bytes);
> +
> +	/* Read data based on which channels are enabled in scan mask. */
> +	ret = st->read_ec_sensors_data(indio_dev,
> +				       *(indio_dev->active_scan_mask),
> +				       (s16 *)st->samples);
> +	if (ret < 0)
> +		goto done;
> +
> +	iio_push_to_buffers_with_timestamp(indio_dev, st->samples,
> +					   iio_get_time_ns(indio_dev));
> +
> +done:
> +	/*
> +	 * Tell the core we are done with this trigger and ready for the
> +	 * next one.
> +	 */
> +	iio_trigger_notify_done(indio_dev->trig);
> +
> +	mutex_unlock(&st->cmd_lock);
> +
> +	return IRQ_HANDLED;
> +}
> +EXPORT_SYMBOL_GPL(cros_ec_sensors_capture);
> +
> +int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st,
> +			  struct iio_chan_spec const *chan,
> +			  int *val, int *val2, long mask)
> +{
> +	int ret = IIO_VAL_INT;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_SAMP_FREQ:
> +		st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
> +		st->param.ec_rate.data =
> +			EC_MOTION_SENSE_NO_VALUE;
> +
> +		if (cros_ec_motion_send_host_cmd(st, 0))
> +			ret = -EIO;
> +		else
> +			*val = st->resp->ec_rate.ret;
> +		break;
> +	case IIO_CHAN_INFO_FREQUENCY:
> +		st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
> +		st->param.sensor_odr.data =
> +			EC_MOTION_SENSE_NO_VALUE;
> +
> +		if (cros_ec_motion_send_host_cmd(st, 0))
> +			ret = -EIO;
> +		else
> +			*val = st->resp->sensor_odr.ret;
> +		break;
> +	default:
> +		break;
> +	}
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read);
> +
> +int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
> +			       struct iio_chan_spec const *chan,
> +			       int val, int val2, long mask)
> +{
> +	int ret = 0;
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_FREQUENCY:
> +		st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
> +		st->param.sensor_odr.data = val;
> +
> +		/* Always roundup, so caller gets at least what it asks for. */
> +		st->param.sensor_odr.roundup = 1;
> +
> +		if (cros_ec_motion_send_host_cmd(st, 0))
> +			ret = -EIO;
> +		break;
> +	case IIO_CHAN_INFO_SAMP_FREQ:
> +		st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
> +		st->param.ec_rate.data = val;
> +
> +		if (cros_ec_motion_send_host_cmd(st, 0))
> +			ret = -EIO;
> +		else
> +			st->curr_sampl_freq = val;
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(cros_ec_sensors_core_write);
> +
> +MODULE_DESCRIPTION("ChromeOS EC sensor hub core functions");
> +MODULE_LICENSE("GPL v2");
> diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
> new file mode 100644
> index 0000000..8bc2ca3
> --- /dev/null
> +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
> @@ -0,0 +1,175 @@
> +/*
> + * ChromeOS EC sensor hub
> + *
> + * Copyright (C) 2016 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.
> + */
> +
> +#ifndef __CROS_EC_SENSORS_CORE_H
> +#define __CROS_EC_SENSORS_CORE_H
> +
> +#include <linux/irqreturn.h>
> +
> +enum {
> +	CROS_EC_SENSOR_X,
> +	CROS_EC_SENSOR_Y,
> +	CROS_EC_SENSOR_Z,
> +	CROS_EC_SENSOR_MAX_AXIS,
> +};
> +
> +/* EC returns sensor values using signed 16 bit registers */
> +#define CROS_EC_SENSOR_BITS 16
> +
> +/*
> + * 4 16 bit channels are allowed.
> + * Good enough for current sensors, they use up to 3 16 bit vectors.
> + */
> +#define CROS_EC_SAMPLE_SIZE  (sizeof(s64) * 2)
> +
> +/* Minimum sampling period to use when device is suspending */
> +#define CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY 1000  /* 1 second */
> +
> +/**
> + * struct cros_ec_sensors_core_state - state data for EC sensors IIO driver
> + * @ec:				cros EC device structure
> + * @cmd_lock:			lock used to prevent simultaneous access to the
> + *				commands.
> + * @msg:			cros EC command structure
> + * @param:			motion sensor parameters structure
> + * @resp:			motion sensor response structure
> + * @type:			type of motion sensor
> + * @loc:			location where the motion sensor is placed
> + * @calib:			calibration parameters. Note that trigger
> + *				captured data will always provide the calibrated
> + *				data
> + * @samples:			static array to hold data from a single capture.
> + *				For each channel we need 2 bytes, except for
> + *				the timestamp. The timestamp is always last and
> + *				is always 8-byte aligned.
> + * @read_ec_sensors_data:	function used for accessing sensors values
> + * @cuur_sampl_freq:		current sampling period
> + */
> +struct cros_ec_sensors_core_state {
> +	struct cros_ec_device *ec;
> +	struct mutex cmd_lock;
> +
> +	struct cros_ec_command *msg;
> +	struct ec_params_motion_sense param;
> +	struct ec_response_motion_sense *resp;
> +
> +	enum motionsensor_type type;
> +	enum motionsensor_location loc;
> +
> +	s16 calib[CROS_EC_SENSOR_MAX_AXIS];
> +
> +	u8 samples[CROS_EC_SAMPLE_SIZE];
> +
> +	int (*read_ec_sensors_data)(struct iio_dev *indio_dev,
> +				    unsigned long scan_mask, s16 *data);
> +
> +	int curr_sampl_freq;
> +};
> +
> +/**
> + * cros_ec_sensors_read_lpc() - retrieve data from EC shared memory
> + * @indio_dev:	pointer to IIO device
> + * @scan_mask:	bitmap of the sensor indices to scan
> + * @data:	location to store data
> + *
> + * This is the safe function for reading the EC data. It guarantees that the
> + * data sampled was not modified by the EC while being read.
> + *
> + * Return: 0 on success, -errno on failure.
> + */
> +int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev, unsigned long scan_mask,
> +			     s16 *data);
> +
> +/**
> + * cros_ec_sensors_read_cmd() - retrieve data using the EC command protocol
> + * @indio_dev:	pointer to IIO device
> + * @scan_mask:	bitmap of the sensor indices to scan
> + * @data:	location to store data
> + *
> + * Return: 0 on success, -errno on failure.
> + */
> +int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, unsigned long scan_mask,
> +			     s16 *data);
> +
> +/**
> + * cros_ec_sensors_core_init() - basic initialization of the core structure
> + * @pdev:		platform device created for the sensors
> + * @indio_dev:		iio device structure of the device
> + * @physical_device:	true if the device refers to a physical device
> + *
> + * Return: 0 on success, -errno on failure.
> + */
> +int cros_ec_sensors_core_init(struct platform_device *pdev,
> +			      struct iio_dev *indio_dev, bool physical_device);
> +
> +/**
> + * cros_ec_sensors_capture() - the trigger handler function
> + * @irq:	the interrupt number.
> + * @p:		a pointer to the poll function.
> + *
> + * On a trigger event occurring, if the pollfunc is attached then this
> + * handler is called as a threaded interrupt (and hence may sleep). It
> + * is responsible for grabbing data from the device and pushing it into
> + * the associated buffer.
> + *
> + * Return: IRQ_HANDLED
> + */
> +irqreturn_t cros_ec_sensors_capture(int irq, void *p);
> +
> +/**
> + * cros_ec_motion_send_host_cmd() - send motion sense host command
> + * @st:		pointer to state information for device
> + * @opt_length:	optional length to reduce the response size, useful on the data
> + *		path. Otherwise, the maximal allowed response size is used
> + *
> + * When called, the sub-command is assumed to be set in param->cmd.
> + *
> + * Return: 0 on success, -errno on failure.
> + */
> +int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *st,
> +				 u16 opt_length);
> +
> +/**
> + * cros_ec_sensors_core_read() - function to request a value from the sensor
> + * @st:		pointer to state information for device
> + * @chan:	channel specification structure table
> + * @val:	will contain one element making up the returned value
> + * @val2:	will contain another element making up the returned value
> + * @mask:	specifies which values to be requested
> + *
> + * Return:	the type of value returned by the device
> + */
> +int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st,
> +			      struct iio_chan_spec const *chan,
> +			      int *val, int *val2, long mask);
> +
> +/**
> + * cros_ec_sensors_core_write() - function to write a value to the sensor
> + * @st:		pointer to state information for device
> + * @chan:	channel specification structure table
> + * @val:	first part of value to write
> + * @val2:	second part of value to write
> + * @mask:	specifies which values to write
> + *
> + * Return:	the type of value returned by the device
> + */
> +int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
> +			       struct iio_chan_spec const *chan,
> +			       int val, int val2, long mask);
> +
> +/* List of extended channel specification for all sensors */
> +extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[];
> +
> +#endif  /* __CROS_EC_SENSORS_CORE_H */
> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
> index d6539c1..7769ea6 100644
> --- a/include/linux/mfd/cros_ec.h
> +++ b/include/linux/mfd/cros_ec.h
> @@ -151,6 +151,15 @@ struct cros_ec_device {
>  	int event_size;
>  };
>  
> +/**
> + * struct cros_ec_sensor_platform - ChromeOS EC sensor platform information
> + *
> + * @sensor_num: Id of the sensor, as reported by the EC.
> + */
> +struct cros_ec_sensor_platform {
> +	u8 sensor_num;
> +};
> +
>  /* struct cros_ec_platform - ChromeOS EC platform information
>   *
>   * @ec_name: name of EC device (e.g. 'cros-ec', 'cros-pd', ...)
> diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h
> index 76728ff..8826e0f 100644
> --- a/include/linux/mfd/cros_ec_commands.h
> +++ b/include/linux/mfd/cros_ec_commands.h
> @@ -1315,6 +1315,24 @@ enum motionsense_command {
>  	 */
>  	MOTIONSENSE_CMD_KB_WAKE_ANGLE = 5,
>  
> +	/*
> +	 * Returns a single sensor data.
> +	 */
> +	MOTIONSENSE_CMD_DATA = 6,
> +
> +	/*
> +	 * Perform low level calibration.. On sensors that support it, ask to
> +	 * do offset calibration.
> +	 */
> +	MOTIONSENSE_CMD_PERFORM_CALIB = 10,
> +
> +	/*
> +	 * Sensor Offset command is a setter/getter command for the offset used
> +	 * for calibration. The offsets can be calculated by the host, or via
> +	 * PERFORM_CALIB command.
> +	 */
> +	MOTIONSENSE_CMD_SENSOR_OFFSET = 11,
> +
>  	/* Number of motionsense sub-commands. */
>  	MOTIONSENSE_NUM_CMDS
>  };
> @@ -1335,12 +1353,18 @@ enum motionsensor_id {
>  enum motionsensor_type {
>  	MOTIONSENSE_TYPE_ACCEL = 0,
>  	MOTIONSENSE_TYPE_GYRO = 1,
> +	MOTIONSENSE_TYPE_MAG = 2,
> +	MOTIONSENSE_TYPE_PROX = 3,
> +	MOTIONSENSE_TYPE_LIGHT = 4,
> +	MOTIONSENSE_TYPE_ACTIVITY = 5,
> +	MOTIONSENSE_TYPE_MAX
>  };
>  
>  /* List of motion sensor locations. */
>  enum motionsensor_location {
>  	MOTIONSENSE_LOC_BASE = 0,
>  	MOTIONSENSE_LOC_LID = 1,
> +	MOTIONSENSE_LOC_MAX,
>  };
>  
>  /* List of motion sensor chips. */
> @@ -1361,6 +1385,31 @@ enum motionsensor_chip {
>   */
>  #define EC_MOTION_SENSE_NO_VALUE -1
>  
> +#define EC_MOTION_SENSE_INVALID_CALIB_TEMP 0x8000
> +
> +/* Set Calibration information */
> +#define MOTION_SENSE_SET_OFFSET	1
> +
> +struct ec_response_motion_sensor_data {
> +	/* Flags for each sensor. */
> +	uint8_t flags;
> +	/* Sensor number the data comes from */
> +	uint8_t sensor_num;
> +	/* Each sensor is up to 3-axis. */
> +	union {
> +		int16_t             data[3];
> +		struct {
> +			uint16_t    rsvd;
> +			uint32_t    timestamp;
> +		} __packed;
> +		struct {
> +			uint8_t     activity; /* motionsensor_activity */
> +			uint8_t     state;
> +			int16_t     add_info[2];
> +		};
> +	};
> +} __packed;
> +
>  struct ec_params_motion_sense {
>  	uint8_t cmd;
>  	union {
> @@ -1378,9 +1427,37 @@ struct ec_params_motion_sense {
>  			int16_t data;
>  		} ec_rate, kb_wake_angle;
>  
> +		/* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */
> +		struct {
> +			uint8_t sensor_num;
> +
> +			/*
> +			 * bit 0: If set (MOTION_SENSE_SET_OFFSET), set
> +			 * the calibration information in the EC.
> +			 * If unset, just retrieve calibration information.
> +			 */
> +			uint16_t flags;
> +
> +			/*
> +			 * Temperature at calibration, in units of 0.01 C
> +			 * 0x8000: invalid / unknown.
> +			 * 0x0: 0C
> +			 * 0x7fff: +327.67C
> +			 */
> +			int16_t temp;
> +
> +			/*
> +			 * Offset for calibration.
> +			 * Unit:
> +			 * Accelerometer: 1/1024 g
> +			 * Gyro:          1/1024 deg/s
> +			 * Compass:       1/16 uT
> +			 */
> +			int16_t offset[3];
> +		} __packed sensor_offset;
> +
>  		/* Used for MOTIONSENSE_CMD_INFO. */
>  		struct {
> -			/* Should be element of enum motionsensor_id. */
>  			uint8_t sensor_num;
>  		} info;
>  
> @@ -1410,11 +1487,14 @@ struct ec_response_motion_sense {
>  			/* Flags representing the motion sensor module. */
>  			uint8_t module_flags;
>  
> -			/* Flags for each sensor in enum motionsensor_id. */
> -			uint8_t sensor_flags[EC_MOTION_SENSOR_COUNT];
> +			/* Number of sensors managed directly by the EC. */
> +			uint8_t sensor_count;
>  
> -			/* Array of all sensor data. Each sensor is 3-axis. */
> -			int16_t data[3*EC_MOTION_SENSOR_COUNT];
> +			/*
> +			 * Sensor data is truncated if response_max is too small
> +			 * for holding all the data.
> +			 */
> +			struct ec_response_motion_sensor_data sensor[0];
>  		} dump;
>  
>  		/* Used for MOTIONSENSE_CMD_INFO. */
> @@ -1429,6 +1509,9 @@ struct ec_response_motion_sense {
>  			uint8_t chip;
>  		} info;
>  
> +		/* Used for MOTIONSENSE_CMD_DATA */
> +		struct ec_response_motion_sensor_data data;
> +
>  		/*
>  		 * Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR,
>  		 * MOTIONSENSE_CMD_SENSOR_RANGE, and
> @@ -1438,6 +1521,12 @@ struct ec_response_motion_sense {
>  			/* Current value of the parameter queried. */
>  			int32_t ret;
>  		} ec_rate, sensor_odr, sensor_range, kb_wake_angle;
> +
> +		/* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */
> +		struct {
> +			int16_t temp;
> +			int16_t offset[3];
> +		} sensor_offset, perform_calib;
>  	};
>  } __packed;
>  
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 2/4] iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver
  2016-08-01  9:54 ` [PATCH v4 2/4] iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver Enric Balletbo i Serra
@ 2016-08-15 15:28   ` Jonathan Cameron
  2016-09-03 17:12     ` Jonathan Cameron
  0 siblings, 1 reply; 30+ messages in thread
From: Jonathan Cameron @ 2016-08-15 15:28 UTC (permalink / raw)
  To: Enric Balletbo i Serra, linux-kernel, linux-iio
  Cc: Olof Johansson, Lee Jones, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Guenter Roeck, Gwendal Grignou

On 01/08/16 10:54, Enric Balletbo i Serra wrote:
> Handle 3d contiguous sensors like Accelerometers, Gyroscope and
> Magnetometer that are presented by the ChromeOS EC Sensor hub.
> 
> Signed-off-by: Guenter Roeck <groeck@chromium.org>
> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
Reviewed-by: Jonathan Cameron <jic23@kernel.org>

Again, fine if this goes via mfd.

Thanks,

Jonathan
> ---
> 
> Changes since v3:
>   - Remove some useless initialitzations as always overwritten.
>   - Convert calib structure to a simple array.
> Changes since v2:
>   - Fix some typos
>   - Skip filling by zero structure parameters that already zero'd.
>   - Order includes alphabetically.
>   - Propagate error codes.
> Changes since v1:
>   - Fixup multiline comments.
>   - Fix some spelling mistakes.
>   - Blank line before return statements.
>   - Add CROS_EC_SENSORS_ prefix.
> 
>  drivers/iio/common/cros_ec_sensors/Kconfig         |   8 +
>  drivers/iio/common/cros_ec_sensors/Makefile        |   1 +
>  .../iio/common/cros_ec_sensors/cros_ec_sensors.c   | 322 +++++++++++++++++++++
>  3 files changed, 331 insertions(+)
>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> 
> diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig b/drivers/iio/common/cros_ec_sensors/Kconfig
> index 24743be..980bea2 100644
> --- a/drivers/iio/common/cros_ec_sensors/Kconfig
> +++ b/drivers/iio/common/cros_ec_sensors/Kconfig
> @@ -12,3 +12,11 @@ config IIO_CROS_EC_SENSORS_CORE
>  	  drivers.
>  	  Define common attributes and sysfs interrupt handler.
>  
> +config IIO_CROS_EC_SENSORS
> +	tristate "ChromeOS EC Contiguous Sensors"
> +	select IIO_CROS_EC_SENSORS_CORE
> +	help
> +	  Module to handle 3d contiguous sensors like
> +	  Accelerometers, Gyroscope and Magnetometer that are
> +	  presented by the ChromeOS EC Sensor hub.
> +	  Creates an IIO device for each functions.
> diff --git a/drivers/iio/common/cros_ec_sensors/Makefile b/drivers/iio/common/cros_ec_sensors/Makefile
> index 95b6901..ec716ff 100644
> --- a/drivers/iio/common/cros_ec_sensors/Makefile
> +++ b/drivers/iio/common/cros_ec_sensors/Makefile
> @@ -3,3 +3,4 @@
>  #
>  
>  obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.o
> +obj-$(CONFIG_IIO_CROS_EC_SENSORS) += cros_ec_sensors.o
> diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> new file mode 100644
> index 0000000..48edeba
> --- /dev/null
> +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> @@ -0,0 +1,322 @@
> +/*
> + * cros_ec_sensors - Driver for Chrome OS Embedded Controller sensors.
> + *
> + * Copyright (C) 2016 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 sensors data. Data access is presented through iio sysfs.
> + */
> +
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/iio/buffer.h>
> +#include <linux/iio/iio.h>
> +#include <linux/iio/kfifo_buf.h>
> +#include <linux/iio/trigger_consumer.h>
> +#include <linux/iio/triggered_buffer.h>
> +#include <linux/kernel.h>
> +#include <linux/mfd/cros_ec.h>
> +#include <linux/mfd/cros_ec_commands.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/sysfs.h>
> +
> +#include "cros_ec_sensors_core.h"
> +
> +#define CROS_EC_SENSORS_MAX_CHANNELS 4
> +
> +/* State data for ec_sensors iio driver. */
> +struct cros_ec_sensors_state {
> +	/* Shared by all sensors */
> +	struct cros_ec_sensors_core_state core;
> +
> +	struct iio_chan_spec channels[CROS_EC_SENSORS_MAX_CHANNELS];
> +};
> +
> +static int cros_ec_sensors_read(struct iio_dev *indio_dev,
> +			  struct iio_chan_spec const *chan,
> +			  int *val, int *val2, long mask)
> +{
> +	struct cros_ec_sensors_state *st = iio_priv(indio_dev);
> +	s16 data = 0;
> +	s64 val64;
> +	int i;
> +	int ret = IIO_VAL_INT;
> +	int idx = chan->scan_index;
> +
> +	mutex_lock(&st->core.cmd_lock);
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_RAW:
> +		ret = st->core.read_ec_sensors_data(indio_dev, 1 << idx, &data);
> +		if (ret < 0)
> +			break;
> +
> +		*val = data;
> +		break;
> +	case IIO_CHAN_INFO_CALIBBIAS:
> +		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
> +		st->core.param.sensor_offset.flags = 0;
> +
> +		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
> +		if (ret < 0)
> +			break;
> +
> +		/* Save values */
> +		for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
> +			st->core.calib[i] =
> +				st->core.resp->sensor_offset.offset[i];
> +
> +		*val = st->core.calib[idx];
> +		break;
> +	case IIO_CHAN_INFO_SCALE:
> +		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
> +		st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE;
> +
> +		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
> +		if (ret < 0)
> +			break;
> +
> +		val64 = st->core.resp->sensor_range.ret;
> +		switch (st->core.type) {
> +		case MOTIONSENSE_TYPE_ACCEL:
> +			/*
> +			 * EC returns data in g, iio exepects m/s^2.
> +			 * Do not use IIO_G_TO_M_S_2 to avoid precision loss.
> +			 */
> +			*val = div_s64(val64 * 980665, 10);
> +			*val2 = 10000 << (CROS_EC_SENSOR_BITS - 1);
> +			ret = IIO_VAL_FRACTIONAL;
> +			break;
> +		case MOTIONSENSE_TYPE_GYRO:
> +			/*
> +			 * EC returns data in dps, iio expects rad/s.
> +			 * Do not use IIO_DEGREE_TO_RAD to avoid precision
> +			 * loss. Round to the nearest integer.
> +			 */
> +			*val = div_s64(val64 * 314159 + 9000000ULL, 1000);
> +			*val2 = 18000 << (CROS_EC_SENSOR_BITS - 1);
> +			ret = IIO_VAL_FRACTIONAL;
> +			break;
> +		case MOTIONSENSE_TYPE_MAG:
> +			/*
> +			 * EC returns data in 16LSB / uT,
> +			 * iio expects Gauss
> +			 */
> +			*val = val64;
> +			*val2 = 100 << (CROS_EC_SENSOR_BITS - 1);
> +			ret = IIO_VAL_FRACTIONAL;
> +			break;
> +		default:
> +			ret = -EINVAL;
> +		}
> +		break;
> +	default:
> +		ret = cros_ec_sensors_core_read(&st->core, chan, val, val2,
> +						mask);
> +		break;
> +	}
> +	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_state *st = iio_priv(indio_dev);
> +	int i;
> +	int ret = 0;
> +	int idx = chan->scan_index;
> +
> +	mutex_lock(&st->core.cmd_lock);
> +
> +	switch (mask) {
> +	case IIO_CHAN_INFO_CALIBBIAS:
> +		st->core.calib[idx] = val;
> +
> +		/* Send to EC for each axis, even if not complete */
> +		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
> +		st->core.param.sensor_offset.flags =
> +			MOTION_SENSE_SET_OFFSET;
> +		for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
> +			st->core.param.sensor_offset.offset[i] =
> +				st->core.calib[i];
> +		st->core.param.sensor_offset.temp =
> +			EC_MOTION_SENSE_INVALID_CALIB_TEMP;
> +
> +		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
> +		break;
> +	case IIO_CHAN_INFO_SCALE:
> +		if (st->core.type == MOTIONSENSE_TYPE_MAG) {
> +			ret = -EINVAL;
> +			break;
> +		}
> +		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
> +		st->core.param.sensor_range.data = val;
> +
> +		/* Always roundup, so caller gets at least what it asks for. */
> +		st->core.param.sensor_range.roundup = 1;
> +
> +		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
> +		break;
> +	default:
> +		ret = cros_ec_sensors_core_write(
> +				&st->core, chan, val, val2, mask);
> +		break;
> +	}
> +
> +	mutex_unlock(&st->core.cmd_lock);
> +
> +	return ret;
> +}
> +
> +static const struct iio_info ec_sensors_info = {
> +	.read_raw = &cros_ec_sensors_read,
> +	.write_raw = &cros_ec_sensors_write,
> +	.driver_module = THIS_MODULE,
> +};
> +
> +static int cros_ec_sensors_probe(struct platform_device *pdev)
> +{
> +	struct device *dev = &pdev->dev;
> +	struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
> +	struct cros_ec_device *ec_device;
> +	struct iio_dev *indio_dev;
> +	struct cros_ec_sensors_state *state;
> +	struct iio_chan_spec *channel;
> +	int ret, i;
> +
> +	if (!ec_dev || !ec_dev->ec_dev) {
> +		dev_warn(&pdev->dev, "No CROS EC device found.\n");
> +		return -EINVAL;
> +	}
> +	ec_device = ec_dev->ec_dev;
> +
> +	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state));
> +	if (!indio_dev)
> +		return -ENOMEM;
> +
> +	ret = cros_ec_sensors_core_init(pdev, indio_dev, true);
> +	if (ret)
> +		return ret;
> +
> +	indio_dev->info = &ec_sensors_info;
> +	state = iio_priv(indio_dev);
> +	for (channel = state->channels, i = CROS_EC_SENSOR_X;
> +	     i < CROS_EC_SENSOR_MAX_AXIS; i++, channel++) {
> +		/* Common part */
> +		channel->info_mask_separate =
> +			BIT(IIO_CHAN_INFO_RAW) |
> +			BIT(IIO_CHAN_INFO_CALIBBIAS);
> +		channel->info_mask_shared_by_all =
> +			BIT(IIO_CHAN_INFO_SCALE) |
> +			BIT(IIO_CHAN_INFO_FREQUENCY) |
> +			BIT(IIO_CHAN_INFO_SAMP_FREQ);
> +		channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
> +		channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
> +		channel->scan_index = i;
> +		channel->ext_info = cros_ec_sensors_ext_info;
> +		channel->modified = 1;
> +		channel->channel2 = IIO_MOD_X + i;
> +		channel->scan_type.sign = 's';
> +
> +		/* Sensor specific */
> +		switch (state->core.type) {
> +		case MOTIONSENSE_TYPE_ACCEL:
> +			channel->type = IIO_ACCEL;
> +			break;
> +		case MOTIONSENSE_TYPE_GYRO:
> +			channel->type = IIO_ANGL_VEL;
> +			break;
> +		case MOTIONSENSE_TYPE_MAG:
> +			channel->type = IIO_MAGN;
> +			break;
> +		default:
> +			dev_err(&pdev->dev, "Unknown motion sensor\n");
> +			return -EINVAL;
> +		}
> +	}
> +
> +	/* Timestamp */
> +	channel->type = IIO_TIMESTAMP;
> +	channel->channel = -1;
> +	channel->scan_index = CROS_EC_SENSOR_MAX_AXIS;
> +	channel->scan_type.sign = 's';
> +	channel->scan_type.realbits = 64;
> +	channel->scan_type.storagebits = 64;
> +
> +	indio_dev->channels = state->channels;
> +	indio_dev->num_channels = CROS_EC_SENSORS_MAX_CHANNELS;
> +
> +	/* There is only enough room for accel and gyro in the io space */
> +	if ((state->core.ec->cmd_readmem != NULL) &&
> +	    (state->core.type != MOTIONSENSE_TYPE_MAG))
> +		state->core.read_ec_sensors_data = cros_ec_sensors_read_lpc;
> +	else
> +		state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;
> +
> +	ret = iio_triggered_buffer_setup(indio_dev, NULL,
> +					 cros_ec_sensors_capture, NULL);
> +	if (ret)
> +		return ret;
> +
> +	ret = iio_device_register(indio_dev);
> +	if (ret)
> +		goto error_uninit_buffer;
> +
> +	return 0;
> +
> +error_uninit_buffer:
> +	iio_triggered_buffer_cleanup(indio_dev);
> +
> +	return ret;
> +}
> +
> +static int cros_ec_sensors_remove(struct platform_device *pdev)
> +{
> +	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
> +
> +	iio_device_unregister(indio_dev);
> +	iio_triggered_buffer_cleanup(indio_dev);
> +
> +	return 0;
> +}
> +
> +static const struct platform_device_id cros_ec_sensors_ids[] = {
> +	{
> +		.name = "cros-ec-accel",
> +	},
> +	{
> +		.name = "cros-ec-gyro",
> +	},
> +	{
> +		.name = "cros-ec-mag",
> +	},
> +	{ /* sentinel */ }
> +};
> +MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids);
> +
> +static struct platform_driver cros_ec_sensors_platform_driver = {
> +	.driver = {
> +		.name	= "cros-ec-sensors",
> +	},
> +	.probe		= cros_ec_sensors_probe,
> +	.remove		= cros_ec_sensors_remove,
> +	.id_table	= cros_ec_sensors_ids,
> +};
> +module_platform_driver(cros_ec_sensors_platform_driver);
> +
> +MODULE_DESCRIPTION("ChromeOS EC 3-axis sensors driver");
> +MODULE_LICENSE("GPL v2");
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 4/4] platform/chrome: cros_ec_dev - Register cros-ec sensors
  2016-08-01  9:54 ` [PATCH v4 4/4] platform/chrome: cros_ec_dev - Register cros-ec sensors Enric Balletbo i Serra
@ 2016-08-15 15:31   ` Jonathan Cameron
  2016-09-03 17:20     ` Jonathan Cameron
  0 siblings, 1 reply; 30+ messages in thread
From: Jonathan Cameron @ 2016-08-15 15:31 UTC (permalink / raw)
  To: Enric Balletbo i Serra, linux-kernel, linux-iio
  Cc: Olof Johansson, Lee Jones, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Guenter Roeck, Gwendal Grignou

On 01/08/16 10:54, Enric Balletbo i Serra wrote:
> Check whether the ChromeOS Embedded Controller is a sensor hub and in
> such case issue a command to get the number of sensors and register them
> all.
> 
> Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> Reviewed-by: Guenter Roeck <groeck@chromium.org>
> ---
> 
> Changes since v3:
>  - Remove Unnecessary ( ) around 'ret < 0'.
>  - Add Reviewed-by tag
> 
>  .../iio/common/cros_ec_sensors/cros_ec_sensors.c   |   4 +-
>  drivers/platform/chrome/cros_ec_dev.c              | 122 +++++++++++++++++++++
>  2 files changed, 124 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> index 48edeba..d6c372b 100644
> --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> @@ -51,7 +51,7 @@ static int cros_ec_sensors_read(struct iio_dev *indio_dev,
>  	s16 data = 0;
>  	s64 val64;
>  	int i;
> -	int ret = IIO_VAL_INT;
> +	int ret;
>  	int idx = chan->scan_index;
>  
>  	mutex_lock(&st->core.cmd_lock);
> @@ -137,7 +137,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
>  {
>  	struct cros_ec_sensors_state *st = iio_priv(indio_dev);
>  	int i;
> -	int ret = 0;
> +	int ret;
>  	int idx = chan->scan_index;
*raises eyebrows*

Enough said?

Was wondering why this patch had strayed into the IIO files.


>  
>  	mutex_lock(&st->core.cmd_lock);
> diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c
> index 7eb5307..47268ec 100644
> --- a/drivers/platform/chrome/cros_ec_dev.c
> +++ b/drivers/platform/chrome/cros_ec_dev.c
> @@ -18,6 +18,7 @@
>   */
>  
>  #include <linux/fs.h>
> +#include <linux/mfd/core.h>
>  #include <linux/module.h>
>  #include <linux/platform_device.h>
>  #include <linux/slab.h>
> @@ -265,6 +266,123 @@ static void __remove(struct device *dev)
>  	kfree(ec);
>  }
>  
> +static void cros_ec_sensors_register(struct cros_ec_dev *ec)
> +{
> +	/*
> +	 * Issue a command to get the number of sensor reported.
> +	 * Build an array of sensors driver and register them all.
> +	 */
> +	int ret, i, id, sensor_num;
> +	struct mfd_cell *sensor_cells;
> +	struct cros_ec_sensor_platform *sensor_platforms;
> +	int sensor_type[MOTIONSENSE_TYPE_MAX];
> +	struct ec_params_motion_sense *params;
> +	struct ec_response_motion_sense *resp;
> +	struct cros_ec_command *msg;
> +
> +	msg = kzalloc(sizeof(struct cros_ec_command) +
> +		      max(sizeof(*params), sizeof(*resp)), GFP_KERNEL);
> +	if (msg == NULL)
> +		return;
> +
> +	msg->version = 2;
> +	msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
> +	msg->outsize = sizeof(*params);
> +	msg->insize = sizeof(*resp);
> +
> +	params = (struct ec_params_motion_sense *)msg->data;
> +	params->cmd = MOTIONSENSE_CMD_DUMP;
> +
> +	ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
> +	if (ret < 0 || msg->result != EC_RES_SUCCESS) {
> +		dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n",
> +			 ret, msg->result);
> +		goto error;
> +	}
> +
> +	resp = (struct ec_response_motion_sense *)msg->data;
> +	sensor_num = resp->dump.sensor_count;
> +	/* Allocate 2 extra sensors in case lid angle or FIFO are needed */
> +	sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 2),
> +			       GFP_KERNEL);
> +	if (sensor_cells == NULL)
> +		goto error;
> +
> +	sensor_platforms = kzalloc(sizeof(struct cros_ec_sensor_platform) *
> +		  (sensor_num + 1), GFP_KERNEL);
> +	if (sensor_platforms == NULL)
> +		goto error_platforms;
> +
> +	memset(sensor_type, 0, sizeof(sensor_type));
> +	id = 0;
> +	for (i = 0; i < sensor_num; i++) {
> +		params->cmd = MOTIONSENSE_CMD_INFO;
> +		params->info.sensor_num = i;
> +		ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
> +		if (ret < 0 || msg->result != EC_RES_SUCCESS) {
> +			dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n",
> +				 i, ret, msg->result);
> +			continue;
> +		}
> +		switch (resp->info.type) {
> +		case MOTIONSENSE_TYPE_ACCEL:
> +			sensor_cells[id].name = "cros-ec-accel";
> +			break;
> +		case MOTIONSENSE_TYPE_GYRO:
> +			sensor_cells[id].name = "cros-ec-gyro";
> +			break;
> +		case MOTIONSENSE_TYPE_MAG:
> +			sensor_cells[id].name = "cros-ec-mag";
> +			break;
> +		case MOTIONSENSE_TYPE_PROX:
> +			sensor_cells[id].name = "cros-ec-prox";
> +			break;
> +		case MOTIONSENSE_TYPE_LIGHT:
> +			sensor_cells[id].name = "cros-ec-light";
> +			break;
> +		case MOTIONSENSE_TYPE_ACTIVITY:
> +			sensor_cells[id].name = "cros-ec-activity";
> +			break;
> +		default:
> +			dev_warn(ec->dev, "unknown type %d\n", resp->info.type);
> +			continue;
> +		}
> +		sensor_platforms[id].sensor_num = i;
> +		sensor_cells[id].id = sensor_type[resp->info.type];
> +		sensor_cells[id].platform_data = &sensor_platforms[id];
> +		sensor_cells[id].pdata_size =
> +			sizeof(struct cros_ec_sensor_platform);
> +
> +		sensor_type[resp->info.type]++;
> +		id++;
> +	}
> +	if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) {
> +		sensor_platforms[id].sensor_num = sensor_num;
> +
> +		sensor_cells[id].name = "cros-ec-angle";
> +		sensor_cells[id].id = 0;
> +		sensor_cells[id].platform_data = &sensor_platforms[id];
> +		sensor_cells[id].pdata_size =
> +			sizeof(struct cros_ec_sensor_platform);
> +		id++;
> +	}
> +	if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
> +		sensor_cells[id].name = "cros-ec-ring";
> +		id++;
> +	}
> +
> +	ret = mfd_add_devices(ec->dev, 0, sensor_cells, id,
> +			      NULL, 0, NULL);
> +	if (ret)
> +		dev_err(ec->dev, "failed to add EC sensors\n");
> +
> +	kfree(sensor_platforms);
> +error_platforms:
> +	kfree(sensor_cells);
> +error:
> +	kfree(msg);
> +}
> +
>  static int ec_device_probe(struct platform_device *pdev)
>  {
>  	int retval = -ENOMEM;
> @@ -319,6 +437,10 @@ static int ec_device_probe(struct platform_device *pdev)
>  		goto dev_reg_failed;
>  	}
>  
> +	/* check whether this EC is a sensor hub. */
> +	if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
> +		cros_ec_sensors_register(ec);
> +
>  	return 0;
>  
>  dev_reg_failed:
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 0/4] Add support for cros-ec-sensors
  2016-08-15 15:24 ` [PATCH v4 0/4] Add support for cros-ec-sensors Jonathan Cameron
@ 2016-08-16 12:49   ` Lee Jones
  2016-08-21 19:57     ` Jonathan Cameron
  0 siblings, 1 reply; 30+ messages in thread
From: Lee Jones @ 2016-08-16 12:49 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Enric Balletbo i Serra, linux-kernel, linux-iio, Olof Johansson,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Guenter Roeck, Gwendal Grignou

On Mon, 15 Aug 2016, Jonathan Cameron wrote:

> On 01/08/16 10:54, Enric Balletbo i Serra wrote:
> > Hi,
> > 
> > This is the four patchset to add support for the sensors behind the ChromeOS
> > Embedded Controller.
> > 
> > This version has only the patches to support common functions and 3d
> > contiguous sensors like Accelerometers, Gyroscope and Magnetometer that are
> > presented by the ChromeOS EC Sensor hub. The patches were tested on an Oak board.
> > 
> > The code was checked out from the ChromeOS v3.18 tree and forward ported to
> > mainline solving all the conflicts and build issues. I splitted the code in
> > single patches that have sense by themselves in order to avoid the chances
> > to fail.
> > 
> > Note that the patches depends on this [1] to apply and work.
> > 
> > [1] https://lkml.org/lkml/2016/7/1/188
> Given this dependency I'm assuming the best route for these is via
> the MFD tree...
> 
> Lee, shout if you want them to go a different route.

IIO looks like a more suitable route.  Please provide me with a
pull-request base off of an immutable tag.

> > Waiting for your reviews and feedback.
> > 
> > Changes since v3 (requested by Guenter Roeck)
> >   - Convert structure to a simple array
> >   - Remove PM declarations
> >   - Remove unnecessary initializations
> >   - cros_ec_sensors_cmd_read_u16: Conversion should only be done if ret >= 0
> >   - Remove unnecessary else
> >   - Add Reviewed-by tag for two last patches.
> > 
> > Changes since v2 (requested by Guenter Roeck and Jonhatan Cameron)
> >   - Rebased and fix build error.
> >   - Include a list of possible values in the description of location attr.
> >   - Fix some typos.
> >   - Remove id sysfs entry.
> >   - Skip filling by zero structure parameters that already zero'd.
> >   - Order includes alphabetically.
> >   - Propagate error codes.
> > 
> > Changes since v1 (requested by Peter Meerwald-Stadler and Jonhatan Cameron)
> >   - Check kernel-doc documentation and 
> >   - Bring some patches together.
> >   - Fix some spelling mistakes.
> >   - Include ABI documentation.
> >   - Be more careful with buffer sizes (sprintf -> snprintf)
> >   - Add cros_ec_sensors prefix to all function.
> >   - Check return values on some functions.
> > 
> > Best regards,
> > 
> > Enric Balletbo i Serra (3):
> >   iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC
> >     Sensor Hub.
> >   iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver
> >   platform/chrome: cros_ec_dev - Register cros-ec sensors
> > 
> > Vincent Palatin (1):
> >   platform/chrome: Introduce a new function to check EC features.
> > 
> >  Documentation/ABI/testing/sysfs-bus-iio-cros-ec    |  18 +
> >  drivers/iio/common/Kconfig                         |   1 +
> >  drivers/iio/common/Makefile                        |   1 +
> >  drivers/iio/common/cros_ec_sensors/Kconfig         |  22 +
> >  drivers/iio/common/cros_ec_sensors/Makefile        |   6 +
> >  .../iio/common/cros_ec_sensors/cros_ec_sensors.c   | 322 +++++++++++++++
> >  .../common/cros_ec_sensors/cros_ec_sensors_core.c  | 450 +++++++++++++++++++++
> >  .../common/cros_ec_sensors/cros_ec_sensors_core.h  | 175 ++++++++
> >  drivers/platform/chrome/cros_ec_dev.c              | 159 ++++++++
> >  include/linux/mfd/cros_ec.h                        |  10 +
> >  include/linux/mfd/cros_ec_commands.h               | 183 ++++++++-
> >  11 files changed, 1342 insertions(+), 5 deletions(-)
> >  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-cros-ec
> >  create mode 100644 drivers/iio/common/cros_ec_sensors/Kconfig
> >  create mode 100644 drivers/iio/common/cros_ec_sensors/Makefile
> >  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> >  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
> >  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
> > 
> 

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 0/4] Add support for cros-ec-sensors
  2016-08-16 12:49   ` Lee Jones
@ 2016-08-21 19:57     ` Jonathan Cameron
  2016-08-29 15:14       ` Jonathan Cameron
  0 siblings, 1 reply; 30+ messages in thread
From: Jonathan Cameron @ 2016-08-21 19:57 UTC (permalink / raw)
  To: Lee Jones
  Cc: Enric Balletbo i Serra, linux-kernel, linux-iio, Olof Johansson,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Guenter Roeck, Gwendal Grignou

On 16/08/16 13:49, Lee Jones wrote:
> On Mon, 15 Aug 2016, Jonathan Cameron wrote:
> 
>> On 01/08/16 10:54, Enric Balletbo i Serra wrote:
>>> Hi,
>>>
>>> This is the four patchset to add support for the sensors behind the ChromeOS
>>> Embedded Controller.
>>>
>>> This version has only the patches to support common functions and 3d
>>> contiguous sensors like Accelerometers, Gyroscope and Magnetometer that are
>>> presented by the ChromeOS EC Sensor hub. The patches were tested on an Oak board.
>>>
>>> The code was checked out from the ChromeOS v3.18 tree and forward ported to
>>> mainline solving all the conflicts and build issues. I splitted the code in
>>> single patches that have sense by themselves in order to avoid the chances
>>> to fail.
>>>
>>> Note that the patches depends on this [1] to apply and work.
>>>
>>> [1] https://lkml.org/lkml/2016/7/1/188
>> Given this dependency I'm assuming the best route for these is via
>> the MFD tree...
>>
>> Lee, shout if you want them to go a different route.
> 
> IIO looks like a more suitable route.  Please provide me with a
> pull-request base off of an immutable tag.
Hi Lee,

As far as I can tell the precursor patch above hasn't gone in your
tree yet which leaves me unable to take this through IIO for now.

Maybe I'm missing something!

Jonathan
> 
>>> Waiting for your reviews and feedback.
>>>
>>> Changes since v3 (requested by Guenter Roeck)
>>>   - Convert structure to a simple array
>>>   - Remove PM declarations
>>>   - Remove unnecessary initializations
>>>   - cros_ec_sensors_cmd_read_u16: Conversion should only be done if ret >= 0
>>>   - Remove unnecessary else
>>>   - Add Reviewed-by tag for two last patches.
>>>
>>> Changes since v2 (requested by Guenter Roeck and Jonhatan Cameron)
>>>   - Rebased and fix build error.
>>>   - Include a list of possible values in the description of location attr.
>>>   - Fix some typos.
>>>   - Remove id sysfs entry.
>>>   - Skip filling by zero structure parameters that already zero'd.
>>>   - Order includes alphabetically.
>>>   - Propagate error codes.
>>>
>>> Changes since v1 (requested by Peter Meerwald-Stadler and Jonhatan Cameron)
>>>   - Check kernel-doc documentation and 
>>>   - Bring some patches together.
>>>   - Fix some spelling mistakes.
>>>   - Include ABI documentation.
>>>   - Be more careful with buffer sizes (sprintf -> snprintf)
>>>   - Add cros_ec_sensors prefix to all function.
>>>   - Check return values on some functions.
>>>
>>> Best regards,
>>>
>>> Enric Balletbo i Serra (3):
>>>   iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC
>>>     Sensor Hub.
>>>   iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver
>>>   platform/chrome: cros_ec_dev - Register cros-ec sensors
>>>
>>> Vincent Palatin (1):
>>>   platform/chrome: Introduce a new function to check EC features.
>>>
>>>  Documentation/ABI/testing/sysfs-bus-iio-cros-ec    |  18 +
>>>  drivers/iio/common/Kconfig                         |   1 +
>>>  drivers/iio/common/Makefile                        |   1 +
>>>  drivers/iio/common/cros_ec_sensors/Kconfig         |  22 +
>>>  drivers/iio/common/cros_ec_sensors/Makefile        |   6 +
>>>  .../iio/common/cros_ec_sensors/cros_ec_sensors.c   | 322 +++++++++++++++
>>>  .../common/cros_ec_sensors/cros_ec_sensors_core.c  | 450 +++++++++++++++++++++
>>>  .../common/cros_ec_sensors/cros_ec_sensors_core.h  | 175 ++++++++
>>>  drivers/platform/chrome/cros_ec_dev.c              | 159 ++++++++
>>>  include/linux/mfd/cros_ec.h                        |  10 +
>>>  include/linux/mfd/cros_ec_commands.h               | 183 ++++++++-
>>>  11 files changed, 1342 insertions(+), 5 deletions(-)
>>>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-cros-ec
>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/Kconfig
>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/Makefile
>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
>>>
>>
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 0/4] Add support for cros-ec-sensors
  2016-08-21 19:57     ` Jonathan Cameron
@ 2016-08-29 15:14       ` Jonathan Cameron
  2016-08-30  8:57         ` Lee Jones
  0 siblings, 1 reply; 30+ messages in thread
From: Jonathan Cameron @ 2016-08-29 15:14 UTC (permalink / raw)
  To: Lee Jones
  Cc: Enric Balletbo i Serra, linux-kernel, linux-iio, Olof Johansson,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Guenter Roeck, Gwendal Grignou

On 21/08/16 20:57, Jonathan Cameron wrote:
> On 16/08/16 13:49, Lee Jones wrote:
>> On Mon, 15 Aug 2016, Jonathan Cameron wrote:
>>
>>> On 01/08/16 10:54, Enric Balletbo i Serra wrote:
>>>> Hi,
>>>>
>>>> This is the four patchset to add support for the sensors behind the ChromeOS
>>>> Embedded Controller.
>>>>
>>>> This version has only the patches to support common functions and 3d
>>>> contiguous sensors like Accelerometers, Gyroscope and Magnetometer that are
>>>> presented by the ChromeOS EC Sensor hub. The patches were tested on an Oak board.
>>>>
>>>> The code was checked out from the ChromeOS v3.18 tree and forward ported to
>>>> mainline solving all the conflicts and build issues. I splitted the code in
>>>> single patches that have sense by themselves in order to avoid the chances
>>>> to fail.
>>>>
>>>> Note that the patches depends on this [1] to apply and work.
>>>>
>>>> [1] https://lkml.org/lkml/2016/7/1/188
>>> Given this dependency I'm assuming the best route for these is via
>>> the MFD tree...
>>>
>>> Lee, shout if you want them to go a different route.
>>
>> IIO looks like a more suitable route.  Please provide me with a
>> pull-request base off of an immutable tag.
> Hi Lee,
> 
> As far as I can tell the precursor patch above hasn't gone in your
> tree yet which leaves me unable to take this through IIO for now.
> 
> Maybe I'm missing something!
> 
> Jonathan

Hi Lee,

Any movement on the dependency above?

Last I can find was you adding your ack to it:
[PATCH v2 1/2] mfd: cros_ec: Add MKBP event support

https://lkml.org/lkml/2016/8/16/423

Jonathan
>>
>>>> Waiting for your reviews and feedback.
>>>>
>>>> Changes since v3 (requested by Guenter Roeck)
>>>>   - Convert structure to a simple array
>>>>   - Remove PM declarations
>>>>   - Remove unnecessary initializations
>>>>   - cros_ec_sensors_cmd_read_u16: Conversion should only be done if ret >= 0
>>>>   - Remove unnecessary else
>>>>   - Add Reviewed-by tag for two last patches.
>>>>
>>>> Changes since v2 (requested by Guenter Roeck and Jonhatan Cameron)
>>>>   - Rebased and fix build error.
>>>>   - Include a list of possible values in the description of location attr.
>>>>   - Fix some typos.
>>>>   - Remove id sysfs entry.
>>>>   - Skip filling by zero structure parameters that already zero'd.
>>>>   - Order includes alphabetically.
>>>>   - Propagate error codes.
>>>>
>>>> Changes since v1 (requested by Peter Meerwald-Stadler and Jonhatan Cameron)
>>>>   - Check kernel-doc documentation and 
>>>>   - Bring some patches together.
>>>>   - Fix some spelling mistakes.
>>>>   - Include ABI documentation.
>>>>   - Be more careful with buffer sizes (sprintf -> snprintf)
>>>>   - Add cros_ec_sensors prefix to all function.
>>>>   - Check return values on some functions.
>>>>
>>>> Best regards,
>>>>
>>>> Enric Balletbo i Serra (3):
>>>>   iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC
>>>>     Sensor Hub.
>>>>   iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver
>>>>   platform/chrome: cros_ec_dev - Register cros-ec sensors
>>>>
>>>> Vincent Palatin (1):
>>>>   platform/chrome: Introduce a new function to check EC features.
>>>>
>>>>  Documentation/ABI/testing/sysfs-bus-iio-cros-ec    |  18 +
>>>>  drivers/iio/common/Kconfig                         |   1 +
>>>>  drivers/iio/common/Makefile                        |   1 +
>>>>  drivers/iio/common/cros_ec_sensors/Kconfig         |  22 +
>>>>  drivers/iio/common/cros_ec_sensors/Makefile        |   6 +
>>>>  .../iio/common/cros_ec_sensors/cros_ec_sensors.c   | 322 +++++++++++++++
>>>>  .../common/cros_ec_sensors/cros_ec_sensors_core.c  | 450 +++++++++++++++++++++
>>>>  .../common/cros_ec_sensors/cros_ec_sensors_core.h  | 175 ++++++++
>>>>  drivers/platform/chrome/cros_ec_dev.c              | 159 ++++++++
>>>>  include/linux/mfd/cros_ec.h                        |  10 +
>>>>  include/linux/mfd/cros_ec_commands.h               | 183 ++++++++-
>>>>  11 files changed, 1342 insertions(+), 5 deletions(-)
>>>>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-cros-ec
>>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/Kconfig
>>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/Makefile
>>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
>>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
>>>>
>>>
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 0/4] Add support for cros-ec-sensors
  2016-08-29 15:14       ` Jonathan Cameron
@ 2016-08-30  8:57         ` Lee Jones
  2016-08-31 20:06           ` Jonathan Cameron
  0 siblings, 1 reply; 30+ messages in thread
From: Lee Jones @ 2016-08-30  8:57 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Enric Balletbo i Serra, linux-kernel, linux-iio, Olof Johansson,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Guenter Roeck, Gwendal Grignou

On Mon, 29 Aug 2016, Jonathan Cameron wrote:

> On 21/08/16 20:57, Jonathan Cameron wrote:
> > On 16/08/16 13:49, Lee Jones wrote:
> >> On Mon, 15 Aug 2016, Jonathan Cameron wrote:
> >>
> >>> On 01/08/16 10:54, Enric Balletbo i Serra wrote:
> >>>> Hi,
> >>>>
> >>>> This is the four patchset to add support for the sensors behind the ChromeOS
> >>>> Embedded Controller.
> >>>>
> >>>> This version has only the patches to support common functions and 3d
> >>>> contiguous sensors like Accelerometers, Gyroscope and Magnetometer that are
> >>>> presented by the ChromeOS EC Sensor hub. The patches were tested on an Oak board.
> >>>>
> >>>> The code was checked out from the ChromeOS v3.18 tree and forward ported to
> >>>> mainline solving all the conflicts and build issues. I splitted the code in
> >>>> single patches that have sense by themselves in order to avoid the chances
> >>>> to fail.
> >>>>
> >>>> Note that the patches depends on this [1] to apply and work.
> >>>>
> >>>> [1] https://lkml.org/lkml/2016/7/1/188
> >>> Given this dependency I'm assuming the best route for these is via
> >>> the MFD tree...
> >>>
> >>> Lee, shout if you want them to go a different route.
> >>
> >> IIO looks like a more suitable route.  Please provide me with a
> >> pull-request base off of an immutable tag.
> > Hi Lee,
> > 
> > As far as I can tell the precursor patch above hasn't gone in your
> > tree yet which leaves me unable to take this through IIO for now.
> > 
> > Maybe I'm missing something!
> > 
> > Jonathan
> 
> Hi Lee,
> 
> Any movement on the dependency above?
> 
> Last I can find was you adding your ack to it:
> [PATCH v2 1/2] mfd: cros_ec: Add MKBP event support
> 
> https://lkml.org/lkml/2016/8/16/423

Well that's annoying.  Okay, well when I send out the pull-request for
this one, I will include you.

Actually, better still -- take all of them on one branch and I will
pull from you.  Saves the toing and froing.

> >>>> Waiting for your reviews and feedback.
> >>>>
> >>>> Changes since v3 (requested by Guenter Roeck)
> >>>>   - Convert structure to a simple array
> >>>>   - Remove PM declarations
> >>>>   - Remove unnecessary initializations
> >>>>   - cros_ec_sensors_cmd_read_u16: Conversion should only be done if ret >= 0
> >>>>   - Remove unnecessary else
> >>>>   - Add Reviewed-by tag for two last patches.
> >>>>
> >>>> Changes since v2 (requested by Guenter Roeck and Jonhatan Cameron)
> >>>>   - Rebased and fix build error.
> >>>>   - Include a list of possible values in the description of location attr.
> >>>>   - Fix some typos.
> >>>>   - Remove id sysfs entry.
> >>>>   - Skip filling by zero structure parameters that already zero'd.
> >>>>   - Order includes alphabetically.
> >>>>   - Propagate error codes.
> >>>>
> >>>> Changes since v1 (requested by Peter Meerwald-Stadler and Jonhatan Cameron)
> >>>>   - Check kernel-doc documentation and 
> >>>>   - Bring some patches together.
> >>>>   - Fix some spelling mistakes.
> >>>>   - Include ABI documentation.
> >>>>   - Be more careful with buffer sizes (sprintf -> snprintf)
> >>>>   - Add cros_ec_sensors prefix to all function.
> >>>>   - Check return values on some functions.
> >>>>
> >>>> Best regards,
> >>>>
> >>>> Enric Balletbo i Serra (3):
> >>>>   iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC
> >>>>     Sensor Hub.
> >>>>   iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver
> >>>>   platform/chrome: cros_ec_dev - Register cros-ec sensors
> >>>>
> >>>> Vincent Palatin (1):
> >>>>   platform/chrome: Introduce a new function to check EC features.
> >>>>
> >>>>  Documentation/ABI/testing/sysfs-bus-iio-cros-ec    |  18 +
> >>>>  drivers/iio/common/Kconfig                         |   1 +
> >>>>  drivers/iio/common/Makefile                        |   1 +
> >>>>  drivers/iio/common/cros_ec_sensors/Kconfig         |  22 +
> >>>>  drivers/iio/common/cros_ec_sensors/Makefile        |   6 +
> >>>>  .../iio/common/cros_ec_sensors/cros_ec_sensors.c   | 322 +++++++++++++++
> >>>>  .../common/cros_ec_sensors/cros_ec_sensors_core.c  | 450 +++++++++++++++++++++
> >>>>  .../common/cros_ec_sensors/cros_ec_sensors_core.h  | 175 ++++++++
> >>>>  drivers/platform/chrome/cros_ec_dev.c              | 159 ++++++++
> >>>>  include/linux/mfd/cros_ec.h                        |  10 +
> >>>>  include/linux/mfd/cros_ec_commands.h               | 183 ++++++++-
> >>>>  11 files changed, 1342 insertions(+), 5 deletions(-)
> >>>>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-cros-ec
> >>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/Kconfig
> >>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/Makefile
> >>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> >>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
> >>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
> >>>>
> >>>
> >>
> > 
> 

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 0/4] Add support for cros-ec-sensors
  2016-08-30  8:57         ` Lee Jones
@ 2016-08-31 20:06           ` Jonathan Cameron
  2016-09-01  7:24             ` Lee Jones
  0 siblings, 1 reply; 30+ messages in thread
From: Jonathan Cameron @ 2016-08-31 20:06 UTC (permalink / raw)
  To: Lee Jones
  Cc: Enric Balletbo i Serra, linux-kernel, linux-iio, Olof Johansson,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Guenter Roeck, Gwendal Grignou

On 30/08/16 09:57, Lee Jones wrote:
> On Mon, 29 Aug 2016, Jonathan Cameron wrote:
> 
>> On 21/08/16 20:57, Jonathan Cameron wrote:
>>> On 16/08/16 13:49, Lee Jones wrote:
>>>> On Mon, 15 Aug 2016, Jonathan Cameron wrote:
>>>>
>>>>> On 01/08/16 10:54, Enric Balletbo i Serra wrote:
>>>>>> Hi,
>>>>>>
>>>>>> This is the four patchset to add support for the sensors behind the ChromeOS
>>>>>> Embedded Controller.
>>>>>>
>>>>>> This version has only the patches to support common functions and 3d
>>>>>> contiguous sensors like Accelerometers, Gyroscope and Magnetometer that are
>>>>>> presented by the ChromeOS EC Sensor hub. The patches were tested on an Oak board.
>>>>>>
>>>>>> The code was checked out from the ChromeOS v3.18 tree and forward ported to
>>>>>> mainline solving all the conflicts and build issues. I splitted the code in
>>>>>> single patches that have sense by themselves in order to avoid the chances
>>>>>> to fail.
>>>>>>
>>>>>> Note that the patches depends on this [1] to apply and work.
>>>>>>
>>>>>> [1] https://lkml.org/lkml/2016/7/1/188
>>>>> Given this dependency I'm assuming the best route for these is via
>>>>> the MFD tree...
>>>>>
>>>>> Lee, shout if you want them to go a different route.
>>>>
>>>> IIO looks like a more suitable route.  Please provide me with a
>>>> pull-request base off of an immutable tag.
>>> Hi Lee,
>>>
>>> As far as I can tell the precursor patch above hasn't gone in your
>>> tree yet which leaves me unable to take this through IIO for now.
>>>
>>> Maybe I'm missing something!
>>>
>>> Jonathan
>>
>> Hi Lee,
>>
>> Any movement on the dependency above?
>>
>> Last I can find was you adding your ack to it:
>> [PATCH v2 1/2] mfd: cros_ec: Add MKBP event support
>>
>> https://lkml.org/lkml/2016/8/16/423
> 
> Well that's annoying.  Okay, well when I send out the pull-request for
> this one, I will include you.
> 
> Actually, better still -- take all of them on one branch and I will
> pull from you.  Saves the toing and froing.
> 
Sure. Will probably be the weekend before I get this sorted.

Jonathan
>>>>>> Waiting for your reviews and feedback.
>>>>>>
>>>>>> Changes since v3 (requested by Guenter Roeck)
>>>>>>   - Convert structure to a simple array
>>>>>>   - Remove PM declarations
>>>>>>   - Remove unnecessary initializations
>>>>>>   - cros_ec_sensors_cmd_read_u16: Conversion should only be done if ret >= 0
>>>>>>   - Remove unnecessary else
>>>>>>   - Add Reviewed-by tag for two last patches.
>>>>>>
>>>>>> Changes since v2 (requested by Guenter Roeck and Jonhatan Cameron)
>>>>>>   - Rebased and fix build error.
>>>>>>   - Include a list of possible values in the description of location attr.
>>>>>>   - Fix some typos.
>>>>>>   - Remove id sysfs entry.
>>>>>>   - Skip filling by zero structure parameters that already zero'd.
>>>>>>   - Order includes alphabetically.
>>>>>>   - Propagate error codes.
>>>>>>
>>>>>> Changes since v1 (requested by Peter Meerwald-Stadler and Jonhatan Cameron)
>>>>>>   - Check kernel-doc documentation and 
>>>>>>   - Bring some patches together.
>>>>>>   - Fix some spelling mistakes.
>>>>>>   - Include ABI documentation.
>>>>>>   - Be more careful with buffer sizes (sprintf -> snprintf)
>>>>>>   - Add cros_ec_sensors prefix to all function.
>>>>>>   - Check return values on some functions.
>>>>>>
>>>>>> Best regards,
>>>>>>
>>>>>> Enric Balletbo i Serra (3):
>>>>>>   iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC
>>>>>>     Sensor Hub.
>>>>>>   iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver
>>>>>>   platform/chrome: cros_ec_dev - Register cros-ec sensors
>>>>>>
>>>>>> Vincent Palatin (1):
>>>>>>   platform/chrome: Introduce a new function to check EC features.
>>>>>>
>>>>>>  Documentation/ABI/testing/sysfs-bus-iio-cros-ec    |  18 +
>>>>>>  drivers/iio/common/Kconfig                         |   1 +
>>>>>>  drivers/iio/common/Makefile                        |   1 +
>>>>>>  drivers/iio/common/cros_ec_sensors/Kconfig         |  22 +
>>>>>>  drivers/iio/common/cros_ec_sensors/Makefile        |   6 +
>>>>>>  .../iio/common/cros_ec_sensors/cros_ec_sensors.c   | 322 +++++++++++++++
>>>>>>  .../common/cros_ec_sensors/cros_ec_sensors_core.c  | 450 +++++++++++++++++++++
>>>>>>  .../common/cros_ec_sensors/cros_ec_sensors_core.h  | 175 ++++++++
>>>>>>  drivers/platform/chrome/cros_ec_dev.c              | 159 ++++++++
>>>>>>  include/linux/mfd/cros_ec.h                        |  10 +
>>>>>>  include/linux/mfd/cros_ec_commands.h               | 183 ++++++++-
>>>>>>  11 files changed, 1342 insertions(+), 5 deletions(-)
>>>>>>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-cros-ec
>>>>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/Kconfig
>>>>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/Makefile
>>>>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>>>>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
>>>>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
>>>>>>
>>>>>
>>>>
>>>
>>
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 0/4] Add support for cros-ec-sensors
  2016-08-31 20:06           ` Jonathan Cameron
@ 2016-09-01  7:24             ` Lee Jones
  2016-09-03 17:21               ` Jonathan Cameron
  0 siblings, 1 reply; 30+ messages in thread
From: Lee Jones @ 2016-09-01  7:24 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Enric Balletbo i Serra, linux-kernel, linux-iio, Olof Johansson,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Guenter Roeck, Gwendal Grignou

> >>>>> Given this dependency I'm assuming the best route for these is via
> >>>>> the MFD tree...
> >>>>>
> >>>>> Lee, shout if you want them to go a different route.
> >>>>
> >>>> IIO looks like a more suitable route.  Please provide me with a
> >>>> pull-request base off of an immutable tag.
> >>> Hi Lee,
> >>>
> >>> As far as I can tell the precursor patch above hasn't gone in your
> >>> tree yet which leaves me unable to take this through IIO for now.
> >>>
> >>> Maybe I'm missing something!
> >>>
> >>> Jonathan
> >>
> >> Hi Lee,
> >>
> >> Any movement on the dependency above?
> >>
> >> Last I can find was you adding your ack to it:
> >> [PATCH v2 1/2] mfd: cros_ec: Add MKBP event support
> >>
> >> https://lkml.org/lkml/2016/8/16/423
> > 
> > Well that's annoying.  Okay, well when I send out the pull-request for
> > this one, I will include you.
> > 
> > Actually, better still -- take all of them on one branch and I will
> > pull from you.  Saves the toing and froing.
> > 
> Sure. Will probably be the weekend before I get this sorted.

No rush.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 1/4] iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC Sensor Hub.
  2016-08-15 15:28   ` Jonathan Cameron
@ 2016-09-03 17:07     ` Jonathan Cameron
  2016-10-25 17:12       ` Jonathan Cameron
  0 siblings, 1 reply; 30+ messages in thread
From: Jonathan Cameron @ 2016-09-03 17:07 UTC (permalink / raw)
  To: Enric Balletbo i Serra, linux-kernel, linux-iio
  Cc: Olof Johansson, Lee Jones, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Guenter Roeck, Gwendal Grignou

On 15/08/16 16:28, Jonathan Cameron wrote:
> On 01/08/16 10:54, Enric Balletbo i Serra wrote:
>> Add the core functions to be able to support the sensors attached behind
>> the ChromeOS Embedded Controller and used by other IIO cros-ec sensor
>> drivers.
>>
>> The cros_ec_sensor_core driver matches with current driver in ChromeOS
>> 4.4 tree, so it includes all the fixes at the moment. The support for
>> this driver was made by Gwendal Grignou. The original patch and all the
>> fixes has been squashed and rebased on top of mainline.
>>
>> Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
>> Signed-off-by: Guenter Roeck <groeck@chromium.org>
>> [eballetbo: split, squash and rebase on top of mainline the patches
>> found in ChromeOS tree]
>> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> Reviewed-by: Jonathan Cameron <jic23@kernel.org>
Applied to a new branch in IIO for the purpose.
ib-iio-mfd-4.9

Not entirely sure which route I'll take to unwinding this to upstream
so it may go through a merge into iio.git or a separate pull request.

Will figure that out later!

Thanks,

Jonathan
> 
> Thanks,
> 
> Jonathan
>> ---
>>
>> Changes since v3:
>>   - Convert structure to a simple array
>>   - Remove PM declarations
>>   - Remove unnecessary initializations
>>   - cros_ec_sensors_cmd_read_u16: Conversion should only be done if ret >= 0
>>   - Remove unnecessary else
>>
>> Changes since v2:
>>   - Rebased and fix build error.
>>   - Include a list of possible values in the description of location attr.
>>   - Fix some typos.
>>   - Remove id sysfs entry.
>>
>> Changes since v1:
>>   - Check kernel-doc documentation.
>>   - Bring this in as an when you need it in the rest of the series.
>>   - Fix some spelling mistakes.
>>   - Include ABI documentation.
>>   - Be more careful with buffer sizes (sprintf -> snprintf)
>>   - Add cros_ec_sensors prefix to all function.
>>   - Check return values on some functions.
>>
>>  Documentation/ABI/testing/sysfs-bus-iio-cros-ec    |  18 +
>>  drivers/iio/common/Kconfig                         |   1 +
>>  drivers/iio/common/Makefile                        |   1 +
>>  drivers/iio/common/cros_ec_sensors/Kconfig         |  14 +
>>  drivers/iio/common/cros_ec_sensors/Makefile        |   5 +
>>  .../common/cros_ec_sensors/cros_ec_sensors_core.c  | 450 +++++++++++++++++++++
>>  .../common/cros_ec_sensors/cros_ec_sensors_core.h  | 175 ++++++++
>>  include/linux/mfd/cros_ec.h                        |   9 +
>>  include/linux/mfd/cros_ec_commands.h               |  99 ++++-
>>  9 files changed, 767 insertions(+), 5 deletions(-)
>>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-cros-ec
>>  create mode 100644 drivers/iio/common/cros_ec_sensors/Kconfig
>>  create mode 100644 drivers/iio/common/cros_ec_sensors/Makefile
>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
>>
>> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-cros-ec b/Documentation/ABI/testing/sysfs-bus-iio-cros-ec
>> new file mode 100644
>> index 0000000..297b972
>> --- /dev/null
>> +++ b/Documentation/ABI/testing/sysfs-bus-iio-cros-ec
>> @@ -0,0 +1,18 @@
>> +What:		/sys/bus/iio/devices/iio:deviceX/calibrate
>> +Date:		July 2015
>> +KernelVersion:	4.7
>> +Contact:	linux-iio@vger.kernel.org
>> +Description:
>> +		Writing '1' will perform a FOC (Fast Online Calibration). The
>> +                corresponding calibration offsets can be read from *_calibbias
>> +                entries.
>> +
>> +What:		/sys/bus/iio/devices/iio:deviceX/location
>> +Date:		July 2015
>> +KernelVersion:	4.7
>> +Contact:	linux-iio@vger.kernel.org
>> +Description:
>> +		This attribute returns a string with the physical location where
>> +                the motion sensor is placed. For example, in a laptop a motion
>> +                sensor can be located on the base or on the lid. Current valid
>> +		values are 'base' and 'lid'.
>> diff --git a/drivers/iio/common/Kconfig b/drivers/iio/common/Kconfig
>> index 26a6026..e108996 100644
>> --- a/drivers/iio/common/Kconfig
>> +++ b/drivers/iio/common/Kconfig
>> @@ -2,6 +2,7 @@
>>  # IIO common modules
>>  #
>>  
>> +source "drivers/iio/common/cros_ec_sensors/Kconfig"
>>  source "drivers/iio/common/hid-sensors/Kconfig"
>>  source "drivers/iio/common/ms_sensors/Kconfig"
>>  source "drivers/iio/common/ssp_sensors/Kconfig"
>> diff --git a/drivers/iio/common/Makefile b/drivers/iio/common/Makefile
>> index 585da6a..6fa760e 100644
>> --- a/drivers/iio/common/Makefile
>> +++ b/drivers/iio/common/Makefile
>> @@ -7,6 +7,7 @@
>>  #
>>  
>>  # When adding new entries keep the list in alphabetical order
>> +obj-y += cros_ec_sensors/
>>  obj-y += hid-sensors/
>>  obj-y += ms_sensors/
>>  obj-y += ssp_sensors/
>> diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig b/drivers/iio/common/cros_ec_sensors/Kconfig
>> new file mode 100644
>> index 0000000..24743be
>> --- /dev/null
>> +++ b/drivers/iio/common/cros_ec_sensors/Kconfig
>> @@ -0,0 +1,14 @@
>> +#
>> +# Chrome OS Embedded Controller managed sensors library
>> +#
>> +config IIO_CROS_EC_SENSORS_CORE
>> +	tristate "ChromeOS EC Sensors Core"
>> +	depends on SYSFS && MFD_CROS_EC
>> +	select IIO_BUFFER
>> +	select IIO_TRIGGERED_BUFFER
>> +	help
>> +	  Base module for the ChromeOS EC Sensors module.
>> +	  Contains core functions used by other IIO CrosEC sensor
>> +	  drivers.
>> +	  Define common attributes and sysfs interrupt handler.
>> +
>> diff --git a/drivers/iio/common/cros_ec_sensors/Makefile b/drivers/iio/common/cros_ec_sensors/Makefile
>> new file mode 100644
>> index 0000000..95b6901
>> --- /dev/null
>> +++ b/drivers/iio/common/cros_ec_sensors/Makefile
>> @@ -0,0 +1,5 @@
>> +#
>> +# Makefile for sensors seen through the ChromeOS EC sensor hub.
>> +#
>> +
>> +obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.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
>> new file mode 100644
>> index 0000000..a3be799
>> --- /dev/null
>> +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
>> @@ -0,0 +1,450 @@
>> +/*
>> + * cros_ec_sensors_core - Common function for Chrome OS EC sensor driver.
>> + *
>> + * Copyright (C) 2016 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.
>> + */
>> +
>> +#include <linux/delay.h>
>> +#include <linux/device.h>
>> +#include <linux/iio/buffer.h>
>> +#include <linux/iio/iio.h>
>> +#include <linux/iio/kfifo_buf.h>
>> +#include <linux/iio/trigger_consumer.h>
>> +#include <linux/kernel.h>
>> +#include <linux/mfd/cros_ec.h>
>> +#include <linux/mfd/cros_ec_commands.h>
>> +#include <linux/module.h>
>> +#include <linux/slab.h>
>> +#include <linux/sysfs.h>
>> +#include <linux/platform_device.h>
>> +
>> +#include "cros_ec_sensors_core.h"
>> +
>> +static char *cros_ec_loc[] = {
>> +	[MOTIONSENSE_LOC_BASE] = "base",
>> +	[MOTIONSENSE_LOC_LID] = "lid",
>> +	[MOTIONSENSE_LOC_MAX] = "unknown",
>> +};
>> +
>> +int cros_ec_sensors_core_init(struct platform_device *pdev,
>> +			      struct iio_dev *indio_dev,
>> +			      bool physical_device)
>> +{
>> +	struct device *dev = &pdev->dev;
>> +	struct cros_ec_sensors_core_state *state = iio_priv(indio_dev);
>> +	struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent);
>> +	struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
>> +
>> +	platform_set_drvdata(pdev, indio_dev);
>> +
>> +	state->ec = ec->ec_dev;
>> +	state->msg = devm_kzalloc(&pdev->dev,
>> +				max((u16)sizeof(struct ec_params_motion_sense),
>> +				state->ec->max_response), GFP_KERNEL);
>> +	if (!state->msg)
>> +		return -ENOMEM;
>> +
>> +	state->resp = (struct ec_response_motion_sense *)state->msg->data;
>> +
>> +	mutex_init(&state->cmd_lock);
>> +
>> +	/* Set up the host command structure. */
>> +	state->msg->version = 2;
>> +	state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
>> +	state->msg->outsize = sizeof(struct ec_params_motion_sense);
>> +
>> +	indio_dev->dev.parent = &pdev->dev;
>> +	indio_dev->name = pdev->name;
>> +
>> +	if (physical_device) {
>> +		indio_dev->modes = INDIO_DIRECT_MODE;
>> +
>> +		state->param.cmd = MOTIONSENSE_CMD_INFO;
>> +		state->param.info.sensor_num = sensor_platform->sensor_num;
>> +		if (cros_ec_motion_send_host_cmd(state, 0)) {
>> +			dev_warn(dev, "Can not access sensor info\n");
>> +			return -EIO;
>> +		}
>> +		state->type = state->resp->info.type;
>> +		state->loc = state->resp->info.location;
>> +	}
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init);
>> +
>> +int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *state,
>> +				 u16 opt_length)
>> +{
>> +	int ret;
>> +
>> +	if (opt_length)
>> +		state->msg->insize = min(opt_length, state->ec->max_response);
>> +	else
>> +		state->msg->insize = state->ec->max_response;
>> +
>> +	memcpy(state->msg->data, &state->param, sizeof(state->param));
>> +
>> +	ret = cros_ec_cmd_xfer_status(state->ec, state->msg);
>> +	if (ret < 0)
>> +		return -EIO;
>> +
>> +	if (ret &&
>> +	    state->resp != (struct ec_response_motion_sense *)state->msg->data)
>> +		memcpy(state->resp, state->msg->data, ret);
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(cros_ec_motion_send_host_cmd);
>> +
>> +static ssize_t cros_ec_sensors_calibrate(struct iio_dev *indio_dev,
>> +		uintptr_t private, const struct iio_chan_spec *chan,
>> +		const char *buf, size_t len)
>> +{
>> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
>> +	int ret, i;
>> +	bool calibrate;
>> +
>> +	ret = strtobool(buf, &calibrate);
>> +	if (ret < 0)
>> +		return ret;
>> +	if (!calibrate)
>> +		return -EINVAL;
>> +
>> +	mutex_lock(&st->cmd_lock);
>> +	st->param.cmd = MOTIONSENSE_CMD_PERFORM_CALIB;
>> +	ret = cros_ec_motion_send_host_cmd(st, 0);
>> +	if (ret != 0) {
>> +		dev_warn(&indio_dev->dev, "Unable to calibrate sensor\n");
>> +	} else {
>> +		/* Save values */
>> +		for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
>> +			st->calib[i] = st->resp->perform_calib.offset[i];
>> +	}
>> +	mutex_unlock(&st->cmd_lock);
>> +
>> +	return ret ? ret : len;
>> +}
>> +
>> +static ssize_t cros_ec_sensors_loc(struct iio_dev *indio_dev,
>> +		uintptr_t private, const struct iio_chan_spec *chan,
>> +		char *buf)
>> +{
>> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
>> +
>> +	return snprintf(buf, PAGE_SIZE, "%s\n", cros_ec_loc[st->loc]);
>> +}
>> +
>> +const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[] = {
>> +	{
>> +		.name = "calibrate",
>> +		.shared = IIO_SHARED_BY_ALL,
>> +		.write = cros_ec_sensors_calibrate
>> +	},
>> +	{
>> +		.name = "location",
>> +		.shared = IIO_SHARED_BY_ALL,
>> +		.read = cros_ec_sensors_loc
>> +	},
>> +	{ },
>> +};
>> +EXPORT_SYMBOL_GPL(cros_ec_sensors_ext_info);
>> +
>> +/**
>> + * cros_ec_sensors_idx_to_reg - convert index into offset in shared memory
>> + * @st:		pointer to state information for device
>> + * @idx:	sensor index (should be element of enum sensor_index)
>> + *
>> + * Return:	address to read at
>> + */
>> +static unsigned int cros_ec_sensors_idx_to_reg(
>> +					struct cros_ec_sensors_core_state *st,
>> +					unsigned int idx)
>> +{
>> +	/*
>> +	 * When using LPC interface, only space for 2 Accel and one Gyro.
>> +	 * First halfword of MOTIONSENSE_TYPE_ACCEL is used by angle.
>> +	 */
>> +	if (st->type == MOTIONSENSE_TYPE_ACCEL)
>> +		return EC_MEMMAP_ACC_DATA + sizeof(u16) *
>> +			(1 + idx + st->param.info.sensor_num *
>> +			 CROS_EC_SENSOR_MAX_AXIS);
>> +
>> +	return EC_MEMMAP_GYRO_DATA + sizeof(u16) * idx;
>> +}
>> +
>> +static int cros_ec_sensors_cmd_read_u8(struct cros_ec_device *ec,
>> +				       unsigned int offset, u8 *dest)
>> +{
>> +	return ec->cmd_readmem(ec, offset, 1, dest);
>> +}
>> +
>> +static int cros_ec_sensors_cmd_read_u16(struct cros_ec_device *ec,
>> +					 unsigned int offset, u16 *dest)
>> +{
>> +	__le16 tmp;
>> +	int ret = ec->cmd_readmem(ec, offset, 2, &tmp);
>> +
>> +	if (ret >= 0)
>> +		*dest = le16_to_cpu(tmp);
>> +
>> +	return ret;
>> +}
>> +
>> +/**
>> + * cros_ec_sensors_read_until_not_busy() - read until is not busy
>> + *
>> + * @st:	pointer to state information for device
>> + *
>> + * Read from EC status byte until it reads not busy.
>> + * Return: 8-bit status if ok, -errno on failure.
>> + */
>> +static int cros_ec_sensors_read_until_not_busy(
>> +					struct cros_ec_sensors_core_state *st)
>> +{
>> +	struct cros_ec_device *ec = st->ec;
>> +	u8 status;
>> +	int ret, attempts = 0;
>> +
>> +	ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status);
>> +	if (ret < 0)
>> +		return ret;
>> +
>> +	while (status & EC_MEMMAP_ACC_STATUS_BUSY_BIT) {
>> +		/* Give up after enough attempts, return error. */
>> +		if (attempts++ >= 50)
>> +			return -EIO;
>> +
>> +		/* Small delay every so often. */
>> +		if (attempts % 5 == 0)
>> +			msleep(25);
>> +
>> +		ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS,
>> +						  &status);
>> +		if (ret < 0)
>> +			return ret;
>> +	}
>> +
>> +	return status;
>> +}
>> +
>> +/**
>> + * read_ec_sensors_data_unsafe() - read acceleration data from EC shared memory
>> + * @indio_dev:	pointer to IIO device
>> + * @scan_mask:	bitmap of the sensor indices to scan
>> + * @data:	location to store data
>> + *
>> + * This is the unsafe function for reading the EC data. It does not guarantee
>> + * that the EC will not modify the data as it is being read in.
>> + *
>> + * Return: 0 on success, -errno on failure.
>> + */
>> +static int cros_ec_sensors_read_data_unsafe(struct iio_dev *indio_dev,
>> +			 unsigned long scan_mask, s16 *data)
>> +{
>> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
>> +	struct cros_ec_device *ec = st->ec;
>> +	unsigned int i;
>> +	int ret;
>> +
>> +	/* Read all sensors enabled in scan_mask. Each value is 2 bytes. */
>> +	for_each_set_bit(i, &scan_mask, indio_dev->masklength) {
>> +		ret = cros_ec_sensors_cmd_read_u16(ec,
>> +					     cros_ec_sensors_idx_to_reg(st, i),
>> +					     data);
>> +		if (ret < 0)
>> +			return ret;
>> +
>> +		data++;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev,
>> +			     unsigned long scan_mask, s16 *data)
>> +{
>> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
>> +	struct cros_ec_device *ec = st->ec;
>> +	u8 samp_id = 0xff, status = 0;
>> +	int ret, attempts = 0;
>> +
>> +	/*
>> +	 * Continually read all data from EC until the status byte after
>> +	 * all reads reflects that the EC is not busy and the sample id
>> +	 * matches the sample id from before all reads. This guarantees
>> +	 * that data read in was not modified by the EC while reading.
>> +	 */
>> +	while ((status & (EC_MEMMAP_ACC_STATUS_BUSY_BIT |
>> +			  EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK)) != samp_id) {
>> +		/* If we have tried to read too many times, return error. */
>> +		if (attempts++ >= 5)
>> +			return -EIO;
>> +
>> +		/* Read status byte until EC is not busy. */
>> +		status = cros_ec_sensors_read_until_not_busy(st);
>> +		if (status < 0)
>> +			return status;
>> +
>> +		/*
>> +		 * Store the current sample id so that we can compare to the
>> +		 * sample id after reading the data.
>> +		 */
>> +		samp_id = status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK;
>> +
>> +		/* Read all EC data, format it, and store it into data. */
>> +		ret = cros_ec_sensors_read_data_unsafe(indio_dev, scan_mask,
>> +						       data);
>> +		if (ret < 0)
>> +			return ret;
>> +
>> +		/* Read status byte. */
>> +		ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS,
>> +						  &status);
>> +		if (ret < 0)
>> +			return ret;
>> +	}
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(cros_ec_sensors_read_lpc);
>> +
>> +int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev,
>> +			     unsigned long scan_mask, s16 *data)
>> +{
>> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
>> +	int ret;
>> +	unsigned int i;
>> +
>> +	/* Read all sensor data through a command. */
>> +	st->param.cmd = MOTIONSENSE_CMD_DATA;
>> +	ret = cros_ec_motion_send_host_cmd(st, sizeof(st->resp->data));
>> +	if (ret != 0) {
>> +		dev_warn(&indio_dev->dev, "Unable to read sensor data\n");
>> +		return ret;
>> +	}
>> +
>> +	for_each_set_bit(i, &scan_mask, indio_dev->masklength) {
>> +		*data = st->resp->data.data[i];
>> +		data++;
>> +	}
>> +
>> +	return 0;
>> +}
>> +EXPORT_SYMBOL_GPL(cros_ec_sensors_read_cmd);
>> +
>> +irqreturn_t cros_ec_sensors_capture(int irq, void *p)
>> +{
>> +	struct iio_poll_func *pf = p;
>> +	struct iio_dev *indio_dev = pf->indio_dev;
>> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
>> +	int ret;
>> +
>> +	mutex_lock(&st->cmd_lock);
>> +
>> +	/* Clear capture data. */
>> +	memset(st->samples, 0, indio_dev->scan_bytes);
>> +
>> +	/* Read data based on which channels are enabled in scan mask. */
>> +	ret = st->read_ec_sensors_data(indio_dev,
>> +				       *(indio_dev->active_scan_mask),
>> +				       (s16 *)st->samples);
>> +	if (ret < 0)
>> +		goto done;
>> +
>> +	iio_push_to_buffers_with_timestamp(indio_dev, st->samples,
>> +					   iio_get_time_ns(indio_dev));
>> +
>> +done:
>> +	/*
>> +	 * Tell the core we are done with this trigger and ready for the
>> +	 * next one.
>> +	 */
>> +	iio_trigger_notify_done(indio_dev->trig);
>> +
>> +	mutex_unlock(&st->cmd_lock);
>> +
>> +	return IRQ_HANDLED;
>> +}
>> +EXPORT_SYMBOL_GPL(cros_ec_sensors_capture);
>> +
>> +int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st,
>> +			  struct iio_chan_spec const *chan,
>> +			  int *val, int *val2, long mask)
>> +{
>> +	int ret = IIO_VAL_INT;
>> +
>> +	switch (mask) {
>> +	case IIO_CHAN_INFO_SAMP_FREQ:
>> +		st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
>> +		st->param.ec_rate.data =
>> +			EC_MOTION_SENSE_NO_VALUE;
>> +
>> +		if (cros_ec_motion_send_host_cmd(st, 0))
>> +			ret = -EIO;
>> +		else
>> +			*val = st->resp->ec_rate.ret;
>> +		break;
>> +	case IIO_CHAN_INFO_FREQUENCY:
>> +		st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
>> +		st->param.sensor_odr.data =
>> +			EC_MOTION_SENSE_NO_VALUE;
>> +
>> +		if (cros_ec_motion_send_host_cmd(st, 0))
>> +			ret = -EIO;
>> +		else
>> +			*val = st->resp->sensor_odr.ret;
>> +		break;
>> +	default:
>> +		break;
>> +	}
>> +
>> +	return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read);
>> +
>> +int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
>> +			       struct iio_chan_spec const *chan,
>> +			       int val, int val2, long mask)
>> +{
>> +	int ret = 0;
>> +
>> +	switch (mask) {
>> +	case IIO_CHAN_INFO_FREQUENCY:
>> +		st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
>> +		st->param.sensor_odr.data = val;
>> +
>> +		/* Always roundup, so caller gets at least what it asks for. */
>> +		st->param.sensor_odr.roundup = 1;
>> +
>> +		if (cros_ec_motion_send_host_cmd(st, 0))
>> +			ret = -EIO;
>> +		break;
>> +	case IIO_CHAN_INFO_SAMP_FREQ:
>> +		st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
>> +		st->param.ec_rate.data = val;
>> +
>> +		if (cros_ec_motion_send_host_cmd(st, 0))
>> +			ret = -EIO;
>> +		else
>> +			st->curr_sampl_freq = val;
>> +		break;
>> +	default:
>> +		ret = -EINVAL;
>> +		break;
>> +	}
>> +	return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(cros_ec_sensors_core_write);
>> +
>> +MODULE_DESCRIPTION("ChromeOS EC sensor hub core functions");
>> +MODULE_LICENSE("GPL v2");
>> diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
>> new file mode 100644
>> index 0000000..8bc2ca3
>> --- /dev/null
>> +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
>> @@ -0,0 +1,175 @@
>> +/*
>> + * ChromeOS EC sensor hub
>> + *
>> + * Copyright (C) 2016 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.
>> + */
>> +
>> +#ifndef __CROS_EC_SENSORS_CORE_H
>> +#define __CROS_EC_SENSORS_CORE_H
>> +
>> +#include <linux/irqreturn.h>
>> +
>> +enum {
>> +	CROS_EC_SENSOR_X,
>> +	CROS_EC_SENSOR_Y,
>> +	CROS_EC_SENSOR_Z,
>> +	CROS_EC_SENSOR_MAX_AXIS,
>> +};
>> +
>> +/* EC returns sensor values using signed 16 bit registers */
>> +#define CROS_EC_SENSOR_BITS 16
>> +
>> +/*
>> + * 4 16 bit channels are allowed.
>> + * Good enough for current sensors, they use up to 3 16 bit vectors.
>> + */
>> +#define CROS_EC_SAMPLE_SIZE  (sizeof(s64) * 2)
>> +
>> +/* Minimum sampling period to use when device is suspending */
>> +#define CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY 1000  /* 1 second */
>> +
>> +/**
>> + * struct cros_ec_sensors_core_state - state data for EC sensors IIO driver
>> + * @ec:				cros EC device structure
>> + * @cmd_lock:			lock used to prevent simultaneous access to the
>> + *				commands.
>> + * @msg:			cros EC command structure
>> + * @param:			motion sensor parameters structure
>> + * @resp:			motion sensor response structure
>> + * @type:			type of motion sensor
>> + * @loc:			location where the motion sensor is placed
>> + * @calib:			calibration parameters. Note that trigger
>> + *				captured data will always provide the calibrated
>> + *				data
>> + * @samples:			static array to hold data from a single capture.
>> + *				For each channel we need 2 bytes, except for
>> + *				the timestamp. The timestamp is always last and
>> + *				is always 8-byte aligned.
>> + * @read_ec_sensors_data:	function used for accessing sensors values
>> + * @cuur_sampl_freq:		current sampling period
>> + */
>> +struct cros_ec_sensors_core_state {
>> +	struct cros_ec_device *ec;
>> +	struct mutex cmd_lock;
>> +
>> +	struct cros_ec_command *msg;
>> +	struct ec_params_motion_sense param;
>> +	struct ec_response_motion_sense *resp;
>> +
>> +	enum motionsensor_type type;
>> +	enum motionsensor_location loc;
>> +
>> +	s16 calib[CROS_EC_SENSOR_MAX_AXIS];
>> +
>> +	u8 samples[CROS_EC_SAMPLE_SIZE];
>> +
>> +	int (*read_ec_sensors_data)(struct iio_dev *indio_dev,
>> +				    unsigned long scan_mask, s16 *data);
>> +
>> +	int curr_sampl_freq;
>> +};
>> +
>> +/**
>> + * cros_ec_sensors_read_lpc() - retrieve data from EC shared memory
>> + * @indio_dev:	pointer to IIO device
>> + * @scan_mask:	bitmap of the sensor indices to scan
>> + * @data:	location to store data
>> + *
>> + * This is the safe function for reading the EC data. It guarantees that the
>> + * data sampled was not modified by the EC while being read.
>> + *
>> + * Return: 0 on success, -errno on failure.
>> + */
>> +int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev, unsigned long scan_mask,
>> +			     s16 *data);
>> +
>> +/**
>> + * cros_ec_sensors_read_cmd() - retrieve data using the EC command protocol
>> + * @indio_dev:	pointer to IIO device
>> + * @scan_mask:	bitmap of the sensor indices to scan
>> + * @data:	location to store data
>> + *
>> + * Return: 0 on success, -errno on failure.
>> + */
>> +int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, unsigned long scan_mask,
>> +			     s16 *data);
>> +
>> +/**
>> + * cros_ec_sensors_core_init() - basic initialization of the core structure
>> + * @pdev:		platform device created for the sensors
>> + * @indio_dev:		iio device structure of the device
>> + * @physical_device:	true if the device refers to a physical device
>> + *
>> + * Return: 0 on success, -errno on failure.
>> + */
>> +int cros_ec_sensors_core_init(struct platform_device *pdev,
>> +			      struct iio_dev *indio_dev, bool physical_device);
>> +
>> +/**
>> + * cros_ec_sensors_capture() - the trigger handler function
>> + * @irq:	the interrupt number.
>> + * @p:		a pointer to the poll function.
>> + *
>> + * On a trigger event occurring, if the pollfunc is attached then this
>> + * handler is called as a threaded interrupt (and hence may sleep). It
>> + * is responsible for grabbing data from the device and pushing it into
>> + * the associated buffer.
>> + *
>> + * Return: IRQ_HANDLED
>> + */
>> +irqreturn_t cros_ec_sensors_capture(int irq, void *p);
>> +
>> +/**
>> + * cros_ec_motion_send_host_cmd() - send motion sense host command
>> + * @st:		pointer to state information for device
>> + * @opt_length:	optional length to reduce the response size, useful on the data
>> + *		path. Otherwise, the maximal allowed response size is used
>> + *
>> + * When called, the sub-command is assumed to be set in param->cmd.
>> + *
>> + * Return: 0 on success, -errno on failure.
>> + */
>> +int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *st,
>> +				 u16 opt_length);
>> +
>> +/**
>> + * cros_ec_sensors_core_read() - function to request a value from the sensor
>> + * @st:		pointer to state information for device
>> + * @chan:	channel specification structure table
>> + * @val:	will contain one element making up the returned value
>> + * @val2:	will contain another element making up the returned value
>> + * @mask:	specifies which values to be requested
>> + *
>> + * Return:	the type of value returned by the device
>> + */
>> +int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st,
>> +			      struct iio_chan_spec const *chan,
>> +			      int *val, int *val2, long mask);
>> +
>> +/**
>> + * cros_ec_sensors_core_write() - function to write a value to the sensor
>> + * @st:		pointer to state information for device
>> + * @chan:	channel specification structure table
>> + * @val:	first part of value to write
>> + * @val2:	second part of value to write
>> + * @mask:	specifies which values to write
>> + *
>> + * Return:	the type of value returned by the device
>> + */
>> +int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
>> +			       struct iio_chan_spec const *chan,
>> +			       int val, int val2, long mask);
>> +
>> +/* List of extended channel specification for all sensors */
>> +extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[];
>> +
>> +#endif  /* __CROS_EC_SENSORS_CORE_H */
>> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
>> index d6539c1..7769ea6 100644
>> --- a/include/linux/mfd/cros_ec.h
>> +++ b/include/linux/mfd/cros_ec.h
>> @@ -151,6 +151,15 @@ struct cros_ec_device {
>>  	int event_size;
>>  };
>>  
>> +/**
>> + * struct cros_ec_sensor_platform - ChromeOS EC sensor platform information
>> + *
>> + * @sensor_num: Id of the sensor, as reported by the EC.
>> + */
>> +struct cros_ec_sensor_platform {
>> +	u8 sensor_num;
>> +};
>> +
>>  /* struct cros_ec_platform - ChromeOS EC platform information
>>   *
>>   * @ec_name: name of EC device (e.g. 'cros-ec', 'cros-pd', ...)
>> diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h
>> index 76728ff..8826e0f 100644
>> --- a/include/linux/mfd/cros_ec_commands.h
>> +++ b/include/linux/mfd/cros_ec_commands.h
>> @@ -1315,6 +1315,24 @@ enum motionsense_command {
>>  	 */
>>  	MOTIONSENSE_CMD_KB_WAKE_ANGLE = 5,
>>  
>> +	/*
>> +	 * Returns a single sensor data.
>> +	 */
>> +	MOTIONSENSE_CMD_DATA = 6,
>> +
>> +	/*
>> +	 * Perform low level calibration.. On sensors that support it, ask to
>> +	 * do offset calibration.
>> +	 */
>> +	MOTIONSENSE_CMD_PERFORM_CALIB = 10,
>> +
>> +	/*
>> +	 * Sensor Offset command is a setter/getter command for the offset used
>> +	 * for calibration. The offsets can be calculated by the host, or via
>> +	 * PERFORM_CALIB command.
>> +	 */
>> +	MOTIONSENSE_CMD_SENSOR_OFFSET = 11,
>> +
>>  	/* Number of motionsense sub-commands. */
>>  	MOTIONSENSE_NUM_CMDS
>>  };
>> @@ -1335,12 +1353,18 @@ enum motionsensor_id {
>>  enum motionsensor_type {
>>  	MOTIONSENSE_TYPE_ACCEL = 0,
>>  	MOTIONSENSE_TYPE_GYRO = 1,
>> +	MOTIONSENSE_TYPE_MAG = 2,
>> +	MOTIONSENSE_TYPE_PROX = 3,
>> +	MOTIONSENSE_TYPE_LIGHT = 4,
>> +	MOTIONSENSE_TYPE_ACTIVITY = 5,
>> +	MOTIONSENSE_TYPE_MAX
>>  };
>>  
>>  /* List of motion sensor locations. */
>>  enum motionsensor_location {
>>  	MOTIONSENSE_LOC_BASE = 0,
>>  	MOTIONSENSE_LOC_LID = 1,
>> +	MOTIONSENSE_LOC_MAX,
>>  };
>>  
>>  /* List of motion sensor chips. */
>> @@ -1361,6 +1385,31 @@ enum motionsensor_chip {
>>   */
>>  #define EC_MOTION_SENSE_NO_VALUE -1
>>  
>> +#define EC_MOTION_SENSE_INVALID_CALIB_TEMP 0x8000
>> +
>> +/* Set Calibration information */
>> +#define MOTION_SENSE_SET_OFFSET	1
>> +
>> +struct ec_response_motion_sensor_data {
>> +	/* Flags for each sensor. */
>> +	uint8_t flags;
>> +	/* Sensor number the data comes from */
>> +	uint8_t sensor_num;
>> +	/* Each sensor is up to 3-axis. */
>> +	union {
>> +		int16_t             data[3];
>> +		struct {
>> +			uint16_t    rsvd;
>> +			uint32_t    timestamp;
>> +		} __packed;
>> +		struct {
>> +			uint8_t     activity; /* motionsensor_activity */
>> +			uint8_t     state;
>> +			int16_t     add_info[2];
>> +		};
>> +	};
>> +} __packed;
>> +
>>  struct ec_params_motion_sense {
>>  	uint8_t cmd;
>>  	union {
>> @@ -1378,9 +1427,37 @@ struct ec_params_motion_sense {
>>  			int16_t data;
>>  		} ec_rate, kb_wake_angle;
>>  
>> +		/* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */
>> +		struct {
>> +			uint8_t sensor_num;
>> +
>> +			/*
>> +			 * bit 0: If set (MOTION_SENSE_SET_OFFSET), set
>> +			 * the calibration information in the EC.
>> +			 * If unset, just retrieve calibration information.
>> +			 */
>> +			uint16_t flags;
>> +
>> +			/*
>> +			 * Temperature at calibration, in units of 0.01 C
>> +			 * 0x8000: invalid / unknown.
>> +			 * 0x0: 0C
>> +			 * 0x7fff: +327.67C
>> +			 */
>> +			int16_t temp;
>> +
>> +			/*
>> +			 * Offset for calibration.
>> +			 * Unit:
>> +			 * Accelerometer: 1/1024 g
>> +			 * Gyro:          1/1024 deg/s
>> +			 * Compass:       1/16 uT
>> +			 */
>> +			int16_t offset[3];
>> +		} __packed sensor_offset;
>> +
>>  		/* Used for MOTIONSENSE_CMD_INFO. */
>>  		struct {
>> -			/* Should be element of enum motionsensor_id. */
>>  			uint8_t sensor_num;
>>  		} info;
>>  
>> @@ -1410,11 +1487,14 @@ struct ec_response_motion_sense {
>>  			/* Flags representing the motion sensor module. */
>>  			uint8_t module_flags;
>>  
>> -			/* Flags for each sensor in enum motionsensor_id. */
>> -			uint8_t sensor_flags[EC_MOTION_SENSOR_COUNT];
>> +			/* Number of sensors managed directly by the EC. */
>> +			uint8_t sensor_count;
>>  
>> -			/* Array of all sensor data. Each sensor is 3-axis. */
>> -			int16_t data[3*EC_MOTION_SENSOR_COUNT];
>> +			/*
>> +			 * Sensor data is truncated if response_max is too small
>> +			 * for holding all the data.
>> +			 */
>> +			struct ec_response_motion_sensor_data sensor[0];
>>  		} dump;
>>  
>>  		/* Used for MOTIONSENSE_CMD_INFO. */
>> @@ -1429,6 +1509,9 @@ struct ec_response_motion_sense {
>>  			uint8_t chip;
>>  		} info;
>>  
>> +		/* Used for MOTIONSENSE_CMD_DATA */
>> +		struct ec_response_motion_sensor_data data;
>> +
>>  		/*
>>  		 * Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR,
>>  		 * MOTIONSENSE_CMD_SENSOR_RANGE, and
>> @@ -1438,6 +1521,12 @@ struct ec_response_motion_sense {
>>  			/* Current value of the parameter queried. */
>>  			int32_t ret;
>>  		} ec_rate, sensor_odr, sensor_range, kb_wake_angle;
>> +
>> +		/* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */
>> +		struct {
>> +			int16_t temp;
>> +			int16_t offset[3];
>> +		} sensor_offset, perform_calib;
>>  	};
>>  } __packed;
>>  
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 2/4] iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver
  2016-08-15 15:28   ` Jonathan Cameron
@ 2016-09-03 17:12     ` Jonathan Cameron
  2016-10-25 17:12       ` Jonathan Cameron
  0 siblings, 1 reply; 30+ messages in thread
From: Jonathan Cameron @ 2016-09-03 17:12 UTC (permalink / raw)
  To: Enric Balletbo i Serra, linux-kernel, linux-iio
  Cc: Olof Johansson, Lee Jones, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Guenter Roeck, Gwendal Grignou

On 15/08/16 16:28, Jonathan Cameron wrote:
> On 01/08/16 10:54, Enric Balletbo i Serra wrote:
>> Handle 3d contiguous sensors like Accelerometers, Gyroscope and
>> Magnetometer that are presented by the ChromeOS EC Sensor hub.
>>
>> Signed-off-by: Guenter Roeck <groeck@chromium.org>
>> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
> Reviewed-by: Jonathan Cameron <jic23@kernel.org>
> 
> Again, fine if this goes via mfd.
A bit of white space fun that I cleaned up in the previous patch
made this interesting to apply but think I got it right
(there was an extra blank line at the end of the Kconfig)

Thanks,

Jonathan
> 
> Thanks,
> 
> Jonathan
>> ---
>>
>> Changes since v3:
>>   - Remove some useless initialitzations as always overwritten.
>>   - Convert calib structure to a simple array.
>> Changes since v2:
>>   - Fix some typos
>>   - Skip filling by zero structure parameters that already zero'd.
>>   - Order includes alphabetically.
>>   - Propagate error codes.
>> Changes since v1:
>>   - Fixup multiline comments.
>>   - Fix some spelling mistakes.
>>   - Blank line before return statements.
>>   - Add CROS_EC_SENSORS_ prefix.
>>
>>  drivers/iio/common/cros_ec_sensors/Kconfig         |   8 +
>>  drivers/iio/common/cros_ec_sensors/Makefile        |   1 +
>>  .../iio/common/cros_ec_sensors/cros_ec_sensors.c   | 322 +++++++++++++++++++++
>>  3 files changed, 331 insertions(+)
>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>>
>> diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig b/drivers/iio/common/cros_ec_sensors/Kconfig
>> index 24743be..980bea2 100644
>> --- a/drivers/iio/common/cros_ec_sensors/Kconfig
>> +++ b/drivers/iio/common/cros_ec_sensors/Kconfig
>> @@ -12,3 +12,11 @@ config IIO_CROS_EC_SENSORS_CORE
>>  	  drivers.
>>  	  Define common attributes and sysfs interrupt handler.
>>  
>> +config IIO_CROS_EC_SENSORS
>> +	tristate "ChromeOS EC Contiguous Sensors"
>> +	select IIO_CROS_EC_SENSORS_CORE
>> +	help
>> +	  Module to handle 3d contiguous sensors like
>> +	  Accelerometers, Gyroscope and Magnetometer that are
>> +	  presented by the ChromeOS EC Sensor hub.
>> +	  Creates an IIO device for each functions.
>> diff --git a/drivers/iio/common/cros_ec_sensors/Makefile b/drivers/iio/common/cros_ec_sensors/Makefile
>> index 95b6901..ec716ff 100644
>> --- a/drivers/iio/common/cros_ec_sensors/Makefile
>> +++ b/drivers/iio/common/cros_ec_sensors/Makefile
>> @@ -3,3 +3,4 @@
>>  #
>>  
>>  obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.o
>> +obj-$(CONFIG_IIO_CROS_EC_SENSORS) += cros_ec_sensors.o
>> diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>> new file mode 100644
>> index 0000000..48edeba
>> --- /dev/null
>> +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>> @@ -0,0 +1,322 @@
>> +/*
>> + * cros_ec_sensors - Driver for Chrome OS Embedded Controller sensors.
>> + *
>> + * Copyright (C) 2016 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 sensors data. Data access is presented through iio sysfs.
>> + */
>> +
>> +#include <linux/delay.h>
>> +#include <linux/device.h>
>> +#include <linux/iio/buffer.h>
>> +#include <linux/iio/iio.h>
>> +#include <linux/iio/kfifo_buf.h>
>> +#include <linux/iio/trigger_consumer.h>
>> +#include <linux/iio/triggered_buffer.h>
>> +#include <linux/kernel.h>
>> +#include <linux/mfd/cros_ec.h>
>> +#include <linux/mfd/cros_ec_commands.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/slab.h>
>> +#include <linux/sysfs.h>
>> +
>> +#include "cros_ec_sensors_core.h"
>> +
>> +#define CROS_EC_SENSORS_MAX_CHANNELS 4
>> +
>> +/* State data for ec_sensors iio driver. */
>> +struct cros_ec_sensors_state {
>> +	/* Shared by all sensors */
>> +	struct cros_ec_sensors_core_state core;
>> +
>> +	struct iio_chan_spec channels[CROS_EC_SENSORS_MAX_CHANNELS];
>> +};
>> +
>> +static int cros_ec_sensors_read(struct iio_dev *indio_dev,
>> +			  struct iio_chan_spec const *chan,
>> +			  int *val, int *val2, long mask)
>> +{
>> +	struct cros_ec_sensors_state *st = iio_priv(indio_dev);
>> +	s16 data = 0;
>> +	s64 val64;
>> +	int i;
>> +	int ret = IIO_VAL_INT;
>> +	int idx = chan->scan_index;
>> +
>> +	mutex_lock(&st->core.cmd_lock);
>> +
>> +	switch (mask) {
>> +	case IIO_CHAN_INFO_RAW:
>> +		ret = st->core.read_ec_sensors_data(indio_dev, 1 << idx, &data);
>> +		if (ret < 0)
>> +			break;
>> +
>> +		*val = data;
>> +		break;
>> +	case IIO_CHAN_INFO_CALIBBIAS:
>> +		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
>> +		st->core.param.sensor_offset.flags = 0;
>> +
>> +		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
>> +		if (ret < 0)
>> +			break;
>> +
>> +		/* Save values */
>> +		for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
>> +			st->core.calib[i] =
>> +				st->core.resp->sensor_offset.offset[i];
>> +
>> +		*val = st->core.calib[idx];
>> +		break;
>> +	case IIO_CHAN_INFO_SCALE:
>> +		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
>> +		st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE;
>> +
>> +		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
>> +		if (ret < 0)
>> +			break;
>> +
>> +		val64 = st->core.resp->sensor_range.ret;
>> +		switch (st->core.type) {
>> +		case MOTIONSENSE_TYPE_ACCEL:
>> +			/*
>> +			 * EC returns data in g, iio exepects m/s^2.
>> +			 * Do not use IIO_G_TO_M_S_2 to avoid precision loss.
>> +			 */
>> +			*val = div_s64(val64 * 980665, 10);
>> +			*val2 = 10000 << (CROS_EC_SENSOR_BITS - 1);
>> +			ret = IIO_VAL_FRACTIONAL;
>> +			break;
>> +		case MOTIONSENSE_TYPE_GYRO:
>> +			/*
>> +			 * EC returns data in dps, iio expects rad/s.
>> +			 * Do not use IIO_DEGREE_TO_RAD to avoid precision
>> +			 * loss. Round to the nearest integer.
>> +			 */
>> +			*val = div_s64(val64 * 314159 + 9000000ULL, 1000);
>> +			*val2 = 18000 << (CROS_EC_SENSOR_BITS - 1);
>> +			ret = IIO_VAL_FRACTIONAL;
>> +			break;
>> +		case MOTIONSENSE_TYPE_MAG:
>> +			/*
>> +			 * EC returns data in 16LSB / uT,
>> +			 * iio expects Gauss
>> +			 */
>> +			*val = val64;
>> +			*val2 = 100 << (CROS_EC_SENSOR_BITS - 1);
>> +			ret = IIO_VAL_FRACTIONAL;
>> +			break;
>> +		default:
>> +			ret = -EINVAL;
>> +		}
>> +		break;
>> +	default:
>> +		ret = cros_ec_sensors_core_read(&st->core, chan, val, val2,
>> +						mask);
>> +		break;
>> +	}
>> +	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_state *st = iio_priv(indio_dev);
>> +	int i;
>> +	int ret = 0;
>> +	int idx = chan->scan_index;
>> +
>> +	mutex_lock(&st->core.cmd_lock);
>> +
>> +	switch (mask) {
>> +	case IIO_CHAN_INFO_CALIBBIAS:
>> +		st->core.calib[idx] = val;
>> +
>> +		/* Send to EC for each axis, even if not complete */
>> +		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
>> +		st->core.param.sensor_offset.flags =
>> +			MOTION_SENSE_SET_OFFSET;
>> +		for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
>> +			st->core.param.sensor_offset.offset[i] =
>> +				st->core.calib[i];
>> +		st->core.param.sensor_offset.temp =
>> +			EC_MOTION_SENSE_INVALID_CALIB_TEMP;
>> +
>> +		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
>> +		break;
>> +	case IIO_CHAN_INFO_SCALE:
>> +		if (st->core.type == MOTIONSENSE_TYPE_MAG) {
>> +			ret = -EINVAL;
>> +			break;
>> +		}
>> +		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
>> +		st->core.param.sensor_range.data = val;
>> +
>> +		/* Always roundup, so caller gets at least what it asks for. */
>> +		st->core.param.sensor_range.roundup = 1;
>> +
>> +		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
>> +		break;
>> +	default:
>> +		ret = cros_ec_sensors_core_write(
>> +				&st->core, chan, val, val2, mask);
>> +		break;
>> +	}
>> +
>> +	mutex_unlock(&st->core.cmd_lock);
>> +
>> +	return ret;
>> +}
>> +
>> +static const struct iio_info ec_sensors_info = {
>> +	.read_raw = &cros_ec_sensors_read,
>> +	.write_raw = &cros_ec_sensors_write,
>> +	.driver_module = THIS_MODULE,
>> +};
>> +
>> +static int cros_ec_sensors_probe(struct platform_device *pdev)
>> +{
>> +	struct device *dev = &pdev->dev;
>> +	struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
>> +	struct cros_ec_device *ec_device;
>> +	struct iio_dev *indio_dev;
>> +	struct cros_ec_sensors_state *state;
>> +	struct iio_chan_spec *channel;
>> +	int ret, i;
>> +
>> +	if (!ec_dev || !ec_dev->ec_dev) {
>> +		dev_warn(&pdev->dev, "No CROS EC device found.\n");
>> +		return -EINVAL;
>> +	}
>> +	ec_device = ec_dev->ec_dev;
>> +
>> +	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state));
>> +	if (!indio_dev)
>> +		return -ENOMEM;
>> +
>> +	ret = cros_ec_sensors_core_init(pdev, indio_dev, true);
>> +	if (ret)
>> +		return ret;
>> +
>> +	indio_dev->info = &ec_sensors_info;
>> +	state = iio_priv(indio_dev);
>> +	for (channel = state->channels, i = CROS_EC_SENSOR_X;
>> +	     i < CROS_EC_SENSOR_MAX_AXIS; i++, channel++) {
>> +		/* Common part */
>> +		channel->info_mask_separate =
>> +			BIT(IIO_CHAN_INFO_RAW) |
>> +			BIT(IIO_CHAN_INFO_CALIBBIAS);
>> +		channel->info_mask_shared_by_all =
>> +			BIT(IIO_CHAN_INFO_SCALE) |
>> +			BIT(IIO_CHAN_INFO_FREQUENCY) |
>> +			BIT(IIO_CHAN_INFO_SAMP_FREQ);
>> +		channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
>> +		channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
>> +		channel->scan_index = i;
>> +		channel->ext_info = cros_ec_sensors_ext_info;
>> +		channel->modified = 1;
>> +		channel->channel2 = IIO_MOD_X + i;
>> +		channel->scan_type.sign = 's';
>> +
>> +		/* Sensor specific */
>> +		switch (state->core.type) {
>> +		case MOTIONSENSE_TYPE_ACCEL:
>> +			channel->type = IIO_ACCEL;
>> +			break;
>> +		case MOTIONSENSE_TYPE_GYRO:
>> +			channel->type = IIO_ANGL_VEL;
>> +			break;
>> +		case MOTIONSENSE_TYPE_MAG:
>> +			channel->type = IIO_MAGN;
>> +			break;
>> +		default:
>> +			dev_err(&pdev->dev, "Unknown motion sensor\n");
>> +			return -EINVAL;
>> +		}
>> +	}
>> +
>> +	/* Timestamp */
>> +	channel->type = IIO_TIMESTAMP;
>> +	channel->channel = -1;
>> +	channel->scan_index = CROS_EC_SENSOR_MAX_AXIS;
>> +	channel->scan_type.sign = 's';
>> +	channel->scan_type.realbits = 64;
>> +	channel->scan_type.storagebits = 64;
>> +
>> +	indio_dev->channels = state->channels;
>> +	indio_dev->num_channels = CROS_EC_SENSORS_MAX_CHANNELS;
>> +
>> +	/* There is only enough room for accel and gyro in the io space */
>> +	if ((state->core.ec->cmd_readmem != NULL) &&
>> +	    (state->core.type != MOTIONSENSE_TYPE_MAG))
>> +		state->core.read_ec_sensors_data = cros_ec_sensors_read_lpc;
>> +	else
>> +		state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;
>> +
>> +	ret = iio_triggered_buffer_setup(indio_dev, NULL,
>> +					 cros_ec_sensors_capture, NULL);
>> +	if (ret)
>> +		return ret;
>> +
>> +	ret = iio_device_register(indio_dev);
>> +	if (ret)
>> +		goto error_uninit_buffer;
>> +
>> +	return 0;
>> +
>> +error_uninit_buffer:
>> +	iio_triggered_buffer_cleanup(indio_dev);
>> +
>> +	return ret;
>> +}
>> +
>> +static int cros_ec_sensors_remove(struct platform_device *pdev)
>> +{
>> +	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>> +
>> +	iio_device_unregister(indio_dev);
>> +	iio_triggered_buffer_cleanup(indio_dev);
>> +
>> +	return 0;
>> +}
>> +
>> +static const struct platform_device_id cros_ec_sensors_ids[] = {
>> +	{
>> +		.name = "cros-ec-accel",
>> +	},
>> +	{
>> +		.name = "cros-ec-gyro",
>> +	},
>> +	{
>> +		.name = "cros-ec-mag",
>> +	},
>> +	{ /* sentinel */ }
>> +};
>> +MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids);
>> +
>> +static struct platform_driver cros_ec_sensors_platform_driver = {
>> +	.driver = {
>> +		.name	= "cros-ec-sensors",
>> +	},
>> +	.probe		= cros_ec_sensors_probe,
>> +	.remove		= cros_ec_sensors_remove,
>> +	.id_table	= cros_ec_sensors_ids,
>> +};
>> +module_platform_driver(cros_ec_sensors_platform_driver);
>> +
>> +MODULE_DESCRIPTION("ChromeOS EC 3-axis sensors driver");
>> +MODULE_LICENSE("GPL v2");
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 4/4] platform/chrome: cros_ec_dev - Register cros-ec sensors
  2016-08-15 15:31   ` Jonathan Cameron
@ 2016-09-03 17:20     ` Jonathan Cameron
  2016-10-25 17:27       ` Jonathan Cameron
  0 siblings, 1 reply; 30+ messages in thread
From: Jonathan Cameron @ 2016-09-03 17:20 UTC (permalink / raw)
  To: Enric Balletbo i Serra, linux-kernel, linux-iio
  Cc: Olof Johansson, Lee Jones, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Guenter Roeck, Gwendal Grignou

On 15/08/16 16:31, Jonathan Cameron wrote:
> On 01/08/16 10:54, Enric Balletbo i Serra wrote:
>> Check whether the ChromeOS Embedded Controller is a sensor hub and in
>> such case issue a command to get the number of sensors and register them
>> all.
>>
>> Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
>> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
>> Reviewed-by: Guenter Roeck <groeck@chromium.org>
Just realised I don't have an Ack from Olof for these.

Olof - after much back and forth I'm taking the rest of
this series via the IIO tree. If you are happy with the below
then I'll pick this one up.

There will be an immutable branch needed for dependencies from
mfd and getting the changes back to them (it's a mess).

Jonathan
>> ---
>>
>> Changes since v3:
>>  - Remove Unnecessary ( ) around 'ret < 0'.
>>  - Add Reviewed-by tag
>>
>>  .../iio/common/cros_ec_sensors/cros_ec_sensors.c   |   4 +-
>>  drivers/platform/chrome/cros_ec_dev.c              | 122 +++++++++++++++++++++
>>  2 files changed, 124 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>> index 48edeba..d6c372b 100644
>> --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>> +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>> @@ -51,7 +51,7 @@ static int cros_ec_sensors_read(struct iio_dev *indio_dev,
>>  	s16 data = 0;
>>  	s64 val64;
>>  	int i;
>> -	int ret = IIO_VAL_INT;
>> +	int ret;
>>  	int idx = chan->scan_index;
>>  
>>  	mutex_lock(&st->core.cmd_lock);
>> @@ -137,7 +137,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
>>  {
>>  	struct cros_ec_sensors_state *st = iio_priv(indio_dev);
>>  	int i;
>> -	int ret = 0;
>> +	int ret;
>>  	int idx = chan->scan_index;
> *raises eyebrows*
> 
> Enough said?
> 
> Was wondering why this patch had strayed into the IIO files.
> 
I moved this to patch 2.
> 
>>  
>>  	mutex_lock(&st->core.cmd_lock);
>> diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c
>> index 7eb5307..47268ec 100644
>> --- a/drivers/platform/chrome/cros_ec_dev.c
>> +++ b/drivers/platform/chrome/cros_ec_dev.c
>> @@ -18,6 +18,7 @@
>>   */
>>  
>>  #include <linux/fs.h>
>> +#include <linux/mfd/core.h>
>>  #include <linux/module.h>
>>  #include <linux/platform_device.h>
>>  #include <linux/slab.h>
>> @@ -265,6 +266,123 @@ static void __remove(struct device *dev)
>>  	kfree(ec);
>>  }
>>  
>> +static void cros_ec_sensors_register(struct cros_ec_dev *ec)
>> +{
>> +	/*
>> +	 * Issue a command to get the number of sensor reported.
>> +	 * Build an array of sensors driver and register them all.
>> +	 */
>> +	int ret, i, id, sensor_num;
>> +	struct mfd_cell *sensor_cells;
>> +	struct cros_ec_sensor_platform *sensor_platforms;
>> +	int sensor_type[MOTIONSENSE_TYPE_MAX];
>> +	struct ec_params_motion_sense *params;
>> +	struct ec_response_motion_sense *resp;
>> +	struct cros_ec_command *msg;
>> +
>> +	msg = kzalloc(sizeof(struct cros_ec_command) +
>> +		      max(sizeof(*params), sizeof(*resp)), GFP_KERNEL);
>> +	if (msg == NULL)
>> +		return;
>> +
>> +	msg->version = 2;
>> +	msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
>> +	msg->outsize = sizeof(*params);
>> +	msg->insize = sizeof(*resp);
>> +
>> +	params = (struct ec_params_motion_sense *)msg->data;
>> +	params->cmd = MOTIONSENSE_CMD_DUMP;
>> +
>> +	ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
>> +	if (ret < 0 || msg->result != EC_RES_SUCCESS) {
>> +		dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n",
>> +			 ret, msg->result);
>> +		goto error;
>> +	}
>> +
>> +	resp = (struct ec_response_motion_sense *)msg->data;
>> +	sensor_num = resp->dump.sensor_count;
>> +	/* Allocate 2 extra sensors in case lid angle or FIFO are needed */
>> +	sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 2),
>> +			       GFP_KERNEL);
>> +	if (sensor_cells == NULL)
>> +		goto error;
>> +
>> +	sensor_platforms = kzalloc(sizeof(struct cros_ec_sensor_platform) *
>> +		  (sensor_num + 1), GFP_KERNEL);
>> +	if (sensor_platforms == NULL)
>> +		goto error_platforms;
>> +
>> +	memset(sensor_type, 0, sizeof(sensor_type));
>> +	id = 0;
>> +	for (i = 0; i < sensor_num; i++) {
>> +		params->cmd = MOTIONSENSE_CMD_INFO;
>> +		params->info.sensor_num = i;
>> +		ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
>> +		if (ret < 0 || msg->result != EC_RES_SUCCESS) {
>> +			dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n",
>> +				 i, ret, msg->result);
>> +			continue;
>> +		}
>> +		switch (resp->info.type) {
>> +		case MOTIONSENSE_TYPE_ACCEL:
>> +			sensor_cells[id].name = "cros-ec-accel";
>> +			break;
>> +		case MOTIONSENSE_TYPE_GYRO:
>> +			sensor_cells[id].name = "cros-ec-gyro";
>> +			break;
>> +		case MOTIONSENSE_TYPE_MAG:
>> +			sensor_cells[id].name = "cros-ec-mag";
>> +			break;
>> +		case MOTIONSENSE_TYPE_PROX:
>> +			sensor_cells[id].name = "cros-ec-prox";
>> +			break;
>> +		case MOTIONSENSE_TYPE_LIGHT:
>> +			sensor_cells[id].name = "cros-ec-light";
>> +			break;
>> +		case MOTIONSENSE_TYPE_ACTIVITY:
>> +			sensor_cells[id].name = "cros-ec-activity";
>> +			break;
>> +		default:
>> +			dev_warn(ec->dev, "unknown type %d\n", resp->info.type);
>> +			continue;
>> +		}
>> +		sensor_platforms[id].sensor_num = i;
>> +		sensor_cells[id].id = sensor_type[resp->info.type];
>> +		sensor_cells[id].platform_data = &sensor_platforms[id];
>> +		sensor_cells[id].pdata_size =
>> +			sizeof(struct cros_ec_sensor_platform);
>> +
>> +		sensor_type[resp->info.type]++;
>> +		id++;
>> +	}
>> +	if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) {
>> +		sensor_platforms[id].sensor_num = sensor_num;
>> +
>> +		sensor_cells[id].name = "cros-ec-angle";
>> +		sensor_cells[id].id = 0;
>> +		sensor_cells[id].platform_data = &sensor_platforms[id];
>> +		sensor_cells[id].pdata_size =
>> +			sizeof(struct cros_ec_sensor_platform);
>> +		id++;
>> +	}
>> +	if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
>> +		sensor_cells[id].name = "cros-ec-ring";
>> +		id++;
>> +	}
>> +
>> +	ret = mfd_add_devices(ec->dev, 0, sensor_cells, id,
>> +			      NULL, 0, NULL);
>> +	if (ret)
>> +		dev_err(ec->dev, "failed to add EC sensors\n");
>> +
>> +	kfree(sensor_platforms);
>> +error_platforms:
>> +	kfree(sensor_cells);
>> +error:
>> +	kfree(msg);
>> +}
>> +
>>  static int ec_device_probe(struct platform_device *pdev)
>>  {
>>  	int retval = -ENOMEM;
>> @@ -319,6 +437,10 @@ static int ec_device_probe(struct platform_device *pdev)
>>  		goto dev_reg_failed;
>>  	}
>>  
>> +	/* check whether this EC is a sensor hub. */
>> +	if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
>> +		cros_ec_sensors_register(ec);
>> +
>>  	return 0;
>>  
>>  dev_reg_failed:
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 0/4] Add support for cros-ec-sensors
  2016-09-01  7:24             ` Lee Jones
@ 2016-09-03 17:21               ` Jonathan Cameron
  2016-10-18  8:35                 ` Enric Balletbo Serra
  0 siblings, 1 reply; 30+ messages in thread
From: Jonathan Cameron @ 2016-09-03 17:21 UTC (permalink / raw)
  To: Lee Jones
  Cc: Enric Balletbo i Serra, linux-kernel, linux-iio, Olof Johansson,
	Hartmut Knaack, Lars-Peter Clausen, Peter Meerwald-Stadler,
	Guenter Roeck, Gwendal Grignou

On 01/09/16 08:24, Lee Jones wrote:
>>>>>>> Given this dependency I'm assuming the best route for these is via
>>>>>>> the MFD tree...
>>>>>>>
>>>>>>> Lee, shout if you want them to go a different route.
>>>>>>
>>>>>> IIO looks like a more suitable route.  Please provide me with a
>>>>>> pull-request base off of an immutable tag.
>>>>> Hi Lee,
>>>>>
>>>>> As far as I can tell the precursor patch above hasn't gone in your
>>>>> tree yet which leaves me unable to take this through IIO for now.
>>>>>
>>>>> Maybe I'm missing something!
>>>>>
>>>>> Jonathan
>>>>
>>>> Hi Lee,
>>>>
>>>> Any movement on the dependency above?
>>>>
>>>> Last I can find was you adding your ack to it:
>>>> [PATCH v2 1/2] mfd: cros_ec: Add MKBP event support
>>>>
>>>> https://lkml.org/lkml/2016/8/16/423
>>>
>>> Well that's annoying.  Okay, well when I send out the pull-request for
>>> this one, I will include you.
>>>
>>> Actually, better still -- take all of them on one branch and I will
>>> pull from you.  Saves the toing and froing.
>>>
>> Sure. Will probably be the weekend before I get this sorted.
> 
> No rush.
> 
Ah, I see you ended up with an immutable branch of this anyway:
your ib-mfd-input-4.9 branch. 
I'll build an immutable branch on that
ib-iio-mfd-4.9 in iio.git.

Unfortunately I don't have an Ack for patch 4 from Olof yet so 
can't take that and until I do, the rest makes little sense as
it's not enabled.

Jonathan

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 0/4] Add support for cros-ec-sensors
  2016-09-03 17:21               ` Jonathan Cameron
@ 2016-10-18  8:35                 ` Enric Balletbo Serra
  2016-10-18  8:56                   ` Jonathan Cameron
  0 siblings, 1 reply; 30+ messages in thread
From: Enric Balletbo Serra @ 2016-10-18  8:35 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Lee Jones, Enric Balletbo i Serra, linux-kernel, linux-iio,
	Olof Johansson, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Guenter Roeck, Gwendal Grignou

Hi Jonathan,

2016-09-03 19:21 GMT+02:00 Jonathan Cameron <jic23@kernel.org>:
> On 01/09/16 08:24, Lee Jones wrote:
>>>>>>>> Given this dependency I'm assuming the best route for these is via
>>>>>>>> the MFD tree...
>>>>>>>>
>>>>>>>> Lee, shout if you want them to go a different route.
>>>>>>>
>>>>>>> IIO looks like a more suitable route.  Please provide me with a
>>>>>>> pull-request base off of an immutable tag.
>>>>>> Hi Lee,
>>>>>>
>>>>>> As far as I can tell the precursor patch above hasn't gone in your
>>>>>> tree yet which leaves me unable to take this through IIO for now.
>>>>>>
>>>>>> Maybe I'm missing something!
>>>>>>
>>>>>> Jonathan
>>>>>
>>>>> Hi Lee,
>>>>>
>>>>> Any movement on the dependency above?
>>>>>
>>>>> Last I can find was you adding your ack to it:
>>>>> [PATCH v2 1/2] mfd: cros_ec: Add MKBP event support
>>>>>
>>>>> https://lkml.org/lkml/2016/8/16/423
>>>>
>>>> Well that's annoying.  Okay, well when I send out the pull-request for
>>>> this one, I will include you.
>>>>
>>>> Actually, better still -- take all of them on one branch and I will
>>>> pull from you.  Saves the toing and froing.
>>>>
>>> Sure. Will probably be the weekend before I get this sorted.
>>
>> No rush.
>>
> Ah, I see you ended up with an immutable branch of this anyway:
> your ib-mfd-input-4.9 branch.
> I'll build an immutable branch on that
> ib-iio-mfd-4.9 in iio.git.
>

Nice, I just saw that the dependencies for this patch series are
already in mainline, thanks.

I don't see the patches in your iio tree, need I to rebase the patch
series on top of mainline and send v5 or you are already taking care
about it?

Cheers,
  Enric.


> Unfortunately I don't have an Ack for patch 4 from Olof yet so
> can't take that and until I do, the rest makes little sense as
> it's not enabled.
>
> Jonathan
>
>

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 0/4] Add support for cros-ec-sensors
  2016-10-18  8:35                 ` Enric Balletbo Serra
@ 2016-10-18  8:56                   ` Jonathan Cameron
  2016-10-22 17:48                     ` Olof Johansson
  2016-10-22 17:49                     ` Olof Johansson
  0 siblings, 2 replies; 30+ messages in thread
From: Jonathan Cameron @ 2016-10-18  8:56 UTC (permalink / raw)
  To: Enric Balletbo Serra, Jonathan Cameron
  Cc: Lee Jones, Enric Balletbo i Serra, linux-kernel, linux-iio,
	Olof Johansson, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Guenter Roeck, Gwendal Grignou



On 18 October 2016 09:35:06 BST, Enric Balletbo Serra <eballetbo@gmail.com> wrote:
>Hi Jonathan,
>
>2016-09-03 19:21 GMT+02:00 Jonathan Cameron <jic23@kernel.org>:
>> On 01/09/16 08:24, Lee Jones wrote:
>>>>>>>>> Given this dependency I'm assuming the best route for these is
>via
>>>>>>>>> the MFD tree...
>>>>>>>>>
>>>>>>>>> Lee, shout if you want them to go a different route.
>>>>>>>>
>>>>>>>> IIO looks like a more suitable route.  Please provide me with a
>>>>>>>> pull-request base off of an immutable tag.
>>>>>>> Hi Lee,
>>>>>>>
>>>>>>> As far as I can tell the precursor patch above hasn't gone in
>your
>>>>>>> tree yet which leaves me unable to take this through IIO for
>now.
>>>>>>>
>>>>>>> Maybe I'm missing something!
>>>>>>>
>>>>>>> Jonathan
>>>>>>
>>>>>> Hi Lee,
>>>>>>
>>>>>> Any movement on the dependency above?
>>>>>>
>>>>>> Last I can find was you adding your ack to it:
>>>>>> [PATCH v2 1/2] mfd: cros_ec: Add MKBP event support
>>>>>>
>>>>>> https://lkml.org/lkml/2016/8/16/423
>>>>>
>>>>> Well that's annoying.  Okay, well when I send out the pull-request
>for
>>>>> this one, I will include you.
>>>>>
>>>>> Actually, better still -- take all of them on one branch and I
>will
>>>>> pull from you.  Saves the toing and froing.
>>>>>
>>>> Sure. Will probably be the weekend before I get this sorted.
>>>
>>> No rush.
>>>
>> Ah, I see you ended up with an immutable branch of this anyway:
>> your ib-mfd-input-4.9 branch.
>> I'll build an immutable branch on that
>> ib-iio-mfd-4.9 in iio.git.
>>
>
>Nice, I just saw that the dependencies for this patch series are
>already in mainline, thanks.
>
>I don't see the patches in your iio tree, need I to rebase the patch
>series on top of mainline and send v5 or you are already taking care
>about it?
>
>Cheers,
>  Enric.
>
>
>> Unfortunately I don't have an Ack for patch 4 from Olof yet so
>> can't take that and until I do, the rest makes little sense as
>> it's not enabled.
Still looking for an Ack from Olof I think...

Perhaps pm him to get him to take a look.
I doubt much reading is needed but feel free to confirm that!

Jonathan
>>
>> Jonathan
>>
>>

-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 0/4] Add support for cros-ec-sensors
  2016-10-18  8:56                   ` Jonathan Cameron
@ 2016-10-22 17:48                     ` Olof Johansson
  2016-10-22 17:49                     ` Olof Johansson
  1 sibling, 0 replies; 30+ messages in thread
From: Olof Johansson @ 2016-10-22 17:48 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Enric Balletbo Serra, Jonathan Cameron, Lee Jones,
	Enric Balletbo i Serra, linux-kernel, linux-iio, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Guenter Roeck,
	Gwendal Grignou, Benson Leung

[-- Attachment #1: Type: text/plain, Size: 2609 bytes --]

On Tue, Oct 18, 2016 at 1:56 AM, Jonathan Cameron <
jic23@jic23.retrosnub.co.uk> wrote:

>
>
> On 18 October 2016 09:35:06 BST, Enric Balletbo Serra <eballetbo@gmail.com>
> wrote:
> >Hi Jonathan,
> >
> >2016-09-03 19:21 GMT+02:00 Jonathan Cameron <jic23@kernel.org>:
> >> On 01/09/16 08:24, Lee Jones wrote:
> >>>>>>>>> Given this dependency I'm assuming the best route for these is
> >via
> >>>>>>>>> the MFD tree...
> >>>>>>>>>
> >>>>>>>>> Lee, shout if you want them to go a different route.
> >>>>>>>>
> >>>>>>>> IIO looks like a more suitable route.  Please provide me with a
> >>>>>>>> pull-request base off of an immutable tag.
> >>>>>>> Hi Lee,
> >>>>>>>
> >>>>>>> As far as I can tell the precursor patch above hasn't gone in
> >your
> >>>>>>> tree yet which leaves me unable to take this through IIO for
> >now.
> >>>>>>>
> >>>>>>> Maybe I'm missing something!
> >>>>>>>
> >>>>>>> Jonathan
> >>>>>>
> >>>>>> Hi Lee,
> >>>>>>
> >>>>>> Any movement on the dependency above?
> >>>>>>
> >>>>>> Last I can find was you adding your ack to it:
> >>>>>> [PATCH v2 1/2] mfd: cros_ec: Add MKBP event support
> >>>>>>
> >>>>>> https://lkml.org/lkml/2016/8/16/423
> >>>>>
> >>>>> Well that's annoying.  Okay, well when I send out the pull-request
> >for
> >>>>> this one, I will include you.
> >>>>>
> >>>>> Actually, better still -- take all of them on one branch and I
> >will
> >>>>> pull from you.  Saves the toing and froing.
> >>>>>
> >>>> Sure. Will probably be the weekend before I get this sorted.
> >>>
> >>> No rush.
> >>>
> >> Ah, I see you ended up with an immutable branch of this anyway:
> >> your ib-mfd-input-4.9 branch.
> >> I'll build an immutable branch on that
> >> ib-iio-mfd-4.9 in iio.git.
> >>
> >
> >Nice, I just saw that the dependencies for this patch series are
> >already in mainline, thanks.
> >
> >I don't see the patches in your iio tree, need I to rebase the patch
> >series on top of mainline and send v5 or you are already taking care
> >about it?
> >
> >Cheers,
> >  Enric.
> >
> >
> >> Unfortunately I don't have an Ack for patch 4 from Olof yet so
> >> can't take that and until I do, the rest makes little sense as
> >> it's not enabled.
> Still looking for an Ack from Olof I think...
>
> Perhaps pm him to get him to take a look.
> I doubt much reading is needed but feel free to confirm that!
>

Acked-by: Olof Johansson <olof@lixom.net>


Apologies for the severe delays here. I don't have hardware to test on for
this, so I have to rely on others to vouch for functionality. I hope to
transition maintainership to someone that can pay closer attention soon.


-Olof

[-- Attachment #2: Type: text/html, Size: 4318 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 0/4] Add support for cros-ec-sensors
  2016-10-18  8:56                   ` Jonathan Cameron
  2016-10-22 17:48                     ` Olof Johansson
@ 2016-10-22 17:49                     ` Olof Johansson
  1 sibling, 0 replies; 30+ messages in thread
From: Olof Johansson @ 2016-10-22 17:49 UTC (permalink / raw)
  To: Jonathan Cameron
  Cc: Enric Balletbo Serra, Jonathan Cameron, Lee Jones,
	Enric Balletbo i Serra, linux-kernel, linux-iio, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Guenter Roeck,
	Gwendal Grignou, Benson Leung

[once more in plain text]


On Tue, Oct 18, 2016 at 1:56 AM, Jonathan Cameron
<jic23@jic23.retrosnub.co.uk> wrote:
>
>
> On 18 October 2016 09:35:06 BST, Enric Balletbo Serra <eballetbo@gmail.com> wrote:
>>Hi Jonathan,
>>
>>2016-09-03 19:21 GMT+02:00 Jonathan Cameron <jic23@kernel.org>:
>>> On 01/09/16 08:24, Lee Jones wrote:
>>>>>>>>>> Given this dependency I'm assuming the best route for these is
>>via
>>>>>>>>>> the MFD tree...
>>>>>>>>>>
>>>>>>>>>> Lee, shout if you want them to go a different route.
>>>>>>>>>
>>>>>>>>> IIO looks like a more suitable route.  Please provide me with a
>>>>>>>>> pull-request base off of an immutable tag.
>>>>>>>> Hi Lee,
>>>>>>>>
>>>>>>>> As far as I can tell the precursor patch above hasn't gone in
>>your
>>>>>>>> tree yet which leaves me unable to take this through IIO for
>>now.
>>>>>>>>
>>>>>>>> Maybe I'm missing something!
>>>>>>>>
>>>>>>>> Jonathan
>>>>>>>
>>>>>>> Hi Lee,
>>>>>>>
>>>>>>> Any movement on the dependency above?
>>>>>>>
>>>>>>> Last I can find was you adding your ack to it:
>>>>>>> [PATCH v2 1/2] mfd: cros_ec: Add MKBP event support
>>>>>>>
>>>>>>> https://lkml.org/lkml/2016/8/16/423
>>>>>>
>>>>>> Well that's annoying.  Okay, well when I send out the pull-request
>>for
>>>>>> this one, I will include you.
>>>>>>
>>>>>> Actually, better still -- take all of them on one branch and I
>>will
>>>>>> pull from you.  Saves the toing and froing.
>>>>>>
>>>>> Sure. Will probably be the weekend before I get this sorted.
>>>>
>>>> No rush.
>>>>
>>> Ah, I see you ended up with an immutable branch of this anyway:
>>> your ib-mfd-input-4.9 branch.
>>> I'll build an immutable branch on that
>>> ib-iio-mfd-4.9 in iio.git.
>>>
>>
>>Nice, I just saw that the dependencies for this patch series are
>>already in mainline, thanks.
>>
>>I don't see the patches in your iio tree, need I to rebase the patch
>>series on top of mainline and send v5 or you are already taking care
>>about it?
>>
>>Cheers,
>>  Enric.
>>
>>
>>> Unfortunately I don't have an Ack for patch 4 from Olof yet so
>>> can't take that and until I do, the rest makes little sense as
>>> it's not enabled.
> Still looking for an Ack from Olof I think...
>
> Perhaps pm him to get him to take a look.
> I doubt much reading is needed but feel free to confirm that!


Acked-by: Olof Johansson <olof@lixom.net>


Apologies for the severe delays here. I don't have hardware to test on
for this, so I have to rely on others to vouch for functionality. I
hope to transition maintainership to someone that can pay closer
attention soon.


-Olof

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 0/4] Add support for cros-ec-sensors
  2016-08-01  9:54 [PATCH v4 0/4] Add support for cros-ec-sensors Enric Balletbo i Serra
                   ` (4 preceding siblings ...)
  2016-08-15 15:24 ` [PATCH v4 0/4] Add support for cros-ec-sensors Jonathan Cameron
@ 2016-10-22 18:47 ` Jonathan Cameron
  5 siblings, 0 replies; 30+ messages in thread
From: Jonathan Cameron @ 2016-10-22 18:47 UTC (permalink / raw)
  To: Enric Balletbo i Serra, linux-kernel, linux-iio
  Cc: Olof Johansson, Lee Jones, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Guenter Roeck, Gwendal Grignou

On 01/08/16 10:54, Enric Balletbo i Serra wrote:
> Hi,
> 
> This is the four patchset to add support for the sensors behind the ChromeOS
> Embedded Controller.
> 
> This version has only the patches to support common functions and 3d
> contiguous sensors like Accelerometers, Gyroscope and Magnetometer that are
> presented by the ChromeOS EC Sensor hub. The patches were tested on an Oak board.
> 
> The code was checked out from the ChromeOS v3.18 tree and forward ported to
> mainline solving all the conflicts and build issues. I splitted the code in
> single patches that have sense by themselves in order to avoid the chances
> to fail.
> 
> Note that the patches depends on this [1] to apply and work.
> 
> [1] https://lkml.org/lkml/2016/7/1/188
OK. All looking good for this with one minor delay.

I need to bring my tree up to date to apply it.  I'll be doing
a pull request to Greg (IIO patches are routed via his staging tree as
we still have quite a few drivers in there and it's awfully convenient).

Once that's pulled I can fast forward and apply this.

Should get this done later this week if there are no hicups in
my pull request.

Jonathan
> 
> Waiting for your reviews and feedback.
> 
> Changes since v3 (requested by Guenter Roeck)
>   - Convert structure to a simple array
>   - Remove PM declarations
>   - Remove unnecessary initializations
>   - cros_ec_sensors_cmd_read_u16: Conversion should only be done if ret >= 0
>   - Remove unnecessary else
>   - Add Reviewed-by tag for two last patches.
> 
> Changes since v2 (requested by Guenter Roeck and Jonhatan Cameron)
>   - Rebased and fix build error.
>   - Include a list of possible values in the description of location attr.
>   - Fix some typos.
>   - Remove id sysfs entry.
>   - Skip filling by zero structure parameters that already zero'd.
>   - Order includes alphabetically.
>   - Propagate error codes.
> 
> Changes since v1 (requested by Peter Meerwald-Stadler and Jonhatan Cameron)
>   - Check kernel-doc documentation and 
>   - Bring some patches together.
>   - Fix some spelling mistakes.
>   - Include ABI documentation.
>   - Be more careful with buffer sizes (sprintf -> snprintf)
>   - Add cros_ec_sensors prefix to all function.
>   - Check return values on some functions.
> 
> Best regards,
> 
> Enric Balletbo i Serra (3):
>   iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC
>     Sensor Hub.
>   iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver
>   platform/chrome: cros_ec_dev - Register cros-ec sensors
> 
> Vincent Palatin (1):
>   platform/chrome: Introduce a new function to check EC features.
> 
>  Documentation/ABI/testing/sysfs-bus-iio-cros-ec    |  18 +
>  drivers/iio/common/Kconfig                         |   1 +
>  drivers/iio/common/Makefile                        |   1 +
>  drivers/iio/common/cros_ec_sensors/Kconfig         |  22 +
>  drivers/iio/common/cros_ec_sensors/Makefile        |   6 +
>  .../iio/common/cros_ec_sensors/cros_ec_sensors.c   | 322 +++++++++++++++
>  .../common/cros_ec_sensors/cros_ec_sensors_core.c  | 450 +++++++++++++++++++++
>  .../common/cros_ec_sensors/cros_ec_sensors_core.h  | 175 ++++++++
>  drivers/platform/chrome/cros_ec_dev.c              | 159 ++++++++
>  include/linux/mfd/cros_ec.h                        |  10 +
>  include/linux/mfd/cros_ec_commands.h               | 183 ++++++++-
>  11 files changed, 1342 insertions(+), 5 deletions(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-cros-ec
>  create mode 100644 drivers/iio/common/cros_ec_sensors/Kconfig
>  create mode 100644 drivers/iio/common/cros_ec_sensors/Makefile
>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 1/4] iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC Sensor Hub.
  2016-09-03 17:07     ` Jonathan Cameron
@ 2016-10-25 17:12       ` Jonathan Cameron
  0 siblings, 0 replies; 30+ messages in thread
From: Jonathan Cameron @ 2016-10-25 17:12 UTC (permalink / raw)
  To: Enric Balletbo i Serra, linux-kernel, linux-iio
  Cc: Olof Johansson, Lee Jones, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Guenter Roeck, Gwendal Grignou

On 03/09/16 18:07, Jonathan Cameron wrote:
> On 15/08/16 16:28, Jonathan Cameron wrote:
>> On 01/08/16 10:54, Enric Balletbo i Serra wrote:
>>> Add the core functions to be able to support the sensors attached behind
>>> the ChromeOS Embedded Controller and used by other IIO cros-ec sensor
>>> drivers.
>>>
>>> The cros_ec_sensor_core driver matches with current driver in ChromeOS
>>> 4.4 tree, so it includes all the fixes at the moment. The support for
>>> this driver was made by Gwendal Grignou. The original patch and all the
>>> fixes has been squashed and rebased on top of mainline.
>>>
>>> Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
>>> Signed-off-by: Guenter Roeck <groeck@chromium.org>
>>> [eballetbo: split, squash and rebase on top of mainline the patches
>>> found in ChromeOS tree]
>>> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
>> Reviewed-by: Jonathan Cameron <jic23@kernel.org>
> Applied to a new branch in IIO for the purpose.
> ib-iio-mfd-4.9
> 
> Not entirely sure which route I'll take to unwinding this to upstream
> so it may go through a merge into iio.git or a separate pull request.
> 
> Will figure that out later!
> 
> Thanks,
Round 2 of trying to merge this :)

There is an unwanted blank line at the the end of the Kconfig.
I've not fixed it as it gets eaten up in the next patch, but thought
I'd point it out at least ;)

Jonathan
> 
> Jonathan
>>
>> Thanks,
>>
>> Jonathan
>>> ---
>>>
>>> Changes since v3:
>>>   - Convert structure to a simple array
>>>   - Remove PM declarations
>>>   - Remove unnecessary initializations
>>>   - cros_ec_sensors_cmd_read_u16: Conversion should only be done if ret >= 0
>>>   - Remove unnecessary else
>>>
>>> Changes since v2:
>>>   - Rebased and fix build error.
>>>   - Include a list of possible values in the description of location attr.
>>>   - Fix some typos.
>>>   - Remove id sysfs entry.
>>>
>>> Changes since v1:
>>>   - Check kernel-doc documentation.
>>>   - Bring this in as an when you need it in the rest of the series.
>>>   - Fix some spelling mistakes.
>>>   - Include ABI documentation.
>>>   - Be more careful with buffer sizes (sprintf -> snprintf)
>>>   - Add cros_ec_sensors prefix to all function.
>>>   - Check return values on some functions.
>>>
>>>  Documentation/ABI/testing/sysfs-bus-iio-cros-ec    |  18 +
>>>  drivers/iio/common/Kconfig                         |   1 +
>>>  drivers/iio/common/Makefile                        |   1 +
>>>  drivers/iio/common/cros_ec_sensors/Kconfig         |  14 +
>>>  drivers/iio/common/cros_ec_sensors/Makefile        |   5 +
>>>  .../common/cros_ec_sensors/cros_ec_sensors_core.c  | 450 +++++++++++++++++++++
>>>  .../common/cros_ec_sensors/cros_ec_sensors_core.h  | 175 ++++++++
>>>  include/linux/mfd/cros_ec.h                        |   9 +
>>>  include/linux/mfd/cros_ec_commands.h               |  99 ++++-
>>>  9 files changed, 767 insertions(+), 5 deletions(-)
>>>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-cros-ec
>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/Kconfig
>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/Makefile
>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
>>>
>>> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-cros-ec b/Documentation/ABI/testing/sysfs-bus-iio-cros-ec
>>> new file mode 100644
>>> index 0000000..297b972
>>> --- /dev/null
>>> +++ b/Documentation/ABI/testing/sysfs-bus-iio-cros-ec
>>> @@ -0,0 +1,18 @@
>>> +What:		/sys/bus/iio/devices/iio:deviceX/calibrate
>>> +Date:		July 2015
>>> +KernelVersion:	4.7
>>> +Contact:	linux-iio@vger.kernel.org
>>> +Description:
>>> +		Writing '1' will perform a FOC (Fast Online Calibration). The
>>> +                corresponding calibration offsets can be read from *_calibbias
>>> +                entries.
>>> +
>>> +What:		/sys/bus/iio/devices/iio:deviceX/location
>>> +Date:		July 2015
>>> +KernelVersion:	4.7
>>> +Contact:	linux-iio@vger.kernel.org
>>> +Description:
>>> +		This attribute returns a string with the physical location where
>>> +                the motion sensor is placed. For example, in a laptop a motion
>>> +                sensor can be located on the base or on the lid. Current valid
>>> +		values are 'base' and 'lid'.
>>> diff --git a/drivers/iio/common/Kconfig b/drivers/iio/common/Kconfig
>>> index 26a6026..e108996 100644
>>> --- a/drivers/iio/common/Kconfig
>>> +++ b/drivers/iio/common/Kconfig
>>> @@ -2,6 +2,7 @@
>>>  # IIO common modules
>>>  #
>>>  
>>> +source "drivers/iio/common/cros_ec_sensors/Kconfig"
>>>  source "drivers/iio/common/hid-sensors/Kconfig"
>>>  source "drivers/iio/common/ms_sensors/Kconfig"
>>>  source "drivers/iio/common/ssp_sensors/Kconfig"
>>> diff --git a/drivers/iio/common/Makefile b/drivers/iio/common/Makefile
>>> index 585da6a..6fa760e 100644
>>> --- a/drivers/iio/common/Makefile
>>> +++ b/drivers/iio/common/Makefile
>>> @@ -7,6 +7,7 @@
>>>  #
>>>  
>>>  # When adding new entries keep the list in alphabetical order
>>> +obj-y += cros_ec_sensors/
>>>  obj-y += hid-sensors/
>>>  obj-y += ms_sensors/
>>>  obj-y += ssp_sensors/
>>> diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig b/drivers/iio/common/cros_ec_sensors/Kconfig
>>> new file mode 100644
>>> index 0000000..24743be
>>> --- /dev/null
>>> +++ b/drivers/iio/common/cros_ec_sensors/Kconfig
>>> @@ -0,0 +1,14 @@
>>> +#
>>> +# Chrome OS Embedded Controller managed sensors library
>>> +#
>>> +config IIO_CROS_EC_SENSORS_CORE
>>> +	tristate "ChromeOS EC Sensors Core"
>>> +	depends on SYSFS && MFD_CROS_EC
>>> +	select IIO_BUFFER
>>> +	select IIO_TRIGGERED_BUFFER
>>> +	help
>>> +	  Base module for the ChromeOS EC Sensors module.
>>> +	  Contains core functions used by other IIO CrosEC sensor
>>> +	  drivers.
>>> +	  Define common attributes and sysfs interrupt handler.
>>> +
>>> diff --git a/drivers/iio/common/cros_ec_sensors/Makefile b/drivers/iio/common/cros_ec_sensors/Makefile
>>> new file mode 100644
>>> index 0000000..95b6901
>>> --- /dev/null
>>> +++ b/drivers/iio/common/cros_ec_sensors/Makefile
>>> @@ -0,0 +1,5 @@
>>> +#
>>> +# Makefile for sensors seen through the ChromeOS EC sensor hub.
>>> +#
>>> +
>>> +obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.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
>>> new file mode 100644
>>> index 0000000..a3be799
>>> --- /dev/null
>>> +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
>>> @@ -0,0 +1,450 @@
>>> +/*
>>> + * cros_ec_sensors_core - Common function for Chrome OS EC sensor driver.
>>> + *
>>> + * Copyright (C) 2016 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.
>>> + */
>>> +
>>> +#include <linux/delay.h>
>>> +#include <linux/device.h>
>>> +#include <linux/iio/buffer.h>
>>> +#include <linux/iio/iio.h>
>>> +#include <linux/iio/kfifo_buf.h>
>>> +#include <linux/iio/trigger_consumer.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/mfd/cros_ec.h>
>>> +#include <linux/mfd/cros_ec_commands.h>
>>> +#include <linux/module.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/sysfs.h>
>>> +#include <linux/platform_device.h>
>>> +
>>> +#include "cros_ec_sensors_core.h"
>>> +
>>> +static char *cros_ec_loc[] = {
>>> +	[MOTIONSENSE_LOC_BASE] = "base",
>>> +	[MOTIONSENSE_LOC_LID] = "lid",
>>> +	[MOTIONSENSE_LOC_MAX] = "unknown",
>>> +};
>>> +
>>> +int cros_ec_sensors_core_init(struct platform_device *pdev,
>>> +			      struct iio_dev *indio_dev,
>>> +			      bool physical_device)
>>> +{
>>> +	struct device *dev = &pdev->dev;
>>> +	struct cros_ec_sensors_core_state *state = iio_priv(indio_dev);
>>> +	struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent);
>>> +	struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
>>> +
>>> +	platform_set_drvdata(pdev, indio_dev);
>>> +
>>> +	state->ec = ec->ec_dev;
>>> +	state->msg = devm_kzalloc(&pdev->dev,
>>> +				max((u16)sizeof(struct ec_params_motion_sense),
>>> +				state->ec->max_response), GFP_KERNEL);
>>> +	if (!state->msg)
>>> +		return -ENOMEM;
>>> +
>>> +	state->resp = (struct ec_response_motion_sense *)state->msg->data;
>>> +
>>> +	mutex_init(&state->cmd_lock);
>>> +
>>> +	/* Set up the host command structure. */
>>> +	state->msg->version = 2;
>>> +	state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
>>> +	state->msg->outsize = sizeof(struct ec_params_motion_sense);
>>> +
>>> +	indio_dev->dev.parent = &pdev->dev;
>>> +	indio_dev->name = pdev->name;
>>> +
>>> +	if (physical_device) {
>>> +		indio_dev->modes = INDIO_DIRECT_MODE;
>>> +
>>> +		state->param.cmd = MOTIONSENSE_CMD_INFO;
>>> +		state->param.info.sensor_num = sensor_platform->sensor_num;
>>> +		if (cros_ec_motion_send_host_cmd(state, 0)) {
>>> +			dev_warn(dev, "Can not access sensor info\n");
>>> +			return -EIO;
>>> +		}
>>> +		state->type = state->resp->info.type;
>>> +		state->loc = state->resp->info.location;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init);
>>> +
>>> +int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *state,
>>> +				 u16 opt_length)
>>> +{
>>> +	int ret;
>>> +
>>> +	if (opt_length)
>>> +		state->msg->insize = min(opt_length, state->ec->max_response);
>>> +	else
>>> +		state->msg->insize = state->ec->max_response;
>>> +
>>> +	memcpy(state->msg->data, &state->param, sizeof(state->param));
>>> +
>>> +	ret = cros_ec_cmd_xfer_status(state->ec, state->msg);
>>> +	if (ret < 0)
>>> +		return -EIO;
>>> +
>>> +	if (ret &&
>>> +	    state->resp != (struct ec_response_motion_sense *)state->msg->data)
>>> +		memcpy(state->resp, state->msg->data, ret);
>>> +
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(cros_ec_motion_send_host_cmd);
>>> +
>>> +static ssize_t cros_ec_sensors_calibrate(struct iio_dev *indio_dev,
>>> +		uintptr_t private, const struct iio_chan_spec *chan,
>>> +		const char *buf, size_t len)
>>> +{
>>> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
>>> +	int ret, i;
>>> +	bool calibrate;
>>> +
>>> +	ret = strtobool(buf, &calibrate);
>>> +	if (ret < 0)
>>> +		return ret;
>>> +	if (!calibrate)
>>> +		return -EINVAL;
>>> +
>>> +	mutex_lock(&st->cmd_lock);
>>> +	st->param.cmd = MOTIONSENSE_CMD_PERFORM_CALIB;
>>> +	ret = cros_ec_motion_send_host_cmd(st, 0);
>>> +	if (ret != 0) {
>>> +		dev_warn(&indio_dev->dev, "Unable to calibrate sensor\n");
>>> +	} else {
>>> +		/* Save values */
>>> +		for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
>>> +			st->calib[i] = st->resp->perform_calib.offset[i];
>>> +	}
>>> +	mutex_unlock(&st->cmd_lock);
>>> +
>>> +	return ret ? ret : len;
>>> +}
>>> +
>>> +static ssize_t cros_ec_sensors_loc(struct iio_dev *indio_dev,
>>> +		uintptr_t private, const struct iio_chan_spec *chan,
>>> +		char *buf)
>>> +{
>>> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
>>> +
>>> +	return snprintf(buf, PAGE_SIZE, "%s\n", cros_ec_loc[st->loc]);
>>> +}
>>> +
>>> +const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[] = {
>>> +	{
>>> +		.name = "calibrate",
>>> +		.shared = IIO_SHARED_BY_ALL,
>>> +		.write = cros_ec_sensors_calibrate
>>> +	},
>>> +	{
>>> +		.name = "location",
>>> +		.shared = IIO_SHARED_BY_ALL,
>>> +		.read = cros_ec_sensors_loc
>>> +	},
>>> +	{ },
>>> +};
>>> +EXPORT_SYMBOL_GPL(cros_ec_sensors_ext_info);
>>> +
>>> +/**
>>> + * cros_ec_sensors_idx_to_reg - convert index into offset in shared memory
>>> + * @st:		pointer to state information for device
>>> + * @idx:	sensor index (should be element of enum sensor_index)
>>> + *
>>> + * Return:	address to read at
>>> + */
>>> +static unsigned int cros_ec_sensors_idx_to_reg(
>>> +					struct cros_ec_sensors_core_state *st,
>>> +					unsigned int idx)
>>> +{
>>> +	/*
>>> +	 * When using LPC interface, only space for 2 Accel and one Gyro.
>>> +	 * First halfword of MOTIONSENSE_TYPE_ACCEL is used by angle.
>>> +	 */
>>> +	if (st->type == MOTIONSENSE_TYPE_ACCEL)
>>> +		return EC_MEMMAP_ACC_DATA + sizeof(u16) *
>>> +			(1 + idx + st->param.info.sensor_num *
>>> +			 CROS_EC_SENSOR_MAX_AXIS);
>>> +
>>> +	return EC_MEMMAP_GYRO_DATA + sizeof(u16) * idx;
>>> +}
>>> +
>>> +static int cros_ec_sensors_cmd_read_u8(struct cros_ec_device *ec,
>>> +				       unsigned int offset, u8 *dest)
>>> +{
>>> +	return ec->cmd_readmem(ec, offset, 1, dest);
>>> +}
>>> +
>>> +static int cros_ec_sensors_cmd_read_u16(struct cros_ec_device *ec,
>>> +					 unsigned int offset, u16 *dest)
>>> +{
>>> +	__le16 tmp;
>>> +	int ret = ec->cmd_readmem(ec, offset, 2, &tmp);
>>> +
>>> +	if (ret >= 0)
>>> +		*dest = le16_to_cpu(tmp);
>>> +
>>> +	return ret;
>>> +}
>>> +
>>> +/**
>>> + * cros_ec_sensors_read_until_not_busy() - read until is not busy
>>> + *
>>> + * @st:	pointer to state information for device
>>> + *
>>> + * Read from EC status byte until it reads not busy.
>>> + * Return: 8-bit status if ok, -errno on failure.
>>> + */
>>> +static int cros_ec_sensors_read_until_not_busy(
>>> +					struct cros_ec_sensors_core_state *st)
>>> +{
>>> +	struct cros_ec_device *ec = st->ec;
>>> +	u8 status;
>>> +	int ret, attempts = 0;
>>> +
>>> +	ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status);
>>> +	if (ret < 0)
>>> +		return ret;
>>> +
>>> +	while (status & EC_MEMMAP_ACC_STATUS_BUSY_BIT) {
>>> +		/* Give up after enough attempts, return error. */
>>> +		if (attempts++ >= 50)
>>> +			return -EIO;
>>> +
>>> +		/* Small delay every so often. */
>>> +		if (attempts % 5 == 0)
>>> +			msleep(25);
>>> +
>>> +		ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS,
>>> +						  &status);
>>> +		if (ret < 0)
>>> +			return ret;
>>> +	}
>>> +
>>> +	return status;
>>> +}
>>> +
>>> +/**
>>> + * read_ec_sensors_data_unsafe() - read acceleration data from EC shared memory
>>> + * @indio_dev:	pointer to IIO device
>>> + * @scan_mask:	bitmap of the sensor indices to scan
>>> + * @data:	location to store data
>>> + *
>>> + * This is the unsafe function for reading the EC data. It does not guarantee
>>> + * that the EC will not modify the data as it is being read in.
>>> + *
>>> + * Return: 0 on success, -errno on failure.
>>> + */
>>> +static int cros_ec_sensors_read_data_unsafe(struct iio_dev *indio_dev,
>>> +			 unsigned long scan_mask, s16 *data)
>>> +{
>>> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
>>> +	struct cros_ec_device *ec = st->ec;
>>> +	unsigned int i;
>>> +	int ret;
>>> +
>>> +	/* Read all sensors enabled in scan_mask. Each value is 2 bytes. */
>>> +	for_each_set_bit(i, &scan_mask, indio_dev->masklength) {
>>> +		ret = cros_ec_sensors_cmd_read_u16(ec,
>>> +					     cros_ec_sensors_idx_to_reg(st, i),
>>> +					     data);
>>> +		if (ret < 0)
>>> +			return ret;
>>> +
>>> +		data++;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev,
>>> +			     unsigned long scan_mask, s16 *data)
>>> +{
>>> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
>>> +	struct cros_ec_device *ec = st->ec;
>>> +	u8 samp_id = 0xff, status = 0;
>>> +	int ret, attempts = 0;
>>> +
>>> +	/*
>>> +	 * Continually read all data from EC until the status byte after
>>> +	 * all reads reflects that the EC is not busy and the sample id
>>> +	 * matches the sample id from before all reads. This guarantees
>>> +	 * that data read in was not modified by the EC while reading.
>>> +	 */
>>> +	while ((status & (EC_MEMMAP_ACC_STATUS_BUSY_BIT |
>>> +			  EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK)) != samp_id) {
>>> +		/* If we have tried to read too many times, return error. */
>>> +		if (attempts++ >= 5)
>>> +			return -EIO;
>>> +
>>> +		/* Read status byte until EC is not busy. */
>>> +		status = cros_ec_sensors_read_until_not_busy(st);
>>> +		if (status < 0)
>>> +			return status;
>>> +
>>> +		/*
>>> +		 * Store the current sample id so that we can compare to the
>>> +		 * sample id after reading the data.
>>> +		 */
>>> +		samp_id = status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK;
>>> +
>>> +		/* Read all EC data, format it, and store it into data. */
>>> +		ret = cros_ec_sensors_read_data_unsafe(indio_dev, scan_mask,
>>> +						       data);
>>> +		if (ret < 0)
>>> +			return ret;
>>> +
>>> +		/* Read status byte. */
>>> +		ret = cros_ec_sensors_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS,
>>> +						  &status);
>>> +		if (ret < 0)
>>> +			return ret;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(cros_ec_sensors_read_lpc);
>>> +
>>> +int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev,
>>> +			     unsigned long scan_mask, s16 *data)
>>> +{
>>> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
>>> +	int ret;
>>> +	unsigned int i;
>>> +
>>> +	/* Read all sensor data through a command. */
>>> +	st->param.cmd = MOTIONSENSE_CMD_DATA;
>>> +	ret = cros_ec_motion_send_host_cmd(st, sizeof(st->resp->data));
>>> +	if (ret != 0) {
>>> +		dev_warn(&indio_dev->dev, "Unable to read sensor data\n");
>>> +		return ret;
>>> +	}
>>> +
>>> +	for_each_set_bit(i, &scan_mask, indio_dev->masklength) {
>>> +		*data = st->resp->data.data[i];
>>> +		data++;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +EXPORT_SYMBOL_GPL(cros_ec_sensors_read_cmd);
>>> +
>>> +irqreturn_t cros_ec_sensors_capture(int irq, void *p)
>>> +{
>>> +	struct iio_poll_func *pf = p;
>>> +	struct iio_dev *indio_dev = pf->indio_dev;
>>> +	struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
>>> +	int ret;
>>> +
>>> +	mutex_lock(&st->cmd_lock);
>>> +
>>> +	/* Clear capture data. */
>>> +	memset(st->samples, 0, indio_dev->scan_bytes);
>>> +
>>> +	/* Read data based on which channels are enabled in scan mask. */
>>> +	ret = st->read_ec_sensors_data(indio_dev,
>>> +				       *(indio_dev->active_scan_mask),
>>> +				       (s16 *)st->samples);
>>> +	if (ret < 0)
>>> +		goto done;
>>> +
>>> +	iio_push_to_buffers_with_timestamp(indio_dev, st->samples,
>>> +					   iio_get_time_ns(indio_dev));
>>> +
>>> +done:
>>> +	/*
>>> +	 * Tell the core we are done with this trigger and ready for the
>>> +	 * next one.
>>> +	 */
>>> +	iio_trigger_notify_done(indio_dev->trig);
>>> +
>>> +	mutex_unlock(&st->cmd_lock);
>>> +
>>> +	return IRQ_HANDLED;
>>> +}
>>> +EXPORT_SYMBOL_GPL(cros_ec_sensors_capture);
>>> +
>>> +int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st,
>>> +			  struct iio_chan_spec const *chan,
>>> +			  int *val, int *val2, long mask)
>>> +{
>>> +	int ret = IIO_VAL_INT;
>>> +
>>> +	switch (mask) {
>>> +	case IIO_CHAN_INFO_SAMP_FREQ:
>>> +		st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
>>> +		st->param.ec_rate.data =
>>> +			EC_MOTION_SENSE_NO_VALUE;
>>> +
>>> +		if (cros_ec_motion_send_host_cmd(st, 0))
>>> +			ret = -EIO;
>>> +		else
>>> +			*val = st->resp->ec_rate.ret;
>>> +		break;
>>> +	case IIO_CHAN_INFO_FREQUENCY:
>>> +		st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
>>> +		st->param.sensor_odr.data =
>>> +			EC_MOTION_SENSE_NO_VALUE;
>>> +
>>> +		if (cros_ec_motion_send_host_cmd(st, 0))
>>> +			ret = -EIO;
>>> +		else
>>> +			*val = st->resp->sensor_odr.ret;
>>> +		break;
>>> +	default:
>>> +		break;
>>> +	}
>>> +
>>> +	return ret;
>>> +}
>>> +EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read);
>>> +
>>> +int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
>>> +			       struct iio_chan_spec const *chan,
>>> +			       int val, int val2, long mask)
>>> +{
>>> +	int ret = 0;
>>> +
>>> +	switch (mask) {
>>> +	case IIO_CHAN_INFO_FREQUENCY:
>>> +		st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
>>> +		st->param.sensor_odr.data = val;
>>> +
>>> +		/* Always roundup, so caller gets at least what it asks for. */
>>> +		st->param.sensor_odr.roundup = 1;
>>> +
>>> +		if (cros_ec_motion_send_host_cmd(st, 0))
>>> +			ret = -EIO;
>>> +		break;
>>> +	case IIO_CHAN_INFO_SAMP_FREQ:
>>> +		st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
>>> +		st->param.ec_rate.data = val;
>>> +
>>> +		if (cros_ec_motion_send_host_cmd(st, 0))
>>> +			ret = -EIO;
>>> +		else
>>> +			st->curr_sampl_freq = val;
>>> +		break;
>>> +	default:
>>> +		ret = -EINVAL;
>>> +		break;
>>> +	}
>>> +	return ret;
>>> +}
>>> +EXPORT_SYMBOL_GPL(cros_ec_sensors_core_write);
>>> +
>>> +MODULE_DESCRIPTION("ChromeOS EC sensor hub core functions");
>>> +MODULE_LICENSE("GPL v2");
>>> diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
>>> new file mode 100644
>>> index 0000000..8bc2ca3
>>> --- /dev/null
>>> +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.h
>>> @@ -0,0 +1,175 @@
>>> +/*
>>> + * ChromeOS EC sensor hub
>>> + *
>>> + * Copyright (C) 2016 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.
>>> + */
>>> +
>>> +#ifndef __CROS_EC_SENSORS_CORE_H
>>> +#define __CROS_EC_SENSORS_CORE_H
>>> +
>>> +#include <linux/irqreturn.h>
>>> +
>>> +enum {
>>> +	CROS_EC_SENSOR_X,
>>> +	CROS_EC_SENSOR_Y,
>>> +	CROS_EC_SENSOR_Z,
>>> +	CROS_EC_SENSOR_MAX_AXIS,
>>> +};
>>> +
>>> +/* EC returns sensor values using signed 16 bit registers */
>>> +#define CROS_EC_SENSOR_BITS 16
>>> +
>>> +/*
>>> + * 4 16 bit channels are allowed.
>>> + * Good enough for current sensors, they use up to 3 16 bit vectors.
>>> + */
>>> +#define CROS_EC_SAMPLE_SIZE  (sizeof(s64) * 2)
>>> +
>>> +/* Minimum sampling period to use when device is suspending */
>>> +#define CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY 1000  /* 1 second */
>>> +
>>> +/**
>>> + * struct cros_ec_sensors_core_state - state data for EC sensors IIO driver
>>> + * @ec:				cros EC device structure
>>> + * @cmd_lock:			lock used to prevent simultaneous access to the
>>> + *				commands.
>>> + * @msg:			cros EC command structure
>>> + * @param:			motion sensor parameters structure
>>> + * @resp:			motion sensor response structure
>>> + * @type:			type of motion sensor
>>> + * @loc:			location where the motion sensor is placed
>>> + * @calib:			calibration parameters. Note that trigger
>>> + *				captured data will always provide the calibrated
>>> + *				data
>>> + * @samples:			static array to hold data from a single capture.
>>> + *				For each channel we need 2 bytes, except for
>>> + *				the timestamp. The timestamp is always last and
>>> + *				is always 8-byte aligned.
>>> + * @read_ec_sensors_data:	function used for accessing sensors values
>>> + * @cuur_sampl_freq:		current sampling period
>>> + */
>>> +struct cros_ec_sensors_core_state {
>>> +	struct cros_ec_device *ec;
>>> +	struct mutex cmd_lock;
>>> +
>>> +	struct cros_ec_command *msg;
>>> +	struct ec_params_motion_sense param;
>>> +	struct ec_response_motion_sense *resp;
>>> +
>>> +	enum motionsensor_type type;
>>> +	enum motionsensor_location loc;
>>> +
>>> +	s16 calib[CROS_EC_SENSOR_MAX_AXIS];
>>> +
>>> +	u8 samples[CROS_EC_SAMPLE_SIZE];
>>> +
>>> +	int (*read_ec_sensors_data)(struct iio_dev *indio_dev,
>>> +				    unsigned long scan_mask, s16 *data);
>>> +
>>> +	int curr_sampl_freq;
>>> +};
>>> +
>>> +/**
>>> + * cros_ec_sensors_read_lpc() - retrieve data from EC shared memory
>>> + * @indio_dev:	pointer to IIO device
>>> + * @scan_mask:	bitmap of the sensor indices to scan
>>> + * @data:	location to store data
>>> + *
>>> + * This is the safe function for reading the EC data. It guarantees that the
>>> + * data sampled was not modified by the EC while being read.
>>> + *
>>> + * Return: 0 on success, -errno on failure.
>>> + */
>>> +int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev, unsigned long scan_mask,
>>> +			     s16 *data);
>>> +
>>> +/**
>>> + * cros_ec_sensors_read_cmd() - retrieve data using the EC command protocol
>>> + * @indio_dev:	pointer to IIO device
>>> + * @scan_mask:	bitmap of the sensor indices to scan
>>> + * @data:	location to store data
>>> + *
>>> + * Return: 0 on success, -errno on failure.
>>> + */
>>> +int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev, unsigned long scan_mask,
>>> +			     s16 *data);
>>> +
>>> +/**
>>> + * cros_ec_sensors_core_init() - basic initialization of the core structure
>>> + * @pdev:		platform device created for the sensors
>>> + * @indio_dev:		iio device structure of the device
>>> + * @physical_device:	true if the device refers to a physical device
>>> + *
>>> + * Return: 0 on success, -errno on failure.
>>> + */
>>> +int cros_ec_sensors_core_init(struct platform_device *pdev,
>>> +			      struct iio_dev *indio_dev, bool physical_device);
>>> +
>>> +/**
>>> + * cros_ec_sensors_capture() - the trigger handler function
>>> + * @irq:	the interrupt number.
>>> + * @p:		a pointer to the poll function.
>>> + *
>>> + * On a trigger event occurring, if the pollfunc is attached then this
>>> + * handler is called as a threaded interrupt (and hence may sleep). It
>>> + * is responsible for grabbing data from the device and pushing it into
>>> + * the associated buffer.
>>> + *
>>> + * Return: IRQ_HANDLED
>>> + */
>>> +irqreturn_t cros_ec_sensors_capture(int irq, void *p);
>>> +
>>> +/**
>>> + * cros_ec_motion_send_host_cmd() - send motion sense host command
>>> + * @st:		pointer to state information for device
>>> + * @opt_length:	optional length to reduce the response size, useful on the data
>>> + *		path. Otherwise, the maximal allowed response size is used
>>> + *
>>> + * When called, the sub-command is assumed to be set in param->cmd.
>>> + *
>>> + * Return: 0 on success, -errno on failure.
>>> + */
>>> +int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *st,
>>> +				 u16 opt_length);
>>> +
>>> +/**
>>> + * cros_ec_sensors_core_read() - function to request a value from the sensor
>>> + * @st:		pointer to state information for device
>>> + * @chan:	channel specification structure table
>>> + * @val:	will contain one element making up the returned value
>>> + * @val2:	will contain another element making up the returned value
>>> + * @mask:	specifies which values to be requested
>>> + *
>>> + * Return:	the type of value returned by the device
>>> + */
>>> +int cros_ec_sensors_core_read(struct cros_ec_sensors_core_state *st,
>>> +			      struct iio_chan_spec const *chan,
>>> +			      int *val, int *val2, long mask);
>>> +
>>> +/**
>>> + * cros_ec_sensors_core_write() - function to write a value to the sensor
>>> + * @st:		pointer to state information for device
>>> + * @chan:	channel specification structure table
>>> + * @val:	first part of value to write
>>> + * @val2:	second part of value to write
>>> + * @mask:	specifies which values to write
>>> + *
>>> + * Return:	the type of value returned by the device
>>> + */
>>> +int cros_ec_sensors_core_write(struct cros_ec_sensors_core_state *st,
>>> +			       struct iio_chan_spec const *chan,
>>> +			       int val, int val2, long mask);
>>> +
>>> +/* List of extended channel specification for all sensors */
>>> +extern const struct iio_chan_spec_ext_info cros_ec_sensors_ext_info[];
>>> +
>>> +#endif  /* __CROS_EC_SENSORS_CORE_H */
>>> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
>>> index d6539c1..7769ea6 100644
>>> --- a/include/linux/mfd/cros_ec.h
>>> +++ b/include/linux/mfd/cros_ec.h
>>> @@ -151,6 +151,15 @@ struct cros_ec_device {
>>>  	int event_size;
>>>  };
>>>  
>>> +/**
>>> + * struct cros_ec_sensor_platform - ChromeOS EC sensor platform information
>>> + *
>>> + * @sensor_num: Id of the sensor, as reported by the EC.
>>> + */
>>> +struct cros_ec_sensor_platform {
>>> +	u8 sensor_num;
>>> +};
>>> +
>>>  /* struct cros_ec_platform - ChromeOS EC platform information
>>>   *
>>>   * @ec_name: name of EC device (e.g. 'cros-ec', 'cros-pd', ...)
>>> diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h
>>> index 76728ff..8826e0f 100644
>>> --- a/include/linux/mfd/cros_ec_commands.h
>>> +++ b/include/linux/mfd/cros_ec_commands.h
>>> @@ -1315,6 +1315,24 @@ enum motionsense_command {
>>>  	 */
>>>  	MOTIONSENSE_CMD_KB_WAKE_ANGLE = 5,
>>>  
>>> +	/*
>>> +	 * Returns a single sensor data.
>>> +	 */
>>> +	MOTIONSENSE_CMD_DATA = 6,
>>> +
>>> +	/*
>>> +	 * Perform low level calibration.. On sensors that support it, ask to
>>> +	 * do offset calibration.
>>> +	 */
>>> +	MOTIONSENSE_CMD_PERFORM_CALIB = 10,
>>> +
>>> +	/*
>>> +	 * Sensor Offset command is a setter/getter command for the offset used
>>> +	 * for calibration. The offsets can be calculated by the host, or via
>>> +	 * PERFORM_CALIB command.
>>> +	 */
>>> +	MOTIONSENSE_CMD_SENSOR_OFFSET = 11,
>>> +
>>>  	/* Number of motionsense sub-commands. */
>>>  	MOTIONSENSE_NUM_CMDS
>>>  };
>>> @@ -1335,12 +1353,18 @@ enum motionsensor_id {
>>>  enum motionsensor_type {
>>>  	MOTIONSENSE_TYPE_ACCEL = 0,
>>>  	MOTIONSENSE_TYPE_GYRO = 1,
>>> +	MOTIONSENSE_TYPE_MAG = 2,
>>> +	MOTIONSENSE_TYPE_PROX = 3,
>>> +	MOTIONSENSE_TYPE_LIGHT = 4,
>>> +	MOTIONSENSE_TYPE_ACTIVITY = 5,
>>> +	MOTIONSENSE_TYPE_MAX
>>>  };
>>>  
>>>  /* List of motion sensor locations. */
>>>  enum motionsensor_location {
>>>  	MOTIONSENSE_LOC_BASE = 0,
>>>  	MOTIONSENSE_LOC_LID = 1,
>>> +	MOTIONSENSE_LOC_MAX,
>>>  };
>>>  
>>>  /* List of motion sensor chips. */
>>> @@ -1361,6 +1385,31 @@ enum motionsensor_chip {
>>>   */
>>>  #define EC_MOTION_SENSE_NO_VALUE -1
>>>  
>>> +#define EC_MOTION_SENSE_INVALID_CALIB_TEMP 0x8000
>>> +
>>> +/* Set Calibration information */
>>> +#define MOTION_SENSE_SET_OFFSET	1
>>> +
>>> +struct ec_response_motion_sensor_data {
>>> +	/* Flags for each sensor. */
>>> +	uint8_t flags;
>>> +	/* Sensor number the data comes from */
>>> +	uint8_t sensor_num;
>>> +	/* Each sensor is up to 3-axis. */
>>> +	union {
>>> +		int16_t             data[3];
>>> +		struct {
>>> +			uint16_t    rsvd;
>>> +			uint32_t    timestamp;
>>> +		} __packed;
>>> +		struct {
>>> +			uint8_t     activity; /* motionsensor_activity */
>>> +			uint8_t     state;
>>> +			int16_t     add_info[2];
>>> +		};
>>> +	};
>>> +} __packed;
>>> +
>>>  struct ec_params_motion_sense {
>>>  	uint8_t cmd;
>>>  	union {
>>> @@ -1378,9 +1427,37 @@ struct ec_params_motion_sense {
>>>  			int16_t data;
>>>  		} ec_rate, kb_wake_angle;
>>>  
>>> +		/* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */
>>> +		struct {
>>> +			uint8_t sensor_num;
>>> +
>>> +			/*
>>> +			 * bit 0: If set (MOTION_SENSE_SET_OFFSET), set
>>> +			 * the calibration information in the EC.
>>> +			 * If unset, just retrieve calibration information.
>>> +			 */
>>> +			uint16_t flags;
>>> +
>>> +			/*
>>> +			 * Temperature at calibration, in units of 0.01 C
>>> +			 * 0x8000: invalid / unknown.
>>> +			 * 0x0: 0C
>>> +			 * 0x7fff: +327.67C
>>> +			 */
>>> +			int16_t temp;
>>> +
>>> +			/*
>>> +			 * Offset for calibration.
>>> +			 * Unit:
>>> +			 * Accelerometer: 1/1024 g
>>> +			 * Gyro:          1/1024 deg/s
>>> +			 * Compass:       1/16 uT
>>> +			 */
>>> +			int16_t offset[3];
>>> +		} __packed sensor_offset;
>>> +
>>>  		/* Used for MOTIONSENSE_CMD_INFO. */
>>>  		struct {
>>> -			/* Should be element of enum motionsensor_id. */
>>>  			uint8_t sensor_num;
>>>  		} info;
>>>  
>>> @@ -1410,11 +1487,14 @@ struct ec_response_motion_sense {
>>>  			/* Flags representing the motion sensor module. */
>>>  			uint8_t module_flags;
>>>  
>>> -			/* Flags for each sensor in enum motionsensor_id. */
>>> -			uint8_t sensor_flags[EC_MOTION_SENSOR_COUNT];
>>> +			/* Number of sensors managed directly by the EC. */
>>> +			uint8_t sensor_count;
>>>  
>>> -			/* Array of all sensor data. Each sensor is 3-axis. */
>>> -			int16_t data[3*EC_MOTION_SENSOR_COUNT];
>>> +			/*
>>> +			 * Sensor data is truncated if response_max is too small
>>> +			 * for holding all the data.
>>> +			 */
>>> +			struct ec_response_motion_sensor_data sensor[0];
>>>  		} dump;
>>>  
>>>  		/* Used for MOTIONSENSE_CMD_INFO. */
>>> @@ -1429,6 +1509,9 @@ struct ec_response_motion_sense {
>>>  			uint8_t chip;
>>>  		} info;
>>>  
>>> +		/* Used for MOTIONSENSE_CMD_DATA */
>>> +		struct ec_response_motion_sensor_data data;
>>> +
>>>  		/*
>>>  		 * Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR,
>>>  		 * MOTIONSENSE_CMD_SENSOR_RANGE, and
>>> @@ -1438,6 +1521,12 @@ struct ec_response_motion_sense {
>>>  			/* Current value of the parameter queried. */
>>>  			int32_t ret;
>>>  		} ec_rate, sensor_odr, sensor_range, kb_wake_angle;
>>> +
>>> +		/* Used for MOTIONSENSE_CMD_SENSOR_OFFSET */
>>> +		struct {
>>> +			int16_t temp;
>>> +			int16_t offset[3];
>>> +		} sensor_offset, perform_calib;
>>>  	};
>>>  } __packed;
>>>  
>>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 2/4] iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver
  2016-09-03 17:12     ` Jonathan Cameron
@ 2016-10-25 17:12       ` Jonathan Cameron
  0 siblings, 0 replies; 30+ messages in thread
From: Jonathan Cameron @ 2016-10-25 17:12 UTC (permalink / raw)
  To: Enric Balletbo i Serra, linux-kernel, linux-iio
  Cc: Olof Johansson, Lee Jones, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Guenter Roeck, Gwendal Grignou

On 03/09/16 18:12, Jonathan Cameron wrote:
> On 15/08/16 16:28, Jonathan Cameron wrote:
>> On 01/08/16 10:54, Enric Balletbo i Serra wrote:
>>> Handle 3d contiguous sensors like Accelerometers, Gyroscope and
>>> Magnetometer that are presented by the ChromeOS EC Sensor hub.
>>>
>>> Signed-off-by: Guenter Roeck <groeck@chromium.org>
>>> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
>> Reviewed-by: Jonathan Cameron <jic23@kernel.org>
>>
>> Again, fine if this goes via mfd.
> A bit of white space fun that I cleaned up in the previous patch
> made this interesting to apply but think I got it right
> (there was an extra blank line at the end of the Kconfig)
> 
> Thanks,
> 
> Jonathan
>>
>> Thanks,
>>
>> Jonathan
>>> ---
>>>
>>> Changes since v3:
>>>   - Remove some useless initialitzations as always overwritten.
>>>   - Convert calib structure to a simple array.
>>> Changes since v2:
>>>   - Fix some typos
>>>   - Skip filling by zero structure parameters that already zero'd.
>>>   - Order includes alphabetically.
>>>   - Propagate error codes.
>>> Changes since v1:
>>>   - Fixup multiline comments.
>>>   - Fix some spelling mistakes.
>>>   - Blank line before return statements.
>>>   - Add CROS_EC_SENSORS_ prefix.
>>>
>>>  drivers/iio/common/cros_ec_sensors/Kconfig         |   8 +
>>>  drivers/iio/common/cros_ec_sensors/Makefile        |   1 +
>>>  .../iio/common/cros_ec_sensors/cros_ec_sensors.c   | 322 +++++++++++++++++++++
>>>  3 files changed, 331 insertions(+)
>>>  create mode 100644 drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>>>
>>> diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig b/drivers/iio/common/cros_ec_sensors/Kconfig
>>> index 24743be..980bea2 100644
>>> --- a/drivers/iio/common/cros_ec_sensors/Kconfig
>>> +++ b/drivers/iio/common/cros_ec_sensors/Kconfig
>>> @@ -12,3 +12,11 @@ config IIO_CROS_EC_SENSORS_CORE
>>>  	  drivers.
>>>  	  Define common attributes and sysfs interrupt handler.
>>>  
>>> +config IIO_CROS_EC_SENSORS
>>> +	tristate "ChromeOS EC Contiguous Sensors"
>>> +	select IIO_CROS_EC_SENSORS_CORE
A quick build test showed this was a problem as
IIO_CROS_EC_SENSORS_CORE has some depends lines...

Need to select any of those not forced to be there
by having access to this signal (so should be fine for IIO and SYSFS).

I've fixed up (I think!) - please confirm
(I'll send a note about which branch this is all in shortly)

Jonathan


>>> +	help
>>> +	  Module to handle 3d contiguous sensors like
>>> +	  Accelerometers, Gyroscope and Magnetometer that are
>>> +	  presented by the ChromeOS EC Sensor hub.
>>> +	  Creates an IIO device for each functions.
>>> diff --git a/drivers/iio/common/cros_ec_sensors/Makefile b/drivers/iio/common/cros_ec_sensors/Makefile
>>> index 95b6901..ec716ff 100644
>>> --- a/drivers/iio/common/cros_ec_sensors/Makefile
>>> +++ b/drivers/iio/common/cros_ec_sensors/Makefile
>>> @@ -3,3 +3,4 @@
>>>  #
>>>  
>>>  obj-$(CONFIG_IIO_CROS_EC_SENSORS_CORE) += cros_ec_sensors_core.o
>>> +obj-$(CONFIG_IIO_CROS_EC_SENSORS) += cros_ec_sensors.o
>>> diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>>> new file mode 100644
>>> index 0000000..48edeba
>>> --- /dev/null
>>> +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>>> @@ -0,0 +1,322 @@
>>> +/*
>>> + * cros_ec_sensors - Driver for Chrome OS Embedded Controller sensors.
>>> + *
>>> + * Copyright (C) 2016 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 sensors data. Data access is presented through iio sysfs.
>>> + */
>>> +
>>> +#include <linux/delay.h>
>>> +#include <linux/device.h>
>>> +#include <linux/iio/buffer.h>
>>> +#include <linux/iio/iio.h>
>>> +#include <linux/iio/kfifo_buf.h>
>>> +#include <linux/iio/trigger_consumer.h>
>>> +#include <linux/iio/triggered_buffer.h>
>>> +#include <linux/kernel.h>
>>> +#include <linux/mfd/cros_ec.h>
>>> +#include <linux/mfd/cros_ec_commands.h>
>>> +#include <linux/module.h>
>>> +#include <linux/platform_device.h>
>>> +#include <linux/slab.h>
>>> +#include <linux/sysfs.h>
>>> +
>>> +#include "cros_ec_sensors_core.h"
>>> +
>>> +#define CROS_EC_SENSORS_MAX_CHANNELS 4
>>> +
>>> +/* State data for ec_sensors iio driver. */
>>> +struct cros_ec_sensors_state {
>>> +	/* Shared by all sensors */
>>> +	struct cros_ec_sensors_core_state core;
>>> +
>>> +	struct iio_chan_spec channels[CROS_EC_SENSORS_MAX_CHANNELS];
>>> +};
>>> +
>>> +static int cros_ec_sensors_read(struct iio_dev *indio_dev,
>>> +			  struct iio_chan_spec const *chan,
>>> +			  int *val, int *val2, long mask)
>>> +{
>>> +	struct cros_ec_sensors_state *st = iio_priv(indio_dev);
>>> +	s16 data = 0;
>>> +	s64 val64;
>>> +	int i;
>>> +	int ret = IIO_VAL_INT;
>>> +	int idx = chan->scan_index;
>>> +
>>> +	mutex_lock(&st->core.cmd_lock);
>>> +
>>> +	switch (mask) {
>>> +	case IIO_CHAN_INFO_RAW:
>>> +		ret = st->core.read_ec_sensors_data(indio_dev, 1 << idx, &data);
>>> +		if (ret < 0)
>>> +			break;
>>> +
>>> +		*val = data;
>>> +		break;
>>> +	case IIO_CHAN_INFO_CALIBBIAS:
>>> +		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
>>> +		st->core.param.sensor_offset.flags = 0;
>>> +
>>> +		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
>>> +		if (ret < 0)
>>> +			break;
>>> +
>>> +		/* Save values */
>>> +		for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
>>> +			st->core.calib[i] =
>>> +				st->core.resp->sensor_offset.offset[i];
>>> +
>>> +		*val = st->core.calib[idx];
>>> +		break;
>>> +	case IIO_CHAN_INFO_SCALE:
>>> +		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
>>> +		st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE;
>>> +
>>> +		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
>>> +		if (ret < 0)
>>> +			break;
>>> +
>>> +		val64 = st->core.resp->sensor_range.ret;
>>> +		switch (st->core.type) {
>>> +		case MOTIONSENSE_TYPE_ACCEL:
>>> +			/*
>>> +			 * EC returns data in g, iio exepects m/s^2.
>>> +			 * Do not use IIO_G_TO_M_S_2 to avoid precision loss.
>>> +			 */
>>> +			*val = div_s64(val64 * 980665, 10);
>>> +			*val2 = 10000 << (CROS_EC_SENSOR_BITS - 1);
>>> +			ret = IIO_VAL_FRACTIONAL;
>>> +			break;
>>> +		case MOTIONSENSE_TYPE_GYRO:
>>> +			/*
>>> +			 * EC returns data in dps, iio expects rad/s.
>>> +			 * Do not use IIO_DEGREE_TO_RAD to avoid precision
>>> +			 * loss. Round to the nearest integer.
>>> +			 */
>>> +			*val = div_s64(val64 * 314159 + 9000000ULL, 1000);
>>> +			*val2 = 18000 << (CROS_EC_SENSOR_BITS - 1);
>>> +			ret = IIO_VAL_FRACTIONAL;
>>> +			break;
>>> +		case MOTIONSENSE_TYPE_MAG:
>>> +			/*
>>> +			 * EC returns data in 16LSB / uT,
>>> +			 * iio expects Gauss
>>> +			 */
>>> +			*val = val64;
>>> +			*val2 = 100 << (CROS_EC_SENSOR_BITS - 1);
>>> +			ret = IIO_VAL_FRACTIONAL;
>>> +			break;
>>> +		default:
>>> +			ret = -EINVAL;
>>> +		}
>>> +		break;
>>> +	default:
>>> +		ret = cros_ec_sensors_core_read(&st->core, chan, val, val2,
>>> +						mask);
>>> +		break;
>>> +	}
>>> +	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_state *st = iio_priv(indio_dev);
>>> +	int i;
>>> +	int ret = 0;
>>> +	int idx = chan->scan_index;
>>> +
>>> +	mutex_lock(&st->core.cmd_lock);
>>> +
>>> +	switch (mask) {
>>> +	case IIO_CHAN_INFO_CALIBBIAS:
>>> +		st->core.calib[idx] = val;
>>> +
>>> +		/* Send to EC for each axis, even if not complete */
>>> +		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
>>> +		st->core.param.sensor_offset.flags =
>>> +			MOTION_SENSE_SET_OFFSET;
>>> +		for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
>>> +			st->core.param.sensor_offset.offset[i] =
>>> +				st->core.calib[i];
>>> +		st->core.param.sensor_offset.temp =
>>> +			EC_MOTION_SENSE_INVALID_CALIB_TEMP;
>>> +
>>> +		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
>>> +		break;
>>> +	case IIO_CHAN_INFO_SCALE:
>>> +		if (st->core.type == MOTIONSENSE_TYPE_MAG) {
>>> +			ret = -EINVAL;
>>> +			break;
>>> +		}
>>> +		st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
>>> +		st->core.param.sensor_range.data = val;
>>> +
>>> +		/* Always roundup, so caller gets at least what it asks for. */
>>> +		st->core.param.sensor_range.roundup = 1;
>>> +
>>> +		ret = cros_ec_motion_send_host_cmd(&st->core, 0);
>>> +		break;
>>> +	default:
>>> +		ret = cros_ec_sensors_core_write(
>>> +				&st->core, chan, val, val2, mask);
>>> +		break;
>>> +	}
>>> +
>>> +	mutex_unlock(&st->core.cmd_lock);
>>> +
>>> +	return ret;
>>> +}
>>> +
>>> +static const struct iio_info ec_sensors_info = {
>>> +	.read_raw = &cros_ec_sensors_read,
>>> +	.write_raw = &cros_ec_sensors_write,
>>> +	.driver_module = THIS_MODULE,
>>> +};
>>> +
>>> +static int cros_ec_sensors_probe(struct platform_device *pdev)
>>> +{
>>> +	struct device *dev = &pdev->dev;
>>> +	struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
>>> +	struct cros_ec_device *ec_device;
>>> +	struct iio_dev *indio_dev;
>>> +	struct cros_ec_sensors_state *state;
>>> +	struct iio_chan_spec *channel;
>>> +	int ret, i;
>>> +
>>> +	if (!ec_dev || !ec_dev->ec_dev) {
>>> +		dev_warn(&pdev->dev, "No CROS EC device found.\n");
>>> +		return -EINVAL;
>>> +	}
>>> +	ec_device = ec_dev->ec_dev;
>>> +
>>> +	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state));
>>> +	if (!indio_dev)
>>> +		return -ENOMEM;
>>> +
>>> +	ret = cros_ec_sensors_core_init(pdev, indio_dev, true);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	indio_dev->info = &ec_sensors_info;
>>> +	state = iio_priv(indio_dev);
>>> +	for (channel = state->channels, i = CROS_EC_SENSOR_X;
>>> +	     i < CROS_EC_SENSOR_MAX_AXIS; i++, channel++) {
>>> +		/* Common part */
>>> +		channel->info_mask_separate =
>>> +			BIT(IIO_CHAN_INFO_RAW) |
>>> +			BIT(IIO_CHAN_INFO_CALIBBIAS);
>>> +		channel->info_mask_shared_by_all =
>>> +			BIT(IIO_CHAN_INFO_SCALE) |
>>> +			BIT(IIO_CHAN_INFO_FREQUENCY) |
>>> +			BIT(IIO_CHAN_INFO_SAMP_FREQ);
>>> +		channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
>>> +		channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
>>> +		channel->scan_index = i;
>>> +		channel->ext_info = cros_ec_sensors_ext_info;
>>> +		channel->modified = 1;
>>> +		channel->channel2 = IIO_MOD_X + i;
>>> +		channel->scan_type.sign = 's';
>>> +
>>> +		/* Sensor specific */
>>> +		switch (state->core.type) {
>>> +		case MOTIONSENSE_TYPE_ACCEL:
>>> +			channel->type = IIO_ACCEL;
>>> +			break;
>>> +		case MOTIONSENSE_TYPE_GYRO:
>>> +			channel->type = IIO_ANGL_VEL;
>>> +			break;
>>> +		case MOTIONSENSE_TYPE_MAG:
>>> +			channel->type = IIO_MAGN;
>>> +			break;
>>> +		default:
>>> +			dev_err(&pdev->dev, "Unknown motion sensor\n");
>>> +			return -EINVAL;
>>> +		}
>>> +	}
>>> +
>>> +	/* Timestamp */
>>> +	channel->type = IIO_TIMESTAMP;
>>> +	channel->channel = -1;
>>> +	channel->scan_index = CROS_EC_SENSOR_MAX_AXIS;
>>> +	channel->scan_type.sign = 's';
>>> +	channel->scan_type.realbits = 64;
>>> +	channel->scan_type.storagebits = 64;
>>> +
>>> +	indio_dev->channels = state->channels;
>>> +	indio_dev->num_channels = CROS_EC_SENSORS_MAX_CHANNELS;
>>> +
>>> +	/* There is only enough room for accel and gyro in the io space */
>>> +	if ((state->core.ec->cmd_readmem != NULL) &&
>>> +	    (state->core.type != MOTIONSENSE_TYPE_MAG))
>>> +		state->core.read_ec_sensors_data = cros_ec_sensors_read_lpc;
>>> +	else
>>> +		state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;
>>> +
>>> +	ret = iio_triggered_buffer_setup(indio_dev, NULL,
>>> +					 cros_ec_sensors_capture, NULL);
>>> +	if (ret)
>>> +		return ret;
>>> +
>>> +	ret = iio_device_register(indio_dev);
>>> +	if (ret)
>>> +		goto error_uninit_buffer;
>>> +
>>> +	return 0;
>>> +
>>> +error_uninit_buffer:
>>> +	iio_triggered_buffer_cleanup(indio_dev);
>>> +
>>> +	return ret;
>>> +}
>>> +
>>> +static int cros_ec_sensors_remove(struct platform_device *pdev)
>>> +{
>>> +	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>>> +
>>> +	iio_device_unregister(indio_dev);
>>> +	iio_triggered_buffer_cleanup(indio_dev);
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static const struct platform_device_id cros_ec_sensors_ids[] = {
>>> +	{
>>> +		.name = "cros-ec-accel",
>>> +	},
>>> +	{
>>> +		.name = "cros-ec-gyro",
>>> +	},
>>> +	{
>>> +		.name = "cros-ec-mag",
>>> +	},
>>> +	{ /* sentinel */ }
>>> +};
>>> +MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids);
>>> +
>>> +static struct platform_driver cros_ec_sensors_platform_driver = {
>>> +	.driver = {
>>> +		.name	= "cros-ec-sensors",
>>> +	},
>>> +	.probe		= cros_ec_sensors_probe,
>>> +	.remove		= cros_ec_sensors_remove,
>>> +	.id_table	= cros_ec_sensors_ids,
>>> +};
>>> +module_platform_driver(cros_ec_sensors_platform_driver);
>>> +
>>> +MODULE_DESCRIPTION("ChromeOS EC 3-axis sensors driver");
>>> +MODULE_LICENSE("GPL v2");
>>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 3/4] platform/chrome: Introduce a new function to check EC features.
  2016-08-09 13:59   ` Lee Jones
@ 2016-10-25 17:14     ` Jonathan Cameron
  0 siblings, 0 replies; 30+ messages in thread
From: Jonathan Cameron @ 2016-10-25 17:14 UTC (permalink / raw)
  To: Lee Jones, Enric Balletbo i Serra
  Cc: linux-kernel, linux-iio, Olof Johansson, Hartmut Knaack,
	Lars-Peter Clausen, Peter Meerwald-Stadler, Guenter Roeck,
	Gwendal Grignou, Vincent Palatin, Tomeu Vizoso

On 09/08/16 14:59, Lee Jones wrote:
> On Mon, 01 Aug 2016, Enric Balletbo i Serra wrote:
> 
>> From: Vincent Palatin <vpalatin@chromium.org>
>>
>> Use the EC_CMD_GET_FEATURES message to check the supported features for
>> each MCU.
>>
>> Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
>> [tomeu: adapted to changes in mainline]
>> Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
>> [enric: remove references to USB PD feature and do it more generic]
>> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
>> Reviewed-by: Guenter Roeck <groeck@chromium.org>
>> ---
>>
>> Changes since v3:
>>  - Add Reviewed-by tag.
>>
>>  drivers/platform/chrome/cros_ec_dev.c | 37 +++++++++++++++
>>  include/linux/mfd/cros_ec.h           |  1 +
>>  include/linux/mfd/cros_ec_commands.h  | 84 +++++++++++++++++++++++++++++++++++
> 
> For the MFD changes:
>   Acked-by: Lee Jones <lee.jones@linaro.org>
Applied.  Will send a note out at the end about an immutable branch.

Jonathan
> 
>>  3 files changed, 122 insertions(+)
>>
>> diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c
>> index 8abd80d..7eb5307 100644
>> --- a/drivers/platform/chrome/cros_ec_dev.c
>> +++ b/drivers/platform/chrome/cros_ec_dev.c
>> @@ -87,6 +87,41 @@ exit:
>>  	return ret;
>>  }
>>  
>> +static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
>> +{
>> +	struct cros_ec_command *msg;
>> +	int ret;
>> +
>> +	if (ec->features[0] == -1U && ec->features[1] == -1U) {
>> +		/* features bitmap not read yet */
>> +
>> +		msg = kmalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL);
>> +		if (!msg)
>> +			return -ENOMEM;
>> +
>> +		msg->version = 0;
>> +		msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset;
>> +		msg->insize = sizeof(ec->features);
>> +		msg->outsize = 0;
>> +
>> +		ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
>> +		if (ret < 0 || msg->result != EC_RES_SUCCESS) {
>> +			dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
>> +				 ret, msg->result);
>> +			memset(ec->features, 0, sizeof(ec->features));
>> +		}
>> +
>> +		memcpy(ec->features, msg->data, sizeof(ec->features));
>> +
>> +		dev_dbg(ec->dev, "EC features %08x %08x\n",
>> +			ec->features[0], ec->features[1]);
>> +
>> +		kfree(msg);
>> +	}
>> +
>> +	return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature);
>> +}
>> +
>>  /* Device file ops */
>>  static int ec_device_open(struct inode *inode, struct file *filp)
>>  {
>> @@ -245,6 +280,8 @@ static int ec_device_probe(struct platform_device *pdev)
>>  	ec->ec_dev = dev_get_drvdata(dev->parent);
>>  	ec->dev = dev;
>>  	ec->cmd_offset = ec_platform->cmd_offset;
>> +	ec->features[0] = -1U; /* Not cached yet */
>> +	ec->features[1] = -1U; /* Not cached yet */
>>  	device_initialize(&ec->class_dev);
>>  	cdev_init(&ec->cdev, &fops);
>>  
>> diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
>> index 7769ea6..7f039b2 100644
>> --- a/include/linux/mfd/cros_ec.h
>> +++ b/include/linux/mfd/cros_ec.h
>> @@ -187,6 +187,7 @@ struct cros_ec_dev {
>>  	struct cros_ec_device *ec_dev;
>>  	struct device *dev;
>>  	u16 cmd_offset;
>> +	u32 features[2];
>>  };
>>  
>>  /**
>> diff --git a/include/linux/mfd/cros_ec_commands.h b/include/linux/mfd/cros_ec_commands.h
>> index 8826e0f..1683003 100644
>> --- a/include/linux/mfd/cros_ec_commands.h
>> +++ b/include/linux/mfd/cros_ec_commands.h
>> @@ -713,6 +713,90 @@ struct ec_response_get_set_value {
>>  /* More than one command can use these structs to get/set paramters. */
>>  #define EC_CMD_GSV_PAUSE_IN_S5	0x0c
>>  
>> +/*****************************************************************************/
>> +/* List the features supported by the firmware */
>> +#define EC_CMD_GET_FEATURES  0x0d
>> +
>> +/* Supported features */
>> +enum ec_feature_code {
>> +	/*
>> +	 * This image contains a limited set of features. Another image
>> +	 * in RW partition may support more features.
>> +	 */
>> +	EC_FEATURE_LIMITED = 0,
>> +	/*
>> +	 * Commands for probing/reading/writing/erasing the flash in the
>> +	 * EC are present.
>> +	 */
>> +	EC_FEATURE_FLASH = 1,
>> +	/*
>> +	 * Can control the fan speed directly.
>> +	 */
>> +	EC_FEATURE_PWM_FAN = 2,
>> +	/*
>> +	 * Can control the intensity of the keyboard backlight.
>> +	 */
>> +	EC_FEATURE_PWM_KEYB = 3,
>> +	/*
>> +	 * Support Google lightbar, introduced on Pixel.
>> +	 */
>> +	EC_FEATURE_LIGHTBAR = 4,
>> +	/* Control of LEDs  */
>> +	EC_FEATURE_LED = 5,
>> +	/* Exposes an interface to control gyro and sensors.
>> +	 * The host goes through the EC to access these sensors.
>> +	 * In addition, the EC may provide composite sensors, like lid angle.
>> +	 */
>> +	EC_FEATURE_MOTION_SENSE = 6,
>> +	/* The keyboard is controlled by the EC */
>> +	EC_FEATURE_KEYB = 7,
>> +	/* The AP can use part of the EC flash as persistent storage. */
>> +	EC_FEATURE_PSTORE = 8,
>> +	/* The EC monitors BIOS port 80h, and can return POST codes. */
>> +	EC_FEATURE_PORT80 = 9,
>> +	/*
>> +	 * Thermal management: include TMP specific commands.
>> +	 * Higher level than direct fan control.
>> +	 */
>> +	EC_FEATURE_THERMAL = 10,
>> +	/* Can switch the screen backlight on/off */
>> +	EC_FEATURE_BKLIGHT_SWITCH = 11,
>> +	/* Can switch the wifi module on/off */
>> +	EC_FEATURE_WIFI_SWITCH = 12,
>> +	/* Monitor host events, through for example SMI or SCI */
>> +	EC_FEATURE_HOST_EVENTS = 13,
>> +	/* The EC exposes GPIO commands to control/monitor connected devices. */
>> +	EC_FEATURE_GPIO = 14,
>> +	/* The EC can send i2c messages to downstream devices. */
>> +	EC_FEATURE_I2C = 15,
>> +	/* Command to control charger are included */
>> +	EC_FEATURE_CHARGER = 16,
>> +	/* Simple battery support. */
>> +	EC_FEATURE_BATTERY = 17,
>> +	/*
>> +	 * Support Smart battery protocol
>> +	 * (Common Smart Battery System Interface Specification)
>> +	 */
>> +	EC_FEATURE_SMART_BATTERY = 18,
>> +	/* EC can dectect when the host hangs. */
>> +	EC_FEATURE_HANG_DETECT = 19,
>> +	/* Report power information, for pit only */
>> +	EC_FEATURE_PMU = 20,
>> +	/* Another Cros EC device is present downstream of this one */
>> +	EC_FEATURE_SUB_MCU = 21,
>> +	/* Support USB Power delivery (PD) commands */
>> +	EC_FEATURE_USB_PD = 22,
>> +	/* Control USB multiplexer, for audio through USB port for instance. */
>> +	EC_FEATURE_USB_MUX = 23,
>> +	/* Motion Sensor code has an internal software FIFO */
>> +	EC_FEATURE_MOTION_SENSE_FIFO = 24,
>> +};
>> +
>> +#define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32))
>> +#define EC_FEATURE_MASK_1(event_code) (1UL << (event_code - 32))
>> +struct ec_response_get_features {
>> +	uint32_t flags[2];
>> +} __packed;
>>  
>>  /*****************************************************************************/
>>  /* Flash commands */
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH v4 4/4] platform/chrome: cros_ec_dev - Register cros-ec sensors
  2016-09-03 17:20     ` Jonathan Cameron
@ 2016-10-25 17:27       ` Jonathan Cameron
  0 siblings, 0 replies; 30+ messages in thread
From: Jonathan Cameron @ 2016-10-25 17:27 UTC (permalink / raw)
  To: Enric Balletbo i Serra, linux-kernel, linux-iio
  Cc: Olof Johansson, Lee Jones, Hartmut Knaack, Lars-Peter Clausen,
	Peter Meerwald-Stadler, Guenter Roeck, Gwendal Grignou, Greg KH

On 03/09/16 18:20, Jonathan Cameron wrote:
> On 15/08/16 16:31, Jonathan Cameron wrote:
>> On 01/08/16 10:54, Enric Balletbo i Serra wrote:
>>> Check whether the ChromeOS Embedded Controller is a sensor hub and in
>>> such case issue a command to get the number of sensors and register them
>>> all.
>>>
>>> Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
>>> Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
>>> Reviewed-by: Guenter Roeck <groeck@chromium.org>
> Just realised I don't have an Ack from Olof for these.
> 
> Olof - after much back and forth I'm taking the rest of
> this series via the IIO tree. If you are happy with the below
> then I'll pick this one up.
> 
> There will be an immutable branch needed for dependencies from
> mfd and getting the changes back to them (it's a mess).

Anyhow now applied to an immutable branch of iio.git
ib-iio-mfd-4.9rc1

Lee, up to you whether you want to pull this in or not.
For now only has these 4 patches.

Jonathan

p.s. Greg just a heads up that there will be a merge commit for
this in the next IIO pull request.
> 
> Jonathan
>>> ---
>>>
>>> Changes since v3:
>>>  - Remove Unnecessary ( ) around 'ret < 0'.
>>>  - Add Reviewed-by tag
>>>
>>>  .../iio/common/cros_ec_sensors/cros_ec_sensors.c   |   4 +-
>>>  drivers/platform/chrome/cros_ec_dev.c              | 122 +++++++++++++++++++++
>>>  2 files changed, 124 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>>> index 48edeba..d6c372b 100644
>>> --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>>> +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
>>> @@ -51,7 +51,7 @@ static int cros_ec_sensors_read(struct iio_dev *indio_dev,
>>>  	s16 data = 0;
>>>  	s64 val64;
>>>  	int i;
>>> -	int ret = IIO_VAL_INT;
>>> +	int ret;
>>>  	int idx = chan->scan_index;
>>>  
>>>  	mutex_lock(&st->core.cmd_lock);
>>> @@ -137,7 +137,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
>>>  {
>>>  	struct cros_ec_sensors_state *st = iio_priv(indio_dev);
>>>  	int i;
>>> -	int ret = 0;
>>> +	int ret;
>>>  	int idx = chan->scan_index;
>> *raises eyebrows*
>>
>> Enough said?
>>
>> Was wondering why this patch had strayed into the IIO files.
>>
> I moved this to patch 2.
>>
>>>  
>>>  	mutex_lock(&st->core.cmd_lock);
>>> diff --git a/drivers/platform/chrome/cros_ec_dev.c b/drivers/platform/chrome/cros_ec_dev.c
>>> index 7eb5307..47268ec 100644
>>> --- a/drivers/platform/chrome/cros_ec_dev.c
>>> +++ b/drivers/platform/chrome/cros_ec_dev.c
>>> @@ -18,6 +18,7 @@
>>>   */
>>>  
>>>  #include <linux/fs.h>
>>> +#include <linux/mfd/core.h>
>>>  #include <linux/module.h>
>>>  #include <linux/platform_device.h>
>>>  #include <linux/slab.h>
>>> @@ -265,6 +266,123 @@ static void __remove(struct device *dev)
>>>  	kfree(ec);
>>>  }
>>>  
>>> +static void cros_ec_sensors_register(struct cros_ec_dev *ec)
>>> +{
>>> +	/*
>>> +	 * Issue a command to get the number of sensor reported.
>>> +	 * Build an array of sensors driver and register them all.
>>> +	 */
>>> +	int ret, i, id, sensor_num;
>>> +	struct mfd_cell *sensor_cells;
>>> +	struct cros_ec_sensor_platform *sensor_platforms;
>>> +	int sensor_type[MOTIONSENSE_TYPE_MAX];
>>> +	struct ec_params_motion_sense *params;
>>> +	struct ec_response_motion_sense *resp;
>>> +	struct cros_ec_command *msg;
>>> +
>>> +	msg = kzalloc(sizeof(struct cros_ec_command) +
>>> +		      max(sizeof(*params), sizeof(*resp)), GFP_KERNEL);
>>> +	if (msg == NULL)
>>> +		return;
>>> +
>>> +	msg->version = 2;
>>> +	msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
>>> +	msg->outsize = sizeof(*params);
>>> +	msg->insize = sizeof(*resp);
>>> +
>>> +	params = (struct ec_params_motion_sense *)msg->data;
>>> +	params->cmd = MOTIONSENSE_CMD_DUMP;
>>> +
>>> +	ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
>>> +	if (ret < 0 || msg->result != EC_RES_SUCCESS) {
>>> +		dev_warn(ec->dev, "cannot get EC sensor information: %d/%d\n",
>>> +			 ret, msg->result);
>>> +		goto error;
>>> +	}
>>> +
>>> +	resp = (struct ec_response_motion_sense *)msg->data;
>>> +	sensor_num = resp->dump.sensor_count;
>>> +	/* Allocate 2 extra sensors in case lid angle or FIFO are needed */
>>> +	sensor_cells = kzalloc(sizeof(struct mfd_cell) * (sensor_num + 2),
>>> +			       GFP_KERNEL);
>>> +	if (sensor_cells == NULL)
>>> +		goto error;
>>> +
>>> +	sensor_platforms = kzalloc(sizeof(struct cros_ec_sensor_platform) *
>>> +		  (sensor_num + 1), GFP_KERNEL);
>>> +	if (sensor_platforms == NULL)
>>> +		goto error_platforms;
>>> +
>>> +	memset(sensor_type, 0, sizeof(sensor_type));
>>> +	id = 0;
>>> +	for (i = 0; i < sensor_num; i++) {
>>> +		params->cmd = MOTIONSENSE_CMD_INFO;
>>> +		params->info.sensor_num = i;
>>> +		ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
>>> +		if (ret < 0 || msg->result != EC_RES_SUCCESS) {
>>> +			dev_warn(ec->dev, "no info for EC sensor %d : %d/%d\n",
>>> +				 i, ret, msg->result);
>>> +			continue;
>>> +		}
>>> +		switch (resp->info.type) {
>>> +		case MOTIONSENSE_TYPE_ACCEL:
>>> +			sensor_cells[id].name = "cros-ec-accel";
>>> +			break;
>>> +		case MOTIONSENSE_TYPE_GYRO:
>>> +			sensor_cells[id].name = "cros-ec-gyro";
>>> +			break;
>>> +		case MOTIONSENSE_TYPE_MAG:
>>> +			sensor_cells[id].name = "cros-ec-mag";
>>> +			break;
>>> +		case MOTIONSENSE_TYPE_PROX:
>>> +			sensor_cells[id].name = "cros-ec-prox";
>>> +			break;
>>> +		case MOTIONSENSE_TYPE_LIGHT:
>>> +			sensor_cells[id].name = "cros-ec-light";
>>> +			break;
>>> +		case MOTIONSENSE_TYPE_ACTIVITY:
>>> +			sensor_cells[id].name = "cros-ec-activity";
>>> +			break;
>>> +		default:
>>> +			dev_warn(ec->dev, "unknown type %d\n", resp->info.type);
>>> +			continue;
>>> +		}
>>> +		sensor_platforms[id].sensor_num = i;
>>> +		sensor_cells[id].id = sensor_type[resp->info.type];
>>> +		sensor_cells[id].platform_data = &sensor_platforms[id];
>>> +		sensor_cells[id].pdata_size =
>>> +			sizeof(struct cros_ec_sensor_platform);
>>> +
>>> +		sensor_type[resp->info.type]++;
>>> +		id++;
>>> +	}
>>> +	if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) {
>>> +		sensor_platforms[id].sensor_num = sensor_num;
>>> +
>>> +		sensor_cells[id].name = "cros-ec-angle";
>>> +		sensor_cells[id].id = 0;
>>> +		sensor_cells[id].platform_data = &sensor_platforms[id];
>>> +		sensor_cells[id].pdata_size =
>>> +			sizeof(struct cros_ec_sensor_platform);
>>> +		id++;
>>> +	}
>>> +	if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
>>> +		sensor_cells[id].name = "cros-ec-ring";
>>> +		id++;
>>> +	}
>>> +
>>> +	ret = mfd_add_devices(ec->dev, 0, sensor_cells, id,
>>> +			      NULL, 0, NULL);
>>> +	if (ret)
>>> +		dev_err(ec->dev, "failed to add EC sensors\n");
>>> +
>>> +	kfree(sensor_platforms);
>>> +error_platforms:
>>> +	kfree(sensor_cells);
>>> +error:
>>> +	kfree(msg);
>>> +}
>>> +
>>>  static int ec_device_probe(struct platform_device *pdev)
>>>  {
>>>  	int retval = -ENOMEM;
>>> @@ -319,6 +437,10 @@ static int ec_device_probe(struct platform_device *pdev)
>>>  		goto dev_reg_failed;
>>>  	}
>>>  
>>> +	/* check whether this EC is a sensor hub. */
>>> +	if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE))
>>> +		cros_ec_sensors_register(ec);
>>> +
>>>  	return 0;
>>>  
>>>  dev_reg_failed:
>>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2016-10-25 17:27 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-01  9:54 [PATCH v4 0/4] Add support for cros-ec-sensors Enric Balletbo i Serra
2016-08-01  9:54 ` [PATCH v4 1/4] iio: cros_ec_sensors_core: Add common functions for the ChromeOS EC Sensor Hub Enric Balletbo i Serra
2016-08-01 16:57   ` Guenter Roeck
2016-08-15 15:28   ` Jonathan Cameron
2016-09-03 17:07     ` Jonathan Cameron
2016-10-25 17:12       ` Jonathan Cameron
2016-08-01  9:54 ` [PATCH v4 2/4] iio: cros_ec_sensors: add ChromeOS EC Contiguous Sensors driver Enric Balletbo i Serra
2016-08-15 15:28   ` Jonathan Cameron
2016-09-03 17:12     ` Jonathan Cameron
2016-10-25 17:12       ` Jonathan Cameron
2016-08-01  9:54 ` [PATCH v4 3/4] platform/chrome: Introduce a new function to check EC features Enric Balletbo i Serra
2016-08-09 13:59   ` Lee Jones
2016-10-25 17:14     ` Jonathan Cameron
2016-08-01  9:54 ` [PATCH v4 4/4] platform/chrome: cros_ec_dev - Register cros-ec sensors Enric Balletbo i Serra
2016-08-15 15:31   ` Jonathan Cameron
2016-09-03 17:20     ` Jonathan Cameron
2016-10-25 17:27       ` Jonathan Cameron
2016-08-15 15:24 ` [PATCH v4 0/4] Add support for cros-ec-sensors Jonathan Cameron
2016-08-16 12:49   ` Lee Jones
2016-08-21 19:57     ` Jonathan Cameron
2016-08-29 15:14       ` Jonathan Cameron
2016-08-30  8:57         ` Lee Jones
2016-08-31 20:06           ` Jonathan Cameron
2016-09-01  7:24             ` Lee Jones
2016-09-03 17:21               ` Jonathan Cameron
2016-10-18  8:35                 ` Enric Balletbo Serra
2016-10-18  8:56                   ` Jonathan Cameron
2016-10-22 17:48                     ` Olof Johansson
2016-10-22 17:49                     ` Olof Johansson
2016-10-22 18:47 ` Jonathan Cameron

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.