[PATCH v2 1/2] platform/chrome: Use dev_groups to set device sysfs attributes

2021-04-05 Thread Gwendal Grignou
Instead of manually call sysfs_create_group()/sysfs_remove_group(), set
.dev_groups driver data structure, and let the bus base code create
sysfs attributes.

Fixes: 6fd7f2bbd442 ("mfd / platform: cros_ec: Move device sysfs attributes to 
its own driver")
Cc: sta...@vger.kernel.org
Signed-off-by: Gwendal Grignou 
---
 New in v2.

 drivers/platform/chrome/cros_ec_sysfs.c | 28 +
 1 file changed, 5 insertions(+), 23 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_sysfs.c 
b/drivers/platform/chrome/cros_ec_sysfs.c
index f07eabcf9494c..114b9dbe981e7 100644
--- a/drivers/platform/chrome/cros_ec_sysfs.c
+++ b/drivers/platform/chrome/cros_ec_sysfs.c
@@ -335,34 +335,16 @@ static const struct attribute_group cros_ec_attr_group = {
.is_visible = cros_ec_ctrl_visible,
 };
 
-static int cros_ec_sysfs_probe(struct platform_device *pd)
-{
-   struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
-   struct device *dev = &pd->dev;
-   int ret;
-
-   ret = sysfs_create_group(&ec_dev->class_dev.kobj, &cros_ec_attr_group);
-   if (ret < 0)
-   dev_err(dev, "failed to create attributes. err=%d\n", ret);
-
-   return ret;
-}
-
-static int cros_ec_sysfs_remove(struct platform_device *pd)
-{
-   struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
-
-   sysfs_remove_group(&ec_dev->class_dev.kobj, &cros_ec_attr_group);
-
-   return 0;
-}
+static const struct attribute_group *cros_ec_attr_groups[] = {
+   &cros_ec_attr_group,
+   NULL,
+};
 
 static struct platform_driver cros_ec_sysfs_driver = {
.driver = {
.name = DRV_NAME,
+   .dev_groups = cros_ec_attr_groups,
},
-   .probe = cros_ec_sysfs_probe,
-   .remove = cros_ec_sysfs_remove,
 };
 
 module_platform_driver(cros_ec_sysfs_driver);
-- 
2.31.0.208.g409f899ff0-goog



[PATCH v2 2/2] platform/chrome: Update cros_ec sysfs attributes on sensors discovery

2021-04-05 Thread Gwendal Grignou
When cros_ec_sysfs probe is called before cros_ec_sensorhub probe
routine, the |kb_wake_angle| attribute will not be displayed, even if
there are two accelerometers in the chromebook.

Call sysfs_update_groups() when accelerometers are enumerated if the
cros_ec sysfs attributes groups have already been created.

Fixes: d60ac88a62df ("mfd / platform / iio: cros_ec: Register sensor through 
sensorhub")
Cc: sta...@vger.kernel.org
Signed-off-by: Gwendal Grignou 
---
 Changes in v2:
 Rebase after .dev_groups is used.

 drivers/platform/chrome/cros_ec_sensorhub.c |  6 +-
 drivers/platform/chrome/cros_ec_sysfs.c | 10 ++
 include/linux/platform_data/cros_ec_proto.h |  2 ++
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/chrome/cros_ec_sensorhub.c 
b/drivers/platform/chrome/cros_ec_sensorhub.c
index 9c4af76a9956e..c69fec935fb50 100644
--- a/drivers/platform/chrome/cros_ec_sensorhub.c
+++ b/drivers/platform/chrome/cros_ec_sensorhub.c
@@ -106,8 +106,11 @@ static int cros_ec_sensorhub_register(struct device *dev,
sensor_type[sensorhub->resp->info.type]++;
}
 
-   if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2)
+   if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) {
ec->has_kb_wake_angle = true;
+   if (ec->groups && sysfs_update_groups(&ec->class_dev.kobj, 
ec->groups))
+   dev_warn(dev, "Unable to update cros-ec-sysfs");
+   }
 
if (cros_ec_check_features(ec,
   EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS)) {
diff --git a/drivers/platform/chrome/cros_ec_sysfs.c 
b/drivers/platform/chrome/cros_ec_sysfs.c
index 114b9dbe981e7..b363f70270a38 100644
--- a/drivers/platform/chrome/cros_ec_sysfs.c
+++ b/drivers/platform/chrome/cros_ec_sysfs.c
@@ -340,11 +340,21 @@ static const struct attribute_group 
*cros_ec_attr_groups[] = {
NULL,
 };
 
+static int cros_ec_sysfs_probe(struct platform_device *pd)
+{
+   struct cros_ec_dev *ec_dev = dev_get_drvdata(pd->dev.parent);
+
+   ec_dev->groups = cros_ec_attr_groups;
+
+   return 0;
+}
+
 static struct platform_driver cros_ec_sysfs_driver = {
.driver = {
.name = DRV_NAME,
.dev_groups = cros_ec_attr_groups,
},
+   .probe = cros_ec_sysfs_probe,
 };
 
 module_platform_driver(cros_ec_sysfs_driver);
diff --git a/include/linux/platform_data/cros_ec_proto.h 
b/include/linux/platform_data/cros_ec_proto.h
index 02599687770c5..de940112f53ae 100644
--- a/include/linux/platform_data/cros_ec_proto.h
+++ b/include/linux/platform_data/cros_ec_proto.h
@@ -191,6 +191,7 @@ struct cros_ec_platform {
 /**
  * struct cros_ec_dev - ChromeOS EC device entry point.
  * @class_dev: Device structure used in sysfs.
+ * @groups: sysfs attributes groups for this EC.
  * @ec_dev: cros_ec_device structure to talk to the physical device.
  * @dev: Pointer to the platform device.
  * @debug_info: cros_ec_debugfs structure for debugging information.
@@ -200,6 +201,7 @@ struct cros_ec_platform {
  */
 struct cros_ec_dev {
struct device class_dev;
+   const struct attribute_group **groups;
struct cros_ec_device *ec_dev;
struct device *dev;
struct cros_ec_debugfs *debug_info;
-- 
2.31.0.208.g409f899ff0-goog



[PATCH v2 0/2] platform/chrome: Update cros_ec sysfs attribute after sensors are found

2021-04-05 Thread Gwendal Grignou
Attribute "kb_wake_angle" in /sys//chromeos/cros_ec,
used to set at which angle the embedded controller must wake up the
host, is only set when there is at least 2 accelerometers in the
chromebook.

The detection of these sensors is done in cros_ec_sensorhub, driver that
can be probed after the cros_ec_sysfs driver that sets the attribute.
Therefore, we need to upgrade the cros_ec sysfs groups in the sensorhub
probe routine.

The first patch cleans up cros_ec_sysfs by using .dev_groups driver
field, the second patch fixes the problem.

Gwendal Grignou (2):
  platform/chrome: Use dev_groups to set device sysfs attributes
  platform/chrome: Update cros_ec sysfs attributes on sensors discovery

 drivers/platform/chrome/cros_ec_sensorhub.c |  5 -
 drivers/platform/chrome/cros_ec_sysfs.c | 22 +++--
 include/linux/platform_data/cros_ec_proto.h |  2 ++
 3 files changed, 13 insertions(+), 16 deletions(-)

-- 
2.31.0.208.g409f899ff0-goog



[PATCH] platform/chrome: Update cros_ec sysfs attributes on sensors discovery

2021-04-02 Thread Gwendal Grignou
When cros_ec_sysfs probe is called before cros_ec_sensorhub probe
routine, the |kb_wake_angle| attribute will not be displayed, even if
there are two accelerometers in the chromebook.

Call sysfs_update_group() when accelerometers are enumerated if the
cros_ec sysfs attributes group has already been created.

Fixes: d60ac88a62df ("mfd / platform / iio: cros_ec: Register sensor through 
sensorhub")
Cc: sta...@vger.kernel.org
Signed-off-by: Gwendal Grignou 
---
 drivers/platform/chrome/cros_ec_sensorhub.c | 5 -
 drivers/platform/chrome/cros_ec_sysfs.c | 2 ++
 include/linux/platform_data/cros_ec_proto.h | 2 ++
 3 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/chrome/cros_ec_sensorhub.c 
b/drivers/platform/chrome/cros_ec_sensorhub.c
index 9c4af76a9956e..78085ad362ca8 100644
--- a/drivers/platform/chrome/cros_ec_sensorhub.c
+++ b/drivers/platform/chrome/cros_ec_sensorhub.c
@@ -106,8 +106,11 @@ static int cros_ec_sensorhub_register(struct device *dev,
sensor_type[sensorhub->resp->info.type]++;
}
 
-   if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2)
+   if (sensor_type[MOTIONSENSE_TYPE_ACCEL] >= 2) {
ec->has_kb_wake_angle = true;
+   if (ec->group)
+   sysfs_update_group(&ec->class_dev.kobj, ec->group);
+   }
 
if (cros_ec_check_features(ec,
   EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS)) {
diff --git a/drivers/platform/chrome/cros_ec_sysfs.c 
b/drivers/platform/chrome/cros_ec_sysfs.c
index f07eabcf9494c..3838d5f51aadc 100644
--- a/drivers/platform/chrome/cros_ec_sysfs.c
+++ b/drivers/platform/chrome/cros_ec_sysfs.c
@@ -344,6 +344,8 @@ static int cros_ec_sysfs_probe(struct platform_device *pd)
ret = sysfs_create_group(&ec_dev->class_dev.kobj, &cros_ec_attr_group);
if (ret < 0)
dev_err(dev, "failed to create attributes. err=%d\n", ret);
+   else
+   ec_dev->group = &cros_ec_attr_group;
 
return ret;
 }
diff --git a/include/linux/platform_data/cros_ec_proto.h 
b/include/linux/platform_data/cros_ec_proto.h
index 02599687770c5..4cd06f68bc536 100644
--- a/include/linux/platform_data/cros_ec_proto.h
+++ b/include/linux/platform_data/cros_ec_proto.h
@@ -191,6 +191,7 @@ struct cros_ec_platform {
 /**
  * struct cros_ec_dev - ChromeOS EC device entry point.
  * @class_dev: Device structure used in sysfs.
+ * @group: sysfs attributes group for this EC.
  * @ec_dev: cros_ec_device structure to talk to the physical device.
  * @dev: Pointer to the platform device.
  * @debug_info: cros_ec_debugfs structure for debugging information.
@@ -200,6 +201,7 @@ struct cros_ec_platform {
  */
 struct cros_ec_dev {
struct device class_dev;
+   struct attribute_group *group;
struct cros_ec_device *ec_dev;
struct device *dev;
struct cros_ec_debugfs *debug_info;
-- 
2.31.0.208.g409f899ff0-goog



Re: [PATCH v6 3/3] iio: proximity: Add a ChromeOS EC MKBP proximity driver

2021-03-12 Thread Gwendal Grignou
On Sun, Feb 21, 2021 at 7:53 AM Jonathan Cameron  wrote:
>
> On Sun, 14 Feb 2021 12:39:58 -0800
> Stephen Boyd  wrote:
>
> > Quoting Jonathan Cameron (2021-02-14 04:48:09)
> > > On Wed, 10 Feb 2021 18:46:01 -0800
> > > Stephen Boyd  wrote:
> > >
> > > > Add support for a ChromeOS EC proximity driver that exposes a "front"
> > > > proximity sensor via the IIO subsystem. The EC decides when front
> > > > proximity is near and sets an MKBP switch 'EC_MKBP_FRONT_PROXIMITY' to
> > > > notify the kernel of proximity. Similarly, when proximity detects
> > > > something far away it sets the switch bit to 0. For now this driver
> > > > exposes a single sensor, but it could be expanded in the future via more
> > > > MKBP bits if desired.
> > > >
> > > > Cc: Dmitry Torokhov 
> > > > Cc: Benson Leung 
> > > > Cc: Guenter Roeck 
> > > > Cc: Douglas Anderson 
> > > > Cc: Gwendal Grignou 
> > > > Reviewed-by: Enric Balletbo i Serra 
> > > > Signed-off-by: Stephen Boyd 
> > >
> > > I'm fine with this, but want to leave a little time for others to take
> > > one last look.  We've missed the coming merge window now anyway.
> > >
> > > If I seem to have forgotten this in a couple of weeks, feel free to
> > > give me a bump.
> > >
> >
> > Ok no problem. Gwendal had some comments on v5 that may be applicable
> > here too but I think they mostly mean that the resume handler may not be
> > needed if cros ec is fixed. Having the resume handler shouldn't hurt
> > though unless I missed something. Gwendal?
>
> @Gwendal, could you take a quick glance at this, or alternatively let
> us know if you need more time to get to it.
It will work as is.

Reviewed-by: Gwendal Grignou 
>
> Thanks,
>
> Jonathan
>
>


Re: [PATCH v6 03/24] iio: make use of devm_iio_kfifo_buffer_setup() helper

2021-02-16 Thread Gwendal Grignou
Reviewed-by: Gwendal Grignou 

On Mon, Feb 15, 2021 at 4:11 AM Jonathan Cameron  wrote:
>
> On Mon, 15 Feb 2021 12:40:22 +0200
> Alexandru Ardelean  wrote:
>
> > All drivers that already call devm_iio_kfifo_allocate() &
> > iio_device_attach_buffer() are simple to convert to
> > iio_device_attach_kfifo_buffer() in a single go.
> >
> > This change does that; the unwind order is preserved.
> > What is important, is that the devm_iio_kfifo_buffer_setup() be called
> > after the indio_dev->modes is assigned, to make sure that
> > INDIO_BUFFER_SOFTWARE flag is set and not overridden by the assignment to
> > indio_dev->modes.
> >
> > Also, the INDIO_BUFFER_SOFTWARE has been removed from the assignments of
> > 'indio_dev->modes' because it is set by devm_iio_kfifo_buffer_setup().
> >
> > Signed-off-by: Alexandru Ardelean 
> I 'think' this one is is in the obviously correct category so I've
> applied it to the togreg branch of iio.git and pushed out as testing.
> Note there is still plenty of time for any additional feedback,
> particularly as the CC list was a little sparse.
>
> I've +CCd those who I know are still active maintainers of some
> of the affected drivers.
>
> Jonathan
>
> > ---
> >  drivers/iio/accel/ssp_accel_sensor.c  | 14 ---
> >  drivers/iio/adc/ina2xx-adc.c  | 14 +--
> >  drivers/iio/adc/ti_am335x_adc.c   | 18 ---
> >  .../cros_ec_sensors/cros_ec_sensors_core.c| 13 ---
> >  drivers/iio/gyro/ssp_gyro_sensor.c| 14 ---
> >  drivers/iio/health/max30100.c | 16 ++---
> >  drivers/iio/health/max30102.c | 16 ++---
> >  .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 14 +--
> >  .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 13 +--
> >  .../iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c| 15 +---
> >  drivers/iio/light/acpi-als.c  | 12 --
> >  drivers/iio/light/apds9960.c  | 16 ++---
> >  .../staging/iio/impedance-analyzer/ad5933.c   | 23 ---
> >  13 files changed, 74 insertions(+), 124 deletions(-)
> >
> > diff --git a/drivers/iio/accel/ssp_accel_sensor.c 
> > b/drivers/iio/accel/ssp_accel_sensor.c
> > index 474477e91b5e..04dcb2b657ee 100644
> > --- a/drivers/iio/accel/ssp_accel_sensor.c
> > +++ b/drivers/iio/accel/ssp_accel_sensor.c
> > @@ -96,7 +96,6 @@ static int ssp_accel_probe(struct platform_device *pdev)
> >   int ret;
> >   struct iio_dev *indio_dev;
> >   struct ssp_sensor_data *spd;
> > - struct iio_buffer *buffer;
> >
> >   indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*spd));
> >   if (!indio_dev)
> > @@ -109,18 +108,15 @@ static int ssp_accel_probe(struct platform_device 
> > *pdev)
> >
> >   indio_dev->name = ssp_accel_device_name;
> >   indio_dev->info = &ssp_accel_iio_info;
> > - indio_dev->modes = INDIO_BUFFER_SOFTWARE;
> >   indio_dev->channels = ssp_acc_channels;
> >   indio_dev->num_channels = ARRAY_SIZE(ssp_acc_channels);
> >   indio_dev->available_scan_masks = ssp_accel_scan_mask;
> >
> > - buffer = devm_iio_kfifo_allocate(&pdev->dev);
> > - if (!buffer)
> > - return -ENOMEM;
> > -
> > - iio_device_attach_buffer(indio_dev, buffer);
> > -
> > - indio_dev->setup_ops = &ssp_accel_buffer_ops;
> > + ret = devm_iio_kfifo_buffer_setup(&pdev->dev, indio_dev,
> > +   INDIO_BUFFER_SOFTWARE,
> > +   &ssp_accel_buffer_ops);
> > + if (ret)
> > + return ret;
> >
> >   platform_set_drvdata(pdev, indio_dev);
> >
> > diff --git a/drivers/iio/adc/ina2xx-adc.c b/drivers/iio/adc/ina2xx-adc.c
> > index b573ec60a8b8..2ae54258b221 100644
> > --- a/drivers/iio/adc/ina2xx-adc.c
> > +++ b/drivers/iio/adc/ina2xx-adc.c
> > @@ -953,7 +953,6 @@ static int ina2xx_probe(struct i2c_client *client,
> >  {
> >   struct ina2xx_chip_info *chip;
> >   struct iio_dev *indio_dev;
> > - struct iio_buffer *buffer;
> >   unsigned int val;
> >   enum ina2xx_ids type;
> >   int ret;
> > @@ -1017,7 +1016,7 @@ static int ina2xx_probe(struct i2c_client *client,
> >   return ret;
> >   }
> >
> > - indio_dev->modes = INDIO_DIRECT_MODE | IND

Re: [PATCH v5 3/3] iio: proximity: Add a ChromeOS EC MKBP proximity driver

2021-02-12 Thread Gwendal Grignou
On Wed, Feb 10, 2021 at 9:45 AM Stephen Boyd  wrote:
>
> Quoting Gwendal Grignou (2021-02-10 00:29:45)
> > On Tue, Feb 9, 2021 at 6:51 PM Stephen Boyd  wrote:
> > > +   if (event_type == EC_MKBP_EVENT_SWITCH) {
> > > +   data = container_of(nb, struct 
> > > cros_ec_mkbp_proximity_data,
> > > +   notifier);
> > > +   indio_dev = data->indio_dev;
> > > +
> > > +   mutex_lock(&data->lock);
> > > +   if (data->enabled) {
> > > +   timestamp = ktime_to_ns(ec->last_event_time);
> > Note to self, ktime_to_ns is a noop, but make code cleaner: need to
> > change other access to ec->last_event_time.
> >
> > > +   if (iio_device_get_clock(indio_dev) != 
> > > CLOCK_BOOTTIME)
> > > +   timestamp = iio_get_time_ns(indio_dev);
> > > +   state = 
> > > cros_ec_mkbp_proximity_parse_state(switches);
> >
> > There can be several switches in the EC (lid open, tablet mode, ...),
> > so you can get a switch event even when the proximity switch did not
> > trigger.
> > You can keep the current state and push an iio event only when there
> > is a change. See cbas_ec_notify().
> >
>
> Ah ok. So we'll have to save a state tracking variable and poll the bit
> once at boot and then at resume time?
Required at boot: There is provision in the EC to report switch events
at init mkbp_report_switch_on_init(), but that's only useful when EC
reboots or transitions from RO to RW while AP is up.
No need to peek at resume time: the EC will send a switch event if the
mask has changed during suspend: when the AP is sleeping, EC just put
the event in a FIFO. But looking at the code, the FIFO can get full,
so if no switch events can be added, we lose them - see
mkbp_fifo_add()).
Then cros_ec_report_events_during_suspend() will gather these events.
> What happens to events that happen across suspend/resume? We drop them?
We should not drop them: if the user gets close while the device is
suspended and she resumes it, we should be able to send that info to
the user space.
EV stores switches values in a single field |mkbp_switch_state|, so 2
events that nullify themselves during suspend will be ignored.
> Or we need to inject the last state
> if it's different into IIO with the time of resume?
The notifier routine will be called. Looking at the code, the ec
last_event_time is not updated, I need to fix cros_ec_resume().
>
> > > +   dir = state ? IIO_EV_DIR_FALLING : 
> > > IIO_EV_DIR_RISING;
> > > +
> > > +   ev = IIO_UNMOD_EVENT_CODE(IIO_PROXIMITY, 0,
> > > + IIO_EV_TYPE_THRESH, 
> > > dir);
> > > +   iio_push_event(indio_dev, ev, timestamp);
> > > +   }
> > > +   mutex_unlock(&data->lock);
> > > +   }
> > > +
> > > +   return NOTIFY_OK;
> > > +}
> > > +
> > > +static int cros_ec_mkbp_proximity_read_raw(struct iio_dev *indio_dev,
> > > +  const struct iio_chan_spec *chan, int *val,
> > > +  int *val2, long mask)
> > > +{
> > > +   struct cros_ec_mkbp_proximity_data *data = iio_priv(indio_dev);
> > > +   struct cros_ec_device *ec = data->ec;
> > > +
> > > +   if (chan->type != IIO_PROXIMITY)
> > > +   return -EINVAL;
> > > +
> > > +   switch (mask) {
> >
> > A switch is not necessary here.
>
> Ok.
>
> > > +   case IIO_CHAN_INFO_RAW:


Re: [PATCH v5 3/3] iio: proximity: Add a ChromeOS EC MKBP proximity driver

2021-02-10 Thread Gwendal Grignou
On Tue, Feb 9, 2021 at 6:51 PM Stephen Boyd  wrote:
>
> Add support for a ChromeOS EC proximity driver that exposes a "front"
> proximity sensor via the IIO subsystem. The EC decides when front
> proximity is near and sets an MKBP switch 'EC_MKBP_FRONT_PROXIMITY' to
> notify the kernel of proximity. Similarly, when proximity detects
> something far away it sets the switch bit to 0. For now this driver
> exposes a single sensor, but it could be expanded in the future via more
> MKBP bits if desired.
>
> Cc: Dmitry Torokhov 
> Cc: Benson Leung 
> Cc: Guenter Roeck 
> Cc: Douglas Anderson 
> Cc: Gwendal Grignou 
> Reviewed-by: Enric Balletbo i Serra 
> Signed-off-by: Stephen Boyd 
> ---
>
> Changes from v4:
>  * Dropped of_match_ptr()
>
>  drivers/iio/proximity/Kconfig |  11 +
>  drivers/iio/proximity/Makefile|   1 +
>  .../iio/proximity/cros_ec_mkbp_proximity.c| 242 ++
>  3 files changed, 254 insertions(+)
>  create mode 100644 drivers/iio/proximity/cros_ec_mkbp_proximity.c
>
> diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig
> index 12672a0e89ed..7c7203ca3ac6 100644
> --- a/drivers/iio/proximity/Kconfig
> +++ b/drivers/iio/proximity/Kconfig
> @@ -21,6 +21,17 @@ endmenu
>
>  menu "Proximity and distance sensors"
>
> +config CROS_EC_MKBP_PROXIMITY
> +   tristate "ChromeOS EC MKBP Proximity sensor"
> +   depends on CROS_EC
> +   help
> + Say Y here to enable the proximity sensor implemented via the 
> ChromeOS EC MKBP
> + switches protocol. You must enable one bus option (CROS_EC_I2C or 
> CROS_EC_SPI)
> + to use this.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called cros_ec_mkbp_proximity.
> +
>  config ISL29501
> tristate "Intersil ISL29501 Time Of Flight sensor"
> depends on I2C
> diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile
> index 9c1aca1a8b79..cbdac09433eb 100644
> --- a/drivers/iio/proximity/Makefile
> +++ b/drivers/iio/proximity/Makefile
> @@ -5,6 +5,7 @@
>
>  # When adding new entries keep the list in alphabetical order
>  obj-$(CONFIG_AS3935)   += as3935.o
> +obj-$(CONFIG_CROS_EC_MKBP_PROXIMITY) += cros_ec_mkbp_proximity.o
>  obj-$(CONFIG_ISL29501) += isl29501.o
>  obj-$(CONFIG_LIDAR_LITE_V2)+= pulsedlight-lidar-lite-v2.o
>  obj-$(CONFIG_MB1232)   += mb1232.o
> diff --git a/drivers/iio/proximity/cros_ec_mkbp_proximity.c 
> b/drivers/iio/proximity/cros_ec_mkbp_proximity.c
> new file mode 100644
> index ..2cdaf05c0ec2
> --- /dev/null
> +++ b/drivers/iio/proximity/cros_ec_mkbp_proximity.c
> @@ -0,0 +1,242 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Driver for cros-ec proximity sensor exposed through MKBP switch
> + *
> + * Copyright 2021 Google LLC.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +
> +struct cros_ec_mkbp_proximity_data {
> +   struct cros_ec_device *ec;
> +   struct iio_dev *indio_dev;
> +   struct mutex lock;
> +   struct notifier_block notifier;
> +   bool enabled;
> +};
> +
> +static const struct iio_event_spec cros_ec_mkbp_proximity_events[] = {
> +   {
> +   .type = IIO_EV_TYPE_THRESH,
> +   .dir = IIO_EV_DIR_EITHER,
> +   .mask_separate = BIT(IIO_EV_INFO_ENABLE),
> +   },
> +};
> +
> +static const struct iio_chan_spec cros_ec_mkbp_proximity_chan_spec[] = {
> +   {
> +   .type = IIO_PROXIMITY,
> +   .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> +   .event_spec = cros_ec_mkbp_proximity_events,
> +   .num_event_specs = ARRAY_SIZE(cros_ec_mkbp_proximity_events),
> +   },
> +};
> +
> +static int cros_ec_mkbp_proximity_parse_state(const void *data)
> +{
> +   u32 switches = get_unaligned_le32(data);
> +
> +   return !!(switches & BIT(EC_MKBP_FRONT_PROXIMITY));
> +}
> +
> +static int cros_ec_mkbp_proximity_query(struct cros_ec_device *ec_dev,
> +   int *state)
> +{
> +   struct {
> +   struct cros_ec_command msg;
> +   union {
> +   struct ec_params_mkbp_info params;
> +   u32 switches;
> +   };
> +   } __packed buf = { };
> +   struct ec_pa

Re: [PATCH 3/3] iio: proximity: Add a ChromeOS EC MKBP proximity driver

2021-01-26 Thread Gwendal Grignou
On Mon, Jan 25, 2021 at 3:44 PM Stephen Boyd  wrote:
>
> Quoting Gwendal Grignou (2021-01-25 14:28:46)
> > On Mon, Jan 25, 2021 at 10:52 AM Stephen Boyd  wrote:
> > >
> > > Quoting Gwendal Grignou (2021-01-24 13:41:44)
> > > > On Sun, Jan 24, 2021 at 9:38 AM Jonathan Cameron  
> > > > wrote:
> > > > >
> > > > > On Fri, 22 Jan 2021 14:54:43 -0800
> > > > > Stephen Boyd  wrote:
> > > > > > + if (event_type == EC_MKBP_EVENT_SWITCH) {
> > > > > > + data = container_of(nb, struct 
> > > > > > cros_ec_proximity_data, notifier);
> > > > > > + indio_dev = data->indio_dev;
> > > > > > +
> > > > > > + mutex_lock(&data->lock);
> > > > > > + if (data->enabled) {
> > > > > > + timestamp = iio_get_time_ns(indio_dev);
> > > > For Android, given the timestamp must be time it happens, not reported
> > > > [https://source.android.com/devices/sensors/sensors-hal2] """The
> > > > timestamp must be accurate and correspond to the time at which the
> > > > event physically happened, not the time it was reported.""", consider
> > > > using ec_dev->last_event_time and apply a delta if the iio clock base
> > > > is different from CLOCK_BOOTTIME.
> > >
> > > Ah alright. Is there a reason why cros_ec_get_time_ns() is using
> > > boottime instead of plain ktime_get(), i.e. CLOCK_MONOTONIC? Otherwise I
> > > suppose some sort of cros_ec API should be exposed to convert the
> > > last_event_time to whatever clock base is desired. Does that exist?
> > CLOCK_BOOTTIME was chosen to be Android compliant, as it includes
> > suspend time and match elapsedRealtime() [see
> > https://developer.android.com/reference/android/os/SystemClock#elapsedRealtime()]
> > Chromebook set iio clock reference for all sensor to CLOCK_BOOTTIME
> > (see 
> > https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/mems_setup/configuration.cc#127).
> > In case the iio device clock_id is not CLOCK_BOOTTIME/"bootime", we
> > need to add a delta, like in cros_ec_sensors_push_data()
> > [https://elixir.bootlin.com/linux/latest/source/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c#L210]
>
> The delta may help but what if the clock is adjusted in the time between
> the event is timestamped and this driver reading the timestamp? That
> could lead to some odd behavior where the timestamp is in the future
> because we don't know what sort of adjustment was made, e.g. the
> realtime clock being moved back in time.
>
> I'd rather have a way to request that cros_ec core timestamp the event
> with some clock base that this driver desires,
ec_dev->last_event_time is collected outside of the IIO stack, and can
be used by multiple drivers.

> instead of having to do
> an offset after the fact. For now I'll use ec_dev->last_event_time
> because this is only used on chromeos and that should work until
> userspace is changed, but in the future I think we'll need to have a way
> for this IIO device to be notified when the clock base changes in
> iio_device_set_clock() and then have this driver call into cros_ec to
> request that such a timestamp be made when this event is seen. Or even
> better have a way to request that cros_ec timestamp the event itself on
> the EC side, but I don't know if that's possible.
One way would be use the EC sensor stack that collect such timestamp,
but that would be more firmware changes.

On second thought, to keep it simple and consistent with other IIO
drivers, I suggest to keep using iio_get_time_ns() when the sensor
clock is not CLOCK_BOOTTIME, ec_dev->last_event_time when it is.
>
> > > > > > +static const struct of_device_id cros_ec_proximity_of_match[] = {
> > > > > > + { .compatible = "google,cros-ec-proximity" },
> > > > > > + {}
> > > > > > +};
> > > > > > +MODULE_DEVICE_TABLE(of, cros_ec_proximity_of_match);
> > > > > > +#endif
> > > > > > +
> > > > > > +static struct platform_driver cros_ec_proximity_driver = {
> > > > > > + .driver = {
> > > > > > + .name = "cros-ec-proximity",
> > > > > > + .of_match_table = 
> > > > > > of_match_ptr(cros_ec_proximity_of_match),
> > > > Add a ACPI match table to match.
> > >
> > > I don't have an ACPI system in hand. What should the ACPI table look
> > > like? Can ACPI use the of_match_table logic?
> > AFAIK, ACPI uses .acpi_match_table, see
> > drivers/iio/magnetometer/ak8975.c for a simple example.
>
> Ok. I'm leaning towards punting on this. I don't have an ACPI system to
> test and I don't know what the ACPI match table should have in it. If
> you can tell me what to put in the acpi_match_table then I can add it.


Re: [PATCH 3/3] iio: proximity: Add a ChromeOS EC MKBP proximity driver

2021-01-25 Thread Gwendal Grignou
On Mon, Jan 25, 2021 at 10:52 AM Stephen Boyd  wrote:
>
> Quoting Gwendal Grignou (2021-01-24 13:41:44)
> > On Sun, Jan 24, 2021 at 9:38 AM Jonathan Cameron  wrote:
> > >
> > > On Fri, 22 Jan 2021 14:54:43 -0800
> > > Stephen Boyd  wrote:
> > >
> > > > ---
> > > >  drivers/iio/proximity/Kconfig |  11 +
> > > >  drivers/iio/proximity/Makefile|   1 +
> > > >  drivers/iio/proximity/cros_ec_proximity.c | 252 ++
>
> I suppose I'll change this to cros_ec_mkbp_proximity as well.
>
> > > > diff --git a/drivers/iio/proximity/cros_ec_proximity.c 
> > > > b/drivers/iio/proximity/cros_ec_proximity.c
> > > > new file mode 100644
> > > > index ..a3aef911e3cc
> > > > --- /dev/null
> > > > +++ b/drivers/iio/proximity/cros_ec_proximity.c
> > > > @@ -0,0 +1,252 @@
> [...]
> > > > +
> > > > +static int cros_ec_proximity_query(struct cros_ec_device *ec_dev, int 
> > > > *state)
> > > > +{
> > > > + struct ec_params_mkbp_info *params;
> > > > + struct cros_ec_command *msg;
> > > > + int ret;
> > > > +
> > > > + msg = kzalloc(sizeof(*msg) + max(sizeof(u32), sizeof(*params)),
> > > > +   GFP_KERNEL);
> > >
> > > Given this is known at build time, perhaps better to add it to the
> > > iio_priv() accessed structure and avoid having to handle allocations
> > > separately.
> > As Jonathan said, it can be preallocated in iio private structure. We
> > can also use the stack, given the response size is known beforehand.
> > See cros_ec_cec_set_log_addr() or cros_ec_pwm_get_duty() for example.
>
> I suppose stack is even simpler. I'll try that.
>
> > > > +
> > > > +static int cros_ec_proximity_notify(struct notifier_block *nb,
> > > > +  unsigned long queued_during_suspend, void 
> > > > *_ec)
> > > > +{
> > > > + struct cros_ec_proximity_data *data;
> > > > + struct cros_ec_device *ec = _ec;
> > > > + u8 event_type = ec->event_data.event_type & 
> > > > EC_MKBP_EVENT_TYPE_MASK;
> > > > + void *switches = &ec->event_data.data.switches;
> > > > + struct iio_dev *indio_dev;
> > > > + s64 timestamp;
> > > > + int state, dir;
> > > > + u64 ev;
> > > > +
> > > > + if (event_type == EC_MKBP_EVENT_SWITCH) {
> > > > + data = container_of(nb, struct cros_ec_proximity_data, 
> > > > notifier);
> > > > + indio_dev = data->indio_dev;
> > > > +
> > > > + mutex_lock(&data->lock);
> > > > + if (data->enabled) {
> > > > + timestamp = iio_get_time_ns(indio_dev);
> > For Android, given the timestamp must be time it happens, not reported
> > [https://source.android.com/devices/sensors/sensors-hal2] """The
> > timestamp must be accurate and correspond to the time at which the
> > event physically happened, not the time it was reported.""", consider
> > using ec_dev->last_event_time and apply a delta if the iio clock base
> > is different from CLOCK_BOOTTIME.
>
> Ah alright. Is there a reason why cros_ec_get_time_ns() is using
> boottime instead of plain ktime_get(), i.e. CLOCK_MONOTONIC? Otherwise I
> suppose some sort of cros_ec API should be exposed to convert the
> last_event_time to whatever clock base is desired. Does that exist?
CLOCK_BOOTTIME was chosen to be Android compliant, as it includes
suspend time and match elapsedRealtime() [see
https://developer.android.com/reference/android/os/SystemClock#elapsedRealtime()]
Chromebook set iio clock reference for all sensor to CLOCK_BOOTTIME
(see 
https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/mems_setup/configuration.cc#127).
In case the iio device clock_id is not CLOCK_BOOTTIME/"bootime", we
need to add a delta, like in cros_ec_sensors_push_data()
[https://elixir.bootlin.com/linux/latest/source/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c#L210]
>
> > > > +static int cros_ec_proximity_probe(struct platform_device *pdev)
> > > > +{
> > > > + struct device *dev = &pdev->dev;
> > > > + struct cros_ec_device *ec = dev_get_drvdata(dev->parent);
> > > > + struct iio_dev *indio_dev;
> > > > + struct c

Re: [PATCH 3/3] iio: proximity: Add a ChromeOS EC MKBP proximity driver

2021-01-24 Thread Gwendal Grignou
On Sun, Jan 24, 2021 at 9:38 AM Jonathan Cameron  wrote:
>
> On Fri, 22 Jan 2021 14:54:43 -0800
> Stephen Boyd  wrote:
>
> > Add support for a ChromeOS EC proximity driver that exposes a "front"
> > proximity sensor via the IIO subsystem. The EC decides when front
> > proximity is near and sets an MKBP switch 'EC_MKBP_FRONT_PROXIMITY' to
> > notify the kernel of proximity. Similarly, when proximity detects
> > something far away it sets the switch bit to 0. For now this driver
> > exposes a single sensor, but it could be expanded in the future via more
> > MKBP bits if desired.
> >
> > Cc: Dmitry Torokhov 
> > Cc: Benson Leung 
> > Cc: Guenter Roeck 
> > Cc: Douglas Anderson 
> > Cc: Gwendal Grignou 
> > Signed-off-by: Stephen Boyd 
>
> Hi Stephen,
>
> Looks more or less fine to me.  My main concern is potential confusion
> in naming with the cros_ec_prox_light driver that we already have.
>
> A few other minor bits and bobs inline.
>
> thanks,
>
> Jonathan
>
>
> > ---
> >  drivers/iio/proximity/Kconfig |  11 +
> >  drivers/iio/proximity/Makefile|   1 +
> >  drivers/iio/proximity/cros_ec_proximity.c | 252 ++
> >  3 files changed, 264 insertions(+)
> >  create mode 100644 drivers/iio/proximity/cros_ec_proximity.c
> >
> > diff --git a/drivers/iio/proximity/Kconfig b/drivers/iio/proximity/Kconfig
> > index 12672a0e89ed..35a04e9ede7d 100644
> > --- a/drivers/iio/proximity/Kconfig
> > +++ b/drivers/iio/proximity/Kconfig
> > @@ -21,6 +21,17 @@ endmenu
> >
> >  menu "Proximity and distance sensors"
> >
> > +config CROS_EC_PROXIMITY
> > + tristate "ChromeOS EC MKBP Proximity sensor"
> > + depends on CROS_EC
> > + help
> > +   Say Y here to enable the proximity sensor implemented via the 
> > ChromeOS EC MKBP
> > +   switches protocol. You must enable one bus option (CROS_EC_I2C or 
> > CROS_EC_SPI)
> > +   to use this.
> > +
> > +   To compile this driver as a module, choose M here: the
> > +   module will be called cros_ec_prox.
> > +
> >  config ISL29501
> >   tristate "Intersil ISL29501 Time Of Flight sensor"
> >   depends on I2C
> > diff --git a/drivers/iio/proximity/Makefile b/drivers/iio/proximity/Makefile
> > index 9c1aca1a8b79..b1330dd8e212 100644
> > --- a/drivers/iio/proximity/Makefile
> > +++ b/drivers/iio/proximity/Makefile
> > @@ -5,6 +5,7 @@
> >
> >  # When adding new entries keep the list in alphabetical order
> >  obj-$(CONFIG_AS3935) += as3935.o
> > +obj-$(CONFIG_CROS_EC_PROXIMITY)  += cros_ec_proximity.o
> >  obj-$(CONFIG_ISL29501)   += isl29501.o
> >  obj-$(CONFIG_LIDAR_LITE_V2)  += pulsedlight-lidar-lite-v2.o
> >  obj-$(CONFIG_MB1232) += mb1232.o
> > diff --git a/drivers/iio/proximity/cros_ec_proximity.c 
> > b/drivers/iio/proximity/cros_ec_proximity.c
> > new file mode 100644
> > index ..a3aef911e3cc
> > --- /dev/null
> > +++ b/drivers/iio/proximity/cros_ec_proximity.c
> > @@ -0,0 +1,252 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * Driver for cros-ec proximity sensor exposed through MKBP switch
> > + *
> > + * Copyright 2021 Google LLC.
> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
>
> Slight preference for alphabetical order though keeping specific
> sections separate as done here is fine.
>
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#include 
> > +#include 
> > +
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#include 
> > +
> > +struct cros_ec_proximity_data {
> > + struct cros_ec_device *ec;
> > + struct iio_dev *indio_dev;
> > + struct mutex lock;
> > + struct notifier_block notifier;
> > + bool enabled;
> > +};
> > +
> > +static const struct iio_event_spec cros_ec_prox_events[] = {
> > + {
> > + .type = IIO_EV_TYPE_THRESH,
> > + .dir = IIO_EV_DIR_EITHER,
> > + .mask_separate = BIT(IIO_EV_INFO_ENABLE),
> > + },
> > +};
> > +
> > +static const struct iio_chan_spec cros_ec_prox_chan_spec[] = {
> > + {
> > + .type = IIO_PROXIMITY,
> > + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
> > + .event_spec = cros_ec_prox_events,
&

Re: [PATCH 2/3] dt-bindings: iio: Add cros ec proximity yaml doc

2021-01-24 Thread Gwendal Grignou
On Sun, Jan 24, 2021 at 9:28 AM Jonathan Cameron  wrote:
>
> On Fri, 22 Jan 2021 14:54:42 -0800
> Stephen Boyd  wrote:
>
> > Some cros ECs support a front proximity MKBP event via
> > 'EC_MKBP_FRONT_PROXIMITY'. Add a DT binding to document this feature via
> > a node that is a child of the main cros_ec device node. Devices that
> > have this ability will describe this in firmware.
> >
> > Cc: Dmitry Torokhov 
> > Cc: Benson Leung 
> > Cc: Guenter Roeck 
> > Cc: Douglas Anderson 
> > Cc: Gwendal Grignou 
> > Cc: 
> > Cc: Rob Herring 
> > Signed-off-by: Stephen Boyd 
> > ---
> >  .../proximity/google,cros-ec-proximity.yaml   | 37 +++
> >  1 file changed, 37 insertions(+)
> >  create mode 100644 
> > Documentation/devicetree/bindings/iio/proximity/google,cros-ec-proximity.yaml
> >
> > diff --git 
> > a/Documentation/devicetree/bindings/iio/proximity/google,cros-ec-proximity.yaml
> >  
> > b/Documentation/devicetree/bindings/iio/proximity/google,cros-ec-proximity.yaml
> > new file mode 100644
> > index ..c0a34bdfe4fd
> > --- /dev/null
> > +++ 
> > b/Documentation/devicetree/bindings/iio/proximity/google,cros-ec-proximity.yaml
> > @@ -0,0 +1,37 @@
> > +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +
> > +$id: 
> > http://devicetree.org/schemas/iio/proximity/google,cros-ec-proximity.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: ChromeOS EC MKBP Proximity Sensor
> > +
> > +maintainers:
> > +  - Stephen Boyd 
> > +  - Benson Leung 
> > +  - Enric Balletbo i Serra 
> > +
> > +description: |
> > +  Google's ChromeOS EC sometimes has the ability to detect user proximity.
> > +  This is implemented on the EC as near/far logic and exposed to the OS
> > +  via an MKBP switch bit.
> > +
> > +properties:
> > +  compatible:
> > +const: google,cros-ec-proximity
Given we have proximity detection in cros_ec via specific sensor (si
1141) or algorithm (on-body/off-body via
MOTIONSENSE_ACTIVITY_BODY_DETECTION), can we name the property
cros-ec-mkbp-proximity?
> > +
> > +  label:
> > +description: Name for proximity sensor
> > +
> > +required:
> > +  - compatible
> > +
> > +unevaluatedProperties: false
> > +
> > +examples:
> > +  - |
> > +proximity {
>
> Can we at least have the example making it clear this is a child of the
> cros_ec device?
>
> > +compatible = "google,cros-ec-proximity";
> > +label = "proximity-wifi-lte";
> > +};
>


Re: [PATCH v4 2/2] mfd: cros_ec: Add peripheral device charger

2021-01-23 Thread Gwendal Grignou
On Sat, Jan 23, 2021 at 7:54 AM Daisuke Nojiri  wrote:
>
> This patch adds a cell entry for PCHG (Peripheral CHarGer). PCHG is a
> framework managing power supplies for peripheral devices.
>
> Signed-off-by: Daisuke Nojiri 
> Acked-for-MFD-by: Lee Jones 
> ---
> v1->v2
> * None
> v2->v3
> * None
> v3->v4
> * None
> ---
>  drivers/mfd/cros_ec_dev.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
> index 6135321592b76c..f3bc1cb6891ba5 100644
> --- a/drivers/mfd/cros_ec_dev.c
> +++ b/drivers/mfd/cros_ec_dev.c
> @@ -116,6 +116,7 @@ static const struct mfd_cell cros_ec_platform_cells[] = {
> { .name = "cros-ec-pd-sysfs" },
> { .name = "cros-ec-sysfs", },
> { .name = "cros-ec-pd-update", },
Will not merge upstream, "cros-ec-pd-update" has not been upstreamed yet.
> +   { .name = "cros-ec-pchg", },
In the other patch, you said the driver probe routine will be called
when the feature is supported. For every EC, even older one, these
drivers are always called. If there is a feature flag in the EC (see
ec_feature_code), you can use cros_subdevices instead.
>  };
>
>  static const struct mfd_cell cros_ec_vbc_cells[] = {
> --
> 2.30.0.280.ga3ce27912f-goog
>

Reviewed-by: Gwendal Grignou 


Re: [PATCH v4 1/2] power: supply: PCHG: Peripheral device charger

2021-01-23 Thread Gwendal Grignou
On Sat, Jan 23, 2021 at 7:53 AM Daisuke Nojiri  wrote:
>
> This patch adds a driver for PCHG (Peripheral CHarGer). PCHG is a
> framework managing power supplies for peripheral devices.
>
> This driver creates a sysfs node for each peripheral charge port:
>
> /sys/class/power_supply/PCHGn
>
> where  is the index of a charge port.
>
> For example, when a stylus is connected to a NFC/WLC port, the node
> prints:
>
> /sys/class/power_supply/PCHG0/
> capacity=50
> scope=Device
> status=Charging
> type=Battery
>
> Signed-off-by: Daisuke Nojiri 
> ---
> v1 -> v2
> * Separate mfd/cros_ec_dev.c
> * Make CONFIG_CHARGER_CROS_PCHG default to CONFIG_MFD_CROS_EC_DEV
> v2 -> v3
> * Return POWER_SUPPLY_SCOPE_DEVICE for POWER_SUPPLY_PROP_SCOPE
> * POWER_SUPPLY_TYPE_WIRELESS -> POWER_SUPPLY_TYPE_BATTERY
> v3 -> v4
> * Return NOTIFY_DONE when a non-host event is notified.
> ---
>  drivers/power/supply/Kconfig  |  10 +
>  drivers/power/supply/Makefile |   1 +
>  .../power/supply/cros_peripheral_charger.c| 350 ++
>  .../linux/platform_data/cros_ec_commands.h|  48 +++
>  4 files changed, 409 insertions(+)
>  create mode 100644 drivers/power/supply/cros_peripheral_charger.c
>
> diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig
> index eec646c568b7be..407f9fbbc2bb50 100644
> --- a/drivers/power/supply/Kconfig
> +++ b/drivers/power/supply/Kconfig
> @@ -714,6 +714,16 @@ config CHARGER_CROS_USBPD
>   what is connected to USB PD ports from the EC and converts
>   that into power_supply properties.
>
> +config CHARGER_CROS_PCHG
> +   tristate "ChromeOS EC based peripheral charger"
> +   depends on MFD_CROS_EC_DEV
> +   default MFD_CROS_EC_DEV
> +   help
> + Say Y here to enable ChromeOS EC based peripheral charge driver.
> + This driver gets various information about the devices connected to
> + the peripheral charge ports from the EC and converts that into
> + power_supply properties.
> +
>  config CHARGER_SC2731
> tristate "Spreadtrum SC2731 charger driver"
> depends on MFD_SC27XX_PMIC || COMPILE_TEST
> diff --git a/drivers/power/supply/Makefile b/drivers/power/supply/Makefile
> index dd4b86318cd9bd..5263472a64809b 100644
> --- a/drivers/power/supply/Makefile
> +++ b/drivers/power/supply/Makefile
> @@ -91,6 +91,7 @@ obj-$(CONFIG_CHARGER_TPS65217)+= tps65217_charger.o
>  obj-$(CONFIG_AXP288_FUEL_GAUGE) += axp288_fuel_gauge.o
>  obj-$(CONFIG_AXP288_CHARGER)   += axp288_charger.o
>  obj-$(CONFIG_CHARGER_CROS_USBPD)   += cros_usbpd-charger.o
> +obj-$(CONFIG_CHARGER_CROS_PCHG)+= cros_peripheral_charger.o
>  obj-$(CONFIG_CHARGER_SC2731)   += sc2731_charger.o
>  obj-$(CONFIG_FUEL_GAUGE_SC27XX)+= sc27xx_fuel_gauge.o
>  obj-$(CONFIG_CHARGER_UCS1002)  += ucs1002_power.o
> diff --git a/drivers/power/supply/cros_peripheral_charger.c 
> b/drivers/power/supply/cros_peripheral_charger.c
> new file mode 100644
> index 00..cd7db4bd5f90d0
> --- /dev/null
> +++ b/drivers/power/supply/cros_peripheral_charger.c
> @@ -0,0 +1,350 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Power supply driver for ChromeOS EC based Peripheral Device Charger.
> + *
> + * Copyright 2020 Google LLC.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
Add

> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#define DRV_NAME   "cros-ec-pchg"
> +#define PCHG_DIR_NAME  "PCHG%d"
nit: to be coherent with function names, define CROS_EC_PCHG_DIR_NAME instead.
Isn't PCHG0, PCHG1, ... too generic? Looking at other driver, we have
strings like
"max1721x-%012X", "wm831x-battery.%d",
> +#define PCHG_DIR_NAME_LENGTH   sizeof("PCHG" __stringify(EC_PCHG_MAX_PORTS))
> +#define PCHG_CACHE_UPDATE_DELAYmsecs_to_jiffies(500)
> +
> +struct port_data {
> +   int port_number;
> +   char name[PCHG_DIR_NAME_LENGTH];
> +   struct power_supply *psy;
> +   struct power_supply_desc psy_desc;
> +   int psy_status;
> +   int battery_percentage;
> +   struct charger_data *charger;
> +   unsigned long last_update;
> +};
> +
> +struct charger_data {
> +   struct device *dev;
> +   struct cros_ec_dev *ec_dev;
> +   struct cros_ec_device *ec_device;
As far as I can see, ec_device is used only once, in cros_pchg_ec_command().
> +   int num_registered_psy;
> +   struct port_data *ports[EC_PCHG_MAX_PORTS];
> +   struct notifier_block notifier;
> +};
> +
> +static enum power_supply_property cros_pchg_props[] = {
> +   POWER_SUPPLY_PROP_STATUS,
> +   POWER_SUPPLY_PROP_CAPACITY,
> +   POWER_SUPPLY_PROP_SCOPE,
> +   /*
> +* todo: Add the following.
> +*
> +* POWER_SUPPLY_PROP_TECHNOLOGY,
> +* POWER_SUPPLY_PROP_ERROR,
> +* POWER_SUPPLY_PROP_SERIAL_NUMBER,
> +*

[PATCH v2 1/2] platform: cros_ec: Call interrupt bottom half in ISH or RPMSG mode

2021-01-21 Thread Gwendal Grignou
Call the same bottom half for all EC protocols (threaded code).

Signed-off-by: Gwendal Grignou 
---
Changes since v1:
- Fix merge issues, make changes in cros_ec.h instead of cros_ec_proto.h
- Fix function comments syntax.

 drivers/platform/chrome/cros_ec.c   | 26 +++--
 drivers/platform/chrome/cros_ec.h   |  4 +++-
 drivers/platform/chrome/cros_ec_ishtp.c |  6 +-
 drivers/platform/chrome/cros_ec_rpmsg.c |  6 +-
 4 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec.c 
b/drivers/platform/chrome/cros_ec.c
index 3104680b7485..bf76a6c49c95 100644
--- a/drivers/platform/chrome/cros_ec.c
+++ b/drivers/platform/chrome/cros_ec.c
@@ -32,7 +32,14 @@ static struct cros_ec_platform pd_p = {
.cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX),
 };
 
-static irqreturn_t ec_irq_handler(int irq, void *data)
+/**
+ * cros_ec_irq_handler() - top half part of the interrupt handler
+ * @irq: IRQ id
+ * @data: (ec_dev) Device with events to process.
+ *
+ * Return: Wakeup the bottom half
+ */
+static irqreturn_t cros_ec_irq_handler(int irq, void *data)
 {
struct cros_ec_device *ec_dev = data;
 
@@ -51,7 +58,7 @@ static irqreturn_t ec_irq_handler(int irq, void *data)
  * Return: true if more events are still pending and this function should be
  * called again.
  */
-bool cros_ec_handle_event(struct cros_ec_device *ec_dev)
+static bool cros_ec_handle_event(struct cros_ec_device *ec_dev)
 {
bool wake_event;
bool ec_has_more_events;
@@ -73,9 +80,15 @@ bool cros_ec_handle_event(struct cros_ec_device *ec_dev)
 
return ec_has_more_events;
 }
-EXPORT_SYMBOL(cros_ec_handle_event);
 
-static irqreturn_t ec_irq_thread(int irq, void *data)
+/**
+ * cros_ec_irq_thread() - bottom half part of the interrupt handler
+ * @irq: IRQ id
+ * @data: (ec_dev) Device with events to process.
+ *
+ * Return: Interrupt handled.
+ */
+irqreturn_t cros_ec_irq_thread(int irq, void *data)
 {
struct cros_ec_device *ec_dev = data;
bool ec_has_more_events;
@@ -86,6 +99,7 @@ static irqreturn_t ec_irq_thread(int irq, void *data)
 
return IRQ_HANDLED;
 }
+EXPORT_SYMBOL(cros_ec_irq_thread);
 
 static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event)
 {
@@ -194,8 +208,8 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
 
if (ec_dev->irq > 0) {
err = devm_request_threaded_irq(dev, ec_dev->irq,
-   ec_irq_handler,
-   ec_irq_thread,
+   cros_ec_irq_handler,
+   cros_ec_irq_thread,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"chromeos-ec", ec_dev);
if (err) {
diff --git a/drivers/platform/chrome/cros_ec.h 
b/drivers/platform/chrome/cros_ec.h
index e69fc1ff68b4..78363dcfdf23 100644
--- a/drivers/platform/chrome/cros_ec.h
+++ b/drivers/platform/chrome/cros_ec.h
@@ -8,12 +8,14 @@
 #ifndef __CROS_EC_H
 #define __CROS_EC_H
 
+#include 
+
 int cros_ec_register(struct cros_ec_device *ec_dev);
 int cros_ec_unregister(struct cros_ec_device *ec_dev);
 
 int cros_ec_suspend(struct cros_ec_device *ec_dev);
 int cros_ec_resume(struct cros_ec_device *ec_dev);
 
-bool cros_ec_handle_event(struct cros_ec_device *ec_dev);
+irqreturn_t cros_ec_irq_thread(int irq, void *data);
 
 #endif /* __CROS_EC_H */
diff --git a/drivers/platform/chrome/cros_ec_ishtp.c 
b/drivers/platform/chrome/cros_ec_ishtp.c
index 81364029af36..f00107017318 100644
--- a/drivers/platform/chrome/cros_ec_ishtp.c
+++ b/drivers/platform/chrome/cros_ec_ishtp.c
@@ -140,12 +140,8 @@ static void ish_evt_handler(struct work_struct *work)
 {
struct ishtp_cl_data *client_data =
container_of(work, struct ishtp_cl_data, work_ec_evt);
-   struct cros_ec_device *ec_dev = client_data->ec_dev;
-   bool ec_has_more_events;
 
-   do {
-   ec_has_more_events = cros_ec_handle_event(ec_dev);
-   } while (ec_has_more_events);
+   cros_ec_irq_thread(0, client_data->ec_dev);
 }
 
 /**
diff --git a/drivers/platform/chrome/cros_ec_rpmsg.c 
b/drivers/platform/chrome/cros_ec_rpmsg.c
index 30d0ba3b8889..d96d15b8ca94 100644
--- a/drivers/platform/chrome/cros_ec_rpmsg.c
+++ b/drivers/platform/chrome/cros_ec_rpmsg.c
@@ -149,12 +149,8 @@ cros_ec_rpmsg_host_event_function(struct work_struct 
*host_event_work)
struct cros_ec_rpmsg *ec_rpmsg = container_of(host_event_work,
  struct cros_ec_rpmsg,
  host_event_work);
-   struct cros_ec_device *ec_dev = dev_get_drvdata(&ec_rpmsg->rpdev->dev);
-   bool ec_has_more_events;
 
-   do {
-   ec_has_more_e

[PATCH v2 0/2] platform: chrome: Simplify interrupt path

2021-01-21 Thread Gwendal Grignou
rrespective of the transport (i2c, spi, ish, rpmsg), have all cros ec
interrupt stack call the threaded part (bottom half) of the interrupt
handler.
Fix an issue where EC could be stuck if it sends a message while the AP
is not powered on.

Changes since v1:
- fix merging issue and function comments syntax.

Gwendal Grignou (2):
  platform: cros_ec: Call interrupt bottom half in ISH or RPMSG mode
  platform: cros_ec: Call interrupt bottom half at probe time

 drivers/platform/chrome/cros_ec.c   | 33 -
 drivers/platform/chrome/cros_ec.h   |  4 ++-
 drivers/platform/chrome/cros_ec_ishtp.c |  6 +
 drivers/platform/chrome/cros_ec_rpmsg.c |  6 +
 4 files changed, 32 insertions(+), 17 deletions(-)

-- 
2.30.0.280.ga3ce27912f-goog



[PATCH v2 2/2] platform: cros_ec: Call interrupt bottom half at probe time

2021-01-21 Thread Gwendal Grignou
While the AP was powered off, the EC may have send messages.
If the message is not serviced within 3s, the EC stops sending message.
Unlock the EC by purging stale messages at probe time.

Signed-off-by: Gwendal Grignou 
---
Changes since v1: None.

 drivers/platform/chrome/cros_ec.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec.c 
b/drivers/platform/chrome/cros_ec.c
index bf76a6c49c95..fc5aa1525d13 100644
--- a/drivers/platform/chrome/cros_ec.c
+++ b/drivers/platform/chrome/cros_ec.c
@@ -283,6 +283,13 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
 
dev_info(dev, "Chrome EC device registered\n");
 
+   /*
+* Unlock EC that may be waiting for AP to process MKBP events.
+* If the AP takes to long to answer, the EC would stop sending events.
+*/
+   if (ec_dev->mkbp_event_supported)
+   cros_ec_irq_thread(0, ec_dev);
+
return 0;
 }
 EXPORT_SYMBOL(cros_ec_register);
-- 
2.30.0.280.ga3ce27912f-goog



[PATCH 2/2] platform: cros_ec: Call interrupt bottom half at probe time

2020-12-10 Thread Gwendal Grignou
While the AP was powered off, the EC may have send messages.
If the message is not serviced within 3s, the EC stops sending message.
Unlock the EC by purging stale messages at probe time.

Signed-off-by: Gwendal Grignou 
---
 drivers/platform/chrome/cros_ec.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec.c 
b/drivers/platform/chrome/cros_ec.c
index 4ac33491d0d18..a45d6a6640d50 100644
--- a/drivers/platform/chrome/cros_ec.c
+++ b/drivers/platform/chrome/cros_ec.c
@@ -252,6 +252,13 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
 
dev_info(dev, "Chrome EC device registered\n");
 
+   /*
+* Unlock EC that may be waiting for AP to process MKBP events.
+* If the AP takes to long to answer, the EC would stop sending events.
+*/
+   if (ec_dev->mkbp_event_supported)
+   cros_ec_irq_thread(0, ec_dev);
+
return 0;
 }
 EXPORT_SYMBOL(cros_ec_register);
-- 
2.29.2.576.ga3fc446d84-goog



[PATCH 0/2] platform: chrome: Simplify interrupt path

2020-12-10 Thread Gwendal Grignou
Irrespective of the transport (i2c, spi, ish, rpmsg), have all cros ec
interrupt stack call the threaded part (bottom half) of the interrupt
handler.
Fix an issue where EC could be stuck if it sends a message while the AP
is not powered on.

Gwendal Grignou (2):
  platform: cros_ec: Call interrupt bottom half in ISH or RPMSG mode
  platform: cros_ec: Call interrupt bottom half at probe time

 drivers/platform/chrome/cros_ec.c   | 33 +
 drivers/platform/chrome/cros_ec_ishtp.c |  6 +---
 drivers/platform/chrome/cros_ec_rpmsg.c |  6 +---
 include/linux/platform_data/cros_ec_proto.h |  3 +-
 4 files changed, 31 insertions(+), 17 deletions(-)

-- 
2.29.2.576.ga3fc446d84-goog



[PATCH 1/2] platform: cros_ec: Call interrupt bottom half in ISH or RPMSG mode

2020-12-10 Thread Gwendal Grignou
Call the same bottom half for all EC protocols (threaded code).

Signed-off-by: Gwendal Grignou 
---
 drivers/platform/chrome/cros_ec.c   | 26 -
 drivers/platform/chrome/cros_ec_ishtp.c |  6 +
 drivers/platform/chrome/cros_ec_rpmsg.c |  6 +
 include/linux/platform_data/cros_ec_proto.h |  3 ++-
 4 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec.c 
b/drivers/platform/chrome/cros_ec.c
index 6d6ce86a1408a..4ac33491d0d18 100644
--- a/drivers/platform/chrome/cros_ec.c
+++ b/drivers/platform/chrome/cros_ec.c
@@ -31,7 +31,14 @@ static struct cros_ec_platform pd_p = {
.cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX),
 };
 
-static irqreturn_t ec_irq_handler(int irq, void *data)
+/**
+ * cros_ec_irq_handler: top half part of the interrupt handler
+ * @irq: IRQ id
+ * @data: (ec_dev) Device with events to process.
+ *
+ * Return: Wakeup the bottom half
+ */
+static irqreturn_t cros_ec_irq_handler(int irq, void *data)
 {
struct cros_ec_device *ec_dev = data;
 
@@ -50,7 +57,7 @@ static irqreturn_t ec_irq_handler(int irq, void *data)
  * Return: true if more events are still pending and this function should be
  * called again.
  */
-bool cros_ec_handle_event(struct cros_ec_device *ec_dev)
+static bool cros_ec_handle_event(struct cros_ec_device *ec_dev)
 {
bool wake_event;
bool ec_has_more_events;
@@ -72,9 +79,15 @@ bool cros_ec_handle_event(struct cros_ec_device *ec_dev)
 
return ec_has_more_events;
 }
-EXPORT_SYMBOL(cros_ec_handle_event);
 
-static irqreturn_t ec_irq_thread(int irq, void *data)
+/**
+ * cros_ec_irq_thread: bottom half part of the interrupt handler
+ * @irq: IRQ id
+ * @data: (ec_dev) Device with events to process.
+ *
+ * Return: Interrupt handled.
+ */
+irqreturn_t cros_ec_irq_thread(int irq, void *data)
 {
struct cros_ec_device *ec_dev = data;
bool ec_has_more_events;
@@ -85,6 +98,7 @@ static irqreturn_t ec_irq_thread(int irq, void *data)
 
return IRQ_HANDLED;
 }
+EXPORT_SYMBOL(cros_ec_irq_thread);
 
 static int cros_ec_sleep_event(struct cros_ec_device *ec_dev, u8 sleep_event)
 {
@@ -175,8 +189,8 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
 
if (ec_dev->irq > 0) {
err = devm_request_threaded_irq(dev, ec_dev->irq,
-   ec_irq_handler,
-   ec_irq_thread,
+   cros_ec_irq_handler,
+   cros_ec_irq_thread,
IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"chromeos-ec", ec_dev);
if (err) {
diff --git a/drivers/platform/chrome/cros_ec_ishtp.c 
b/drivers/platform/chrome/cros_ec_ishtp.c
index 316cb4bee80d3..62c03be0183a2 100644
--- a/drivers/platform/chrome/cros_ec_ishtp.c
+++ b/drivers/platform/chrome/cros_ec_ishtp.c
@@ -138,12 +138,8 @@ static void ish_evt_handler(struct work_struct *work)
 {
struct ishtp_cl_data *client_data =
container_of(work, struct ishtp_cl_data, work_ec_evt);
-   struct cros_ec_device *ec_dev = client_data->ec_dev;
-   bool ec_has_more_events;
 
-   do {
-   ec_has_more_events = cros_ec_handle_event(ec_dev);
-   } while (ec_has_more_events);
+   cros_ec_irq_thread(0, client_data->ec_dev);
 }
 
 /**
diff --git a/drivers/platform/chrome/cros_ec_rpmsg.c 
b/drivers/platform/chrome/cros_ec_rpmsg.c
index 1b38bc8e164c3..12ddc5a4729b7 100644
--- a/drivers/platform/chrome/cros_ec_rpmsg.c
+++ b/drivers/platform/chrome/cros_ec_rpmsg.c
@@ -144,12 +144,8 @@ cros_ec_rpmsg_host_event_function(struct work_struct 
*host_event_work)
struct cros_ec_rpmsg *ec_rpmsg = container_of(host_event_work,
  struct cros_ec_rpmsg,
  host_event_work);
-   struct cros_ec_device *ec_dev = dev_get_drvdata(&ec_rpmsg->rpdev->dev);
-   bool ec_has_more_events;
 
-   do {
-   ec_has_more_events = cros_ec_handle_event(ec_dev);
-   } while (ec_has_more_events);
+   cros_ec_irq_thread(0, dev_get_drvdata(&ec_rpmsg->rpdev->dev));
 }
 
 static int cros_ec_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
diff --git a/include/linux/platform_data/cros_ec_proto.h 
b/include/linux/platform_data/cros_ec_proto.h
index 8776041d5cead..37cfd05d30a0b 100644
--- a/include/linux/platform_data/cros_ec_proto.h
+++ b/include/linux/platform_data/cros_ec_proto.h
@@ -9,6 +9,7 @@
 #define __LINUX_CROS_EC_PROTO_H
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -241,7 +242,7 @@ int cros_ec_check_features(struct cros_ec_dev *ec, int 
feature);
 
 int cros_ec_get_sensor_count(struct cros_ec_dev *ec);
 
-bool cros_ec_handle_event

Re: [PATCH 1/2] platform/chrome: cros_ec_proto: Update cros_ec_cmd_xfer() call-sites

2020-09-18 Thread Gwendal Grignou
On Mon, Sep 14, 2020 at 4:29 PM Prashant Malani  wrote:
>
> Thanks Enric,
>
> On Mon, Sep 7, 2020 at 3:48 AM Enric Balletbo i Serra
>  wrote:
> >
> > Hi Prashant,
> >
> > Thank you for your patch.
> >
> > On 3/9/20 11:54, Prashant Malani wrote:
> > > Since all the other call-sites of cros_ec_cmd_xfer() have been converted
> > > to use cros_ec_cmd_xfer_status() instead, update the remaining
> > > call-sites to prepare for the merge of cros_ec_cmd_xfer() into
> > > cros_ec_cmd_xfer_status().
> > >
> > > As part of this update, change the error handling inside
> > > cros_ec_get_sensor_count() such that the legacy LPC interface is tried
> > > on all error values, not just when msg->result != EC_RESULT_SUCCESS.
> > >
> > > Signed-off-by: Prashant Malani 
Reviewed-by: Gwendal Grignou 
Tested-by: Gwendal Grignou 

There is a slight change in API in cros_ec_get_sensor_count(): it will
return a negative number of sensors when there
are no sensors on arm platform when MOTIONSENSE_CMD_DUMP is not
supported (typical for sensorless chromebook) instead of 0.
However, this is not a problem when probing the EC as we ignore errors
only looking for cros_ec_get_sensor_count() returning a positive
number of sensors.

> >
> > Gwendal, I'd like to hear from you regarding this patch as you're the one 
> > that
> > know most about the corner cases for the sensors in different hardware. 
> > Could
> > you take a look and give us your Reviewed tag if all is good?
> >
> Gwendal, could you kindly take a look? Thanks!
>
> > Thanks,
> >
> >  Enric
> >
> > > ---
> > >  drivers/platform/chrome/cros_ec_proto.c | 15 ---
> > >  1 file changed, 4 insertions(+), 11 deletions(-)
> > >
> > > diff --git a/drivers/platform/chrome/cros_ec_proto.c 
> > > b/drivers/platform/chrome/cros_ec_proto.c
> > > index dda182132a6a..2cb1defcdd13 100644
> > > --- a/drivers/platform/chrome/cros_ec_proto.c
> > > +++ b/drivers/platform/chrome/cros_ec_proto.c
> > > @@ -650,7 +650,7 @@ static int get_next_event_xfer(struct cros_ec_device 
> > > *ec_dev,
> > >   msg->insize = size;
> > >   msg->outsize = 0;
> > >
> > > - ret = cros_ec_cmd_xfer(ec_dev, msg);
> > > + ret = cros_ec_cmd_xfer_status(ec_dev, msg);
> > >   if (ret > 0) {
> > >   ec_dev->event_size = ret - 1;
> > >   ec_dev->event_data = *event;
> > > @@ -694,7 +694,7 @@ static int get_keyboard_state_event(struct 
> > > cros_ec_device *ec_dev)
> > >   msg->insize = sizeof(ec_dev->event_data.data);
> > >   msg->outsize = 0;
> > >
> > > - ec_dev->event_size = cros_ec_cmd_xfer(ec_dev, msg);
> > > + ec_dev->event_size = cros_ec_cmd_xfer_status(ec_dev, msg);
> > >   ec_dev->event_data.event_type = EC_MKBP_EVENT_KEY_MATRIX;
> > >   memcpy(&ec_dev->event_data.data, msg->data,
> > >  sizeof(ec_dev->event_data.data));
> > > @@ -883,11 +883,9 @@ int cros_ec_get_sensor_count(struct cros_ec_dev *ec)
> > >   params = (struct ec_params_motion_sense *)msg->data;
> > >   params->cmd = MOTIONSENSE_CMD_DUMP;
> > >
> > > - ret = cros_ec_cmd_xfer(ec->ec_dev, msg);
> > > + ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
> > >   if (ret < 0) {
> > >   sensor_count = ret;
> > > - } else if (msg->result != EC_RES_SUCCESS) {
> > > - sensor_count = -EPROTO;
> > >   } else {
> > >   resp = (struct ec_response_motion_sense *)msg->data;
> > >   sensor_count = resp->dump.sensor_count;
> > > @@ -898,9 +896,7 @@ int cros_ec_get_sensor_count(struct cros_ec_dev *ec)
> > >* Check legacy mode: Let's find out if sensors are accessible
> > >* via LPC interface.
> > >*/
> > > - if (sensor_count == -EPROTO &&
> > > - ec->cmd_offset == 0 &&
> > > - ec_dev->cmd_readmem) {
> > > + if (sensor_count < 0 && ec->cmd_offset == 0 && ec_dev->cmd_readmem) 
> > > {
> > >   ret = ec_dev->cmd_readmem(ec_dev, EC_MEMMAP_ACC_STATUS,
> > >   1, &status);
> > >   if (ret >= 0 &&
> > > @@ -915,9 +911,6 @@ int cros_ec_get_sensor_count(struct cros_ec_dev *ec)
> > >*/
> > >   sensor_count = 0;
> > >   }
> > > - } else if (sensor_count == -EPROTO) {
> > > - /* EC responded, but does not understand DUMP command. */
> > > - sensor_count = 0;
> > >   }
> > >   return sensor_count;
> > >  }
> > >


Re: [PATCH] platform/chrome: Kconfig: Remove the transitional MFD_CROS_EC config

2020-09-03 Thread Gwendal Grignou
On Thu, Sep 3, 2020 at 8:02 AM Guenter Roeck  wrote:
>
> On Thu, Sep 3, 2020 at 7:17 AM Enric Balletbo i Serra
>  wrote:
> >
> > The MFD_CROS_EC config was a transitional Kconfig option to not break
> > current defconfigs in the kernel. Now, this is not required anymore
> > because all the defconfigs have been removed this option and migrated to
> > enable the CrOS EC parts individually.
> >
> > Signed-off-by: Enric Balletbo i Serra 
>
> Reviewed-by: Guenter Roeck 
Tested-by: Gwendal Grignou 
>
> > ---
> >
> >  drivers/platform/chrome/Kconfig | 10 --
> >  1 file changed, 10 deletions(-)
> >
> > diff --git a/drivers/platform/chrome/Kconfig 
> > b/drivers/platform/chrome/Kconfig
> > index a056031dee81..ccc23d8686e8 100644
> > --- a/drivers/platform/chrome/Kconfig
> > +++ b/drivers/platform/chrome/Kconfig
> > @@ -3,16 +3,6 @@
> >  # Platform support for Chrome OS hardware (Chromebooks and Chromeboxes)
> >  #
> >
> > -config MFD_CROS_EC
> > -   tristate "Platform support for Chrome hardware (transitional)"
> > -   select CHROME_PLATFORMS
> > -   select CROS_EC
> > -   select MFD_CROS_EC_DEV
> > -   depends on X86 || ARM || ARM64 || COMPILE_TEST
> > -   help
> > - This is a transitional Kconfig option and will be removed after
> > - everyone enables the parts individually.
> > -
> >  menuconfig CHROME_PLATFORMS
> > bool "Platform support for Chrome hardware"
> > depends on X86 || ARM || ARM64 || COMPILE_TEST
> > --
> > 2.28.0
> >


Re: [PATCH v2] platform: cros_ec: Reduce ligthbar get version command

2020-08-30 Thread Gwendal Grignou
On Sat, Aug 29, 2020 at 8:54 AM Jonathan Cameron  wrote:
>
> On Tue, 25 Aug 2020 17:29:45 -0700
> Gwendal Grignou  wrote:
>
> > By default, the lightbar commands are set to the
> > biggest lightbar command and response. That length is greater than 128
> > bytes and may not work on all machines.
> > But all EC are probed for lightbar by sending a get version request.
> > Set that request size precisely.
> >
> > Before the command would be:
> > cros_ec_cmd: version: 0, command: EC_CMD_LIGHTBAR_CMD, outsize: 194, 
> > insize: 128, result: 0
> > Afer:
> > cros_ec_cmd: version: 0, command: EC_CMD_LIGHTBAR_CMD, outsize: 1, insize: 
> > 8, result: 0
> >
> > Signed-off-by: Gwendal Grignou 
> Hi Gwendal,
>
> Description seems to me to suggest this is a fix?
> Are there known machines on which it doesn't work currently?
We have a prototype [without lightbar] where the command size was
limited to 128 bytes.
Given we issue a get_lightbar_version on all chromebooks, we had a
failure on this prototype. Devices with a lightbar must support a
command size greater or equal to 194 bytes.
Beside helping the prototype to boot, this patch slightly speeds up
the enumeration of devices managed by the EC.
>
> If so, please can I have a fixes tag.  If it's just a precaution
> against future problems then let me know and I can add it for the
> next merge window.
Done in v3.
Note I made a mistake by sending the patch to linux-iio as it targeted
platform/chromeos.
>
> Thanks,
>
> Jonathan
>
> > ---
> > Changes since v1:
> > - Remove BUG and TEST fields.
> >
> >  drivers/platform/chrome/cros_ec_lightbar.c | 2 ++
> >  1 file changed, 2 insertions(+)
> >
> > diff --git a/drivers/platform/chrome/cros_ec_lightbar.c 
> > b/drivers/platform/chrome/cros_ec_lightbar.c
> > index b59180bff5a3e..ef61298c30bdd 100644
> > --- a/drivers/platform/chrome/cros_ec_lightbar.c
> > +++ b/drivers/platform/chrome/cros_ec_lightbar.c
> > @@ -116,6 +116,8 @@ static int get_lightbar_version(struct cros_ec_dev *ec,
> >
> >   param = (struct ec_params_lightbar *)msg->data;
> >   param->cmd = LIGHTBAR_CMD_VERSION;
> > + msg->outsize = sizeof(param->cmd);
> > + msg->result = sizeof(resp->version);
> >   ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
> >   if (ret < 0) {
> >   ret = 0;
>


[PATCH v3] platform: cros_ec: Reduce ligthbar get version command

2020-08-30 Thread Gwendal Grignou
By default, the lightbar commands are set to the
biggest lightbar command and response. That length is greater than 128
bytes and may not work on all machines.
But all EC are probed for lightbar by sending a get version request.
Set that request size precisely.

Before the command would be:
cros_ec_cmd: version: 0, command: EC_CMD_LIGHTBAR_CMD, outsize: 194, insize: 
128, result: 0
Afer:
cros_ec_cmd: version: 0, command: EC_CMD_LIGHTBAR_CMD, outsize: 1, insize: 8, 
result: 0

Fixes: a841178445bb7 ("mfd: cros_ec: Use a zero-length array for command data")
Signed-off-by: Gwendal Grignou 
---
Changes since v2:
- Add fix field where the inefficiency was present.

Changes since v1:
- Remove BUG and TEST fields.

 drivers/platform/chrome/cros_ec_lightbar.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_lightbar.c 
b/drivers/platform/chrome/cros_ec_lightbar.c
index b59180bff5a3e..ef61298c30bdd 100644
--- a/drivers/platform/chrome/cros_ec_lightbar.c
+++ b/drivers/platform/chrome/cros_ec_lightbar.c
@@ -116,6 +116,8 @@ static int get_lightbar_version(struct cros_ec_dev *ec,
 
param = (struct ec_params_lightbar *)msg->data;
param->cmd = LIGHTBAR_CMD_VERSION;
+   msg->outsize = sizeof(param->cmd);
+   msg->result = sizeof(resp->version);
ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
if (ret < 0) {
ret = 0;
-- 
2.28.0.402.g5ffc5be6b7-goog



Re: [PATCH v2] platform: cros_ec: Reduce ligthbar get version command

2020-08-28 Thread Gwendal Grignou
[-iio list][+kernel list]


On Tue, Aug 25, 2020 at 5:29 PM Gwendal Grignou  wrote:
>
> By default, the lightbar commands are set to the
> biggest lightbar command and response. That length is greater than 128
> bytes and may not work on all machines.
> But all EC are probed for lightbar by sending a get version request.
> Set that request size precisely.
>
> Before the command would be:
> cros_ec_cmd: version: 0, command: EC_CMD_LIGHTBAR_CMD, outsize: 194, insize: 
> 128, result: 0
> Afer:
> cros_ec_cmd: version: 0, command: EC_CMD_LIGHTBAR_CMD, outsize: 1, insize: 8, 
> result: 0
>
> Signed-off-by: Gwendal Grignou 
> ---
> Changes since v1:
> - Remove BUG and TEST fields.
>
>  drivers/platform/chrome/cros_ec_lightbar.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/drivers/platform/chrome/cros_ec_lightbar.c 
> b/drivers/platform/chrome/cros_ec_lightbar.c
> index b59180bff5a3e..ef61298c30bdd 100644
> --- a/drivers/platform/chrome/cros_ec_lightbar.c
> +++ b/drivers/platform/chrome/cros_ec_lightbar.c
> @@ -116,6 +116,8 @@ static int get_lightbar_version(struct cros_ec_dev *ec,
>
> param = (struct ec_params_lightbar *)msg->data;
> param->cmd = LIGHTBAR_CMD_VERSION;
> +   msg->outsize = sizeof(param->cmd);
> +   msg->result = sizeof(resp->version);
> ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
> if (ret < 0) {
> ret = 0;
> --
> 2.28.0.297.g1956fa8f8d-goog
>


[PATCH] platform: cros_ec: Add fields to command traces

2020-08-15 Thread Gwendal Grignou
In ftrace, add more fields to the cros_ec command event:
- Add size of commands to check if they are properly set.
- Add offset (in case an EC is cascaded being another EC),
to allow proper command output

With:
echo 1 > events/cros_ec/cros_ec_cmd/enable
We now have (on samus)

invalid command for the sensor stack:
ectool-6942  [002]   3082.783116: cros_ec_request_done: version: 3,
 offset: 0, command: EC_CMD_MOTION_SENSE_CMD, outsize: 2, insize: 19,
 ec result: EC_RES_INVALID_PARAM, retval: 0

powerd accessing PD EC being the main EC:
powerd-1272  [002] 40.644026: cros_ec_request_done: version: 0,
 offset: 1, command: EC_CMD_USB_PD_POWER_INFO, outsize: 1, insize: 16,
 ec result: EC_RES_SUCCESS, retval: 16

Signed-off-by: Gwendal Grignou 
---
 drivers/platform/chrome/cros_ec_trace.h | 27 +++--
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_trace.h 
b/drivers/platform/chrome/cros_ec_trace.h
index e9fb05f89ef07..f744b21bc655f 100644
--- a/drivers/platform/chrome/cros_ec_trace.h
+++ b/drivers/platform/chrome/cros_ec_trace.h
@@ -23,14 +23,22 @@ TRACE_EVENT(cros_ec_request_start,
TP_ARGS(cmd),
TP_STRUCT__entry(
__field(uint32_t, version)
+   __field(uint32_t, offset)
__field(uint32_t, command)
+   __field(uint32_t, outsize)
+   __field(uint32_t, insize)
),
TP_fast_assign(
__entry->version = cmd->version;
-   __entry->command = cmd->command;
+   __entry->offset = cmd->command / EC_CMD_PASSTHRU_OFFSET(1);
+   __entry->command = cmd->command % EC_CMD_PASSTHRU_OFFSET(1);
+   __entry->outsize = cmd->outsize;
+   __entry->insize = cmd->insize;
),
-   TP_printk("version: %u, command: %s", __entry->version,
- __print_symbolic(__entry->command, EC_CMDS))
+   TP_printk("version: %u, offset: %d, command: %s, outsize: %u, insize: 
%u",
+ __entry->version, __entry->offset,
+ __print_symbolic(__entry->command, EC_CMDS),
+ __entry->outsize, __entry->insize)
 );
 
 TRACE_EVENT(cros_ec_request_done,
@@ -38,19 +46,26 @@ TRACE_EVENT(cros_ec_request_done,
TP_ARGS(cmd, retval),
TP_STRUCT__entry(
__field(uint32_t, version)
+   __field(uint32_t, offset)
__field(uint32_t, command)
+   __field(uint32_t, outsize)
+   __field(uint32_t, insize)
__field(uint32_t, result)
__field(int, retval)
),
TP_fast_assign(
__entry->version = cmd->version;
-   __entry->command = cmd->command;
+   __entry->offset = cmd->command / EC_CMD_PASSTHRU_OFFSET(1);
+   __entry->command = cmd->command % EC_CMD_PASSTHRU_OFFSET(1);
+   __entry->outsize = cmd->outsize;
+   __entry->insize = cmd->insize;
__entry->result = cmd->result;
__entry->retval = retval;
),
-   TP_printk("version: %u, command: %s, ec result: %s, retval: %d",
- __entry->version,
+   TP_printk("version: %u, offset: %d, command: %s, outsize: %u, insize: 
%u, ec result: %s, retval: %u",
+ __entry->version, __entry->offset,
  __print_symbolic(__entry->command, EC_CMDS),
+ __entry->outsize, __entry->insize,
  __print_symbolic(__entry->result, EC_RESULT),
  __entry->retval)
 );
-- 
2.28.0.220.ged08abb693-goog



[PATCH] platform: cros_ec: Reduce ligthbar get version command

2020-08-15 Thread Gwendal Grignou
By default, the lightbar commands are set to the
biggest lightbar command and response. That length is greater than 128
bytes and may not work on all machines.
But all EC are probed for lightbar by sending a get version request.
Set that request size precisely.

BUG=chromium:160662061
TEST=Before the command would be:
cros_ec_cmd: version: 0, command: EC_CMD_LIGHTBAR_CMD, outsize: 194, insize: 
128, result: 0
Afer:
cros_ec_cmd: version: 0, command: EC_CMD_LIGHTBAR_CMD, outsize: 1, insize: 8, 
result: 0

Signed-off-by: Gwendal Grignou 
---
 drivers/platform/chrome/cros_ec_lightbar.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_lightbar.c 
b/drivers/platform/chrome/cros_ec_lightbar.c
index b59180bff5a3e..ef61298c30bdd 100644
--- a/drivers/platform/chrome/cros_ec_lightbar.c
+++ b/drivers/platform/chrome/cros_ec_lightbar.c
@@ -116,6 +116,8 @@ static int get_lightbar_version(struct cros_ec_dev *ec,
 
param = (struct ec_params_lightbar *)msg->data;
param->cmd = LIGHTBAR_CMD_VERSION;
+   msg->outsize = sizeof(param->cmd);
+   msg->result = sizeof(resp->version);
ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
if (ret < 0) {
ret = 0;
-- 
2.28.0.220.ged08abb693-goog



[PATCH] platform: cros_ec: sensorhub: Simplify legacy timestamp spreading

2020-07-28 Thread Gwendal Grignou
On some machine (nami), interrupt latency cause samples to appear
to be from the future and are pegged to the current time.
We would see samples with this pattern:

[t, t + ~5ms, t + ~10ms, t + ~10ms + 100us, t + ~10ms + 200us],
 (current now)  (current now)
(t is the last timestamp time)

Last 2 samples would be barely spread, causing applications to
complain.
We now spread the entire sequence. This is not great: in the example
the sensor was supposed to send samples every 5ms, it now appears to
send one every 2.5ms, but it is slightly closer to reality:

sampling time in the example above
At sensor level

1 2 3 45
+-5ms-+-5ms-+-5ms-+5ms-+---> t

Before, at host level
   1 2 3 4 5
--interrupt delay--+-5ms-+-5ms-+-+-+---> t

Afer, at host level
   1   2   3   4   5
--interrupt delay--+-2.5ms-+-2.5ms-+-2.5ms-+-2.5ms-+---> t

Signed-off-by: Gwendal Grignou 
---
 .../platform/chrome/cros_ec_sensorhub_ring.c  | 94 +++
 1 file changed, 33 insertions(+), 61 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_sensorhub_ring.c 
b/drivers/platform/chrome/cros_ec_sensorhub_ring.c
index 1b9637655e63e..0b0bf93073c30 100644
--- a/drivers/platform/chrome/cros_ec_sensorhub_ring.c
+++ b/drivers/platform/chrome/cros_ec_sensorhub_ring.c
@@ -719,29 +719,22 @@ done_with_this_batch:
  * cros_ec_sensor_ring_spread_add_legacy: Calculate proper timestamps then
  * add to ringbuffer (legacy).
  *
- * Note: This assumes we're running old firmware, where every sample's 
timestamp
- * is after the sample. Run if tight_timestamps == false.
- *
- * If there is a sample with a proper timestamp
+ * Note: This assumes we're running old firmware, where timestamp
+ * is inserted after its sample(s)e. There can be several samples between
+ * timestamps, so several samples can have the same timestamp.
  *
  *timestamp | count
  *-
- * older_unprocess_out --> TS1  | 1
- * TS1  | 2
- *out -->  TS1  | 3
- *   next_out -->  TS2  |
- *
- * We spread time for the samples [older_unprocess_out .. out]
- * between TS1 and TS2: [TS1+1/4, TS1+2/4, TS1+3/4, TS2].
+ *  1st sample --> TS1  | 1
+ * TS2  | 2
+ * TS2  | 3
+ * TS3  | 4
+ *   last_out -->
  *
- * If we reach the end of the samples, we compare with the
- * current timestamp:
  *
- * older_unprocess_out --> TS1  | 1
- * TS1  | 2
- * out --> TS1  | 3
+ * We spread time for the samples using perod p = (current - TS1)/4.
+ * between TS1 and TS2: [TS1+p/4, TS1+2p/4, TS1+3p/4, current_timestamp].
  *
- * We know have [TS1+1/3, TS1+2/3, current timestamp]
  */
 static void
 cros_ec_sensor_ring_spread_add_legacy(struct cros_ec_sensorhub *sensorhub,
@@ -754,58 +747,37 @@ cros_ec_sensor_ring_spread_add_legacy(struct 
cros_ec_sensorhub *sensorhub,
int i;
 
for_each_set_bit(i, &sensor_mask, sensorhub->sensor_num) {
-   s64 older_timestamp;
s64 timestamp;
-   struct cros_ec_sensors_ring_sample *older_unprocess_out =
-   sensorhub->ring;
-   struct cros_ec_sensors_ring_sample *next_out;
-   int count = 1;
-
-   for (out = sensorhub->ring; out < last_out; out = next_out) {
-   s64 time_period;
+   int count = 0;
+   s64 time_period;
 
-   next_out = out + 1;
+   for (out = sensorhub->ring; out < last_out; out++) {
if (out->sensor_id != i)
continue;
 
/* Timestamp to start with */
-   older_timestamp = out->timestamp;
-
-   /* Find next sample. */
-   while (next_out < last_out && next_out->sensor_id != i)
-   next_out++;
+   timestamp = out->timestamp;
+   out++;
+   count = 1;
+   break;
+   }
+   for (; out < last_out; out++) {
+   /* Find last sample. */
+   if (out->sensor_id != i)
+   continue;
+   count++;
+   }
+   if (count == 0)
+   continue;
 
-   if (next_out >= last_out) {
-   timestamp = current_timestamp;
-   } else {
-  

[PATCH] platform: chrome: Fix EC timestamp overflow

2020-06-30 Thread Gwendal Grignou
EC is using 32 bit timestamps (us), and before converting it to 64bit
they were not casted, so it would overflow every 4s.
Regular overflow every ~70 minutes was not taken into acoun either.

Signed-off-by: Gwendal Grignou 
---
 drivers/platform/chrome/cros_ec_sensorhub_ring.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_sensorhub_ring.c 
b/drivers/platform/chrome/cros_ec_sensorhub_ring.c
index 23960f3acc0b1..641d91088cee2 100644
--- a/drivers/platform/chrome/cros_ec_sensorhub_ring.c
+++ b/drivers/platform/chrome/cros_ec_sensorhub_ring.c
@@ -465,9 +465,7 @@ cros_ec_sensor_ring_process_event(struct cros_ec_sensorhub 
*sensorhub,
 * Disable filtering since we might add more jitter
 * if b is in a random point in time.
 */
-   new_timestamp = fifo_timestamp -
-   fifo_info->timestamp  * 1000 +
-   in->timestamp * 1000;
+   new_timestamp = c - b * 1000 + a * 1000;
/*
 * The timestamp can be stale if we had to use the fifo
 * info timestamp.
-- 
2.27.0.212.ge8ba1cc988-goog



Re: [PATCH] platform/chrome: cros_ec_spi: Document missing function parameters

2020-06-25 Thread Gwendal Grignou
Reviewed-by: Gwendal Grignou 

On Thu, Jun 25, 2020 at 10:02 AM Enric Balletbo i Serra
 wrote:
>
> Kerneldoc expects all kernel function members to be documented.
>
> Fixes the following W=1 level warnings:
>
>   cros_ec_spi.c:153: warning: Function parameter or member 'ec_dev' not 
> described in 'receive_n_bytes'
>   cros_ec_spi.c:153: warning: Function parameter or member 'buf' not 
> described in 'receive_n_bytes'
>   cros_ec_spi.c:153: warning: Function parameter or member 'n' not described 
> in 'receive_n_bytes'
>
> Signed-off-by: Enric Balletbo i Serra 
> ---
>
>  drivers/platform/chrome/cros_ec_spi.c | 4 
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/platform/chrome/cros_ec_spi.c 
> b/drivers/platform/chrome/cros_ec_spi.c
> index f7cf7c6a04507..d17f5c74ae976 100644
> --- a/drivers/platform/chrome/cros_ec_spi.c
> +++ b/drivers/platform/chrome/cros_ec_spi.c
> @@ -148,6 +148,10 @@ static int terminate_request(struct cros_ec_device 
> *ec_dev)
>   * receive_n_bytes - receive n bytes from the EC.
>   *
>   * Assumes buf is a pointer into the ec_dev->din buffer
> + *
> + * @ec_dev: ChromeOS EC device.
> + * @buf: Pointer to the buffer receiving the data.
> + * @n: Number of bytes received.
>   */
>  static int receive_n_bytes(struct cros_ec_device *ec_dev, u8 *buf, int n)
>  {
> --
> 2.27.0
>


Re: [PATCH] platform/chrome: cros_ec_rpmsg: Document missing struct parameters

2020-06-25 Thread Gwendal Grignou
Reviewed-by: Gwendal Grignou 

On Thu, Jun 25, 2020 at 10:03 AM Enric Balletbo i Serra
 wrote:
>
> Kerneldoc expects all kernel structure member to be documented.
>
> Fixes the following W=1 level warnings:
>
>   cros_ec_rpmsg.c:49: warning: Function parameter or member 'ept' not 
> described in 'cros_ec_rpmsg'
>   cros_ec_rpmsg.c:49: warning: Function parameter or member 
> 'has_pending_host_event' not described in 'cros_ec_rpmsg'
>   cros_ec_rpmsg.c:49: warning: Function parameter or member 'probe_done' not 
> described in 'cros_ec_rpmsg'
>
> Signed-off-by: Enric Balletbo i Serra 
> ---
>
>  drivers/platform/chrome/cros_ec_rpmsg.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/drivers/platform/chrome/cros_ec_rpmsg.c 
> b/drivers/platform/chrome/cros_ec_rpmsg.c
> index ff08c3d12873a..ad0a30afd7423 100644
> --- a/drivers/platform/chrome/cros_ec_rpmsg.c
> +++ b/drivers/platform/chrome/cros_ec_rpmsg.c
> @@ -38,6 +38,9 @@ struct cros_ec_rpmsg_response {
>   * @rpdev: rpmsg device we are connected to
>   * @xfer_ack:  completion for host command transfer.
>   * @host_event_work:   Work struct for pending host event.
> + * @ept: The rpmsg endpoint of this channel.
> + * @has_pending_host_event: Boolean used to check if there is a pending 
> event.
> + * @probe_done: Flag to indicate that probe is done.
>   */
>  struct cros_ec_rpmsg {
> struct rpmsg_device *rpdev;
> --
> 2.27.0
>


[PATCH] iio: cros_ec: Reapply range at resume

2020-05-26 Thread Gwendal Grignou
EC does not currently preserve range across sensor reinit.
If sensor is powered down at suspend, it will default to the EC default
range at resume, not the range set by the host.

Save range if modified, and apply at resume.

Signed-off-by: Gwendal Grignou 
---
 .../common/cros_ec_sensors/cros_ec_sensors.c  |  5 +
 .../cros_ec_sensors/cros_ec_sensors_core.c| 21 +++
 drivers/iio/light/cros_ec_light_prox.c|  6 +-
 drivers/iio/pressure/cros_ec_baro.c   |  8 +--
 .../linux/iio/common/cros_ec_sensors_core.h   | 11 +-
 5 files changed, 47 insertions(+), 4 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 a66941fdb3855..130ab8ce0269b 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -200,6 +200,10 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
st->core.param.sensor_range.roundup = 1;
 
ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+   if (ret == 0) {
+   st->core.range_updated = true;
+   st->core.curr_range = val;
+   }
break;
default:
ret = cros_ec_sensors_core_write(
@@ -315,6 +319,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids);
 static struct platform_driver cros_ec_sensors_platform_driver = {
.driver = {
.name   = "cros-ec-sensors",
+   .pm = &cros_ec_sensors_pm_ops,
},
.probe  = cros_ec_sensors_probe,
.id_table   = cros_ec_sensors_ids,
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
index c831915ca7e56..cda459b612067 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -824,5 +824,26 @@ int cros_ec_sensors_core_write(struct 
cros_ec_sensors_core_state *st,
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_write);
 
+static int __maybe_unused cros_ec_sensors_resume(struct device *dev)
+{
+   struct platform_device *pdev = to_platform_device(dev);
+   struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+   int ret = 0;
+
+   if (st->range_updated) {
+   mutex_lock(&st->cmd_lock);
+   st->param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
+   st->param.sensor_range.data = st->curr_range;
+   st->param.sensor_range.roundup = 1;
+   ret = cros_ec_motion_send_host_cmd(st, 0);
+   mutex_unlock(&st->cmd_lock);
+   }
+   return ret;
+}
+
+SIMPLE_DEV_PM_OPS(cros_ec_sensors_pm_ops, NULL, cros_ec_sensors_resume);
+EXPORT_SYMBOL_GPL(cros_ec_sensors_pm_ops);
+
 MODULE_DESCRIPTION("ChromeOS EC sensor hub core functions");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/light/cros_ec_light_prox.c 
b/drivers/iio/light/cros_ec_light_prox.c
index 2198b50909ed0..fed79ba27fda5 100644
--- a/drivers/iio/light/cros_ec_light_prox.c
+++ b/drivers/iio/light/cros_ec_light_prox.c
@@ -145,8 +145,11 @@ static int cros_ec_light_prox_write(struct iio_dev 
*indio_dev,
break;
case IIO_CHAN_INFO_CALIBSCALE:
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
-   st->core.param.sensor_range.data = (val << 16) | (val2 / 100);
+   st->core.curr_range = (val << 16) | (val2 / 100);
+   st->core.param.sensor_range.data = st->core.curr_range;
ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+   if (ret == 0)
+   st->core.range_updated = true;
break;
default:
ret = cros_ec_sensors_core_write(&st->core, chan, val, val2,
@@ -256,6 +259,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_light_prox_ids);
 static struct platform_driver cros_ec_light_prox_platform_driver = {
.driver = {
.name   = "cros-ec-light-prox",
+   .pm = &cros_ec_sensors_pm_ops,
},
.probe  = cros_ec_light_prox_probe,
.id_table   = cros_ec_light_prox_ids,
diff --git a/drivers/iio/pressure/cros_ec_baro.c 
b/drivers/iio/pressure/cros_ec_baro.c
index c079b89600824..f0938b6fbba07 100644
--- a/drivers/iio/pressure/cros_ec_baro.c
+++ b/drivers/iio/pressure/cros_ec_baro.c
@@ -96,8 +96,11 @@ static int cros_ec_baro_write(struct iio_dev *indio_dev,
/* Always roundup, so caller gets at least what it asks for. */
st->core.param.sensor_range.roundup = 1;
 
-   if (cros_ec_motion_send_host_cmd(&

[PATCH v2] platform: cros_ec_debugfs: control uptime information request

2020-05-26 Thread Gwendal Grignou
When EC does not support uptime command (EC_CMD_GET_UPTIME_INFO),
do not create the uptime sysfs entry point.
User space application will not probe the file needlessly.

The EC console log will not contain EC_CMD_GET_UPTIME_INFO anymore.

Signed-off-by: Gwendal Grignou 
---
 drivers/platform/chrome/cros_ec_debugfs.c | 24 +--
 1 file changed, 22 insertions(+), 2 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_debugfs.c 
b/drivers/platform/chrome/cros_ec_debugfs.c
index 6ae484989d1f5..303a8c4686f89 100644
--- a/drivers/platform/chrome/cros_ec_debugfs.c
+++ b/drivers/platform/chrome/cros_ec_debugfs.c
@@ -243,6 +243,25 @@ static ssize_t cros_ec_pdinfo_read(struct file *file,
   read_buf, p - read_buf);
 }
 
+static bool cros_ec_uptime_is_supported(struct cros_ec_device *ec_dev)
+{
+   struct {
+   struct cros_ec_command cmd;
+   struct ec_response_uptime_info resp;
+   } __packed msg = {};
+   int ret;
+
+   msg.cmd.command = EC_CMD_GET_UPTIME_INFO;
+   msg.cmd.insize = sizeof(msg.resp);
+
+   ret = cros_ec_cmd_xfer_status(ec_dev, &msg.cmd);
+   if (ret == -EPROTO && msg.cmd.result == EC_RES_INVALID_COMMAND)
+   return false;
+
+   /* Other errors maybe a transient error, do not rule about support. */
+   return true;
+}
+
 static ssize_t cros_ec_uptime_read(struct file *file, char __user *user_buf,
   size_t count, loff_t *ppos)
 {
@@ -445,8 +464,9 @@ static int cros_ec_debugfs_probe(struct platform_device *pd)
debugfs_create_file("pdinfo", 0444, debug_info->dir, debug_info,
&cros_ec_pdinfo_fops);
 
-   debugfs_create_file("uptime", 0444, debug_info->dir, debug_info,
-   &cros_ec_uptime_fops);
+   if (cros_ec_uptime_is_supported(ec->ec_dev))
+   debugfs_create_file("uptime", 0444, debug_info->dir, debug_info,
+   &cros_ec_uptime_fops);
 
debugfs_create_x32("last_resume_result", 0444, debug_info->dir,
   &ec->ec_dev->last_resume_result);
-- 
2.27.0.rc0.183.gde8f92d652-goog



Re: [PATCH] platform: cros_ec_debugfs: control uptime information request

2020-05-26 Thread Gwendal Grignou
On Thu, May 21, 2020 at 2:21 AM Enric Balletbo i Serra
 wrote:
>
> Hi Gwendal,
>
> Thank you for your patch.
>
> On 21/5/20 7:28, Gwendal Grignou wrote:
> > When EC does not support uptime command (EC_CMD_GET_UPTIME_INFO),
> > return -EPROTO to read of /sys/kernel/debug/cros_ec/uptime without
> > calling the EC after the first try.
> >
> > The EC console log will not contain EC_CMD_GET_UPTIME_INFO anymore.
> >
>
> Oh, what you mean with this? Uptime is only exposed via sysfs or I am missing
> something.
I was checking the ec console log (via
/sys/kernel/debug/cros_ec/console_log) to check the EC was not
receiving and erroring on the command (pixelbook)
>
> > Signed-off-by: Gwendal Grignou 
> > ---
> >  drivers/platform/chrome/cros_ec_debugfs.c | 12 
> >  1 file changed, 12 insertions(+)
> >
> > diff --git a/drivers/platform/chrome/cros_ec_debugfs.c 
> > b/drivers/platform/chrome/cros_ec_debugfs.c
> > index 6ae484989d1f5..70a29afb6d9e7 100644
> > --- a/drivers/platform/chrome/cros_ec_debugfs.c
> > +++ b/drivers/platform/chrome/cros_ec_debugfs.c
> > @@ -49,6 +49,8 @@ struct cros_ec_debugfs {
> >   struct delayed_work log_poll_work;
> >   /* EC panicinfo */
> >   struct debugfs_blob_wrapper panicinfo_blob;
> > + /* EC uptime */
> > + bool uptime_supported;
>
> Ideally, if uptime can be supported or not we should only expose uptime when 
> is
> supported, so the sysfs entry should only be created when is supported, 
> similar
> to what we do with the console_log. See cros_ec_create_console_log()
>
> If doing this doesn't break userspace, I'd prefer doing in that way.
Good point, sending a v2.

Gwendal.
>
> Thanks,
>  Enric
>
>
> >  };
> >
> >  /*
> > @@ -256,12 +258,19 @@ static ssize_t cros_ec_uptime_read(struct file *file, 
> > char __user *user_buf,
> >   char read_buf[32];
> >   int ret;
> >
> > + if (!debug_info->uptime_supported)
> > + return -EPROTO;
> > +
> >   resp = (struct ec_response_uptime_info *)&msg.resp;
> >
> >   msg.cmd.command = EC_CMD_GET_UPTIME_INFO;
> >   msg.cmd.insize = sizeof(*resp);
> >
> >   ret = cros_ec_cmd_xfer_status(ec_dev, &msg.cmd);
> > + if (ret == -EPROTO && msg.cmd.result == EC_RES_INVALID_COMMAND) {
> > + debug_info->uptime_supported = false;
> > + return ret;
> > + }
> >   if (ret < 0)
> >   return ret;
> >
> > @@ -434,6 +443,9 @@ static int cros_ec_debugfs_probe(struct platform_device 
> > *pd)
> >   debug_info->ec = ec;
> >   debug_info->dir = debugfs_create_dir(name, NULL);
> >
> > + /* Give uptime a chance to run. */
> > + debug_info->uptime_supported = true;
> > +
> >   ret = cros_ec_create_panicinfo(debug_info);
> >   if (ret)
> >   goto remove_debugfs;
> >


[PATCH] platform: cros_ec_debugfs: control uptime information request

2020-05-20 Thread Gwendal Grignou
When EC does not support uptime command (EC_CMD_GET_UPTIME_INFO),
return -EPROTO to read of /sys/kernel/debug/cros_ec/uptime without
calling the EC after the first try.

The EC console log will not contain EC_CMD_GET_UPTIME_INFO anymore.

Signed-off-by: Gwendal Grignou 
---
 drivers/platform/chrome/cros_ec_debugfs.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_debugfs.c 
b/drivers/platform/chrome/cros_ec_debugfs.c
index 6ae484989d1f5..70a29afb6d9e7 100644
--- a/drivers/platform/chrome/cros_ec_debugfs.c
+++ b/drivers/platform/chrome/cros_ec_debugfs.c
@@ -49,6 +49,8 @@ struct cros_ec_debugfs {
struct delayed_work log_poll_work;
/* EC panicinfo */
struct debugfs_blob_wrapper panicinfo_blob;
+   /* EC uptime */
+   bool uptime_supported;
 };
 
 /*
@@ -256,12 +258,19 @@ static ssize_t cros_ec_uptime_read(struct file *file, 
char __user *user_buf,
char read_buf[32];
int ret;
 
+   if (!debug_info->uptime_supported)
+   return -EPROTO;
+
resp = (struct ec_response_uptime_info *)&msg.resp;
 
msg.cmd.command = EC_CMD_GET_UPTIME_INFO;
msg.cmd.insize = sizeof(*resp);
 
ret = cros_ec_cmd_xfer_status(ec_dev, &msg.cmd);
+   if (ret == -EPROTO && msg.cmd.result == EC_RES_INVALID_COMMAND) {
+   debug_info->uptime_supported = false;
+   return ret;
+   }
if (ret < 0)
return ret;
 
@@ -434,6 +443,9 @@ static int cros_ec_debugfs_probe(struct platform_device *pd)
debug_info->ec = ec;
debug_info->dir = debugfs_create_dir(name, NULL);
 
+   /* Give uptime a chance to run. */
+   debug_info->uptime_supported = true;
+
ret = cros_ec_create_panicinfo(debug_info);
if (ret)
goto remove_debugfs;
-- 
2.26.2.761.g0e0b3e54be-goog



Re: [PATCH v2 1/3] iio: Add in_illumincance vectors in different color spaces

2020-05-11 Thread Gwendal Grignou
On Fri, May 8, 2020 at 8:16 AM Jonathan Cameron
 wrote:
>
> On Wed, 6 May 2020 16:03:22 -0700
> Gwendal Grignou  wrote:
>
> Illuminance in the title.  Plus I'm still arguing these
> aren't illuminance values.
>
> The Y value is illuminance but X and Z definitely aren't.
> RGB needs to stick to intensity - like the other existing
> RGB sensors.
>
> Gah.  XYZ and IIO is a mess.
>
> I suppose we could introduce a new type and have
> in_illumiance_raw
> in_chromacity_x_raw
> in_chromacity_z_raw but chances of anyone understanding what we
> are on about without reading wikipedia is low...
>
> Sigh.  Unless someone else chips in, I'm inclined to be lazy and rely
> on documentation to let in_illuminance_x,y,z be defined as being
> cie xyz color space measurements.
>
> It seems slighlty preferable to defining another type for these,
> though I suspect I'll regret this comment when some adds
> cie lab which was always my favourite colour space :)
>
>
>
> > Define 2 spaces for defining color coming from color sensors:
> > RGB and XYZ: Both are in lux.
> > RGB is the raw output from sensors (Red, Green and Blue channels), in
> > addition to the existing clear channel (C).
>
> > The RGBC vector goes through a matrix transformation to produce the XYZ
> > vector. Y is illumincance, and XY caries the chromaticity information.
> > The matrix is model specific, as the color sensor can be behing a glass
> > that can filter some wavelengths.
> >
> > Signed-off-by: Gwendal Grignou 
> > ---
> > New in v2.
> >
> >  Documentation/ABI/testing/sysfs-bus-iio | 27 +
> >  1 file changed, 27 insertions(+)
> >
> > diff --git a/Documentation/ABI/testing/sysfs-bus-iio 
> > b/Documentation/ABI/testing/sysfs-bus-iio
> > index d3e53a6d8331b..256db6e63a25e 100644
> > --- a/Documentation/ABI/testing/sysfs-bus-iio
> > +++ b/Documentation/ABI/testing/sysfs-bus-iio
> > @@ -1309,6 +1309,33 @@ Description:
> >   Illuminance measurement, units after application of scale
> >   and offset are lux.
> >
> > +What:/sys/.../iio:deviceX/in_illuminance_red_raw
> > +What:/sys/.../iio:deviceX/in_illuminance_green_raw
> > +What:/sys/.../iio:deviceX/in_illuminance_blue_raw
> > +KernelVersion:   5.7
> > +Contact: linux-...@vger.kernel.org
> > +Description:
> > + Illuminance measuremed in red, green or blue channels, units
> > + after application of scale and offset are lux.
>
> No they aren't.  Units are some magic intensity at some magic wavelength.
>
> > +
> > +What:/sys/.../iio:deviceX/in_illuminance_x_raw
> > +What:/sys/.../iio:deviceX/in_illuminance_y_raw
> > +What:/sys/.../iio:deviceX/in_illuminance_z_raw
> > +KernelVersion:   5.7
> > +Contact: linux-...@vger.kernel.org
> > +Description:
> > + lluminance measured in the CIE 1931 color space (XYZ).
> > + in_illuminance_y_raw is a measure of the brightness, and is
> > + identical in_illuminance_raw.
>
> That is fair enough.
>
> > + in_illuminance_x_raw and in_illuminance_z_raw carry chromacity
> > + information.
> > + in_illuminance_x,y,z_raw are be obtained from the sensor color
> > + channels using color matching functions that may be device
> > + specific.
> > + Units after application of scale and offset are lux.
>
> True for Y, not for X and Z which don't have 'units' as such.
Indeed,I have difficulty mapping what comes from the sensor after
adapting to an acceptable universal entity.

The goal of the sensor is to measure the ambient correlated color
temperature (CCT), based on the x and y of the CIE xyY color space.
Given x and y are defined as x = X / (X + Y +Z) and y = X / (X + Y +
Z), X, Y and Z must have the same units.

CCT(x,y) is computed in user space, for example using this
approximation (https://en.wikipedia.org/wiki/Color_temperature#Approximation).

Gwendal.


>
> > + The measurments can be used to represent colors in the CIE
> > + xyY color space
>
> XYZ
>
> > +
> >  What:/sys/.../iio:deviceX/in_intensityY_raw
> >  What:/sys/.../iio:deviceX/in_intensityY_ir_raw
> >  What:/sys/.../iio:deviceX/in_intensityY_both_raw
>
>


[PATCH v2 3/3] iio: cros_ec_light: Add support for RGB sensor

2020-05-06 Thread Gwendal Grignou
Add support for color sensors behind EC like TCS3400.
The color data can be presented in Red Green Blue color space (RGB) or
the CIE 1931 XYZ color space (XYZ).
In XYZ mode, the sensor is configured for auto calibrating its channels
and is the "normal" mode.
The driver tells the EC to switch between the 2 modes by using the
calibration command.
When the sensor is in calibration mode, only clear and RGB channels are
available. In normal mode, only clear and XYZ are.
When RGB channels are enabled, the sensor switches to calibration mode
when the buffer is enabled.

When reading trhough sysfs command, set calibration mode and then read
the channel(s). A command will be issue for each read, so the channels
may come from different sensor sample.
When using the buffer, after setting the mask, when the buffer is
enabled, the calibration will be set based on the channel mask.

libiio tools can be used to gather sensor information:
iio_readdev -s 10 cros-ec-light \
illuminance_clear illuminance_x illuminance_y illuminance_z

To match IIO ABI, the clear illuminance channel has been renamed
in_illuminance_clear_raw from in_illuminance_input.

Signed-off-by: Gwendal Grignou 
---
 drivers/iio/light/cros_ec_light_prox.c| 469 +++---
 drivers/platform/chrome/cros_ec_sensorhub.c   |   3 +
 .../linux/iio/common/cros_ec_sensors_core.h   |   1 -
 .../linux/platform_data/cros_ec_commands.h|   2 +
 4 files changed, 404 insertions(+), 71 deletions(-)

diff --git a/drivers/iio/light/cros_ec_light_prox.c 
b/drivers/iio/light/cros_ec_light_prox.c
index 2198b50909ed0..83bd3057b334c 100644
--- a/drivers/iio/light/cros_ec_light_prox.c
+++ b/drivers/iio/light/cros_ec_light_prox.c
@@ -17,82 +17,188 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
 /*
- * We only represent one entry for light or proximity. EC is merging different
- * light sensors to return the what the eye would see. For proximity, we
- * currently support only one light source.
+ * We may present up to 7 channels:
+ *
+ * +-+-+-+-+-+-+-+
+ * |Clear|  X  |  Y  |  Z  | RED |BLUE |GREEN|
+ * |Prox | | | | | | |
+ * +-+-+-+-+-+-+-+
+ *
+ * Prox[imity] is presented by proximity sensors.
+ * The clear channel is supported by single and color light sensors.
+ * Color light sensor either reports color information in the RGB space or
+ * the CIE 1931 XYZ (XYZ) color space.
  */
-#define CROS_EC_LIGHT_PROX_MAX_CHANNELS (1 + 1)
+#define CROS_EC_LIGHT_CLEAR_OR_PROXIMITY_MASK GENMASK(0, 0)
+#define CROS_EC_LIGHT_XYZ_SPACE_MASK GENMASK(3, 1)
+#define CROS_EC_LIGHT_RGB_SPACE_MASK (6, 4)
+
+/*
+ * We always represent one entry for light or proximity, and all
+ * samples can be timestamped.
+ */
+#define CROS_EC_LIGHT_PROX_MIN_CHANNELS (1 + 1)
+
+static const unsigned long cros_ec_light_prox_bitmasks[] = {
+   CROS_EC_LIGHT_CLEAR_OR_PROXIMITY_MASK,
+   CROS_EC_LIGHT_XYZ_SPACE_MASK,
+   CROS_EC_LIGHT_XYZ_SPACE_MASK | CROS_EC_LIGHT_CLEAR_OR_PROXIMITY_MASK,
+   CROS_EC_LIGHT_RGB_SPACE_MASK,
+   CROS_EC_LIGHT_RGB_SPACE_MASK | CROS_EC_LIGHT_CLEAR_OR_PROXIMITY_MASK,
+   0,
+};
+
+#define CROS_EC_LIGHT_IDX_TO_CHAN(_idx) (((_idx) - 1) % 
CROS_EC_SENSOR_MAX_AXIS)
 
 /* State data for ec_sensors iio driver. */
 struct cros_ec_light_prox_state {
/* Shared by all sensors */
struct cros_ec_sensors_core_state core;
 
-   struct iio_chan_spec channels[CROS_EC_LIGHT_PROX_MAX_CHANNELS];
+   /* Calibration information for the color channels. */
+   struct calib_data rgb_calib[CROS_EC_SENSOR_MAX_AXIS];
 };
 
+static void cros_ec_light_channel_common(struct iio_chan_spec *channel)
+{
+   channel->info_mask_shared_by_all =
+   BIT(IIO_CHAN_INFO_SAMP_FREQ);
+   channel->info_mask_shared_by_all_available =
+   BIT(IIO_CHAN_INFO_SAMP_FREQ);
+   channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
+   channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
+   channel->ext_info = cros_ec_sensors_ext_info;
+   channel->scan_type.sign = 'u';
+}
+
+static int
+cros_ec_light_extra_send_host_cmd(struct cros_ec_sensors_core_state *state,
+ int increment, u16 opt_length)
+{
+   u8 save_sensor_num = state->param.info.sensor_num;
+   int ret;
+
+   state->param.info.sensor_num += increment;
+   ret = cros_ec_motion_send_host_cmd(state, opt_length);
+   state->param.info.sensor_num = save_sensor_num;
+   return ret;
+}
+
+static int cros_ec_light_prox_read_data(struct iio_dev *indio_dev,
+   struct iio_chan_spec const *chan,
+   int *val)
+{
+   struct cros_ec_light_prox_state *st = iio_priv(indio_dev);
+   int ret;
+   int idx = chan->scan_index;
+   s16 data;
+
+   /*
+* The data coming fro

[PATCH v3 0/3] iio: cros_ec: Add support for RGB light sensor

2020-05-06 Thread Gwendal Grignou
Add support for color light sensor presented by the Chromebook Embedded
Controller (EC).
Instead of just presenting lux measurement (clear channel), a color light
sensor is able to report color temperature measurement.

The EC, using factory settings, can transform the raw measurement into
the CIE 1931 XYZ color space (XYZ) and take adavantage of color sensor
autocalibration to provide the most accurate measurements.

Gwendal Grignou (3):
  iio: Add in_illumincance vectors in different color spaces
  iio: cros_ec: Allow enabling/disabling calibration mode
  iio: cros_ec_light: Add support for RGB sensor

 Documentation/ABI/testing/sysfs-bus-iio   |  27 +
 .../cros_ec_sensors/cros_ec_sensors_core.c|   3 +-
 drivers/iio/light/cros_ec_light_prox.c| 469 +++---
 drivers/platform/chrome/cros_ec_sensorhub.c   |   3 +
 .../linux/iio/common/cros_ec_sensors_core.h   |   1 -
 .../linux/platform_data/cros_ec_commands.h|  14 +-
 6 files changed, 441 insertions(+), 76 deletions(-)

-- 
2.26.2.526.g744177e7f7-goog



[PATCH v2 1/3] iio: Add in_illumincance vectors in different color spaces

2020-05-06 Thread Gwendal Grignou
Define 2 spaces for defining color coming from color sensors:
RGB and XYZ: Both are in lux.
RGB is the raw output from sensors (Red, Green and Blue channels), in
addition to the existing clear channel (C).
The RGBC vector goes through a matrix transformation to produce the XYZ
vector. Y is illumincance, and XY caries the chromaticity information.
The matrix is model specific, as the color sensor can be behing a glass
that can filter some wavelengths.

Signed-off-by: Gwendal Grignou 
---
New in v2.

 Documentation/ABI/testing/sysfs-bus-iio | 27 +
 1 file changed, 27 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-bus-iio 
b/Documentation/ABI/testing/sysfs-bus-iio
index d3e53a6d8331b..256db6e63a25e 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -1309,6 +1309,33 @@ Description:
Illuminance measurement, units after application of scale
and offset are lux.
 
+What:  /sys/.../iio:deviceX/in_illuminance_red_raw
+What:  /sys/.../iio:deviceX/in_illuminance_green_raw
+What:  /sys/.../iio:deviceX/in_illuminance_blue_raw
+KernelVersion: 5.7
+Contact:   linux-...@vger.kernel.org
+Description:
+   Illuminance measuremed in red, green or blue channels, units
+   after application of scale and offset are lux.
+
+What:  /sys/.../iio:deviceX/in_illuminance_x_raw
+What:  /sys/.../iio:deviceX/in_illuminance_y_raw
+What:  /sys/.../iio:deviceX/in_illuminance_z_raw
+KernelVersion: 5.7
+Contact:   linux-...@vger.kernel.org
+Description:
+   lluminance measured in the CIE 1931 color space (XYZ).
+   in_illuminance_y_raw is a measure of the brightness, and is
+   identical in_illuminance_raw.
+   in_illuminance_x_raw and in_illuminance_z_raw carry chromacity
+   information.
+   in_illuminance_x,y,z_raw are be obtained from the sensor color
+   channels using color matching functions that may be device
+   specific.
+   Units after application of scale and offset are lux.
+   The measurments can be used to represent colors in the CIE
+   xyY color space
+
 What:  /sys/.../iio:deviceX/in_intensityY_raw
 What:  /sys/.../iio:deviceX/in_intensityY_ir_raw
 What:  /sys/.../iio:deviceX/in_intensityY_both_raw
-- 
2.26.2.526.g744177e7f7-goog



[PATCH v2 2/3] iio: cros_ec: Allow enabling/disabling calibration mode

2020-05-06 Thread Gwendal Grignou
calibration was a one-shot event sent to the sensor to calibrate itself.
It is used on Bosch sensors (BMI160, BMA254).
For TCS3400 light sensor, we need to stay in calibration mode to run
tests.
Accept boolean true and false (not just true) to enter/exit calibration.

Signed-off-by: Gwendal Grignou 
---
 .../common/cros_ec_sensors/cros_ec_sensors_core.c|  3 +--
 include/linux/platform_data/cros_ec_commands.h   | 12 +---
 2 files changed, 10 insertions(+), 5 deletions(-)

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
index c831915ca7e56..3d8b25ee9d80c 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -411,11 +411,10 @@ static ssize_t cros_ec_sensors_calibrate(struct iio_dev 
*indio_dev,
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;
+   st->param.perform_calib.enable = calibrate;
ret = cros_ec_motion_send_host_cmd(st, 0);
if (ret != 0) {
dev_warn(&indio_dev->dev, "Unable to calibrate sensor\n");
diff --git a/include/linux/platform_data/cros_ec_commands.h 
b/include/linux/platform_data/cros_ec_commands.h
index 451885c697cc3..395c9b2b05c66 100644
--- a/include/linux/platform_data/cros_ec_commands.h
+++ b/include/linux/platform_data/cros_ec_commands.h
@@ -2517,13 +2517,19 @@ struct ec_params_motion_sense {
 
/*
 * Used for MOTIONSENSE_CMD_INFO, MOTIONSENSE_CMD_DATA
-* and MOTIONSENSE_CMD_PERFORM_CALIB.
 */
struct __ec_todo_unpacked {
uint8_t sensor_num;
-   } info, info_3, data, fifo_flush, perform_calib,
-   list_activities;
+   } info, info_3, data, fifo_flush, list_activities;
 
+   /*
+* Used for MOTIONSENSE_CMD_PERFORM_CALIB:
+* Allow entering/exiting the calibration mode.
+*/
+   struct __ec_todo_unpacked {
+   uint8_t sensor_num;
+   uint8_t enable;
+   } perform_calib;
/*
 * Used for MOTIONSENSE_CMD_EC_RATE, MOTIONSENSE_CMD_SENSOR_ODR
 * and MOTIONSENSE_CMD_SENSOR_RANGE.
-- 
2.26.2.526.g744177e7f7-goog



Re: [PATCH 2/2] iio: cros_ec_light: Add support for RGB sensor

2020-04-30 Thread Gwendal Grignou
On Sat, Apr 25, 2020 at 10:31 AM Jonathan Cameron  wrote:
>
> On Wed, 22 Apr 2020 17:02:30 -0700
> Gwendal Grignou  wrote:
>
> > Add support for color sensors behind EC like TCS3400.
> > The color data can be presented in Red Green Blue color space (RGB) or
> > the CIE 1931 XYZ color space (XYZ).
> > In XYZ mode, the sensor is configured for auto calibrating its channels
> > and is the "normal" mode.
> > The driver tells the EC to switch between the 2 modes by using the
> > calibration command.
> > When the sensor is in calibration mode, only clear and RGB channels are
> > available. In normal mode, only clear and XYZ are.
> > When RGB channels are enabled, the sensor switches to calibration mode
> > when the buffer is enabled.
> >
> > When reading trhough sysfs command, set calibration mode and then read
> > the channel(s). A command will be issue for each read, so the channels
> > may come from different sensor sample.
> > When using the buffer, after setting the mask, when the buffer is
> > enabled, the calibration will be set based on the channel mask.
> >
> > libiio tools can be used to gather sensor information:
> > iio_readdev -s 10 cros-ec-light \
> > illuminance_clear illuminance_x illuminance_y illuminance_z
> Illuminance is not defined for color channels.  It's units are LUX which
> is only defined wrt to a model of the human eye's response to
> 'brightness' (kind of).
Looking at "Calculating Color Temperature and Illuminance " from AMS
[https://ams.com/documents/20143/80162/TCS34xx_AN000517_1-00.pdf/1efe49f7-4f92-ba88-ca7c-5121691daff7]
page 5, equation 2, the illuminance (Y) is a derived from the vector
(X, Y, Z) with coefficient applied. Doesn't it mean
in_illumincance_[X,Y,Z,R,G,B,clear ...]_raw have all the same unit,
lux?


>
> For RGB colour channels they are normally unit free so use intensity
> instead.  For XYZ.. hmm not sure.
>
> As Peter pointed out we need some doc updates to cover this use
> of x, y and z.
Will also add definition for  in_illuminance_[red|green|blue]_raw.

>
> >
> > To match IIO ABI, the clear illuminance channel has been renamed
> > in_illuminance_clear_raw from in_illuminance_input.
> >
> > Signed-off-by: Gwendal Grignou 
> A few additional comments inline.
>
> J
> > ---
> >  drivers/iio/light/cros_ec_light_prox.c| 470 +++---
> >  drivers/platform/chrome/cros_ec_sensorhub.c   |   3 +
> >  .../linux/iio/common/cros_ec_sensors_core.h   |   1 -
> >  .../linux/platform_data/cros_ec_commands.h|   2 +
> >  4 files changed, 405 insertions(+), 71 deletions(-)
> >
> > diff --git a/drivers/iio/light/cros_ec_light_prox.c 
> > b/drivers/iio/light/cros_ec_light_prox.c
> > index 2198b50909ed0..57eee557a785c 100644
> > --- a/drivers/iio/light/cros_ec_light_prox.c
> > +++ b/drivers/iio/light/cros_ec_light_prox.c
> > @@ -17,82 +17,190 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >
> >  /*
> > - * We only represent one entry for light or proximity. EC is merging 
> > different
> > - * light sensors to return the what the eye would see. For proximity, we
> > - * currently support only one light source.
> > + * We may present up to 7 channels:
> > + *
> > + * +-+-+-+-+-+-+-+
> > + * |Clear|  X  |  Y  |  Z  | RED |BLUE |GREEN|
> > + * |Prox | | | | | | |
> > + * +-+-+-+-+-+-+-+
> > + *
> > + * Prox[imity] is presented by proximity sensors.
> > + * The clear channel is supported by single and color light sensors.
> > + * Color light sensor either reports color information in the RGB space or
> > + * the CIE 1931 XYZ (XYZ) color space.
> >   */
> > -#define CROS_EC_LIGHT_PROX_MAX_CHANNELS (1 + 1)
> > +#define CROS_EC_LIGHT_CLEAR_OR_PROXIMITY_MASK 1
> > +#define CROS_EC_LIGHT_XYZ_SPACE_MASK (0x7 << 1)
> > +#define CROS_EC_LIGHT_RGB_SPACE_MASK (0x7 << 4)
> > +
> > +/*
> > + * We always represent one entry for light or proximity, and all
> > + * samples can be timestamped.
> > + */
> > +#define CROS_EC_LIGHT_PROX_MIN_CHANNELS (1 + 1)
> > +
> > +static const unsigned long cros_ec_light_prox_bitmasks[] = {
> > + CROS_EC_LIGHT_CLEAR_OR_PROXIMITY_MASK,
> > + CROS_EC_LIGHT_XYZ_SPACE_MASK,
> > + CROS_EC_LIGHT_XYZ_SPACE_MASK | CROS_EC_LIGHT_CLEAR_OR_PROXIMITY_MASK,
> > + CROS_EC_LIGHT_RGB_SPACE_MASK,
> > + CROS_EC_LIGHT_RGB_SPACE_MASK | CROS_EC_L

Re: [PATCH 2/2] iio: cros_ec_light: Add support for RGB sensor

2020-04-30 Thread Gwendal Grignou
On Thu, Apr 23, 2020 at 12:50 AM Peter Meerwald-Stadler
 wrote:
>
> On Wed, 22 Apr 2020, Gwendal Grignou wrote:
>
> comments below
>
> > Add support for color sensors behind EC like TCS3400.
> > The color data can be presented in Red Green Blue color space (RGB) or
> > the CIE 1931 XYZ color space (XYZ).
> > In XYZ mode, the sensor is configured for auto calibrating its channels
> > and is the "normal" mode.
> > The driver tells the EC to switch between the 2 modes by using the
> > calibration command.
> > When the sensor is in calibration mode, only clear and RGB channels are
> > available. In normal mode, only clear and XYZ are.
> > When RGB channels are enabled, the sensor switches to calibration mode
> > when the buffer is enabled.
> >
> > When reading trhough sysfs command, set calibration mode and then read
> > the channel(s). A command will be issue for each read, so the channels
> > may come from different sensor sample.
> > When using the buffer, after setting the mask, when the buffer is
> > enabled, the calibration will be set based on the channel mask.
> >
> > libiio tools can be used to gather sensor information:
> > iio_readdev -s 10 cros-ec-light \
> > illuminance_clear illuminance_x illuminance_y illuminance_z
> >
> > To match IIO ABI, the clear illuminance channel has been renamed
> > in_illuminance_clear_raw from in_illuminance_input.
> >
> > Signed-off-by: Gwendal Grignou 
> > ---
> >  drivers/iio/light/cros_ec_light_prox.c| 470 +++---
> >  drivers/platform/chrome/cros_ec_sensorhub.c   |   3 +
> >  .../linux/iio/common/cros_ec_sensors_core.h   |   1 -
> >  .../linux/platform_data/cros_ec_commands.h|   2 +
> >  4 files changed, 405 insertions(+), 71 deletions(-)
> >
> > diff --git a/drivers/iio/light/cros_ec_light_prox.c 
> > b/drivers/iio/light/cros_ec_light_prox.c
> > index 2198b50909ed0..57eee557a785c 100644
> > --- a/drivers/iio/light/cros_ec_light_prox.c
> > +++ b/drivers/iio/light/cros_ec_light_prox.c
> > @@ -17,82 +17,190 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >
> >  /*
> > - * We only represent one entry for light or proximity. EC is merging 
> > different
> > - * light sensors to return the what the eye would see. For proximity, we
> > - * currently support only one light source.
> > + * We may present up to 7 channels:
> > + *
> > + * +-+-+-+-+-+-+-+
> > + * |Clear|  X  |  Y  |  Z  | RED |BLUE |GREEN|
> > + * |Prox | | | | | | |
> > + * +-+-+-+-+-+-+-+
> > + *
> > + * Prox[imity] is presented by proximity sensors.
> > + * The clear channel is supported by single and color light sensors.
> > + * Color light sensor either reports color information in the RGB space or
> > + * the CIE 1931 XYZ (XYZ) color space.
> >   */
> > -#define CROS_EC_LIGHT_PROX_MAX_CHANNELS (1 + 1)
> > +#define CROS_EC_LIGHT_CLEAR_OR_PROXIMITY_MASK 1
> > +#define CROS_EC_LIGHT_XYZ_SPACE_MASK (0x7 << 1)
> > +#define CROS_EC_LIGHT_RGB_SPACE_MASK (0x7 << 4)
>
> could use GENMASK()
Done [in v2]
>
> > +
> > +/*
> > + * We always represent one entry for light or proximity, and all
> > + * samples can be timestamped.
> > + */
> > +#define CROS_EC_LIGHT_PROX_MIN_CHANNELS (1 + 1)
> > +
> > +static const unsigned long cros_ec_light_prox_bitmasks[] = {
> > + CROS_EC_LIGHT_CLEAR_OR_PROXIMITY_MASK,
> > + CROS_EC_LIGHT_XYZ_SPACE_MASK,
> > + CROS_EC_LIGHT_XYZ_SPACE_MASK | CROS_EC_LIGHT_CLEAR_OR_PROXIMITY_MASK,
> > + CROS_EC_LIGHT_RGB_SPACE_MASK,
> > + CROS_EC_LIGHT_RGB_SPACE_MASK | CROS_EC_LIGHT_CLEAR_OR_PROXIMITY_MASK,
>
> so it's not possible to read all 7 channels in one go?
> maybe that's not really needed
Yes, it is not possible: the interface between the embedded controller
(EC) and the host has been defined to send up to 3 values at a time,
so for the color sensor, we use the vector to either send the
measurement in RGB or XYZ space.
>
> > + 0,
> > +};
> > +
> > +#define CROS_EC_IDX_TO_CHAN(_idx) (((_idx) - 1) % CROS_EC_SENSOR_MAX_AXIS)
>
> may CROS_EC_LIGHT_IDX_TO_CHAN for consistency
>
> MAX_AXIS sounds more like something for an accelerometer (which also has 3
> components by incident)
It is what the embedded controller can do.
>
> X, Y, Z is not documented (sysfs-bus-iio) to can represent color
> components
Will do.
>
> >
>

Re: [PATCH v2 18/18] iio: cros_ec: Use Hertz as unit for sampling frequency

2019-10-22 Thread Gwendal Grignou
On Mon, Oct 21, 2019 at 9:45 AM Jonathan Cameron  wrote:
>
> On Sun, 20 Oct 2019 22:54:03 -0700
> Gwendal Grignou  wrote:
>
> > To be compliant with other sensors, set and get sensor sampling
> > frequency in Hz, not mHz.
> >
> > Fixes: ae7b02ad2f32 ("iio: common: cros_ec_sensors: Expose
> > cros_ec_sensors frequency range via iio sysfs")
> >
> > Signed-off-by: Gwendal Grignou 
>
> Do we need to look at back porting this?
>
> Acked-by: Jonathan Cameron 
>
> Not sure which path this set will take in, hence I've given
> acks for various patches incase it's not via me.
>
> Whole set is in general good to have, but I do worry a bit about
> people noticing ABI breakage. *crosses fingers*
I am planning to backport the sysfs change to older kernel.
I am adding some code to the clients that use the sysfs interface: if
frequency is absent, assume sample_frequency is the new frequency.
Clients should be able to handle both ABI, the code has been around
since 3.14.

>
> Jonathan
>
> > ---
> > No changes in v2.
> >
> >  .../cros_ec_sensors/cros_ec_sensors_core.c| 32 +++
> >  .../linux/iio/common/cros_ec_sensors_core.h   |  6 ++--
> >  2 files changed, 22 insertions(+), 16 deletions(-)
> >
> > 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
> > index f50e239f9a1e9..76dc8cad1b4b5 100644
> > --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
> > +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
> > @@ -256,6 +256,7 @@ int cros_ec_sensors_core_init(struct platform_device 
> > *pdev,
> >   struct cros_ec_dev *ec = sensor_hub->ec;
> >   struct cros_ec_sensor_platform *sensor_platform = 
> > dev_get_platdata(dev);
> >   u32 ver_mask;
> > + int frequencies[ARRAY_SIZE(state->frequencies) / 2] = { 0 };
> >   int ret, i;
> >
> >   platform_set_drvdata(pdev, indio_dev);
> > @@ -304,20 +305,22 @@ int cros_ec_sensors_core_init(struct platform_device 
> > *pdev,
> >   state->calib[i].scale = MOTION_SENSE_DEFAULT_SCALE;
> >
> >   /* 0 is a correct value used to stop the device */
> > - state->frequencies[0] = 0;
> >   if (state->msg->version < 3) {
> >   get_default_min_max_freq(state->resp->info.type,
> > -  &state->frequencies[1],
> > -  &state->frequencies[2],
> > +  &frequencies[1],
> > +  &frequencies[2],
> >
> > &state->fifo_max_event_count);
> >   } else {
> > - state->frequencies[1] =
> > - state->resp->info_3.min_frequency;
> > - state->frequencies[2] =
> > - state->resp->info_3.max_frequency;
> > + frequencies[1] = state->resp->info_3.min_frequency;
> > + frequencies[2] = state->resp->info_3.max_frequency;
> >   state->fifo_max_event_count =
> >   state->resp->info_3.fifo_max_event_count;
> >   }
> > + for (i = 0; i < ARRAY_SIZE(frequencies); i++) {
> > + state->frequencies[2 * i] = frequencies[i] / 1000;
> > + state->frequencies[2 * i + 1] =
> > + (frequencies[i] % 1000) * 1000;
> > + }
> >
> >   ret = devm_iio_triggered_buffer_setup(
> >   dev, indio_dev, NULL,
> > @@ -707,7 +710,7 @@ 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;
> > + int ret, frequency;
> >
> >   switch (mask) {
> >   case IIO_CHAN_INFO_SAMP_FREQ:
> > @@ -719,8 +722,10 @@ int cros_ec_sensors_core_read(struct 
> > cros_ec_sensors_core_state *st,
> >   if (ret)
> >   break;
> >
> > - *val = st->resp->sensor_odr.ret;
> > - ret = IIO_VAL_INT;
> > + frequency = st->resp->sen

Re: [PATCH v2 10/18] platform: chrome: sensorhub: Add FIFO support

2019-10-21 Thread Gwendal Grignou
On Mon, Oct 21, 2019 at 9:27 AM Jonathan Cameron  wrote:
>
> On Sun, 20 Oct 2019 22:53:55 -0700
> Gwendal Grignou  wrote:
>
> > cros_ec_sensorhub registers a listener and query motion sense FIFO,
> > spread to iio sensors registers.
> >
> > To test, we can use libiio:
> > iiod&
> > iio_readdev -u ip:localhost -T 1 -s 25 -b 16 cros-ec-gyro | od -x
> >
> > Signed-off-by: Gwendal Grignou 
>
> A few new bits inline.  I'm not an expert in power management, but
> using prepare as done here doesn't immediately seem the right choice
> to me (I'd not come across it before so had to read the docs ;)
>
> Thanks,
>
> Jonathan
>
>
> > ---
> > Changes sunce v2:
> > - Do not register a .remove routinge in plaform_driver. A
> >   devm_action_add is added later patch IIO driver register their
> > callback.
> > - Remove double lines, add lines before return calls.
> > - Handle FLUSH flag from EC.
> > - Use ktime_t for most timestamp measurements.
> > - Add doxygen comments
> > - Cleanup timestamp collection when processing FIFO.
> > - Rename fifo_toggle to fifo_enable
> >
> >  drivers/platform/chrome/Makefile  |   3 +-
> >  drivers/platform/chrome/cros_ec_sensorhub.c   | 123 --
> >  .../platform/chrome/cros_ec_sensorhub_ring.c  | 412 ++
> >  .../linux/platform_data/cros_ec_sensorhub.h   |  77 
> >  4 files changed, 583 insertions(+), 32 deletions(-)
> >  create mode 100644 drivers/platform/chrome/cros_ec_sensorhub_ring.c
> >
> > diff --git a/drivers/platform/chrome/Makefile 
> > b/drivers/platform/chrome/Makefile
> > index a164c40dc0996..cb709048c003e 100644
> > --- a/drivers/platform/chrome/Makefile
> > +++ b/drivers/platform/chrome/Makefile
> > @@ -17,7 +17,8 @@ obj-$(CONFIG_CROS_EC_PROTO) += cros_ec_proto.o 
> > cros_ec_trace.o
> >  obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT) += cros_kbd_led_backlight.o
> >  obj-$(CONFIG_CROS_EC_CHARDEV)+= cros_ec_chardev.o
> >  obj-$(CONFIG_CROS_EC_LIGHTBAR)   += cros_ec_lightbar.o
> > -obj-$(CONFIG_CROS_EC_SENSORHUB)  += cros_ec_sensorhub.o
> > +cros_ec_sensorsupport-objs   := cros_ec_sensorhub_ring.o 
> > cros_ec_sensorhub.o
> > +obj-$(CONFIG_CROS_EC_SENSORHUB)  += cros_ec_sensorsupport.o
> >  obj-$(CONFIG_CROS_EC_VBC)+= cros_ec_vbc.o
> >  obj-$(CONFIG_CROS_EC_DEBUGFS)+= cros_ec_debugfs.o
> >  obj-$(CONFIG_CROS_EC_SYSFS)  += cros_ec_sysfs.o
> > diff --git a/drivers/platform/chrome/cros_ec_sensorhub.c 
> > b/drivers/platform/chrome/cros_ec_sensorhub.c
> > index 5fea4c28c5c95..87308dadc32c5 100644
> > --- a/drivers/platform/chrome/cros_ec_sensorhub.c
> > +++ b/drivers/platform/chrome/cros_ec_sensorhub.c
> > @@ -24,7 +24,6 @@
> >
> >  #define DRV_NAME "cros-ec-sensorhub"
> >
> > -
> >  static struct device_type cros_ec_sensorhub_dev_type = {
> >   .name   = "cros_ec_iio_sensor",
> >  };
> > @@ -64,14 +63,13 @@ static int cros_ec_sensorhub_allocate_single_sensor(
> >  }
> >
> >  static int cros_ec_sensorhub_register(struct device *dev,
> > - struct cros_ec_dev *ec)
> > + struct cros_ec_sensorhub *sensorhub)
> >  {
> >   int ret, i, id, sensor_num;
> >   int sensor_type[MOTIONSENSE_TYPE_MAX] = { 0 };
> > - struct ec_params_motion_sense *params;
> > - struct ec_response_motion_sense *resp;
> > - struct cros_ec_command *msg;
> >   char *name;
> > + struct cros_ec_command *msg = sensorhub->msg;
> > + struct cros_ec_dev *ec = sensorhub->ec;
> >
> >   sensor_num = cros_ec_get_sensor_count(ec);
> >   if (sensor_num < 0) {
> > @@ -86,32 +84,21 @@ static int cros_ec_sensorhub_register(struct device 
> > *dev,
> >   return -EINVAL;
> >   }
> >
> > - /* Prepare a message to send INFO command to each sensor. */
> > - msg = kzalloc(sizeof(struct cros_ec_command) +
> > -   max(sizeof(*params), sizeof(*resp)), GFP_KERNEL);
> > - if (!msg) {
> > - ret = -ENOMEM;
> > - goto error;
> > - }
> > -
> >   msg->version = 1;
> > - 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;
> > - resp = (struct

[PATCH v2 01/18] platform: chrome: Put docs with the code

2019-10-20 Thread Gwendal Grignou
To avoid doc rot, put function documentations with code, not header.
Use kernel-doc style comments for exported functions.

Signed-off-by: Gwendal Grignou 
---
New in v2.

 drivers/platform/chrome/cros_ec.c   |  33 +++
 drivers/platform/chrome/cros_ec_proto.c |  70 +
 include/linux/platform_data/cros_ec_proto.h | 103 
 3 files changed, 103 insertions(+), 103 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec.c 
b/drivers/platform/chrome/cros_ec.c
index fd77e6fa74c2c..9b2d07422e175 100644
--- a/drivers/platform/chrome/cros_ec.c
+++ b/drivers/platform/chrome/cros_ec.c
@@ -104,6 +104,15 @@ static int cros_ec_sleep_event(struct cros_ec_device 
*ec_dev, u8 sleep_event)
return ret;
 }
 
+/**
+ * cros_ec_register() - Register a new ChromeOS EC, using the provided info.
+ * @ec_dev: Device to register.
+ *
+ * Before calling this, allocate a pointer to a new device and then fill
+ * in all the fields up to the --private-- marker.
+ *
+ * Return: 0 on success or negative error code.
+ */
 int cros_ec_register(struct cros_ec_device *ec_dev)
 {
struct device *dev = ec_dev->dev;
@@ -198,6 +207,14 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
 }
 EXPORT_SYMBOL(cros_ec_register);
 
+/**
+ * cros_ec_unregister() - Remove a ChromeOS EC.
+ * @ec_dev: Device to unregister.
+ *
+ * Call this to deregister a ChromeOS EC, then clean up any private data.
+ *
+ * Return: 0 on success or negative error code.
+ */
 int cros_ec_unregister(struct cros_ec_device *ec_dev)
 {
if (ec_dev->pd)
@@ -209,6 +226,14 @@ int cros_ec_unregister(struct cros_ec_device *ec_dev)
 EXPORT_SYMBOL(cros_ec_unregister);
 
 #ifdef CONFIG_PM_SLEEP
+/**
+ * cros_ec_suspend() - Handle a suspend operation for the ChromeOS EC device.
+ * @ec_dev: Device to suspend.
+ *
+ * This can be called by drivers to handle a suspend event.
+ *
+ * Return: 0 on success or negative error code.
+ */
 int cros_ec_suspend(struct cros_ec_device *ec_dev)
 {
struct device *dev = ec_dev->dev;
@@ -243,6 +268,14 @@ static void cros_ec_report_events_during_suspend(struct 
cros_ec_device *ec_dev)
 1, ec_dev);
 }
 
+/**
+ * cros_ec_resume() - Handle a resume operation for the ChromeOS EC device.
+ * @ec_dev: Device to resume.
+ *
+ * This can be called by drivers to handle a resume event.
+ *
+ * Return: 0 on success or negative error code.
+ */
 int cros_ec_resume(struct cros_ec_device *ec_dev)
 {
int ret;
diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index f659f96bda128..7db58771ec77c 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -117,6 +117,17 @@ static int send_command(struct cros_ec_device *ec_dev,
return ret;
 }
 
+/**
+ * cros_ec_prepare_tx() - Prepare an outgoing message in the output buffer.
+ * @ec_dev: Device to register.
+ * @msg: Message to write.
+ *
+ * This is intended to be used by all ChromeOS EC drivers, but at present
+ * only SPI uses it. Once LPC uses the same protocol it can start using it.
+ * I2C could use it now, with a refactor of the existing code.
+ *
+ * Return: 0 on success or negative error code.
+ */
 int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
   struct cros_ec_command *msg)
 {
@@ -141,6 +152,16 @@ int cros_ec_prepare_tx(struct cros_ec_device *ec_dev,
 }
 EXPORT_SYMBOL(cros_ec_prepare_tx);
 
+/**
+ * cros_ec_check_result() - Check ec_msg->result.
+ * @ec_dev: EC device.
+ * @msg: Message to check.
+ *
+ * This is used by ChromeOS EC drivers to check the ec_msg->result for
+ * errors and to warn about them.
+ *
+ * Return: 0 on success or negative error code.
+ */
 int cros_ec_check_result(struct cros_ec_device *ec_dev,
 struct cros_ec_command *msg)
 {
@@ -326,6 +347,13 @@ static int cros_ec_get_host_command_version_mask(struct 
cros_ec_device *ec_dev,
return ret;
 }
 
+/**
+ * cros_ec_query_all() -  Query the protocol version supported by the
+ * ChromeOS EC.
+ * @ec_dev: Device to register.
+ *
+ * Return: 0 on success or negative error code.
+ */
 int cros_ec_query_all(struct cros_ec_device *ec_dev)
 {
struct device *dev = ec_dev->dev;
@@ -453,6 +481,16 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev)
 }
 EXPORT_SYMBOL(cros_ec_query_all);
 
+/**
+ * cros_ec_cmd_xfer() - Send a command to the ChromeOS EC.
+ * @ec_dev: EC device.
+ * @msg: Message to write.
+ *
+ * Call this to send a command to the ChromeOS EC.  This should be used
+ * instead of calling the EC's cmd_xfer() callback directly.
+ *
+ * Return: 0 on success or negative error code.
+ */
 int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
 struct cros_ec_command *msg)
 {
@@ -500,6 +538,18 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
 }
 EXPORT_SYMBOL(cros_ec_cmd_xfer);
 
+/**
+ * cros_ec_cmd

[PATCH v2 08/18] Revert "Input: cros_ec_keyb - add back missing mask for event_type"

2019-10-20 Thread Gwendal Grignou
This reverts commit 62c3801619e16b68a37ea899b76572145dfe41c9.

This patch is not needed anymore since we clear EC_MKBP_HAS_MORE_EVENTS
flag before calling the notifiers in patch
"9d9518f5b52a (platform: chrome: cros_ec: handle MKBP more events flag)"

Signed-off-by: Gwendal Grignou 
---
New to v2.

 drivers/input/keyboard/cros_ec_keyb.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/input/keyboard/cros_ec_keyb.c 
b/drivers/input/keyboard/cros_ec_keyb.c
index 8d4d9786cc745..a29e81fdf1861 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -226,8 +226,6 @@ static int cros_ec_keyb_work(struct notifier_block *nb,
 {
struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
  notifier);
-   uint8_t mkbp_event_type = ckdev->ec->event_data.event_type &
- EC_MKBP_EVENT_TYPE_MASK;
u32 val;
unsigned int ev_type;
 
@@ -239,7 +237,7 @@ static int cros_ec_keyb_work(struct notifier_block *nb,
if (queued_during_suspend && !device_may_wakeup(ckdev->dev))
return NOTIFY_OK;
 
-   switch (mkbp_event_type) {
+   switch (ckdev->ec->event_data.event_type & EC_MKBP_EVENT_TYPE_MASK) {
case EC_MKBP_EVENT_KEY_MATRIX:
pm_wakeup_event(ckdev->dev, 0);
 
@@ -266,7 +264,7 @@ static int cros_ec_keyb_work(struct notifier_block *nb,
case EC_MKBP_EVENT_SWITCH:
pm_wakeup_event(ckdev->dev, 0);
 
-   if (mkbp_event_type == EC_MKBP_EVENT_BUTTON) {
+   if (ckdev->ec->event_data.event_type == EC_MKBP_EVENT_BUTTON) {
val = get_unaligned_le32(
&ckdev->ec->event_data.data.buttons);
ev_type = EV_KEY;
-- 
2.23.0.866.gb869b98d4c-goog



[PATCH v2 06/18] platform: chrome: cros_ec: Do not attempt to register a non-positive IRQ number

2019-10-20 Thread Gwendal Grignou
From: Enrico Granata 

Add a layer of sanity checking to cros_ec_register against attempting to
register IRQ values that are not strictly greater than 0.

Signed-off-by: Enrico Granata 
Signed-off-by: Gwendal Grignou 
---
Changes in v2:
  Remove dual Enrico's signature.

 drivers/platform/chrome/cros_ec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/platform/chrome/cros_ec.c 
b/drivers/platform/chrome/cros_ec.c
index 739f3cffe26e3..9b19f50572313 100644
--- a/drivers/platform/chrome/cros_ec.c
+++ b/drivers/platform/chrome/cros_ec.c
@@ -149,7 +149,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
return err;
}
 
-   if (ec_dev->irq) {
+   if (ec_dev->irq > 0) {
err = devm_request_threaded_irq(
dev, ec_dev->irq, ec_irq_handler,
ec_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-- 
2.23.0.866.gb869b98d4c-goog



[PATCH v2 16/18] iio: cros_ec: Expose hwfifo_timeout

2019-10-20 Thread Gwendal Grignou
Expose EC minimal interrupt period through buffer/hwfifo_timeout:
- Maximal timeout is limited to 65s.
- When timeout for all sensors is set to 0, EC will not send events,
  even if the sensor sampling rate is greater than 0.
- curr_sample_rate is no more, the pm functions have been removed.

Rename frequency to sampling_frequency to match IIO ABI.

Signed-off-by: Gwendal Grignou 
---
Changes in v2:
- Register fifo_attributes in sensors drivers that previously advertise
  that feature.


 .../common/cros_ec_sensors/cros_ec_sensors.c  |  4 +-
 .../cros_ec_sensors/cros_ec_sensors_core.c| 95 ++-
 drivers/iio/light/cros_ec_light_prox.c|  6 +-
 drivers/iio/pressure/cros_ec_baro.c   |  6 +-
 .../linux/iio/common/cros_ec_sensors_core.h   |  4 +-
 5 files changed, 85 insertions(+), 30 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 2eb4bb254fbde..8c57a3ade78ed 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -236,6 +236,9 @@ static int cros_ec_sensors_probe(struct platform_device 
*pdev)
if (ret)
return ret;
 
+   iio_buffer_set_attrs(indio_dev->buffer,
+   cros_ec_sensor_fifo_attributes);
+
indio_dev->info = &ec_sensors_info;
state = iio_priv(indio_dev);
for (channel = state->channels, i = CROS_EC_SENSOR_X;
@@ -247,7 +250,6 @@ static int cros_ec_sensors_probe(struct platform_device 
*pdev)
BIT(IIO_CHAN_INFO_CALIBSCALE);
channel->info_mask_shared_by_all =
BIT(IIO_CHAN_INFO_SCALE) |
-   BIT(IIO_CHAN_INFO_FREQUENCY) |
BIT(IIO_CHAN_INFO_SAMP_FREQ);
channel->info_mask_shared_by_all_available =
BIT(IIO_CHAN_INFO_SAMP_FREQ);
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
index e89c355bb4b35..92128c67a166e 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -84,6 +85,77 @@ static void get_default_min_max_freq(enum motionsensor_type 
type,
}
 }
 
+static int cros_ec_sensor_set_ec_rate(struct cros_ec_sensors_core_state *st,
+ int rate)
+{
+   int ret;
+
+   if (rate > U16_MAX)
+   rate = U16_MAX;
+
+   mutex_lock(&st->cmd_lock);
+   st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
+   st->param.ec_rate.data = rate;
+   ret = cros_ec_motion_send_host_cmd(st, 0);
+   mutex_unlock(&st->cmd_lock);
+   return ret;
+}
+
+static ssize_t cros_ec_sensor_set_report_latency(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+   int integer, fract, ret;
+   int latency;
+
+   ret = iio_str_to_fixpoint(buf, 10, &integer, &fract);
+   if (ret)
+   return ret;
+
+   /* EC rate is in ms. */
+   latency = integer * 1000 + fract / 1000;
+   ret = cros_ec_sensor_set_ec_rate(st, latency);
+   if (ret < 0)
+   return ret;
+
+   return len;
+}
+
+static ssize_t cros_ec_sensor_get_report_latency(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+   int latency, ret;
+
+   mutex_lock(&st->cmd_lock);
+   st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
+   st->param.ec_rate.data = EC_MOTION_SENSE_NO_VALUE;
+
+   ret = cros_ec_motion_send_host_cmd(st, 0);
+   latency = st->resp->ec_rate.ret;
+   mutex_unlock(&st->cmd_lock);
+   if (ret < 0)
+   return ret;
+
+   return sprintf(buf, "%d.%06u\n",
+  latency / 1000,
+  (latency % 1000) * 1000);
+}
+
+static IIO_DEVICE_ATTR(hwfifo_timeout, 0644,
+  cros_ec_sensor_get_report_latency,
+  cros_ec_sensor_set_report_latency, 0);
+
+const struct attribute *cros_ec_sensor_fifo_attributes[] = {
+   &iio_dev_attr_hwfifo_timeout.dev_attr.attr,
+   NULL,
+};
+EXPORT_SYMBOL_GPL(cros_ec_sensor_fifo_attributes);
+
 int cros_ec_sensors_push_data(
struct iio_dev 

[PATCH v2 18/18] iio: cros_ec: Use Hertz as unit for sampling frequency

2019-10-20 Thread Gwendal Grignou
To be compliant with other sensors, set and get sensor sampling
frequency in Hz, not mHz.

Fixes: ae7b02ad2f32 ("iio: common: cros_ec_sensors: Expose
cros_ec_sensors frequency range via iio sysfs")

Signed-off-by: Gwendal Grignou 
---
No changes in v2.

 .../cros_ec_sensors/cros_ec_sensors_core.c| 32 +++
 .../linux/iio/common/cros_ec_sensors_core.h   |  6 ++--
 2 files changed, 22 insertions(+), 16 deletions(-)

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
index f50e239f9a1e9..76dc8cad1b4b5 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -256,6 +256,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
struct cros_ec_dev *ec = sensor_hub->ec;
struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
u32 ver_mask;
+   int frequencies[ARRAY_SIZE(state->frequencies) / 2] = { 0 };
int ret, i;
 
platform_set_drvdata(pdev, indio_dev);
@@ -304,20 +305,22 @@ int cros_ec_sensors_core_init(struct platform_device 
*pdev,
state->calib[i].scale = MOTION_SENSE_DEFAULT_SCALE;
 
/* 0 is a correct value used to stop the device */
-   state->frequencies[0] = 0;
if (state->msg->version < 3) {
get_default_min_max_freq(state->resp->info.type,
-&state->frequencies[1],
-&state->frequencies[2],
+&frequencies[1],
+&frequencies[2],
 &state->fifo_max_event_count);
} else {
-   state->frequencies[1] =
-   state->resp->info_3.min_frequency;
-   state->frequencies[2] =
-   state->resp->info_3.max_frequency;
+   frequencies[1] = state->resp->info_3.min_frequency;
+   frequencies[2] = state->resp->info_3.max_frequency;
state->fifo_max_event_count =
state->resp->info_3.fifo_max_event_count;
}
+   for (i = 0; i < ARRAY_SIZE(frequencies); i++) {
+   state->frequencies[2 * i] = frequencies[i] / 1000;
+   state->frequencies[2 * i + 1] =
+   (frequencies[i] % 1000) * 1000;
+   }
 
ret = devm_iio_triggered_buffer_setup(
dev, indio_dev, NULL,
@@ -707,7 +710,7 @@ 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;
+   int ret, frequency;
 
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
@@ -719,8 +722,10 @@ int cros_ec_sensors_core_read(struct 
cros_ec_sensors_core_state *st,
if (ret)
break;
 
-   *val = st->resp->sensor_odr.ret;
-   ret = IIO_VAL_INT;
+   frequency = st->resp->sensor_odr.ret;
+   *val = frequency / 1000;
+   *val2 = (frequency % 1000) * 1000;
+   ret = IIO_VAL_INT_PLUS_MICRO;
break;
default:
ret = -EINVAL;
@@ -755,7 +760,7 @@ int cros_ec_sensors_core_read_avail(struct iio_dev 
*indio_dev,
case IIO_CHAN_INFO_SAMP_FREQ:
*length = ARRAY_SIZE(state->frequencies);
*vals = (const int *)&state->frequencies;
-   *type = IIO_VAL_INT;
+   *type = IIO_VAL_INT_PLUS_MICRO;
return IIO_AVAIL_LIST;
}
 
@@ -777,12 +782,13 @@ 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;
+   int ret, frequency;
 
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
+   frequency = val * 1000 + val2 / 1000;
st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
-   st->param.sensor_odr.data = val;
+   st->param.sensor_odr.data = frequency;
 
/* Always roundup, so caller gets at least what it asks for. */
st->param.sensor_odr.roundup = 1;
diff --git a/include/linux/iio/common/cros_ec_sensors_core.h 
b/include/linux/iio/common/cros_ec_sensors_core.h
index 4df3abd151fbf..256447b136296 100644
--- a/include/linux/iio/common/cro

[PATCH v2 04/18] platform/mfd:iio: cros_ec: Register sensor through sensorhub

2019-10-20 Thread Gwendal Grignou
- Remove duplicate code in mfd, since mfd just register
  cros_ec_sensorhub if at least one sensor is present
- Change iio cros_ec driver to get the pointer to the cros_ec_dev
  through cros_ec_sensorhub.

Signed-off-by: Gwendal Grignou 
---
Changes in v2:
- Remove unerelated changes.
- Remove ec presence test in iio driver, done in cros_ec_sensorhub.

 drivers/iio/accel/cros_ec_accel_legacy.c  |   6 -
 .../common/cros_ec_sensors/cros_ec_sensors.c  |   6 -
 .../cros_ec_sensors/cros_ec_sensors_core.c|   4 +-
 drivers/iio/light/cros_ec_light_prox.c|   6 -
 drivers/mfd/cros_ec_dev.c | 203 ++
 include/linux/platform_data/cros_ec_proto.h   |   8 -
 .../linux/platform_data/cros_ec_sensorhub.h   |   8 +
 7 files changed, 23 insertions(+), 218 deletions(-)

diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c 
b/drivers/iio/accel/cros_ec_accel_legacy.c
index fcc3f999e4827..65f85faf6f31d 100644
--- a/drivers/iio/accel/cros_ec_accel_legacy.c
+++ b/drivers/iio/accel/cros_ec_accel_legacy.c
@@ -163,16 +163,10 @@ static const struct iio_chan_spec 
cros_ec_accel_legacy_channels[] = {
 static int cros_ec_accel_legacy_probe(struct platform_device *pdev)
 {
struct device *dev = &pdev->dev;
-   struct cros_ec_dev *ec = dev_get_drvdata(dev->parent);
struct iio_dev *indio_dev;
struct cros_ec_sensors_core_state *state;
int ret;
 
-   if (!ec || !ec->ec_dev) {
-   dev_warn(&pdev->dev, "No EC device found.\n");
-   return -EINVAL;
-   }
-
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state));
if (!indio_dev)
return -ENOMEM;
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 a6987726eeb8a..7dce044734678 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -222,17 +222,11 @@ static const struct iio_info ec_sensors_info = {
 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 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;
-   }
-
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*state));
if (!indio_dev)
return -ENOMEM;
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
index d2609e6feda4d..81a7f692de2f3 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 static char *cros_ec_loc[] = {
@@ -88,7 +89,8 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
 {
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_sensorhub *sensor_hub = dev_get_drvdata(dev->parent);
+   struct cros_ec_dev *ec = sensor_hub->ec;
struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
u32 ver_mask;
int ret, i;
diff --git a/drivers/iio/light/cros_ec_light_prox.c 
b/drivers/iio/light/cros_ec_light_prox.c
index c5263b563fc19..d85a391e50c59 100644
--- a/drivers/iio/light/cros_ec_light_prox.c
+++ b/drivers/iio/light/cros_ec_light_prox.c
@@ -169,17 +169,11 @@ static const struct iio_info cros_ec_light_prox_info = {
 static int cros_ec_light_prox_probe(struct platform_device *pdev)
 {
struct device *dev = &pdev->dev;
-   struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
struct iio_dev *indio_dev;
struct cros_ec_light_prox_state *state;
struct iio_chan_spec *channel;
int ret;
 
-   if (!ec_dev || !ec_dev->ec_dev) {
-   dev_warn(dev, "No CROS EC device found.\n");
-   return -EINVAL;
-   }
-
indio_dev = devm_iio_device_alloc(dev, sizeof(*state));
if (!indio_dev)
return -ENOMEM;
diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
index a35104e35cb4e..c4b977a5dd966 100644
--- a/drivers/mfd/cros_ec_dev.c
+++ b/drivers/mfd/cros_ec_dev.c
@@ -78,6 +78,10 @@ static const struct mfd_cell cros_ec_rtc_cells[] = {
{ .name = "cros-ec-rtc", },
 };
 
+static const struct mfd_cell cros_ec_sensorhub_cells[] = {
+   { .name = "cros-ec-sensorhub", },
+};
+
 static

[PATCH v2 12/18] platform: chrome: sensorhub: Add median filter

2019-10-20 Thread Gwendal Grignou
Events are timestamped in EC time space, their timestamps need to be
converted in host time space.
The assumption is the time delta between when the interrupt is sent
by the EC and when it is receive by the host is a [small] constant.
This is not always true, even with hard-wired interrupt. To mitigate
worst offenders, add a median filter to weed out bigger than expected
delays.

Signed-off-by: Gwendal Grignou 
---
Changes in v2:
- Move some #define in .c to prevent name collisions.
- Add proper doxygen comments.
- Use /* instead of //


 .../platform/chrome/cros_ec_sensorhub_ring.c  | 504 +-
 .../linux/platform_data/cros_ec_sensorhub.h   |  65 +++
 2 files changed, 551 insertions(+), 18 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_sensorhub_ring.c 
b/drivers/platform/chrome/cros_ec_sensorhub_ring.c
index 0b851ac7c067e..090773af70f48 100644
--- a/drivers/platform/chrome/cros_ec_sensorhub_ring.c
+++ b/drivers/platform/chrome/cros_ec_sensorhub_ring.c
@@ -18,6 +18,21 @@
 #include 
 #include 
 
+/* Precision of fixed point for the m values from the filter */
+#define M_PRECISION (1 << 23)
+
+/* Only activate the filter once we have at least this many elements. */
+#define TS_HISTORY_THRESHOLD 8
+
+/*
+ * If we don't have any history entries for this long, empty the filter to
+ * make sure there are no big discontinuities.
+ */
+#define TS_HISTORY_BORED_US 50
+
+/* To measure by how much the filter is overshooting, if it happens. */
+#define FUTURE_TS_ANALYTICS_COUNT_MAX 100
+
 static inline int cros_sensorhub_send_sample(
struct cros_ec_sensorhub *sensorhub,
struct cros_ec_sensors_ring_sample *sample)
@@ -87,9 +102,11 @@ int cros_ec_sensorhub_ring_fifo_enable(
struct cros_ec_sensorhub *sensorhub,
bool on)
 {
-   int ret;
+   int ret, i;
 
mutex_lock(&sensorhub->cmd_lock);
+   for (i = 0; i < CROS_EC_SENSOR_MAX; i++)
+   sensorhub->last_batch_len[i] = 0;
sensorhub->params->cmd = MOTIONSENSE_CMD_FIFO_INT_ENABLE;
sensorhub->params->fifo_int_enable.enable = on;
 
@@ -105,6 +122,229 @@ int cros_ec_sensorhub_ring_fifo_enable(
return ret;
 }
 
+static int cros_ec_ring_median_cmp(const void *pv1, const void *pv2)
+{
+   s64 v1 = *(s64 *)pv1;
+   s64 v2 = *(s64 *)pv2;
+
+   if (v1 > v2)
+   return 1;
+   else if (v1 < v2)
+   return -1;
+   else
+   return 0;
+}
+
+/*
+ * cros_ec_ring_median: Gets median of an array of numbers
+ *
+ * For now it's implemented using an inefficient > O(n) sort then return
+ * the middle element. A more optimal method would be something like
+ * quickselect, but given that n = 64 we can probably live with it in the
+ * name of clarity.
+ *
+ * Warning: the input array gets modified (sorted)!
+ */
+static s64 cros_ec_ring_median(s64 *array, size_t length)
+{
+   sort(array, length, sizeof(s64), cros_ec_ring_median_cmp, NULL);
+   return array[length / 2];
+}
+
+/*
+ * IRQ Timestamp Filtering
+ *
+ * Lower down in cros_ec_ring_process_event(), for each sensor event we have to
+ * calculate it's timestamp in the AP timebase. There are 3 time points:
+ *   a - EC timebase, sensor event
+ *   b - EC timebase, IRQ
+ *   c - AP timebase, IRQ
+ *   a' - what we want: sensor even in AP timebase
+ *
+ * While a and b are recorded at accurate times (due to the EC real time
+ * nature); c is pretty untrustworthy, even though it's recorded the
+ * first thing in ec_irq_handler(). There is a very good change we'll get
+ * added lantency due to:
+ *   other irqs
+ *   ddrfreq
+ *   cpuidle
+ *
+ * Normally a' = c - b + a, but if we do that naive math any jitter in c
+ * will get coupled in a', which we don't want. We want a function
+ * a' = cros_ec_ring_ts_filter(a) which will filter out outliers in c.
+ *
+ * Think of a graph of AP time(b) on the y axis vs EC time(c) on the x axis.
+ * The slope of the line won't be exactly 1, there will be some clock drift
+ * between the 2 chips for various reasons (mechanical stress, temperature,
+ * voltage). We need to extrapolate values for a future x, without trusting
+ * recent y values too much.
+ *
+ * We use a median filter for the slope, then another median filter for the
+ * y-intercept to calculate this function:
+ *   dx[n] = x[n-1] - x[n]
+ *   dy[n] = x[n-1] - x[n]
+ *   m[n] = dy[n] / dx[n]
+ *   median_m = median(m[n-k:n])
+ *   error[i] = y[n-i] - median_m * x[n-i]
+ *   median_error = median(error[:k])
+ *   predicted_y = median_m * x + median_error
+ *
+ * Implementation differences from above:
+ * - Redefined y to be actually c - b, this gives us a lot more precision
+ * to do the math. (c-b)/b variations are more obvious than c/b variations.
+ * - Since we don't have floating point, any operations involving slope are
+ * done

[PATCH v2 17/18] iio: cros_ec: Report hwfifo_watermark_max

2019-10-20 Thread Gwendal Grignou
Report the maximum amount of sample the EC can hold.
This is not tunable, but can be useful for application to find out the
maximum amount of time it can sleep when hwfifo_timeout is set to a
large number.

Signed-off-by: Gwendal Grignou 
---
Changes in v2:
- Remove double lines, add line before return for visibility.

 .../cros_ec_sensors/cros_ec_sensors_core.c| 34 +--
 .../linux/iio/common/cros_ec_sensors_core.h   |  3 ++
 2 files changed, 35 insertions(+), 2 deletions(-)

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
index 92128c67a166e..f50e239f9a1e9 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -23,6 +23,12 @@
 #include 
 #include 
 
+/*
+ * Hard coded to the first device to support sensor fifo.  The EC has a 2048
+ * byte fifo and will trigger an interrupt when fifo is 2/3 full.
+ */
+#define CROS_EC_FIFO_SIZE (2048 * 2 / 3)
+
 static char *cros_ec_loc[] = {
[MOTIONSENSE_LOC_BASE] = "base",
[MOTIONSENSE_LOC_LID] = "lid",
@@ -56,8 +62,15 @@ static int cros_ec_get_host_cmd_version_mask(struct 
cros_ec_device *ec_dev,
 
 static void get_default_min_max_freq(enum motionsensor_type type,
 u32 *min_freq,
-u32 *max_freq)
+u32 *max_freq,
+u32 *max_fifo_events)
 {
+   /*
+* We don't know fifo size, set to size previously used by older
+* hardware.
+*/
+   *max_fifo_events = CROS_EC_FIFO_SIZE;
+
switch (type) {
case MOTIONSENSE_TYPE_ACCEL:
case MOTIONSENSE_TYPE_GYRO:
@@ -150,8 +163,22 @@ static IIO_DEVICE_ATTR(hwfifo_timeout, 0644,
   cros_ec_sensor_get_report_latency,
   cros_ec_sensor_set_report_latency, 0);
 
+static ssize_t hwfifo_watermark_max_show(
+   struct device *dev,
+   struct device_attribute *attr,
+   char *buf)
+{
+   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+
+   return sprintf(buf, "%d\n", st->fifo_max_event_count);
+}
+
+static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0);
+
 const struct attribute *cros_ec_sensor_fifo_attributes[] = {
&iio_dev_attr_hwfifo_timeout.dev_attr.attr,
+   &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
NULL,
 };
 EXPORT_SYMBOL_GPL(cros_ec_sensor_fifo_attributes);
@@ -281,12 +308,15 @@ int cros_ec_sensors_core_init(struct platform_device 
*pdev,
if (state->msg->version < 3) {
get_default_min_max_freq(state->resp->info.type,
 &state->frequencies[1],
-&state->frequencies[2]);
+&state->frequencies[2],
+&state->fifo_max_event_count);
} else {
state->frequencies[1] =
state->resp->info_3.min_frequency;
state->frequencies[2] =
state->resp->info_3.max_frequency;
+   state->fifo_max_event_count =
+   state->resp->info_3.fifo_max_event_count;
}
 
ret = devm_iio_triggered_buffer_setup(
diff --git a/include/linux/iio/common/cros_ec_sensors_core.h 
b/include/linux/iio/common/cros_ec_sensors_core.h
index 387ca9e61dac8..4df3abd151fbf 100644
--- a/include/linux/iio/common/cros_ec_sensors_core.h
+++ b/include/linux/iio/common/cros_ec_sensors_core.h
@@ -51,6 +51,7 @@ typedef irqreturn_t (*cros_ec_sensors_capture_t)(int irq, 
void *p);
  * the timestamp. The timestamp is always last and
  * is always 8-byte aligned.
  * @read_ec_sensors_data:  function used for accessing sensors values
+ * @fifo_max_event_count:  Size of the EC sensor FIFO
  */
 struct cros_ec_sensors_core_state {
struct cros_ec_device *ec;
@@ -73,6 +74,8 @@ struct cros_ec_sensors_core_state {
int (*read_ec_sensors_data)(struct iio_dev *indio_dev,
unsigned long scan_mask, s16 *data);
 
+   u32 fifo_max_event_count;
+
/* Table of known available frequencies : 0, Min and Max in mHz */
int frequencies[3];
 };
-- 
2.23.0.866.gb869b98d4c-goog



[PATCH v2 09/18] Revert "Input: cros_ec_keyb: mask out extra flags in event_type"

2019-10-20 Thread Gwendal Grignou
This reverts commit d096aa3eb6045a6a475a0239f3471c59eedf3d61.

This patch is not needed anymore since we clear EC_MKBP_HAS_MORE_EVENTS
flag before calling the notifiers in patch
"9d9518f5b52a (platform: chrome: cros_ec: handle MKBP more events flag)"

Signed-off-by: Gwendal Grignou 
---
New to v2.

 drivers/input/keyboard/cros_ec_keyb.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/input/keyboard/cros_ec_keyb.c 
b/drivers/input/keyboard/cros_ec_keyb.c
index a29e81fdf1861..2b71c5a51f907 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -237,7 +237,7 @@ static int cros_ec_keyb_work(struct notifier_block *nb,
if (queued_during_suspend && !device_may_wakeup(ckdev->dev))
return NOTIFY_OK;
 
-   switch (ckdev->ec->event_data.event_type & EC_MKBP_EVENT_TYPE_MASK) {
+   switch (ckdev->ec->event_data.event_type) {
case EC_MKBP_EVENT_KEY_MATRIX:
pm_wakeup_event(ckdev->dev, 0);
 
-- 
2.23.0.866.gb869b98d4c-goog



[PATCH v2 03/18] platform: cros_ec: Add cros_ec_sensor_hub driver

2019-10-20 Thread Gwendal Grignou
Similar to HID sensor stack, the new driver sits between cros_ec_dev
and the iio device drivers:

EC based iio device topology would be:
iio:device1 ->
...0/:00:1f.0/PNP0C09:00/GOOG0004:00/cros-ec-dev.6.auto/
 cros-ec-sensorhub.7.auto/
 cros-ec-accel.15.auto/
 iio:device1

It will be expanded to control EC sensor FIFO.

Signed-off-by: Gwendal Grignou 
---
Changes in v2:
- Remove unerelated changes.
- Fix spelling.
- Use !x instead of x == NULL
- Use platform_ API directly to register IIO sensors from
  cros_ec_sensorhub.

 drivers/iio/common/cros_ec_sensors/Kconfig|   2 +-
 drivers/platform/chrome/Kconfig   |  12 ++
 drivers/platform/chrome/Makefile  |   1 +
 drivers/platform/chrome/cros_ec_sensorhub.c   | 202 ++
 .../linux/platform_data/cros_ec_sensorhub.h   |  21 ++
 5 files changed, 237 insertions(+), 1 deletion(-)
 create mode 100644 drivers/platform/chrome/cros_ec_sensorhub.c
 create mode 100644 include/linux/platform_data/cros_ec_sensorhub.h

diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig 
b/drivers/iio/common/cros_ec_sensors/Kconfig
index cdbb29cfb9076..fefad95727907 100644
--- a/drivers/iio/common/cros_ec_sensors/Kconfig
+++ b/drivers/iio/common/cros_ec_sensors/Kconfig
@@ -4,7 +4,7 @@
 #
 config IIO_CROS_EC_SENSORS_CORE
tristate "ChromeOS EC Sensors Core"
-   depends on SYSFS && CROS_EC
+   depends on SYSFS && CROS_EC_SENSORHUB
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index ee5f08ea57b6c..56a25317a6bee 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -190,6 +190,18 @@ config CROS_EC_DEBUGFS
  To compile this driver as a module, choose M here: the
  module will be called cros_ec_debugfs.
 
+config CROS_EC_SENSORHUB
+   tristate "ChromeOS EC MEMS Sensor Hub"
+   depends on CROS_EC && IIO
+   help
+ Allow loading IIO sensors. This driver is loaded by MFD and will in
+ turn query the EC and register the sensors.
+ It also spreads the sensor data coming from the EC to the IIO sensor
+ object.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cros_ec_sensorhub.
+
 config CROS_EC_SYSFS
tristate "ChromeOS EC control and information through sysfs"
depends on MFD_CROS_EC_DEV && SYSFS
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 477ec3d1d1c98..a164c40dc0996 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_CROS_EC_PROTO)   += cros_ec_proto.o 
cros_ec_trace.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_chardev.o
 obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o
+obj-$(CONFIG_CROS_EC_SENSORHUB)+= cros_ec_sensorhub.o
 obj-$(CONFIG_CROS_EC_VBC)  += cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_DEBUGFS)  += cros_ec_debugfs.o
 obj-$(CONFIG_CROS_EC_SYSFS)+= cros_ec_sysfs.o
diff --git a/drivers/platform/chrome/cros_ec_sensorhub.c 
b/drivers/platform/chrome/cros_ec_sensorhub.c
new file mode 100644
index 0..5fea4c28c5c95
--- /dev/null
+++ b/drivers/platform/chrome/cros_ec_sensorhub.c
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SensorHub: driver that discover sensors behind
+ * a ChromeOS Embedded controller.
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define DRV_NAME   "cros-ec-sensorhub"
+
+
+static struct device_type cros_ec_sensorhub_dev_type = {
+   .name   = "cros_ec_iio_sensor",
+};
+
+static int cros_ec_sensorhub_allocate_single_sensor(
+   struct device *parent,
+   char *sensor_name,
+   int sensor_num)
+{
+   struct platform_device *pdev;
+   struct cros_ec_sensor_platform sensor_platforms = {
+   .sensor_num = sensor_num,
+   };
+   int ret;
+
+   pdev = platform_device_alloc(sensor_name, PLATFORM_DEVID_AUTO);
+   if (!pdev)
+   return -ENOMEM;
+
+   pdev->dev.parent = parent;
+   pdev->dev.type = &cros_ec_sensorhub_dev_type;
+
+   ret = platform_device_add_data(pdev, &sensor_platforms,
+   sizeof(sensor_platforms));
+   if (ret)
+   goto fail_device;
+
+   ret = platform_device_add(pdev);
+   if (ret)
+   goto fail_device;
+
+   return 0;
+
+fail_device:
+ 

[PATCH v2 13/18] iio: cros_ec: Move function description to .c file

2019-10-20 Thread Gwendal Grignou
To prevent comment rot, move function description to
cros_ec_sensors_core.c.

Signed-off-by: Gwendal Grignou 
---
New in v2.

 .../cros_ec_sensors/cros_ec_sensors_core.c| 69 
 .../linux/iio/common/cros_ec_sensors_core.h   | 80 ---
 2 files changed, 69 insertions(+), 80 deletions(-)

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
index 81a7f692de2f3..4acb8b7310d43 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -83,6 +83,14 @@ static void get_default_min_max_freq(enum motionsensor_type 
type,
}
 }
 
+/**
+ * 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)
@@ -160,6 +168,16 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init);
 
+/**
+ * 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 *state,
 u16 opt_length)
 {
@@ -422,6 +440,14 @@ int cros_ec_sensors_read_lpc(struct iio_dev *indio_dev,
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_read_lpc);
 
+/**
+ * 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)
 {
@@ -446,6 +472,18 @@ int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev,
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_read_cmd);
 
+/**
+ * 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)
 {
struct iio_poll_func *pf = p;
@@ -481,6 +519,16 @@ irqreturn_t cros_ec_sensors_capture(int irq, void *p)
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_capture);
 
+/**
+ * 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)
@@ -521,6 +569,17 @@ int cros_ec_sensors_core_read(struct 
cros_ec_sensors_core_state *st,
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read);
 
+/**
+ * cros_ec_sensors_core_read_avail() - get available values
+ * @indio_dev: pointer to state information for device
+ * @chan:  channel specification structure table
+ * @vals:  list of available values
+ * @type:  type of data returned
+ * @length:number of data returned in the array
+ * @mask:  specifies which values to be requested
+ *
+ * Return: an error code, IIO_AVAIL_RANGE or IIO_AVAIL_LIST
+ */
 int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
const int **vals,
@@ -542,6 +601,16 @@ int cros_ec_sensors_core_read_avail(struct iio_dev 
*indio_dev,
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read_avail);
 
+/**
+ * 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
+ * @

[PATCH v2 15/18] iio: cros_ec: Remove pm function

2019-10-20 Thread Gwendal Grignou
Since cros_ec_sensorhub is shutting down the FIFO when the device
suspends, no need to slow down the EC sampling period rate.
It was necesseary to do that before command CMD_FIFO_INT_ENABLE was
introduced, but now all supported chromebooks have it.

Signed-off-by: Gwendal Grignou 
---
New in v2.

 .../cros_ec_sensors/cros_ec_lid_angle.c   |  1 -
 .../common/cros_ec_sensors/cros_ec_sensors.c  |  1 -
 .../cros_ec_sensors/cros_ec_sensors_core.c| 47 ---
 drivers/iio/light/cros_ec_light_prox.c|  1 -
 .../linux/iio/common/cros_ec_sensors_core.h   |  5 --
 5 files changed, 55 deletions(-)

diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c 
b/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c
index e30a59fcf0f95..af801e203623e 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c
@@ -127,7 +127,6 @@ MODULE_DEVICE_TABLE(platform, cros_ec_lid_angle_ids);
 static struct platform_driver cros_ec_lid_angle_platform_driver = {
.driver = {
.name   = DRV_NAME,
-   .pm = &cros_ec_sensors_pm_ops,
},
.probe  = cros_ec_lid_angle_probe,
.id_table   = cros_ec_lid_angle_ids,
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 9e7903ff99f80..2eb4bb254fbde 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -314,7 +314,6 @@ MODULE_DEVICE_TABLE(platform, cros_ec_sensors_ids);
 static struct platform_driver cros_ec_sensors_platform_driver = {
.driver = {
.name   = "cros-ec-sensors",
-   .pm = &cros_ec_sensors_pm_ops,
},
.probe  = cros_ec_sensors_probe,
.id_table   = cros_ec_sensors_ids,
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
index 3d2e17093c75a..e89c355bb4b35 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -716,52 +716,5 @@ int cros_ec_sensors_core_write(struct 
cros_ec_sensors_core_state *st,
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_write);
 
-static int __maybe_unused cros_ec_sensors_prepare(struct device *dev)
-{
-   struct iio_dev *indio_dev = dev_get_drvdata(dev);
-   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
-
-   if (st->curr_sampl_freq == 0)
-   return 0;
-
-   /*
-* If the sensors are sampled at high frequency, we will not be able to
-* sleep. Set sampling to a long period if necessary.
-*/
-   if (st->curr_sampl_freq < CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY) {
-   mutex_lock(&st->cmd_lock);
-   st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
-   st->param.ec_rate.data = CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY;
-   cros_ec_motion_send_host_cmd(st, 0);
-   mutex_unlock(&st->cmd_lock);
-   }
-   return 0;
-}
-
-static void __maybe_unused cros_ec_sensors_complete(struct device *dev)
-{
-   struct iio_dev *indio_dev = dev_get_drvdata(dev);
-   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
-
-   if (st->curr_sampl_freq == 0)
-   return;
-
-   if (st->curr_sampl_freq < CROS_EC_MIN_SUSPEND_SAMPLING_FREQUENCY) {
-   mutex_lock(&st->cmd_lock);
-   st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
-   st->param.ec_rate.data = st->curr_sampl_freq;
-   cros_ec_motion_send_host_cmd(st, 0);
-   mutex_unlock(&st->cmd_lock);
-   }
-}
-
-const struct dev_pm_ops cros_ec_sensors_pm_ops = {
-#ifdef CONFIG_PM_SLEEP
-   .prepare = cros_ec_sensors_prepare,
-   .complete = cros_ec_sensors_complete
-#endif
-};
-EXPORT_SYMBOL_GPL(cros_ec_sensors_pm_ops);
-
 MODULE_DESCRIPTION("ChromeOS EC sensor hub core functions");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/light/cros_ec_light_prox.c 
b/drivers/iio/light/cros_ec_light_prox.c
index da40c38370965..6bac02cdd898a 100644
--- a/drivers/iio/light/cros_ec_light_prox.c
+++ b/drivers/iio/light/cros_ec_light_prox.c
@@ -255,7 +255,6 @@ MODULE_DEVICE_TABLE(platform, cros_ec_light_prox_ids);
 static struct platform_driver cros_ec_light_prox_platform_driver = {
.driver = {
.name   = "cros-ec-light-prox",
-   .pm = &cros_ec_sensors_pm_ops,
},
.probe  = cros_ec_light_prox_probe,
.id_table   = cros_ec_light_prox_ids,
diff --git a/include/linux/iio/common/cros_ec_sensors_core.h 
b/include/linux/iio/common/cros_ec_sensors_core.h
index b4eb3790cde11..db3da7ffcc376 100644
--- a/inc

[PATCH v2 11/18] platform: chrome: sensorhub: Add code to spread timestmap

2019-10-20 Thread Gwendal Grignou
EC FIFO can send sensor events in batch. Spread them based on
previous (TSa) and currnet timestamp (TSb)

  EC FIFO iio events
+---+
| TSa   |
+---+ +---+
| event 1   | | event 1 | TSb - (TSb - TSa)/n * (n-1) |
+---+ +---+
| event 2   | | event 2 | TSb - (TSb - TSa)/n * (n-2) |
+---+ +---+
|  ...  |  -->|     | |
+---+ +---+
| event n-1 | | event 2 | TSb - (TSb - TSa)/n |
+---+ +---+
| event n   | | event 2 | TSb |
+---+ +---+
| TSb   |
+---+

Signed-off-by: Gwendal Grignou 
---
Changes in v2:
- Use CROS_EC_SENSOR_LAST_TS instead of LAST_TS to avoid name colisions.

 .../platform/chrome/cros_ec_sensorhub_ring.c  | 99 ++-
 1 file changed, 96 insertions(+), 3 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_sensorhub_ring.c 
b/drivers/platform/chrome/cros_ec_sensorhub_ring.c
index caf4b02d5e345..0b851ac7c067e 100644
--- a/drivers/platform/chrome/cros_ec_sensorhub_ring.c
+++ b/drivers/platform/chrome/cros_ec_sensorhub_ring.c
@@ -183,6 +183,97 @@ static bool cros_ec_ring_process_event(
return true;
 }
 
+/*
+ * cros_ec_ring_spread_add: Calculate proper timestamps then
+ * add to ringbuffer (legacy).
+ *
+ * If there is a sample with a proper timestamp
+ *timestamp | count
+ * older_unprocess_out --> TS1  | 1
+ * TS1  | 2
+ * out --> TS1  | 3
+ * next_out -->TS2  |
+ * We spread time for the samples [older_unprocess_out .. out]
+ * between TS1 and TS2: [TS1+1/4, TS1+2/4, TS1+3/4, TS2].
+ *
+ * If we reach the end of the samples, we compare with the
+ * current timestamp:
+ *
+ * older_unprocess_out --> TS1  | 1
+ * TS1  | 2
+ * out --> TS1  | 3
+ * We know have [TS1+1/3, TS1+2/3, current timestamp]
+ */
+static void cros_ec_ring_spread_add(
+   struct cros_ec_sensorhub *sensorhub,
+   unsigned long sensor_mask,
+   s64 current_timestamp,
+   struct cros_ec_sensors_ring_sample *last_out)
+{
+   struct cros_ec_sensors_ring_sample *out;
+   int i;
+
+   for_each_set_bit(i, &sensor_mask, BITS_PER_LONG) {
+   s64 older_timestamp;
+   s64 timestamp;
+   struct cros_ec_sensors_ring_sample *older_unprocess_out =
+   sensorhub->ring;
+   struct cros_ec_sensors_ring_sample *next_out;
+   int count = 1;
+
+   for (out = sensorhub->ring; out < last_out; out = next_out) {
+   s64 time_period;
+
+   next_out = out + 1;
+   if (out->sensor_id != i)
+   continue;
+
+   /* Timestamp to start with */
+   older_timestamp = out->timestamp;
+
+   /* find next sample */
+   while (next_out < last_out && next_out->sensor_id != i)
+   next_out++;
+
+   if (next_out >= last_out) {
+   timestamp = current_timestamp;
+   } else {
+   timestamp = next_out->timestamp;
+   if (timestamp == older_timestamp) {
+   count++;
+   continue;
+   }
+   }
+
+   /*
+* The next sample has a new timestamp,
+* spread the unprocessed samples.
+*/
+   if (next_out < last_out)
+   count++;
+   time_period = div_s64(timestamp - older_timestamp,
+ count);
+
+   for (; older_unprocess_out <= out;
+   older_unprocess_out++) {
+   if (older_unprocess_out->sensor_id != i)
+   continue;
+   older_timestamp += time_period;
+   older_unprocess_out->timestamp =
+   older_timestamp;
+   }
+   count = 1;
+

[PATCH v2 07/18] platform: chrome: cros_ec: handle MKBP more events flag

2019-10-20 Thread Gwendal Grignou
From: Enrico Granata 

The ChromeOS EC has support for signaling to the host that
a single IRQ can serve multiple MKBP (Matrix KeyBoard Protocol)
events.

Doing this serves an optimization purpose, as it minimizes the
number of round-trips into the interrupt handling machinery, and
it proves beneficial to sensor timestamping as it keeps the desired
synchronization of event times between the two processors.

This patch adds kernel support for this EC feature, allowing the
ec_irq to loop until all events have been served.

Signed-off-by: Enrico Granata 
Signed-off-by: Gwendal Grignou 
---
Changes in v2:
  Process flag inside cros_ec_get_next_event, clean flag from event.
  Introduce public function cros_ec_handle_event(), use it in rpmsg and
ishtp transport layer.
  Remplace dev_info with dev_dbg, call only once.

 drivers/platform/chrome/cros_ec.c   | 35 +++--
 drivers/platform/chrome/cros_ec_ishtp.c |  8 +-
 drivers/platform/chrome/cros_ec_lpc.c   | 15 +++-
 drivers/platform/chrome/cros_ec_proto.c | 81 +
 drivers/platform/chrome/cros_ec_rpmsg.c | 23 ++
 include/linux/platform_data/cros_ec_proto.h | 12 ++-
 6 files changed, 110 insertions(+), 64 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec.c 
b/drivers/platform/chrome/cros_ec.c
index 9b19f50572313..eb7f60140e2c1 100644
--- a/drivers/platform/chrome/cros_ec.c
+++ b/drivers/platform/chrome/cros_ec.c
@@ -40,13 +40,24 @@ static irqreturn_t ec_irq_handler(int irq, void *data)
return IRQ_WAKE_THREAD;
 }
 
-static irqreturn_t ec_irq_thread(int irq, void *data)
+/**
+ * cros_ec_handle_event - process and forward pending events on EC
+ *
+ * Call this function in a loop when the kernel is notified that the EC has
+ * pending events.
+ *
+ * Returns true if more events are still pending and this function should be
+ * called again.
+ */
+bool cros_ec_handle_event(struct cros_ec_device *ec_dev)
 {
-   struct cros_ec_device *ec_dev = data;
-   bool wake_event = true;
+   bool wake_event;
+   bool ec_has_more_events;
int ret;
 
-   ret = cros_ec_get_next_event(ec_dev, &wake_event);
+   ret = cros_ec_get_next_event(ec_dev,
+   &wake_event,
+   &ec_has_more_events);
 
/*
 * Signal only if wake host events or any interrupt if
@@ -59,6 +70,20 @@ static irqreturn_t ec_irq_thread(int irq, void *data)
if (ret > 0)
blocking_notifier_call_chain(&ec_dev->event_notifier,
 0, ec_dev);
+
+   return ec_has_more_events;
+}
+EXPORT_SYMBOL(cros_ec_handle_event);
+
+static irqreturn_t ec_irq_thread(int irq, void *data)
+{
+   struct cros_ec_device *ec_dev = data;
+   bool ec_has_more_events;
+
+   do {
+   ec_has_more_events = cros_ec_handle_event(ec_dev);
+   } while (ec_has_more_events);
+
return IRQ_HANDLED;
 }
 
@@ -273,7 +298,7 @@ EXPORT_SYMBOL(cros_ec_suspend);
 static void cros_ec_report_events_during_suspend(struct cros_ec_device *ec_dev)
 {
while (ec_dev->mkbp_event_supported &&
-  cros_ec_get_next_event(ec_dev, NULL) > 0)
+  cros_ec_get_next_event(ec_dev, NULL, NULL) > 0)
blocking_notifier_call_chain(&ec_dev->event_notifier,
 1, ec_dev);
 }
diff --git a/drivers/platform/chrome/cros_ec_ishtp.c 
b/drivers/platform/chrome/cros_ec_ishtp.c
index 5c848f22b44b4..e5996821d08b3 100644
--- a/drivers/platform/chrome/cros_ec_ishtp.c
+++ b/drivers/platform/chrome/cros_ec_ishtp.c
@@ -136,11 +136,11 @@ static void ish_evt_handler(struct work_struct *work)
struct ishtp_cl_data *client_data =
container_of(work, struct ishtp_cl_data, work_ec_evt);
struct cros_ec_device *ec_dev = client_data->ec_dev;
+   bool ec_has_more_events;
 
-   if (cros_ec_get_next_event(ec_dev, NULL) > 0) {
-   blocking_notifier_call_chain(&ec_dev->event_notifier,
-0, ec_dev);
-   }
+   do {
+   ec_has_more_events = cros_ec_handle_event(ec_dev);
+   } while (ec_has_more_events);
 }
 
 /**
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index 3c77496e164da..7d2db3d2b094a 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -312,13 +312,20 @@ static int cros_ec_lpc_readmem(struct cros_ec_device *ec, 
unsigned int offset,
 static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
 {
struct cros_ec_device *ec_dev = data;
+   bool ec_has_more_events;
+   int ret;
 
ec_dev->last_event_time = cros_ec_get_time_ns();
 
-   if (ec_dev->mkbp_event_supported &&
-   cros_ec_get_next_event(ec_dev, NULL) >

[PATCH v2 10/18] platform: chrome: sensorhub: Add FIFO support

2019-10-20 Thread Gwendal Grignou
cros_ec_sensorhub registers a listener and query motion sense FIFO,
spread to iio sensors registers.

To test, we can use libiio:
iiod&
iio_readdev -u ip:localhost -T 1 -s 25 -b 16 cros-ec-gyro | od -x

Signed-off-by: Gwendal Grignou 
---
Changes sunce v2:
- Do not register a .remove routinge in plaform_driver. A
  devm_action_add is added later patch IIO driver register their
callback.
- Remove double lines, add lines before return calls.
- Handle FLUSH flag from EC.
- Use ktime_t for most timestamp measurements.
- Add doxygen comments
- Cleanup timestamp collection when processing FIFO.
- Rename fifo_toggle to fifo_enable

 drivers/platform/chrome/Makefile  |   3 +-
 drivers/platform/chrome/cros_ec_sensorhub.c   | 123 --
 .../platform/chrome/cros_ec_sensorhub_ring.c  | 412 ++
 .../linux/platform_data/cros_ec_sensorhub.h   |  77 
 4 files changed, 583 insertions(+), 32 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_sensorhub_ring.c

diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index a164c40dc0996..cb709048c003e 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -17,7 +17,8 @@ obj-$(CONFIG_CROS_EC_PROTO)   += cros_ec_proto.o 
cros_ec_trace.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_chardev.o
 obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o
-obj-$(CONFIG_CROS_EC_SENSORHUB)+= cros_ec_sensorhub.o
+cros_ec_sensorsupport-objs := cros_ec_sensorhub_ring.o 
cros_ec_sensorhub.o
+obj-$(CONFIG_CROS_EC_SENSORHUB)+= cros_ec_sensorsupport.o
 obj-$(CONFIG_CROS_EC_VBC)  += cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_DEBUGFS)  += cros_ec_debugfs.o
 obj-$(CONFIG_CROS_EC_SYSFS)+= cros_ec_sysfs.o
diff --git a/drivers/platform/chrome/cros_ec_sensorhub.c 
b/drivers/platform/chrome/cros_ec_sensorhub.c
index 5fea4c28c5c95..87308dadc32c5 100644
--- a/drivers/platform/chrome/cros_ec_sensorhub.c
+++ b/drivers/platform/chrome/cros_ec_sensorhub.c
@@ -24,7 +24,6 @@
 
 #define DRV_NAME   "cros-ec-sensorhub"
 
-
 static struct device_type cros_ec_sensorhub_dev_type = {
.name   = "cros_ec_iio_sensor",
 };
@@ -64,14 +63,13 @@ static int cros_ec_sensorhub_allocate_single_sensor(
 }
 
 static int cros_ec_sensorhub_register(struct device *dev,
-   struct cros_ec_dev *ec)
+   struct cros_ec_sensorhub *sensorhub)
 {
int ret, i, id, sensor_num;
int sensor_type[MOTIONSENSE_TYPE_MAX] = { 0 };
-   struct ec_params_motion_sense *params;
-   struct ec_response_motion_sense *resp;
-   struct cros_ec_command *msg;
char *name;
+   struct cros_ec_command *msg = sensorhub->msg;
+   struct cros_ec_dev *ec = sensorhub->ec;
 
sensor_num = cros_ec_get_sensor_count(ec);
if (sensor_num < 0) {
@@ -86,32 +84,21 @@ static int cros_ec_sensorhub_register(struct device *dev,
return -EINVAL;
}
 
-   /* Prepare a message to send INFO command to each sensor. */
-   msg = kzalloc(sizeof(struct cros_ec_command) +
- max(sizeof(*params), sizeof(*resp)), GFP_KERNEL);
-   if (!msg) {
-   ret = -ENOMEM;
-   goto error;
-   }
-
msg->version = 1;
-   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;
-   resp = (struct ec_response_motion_sense *)msg->data;
+   msg->insize = sizeof(struct ec_response_motion_sense);
+   msg->outsize = sizeof(struct ec_params_motion_sense);
 
id = 0;
for (i = 0; i < sensor_num; i++) {
-   params->cmd = MOTIONSENSE_CMD_INFO;
-   params->info.sensor_num = i;
+   sensorhub->params->cmd = MOTIONSENSE_CMD_INFO;
+   sensorhub->params->info.sensor_num = i;
ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
if (ret < 0) {
dev_warn(dev, "no info for EC sensor %d : %d/%d\n",
 i, ret, msg->result);
continue;
}
-   switch (resp->info.type) {
+   switch (sensorhub->resp->info.type) {
case MOTIONSENSE_TYPE_ACCEL:
name = "cros-ec-accel";
break;
@@ -134,14 +121,15 @@ static int cros_ec_sensorhub_register(struct device *dev,
name = "cros-ec-activity";
break;
default:
-   dev_warn(dev, "unknown type %d\n"

[PATCH v2 14/18] iio: cros_ec: Register to cros_ec_sensorhub when EC supports FIFO

2019-10-20 Thread Gwendal Grignou
When EC supports FIFO, each IIO device registers a callback, to put
samples in the buffer when they arrives from the FIFO.
We can still use a trigger to collect samples, but there may be some
duplications in the buffer: EC has a single FIFO, so once one sensor is
using it, all sensors event will be in the FIFO.
To be sure events generated by cros_ec_sensorhub or the trigger uses the
same time domain, current_timestamp_clock must be set to "boottime".

When no FIFO, the user space app needs to call trigger_new, or better
register a high precision timer.

Signed-off-by: Gwendal Grignou 
---
Change in v2 from "Use triggered buffer only when EC does not support
FIFO":
- Keep trigger all the time.
- Add  devm_add_action to cleanup callback registration.
- EC that "reports" legacy sensors do not have FIFO.
- Use iiio_is_buffer_enabled instead of checking the scan_mask
  before sending samples to buffer.
- Add empty lines for visibility.

 drivers/iio/accel/cros_ec_accel_legacy.c  |  8 +-
 .../cros_ec_sensors/cros_ec_lid_angle.c   |  2 +-
 .../common/cros_ec_sensors/cros_ec_sensors.c  |  8 +-
 .../cros_ec_sensors/cros_ec_sensors_core.c| 80 ++-
 drivers/iio/light/cros_ec_light_prox.c|  8 +-
 drivers/iio/pressure/cros_ec_baro.c   |  8 +-
 .../linux/iio/common/cros_ec_sensors_core.h   | 12 ++-
 7 files changed, 96 insertions(+), 30 deletions(-)

diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c 
b/drivers/iio/accel/cros_ec_accel_legacy.c
index 65f85faf6f31d..66683df9fc433 100644
--- a/drivers/iio/accel/cros_ec_accel_legacy.c
+++ b/drivers/iio/accel/cros_ec_accel_legacy.c
@@ -171,7 +171,8 @@ static int cros_ec_accel_legacy_probe(struct 
platform_device *pdev)
if (!indio_dev)
return -ENOMEM;
 
-   ret = cros_ec_sensors_core_init(pdev, indio_dev, true);
+   ret = cros_ec_sensors_core_init(pdev, indio_dev, true,
+   cros_ec_sensors_capture, NULL);
if (ret)
return ret;
 
@@ -191,11 +192,6 @@ static int cros_ec_accel_legacy_probe(struct 
platform_device *pdev)
state->sign[CROS_EC_SENSOR_Z] = -1;
}
 
-   ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
-   cros_ec_sensors_capture, NULL);
-   if (ret)
-   return ret;
-
return devm_iio_device_register(dev, indio_dev);
 }
 
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c 
b/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c
index 1dcc2a16ab2dd..e30a59fcf0f95 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c
@@ -97,7 +97,7 @@ static int cros_ec_lid_angle_probe(struct platform_device 
*pdev)
if (!indio_dev)
return -ENOMEM;
 
-   ret = cros_ec_sensors_core_init(pdev, indio_dev, false);
+   ret = cros_ec_sensors_core_init(pdev, indio_dev, false, NULL, NULL);
if (ret)
return ret;
 
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 7dce044734678..9e7903ff99f80 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -231,7 +231,8 @@ static int cros_ec_sensors_probe(struct platform_device 
*pdev)
if (!indio_dev)
return -ENOMEM;
 
-   ret = cros_ec_sensors_core_init(pdev, indio_dev, true);
+   ret = cros_ec_sensors_core_init(pdev, indio_dev, true,
+   cros_ec_sensors_capture, cros_ec_sensors_push_data);
if (ret)
return ret;
 
@@ -293,11 +294,6 @@ static int cros_ec_sensors_probe(struct platform_device 
*pdev)
else
state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;
 
-   ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
-   cros_ec_sensors_capture, NULL);
-   if (ret)
-   return ret;
-
return devm_iio_device_register(dev, indio_dev);
 }
 
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
index 4acb8b7310d43..3d2e17093c75a 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -83,17 +84,72 @@ static void get_default_min_max_freq(enum motionsensor_type 
type,
}
 }
 
+int cros_ec_sensors_push_data(
+   struct iio_dev *indio_dev,
+   s16 *data,
+   s64 timestamp)
+{
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+   s16 *out;
+   unsigned int i;
+
+   /*
+* It can happen if we get a samples before the iio device is fully
+* reg

[PATCH v2 02/18] mfd: cros_ec: Add sensor_count and make check_features public

2019-10-20 Thread Gwendal Grignou
Add a new function to return the number of MEMS sensors available in a
ChromeOS Embedded Controller.
It uses MOTIONSENSE_CMD_DUMP if available or a specific memory map ACPI
registers to find out.

Also, make check_features public as it can be useful for other drivers
to know what the Embedded Controller supports.

Signed-off-by: Gwendal Grignou 
---
Changes in v2:
  Fix spelling in commit message.
  Cleanup the case where DUMP command is not supported.
  Move code from mfd to platform/chrome/

 drivers/mfd/cros_ec_dev.c   |  32 --
 drivers/platform/chrome/cros_ec_proto.c | 116 
 include/linux/platform_data/cros_ec_proto.h |   5 +
 3 files changed, 121 insertions(+), 32 deletions(-)

diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
index 6e6dfd6c18711..a35104e35cb4e 100644
--- a/drivers/mfd/cros_ec_dev.c
+++ b/drivers/mfd/cros_ec_dev.c
@@ -112,38 +112,6 @@ static const struct mfd_cell cros_ec_vbc_cells[] = {
{ .name = "cros-ec-vbc", }
 };
 
-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 = kzalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL);
-   if (!msg)
-   return -ENOMEM;
-
-   msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset;
-   msg->insize = sizeof(ec->features);
-
-   ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
-   if (ret < 0) {
-   dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
-ret, msg->result);
-   memset(ec->features, 0, sizeof(ec->features));
-   } else {
-   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);
-}
-
 static void cros_ec_class_release(struct device *dev)
 {
kfree(to_cros_ec_dev(dev));
diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index 7db58771ec77c..2357c717399ad 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -717,3 +717,119 @@ u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev)
return host_event;
 }
 EXPORT_SYMBOL(cros_ec_get_host_event);
+
+/**
+ * cros_ec_check_features - Test for the presence of EC features
+ *
+ * Call this function to test whether the ChromeOS EC supports a feature.
+ *
+ * @ec_dev: EC device: does not have to be connected directly to the AP,
+ *  can be daisy chained through another device.
+ * @feature: One of ec_feature_code bit.
+ * @return: 1 if supported, 0 if not
+ */
+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 = kzalloc(sizeof(*msg) + sizeof(ec->features), GFP_KERNEL);
+   if (!msg)
+   return -ENOMEM;
+
+   msg->command = EC_CMD_GET_FEATURES + ec->cmd_offset;
+   msg->insize = sizeof(ec->features);
+
+   ret = cros_ec_cmd_xfer_status(ec->ec_dev, msg);
+   if (ret < 0) {
+   dev_warn(ec->dev, "cannot get EC features: %d/%d\n",
+ret, msg->result);
+   memset(ec->features, 0, sizeof(ec->features));
+   } else {
+   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);
+}
+EXPORT_SYMBOL_GPL(cros_ec_check_features);
+
+/**
+ * Return the number of MEMS sensors supported.
+ *
+ * @ec_dev: EC device: does not have to be connected directly to the AP,
+ *  can be daisy chained through another device.
+ * Return < 0 in case of error.
+ */
+int cros_ec_get_sensor_count(struct cros_ec_dev *ec)
+{
+   /*
+* Issue a command to get the number of sensor reported.
+* If not supported, check for legacy mode.
+*/
+   int ret, sensor_count;
+   struct ec_params_motion_sense *params;
+   struct ec_response_motion_sense *r

[PATCH v2 05/18] platform: chrome: cros-ec: record event timestamp in the hard irq

2019-10-20 Thread Gwendal Grignou
To improve sensor timestamp precision, given EC and AP are in
different time domains, the AP needs to try to record the exact
moment an event was signalled to the AP by the EC as soon as
possible after it happens.

First thing in the hard irq is the best place for this.

Signed-off-by: Gwendal Grignou 
---
Changes in v2:
  Make cros_ec_get_time_ns inline.
  Using ktime_t instead of s64 when dealing with time.
  Added code in ishtp to gather timestamp.

 drivers/platform/chrome/cros_ec.c   | 12 +++-
 drivers/platform/chrome/cros_ec_ishtp.c | 17 +++--
 drivers/platform/chrome/cros_ec_lpc.c   |  2 ++
 include/linux/platform_data/cros_ec_proto.h | 16 
 4 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec.c 
b/drivers/platform/chrome/cros_ec.c
index 9b2d07422e175..739f3cffe26e3 100644
--- a/drivers/platform/chrome/cros_ec.c
+++ b/drivers/platform/chrome/cros_ec.c
@@ -31,6 +31,15 @@ static struct cros_ec_platform pd_p = {
.cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX),
 };
 
+static irqreturn_t ec_irq_handler(int irq, void *data)
+{
+   struct cros_ec_device *ec_dev = data;
+
+   ec_dev->last_event_time = cros_ec_get_time_ns();
+
+   return IRQ_WAKE_THREAD;
+}
+
 static irqreturn_t ec_irq_thread(int irq, void *data)
 {
struct cros_ec_device *ec_dev = data;
@@ -141,7 +150,8 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
}
 
if (ec_dev->irq) {
-   err = devm_request_threaded_irq(dev, ec_dev->irq, NULL,
+   err = devm_request_threaded_irq(
+   dev, ec_dev->irq, ec_irq_handler,
ec_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"chromeos-ec", ec_dev);
if (err) {
diff --git a/drivers/platform/chrome/cros_ec_ishtp.c 
b/drivers/platform/chrome/cros_ec_ishtp.c
index 25ca2c894b4de..5c848f22b44b4 100644
--- a/drivers/platform/chrome/cros_ec_ishtp.c
+++ b/drivers/platform/chrome/cros_ec_ishtp.c
@@ -200,13 +200,14 @@ static int ish_send(struct ishtp_cl_data *client_data,
  * process_recv() - Received and parse incoming packet
  * @cros_ish_cl: Client instance to get stats
  * @rb_in_proc: Host interface message buffer
+ * @timestamp: Timestamp of when parent callback started
  *
  * Parse the incoming packet. If it is a response packet then it will
  * update per instance flags and wake up the caller waiting to for the
  * response. If it is an event packet then it will schedule event work.
  */
 static void process_recv(struct ishtp_cl *cros_ish_cl,
-struct ishtp_cl_rb *rb_in_proc)
+struct ishtp_cl_rb *rb_in_proc, ktime_t timestamp)
 {
size_t data_len = rb_in_proc->buf_idx;
struct ishtp_cl_data *client_data =
@@ -295,6 +296,11 @@ static void process_recv(struct ishtp_cl *cros_ish_cl,
break;
 
case CROS_MKBP_EVENT:
+   /*
+* Set timestamp from beginning of function since we actually
+* got an incoming MKBP event
+*/
+   client_data->ec_dev->last_event_time = timestamp;
/* The event system doesn't send any data in buffer */
schedule_work(&client_data->work_ec_evt);
 
@@ -322,10 +328,17 @@ static void ish_event_cb(struct ishtp_cl_device 
*cl_device)
 {
struct ishtp_cl_rb *rb_in_proc;
struct ishtp_cl *cros_ish_cl = ishtp_get_drvdata(cl_device);
+   ktime_t timestamp;
+
+   /*
+* Take timestamp as close to hardware interrupt as possible for sensor
+* timestamps.
+*/
+   timestamp = cros_ec_get_time_ns();
 
while ((rb_in_proc = ishtp_cl_rx_get_rb(cros_ish_cl)) != NULL) {
/* Decide what to do with received data */
-   process_recv(cros_ish_cl, rb_in_proc);
+   process_recv(cros_ish_cl, rb_in_proc, timestamp);
}
 }
 
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index 7d10d909435ff..3c77496e164da 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -313,6 +313,8 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 
value, void *data)
 {
struct cros_ec_device *ec_dev = data;
 
+   ec_dev->last_event_time = cros_ec_get_time_ns();
+
if (ec_dev->mkbp_event_supported &&
cros_ec_get_next_event(ec_dev, NULL) > 0)
blocking_notifier_call_chain(&ec_dev->event_notifier, 0,
diff --git a/include/linux/platform_data/cros_ec_proto.h 
b/include/linux/platform_data/cros_ec_proto.h
index 691f9e953a96a..b183024fef1f6 100644
--- a/include/linux/platform_data/cros_ec_proto.h
+++ b/include/linux/platform_data/cros_ec_proto.h
@@ -122,6 +122,8 @@ struct cros_ec_com

[PATCH v2 00/18] cros_ec: Add sensorhub driver and FIFO processing*** SUBJECT HERE

2019-10-20 Thread Gwendal Grignou
This patchset adds a sensorhub driver for spreading sensor
events coming from the Embedded controller sensor FIFO:

   +---+ +--+ +
   | cros_ec_accel | | cros_ec_gyro | | ...
   +---+ +--+ +
   id:0   \id:1 |   / id:..
 +--+
 |   cros_ec_sensorhub  |
 +--+
 |   cros_ec_dev|
 +--+
 | cros_ec_i2c, cros_ec_lpc, .. |
 +--+
 |
 EC

When new sensors events are present, the EC raises and interrupt,
sensorhub reads the FIFO and uses the 'id' field to spread the event to
the proper IIO sensors. This stack is similar to the HID sensor input
stack.

The first patch move cros_ec_proto functions documentations into the
code to prevent rot.

The inext 3 patches add a primitive cros_ec_sensorhub. MFD just have to
register this driver if at least one sensor is presented by the EC.
cros_ec_sensorhub retrieves more information from the EC to find out
which sensors are actually present:
  mfd: cros_ec: Add sensor_count and make check_features public
  platform: cros_ec: Add cros_ec_sensor_hub driver
  platform/mfd:iio: cros_ec: Register sensor through sensorhub

The next 3 patches prepare for FIFO support:
  platform: chrome: cros-ec: record event timestamp in the hard irq
  platform: chrome: cros_ec: Do not attempt to register a non-positive
  platform: chrome: cros_ec: handle MKBP more events flag

That last patch fixes a regression that changes event processing.
Revert the patches that fixed that regression.

The next 3 patches add FIFO support. An interface is added to connect
the IIO sensors with cros_ec_sensorhub, and filters are needed to spread
the timestamp when the EC send batches of events and deal with variation
in interrupt delay.
  platform: chrome: sensorhub: Add FIFO support
  platform: chrome: sensorhub: Add code to spread timestmap
  platform: chrome: sensorhub: Add median filter

The remaining patches update IIO cros_ec drivers:
The first patch moves cros_ec_sensor_core functions documentation into
the .c file.
Then we can use the FIFO function exposed by cros_ec_sensorhub:
  iio: cros_ec: Use triggered buffer only when EC does not support FIFO

The power management functions are not necessary anymore, since we
shutoff the FIFO from cros_ec_sensorhub:
  iio: cros_ec: Register to cros_ec_sensorhub when EC supports FIFO

Finally, the last 3 patches present sensor information following the IIO
ABI:
-  Configurable EC timeout to allow batch mode in buffer/hwfifo_timeout,
  in seconds.
-  Hard coded EC FIFO size in buffer/hwfifo_watermark_max
-  Sensor sampling frequency in hertz at sampling_frequency:
  iio: cros_ec: Expose hwfifo_timeout
  iio: cros_ec: Report hwfifo_watermark_max
  iio: cros_ec: Use Hertz as unit for sampling frequency

For testing, libiio test tools can be used:
A iio device link looks like:
iio:device1 ->
...09:00/GOOG0004:00/cros-ec-dev.6.auto/cros-ec-sensorhub.7.auto/
 cros-ec-accel.15.auto/iio:device1

When FIFO is available, no trigger are presented. Once
sampling_freqeuncy and hwfifo_timeout are set, sensor events flow
when listening to /dev/iio:device1:
echo 12 > sampling_frequency   # Set ODR to at least 12Hz
echo .100 > buffer/hwfifo_timeout  # do not wait more than 100ms to
   # to send samples
iio_readdev -b 2 -T 1000 -s 2 iio:device1 2>/dev/null| od -x
000 ffd0 2e20 d990  8630 b56c 07ea 
020 ffc0 2e10 d970  877e b56c 07ea 
040`

When FIFO is not supported by the EC, a trigger is present in the
directory. After registering a trigger, setting sampling_frequency,
the latest data collected by the sensor will be retrieved by the host
when the trigger expires.

When cros_ec_accel_legacy driver is used, no FIFO is supported and the
sampling frequency for the accelerometers is hard coded at 10Hz.

This set is built upon the master branch of
git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git

Enrico Granata (2):
  platform: chrome: cros_ec: Do not attempt to register a non-positive
IRQ number
  platform: chrome: cros_ec: handle MKBP more events flag

Gwendal Grignou (16):
  platform: chrome: Put docs with the code
  mfd: cros_ec: Add sensor_count and make check_features public
  platform: cros_ec: Add cros_ec_sensor_hub driver
  platform/mfd:iio: cros_ec: Register sensor through sensorhub
  platform: chrome: cros-ec: record event timestamp in the hard irq
  Revert "Input: cros_ec_keyb - add back missing mask for event_type"
  Revert "Input: cros_ec_keyb: mask out extra flags in event_type"
  platform: chrome: sensorhub: Add FIFO support
  platf

Re: [PATCH 01/13] mfd: cros_ec: Add sensor_count and make check_features public

2019-09-30 Thread Gwendal Grignou
Sounds good to me, I will make the change in rev2.

On Mon, Sep 30, 2019 at 6:15 AM Enric Balletbo i Serra
 wrote:
>
> Hi Gwendal,
>
> Many thanks for the patches.
>
> On 22/9/19 19:50, Gwendal Grignou wrote:
> > Add a new function to return the number of MEMS sensors available in a
> > ChromeOS Embedded Controller.
> > It uses MOTIONSENSE_CMD_DUMP if available or a specific memory map ACPI
> > registers to find out.
> >
> > Also, make check_features public as it can be useful for other drivers
> > to know whant the Embedded Controller supports.
> >
> > Signed-off-by: Gwendal Grignou 
> > ---
> >  drivers/mfd/cros_ec_dev.c   | 61 -
> >  include/linux/mfd/cros_ec.h | 17 +++
> >  2 files changed, 77 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
> > index 6e6dfd6c1871..3be80183ccaa 100644
> > --- a/drivers/mfd/cros_ec_dev.c
> > +++ b/drivers/mfd/cros_ec_dev.c
> > @@ -112,7 +112,7 @@ static const struct mfd_cell cros_ec_vbc_cells[] = {
> >   { .name = "cros-ec-vbc", }
> >  };
> >
> > -static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
> > +int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
> >  {
> >   struct cros_ec_command *msg;
> >   int ret;
> > @@ -143,12 +143,71 @@ static int cros_ec_check_features(struct cros_ec_dev 
> > *ec, int feature)
> >
> >   return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature);
> >  }
> > +EXPORT_SYMBOL_GPL(cros_ec_check_features);
> >
> >  static void cros_ec_class_release(struct device *dev)
> >  {
> >   kfree(to_cros_ec_dev(dev));
> >  }
> >
> > +int cros_ec_get_sensor_count(struct cros_ec_dev *ec)
> > +{
> > + /*
> > +  * Issue a command to get the number of sensor reported.
> > +  * If not supported, check for legacy mode.
> > +  */
> > + int ret, sensor_count;
> > + struct ec_params_motion_sense *params;
> > + struct ec_response_motion_sense *resp;
> > + struct cros_ec_command *msg;
> > + struct cros_ec_device *ec_dev = ec->ec_dev;
> > + u8 status;
> > +
> > + msg = kzalloc(sizeof(struct cros_ec_command) +
> > + max(sizeof(*params), sizeof(*resp)), GFP_KERNEL);
> > + if (msg == NULL)
> > + return -ENOMEM;
> > +
> > + msg->version = 1;
> > + 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) {
> > + sensor_count = ret;
> > + } else if (msg->result != EC_RES_SUCCESS) {
> > + sensor_count = -EPROTO;
> > + } else {
> > + resp = (struct ec_response_motion_sense *)msg->data;
> > + sensor_count = resp->dump.sensor_count;
> > + }
> > + kfree(msg);
> > +
> > + /*
> > +  * Check legacy mode: Let's find out if sensors are accessible
> > +  * via LPC interface.
> > +  */
> > + if (sensor_count == -EPROTO &&
> > + ec->cmd_offset == 0 &&
> > + ec_dev->cmd_readmem) {
> > + ret = ec_dev->cmd_readmem(ec_dev, EC_MEMMAP_ACC_STATUS,
> > + 1, &status);
> > + if ((ret >= 0) &&
> > + (status & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT)) {
> > + /*
> > +  * We have 2 sensors, one in the lid, one in the base.
> > +  */
> > + sensor_count = 2;
> > + }
> > + }
> > + return sensor_count;
> > +}
> > +EXPORT_SYMBOL_GPL(cros_ec_get_sensor_count);
> > +
> >  static void cros_ec_sensors_register(struct cros_ec_dev *ec)
> >  {
> >   /*
> > diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
> > index 61c2875c2a40..578e0bbcafdc 100644
> > --- a/include/linux/mfd/cros_ec.h
> > +++ b/include/linux/mfd/cros_ec.h
> > @@ -32,4 +32,21 @@ struct cros_ec_dev {
> >
> >  #define to_cros_ec_dev(dev)  container_of(dev, struct cros_ec_dev, 
> > class_dev)
>

[PATCH 13/13] iio: cros_ec: Use Hertz as unit for sampling frequency

2019-09-22 Thread Gwendal Grignou
To be compliant with other sensors, set and get sensor sampling
frequency in Hz, not mHz.

Fixes: ae7b02ad2f32 ("iio: common: cros_ec_sensors: Expose
cros_ec_sensors frequency range via iio sysfs")

Signed-off-by: Gwendal Grignou 
---
 .../cros_ec_sensors/cros_ec_sensors_core.c| 32 +++
 .../linux/iio/common/cros_ec_sensors_core.h   |  6 ++--
 2 files changed, 22 insertions(+), 16 deletions(-)

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
index a32260c9bc09..f7e6827bd4cb 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -227,6 +227,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
struct iio_buffer *buffer;
u32 ver_mask;
+   int frequencies[ARRAY_SIZE(state->frequencies) / 2] = { 0 };
int ret, i;
 
platform_set_drvdata(pdev, indio_dev);
@@ -275,20 +276,22 @@ int cros_ec_sensors_core_init(struct platform_device 
*pdev,
state->calib[i].scale = MOTION_SENSE_DEFAULT_SCALE;
 
/* 0 is a correct value used to stop the device */
-   state->frequencies[0] = 0;
if (state->msg->version < 3) {
get_default_min_max_freq(state->resp->info.type,
-&state->frequencies[1],
-&state->frequencies[2],
+&frequencies[1],
+&frequencies[2],
 &state->fifo_max_event_count);
} else {
-   state->frequencies[1] =
-   state->resp->info_3.min_frequency;
-   state->frequencies[2] =
-   state->resp->info_3.max_frequency;
+   frequencies[1] = state->resp->info_3.min_frequency;
+   frequencies[2] = state->resp->info_3.max_frequency;
state->fifo_max_event_count =
state->resp->info_3.fifo_max_event_count;
}
+   for (i = 0; i < ARRAY_SIZE(frequencies); i++) {
+   state->frequencies[2 * i] = frequencies[i] / 1000;
+   state->frequencies[2 * i + 1] =
+   (frequencies[i] % 1000) * 1000;
+   }
 
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
buffer = devm_iio_kfifo_allocate(dev);
@@ -653,7 +656,7 @@ 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;
+   int ret, frequency;
 
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
@@ -665,8 +668,10 @@ int cros_ec_sensors_core_read(struct 
cros_ec_sensors_core_state *st,
if (ret)
break;
 
-   *val = st->resp->sensor_odr.ret;
-   ret = IIO_VAL_INT;
+   frequency = st->resp->sensor_odr.ret;
+   *val = frequency / 1000;
+   *val2 = (frequency % 1000) * 1000;
+   ret = IIO_VAL_INT_PLUS_MICRO;
break;
default:
ret = -EINVAL;
@@ -690,7 +695,7 @@ int cros_ec_sensors_core_read_avail(struct iio_dev 
*indio_dev,
case IIO_CHAN_INFO_SAMP_FREQ:
*length = ARRAY_SIZE(state->frequencies);
*vals = (const int *)&state->frequencies;
-   *type = IIO_VAL_INT;
+   *type = IIO_VAL_INT_PLUS_MICRO;
return IIO_AVAIL_LIST;
}
 
@@ -702,12 +707,13 @@ 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;
+   int ret, frequency;
 
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
+   frequency = val * 1000 + val2 / 1000;
st->param.cmd = MOTIONSENSE_CMD_SENSOR_ODR;
-   st->param.sensor_odr.data = val;
+   st->param.sensor_odr.data = frequency;
 
/* Always roundup, so caller gets at least what it asks for. */
st->param.sensor_odr.roundup = 1;
diff --git a/include/linux/iio/common/cros_ec_sensors_core.h 
b/include/linux/iio/common/cros_ec_sensors_core.h
index 2c6acbde0d02..46d5110b2fe4 100644
--- a/include/linux/iio/common/cros_ec_senso

[PATCH 12/13] iio: cros_ec: Report hwfifo_watermark_max

2019-09-22 Thread Gwendal Grignou
Report the maximum amount of sample the EC can hold.
This is not tunable, but can be useful for application to find out the
maximum amount of time it can sleep when hwfifo_timeout is set to a
large number.

Signed-off-by: Gwendal Grignou 
---
 .../cros_ec_sensors/cros_ec_sensors_core.c| 35 +--
 .../linux/iio/common/cros_ec_sensors_core.h   |  4 ++-
 2 files changed, 36 insertions(+), 3 deletions(-)

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
index a31a761e3a81..a32260c9bc09 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -23,6 +23,12 @@
 #include 
 #include 
 
+/*
+ * Hard coded to the first device to support sensor fifo.  The EC has a 2048
+ * byte fifo and will trigger an interrupt when fifo is 2/3 full.
+ */
+#define CROS_EC_FIFO_SIZE (2048 * 2 / 3)
+
 static char *cros_ec_loc[] = {
[MOTIONSENSE_LOC_BASE] = "base",
[MOTIONSENSE_LOC_LID] = "lid",
@@ -56,8 +62,15 @@ static int cros_ec_get_host_cmd_version_mask(struct 
cros_ec_device *ec_dev,
 
 static void get_default_min_max_freq(enum motionsensor_type type,
 u32 *min_freq,
-u32 *max_freq)
+u32 *max_freq,
+u32 *max_fifo_events)
 {
+   /*
+* We don't know fifo size, set to size previously used by older
+* hardware.
+*/
+   *max_fifo_events = CROS_EC_FIFO_SIZE;
+
switch (type) {
case MOTIONSENSE_TYPE_ACCEL:
case MOTIONSENSE_TYPE_GYRO:
@@ -122,6 +135,7 @@ static ssize_t cros_ec_sensor_set_report_latency(struct 
device *dev,
return len;
 }
 
+
 static ssize_t cros_ec_sensor_get_report_latency(struct device *dev,
  struct device_attribute *attr,
  char *buf)
@@ -149,8 +163,22 @@ static IIO_DEVICE_ATTR(hwfifo_timeout, 0644,
   cros_ec_sensor_get_report_latency,
   cros_ec_sensor_set_report_latency, 0);
 
+static ssize_t hwfifo_watermark_max_show(
+   struct device *dev,
+   struct device_attribute *attr,
+   char *buf)
+{
+   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+
+   return sprintf(buf, "%d\n", st->fifo_max_event_count);
+}
+
+static IIO_DEVICE_ATTR_RO(hwfifo_watermark_max, 0);
+
 static const struct attribute *cros_ec_sensor_fifo_attributes[] = {
&iio_dev_attr_hwfifo_timeout.dev_attr.attr,
+   &iio_dev_attr_hwfifo_watermark_max.dev_attr.attr,
NULL,
 };
 
@@ -251,12 +279,15 @@ int cros_ec_sensors_core_init(struct platform_device 
*pdev,
if (state->msg->version < 3) {
get_default_min_max_freq(state->resp->info.type,
 &state->frequencies[1],
-&state->frequencies[2]);
+&state->frequencies[2],
+&state->fifo_max_event_count);
} else {
state->frequencies[1] =
state->resp->info_3.min_frequency;
state->frequencies[2] =
state->resp->info_3.max_frequency;
+   state->fifo_max_event_count =
+   state->resp->info_3.fifo_max_event_count;
}
 
if (cros_ec_check_features(ec, EC_FEATURE_MOTION_SENSE_FIFO)) {
diff --git a/include/linux/iio/common/cros_ec_sensors_core.h 
b/include/linux/iio/common/cros_ec_sensors_core.h
index 60f78f0e4884..2c6acbde0d02 100644
--- a/include/linux/iio/common/cros_ec_sensors_core.h
+++ b/include/linux/iio/common/cros_ec_sensors_core.h
@@ -54,7 +54,8 @@ typedef irqreturn_t (*cros_ec_sensors_capture_t)(int irq, 
void *p);
  * 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
+ * @curr_sampl_freq:   current sampling period
+ * @fifo_max_event_count:  Size of the EC sensor FIFO
  */
 struct cros_ec_sensors_core_state {
struct cros_ec_device *ec;
@@ -78,6 +79,7 @@ struct cros_ec_sensors_core_state {
unsigned long scan_mask, s16 *data);
 
int curr_sampl_freq;
+   u32 fifo_max_event_count;
 
/* Table of known available frequencies : 0, Min and Max in mHz */
int frequencies[3];
-- 
2.23.0.351.gc4317032e6-goog



[PATCH 03/13] platform/mfd:iio: cros_ec: Register sensor through sensorhub

2019-09-22 Thread Gwendal Grignou
- Add sensorhub include file
- Remove duplicate code in mfd, since mfd just register
  cros_ec_sensorhub if at least one sensor is present
- Change iio cros_ec driver to get the pointer to the cros_ec_dev
  through cros_ec_sensorhub.

Signed-off-by: Gwendal Grignou 
---
 drivers/iio/accel/cros_ec_accel_legacy.c  |   4 +-
 .../common/cros_ec_sensors/cros_ec_sensors.c  |   4 +-
 .../cros_ec_sensors/cros_ec_sensors_core.c|   4 +-
 drivers/iio/light/cros_ec_light_prox.c|   6 +-
 drivers/mfd/cros_ec_dev.c | 203 ++
 drivers/platform/chrome/cros_ec_sensorhub.c   |   2 +-
 include/linux/platform_data/cros_ec_proto.h   |   8 -
 .../linux/platform_data/cros_ec_sensorhub.h   |   8 +
 8 files changed, 34 insertions(+), 205 deletions(-)

diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c 
b/drivers/iio/accel/cros_ec_accel_legacy.c
index fcc3f999e482..c9af6fa0670d 100644
--- a/drivers/iio/accel/cros_ec_accel_legacy.c
+++ b/drivers/iio/accel/cros_ec_accel_legacy.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #define DRV_NAME   "cros-ec-accel-legacy"
@@ -163,7 +164,8 @@ static const struct iio_chan_spec 
cros_ec_accel_legacy_channels[] = {
 static int cros_ec_accel_legacy_probe(struct platform_device *pdev)
 {
struct device *dev = &pdev->dev;
-   struct cros_ec_dev *ec = dev_get_drvdata(dev->parent);
+   struct cros_ec_sensorhub *sensor_hub = dev_get_drvdata(dev->parent);
+   struct cros_ec_dev *ec = sensor_hub->ec;
struct iio_dev *indio_dev;
struct cros_ec_sensors_core_state *state;
int ret;
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 a6987726eeb8..5bd6f54afc42 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -222,7 +223,8 @@ static const struct iio_info ec_sensors_info = {
 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_sensorhub *sensor_hub = dev_get_drvdata(dev->parent);
+   struct cros_ec_dev *ec_dev = sensor_hub->ec;
struct iio_dev *indio_dev;
struct cros_ec_sensors_state *state;
struct iio_chan_spec *channel;
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
index d2609e6feda4..81a7f692de2f 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 static char *cros_ec_loc[] = {
@@ -88,7 +89,8 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
 {
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_sensorhub *sensor_hub = dev_get_drvdata(dev->parent);
+   struct cros_ec_dev *ec = sensor_hub->ec;
struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
u32 ver_mask;
int ret, i;
diff --git a/drivers/iio/light/cros_ec_light_prox.c 
b/drivers/iio/light/cros_ec_light_prox.c
index c5263b563fc1..205effc1f404 100644
--- a/drivers/iio/light/cros_ec_light_prox.c
+++ b/drivers/iio/light/cros_ec_light_prox.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -169,13 +170,14 @@ static const struct iio_info cros_ec_light_prox_info = {
 static int cros_ec_light_prox_probe(struct platform_device *pdev)
 {
struct device *dev = &pdev->dev;
-   struct cros_ec_dev *ec_dev = dev_get_drvdata(dev->parent);
+   struct cros_ec_sensorhub *sensor_hub = dev_get_drvdata(dev->parent);
+   struct cros_ec_dev *ec = sensor_hub->ec;
struct iio_dev *indio_dev;
struct cros_ec_light_prox_state *state;
struct iio_chan_spec *channel;
int ret;
 
-   if (!ec_dev || !ec_dev->ec_dev) {
+   if (!ec || !ec->ec_dev) {
dev_warn(dev, "No CROS EC device found.\n");
return -EINVAL;
}
diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
index 3be80183ccaa..3a583d3503ca 100644
--- a/drivers/mfd/cros_ec_dev.c
+++ b/drivers/mfd/cros_ec_dev.c
@@ -78,6 +78,10 @@ static const struct mfd_cell cros_ec_rtc_cells[] = {
{ .name = "cros-ec-rtc", },
 };
 
+static const struct mfd_cell cros_ec_sensorhub_cells[] = {
+   { .name = "cros-ec-sensorhub", },
+};
+
 static const struct mfd_cell cros_usbpd_charger_cells[] = {

[PATCH 06/13] platform: chrome: cros_ec: handle MKBP more events flag

2019-09-22 Thread Gwendal Grignou
From: Enrico Granata 

The ChromeOS EC has support for signaling to the host that
a single IRQ can serve multiple MKBP events.

Doing this serves an optimization purpose, as it minimizes the
number of round-trips into the interrupt handling machinery, and
it proves beneficial to sensor timestamping as it keeps the desired
synchronization of event times between the two processors.

This patch adds kernel support for this EC feature, allowing the
ec_irq to loop until all events have been served.

Signed-off-by: Enrico Granata 
Signed-off-by: Gwendal Grignou 
---
 drivers/platform/chrome/cros_ec.c   | 33 +
 drivers/platform/chrome/cros_ec_proto.c | 51 -
 include/linux/platform_data/cros_ec_proto.h |  7 ++-
 3 files changed, 57 insertions(+), 34 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec.c 
b/drivers/platform/chrome/cros_ec.c
index 9c8dc7cdb2b7..4adc007c357c 100644
--- a/drivers/platform/chrome/cros_ec.c
+++ b/drivers/platform/chrome/cros_ec.c
@@ -46,25 +46,38 @@ static irqreturn_t ec_irq_handler(int irq, void *data)
return IRQ_WAKE_THREAD;
 }
 
-static irqreturn_t ec_irq_thread(int irq, void *data)
+static bool ec_handle_event(struct cros_ec_device *ec_dev)
 {
-   struct cros_ec_device *ec_dev = data;
bool wake_event = true;
-   int ret;
+   bool ec_has_more_events = false;
+   int ret = cros_ec_get_next_event(ec_dev, &wake_event);
 
-   ret = cros_ec_get_next_event(ec_dev, &wake_event);
+   if (ec_dev->mkbp_event_supported) {
+   ec_has_more_events = (ret > 0) &&
+   (ec_dev->event_data.event_type &
+   EC_MKBP_HAS_MORE_EVENTS);
+   }
 
-   /*
-* Signal only if wake host events or any interrupt if
-* cros_ec_get_next_event() returned an error (default value for
-* wake_event is true)
-*/
-   if (wake_event && device_may_wakeup(ec_dev->dev))
+   if (device_may_wakeup(ec_dev->dev) && wake_event)
pm_wakeup_event(ec_dev->dev, 0);
 
if (ret > 0)
blocking_notifier_call_chain(&ec_dev->event_notifier,
 0, ec_dev);
+
+   return ec_has_more_events;
+
+}
+
+static irqreturn_t ec_irq_thread(int irq, void *data)
+{
+   struct cros_ec_device *ec_dev = data;
+   bool ec_has_more_events;
+
+   do {
+   ec_has_more_events = ec_handle_event(ec_dev);
+   } while (ec_has_more_events);
+
return IRQ_HANDLED;
 }
 
diff --git a/drivers/platform/chrome/cros_ec_proto.c 
b/drivers/platform/chrome/cros_ec_proto.c
index f659f96bda12..70e6d6c93b8d 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -425,10 +425,14 @@ int cros_ec_query_all(struct cros_ec_device *ec_dev)
ret = cros_ec_get_host_command_version_mask(ec_dev,
EC_CMD_GET_NEXT_EVENT,
&ver_mask);
-   if (ret < 0 || ver_mask == 0)
+   if (ret < 0 || ver_mask == 0) {
ec_dev->mkbp_event_supported = 0;
-   else
-   ec_dev->mkbp_event_supported = 1;
+   dev_info(ec_dev->dev, "MKBP not supported\n");
+   } else {
+   ec_dev->mkbp_event_supported = fls(ver_mask);
+   dev_info(ec_dev->dev, "MKBP support version %u\n",
+   ec_dev->mkbp_event_supported - 1);
+   }
 
/* Probe if host sleep v1 is supported for S0ix failure detection. */
ret = cros_ec_get_host_command_version_mask(ec_dev,
@@ -519,6 +523,7 @@ EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
 
 static int get_next_event_xfer(struct cros_ec_device *ec_dev,
   struct cros_ec_command *msg,
+  struct ec_response_get_next_event_v1 *event,
   int version, uint32_t size)
 {
int ret;
@@ -531,7 +536,7 @@ static int get_next_event_xfer(struct cros_ec_device 
*ec_dev,
ret = cros_ec_cmd_xfer(ec_dev, msg);
if (ret > 0) {
ec_dev->event_size = ret - 1;
-   memcpy(&ec_dev->event_data, msg->data, ret);
+   ec_dev->event_data = *event;
}
 
return ret;
@@ -539,30 +544,29 @@ static int get_next_event_xfer(struct cros_ec_device 
*ec_dev,
 
 static int get_next_event(struct cros_ec_device *ec_dev)
 {
-   u8 buffer[sizeof(struct cros_ec_command) + sizeof(ec_dev->event_data)];
-   struct cros_ec_command *msg = (struct cros_ec_command *)&buffer;
-   static int cmd_version = 1;
-   int ret;
+   struct {
+   struct cros_ec_command msg;
+   struct ec_response_get_next_event_v1 event;
+   } __packed buf;
+   struct

[PATCH 11/13] iio: cros_ec: Expose hwfifo_timeout

2019-09-22 Thread Gwendal Grignou
Expose EC sampling rate through buffer/hwfifo_timeout.
Rename frequency to sampling_frequency to match IIO ABI.

Signed-off-by: Gwendal Grignou 
---
 .../common/cros_ec_sensors/cros_ec_sensors.c  |   1 -
 .../cros_ec_sensors/cros_ec_sensors_core.c| 110 +-
 drivers/iio/light/cros_ec_light_prox.c|   3 +-
 drivers/iio/pressure/cros_ec_baro.c   |   3 +-
 4 files changed, 81 insertions(+), 36 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 b78a942ac8e5..95a4b4cf8f87 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -255,7 +255,6 @@ static int cros_ec_sensors_probe(struct platform_device 
*pdev)
BIT(IIO_CHAN_INFO_CALIBSCALE);
channel->info_mask_shared_by_all =
BIT(IIO_CHAN_INFO_SCALE) |
-   BIT(IIO_CHAN_INFO_FREQUENCY) |
BIT(IIO_CHAN_INFO_SAMP_FREQ);
channel->info_mask_shared_by_all_available =
BIT(IIO_CHAN_INFO_SAMP_FREQ);
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
index c4c37c6df301..a31a761e3a81 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -84,6 +85,75 @@ static void get_default_min_max_freq(enum motionsensor_type 
type,
}
 }
 
+static int cros_ec_sensor_set_ec_rate(struct cros_ec_sensors_core_state *st,
+ int rate)
+{
+   int ret;
+
+   mutex_lock(&st->cmd_lock);
+   st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
+   st->param.ec_rate.data = rate;
+   ret = cros_ec_motion_send_host_cmd(st, 0);
+   if (ret == 0)
+   st->curr_sampl_freq = rate;
+   mutex_unlock(&st->cmd_lock);
+   return ret;
+}
+
+static ssize_t cros_ec_sensor_set_report_latency(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t len)
+{
+   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+   int integer, fract, ret;
+   int latency;
+
+   ret = iio_str_to_fixpoint(buf, 10, &integer, &fract);
+   if (ret)
+   return ret;
+
+   /* EC rate is in ms. */
+   latency = integer * 1000 + fract / 1000;
+   ret = cros_ec_sensor_set_ec_rate(st, latency);
+   if (ret < 0)
+   return ret;
+
+   return len;
+}
+
+static ssize_t cros_ec_sensor_get_report_latency(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+   struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+   int latency, ret;
+
+   mutex_lock(&st->cmd_lock);
+   st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
+   st->param.ec_rate.data = EC_MOTION_SENSE_NO_VALUE;
+
+   ret = cros_ec_motion_send_host_cmd(st, 0);
+   latency = st->resp->ec_rate.ret;
+   mutex_unlock(&st->cmd_lock);
+   if (ret < 0)
+   return ret;
+
+   return sprintf(buf, "%d.%06u\n",
+  latency / 1000,
+  (latency % 1000) * 1000);
+}
+
+static IIO_DEVICE_ATTR(hwfifo_timeout, 0644,
+  cros_ec_sensor_get_report_latency,
+  cros_ec_sensor_set_report_latency, 0);
+
+static const struct attribute *cros_ec_sensor_fifo_attributes[] = {
+   &iio_dev_attr_hwfifo_timeout.dev_attr.attr,
+   NULL,
+};
+
 int cros_ec_sensors_push_data(
struct iio_dev *indio_dev,
s16 *data,
@@ -194,6 +264,9 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
if (!buffer)
return -ENOMEM;
 
+   iio_buffer_set_attrs(buffer,
+cros_ec_sensor_fifo_attributes);
+
iio_device_attach_buffer(indio_dev, buffer);
indio_dev->modes = INDIO_BUFFER_SOFTWARE;
ret = cros_ec_sensorhub_register_push_data(
@@ -553,18 +626,6 @@ int cros_ec_sensors_core_read(struct 
cros_ec_sensors_core_state *st,
 
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
-   st->param.cmd = MOTIONSENSE_CMD_EC_RATE;
-   st->param.ec_rate.data =
-   EC_MOTION_SENSE_NO

[PATCH 05/13] platform: chrome: cros_ec: Do not attempt to register a non-positive IRQ number

2019-09-22 Thread Gwendal Grignou
From: Enrico Granata 

Add a layer of sanity checking to cros_ec_register against attempting to
register IRQ values that are not strictly greater than 0.

Signed-off-by: Enrico Granata 
Signed-off-by: Enrico Granata 
Signed-off-by: Gwendal Grignou 
---
 drivers/platform/chrome/cros_ec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/platform/chrome/cros_ec.c 
b/drivers/platform/chrome/cros_ec.c
index f49eb1d1e3cd..9c8dc7cdb2b7 100644
--- a/drivers/platform/chrome/cros_ec.c
+++ b/drivers/platform/chrome/cros_ec.c
@@ -146,7 +146,7 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
return err;
}
 
-   if (ec_dev->irq) {
+   if (ec_dev->irq > 0) {
err = devm_request_threaded_irq(
dev, ec_dev->irq, ec_irq_handler,
ec_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-- 
2.23.0.351.gc4317032e6-goog



[PATCH 10/13] iio: cros_ec: Use triggered buffer only when EC does not support FIFO

2019-09-22 Thread Gwendal Grignou
When EC supports FIFO, the samples will flow from the kernel by
themselves.
When no FIFO, the user space app needs to call trigger_new, or better
register a high precision timer.

Signed-off-by: Gwendal Grignou 
---
 drivers/iio/accel/cros_ec_accel_legacy.c  |  8 +--
 .../cros_ec_sensors/cros_ec_lid_angle.c   |  2 +-
 .../common/cros_ec_sensors/cros_ec_sensors.c  |  8 +--
 .../cros_ec_sensors/cros_ec_sensors_core.c| 61 +--
 drivers/iio/light/cros_ec_light_prox.c|  8 +--
 drivers/iio/pressure/cros_ec_baro.c   |  8 +--
 .../linux/iio/common/cros_ec_sensors_core.h   | 16 -
 7 files changed, 80 insertions(+), 31 deletions(-)

diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c 
b/drivers/iio/accel/cros_ec_accel_legacy.c
index 591c0d962c44..d607fbc52c95 100644
--- a/drivers/iio/accel/cros_ec_accel_legacy.c
+++ b/drivers/iio/accel/cros_ec_accel_legacy.c
@@ -179,7 +179,8 @@ static int cros_ec_accel_legacy_probe(struct 
platform_device *pdev)
if (!indio_dev)
return -ENOMEM;
 
-   ret = cros_ec_sensors_core_init(pdev, indio_dev, true);
+   ret = cros_ec_sensors_core_init(pdev, indio_dev, true,
+   cros_ec_sensors_capture, cros_ec_sensors_push_data);
if (ret)
return ret;
 
@@ -199,11 +200,6 @@ static int cros_ec_accel_legacy_probe(struct 
platform_device *pdev)
state->sign[CROS_EC_SENSOR_Z] = -1;
}
 
-   ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
-   cros_ec_sensors_capture, NULL);
-   if (ret)
-   return ret;
-
return devm_iio_device_register(dev, indio_dev);
 }
 
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c 
b/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c
index 1dcc2a16ab2d..e30a59fcf0f9 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_lid_angle.c
@@ -97,7 +97,7 @@ static int cros_ec_lid_angle_probe(struct platform_device 
*pdev)
if (!indio_dev)
return -ENOMEM;
 
-   ret = cros_ec_sensors_core_init(pdev, indio_dev, false);
+   ret = cros_ec_sensors_core_init(pdev, indio_dev, false, NULL, NULL);
if (ret)
return ret;
 
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 a88dd8deade9..b78a942ac8e5 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -239,7 +239,8 @@ static int cros_ec_sensors_probe(struct platform_device 
*pdev)
if (!indio_dev)
return -ENOMEM;
 
-   ret = cros_ec_sensors_core_init(pdev, indio_dev, true);
+   ret = cros_ec_sensors_core_init(pdev, indio_dev, true,
+   cros_ec_sensors_capture, cros_ec_sensors_push_data);
if (ret)
return ret;
 
@@ -301,11 +302,6 @@ static int cros_ec_sensors_probe(struct platform_device 
*pdev)
else
state->core.read_ec_sensors_data = cros_ec_sensors_read_cmd;
 
-   ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
-   cros_ec_sensors_capture, NULL);
-   if (ret)
-   return ret;
-
return devm_iio_device_register(dev, indio_dev);
 }
 
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
index 43eb1d42820e..c4c37c6df301 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -83,15 +84,50 @@ static void get_default_min_max_freq(enum motionsensor_type 
type,
}
 }
 
+int cros_ec_sensors_push_data(
+   struct iio_dev *indio_dev,
+   s16 *data,
+   s64 timestamp)
+{
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+   s16 *out;
+   unsigned int i;
+
+   /*
+* It can happen if we get a samples before the iio device is fully
+* registered.
+*/
+   if (!st)
+   return 0;
+
+   /* Ignore samples if the buffer is not set. */
+   if (!indio_dev->active_scan_mask)
+   return 0;
+
+   out = (s16 *)st->samples;
+   for_each_set_bit(i,
+indio_dev->active_scan_mask,
+indio_dev->masklength) {
+   *out = data[i];
+   out++;
+   }
+   iio_push_to_buffers_with_timestamp(indio_dev, st->samples, timestamp);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(cros_ec_sensors_push_data);
+
 int cros_ec_sensors_core_init(struct platform_device *pdev,
  struct iio_dev *indio_dev,
-

[PATCH 09/13] platform: chrome: sensorhub: Add median filter

2019-09-22 Thread Gwendal Grignou
Events are timestamped in EC time space, their timestamps need to be
converted in host time space.
The assumption is the time delta between when the interrupt is sent
by the EC and when it is receive by the host is a [small] constant.
This is not always true, even with hard-wired interrupt. To mitigate
worst offenders, add a median filter to weed out bigger than expected
delays.

Signed-off-by: Gwendal Grignou 
---
 .../platform/chrome/cros_ec_sensorhub_ring.c  | 485 +-
 .../linux/platform_data/cros_ec_sensorhub.h   |  65 +++
 2 files changed, 533 insertions(+), 17 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_sensorhub_ring.c 
b/drivers/platform/chrome/cros_ec_sensorhub_ring.c
index 48327e80a5a3..9955c80d0907 100644
--- a/drivers/platform/chrome/cros_ec_sensorhub_ring.c
+++ b/drivers/platform/chrome/cros_ec_sensorhub_ring.c
@@ -69,9 +69,11 @@ int cros_ec_sensorhub_ring_fifo_toggle(
struct cros_ec_sensorhub *sensorhub,
bool on)
 {
-   int ret;
+   int ret, i;
 
mutex_lock(&sensorhub->cmd_lock);
+   for (i = 0; i < CROS_EC_SENSOR_MAX; i++)
+   sensorhub->last_batch_len[i] = 0;
sensorhub->params->cmd = MOTIONSENSE_CMD_FIFO_INT_ENABLE;
sensorhub->params->fifo_int_enable.enable = on;
 
@@ -86,6 +88,227 @@ int cros_ec_sensorhub_ring_fifo_toggle(
return ret;
 }
 
+static int cros_ec_ring_median_cmp(const void *pv1, const void *pv2)
+{
+   s64 v1 = *(s64 *)pv1;
+   s64 v2 = *(s64 *)pv2;
+
+   if (v1 > v2)
+   return 1;
+   else if (v1 < v2)
+   return -1;
+   else
+   return 0;
+}
+
+/*
+ * cros_ec_ring_median: Gets median of an array of numbers
+ *
+ * For now it's implemented using an inefficient > O(n) sort then return
+ * the middle element. A more optimal method would be something like
+ * quickselect, but given that n = 64 we can probably live with it in the
+ * name of clarity.
+ *
+ * Warning: the input array gets modified (sorted)!
+ */
+static s64 cros_ec_ring_median(s64 *array, size_t length)
+{
+   sort(array, length, sizeof(s64), cros_ec_ring_median_cmp, NULL);
+   return array[length / 2];
+}
+
+/*
+ * IRQ Timestamp Filtering
+ *
+ * Lower down in cros_ec_ring_process_event(), for each sensor event we have to
+ * calculate it's timestamp in the AP timebase. There are 3 time points:
+ *   a - EC timebase, sensor event
+ *   b - EC timebase, IRQ
+ *   c - AP timebase, IRQ
+ *   a' - what we want: sensor even in AP timebase
+ *
+ * While a and b are recorded at accurate times (due to the EC real time
+ * nature); c is pretty untrustworthy, even though it's recorded the
+ * first thing in ec_irq_handler(). There is a very good change we'll get
+ * added lantency due to:
+ *   other irqs
+ *   ddrfreq
+ *   cpuidle
+ *
+ * Normally a' = c - b + a, but if we do that naive math any jitter in c
+ * will get coupled in a', which we don't want. We want a function
+ * a' = cros_ec_ring_ts_filter(a) which will filter out outliers in c.
+ *
+ * Think of a graph of AP time(b) on the y axis vs EC time(c) on the x axis.
+ * The slope of the line won't be exactly 1, there will be some clock drift
+ * between the 2 chips for various reasons (mechanical stress, temperature,
+ * voltage). We need to extrapolate values for a future x, without trusting
+ * recent y values too much.
+ *
+ * We use a median filter for the slope, then another median filter for the
+ * y-intercept to calculate this function:
+ *   dx[n] = x[n-1] - x[n]
+ *   dy[n] = x[n-1] - x[n]
+ *   m[n] = dy[n] / dx[n]
+ *   median_m = median(m[n-k:n])
+ *   error[i] = y[n-i] - median_m * x[n-i]
+ *   median_error = median(error[:k])
+ *   predicted_y = median_m * x + median_error
+ *
+ * Implementation differences from above:
+ * - Redefined y to be actually c - b, this gives us a lot more precision
+ * to do the math. (c-b)/b variations are more obvious than c/b variations.
+ * - Since we don't have floating point, any operations involving slope are
+ * done using fixed point math (*M_PRECISION)
+ * - Since x and y grow with time, we keep zeroing the graph (relative to
+ * the last sample), this way math involving *x[n-i] will not overflow
+ * - EC timestamps are kept in us, it improves the slope calculation precision
+ */
+
+/*
+ * cros_ec_ring_ts_filter_update: Given a new IRQ timestamp pair (EC and
+ * AP timebases), add it to the filter history.
+ *
+ * @b IRQ timestamp, EC timebase (us)
+ * @c IRQ timestamp, AP timebase (ns)
+ */
+static void cros_ec_ring_ts_filter_update(
+   struct cros_ec_sensors_ts_filter_state *state,
+   s64 b, s64 c)
+{
+   s64 x, y;
+   s64 dx, dy;
+   s64 m; /* stored as *M_PRECISION */
+   s64 *m_history_copy = state->temp_buf;
+   s64 *error = state->temp_buf;
+   int i;
+
+   /*

[PATCH 02/13] platform: cros_ec: Add cros_ec_sensor_hub driver

2019-09-22 Thread Gwendal Grignou
Similar to HID sensor stack, the new driver sits between cros_ec_dev
and the iio device drivers:

EC based iio device topology would be:
iio:device1 ->
...0/:00:1f.0/PNP0C09:00/GOOG0004:00/cros-ec-dev.6.auto/
 cros-ec-sensorhub.7.auto/
 cros-ec-accel.15.auto/
 iio:device1

It will be expanded to control EC sensor FIFO.

Signed-off-by: Gwendal Grignou 
---
 drivers/iio/common/cros_ec_sensors/Kconfig|   2 +-
 drivers/platform/chrome/Kconfig   |  18 +-
 drivers/platform/chrome/Makefile  |   1 +
 drivers/platform/chrome/cros_ec_sensorhub.c   | 211 ++
 .../linux/platform_data/cros_ec_sensorhub.h   |  21 ++
 5 files changed, 249 insertions(+), 4 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_sensorhub.c
 create mode 100644 include/linux/platform_data/cros_ec_sensorhub.h

diff --git a/drivers/iio/common/cros_ec_sensors/Kconfig 
b/drivers/iio/common/cros_ec_sensors/Kconfig
index cdbb29cfb907..fefad9572790 100644
--- a/drivers/iio/common/cros_ec_sensors/Kconfig
+++ b/drivers/iio/common/cros_ec_sensors/Kconfig
@@ -4,7 +4,7 @@
 #
 config IIO_CROS_EC_SENSORS_CORE
tristate "ChromeOS EC Sensors Core"
-   depends on SYSFS && CROS_EC
+   depends on SYSFS && CROS_EC_SENSORHUB
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index ee5f08ea57b6..add967236cfb 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -132,9 +132,9 @@ config CROS_EC_LPC
  module will be called cros_ec_lpcs.
 
 config CROS_EC_PROTO
-bool
-help
-  ChromeOS EC communication protocol helpers.
+   bool
+   help
+ ChromeOS EC communication protocol helpers.
 
 config CROS_KBD_LED_BACKLIGHT
tristate "Backlight LED support for Chrome OS keyboards"
@@ -190,6 +190,18 @@ config CROS_EC_DEBUGFS
  To compile this driver as a module, choose M here: the
  module will be called cros_ec_debugfs.
 
+config CROS_EC_SENSORHUB
+   tristate "ChromeOS EC MEMS Senosr Hub"
+   depends on CROS_EC && IIO
+   help
+ Allow loading IIO sensors. This driver is loaded by MFD and will in
+ turn query the EC and register the sensors.
+ It also spreads the sensor data coming from the EC to the IIO sensorr
+ object.
+
+ To compile this driver as a module, choose M here: the
+ module will be called cros_ec_sensorhub.
+
 config CROS_EC_SYSFS
tristate "ChromeOS EC control and information through sysfs"
depends on MFD_CROS_EC_DEV && SYSFS
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 477ec3d1d1c9..a164c40dc099 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_CROS_EC_PROTO)   += cros_ec_proto.o 
cros_ec_trace.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_chardev.o
 obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o
+obj-$(CONFIG_CROS_EC_SENSORHUB)+= cros_ec_sensorhub.o
 obj-$(CONFIG_CROS_EC_VBC)  += cros_ec_vbc.o
 obj-$(CONFIG_CROS_EC_DEBUGFS)  += cros_ec_debugfs.o
 obj-$(CONFIG_CROS_EC_SYSFS)+= cros_ec_sysfs.o
diff --git a/drivers/platform/chrome/cros_ec_sensorhub.c 
b/drivers/platform/chrome/cros_ec_sensorhub.c
new file mode 100644
index ..80688018ef66
--- /dev/null
+++ b/drivers/platform/chrome/cros_ec_sensorhub.c
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SensorHub: driver that discover sensors behind
+ * a ChromeOS Embedded controller.
+ *
+ * Copyright 2019 Google LLC
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define DRV_NAME   "cros-ec-sensorhub"
+
+static int cros_ec_sensors_register(struct device *dev,
+   struct cros_ec_dev *ec)
+{
+   int ret, i, id, sensor_num;
+   struct mfd_cell *sensor_cells;
+   struct cros_ec_sensor_platform *sensor_platforms;
+   int sensor_type[MOTIONSENSE_TYPE_MAX] = { 0 };
+   struct ec_params_motion_sense *params;
+   struct ec_response_motion_sense *resp;
+   struct cros_ec_command *msg;
+
+   sensor_num = cros_ec_get_sensor_count(ec);
+   if (sensor_num < 0) {
+   dev_err(dev,
+   "Unable to retrieve sensor information (err:%d)\n",
+   sensor_num);
+   return sensor_num;
+   }
+
+   if (sensor_num == 0) {
+   dev_err(dev, &q

[PATCH 08/13] platform: chrome: sensorhub: Add code to spread timestmap

2019-09-22 Thread Gwendal Grignou
EC FIFO can send sensor events in batch. Spread them based on
previous (TSa) and currnet timestamp (TSb)

  EC FIFO iio events
+---+
| TSa   |
+---+ +---+
| event 1   | | event 1 | TSb - (TSb - TSa)/n * (n-1) |
+---+ +---+
| event 2   | | event 2 | TSb - (TSb - TSa)/n * (n-2) |
+---+ +---+
|  ...  |  -->|     | |
+---+ +---+
| event n-1 | | event 2 | TSb - (TSb - TSa)/n |
+---+ +---+
| event n   | | event 2 | TSb |
+---+ +---+
| TSb   |
+---+

Signed-off-by: Gwendal Grignou 
---
 .../platform/chrome/cros_ec_sensorhub_ring.c  | 99 ++-
 1 file changed, 96 insertions(+), 3 deletions(-)

diff --git a/drivers/platform/chrome/cros_ec_sensorhub_ring.c 
b/drivers/platform/chrome/cros_ec_sensorhub_ring.c
index 8cd533d5542e..48327e80a5a3 100644
--- a/drivers/platform/chrome/cros_ec_sensorhub_ring.c
+++ b/drivers/platform/chrome/cros_ec_sensorhub_ring.c
@@ -160,6 +160,97 @@ static bool cros_ec_ring_process_event(
return true;
 }
 
+/*
+ * cros_ec_ring_spread_add: Calculate proper timestamps then
+ * add to ringbuffer (legacy).
+ *
+ * If there is a sample with a proper timestamp
+ *timestamp | count
+ * older_unprocess_out --> TS1  | 1
+ * TS1  | 2
+ * out --> TS1  | 3
+ * next_out -->TS2  |
+ * We spread time for the samples [older_unprocess_out .. out]
+ * between TS1 and TS2: [TS1+1/4, TS1+2/4, TS1+3/4, TS2].
+ *
+ * If we reach the end of the samples, we compare with the
+ * current timestamp:
+ *
+ * older_unprocess_out --> TS1  | 1
+ * TS1  | 2
+ * out --> TS1  | 3
+ * We know have [TS1+1/3, TS1+2/3, current timestamp]
+ */
+static void cros_ec_ring_spread_add(
+   struct cros_ec_sensorhub *sensorhub,
+   unsigned long sensor_mask,
+   s64 current_timestamp,
+   struct cros_ec_sensors_ring_sample *last_out)
+{
+   struct cros_ec_sensors_ring_sample *out;
+   int i;
+
+   for_each_set_bit(i, &sensor_mask, BITS_PER_LONG) {
+   s64 older_timestamp;
+   s64 timestamp;
+   struct cros_ec_sensors_ring_sample *older_unprocess_out =
+   sensorhub->ring;
+   struct cros_ec_sensors_ring_sample *next_out;
+   int count = 1;
+
+   for (out = sensorhub->ring; out < last_out; out = next_out) {
+   s64 time_period;
+
+   next_out = out + 1;
+   if (out->sensor_id != i)
+   continue;
+
+   /* Timestamp to start with */
+   older_timestamp = out->timestamp;
+
+   /* find next sample */
+   while (next_out < last_out && next_out->sensor_id != i)
+   next_out++;
+
+   if (next_out >= last_out) {
+   timestamp = current_timestamp;
+   } else {
+   timestamp = next_out->timestamp;
+   if (timestamp == older_timestamp) {
+   count++;
+   continue;
+   }
+   }
+
+   /*
+* The next sample has a new timestamp,
+* spread the unprocessed samples.
+*/
+   if (next_out < last_out)
+   count++;
+   time_period = div_s64(timestamp - older_timestamp,
+ count);
+
+   for (; older_unprocess_out <= out;
+   older_unprocess_out++) {
+   if (older_unprocess_out->sensor_id != i)
+   continue;
+   older_timestamp += time_period;
+   older_unprocess_out->timestamp =
+   older_timestamp;
+   }
+   count = 1;
+   /* The next_out sample has a valid timestamp, skip. */
+

[PATCH 01/13] mfd: cros_ec: Add sensor_count and make check_features public

2019-09-22 Thread Gwendal Grignou
Add a new function to return the number of MEMS sensors available in a
ChromeOS Embedded Controller.
It uses MOTIONSENSE_CMD_DUMP if available or a specific memory map ACPI
registers to find out.

Also, make check_features public as it can be useful for other drivers
to know whant the Embedded Controller supports.

Signed-off-by: Gwendal Grignou 
---
 drivers/mfd/cros_ec_dev.c   | 61 -
 include/linux/mfd/cros_ec.h | 17 +++
 2 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
index 6e6dfd6c1871..3be80183ccaa 100644
--- a/drivers/mfd/cros_ec_dev.c
+++ b/drivers/mfd/cros_ec_dev.c
@@ -112,7 +112,7 @@ static const struct mfd_cell cros_ec_vbc_cells[] = {
{ .name = "cros-ec-vbc", }
 };
 
-static int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
+int cros_ec_check_features(struct cros_ec_dev *ec, int feature)
 {
struct cros_ec_command *msg;
int ret;
@@ -143,12 +143,71 @@ static int cros_ec_check_features(struct cros_ec_dev *ec, 
int feature)
 
return ec->features[feature / 32] & EC_FEATURE_MASK_0(feature);
 }
+EXPORT_SYMBOL_GPL(cros_ec_check_features);
 
 static void cros_ec_class_release(struct device *dev)
 {
kfree(to_cros_ec_dev(dev));
 }
 
+int cros_ec_get_sensor_count(struct cros_ec_dev *ec)
+{
+   /*
+* Issue a command to get the number of sensor reported.
+* If not supported, check for legacy mode.
+*/
+   int ret, sensor_count;
+   struct ec_params_motion_sense *params;
+   struct ec_response_motion_sense *resp;
+   struct cros_ec_command *msg;
+   struct cros_ec_device *ec_dev = ec->ec_dev;
+   u8 status;
+
+   msg = kzalloc(sizeof(struct cros_ec_command) +
+   max(sizeof(*params), sizeof(*resp)), GFP_KERNEL);
+   if (msg == NULL)
+   return -ENOMEM;
+
+   msg->version = 1;
+   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) {
+   sensor_count = ret;
+   } else if (msg->result != EC_RES_SUCCESS) {
+   sensor_count = -EPROTO;
+   } else {
+   resp = (struct ec_response_motion_sense *)msg->data;
+   sensor_count = resp->dump.sensor_count;
+   }
+   kfree(msg);
+
+   /*
+* Check legacy mode: Let's find out if sensors are accessible
+* via LPC interface.
+*/
+   if (sensor_count == -EPROTO &&
+   ec->cmd_offset == 0 &&
+   ec_dev->cmd_readmem) {
+   ret = ec_dev->cmd_readmem(ec_dev, EC_MEMMAP_ACC_STATUS,
+   1, &status);
+   if ((ret >= 0) &&
+   (status & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT)) {
+   /*
+* We have 2 sensors, one in the lid, one in the base.
+*/
+   sensor_count = 2;
+   }
+   }
+   return sensor_count;
+}
+EXPORT_SYMBOL_GPL(cros_ec_get_sensor_count);
+
 static void cros_ec_sensors_register(struct cros_ec_dev *ec)
 {
/*
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 61c2875c2a40..578e0bbcafdc 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -32,4 +32,21 @@ struct cros_ec_dev {
 
 #define to_cros_ec_dev(dev)  container_of(dev, struct cros_ec_dev, class_dev)
 
+/**
+ * cros_ec_check_features - Test for the presence of EC features
+ *
+ * Call this function to test whether the ChromeOS EC supports a feature.
+ *
+ * @ec_dev: EC device
+ * @msg: One of ec_feature_code values
+ * @return: 1 if supported, 0 if not
+ */
+int cros_ec_check_features(struct cros_ec_dev *ec, int feature);
+
+/*
+ * Return the number of MEMS sensors supported.
+ * Return < 0 in case of error.
+ */
+int cros_ec_get_sensor_count(struct cros_ec_dev *ec);
+
 #endif /* __LINUX_MFD_CROS_EC_H */
-- 
2.23.0.351.gc4317032e6-goog



[PATCH 00/13] cros_ec: Add sensorhub driver and FIFO processing

2019-09-22 Thread Gwendal Grignou
This patchset adds a sensorhub driver for spreading sensor
events coming from the Embedded controller sensor FIFO:

   +---+ +--+ +
   | cros_ec_accel | | cros_ec_gyro | | ...
   +---+ +--+ +
   id:0   \id:1 |   / id:..
 +--+
 |   cros_ec_sensorhub  |
 +--+
 |   cros_ec_dev|
 +--+
 | cros_ec_i2c, cros_ec_lpc, .. |
 +--+
 |
 EC

When new sensors events are present, the EC raises and interrupt,
sensorhub reads the FIFO and uses the 'id' field to spread the event to
the proper IIO sensors. This stack is similar to the HID sensor input
stack.

The first 3 patches add a primitive cros_ec_sensorhub. MFD just have to
register this driver if at least one sensor is presented by the EC.
cros_ec_sensorhub retrieves more information from the EC to find out
which sensors are actually present:
  mfd: cros_ec: Add sensor_count and make check_features public
  platform: cros_ec: Add cros_ec_sensor_hub driver
  platform/mfd:iio: cros_ec: Register sensor through sensorhub

The next 3 patches prepare for FIFO support:
  platform: chrome: cros-ec: record event timestamp in the hard irq
  platform: chrome: cros_ec: Do not attempt to register a non-positive
  platform: chrome: cros_ec: handle MKBP more events flag

The next 4 patches add FIFO support. An interface is added to connect
the IIO sensors with cros_ec_sensorhub, and filters are needed to spread
the timestamp when the EC send batches of events and deal with variation
in interrupt delay.
  platform: chrome: sensorhub: Add FIFO support
  platform: chrome: sensorhub: Add code to spread timestmap
  platform: chrome: sensorhub: Add median filter
  iio: cros_ec: Use triggered buffer only when EC does not support FIFO

Finally, the last 3 patches present sensor information following the IIO
ABI:
-  Configurable EC timeout to allow batch mode in buffer/hwfifo_timeout,
  in seconds.
-  Hard coded EC FIFO size in buffer/hwfifo_watermark_max
-  Sensor sampling frequency in hertz at sampling_frequency:
  iio: cros_ec: Expose hwfifo_timeout
  iio: cros_ec: Report hwfifo_watermark_max
  iio: cros_ec: Use Hertz as unit for sampling frequency

For testing, libiio test tools can be used:
A iio device link looks like:
iio:device1 ->
...09:00/GOOG0004:00/cros-ec-dev.6.auto/cros-ec-sensorhub.7.auto/
 cros-ec-accel.15.auto/iio:device1

When FIFO is available, no trigger are presented. Once
sampling_freqeuncy and hwfifo_timeout are set, sensor events flow
when listening to /dev/iio:device1:
echo 12 > sampling_frequency   # Set ODR to at least 12Hz
echo .100 > buffer/hwfifo_timeout  # do not wait more than 100ms to
   # to send samples
iio_readdev -b 2 -T 1000 -s 2 iio:device1 2>/dev/null| od -x
000 ffd0 2e20 d990  8630 b56c 07ea 
020 ffc0 2e10 d970  877e b56c 07ea 
040`

When FIFO is not supported by the EC, a trigger is present in the
directory. After registering a trigger, setting sampling_frequency,
the latest data collected by the sensor will be retrieved by the host
when the trigger expires.

When cros_ec_accel_legacy driver is used, no FIFO is supported and the
sampling frequency for the accelerometers is hard coded at 10Hz.

This set is built upon the master branch of
git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git


Enrico Granata (2):
  platform: chrome: cros_ec: Do not attempt to register a non-positive
IRQ number
  platform: chrome: cros_ec: handle MKBP more events flag

Gwendal Grignou (11):
  mfd: cros_ec: Add sensor_count and make check_features public
  platform: cros_ec: Add cros_ec_sensor_hub driver
  platform/mfd:iio: cros_ec: Register sensor through sensorhub
  platform: chrome: cros-ec: record event timestamp in the hard irq
  platform: chrome: sensorhub: Add FIFO support
  platform: chrome: sensorhub: Add code to spread timestmap
  platform: chrome: sensorhub: Add median filter
  iio: cros_ec: Use triggered buffer only when EC does not support FIFO
  iio: cros_ec: Expose hwfifo_timeout
  iio: cros_ec: Report hwfifo_watermark_max
  iio: cros_ec: Use Hertz as unit for sampling frequency

 drivers/iio/accel/cros_ec_accel_legacy.c  |  13 +-
 drivers/iio/common/cros_ec_sensors/Kconfig|   2 +-
 .../cros_ec_sensors/cros_ec_lid_angle.c   |   2 +-
 .../common/cros_ec_sensors/cros_ec_sensors.c  |  14 +-
 .../cros_ec_sensors/cros_ec_sensors_core.c| 251 -
 drivers/iio/light/cros_ec_light_prox.c|  18 +-
 drivers/iio/pressure/cros_ec_baro.c   |  12 +-
 drivers/mfd/cros_ec_dev.c | 208 +---
 drivers/p

[PATCH 07/13] platform: chrome: sensorhub: Add FIFO support

2019-09-22 Thread Gwendal Grignou
cros_ec_sensorhub registers a listener and query motion sense FIFO,
spread to iio sensors registers.

To test, we can use libiio:
iiod&
iio_readdev -u ip:localhost -T 1 -s 25 -b 16 cros-ec-gyro | od -x

Signed-off-by: Gwendal Grignou 
---
 drivers/iio/accel/cros_ec_accel_legacy.c  |   1 +
 .../common/cros_ec_sensors/cros_ec_sensors.c  |   1 +
 .../cros_ec_sensors/cros_ec_sensors_core.c|  13 +
 drivers/iio/light/cros_ec_light_prox.c|   1 +
 drivers/iio/pressure/cros_ec_baro.c   |   1 +
 drivers/platform/chrome/Makefile  |   3 +-
 drivers/platform/chrome/cros_ec_sensorhub.c   | 130 --
 .../platform/chrome/cros_ec_sensorhub_ring.c  | 374 ++
 .../linux/iio/common/cros_ec_sensors_core.h   |   3 +
 .../linux/platform_data/cros_ec_sensorhub.h   |  79 
 10 files changed, 569 insertions(+), 37 deletions(-)
 create mode 100644 drivers/platform/chrome/cros_ec_sensorhub_ring.c

diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c 
b/drivers/iio/accel/cros_ec_accel_legacy.c
index c9af6fa0670d..591c0d962c44 100644
--- a/drivers/iio/accel/cros_ec_accel_legacy.c
+++ b/drivers/iio/accel/cros_ec_accel_legacy.c
@@ -212,6 +212,7 @@ static struct platform_driver cros_ec_accel_platform_driver 
= {
.name   = DRV_NAME,
},
.probe  = cros_ec_accel_legacy_probe,
+   .remove = cros_ec_sensors_core_clean,
 };
 module_platform_driver(cros_ec_accel_platform_driver);
 
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 5bd6f54afc42..a88dd8deade9 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -329,6 +329,7 @@ static struct platform_driver 
cros_ec_sensors_platform_driver = {
.pm = &cros_ec_sensors_pm_ops,
},
.probe  = cros_ec_sensors_probe,
+   .remove = cros_ec_sensors_core_clean,
.id_table   = cros_ec_sensors_ids,
 };
 module_platform_driver(cros_ec_sensors_platform_driver);
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
index 81a7f692de2f..43eb1d42820e 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -160,6 +160,19 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init);
 
+int cros_ec_sensors_core_clean(struct platform_device *pdev)
+{
+   struct cros_ec_sensorhub *sensor_hub =
+   dev_get_drvdata(pdev->dev.parent);
+   struct iio_dev *indio_dev = platform_get_drvdata(pdev);
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+   u8 sensor_num = st->param.info.sensor_num;
+
+   cros_ec_sensorhub_unregister_push_data(sensor_hub, sensor_num);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(cros_ec_sensors_core_clean);
+
 int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *state,
 u16 opt_length)
 {
diff --git a/drivers/iio/light/cros_ec_light_prox.c 
b/drivers/iio/light/cros_ec_light_prox.c
index 205effc1f404..c431e4d1482d 100644
--- a/drivers/iio/light/cros_ec_light_prox.c
+++ b/drivers/iio/light/cros_ec_light_prox.c
@@ -270,6 +270,7 @@ static struct platform_driver 
cros_ec_light_prox_platform_driver = {
.pm = &cros_ec_sensors_pm_ops,
},
.probe  = cros_ec_light_prox_probe,
+   .remove = cros_ec_sensors_core_clean,
.id_table   = cros_ec_light_prox_ids,
 };
 module_platform_driver(cros_ec_light_prox_platform_driver);
diff --git a/drivers/iio/pressure/cros_ec_baro.c 
b/drivers/iio/pressure/cros_ec_baro.c
index 2354302375de..2f4d6d3ab41d 100644
--- a/drivers/iio/pressure/cros_ec_baro.c
+++ b/drivers/iio/pressure/cros_ec_baro.c
@@ -201,6 +201,7 @@ static struct platform_driver cros_ec_baro_platform_driver 
= {
.name   = "cros-ec-baro",
},
.probe  = cros_ec_baro_probe,
+   .remove = cros_ec_sensors_core_clean,
.id_table   = cros_ec_baro_ids,
 };
 module_platform_driver(cros_ec_baro_platform_driver);
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index a164c40dc099..cb709048c003 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -17,7 +17,8 @@ obj-$(CONFIG_CROS_EC_PROTO)   += cros_ec_proto.o 
cros_ec_trace.o
 obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
 obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_chardev.o
 obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o
-obj-$(CONFIG_CROS_EC_SENSORHUB)+= cros_ec_sensorhub.o
+cros_ec_sensorsupport-objs := cros_ec_sensorhub_ring

[PATCH 04/13] platform: chrome: cros-ec: record event timestamp in the hard irq

2019-09-22 Thread Gwendal Grignou
To improve sensor timestamp precision, given EC and AP are in
different time domains, the AP needs to try to record the exact
moment an event was signalled to the AP by the EC as soon as
possible after it happens.

First thing in the hard irq is the best place for this.

Signed-off-by: Gwendal Grignou 
---
 drivers/platform/chrome/cros_ec.c   | 18 +-
 drivers/platform/chrome/cros_ec_lpc.c   |  2 ++
 include/linux/platform_data/cros_ec_proto.h | 15 +++
 3 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/chrome/cros_ec.c 
b/drivers/platform/chrome/cros_ec.c
index fd77e6fa74c2..f49eb1d1e3cd 100644
--- a/drivers/platform/chrome/cros_ec.c
+++ b/drivers/platform/chrome/cros_ec.c
@@ -31,6 +31,21 @@ static struct cros_ec_platform pd_p = {
.cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX),
 };
 
+s64 cros_ec_get_time_ns(void)
+{
+   return ktime_get_boottime_ns();
+}
+EXPORT_SYMBOL(cros_ec_get_time_ns);
+
+static irqreturn_t ec_irq_handler(int irq, void *data)
+{
+   struct cros_ec_device *ec_dev = data;
+
+   ec_dev->last_event_time = cros_ec_get_time_ns();
+
+   return IRQ_WAKE_THREAD;
+}
+
 static irqreturn_t ec_irq_thread(int irq, void *data)
 {
struct cros_ec_device *ec_dev = data;
@@ -132,7 +147,8 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
}
 
if (ec_dev->irq) {
-   err = devm_request_threaded_irq(dev, ec_dev->irq, NULL,
+   err = devm_request_threaded_irq(
+   dev, ec_dev->irq, ec_irq_handler,
ec_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT,
"chromeos-ec", ec_dev);
if (err) {
diff --git a/drivers/platform/chrome/cros_ec_lpc.c 
b/drivers/platform/chrome/cros_ec_lpc.c
index 7d10d909435f..3c77496e164d 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -313,6 +313,8 @@ static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 
value, void *data)
 {
struct cros_ec_device *ec_dev = data;
 
+   ec_dev->last_event_time = cros_ec_get_time_ns();
+
if (ec_dev->mkbp_event_supported &&
cros_ec_get_next_event(ec_dev, NULL) > 0)
blocking_notifier_call_chain(&ec_dev->event_notifier, 0,
diff --git a/include/linux/platform_data/cros_ec_proto.h 
b/include/linux/platform_data/cros_ec_proto.h
index e91e3fcb0348..ab12e28f2107 100644
--- a/include/linux/platform_data/cros_ec_proto.h
+++ b/include/linux/platform_data/cros_ec_proto.h
@@ -121,6 +121,8 @@ struct cros_ec_command {
  * @event_data: Raw payload transferred with the MKBP event.
  * @event_size: Size in bytes of the event data.
  * @host_event_wake_mask: Mask of host events that cause wake from suspend.
+ * @last_event_time: exact time from the hard irq when we got notified of
+ * a new event.
  * @ec: The platform_device used by the mfd driver to interface with the
  *  main EC.
  * @pd: The platform_device used by the mfd driver to interface with the
@@ -161,6 +163,7 @@ struct cros_ec_device {
int event_size;
u32 host_event_wake_mask;
u32 last_resume_result;
+   s64 last_event_time;
 
/* The platform devices used by the mfd driver */
struct platform_device *ec;
@@ -308,4 +311,16 @@ int cros_ec_get_next_event(struct cros_ec_device *ec_dev, 
bool *wake_event);
  */
 u32 cros_ec_get_host_event(struct cros_ec_device *ec_dev);
 
+/**
+ * cros_ec_get_time_ns - Return time in ns.
+ *
+ * This is the function used to record the time for last_event_time in struct
+ * cros_ec_device during the hard irq.
+ *
+ * This function is probably implemented using ktime_get_boot_ns(), but it's
+ * exposed here to make sure all cros_ec drivers use the same code path to get
+ * the time.
+ */
+s64 cros_ec_get_time_ns(void);
+
 #endif /* __LINUX_CROS_EC_PROTO_H */
-- 
2.23.0.351.gc4317032e6-goog



Re: [PATCH v2] platform/chrome: cros_ec_chardev: Add a poll handler to receive MKBP events

2019-09-05 Thread Gwendal Grignou
On Mon, Sep 2, 2019 at 9:24 AM Andy Shevchenko
 wrote:
>
> On Mon, Sep 02, 2019 at 06:08:48PM +0200, Enric Balletbo i Serra wrote:
> > Allow to poll on the cros_ec device to receive the MKBP events.
> >
> > The /dev/cros_[ec|fp|..] file operations now implements the poll
> > operation. The userspace can now receive specific MKBP events by doing
> > the
> > following:
> > - Open the /dev/cros_XX file.
> > - Call the CROS_EC_DEV_IOCEVENTMASK ioctl with the bitmap of the MKBP
> >   events it wishes to receive as argument.
> > - Poll on the file descriptor.
> > - When it gets POLLIN, do a read on the file descriptor, the first
> >   queued event will be returned (using the struct
> >   ec_response_get_next_event format: one byte of event type, then
> >   the payload).
> >
> > The read() operation returns at most one event even if there are several
> > queued, and it might be truncated if the buffer is smaller than the
> > event (but the caller should know the maximum size of the events it is
> > reading).
> >
> > read() used to return the EC version string, it still does it when no
> > event mask or an empty event is set for backward compatibility (despite
> > nobody really using this feature).
> >
> > This will be used, for example, by the userspace daemon to receive and
> > treat the EC_MKBP_EVENT_FINGERPRINT sent by the FP MCU.
> >
>
> Acked-by: Andy Shevchenko 
Reviewed-by: Gwendal Grignou 
>
> > Signed-off-by: Vincent Palatin 
> > Signed-off-by: Enric Balletbo i Serra 
> > ---
> > Note that this patch depends on the immutable branch [1] to apply
> > cleanly.
> >
> > [1] 
> > https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git/log/?h=ib-mfd-extcon-hid-i2c-iio-input-media-chrome-power-pwm-rtc-sound-5.4
> >
> >
> > Changes in v2:
> > - Moved the code to the cros_ec_chardev driver.
> >
> >  drivers/platform/chrome/cros_ec_chardev.c | 177 +-
> >  include/linux/platform_data/cros_ec_chardev.h |   1 +
> >  2 files changed, 173 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/platform/chrome/cros_ec_chardev.c 
> > b/drivers/platform/chrome/cros_ec_chardev.c
> > index 08abd7e5c7bf..eabb1fe85688 100644
> > --- a/drivers/platform/chrome/cros_ec_chardev.c
> > +++ b/drivers/platform/chrome/cros_ec_chardev.c
> > @@ -16,21 +16,42 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> >
> >  #define DRV_NAME "cros-ec-chardev"
> >
> > +/* Arbitrary bounded size for the event queue */
> > +#define CROS_MAX_EVENT_LEN   PAGE_SIZE
> > +
> >  struct chardev_data {
> >   struct cros_ec_dev *ec_dev;
> >   struct miscdevice misc;
> >  };
> >
> > +struct chardev_priv {
> > + struct cros_ec_dev *ec_dev;
> > + struct notifier_block notifier;
> > + wait_queue_head_t wait_event;
> > + unsigned long event_mask;
> > + struct list_head events;
> > + size_t event_len;
> > +};
> > +
> > +struct ec_event {
> > + struct list_head node;
> > + size_t size;
> > + u8 event_type;
> > + u8 data[0];
> > +};
> > +
> >  static int ec_get_version(struct cros_ec_dev *ec, char *str, int maxlen)
> >  {
> >   static const char * const current_image_name[] = {
> > @@ -69,6 +90,71 @@ static int ec_get_version(struct cros_ec_dev *ec, char 
> > *str, int maxlen)
> >   return ret;
> >  }
> >
> > +static int ec_mkbp_event(struct notifier_block *nb,
> > +  unsigned long queued_during_suspend,
> > +  void *_notify)
nit: call it cros_ec_chardev_mkbp_event()  to fit other functions
naming convention. Change only if a v3 is needed.
> > +{
> > + struct chardev_priv *priv = container_of(nb, struct chardev_priv,
> > +  notifier);
> > + struct cros_ec_device *ec_dev = priv->ec_dev->ec_dev;
> > + struct ec_event *event;
> > + unsigned long event_bit = 1 << ec_dev->event_data.event_type;
> > + int total_size = sizeof(*event) + ec_dev->event_size;
> > +
> > + if (!(event_bit & priv->event_mask) ||
> > + (priv->event_len + total_size) > CROS_MAX_EVENT_LEN)
> > + return NOTIFY_DONE;
> > +

[PATCH] iio: cros_ec: set calibscale for 3d MEMS to unit vector

2019-08-19 Thread Gwendal Grignou
By default, set the calibscale vector to unit vector.
It prevents sending 0 as calibscale when not initialized.

Signed-off-by: Gwendal Grignou 
---

 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

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
index fd833295bb173..d44ae126f4578 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -90,7 +90,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
struct cros_ec_dev *ec = dev_get_drvdata(pdev->dev.parent);
struct cros_ec_sensor_platform *sensor_platform = dev_get_platdata(dev);
u32 ver_mask;
-   int ret;
+   int ret, i;
 
platform_set_drvdata(pdev, indio_dev);
 
@@ -136,6 +136,9 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
/* Set sign vector, only used for backward compatibility. */
memset(state->sign, 1, CROS_EC_SENSOR_MAX_AXIS);
 
+   for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
+   state->calib[i].scale = MOTION_SENSE_DEFAULT_SCALE;
+
/* 0 is a correct value used to stop the device */
state->frequencies[0] = 0;
if (state->msg->version < 3) {
-- 
2.23.0.rc1.153.gdeed80330f-goog



[PATCH] iio: cros_ec: Add calibscale for 3d MEMS

2019-07-18 Thread Gwendal Grignou
Add calibration scale support to accel, gyro and magnetometer.

Check on eve with current firmware, check reading calibscale returns 1.0,
check with newer firmware values are applied.

Signed-off-by: Gwendal Grignou 
---

 .../common/cros_ec_sensors/cros_ec_sensors.c  | 51 +--
 .../cros_ec_sensors/cros_ec_sensors_core.c|  2 +-
 drivers/iio/light/cros_ec_light_prox.c| 12 ++---
 drivers/iio/pressure/cros_ec_baro.c   |  2 -
 .../linux/iio/common/cros_ec_sensors_core.h   |  5 +-
 5 files changed, 57 insertions(+), 15 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 17af4e0fd5f8..2af09606c438 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -63,10 +63,35 @@ static int cros_ec_sensors_read(struct iio_dev *indio_dev,
 
/* Save values */
for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
-   st->core.calib[i] =
+   st->core.calib[i].offset =
st->core.resp->sensor_offset.offset[i];
ret = IIO_VAL_INT;
-   *val = st->core.calib[idx];
+   *val = st->core.calib[idx].offset;
+   break;
+   case IIO_CHAN_INFO_CALIBSCALE:
+   st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_SCALE;
+   st->core.param.sensor_offset.flags = 0;
+
+   ret = cros_ec_motion_send_host_cmd(&st->core, 0);
+   if (ret == -EPROTO) {
+   /* Reading calibscale is not supported on older EC. */
+   *val = 1;
+   *val2 = 0;
+   ret = IIO_VAL_INT_PLUS_MICRO;
+   break;
+   } else if (ret) {
+   break;
+   }
+
+   /* Save values */
+   for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
+   st->core.calib[i].scale =
+   st->core.resp->sensor_scale.scale[i];
+
+   *val = st->core.calib[idx].scale >> 15;
+   *val2 = ((st->core.calib[idx].scale & 0x7FFF) * 100LL) /
+   MOTION_SENSE_DEFAULT_SCALE;
+   ret = IIO_VAL_INT_PLUS_MICRO;
break;
case IIO_CHAN_INFO_SCALE:
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
@@ -134,7 +159,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
 
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
-   st->core.calib[idx] = val;
+   st->core.calib[idx].offset = val;
 
/* Send to EC for each axis, even if not complete */
st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
@@ -142,10 +167,25 @@ static int cros_ec_sensors_write(struct iio_dev 
*indio_dev,
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.calib[i].offset;
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_CALIBSCALE:
+   st->core.calib[idx].scale = val;
+   /* Send to EC for each axis, even if not complete */
+
+   st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_SCALE;
+   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_scale.scale[i] =
+   st->core.calib[i].scale;
+   st->core.param.sensor_scale.temp =
+   EC_MOTION_SENSE_INVALID_CALIB_TEMP;
+
ret = cros_ec_motion_send_host_cmd(&st->core, 0);
break;
case IIO_CHAN_INFO_SCALE:
@@ -206,7 +246,8 @@ static int cros_ec_sensors_probe(struct platform_device 
*pdev)
/* Common part */
channel->info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) |
-   BIT(IIO_CHAN_INFO_CALIBBIAS);
+   BIT(IIO_CHAN_INFO_CALIBBIAS) |
+   BIT(IIO_CHAN_INFO_CALIBSCALE);
channel->info_mask_shared_by_all =
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_FREQUENCY) |
diff --git a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_co

[PATCH] iio: cros_ec: Remove replacing error code with -EIO

2019-07-18 Thread Gwendal Grignou
Due to an API misread, error code can be different for -EIO when reading
a sysfs entry. Return the error reported by the cros_ec stack.

Check the proper error message (protocol error, not supported) is
reported when there is an error returned by the EC stack.

Signed-off-by: Gwendal Grignou 
---

 .../cros_ec_sensors/cros_ec_sensors_core.c| 44 +++
 drivers/iio/light/cros_ec_light_prox.c| 36 +++
 drivers/iio/pressure/cros_ec_baro.c   | 17 ---
 3 files changed, 51 insertions(+), 46 deletions(-)

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
index 130362ca421b..ed29ac22dff8 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -33,6 +33,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
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);
+   int ret;
 
platform_set_drvdata(pdev, indio_dev);
 
@@ -60,9 +61,10 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
 
state->param.cmd = MOTIONSENSE_CMD_INFO;
state->param.info.sensor_num = sensor_platform->sensor_num;
-   if (cros_ec_motion_send_host_cmd(state, 0)) {
+   ret = cros_ec_motion_send_host_cmd(state, 0);
+   if (ret) {
dev_warn(dev, "Can not access sensor info\n");
-   return -EIO;
+   return ret;
}
state->type = state->resp->info.type;
state->loc = state->resp->info.location;
@@ -86,7 +88,7 @@ int cros_ec_motion_send_host_cmd(struct 
cros_ec_sensors_core_state *state,
 
ret = cros_ec_cmd_xfer_status(state->ec, state->msg);
if (ret < 0)
-   return -EIO;
+   return ret;
 
if (ret &&
state->resp != (struct ec_response_motion_sense *)state->msg->data)
@@ -396,7 +398,7 @@ 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;
+   int ret;
 
switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
@@ -404,22 +406,27 @@ int cros_ec_sensors_core_read(struct 
cros_ec_sensors_core_state *st,
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;
+   ret = cros_ec_motion_send_host_cmd(st, 0);
+   if (ret)
+   break;
+
+   *val = st->resp->ec_rate.ret;
+   ret = IIO_VAL_INT;
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;
+   ret = cros_ec_motion_send_host_cmd(st, 0);
+   if (ret)
+   break;
+
+   *val = st->resp->sensor_odr.ret;
+   ret = IIO_VAL_INT;
break;
default:
+   ret = -EINVAL;
break;
}
 
@@ -431,7 +438,7 @@ 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;
+   int ret;
 
switch (mask) {
case IIO_CHAN_INFO_FREQUENCY:
@@ -441,17 +448,16 @@ int cros_ec_sensors_core_write(struct 
cros_ec_sensors_core_state *st,
/* 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;
+   ret = cros_ec_motion_send_host_cmd(st, 0);
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;
+   ret = cros_ec_motion_send_host_cmd(st, 0);
+   if (ret)
+

Re: [PATCH] iio: cros_ec_accel_legacy: Always release lock when returning from _read()

2019-07-15 Thread Gwendal Grignou
Let's use Matthias CL.

On Mon, Jul 15, 2019 at 4:17 PM Gwendal Grignou  wrote:
>
> Sorry for the original mistake. I upload a patch at
> https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/1702884.
>
> On Mon, Jul 15, 2019 at 1:04 PM Matthias Kaehlcke  wrote:
> >
> > Hi Benson,
> >
> > On Mon, Jul 15, 2019 at 12:55:57PM -0700, Benson Leung wrote:
> > > Hi Matthias,
> > >
> > > On Mon, Jul 15, 2019 at 12:10:17PM -0700, Matthias Kaehlcke wrote:
> > > > Before doing any actual work cros_ec_accel_legacy_read() acquires
> > > > a mutex, which is released at the end of the function. However for
> > > > 'calibbias' channels the function returns directly, without releasing
> > > > the lock. The next attempt to acquire the lock blocks forever. Instead
> > > > of an explicit return statement use the common return path, which
> > > > releases the lock.
> > > >
> > > > Fixes: 11b86c7004ef1 ("platform/chrome: Add cros_ec_accel_legacy 
> > > > driver")
> > > > Signed-off-by: Matthias Kaehlcke 
> > > > ---
> > > >  drivers/iio/accel/cros_ec_accel_legacy.c | 3 ++-
> > > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c 
> > > > b/drivers/iio/accel/cros_ec_accel_legacy.c
> > > > index 46bb2e421bb9..27ca4a64dddf 100644
> > > > --- a/drivers/iio/accel/cros_ec_accel_legacy.c
> > > > +++ b/drivers/iio/accel/cros_ec_accel_legacy.c
> > > > @@ -206,7 +206,8 @@ static int cros_ec_accel_legacy_read(struct iio_dev 
> > > > *indio_dev,
> > > > case IIO_CHAN_INFO_CALIBBIAS:
> > > > /* Calibration not supported. */
> > > > *val = 0;
> > > > -   return IIO_VAL_INT;
> > > > +   ret = IIO_VAL_INT;
> > > > +   break;
> > >
> > > The value of ret is not used below this. It seems to be only used in
> > > case IIO_CHAN_INFO_RAW. In fact, with your change,
> > > there's no return value at all and we just reach the end of
> > > cros_ec_accel_legacy_read.
> > >
> > > > default:
> > > > return -EINVAL;
> > > > }
> > >
> >
> > I messed up. I was over-confident that a FROMLIST patch in our 4.19
> > kernel + this patch applying on upstream means that upstream uses the
> > same code. I should have double-checked that the upstream context is
> > actually the same.
> >
> > Sorry for the noise.


Re: [PATCH] iio: cros_ec_accel_legacy: Always release lock when returning from _read()

2019-07-15 Thread Gwendal Grignou
Sorry for the original mistake. I upload a patch at
https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/1702884.

On Mon, Jul 15, 2019 at 1:04 PM Matthias Kaehlcke  wrote:
>
> Hi Benson,
>
> On Mon, Jul 15, 2019 at 12:55:57PM -0700, Benson Leung wrote:
> > Hi Matthias,
> >
> > On Mon, Jul 15, 2019 at 12:10:17PM -0700, Matthias Kaehlcke wrote:
> > > Before doing any actual work cros_ec_accel_legacy_read() acquires
> > > a mutex, which is released at the end of the function. However for
> > > 'calibbias' channels the function returns directly, without releasing
> > > the lock. The next attempt to acquire the lock blocks forever. Instead
> > > of an explicit return statement use the common return path, which
> > > releases the lock.
> > >
> > > Fixes: 11b86c7004ef1 ("platform/chrome: Add cros_ec_accel_legacy driver")
> > > Signed-off-by: Matthias Kaehlcke 
> > > ---
> > >  drivers/iio/accel/cros_ec_accel_legacy.c | 3 ++-
> > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c 
> > > b/drivers/iio/accel/cros_ec_accel_legacy.c
> > > index 46bb2e421bb9..27ca4a64dddf 100644
> > > --- a/drivers/iio/accel/cros_ec_accel_legacy.c
> > > +++ b/drivers/iio/accel/cros_ec_accel_legacy.c
> > > @@ -206,7 +206,8 @@ static int cros_ec_accel_legacy_read(struct iio_dev 
> > > *indio_dev,
> > > case IIO_CHAN_INFO_CALIBBIAS:
> > > /* Calibration not supported. */
> > > *val = 0;
> > > -   return IIO_VAL_INT;
> > > +   ret = IIO_VAL_INT;
> > > +   break;
> >
> > The value of ret is not used below this. It seems to be only used in
> > case IIO_CHAN_INFO_RAW. In fact, with your change,
> > there's no return value at all and we just reach the end of
> > cros_ec_accel_legacy_read.
> >
> > > default:
> > > return -EINVAL;
> > > }
> >
>
> I messed up. I was over-confident that a FROMLIST patch in our 4.19
> kernel + this patch applying on upstream means that upstream uses the
> same code. I should have double-checked that the upstream context is
> actually the same.
>
> Sorry for the noise.


[PATCH v6 2/4] iio: cros_ec_accel_legacy: Fix incorrect channel setting

2019-07-15 Thread Gwendal Grignou
INFO_SCALE is set both for each channel and all channels.
iio is using all channel setting, so the error was not user visible.

Signed-off-by: Gwendal Grignou 
---
 drivers/iio/accel/cros_ec_accel_legacy.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c 
b/drivers/iio/accel/cros_ec_accel_legacy.c
index 46bb2e421bb9..ad19d9c716f4 100644
--- a/drivers/iio/accel/cros_ec_accel_legacy.c
+++ b/drivers/iio/accel/cros_ec_accel_legacy.c
@@ -319,7 +319,6 @@ static const struct iio_chan_spec_ext_info 
cros_ec_accel_legacy_ext_info[] = {
.modified = 1,  \
.info_mask_separate =   \
BIT(IIO_CHAN_INFO_RAW) |\
-   BIT(IIO_CHAN_INFO_SCALE) |  \
BIT(IIO_CHAN_INFO_CALIBBIAS),   \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE),\
.ext_info = cros_ec_accel_legacy_ext_info,  \
-- 
2.22.0.510.g264f2c817a-goog



[PATCH v6 3/4] iio: cros_ec_accel_legacy: Use cros_ec_sensors_core

2019-07-15 Thread Gwendal Grignou
Remove duplicate code in cros-ec-accel-legacy,
use cros-ec-sensors-core functions and structures when possible.

On glimmer, check the 2 accelerometers are presented and working.

Signed-off-by: Gwendal Grignou 
Acked-by: Jonathan Cameron 
---
 drivers/iio/accel/Kconfig|   4 +-
 drivers/iio/accel/cros_ec_accel_legacy.c | 336 ---
 2 files changed, 55 insertions(+), 285 deletions(-)

diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 62a970a20219..7d0848f9ea45 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -201,9 +201,7 @@ config HID_SENSOR_ACCEL_3D
 
 config IIO_CROS_EC_ACCEL_LEGACY
tristate "ChromeOS EC Legacy Accelerometer Sensor"
-   select IIO_BUFFER
-   select IIO_TRIGGERED_BUFFER
-   select CROS_EC_LPC_REGISTER_DEVICE
+   depends on IIO_CROS_EC_SENSORS_CORE
help
  Say yes here to get support for accelerometers on Chromebook using
  legacy EC firmware.
diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c 
b/drivers/iio/accel/cros_ec_accel_legacy.c
index ad19d9c716f4..f65578c65a1c 100644
--- a/drivers/iio/accel/cros_ec_accel_legacy.c
+++ b/drivers/iio/accel/cros_ec_accel_legacy.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -25,191 +26,51 @@
 
 #define DRV_NAME   "cros-ec-accel-legacy"
 
+#define CROS_EC_SENSOR_LEGACY_NUM 2
 /*
  * Sensor scale hard coded at 10 bits per g, computed as:
  * g / (2^10 - 1) = 0.009586168; with g = 9.80665 m.s^-2
  */
 #define ACCEL_LEGACY_NSCALE 9586168
 
-/* Indices for EC sensor values. */
-enum {
-   X,
-   Y,
-   Z,
-   MAX_AXIS,
-};
-
-/* State data for cros_ec_accel_legacy iio driver. */
-struct cros_ec_accel_legacy_state {
-   struct cros_ec_device *ec;
-
-   /*
-* Array holding data from a single capture. 2 bytes per channel
-* for the 3 channels plus the timestamp which is always last and
-* 8-bytes aligned.
-*/
-   s16 capture_data[8];
-   s8 sign[MAX_AXIS];
-   u8 sensor_num;
-};
-
-static int ec_cmd_read_u8(struct cros_ec_device *ec, unsigned int offset,
- u8 *dest)
-{
-   return ec->cmd_readmem(ec, offset, 1, dest);
-}
-
-static int ec_cmd_read_u16(struct cros_ec_device *ec, unsigned int offset,
-  u16 *dest)
-{
-   __le16 tmp;
-   int ret = ec->cmd_readmem(ec, offset, 2, &tmp);
-
-   *dest = le16_to_cpu(tmp);
-
-   return ret;
-}
-
-/**
- * read_ec_until_not_busy() - Read from EC status byte until it reads not busy.
- * @st: Pointer to state information for device.
- *
- * This function reads EC status until its busy bit gets cleared. It does not
- * wait indefinitely and returns -EIO if the EC status is still busy after a
- * few hundreds milliseconds.
- *
- * Return: 8-bit status if ok, -EIO on error
- */
-static int read_ec_until_not_busy(struct cros_ec_accel_legacy_state *st)
-{
-   struct cros_ec_device *ec = st->ec;
-   u8 status;
-   int attempts = 0;
-
-   ec_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status);
-   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);
-
-   ec_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status);
-   }
-
-   return status;
-}
-
-/**
- * read_ec_accel_data_unsafe() - Read acceleration data from EC shared memory.
- * @st:Pointer to state information for 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.
- */
-static void read_ec_accel_data_unsafe(struct cros_ec_accel_legacy_state *st,
- unsigned long scan_mask, s16 *data)
-{
-   int i = 0;
-   int num_enabled = bitmap_weight(&scan_mask, MAX_AXIS);
-
-   /* Read all sensors enabled in scan_mask. Each value is 2 bytes. */
-   while (num_enabled--) {
-   i = find_next_bit(&scan_mask, MAX_AXIS, i);
-   ec_cmd_read_u16(st->ec,
-   EC_MEMMAP_ACC_DATA +
-   sizeof(s16) *
-   (1 + i + st->sensor_num * MAX_AXIS),
-   data);
-   *data *= st->sign[i];
-   i++;
-   data++;
-   }
-}
-
-/**
- * read_ec_accel_data() - Read acceleration data from EC shared memory.
- * @st:Pointer to state information for device.
- * @scan_mask: Bitmap of the sensor indices to scan.
- * @data:  

[PATCH v6 0/4] Support accelerometers for veyron_minnie

2019-07-15 Thread Gwendal Grignou
veyron_minnie - ASUS Chromebook Flip C100PA - embedded controller
controls two accelerometers, one in the lid, one in the base.
However, the EC firmware does not follow the new interface that
cros_ec_accel driver use.
Extend the legacy driver used on glimmer - Lenovo ThinkPad 11e
Chromebook - to veyron_minnie.
veyron_minnie being ARM based, issue command over the I2C bus to the EC
instead of relying on the shared registers over LPC.

Gwendal Grignou (4):
  iio: cros_ec: Add sign vector in core for backward compatibility
  iio: cros_ec_accel_legacy: Fix incorrect channel setting
  iio: cros_ec_accel_legacy: Use cros_ec_sensors_core
  iio: cros_ec_accel_legacy: Add support for veyron-minnie

Changes in v5:
- In "Use cros_ec_sensors_core", fix return without unlock on the error
  path properly.

Changes in v5:
- In "Use cros_ec_sensors_core", fix return without unlock on the error
  path.
- Add acked for the last 2 patches.

Changes in v4:
- No change in iio/common/cros_ec_sensors
- Split cros_ec_accel_legacy code in 3:
  - fix an error in channel setting.
  - remove duplicate code in cros_ec_accel, use cros_ec_sensors_core.
  - extend cros_ec_accel to ARM device.
- Define cros_ec_accel_legacy_read_cmd() as static.

Changes in v3:
- Fix commit message, add reviewed-by for first patch.

Changes in v2:
- Readd empty line to reduce amount of change in patch.
- Remove Keywords used by ChromeOS commit queue.


 drivers/iio/accel/Kconfig |   4 +-
 drivers/iio/accel/cros_ec_accel_legacy.c  | 353 --
 .../cros_ec_sensors/cros_ec_sensors_core.c|   4 +
 .../linux/iio/common/cros_ec_sensors_core.h   |   1 +
 4 files changed, 86 insertions(+), 276 deletions(-)

-- 
2.22.0.510.g264f2c817a-goog



[PATCH v6 1/4] iio: cros_ec: Add sign vector in core for backward compatibility

2019-07-15 Thread Gwendal Grignou
To allow cros_ec iio core library to be used with legacy device, add a
vector to rotate sensor data if necessary: legacy devices are not
reporting data in HTML5/Android sensor referential.

Check the data is not rotated on recent chromebooks that use the HTML5
standard to present sensor data.

Signed-off-by: Gwendal Grignou 
Reviewed-by: Douglas Anderson 
---
 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c | 4 
 include/linux/iio/common/cros_ec_sensors_core.h   | 1 +
 2 files changed, 5 insertions(+)

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
index 719a0df5aeeb..e8a4d78659c8 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -66,6 +66,9 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
}
state->type = state->resp->info.type;
state->loc = state->resp->info.location;
+
+   /* Set sign vector, only used for backward compatibility. */
+   memset(state->sign, 1, CROS_EC_SENSOR_MAX_AXIS);
}
 
return 0;
@@ -254,6 +257,7 @@ static int cros_ec_sensors_read_data_unsafe(struct iio_dev 
*indio_dev,
if (ret < 0)
return ret;
 
+   *data *= st->sign[i];
data++;
}
 
diff --git a/include/linux/iio/common/cros_ec_sensors_core.h 
b/include/linux/iio/common/cros_ec_sensors_core.h
index ce16445411ac..a1c85ad4df91 100644
--- a/include/linux/iio/common/cros_ec_sensors_core.h
+++ b/include/linux/iio/common/cros_ec_sensors_core.h
@@ -71,6 +71,7 @@ struct cros_ec_sensors_core_state {
enum motionsensor_location loc;
 
s16 calib[CROS_EC_SENSOR_MAX_AXIS];
+   s8 sign[CROS_EC_SENSOR_MAX_AXIS];
 
u8 samples[CROS_EC_SAMPLE_SIZE];
 
-- 
2.22.0.510.g264f2c817a-goog



[PATCH v6 4/4] iio: cros_ec_accel_legacy: Add support for veyron-minnie

2019-07-15 Thread Gwendal Grignou
Veyron minnie embedded controller presents 2 accelerometers using an
older interface. Add function to query the data in cros_ec_accel.

Verify accelerometers on veyron-minnie are presented and working.

Signed-off-by: Gwendal Grignou 
Acked-by: Jonathan Cameron 
---
 drivers/iio/accel/cros_ec_accel_legacy.c | 40 ++--
 1 file changed, 38 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c 
b/drivers/iio/accel/cros_ec_accel_legacy.c
index f65578c65a1c..39002cb5605d 100644
--- a/drivers/iio/accel/cros_ec_accel_legacy.c
+++ b/drivers/iio/accel/cros_ec_accel_legacy.c
@@ -5,7 +5,7 @@
  * Copyright 2017 Google, Inc
  *
  * This driver uses the memory mapper cros-ec interface to communicate
- * with the Chrome OS EC about accelerometer data.
+ * with the Chrome OS EC about accelerometer data or older commands.
  * Accelerometer access is presented through iio sysfs.
  */
 
@@ -33,6 +33,39 @@
  */
 #define ACCEL_LEGACY_NSCALE 9586168
 
+static int cros_ec_accel_legacy_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;
+   u8 sensor_num;
+
+   /*
+* Read all sensor data through a command.
+* Save sensor_num, it is assumed to stay.
+*/
+   sensor_num = st->param.info.sensor_num;
+   st->param.cmd = MOTIONSENSE_CMD_DUMP;
+   st->param.dump.max_sensor_count = CROS_EC_SENSOR_LEGACY_NUM;
+   ret = cros_ec_motion_send_host_cmd(st,
+   sizeof(st->resp->dump) + CROS_EC_SENSOR_LEGACY_NUM *
+   sizeof(struct ec_response_motion_sensor_data));
+   st->param.info.sensor_num = sensor_num;
+   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->dump.sensor[sensor_num].data[i] *
+   st->sign[i];
+   data++;
+   }
+
+   return 0;
+}
+
 static int cros_ec_accel_legacy_read(struct iio_dev *indio_dev,
 struct iio_chan_spec const *chan,
 int *val, int *val2, long mask)
@@ -150,7 +183,10 @@ static int cros_ec_accel_legacy_probe(struct 
platform_device *pdev)
indio_dev->info = &cros_ec_accel_legacy_info;
state = iio_priv(indio_dev);
 
-   state->read_ec_sensors_data = cros_ec_sensors_read_lpc;
+   if (state->ec->cmd_readmem != NULL)
+   state->read_ec_sensors_data = cros_ec_sensors_read_lpc;
+   else
+   state->read_ec_sensors_data = cros_ec_accel_legacy_read_cmd;
 
indio_dev->channels = cros_ec_accel_legacy_channels;
indio_dev->num_channels = ARRAY_SIZE(cros_ec_accel_legacy_channels);
-- 
2.22.0.510.g264f2c817a-goog



[PATCH v5 0/4] Support accelerometers for veyron_minnie

2019-07-15 Thread Gwendal Grignou
veyron_minnie - ASUS Chromebook Flip C100PA - embedded controller
controls two accelerometers, one in the lid, one in the base.
However, the EC firmware does not follow the new interface that
cros_ec_accel driver use.
Extend the legacy driver used on glimmer - Lenovo ThinkPad 11e
Chromebook - to veyron_minnie.
veyron_minnie being ARM based, issue command over the I2C bus to the EC
instead of relying on the shared registers over LPC.

Gwendal Grignou (4):
  iio: cros_ec: Add sign vector in core for backward compatibility
  iio: cros_ec_accel_legacy: Fix incorrect channel setting
  iio: cros_ec_accel_legacy: Use cros_ec_sensors_core
  iio: cros_ec_accel_legacy: Add support for veyron-minnie

Changes in v4:
- In "Use cros_ec_sensors_core", fix return without unlock on the error
  path.
- Add acked for the last 2 patches.

Changes in v4:
- No change in iio/common/cros_ec_sensors
- Split cros_ec_accel_legacy code in 3:
  - fix an error in channel setting.
  - remove duplicate code in cros_ec_accel, use cros_ec_sensors_core.
  - extend cros_ec_accel to ARM device.
- Define cros_ec_accel_legacy_read_cmd() as static.

Changes in v3:
- Fix commit message, add reviewed-by for first patch.

Changes in v2:
- Readd empty line to reduce amount of change in patch.
- Remove Keywords used by ChromeOS commit queue.


 drivers/iio/accel/Kconfig |   4 +-
 drivers/iio/accel/cros_ec_accel_legacy.c  | 352 --
 .../cros_ec_sensors/cros_ec_sensors_core.c|   4 +
 .../linux/iio/common/cros_ec_sensors_core.h   |   1 +
 4 files changed, 85 insertions(+), 276 deletions(-)

-- 
2.22.0.510.g264f2c817a-goog



[PATCH v5 3/4] iio: cros_ec_accel_legacy: Use cros_ec_sensors_core

2019-07-15 Thread Gwendal Grignou
Remove duplicate code in cros-ec-accel-legacy,
use cros-ec-sensors-core functions and structures when possible.

On glimmer, check the 2 accelerometers are presented and working.

Signed-off-by: Gwendal Grignou 
Acked-by: Jonathan Cameron 
---
 drivers/iio/accel/Kconfig|   4 +-
 drivers/iio/accel/cros_ec_accel_legacy.c | 335 ---
 2 files changed, 54 insertions(+), 285 deletions(-)

diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 62a970a20219..7d0848f9ea45 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -201,9 +201,7 @@ config HID_SENSOR_ACCEL_3D
 
 config IIO_CROS_EC_ACCEL_LEGACY
tristate "ChromeOS EC Legacy Accelerometer Sensor"
-   select IIO_BUFFER
-   select IIO_TRIGGERED_BUFFER
-   select CROS_EC_LPC_REGISTER_DEVICE
+   depends on IIO_CROS_EC_SENSORS_CORE
help
  Say yes here to get support for accelerometers on Chromebook using
  legacy EC firmware.
diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c 
b/drivers/iio/accel/cros_ec_accel_legacy.c
index ad19d9c716f4..4d77472e2f72 100644
--- a/drivers/iio/accel/cros_ec_accel_legacy.c
+++ b/drivers/iio/accel/cros_ec_accel_legacy.c
@@ -12,6 +12,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -25,191 +26,50 @@
 
 #define DRV_NAME   "cros-ec-accel-legacy"
 
+#define CROS_EC_SENSOR_LEGACY_NUM 2
 /*
  * Sensor scale hard coded at 10 bits per g, computed as:
  * g / (2^10 - 1) = 0.009586168; with g = 9.80665 m.s^-2
  */
 #define ACCEL_LEGACY_NSCALE 9586168
 
-/* Indices for EC sensor values. */
-enum {
-   X,
-   Y,
-   Z,
-   MAX_AXIS,
-};
-
-/* State data for cros_ec_accel_legacy iio driver. */
-struct cros_ec_accel_legacy_state {
-   struct cros_ec_device *ec;
-
-   /*
-* Array holding data from a single capture. 2 bytes per channel
-* for the 3 channels plus the timestamp which is always last and
-* 8-bytes aligned.
-*/
-   s16 capture_data[8];
-   s8 sign[MAX_AXIS];
-   u8 sensor_num;
-};
-
-static int ec_cmd_read_u8(struct cros_ec_device *ec, unsigned int offset,
- u8 *dest)
-{
-   return ec->cmd_readmem(ec, offset, 1, dest);
-}
-
-static int ec_cmd_read_u16(struct cros_ec_device *ec, unsigned int offset,
-  u16 *dest)
-{
-   __le16 tmp;
-   int ret = ec->cmd_readmem(ec, offset, 2, &tmp);
-
-   *dest = le16_to_cpu(tmp);
-
-   return ret;
-}
-
-/**
- * read_ec_until_not_busy() - Read from EC status byte until it reads not busy.
- * @st: Pointer to state information for device.
- *
- * This function reads EC status until its busy bit gets cleared. It does not
- * wait indefinitely and returns -EIO if the EC status is still busy after a
- * few hundreds milliseconds.
- *
- * Return: 8-bit status if ok, -EIO on error
- */
-static int read_ec_until_not_busy(struct cros_ec_accel_legacy_state *st)
-{
-   struct cros_ec_device *ec = st->ec;
-   u8 status;
-   int attempts = 0;
-
-   ec_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status);
-   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);
-
-   ec_cmd_read_u8(ec, EC_MEMMAP_ACC_STATUS, &status);
-   }
-
-   return status;
-}
-
-/**
- * read_ec_accel_data_unsafe() - Read acceleration data from EC shared memory.
- * @st:Pointer to state information for 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.
- */
-static void read_ec_accel_data_unsafe(struct cros_ec_accel_legacy_state *st,
- unsigned long scan_mask, s16 *data)
-{
-   int i = 0;
-   int num_enabled = bitmap_weight(&scan_mask, MAX_AXIS);
-
-   /* Read all sensors enabled in scan_mask. Each value is 2 bytes. */
-   while (num_enabled--) {
-   i = find_next_bit(&scan_mask, MAX_AXIS, i);
-   ec_cmd_read_u16(st->ec,
-   EC_MEMMAP_ACC_DATA +
-   sizeof(s16) *
-   (1 + i + st->sensor_num * MAX_AXIS),
-   data);
-   *data *= st->sign[i];
-   i++;
-   data++;
-   }
-}
-
-/**
- * read_ec_accel_data() - Read acceleration data from EC shared memory.
- * @st:Pointer to state information for device.
- * @scan_mask: Bitmap of the sensor indices to scan.
- * @data:  

[PATCH v5 1/4] iio: cros_ec: Add sign vector in core for backward compatibility

2019-07-15 Thread Gwendal Grignou
To allow cros_ec iio core library to be used with legacy device, add a
vector to rotate sensor data if necessary: legacy devices are not
reporting data in HTML5/Android sensor referential.

Check the data is not rotated on recent chromebooks that use the HTML5
standard to present sensor data.

Signed-off-by: Gwendal Grignou 
Reviewed-by: Douglas Anderson 
---
 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c | 4 
 include/linux/iio/common/cros_ec_sensors_core.h   | 1 +
 2 files changed, 5 insertions(+)

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
index 719a0df5aeeb..e8a4d78659c8 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -66,6 +66,9 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
}
state->type = state->resp->info.type;
state->loc = state->resp->info.location;
+
+   /* Set sign vector, only used for backward compatibility. */
+   memset(state->sign, 1, CROS_EC_SENSOR_MAX_AXIS);
}
 
return 0;
@@ -254,6 +257,7 @@ static int cros_ec_sensors_read_data_unsafe(struct iio_dev 
*indio_dev,
if (ret < 0)
return ret;
 
+   *data *= st->sign[i];
data++;
}
 
diff --git a/include/linux/iio/common/cros_ec_sensors_core.h 
b/include/linux/iio/common/cros_ec_sensors_core.h
index ce16445411ac..a1c85ad4df91 100644
--- a/include/linux/iio/common/cros_ec_sensors_core.h
+++ b/include/linux/iio/common/cros_ec_sensors_core.h
@@ -71,6 +71,7 @@ struct cros_ec_sensors_core_state {
enum motionsensor_location loc;
 
s16 calib[CROS_EC_SENSOR_MAX_AXIS];
+   s8 sign[CROS_EC_SENSOR_MAX_AXIS];
 
u8 samples[CROS_EC_SAMPLE_SIZE];
 
-- 
2.22.0.510.g264f2c817a-goog



[PATCH v5 4/4] iio: cros_ec_accel_legacy: Add support for veyron-minnie

2019-07-15 Thread Gwendal Grignou
Veyron minnie embedded controller presents 2 accelerometers using an
older interface. Add function to query the data in cros_ec_accel.

Verify accelerometers on veyron-minnie are presented and working.

Signed-off-by: Gwendal Grignou 
Acked-by: Jonathan Cameron 
---
 drivers/iio/accel/cros_ec_accel_legacy.c | 40 ++--
 1 file changed, 38 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c 
b/drivers/iio/accel/cros_ec_accel_legacy.c
index 4d77472e2f72..545e23f0c033 100644
--- a/drivers/iio/accel/cros_ec_accel_legacy.c
+++ b/drivers/iio/accel/cros_ec_accel_legacy.c
@@ -5,7 +5,7 @@
  * Copyright 2017 Google, Inc
  *
  * This driver uses the memory mapper cros-ec interface to communicate
- * with the Chrome OS EC about accelerometer data.
+ * with the Chrome OS EC about accelerometer data or older commands.
  * Accelerometer access is presented through iio sysfs.
  */
 
@@ -33,6 +33,39 @@
  */
 #define ACCEL_LEGACY_NSCALE 9586168
 
+static int cros_ec_accel_legacy_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;
+   u8 sensor_num;
+
+   /*
+* Read all sensor data through a command.
+* Save sensor_num, it is assumed to stay.
+*/
+   sensor_num = st->param.info.sensor_num;
+   st->param.cmd = MOTIONSENSE_CMD_DUMP;
+   st->param.dump.max_sensor_count = CROS_EC_SENSOR_LEGACY_NUM;
+   ret = cros_ec_motion_send_host_cmd(st,
+   sizeof(st->resp->dump) + CROS_EC_SENSOR_LEGACY_NUM *
+   sizeof(struct ec_response_motion_sensor_data));
+   st->param.info.sensor_num = sensor_num;
+   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->dump.sensor[sensor_num].data[i] *
+   st->sign[i];
+   data++;
+   }
+
+   return 0;
+}
+
 static int cros_ec_accel_legacy_read(struct iio_dev *indio_dev,
 struct iio_chan_spec const *chan,
 int *val, int *val2, long mask)
@@ -149,7 +182,10 @@ static int cros_ec_accel_legacy_probe(struct 
platform_device *pdev)
indio_dev->info = &cros_ec_accel_legacy_info;
state = iio_priv(indio_dev);
 
-   state->read_ec_sensors_data = cros_ec_sensors_read_lpc;
+   if (state->ec->cmd_readmem != NULL)
+   state->read_ec_sensors_data = cros_ec_sensors_read_lpc;
+   else
+   state->read_ec_sensors_data = cros_ec_accel_legacy_read_cmd;
 
indio_dev->channels = cros_ec_accel_legacy_channels;
indio_dev->num_channels = ARRAY_SIZE(cros_ec_accel_legacy_channels);
-- 
2.22.0.510.g264f2c817a-goog



[PATCH v5 2/4] iio: cros_ec_accel_legacy: Fix incorrect channel setting

2019-07-15 Thread Gwendal Grignou
INFO_SCALE is set both for each channel and all channels.
iio is using all channel setting, so the error was not user visible.

Signed-off-by: Gwendal Grignou 
---
 drivers/iio/accel/cros_ec_accel_legacy.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c 
b/drivers/iio/accel/cros_ec_accel_legacy.c
index 46bb2e421bb9..ad19d9c716f4 100644
--- a/drivers/iio/accel/cros_ec_accel_legacy.c
+++ b/drivers/iio/accel/cros_ec_accel_legacy.c
@@ -319,7 +319,6 @@ static const struct iio_chan_spec_ext_info 
cros_ec_accel_legacy_ext_info[] = {
.modified = 1,  \
.info_mask_separate =   \
BIT(IIO_CHAN_INFO_RAW) |\
-   BIT(IIO_CHAN_INFO_SCALE) |  \
BIT(IIO_CHAN_INFO_CALIBBIAS),   \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE),\
.ext_info = cros_ec_accel_legacy_ext_info,  \
-- 
2.22.0.510.g264f2c817a-goog



Re: [PATCH v4 03/11] mfd / platform: cros_ec: Miscellaneous character device to talk with the EC

2019-07-15 Thread Gwendal Grignou
On Thu, Jun 27, 2019 at 3:40 AM Enric Balletbo i Serra
 wrote:
>
> That's a driver to talk with the ChromeOS Embedded Controller via a
> miscellaneous character device, it creates an entry in /dev for every
> instance and implements basic file operations for communicating with the
> Embedded Controller with an userspace application. The API is moved to
> the uapi folder, which is supposed to contain the user space API of the
> kernel.
>
> Note that this will replace current character device interface
> implemented in the cros-ec-dev driver in the MFD subsystem. The idea is
> to move all the functionality that extends the bounds of what MFD was
> designed to platform/chrome subsystem.
>
> Signed-off-by: Enric Balletbo i Serra 
> Acked-by: Andy Shevchenko 
> Tested-by: Gwendal Grignou 
> ---
>
> Changes in v4: None
> Changes in v3:
> - Fix 'linux/mfd/cros_ec.h' is not exported (reported by lkp)
>
> Changes in v2:
> - Remove the list, and the lock, as are not needed (Greg Kroah-Hartman)
> - Remove dev_info in probe, anyway we will see the chardev or not if the
>   probe fails (Greg Kroah-Hartman)
>
>  Documentation/ioctl/ioctl-number.txt  |   2 +-
>  drivers/mfd/cros_ec_dev.c |   4 +-
>  drivers/platform/chrome/Kconfig   |  11 +
>  drivers/platform/chrome/Makefile  |   1 +
>  drivers/platform/chrome/cros_ec_chardev.c | 253 ++
>  .../uapi/linux/cros_ec_chardev.h  |  21 +-
>  6 files changed, 273 insertions(+), 19 deletions(-)
>  create mode 100644 drivers/platform/chrome/cros_ec_chardev.c
>  rename drivers/mfd/cros_ec_dev.h => include/uapi/linux/cros_ec_chardev.h 
> (50%)
>
> diff --git a/Documentation/ioctl/ioctl-number.txt 
> b/Documentation/ioctl/ioctl-number.txt
> index c9558146ac58..8bd7907ee36d 100644
> --- a/Documentation/ioctl/ioctl-number.txt
> +++ b/Documentation/ioctl/ioctl-number.txt
> @@ -340,7 +340,7 @@ Code  Seq#(hex) Include FileComments
>  0xDD   00-3F   ZFCP device driver  see drivers/s390/scsi/
> <mailto:aherr...@de.ibm.com>
>  0xE5   00-3F   linux/fuse.h
> -0xEC   00-01   drivers/platform/chrome/cros_ec_dev.h   ChromeOS EC driver
> +0xEC   00-01   include/uapi/linux/cros_ec_chardev.hChromeOS EC driver
>  0xF3   00-3F   drivers/usb/misc/sisusbvga/sisusb.h sisfb (in development)
> <mailto:tho...@winischhofer.net>
>  0xF4   00-1F   video/mbxfb.h   mbxfb
> diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
> index eb77bf6406f3..3334bc4e42ee 100644
> --- a/drivers/mfd/cros_ec_dev.c
> +++ b/drivers/mfd/cros_ec_dev.c
> @@ -19,6 +19,8 @@
>
>  #include 
>  #include 
> +#include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -27,7 +29,7 @@
>  #include 
>  #include 
>
> -#include "cros_ec_dev.h"
> +#include 
>
>  #define DRV_NAME "cros-ec-dev"
>
> diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
> index 1e7a10500b3f..221e709358c0 100644
> --- a/drivers/platform/chrome/Kconfig
> +++ b/drivers/platform/chrome/Kconfig
> @@ -133,6 +133,17 @@ config CROS_KBD_LED_BACKLIGHT
>   To compile this driver as a module, choose M here: the
>   module will be called cros_kbd_led_backlight.
>
> +config CROS_EC_CHARDEV
> +   tristate "ChromeOS EC miscdevice"
> +   depends on MFD_CROS_EC_CHARDEV
> +   default MFD_CROS_EC_CHARDEV
> +   help
> + This driver adds file operations support to talk with the
> + ChromeOS EC from userspace via a character device.
> +
> + To compile this driver as a module, choose M here: the
> + module will be called cros_ec_chardev.
> +
>  config CROS_EC_LIGHTBAR
> tristate "Chromebook Pixel's lightbar support"
> depends on MFD_CROS_EC_CHARDEV
> diff --git a/drivers/platform/chrome/Makefile 
> b/drivers/platform/chrome/Makefile
> index f69e0be98bd6..e6758e967ac5 100644
> --- a/drivers/platform/chrome/Makefile
> +++ b/drivers/platform/chrome/Makefile
> @@ -15,6 +15,7 @@ cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC)+= 
> cros_ec_lpc_mec.o
>  obj-$(CONFIG_CROS_EC_LPC)  += cros_ec_lpcs.o
>  obj-$(CONFIG_CROS_EC_PROTO)+= cros_ec_proto.o cros_ec_trace.o
>  obj-$(CONFIG_CROS_KBD_LED_BACKLIGHT)   += cros_kbd_led_backlight.o
> +obj-$(CONFIG_CROS_EC_CHARDEV)  += cros_ec_chardev.o
>  obj-$(CONFIG_CROS_EC_LIGHTBAR) += cros_ec_lightbar.o
>  obj-$(CONFIG_CROS_EC_VBC)  += cros_ec_vbc.o
>  obj-$(CONFIG_CROS_EC_DEBUGFS)  

Re: [PATCH] mfd: cros_ec: Update cros_ec_commands.h

2019-07-11 Thread Gwendal Grignou
Reviewed-by: Gwendal Grignou 

Note there is a patch series that move cros_ec_commands.h from
nclude/linux/mfd/ to include/linux/platform_data.

On Mon, Jul 8, 2019 at 11:16 AM Yicheng Li  wrote:
>
> Update cros_ec_commands.h to match the fingerprint MCU section in
> the current ec_commands.h
>
> Signed-off-by: Yicheng Li 
> ---
>
>  include/linux/mfd/cros_ec_commands.h | 12 
>  1 file changed, 12 insertions(+)
>
> diff --git a/include/linux/mfd/cros_ec_commands.h 
> b/include/linux/mfd/cros_ec_commands.h
> index 7ccb8757b79d..98415686cbfa 100644
> --- a/include/linux/mfd/cros_ec_commands.h
> +++ b/include/linux/mfd/cros_ec_commands.h
> @@ -5513,6 +5513,18 @@ struct ec_params_fp_seed {
> uint8_t seed[FP_CONTEXT_TPM_BYTES];
>  } __ec_align4;
>
> +#define EC_CMD_FP_ENC_STATUS 0x0409
> +
> +/* FP TPM seed has been set or not */
> +#define FP_ENC_STATUS_SEED_SET BIT(0)
> +
> +struct ec_response_fp_encryption_status {
> +   /* Used bits in encryption engine status */
> +   uint32_t valid_flags;
> +   /* Encryption engine status */
> +   uint32_t status;
> +} __ec_align4;
> +
>  
> /*/
>  /* Touchpad MCU commands: range 0x0500-0x05FF */
>
> --
> 2.20.1
>


Re: [PATCH v4 01/11] mfd / platform: cros_ec: Handle chained ECs as platform devices

2019-06-29 Thread Gwendal Grignou
Review and tested the whole series:
Reviewed-by: Gwendal Grignou 
Tested-by: Gwendal Grignou 

On Thu, Jun 27, 2019 at 3:40 AM Enric Balletbo i Serra
 wrote:
>
> An MFD is a device that contains several sub-devices (cells). For instance,
> the ChromeOS EC fits in this description as usually contains a charger and
> can have other devices with different functions like a Real-Time Clock,
> an Audio codec, a Real-Time Clock, ...
>
> If you look at the driver, though, we're doing something odd. We have
> two MFD cros-ec drivers where one of them (cros-ec-core) instantiates
> another MFD driver as sub-driver (cros-ec-dev), and the latest
> instantiates the different sub-devices (Real-Time Clock, Audio codec,
> etc).
>
>   MFD
> --
>cros-ec-core
>|___ mfd-cellA (cros-ec-dev)
>|   |__ mfd-cell0
>|   |__ mfd-cell1
>|   |__ ...
>|
>|___ mfd-cellB (cros-ec-dev)
>|__ mfd-cell0
>|__ mfd-cell1
>|__ ...
>
> The problem that was trying to solve is to describe some kind of topology for
> the case where we have an EC (cros-ec) chained with another EC
> (cros-pd). Apart from that this extends the bounds of what MFD was
> designed to do we might be interested on have other kinds of topology that
> can't be implemented in that way.
>
> Let's prepare the code to move the cros-ec-core part from MFD to
> platform/chrome as this is clearly a platform specific thing non-related
> to a MFD device.
>
>   platform/chrome  | MFD
> --
>|
>cros-ec |___ cros-ec-dev
>|   |__ mfd-cell0
>|   |__ mfd-cell1
>|   |__ ...
>|
>cros-pd |___ cros-ec-dev
>||__ mfd-cell0
>    |    |__ mfd-cell1
>||__ ...
>
> Signed-off-by: Enric Balletbo i Serra 
> Acked-by: Andy Shevchenko 
> Tested-by: Gwendal Grignou 
> ---
>
> Changes in v4:
> - Rebase again on top of for-mfd-next to avoid conflicts.
>
> Changes in v3:
> - Collect more acks an tested-by
>
> Changes in v2:
> - Collect acks received.
> - Remove '[PATCH 07/10] mfd: cros_ec: Update with SPDX Licence identifier
>   and fix description' to avoid conflicts with some tree-wide patches
>   that actually updates the Licence identifier.
> - Add '[PATCH 10/10] arm/arm64: defconfig: Update configs to use the new
>   CROS_EC options' to update the defconfigs after change some config
>   symbols.
>
>  drivers/mfd/cros_ec.c   | 61 +
>  drivers/platform/chrome/cros_ec_i2c.c   |  8 
>  drivers/platform/chrome/cros_ec_lpc.c   |  3 +-
>  drivers/platform/chrome/cros_ec_rpmsg.c |  2 +
>  drivers/platform/chrome/cros_ec_spi.c   |  8 
>  include/linux/mfd/cros_ec.h | 18 
>  6 files changed, 69 insertions(+), 31 deletions(-)
>
> diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
> index bd2bcdd4718b..11fced7917fc 100644
> --- a/drivers/mfd/cros_ec.c
> +++ b/drivers/mfd/cros_ec.c
> @@ -21,7 +21,6 @@
>  #include 
>  #include 
>  #include 
> -#include 
>  #include 
>  #include 
>  #include 
> @@ -39,18 +38,6 @@ static struct cros_ec_platform pd_p = {
> .cmd_offset = EC_CMD_PASSTHRU_OFFSET(CROS_EC_DEV_PD_INDEX),
>  };
>
> -static const struct mfd_cell ec_cell = {
> -   .name = "cros-ec-dev",
> -   .platform_data = &ec_p,
> -   .pdata_size = sizeof(ec_p),
> -};
> -
> -static const struct mfd_cell ec_pd_cell = {
> -   .name = "cros-ec-dev",
> -   .platform_data = &pd_p,
> -   .pdata_size = sizeof(pd_p),
> -};
> -
>  static irqreturn_t ec_irq_thread(int irq, void *data)
>  {
> struct cros_ec_device *ec_dev = data;
> @@ -158,38 +145,42 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
> }
> }
>
> -   err = devm_mfd_add_devices(ec_dev->dev, PLATFORM_DEVID_AUTO, &ec_cell,
> -  1, NULL, ec_dev->irq, NULL);
> -   if (err) {
> -   dev_err(dev,
> -   "Failed to register Embedded Controller subdevice 
> %d\n",
> -   err);
> -   return err;
> +   /* Register a platform device for the main EC instance */
> +   ec_dev->ec = platform_device_register_data(ec_dev->dev, "cros-ec-dev",
> +

[PATCH v4 1/4] iio: cros_ec: Add sign vector in core for backward compatibility

2019-06-28 Thread Gwendal Grignou
To allow cros_ec iio core library to be used with legacy device, add a
vector to rotate sensor data if necessary: legacy devices are not
reporting data in HTML5/Android sensor referential.

Check the data is not rotated on recent chromebooks that use the HTML5
standard to present sensor data.

Signed-off-by: Gwendal Grignou 
Reviewed-by: Douglas Anderson 
---
 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c | 4 
 include/linux/iio/common/cros_ec_sensors_core.h   | 1 +
 2 files changed, 5 insertions(+)

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
index 719a0df5aeeb..e8a4d78659c8 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c
@@ -66,6 +66,9 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
}
state->type = state->resp->info.type;
state->loc = state->resp->info.location;
+
+   /* Set sign vector, only used for backward compatibility. */
+   memset(state->sign, 1, CROS_EC_SENSOR_MAX_AXIS);
}
 
return 0;
@@ -254,6 +257,7 @@ static int cros_ec_sensors_read_data_unsafe(struct iio_dev 
*indio_dev,
if (ret < 0)
return ret;
 
+   *data *= st->sign[i];
data++;
}
 
diff --git a/include/linux/iio/common/cros_ec_sensors_core.h 
b/include/linux/iio/common/cros_ec_sensors_core.h
index ce16445411ac..a1c85ad4df91 100644
--- a/include/linux/iio/common/cros_ec_sensors_core.h
+++ b/include/linux/iio/common/cros_ec_sensors_core.h
@@ -71,6 +71,7 @@ struct cros_ec_sensors_core_state {
enum motionsensor_location loc;
 
s16 calib[CROS_EC_SENSOR_MAX_AXIS];
+   s8 sign[CROS_EC_SENSOR_MAX_AXIS];
 
u8 samples[CROS_EC_SAMPLE_SIZE];
 
-- 
2.22.0.410.gd8fdbe21b5-goog



[PATCH v4 4/4] iio: cros_ec_accel_legacy: Add support for veyron-minnie

2019-06-28 Thread Gwendal Grignou
Veyron minnie embedded controller presents 2 accelerometers using an
older interface. Add function to query the data in cros_ec_accel.

Verify accelerometers on veyron-minnie are presented and working.

Signed-off-by: Gwendal Grignou 
---
 drivers/iio/accel/cros_ec_accel_legacy.c | 40 ++--
 1 file changed, 38 insertions(+), 2 deletions(-)

diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c 
b/drivers/iio/accel/cros_ec_accel_legacy.c
index 2399f0cbdf2b..2c6196446d90 100644
--- a/drivers/iio/accel/cros_ec_accel_legacy.c
+++ b/drivers/iio/accel/cros_ec_accel_legacy.c
@@ -5,7 +5,7 @@
  * Copyright 2017 Google, Inc
  *
  * This driver uses the memory mapper cros-ec interface to communicate
- * with the Chrome OS EC about accelerometer data.
+ * with the Chrome OS EC about accelerometer data or older commands.
  * Accelerometer access is presented through iio sysfs.
  */
 
@@ -33,6 +33,39 @@
  */
 #define ACCEL_LEGACY_NSCALE 9586168
 
+static int cros_ec_accel_legacy_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;
+   u8 sensor_num;
+
+   /*
+* Read all sensor data through a command.
+* Save sensor_num, it is assumed to stay.
+*/
+   sensor_num = st->param.info.sensor_num;
+   st->param.cmd = MOTIONSENSE_CMD_DUMP;
+   st->param.dump.max_sensor_count = CROS_EC_SENSOR_LEGACY_NUM;
+   ret = cros_ec_motion_send_host_cmd(st,
+   sizeof(st->resp->dump) + CROS_EC_SENSOR_LEGACY_NUM *
+   sizeof(struct ec_response_motion_sensor_data));
+   st->param.info.sensor_num = sensor_num;
+   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->dump.sensor[sensor_num].data[i] *
+   st->sign[i];
+   data++;
+   }
+
+   return 0;
+}
+
 static int cros_ec_accel_legacy_read(struct iio_dev *indio_dev,
 struct iio_chan_spec const *chan,
 int *val, int *val2, long mask)
@@ -149,7 +182,10 @@ static int cros_ec_accel_legacy_probe(struct 
platform_device *pdev)
indio_dev->info = &cros_ec_accel_legacy_info;
state = iio_priv(indio_dev);
 
-   state->read_ec_sensors_data = cros_ec_sensors_read_lpc;
+   if (state->ec->cmd_readmem != NULL)
+   state->read_ec_sensors_data = cros_ec_sensors_read_lpc;
+   else
+   state->read_ec_sensors_data = cros_ec_accel_legacy_read_cmd;
 
indio_dev->channels = cros_ec_accel_legacy_channels;
indio_dev->num_channels = ARRAY_SIZE(cros_ec_accel_legacy_channels);
-- 
2.22.0.410.gd8fdbe21b5-goog



[PATCH v4 2/4] iio: cros_ec_accel_legacy: Fix incorrect channel setting

2019-06-28 Thread Gwendal Grignou
INFO_SCALE is set both for each channel and all channels.
iio is using all channel setting, so the error was not user visible.

Signed-off-by: Gwendal Grignou 
---
 drivers/iio/accel/cros_ec_accel_legacy.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/iio/accel/cros_ec_accel_legacy.c 
b/drivers/iio/accel/cros_ec_accel_legacy.c
index 46bb2e421bb9..ad19d9c716f4 100644
--- a/drivers/iio/accel/cros_ec_accel_legacy.c
+++ b/drivers/iio/accel/cros_ec_accel_legacy.c
@@ -319,7 +319,6 @@ static const struct iio_chan_spec_ext_info 
cros_ec_accel_legacy_ext_info[] = {
.modified = 1,  \
.info_mask_separate =   \
BIT(IIO_CHAN_INFO_RAW) |\
-   BIT(IIO_CHAN_INFO_SCALE) |  \
BIT(IIO_CHAN_INFO_CALIBBIAS),   \
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE),\
.ext_info = cros_ec_accel_legacy_ext_info,  \
-- 
2.22.0.410.gd8fdbe21b5-goog



  1   2   3   4   >