[PATCH v2 1/1] counter: cros_ec: Add synchronization sensor

2019-08-23 Thread Fabien Lahoudere
From: Gwendal Grignou 

EC returns a counter when there is an event on camera vsync.
This patch comes from chromeos kernel 4.4

Signed-off-by: Gwendal Grignou 
Signed-off-by: Fabien Lahoudere 

CROS EC sync sensor was originally designed as an IIO device.
Now that the counter subsystem will replace IIO_COUNTER, we
have to implement a new way to get sync count.

Signed-off-by: Fabien Lahoudere 
---
 Documentation/driver-api/generic-counter.rst  |   3 +
 MAINTAINERS   |   7 +
 drivers/counter/Kconfig   |   9 +
 drivers/counter/Makefile  |   1 +
 drivers/counter/counter.c |   2 +
 drivers/counter/cros_ec_sensors_sync.c| 208 ++
 .../cros_ec_sensors/cros_ec_sensors_core.c|   1 +
 drivers/mfd/cros_ec_dev.c |   3 +
 include/linux/counter.h   |   1 +
 9 files changed, 235 insertions(+)
 create mode 100644 drivers/counter/cros_ec_sensors_sync.c

diff --git a/Documentation/driver-api/generic-counter.rst 
b/Documentation/driver-api/generic-counter.rst
index 8382f01a53e3..beb80714ac8b 100644
--- a/Documentation/driver-api/generic-counter.rst
+++ b/Documentation/driver-api/generic-counter.rst
@@ -44,6 +44,9 @@ Counter interface provides the following available count data 
types:
 * COUNT_POSITION:
   Unsigned integer value representing position.
 
+* COUNT_TALLY:
+  Unsigned integer value representing tally.
+
 A Count has a count function mode which represents the update behavior
 for the count data. The Generic Counter interface provides the following
 available count function modes:
diff --git a/MAINTAINERS b/MAINTAINERS
index e60f5c361969..83bd291d103e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3902,6 +3902,13 @@ R:   Guenter Roeck 
 F: Documentation/devicetree/bindings/sound/google,cros-ec-codec.txt
 F: sound/soc/codecs/cros_ec_codec.*
 
+CHROMEOS EC COUNTER DRIVER
+M: Fabien Lahoudere 
+M: William Breathitt Gray 
+L: linux-...@vger.kernel.org
+S: Maintained
+F: drivers/counter/cros_ec_sensors_sync.c
+
 CIRRUS LOGIC AUDIO CODEC DRIVERS
 M: Brian Austin 
 M: Paul Handrigan 
diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig
index 2967d0a9ff91..22287f5715e5 100644
--- a/drivers/counter/Kconfig
+++ b/drivers/counter/Kconfig
@@ -59,4 +59,13 @@ config FTM_QUADDEC
  To compile this driver as a module, choose M here: the
  module will be called ftm-quaddec.
 
+config IIO_CROS_EC_SENSORS_SYNC
+   tristate "ChromeOS EC Counter Sensors"
+   depends on IIO_CROS_EC_SENSORS_CORE && IIO
+   help
+ Module to handle synchronisation sensors presented by the ChromeOS EC
+ Sensor hub.
+ Synchronisation sensors are counter sensors triggered when events
+ occurs from other subsystems.
+
 endif # COUNTER
diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile
index 40d35522937d..6fe4c98a446f 100644
--- a/drivers/counter/Makefile
+++ b/drivers/counter/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_104_QUAD_8)+= 104-quad-8.o
 obj-$(CONFIG_STM32_TIMER_CNT)  += stm32-timer-cnt.o
 obj-$(CONFIG_STM32_LPTIMER_CNT)+= stm32-lptimer-cnt.o
 obj-$(CONFIG_FTM_QUADDEC)  += ftm-quaddec.o
+obj-$(CONFIG_IIO_CROS_EC_SENSORS_SYNC) += cros_ec_sensors_sync.o
diff --git a/drivers/counter/counter.c b/drivers/counter/counter.c
index 106bc7180cd8..53525b109094 100644
--- a/drivers/counter/counter.c
+++ b/drivers/counter/counter.c
@@ -261,6 +261,7 @@ void counter_count_read_value_set(struct 
counter_count_read_value *const val,
 {
switch (type) {
case COUNTER_COUNT_POSITION:
+   case COUNTER_COUNT_TALLY:
val->len = sprintf(val->buf, "%lu\n", *(unsigned long *)data);
break;
default:
@@ -290,6 +291,7 @@ int counter_count_write_value_get(void *const data,
 
switch (type) {
case COUNTER_COUNT_POSITION:
+   case COUNTER_COUNT_TALLY:
err = kstrtoul(val->buf, 0, data);
if (err)
return err;
diff --git a/drivers/counter/cros_ec_sensors_sync.c 
b/drivers/counter/cros_ec_sensors_sync.c
new file mode 100644
index ..b6f5e2c6da9f
--- /dev/null
+++ b/drivers/counter/cros_ec_sensors_sync.c
@@ -0,0 +1,208 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver of counter incremented after events on interrupt line in EC.
+ *
+ * Copyright 2018 Google, Inc
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DRV_NAME "cros-ec-sync"
+
+/*
+ * One channel for counter, the other for timestamp.
+ */
+#define MAX_CHANNELS (1)
+
+/* State data for ec_sensors iio driver. */
+struct cros_ec_sensors_sync_state {
+   /* Shared by all sensors */
+   struct cros_ec_sensors_core_state core;
+   struct counter_device counter;
+   struct iio_

[PATCH v2 0/1] counter: cros_ec: Add sync sensor driver

2019-08-23 Thread Fabien Lahoudere
Some chromebook EC provides a counter to get all vsync coming from the back
camera.
This series introduces a patch coming from chromebook kernel 4.4 designed as an
IIO counter. As IIO counter will be deprecated in favor of counter, I rebase the
original patch and support the new counter API.

The serie need to be merged after https://lkml.org/lkml/2019/7/9/305

Changes since v1:
- Drop code related to IIO_COUNT
- Add external attribute to the counter driver
- Add cros_ec_sensors_sync.c to MAINTAINERS file

Gwendal Grignou (1):
  counter: cros_ec: Add synchronization sensor

 Documentation/driver-api/generic-counter.rst  |   3 +
 MAINTAINERS   |   7 +
 drivers/counter/Kconfig   |   9 +
 drivers/counter/Makefile  |   1 +
 drivers/counter/counter.c |   2 +
 drivers/counter/cros_ec_sensors_sync.c| 208 ++
 .../cros_ec_sensors/cros_ec_sensors_core.c|   1 +
 drivers/mfd/cros_ec_dev.c |   3 +
 include/linux/counter.h   |   1 +
 9 files changed, 235 insertions(+)
 create mode 100644 drivers/counter/cros_ec_sensors_sync.c

-- 
2.20.1



[PATCH v5 1/1] iio: common: cros_ec_sensors: Expose cros_ec_sensors frequency range via iio sysfs

2019-07-16 Thread Fabien Lahoudere
Embedded controller return minimum and maximum frequencies, unfortunately
we have no way to know the step for all available frequencies.
Even if not complete, we can return a list of known values using the
standard read_avail callback (IIO_CHAN_INFO_SAMP_FREQ) to provide them to
userland.

Now cros_ec_* sensors provides frequencies values in sysfs like this:
"0 min max". 0 is always true to disable the sensor.

Default frequencies are provided for earlier protocol.

Signed-off-by: Nick Vaccaro 
Signed-off-by: Fabien Lahoudere 
Acked-by: Jonathan Cameron 
---
 .../common/cros_ec_sensors/cros_ec_sensors.c  |  3 +
 .../cros_ec_sensors/cros_ec_sensors_core.c| 65 +++
 drivers/iio/light/cros_ec_light_prox.c|  3 +
 .../linux/iio/common/cros_ec_sensors_core.h   | 21 ++
 4 files changed, 92 insertions(+)

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..dbca02688c4f 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -175,6 +175,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
 static const struct iio_info ec_sensors_info = {
.read_raw = _ec_sensors_read,
.write_raw = _ec_sensors_write,
+   .read_avail = _ec_sensors_core_read_avail,
 };
 
 static int cros_ec_sensors_probe(struct platform_device *pdev)
@@ -211,6 +212,8 @@ static int cros_ec_sensors_probe(struct platform_device 
*pdev)
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);
channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
channel->scan_index = i;
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 8af8a167..805652250960 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
@@ -50,6 +50,37 @@ static int cros_ec_get_host_cmd_version_mask(struct 
cros_ec_device *ec_dev,
return ret;
 }
 
+static void get_default_min_max_freq(enum motionsensor_type type,
+u32 *min_freq,
+u32 *max_freq)
+{
+   switch (type) {
+   case MOTIONSENSE_TYPE_ACCEL:
+   case MOTIONSENSE_TYPE_GYRO:
+   *min_freq = 12500;
+   *max_freq = 10;
+   break;
+   case MOTIONSENSE_TYPE_MAG:
+   *min_freq = 5000;
+   *max_freq = 25000;
+   break;
+   case MOTIONSENSE_TYPE_PROX:
+   case MOTIONSENSE_TYPE_LIGHT:
+   *min_freq = 100;
+   *max_freq = 5;
+   break;
+   case MOTIONSENSE_TYPE_BARO:
+   *min_freq = 250;
+   *max_freq = 2;
+   break;
+   case MOTIONSENSE_TYPE_ACTIVITY:
+   default:
+   *min_freq = 0;
+   *max_freq = 0;
+   break;
+   }
+}
+
 int cros_ec_sensors_core_init(struct platform_device *pdev,
  struct iio_dev *indio_dev,
  bool physical_device)
@@ -100,6 +131,19 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
}
state->type = state->resp->info.type;
state->loc = state->resp->info.location;
+
+   /* 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,
+>frequencies[1],
+>frequencies[2]);
+   } else {
+   state->frequencies[1] =
+   state->resp->info_3.min_frequency;
+   state->frequencies[2] =
+   state->resp->info_3.max_frequency;
+   }
}
 
return 0;
@@ -461,6 +505,27 @@ int cros_ec_sensors_core_read(struct 
cros_ec_sensors_core_state *st,
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read);
 
+int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev,
+   struct iio_chan_spec const *chan,
+   const int **vals,
+   int *type,
+   int *length,
+   long mask)
+{
+   struct cros_ec_sensors_core_state *state = i

[PATCH v5 0/1] Expose cros_ec_sensors frequency range via iio sysfs

2019-07-16 Thread Fabien Lahoudere
Chromebooks EC sensors must expose a range of frequencies for each sensors using
the standard ABI sampling_frquency_available.

This patch needs https://lkml.org/lkml/2019/7/2/345

Changes since v4:
- Remove trailing whitespace
- Use checkpatch.pl successfully

Changes since v3:
- Split patch 6
- Drop clean up patches
- Fix minor changes

Changes since v2:
- use read_avail callback
- rework core functions to avoid code duplication

Changes since v1:
- Add a cover letter
- Add Nick Vaccaro SoB to patch 1
- Drop fifo size related code

Fabien Lahoudere (1):
  iio: common: cros_ec_sensors: Expose cros_ec_sensors frequency range
via iio sysfs

 .../common/cros_ec_sensors/cros_ec_sensors.c  |  3 +
 .../cros_ec_sensors/cros_ec_sensors_core.c| 65 +++
 drivers/iio/light/cros_ec_light_prox.c|  3 +
 .../linux/iio/common/cros_ec_sensors_core.h   | 21 ++
 4 files changed, 92 insertions(+)

-- 
2.20.1



Re: [PATCH v4 1/1] iio: common: cros_ec_sensors: determine protocol version

2019-07-16 Thread Fabien Lahoudere
Le dimanche 14 juillet 2019 à 17:19 +0100, Jonathan Cameron a écrit :
> On Tue,  2 Jul 2019 10:49:38 +0200
> Fabien Lahoudere  wrote:
> 
> > This patch adds a function to determine which version of the
> > protocol is used to communicate with EC.
> > 
> > Signed-off-by: Fabien Lahoudere 
> > Signed-off-by: Nick Vaccaro 
> > Reviewed-by: Gwendal Grignou 
> > Tested-by: Gwendal Grignou 
> > Acked-by: Enric Balletbo i Serra 
> There are so many different series flying around for this driver that
> I have given up trying to figure out if I should be picking some of
> them up.  I'll ack them on the assumption they'll all go together,
> but feel free to ping me if you want me to pick some of them up
> through IIO.
> 

Yes sorry for all that confusing series.
Enric wanted this patch first and it is independant of others, so feel
free to pick it. Others patcheshave been sent separately.

Thanks

> Acked-by: Jonathan Cameron 
> 
> Thanks,
> 
> Jonathan
> 
> > ---
> >  .../cros_ec_sensors/cros_ec_sensors_core.c| 36
> > ++-
> >  1 file changed, 35 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 130362ca421b..8af8a167 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
> > @@ -25,6 +25,31 @@ static char *cros_ec_loc[] = {
> > [MOTIONSENSE_LOC_MAX] = "unknown",
> >  };
> >  
> > +static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device
> > *ec_dev,
> > +u16 cmd_offset, u16 cmd,
> > u32 *mask)
> > +{
> > +   int ret;
> > +   struct {
> > +   struct cros_ec_command msg;
> > +   union {
> > +   struct ec_params_get_cmd_versions params;
> > +   struct ec_response_get_cmd_versions resp;
> > +   };
> > +   } __packed buf = {
> > +   .msg = {
> > +   .command = EC_CMD_GET_CMD_VERSIONS +
> > cmd_offset,
> > +   .insize = sizeof(struct
> > ec_response_get_cmd_versions),
> > +   .outsize = sizeof(struct
> > ec_params_get_cmd_versions)
> > +   },
> > +   .params = {.cmd = cmd}
> > +   };
> > +
> > +   ret = cros_ec_cmd_xfer_status(ec_dev, );
> > +   if (ret >= 0)
> > +   *mask = buf.resp.version_mask;
> > +   return ret;
> > +}
> > +
> >  int cros_ec_sensors_core_init(struct platform_device *pdev,
> >   struct iio_dev *indio_dev,
> >   bool physical_device)
> > @@ -33,6 +58,8 @@ 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);
> > +   u32 ver_mask;
> > +   int ret;
> >  
> > platform_set_drvdata(pdev, indio_dev);
> >  
> > @@ -47,8 +74,15 @@ int cros_ec_sensors_core_init(struct
> > platform_device *pdev,
> >  
> > mutex_init(>cmd_lock);
> >  
> > +   ret = cros_ec_get_host_cmd_version_mask(state->ec,
> > +   ec->cmd_offset,
> > +   EC_CMD_MOTION_SENSE_CMD
> > ,
> > +   _mask);
> > +   if (ret < 0)
> > +   return ret;
> > +
> > /* Set up the host command structure. */
> > -   state->msg->version = 2;
> > +   state->msg->version = fls(ver_mask) - 1;
> > state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
> > state->msg->outsize = sizeof(struct ec_params_motion_sense);
> >  



Re: [PATCH v4 1/1] iio: common: cros_ec_sensors: Expose cros_ec_sensors frequency range via iio sysfs

2019-07-16 Thread Fabien Lahoudere
Le dimanche 14 juillet 2019 à 18:31 +0100, Jonathan Cameron a écrit :
> On Tue,  9 Jul 2019 13:53:45 +0200
> Fabien Lahoudere  wrote:
> 
> > Embedded controller return minimum and maximum frequencies,
> > unfortunately
> > we have no way to know the step for all available frequencies.
> > Even if not complete, we can return a list of known values using
> > the
> > standard read_avail callback (IIO_CHAN_INFO_SAMP_FREQ) to provide
> > them to
> > userland.
> > 
> > Now cros_ec_* sensors provides frequencies values in sysfs like
> > this:
> > "0 min max". 0 is always true to disable the sensor.
> > 
> > Default frequencies are provided for earlier protocol.
> > 
> > Signed-off-by: Nick Vaccaro 
> > Signed-off-by: Fabien Lahoudere 
> There is some trailing whitespace in here, and with the high level
> of other work going on in this driver a lot of fuzz.
> 

Sorry for that, I will fix it quickly.
Thanks for reviewing

> So with the whitespace fixed,
> Acked-by: Jonathan Cameron 
> > ---
> >  .../common/cros_ec_sensors/cros_ec_sensors.c  |  3 +
> >  .../cros_ec_sensors/cros_ec_sensors_core.c| 65
> > +++
> >  drivers/iio/light/cros_ec_light_prox.c|  3 +
> >  .../linux/iio/common/cros_ec_sensors_core.h   | 21 ++
> >  4 files changed, 92 insertions(+)
> > 
> > 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..2f1b6d8d617b 100644
> > --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> > +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> > @@ -175,6 +175,7 @@ static int cros_ec_sensors_write(struct iio_dev
> > *indio_dev,
> >  static const struct iio_info ec_sensors_info = {
> > .read_raw = _ec_sensors_read,
> > .write_raw = _ec_sensors_write,
> > +   .read_avail = _ec_sensors_core_read_avail,
> >  };
> >  
> >  static int cros_ec_sensors_probe(struct platform_device *pdev)
> > @@ -211,6 +212,8 @@ static int cros_ec_sensors_probe(struct
> > platform_device *pdev)
> > 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);
> > channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
> > channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
> > channel->scan_index = i;
> > 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 8af8a167..805652250960 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
> > @@ -50,6 +50,37 @@ static int
> > cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev,
> > return ret;
> >  }
> >  
> > +static void get_default_min_max_freq(enum motionsensor_type type,
> > +u32 *min_freq,
> > +u32 *max_freq)
> > +{
> > +   switch (type) {
> > +   case MOTIONSENSE_TYPE_ACCEL:
> > +   case MOTIONSENSE_TYPE_GYRO:
> > +   *min_freq = 12500;
> > +   *max_freq = 10;
> > +   break;
> > +   case MOTIONSENSE_TYPE_MAG:
> > +   *min_freq = 5000;
> > +   *max_freq = 25000;
> > +   break;
> > +   case MOTIONSENSE_TYPE_PROX:
> > +   case MOTIONSENSE_TYPE_LIGHT:
> > +   *min_freq = 100;
> > +   *max_freq = 5;
> > +   break;
> > +   case MOTIONSENSE_TYPE_BARO:
> > +   *min_freq = 250;
> > +   *max_freq = 2;
> > +   break;
> > +   case MOTIONSENSE_TYPE_ACTIVITY:
> > +   default:
> > +   *min_freq = 0;
> > +   *max_freq = 0;
> > +   break;
> > +   }
> > +}
> > +
> >  int cros_ec_sensors_core_init(struct platform_device *pdev,
> >   struct iio_dev *indio_dev,
> >   bool physical_device)
> > @@ -100,6 +131,19 @@ int cros_ec_sensors_core_init(struct
> > platform_device *pdev,
> > }
> > state->type = state->resp->info.type;
> > state->loc = state->resp->info.location;
> > +
> > +

[PATCH 1/1] counter: cros_ec: Add synchronization sensor

2019-07-09 Thread Fabien Lahoudere
From: Gwendal Grignou 

EC returns a counter when there is an event on camera vsync.
This patch comes from chromeos kernel 4.4

Signed-off-by: Gwendal Grignou 
Signed-off-by: Fabien Lahoudere 

CROS EC sync sensor was originally designed as an IIO device.
Now that the counter subsystem will replace IIO_COUNTER, we
have to implement a new way to get sync count.

Signed-off-by: Fabien Lahoudere 
---
 drivers/counter/Kconfig   |   9 +
 drivers/counter/Makefile  |   1 +
 drivers/counter/cros_ec_sensors_sync.c| 200 ++
 .../cros_ec_sensors/cros_ec_sensors_core.c|   1 +
 drivers/mfd/cros_ec_dev.c |   3 +
 5 files changed, 214 insertions(+)
 create mode 100644 drivers/counter/cros_ec_sensors_sync.c

diff --git a/drivers/counter/Kconfig b/drivers/counter/Kconfig
index 2967d0a9ff91..22287f5715e5 100644
--- a/drivers/counter/Kconfig
+++ b/drivers/counter/Kconfig
@@ -59,4 +59,13 @@ config FTM_QUADDEC
  To compile this driver as a module, choose M here: the
  module will be called ftm-quaddec.
 
+config IIO_CROS_EC_SENSORS_SYNC
+   tristate "ChromeOS EC Counter Sensors"
+   depends on IIO_CROS_EC_SENSORS_CORE && IIO
+   help
+ Module to handle synchronisation sensors presented by the ChromeOS EC
+ Sensor hub.
+ Synchronisation sensors are counter sensors triggered when events
+ occurs from other subsystems.
+
 endif # COUNTER
diff --git a/drivers/counter/Makefile b/drivers/counter/Makefile
index 40d35522937d..6fe4c98a446f 100644
--- a/drivers/counter/Makefile
+++ b/drivers/counter/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_104_QUAD_8)+= 104-quad-8.o
 obj-$(CONFIG_STM32_TIMER_CNT)  += stm32-timer-cnt.o
 obj-$(CONFIG_STM32_LPTIMER_CNT)+= stm32-lptimer-cnt.o
 obj-$(CONFIG_FTM_QUADDEC)  += ftm-quaddec.o
+obj-$(CONFIG_IIO_CROS_EC_SENSORS_SYNC) += cros_ec_sensors_sync.o
diff --git a/drivers/counter/cros_ec_sensors_sync.c 
b/drivers/counter/cros_ec_sensors_sync.c
new file mode 100644
index ..715a4860cade
--- /dev/null
+++ b/drivers/counter/cros_ec_sensors_sync.c
@@ -0,0 +1,200 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver of counter increaseded after events on interrupt line in EC.
+ *
+ * Copyright 2018 Google, Inc
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DRV_NAME "cros-ec-sync"
+
+/*
+ * One channel for counter, the other for timestamp.
+ */
+#define MAX_CHANNELS (1 + 1)
+
+/* State data for ec_sensors iio driver. */
+struct cros_ec_sensors_sync_state {
+   /* Shared by all sensors */
+   struct cros_ec_sensors_core_state core;
+   struct counter_device counter;
+   struct iio_chan_spec channels[MAX_CHANNELS];
+};
+
+static int cros_ec_sensors_sync_read(struct iio_dev *indio_dev,
+struct iio_chan_spec const *chan,
+int *val, int *val2, long mask)
+{
+   struct cros_ec_sensors_sync_state *st = iio_priv(indio_dev);
+   u16 data;
+   int ret;
+   int idx = chan->scan_index;
+
+   mutex_lock(>core.cmd_lock);
+   switch (mask) {
+   case IIO_CHAN_INFO_RAW:
+   ret = cros_ec_sensors_read_cmd(indio_dev, BIT(idx), );
+   if (ret < 0)
+   break;
+   ret = IIO_VAL_INT;
+   *val = data;
+   break;
+   default:
+   ret = cros_ec_sensors_core_read(>core, chan, val, val2,
+   mask);
+   break;
+   }
+   mutex_unlock(>core.cmd_lock);
+   return ret;
+}
+
+static int cros_ec_sensors_write(struct iio_dev *indio_dev,
+struct iio_chan_spec const *chan,
+int val, int val2, long mask)
+{
+   struct cros_ec_sensors_sync_state *st = iio_priv(indio_dev);
+   int ret;
+
+   mutex_lock(>core.cmd_lock);
+
+   ret = cros_ec_sensors_core_write(>core, chan, val, val2, mask);
+
+   mutex_unlock(>core.cmd_lock);
+   return ret;
+}
+
+static struct iio_info cros_ec_sensors_sync_info = {
+   .read_raw = _ec_sensors_sync_read,
+   .write_raw = _ec_sensors_write,
+   .read_avail = _ec_sensors_core_read_avail,
+};
+
+static struct counter_count cros_ec_sync_counts = {
+   .id = 0,
+   .name = "Cros EC sync counter",
+};
+
+static int cros_ec_sync_cnt_read(struct counter_device *counter,
+   struct counter_count *count,
+   struct counter_count_read_value *val)
+{
+   s16 cnt;
+   int ret;
+   struct iio_dev * indio_dev = counter->priv;
+   struct cros_ec_sensors_sync_state *const st = iio_priv(indio_dev);
+   unsigned long data;
+
+   mutex_lock(>core.cmd_lock);
+   ret =

[PATCH 0/1] counter: cros_ec: Add sync sensor driver

2019-07-09 Thread Fabien Lahoudere
Some chromebook EC provides a counter to get all vsync coming from the back
camera.
This series introduces a patch coming from chromebook kernel 4.4 designed as an
IIO counter. As IIO counter will be deprecated in favor of counter, I rebase the
original patch and support the new counter API.

The serie need to be merged after https://lkml.org/lkml/2019/7/9/305

Gwendal Grignou (1):
  counter: cros_ec: Add synchronization sensor

 drivers/counter/Kconfig   |   9 +
 drivers/counter/Makefile  |   1 +
 drivers/counter/cros_ec_sensors_sync.c| 200 ++
 .../cros_ec_sensors/cros_ec_sensors_core.c|   1 +
 drivers/mfd/cros_ec_dev.c |   3 +
 5 files changed, 214 insertions(+)
 create mode 100644 drivers/counter/cros_ec_sensors_sync.c

-- 
2.19.2



[PATCH v4 1/1] iio: common: cros_ec_sensors: Expose cros_ec_sensors frequency range via iio sysfs

2019-07-09 Thread Fabien Lahoudere
Embedded controller return minimum and maximum frequencies, unfortunately
we have no way to know the step for all available frequencies.
Even if not complete, we can return a list of known values using the
standard read_avail callback (IIO_CHAN_INFO_SAMP_FREQ) to provide them to
userland.

Now cros_ec_* sensors provides frequencies values in sysfs like this:
"0 min max". 0 is always true to disable the sensor.

Default frequencies are provided for earlier protocol.

Signed-off-by: Nick Vaccaro 
Signed-off-by: Fabien Lahoudere 
---
 .../common/cros_ec_sensors/cros_ec_sensors.c  |  3 +
 .../cros_ec_sensors/cros_ec_sensors_core.c| 65 +++
 drivers/iio/light/cros_ec_light_prox.c|  3 +
 .../linux/iio/common/cros_ec_sensors_core.h   | 21 ++
 4 files changed, 92 insertions(+)

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..2f1b6d8d617b 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -175,6 +175,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
 static const struct iio_info ec_sensors_info = {
.read_raw = _ec_sensors_read,
.write_raw = _ec_sensors_write,
+   .read_avail = _ec_sensors_core_read_avail,
 };
 
 static int cros_ec_sensors_probe(struct platform_device *pdev)
@@ -211,6 +212,8 @@ static int cros_ec_sensors_probe(struct platform_device 
*pdev)
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);
channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
channel->scan_index = i;
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 8af8a167..805652250960 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
@@ -50,6 +50,37 @@ static int cros_ec_get_host_cmd_version_mask(struct 
cros_ec_device *ec_dev,
return ret;
 }
 
+static void get_default_min_max_freq(enum motionsensor_type type,
+u32 *min_freq,
+u32 *max_freq)
+{
+   switch (type) {
+   case MOTIONSENSE_TYPE_ACCEL:
+   case MOTIONSENSE_TYPE_GYRO:
+   *min_freq = 12500;
+   *max_freq = 10;
+   break;
+   case MOTIONSENSE_TYPE_MAG:
+   *min_freq = 5000;
+   *max_freq = 25000;
+   break;
+   case MOTIONSENSE_TYPE_PROX:
+   case MOTIONSENSE_TYPE_LIGHT:
+   *min_freq = 100;
+   *max_freq = 5;
+   break;
+   case MOTIONSENSE_TYPE_BARO:
+   *min_freq = 250;
+   *max_freq = 2;
+   break;
+   case MOTIONSENSE_TYPE_ACTIVITY:
+   default:
+   *min_freq = 0;
+   *max_freq = 0;
+   break;
+   }
+}
+
 int cros_ec_sensors_core_init(struct platform_device *pdev,
  struct iio_dev *indio_dev,
  bool physical_device)
@@ -100,6 +131,19 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
}
state->type = state->resp->info.type;
state->loc = state->resp->info.location;
+
+   /* 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,
+>frequencies[1],
+>frequencies[2]);
+   } else {
+   state->frequencies[1] =
+   state->resp->info_3.min_frequency;
+   state->frequencies[2] =
+   state->resp->info_3.max_frequency;
+   }
}
 
return 0;
@@ -461,6 +505,27 @@ int cros_ec_sensors_core_read(struct 
cros_ec_sensors_core_state *st,
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_read);
 
+int cros_ec_sensors_core_read_avail(struct iio_dev *indio_dev,
+   struct iio_chan_spec const *chan,
+   const int **vals,
+   int *type,
+   int *length,
+   long mask)
+{
+   struct cros_ec_sensors_core_state *state = iio_priv(indio_dev);
+
+  

[PATCH v4 0/1] Expose cros_ec_sensors frequency range via iio sysfs

2019-07-09 Thread Fabien Lahoudere
Chromebooks EC sensors must expose a range of frequencies for each sensors using
the standard ABI sampling_frquency_available.

This patch needs https://lkml.org/lkml/2019/7/2/345

Changes since v3:
- Split patch 6
- Drop clean up patches
- Fix minor changes

Changes since v2:
- use read_avail callback
- rework core functions to avoid code duplication

Changes since v1:
- Add a cover letter
- Add Nick Vaccaro SoB to patch 1
- Drop fifo size related code

Fabien Lahoudere (1):
  iio: common: cros_ec_sensors: Expose cros_ec_sensors frequency range
via iio sysfs

 .../common/cros_ec_sensors/cros_ec_sensors.c  |  3 +
 .../cros_ec_sensors/cros_ec_sensors_core.c| 65 +++
 drivers/iio/light/cros_ec_light_prox.c|  3 +
 .../linux/iio/common/cros_ec_sensors_core.h   | 21 ++
 4 files changed, 92 insertions(+)

-- 
2.19.2



Re: [PATCH v3 8/8] docs: iio: add precision about sampling_frequency_available

2019-07-09 Thread Fabien Lahoudere
Le samedi 22 juin 2019 à 11:21 +0100, Jonathan Cameron a écrit :
> On Tue, 18 Jun 2019 11:06:39 +0200
> Fabien Lahoudere  wrote:
> 
> > The documentation give some exemple on what format can be expected
> > from sampling_frequency_available sysfs attribute
> > 
> > Signed-off-by: Fabien Lahoudere 
> It seems I already applied this one, though probably haven't sent
> a pull request for it to Greg yet.
> 
> Please drop it from your v4 posting as otherwise I'll get confused
> (again).
> 

Sorry, it will be dropped next time.

> Thanks,
> 
> Jonathan
> 
> 
> > ---
> >  Documentation/ABI/testing/sysfs-bus-iio | 7 +--
> >  1 file changed, 5 insertions(+), 2 deletions(-)
> > 
> > diff --git a/Documentation/ABI/testing/sysfs-bus-iio
> > b/Documentation/ABI/testing/sysfs-bus-iio
> > index 6aef7dbbde44..680451695422 100644
> > --- a/Documentation/ABI/testing/sysfs-bus-iio
> > +++ b/Documentation/ABI/testing/sysfs-bus-iio
> > @@ -61,8 +61,11 @@ What:/sys/bus/iio/devices/triggerX/s
> > ampling_frequency_available
> >  KernelVersion: 2.6.35
> >  Contact:   linux-...@vger.kernel.org
> >  Description:
> > -   When the internal sampling clock can only take a small
> > -   discrete set of values, this file lists those
> > available.
> > +   When the internal sampling clock can only take a
> > specific set of
> > +   frequencies, we can specify the available values with:
> > +   - a small discrete set of values like "0 2 4 6 8"
> > +   - a range with minimum, step and maximum frequencies
> > like
> > + "[min step max]"
> >  
> >  What:  /sys/bus/iio/devices/iio:deviceX/oversampling_r
> > atio
> >  KernelVersion: 2.6.38



[PATCH v4 0/1] iio: common: cros_ec_sensors: Add protocol v3 support

2019-07-02 Thread Fabien Lahoudere
This patch is part of a split of the following patch:
https://lkml.org/lkml/2019/6/18/268
To fix Enric comments from https://lkml.org/lkml/2019/6/25/949
I extract it from the other serie to speed up acceptance because
other patches need it to be upstreamed.

Changes since v3:
- Remove unneeded semicolon
- Add Enric Acked-by

Changes since v2:
- Use patch 1 from v1 after discussion on ML

Changes since v1:
- Drop second patch
- return ENODEV if version is 0

Fabien Lahoudere (1):
  iio: common: cros_ec_sensors: determine protocol version

 .../cros_ec_sensors/cros_ec_sensors_core.c| 36 ++-
 1 file changed, 35 insertions(+), 1 deletion(-)

-- 
2.19.2



[PATCH v4 1/1] iio: common: cros_ec_sensors: determine protocol version

2019-07-02 Thread Fabien Lahoudere
This patch adds a function to determine which version of the
protocol is used to communicate with EC.

Signed-off-by: Fabien Lahoudere 
Signed-off-by: Nick Vaccaro 
Reviewed-by: Gwendal Grignou 
Tested-by: Gwendal Grignou 
Acked-by: Enric Balletbo i Serra 
---
 .../cros_ec_sensors/cros_ec_sensors_core.c| 36 ++-
 1 file changed, 35 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 130362ca421b..8af8a167 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
@@ -25,6 +25,31 @@ static char *cros_ec_loc[] = {
[MOTIONSENSE_LOC_MAX] = "unknown",
 };
 
+static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev,
+u16 cmd_offset, u16 cmd, u32 *mask)
+{
+   int ret;
+   struct {
+   struct cros_ec_command msg;
+   union {
+   struct ec_params_get_cmd_versions params;
+   struct ec_response_get_cmd_versions resp;
+   };
+   } __packed buf = {
+   .msg = {
+   .command = EC_CMD_GET_CMD_VERSIONS + cmd_offset,
+   .insize = sizeof(struct ec_response_get_cmd_versions),
+   .outsize = sizeof(struct ec_params_get_cmd_versions)
+   },
+   .params = {.cmd = cmd}
+   };
+
+   ret = cros_ec_cmd_xfer_status(ec_dev, );
+   if (ret >= 0)
+   *mask = buf.resp.version_mask;
+   return ret;
+}
+
 int cros_ec_sensors_core_init(struct platform_device *pdev,
  struct iio_dev *indio_dev,
  bool physical_device)
@@ -33,6 +58,8 @@ 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);
+   u32 ver_mask;
+   int ret;
 
platform_set_drvdata(pdev, indio_dev);
 
@@ -47,8 +74,15 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
 
mutex_init(>cmd_lock);
 
+   ret = cros_ec_get_host_cmd_version_mask(state->ec,
+   ec->cmd_offset,
+   EC_CMD_MOTION_SENSE_CMD,
+   _mask);
+   if (ret < 0)
+   return ret;
+
/* Set up the host command structure. */
-   state->msg->version = 2;
+   state->msg->version = fls(ver_mask) - 1;
state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
state->msg->outsize = sizeof(struct ec_params_motion_sense);
 
-- 
2.19.2



Re: [PATCH v3 1/1] iio: common: cros_ec_sensors: determine protocol version

2019-07-02 Thread Fabien Lahoudere
Hi,

There is a double semi colon in that patch.
Let me send a v4 without it.

Le lundi 01 juillet 2019 à 10:14 +0200, Fabien Lahoudere a écrit :
> This patch adds a function to determine which version of the
> protocol is used to communicate with EC.
> 
> Signed-off-by: Fabien Lahoudere 
> Signed-off-by: Nick Vaccaro 
> Reviewed-by: Gwendal Grignou 
> Tested-by: Gwendal Grignou 
> ---
>  .../cros_ec_sensors/cros_ec_sensors_core.c| 36
> ++-
>  1 file changed, 35 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 130362ca421b..2e0f97448e64 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
> @@ -25,6 +25,31 @@ static char *cros_ec_loc[] = {
>   [MOTIONSENSE_LOC_MAX] = "unknown",
>  };
>  
> +static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device
> *ec_dev,
> +  u16 cmd_offset, u16 cmd,
> u32 *mask)
> +{
> + int ret;
> + struct {
> + struct cros_ec_command msg;
> + union {
> + struct ec_params_get_cmd_versions params;
> + struct ec_response_get_cmd_versions resp;
> + };
> + } __packed buf = {
> + .msg = {
> + .command = EC_CMD_GET_CMD_VERSIONS +
> cmd_offset,
> + .insize = sizeof(struct
> ec_response_get_cmd_versions),
> + .outsize = sizeof(struct
> ec_params_get_cmd_versions)
> + },
> + .params = {.cmd = cmd}
> + };
> +
> + ret = cros_ec_cmd_xfer_status(ec_dev, );
> + if (ret >= 0)
> + *mask = buf.resp.version_mask;
> + return ret;
> +}
> +
>  int cros_ec_sensors_core_init(struct platform_device *pdev,
> struct iio_dev *indio_dev,
> bool physical_device)
> @@ -33,6 +58,8 @@ 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);
> + u32 ver_mask;
> + int ret;
>  
>   platform_set_drvdata(pdev, indio_dev);
>  
> @@ -47,8 +74,15 @@ int cros_ec_sensors_core_init(struct
> platform_device *pdev,
>  
>   mutex_init(>cmd_lock);
>  
> + ret = cros_ec_get_host_cmd_version_mask(state->ec,
> + ec->cmd_offset,
> + EC_CMD_MOTION_SENSE_CMD
> ,
> + _mask);
> + if (ret < 0)
> + return ret;
> +
>   /* Set up the host command structure. */
> - state->msg->version = 2;
> + state->msg->version = fls(ver_mask) - 1;;

Unneeded semi colon.

>   state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
>   state->msg->outsize = sizeof(struct ec_params_motion_sense);
>  



[PATCH v3 1/1] iio: common: cros_ec_sensors: determine protocol version

2019-07-01 Thread Fabien Lahoudere
This patch adds a function to determine which version of the
protocol is used to communicate with EC.

Signed-off-by: Fabien Lahoudere 
Signed-off-by: Nick Vaccaro 
Reviewed-by: Gwendal Grignou 
Tested-by: Gwendal Grignou 
---
 .../cros_ec_sensors/cros_ec_sensors_core.c| 36 ++-
 1 file changed, 35 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 130362ca421b..2e0f97448e64 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
@@ -25,6 +25,31 @@ static char *cros_ec_loc[] = {
[MOTIONSENSE_LOC_MAX] = "unknown",
 };
 
+static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev,
+u16 cmd_offset, u16 cmd, u32 *mask)
+{
+   int ret;
+   struct {
+   struct cros_ec_command msg;
+   union {
+   struct ec_params_get_cmd_versions params;
+   struct ec_response_get_cmd_versions resp;
+   };
+   } __packed buf = {
+   .msg = {
+   .command = EC_CMD_GET_CMD_VERSIONS + cmd_offset,
+   .insize = sizeof(struct ec_response_get_cmd_versions),
+   .outsize = sizeof(struct ec_params_get_cmd_versions)
+   },
+   .params = {.cmd = cmd}
+   };
+
+   ret = cros_ec_cmd_xfer_status(ec_dev, );
+   if (ret >= 0)
+   *mask = buf.resp.version_mask;
+   return ret;
+}
+
 int cros_ec_sensors_core_init(struct platform_device *pdev,
  struct iio_dev *indio_dev,
  bool physical_device)
@@ -33,6 +58,8 @@ 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);
+   u32 ver_mask;
+   int ret;
 
platform_set_drvdata(pdev, indio_dev);
 
@@ -47,8 +74,15 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
 
mutex_init(>cmd_lock);
 
+   ret = cros_ec_get_host_cmd_version_mask(state->ec,
+   ec->cmd_offset,
+   EC_CMD_MOTION_SENSE_CMD,
+   _mask);
+   if (ret < 0)
+   return ret;
+
/* Set up the host command structure. */
-   state->msg->version = 2;
+   state->msg->version = fls(ver_mask) - 1;;
state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
state->msg->outsize = sizeof(struct ec_params_motion_sense);
 
-- 
2.19.2



[PATCH v3 0/1] iio: common: cros_ec_sensors: Add protocol v3 support

2019-07-01 Thread Fabien Lahoudere
This patch is part of a split of the following patch:
https://lkml.org/lkml/2019/6/18/268
To fix Enric comments from https://lkml.org/lkml/2019/6/25/949
I extract it from the other serie to speed up acceptance because
other patches need it to be upstreamed.

Changes since v2:
- Use patch 1 from v1 after discussion on ML

Changes since v1:
- Drop second patch
- return ENODEV if version is 0

Fabien Lahoudere (1):
  iio: common: cros_ec_sensors: determine protocol version

 .../cros_ec_sensors/cros_ec_sensors_core.c| 36 ++-
 1 file changed, 35 insertions(+), 1 deletion(-)

-- 
2.19.2



[PATCH v2 1/1] iio: common: cros_ec_sensors: determine protocol version

2019-06-28 Thread Fabien Lahoudere
This patch adds a function to determine which version of the
protocol is used to communicate with EC.

Signed-off-by: Fabien Lahoudere 
Signed-off-by: Nick Vaccaro 
---
 .../cros_ec_sensors/cros_ec_sensors_core.c| 40 ++-
 1 file changed, 39 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 130362ca421b..75d9b617f6c8 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
@@ -25,6 +25,35 @@ static char *cros_ec_loc[] = {
[MOTIONSENSE_LOC_MAX] = "unknown",
 };
 
+static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev,
+u16 cmd_offset, u16 cmd, u32 *mask)
+{
+   int ret;
+   struct {
+   struct cros_ec_command msg;
+   union {
+   struct ec_params_get_cmd_versions params;
+   struct ec_response_get_cmd_versions resp;
+   };
+   } __packed buf = {
+   .msg = {
+   .version = 0,
+   .command = EC_CMD_GET_CMD_VERSIONS + cmd_offset,
+   .insize = sizeof(struct ec_response_get_cmd_versions),
+   .outsize = sizeof(struct ec_params_get_cmd_versions)
+   },
+   .params = {.cmd = cmd}
+   };
+
+   ret = cros_ec_cmd_xfer_status(ec_dev, );
+   if (ret < 0)
+   return ret;
+
+   *mask = buf.resp.version_mask;
+
+   return 0;
+}
+
 int cros_ec_sensors_core_init(struct platform_device *pdev,
  struct iio_dev *indio_dev,
  bool physical_device)
@@ -33,6 +62,8 @@ 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);
+   u32 ver_mask;
+   int ret;
 
platform_set_drvdata(pdev, indio_dev);
 
@@ -47,8 +78,15 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
 
mutex_init(>cmd_lock);
 
+   ret = cros_ec_get_host_cmd_version_mask(state->ec,
+   ec->cmd_offset,
+   EC_CMD_MOTION_SENSE_CMD,
+   _mask);
+   if (ret < 0 || ver_mask == 0)
+   return -ENODEV;
+
/* Set up the host command structure. */
-   state->msg->version = 2;
+   state->msg->version = fls(ver_mask) - 1;;
state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
state->msg->outsize = sizeof(struct ec_params_motion_sense);
 
-- 
2.19.2



[PATCH v2 0/1] iio: common: cros_ec_sensors: Add protocol v3 support

2019-06-28 Thread Fabien Lahoudere
This patch is part of a split of the following patch:
https://lkml.org/lkml/2019/6/18/268
To fix Enric comments from https://lkml.org/lkml/2019/6/25/949
I extract it from the other serie to speed up acceptance because
other patches need it to be upstreamed.

Changes since v1:
- Drop second patch
- return ENODEV if version is 0

Fabien Lahoudere (1):
  iio: common: cros_ec_sensors: determine protocol version

 .../cros_ec_sensors/cros_ec_sensors_core.c| 40 ++-
 1 file changed, 39 insertions(+), 1 deletion(-)

-- 
2.19.2



Re: [PATCH 1/2] iio: common: cros_ec_sensors: determine protocol version

2019-06-28 Thread Fabien Lahoudere
Le jeudi 27 juin 2019 à 14:59 -0700, Gwendal Grignou a écrit :
> On Thu, Jun 27, 2019 at 8:59 AM Enric Balletbo i Serra
>  wrote:
> > Hi,
> > 
> > cc'ing Doug, Gwendal and Enrico that might be interested to give a
> > review.
> > 
> > This patch can be picked alone without 2/2, an is needed to have
> > cros-ec-sensors
> > legacy support on ARM (see [1] and [2])
> > 
> > Jonathan, as [1] and [2] will go through the chrome-platform tree
> > if you don't
> > mind I'd also like to carry with this patch once you're fine with
> > it.
> > 
> > Thanks,
> > ~ Enric
> > 
> > [1] https://patchwork.kernel.org/patch/11014329/
> > [2] https://patchwork.kernel.org/patch/11014327/
> > 
> > On 27/6/19 16:04, Fabien Lahoudere wrote:
> > > This patch adds a function to determine which version of the
> > > protocol is used to communicate with EC.
> > > 
> > > Signed-off-by: Fabien Lahoudere 
> > > Signed-off-by: Nick Vaccaro 
> > 
> > Tested-by: Enric Balletbo i Serra 
> > 
> > > ---
> > >  .../cros_ec_sensors/cros_ec_sensors_core.c| 36
> > > ++-
> > >  1 file changed, 35 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 130362ca421b..2e0f97448e64 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
> > > @@ -25,6 +25,31 @@ static char *cros_ec_loc[] = {
> > >   [MOTIONSENSE_LOC_MAX] = "unknown",
> > >  };
> > > 
> > > +static int cros_ec_get_host_cmd_version_mask(struct
> > > cros_ec_device *ec_dev,
> > > +  u16 cmd_offset, u16
> > > cmd, u32 *mask)
> > > +{
> > > + int ret;
> > > + struct {
> > > + struct cros_ec_command msg;
> > > + union {
> > > + struct ec_params_get_cmd_versions params;
> > > + struct ec_response_get_cmd_versions resp;
> > > + };
> > > + } __packed buf = {
> > > + .msg = {
> add
> .version = 0,
> As the variable is coming from the stack, the version should be set.
> > > + .command = EC_CMD_GET_CMD_VERSIONS +
> > > cmd_offset,
> > > + .insize = sizeof(struct
> > > ec_response_get_cmd_versions),
> > > + .outsize = sizeof(struct
> > > ec_params_get_cmd_versions)
> > > + },
> > > + .params = {.cmd = cmd}
> > > + };
> > > +
> > > + ret = cros_ec_cmd_xfer_status(ec_dev, );
> > > + if (ret >= 0)
> It should be > 0: when the command is a success, it returns the
> number
> of byte in the response buffer. When don't expect == 0  here, because
> when successful, EC_CMD_GET_CMD_VERSIONS will return a mask.
> > > + *mask = buf.resp.version_mask;
> > > + return ret;
> > > +}
> > > +
> > >  int cros_ec_sensors_core_init(struct platform_device *pdev,
> > > struct iio_dev *indio_dev,
> > > bool physical_device)
> > > @@ -33,6 +58,8 @@ 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);
> > > + u32 ver_mask;
> > > + int ret;
> > > 
> > >   platform_set_drvdata(pdev, indio_dev);
> > > 
> > > @@ -47,8 +74,15 @@ int cros_ec_sensors_core_init(struct
> > > platform_device *pdev,
> > > 
> > >   mutex_init(>cmd_lock);
> > > 
> > > + ret = cros_ec_get_host_cmd_version_mask(state->ec,
> > > + ec->cmd_offset,
> > > + EC_CMD_MOTION_SENSE
> > > _CMD,
> > > + _mask);
> > > + if (ret < 0)
> Use:
> if (ret <= 0 || ver_mask == 0) {
> In case the EC is really old or misbehaving, we don't want to set an
> invalid version later.

To not return a positive value on error if ret >= 0 and ver_mask = 0  
I would prefer this:

if (ret <= 0)
return ret;

if (ver_mask == 0)
return -EIO;

Let me know if I am wrong

> > > + return ret;
> > > +
> > >   /* Set up the host command structure. */
> > > - state->msg->version = 2;
> > > + state->msg->version = fls(ver_mask) - 1;;
> > >   state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec-
> > > >cmd_offset;
> > >   state->msg->outsize = sizeof(struct
> > > ec_params_motion_sense);
> > > 
> > > 



Re: [PATCH 2/2] iio: common: cros_ec_sensors: set default frequencies

2019-06-28 Thread Fabien Lahoudere
Hi Enric

Le jeudi 27 juin 2019 à 17:48 +0200, Enric Balletbo i Serra a écrit :
> Hi Fabien,
> 
> On 27/6/19 16:04, Fabien Lahoudere wrote:
> > Version 3 of the EC protocol provides min and max frequencies for
> > EC sensors.
> > Default frequencies are provided for earlier protocol.
> > 
> 
> This patch should really go together with a respin of your previous
> patchset to
> 'Expose cros_ec_sensors frequency range via iio sysfs' [1]
> 
> [1] https://www.spinics.net/lists/linux-iio/msg44963.html
> 

I agree, you're right. I will send only the first patch with Gwendal
comments for v2.

Thanks

> > Signed-off-by: Fabien Lahoudere 
> > Signed-off-by: Nick Vaccaro 
> > ---
> >  .../cros_ec_sensors/cros_ec_sensors_core.c| 44
> > +++
> >  .../linux/iio/common/cros_ec_sensors_core.h   |  3 ++
> >  2 files changed, 47 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 2e0f97448e64..72f56d54cccd 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
> > @@ -50,6 +50,37 @@ static int
> > cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev,
> > return ret;
> >  }
> >  
> > +static void get_default_min_max_freq(enum motionsensor_type type,
> > +u32 *min_freq,
> > +u32 *max_freq)
> > +{
> > +   switch (type) {
> > +   case MOTIONSENSE_TYPE_ACCEL:
> > +   case MOTIONSENSE_TYPE_GYRO:
> > +   *min_freq = 12500;
> > +   *max_freq = 10;
> > +   break;
> > +   case MOTIONSENSE_TYPE_MAG:
> > +   *min_freq = 5000;
> > +   *max_freq = 25000;
> > +   break;
> > +   case MOTIONSENSE_TYPE_PROX:
> > +   case MOTIONSENSE_TYPE_LIGHT:
> > +   *min_freq = 100;
> > +   *max_freq = 5;
> > +   break;
> > +   case MOTIONSENSE_TYPE_BARO:
> > +   *min_freq = 250;
> > +   *max_freq = 2;
> > +   break;
> > +   case MOTIONSENSE_TYPE_ACTIVITY:
> > +   default:
> > +   *min_freq = 0;
> > +   *max_freq = 0;
> > +   break;
> > +   }
> > +}
> > +
> >  int cros_ec_sensors_core_init(struct platform_device *pdev,
> >   struct iio_dev *indio_dev,
> >   bool physical_device)
> > @@ -100,6 +131,19 @@ int cros_ec_sensors_core_init(struct
> > platform_device *pdev,
> > }
> > state->type = state->resp->info.type;
> > state->loc = state->resp->info.location;
> > +
> > +   /* Value to stop the device */
> > +   state->frequencies[0] = 0;
> > +   if (state->msg->version < 3) {
> > +   get_default_min_max_freq(state->resp-
> > >info.type,
> > +
> > >frequencies[1],
> > +
> > >frequencies[2]);
> > +   } else {
> > +   state->frequencies[1] =
> > +   state->resp->info_3.min_frequency;
> > +   state->frequencies[2] =
> > +   state->resp->info_3.max_frequency;
> > +   }
> > }
> >  
> > return 0;
> > diff --git a/include/linux/iio/common/cros_ec_sensors_core.h
> > b/include/linux/iio/common/cros_ec_sensors_core.h
> > index 0c636b9fe8d7..94c87da22c04 100644
> > --- a/include/linux/iio/common/cros_ec_sensors_core.h
> > +++ b/include/linux/iio/common/cros_ec_sensors_core.h
> > @@ -70,6 +70,9 @@ struct cros_ec_sensors_core_state {
> > unsigned long scan_mask, s16
> > *data);
> >  
> > int curr_sampl_freq;
> > +
> > +   /* Disable, Min and Max Sampling Frequency in mHz */
> > +   int frequencies[3];
> >  };
> >  
> >  /**
> > 



Re: [PATCH 1/2] iio: common: cros_ec_sensors: determine protocol version

2019-06-28 Thread Fabien Lahoudere
Thanks Gwendal for reviewing.

Le jeudi 27 juin 2019 à 14:59 -0700, Gwendal Grignou a écrit :
> On Thu, Jun 27, 2019 at 8:59 AM Enric Balletbo i Serra
>  wrote:
> > Hi,
> > 
> > cc'ing Doug, Gwendal and Enrico that might be interested to give a
> > review.
> > 
> > This patch can be picked alone without 2/2, an is needed to have
> > cros-ec-sensors
> > legacy support on ARM (see [1] and [2])
> > 
> > Jonathan, as [1] and [2] will go through the chrome-platform tree
> > if you don't
> > mind I'd also like to carry with this patch once you're fine with
> > it.
> > 
> > Thanks,
> > ~ Enric
> > 
> > [1] https://patchwork.kernel.org/patch/11014329/
> > [2] https://patchwork.kernel.org/patch/11014327/
> > 
> > On 27/6/19 16:04, Fabien Lahoudere wrote:
> > > This patch adds a function to determine which version of the
> > > protocol is used to communicate with EC.
> > > 
> > > Signed-off-by: Fabien Lahoudere 
> > > Signed-off-by: Nick Vaccaro 
> > 
> > Tested-by: Enric Balletbo i Serra 
> > 
> > > ---
> > >  .../cros_ec_sensors/cros_ec_sensors_core.c| 36
> > > ++-
> > >  1 file changed, 35 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 130362ca421b..2e0f97448e64 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
> > > @@ -25,6 +25,31 @@ static char *cros_ec_loc[] = {
> > >   [MOTIONSENSE_LOC_MAX] = "unknown",
> > >  };
> > > 
> > > +static int cros_ec_get_host_cmd_version_mask(struct
> > > cros_ec_device *ec_dev,
> > > +  u16 cmd_offset, u16
> > > cmd, u32 *mask)
> > > +{
> > > + int ret;
> > > + struct {
> > > + struct cros_ec_command msg;
> > > + union {
> > > + struct ec_params_get_cmd_versions params;
> > > + struct ec_response_get_cmd_versions resp;
> > > + };
> > > + } __packed buf = {
> > > + .msg = {
> add
> .version = 0,
> As the variable is coming from the stack, the version should be set.

Ack

> > > + .command = EC_CMD_GET_CMD_VERSIONS +
> > > cmd_offset,
> > > + .insize = sizeof(struct
> > > ec_response_get_cmd_versions),
> > > + .outsize = sizeof(struct
> > > ec_params_get_cmd_versions)
> > > + },
> > > + .params = {.cmd = cmd}
> > > + };
> > > +
> > > + ret = cros_ec_cmd_xfer_status(ec_dev, );
> > > + if (ret >= 0)
> It should be > 0: when the command is a success, it returns the
> number
> of byte in the response buffer. When don't expect == 0  here, because
> when successful, EC_CMD_GET_CMD_VERSIONS will return a mask.

Ack, so we assume that on success, 0 is not possible.

> > > + *mask = buf.resp.version_mask;
> > > + return ret;
> > > +}
> > > +
> > >  int cros_ec_sensors_core_init(struct platform_device *pdev,
> > > struct iio_dev *indio_dev,
> > > bool physical_device)
> > > @@ -33,6 +58,8 @@ 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);
> > > + u32 ver_mask;
> > > + int ret;
> > > 
> > >   platform_set_drvdata(pdev, indio_dev);
> > > 
> > > @@ -47,8 +74,15 @@ int cros_ec_sensors_core_init(struct
> > > platform_device *pdev,
> > > 
> > >   mutex_init(>cmd_lock);
> > > 
> > > + ret = cros_ec_get_host_cmd_version_mask(state->ec,
> > > + ec->cmd_offset,
> > > + EC_CMD_MOTION_SENSE
> > > _CMD,
> > > + _mask);
> > > + if (ret < 0)
> Use:
> if (ret <= 0 || ver_mask == 0) {
> In case the EC is really old or misbehaving, we don't want to set an
> invalid version later.
Ack, indeed the communication can work but with invalid data.
> > > + return ret;
> > > +
> > >   /* Set up the host command structure. */
> > > - state->msg->version = 2;
> > > + state->msg->version = fls(ver_mask) - 1;;
> > >   state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec-
> > > >cmd_offset;
> > >   state->msg->outsize = sizeof(struct
> > > ec_params_motion_sense);
> > > 
> > > 



[PATCH 1/2] iio: common: cros_ec_sensors: determine protocol version

2019-06-27 Thread Fabien Lahoudere
This patch adds a function to determine which version of the
protocol is used to communicate with EC.

Signed-off-by: Fabien Lahoudere 
Signed-off-by: Nick Vaccaro 
---
 .../cros_ec_sensors/cros_ec_sensors_core.c| 36 ++-
 1 file changed, 35 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 130362ca421b..2e0f97448e64 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
@@ -25,6 +25,31 @@ static char *cros_ec_loc[] = {
[MOTIONSENSE_LOC_MAX] = "unknown",
 };
 
+static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev,
+u16 cmd_offset, u16 cmd, u32 *mask)
+{
+   int ret;
+   struct {
+   struct cros_ec_command msg;
+   union {
+   struct ec_params_get_cmd_versions params;
+   struct ec_response_get_cmd_versions resp;
+   };
+   } __packed buf = {
+   .msg = {
+   .command = EC_CMD_GET_CMD_VERSIONS + cmd_offset,
+   .insize = sizeof(struct ec_response_get_cmd_versions),
+   .outsize = sizeof(struct ec_params_get_cmd_versions)
+   },
+   .params = {.cmd = cmd}
+   };
+
+   ret = cros_ec_cmd_xfer_status(ec_dev, );
+   if (ret >= 0)
+   *mask = buf.resp.version_mask;
+   return ret;
+}
+
 int cros_ec_sensors_core_init(struct platform_device *pdev,
  struct iio_dev *indio_dev,
  bool physical_device)
@@ -33,6 +58,8 @@ 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);
+   u32 ver_mask;
+   int ret;
 
platform_set_drvdata(pdev, indio_dev);
 
@@ -47,8 +74,15 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
 
mutex_init(>cmd_lock);
 
+   ret = cros_ec_get_host_cmd_version_mask(state->ec,
+   ec->cmd_offset,
+   EC_CMD_MOTION_SENSE_CMD,
+   _mask);
+   if (ret < 0)
+   return ret;
+
/* Set up the host command structure. */
-   state->msg->version = 2;
+   state->msg->version = fls(ver_mask) - 1;;
state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
state->msg->outsize = sizeof(struct ec_params_motion_sense);
 
-- 
2.20.1



[PATCH 2/2] iio: common: cros_ec_sensors: set default frequencies

2019-06-27 Thread Fabien Lahoudere
Version 3 of the EC protocol provides min and max frequencies for EC sensors.
Default frequencies are provided for earlier protocol.

Signed-off-by: Fabien Lahoudere 
Signed-off-by: Nick Vaccaro 
---
 .../cros_ec_sensors/cros_ec_sensors_core.c| 44 +++
 .../linux/iio/common/cros_ec_sensors_core.h   |  3 ++
 2 files changed, 47 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 2e0f97448e64..72f56d54cccd 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
@@ -50,6 +50,37 @@ static int cros_ec_get_host_cmd_version_mask(struct 
cros_ec_device *ec_dev,
return ret;
 }
 
+static void get_default_min_max_freq(enum motionsensor_type type,
+u32 *min_freq,
+u32 *max_freq)
+{
+   switch (type) {
+   case MOTIONSENSE_TYPE_ACCEL:
+   case MOTIONSENSE_TYPE_GYRO:
+   *min_freq = 12500;
+   *max_freq = 10;
+   break;
+   case MOTIONSENSE_TYPE_MAG:
+   *min_freq = 5000;
+   *max_freq = 25000;
+   break;
+   case MOTIONSENSE_TYPE_PROX:
+   case MOTIONSENSE_TYPE_LIGHT:
+   *min_freq = 100;
+   *max_freq = 5;
+   break;
+   case MOTIONSENSE_TYPE_BARO:
+   *min_freq = 250;
+   *max_freq = 2;
+   break;
+   case MOTIONSENSE_TYPE_ACTIVITY:
+   default:
+   *min_freq = 0;
+   *max_freq = 0;
+   break;
+   }
+}
+
 int cros_ec_sensors_core_init(struct platform_device *pdev,
  struct iio_dev *indio_dev,
  bool physical_device)
@@ -100,6 +131,19 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
}
state->type = state->resp->info.type;
state->loc = state->resp->info.location;
+
+   /* Value to stop the device */
+   state->frequencies[0] = 0;
+   if (state->msg->version < 3) {
+   get_default_min_max_freq(state->resp->info.type,
+>frequencies[1],
+>frequencies[2]);
+   } else {
+   state->frequencies[1] =
+   state->resp->info_3.min_frequency;
+   state->frequencies[2] =
+   state->resp->info_3.max_frequency;
+   }
}
 
return 0;
diff --git a/include/linux/iio/common/cros_ec_sensors_core.h 
b/include/linux/iio/common/cros_ec_sensors_core.h
index 0c636b9fe8d7..94c87da22c04 100644
--- a/include/linux/iio/common/cros_ec_sensors_core.h
+++ b/include/linux/iio/common/cros_ec_sensors_core.h
@@ -70,6 +70,9 @@ struct cros_ec_sensors_core_state {
unsigned long scan_mask, s16 *data);
 
int curr_sampl_freq;
+
+   /* Disable, Min and Max Sampling Frequency in mHz */
+   int frequencies[3];
 };
 
 /**
-- 
2.20.1



[PATCH 0/2] Add protocol v3 support

2019-06-27 Thread Fabien Lahoudere
This series is a split of the following patch:
https://lkml.org/lkml/2019/6/18/268
To fix Enric comments from https://lkml.org/lkml/2019/6/25/949
I extract it from the other serie to speed up acceptance because
other patches need it to be upstreamed.

Fabien Lahoudere (2):
  iio: common: cros_ec_sensors: determine protocol version
  iio: common: cros_ec_sensors: set default frequencies

 .../cros_ec_sensors/cros_ec_sensors_core.c| 80 ++-
 .../linux/iio/common/cros_ec_sensors_core.h   |  3 +
 2 files changed, 82 insertions(+), 1 deletion(-)

-- 
2.20.1



Re: [PATCH v3 6/8] iio: common: cros_ec_sensors: support protocol v3 message

2019-06-27 Thread Fabien Lahoudere
Hi Enric

I will split in two patches and send it soon.
Nevertheless, I won't change the structure initialisation because it
was requested on a previous comment.
I will fix other comments.

Thanks for reviewing

Le mardi 25 juin 2019 à 19:04 +0200, Enric Balletbo i Serra a écrit :
> Hi Fabien, Jonathan,
> 
> cc'ing Gwendal and Enrico who might be interested on this patch.
> 
> It'd be nice if we can land this patch before [1], otherwise the
> legacy support
> for cros-ec sensors on veyron minnie won't work and we will mess the
> kernel log
> with a couple of errors.
> 
> I just have a few comments that I think should be quick to respin.
> 
> [1] https://lkml.org/lkml/2019/6/24/1464
> 
> On 22/6/19 12:15, Jonathan Cameron wrote:
> > On Tue, 18 Jun 2019 11:06:37 +0200
> > Fabien Lahoudere  wrote:
> > 
> > > Version 3 of the EC protocol provides min and max frequencies for
> > > EC sensors.
> > > 
> 
> I think we are mixing two things. One is determine what version of
> the
> MOTIONSENSE command the EC has, and another one is add some default
> values
> supported by the third version. I'd split this in two separate
> patches, and fix
> the subject and the commit description.
> 
> 
> > > Signed-off-by: Fabien Lahoudere 
> > > Signed-off-by: Nick Vaccaro 
> > Looks good to me. I'll pick up next time if no one else raises any
> > issues on this one.
> > 
> > Thanks,
> > 
> > Jonathan
> > 
> > > ---
> > >  .../cros_ec_sensors/cros_ec_sensors_core.c| 85
> > > ++-
> > >  .../linux/iio/common/cros_ec_sensors_core.h   |  3 +
> > >  2 files changed, 87 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 57034e212fe1..2ce077b576a4 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
> > > @@ -26,6 +26,66 @@ static char *cros_ec_loc[] = {
> > >   [MOTIONSENSE_LOC_MAX] = "unknown",
> > >  };
> > >  
> > > +static void get_default_min_max_freq(enum motionsensor_type
> > > type,
> > > +  u32 *min_freq,
> > > +  u32 *max_freq)
> > > +{
> > > + switch (type) {
> > > + case MOTIONSENSE_TYPE_ACCEL:
> > > + case MOTIONSENSE_TYPE_GYRO:
> > > + *min_freq = 12500;
> > > + *max_freq = 10;
> > > + break;
> > > + case MOTIONSENSE_TYPE_MAG:
> > > + *min_freq = 5000;
> > > + *max_freq = 25000;
> > > + break;
> > > + case MOTIONSENSE_TYPE_PROX:
> > > + case MOTIONSENSE_TYPE_LIGHT:
> > > + *min_freq = 100;
> > > + *max_freq = 5;
> > > + break;
> > > + case MOTIONSENSE_TYPE_BARO:
> > > + *min_freq = 250;
> > > + *max_freq = 2;
> > > + break;
> > > + case MOTIONSENSE_TYPE_ACTIVITY:
> > > + default:
> > > + *min_freq = 0;
> > > + *max_freq = 0;
> > > + break;
> > > + }
> > > +}
> 
> This is the second part. It adds default values for version 3. I'd
> send this
> part on the patch that adds support min/max freq.
> 
> > > +
> > > +static int cros_ec_get_host_cmd_version_mask(struct
> > > cros_ec_device *ec_dev,
> > > +  u16 cmd_offset, u16 cmd,
> > > u32 *mask)
> > > +{
> > > + int ret;
> > > + struct {
> > > + struct cros_ec_command msg;
> > > + union {
> > > + struct ec_params_get_cmd_versions params;
> > > + struct ec_response_get_cmd_versions resp;
> > > + };
> > > + } __packed buf = {
> > > + .msg = {
> > > + .command = EC_CMD_GET_CMD_VERSIONS +
> > > cmd_offset,
> > > + .insize = sizeof(struct
> > > ec_response_get_cmd_versions),
> > > + .outsize = sizeof(struct
> > > ec_params_get_cmd_versions)
> > > + },
> > > + .params = {.cmd = cmd}
> > > + };
> > > +
> 
> nit: Actually when someone is sending a command to the EC there is a
> bit of mess
> how to do it, some use dynamic al

Re: [PATCH v3 0/8] Expose cros_ec_sensors frequency range via iio sysfs

2019-06-19 Thread Fabien Lahoudere
Le mardi 18 juin 2019 à 11:06 +0200, Fabien Lahoudere a écrit :
> Chromebooks EC sensors must expose a range of frequencies for each
> sensors using
> the standard ABI sampling_frquency_available.
> 
> Changes since v2:
> 
> - use read_avail callback
> - rework core functions to avoid code duplication

- now sample-frequency-available sysfs return a list of known
frequencies instead of a range, because the step depend on sensors
(fast vs slow) and is hidden by EC.
See https://patchwork.kernel.org/patch/10957141/#22662201

> 
> Changes since v1:
> - Add a cover letter
> - Add Nick Vaccaro SoB to patch 1
> - Drop fifo size related code
> 
> Fabien Lahoudere (8):
>   iio: common: cros_ec_sensors: move iio_info management to core
>   iio: common: cros_ec_sensors: move channels to core structure
>   iio: common: cros_ec_sensors: move registration to core
>   iio: common: cros_ec_sensors: clean code
>   iio: common: cros_ec_sensors: use core structure
>   iio: common: cros_ec_sensors: support protocol v3 message
>   iio: common: cros_ec_sensors: add sysfs attribute for frequencies
>   docs: iio: add precision about sampling_frequency_available
> 
>  Documentation/ABI/testing/sysfs-bus-iio   |   7 +-
>  .../common/cros_ec_sensors/cros_ec_sensors.c  | 148 +--
>  .../cros_ec_sensors/cros_ec_sensors_core.c| 230 +++-
> --
>  drivers/iio/light/cros_ec_light_prox.c| 124 --
>  drivers/iio/pressure/cros_ec_baro.c   | 101 +++-
>  .../linux/iio/common/cros_ec_sensors_core.h   |  43 +++-
>  6 files changed, 357 insertions(+), 296 deletions(-)
> 



[PATCH v3 1/8] iio: common: cros_ec_sensors: move iio_info management to core

2019-06-18 Thread Fabien Lahoudere
In order to avoid code duplication and make future works easier,
we add an iio_info structure to cros_ec_sensors_core_state structure.

Signed-off-by: Fabien Lahoudere 
---
 drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c  | 8 ++--
 drivers/iio/common/cros_ec_sensors/cros_ec_sensors_core.c | 2 ++
 drivers/iio/light/cros_ec_light_prox.c| 8 ++--
 drivers/iio/pressure/cros_ec_baro.c   | 8 ++--
 include/linux/iio/common/cros_ec_sensors_core.h   | 1 +
 5 files changed, 9 insertions(+), 18 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..c59b0ab8fe7d 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -172,11 +172,6 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
return ret;
 }
 
-static const struct iio_info ec_sensors_info = {
-   .read_raw = _ec_sensors_read,
-   .write_raw = _ec_sensors_write,
-};
-
 static int cros_ec_sensors_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -199,7 +194,6 @@ static int cros_ec_sensors_probe(struct platform_device 
*pdev)
if (ret)
return ret;
 
-   indio_dev->info = _sensors_info;
state = iio_priv(indio_dev);
for (channel = state->channels, i = CROS_EC_SENSOR_X;
 i < CROS_EC_SENSOR_MAX_AXIS; i++, channel++) {
@@ -235,6 +229,8 @@ static int cros_ec_sensors_probe(struct platform_device 
*pdev)
return -EINVAL;
}
}
+   state->core.info.read_raw = _ec_sensors_read;
+   state->core.info.write_raw = _ec_sensors_write;
 
/* Timestamp */
channel->type = IIO_TIMESTAMP;
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..a1b324e1a5d8 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
@@ -68,6 +68,8 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
state->loc = state->resp->info.location;
}
 
+   indio_dev->info = >info;
+
return 0;
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init);
diff --git a/drivers/iio/light/cros_ec_light_prox.c 
b/drivers/iio/light/cros_ec_light_prox.c
index 308ee6ff2e22..b319d95fb70f 100644
--- a/drivers/iio/light/cros_ec_light_prox.c
+++ b/drivers/iio/light/cros_ec_light_prox.c
@@ -161,11 +161,6 @@ static int cros_ec_light_prox_write(struct iio_dev 
*indio_dev,
return ret;
 }
 
-static const struct iio_info cros_ec_light_prox_info = {
-   .read_raw = _ec_light_prox_read,
-   .write_raw = _ec_light_prox_write,
-};
-
 static int cros_ec_light_prox_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -188,10 +183,11 @@ static int cros_ec_light_prox_probe(struct 
platform_device *pdev)
if (ret)
return ret;
 
-   indio_dev->info = _ec_light_prox_info;
state = iio_priv(indio_dev);
state->core.type = state->core.resp->info.type;
state->core.loc = state->core.resp->info.location;
+   state->core.info.read_raw = _ec_light_prox_read;
+   state->core.info.write_raw = _ec_light_prox_write;
channel = state->channels;
 
/* Common part */
diff --git a/drivers/iio/pressure/cros_ec_baro.c 
b/drivers/iio/pressure/cros_ec_baro.c
index 034ce98d6e97..85a4864e3a4e 100644
--- a/drivers/iio/pressure/cros_ec_baro.c
+++ b/drivers/iio/pressure/cros_ec_baro.c
@@ -107,11 +107,6 @@ static int cros_ec_baro_write(struct iio_dev *indio_dev,
return ret;
 }
 
-static const struct iio_info cros_ec_baro_info = {
-   .read_raw = _ec_baro_read,
-   .write_raw = _ec_baro_write,
-};
-
 static int cros_ec_baro_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -134,10 +129,11 @@ static int cros_ec_baro_probe(struct platform_device 
*pdev)
if (ret)
return ret;
 
-   indio_dev->info = _ec_baro_info;
state = iio_priv(indio_dev);
state->core.type = state->core.resp->info.type;
state->core.loc = state->core.resp->info.location;
+   state->core.info.read_raw = _ec_baro_read;
+   state->core.info.write_raw = _ec_baro_write;
channel = state->channels;
/* Common part */
channel->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
diff --git a/include/linux/iio/common/cros_ec_sensors_core.h 
b/include/linux/iio/common/cros_ec_sensors_core.h
index 0c636b9fe8d7..a729e667f760 100644
--- a/include/linux/iio/common/cros_ec_sensors_core.h
+++ b/include/linux/iio/common/cros_ec_sensors_core.h
@@ -70,6 +70,7 @@ struct cros_ec_se

[PATCH v3 5/8] iio: common: cros_ec_sensors: use core structure

2019-06-18 Thread Fabien Lahoudere
Drivers based on cros_ec_sensors_core have structure containing the
core structure. In order to simplify, we drop all the specific and
useless structure to use the same one in all drivers.
If a future driver need specific field, we can add a private pointer
to that data.

Signed-off-by: Fabien Lahoudere 
---
 .../common/cros_ec_sensors/cros_ec_sensors.c  | 114 --
 .../cros_ec_sensors/cros_ec_sensors_core.c|   3 +-
 drivers/iio/light/cros_ec_light_prox.c|  85 ++---
 drivers/iio/pressure/cros_ec_baro.c   |  62 +-
 .../linux/iio/common/cros_ec_sensors_core.h   |   3 +-
 5 files changed, 121 insertions(+), 146 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 c4bee9265246..1f0d1c614ffc 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -24,58 +24,52 @@
 
 #define CROS_EC_SENSORS_MAX_CHANNELS 4
 
-/* State data for ec_sensors iio driver. */
-struct cros_ec_sensors_state {
-   /* Shared by all sensors */
-   struct cros_ec_sensors_core_state core;
-};
-
 static int cros_ec_sensors_read(struct iio_dev *indio_dev,
  struct iio_chan_spec const *chan,
  int *val, int *val2, long mask)
 {
-   struct cros_ec_sensors_state *st = iio_priv(indio_dev);
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
s16 data = 0;
s64 val64;
int i;
int ret;
int idx = chan->scan_index;
 
-   mutex_lock(>core.cmd_lock);
+   mutex_lock(>cmd_lock);
 
switch (mask) {
case IIO_CHAN_INFO_RAW:
-   ret = st->core.read_ec_sensors_data(indio_dev, 1 << idx, );
+   ret = st->read_ec_sensors_data(indio_dev, 1 << idx, );
if (ret < 0)
break;
ret = IIO_VAL_INT;
*val = data;
break;
case IIO_CHAN_INFO_CALIBBIAS:
-   st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
-   st->core.param.sensor_offset.flags = 0;
+   st->param.cmd = MOTIONSENSE_CMD_SENSOR_OFFSET;
+   st->param.sensor_offset.flags = 0;
 
-   ret = cros_ec_motion_send_host_cmd(>core, 0);
+   ret = cros_ec_motion_send_host_cmd(st, 0);
if (ret < 0)
break;
 
/* Save values */
for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++)
-   st->core.calib[i] =
-   st->core.resp->sensor_offset.offset[i];
+   st->calib[i] =
+   st->resp->sensor_offset.offset[i];
ret = IIO_VAL_INT;
-   *val = st->core.calib[idx];
+   *val = st->calib[idx];
break;
case IIO_CHAN_INFO_SCALE:
-   st->core.param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
-   st->core.param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE;
+   st->param.cmd = MOTIONSENSE_CMD_SENSOR_RANGE;
+   st->param.sensor_range.data = EC_MOTION_SENSE_NO_VALUE;
 
-   ret = cros_ec_motion_send_host_cmd(>core, 0);
+   ret = cros_ec_motion_send_host_cmd(st, 0);
if (ret < 0)
break;
 
-   val64 = st->core.resp->sensor_range.ret;
-   switch (st->core.type) {
+   val64 = st->resp->sensor_range.ret;
+   switch (st->type) {
case MOTIONSENSE_TYPE_ACCEL:
/*
 * EC returns data in g, iio exepects m/s^2.
@@ -110,11 +104,10 @@ static int cros_ec_sensors_read(struct iio_dev *indio_dev,
}
break;
default:
-   ret = cros_ec_sensors_core_read(>core, chan, val, val2,
-   mask);
+   ret = cros_ec_sensors_core_read(st, chan, val, val2, mask);
break;
}
-   mutex_unlock(>core.cmd_lock);
+   mutex_unlock(>cmd_lock);
 
return ret;
 }
@@ -123,49 +116,48 @@ static int cros_ec_sensors_write(struct iio_dev 
*indio_dev,
   struct iio_chan_spec const *chan,
   int val, int val2, long mask)
 {
-   struct cros_ec_sensors_state *st = iio_priv(indio_dev);
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
int i;
int ret;
int idx = chan->scan_index;
 
-   mutex_lock(>core.cmd_lock);
+   mutex_lock(>cmd_lock);
 
switch (mask) {
case IIO_CHAN_INFO_CALIBBIAS:
-   st->core.calib[idx] = val;
+  

[PATCH v3 2/8] iio: common: cros_ec_sensors: move channels to core structure

2019-06-18 Thread Fabien Lahoudere
To avoid code duplication, we move channels initialization in
cros_ec_sensors_core.

Signed-off-by: Fabien Lahoudere 
---
 .../common/cros_ec_sensors/cros_ec_sensors.c  | 49 ++-
 .../cros_ec_sensors/cros_ec_sensors_core.c| 25 +-
 drivers/iio/light/cros_ec_light_prox.c| 42 
 drivers/iio/pressure/cros_ec_baro.c   | 38 +++---
 .../linux/iio/common/cros_ec_sensors_core.h   | 24 -
 5 files changed, 78 insertions(+), 100 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 c59b0ab8fe7d..897dc83a3355 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -28,8 +28,6 @@
 struct cros_ec_sensors_state {
/* Shared by all sensors */
struct cros_ec_sensors_core_state core;
-
-   struct iio_chan_spec channels[CROS_EC_SENSORS_MAX_CHANNELS];
 };
 
 static int cros_ec_sensors_read(struct iio_dev *indio_dev,
@@ -178,7 +176,6 @@ static int cros_ec_sensors_probe(struct platform_device 
*pdev)
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) {
@@ -186,63 +183,49 @@ static int cros_ec_sensors_probe(struct platform_device 
*pdev)
return -EINVAL;
}
 
-   indio_dev = devm_iio_device_alloc(>dev, sizeof(*state));
-   if (!indio_dev)
-   return -ENOMEM;
-
-   ret = cros_ec_sensors_core_init(pdev, indio_dev, true);
+   ret = cros_ec_sensors_core_init(pdev, sizeof(*state),
+   CROS_EC_SENSORS_MAX_CHANNELS, true);
if (ret)
return ret;
 
+   indio_dev = platform_get_drvdata(pdev);
state = iio_priv(indio_dev);
-   for (channel = state->channels, i = CROS_EC_SENSOR_X;
-i < CROS_EC_SENSOR_MAX_AXIS; i++, channel++) {
+   for (i = CROS_EC_SENSOR_X; i < CROS_EC_SENSOR_MAX_AXIS; i++) {
/* Common part */
-   channel->info_mask_separate =
+   cros_ec_core_channel_init(state->core.channels, i + 1);
+   state->core.channels[i + 1].info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_CALIBBIAS);
-   channel->info_mask_shared_by_all =
+   state->core.channels[i + 1].info_mask_shared_by_all =
BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_FREQUENCY) |
BIT(IIO_CHAN_INFO_SAMP_FREQ);
-   channel->scan_type.realbits = CROS_EC_SENSOR_BITS;
-   channel->scan_type.storagebits = CROS_EC_SENSOR_BITS;
-   channel->scan_index = i;
-   channel->ext_info = cros_ec_sensors_ext_info;
-   channel->modified = 1;
-   channel->channel2 = IIO_MOD_X + i;
-   channel->scan_type.sign = 's';
+   state->core.channels[i + 1].scan_index = i;
+   state->core.channels[i + 1].modified = 1;
+   state->core.channels[i + 1].channel2 = IIO_MOD_X + i;
+   state->core.channels[i + 1].scan_type.sign = 's';
 
/* Sensor specific */
switch (state->core.type) {
case MOTIONSENSE_TYPE_ACCEL:
-   channel->type = IIO_ACCEL;
+   state->core.channels[i + 1].type = IIO_ACCEL;
break;
case MOTIONSENSE_TYPE_GYRO:
-   channel->type = IIO_ANGL_VEL;
+   state->core.channels[i + 1].type = IIO_ANGL_VEL;
break;
case MOTIONSENSE_TYPE_MAG:
-   channel->type = IIO_MAGN;
+   state->core.channels[i + 1].type = IIO_MAGN;
break;
default:
dev_err(>dev, "Unknown motion sensor\n");
return -EINVAL;
}
}
+   state->core.channels[0].scan_index = CROS_EC_SENSOR_MAX_AXIS;
+
state->core.info.read_raw = _ec_sensors_read;
state->core.info.write_raw = _ec_sensors_write;
 
-   /* Timestamp */
-   channel->type = IIO_TIMESTAMP;
-   channel->channel = -1;
-   channel->scan_index = CROS_EC_SENSOR_MAX_AXIS;
-   channel->scan_type.sign = 's';
-   channel->scan_type.realbits = 64;
-   channel->scan_type.storagebits = 64;
-
-   indio_dev->channels = state->channels;
-   indio_dev->num_channels = CROS_EC_SENSORS_MAX_CHANNELS;
-
/* There is only enough room for acce

[PATCH v3 3/8] iio: common: cros_ec_sensors: move registration to core

2019-06-18 Thread Fabien Lahoudere
In order to simplify derivated drivers from cros_ec_sensors_core,
a new core function is created to registered IIO stricture.

Signed-off-by: Fabien Lahoudere 
---
 .../common/cros_ec_sensors/cros_ec_sensors.c  |  9 +-
 .../cros_ec_sensors/cros_ec_sensors_core.c| 97 ---
 drivers/iio/light/cros_ec_light_prox.c|  7 +-
 drivers/iio/pressure/cros_ec_baro.c   |  7 +-
 .../linux/iio/common/cros_ec_sensors_core.h   | 16 ++-
 5 files changed, 72 insertions(+), 64 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 897dc83a3355..c4bee9265246 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -14,7 +14,7 @@
 #include 
 #include 
 #include 
-#include 
+
 #include 
 #include 
 #include 
@@ -233,12 +233,7 @@ 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);
+   return cros_ec_sensors_core_register(pdev, indio_dev);
 }
 
 static const struct platform_device_id 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 e5181e007dd7..3880849c5cca 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 
@@ -95,6 +96,67 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init);
 
+/**
+ * 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
+ */
+static irqreturn_t cros_ec_sensors_capture(int irq, void *p)
+{
+   struct iio_poll_func *pf = p;
+   struct iio_dev *indio_dev = pf->indio_dev;
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+   int ret;
+
+   mutex_lock(>cmd_lock);
+
+   /* Clear capture data. */
+   memset(st->samples, 0, indio_dev->scan_bytes);
+
+   /* Read data based on which channels are enabled in scan mask. */
+   ret = st->read_ec_sensors_data(indio_dev,
+  *indio_dev->active_scan_mask,
+  (s16 *)st->samples);
+   if (ret < 0)
+   goto done;
+
+   iio_push_to_buffers_with_timestamp(indio_dev, st->samples,
+  iio_get_time_ns(indio_dev));
+
+done:
+   /*
+* Tell the core we are done with this trigger and ready for the
+* next one.
+*/
+   iio_trigger_notify_done(indio_dev->trig);
+
+   mutex_unlock(>cmd_lock);
+
+   return IRQ_HANDLED;
+}
+
+int cros_ec_sensors_core_register(struct platform_device *pdev,
+ struct iio_dev *indio_dev)
+{
+   int ret;
+   struct device *dev = >dev;
+
+   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);
+}
+EXPORT_SYMBOL_GPL(cros_ec_sensors_core_register);
+
 int cros_ec_motion_send_host_cmd(struct cros_ec_sensors_core_state *state,
 u16 opt_length)
 {
@@ -380,41 +442,6 @@ int cros_ec_sensors_read_cmd(struct iio_dev *indio_dev,
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_read_cmd);
 
-irqreturn_t cros_ec_sensors_capture(int irq, void *p)
-{
-   struct iio_poll_func *pf = p;
-   struct iio_dev *indio_dev = pf->indio_dev;
-   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
-   int ret;
-
-   mutex_lock(>cmd_lock);
-
-   /* Clear capture data. */
-   memset(st->samples, 0, indio_dev->scan_bytes);
-
-   /* Read data based on which channels are enabled in scan mask. */
-   ret = st->read_ec_sensors_data(indio_dev,
-  *(indio_dev->active_scan_mask),
-  (s16 *)st->samples);
-   if (ret < 0)
-   goto done;
-
-   iio_push_to_buffers_with_timestamp(indio_dev, st->samples,
-

[PATCH v3 7/8] iio: common: cros_ec_sensors: add sysfs attribute for frequencies

2019-06-18 Thread Fabien Lahoudere
Embedded controller return minimum and maximum frequencies, unfortunately
we have no way to know the step for all available frequencies.
Even if not complete, we can return a list of known values using the
standard read_avail callback (IIO_CHAN_INFO_SAMP_FREQ) to provide them to
userland.

Now cros_ec_* sensors provides frequencies values in sysfs like this:
"0 min max".

0 is always true to disable the sensor.

Signed-off-by: Fabien Lahoudere 
---
 .../cros_ec_sensors/cros_ec_sensors_core.c| 22 +++
 .../linux/iio/common/cros_ec_sensors_core.h   |  4 +++-
 2 files changed, 25 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 2ce077b576a4..8df82b675752 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
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -86,6 +87,26 @@ static int cros_ec_get_host_cmd_version_mask(struct 
cros_ec_device *ec_dev,
return ret;
 }
 
+static int cros_ec_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals,
+ int *type,
+ int *length,
+ long mask)
+{
+   struct cros_ec_sensors_core_state *state = iio_priv(indio_dev);
+
+   switch (mask) {
+   case IIO_CHAN_INFO_SAMP_FREQ:
+   *length = 3;
+   *vals = (const int *)>frequency_range;
+   *type = IIO_VAL_INT;
+   return IIO_AVAIL_LIST;
+   }
+
+   return -EINVAL;
+}
+
 int cros_ec_sensors_core_init(struct platform_device *pdev,
  int num_channels,
  bool physical_device)
@@ -161,6 +182,7 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
}
}
 
+   state->info.read_avail = cros_ec_read_avail;
indio_dev->info = >info;
 
/* Timestamp channel */
diff --git a/include/linux/iio/common/cros_ec_sensors_core.h 
b/include/linux/iio/common/cros_ec_sensors_core.h
index 89937ad242ef..5fa9ba5332e0 100644
--- a/include/linux/iio/common/cros_ec_sensors_core.h
+++ b/include/linux/iio/common/cros_ec_sensors_core.h
@@ -140,7 +140,9 @@ int cros_ec_sensors_core_register(struct platform_device 
*pdev,
channel[idx].scan_type.shift = 0;\
channel[idx].scan_index = idx;\
channel[idx].ext_info = cros_ec_sensors_ext_info;\
-   channel[idx].scan_type.sign = 'u';
+   channel[idx].scan_type.sign = 'u';\
+   channel[idx].info_mask_shared_by_all_available = \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ);
 
 /**
  * cros_ec_motion_send_host_cmd() - send motion sense host command
-- 
2.20.1



[PATCH v3 6/8] iio: common: cros_ec_sensors: support protocol v3 message

2019-06-18 Thread Fabien Lahoudere
Version 3 of the EC protocol provides min and max frequencies for EC sensors.

Signed-off-by: Fabien Lahoudere 
Signed-off-by: Nick Vaccaro 
---
 .../cros_ec_sensors/cros_ec_sensors_core.c| 85 ++-
 .../linux/iio/common/cros_ec_sensors_core.h   |  3 +
 2 files changed, 87 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 57034e212fe1..2ce077b576a4 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
@@ -26,6 +26,66 @@ static char *cros_ec_loc[] = {
[MOTIONSENSE_LOC_MAX] = "unknown",
 };
 
+static void get_default_min_max_freq(enum motionsensor_type type,
+u32 *min_freq,
+u32 *max_freq)
+{
+   switch (type) {
+   case MOTIONSENSE_TYPE_ACCEL:
+   case MOTIONSENSE_TYPE_GYRO:
+   *min_freq = 12500;
+   *max_freq = 10;
+   break;
+   case MOTIONSENSE_TYPE_MAG:
+   *min_freq = 5000;
+   *max_freq = 25000;
+   break;
+   case MOTIONSENSE_TYPE_PROX:
+   case MOTIONSENSE_TYPE_LIGHT:
+   *min_freq = 100;
+   *max_freq = 5;
+   break;
+   case MOTIONSENSE_TYPE_BARO:
+   *min_freq = 250;
+   *max_freq = 2;
+   break;
+   case MOTIONSENSE_TYPE_ACTIVITY:
+   default:
+   *min_freq = 0;
+   *max_freq = 0;
+   break;
+   }
+}
+
+static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev,
+u16 cmd_offset, u16 cmd, u32 *mask)
+{
+   int ret;
+   struct {
+   struct cros_ec_command msg;
+   union {
+   struct ec_params_get_cmd_versions params;
+   struct ec_response_get_cmd_versions resp;
+   };
+   } __packed buf = {
+   .msg = {
+   .command = EC_CMD_GET_CMD_VERSIONS + cmd_offset,
+   .insize = sizeof(struct ec_response_get_cmd_versions),
+   .outsize = sizeof(struct ec_params_get_cmd_versions)
+   },
+   .params = {.cmd = cmd}
+   };
+
+   ret = cros_ec_cmd_xfer_status(ec_dev, );
+   if (ret >= 0) {
+   if (buf.msg.result == EC_RES_SUCCESS)
+   *mask = buf.resp.version_mask;
+   else
+   *mask = 0;
+   }
+   return ret;
+}
+
 int cros_ec_sensors_core_init(struct platform_device *pdev,
  int num_channels,
  bool physical_device)
@@ -35,6 +95,8 @@ 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);
struct iio_dev *indio_dev;
+   u32 ver_mask;
+   int ret;
 
if (num_channels > CROS_EC_SENSORS_CORE_MAX_CHANNELS)
return -EINVAL;
@@ -57,8 +119,16 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
 
mutex_init(>cmd_lock);
 
+   /* determine what version of MOTIONSENSE CMD EC has */
+   ret = cros_ec_get_host_cmd_version_mask(state->ec,
+   ec->cmd_offset,
+   EC_CMD_MOTION_SENSE_CMD,
+   _mask);
+   if (ret < 0 || ver_mask == 0)
+   return -ENODEV;
+
/* Set up the host command structure. */
-   state->msg->version = 2;
+   state->msg->version = fls(ver_mask) - 1;
state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
state->msg->outsize = sizeof(struct ec_params_motion_sense);
 
@@ -76,6 +146,19 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
}
state->type = state->resp->info.type;
state->loc = state->resp->info.location;
+
+   /* Value to stop the device */
+   state->frequency_range[0] = 0;
+   if (state->msg->version < 3) {
+   get_default_min_max_freq(state->resp->info.type,
+>frequency_range[1],
+>frequency_range[2]);
+   } else {
+   state->frequency_range[1] =
+   state->resp->info_3.min_frequency;
+   state->frequency_range[2] =
+   state->resp->info_3.max_frequency;
+   

[PATCH v3 8/8] docs: iio: add precision about sampling_frequency_available

2019-06-18 Thread Fabien Lahoudere
The documentation give some exemple on what format can be expected
from sampling_frequency_available sysfs attribute

Signed-off-by: Fabien Lahoudere 
---
 Documentation/ABI/testing/sysfs-bus-iio | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-iio 
b/Documentation/ABI/testing/sysfs-bus-iio
index 6aef7dbbde44..680451695422 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -61,8 +61,11 @@ What:
/sys/bus/iio/devices/triggerX/sampling_frequency_available
 KernelVersion: 2.6.35
 Contact:   linux-...@vger.kernel.org
 Description:
-   When the internal sampling clock can only take a small
-   discrete set of values, this file lists those available.
+   When the internal sampling clock can only take a specific set of
+   frequencies, we can specify the available values with:
+   - a small discrete set of values like "0 2 4 6 8"
+   - a range with minimum, step and maximum frequencies like
+ "[min step max]"
 
 What:  /sys/bus/iio/devices/iio:deviceX/oversampling_ratio
 KernelVersion: 2.6.38
-- 
2.20.1



[PATCH v3 0/8] Expose cros_ec_sensors frequency range via iio sysfs

2019-06-18 Thread Fabien Lahoudere
Chromebooks EC sensors must expose a range of frequencies for each sensors using
the standard ABI sampling_frquency_available.

Changes since v2:

- use read_avail callback
- rework core functions to avoid code duplication

Changes since v1:
- Add a cover letter
- Add Nick Vaccaro SoB to patch 1
- Drop fifo size related code

Fabien Lahoudere (8):
  iio: common: cros_ec_sensors: move iio_info management to core
  iio: common: cros_ec_sensors: move channels to core structure
  iio: common: cros_ec_sensors: move registration to core
  iio: common: cros_ec_sensors: clean code
  iio: common: cros_ec_sensors: use core structure
  iio: common: cros_ec_sensors: support protocol v3 message
  iio: common: cros_ec_sensors: add sysfs attribute for frequencies
  docs: iio: add precision about sampling_frequency_available

 Documentation/ABI/testing/sysfs-bus-iio   |   7 +-
 .../common/cros_ec_sensors/cros_ec_sensors.c  | 148 +--
 .../cros_ec_sensors/cros_ec_sensors_core.c| 230 +++---
 drivers/iio/light/cros_ec_light_prox.c| 124 --
 drivers/iio/pressure/cros_ec_baro.c   | 101 +++-
 .../linux/iio/common/cros_ec_sensors_core.h   |  43 +++-
 6 files changed, 357 insertions(+), 296 deletions(-)

-- 
2.20.1



[PATCH v3 4/8] iio: common: cros_ec_sensors: clean code

2019-06-18 Thread Fabien Lahoudere
Drop redundant initialization previously set in cros_ec_sensors_init

Signed-off-by: Fabien Lahoudere 
---
 drivers/iio/light/cros_ec_light_prox.c | 2 --
 drivers/iio/pressure/cros_ec_baro.c| 2 --
 2 files changed, 4 deletions(-)

diff --git a/drivers/iio/light/cros_ec_light_prox.c 
b/drivers/iio/light/cros_ec_light_prox.c
index 682dc19c2bf3..73f5dcbda0d5 100644
--- a/drivers/iio/light/cros_ec_light_prox.c
+++ b/drivers/iio/light/cros_ec_light_prox.c
@@ -179,8 +179,6 @@ static int cros_ec_light_prox_probe(struct platform_device 
*pdev)
 
indio_dev = platform_get_drvdata(pdev);
state = iio_priv(indio_dev);
-   state->core.type = state->core.resp->info.type;
-   state->core.loc = state->core.resp->info.location;
state->core.info.read_raw = _ec_light_prox_read;
state->core.info.write_raw = _ec_light_prox_write;
 
diff --git a/drivers/iio/pressure/cros_ec_baro.c 
b/drivers/iio/pressure/cros_ec_baro.c
index 9d3745bc2fba..f8107a8b8e72 100644
--- a/drivers/iio/pressure/cros_ec_baro.c
+++ b/drivers/iio/pressure/cros_ec_baro.c
@@ -125,8 +125,6 @@ static int cros_ec_baro_probe(struct platform_device *pdev)
 
indio_dev = platform_get_drvdata(pdev);
state = iio_priv(indio_dev);
-   state->core.type = state->core.resp->info.type;
-   state->core.loc = state->core.resp->info.location;
state->core.info.read_raw = _ec_baro_read;
state->core.info.write_raw = _ec_baro_write;
 
-- 
2.20.1



Re: [PATCH v2 1/3] iio: common: cros_ec_sensors: support protocol v3 message

2019-06-12 Thread Fabien Lahoudere
Le mercredi 12 juin 2019 à 09:42 +0100, Lee Jones a écrit :
> On Thu, 23 May 2019, Fabien Lahoudere wrote:
> 
> > Version 3 of the EC protocol provides min and max frequencies and
> > fifo
> > size for EC sensors.
> > 
> > Signed-off-by: Fabien Lahoudere 
> > Signed-off-by: Nick Vaccaro 
> > ---
> >  .../cros_ec_sensors/cros_ec_sensors_core.c| 83
> > ++-
> >  .../linux/iio/common/cros_ec_sensors_core.h   |  4 +
> >  include/linux/mfd/cros_ec_commands.h  | 21 +
> 
> There have been many changes to this file recently.  We will have to
> co-ordinate the merge.
> 
> But for now:
> 
> For my own reference:
>   Acked-for-MFD-by: Lee Jones 
> 

Yes I see the changes and my next submission will use recent patch and
drop my modification in cros_ec_commands.h.

Thanks for reviewing




Re: [PATCH v2 2/3] iio: common: cros_ec_sensors: add sysfs attribute for frequencies

2019-06-04 Thread Fabien Lahoudere
Le mardi 28 mai 2019 à 04:04 -0700, Gwendal Grignou a écrit :
> On Mon, May 27, 2019 at 2:55 AM Fabien Lahoudere
>  wrote:
> > Le dimanche 26 mai 2019 à 18:45 +0100, Jonathan Cameron a écrit :
> > > On Thu, 23 May 2019 11:07:36 +0200
> > > Fabien Lahoudere  wrote:
> > > 
> > > > In order to provide minimum and maximum frequencies for each
> > > > sensors,
> > > > we use a standard API (sampling_frequency_available) to provide
> > > > them
> > > > to userland.
> > > > As cros_ec_sensors_core_init do not manage default attrs, we
> > > > change
> > > > the signature to let all kind of sensors to provide "struct
> > > > iio_info"
> > > > with their callback. This change impact drivers using that
> > > > function.
> > > > 
> > > > Then cros_ec_* sensors provides frequencies range in sysfs like
> > > > this:
> > > > [min step max]
> > > > 
> > > > Signed-off-by: Fabien Lahoudere  > > > >
> > > When I was pointing at the _available syntax I was meaning that
> > > the ideal is to implement this using the associated callbacks
> > > rather
> > > than as a custom sysfs attribute.
> > > 
> > 
> > Sorry, I misunderstood. Let me retry with that callback
> > implemented.
> > 
> > > > ---
> > > >  .../common/cros_ec_sensors/cros_ec_sensors.c  |  6 +--
> > > >  .../cros_ec_sensors/cros_ec_sensors_core.c| 38
> > > > +++
> > > >  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, 50 insertions(+), 10 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..a0ecee15a6c8 100644
> > > > --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> > > > +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> > > > @@ -172,7 +172,7 @@ static int cros_ec_sensors_write(struct
> > > > iio_dev
> > > > *indio_dev,
> > > > return ret;
> > > >  }
> > > > 
> > > > -static const struct iio_info ec_sensors_info = {
> > > > +static struct iio_info ec_sensors_info = {
> > > > .read_raw = _ec_sensors_read,
> > > > .write_raw = _ec_sensors_write,
> > > >  };
> > > > @@ -195,11 +195,11 @@ 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,
> > > > _sensors_info,
> > > > +   true);
> > > > if (ret)
> > > > return ret;
> > > > 
> > > > -   indio_dev->info = _sensors_info;
> > > > state = iio_priv(indio_dev);
> > > > for (channel = state->channels, i = CROS_EC_SENSOR_X;
> > > >  i < CROS_EC_SENSOR_MAX_AXIS; i++, 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 ac53ea32c1b1..08fb5d3dc7b5 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
> > > > @@ -10,6 +10,7 @@
> > > >  #include 
> > > >  #include 
> > > >  #include 
> > > > +#include 
> > > >  #include 
> > > >  #include 
> > > >  #include 
> > > > @@ -86,8 +87,42 @@ static int
> > > > cros_ec_get_host_cmd_version_mask(struct cros_ec_device
> > > > *ec_dev,
> > > > return ret;
> > > >  }
> > > > 
> > > > +/**
> > > > + * cros_ec_sensors_read_freq() - sysfs function to get
> > > > available
> > > > frequencies
> > > > + * @dev: Device structure for this device.
> > > > + * @attr: Description of the attribute.
&g

Re: [PATCH 1/3] iio: common: cros_ec_sensors: support protocol v3 message

2019-06-04 Thread Fabien Lahoudere
Le lundi 03 juin 2019 à 13:55 +0100, Lee Jones a écrit :
> On Wed, 22 May 2019, Fabien Lahoudere wrote:
> 
> > Version 3 of the EC protocol provides min and max frequencies and
> > fifo
> > size for EC sensors.
> > 
> > Signed-off-by: Fabien Lahoudere 
> > ---
> >  .../cros_ec_sensors/cros_ec_sensors_core.c| 98
> > ++-
> >  .../linux/iio/common/cros_ec_sensors_core.h   |  7 ++
> >  include/linux/mfd/cros_ec_commands.h  | 21 
> 
> Please note that we are about to add a pretty bit update for this
> file.  Once it's complete you may wish to rebase in order to avoid
> any possible merge conflicts.
> 

Thanks Lee. Indeed I see and reviewed this 30 patches series.
I am waiting they are applied to rebase ans submit v3.

> >  3 files changed, 125 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 719a0df5aeeb..d5c8b4714ad6 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
> > @@ -19,12 +19,84 @@
> >  #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",
> > [MOTIONSENSE_LOC_MAX] = "unknown",
> >  };
> >  
> > +static void get_default_min_max_freq_and_fifo_size(enum
> > motionsensor_type type,
> > +  u32 *min_freq,
> > +  u32 *max_freq,
> > +  u32
> > *max_fifo_events)
> > +{
> > +   /* we don't know fifo size, set to size previously used by
> > sensor HAL */
> > +   *max_fifo_events = CROS_EC_FIFO_SIZE;
> > +
> > +   switch (type) {
> > +   case MOTIONSENSE_TYPE_ACCEL:
> > +   case MOTIONSENSE_TYPE_GYRO:
> > +   *min_freq = 12500;
> > +   *max_freq = 10;
> > +   break;
> > +   case MOTIONSENSE_TYPE_MAG:
> > +   *min_freq = 5000;
> > +   *max_freq = 25000;
> > +   break;
> > +   case MOTIONSENSE_TYPE_PROX:
> > +   case MOTIONSENSE_TYPE_LIGHT:
> > +   *min_freq = 100;
> > +   *max_freq = 5;
> > +   break;
> > +   case MOTIONSENSE_TYPE_BARO:
> > +   *min_freq = 250;
> > +   *max_freq = 2;
> > +   break;
> > +   case MOTIONSENSE_TYPE_ACTIVITY:
> > +   default:
> > +   *max_fifo_events = 0;
> > +   *min_freq = 0;
> > +   *max_freq = 0;
> > +   break;
> > +   }
> > +}
> > +
> > +static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device
> > *ec_dev,
> > +u16 cmd_offset, u16 cmd,
> > u32 *mask)
> > +{
> > +   struct {
> > +   struct cros_ec_command msg;
> > +   union {
> > +   struct ec_params_get_cmd_versions params;
> > +   struct ec_response_get_cmd_versions resp;
> > +   };
> > +   } __packed buf;
> > +   struct ec_params_get_cmd_versions *params = 
> > +   struct ec_response_get_cmd_versions *resp = 
> > +   struct cros_ec_command *msg = 
> > +   int ret;
> > +
> > +   memset(, 0, sizeof(buf));
> > +   msg->command = EC_CMD_GET_CMD_VERSIONS + cmd_offset;
> > +   msg->insize = sizeof(*resp);
> > +   msg->outsize = sizeof(*params);
> > +   params->cmd = cmd;
> > +   ret = cros_ec_cmd_xfer_status(ec_dev, msg);
> > +   if (ret >= 0) {
> > +   if (msg->result == EC_RES_SUCCESS)
> > +   *mask = resp->version_mask;
> > +   else
> > +   *mask = 0;
> > +   }
> > +   return ret;
> > +}
> > +
> >  int cros_ec_sensors_core_init(struct platform_device *pdev,
> >   struct iio_dev *indio_dev,
> >   bool physical_device)
> > @@ -33,6 +105,8 @@ int cros_ec_sensors_core_init(struct
> > platform_device *pdev,
> > struct cros_ec_sensors_core_state *state 

Re: [PATCH v2 2/3] iio: common: cros_ec_sensors: add sysfs attribute for frequencies

2019-05-27 Thread Fabien Lahoudere
Le dimanche 26 mai 2019 à 18:45 +0100, Jonathan Cameron a écrit :
> On Thu, 23 May 2019 11:07:36 +0200
> Fabien Lahoudere  wrote:
> 
> > In order to provide minimum and maximum frequencies for each
> > sensors,
> > we use a standard API (sampling_frequency_available) to provide
> > them
> > to userland.
> > As cros_ec_sensors_core_init do not manage default attrs, we change
> > the signature to let all kind of sensors to provide "struct
> > iio_info"
> > with their callback. This change impact drivers using that
> > function.
> > 
> > Then cros_ec_* sensors provides frequencies range in sysfs like
> > this:
> > [min step max]
> > 
> > Signed-off-by: Fabien Lahoudere 
> When I was pointing at the _available syntax I was meaning that
> the ideal is to implement this using the associated callbacks rather
> than as a custom sysfs attribute.
> 

Sorry, I misunderstood. Let me retry with that callback implemented.

> > ---
> >  .../common/cros_ec_sensors/cros_ec_sensors.c  |  6 +--
> >  .../cros_ec_sensors/cros_ec_sensors_core.c| 38
> > +++
> >  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, 50 insertions(+), 10 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..a0ecee15a6c8 100644
> > --- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> > +++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
> > @@ -172,7 +172,7 @@ static int cros_ec_sensors_write(struct iio_dev
> > *indio_dev,
> > return ret;
> >  }
> >  
> > -static const struct iio_info ec_sensors_info = {
> > +static struct iio_info ec_sensors_info = {
> > .read_raw = _ec_sensors_read,
> > .write_raw = _ec_sensors_write,
> >  };
> > @@ -195,11 +195,11 @@ 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,
> > _sensors_info,
> > +   true);
> > if (ret)
> > return ret;
> >  
> > -   indio_dev->info = _sensors_info;
> > state = iio_priv(indio_dev);
> > for (channel = state->channels, i = CROS_EC_SENSOR_X;
> >  i < CROS_EC_SENSOR_MAX_AXIS; i++, 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 ac53ea32c1b1..08fb5d3dc7b5 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
> > @@ -10,6 +10,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -86,8 +87,42 @@ static int
> > cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev,
> > return ret;
> >  }
> >  
> > +/**
> > + * cros_ec_sensors_read_freq() - sysfs function to get available
> > frequencies
> > + * @dev: Device structure for this device.
> > + * @attr: Description of the attribute.
> > + * @buf: Incoming string
> > + *
> > + * The later modes are only relevant to the ring buffer - and
> > depend on current
> > + * mode. Note that data sheet gives rather wide tolerances for
> > these so integer
> > + * division will give good enough answer and not all chips have
> > them specified
> > + * at all.
> > + **/
> > +static ssize_t cros_ec_sensors_read_freq(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 *state = iio_priv(indio_dev);
> > +
> > +   return snprintf(buf, PAGE_SIZE, "[%d 1 %d]\n", state->min_freq,
> > +   state->max_freq);
> Whilst it is a bit more fiddly I would much prefer if this was done
> with
> the info_mask_shared_by_all_available bit mask in the iio_dev and
> providing
> the read_avail callback.
> 
> The original reason to introduce this form was as part of trying to
&

[PATCH v2 3/3] docs: iio: add precision about sampling_frequency_available

2019-05-23 Thread Fabien Lahoudere
The documentation give some exemple on what format can be expected
from sampling_frequency_available sysfs attribute

Signed-off-by: Fabien Lahoudere 
---
 Documentation/ABI/testing/sysfs-bus-iio | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-iio 
b/Documentation/ABI/testing/sysfs-bus-iio
index 6aef7dbbde44..680451695422 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -61,8 +61,11 @@ What:
/sys/bus/iio/devices/triggerX/sampling_frequency_available
 KernelVersion: 2.6.35
 Contact:   linux-...@vger.kernel.org
 Description:
-   When the internal sampling clock can only take a small
-   discrete set of values, this file lists those available.
+   When the internal sampling clock can only take a specific set of
+   frequencies, we can specify the available values with:
+   - a small discrete set of values like "0 2 4 6 8"
+   - a range with minimum, step and maximum frequencies like
+ "[min step max]"
 
 What:  /sys/bus/iio/devices/iio:deviceX/oversampling_ratio
 KernelVersion: 2.6.38
-- 
2.20.1



[PATCH v2 1/3] iio: common: cros_ec_sensors: support protocol v3 message

2019-05-23 Thread Fabien Lahoudere
Version 3 of the EC protocol provides min and max frequencies and fifo
size for EC sensors.

Signed-off-by: Fabien Lahoudere 
Signed-off-by: Nick Vaccaro 
---
 .../cros_ec_sensors/cros_ec_sensors_core.c| 83 ++-
 .../linux/iio/common/cros_ec_sensors_core.h   |  4 +
 include/linux/mfd/cros_ec_commands.h  | 21 +
 3 files changed, 107 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 719a0df5aeeb..ac53ea32c1b1 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
@@ -25,6 +25,67 @@ static char *cros_ec_loc[] = {
[MOTIONSENSE_LOC_MAX] = "unknown",
 };
 
+static void get_default_min_max_freq(enum motionsensor_type type,
+u32 *min_freq,
+u32 *max_freq)
+{
+   switch (type) {
+   case MOTIONSENSE_TYPE_ACCEL:
+   case MOTIONSENSE_TYPE_GYRO:
+   *min_freq = 12500;
+   *max_freq = 10;
+   break;
+   case MOTIONSENSE_TYPE_MAG:
+   *min_freq = 5000;
+   *max_freq = 25000;
+   break;
+   case MOTIONSENSE_TYPE_PROX:
+   case MOTIONSENSE_TYPE_LIGHT:
+   *min_freq = 100;
+   *max_freq = 5;
+   break;
+   case MOTIONSENSE_TYPE_BARO:
+   *min_freq = 250;
+   *max_freq = 2;
+   break;
+   case MOTIONSENSE_TYPE_ACTIVITY:
+   default:
+   *min_freq = 0;
+   *max_freq = 0;
+   break;
+   }
+}
+
+static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev,
+u16 cmd_offset, u16 cmd, u32 *mask)
+{
+   struct {
+   struct cros_ec_command msg;
+   union {
+   struct ec_params_get_cmd_versions params;
+   struct ec_response_get_cmd_versions resp;
+   };
+   } __packed buf;
+   struct ec_params_get_cmd_versions *params = 
+   struct ec_response_get_cmd_versions *resp = 
+   struct cros_ec_command *msg = 
+   int ret;
+
+   memset(, 0, sizeof(buf));
+   msg->command = EC_CMD_GET_CMD_VERSIONS + cmd_offset;
+   msg->insize = sizeof(*resp);
+   msg->outsize = sizeof(*params);
+   params->cmd = cmd;
+   ret = cros_ec_cmd_xfer_status(ec_dev, msg);
+   if (ret >= 0) {
+   if (msg->result == EC_RES_SUCCESS)
+   *mask = resp->version_mask;
+   else
+   *mask = 0;
+   }
+   return ret;
+}
+
 int cros_ec_sensors_core_init(struct platform_device *pdev,
  struct iio_dev *indio_dev,
  bool physical_device)
@@ -33,6 +94,8 @@ 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);
+   u32 ver_mask;
+   int ret;
 
platform_set_drvdata(pdev, indio_dev);
 
@@ -47,8 +110,16 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
 
mutex_init(>cmd_lock);
 
+   /* determine what version of MOTIONSENSE CMD EC has */
+   ret = cros_ec_get_host_cmd_version_mask(state->ec,
+   ec->cmd_offset,
+   EC_CMD_MOTION_SENSE_CMD,
+   _mask);
+   if (ret < 0 || ver_mask == 0)
+   return -ENODEV;
+
/* Set up the host command structure. */
-   state->msg->version = 2;
+   state->msg->version = fls(ver_mask) - 1;
state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
state->msg->outsize = sizeof(struct ec_params_motion_sense);
 
@@ -66,6 +137,16 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
}
state->type = state->resp->info.type;
state->loc = state->resp->info.location;
+   if (state->msg->version < 3) {
+   get_default_min_max_freq(state->resp->info.type,
+>min_freq,
+>max_freq);
+   } else {
+   state->min_freq =
+   state->resp->info_3.min_frequency;
+   state->max_freq =
+   state->resp->info_3.max_frequency;
+   }
}
 
return 0;

[PATCH v2 2/3] iio: common: cros_ec_sensors: add sysfs attribute for frequencies

2019-05-23 Thread Fabien Lahoudere
In order to provide minimum and maximum frequencies for each sensors,
we use a standard API (sampling_frequency_available) to provide them
to userland.
As cros_ec_sensors_core_init do not manage default attrs, we change
the signature to let all kind of sensors to provide "struct iio_info"
with their callback. This change impact drivers using that function.

Then cros_ec_* sensors provides frequencies range in sysfs like this:
[min step max]

Signed-off-by: Fabien Lahoudere 
---
 .../common/cros_ec_sensors/cros_ec_sensors.c  |  6 +--
 .../cros_ec_sensors/cros_ec_sensors_core.c| 38 +++
 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, 50 insertions(+), 10 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..a0ecee15a6c8 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -172,7 +172,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
return ret;
 }
 
-static const struct iio_info ec_sensors_info = {
+static struct iio_info ec_sensors_info = {
.read_raw = _ec_sensors_read,
.write_raw = _ec_sensors_write,
 };
@@ -195,11 +195,11 @@ 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, _sensors_info,
+   true);
if (ret)
return ret;
 
-   indio_dev->info = _sensors_info;
state = iio_priv(indio_dev);
for (channel = state->channels, i = CROS_EC_SENSOR_X;
 i < CROS_EC_SENSOR_MAX_AXIS; i++, 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 ac53ea32c1b1..08fb5d3dc7b5 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
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -86,8 +87,42 @@ static int cros_ec_get_host_cmd_version_mask(struct 
cros_ec_device *ec_dev,
return ret;
 }
 
+/**
+ * cros_ec_sensors_read_freq() - sysfs function to get available frequencies
+ * @dev: Device structure for this device.
+ * @attr: Description of the attribute.
+ * @buf: Incoming string
+ *
+ * The later modes are only relevant to the ring buffer - and depend on current
+ * mode. Note that data sheet gives rather wide tolerances for these so integer
+ * division will give good enough answer and not all chips have them specified
+ * at all.
+ **/
+static ssize_t cros_ec_sensors_read_freq(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 *state = iio_priv(indio_dev);
+
+   return snprintf(buf, PAGE_SIZE, "[%d 1 %d]\n", state->min_freq,
+   state->max_freq);
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(cros_ec_sensors_read_freq);
+
+static struct attribute *cros_ec_sensors_attributes[] = {
+   _dev_attr_sampling_frequency_available.dev_attr.attr,
+   NULL,
+};
+
+static const struct attribute_group cros_ec_sensors_attribute_group = {
+   .attrs = cros_ec_sensors_attributes,
+};
+
 int cros_ec_sensors_core_init(struct platform_device *pdev,
  struct iio_dev *indio_dev,
+ struct iio_info *info,
  bool physical_device)
 {
struct device *dev = >dev;
@@ -149,6 +184,9 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
}
}
 
+   info->attrs = _ec_sensors_attribute_group;
+   indio_dev->info = info;
+
return 0;
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init);
diff --git a/drivers/iio/light/cros_ec_light_prox.c 
b/drivers/iio/light/cros_ec_light_prox.c
index 308ee6ff2e22..1772e339cf14 100644
--- a/drivers/iio/light/cros_ec_light_prox.c
+++ b/drivers/iio/light/cros_ec_light_prox.c
@@ -161,7 +161,7 @@ static int cros_ec_light_prox_write(struct iio_dev 
*indio_dev,
return ret;
 }
 
-static const struct iio_info cros_ec_light_prox_info = {
+static struct iio_info cros_ec_light_prox_info = {
.read_raw = _ec_light_prox_read,
.write_raw = _ec_light_prox_write,
 };
@@ -184,11 +184,11 @@ static int cros_ec_light_prox_probe(struct 
platform_device *pdev)
if (!indio_dev)
return -ENOMEM;
 
-   ret = cros_ec_sensors_c

[PATCH v2 0/3] Expose cros_ec_sensors frequency range via iio sysfs

2019-05-23 Thread Fabien Lahoudere
Chromebooks EC sensors must expose a range of frequencies for each sensors using
the standard ABI sampling_frquency_available.

Changes since v1:
- Add a cover letter
- Add Nick Vaccaro SoB to patch 1
- Drop fifo size related code

Fabien Lahoudere (3):
  iio: common: cros_ec_sensors: support protocol v3 message
  iio: common: cros_ec_sensors: add sysfs attribute for frequencies
  docs: iio: add precision about sampling_frequency_available

 Documentation/ABI/testing/sysfs-bus-iio   |   7 +-
 .../common/cros_ec_sensors/cros_ec_sensors.c  |   6 +-
 .../cros_ec_sensors/cros_ec_sensors_core.c| 121 +-
 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   |   8 +-
 include/linux/mfd/cros_ec_commands.h  |  21 +++
 7 files changed, 162 insertions(+), 13 deletions(-)

-- 
2.20.1



[PATCH 1/3] iio: common: cros_ec_sensors: support protocol v3 message

2019-05-22 Thread Fabien Lahoudere
Version 3 of the EC protocol provides min and max frequencies and fifo
size for EC sensors.

Signed-off-by: Fabien Lahoudere 
---
 .../cros_ec_sensors/cros_ec_sensors_core.c| 98 ++-
 .../linux/iio/common/cros_ec_sensors_core.h   |  7 ++
 include/linux/mfd/cros_ec_commands.h  | 21 
 3 files changed, 125 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 719a0df5aeeb..d5c8b4714ad6 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
@@ -19,12 +19,84 @@
 #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",
[MOTIONSENSE_LOC_MAX] = "unknown",
 };
 
+static void get_default_min_max_freq_and_fifo_size(enum motionsensor_type type,
+  u32 *min_freq,
+  u32 *max_freq,
+  u32 *max_fifo_events)
+{
+   /* we don't know fifo size, set to size previously used by sensor HAL */
+   *max_fifo_events = CROS_EC_FIFO_SIZE;
+
+   switch (type) {
+   case MOTIONSENSE_TYPE_ACCEL:
+   case MOTIONSENSE_TYPE_GYRO:
+   *min_freq = 12500;
+   *max_freq = 10;
+   break;
+   case MOTIONSENSE_TYPE_MAG:
+   *min_freq = 5000;
+   *max_freq = 25000;
+   break;
+   case MOTIONSENSE_TYPE_PROX:
+   case MOTIONSENSE_TYPE_LIGHT:
+   *min_freq = 100;
+   *max_freq = 5;
+   break;
+   case MOTIONSENSE_TYPE_BARO:
+   *min_freq = 250;
+   *max_freq = 2;
+   break;
+   case MOTIONSENSE_TYPE_ACTIVITY:
+   default:
+   *max_fifo_events = 0;
+   *min_freq = 0;
+   *max_freq = 0;
+   break;
+   }
+}
+
+static int cros_ec_get_host_cmd_version_mask(struct cros_ec_device *ec_dev,
+u16 cmd_offset, u16 cmd, u32 *mask)
+{
+   struct {
+   struct cros_ec_command msg;
+   union {
+   struct ec_params_get_cmd_versions params;
+   struct ec_response_get_cmd_versions resp;
+   };
+   } __packed buf;
+   struct ec_params_get_cmd_versions *params = 
+   struct ec_response_get_cmd_versions *resp = 
+   struct cros_ec_command *msg = 
+   int ret;
+
+   memset(, 0, sizeof(buf));
+   msg->command = EC_CMD_GET_CMD_VERSIONS + cmd_offset;
+   msg->insize = sizeof(*resp);
+   msg->outsize = sizeof(*params);
+   params->cmd = cmd;
+   ret = cros_ec_cmd_xfer_status(ec_dev, msg);
+   if (ret >= 0) {
+   if (msg->result == EC_RES_SUCCESS)
+   *mask = resp->version_mask;
+   else
+   *mask = 0;
+   }
+   return ret;
+}
+
 int cros_ec_sensors_core_init(struct platform_device *pdev,
  struct iio_dev *indio_dev,
  bool physical_device)
@@ -33,6 +105,8 @@ 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);
+   u32 ver_mask;
+   int ret;
 
platform_set_drvdata(pdev, indio_dev);
 
@@ -47,8 +121,16 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
 
mutex_init(>cmd_lock);
 
+   /* determine what version of MOTIONSENSE CMD EC has */
+   ret = cros_ec_get_host_cmd_version_mask(state->ec,
+   ec->cmd_offset,
+   EC_CMD_MOTION_SENSE_CMD,
+   _mask);
+   if (ret < 0 || ver_mask == 0)
+   return -ENODEV;
+
/* Set up the host command structure. */
-   state->msg->version = 2;
+   state->msg->version = fls(ver_mask) - 1;
state->msg->command = EC_CMD_MOTION_SENSE_CMD + ec->cmd_offset;
state->msg->outsize = sizeof(struct ec_params_motion_sense);
 
@@ -66,6 +148,20 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
}
state->type = state->resp->info.type

[PATCH 3/3] docs: iio: add precision about sampling_frequency_available

2019-05-22 Thread Fabien Lahoudere
The documentation give some exemple on what format can be expected
from sampling_frequency_available sysfs attribute

Signed-off-by: Fabien Lahoudere 
---
 Documentation/ABI/testing/sysfs-bus-iio | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-iio 
b/Documentation/ABI/testing/sysfs-bus-iio
index 6aef7dbbde44..680451695422 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -61,8 +61,11 @@ What:
/sys/bus/iio/devices/triggerX/sampling_frequency_available
 KernelVersion: 2.6.35
 Contact:   linux-...@vger.kernel.org
 Description:
-   When the internal sampling clock can only take a small
-   discrete set of values, this file lists those available.
+   When the internal sampling clock can only take a specific set of
+   frequencies, we can specify the available values with:
+   - a small discrete set of values like "0 2 4 6 8"
+   - a range with minimum, step and maximum frequencies like
+ "[min step max]"
 
 What:  /sys/bus/iio/devices/iio:deviceX/oversampling_ratio
 KernelVersion: 2.6.38
-- 
2.20.1



[PATCH 2/3] iio: common: cros_ec_sensors: add sysfs attribute for frequencies

2019-05-22 Thread Fabien Lahoudere
In order to provide minimum and maximum frequencies for each sensors,
we use a standard API (sampling_frequency_available) to provide them
to userland.
As cros_ec_sensors_core_init do not manage default attrs, we change
the signature to let all kind of sensors to provide "struct iio_info"
with their callback. This change impact drivers using that function.

Then cros_ec_* sensors provides frequencies range in sysfs like this:
[min step max]

Signed-off-by: Fabien Lahoudere 
---
 .../common/cros_ec_sensors/cros_ec_sensors.c  |  6 +--
 .../cros_ec_sensors/cros_ec_sensors_core.c| 38 +++
 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, 50 insertions(+), 10 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..a0ecee15a6c8 100644
--- a/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
+++ b/drivers/iio/common/cros_ec_sensors/cros_ec_sensors.c
@@ -172,7 +172,7 @@ static int cros_ec_sensors_write(struct iio_dev *indio_dev,
return ret;
 }
 
-static const struct iio_info ec_sensors_info = {
+static struct iio_info ec_sensors_info = {
.read_raw = _ec_sensors_read,
.write_raw = _ec_sensors_write,
 };
@@ -195,11 +195,11 @@ 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, _sensors_info,
+   true);
if (ret)
return ret;
 
-   indio_dev->info = _sensors_info;
state = iio_priv(indio_dev);
for (channel = state->channels, i = CROS_EC_SENSOR_X;
 i < CROS_EC_SENSOR_MAX_AXIS; i++, 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 d5c8b4714ad6..2c2a608a10ec 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
@@ -10,6 +10,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -97,8 +98,42 @@ static int cros_ec_get_host_cmd_version_mask(struct 
cros_ec_device *ec_dev,
return ret;
 }
 
+/**
+ * cros_ec_sensors_read_freq() - sysfs function to get available frequencies
+ * @dev: Device structure for this device.
+ * @attr: Description of the attribute.
+ * @buf: Incoming string
+ *
+ * The later modes are only relevant to the ring buffer - and depend on current
+ * mode. Note that data sheet gives rather wide tolerances for these so integer
+ * division will give good enough answer and not all chips have them specified
+ * at all.
+ **/
+static ssize_t cros_ec_sensors_read_freq(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 *state = iio_priv(indio_dev);
+
+   return snprintf(buf, PAGE_SIZE, "[ %d 1 %d ]\n", state->min_freq,
+   state->max_freq);
+}
+
+static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(cros_ec_sensors_read_freq);
+
+static struct attribute *cros_ec_sensors_attributes[] = {
+   _dev_attr_sampling_frequency_available.dev_attr.attr,
+   NULL,
+};
+
+static const struct attribute_group cros_ec_sensors_attribute_group = {
+   .attrs = cros_ec_sensors_attributes,
+};
+
 int cros_ec_sensors_core_init(struct platform_device *pdev,
  struct iio_dev *indio_dev,
+ struct iio_info *info,
  bool physical_device)
 {
struct device *dev = >dev;
@@ -164,6 +199,9 @@ int cros_ec_sensors_core_init(struct platform_device *pdev,
}
}
 
+   info->attrs = _ec_sensors_attribute_group;
+   indio_dev->info = info;
+
return 0;
 }
 EXPORT_SYMBOL_GPL(cros_ec_sensors_core_init);
diff --git a/drivers/iio/light/cros_ec_light_prox.c 
b/drivers/iio/light/cros_ec_light_prox.c
index 308ee6ff2e22..1772e339cf14 100644
--- a/drivers/iio/light/cros_ec_light_prox.c
+++ b/drivers/iio/light/cros_ec_light_prox.c
@@ -161,7 +161,7 @@ static int cros_ec_light_prox_write(struct iio_dev 
*indio_dev,
return ret;
 }
 
-static const struct iio_info cros_ec_light_prox_info = {
+static struct iio_info cros_ec_light_prox_info = {
.read_raw = _ec_light_prox_read,
.write_raw = _ec_light_prox_write,
 };
@@ -184,11 +184,11 @@ static int cros_ec_light_prox_probe(struct 
platform_device *pdev)
if (!indio_dev)
return -ENOMEM;
 
-   ret = cros_ec_sensors_c

Re: [alsa-devel] [PATCH v3 00/30] Update cros_ec_commands.h

2019-05-21 Thread Fabien Lahoudere
Le jeudi 09 mai 2019 à 14:13 -0700, Gwendal Grignou a écrit :
> The interface between CrosEC embedded controller and the host,
> described by cros_ec_commands.h, as diverged from what the embedded
> controller really support.
> 
> The source of thruth is at
> https://chromium.googlesource.com/chromiumos/platform/ec/+/master/include/ec_commands.h
> 
> That include file is converted to remove ACPI and Embedded only code.

Hi, 

I reviewed patches of the series and they looks good to me.

Reviewed-by: Fabien Lahoudere 



[PATCH 1/1] iio: cros_ec: add 'id' sysfs entry

2019-04-26 Thread Fabien Lahoudere
From: Gwendal Grignou 

This new sysfs entry is used to interpret ring buffer information,
mainly by Android sensor HAL.
It expand to all sensors, the documentation about 'id' we can found
in Documentation/ABI/testing/sysfs-bus-iio-cros-ec.

Also fix typo in docs, I replace 'Septembre' by 'September'.

Signed-off-by: Gwendal Grignou 
Signed-off-by: Fabien Lahoudere 
---
 Documentation/ABI/testing/sysfs-bus-iio-cros-ec| 10 +-
 .../common/cros_ec_sensors/cros_ec_sensors_core.c  | 14 ++
 2 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-bus-iio-cros-ec 
b/Documentation/ABI/testing/sysfs-bus-iio-cros-ec
index 0e95c2ca105c..6158f831c761 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio-cros-ec
+++ b/Documentation/ABI/testing/sysfs-bus-iio-cros-ec
@@ -18,11 +18,11 @@ Description:
values are 'base' and 'lid'.
 
 What:  /sys/bus/iio/devices/iio:deviceX/id
-Date:  Septembre 2017
+Date:  September 2017
 KernelVersion: 4.14
 Contact:   linux-...@vger.kernel.org
 Description:
-   This attribute is exposed by the CrOS EC legacy accelerometer
-   driver and represents the sensor ID as exposed by the EC. This
-   ID is used by the Android sensor service hardware abstraction
-   layer (sensor HAL) through the Android container on ChromeOS.
+   This attribute is exposed by the CrOS EC sensors driver and
+   represents the sensor ID as exposed by the EC. This ID is used
+   by the Android sensor service hardware abstraction layer (sensor
+   HAL) through the Android container on ChromeOS.
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..130362ca421b 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
@@ -125,6 +125,15 @@ static ssize_t cros_ec_sensors_calibrate(struct iio_dev 
*indio_dev,
return ret ? ret : len;
 }
 
+static ssize_t cros_ec_sensors_id(struct iio_dev *indio_dev,
+ uintptr_t private,
+ const struct iio_chan_spec *chan, char *buf)
+{
+   struct cros_ec_sensors_core_state *st = iio_priv(indio_dev);
+
+   return snprintf(buf, PAGE_SIZE, "%d\n", st->param.info.sensor_num);
+}
+
 static ssize_t cros_ec_sensors_loc(struct iio_dev *indio_dev,
uintptr_t private, const struct iio_chan_spec *chan,
char *buf)
@@ -140,6 +149,11 @@ const struct iio_chan_spec_ext_info 
cros_ec_sensors_ext_info[] = {
.shared = IIO_SHARED_BY_ALL,
.write = cros_ec_sensors_calibrate
},
+   {
+   .name = "id",
+   .shared = IIO_SHARED_BY_ALL,
+   .read = cros_ec_sensors_id
+   },
{
.name = "location",
.shared = IIO_SHARED_BY_ALL,
-- 
2.19.2



Re: [PATCH v3 1/1] serial: imx - Add dma buffer confugration via sysfs

2018-10-17 Thread Fabien Lahoudere
Hi Greg,

On Mon, 2018-10-15 at 16:01 +0200, Greg KH wrote:
> On Thu, Oct 11, 2018 at 11:25:03AM +0200, Fabien Lahoudere wrote:
> > In order to optimize serial communication on imx53 and imx6, we may
> > need to tweak DMA period and buffer length per period.
> 
> Why can you not just automatically determine this information?  What is
> userspace going to know that the kernel can not just learn now?
> 
> Having tunables is nice, but it is even better to not need them at all.

I agree that it is better to let the kernel do the configuration.
However in our case we use several serial communication for different device
and one of them need to tweak that configuration to get small data with a better
period. However having this parameter for all serial port implies a bigger 
number
of interrupts for others too.

> 
> thanks,
> 
> greg k-h
-- 
Fabien


Re: [PATCH v3 1/1] serial: imx - Add dma buffer confugration via sysfs

2018-10-17 Thread Fabien Lahoudere
Hi Greg,

On Mon, 2018-10-15 at 16:01 +0200, Greg KH wrote:
> On Thu, Oct 11, 2018 at 11:25:03AM +0200, Fabien Lahoudere wrote:
> > In order to optimize serial communication on imx53 and imx6, we may
> > need to tweak DMA period and buffer length per period.
> 
> Why can you not just automatically determine this information?  What is
> userspace going to know that the kernel can not just learn now?
> 
> Having tunables is nice, but it is even better to not need them at all.

I agree that it is better to let the kernel do the configuration.
However in our case we use several serial communication for different device
and one of them need to tweak that configuration to get small data with a better
period. However having this parameter for all serial port implies a bigger 
number
of interrupts for others too.

> 
> thanks,
> 
> greg k-h
-- 
Fabien


[PATCH v3 1/1] serial: imx - Add dma buffer confugration via sysfs

2018-10-11 Thread Fabien Lahoudere
In order to optimize serial communication on imx53 and imx6, we may
need to tweak DMA period and buffer length per period.
This patch add sysfs attributes to configure thoses values before
initialising DMA.

For example, you can access values by reading/writing:

/sys/class/tty/ttymxc*/dma_buffer_size
/sys/class/tty/ttymxc*/dma_buffer_count

Signed-off-by: Fabien Lahoudere 
---
Changes since v2:
  - Improve attribute documentation
  - Fix various typo
  - Remove useless debug message
  - Clean code

 Documentation/ABI/stable/sysfs-driver-imx-uart | 13 
 drivers/tty/serial/imx.c   | 89 --
 2 files changed, 97 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/ABI/stable/sysfs-driver-imx-uart

diff --git a/Documentation/ABI/stable/sysfs-driver-imx-uart 
b/Documentation/ABI/stable/sysfs-driver-imx-uart
new file mode 100644
index 000..0a55fcf
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-driver-imx-uart
@@ -0,0 +1,13 @@
+What:  /sys/class/tty/ttymxc*/dma_buffer_count
+Date:  October 2018
+Contact:   Fabien Lahoudere 
+Description:   imx serial use dma buffer for rx communication. The size of this
+   buffer is splited in several chunk. The number of chunk is
+   determined by the field rx_periods (in struct imx_uart). This
+   attribute allows to modify rx_periods.
+
+What:  /sys/class/tty/ttymxc*/dma_buffer_size
+Date:  October 2018
+Contact:   Fabien Lahoudere 
+Description:   Field rx_period_length (in struct imx_uart) allows us to
+   determine the size of each chunk of rx DMA buffer.
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index d4e051b..9622492 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -220,6 +220,8 @@ struct imx_port {
struct scatterlist  rx_sgl, tx_sgl[2];
void*rx_buf;
struct circ_buf rx_ring;
+   unsigned intrx_buf_size;
+   unsigned intrx_period_length;
unsigned intrx_periods;
dma_cookie_trx_cookie;
unsigned inttx_bytes;
@@ -1025,8 +1027,6 @@ static void imx_uart_timeout(struct timer_list *t)
}
 }
 
-#define RX_BUF_SIZE(PAGE_SIZE)
-
 /*
  * There are two kinds of RX DMA interrupts(such as in the MX6Q):
  *   [1] the RX DMA buffer is full.
@@ -1121,9 +1121,8 @@ static int imx_uart_start_rx_dma(struct imx_port *sport)
 
sport->rx_ring.head = 0;
sport->rx_ring.tail = 0;
-   sport->rx_periods = RX_DMA_PERIODS;
 
-   sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE);
+   sg_init_one(sgl, sport->rx_buf, sport->rx_buf_size);
ret = dma_map_sg(dev, sgl, 1, DMA_FROM_DEVICE);
if (ret == 0) {
dev_err(dev, "DMA mapping error for RX.\n");
@@ -1241,7 +1240,8 @@ static int imx_uart_dma_init(struct imx_port *sport)
goto err;
}
 
-   sport->rx_buf = kzalloc(RX_BUF_SIZE, GFP_KERNEL);
+   sport->rx_buf_size = sport->rx_period_length * sport->rx_periods;
+   sport->rx_buf = kzalloc(sport->rx_buf_size, GFP_KERNEL);
if (!sport->rx_buf) {
ret = -ENOMEM;
goto err;
@@ -1702,6 +1702,82 @@ static const char *imx_uart_type(struct uart_port *port)
return sport->port.type == PORT_IMX ? "IMX" : NULL;
 }
 
+
+static ssize_t dma_buffer_size_store(struct device *dev,
+struct device_attribute *attr,
+const char *buf, size_t count)
+{
+   unsigned int plen;
+   int ret;
+   struct device *port_device = dev->parent;
+   struct imx_port *sport = dev_get_drvdata(port_device);
+
+   if (sport->dma_chan_rx) {
+   dev_warn(dev, "DMA channel is not initialized\n");
+   return -EBUSY;
+   }
+   ret = kstrtou32(buf, 0, );
+   if (ret == 0) {
+   sport->rx_period_length = plen;
+   ret = count;
+   }
+   return ret;
+}
+
+static ssize_t dma_buffer_size_show(struct device *dev,
+   struct device_attribute *attr,
+   char *buf)
+{
+   struct device *port_device = dev->parent;
+   struct imx_port *sport = dev_get_drvdata(port_device);
+
+   return sprintf(buf, "%u\n", sport->rx_period_length);
+}
+
+static DEVICE_ATTR_RW(dma_buffer_size);
+
+static ssize_t dma_buffer_count_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   unsigned int periods;
+   int ret;
+   struct device *port_device = dev->parent;
+   struct imx_port *sport = dev_get_drvdata(port_device);

[PATCH v3 1/1] serial: imx - Add dma buffer confugration via sysfs

2018-10-11 Thread Fabien Lahoudere
In order to optimize serial communication on imx53 and imx6, we may
need to tweak DMA period and buffer length per period.
This patch add sysfs attributes to configure thoses values before
initialising DMA.

For example, you can access values by reading/writing:

/sys/class/tty/ttymxc*/dma_buffer_size
/sys/class/tty/ttymxc*/dma_buffer_count

Signed-off-by: Fabien Lahoudere 
---
Changes since v2:
  - Improve attribute documentation
  - Fix various typo
  - Remove useless debug message
  - Clean code

 Documentation/ABI/stable/sysfs-driver-imx-uart | 13 
 drivers/tty/serial/imx.c   | 89 --
 2 files changed, 97 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/ABI/stable/sysfs-driver-imx-uart

diff --git a/Documentation/ABI/stable/sysfs-driver-imx-uart 
b/Documentation/ABI/stable/sysfs-driver-imx-uart
new file mode 100644
index 000..0a55fcf
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-driver-imx-uart
@@ -0,0 +1,13 @@
+What:  /sys/class/tty/ttymxc*/dma_buffer_count
+Date:  October 2018
+Contact:   Fabien Lahoudere 
+Description:   imx serial use dma buffer for rx communication. The size of this
+   buffer is splited in several chunk. The number of chunk is
+   determined by the field rx_periods (in struct imx_uart). This
+   attribute allows to modify rx_periods.
+
+What:  /sys/class/tty/ttymxc*/dma_buffer_size
+Date:  October 2018
+Contact:   Fabien Lahoudere 
+Description:   Field rx_period_length (in struct imx_uart) allows us to
+   determine the size of each chunk of rx DMA buffer.
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index d4e051b..9622492 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -220,6 +220,8 @@ struct imx_port {
struct scatterlist  rx_sgl, tx_sgl[2];
void*rx_buf;
struct circ_buf rx_ring;
+   unsigned intrx_buf_size;
+   unsigned intrx_period_length;
unsigned intrx_periods;
dma_cookie_trx_cookie;
unsigned inttx_bytes;
@@ -1025,8 +1027,6 @@ static void imx_uart_timeout(struct timer_list *t)
}
 }
 
-#define RX_BUF_SIZE(PAGE_SIZE)
-
 /*
  * There are two kinds of RX DMA interrupts(such as in the MX6Q):
  *   [1] the RX DMA buffer is full.
@@ -1121,9 +1121,8 @@ static int imx_uart_start_rx_dma(struct imx_port *sport)
 
sport->rx_ring.head = 0;
sport->rx_ring.tail = 0;
-   sport->rx_periods = RX_DMA_PERIODS;
 
-   sg_init_one(sgl, sport->rx_buf, RX_BUF_SIZE);
+   sg_init_one(sgl, sport->rx_buf, sport->rx_buf_size);
ret = dma_map_sg(dev, sgl, 1, DMA_FROM_DEVICE);
if (ret == 0) {
dev_err(dev, "DMA mapping error for RX.\n");
@@ -1241,7 +1240,8 @@ static int imx_uart_dma_init(struct imx_port *sport)
goto err;
}
 
-   sport->rx_buf = kzalloc(RX_BUF_SIZE, GFP_KERNEL);
+   sport->rx_buf_size = sport->rx_period_length * sport->rx_periods;
+   sport->rx_buf = kzalloc(sport->rx_buf_size, GFP_KERNEL);
if (!sport->rx_buf) {
ret = -ENOMEM;
goto err;
@@ -1702,6 +1702,82 @@ static const char *imx_uart_type(struct uart_port *port)
return sport->port.type == PORT_IMX ? "IMX" : NULL;
 }
 
+
+static ssize_t dma_buffer_size_store(struct device *dev,
+struct device_attribute *attr,
+const char *buf, size_t count)
+{
+   unsigned int plen;
+   int ret;
+   struct device *port_device = dev->parent;
+   struct imx_port *sport = dev_get_drvdata(port_device);
+
+   if (sport->dma_chan_rx) {
+   dev_warn(dev, "DMA channel is not initialized\n");
+   return -EBUSY;
+   }
+   ret = kstrtou32(buf, 0, );
+   if (ret == 0) {
+   sport->rx_period_length = plen;
+   ret = count;
+   }
+   return ret;
+}
+
+static ssize_t dma_buffer_size_show(struct device *dev,
+   struct device_attribute *attr,
+   char *buf)
+{
+   struct device *port_device = dev->parent;
+   struct imx_port *sport = dev_get_drvdata(port_device);
+
+   return sprintf(buf, "%u\n", sport->rx_period_length);
+}
+
+static DEVICE_ATTR_RW(dma_buffer_size);
+
+static ssize_t dma_buffer_count_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+   unsigned int periods;
+   int ret;
+   struct device *port_device = dev->parent;
+   struct imx_port *sport = dev_get_drvdata(port_device);

Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-06-09 Thread Fabien Lahoudere
Hi Peter

On Fri, 2017-06-09 at 08:26 +, Peter Chen wrote:
>  
> > 
> > I have a look at your patches 
> > (http://www.spinics.net/lists/linux-usb/msg157134.html)
> > and I wonder if power sequence is applicable only on hub node?
> 
> No, power sequence can be used for any devices which needs to carry out power 
> on
> before probe.
> 
> > hub are probed too
> > late (after ci_ulpi_init). Do you think it is possible to read a power 
> > sequence in dts
> > from ci_ulpi_init?
> > 
> 
> I think the suitable place for power sequence is at ulpi_of_register, some 
> ULPI PHYs
> need to carry out power on before reading ID.
> 

I do some test to verify that ulpi_of_register is called before 
hw_phymode_configure but it is not
the case.

Can you confirm that ULPI phys works with IMX6? 

It seems that IMX53 and IMX6 use the same chipidea controller and should have 
the same behaviour. So
I wonder if the issue I encounter can be a SOC issue.

Thanks

> Peter


Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-06-09 Thread Fabien Lahoudere
Hi Peter

On Fri, 2017-06-09 at 08:26 +, Peter Chen wrote:
>  
> > 
> > I have a look at your patches 
> > (http://www.spinics.net/lists/linux-usb/msg157134.html)
> > and I wonder if power sequence is applicable only on hub node?
> 
> No, power sequence can be used for any devices which needs to carry out power 
> on
> before probe.
> 
> > hub are probed too
> > late (after ci_ulpi_init). Do you think it is possible to read a power 
> > sequence in dts
> > from ci_ulpi_init?
> > 
> 
> I think the suitable place for power sequence is at ulpi_of_register, some 
> ULPI PHYs
> need to carry out power on before reading ID.
> 

I do some test to verify that ulpi_of_register is called before 
hw_phymode_configure but it is not
the case.

Can you confirm that ULPI phys works with IMX6? 

It seems that IMX53 and IMX6 use the same chipidea controller and should have 
the same behaviour. So
I wonder if the issue I encounter can be a SOC issue.

Thanks

> Peter


Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-06-08 Thread Fabien Lahoudere
Hi Peter

I have a look at your patches 
(http://www.spinics.net/lists/linux-usb/msg157134.html) and I wonder
if power sequence is applicable only on hub node? hub are probed too late 
(after ci_ulpi_init). Do
you think it is possible to read a power sequence in dts from ci_ulpi_init?

Thanks

Fabien



Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-06-08 Thread Fabien Lahoudere
Hi Peter

I have a look at your patches 
(http://www.spinics.net/lists/linux-usb/msg157134.html) and I wonder
if power sequence is applicable only on hub node? hub are probed too late 
(after ci_ulpi_init). Do
you think it is possible to read a power sequence in dts from ci_ulpi_init?

Thanks

Fabien



Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-06-07 Thread Fabien Lahoudere
On Wed, 2017-06-07 at 09:43 +0800, Peter Chen wrote:
> On Tue, Jun 06, 2017 at 07:36:10PM +0200, Fabien Lahoudere wrote:
> > Hi Peter,
> > 
> > On Tue, 2017-06-06 at 09:55 +0800, Peter Chen wrote:
> > > On Mon, Jun 05, 2017 at 11:52:26AM +0200, Fabien Lahoudere wrote:
> > > > On Mon, 2017-06-05 at 17:43 +0800, Peter Chen wrote:
> > > > > On Mon, Jun 05, 2017 at 10:57:00AM +0200, Fabien Lahoudere wrote:
> > > > > > On Fri, 2017-06-02 at 15:00 -0700, Stephen Boyd wrote:
> > > > > > > On 05/26, Fabien Lahoudere wrote:
> > > > > > > > Hello
> > > > > > > > 
> > > > > > > > I modify ci_hrdc_imx_probe to bypass "data->phy = 
> > > > > > > > devm_usb_get_phy_by_phandle(
> > > > > > > > > dev,
> > > > > > > > 
> > > > > > > > "fsl,usbphy", 0);". Everything works as expected and call 
> > > > > > > > ci_ulpi_init.
> > > > > > > > 
> > > > > > > > The problem is that in ci_ulpi_init, before calling "ci->ulpi =
> > > > > > > > ulpi_register_interface(ci-
> > > > > > > > > dev,
> > > > > > > > 
> > > > > > > > >ulpi_ops);" (to initialize our phy), 
> > > > > > > > "hw_phymode_configure(ci);" is called
> > > > > > > > which is
> > > > > > > > the
> > > > > > > > original function that make our system to hang.
> > > > > > > > 
> > > > > > > > Our phy is not initialised before calling 
> > > > > > > > ulpi_register_interface so I don't
> > > > > > > > understand
> > > > > > > > how
> > > > > > > > the
> > > > > > > > phy
> > > > > > > > can reply if it is not out of reset state.
> > > > > > > 
> > > > > > > I haven't see any problem in hw_phymode_configure(). What's the
> > > > > > > value of ci->platdata->phy_mode? USBPHY_INTERFACE_MODE_ULPI? If
> > > > > > > you phy needs to be taken out of reset to reply to the ulpi reads
> > > > > > > of the vendor/product ids, then it sounds like you have a similar
> > > > > > > situation to what I had. I needed to turn on some regulators to
> > > > > > > get those reads to work, otherwise they would fail, but knowing
> > > > > > > what needed to be turned on basically meant I needed to probe the
> > > > > > > ulpi driver so probing the ids wasn't going to be useful. So on
> > > > > > > my device the reads for the ids go through, but they get all
> > > > > > > zeroes back, which is actually ok because there aren't any bits
> > > > > > > set on my devices anyway. After the reads see 0, we fallback to
> > > > > > > DT matching, which avoids the "bring it out of reset/power it on"
> > > > > > > sorts of problems entirely.
> > > > > > > 
> > > > > > 
> > > > > > Yes the phy mode is configured to USBPHY_INTERFACE_MODE_ULPI.
> > > > > > Indeed, this phy need to be out of reset to work. For example 
> > > > > > everything works fine if I
> > > > > > call 
> > > > > > "_ci_usb_phy_init(ci);" before calling "hw_phymode_configure(ci);"
> > > > > > This function only init reset GPIO and clock.
> > > > > > 
> > > > > > For information, the original patch I have to fix the issue:
> > > > > > 
> > > > > > diff --git a/drivers/usb/chipidea/core.c 
> > > > > > b/drivers/usb/chipidea/core.c
> > > > > > index 79ad8e9..21aaff1 100644
> > > > > > --- a/drivers/usb/chipidea/core.c
> > > > > > +++ b/drivers/usb/chipidea/core.c
> > > > > > @@ -391,6 +391,7 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
> > > > > >     case USBPHY_INTERFACE_MODE_UTMI:
> > > > > >     case USBPHY_INTERFACE_MODE_UTMIW:
> > > > > >     case USBPHY_INTERFACE_MODE_HSIC:
> > > > > > +   case USBPHY_INTERFACE_MODE_ULPI:
> > > > > >     ret = 

Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-06-07 Thread Fabien Lahoudere
On Wed, 2017-06-07 at 09:43 +0800, Peter Chen wrote:
> On Tue, Jun 06, 2017 at 07:36:10PM +0200, Fabien Lahoudere wrote:
> > Hi Peter,
> > 
> > On Tue, 2017-06-06 at 09:55 +0800, Peter Chen wrote:
> > > On Mon, Jun 05, 2017 at 11:52:26AM +0200, Fabien Lahoudere wrote:
> > > > On Mon, 2017-06-05 at 17:43 +0800, Peter Chen wrote:
> > > > > On Mon, Jun 05, 2017 at 10:57:00AM +0200, Fabien Lahoudere wrote:
> > > > > > On Fri, 2017-06-02 at 15:00 -0700, Stephen Boyd wrote:
> > > > > > > On 05/26, Fabien Lahoudere wrote:
> > > > > > > > Hello
> > > > > > > > 
> > > > > > > > I modify ci_hrdc_imx_probe to bypass "data->phy = 
> > > > > > > > devm_usb_get_phy_by_phandle(
> > > > > > > > > dev,
> > > > > > > > 
> > > > > > > > "fsl,usbphy", 0);". Everything works as expected and call 
> > > > > > > > ci_ulpi_init.
> > > > > > > > 
> > > > > > > > The problem is that in ci_ulpi_init, before calling "ci->ulpi =
> > > > > > > > ulpi_register_interface(ci-
> > > > > > > > > dev,
> > > > > > > > 
> > > > > > > > >ulpi_ops);" (to initialize our phy), 
> > > > > > > > "hw_phymode_configure(ci);" is called
> > > > > > > > which is
> > > > > > > > the
> > > > > > > > original function that make our system to hang.
> > > > > > > > 
> > > > > > > > Our phy is not initialised before calling 
> > > > > > > > ulpi_register_interface so I don't
> > > > > > > > understand
> > > > > > > > how
> > > > > > > > the
> > > > > > > > phy
> > > > > > > > can reply if it is not out of reset state.
> > > > > > > 
> > > > > > > I haven't see any problem in hw_phymode_configure(). What's the
> > > > > > > value of ci->platdata->phy_mode? USBPHY_INTERFACE_MODE_ULPI? If
> > > > > > > you phy needs to be taken out of reset to reply to the ulpi reads
> > > > > > > of the vendor/product ids, then it sounds like you have a similar
> > > > > > > situation to what I had. I needed to turn on some regulators to
> > > > > > > get those reads to work, otherwise they would fail, but knowing
> > > > > > > what needed to be turned on basically meant I needed to probe the
> > > > > > > ulpi driver so probing the ids wasn't going to be useful. So on
> > > > > > > my device the reads for the ids go through, but they get all
> > > > > > > zeroes back, which is actually ok because there aren't any bits
> > > > > > > set on my devices anyway. After the reads see 0, we fallback to
> > > > > > > DT matching, which avoids the "bring it out of reset/power it on"
> > > > > > > sorts of problems entirely.
> > > > > > > 
> > > > > > 
> > > > > > Yes the phy mode is configured to USBPHY_INTERFACE_MODE_ULPI.
> > > > > > Indeed, this phy need to be out of reset to work. For example 
> > > > > > everything works fine if I
> > > > > > call 
> > > > > > "_ci_usb_phy_init(ci);" before calling "hw_phymode_configure(ci);"
> > > > > > This function only init reset GPIO and clock.
> > > > > > 
> > > > > > For information, the original patch I have to fix the issue:
> > > > > > 
> > > > > > diff --git a/drivers/usb/chipidea/core.c 
> > > > > > b/drivers/usb/chipidea/core.c
> > > > > > index 79ad8e9..21aaff1 100644
> > > > > > --- a/drivers/usb/chipidea/core.c
> > > > > > +++ b/drivers/usb/chipidea/core.c
> > > > > > @@ -391,6 +391,7 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
> > > > > >     case USBPHY_INTERFACE_MODE_UTMI:
> > > > > >     case USBPHY_INTERFACE_MODE_UTMIW:
> > > > > >     case USBPHY_INTERFACE_MODE_HSIC:
> > > > > > +   case USBPHY_INTERFACE_MODE_ULPI:
> > > > > >     ret = 

Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-06-06 Thread Fabien Lahoudere
Hi Peter,

On Tue, 2017-06-06 at 09:55 +0800, Peter Chen wrote:
> On Mon, Jun 05, 2017 at 11:52:26AM +0200, Fabien Lahoudere wrote:
> > On Mon, 2017-06-05 at 17:43 +0800, Peter Chen wrote:
> > > On Mon, Jun 05, 2017 at 10:57:00AM +0200, Fabien Lahoudere wrote:
> > > > On Fri, 2017-06-02 at 15:00 -0700, Stephen Boyd wrote:
> > > > > On 05/26, Fabien Lahoudere wrote:
> > > > > > Hello
> > > > > > 
> > > > > > I modify ci_hrdc_imx_probe to bypass "data->phy = 
> > > > > > devm_usb_get_phy_by_phandle(
> > > > > > >dev,
> > > > > > "fsl,usbphy", 0);". Everything works as expected and call 
> > > > > > ci_ulpi_init.
> > > > > > 
> > > > > > The problem is that in ci_ulpi_init, before calling "ci->ulpi =
> > > > > > ulpi_register_interface(ci-
> > > > > > > dev,
> > > > > > 
> > > > > > >ulpi_ops);" (to initialize our phy), 
> > > > > > "hw_phymode_configure(ci);" is called which is
> > > > > > the
> > > > > > original function that make our system to hang.
> > > > > > 
> > > > > > Our phy is not initialised before calling ulpi_register_interface 
> > > > > > so I don't understand
> > > > > > how
> > > > > > the
> > > > > > phy
> > > > > > can reply if it is not out of reset state.
> > > > > 
> > > > > I haven't see any problem in hw_phymode_configure(). What's the
> > > > > value of ci->platdata->phy_mode? USBPHY_INTERFACE_MODE_ULPI? If
> > > > > you phy needs to be taken out of reset to reply to the ulpi reads
> > > > > of the vendor/product ids, then it sounds like you have a similar
> > > > > situation to what I had. I needed to turn on some regulators to
> > > > > get those reads to work, otherwise they would fail, but knowing
> > > > > what needed to be turned on basically meant I needed to probe the
> > > > > ulpi driver so probing the ids wasn't going to be useful. So on
> > > > > my device the reads for the ids go through, but they get all
> > > > > zeroes back, which is actually ok because there aren't any bits
> > > > > set on my devices anyway. After the reads see 0, we fallback to
> > > > > DT matching, which avoids the "bring it out of reset/power it on"
> > > > > sorts of problems entirely.
> > > > > 
> > > > 
> > > > Yes the phy mode is configured to USBPHY_INTERFACE_MODE_ULPI.
> > > > Indeed, this phy need to be out of reset to work. For example 
> > > > everything works fine if I
> > > > call 
> > > > "_ci_usb_phy_init(ci);" before calling "hw_phymode_configure(ci);"
> > > > This function only init reset GPIO and clock.
> > > > 
> > > > For information, the original patch I have to fix the issue:
> > > > 
> > > > diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
> > > > index 79ad8e9..21aaff1 100644
> > > > --- a/drivers/usb/chipidea/core.c
> > > > +++ b/drivers/usb/chipidea/core.c
> > > > @@ -391,6 +391,7 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
> > > >     case USBPHY_INTERFACE_MODE_UTMI:
> > > >     case USBPHY_INTERFACE_MODE_UTMIW:
> > > >     case USBPHY_INTERFACE_MODE_HSIC:
> > > > +   case USBPHY_INTERFACE_MODE_ULPI:
> > > >     ret = _ci_usb_phy_init(ci);
> > > >     if (!ret)
> > > >     hw_wait_phy_stable();
> > > > @@ -398,7 +399,6 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
> > > >     return ret;
> > > >     hw_phymode_configure(ci);
> > > >     break;
> > > > -   case USBPHY_INTERFACE_MODE_ULPI:
> > > >     case USBPHY_INTERFACE_MODE_SERIAL:
> > > >     hw_phymode_configure(ci);
> > > >     ret = _ci_usb_phy_init(ci);
> > > > -- 
> > > 
> > > Currently, the hw_phymode_configure is called twice for ULPI PHY, the
> > > two execution are between _ci_usb_phy_init, would you test which one
> > > causes hang? If the second causes hang, you can make a patch f

Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-06-06 Thread Fabien Lahoudere
Hi Peter,

On Tue, 2017-06-06 at 09:55 +0800, Peter Chen wrote:
> On Mon, Jun 05, 2017 at 11:52:26AM +0200, Fabien Lahoudere wrote:
> > On Mon, 2017-06-05 at 17:43 +0800, Peter Chen wrote:
> > > On Mon, Jun 05, 2017 at 10:57:00AM +0200, Fabien Lahoudere wrote:
> > > > On Fri, 2017-06-02 at 15:00 -0700, Stephen Boyd wrote:
> > > > > On 05/26, Fabien Lahoudere wrote:
> > > > > > Hello
> > > > > > 
> > > > > > I modify ci_hrdc_imx_probe to bypass "data->phy = 
> > > > > > devm_usb_get_phy_by_phandle(
> > > > > > >dev,
> > > > > > "fsl,usbphy", 0);". Everything works as expected and call 
> > > > > > ci_ulpi_init.
> > > > > > 
> > > > > > The problem is that in ci_ulpi_init, before calling "ci->ulpi =
> > > > > > ulpi_register_interface(ci-
> > > > > > > dev,
> > > > > > 
> > > > > > >ulpi_ops);" (to initialize our phy), 
> > > > > > "hw_phymode_configure(ci);" is called which is
> > > > > > the
> > > > > > original function that make our system to hang.
> > > > > > 
> > > > > > Our phy is not initialised before calling ulpi_register_interface 
> > > > > > so I don't understand
> > > > > > how
> > > > > > the
> > > > > > phy
> > > > > > can reply if it is not out of reset state.
> > > > > 
> > > > > I haven't see any problem in hw_phymode_configure(). What's the
> > > > > value of ci->platdata->phy_mode? USBPHY_INTERFACE_MODE_ULPI? If
> > > > > you phy needs to be taken out of reset to reply to the ulpi reads
> > > > > of the vendor/product ids, then it sounds like you have a similar
> > > > > situation to what I had. I needed to turn on some regulators to
> > > > > get those reads to work, otherwise they would fail, but knowing
> > > > > what needed to be turned on basically meant I needed to probe the
> > > > > ulpi driver so probing the ids wasn't going to be useful. So on
> > > > > my device the reads for the ids go through, but they get all
> > > > > zeroes back, which is actually ok because there aren't any bits
> > > > > set on my devices anyway. After the reads see 0, we fallback to
> > > > > DT matching, which avoids the "bring it out of reset/power it on"
> > > > > sorts of problems entirely.
> > > > > 
> > > > 
> > > > Yes the phy mode is configured to USBPHY_INTERFACE_MODE_ULPI.
> > > > Indeed, this phy need to be out of reset to work. For example 
> > > > everything works fine if I
> > > > call 
> > > > "_ci_usb_phy_init(ci);" before calling "hw_phymode_configure(ci);"
> > > > This function only init reset GPIO and clock.
> > > > 
> > > > For information, the original patch I have to fix the issue:
> > > > 
> > > > diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
> > > > index 79ad8e9..21aaff1 100644
> > > > --- a/drivers/usb/chipidea/core.c
> > > > +++ b/drivers/usb/chipidea/core.c
> > > > @@ -391,6 +391,7 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
> > > >     case USBPHY_INTERFACE_MODE_UTMI:
> > > >     case USBPHY_INTERFACE_MODE_UTMIW:
> > > >     case USBPHY_INTERFACE_MODE_HSIC:
> > > > +   case USBPHY_INTERFACE_MODE_ULPI:
> > > >     ret = _ci_usb_phy_init(ci);
> > > >     if (!ret)
> > > >     hw_wait_phy_stable();
> > > > @@ -398,7 +399,6 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
> > > >     return ret;
> > > >     hw_phymode_configure(ci);
> > > >     break;
> > > > -   case USBPHY_INTERFACE_MODE_ULPI:
> > > >     case USBPHY_INTERFACE_MODE_SERIAL:
> > > >     hw_phymode_configure(ci);
> > > >     ret = _ci_usb_phy_init(ci);
> > > > -- 
> > > 
> > > Currently, the hw_phymode_configure is called twice for ULPI PHY, the
> > > two execution are between _ci_usb_phy_init, would you test which one
> > > causes hang? If the second causes hang, you can make a pat

Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-06-05 Thread Fabien Lahoudere
On Mon, 2017-06-05 at 17:43 +0800, Peter Chen wrote:
> On Mon, Jun 05, 2017 at 10:57:00AM +0200, Fabien Lahoudere wrote:
> > On Fri, 2017-06-02 at 15:00 -0700, Stephen Boyd wrote:
> > > On 05/26, Fabien Lahoudere wrote:
> > > > Hello
> > > > 
> > > > I modify ci_hrdc_imx_probe to bypass "data->phy = 
> > > > devm_usb_get_phy_by_phandle(>dev,
> > > > "fsl,usbphy", 0);". Everything works as expected and call ci_ulpi_init.
> > > > 
> > > > The problem is that in ci_ulpi_init, before calling "ci->ulpi = 
> > > > ulpi_register_interface(ci-
> > > > >dev,
> > > > >ulpi_ops);" (to initialize our phy), "hw_phymode_configure(ci);" 
> > > > is called which is the
> > > > original function that make our system to hang.
> > > > 
> > > > Our phy is not initialised before calling ulpi_register_interface so I 
> > > > don't understand how
> > > > the
> > > > phy
> > > > can reply if it is not out of reset state.
> > > 
> > > I haven't see any problem in hw_phymode_configure(). What's the
> > > value of ci->platdata->phy_mode? USBPHY_INTERFACE_MODE_ULPI? If
> > > you phy needs to be taken out of reset to reply to the ulpi reads
> > > of the vendor/product ids, then it sounds like you have a similar
> > > situation to what I had. I needed to turn on some regulators to
> > > get those reads to work, otherwise they would fail, but knowing
> > > what needed to be turned on basically meant I needed to probe the
> > > ulpi driver so probing the ids wasn't going to be useful. So on
> > > my device the reads for the ids go through, but they get all
> > > zeroes back, which is actually ok because there aren't any bits
> > > set on my devices anyway. After the reads see 0, we fallback to
> > > DT matching, which avoids the "bring it out of reset/power it on"
> > > sorts of problems entirely.
> > > 
> > 
> > Yes the phy mode is configured to USBPHY_INTERFACE_MODE_ULPI.
> > Indeed, this phy need to be out of reset to work. For example everything 
> > works fine if I call 
> > "_ci_usb_phy_init(ci);" before calling "hw_phymode_configure(ci);"
> > This function only init reset GPIO and clock.
> > 
> > For information, the original patch I have to fix the issue:
> > 
> > diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
> > index 79ad8e9..21aaff1 100644
> > --- a/drivers/usb/chipidea/core.c
> > +++ b/drivers/usb/chipidea/core.c
> > @@ -391,6 +391,7 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
> >     case USBPHY_INTERFACE_MODE_UTMI:
> >     case USBPHY_INTERFACE_MODE_UTMIW:
> >     case USBPHY_INTERFACE_MODE_HSIC:
> > +   case USBPHY_INTERFACE_MODE_ULPI:
> >     ret = _ci_usb_phy_init(ci);
> >     if (!ret)
> >     hw_wait_phy_stable();
> > @@ -398,7 +399,6 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
> >     return ret;
> >     hw_phymode_configure(ci);
> >     break;
> > -   case USBPHY_INTERFACE_MODE_ULPI:
> >     case USBPHY_INTERFACE_MODE_SERIAL:
> >     hw_phymode_configure(ci);
> >     ret = _ci_usb_phy_init(ci);
> > -- 
> 
> Currently, the hw_phymode_configure is called twice for ULPI PHY, the
> two execution are between _ci_usb_phy_init, would you test which one
> causes hang? If the second causes hang, you can make a patch for
> hw_phymode_configure that if the required PORTSC_PTS is the same
> the value in register, do noop.

The first one hangs, _ci_usb_phy_init is not called due to hang.



Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-06-05 Thread Fabien Lahoudere
On Mon, 2017-06-05 at 17:43 +0800, Peter Chen wrote:
> On Mon, Jun 05, 2017 at 10:57:00AM +0200, Fabien Lahoudere wrote:
> > On Fri, 2017-06-02 at 15:00 -0700, Stephen Boyd wrote:
> > > On 05/26, Fabien Lahoudere wrote:
> > > > Hello
> > > > 
> > > > I modify ci_hrdc_imx_probe to bypass "data->phy = 
> > > > devm_usb_get_phy_by_phandle(>dev,
> > > > "fsl,usbphy", 0);". Everything works as expected and call ci_ulpi_init.
> > > > 
> > > > The problem is that in ci_ulpi_init, before calling "ci->ulpi = 
> > > > ulpi_register_interface(ci-
> > > > >dev,
> > > > >ulpi_ops);" (to initialize our phy), "hw_phymode_configure(ci);" 
> > > > is called which is the
> > > > original function that make our system to hang.
> > > > 
> > > > Our phy is not initialised before calling ulpi_register_interface so I 
> > > > don't understand how
> > > > the
> > > > phy
> > > > can reply if it is not out of reset state.
> > > 
> > > I haven't see any problem in hw_phymode_configure(). What's the
> > > value of ci->platdata->phy_mode? USBPHY_INTERFACE_MODE_ULPI? If
> > > you phy needs to be taken out of reset to reply to the ulpi reads
> > > of the vendor/product ids, then it sounds like you have a similar
> > > situation to what I had. I needed to turn on some regulators to
> > > get those reads to work, otherwise they would fail, but knowing
> > > what needed to be turned on basically meant I needed to probe the
> > > ulpi driver so probing the ids wasn't going to be useful. So on
> > > my device the reads for the ids go through, but they get all
> > > zeroes back, which is actually ok because there aren't any bits
> > > set on my devices anyway. After the reads see 0, we fallback to
> > > DT matching, which avoids the "bring it out of reset/power it on"
> > > sorts of problems entirely.
> > > 
> > 
> > Yes the phy mode is configured to USBPHY_INTERFACE_MODE_ULPI.
> > Indeed, this phy need to be out of reset to work. For example everything 
> > works fine if I call 
> > "_ci_usb_phy_init(ci);" before calling "hw_phymode_configure(ci);"
> > This function only init reset GPIO and clock.
> > 
> > For information, the original patch I have to fix the issue:
> > 
> > diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
> > index 79ad8e9..21aaff1 100644
> > --- a/drivers/usb/chipidea/core.c
> > +++ b/drivers/usb/chipidea/core.c
> > @@ -391,6 +391,7 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
> >     case USBPHY_INTERFACE_MODE_UTMI:
> >     case USBPHY_INTERFACE_MODE_UTMIW:
> >     case USBPHY_INTERFACE_MODE_HSIC:
> > +   case USBPHY_INTERFACE_MODE_ULPI:
> >     ret = _ci_usb_phy_init(ci);
> >     if (!ret)
> >     hw_wait_phy_stable();
> > @@ -398,7 +399,6 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
> >     return ret;
> >     hw_phymode_configure(ci);
> >     break;
> > -   case USBPHY_INTERFACE_MODE_ULPI:
> >     case USBPHY_INTERFACE_MODE_SERIAL:
> >     hw_phymode_configure(ci);
> >     ret = _ci_usb_phy_init(ci);
> > -- 
> 
> Currently, the hw_phymode_configure is called twice for ULPI PHY, the
> two execution are between _ci_usb_phy_init, would you test which one
> causes hang? If the second causes hang, you can make a patch for
> hw_phymode_configure that if the required PORTSC_PTS is the same
> the value in register, do noop.

The first one hangs, _ci_usb_phy_init is not called due to hang.



Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-06-05 Thread Fabien Lahoudere
On Fri, 2017-06-02 at 15:00 -0700, Stephen Boyd wrote:
> On 05/26, Fabien Lahoudere wrote:
> > Hello
> > 
> > I modify ci_hrdc_imx_probe to bypass "data->phy = 
> > devm_usb_get_phy_by_phandle(>dev,
> > "fsl,usbphy", 0);". Everything works as expected and call ci_ulpi_init.
> > 
> > The problem is that in ci_ulpi_init, before calling "ci->ulpi = 
> > ulpi_register_interface(ci->dev,
> > >ulpi_ops);" (to initialize our phy), "hw_phymode_configure(ci);" is 
> > called which is the
> > original function that make our system to hang.
> > 
> > Our phy is not initialised before calling ulpi_register_interface so I 
> > don't understand how the
> > phy
> > can reply if it is not out of reset state.
> 
> I haven't see any problem in hw_phymode_configure(). What's the
> value of ci->platdata->phy_mode? USBPHY_INTERFACE_MODE_ULPI? If
> you phy needs to be taken out of reset to reply to the ulpi reads
> of the vendor/product ids, then it sounds like you have a similar
> situation to what I had. I needed to turn on some regulators to
> get those reads to work, otherwise they would fail, but knowing
> what needed to be turned on basically meant I needed to probe the
> ulpi driver so probing the ids wasn't going to be useful. So on
> my device the reads for the ids go through, but they get all
> zeroes back, which is actually ok because there aren't any bits
> set on my devices anyway. After the reads see 0, we fallback to
> DT matching, which avoids the "bring it out of reset/power it on"
> sorts of problems entirely.
> 

Yes the phy mode is configured to USBPHY_INTERFACE_MODE_ULPI.
Indeed, this phy need to be out of reset to work. For example everything works 
fine if I call 
"_ci_usb_phy_init(ci);" before calling "hw_phymode_configure(ci);"
This function only init reset GPIO and clock.

For information, the original patch I have to fix the issue:

diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 79ad8e9..21aaff1 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -391,6 +391,7 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
    case USBPHY_INTERFACE_MODE_UTMI:
    case USBPHY_INTERFACE_MODE_UTMIW:
    case USBPHY_INTERFACE_MODE_HSIC:
+   case USBPHY_INTERFACE_MODE_ULPI:
    ret = _ci_usb_phy_init(ci);
    if (!ret)
    hw_wait_phy_stable();
@@ -398,7 +399,6 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
    return ret;
    hw_phymode_configure(ci);
    break;
-   case USBPHY_INTERFACE_MODE_ULPI:
    case USBPHY_INTERFACE_MODE_SERIAL:
    hw_phymode_configure(ci);
    ret = _ci_usb_phy_init(ci);
-- 

So if some ULPI phys need to be initialised before calling 
"hw_phymode_configure", is it acceptable
if I separate "case USBPHY_INTERFACE_MODE_ULPI:" and add a DT binding 
("init_phy_first") to define
the order to call both functions?

Something like:

case USBPHY_INTERFACE_MODE_ULPI:
if (ci->platdata->init_phy_first) {
ret = _ci_usb_phy_init(ci);
if (!ret)
    hw_wait_phy_stable();
    else
    return ret;
}
hw_phymode_configure(ci);
if (!ci->platdata->init_phy_first) {
ret = _ci_usb_phy_init(ci);
if (ret)
    return ret;
}
break;

This approach will not modify current behaviour but allow to initialize phy 
first on demand.



Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-06-05 Thread Fabien Lahoudere
On Fri, 2017-06-02 at 15:00 -0700, Stephen Boyd wrote:
> On 05/26, Fabien Lahoudere wrote:
> > Hello
> > 
> > I modify ci_hrdc_imx_probe to bypass "data->phy = 
> > devm_usb_get_phy_by_phandle(>dev,
> > "fsl,usbphy", 0);". Everything works as expected and call ci_ulpi_init.
> > 
> > The problem is that in ci_ulpi_init, before calling "ci->ulpi = 
> > ulpi_register_interface(ci->dev,
> > >ulpi_ops);" (to initialize our phy), "hw_phymode_configure(ci);" is 
> > called which is the
> > original function that make our system to hang.
> > 
> > Our phy is not initialised before calling ulpi_register_interface so I 
> > don't understand how the
> > phy
> > can reply if it is not out of reset state.
> 
> I haven't see any problem in hw_phymode_configure(). What's the
> value of ci->platdata->phy_mode? USBPHY_INTERFACE_MODE_ULPI? If
> you phy needs to be taken out of reset to reply to the ulpi reads
> of the vendor/product ids, then it sounds like you have a similar
> situation to what I had. I needed to turn on some regulators to
> get those reads to work, otherwise they would fail, but knowing
> what needed to be turned on basically meant I needed to probe the
> ulpi driver so probing the ids wasn't going to be useful. So on
> my device the reads for the ids go through, but they get all
> zeroes back, which is actually ok because there aren't any bits
> set on my devices anyway. After the reads see 0, we fallback to
> DT matching, which avoids the "bring it out of reset/power it on"
> sorts of problems entirely.
> 

Yes the phy mode is configured to USBPHY_INTERFACE_MODE_ULPI.
Indeed, this phy need to be out of reset to work. For example everything works 
fine if I call 
"_ci_usb_phy_init(ci);" before calling "hw_phymode_configure(ci);"
This function only init reset GPIO and clock.

For information, the original patch I have to fix the issue:

diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 79ad8e9..21aaff1 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -391,6 +391,7 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
    case USBPHY_INTERFACE_MODE_UTMI:
    case USBPHY_INTERFACE_MODE_UTMIW:
    case USBPHY_INTERFACE_MODE_HSIC:
+   case USBPHY_INTERFACE_MODE_ULPI:
    ret = _ci_usb_phy_init(ci);
    if (!ret)
    hw_wait_phy_stable();
@@ -398,7 +399,6 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
    return ret;
    hw_phymode_configure(ci);
    break;
-   case USBPHY_INTERFACE_MODE_ULPI:
    case USBPHY_INTERFACE_MODE_SERIAL:
    hw_phymode_configure(ci);
    ret = _ci_usb_phy_init(ci);
-- 

So if some ULPI phys need to be initialised before calling 
"hw_phymode_configure", is it acceptable
if I separate "case USBPHY_INTERFACE_MODE_ULPI:" and add a DT binding 
("init_phy_first") to define
the order to call both functions?

Something like:

case USBPHY_INTERFACE_MODE_ULPI:
if (ci->platdata->init_phy_first) {
ret = _ci_usb_phy_init(ci);
if (!ret)
    hw_wait_phy_stable();
    else
    return ret;
}
hw_phymode_configure(ci);
if (!ci->platdata->init_phy_first) {
ret = _ci_usb_phy_init(ci);
if (ret)
    return ret;
}
break;

This approach will not modify current behaviour but allow to initialize phy 
first on demand.



Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-05-26 Thread Fabien Lahoudere
Hello

I modify ci_hrdc_imx_probe to bypass "data->phy = 
devm_usb_get_phy_by_phandle(>dev,
"fsl,usbphy", 0);". Everything works as expected and call ci_ulpi_init.

The problem is that in ci_ulpi_init, before calling "ci->ulpi = 
ulpi_register_interface(ci->dev,
>ulpi_ops);" (to initialize our phy), "hw_phymode_configure(ci);" is called 
which is the
original function that make our system to hang.

Our phy is not initialised before calling ulpi_register_interface so I don't 
understand how the phy
can reply if it is not out of reset state.

The conclusion is that using ulpi_bus to manage our phy doesn't improve and we 
reach the same issue.

I will try to check if we don't do bad things in hw_phymode_configure.
If anyone have an idea it is welcome??

Fabien

On Thu, 2017-05-25 at 12:36 +0200, Fabien Lahoudere wrote:
> On Tue, 2017-05-23 at 14:00 -0700, Stephen Boyd wrote:
> > On 05/23, Fabien Lahoudere wrote:
> > > Hi,
> > > 
> > > We investigate on the topic and now our device tree look like:
> > > 
> > > in imx53.dtsi:
> > > 
> > > usbh2: usb@53f80400 {
> > >   compatible = "fsl,imx53-usb", "fsl,imx27-usb";
> > > reg = <0x53f80400 0x0200>;
> > > interrupts = <16>;
> > > clocks = < IMX5_CLK_USBOH3_GATE>;
> > > fsl,usbmisc = < 2>;
> > > dr_mode = "host";
> > > status = "disabled";
> > > };
> > > 
> > > usbmisc: usbmisc@53f80800 {
> > >   #index-cells = <1>;
> > >   compatible = "fsl,imx53-usbmisc";
> > >   reg = <0x53f80800 0x200>;
> > >   clocks = < IMX5_CLK_USBOH3_GATE>;
> > > };
> > > 
> > > and in our dts:
> > > 
> > >  {
> > > pinctrl-names = "default";
> > >   pinctrl-0 = <_usbh2>;
> > >   disable-int60ck;
> > > dr_mode = "host";
> > > //fsl,usbphy = <>;
> > > vbus-supply = <_usbh2_vbus>;
> > > status = "okay";
> > >   ulpi {
> > > phy {
> > > compatible = "smsc,usb3315-ulpi";
> > > reset-gpios = < 4 GPIO_ACTIVE_LOW>;
> > >   clock-names = "main_clk";
> > >   /*
> > >  * Hardware uses CKO2 at 24MHz at several places. 
> > > Set the parent
> > >    *  clock of CKO2 to OSC.
> > >  */
> > >   clock-frequency = <2400>;
> > >   clocks = < IMX5_CLK_CKO2>;
> > > assigned-clocks = < IMX5_CLK_CKO2_SEL>, 
> > > < IMX5_CLK_OSC>;
> > >   assigned-clock-parents = < IMX5_CLK_OSC>;
> > > status = "okay";
> > > };
> > > };
> > > };
> > > 
> > > And we create a basic driver to check what happened:
> > > 
> > > static int smsc_usb3315_phy_probe(struct ulpi *ulpi)
> > > {
> > > printk(KERN_ERR "Fabien: %s:%d-%s\n", __FILE__, __LINE__, 
> > > __func__);
> > > 
> > > return 0;
> > > }
> > > 
> > > static const struct of_device_id smsc_usb3315_phy_match[] = {
> > > { .compatible = "smsc,usb3315-phy", },
> > > { }
> > > };
> > > MODULE_DEVICE_TABLE(of, smsc_usb3315_phy_match);
> > > 
> > > static struct ulpi_driver smsc_usb3315_phy_driver = {
> > > .probe = smsc_usb3315_phy_probe,
> > > .driver = {
> > > .name = "smsc_usb3315_phy",
> > > .of_match_table = smsc_usb3315_phy_match,
> > > },
> > > };
> > > module_ulpi_driver(smsc_usb3315_phy_driver);
> > > 
> > > /*MODULE_ALIAS("platform:usb_phy_generic");*/
> > > MODULE_AUTHOR("GE Healthcare");
> > > MODULE_DESCRIPTION("SMSC USB 3315 ULPI Phy driver");
> > > MODULE_LICENSE("GPL v2");
> > > 
> > > I checked that the driver is registered by 
> > > drivers/usb/common/ulpi.c:__ulpi_register_driver
> > > successfully.
> > 
> > Does the ulpi device have some vendor/product ids associated
> > with it? The design is made to only fallback to matching the
> > device to driver based on DT if the ulpi vendor id is 0.
> > Otherwise, if vendor is non-zero you'll need to have a
> > ulpi_device_id id table in your ulpi_driver structure.
> > 
> 
> Hi,
> 
> Thanks Stephen for your reply.
> Indeed we have a vendor/product so I modify my code but without effect.
> 
> After looking at the ulpi source code in the kernel, it seems that I need to 
> call
> ulpi_register_interface. ci_hdrc_probe should be called to execute the ulpi 
> init.
> 
> The problem is that we replace "fsl,usbphy = <>;" by an ulpi node but 
> ci_hdrc_imx_probe
> fail
> because of "data->phy = devm_usb_get_phy_by_phandle(>dev, "fsl,usbphy", 
> 0);"
> 
> So I will try to adapt ci_hdrc_imx_probe to continue phy initialisation if 
> fsl,usbphy is missing.
> Is it the good way to proceed?
> 
> Thanks for any advice
> Fabien
> 


Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-05-26 Thread Fabien Lahoudere
Hello

I modify ci_hrdc_imx_probe to bypass "data->phy = 
devm_usb_get_phy_by_phandle(>dev,
"fsl,usbphy", 0);". Everything works as expected and call ci_ulpi_init.

The problem is that in ci_ulpi_init, before calling "ci->ulpi = 
ulpi_register_interface(ci->dev,
>ulpi_ops);" (to initialize our phy), "hw_phymode_configure(ci);" is called 
which is the
original function that make our system to hang.

Our phy is not initialised before calling ulpi_register_interface so I don't 
understand how the phy
can reply if it is not out of reset state.

The conclusion is that using ulpi_bus to manage our phy doesn't improve and we 
reach the same issue.

I will try to check if we don't do bad things in hw_phymode_configure.
If anyone have an idea it is welcome??

Fabien

On Thu, 2017-05-25 at 12:36 +0200, Fabien Lahoudere wrote:
> On Tue, 2017-05-23 at 14:00 -0700, Stephen Boyd wrote:
> > On 05/23, Fabien Lahoudere wrote:
> > > Hi,
> > > 
> > > We investigate on the topic and now our device tree look like:
> > > 
> > > in imx53.dtsi:
> > > 
> > > usbh2: usb@53f80400 {
> > >   compatible = "fsl,imx53-usb", "fsl,imx27-usb";
> > > reg = <0x53f80400 0x0200>;
> > > interrupts = <16>;
> > > clocks = < IMX5_CLK_USBOH3_GATE>;
> > > fsl,usbmisc = < 2>;
> > > dr_mode = "host";
> > > status = "disabled";
> > > };
> > > 
> > > usbmisc: usbmisc@53f80800 {
> > >   #index-cells = <1>;
> > >   compatible = "fsl,imx53-usbmisc";
> > >   reg = <0x53f80800 0x200>;
> > >   clocks = < IMX5_CLK_USBOH3_GATE>;
> > > };
> > > 
> > > and in our dts:
> > > 
> > >  {
> > > pinctrl-names = "default";
> > >   pinctrl-0 = <_usbh2>;
> > >   disable-int60ck;
> > > dr_mode = "host";
> > > //fsl,usbphy = <>;
> > > vbus-supply = <_usbh2_vbus>;
> > > status = "okay";
> > >   ulpi {
> > > phy {
> > > compatible = "smsc,usb3315-ulpi";
> > > reset-gpios = < 4 GPIO_ACTIVE_LOW>;
> > >   clock-names = "main_clk";
> > >   /*
> > >  * Hardware uses CKO2 at 24MHz at several places. 
> > > Set the parent
> > >    *  clock of CKO2 to OSC.
> > >  */
> > >   clock-frequency = <2400>;
> > >   clocks = < IMX5_CLK_CKO2>;
> > > assigned-clocks = < IMX5_CLK_CKO2_SEL>, 
> > > < IMX5_CLK_OSC>;
> > >   assigned-clock-parents = < IMX5_CLK_OSC>;
> > > status = "okay";
> > > };
> > > };
> > > };
> > > 
> > > And we create a basic driver to check what happened:
> > > 
> > > static int smsc_usb3315_phy_probe(struct ulpi *ulpi)
> > > {
> > > printk(KERN_ERR "Fabien: %s:%d-%s\n", __FILE__, __LINE__, 
> > > __func__);
> > > 
> > > return 0;
> > > }
> > > 
> > > static const struct of_device_id smsc_usb3315_phy_match[] = {
> > > { .compatible = "smsc,usb3315-phy", },
> > > { }
> > > };
> > > MODULE_DEVICE_TABLE(of, smsc_usb3315_phy_match);
> > > 
> > > static struct ulpi_driver smsc_usb3315_phy_driver = {
> > > .probe = smsc_usb3315_phy_probe,
> > > .driver = {
> > > .name = "smsc_usb3315_phy",
> > > .of_match_table = smsc_usb3315_phy_match,
> > > },
> > > };
> > > module_ulpi_driver(smsc_usb3315_phy_driver);
> > > 
> > > /*MODULE_ALIAS("platform:usb_phy_generic");*/
> > > MODULE_AUTHOR("GE Healthcare");
> > > MODULE_DESCRIPTION("SMSC USB 3315 ULPI Phy driver");
> > > MODULE_LICENSE("GPL v2");
> > > 
> > > I checked that the driver is registered by 
> > > drivers/usb/common/ulpi.c:__ulpi_register_driver
> > > successfully.
> > 
> > Does the ulpi device have some vendor/product ids associated
> > with it? The design is made to only fallback to matching the
> > device to driver based on DT if the ulpi vendor id is 0.
> > Otherwise, if vendor is non-zero you'll need to have a
> > ulpi_device_id id table in your ulpi_driver structure.
> > 
> 
> Hi,
> 
> Thanks Stephen for your reply.
> Indeed we have a vendor/product so I modify my code but without effect.
> 
> After looking at the ulpi source code in the kernel, it seems that I need to 
> call
> ulpi_register_interface. ci_hdrc_probe should be called to execute the ulpi 
> init.
> 
> The problem is that we replace "fsl,usbphy = <>;" by an ulpi node but 
> ci_hdrc_imx_probe
> fail
> because of "data->phy = devm_usb_get_phy_by_phandle(>dev, "fsl,usbphy", 
> 0);"
> 
> So I will try to adapt ci_hdrc_imx_probe to continue phy initialisation if 
> fsl,usbphy is missing.
> Is it the good way to proceed?
> 
> Thanks for any advice
> Fabien
> 


Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-05-25 Thread Fabien Lahoudere
On Tue, 2017-05-23 at 14:00 -0700, Stephen Boyd wrote:
> On 05/23, Fabien Lahoudere wrote:
> > Hi,
> > 
> > We investigate on the topic and now our device tree look like:
> > 
> > in imx53.dtsi:
> > 
> > usbh2: usb@53f80400 {
> > compatible = "fsl,imx53-usb", "fsl,imx27-usb";
> > reg = <0x53f80400 0x0200>;
> > interrupts = <16>;
> > clocks = < IMX5_CLK_USBOH3_GATE>;
> > fsl,usbmisc = < 2>;
> > dr_mode = "host";
> > status = "disabled";
> > };
> > 
> > usbmisc: usbmisc@53f80800 {
> > #index-cells = <1>;
> > compatible = "fsl,imx53-usbmisc";
> > reg = <0x53f80800 0x200>;
> > clocks = < IMX5_CLK_USBOH3_GATE>;
> > };
> > 
> > and in our dts:
> > 
> >  {
> > pinctrl-names = "default";
> > pinctrl-0 = <_usbh2>;
> > disable-int60ck;
> > dr_mode = "host";
> > //fsl,usbphy = <>;
> > vbus-supply = <_usbh2_vbus>;
> > status = "okay";
> > ulpi {
> > phy {
> > compatible = "smsc,usb3315-ulpi";
> > reset-gpios = < 4 GPIO_ACTIVE_LOW>;
> > clock-names = "main_clk";
> > /*
> >  * Hardware uses CKO2 at 24MHz at several places. 
> > Set the parent
> >  *  clock of CKO2 to OSC.
> >  */
> > clock-frequency = <2400>;
> > clocks = < IMX5_CLK_CKO2>;
> > assigned-clocks = < IMX5_CLK_CKO2_SEL>, < 
> > IMX5_CLK_OSC>;
> > assigned-clock-parents = < IMX5_CLK_OSC>;
> > status = "okay";
> > };
> > };
> > };
> > 
> > And we create a basic driver to check what happened:
> > 
> > static int smsc_usb3315_phy_probe(struct ulpi *ulpi)
> > {
> > printk(KERN_ERR "Fabien: %s:%d-%s\n", __FILE__, __LINE__, __func__);
> > 
> > return 0;
> > }
> > 
> > static const struct of_device_id smsc_usb3315_phy_match[] = {
> > { .compatible = "smsc,usb3315-phy", },
> > { }
> > };
> > MODULE_DEVICE_TABLE(of, smsc_usb3315_phy_match);
> > 
> > static struct ulpi_driver smsc_usb3315_phy_driver = {
> > .probe = smsc_usb3315_phy_probe,
> > .driver = {
> > .name = "smsc_usb3315_phy",
> > .of_match_table = smsc_usb3315_phy_match,
> > },
> > };
> > module_ulpi_driver(smsc_usb3315_phy_driver);
> > 
> > /*MODULE_ALIAS("platform:usb_phy_generic");*/
> > MODULE_AUTHOR("GE Healthcare");
> > MODULE_DESCRIPTION("SMSC USB 3315 ULPI Phy driver");
> > MODULE_LICENSE("GPL v2");
> > 
> > I checked that the driver is registered by 
> > drivers/usb/common/ulpi.c:__ulpi_register_driver
> > successfully.
> 
> Does the ulpi device have some vendor/product ids associated
> with it? The design is made to only fallback to matching the
> device to driver based on DT if the ulpi vendor id is 0.
> Otherwise, if vendor is non-zero you'll need to have a
> ulpi_device_id id table in your ulpi_driver structure.
> 

Hi,

Thanks Stephen for your reply.
Indeed we have a vendor/product so I modify my code but without effect.

After looking at the ulpi source code in the kernel, it seems that I need to 
call
ulpi_register_interface. ci_hdrc_probe should be called to execute the ulpi 
init.

The problem is that we replace "fsl,usbphy = <>;" by an ulpi node but 
ci_hdrc_imx_probe fail
because of "data->phy = devm_usb_get_phy_by_phandle(>dev, "fsl,usbphy", 
0);"

So I will try to adapt ci_hdrc_imx_probe to continue phy initialisation if 
fsl,usbphy is missing.
Is it the good way to proceed?

Thanks for any advice
Fabien


Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-05-25 Thread Fabien Lahoudere
On Tue, 2017-05-23 at 14:00 -0700, Stephen Boyd wrote:
> On 05/23, Fabien Lahoudere wrote:
> > Hi,
> > 
> > We investigate on the topic and now our device tree look like:
> > 
> > in imx53.dtsi:
> > 
> > usbh2: usb@53f80400 {
> > compatible = "fsl,imx53-usb", "fsl,imx27-usb";
> > reg = <0x53f80400 0x0200>;
> > interrupts = <16>;
> > clocks = < IMX5_CLK_USBOH3_GATE>;
> > fsl,usbmisc = < 2>;
> > dr_mode = "host";
> > status = "disabled";
> > };
> > 
> > usbmisc: usbmisc@53f80800 {
> > #index-cells = <1>;
> > compatible = "fsl,imx53-usbmisc";
> > reg = <0x53f80800 0x200>;
> > clocks = < IMX5_CLK_USBOH3_GATE>;
> > };
> > 
> > and in our dts:
> > 
> >  {
> > pinctrl-names = "default";
> > pinctrl-0 = <_usbh2>;
> > disable-int60ck;
> > dr_mode = "host";
> > //fsl,usbphy = <>;
> > vbus-supply = <_usbh2_vbus>;
> > status = "okay";
> > ulpi {
> > phy {
> > compatible = "smsc,usb3315-ulpi";
> > reset-gpios = < 4 GPIO_ACTIVE_LOW>;
> > clock-names = "main_clk";
> > /*
> >  * Hardware uses CKO2 at 24MHz at several places. 
> > Set the parent
> >  *  clock of CKO2 to OSC.
> >  */
> > clock-frequency = <2400>;
> > clocks = < IMX5_CLK_CKO2>;
> > assigned-clocks = < IMX5_CLK_CKO2_SEL>, < 
> > IMX5_CLK_OSC>;
> > assigned-clock-parents = < IMX5_CLK_OSC>;
> > status = "okay";
> > };
> > };
> > };
> > 
> > And we create a basic driver to check what happened:
> > 
> > static int smsc_usb3315_phy_probe(struct ulpi *ulpi)
> > {
> > printk(KERN_ERR "Fabien: %s:%d-%s\n", __FILE__, __LINE__, __func__);
> > 
> > return 0;
> > }
> > 
> > static const struct of_device_id smsc_usb3315_phy_match[] = {
> > { .compatible = "smsc,usb3315-phy", },
> > { }
> > };
> > MODULE_DEVICE_TABLE(of, smsc_usb3315_phy_match);
> > 
> > static struct ulpi_driver smsc_usb3315_phy_driver = {
> > .probe = smsc_usb3315_phy_probe,
> > .driver = {
> > .name = "smsc_usb3315_phy",
> > .of_match_table = smsc_usb3315_phy_match,
> > },
> > };
> > module_ulpi_driver(smsc_usb3315_phy_driver);
> > 
> > /*MODULE_ALIAS("platform:usb_phy_generic");*/
> > MODULE_AUTHOR("GE Healthcare");
> > MODULE_DESCRIPTION("SMSC USB 3315 ULPI Phy driver");
> > MODULE_LICENSE("GPL v2");
> > 
> > I checked that the driver is registered by 
> > drivers/usb/common/ulpi.c:__ulpi_register_driver
> > successfully.
> 
> Does the ulpi device have some vendor/product ids associated
> with it? The design is made to only fallback to matching the
> device to driver based on DT if the ulpi vendor id is 0.
> Otherwise, if vendor is non-zero you'll need to have a
> ulpi_device_id id table in your ulpi_driver structure.
> 

Hi,

Thanks Stephen for your reply.
Indeed we have a vendor/product so I modify my code but without effect.

After looking at the ulpi source code in the kernel, it seems that I need to 
call
ulpi_register_interface. ci_hdrc_probe should be called to execute the ulpi 
init.

The problem is that we replace "fsl,usbphy = <>;" by an ulpi node but 
ci_hdrc_imx_probe fail
because of "data->phy = devm_usb_get_phy_by_phandle(>dev, "fsl,usbphy", 
0);"

So I will try to adapt ci_hdrc_imx_probe to continue phy initialisation if 
fsl,usbphy is missing.
Is it the good way to proceed?

Thanks for any advice
Fabien


Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-05-23 Thread Fabien Lahoudere
Hi,

We investigate on the topic and now our device tree look like:

in imx53.dtsi:

usbh2: usb@53f80400 {
compatible = "fsl,imx53-usb", "fsl,imx27-usb";
reg = <0x53f80400 0x0200>;
interrupts = <16>;
clocks = < IMX5_CLK_USBOH3_GATE>;
fsl,usbmisc = < 2>;
dr_mode = "host";
status = "disabled";
};

usbmisc: usbmisc@53f80800 {
#index-cells = <1>;
compatible = "fsl,imx53-usbmisc";
reg = <0x53f80800 0x200>;
clocks = < IMX5_CLK_USBOH3_GATE>;
};

and in our dts:

 {
pinctrl-names = "default";
pinctrl-0 = <_usbh2>;
disable-int60ck;
dr_mode = "host";
//fsl,usbphy = <>;
vbus-supply = <_usbh2_vbus>;
status = "okay";
ulpi {
phy {
compatible = "smsc,usb3315-ulpi";
reset-gpios = < 4 GPIO_ACTIVE_LOW>;
clock-names = "main_clk";
/*
 * Hardware uses CKO2 at 24MHz at several places. Set 
the parent
 *  clock of CKO2 to OSC.
 */
clock-frequency = <2400>;
clocks = < IMX5_CLK_CKO2>;
assigned-clocks = < IMX5_CLK_CKO2_SEL>, < 
IMX5_CLK_OSC>;
assigned-clock-parents = < IMX5_CLK_OSC>;
status = "okay";
};
};
};

And we create a basic driver to check what happened:

static int smsc_usb3315_phy_probe(struct ulpi *ulpi)
{
printk(KERN_ERR "Fabien: %s:%d-%s\n", __FILE__, __LINE__, __func__);

return 0;
}

static const struct of_device_id smsc_usb3315_phy_match[] = {
{ .compatible = "smsc,usb3315-phy", },
{ }
};
MODULE_DEVICE_TABLE(of, smsc_usb3315_phy_match);

static struct ulpi_driver smsc_usb3315_phy_driver = {
.probe = smsc_usb3315_phy_probe,
.driver = {
.name = "smsc_usb3315_phy",
.of_match_table = smsc_usb3315_phy_match,
},
};
module_ulpi_driver(smsc_usb3315_phy_driver);

/*MODULE_ALIAS("platform:usb_phy_generic");*/
MODULE_AUTHOR("GE Healthcare");
MODULE_DESCRIPTION("SMSC USB 3315 ULPI Phy driver");
MODULE_LICENSE("GPL v2");

I checked that the driver is registered by 
drivers/usb/common/ulpi.c:__ulpi_register_driver
successfully.

But our probe function (smsc_usb3315_phy_probe) is never called.

Our understanding is that we need to use the ulpi_bus instead of 
devm_usb_get_phy_by_phandle(
>dev, "fsl,usbphy", 0); in drivers/usb/chipidea/ci_hdrc_imx.c.

Is our approach good?
How can we use this bus from our controller probe function ?

Thanks
Fabien

On Thu, 2017-04-20 at 16:50 +0800, Peter Chen wrote:
> On Wed, Apr 19, 2017 at 06:14:13AM +, Peter Senna Tschudin wrote:
> > We need the SMSC USB3315 clock and regulator to always be initialized.
> > We also need the PHY driver to take the PHY out of reset. This patch
> > extends the existing USB generic nop phy driver to include a new
> > initialization path.
> > 
> > A new compatible string "smsc,usb3315" is used to decide which
> > initialization path to use.
> > 
> 
> Hi Peter,
> 
> This is an ULPI PHY, so it is not suitable using generic USB PHY.
> Taking a look of drivers/phy/phy-qcom-usb-hs.c, you may have some
> clues.
> 
> Peter
> 
> > CC: Peter Chen <peter.c...@nxp.com>
> > CC: Stephen Boyd <sb...@codeaurora.org>
> > CC: Fabien Lahoudere <fabien.lahoud...@collabora.co.uk>
> > Signed-off-by: Peter Senna Tschudin <peter.se...@collabora.com>
> > ---
> > 
> > This is a follow-up of previous discussion:
> >   https://www.spinics.net/lists/linux-usb/msg146680.html
> > 
> >  drivers/usb/phy/phy-generic.c | 33 +
> >  drivers/usb/phy/phy-generic.h |  1 +
> >  2 files changed, 30 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
> > index 89d6e7a..6ea9ce4 100644
> > --- a/drivers/usb/phy/phy-generic.c
> > +++ b/drivers/usb/phy/phy-generic.c
> > @@ -151,6 +151,9 @@ int usb_gen_phy_init(struct usb_phy *phy)
> >     struct usb_phy_generic *nop = dev_get_drvdata(phy->dev);
> >     int ret;
> >  
> > +   if (nop->init_done)
> > +   return 0;
> > +
> >     if (!IS_ERR(nop->vcc)) {
> >     if (regulator_enable(nop->vcc))
> >     

Re: [RFC] usb-phy-generic: Add support to SMSC USB3315

2017-05-23 Thread Fabien Lahoudere
Hi,

We investigate on the topic and now our device tree look like:

in imx53.dtsi:

usbh2: usb@53f80400 {
compatible = "fsl,imx53-usb", "fsl,imx27-usb";
reg = <0x53f80400 0x0200>;
interrupts = <16>;
clocks = < IMX5_CLK_USBOH3_GATE>;
fsl,usbmisc = < 2>;
dr_mode = "host";
status = "disabled";
};

usbmisc: usbmisc@53f80800 {
#index-cells = <1>;
compatible = "fsl,imx53-usbmisc";
reg = <0x53f80800 0x200>;
clocks = < IMX5_CLK_USBOH3_GATE>;
};

and in our dts:

 {
pinctrl-names = "default";
pinctrl-0 = <_usbh2>;
disable-int60ck;
dr_mode = "host";
//fsl,usbphy = <>;
vbus-supply = <_usbh2_vbus>;
status = "okay";
ulpi {
phy {
compatible = "smsc,usb3315-ulpi";
reset-gpios = < 4 GPIO_ACTIVE_LOW>;
clock-names = "main_clk";
/*
 * Hardware uses CKO2 at 24MHz at several places. Set 
the parent
 *  clock of CKO2 to OSC.
 */
clock-frequency = <2400>;
clocks = < IMX5_CLK_CKO2>;
assigned-clocks = < IMX5_CLK_CKO2_SEL>, < 
IMX5_CLK_OSC>;
assigned-clock-parents = < IMX5_CLK_OSC>;
status = "okay";
};
};
};

And we create a basic driver to check what happened:

static int smsc_usb3315_phy_probe(struct ulpi *ulpi)
{
printk(KERN_ERR "Fabien: %s:%d-%s\n", __FILE__, __LINE__, __func__);

return 0;
}

static const struct of_device_id smsc_usb3315_phy_match[] = {
{ .compatible = "smsc,usb3315-phy", },
{ }
};
MODULE_DEVICE_TABLE(of, smsc_usb3315_phy_match);

static struct ulpi_driver smsc_usb3315_phy_driver = {
.probe = smsc_usb3315_phy_probe,
.driver = {
.name = "smsc_usb3315_phy",
.of_match_table = smsc_usb3315_phy_match,
},
};
module_ulpi_driver(smsc_usb3315_phy_driver);

/*MODULE_ALIAS("platform:usb_phy_generic");*/
MODULE_AUTHOR("GE Healthcare");
MODULE_DESCRIPTION("SMSC USB 3315 ULPI Phy driver");
MODULE_LICENSE("GPL v2");

I checked that the driver is registered by 
drivers/usb/common/ulpi.c:__ulpi_register_driver
successfully.

But our probe function (smsc_usb3315_phy_probe) is never called.

Our understanding is that we need to use the ulpi_bus instead of 
devm_usb_get_phy_by_phandle(
>dev, "fsl,usbphy", 0); in drivers/usb/chipidea/ci_hdrc_imx.c.

Is our approach good?
How can we use this bus from our controller probe function ?

Thanks
Fabien

On Thu, 2017-04-20 at 16:50 +0800, Peter Chen wrote:
> On Wed, Apr 19, 2017 at 06:14:13AM +, Peter Senna Tschudin wrote:
> > We need the SMSC USB3315 clock and regulator to always be initialized.
> > We also need the PHY driver to take the PHY out of reset. This patch
> > extends the existing USB generic nop phy driver to include a new
> > initialization path.
> > 
> > A new compatible string "smsc,usb3315" is used to decide which
> > initialization path to use.
> > 
> 
> Hi Peter,
> 
> This is an ULPI PHY, so it is not suitable using generic USB PHY.
> Taking a look of drivers/phy/phy-qcom-usb-hs.c, you may have some
> clues.
> 
> Peter
> 
> > CC: Peter Chen 
> > CC: Stephen Boyd 
> > CC: Fabien Lahoudere 
> > Signed-off-by: Peter Senna Tschudin 
> > ---
> > 
> > This is a follow-up of previous discussion:
> >   https://www.spinics.net/lists/linux-usb/msg146680.html
> > 
> >  drivers/usb/phy/phy-generic.c | 33 +
> >  drivers/usb/phy/phy-generic.h |  1 +
> >  2 files changed, 30 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
> > index 89d6e7a..6ea9ce4 100644
> > --- a/drivers/usb/phy/phy-generic.c
> > +++ b/drivers/usb/phy/phy-generic.c
> > @@ -151,6 +151,9 @@ int usb_gen_phy_init(struct usb_phy *phy)
> >     struct usb_phy_generic *nop = dev_get_drvdata(phy->dev);
> >     int ret;
> >  
> > +   if (nop->init_done)
> > +   return 0;
> > +
> >     if (!IS_ERR(nop->vcc)) {
> >     if (regulator_enable(nop->vcc))
> >     dev_err(phy->dev, "Failed to enable power\n");
> > @@ -164,6 +167,8 @@ int usb_gen_phy_init(struct usb

[PATCH v3 1/1] ahci: imx: Add imx53 SATA temperature sensor support

2016-10-25 Thread Fabien Lahoudere
From: Csaba Kertesz <csaba.kert...@vincit.fi>

Add a hwmon entry to get the temperature from the die of imx53
SATA.

The original patch was made by Richard Zhu for kernel 2.6.x:
ENGR00134041-MX53-Add-the-SATA-AHCI-temperature-monitor.patch

Signed-off-by: Fabien Lahoudere <fabien.lahoud...@collabora.co.uk>
---
 drivers/ata/ahci_imx.c | 195 +
 1 file changed, 195 insertions(+)

diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 3f3a7db..420f065 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -26,6 +26,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include "ahci.h"
 
 #define DRV_NAME "ahci-imx"
@@ -214,6 +217,180 @@ static int imx_sata_phy_reset(struct ahci_host_priv 
*hpriv)
return timeout ? 0 : -ETIMEDOUT;
 }
 
+enum {
+   /* SATA PHY Register */
+   SATA_PHY_CR_CLOCK_CRCMP_LT_LIMIT = 0x0001,
+   SATA_PHY_CR_CLOCK_DAC_CTL = 0x0008,
+   SATA_PHY_CR_CLOCK_RTUNE_CTL = 0x0009,
+   SATA_PHY_CR_CLOCK_ADC_OUT = 0x000A,
+   SATA_PHY_CR_CLOCK_MPLL_TST = 0x0017,
+};
+
+static int read_adc_sum(void *dev, u16 rtune_ctl_reg, void __iomem * mmio)
+{
+   u16 adc_out_reg, read_sum;
+   u32 index, read_attempt;
+   const u32 attempt_limit = 100;
+
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
+   imx_phy_reg_write(rtune_ctl_reg, mmio);
+
+   /* two dummy read */
+   index = 0;
+   read_attempt = 0;
+   adc_out_reg = 0;
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_ADC_OUT, mmio);
+   while (index < 2) {
+   imx_phy_reg_read(_out_reg, mmio);
+   /* check if valid */
+   if (adc_out_reg & 0x400)
+   index++;
+
+   read_attempt++;
+   if (read_attempt > attempt_limit) {
+   dev_err(dev, "Read REG more than %d times!\n",
+   attempt_limit);
+   break;
+   }
+   }
+
+   index = 0;
+   read_attempt = 0;
+   read_sum = 0;
+   while (index < 80) {
+   imx_phy_reg_read(_out_reg, mmio);
+   if (adc_out_reg & 0x400) {
+   read_sum = read_sum + (adc_out_reg & 0x3FF);
+   index++;
+   }
+   read_attempt++;
+   if (read_attempt > attempt_limit) {
+   dev_err(dev, "Read REG more than %d times!\n",
+   attempt_limit);
+   break;
+   }
+   }
+
+   /* Use the U32 to make 1000 precision */
+   return (read_sum * 1000) / 80;
+}
+
+/* SATA AHCI temperature monitor */
+static int sata_ahci_read_temperature(void *dev, int *temp)
+{
+   u16 mpll_test_reg, rtune_ctl_reg, dac_ctl_reg, read_sum;
+   u32 str1, str2, str3, str4;
+   int m1, m2, a;
+   struct ahci_host_priv *hpriv = dev_get_drvdata(dev);
+   void __iomem *mmio = hpriv->mmio;
+
+   /* check rd-wr to reg */
+   read_sum = 0;
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_CRCMP_LT_LIMIT, mmio);
+   imx_phy_reg_write(read_sum, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   imx_phy_reg_write(0x5A5A, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0x5A5A)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   imx_phy_reg_write(0x1234, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0x1234)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   /* start temperature test */
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_MPLL_TST, mmio);
+   imx_phy_reg_read(_test_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
+   imx_phy_reg_read(_ctl_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_DAC_CTL, mmio);
+   imx_phy_reg_read(_ctl_reg, mmio);
+
+   /* mpll_tst.meas_iv   ([12:2]) */
+   str1 = (mpll_test_reg >> 2) & 0x7FF;
+   /* rtune_ctl.mode ([1:0]) */
+   str2 = (rtune_ctl_reg) & 0x3;
+   /* dac_ctl.dac_mode   ([14:12]) */
+   str3 = (dac_ctl_reg >> 12)  & 0x7;
+   /* rtune_ctl.sel_atbp ([4]) */
+   str4 = (rtune_ctl_reg >> 4);
+
+   /* Calculate the m1 */
+   /* mpll_tst.meas_iv */
+   mpll_test_reg = (mpll_test_reg & 0xE03) | (512) << 2;
+   /* rtune_ctl.mode */
+   rtune_ctl_reg = (rtune_ctl_reg & 0xFFC) | (1);
+   /* dac_ctl.dac_mode */
+   dac_ctl_reg = (dac_ctl_reg & 0x8FF) | (4) << 12;
+   /* rtune_ctl.sel_atbp */
+   rtune_ctl_reg = (rtun

[PATCH v3 1/1] ahci: imx: Add imx53 SATA temperature sensor support

2016-10-25 Thread Fabien Lahoudere
From: Csaba Kertesz 

Add a hwmon entry to get the temperature from the die of imx53
SATA.

The original patch was made by Richard Zhu for kernel 2.6.x:
ENGR00134041-MX53-Add-the-SATA-AHCI-temperature-monitor.patch

Signed-off-by: Fabien Lahoudere 
---
 drivers/ata/ahci_imx.c | 195 +
 1 file changed, 195 insertions(+)

diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 3f3a7db..420f065 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -26,6 +26,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include "ahci.h"
 
 #define DRV_NAME "ahci-imx"
@@ -214,6 +217,180 @@ static int imx_sata_phy_reset(struct ahci_host_priv 
*hpriv)
return timeout ? 0 : -ETIMEDOUT;
 }
 
+enum {
+   /* SATA PHY Register */
+   SATA_PHY_CR_CLOCK_CRCMP_LT_LIMIT = 0x0001,
+   SATA_PHY_CR_CLOCK_DAC_CTL = 0x0008,
+   SATA_PHY_CR_CLOCK_RTUNE_CTL = 0x0009,
+   SATA_PHY_CR_CLOCK_ADC_OUT = 0x000A,
+   SATA_PHY_CR_CLOCK_MPLL_TST = 0x0017,
+};
+
+static int read_adc_sum(void *dev, u16 rtune_ctl_reg, void __iomem * mmio)
+{
+   u16 adc_out_reg, read_sum;
+   u32 index, read_attempt;
+   const u32 attempt_limit = 100;
+
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
+   imx_phy_reg_write(rtune_ctl_reg, mmio);
+
+   /* two dummy read */
+   index = 0;
+   read_attempt = 0;
+   adc_out_reg = 0;
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_ADC_OUT, mmio);
+   while (index < 2) {
+   imx_phy_reg_read(_out_reg, mmio);
+   /* check if valid */
+   if (adc_out_reg & 0x400)
+   index++;
+
+   read_attempt++;
+   if (read_attempt > attempt_limit) {
+   dev_err(dev, "Read REG more than %d times!\n",
+   attempt_limit);
+   break;
+   }
+   }
+
+   index = 0;
+   read_attempt = 0;
+   read_sum = 0;
+   while (index < 80) {
+   imx_phy_reg_read(_out_reg, mmio);
+   if (adc_out_reg & 0x400) {
+   read_sum = read_sum + (adc_out_reg & 0x3FF);
+   index++;
+   }
+   read_attempt++;
+   if (read_attempt > attempt_limit) {
+   dev_err(dev, "Read REG more than %d times!\n",
+   attempt_limit);
+   break;
+   }
+   }
+
+   /* Use the U32 to make 1000 precision */
+   return (read_sum * 1000) / 80;
+}
+
+/* SATA AHCI temperature monitor */
+static int sata_ahci_read_temperature(void *dev, int *temp)
+{
+   u16 mpll_test_reg, rtune_ctl_reg, dac_ctl_reg, read_sum;
+   u32 str1, str2, str3, str4;
+   int m1, m2, a;
+   struct ahci_host_priv *hpriv = dev_get_drvdata(dev);
+   void __iomem *mmio = hpriv->mmio;
+
+   /* check rd-wr to reg */
+   read_sum = 0;
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_CRCMP_LT_LIMIT, mmio);
+   imx_phy_reg_write(read_sum, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   imx_phy_reg_write(0x5A5A, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0x5A5A)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   imx_phy_reg_write(0x1234, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0x1234)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   /* start temperature test */
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_MPLL_TST, mmio);
+   imx_phy_reg_read(_test_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
+   imx_phy_reg_read(_ctl_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_DAC_CTL, mmio);
+   imx_phy_reg_read(_ctl_reg, mmio);
+
+   /* mpll_tst.meas_iv   ([12:2]) */
+   str1 = (mpll_test_reg >> 2) & 0x7FF;
+   /* rtune_ctl.mode ([1:0]) */
+   str2 = (rtune_ctl_reg) & 0x3;
+   /* dac_ctl.dac_mode   ([14:12]) */
+   str3 = (dac_ctl_reg >> 12)  & 0x7;
+   /* rtune_ctl.sel_atbp ([4]) */
+   str4 = (rtune_ctl_reg >> 4);
+
+   /* Calculate the m1 */
+   /* mpll_tst.meas_iv */
+   mpll_test_reg = (mpll_test_reg & 0xE03) | (512) << 2;
+   /* rtune_ctl.mode */
+   rtune_ctl_reg = (rtune_ctl_reg & 0xFFC) | (1);
+   /* dac_ctl.dac_mode */
+   dac_ctl_reg = (dac_ctl_reg & 0x8FF) | (4) << 12;
+   /* rtune_ctl.sel_atbp */
+   rtune_ctl_reg = (rtune_ctl_reg & 0xFEF) | (0) << 4;
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_

[PATCH v2 1/1] ahci: imx: Add imx53 SATA temperature sensor support

2016-10-21 Thread Fabien Lahoudere
From: Csaba Kertesz <csaba.kert...@vincit.fi>

Add a hwmon entry to get the temperature from the die of imx53
SATA.

The original patch was made by Richard Zhu for kernel 2.6.x:
ENGR00134041-MX53-Add-the-SATA-AHCI-temperature-monitor.patch

Signed-off-by: Fabien Lahoudere <fabien.lahoud...@collabora.co.uk>
---
 drivers/ata/ahci_imx.c | 225 +
 1 file changed, 225 insertions(+)

diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 3f3a7db..a2a8c63 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -26,6 +26,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include "ahci.h"
 
 #define DRV_NAME "ahci-imx"
@@ -214,6 +217,210 @@ static int imx_sata_phy_reset(struct ahci_host_priv 
*hpriv)
return timeout ? 0 : -ETIMEDOUT;
 }
 
+enum {
+   /* SATA PHY Register */
+   SATA_PHY_CR_CLOCK_CRCMP_LT_LIMIT = 0x0001,
+   SATA_PHY_CR_CLOCK_DAC_CTL = 0x0008,
+   SATA_PHY_CR_CLOCK_RTUNE_CTL = 0x0009,
+   SATA_PHY_CR_CLOCK_ADC_OUT = 0x000A,
+   SATA_PHY_CR_CLOCK_MPLL_TST = 0x0017,
+};
+
+/* SATA AHCI temperature monitor */
+static int sata_ahci_read_temperature(void *dev, int *temp)
+{
+   u16 mpll_test_reg, rtune_ctl_reg, dac_ctl_reg, adc_out_reg, read_sum;
+   u32 str1, str2, str3, str4, index, read_attempt;
+   const u32 attempt_limit = 100;
+   int m1, m2, a;
+   struct ahci_host_priv *hpriv = dev_get_drvdata(dev);
+   void __iomem *mmio = hpriv->mmio;
+
+   /* check rd-wr to reg */
+   read_sum = 0;
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_CRCMP_LT_LIMIT, mmio);
+   imx_phy_reg_write(read_sum, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   imx_phy_reg_write(0x5A5A, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0x5A5A)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   imx_phy_reg_write(0x1234, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0x1234)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   /* start temperature test */
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_MPLL_TST, mmio);
+   imx_phy_reg_read(_test_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
+   imx_phy_reg_read(_ctl_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_DAC_CTL, mmio);
+   imx_phy_reg_read(_ctl_reg, mmio);
+
+   /* mpll_tst.meas_iv   ([12:2]) */
+   str1 = (mpll_test_reg >> 2) & 0x7FF;
+   /* rtune_ctl.mode ([1:0]) */
+   str2 = (rtune_ctl_reg) & 0x3;
+   /* dac_ctl.dac_mode   ([14:12]) */
+   str3 = (dac_ctl_reg >> 12)  & 0x7;
+   /* rtune_ctl.sel_atbp ([4]) */
+   str4 = (rtune_ctl_reg >> 4);
+
+   /* Calculate the m1 */
+   /* mpll_tst.meas_iv */
+   mpll_test_reg = (mpll_test_reg & 0xE03) | (512) << 2;
+   /* rtune_ctl.mode */
+   rtune_ctl_reg = (rtune_ctl_reg & 0xFFC) | (1);
+   /* dac_ctl.dac_mode */
+   dac_ctl_reg = (dac_ctl_reg & 0x8FF) | (4) << 12;
+   /* rtune_ctl.sel_atbp */
+   rtune_ctl_reg = (rtune_ctl_reg & 0xFEF) | (0) << 4;
+
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_MPLL_TST, mmio);
+   imx_phy_reg_write(mpll_test_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_DAC_CTL, mmio);
+   imx_phy_reg_write(dac_ctl_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
+   imx_phy_reg_write(rtune_ctl_reg, mmio);
+
+   /* two dummy read */
+   index = 0;
+   read_attempt = 0;
+   adc_out_reg = 0;
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_ADC_OUT, mmio);
+   while (index < 2) {
+   imx_phy_reg_read(_out_reg, mmio);
+   /* check if valid */
+   if (adc_out_reg & 0x400)
+   index++;
+
+   read_attempt++;
+   if (read_attempt > attempt_limit) {
+   dev_err(dev, "Read REG more than %d times!\n",
+   attempt_limit);
+   break;
+   }
+   }
+
+   index = 0;
+   read_attempt = 0;
+   read_sum = 0;
+   while (index < 80) {
+   imx_phy_reg_read(_out_reg, mmio);
+   if (adc_out_reg & 0x400) {
+   read_sum = read_sum + (adc_out_reg & 0x3FF);
+   index++;
+   }
+   read_attempt++;
+   if (read_attempt > attempt_limit) {
+   dev_err(dev, "Read REG more than %d times!\n",
+   attem

[PATCH v2 1/1] ahci: imx: Add imx53 SATA temperature sensor support

2016-10-21 Thread Fabien Lahoudere
From: Csaba Kertesz 

Add a hwmon entry to get the temperature from the die of imx53
SATA.

The original patch was made by Richard Zhu for kernel 2.6.x:
ENGR00134041-MX53-Add-the-SATA-AHCI-temperature-monitor.patch

Signed-off-by: Fabien Lahoudere 
---
 drivers/ata/ahci_imx.c | 225 +
 1 file changed, 225 insertions(+)

diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 3f3a7db..a2a8c63 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -26,6 +26,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include "ahci.h"
 
 #define DRV_NAME "ahci-imx"
@@ -214,6 +217,210 @@ static int imx_sata_phy_reset(struct ahci_host_priv 
*hpriv)
return timeout ? 0 : -ETIMEDOUT;
 }
 
+enum {
+   /* SATA PHY Register */
+   SATA_PHY_CR_CLOCK_CRCMP_LT_LIMIT = 0x0001,
+   SATA_PHY_CR_CLOCK_DAC_CTL = 0x0008,
+   SATA_PHY_CR_CLOCK_RTUNE_CTL = 0x0009,
+   SATA_PHY_CR_CLOCK_ADC_OUT = 0x000A,
+   SATA_PHY_CR_CLOCK_MPLL_TST = 0x0017,
+};
+
+/* SATA AHCI temperature monitor */
+static int sata_ahci_read_temperature(void *dev, int *temp)
+{
+   u16 mpll_test_reg, rtune_ctl_reg, dac_ctl_reg, adc_out_reg, read_sum;
+   u32 str1, str2, str3, str4, index, read_attempt;
+   const u32 attempt_limit = 100;
+   int m1, m2, a;
+   struct ahci_host_priv *hpriv = dev_get_drvdata(dev);
+   void __iomem *mmio = hpriv->mmio;
+
+   /* check rd-wr to reg */
+   read_sum = 0;
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_CRCMP_LT_LIMIT, mmio);
+   imx_phy_reg_write(read_sum, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   imx_phy_reg_write(0x5A5A, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0x5A5A)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   imx_phy_reg_write(0x1234, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0x1234)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   /* start temperature test */
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_MPLL_TST, mmio);
+   imx_phy_reg_read(_test_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
+   imx_phy_reg_read(_ctl_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_DAC_CTL, mmio);
+   imx_phy_reg_read(_ctl_reg, mmio);
+
+   /* mpll_tst.meas_iv   ([12:2]) */
+   str1 = (mpll_test_reg >> 2) & 0x7FF;
+   /* rtune_ctl.mode ([1:0]) */
+   str2 = (rtune_ctl_reg) & 0x3;
+   /* dac_ctl.dac_mode   ([14:12]) */
+   str3 = (dac_ctl_reg >> 12)  & 0x7;
+   /* rtune_ctl.sel_atbp ([4]) */
+   str4 = (rtune_ctl_reg >> 4);
+
+   /* Calculate the m1 */
+   /* mpll_tst.meas_iv */
+   mpll_test_reg = (mpll_test_reg & 0xE03) | (512) << 2;
+   /* rtune_ctl.mode */
+   rtune_ctl_reg = (rtune_ctl_reg & 0xFFC) | (1);
+   /* dac_ctl.dac_mode */
+   dac_ctl_reg = (dac_ctl_reg & 0x8FF) | (4) << 12;
+   /* rtune_ctl.sel_atbp */
+   rtune_ctl_reg = (rtune_ctl_reg & 0xFEF) | (0) << 4;
+
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_MPLL_TST, mmio);
+   imx_phy_reg_write(mpll_test_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_DAC_CTL, mmio);
+   imx_phy_reg_write(dac_ctl_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
+   imx_phy_reg_write(rtune_ctl_reg, mmio);
+
+   /* two dummy read */
+   index = 0;
+   read_attempt = 0;
+   adc_out_reg = 0;
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_ADC_OUT, mmio);
+   while (index < 2) {
+   imx_phy_reg_read(_out_reg, mmio);
+   /* check if valid */
+   if (adc_out_reg & 0x400)
+   index++;
+
+   read_attempt++;
+   if (read_attempt > attempt_limit) {
+   dev_err(dev, "Read REG more than %d times!\n",
+   attempt_limit);
+   break;
+   }
+   }
+
+   index = 0;
+   read_attempt = 0;
+   read_sum = 0;
+   while (index < 80) {
+   imx_phy_reg_read(_out_reg, mmio);
+   if (adc_out_reg & 0x400) {
+   read_sum = read_sum + (adc_out_reg & 0x3FF);
+   index++;
+   }
+   read_attempt++;
+   if (read_attempt > attempt_limit) {
+   dev_err(dev, "Read REG more than %d times!\n",
+   attempt_limit);
+   break;
+   }
+   }
+   /* Use the U32 to make 

[PATCH v2 1/1] ahci: imx: Add imx53 SATA temperature sensor support

2016-10-17 Thread Fabien Lahoudere
From: Csaba Kertesz <csaba.kert...@vincit.fi>

Add a hwmon entry to get the temperature from the die of imx53
SATA.

The original patch was made by Richard Zhu for kernel 2.6.x:
ENGR00134041-MX53-Add-the-SATA-AHCI-temperature-monitor.patch

Signed-off-by: Fabien Lahoudere <fabien.lahoud...@collabora.co.uk>
---
 drivers/ata/ahci_imx.c | 225 +
 1 file changed, 225 insertions(+)

diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 3f3a7db..a2a8c63 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -26,6 +26,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include "ahci.h"
 
 #define DRV_NAME "ahci-imx"
@@ -214,6 +217,210 @@ static int imx_sata_phy_reset(struct ahci_host_priv 
*hpriv)
return timeout ? 0 : -ETIMEDOUT;
 }
 
+enum {
+   /* SATA PHY Register */
+   SATA_PHY_CR_CLOCK_CRCMP_LT_LIMIT = 0x0001,
+   SATA_PHY_CR_CLOCK_DAC_CTL = 0x0008,
+   SATA_PHY_CR_CLOCK_RTUNE_CTL = 0x0009,
+   SATA_PHY_CR_CLOCK_ADC_OUT = 0x000A,
+   SATA_PHY_CR_CLOCK_MPLL_TST = 0x0017,
+};
+
+/* SATA AHCI temperature monitor */
+static int sata_ahci_read_temperature(void *dev, int *temp)
+{
+   u16 mpll_test_reg, rtune_ctl_reg, dac_ctl_reg, adc_out_reg, read_sum;
+   u32 str1, str2, str3, str4, index, read_attempt;
+   const u32 attempt_limit = 100;
+   int m1, m2, a;
+   struct ahci_host_priv *hpriv = dev_get_drvdata(dev);
+   void __iomem *mmio = hpriv->mmio;
+
+   /* check rd-wr to reg */
+   read_sum = 0;
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_CRCMP_LT_LIMIT, mmio);
+   imx_phy_reg_write(read_sum, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   imx_phy_reg_write(0x5A5A, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0x5A5A)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   imx_phy_reg_write(0x1234, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0x1234)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   /* start temperature test */
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_MPLL_TST, mmio);
+   imx_phy_reg_read(_test_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
+   imx_phy_reg_read(_ctl_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_DAC_CTL, mmio);
+   imx_phy_reg_read(_ctl_reg, mmio);
+
+   /* mpll_tst.meas_iv   ([12:2]) */
+   str1 = (mpll_test_reg >> 2) & 0x7FF;
+   /* rtune_ctl.mode ([1:0]) */
+   str2 = (rtune_ctl_reg) & 0x3;
+   /* dac_ctl.dac_mode   ([14:12]) */
+   str3 = (dac_ctl_reg >> 12)  & 0x7;
+   /* rtune_ctl.sel_atbp ([4]) */
+   str4 = (rtune_ctl_reg >> 4);
+
+   /* Calculate the m1 */
+   /* mpll_tst.meas_iv */
+   mpll_test_reg = (mpll_test_reg & 0xE03) | (512) << 2;
+   /* rtune_ctl.mode */
+   rtune_ctl_reg = (rtune_ctl_reg & 0xFFC) | (1);
+   /* dac_ctl.dac_mode */
+   dac_ctl_reg = (dac_ctl_reg & 0x8FF) | (4) << 12;
+   /* rtune_ctl.sel_atbp */
+   rtune_ctl_reg = (rtune_ctl_reg & 0xFEF) | (0) << 4;
+
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_MPLL_TST, mmio);
+   imx_phy_reg_write(mpll_test_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_DAC_CTL, mmio);
+   imx_phy_reg_write(dac_ctl_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
+   imx_phy_reg_write(rtune_ctl_reg, mmio);
+
+   /* two dummy read */
+   index = 0;
+   read_attempt = 0;
+   adc_out_reg = 0;
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_ADC_OUT, mmio);
+   while (index < 2) {
+   imx_phy_reg_read(_out_reg, mmio);
+   /* check if valid */
+   if (adc_out_reg & 0x400)
+   index++;
+
+   read_attempt++;
+   if (read_attempt > attempt_limit) {
+   dev_err(dev, "Read REG more than %d times!\n",
+   attempt_limit);
+   break;
+   }
+   }
+
+   index = 0;
+   read_attempt = 0;
+   read_sum = 0;
+   while (index < 80) {
+   imx_phy_reg_read(_out_reg, mmio);
+   if (adc_out_reg & 0x400) {
+   read_sum = read_sum + (adc_out_reg & 0x3FF);
+   index++;
+   }
+   read_attempt++;
+   if (read_attempt > attempt_limit) {
+   dev_err(dev, "Read REG more than %d times!\n",
+   attem

[PATCH v2 1/1] ahci: imx: Add imx53 SATA temperature sensor support

2016-10-17 Thread Fabien Lahoudere
From: Csaba Kertesz 

Add a hwmon entry to get the temperature from the die of imx53
SATA.

The original patch was made by Richard Zhu for kernel 2.6.x:
ENGR00134041-MX53-Add-the-SATA-AHCI-temperature-monitor.patch

Signed-off-by: Fabien Lahoudere 
---
 drivers/ata/ahci_imx.c | 225 +
 1 file changed, 225 insertions(+)

diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 3f3a7db..a2a8c63 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -26,6 +26,9 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 #include "ahci.h"
 
 #define DRV_NAME "ahci-imx"
@@ -214,6 +217,210 @@ static int imx_sata_phy_reset(struct ahci_host_priv 
*hpriv)
return timeout ? 0 : -ETIMEDOUT;
 }
 
+enum {
+   /* SATA PHY Register */
+   SATA_PHY_CR_CLOCK_CRCMP_LT_LIMIT = 0x0001,
+   SATA_PHY_CR_CLOCK_DAC_CTL = 0x0008,
+   SATA_PHY_CR_CLOCK_RTUNE_CTL = 0x0009,
+   SATA_PHY_CR_CLOCK_ADC_OUT = 0x000A,
+   SATA_PHY_CR_CLOCK_MPLL_TST = 0x0017,
+};
+
+/* SATA AHCI temperature monitor */
+static int sata_ahci_read_temperature(void *dev, int *temp)
+{
+   u16 mpll_test_reg, rtune_ctl_reg, dac_ctl_reg, adc_out_reg, read_sum;
+   u32 str1, str2, str3, str4, index, read_attempt;
+   const u32 attempt_limit = 100;
+   int m1, m2, a;
+   struct ahci_host_priv *hpriv = dev_get_drvdata(dev);
+   void __iomem *mmio = hpriv->mmio;
+
+   /* check rd-wr to reg */
+   read_sum = 0;
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_CRCMP_LT_LIMIT, mmio);
+   imx_phy_reg_write(read_sum, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   imx_phy_reg_write(0x5A5A, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0x5A5A)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   imx_phy_reg_write(0x1234, mmio);
+   imx_phy_reg_read(_sum, mmio);
+   if ((read_sum & 0x) != 0x1234)
+   dev_err(dev, "Read/Write REG error, 0x%x!\n", read_sum);
+
+   /* start temperature test */
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_MPLL_TST, mmio);
+   imx_phy_reg_read(_test_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
+   imx_phy_reg_read(_ctl_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_DAC_CTL, mmio);
+   imx_phy_reg_read(_ctl_reg, mmio);
+
+   /* mpll_tst.meas_iv   ([12:2]) */
+   str1 = (mpll_test_reg >> 2) & 0x7FF;
+   /* rtune_ctl.mode ([1:0]) */
+   str2 = (rtune_ctl_reg) & 0x3;
+   /* dac_ctl.dac_mode   ([14:12]) */
+   str3 = (dac_ctl_reg >> 12)  & 0x7;
+   /* rtune_ctl.sel_atbp ([4]) */
+   str4 = (rtune_ctl_reg >> 4);
+
+   /* Calculate the m1 */
+   /* mpll_tst.meas_iv */
+   mpll_test_reg = (mpll_test_reg & 0xE03) | (512) << 2;
+   /* rtune_ctl.mode */
+   rtune_ctl_reg = (rtune_ctl_reg & 0xFFC) | (1);
+   /* dac_ctl.dac_mode */
+   dac_ctl_reg = (dac_ctl_reg & 0x8FF) | (4) << 12;
+   /* rtune_ctl.sel_atbp */
+   rtune_ctl_reg = (rtune_ctl_reg & 0xFEF) | (0) << 4;
+
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_MPLL_TST, mmio);
+   imx_phy_reg_write(mpll_test_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_DAC_CTL, mmio);
+   imx_phy_reg_write(dac_ctl_reg, mmio);
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_RTUNE_CTL, mmio);
+   imx_phy_reg_write(rtune_ctl_reg, mmio);
+
+   /* two dummy read */
+   index = 0;
+   read_attempt = 0;
+   adc_out_reg = 0;
+   imx_phy_reg_addressing(SATA_PHY_CR_CLOCK_ADC_OUT, mmio);
+   while (index < 2) {
+   imx_phy_reg_read(_out_reg, mmio);
+   /* check if valid */
+   if (adc_out_reg & 0x400)
+   index++;
+
+   read_attempt++;
+   if (read_attempt > attempt_limit) {
+   dev_err(dev, "Read REG more than %d times!\n",
+   attempt_limit);
+   break;
+   }
+   }
+
+   index = 0;
+   read_attempt = 0;
+   read_sum = 0;
+   while (index < 80) {
+   imx_phy_reg_read(_out_reg, mmio);
+   if (adc_out_reg & 0x400) {
+   read_sum = read_sum + (adc_out_reg & 0x3FF);
+   index++;
+   }
+   read_attempt++;
+   if (read_attempt > attempt_limit) {
+   dev_err(dev, "Read REG more than %d times!\n",
+   attempt_limit);
+   break;
+   }
+   }
+   /* Use the U32 to make 

[PATCH v4 1/1] drm/panel: simple: Add nvd9128 as a simple panel

2016-10-17 Thread Fabien Lahoudere
Add New Vision Display 7.0" 800 RGB x 480 TFT LCD panel

Signed-off-by: Fabien Lahoudere <fabien.lahoud...@collabora.co.uk>
Acked-by: Rob Herring <r...@kernel.org>
---
 .../devicetree/bindings/display/panel/nvd,9128.txt |  7 ++
 .../devicetree/bindings/vendor-prefixes.txt|  1 +
 drivers/gpu/drm/panel/panel-simple.c   | 26 ++
 3 files changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/panel/nvd,9128.txt

diff --git a/Documentation/devicetree/bindings/display/panel/nvd,9128.txt 
b/Documentation/devicetree/bindings/display/panel/nvd,9128.txt
new file mode 100644
index 000..17bcd01
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/nvd,9128.txt
@@ -0,0 +1,7 @@
+New Vision Display 7.0" 800 RGB x 480 TFT LCD panel
+
+Required properties:
+- compatible: should be "nvd,9128"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt 
b/Documentation/devicetree/bindings/vendor-prefixes.txt
index f0a48ea..d9c51d7 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -187,6 +187,7 @@ netgear NETGEAR
 netlogic   Broadcom Corporation (formerly NetLogic Microsystems)
 netxeonShenzhen Netxeon Technology CO., LTD
 newhaven   Newhaven Display International
+nvdNew Vision Display
 nintendo   Nintendo
 nokia  Nokia
 nuvotonNuvoton Technology Corporation
diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index 113db3c..fb8f694 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -1164,6 +1164,29 @@ static const struct panel_desc nec_nl4827hc19_05b = {
.bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE,
 };
 
+static const struct drm_display_mode nvd_9128_mode = {
+   .clock = 29500,
+   .hdisplay = 800,
+   .hsync_start = 800 + 130,
+   .hsync_end = 800 + 130 + 98,
+   .htotal = 800 + 0 + 130 + 98,
+   .vdisplay = 480,
+   .vsync_start = 480 + 10,
+   .vsync_end = 480 + 10 + 50,
+   .vtotal = 480 + 0 + 10 + 50,
+};
+
+static const struct panel_desc nvd_9128 = {
+   .modes = _9128_mode,
+   .num_modes = 1,
+   .bpc = 8,
+   .size = {
+   .width = 156,
+   .height = 88,
+   },
+   .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+};
+
 static const struct display_timing okaya_rs800480t_7x0gp_timing = {
.pixelclock = { 3000, 3000, 4000 },
.hactive = { 800, 800, 800 },
@@ -1653,6 +1676,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "nec,nl4827hc19-05b",
.data = _nl4827hc19_05b,
}, {
+   .compatible = "nvd,9128",
+   .data = _9128,
+   }, {
.compatible = "okaya,rs800480t-7x0gp",
.data = _rs800480t_7x0gp,
}, {
-- 
2.1.4



[PATCH v4 1/1] drm/panel: simple: Add nvd9128 as a simple panel

2016-10-17 Thread Fabien Lahoudere
Add New Vision Display 7.0" 800 RGB x 480 TFT LCD panel

Signed-off-by: Fabien Lahoudere 
Acked-by: Rob Herring 
---
 .../devicetree/bindings/display/panel/nvd,9128.txt |  7 ++
 .../devicetree/bindings/vendor-prefixes.txt|  1 +
 drivers/gpu/drm/panel/panel-simple.c   | 26 ++
 3 files changed, 34 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/display/panel/nvd,9128.txt

diff --git a/Documentation/devicetree/bindings/display/panel/nvd,9128.txt 
b/Documentation/devicetree/bindings/display/panel/nvd,9128.txt
new file mode 100644
index 000..17bcd01
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/nvd,9128.txt
@@ -0,0 +1,7 @@
+New Vision Display 7.0" 800 RGB x 480 TFT LCD panel
+
+Required properties:
+- compatible: should be "nvd,9128"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt 
b/Documentation/devicetree/bindings/vendor-prefixes.txt
index f0a48ea..d9c51d7 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -187,6 +187,7 @@ netgear NETGEAR
 netlogic   Broadcom Corporation (formerly NetLogic Microsystems)
 netxeonShenzhen Netxeon Technology CO., LTD
 newhaven   Newhaven Display International
+nvdNew Vision Display
 nintendo   Nintendo
 nokia  Nokia
 nuvotonNuvoton Technology Corporation
diff --git a/drivers/gpu/drm/panel/panel-simple.c 
b/drivers/gpu/drm/panel/panel-simple.c
index 113db3c..fb8f694 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -1164,6 +1164,29 @@ static const struct panel_desc nec_nl4827hc19_05b = {
.bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE,
 };
 
+static const struct drm_display_mode nvd_9128_mode = {
+   .clock = 29500,
+   .hdisplay = 800,
+   .hsync_start = 800 + 130,
+   .hsync_end = 800 + 130 + 98,
+   .htotal = 800 + 0 + 130 + 98,
+   .vdisplay = 480,
+   .vsync_start = 480 + 10,
+   .vsync_end = 480 + 10 + 50,
+   .vtotal = 480 + 0 + 10 + 50,
+};
+
+static const struct panel_desc nvd_9128 = {
+   .modes = _9128_mode,
+   .num_modes = 1,
+   .bpc = 8,
+   .size = {
+   .width = 156,
+   .height = 88,
+   },
+   .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+};
+
 static const struct display_timing okaya_rs800480t_7x0gp_timing = {
.pixelclock = { 3000, 3000, 4000 },
.hactive = { 800, 800, 800 },
@@ -1653,6 +1676,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "nec,nl4827hc19-05b",
.data = _nl4827hc19_05b,
}, {
+   .compatible = "nvd,9128",
+   .data = _9128,
+   }, {
.compatible = "okaya,rs800480t-7x0gp",
.data = _rs800480t_7x0gp,
}, {
-- 
2.1.4



[PATCH v2 1/1] Add device to spidev device tree compatibility list

2016-10-06 Thread Fabien Lahoudere
Entries are needed in the spidev ID list to configure configure it from a
device tree. Add entry for the following device:
- "ge,achc" :  GE Healthcare USB Management Controller

The USB Management Controller does not expose USB to the host, but acts as
an offload engine, communicating with specific USB based data acquisition
devices which are connected to it, extracting the required data and
providing it to the host via other methods. SPI is used as an out-of-band
configuration channel.

Signed-off-by: Fabien Lahoudere <fabien.lahoud...@collabora.co.uk>
---
 drivers/spi/spidev.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 2e05046..9e2e099 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -696,6 +696,7 @@ static struct class *spidev_class;
 static const struct of_device_id spidev_dt_ids[] = {
{ .compatible = "rohm,dh2228fv" },
{ .compatible = "lineartechnology,ltc2488" },
+   { .compatible = "ge,achc" },
{},
 };
 MODULE_DEVICE_TABLE(of, spidev_dt_ids);
-- 
2.1.4



[PATCH v2 1/1] Add device to spidev device tree compatibility list

2016-10-06 Thread Fabien Lahoudere
Entries are needed in the spidev ID list to configure configure it from a
device tree. Add entry for the following device:
- "ge,achc" :  GE Healthcare USB Management Controller

The USB Management Controller does not expose USB to the host, but acts as
an offload engine, communicating with specific USB based data acquisition
devices which are connected to it, extracting the required data and
providing it to the host via other methods. SPI is used as an out-of-band
configuration channel.

Signed-off-by: Fabien Lahoudere 
---
 drivers/spi/spidev.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 2e05046..9e2e099 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -696,6 +696,7 @@ static struct class *spidev_class;
 static const struct of_device_id spidev_dt_ids[] = {
{ .compatible = "rohm,dh2228fv" },
{ .compatible = "lineartechnology,ltc2488" },
+   { .compatible = "ge,achc" },
{},
 };
 MODULE_DEVICE_TABLE(of, spidev_dt_ids);
-- 
2.1.4



Re: [PATCH 1/1] Add devices to spidev device tree compatibility list

2016-10-06 Thread Fabien Lahoudere

Hi,

On 30/09/16 19:35, Geert Uytterhoeven wrote:

On Fri, Sep 30, 2016 at 12:15 PM, Fabien Lahoudere
<fabien.lahoud...@collabora.co.uk> wrote:

Entries are needed in the spidev ID list to configure configure it from a
device tree. Add entries for the following devices:



- "exar,xra1403" : a GPIO expander


Looks like a suitable target for a drivers/gpio/ driver.
Datasheet available at
https://www.exar.com/product/interface/bridges/bridging-solutions/spi-gpio-expanders/xra1403



Good idea, however we have to measure impact of this change on the project.

Thanks

Fabien


Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds



Re: [PATCH 1/1] Add devices to spidev device tree compatibility list

2016-10-06 Thread Fabien Lahoudere

Hi,

On 30/09/16 19:35, Geert Uytterhoeven wrote:

On Fri, Sep 30, 2016 at 12:15 PM, Fabien Lahoudere
 wrote:

Entries are needed in the spidev ID list to configure configure it from a
device tree. Add entries for the following devices:



- "exar,xra1403" : a GPIO expander


Looks like a suitable target for a drivers/gpio/ driver.
Datasheet available at
https://www.exar.com/product/interface/bridges/bridging-solutions/spi-gpio-expanders/xra1403



Good idea, however we have to measure impact of this change on the project.

Thanks

Fabien


Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds



[PATCH 1/1] Add devices to spidev device tree compatibility list

2016-09-30 Thread Fabien Lahoudere
Entries are needed in the spidev ID list to configure configure it from a
device tree. Add entries for the following devices:
- "fsl,mk20fn1m0vmd12" : a cortex m4 based chip
- "exar,xra1403" : a GPIO expander

Signed-off-by: Fabien Lahoudere <fabien.lahoud...@collabora.co.uk>
---
 drivers/spi/spidev.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 2e05046..821937a 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -696,6 +696,8 @@ static struct class *spidev_class;
 static const struct of_device_id spidev_dt_ids[] = {
{ .compatible = "rohm,dh2228fv" },
{ .compatible = "lineartechnology,ltc2488" },
+   { .compatible = "fsl,MK20FN1M0VMD12" },
+   { .compatible = "exar,xra1403" },
{},
 };
 MODULE_DEVICE_TABLE(of, spidev_dt_ids);
-- 
2.1.4



[PATCH 1/1] Add devices to spidev device tree compatibility list

2016-09-30 Thread Fabien Lahoudere
Entries are needed in the spidev ID list to configure configure it from a
device tree. Add entries for the following devices:
- "fsl,mk20fn1m0vmd12" : a cortex m4 based chip
- "exar,xra1403" : a GPIO expander

Signed-off-by: Fabien Lahoudere 
---
 drivers/spi/spidev.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index 2e05046..821937a 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -696,6 +696,8 @@ static struct class *spidev_class;
 static const struct of_device_id spidev_dt_ids[] = {
{ .compatible = "rohm,dh2228fv" },
{ .compatible = "lineartechnology,ltc2488" },
+   { .compatible = "fsl,MK20FN1M0VMD12" },
+   { .compatible = "exar,xra1403" },
{},
 };
 MODULE_DEVICE_TABLE(of, spidev_dt_ids);
-- 
2.1.4



[PATCH v6 0/2] Add USB configuration for imx53

2016-09-26 Thread Fabien Lahoudere
Changes in V2:
- Patches sent to early with bad contents
Changes in V3:
- Change subject
- Split "configure imx for ULPI phy" for disable-oc code
Changes in V4:
- Fix "Change switch order" commit message
- Indent switch/case (set case on the same column as switch)
- Remove useless test in "Change switch order"
Changes in V5:
- Squash "Change switch order" and "configure imx for ULPI phy"
- Add device tree binding documentation
Changes in v6:
- Remove dt binding because we can disable the feature by using an 
existing binding

Fabien Lahoudere (2):
  usb: chipidea: imx: configure imx for ULPI phy
  usb: chipidea: imx: Disable internal 60Mhz clock with ULPI PHY

 drivers/usb/chipidea/ci_hdrc_imx.c |  4 ++
 drivers/usb/chipidea/ci_hdrc_imx.h |  1 +
 drivers/usb/chipidea/usbmisc_imx.c | 86 +++---
 3 files changed, 77 insertions(+), 14 deletions(-)

-- 
2.1.4



[PATCH v6 1/2] usb: chipidea: imx: configure imx for ULPI phy

2016-09-26 Thread Fabien Lahoudere
In order to use ULPI phy with usb host 2 and 3, we need to configure
controller register to enable ULPI features.

Each USB controller have different behaviour, so in order to avoid to have
several "swicth(data->index)" and lock/unlock, we prefer to get the index
switch and then test for features if they exist for this index.
This patch also remove useless test of reg and val. Those two values cannot
be NULL.

Signed-off-by: Fabien Lahoudere <fabien.lahoud...@collabora.co.uk>
---
 drivers/usb/chipidea/ci_hdrc_imx.c |  4 ++
 drivers/usb/chipidea/ci_hdrc_imx.h |  1 +
 drivers/usb/chipidea/usbmisc_imx.c | 75 +++---
 3 files changed, 66 insertions(+), 14 deletions(-)

diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c 
b/drivers/usb/chipidea/ci_hdrc_imx.c
index 0991794..5f4a815 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "ci.h"
@@ -146,6 +147,9 @@ static struct imx_usbmisc_data 
*usbmisc_get_init_data(struct device *dev)
if (of_find_property(np, "external-vbus-divider", NULL))
data->evdo = 1;
 
+   if (of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI)
+   data->ulpi = 1;
+
return data;
 }
 
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h 
b/drivers/usb/chipidea/ci_hdrc_imx.h
index 409aa5ca8..d666c9f 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.h
+++ b/drivers/usb/chipidea/ci_hdrc_imx.h
@@ -19,6 +19,7 @@ struct imx_usbmisc_data {
unsigned int disable_oc:1; /* over current detect disabled */
unsigned int oc_polarity:1; /* over current polarity if oc enabled */
unsigned int evdo:1; /* set external vbus divider option */
+   unsigned int ulpi:1; /* connected to an ULPI phy */
 };
 
 int imx_usbmisc_init(struct imx_usbmisc_data *);
diff --git a/drivers/usb/chipidea/usbmisc_imx.c 
b/drivers/usb/chipidea/usbmisc_imx.c
index 20d02a5..11f51bd 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -46,11 +46,20 @@
 
 #define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08
 #define MX53_USB_OTG_PHY_CTRL_1_OFFSET 0x0c
+#define MX53_USB_CTRL_1_OFFSET 0x10
+#define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK (0x11 << 2)
+#define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI BIT(2)
+#define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK (0x11 << 6)
+#define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI BIT(6)
 #define MX53_USB_UH2_CTRL_OFFSET   0x14
 #define MX53_USB_UH3_CTRL_OFFSET   0x18
 #define MX53_BM_OVER_CUR_DIS_H1BIT(5)
 #define MX53_BM_OVER_CUR_DIS_OTG   BIT(8)
 #define MX53_BM_OVER_CUR_DIS_UHx   BIT(30)
+#define MX53_USB_CTRL_1_UH2_ULPI_ENBIT(26)
+#define MX53_USB_CTRL_1_UH3_ULPI_ENBIT(27)
+#define MX53_USB_UHx_CTRL_WAKE_UP_EN   BIT(7)
+#define MX53_USB_UHx_CTRL_ULPI_INT_EN  BIT(8)
 #define MX53_USB_PHYCTRL1_PLLDIV_MASK  0x3
 #define MX53_USB_PLL_DIV_24_MHZ0x01
 
@@ -199,31 +208,69 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data 
*data)
val |= MX53_USB_PLL_DIV_24_MHZ;
writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
 
-   if (data->disable_oc) {
-   spin_lock_irqsave(>lock, flags);
-   switch (data->index) {
-   case 0:
+   spin_lock_irqsave(>lock, flags);
+
+   switch (data->index) {
+   case 0:
+   if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
-   break;
-   case 1:
+   writel(val, reg);
+   }
+   break;
+   case 1:
+   if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
-   break;
-   case 2:
+   writel(val, reg);
+   }
+   break;
+   case 2:
+   if (data->ulpi) {
+   /* set USBH2 into ULPI-mode. */
+   reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
+   val = readl(reg) | MX53_USB_CTRL_1_UH2_ULPI_EN;
+   /* select ULPI clock */
+   val &= ~MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK;
+   val |= MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI;
+   writel(val, reg);
+   /* Set interrupt wake up enable */
+   reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
+   val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
+   | MX53_USB_UHx_CTRL_ULPI_INT_EN;
+   writel(val, reg);
+

[PATCH v6 0/2] Add USB configuration for imx53

2016-09-26 Thread Fabien Lahoudere
Changes in V2:
- Patches sent to early with bad contents
Changes in V3:
- Change subject
- Split "configure imx for ULPI phy" for disable-oc code
Changes in V4:
- Fix "Change switch order" commit message
- Indent switch/case (set case on the same column as switch)
- Remove useless test in "Change switch order"
Changes in V5:
- Squash "Change switch order" and "configure imx for ULPI phy"
- Add device tree binding documentation
Changes in v6:
- Remove dt binding because we can disable the feature by using an 
existing binding

Fabien Lahoudere (2):
  usb: chipidea: imx: configure imx for ULPI phy
  usb: chipidea: imx: Disable internal 60Mhz clock with ULPI PHY

 drivers/usb/chipidea/ci_hdrc_imx.c |  4 ++
 drivers/usb/chipidea/ci_hdrc_imx.h |  1 +
 drivers/usb/chipidea/usbmisc_imx.c | 86 +++---
 3 files changed, 77 insertions(+), 14 deletions(-)

-- 
2.1.4



[PATCH v6 1/2] usb: chipidea: imx: configure imx for ULPI phy

2016-09-26 Thread Fabien Lahoudere
In order to use ULPI phy with usb host 2 and 3, we need to configure
controller register to enable ULPI features.

Each USB controller have different behaviour, so in order to avoid to have
several "swicth(data->index)" and lock/unlock, we prefer to get the index
switch and then test for features if they exist for this index.
This patch also remove useless test of reg and val. Those two values cannot
be NULL.

Signed-off-by: Fabien Lahoudere 
---
 drivers/usb/chipidea/ci_hdrc_imx.c |  4 ++
 drivers/usb/chipidea/ci_hdrc_imx.h |  1 +
 drivers/usb/chipidea/usbmisc_imx.c | 75 +++---
 3 files changed, 66 insertions(+), 14 deletions(-)

diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c 
b/drivers/usb/chipidea/ci_hdrc_imx.c
index 0991794..5f4a815 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "ci.h"
@@ -146,6 +147,9 @@ static struct imx_usbmisc_data 
*usbmisc_get_init_data(struct device *dev)
if (of_find_property(np, "external-vbus-divider", NULL))
data->evdo = 1;
 
+   if (of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI)
+   data->ulpi = 1;
+
return data;
 }
 
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h 
b/drivers/usb/chipidea/ci_hdrc_imx.h
index 409aa5ca8..d666c9f 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.h
+++ b/drivers/usb/chipidea/ci_hdrc_imx.h
@@ -19,6 +19,7 @@ struct imx_usbmisc_data {
unsigned int disable_oc:1; /* over current detect disabled */
unsigned int oc_polarity:1; /* over current polarity if oc enabled */
unsigned int evdo:1; /* set external vbus divider option */
+   unsigned int ulpi:1; /* connected to an ULPI phy */
 };
 
 int imx_usbmisc_init(struct imx_usbmisc_data *);
diff --git a/drivers/usb/chipidea/usbmisc_imx.c 
b/drivers/usb/chipidea/usbmisc_imx.c
index 20d02a5..11f51bd 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -46,11 +46,20 @@
 
 #define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08
 #define MX53_USB_OTG_PHY_CTRL_1_OFFSET 0x0c
+#define MX53_USB_CTRL_1_OFFSET 0x10
+#define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK (0x11 << 2)
+#define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI BIT(2)
+#define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK (0x11 << 6)
+#define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI BIT(6)
 #define MX53_USB_UH2_CTRL_OFFSET   0x14
 #define MX53_USB_UH3_CTRL_OFFSET   0x18
 #define MX53_BM_OVER_CUR_DIS_H1BIT(5)
 #define MX53_BM_OVER_CUR_DIS_OTG   BIT(8)
 #define MX53_BM_OVER_CUR_DIS_UHx   BIT(30)
+#define MX53_USB_CTRL_1_UH2_ULPI_ENBIT(26)
+#define MX53_USB_CTRL_1_UH3_ULPI_ENBIT(27)
+#define MX53_USB_UHx_CTRL_WAKE_UP_EN   BIT(7)
+#define MX53_USB_UHx_CTRL_ULPI_INT_EN  BIT(8)
 #define MX53_USB_PHYCTRL1_PLLDIV_MASK  0x3
 #define MX53_USB_PLL_DIV_24_MHZ0x01
 
@@ -199,31 +208,69 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data 
*data)
val |= MX53_USB_PLL_DIV_24_MHZ;
writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
 
-   if (data->disable_oc) {
-   spin_lock_irqsave(>lock, flags);
-   switch (data->index) {
-   case 0:
+   spin_lock_irqsave(>lock, flags);
+
+   switch (data->index) {
+   case 0:
+   if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
-   break;
-   case 1:
+   writel(val, reg);
+   }
+   break;
+   case 1:
+   if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
-   break;
-   case 2:
+   writel(val, reg);
+   }
+   break;
+   case 2:
+   if (data->ulpi) {
+   /* set USBH2 into ULPI-mode. */
+   reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
+   val = readl(reg) | MX53_USB_CTRL_1_UH2_ULPI_EN;
+   /* select ULPI clock */
+   val &= ~MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK;
+   val |= MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI;
+   writel(val, reg);
+   /* Set interrupt wake up enable */
+   reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
+   val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
+   | MX53_USB_UHx_CTRL_ULPI_INT_EN;
+   writel(val, reg);
+   }
+   

[PATCH v6 2/2] usb: chipidea: imx: Disable internal 60Mhz clock with ULPI PHY

2016-09-26 Thread Fabien Lahoudere
The internal 60Mhz clock for host2 and host3 are useless in ULPI
phy mode, so we disable it when configuring ULPI PHY node for
those host.

Signed-off-by: Fabien Lahoudere <fabien.lahoud...@collabora.co.uk>
---
 drivers/usb/chipidea/usbmisc_imx.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/usb/chipidea/usbmisc_imx.c 
b/drivers/usb/chipidea/usbmisc_imx.c
index 11f51bd..e77a4ed 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -53,6 +53,9 @@
 #define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI BIT(6)
 #define MX53_USB_UH2_CTRL_OFFSET   0x14
 #define MX53_USB_UH3_CTRL_OFFSET   0x18
+#define MX53_USB_CLKONOFF_CTRL_OFFSET  0x24
+#define MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF BIT(21)
+#define MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF BIT(22)
 #define MX53_BM_OVER_CUR_DIS_H1BIT(5)
 #define MX53_BM_OVER_CUR_DIS_OTG   BIT(8)
 #define MX53_BM_OVER_CUR_DIS_UHx   BIT(30)
@@ -239,6 +242,10 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data 
*data)
val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
| MX53_USB_UHx_CTRL_ULPI_INT_EN;
writel(val, reg);
+   /* Disable internal 60Mhz clock */
+   reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET;
+   val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF;
+   writel(val, reg);
}
if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
@@ -260,6 +267,10 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data 
*data)
val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
| MX53_USB_UHx_CTRL_ULPI_INT_EN;
writel(val, reg);
+   /* Disable internal 60Mhz clock */
+   reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET;
+   val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF;
+   writel(val, reg);
}
if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
-- 
2.1.4



[PATCH v6 2/2] usb: chipidea: imx: Disable internal 60Mhz clock with ULPI PHY

2016-09-26 Thread Fabien Lahoudere
The internal 60Mhz clock for host2 and host3 are useless in ULPI
phy mode, so we disable it when configuring ULPI PHY node for
those host.

Signed-off-by: Fabien Lahoudere 
---
 drivers/usb/chipidea/usbmisc_imx.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/usb/chipidea/usbmisc_imx.c 
b/drivers/usb/chipidea/usbmisc_imx.c
index 11f51bd..e77a4ed 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -53,6 +53,9 @@
 #define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI BIT(6)
 #define MX53_USB_UH2_CTRL_OFFSET   0x14
 #define MX53_USB_UH3_CTRL_OFFSET   0x18
+#define MX53_USB_CLKONOFF_CTRL_OFFSET  0x24
+#define MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF BIT(21)
+#define MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF BIT(22)
 #define MX53_BM_OVER_CUR_DIS_H1BIT(5)
 #define MX53_BM_OVER_CUR_DIS_OTG   BIT(8)
 #define MX53_BM_OVER_CUR_DIS_UHx   BIT(30)
@@ -239,6 +242,10 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data 
*data)
val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
| MX53_USB_UHx_CTRL_ULPI_INT_EN;
writel(val, reg);
+   /* Disable internal 60Mhz clock */
+   reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET;
+   val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF;
+   writel(val, reg);
}
if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
@@ -260,6 +267,10 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data 
*data)
val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
| MX53_USB_UHx_CTRL_ULPI_INT_EN;
writel(val, reg);
+   /* Disable internal 60Mhz clock */
+   reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET;
+   val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF;
+   writel(val, reg);
}
if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
-- 
2.1.4



Re: [PATCH v5 2/2] usb: chipidea: imx: Add binding to disable USB 60Mhz clock

2016-09-26 Thread Fabien Lahoudere

Hi,

On 23/09/16 21:47, Rob Herring wrote:

On Wed, Sep 21, 2016 at 11:07:07AM +0200, Fabien Lahoudere wrote:

This binding allow to disable the internal 60Mhz clock for USB host2 or
host3.

Signed-off-by: Fabien Lahoudere <fabien.lahoud...@collabora.co.uk>
---
 Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt |  1 +
 drivers/usb/chipidea/ci_hdrc_imx.c |  2 ++
 drivers/usb/chipidea/ci_hdrc_imx.h |  1 +
 drivers/usb/chipidea/usbmisc_imx.c | 13 +
 4 files changed, 17 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt 
b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
index 0e03344..f83da66 100644
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
@@ -84,6 +84,7 @@ i.mx specific properties
 - over-current-active-high: over current signal polarity is high active,
   typically over current signal polarity is low active.
 - external-vbus-divider: enables off-chip resistor divider for Vbus
+- disable-int60ck: disable internal 60MHz clock for usb host2 or host3 on imx53


Doesn't this depend on something else like the type of phy connected? If
not, when can you do this or not?



We can disable it in OTG mode and with ULPI phy and Sascha Hauer think 
we can do it without dt binding for example based on PHY mode. So I will 
remove the binding and just disable clock if ULPI is selected.



Rob



Fabien


Re: [PATCH v5 2/2] usb: chipidea: imx: Add binding to disable USB 60Mhz clock

2016-09-26 Thread Fabien Lahoudere

Hi,

On 23/09/16 21:47, Rob Herring wrote:

On Wed, Sep 21, 2016 at 11:07:07AM +0200, Fabien Lahoudere wrote:

This binding allow to disable the internal 60Mhz clock for USB host2 or
host3.

Signed-off-by: Fabien Lahoudere 
---
 Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt |  1 +
 drivers/usb/chipidea/ci_hdrc_imx.c |  2 ++
 drivers/usb/chipidea/ci_hdrc_imx.h |  1 +
 drivers/usb/chipidea/usbmisc_imx.c | 13 +
 4 files changed, 17 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt 
b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
index 0e03344..f83da66 100644
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
@@ -84,6 +84,7 @@ i.mx specific properties
 - over-current-active-high: over current signal polarity is high active,
   typically over current signal polarity is low active.
 - external-vbus-divider: enables off-chip resistor divider for Vbus
+- disable-int60ck: disable internal 60MHz clock for usb host2 or host3 on imx53


Doesn't this depend on something else like the type of phy connected? If
not, when can you do this or not?



We can disable it in OTG mode and with ULPI phy and Sascha Hauer think 
we can do it without dt binding for example based on PHY mode. So I will 
remove the binding and just disable clock if ULPI is selected.



Rob



Fabien


Re: [PATCH v5 2/2] usb: chipidea: imx: Add binding to disable USB 60Mhz clock

2016-09-26 Thread Fabien Lahoudere

Hi,

On 26/09/16 10:18, Sascha Hauer wrote:

On Wed, Sep 21, 2016 at 11:07:07AM +0200, Fabien Lahoudere wrote:

This binding allow to disable the internal 60Mhz clock for USB host2 or
host3.

Signed-off-by: Fabien Lahoudere <fabien.lahoud...@collabora.co.uk>
---
 Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt |  1 +
 drivers/usb/chipidea/ci_hdrc_imx.c |  2 ++
 drivers/usb/chipidea/ci_hdrc_imx.h |  1 +
 drivers/usb/chipidea/usbmisc_imx.c | 13 +
 4 files changed, 17 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt 
b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
index 0e03344..f83da66 100644
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
@@ -84,6 +84,7 @@ i.mx specific properties
 - over-current-active-high: over current signal polarity is high active,
   typically over current signal polarity is low active.
 - external-vbus-divider: enables off-chip resistor divider for Vbus
+- disable-int60ck: disable internal 60MHz clock for usb host2 or host3 on imx53


Why do we need a binding for this? I would assume the driver should know
whether this clock is in use or not. If it doesn't that's a problem we
should solve.



Yes you are right because we can disable this clock for OTG and with 
ULPI PHY. I think that it will be better to have a dt binding but if it 
is useless I can remove it and disable clock when ULPI mode is enabled.



Sascha



Fabien


Re: [PATCH v5 2/2] usb: chipidea: imx: Add binding to disable USB 60Mhz clock

2016-09-26 Thread Fabien Lahoudere

Hi,

On 26/09/16 10:18, Sascha Hauer wrote:

On Wed, Sep 21, 2016 at 11:07:07AM +0200, Fabien Lahoudere wrote:

This binding allow to disable the internal 60Mhz clock for USB host2 or
host3.

Signed-off-by: Fabien Lahoudere 
---
 Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt |  1 +
 drivers/usb/chipidea/ci_hdrc_imx.c |  2 ++
 drivers/usb/chipidea/ci_hdrc_imx.h |  1 +
 drivers/usb/chipidea/usbmisc_imx.c | 13 +
 4 files changed, 17 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt 
b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
index 0e03344..f83da66 100644
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
@@ -84,6 +84,7 @@ i.mx specific properties
 - over-current-active-high: over current signal polarity is high active,
   typically over current signal polarity is low active.
 - external-vbus-divider: enables off-chip resistor divider for Vbus
+- disable-int60ck: disable internal 60MHz clock for usb host2 or host3 on imx53


Why do we need a binding for this? I would assume the driver should know
whether this clock is in use or not. If it doesn't that's a problem we
should solve.



Yes you are right because we can disable this clock for OTG and with 
ULPI PHY. I think that it will be better to have a dt binding but if it 
is useless I can remove it and disable clock when ULPI mode is enabled.



Sascha



Fabien


[PATCH v5 2/2] usb: chipidea: imx: Add binding to disable USB 60Mhz clock

2016-09-21 Thread Fabien Lahoudere
This binding allow to disable the internal 60Mhz clock for USB host2 or
host3.

Signed-off-by: Fabien Lahoudere <fabien.lahoud...@collabora.co.uk>
---
 Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt |  1 +
 drivers/usb/chipidea/ci_hdrc_imx.c |  2 ++
 drivers/usb/chipidea/ci_hdrc_imx.h |  1 +
 drivers/usb/chipidea/usbmisc_imx.c | 13 +
 4 files changed, 17 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt 
b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
index 0e03344..f83da66 100644
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
@@ -84,6 +84,7 @@ i.mx specific properties
 - over-current-active-high: over current signal polarity is high active,
   typically over current signal polarity is low active.
 - external-vbus-divider: enables off-chip resistor divider for Vbus
+- disable-int60ck: disable internal 60MHz clock for usb host2 or host3 on imx53
 
 Example:
 
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c 
b/drivers/usb/chipidea/ci_hdrc_imx.c
index 96c0e33..89a9d98 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -147,6 +147,8 @@ static struct imx_usbmisc_data 
*usbmisc_get_init_data(struct device *dev)
if (of_find_property(np, "external-vbus-divider", NULL))
data->evdo = 1;
 
+   if (of_find_property(np, "disable-int60ck", NULL))
+   data->disable_int60ck = 1;
 
if (of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI)
data->ulpi = 1;
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h 
b/drivers/usb/chipidea/ci_hdrc_imx.h
index d666c9f..43bafae 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.h
+++ b/drivers/usb/chipidea/ci_hdrc_imx.h
@@ -20,6 +20,7 @@ struct imx_usbmisc_data {
unsigned int oc_polarity:1; /* over current polarity if oc enabled */
unsigned int evdo:1; /* set external vbus divider option */
unsigned int ulpi:1; /* connected to an ULPI phy */
+   unsigned int disable_int60ck:1; /* disable 60 MHZ clock */
 };
 
 int imx_usbmisc_init(struct imx_usbmisc_data *);
diff --git a/drivers/usb/chipidea/usbmisc_imx.c 
b/drivers/usb/chipidea/usbmisc_imx.c
index 11f51bd..a781f87 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -53,6 +53,9 @@
 #define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI BIT(6)
 #define MX53_USB_UH2_CTRL_OFFSET   0x14
 #define MX53_USB_UH3_CTRL_OFFSET   0x18
+#define MX53_USB_CLKONOFF_CTRL_OFFSET  0x24
+#define MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF BIT(21)
+#define MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF BIT(22)
 #define MX53_BM_OVER_CUR_DIS_H1BIT(5)
 #define MX53_BM_OVER_CUR_DIS_OTG   BIT(8)
 #define MX53_BM_OVER_CUR_DIS_UHx   BIT(30)
@@ -240,6 +243,11 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data 
*data)
| MX53_USB_UHx_CTRL_ULPI_INT_EN;
writel(val, reg);
}
+   if (data->disable_int60ck) {
+   reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET;
+   val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF;
+   writel(val, reg);
+   }
if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
@@ -261,6 +269,11 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data 
*data)
| MX53_USB_UHx_CTRL_ULPI_INT_EN;
writel(val, reg);
}
+   if (data->disable_int60ck) {
+   reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET;
+   val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF;
+   writel(val, reg);
+   }
if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
-- 
2.1.4



[PATCH v5 2/2] usb: chipidea: imx: Add binding to disable USB 60Mhz clock

2016-09-21 Thread Fabien Lahoudere
This binding allow to disable the internal 60Mhz clock for USB host2 or
host3.

Signed-off-by: Fabien Lahoudere 
---
 Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt |  1 +
 drivers/usb/chipidea/ci_hdrc_imx.c |  2 ++
 drivers/usb/chipidea/ci_hdrc_imx.h |  1 +
 drivers/usb/chipidea/usbmisc_imx.c | 13 +
 4 files changed, 17 insertions(+)

diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt 
b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
index 0e03344..f83da66 100644
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
@@ -84,6 +84,7 @@ i.mx specific properties
 - over-current-active-high: over current signal polarity is high active,
   typically over current signal polarity is low active.
 - external-vbus-divider: enables off-chip resistor divider for Vbus
+- disable-int60ck: disable internal 60MHz clock for usb host2 or host3 on imx53
 
 Example:
 
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c 
b/drivers/usb/chipidea/ci_hdrc_imx.c
index 96c0e33..89a9d98 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -147,6 +147,8 @@ static struct imx_usbmisc_data 
*usbmisc_get_init_data(struct device *dev)
if (of_find_property(np, "external-vbus-divider", NULL))
data->evdo = 1;
 
+   if (of_find_property(np, "disable-int60ck", NULL))
+   data->disable_int60ck = 1;
 
if (of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI)
data->ulpi = 1;
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h 
b/drivers/usb/chipidea/ci_hdrc_imx.h
index d666c9f..43bafae 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.h
+++ b/drivers/usb/chipidea/ci_hdrc_imx.h
@@ -20,6 +20,7 @@ struct imx_usbmisc_data {
unsigned int oc_polarity:1; /* over current polarity if oc enabled */
unsigned int evdo:1; /* set external vbus divider option */
unsigned int ulpi:1; /* connected to an ULPI phy */
+   unsigned int disable_int60ck:1; /* disable 60 MHZ clock */
 };
 
 int imx_usbmisc_init(struct imx_usbmisc_data *);
diff --git a/drivers/usb/chipidea/usbmisc_imx.c 
b/drivers/usb/chipidea/usbmisc_imx.c
index 11f51bd..a781f87 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -53,6 +53,9 @@
 #define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI BIT(6)
 #define MX53_USB_UH2_CTRL_OFFSET   0x14
 #define MX53_USB_UH3_CTRL_OFFSET   0x18
+#define MX53_USB_CLKONOFF_CTRL_OFFSET  0x24
+#define MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF BIT(21)
+#define MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF BIT(22)
 #define MX53_BM_OVER_CUR_DIS_H1BIT(5)
 #define MX53_BM_OVER_CUR_DIS_OTG   BIT(8)
 #define MX53_BM_OVER_CUR_DIS_UHx   BIT(30)
@@ -240,6 +243,11 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data 
*data)
| MX53_USB_UHx_CTRL_ULPI_INT_EN;
writel(val, reg);
}
+   if (data->disable_int60ck) {
+   reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET;
+   val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H2_INT60CKOFF;
+   writel(val, reg);
+   }
if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
@@ -261,6 +269,11 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data 
*data)
| MX53_USB_UHx_CTRL_ULPI_INT_EN;
writel(val, reg);
}
+   if (data->disable_int60ck) {
+   reg = usbmisc->base + MX53_USB_CLKONOFF_CTRL_OFFSET;
+   val = readl(reg) | MX53_USB_CLKONOFF_CTRL_H3_INT60CKOFF;
+   writel(val, reg);
+   }
if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_UH3_CTRL_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_UHx;
-- 
2.1.4



[PATCH v5 1/2] usb: chipidea: imx: configure imx for ULPI phy

2016-09-21 Thread Fabien Lahoudere
In order to use ULPI phy with usb host 2 and 3, we need to configure
controller register to enable ULPI features.

Each USB controller have different behaviour, so in order to avoid to have
several "swicth(data->index)" and lock/unlock, we prefer to get the index
switch and then test for features if they exist for this index.
This patch also remove useless test of reg and val. Those two values cannot
be NULL.

Signed-off-by: Fabien Lahoudere <fabien.lahoud...@collabora.co.uk>
---
 drivers/usb/chipidea/ci_hdrc_imx.c |  5 +++
 drivers/usb/chipidea/ci_hdrc_imx.h |  1 +
 drivers/usb/chipidea/usbmisc_imx.c | 75 +++---
 3 files changed, 67 insertions(+), 14 deletions(-)

diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c 
b/drivers/usb/chipidea/ci_hdrc_imx.c
index 0991794..96c0e33 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "ci.h"
@@ -146,6 +147,10 @@ static struct imx_usbmisc_data 
*usbmisc_get_init_data(struct device *dev)
if (of_find_property(np, "external-vbus-divider", NULL))
data->evdo = 1;
 
+
+   if (of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI)
+   data->ulpi = 1;
+
return data;
 }
 
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h 
b/drivers/usb/chipidea/ci_hdrc_imx.h
index 409aa5ca8..d666c9f 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.h
+++ b/drivers/usb/chipidea/ci_hdrc_imx.h
@@ -19,6 +19,7 @@ struct imx_usbmisc_data {
unsigned int disable_oc:1; /* over current detect disabled */
unsigned int oc_polarity:1; /* over current polarity if oc enabled */
unsigned int evdo:1; /* set external vbus divider option */
+   unsigned int ulpi:1; /* connected to an ULPI phy */
 };
 
 int imx_usbmisc_init(struct imx_usbmisc_data *);
diff --git a/drivers/usb/chipidea/usbmisc_imx.c 
b/drivers/usb/chipidea/usbmisc_imx.c
index 20d02a5..11f51bd 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -46,11 +46,20 @@
 
 #define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08
 #define MX53_USB_OTG_PHY_CTRL_1_OFFSET 0x0c
+#define MX53_USB_CTRL_1_OFFSET 0x10
+#define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK (0x11 << 2)
+#define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI BIT(2)
+#define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK (0x11 << 6)
+#define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI BIT(6)
 #define MX53_USB_UH2_CTRL_OFFSET   0x14
 #define MX53_USB_UH3_CTRL_OFFSET   0x18
 #define MX53_BM_OVER_CUR_DIS_H1BIT(5)
 #define MX53_BM_OVER_CUR_DIS_OTG   BIT(8)
 #define MX53_BM_OVER_CUR_DIS_UHx   BIT(30)
+#define MX53_USB_CTRL_1_UH2_ULPI_ENBIT(26)
+#define MX53_USB_CTRL_1_UH3_ULPI_ENBIT(27)
+#define MX53_USB_UHx_CTRL_WAKE_UP_EN   BIT(7)
+#define MX53_USB_UHx_CTRL_ULPI_INT_EN  BIT(8)
 #define MX53_USB_PHYCTRL1_PLLDIV_MASK  0x3
 #define MX53_USB_PLL_DIV_24_MHZ0x01
 
@@ -199,31 +208,69 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data 
*data)
val |= MX53_USB_PLL_DIV_24_MHZ;
writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
 
-   if (data->disable_oc) {
-   spin_lock_irqsave(>lock, flags);
-   switch (data->index) {
-   case 0:
+   spin_lock_irqsave(>lock, flags);
+
+   switch (data->index) {
+   case 0:
+   if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
-   break;
-   case 1:
+   writel(val, reg);
+   }
+   break;
+   case 1:
+   if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
-   break;
-   case 2:
+   writel(val, reg);
+   }
+   break;
+   case 2:
+   if (data->ulpi) {
+   /* set USBH2 into ULPI-mode. */
+   reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
+   val = readl(reg) | MX53_USB_CTRL_1_UH2_ULPI_EN;
+   /* select ULPI clock */
+   val &= ~MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK;
+   val |= MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI;
+   writel(val, reg);
+   /* Set interrupt wake up enable */
+   reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
+   val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
+   | MX53_USB_UHx_CTRL_ULPI_INT_EN;
+   writel(val, reg);
+

[PATCH v5 1/2] usb: chipidea: imx: configure imx for ULPI phy

2016-09-21 Thread Fabien Lahoudere
In order to use ULPI phy with usb host 2 and 3, we need to configure
controller register to enable ULPI features.

Each USB controller have different behaviour, so in order to avoid to have
several "swicth(data->index)" and lock/unlock, we prefer to get the index
switch and then test for features if they exist for this index.
This patch also remove useless test of reg and val. Those two values cannot
be NULL.

Signed-off-by: Fabien Lahoudere 
---
 drivers/usb/chipidea/ci_hdrc_imx.c |  5 +++
 drivers/usb/chipidea/ci_hdrc_imx.h |  1 +
 drivers/usb/chipidea/usbmisc_imx.c | 75 +++---
 3 files changed, 67 insertions(+), 14 deletions(-)

diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c 
b/drivers/usb/chipidea/ci_hdrc_imx.c
index 0991794..96c0e33 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "ci.h"
@@ -146,6 +147,10 @@ static struct imx_usbmisc_data 
*usbmisc_get_init_data(struct device *dev)
if (of_find_property(np, "external-vbus-divider", NULL))
data->evdo = 1;
 
+
+   if (of_usb_get_phy_mode(np) == USBPHY_INTERFACE_MODE_ULPI)
+   data->ulpi = 1;
+
return data;
 }
 
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.h 
b/drivers/usb/chipidea/ci_hdrc_imx.h
index 409aa5ca8..d666c9f 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.h
+++ b/drivers/usb/chipidea/ci_hdrc_imx.h
@@ -19,6 +19,7 @@ struct imx_usbmisc_data {
unsigned int disable_oc:1; /* over current detect disabled */
unsigned int oc_polarity:1; /* over current polarity if oc enabled */
unsigned int evdo:1; /* set external vbus divider option */
+   unsigned int ulpi:1; /* connected to an ULPI phy */
 };
 
 int imx_usbmisc_init(struct imx_usbmisc_data *);
diff --git a/drivers/usb/chipidea/usbmisc_imx.c 
b/drivers/usb/chipidea/usbmisc_imx.c
index 20d02a5..11f51bd 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -46,11 +46,20 @@
 
 #define MX53_USB_OTG_PHY_CTRL_0_OFFSET 0x08
 #define MX53_USB_OTG_PHY_CTRL_1_OFFSET 0x0c
+#define MX53_USB_CTRL_1_OFFSET 0x10
+#define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK (0x11 << 2)
+#define MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI BIT(2)
+#define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_MASK (0x11 << 6)
+#define MX53_USB_CTRL_1_H3_XCVR_CLK_SEL_ULPI BIT(6)
 #define MX53_USB_UH2_CTRL_OFFSET   0x14
 #define MX53_USB_UH3_CTRL_OFFSET   0x18
 #define MX53_BM_OVER_CUR_DIS_H1BIT(5)
 #define MX53_BM_OVER_CUR_DIS_OTG   BIT(8)
 #define MX53_BM_OVER_CUR_DIS_UHx   BIT(30)
+#define MX53_USB_CTRL_1_UH2_ULPI_ENBIT(26)
+#define MX53_USB_CTRL_1_UH3_ULPI_ENBIT(27)
+#define MX53_USB_UHx_CTRL_WAKE_UP_EN   BIT(7)
+#define MX53_USB_UHx_CTRL_ULPI_INT_EN  BIT(8)
 #define MX53_USB_PHYCTRL1_PLLDIV_MASK  0x3
 #define MX53_USB_PLL_DIV_24_MHZ0x01
 
@@ -199,31 +208,69 @@ static int usbmisc_imx53_init(struct imx_usbmisc_data 
*data)
val |= MX53_USB_PLL_DIV_24_MHZ;
writel(val, usbmisc->base + MX53_USB_OTG_PHY_CTRL_1_OFFSET);
 
-   if (data->disable_oc) {
-   spin_lock_irqsave(>lock, flags);
-   switch (data->index) {
-   case 0:
+   spin_lock_irqsave(>lock, flags);
+
+   switch (data->index) {
+   case 0:
+   if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_OTG;
-   break;
-   case 1:
+   writel(val, reg);
+   }
+   break;
+   case 1:
+   if (data->disable_oc) {
reg = usbmisc->base + MX53_USB_OTG_PHY_CTRL_0_OFFSET;
val = readl(reg) | MX53_BM_OVER_CUR_DIS_H1;
-   break;
-   case 2:
+   writel(val, reg);
+   }
+   break;
+   case 2:
+   if (data->ulpi) {
+   /* set USBH2 into ULPI-mode. */
+   reg = usbmisc->base + MX53_USB_CTRL_1_OFFSET;
+   val = readl(reg) | MX53_USB_CTRL_1_UH2_ULPI_EN;
+   /* select ULPI clock */
+   val &= ~MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_MASK;
+   val |= MX53_USB_CTRL_1_H2_XCVR_CLK_SEL_ULPI;
+   writel(val, reg);
+   /* Set interrupt wake up enable */
+   reg = usbmisc->base + MX53_USB_UH2_CTRL_OFFSET;
+   val = readl(reg) | MX53_USB_UHx_CTRL_WAKE_UP_EN
+   | MX53_USB_UHx_CTRL_ULPI_INT_EN;
+   writel(val, reg);
+   }
+   

[PATCH v5 0/2] usb: chipidea: imx: Add USB configuration for imx53

2016-09-21 Thread Fabien Lahoudere
Changes in V2:
- Patches sent to early with bad contents
Changes in V3:
- Change subject
- Split "configure imx for ULPI phy" for disable-oc code
Changes in V4:
- Fix "Change switch order" commit message
- Indent switch/case (set case on the same column as switch)
- Remove useless test in "Change switch order"
Changes in V5:
- Squash "Change switch order" and "configure imx for ULPI phy"
    - Add device tree binding documentation

Fabien Lahoudere (2):
  usb: chipidea: imx: configure imx for ULPI phy
  usb: chipidea: imx: Add binding to disable USB 60Mhz clock

 .../devicetree/bindings/usb/ci-hdrc-usb2.txt   |  1 +
 drivers/usb/chipidea/ci_hdrc_imx.c |  7 ++
 drivers/usb/chipidea/ci_hdrc_imx.h |  2 +
 drivers/usb/chipidea/usbmisc_imx.c | 88 ++
 4 files changed, 84 insertions(+), 14 deletions(-)

-- 
2.1.4



[PATCH v5 0/2] usb: chipidea: imx: Add USB configuration for imx53

2016-09-21 Thread Fabien Lahoudere
Changes in V2:
- Patches sent to early with bad contents
Changes in V3:
- Change subject
- Split "configure imx for ULPI phy" for disable-oc code
Changes in V4:
- Fix "Change switch order" commit message
- Indent switch/case (set case on the same column as switch)
- Remove useless test in "Change switch order"
Changes in V5:
- Squash "Change switch order" and "configure imx for ULPI phy"
    - Add device tree binding documentation

Fabien Lahoudere (2):
  usb: chipidea: imx: configure imx for ULPI phy
  usb: chipidea: imx: Add binding to disable USB 60Mhz clock

 .../devicetree/bindings/usb/ci-hdrc-usb2.txt   |  1 +
 drivers/usb/chipidea/ci_hdrc_imx.c |  7 ++
 drivers/usb/chipidea/ci_hdrc_imx.h |  2 +
 drivers/usb/chipidea/usbmisc_imx.c | 88 ++
 4 files changed, 84 insertions(+), 14 deletions(-)

-- 
2.1.4



  1   2   >