Re: [PATCH] dt-bindings: iio: imu: mpu6050: Improve i2c-gate disallow list

2024-04-08 Thread Jean-Baptiste Maneyrol
Hello Luca,

good catch, thanks for the patch!

Acked-by: Jean-Baptiste Maneyrol 


From: Luca Weiss 
Sent: Monday, April 8, 2024 18:34
To: ~postmarketos/upstream...@lists.sr.ht 
<~postmarketos/upstream...@lists.sr.ht>; phone-de...@vger.kernel.org 
; Jonathan Cameron ; Lars-Peter 
Clausen ; Rob Herring ; Krzysztof Kozlowski 
; Conor Dooley ; Jean-Baptiste 
Maneyrol 
Cc: linux-...@vger.kernel.org ; 
devicet...@vger.kernel.org ; 
linux-kernel@vger.kernel.org ; Luca Weiss 

Subject: [PATCH] dt-bindings: iio: imu: mpu6050: Improve i2c-gate disallow list
 
This Message Is From an Untrusted Sender
You have not previously corresponded with this sender.
 
Before all supported sensors except for MPU{9150,9250,9255} were not
allowed to use i2c-gate in the bindings which excluded quite a few
supported sensors where this functionality is supported.

Switch the list of sensors to ones where the Linux driver explicitly
disallows support for the auxiliary bus ("inv_mpu_i2c_aux_bus"). Since
the driver is also based on "default: return true" this should scale
better into the future.

Signed-off-by: Luca Weiss 
---
This fixes dt validation error on qcom-msm8974-lge-nexus5-hammerhead
which uses mpu6515

arch/arm/boot/dts/qcom/qcom-msm8974-lge-nexus5-hammerhead.dtb: mpu6515@68: 
i2c-gate: False schema does not allow {'#address-cells': [[1]], '#size-cells': 
[[0]], 'ak8963@f': {'compatible': ['asahi-kasei,ak8963'], 'reg': [[15]], 
'gpios': [[40, 67, 0]], 'vid-supply': [[50]], 'vdd-supply': [[49]]}, 
'bmp280@76': {'compatible': ['bosch,bmp280'], 'reg': [[118]], 'vdda-supply': 
[[50]], 'vddd-supply': [[49]]}}
from schema $id: 
https://urldefense.com/v3/__http://devicetree.org/schemas/iio/imu/invensense,mpu6050.yaml*__;Iw!!FtrhtPsWDhZ6tw!Athn1pwCL_LPpZ97exHEFSkirApIqFF2ISY01IuyHtFBxpbPkcPWh_FmzB_TiCzb8uv1HO0AHY4IeIlv1-o$[devicetree[.]org]
---
 .../devicetree/bindings/iio/imu/invensense,mpu6050.yaml | 17 +
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml 
b/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
index 297b8a1a7ffb..587ff2bced2d 100644
--- a/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
+++ b/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
@@ -62,14 +62,15 @@ properties:
 allOf:
   - $ref: /schemas/spi/spi-peripheral-props.yaml#
   - if:
-  not:
-properties:
-  compatible:
-contains:
-  enum:
-- invensense,mpu9150
-- invensense,mpu9250
-- invensense,mpu9255
+  properties:
+compatible:
+  contains:
+enum:
+  - invensense,iam20680
+  - invensense,icm20602
+  - invensense,icm20608
+  - invensense,icm20609
+  - invensense,icm20689
 then:
   properties:
 i2c-gate: false

---
base-commit: 8568bb2ccc278f344e6ac44af6ed010a90aa88dc
change-id: 20240408-mpu6050-i2c-gate-4ea473e492f4

Best regards,
-- 
Luca Weiss 




Re: [PATCH V4] iio:imu:mpu6050: Modify matricies to matrices

2021-03-25 Thread Jean-Baptiste Maneyrol
Hello,

thanks for the patch,
JB

Acked-by: Jean-Baptiste Maneyrol 


From: Guoqing chi 
Sent: Monday, March 22, 2021 02:30
To: ji...@kernel.org 
Cc: linux-kernel@vger.kernel.org ; 
chiguoq...@yulong.com ; rdun...@infradead.org 
; linux-...@vger.kernel.org ; 
chi96246...@163.com 
Subject: [PATCH V4] iio:imu:mpu6050: Modify matricies to matrices 
 
 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.

From: Guoqing Chi 

The plural of "matrix" is "matrices".

Signed-off-by: Guoqing Chi 
Acked-by: Randy Dunlap 
---
V4:adding linux-...@vger.kernel.org.

 include/linux/platform_data/invensense_mpu6050.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/platform_data/invensense_mpu6050.h 
b/include/linux/platform_data/invensense_mpu6050.h
index 93974f4cfba1..f05b37521f67 100644
--- a/include/linux/platform_data/invensense_mpu6050.h
+++ b/include/linux/platform_data/invensense_mpu6050.h
@@ -12,7 +12,7 @@
  * mounting matrix retrieved from device-tree)
  *
  * Contains platform specific information on how to configure the MPU6050 to
- * work on this platform.  The orientation matricies are 3x3 rotation matricies
+ * work on this platform.  The orientation matrices are 3x3 rotation matrices
  * that are applied to the data to rotate from the mounting orientation to the
  * platform orientation.  The values must be one of 0, 1, or -1 and each row 
and
  * column should have exactly 1 non-zero value.
-- 
2.17.1



Re: [PATCH v4 08/13] Documentation: ABI: add specific icm42600 documentation

2020-11-16 Thread Jean-Baptiste Maneyrol
Hello Jonathan,

no problem for me, you can move it wherever you see fit.

Thank you.
JB


From: Jonathan Cameron 
Sent: Saturday, November 14, 2020 16:23
To: Jean-Baptiste Maneyrol 
Cc: robh...@kernel.org ; r...@kernel.org ; 
mchehab+hua...@kernel.org ; da...@davemloft.net 
; gre...@linuxfoundation.org ; 
linux-...@vger.kernel.org ; 
devicet...@vger.kernel.org ; 
linux-kernel@vger.kernel.org 
Subject: Re: [PATCH v4 08/13] Documentation: ABI: add specific icm42600 
documentation 
 
 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.

On Mon, 22 Jun 2020 17:37:24 +0200
Jean-Baptiste Maneyrol  wrote:

> Hardware offset available as calibscale sysfs attributes are real
> physical values exprimed in SI units.
> 
> calibscale_available sysfs attributes represents the range of
> acceptable values.
> 
> Signed-off-by: Jean-Baptiste Maneyrol 

Hi Jean-Baptiste. 

This is causing us some issues as the ABI docs are now added to the
generated html docs for the kernel.  It's been a while, so I've kind
of forgotten why we have this file.  Was the issue that these are
in SI units as opposed to most calibbias controls which are offsets
applied to the raw analog reading hitting the ADC?

Would you mind if we moved this into the main doc as a note for this
particular device?

i.e. something in sysfs-bus-iio saying

icm42600: Hardware applied calibration offset is in SI units (rad/s or m/s^2 as 
appropriate)

?

Thanks,

Jonathan
 
> ---
>  .../ABI/testing/sysfs-bus-iio-icm42600    | 20 +++
>  1 file changed, 20 insertions(+)
>  create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-icm42600
> 
> diff --git a/Documentation/ABI/testing/sysfs-bus-iio-icm42600 
> b/Documentation/ABI/testing/sysfs-bus-iio-icm42600
> new file mode 100644
> index ..0bf1fd4f5bf1
> --- /dev/null
> +++ b/Documentation/ABI/testing/sysfs-bus-iio-icm42600
> @@ -0,0 +1,20 @@
> +What:    /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibbias
> +What:    /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibbias
> +What:    /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibbias
> +What:    /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibbias
> +What:    /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias
> +What:    /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias
> +KernelVersion:  5.8
> +Contact:    linux-...@vger.kernel.org
> +Description:
> + Hardware applied calibration offset (assumed to fix production
> + inaccuracies). Values represent a real physical offset expressed
> + in SI units (m/s^2 for accelerometer and rad/s for gyroscope).
> +
> +What:    
> /sys/bus/iio/devices/iio:deviceX/in_accel_calibbias_available
> +What:    
> /sys/bus/iio/devices/iio:deviceX/in_anglvel_calibbias_available
> +KernelVersion:  5.8
> +Contact:    linux-...@vger.kernel.org
> +Description:
> + Range of available values for hardware offset. Values in SI
> + units (m/s^2 for accelerometer and rad/s for gyroscope).


Re: [PATCH v2 13/18] iio: imu: inv_mpu6050: Simplify with dev_err_probe()

2020-08-28 Thread Jean-Baptiste Maneyrol
Hello,

thanks for the patch.

Best regards,
JB

Reviewed-by: Jean-Baptiste Maneyrol 


From: linux-iio-ow...@vger.kernel.org  on 
behalf of Krzysztof Kozlowski 
Sent: Thursday, August 27, 2020 21:26
To: Jonathan Cameron; Hartmut Knaack; Lars-Peter Clausen; Peter 
Meerwald-Stadler; Peter Rosin; Kukjin Kim; Krzysztof Kozlowski; Michael 
Hennerich; Kevin Hilman; Neil Armstrong; Jerome Brunet; Martin Blumenstingl; 
Marek Vasut; Maxime Coquelin; Alexandre Torgue; Beniamin Bia; Tomasz Duszynski; 
Linus Walleij; Andy Shevchenko; linux-...@vger.kernel.org; 
linux-kernel@vger.kernel.org; linux-arm-ker...@lists.infradead.org; 
linux-samsung-...@vger.kernel.org; linux-amlo...@lists.infradead.org; 
linux-st...@st-md-mailman.stormreply.com
Subject: [PATCH v2 13/18] iio: imu: inv_mpu6050: Simplify with dev_err_probe()

 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.

Common pattern of handling deferred probe can be simplified with
dev_err_probe().  Less code and also it prints the error value.

Signed-off-by: Krzysztof Kozlowski 
---
 drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 20 ++--
 1 file changed, 6 insertions(+), 14 deletions(-)

diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c 
b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 3fee3947f772..18a1898e3e34 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -1475,22 +1475,14 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, 
const char *name,
}

st->vdd_supply = devm_regulator_get(dev, "vdd");
-   if (IS_ERR(st->vdd_supply)) {
-   if (PTR_ERR(st->vdd_supply) != -EPROBE_DEFER)
-   dev_err(dev, "Failed to get vdd regulator %d\n",
-   (int)PTR_ERR(st->vdd_supply));
-
-   return PTR_ERR(st->vdd_supply);
-   }
+   if (IS_ERR(st->vdd_supply))
+   return dev_err_probe(dev, PTR_ERR(st->vdd_supply),
+"Failed to get vdd regulator\n");

st->vddio_supply = devm_regulator_get(dev, "vddio");
-   if (IS_ERR(st->vddio_supply)) {
-   if (PTR_ERR(st->vddio_supply) != -EPROBE_DEFER)
-   dev_err(dev, "Failed to get vddio regulator %d\n",
-   (int)PTR_ERR(st->vddio_supply));
-
-   return PTR_ERR(st->vddio_supply);
-   }
+   if (IS_ERR(st->vddio_supply))
+   return dev_err_probe(dev, PTR_ERR(st->vddio_supply),
+"Failed to get vddio regulator\n");

result = regulator_enable(st->vdd_supply);
if (result) {
--
2.17.1



Re: [PATCH] iio: imu: inv_mpu6050: check for temp_fifo_enable

2020-08-13 Thread Jean-Baptiste Maneyrol
Hello,

this is a case that should never be happening since available scan mask only 
advertise Accel + Temp, Gyro + Temp, or Accel + Gyro + Temp.
More than that, temperature sensor is not working when MEMS engine is off. 
(it's only purpose it to measure temperature of the MEMS to do data temperature 
compensation).

So I think we can let this check as it is currently, since this is not a 
supported configuration.

Best regards,
JB


From: Andy Shevchenko 
Sent: Monday, August 10, 2020 10:02
To: t...@redhat.com 
Cc: Jonathan Cameron ; Hartmut Knaack ; 
Lars-Peter Clausen ; Peter Meerwald ; 
Jean-Baptiste Maneyrol ; Michał Mirosław 
; Lee Jones ; linux-iio 
; Linux Kernel Mailing List 

Subject: Re: [PATCH] iio: imu: inv_mpu6050: check for temp_fifo_enable 
 
 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.

On Sun, Aug 9, 2020 at 7:00 PM  wrote:
>
> From: Tom Rix 
>
> clang static analysis reports this problem
>
> inv_mpu_ring.c:181:18: warning: Division by zero
> nb = fifo_count / bytes_per_datum;
>  ~~~^
>
> This is a false positive.
> Dividing by 0 is protected by this check
>
> if (!(st->chip_config.accl_fifo_enable |
> st->chip_config.gyro_fifo_enable |
> st->chip_config.magn_fifo_enable))
> goto end_session;
> bytes_per_datum = 0;
>
> But there is another fifo, temp_fifo
>
> if (st->chip_config.temp_fifo_enable)
> bytes_per_datum += INV_MPU6050_BYTES_PER_TEMP_SENSOR;
>
> Which would be skipped if it was the only enabled fifo.
> So add to the check.
>

> Fixes: 2e4c0a5e2576 ("iio: imu: inv_mpu6050: add fifo temperature data 
> support")
>
> Signed-off-by: Tom Rix 

There shouldn't be a blank line in between.

Other than that,
Reviewed-by: Andy Shevchenko 



> ---
>  drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c 
> b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
> index b533fa2dad0a..5240a400dcb4 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c
> @@ -141,6 +141,7 @@ irqreturn_t inv_mpu6050_read_fifo(int irq, void *p)
>
> if (!(st->chip_config.accl_fifo_enable |
> st->chip_config.gyro_fifo_enable |
> +   st->chip_config.temp_fifo_enable |
> st->chip_config.magn_fifo_enable))
> goto end_session;
> bytes_per_datum = 0;
> --
> 2.18.1
>


--
With Best Regards,
Andy Shevchenko

[PATCH v4 09/13] iio: imu: inv_icm42600: add device interrupt

2020-06-22 Thread Jean-Baptiste Maneyrol
Add INT1 interrupt support. Support interrupt edge and level,
active high or low. Push-pull or open-drain configurations.

Interrupt will be used to read data from the FIFO.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   2 +-
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  | 101 +-
 .../iio/imu/inv_icm42600/inv_icm42600_i2c.c   |   3 +-
 .../iio/imu/inv_icm42600/inv_icm42600_spi.c   |   3 +-
 4 files changed, 105 insertions(+), 4 deletions(-)

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index 3b190461a2b6..148894c888cc 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -372,7 +372,7 @@ int inv_icm42600_set_temp_conf(struct inv_icm42600_state 
*st, bool enable,
 int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg,
 unsigned int writeval, unsigned int *readval);
 
-int inv_icm42600_core_probe(struct regmap *regmap, int chip,
+int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
inv_icm42600_bus_setup bus_setup);
 
 struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st);
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
index a35ff21f50bb..95b2a6d91e5b 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
@@ -9,8 +9,11 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -408,6 +411,82 @@ static int inv_icm42600_setup(struct inv_icm42600_state 
*st,
return inv_icm42600_set_conf(st, hw->conf);
 }
 
+static irqreturn_t inv_icm42600_irq_handler(int irq, void *_data)
+{
+   struct inv_icm42600_state *st = _data;
+   struct device *dev = regmap_get_device(st->map);
+   unsigned int status;
+   int ret;
+
+   mutex_lock(>lock);
+
+   ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, );
+   if (ret)
+   goto out_unlock;
+
+   /* FIFO full */
+   if (status & INV_ICM42600_INT_STATUS_FIFO_FULL)
+   dev_warn(dev, "FIFO full data lost!\n");
+
+out_unlock:
+   mutex_unlock(>lock);
+   return IRQ_HANDLED;
+}
+
+/**
+ * inv_icm42600_irq_init() - initialize int pin and interrupt handler
+ * @st:driver internal state
+ * @irq:   irq number
+ * @irq_type:  irq trigger type
+ * @open_drain:true if irq is open drain, false for push-pull
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+static int inv_icm42600_irq_init(struct inv_icm42600_state *st, int irq,
+int irq_type, bool open_drain)
+{
+   struct device *dev = regmap_get_device(st->map);
+   unsigned int val;
+   int ret;
+
+   /* configure INT1 interrupt: default is active low on edge */
+   switch (irq_type) {
+   case IRQF_TRIGGER_RISING:
+   case IRQF_TRIGGER_HIGH:
+   val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH;
+   break;
+   default:
+   val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW;
+   break;
+   }
+
+   switch (irq_type) {
+   case IRQF_TRIGGER_LOW:
+   case IRQF_TRIGGER_HIGH:
+   val |= INV_ICM42600_INT_CONFIG_INT1_LATCHED;
+   break;
+   default:
+   break;
+   }
+
+   if (!open_drain)
+   val |= INV_ICM42600_INT_CONFIG_INT1_PUSH_PULL;
+
+   ret = regmap_write(st->map, INV_ICM42600_REG_INT_CONFIG, val);
+   if (ret)
+   return ret;
+
+   /* Deassert async reset for proper INT pin operation (cf datasheet) */
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_CONFIG1,
+INV_ICM42600_INT_CONFIG1_ASYNC_RESET, 0);
+   if (ret)
+   return ret;
+
+   return devm_request_threaded_irq(dev, irq, NULL,
+inv_icm42600_irq_handler, irq_type,
+"inv_icm42600", st);
+}
+
 static int inv_icm42600_enable_regulator_vddio(struct inv_icm42600_state *st)
 {
int ret;
@@ -452,11 +531,14 @@ static void inv_icm42600_disable_pm(void *_data)
pm_runtime_disable(dev);
 }
 
-int inv_icm42600_core_probe(struct regmap *regmap, int chip,
+int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
inv_icm42600_bus_setup bus_setup)
 {
struct device *dev = regmap_get_device(regmap);
struct inv_icm42600_state *st;
+   struct irq_data *irq_desc;
+   int irq_type;
+   bool open_drain;
int ret;
 
if (chip < 0 || chip >= INV_CHIP_NB) {
@@ -464,6 +546,19 @@ int inv_icm42600_core_probe(struct reg

[PATCH v4 04/13] iio: imu: inv_icm42600: add gyroscope IIO device

2020-06-22 Thread Jean-Baptiste Maneyrol
Add IIO device for gyroscope sensor with data polling interface.
Attributes: raw, scale, sampling_frequency, calibbias.

Gyroscope in low noise mode.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   6 +
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |   4 +
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 603 ++
 3 files changed, 613 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index 14c8ef152418..d155470d770a 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -120,6 +120,8 @@ struct inv_icm42600_suspended {
  *  @orientation:  sensor chip orientation relative to main hardware.
  *  @conf: chip sensors configurations.
  *  @suspended:suspended sensors configuration.
+ *  @indio_gyro:   gyroscope IIO device.
+ *  @buffer:   data transfer buffer aligned for DMA.
  */
 struct inv_icm42600_state {
struct mutex lock;
@@ -131,6 +133,8 @@ struct inv_icm42600_state {
struct iio_mount_matrix orientation;
struct inv_icm42600_conf conf;
struct inv_icm42600_suspended suspended;
+   struct iio_dev *indio_gyro;
+   uint8_t buffer[2] cacheline_aligned;
 };
 
 /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
@@ -369,4 +373,6 @@ int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, 
unsigned int reg,
 int inv_icm42600_core_probe(struct regmap *regmap, int chip,
inv_icm42600_bus_setup bus_setup);
 
+struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st);
+
 #endif
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
index 2eb25c5f77f8..84e9ff320b3b 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
@@ -509,6 +509,10 @@ int inv_icm42600_core_probe(struct regmap *regmap, int 
chip,
if (ret)
return ret;
 
+   st->indio_gyro = inv_icm42600_gyro_init(st);
+   if (IS_ERR(st->indio_gyro))
+   return PTR_ERR(st->indio_gyro);
+
/* setup runtime power management */
ret = pm_runtime_set_active(dev);
if (ret)
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
new file mode 100644
index ..3875ecbee67e
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
@@ -0,0 +1,603 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+
+#define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info)   \
+   {   \
+   .type = IIO_ANGL_VEL,   \
+   .modified = 1,  \
+   .channel2 = _modifier,  \
+   .info_mask_separate =   \
+   BIT(IIO_CHAN_INFO_RAW) |\
+   BIT(IIO_CHAN_INFO_CALIBBIAS),   \
+   .info_mask_shared_by_type = \
+   BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_type_available =   \
+   BIT(IIO_CHAN_INFO_SCALE) |  \
+   BIT(IIO_CHAN_INFO_CALIBBIAS),   \
+   .info_mask_shared_by_all =  \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   .info_mask_shared_by_all_available =\
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   .scan_index = _index,   \
+   .scan_type = {  \
+   .sign = 's',\
+   .realbits = 16, \
+   .storagebits = 16,  \
+   .endianness = IIO_BE,   \
+   },  \
+   .ext_info = _ext_info,  \
+   }
+
+enum inv_icm42600_gyro_scan {
+   INV_ICM42600_GYRO_SCAN_X,
+   INV_ICM42600_GYRO_SCAN_Y,
+   INV_ICM42600_GYRO_SCAN_Z,
+};
+
+static const struct iio_chan_spec_ext_info inv_icm4

[PATCH v4 05/13] iio: imu: inv_icm42600: add accelerometer IIO device

2020-06-22 Thread Jean-Baptiste Maneyrol
Add IIO device for accelerometer sensor with data polling
interface.
Attributes: raw, scale, sampling_frequency, calibbias.

Accelerometer in low noise mode.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   4 +
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 592 ++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |   4 +
 3 files changed, 600 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index d155470d770a..3b190461a2b6 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -121,6 +121,7 @@ struct inv_icm42600_suspended {
  *  @conf: chip sensors configurations.
  *  @suspended:suspended sensors configuration.
  *  @indio_gyro:   gyroscope IIO device.
+ *  @indio_accel:  accelerometer IIO device.
  *  @buffer:   data transfer buffer aligned for DMA.
  */
 struct inv_icm42600_state {
@@ -134,6 +135,7 @@ struct inv_icm42600_state {
struct inv_icm42600_conf conf;
struct inv_icm42600_suspended suspended;
struct iio_dev *indio_gyro;
+   struct iio_dev *indio_accel;
uint8_t buffer[2] cacheline_aligned;
 };
 
@@ -375,4 +377,6 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip,
 
 struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st);
 
+struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st);
+
 #endif
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
new file mode 100644
index ..717c6b0869fc
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -0,0 +1,592 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+
+#define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)  \
+   {   \
+   .type = IIO_ACCEL,  \
+   .modified = 1,  \
+   .channel2 = _modifier,  \
+   .info_mask_separate =   \
+   BIT(IIO_CHAN_INFO_RAW) |\
+   BIT(IIO_CHAN_INFO_CALIBBIAS),   \
+   .info_mask_shared_by_type = \
+   BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_type_available =   \
+   BIT(IIO_CHAN_INFO_SCALE) |  \
+   BIT(IIO_CHAN_INFO_CALIBBIAS),   \
+   .info_mask_shared_by_all =  \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   .info_mask_shared_by_all_available =\
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   .scan_index = _index,   \
+   .scan_type = {  \
+   .sign = 's',\
+   .realbits = 16, \
+   .storagebits = 16,  \
+   .endianness = IIO_BE,   \
+   },  \
+   .ext_info = _ext_info,  \
+   }
+
+enum inv_icm42600_accel_scan {
+   INV_ICM42600_ACCEL_SCAN_X,
+   INV_ICM42600_ACCEL_SCAN_Y,
+   INV_ICM42600_ACCEL_SCAN_Z,
+};
+
+static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
+   IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42600_get_mount_matrix),
+   {},
+};
+
+static const struct iio_chan_spec inv_icm42600_accel_channels[] = {
+   INV_ICM42600_ACCEL_CHAN(IIO_MOD_X, INV_ICM42600_ACCEL_SCAN_X,
+   inv_icm42600_accel_ext_infos),
+   INV_ICM42600_ACCEL_CHAN(IIO_MOD_Y, INV_ICM42600_ACCEL_SCAN_Y,
+   inv_icm42600_accel_ext_infos),
+   INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z,
+   inv_icm42600_accel_ext_infos),
+};
+
+static int inv_icm42600_accel_read_sensor(struct inv_icm42600_state *st,
+ struct iio_chan_spec const *chan,
+ int16_t *val)
+{
+   struct device *dev = regmap_get_devi

[PATCH v4 13/13] MAINTAINERS: add entry for inv_icm42600 6-axis imu sensor

2020-06-22 Thread Jean-Baptiste Maneyrol
Add MAINTAINERS entry for InvenSense ICM-426xx IMU device.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 MAINTAINERS | 8 
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 510fa7f7c756..a65771cfc506 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8979,6 +8979,14 @@ F:   include/dt-bindings/interconnect/
 F: include/linux/interconnect-provider.h
 F: include/linux/interconnect.h
 
+INVENSENSE ICM-426xx IMU DRIVER
+M: Jean-Baptiste Maneyrol 
+L: linux-...@vger.kernel.org
+S: Maintained
+W  https://invensense.tdk.com/
+F: Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
+F: drivers/iio/imu/inv_icm42600/
+
 INVENSENSE MPU-3050 GYROSCOPE DRIVER
 M: Linus Walleij 
 L: linux-...@vger.kernel.org
-- 
2.17.1



[PATCH v4 08/13] Documentation: ABI: add specific icm42600 documentation

2020-06-22 Thread Jean-Baptiste Maneyrol
Hardware offset available as calibscale sysfs attributes are real
physical values exprimed in SI units.

calibscale_available sysfs attributes represents the range of
acceptable values.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../ABI/testing/sysfs-bus-iio-icm42600| 20 +++
 1 file changed, 20 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-icm42600

diff --git a/Documentation/ABI/testing/sysfs-bus-iio-icm42600 
b/Documentation/ABI/testing/sysfs-bus-iio-icm42600
new file mode 100644
index ..0bf1fd4f5bf1
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-iio-icm42600
@@ -0,0 +1,20 @@
+What:  /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibbias
+What:  /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibbias
+What:  /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibbias
+What:  /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibbias
+What:  /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias
+What:  /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias
+KernelVersion:  5.8
+Contact:linux-...@vger.kernel.org
+Description:
+   Hardware applied calibration offset (assumed to fix production
+   inaccuracies). Values represent a real physical offset expressed
+   in SI units (m/s^2 for accelerometer and rad/s for gyroscope).
+
+What:  /sys/bus/iio/devices/iio:deviceX/in_accel_calibbias_available
+What:  /sys/bus/iio/devices/iio:deviceX/in_anglvel_calibbias_available
+KernelVersion:  5.8
+Contact:linux-...@vger.kernel.org
+Description:
+   Range of available values for hardware offset. Values in SI
+   units (m/s^2 for accelerometer and rad/s for gyroscope).
-- 
2.17.1



[PATCH v4 06/13] iio: imu: inv_icm42600: add temperature sensor support

2020-06-22 Thread Jean-Baptiste Maneyrol
Add temperature channel in gyroscope and accelerometer devices.

Temperature is available in full 16 bits resolution when reading
register and in low 8 bits resolution in the FIFO. Return full
precision raw temperature with corresponding scale and offset.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 11 ++-
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 11 ++-
 .../iio/imu/inv_icm42600/inv_icm42600_temp.c  | 84 +++
 .../iio/imu/inv_icm42600/inv_icm42600_temp.h  | 30 +++
 4 files changed, 134 insertions(+), 2 deletions(-)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index 717c6b0869fc..3f214df44093 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -13,6 +13,7 @@
 #include 
 
 #include "inv_icm42600.h"
+#include "inv_icm42600_temp.h"
 
 #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)  \
{   \
@@ -45,6 +46,7 @@ enum inv_icm42600_accel_scan {
INV_ICM42600_ACCEL_SCAN_X,
INV_ICM42600_ACCEL_SCAN_Y,
INV_ICM42600_ACCEL_SCAN_Z,
+   INV_ICM42600_ACCEL_SCAN_TEMP,
 };
 
 static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
@@ -59,6 +61,7 @@ static const struct iio_chan_spec 
inv_icm42600_accel_channels[] = {
inv_icm42600_accel_ext_infos),
INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z,
inv_icm42600_accel_ext_infos),
+   INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP),
 };
 
 static int inv_icm42600_accel_read_sensor(struct inv_icm42600_state *st,
@@ -450,8 +453,14 @@ static int inv_icm42600_accel_read_raw(struct iio_dev 
*indio_dev,
int16_t data;
int ret;
 
-   if (chan->type != IIO_ACCEL)
+   switch (chan->type) {
+   case IIO_ACCEL:
+   break;
+   case IIO_TEMP:
+   return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, 
mask);
+   default:
return -EINVAL;
+   }
 
switch (mask) {
case IIO_CHAN_INFO_RAW:
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
index 3875ecbee67e..6a0e7661fa48 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
@@ -13,6 +13,7 @@
 #include 
 
 #include "inv_icm42600.h"
+#include "inv_icm42600_temp.h"
 
 #define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info)   \
{   \
@@ -45,6 +46,7 @@ enum inv_icm42600_gyro_scan {
INV_ICM42600_GYRO_SCAN_X,
INV_ICM42600_GYRO_SCAN_Y,
INV_ICM42600_GYRO_SCAN_Z,
+   INV_ICM42600_GYRO_SCAN_TEMP,
 };
 
 static const struct iio_chan_spec_ext_info inv_icm42600_gyro_ext_infos[] = {
@@ -59,6 +61,7 @@ static const struct iio_chan_spec 
inv_icm42600_gyro_channels[] = {
   inv_icm42600_gyro_ext_infos),
INV_ICM42600_GYRO_CHAN(IIO_MOD_Z, INV_ICM42600_GYRO_SCAN_Z,
   inv_icm42600_gyro_ext_infos),
+   INV_ICM42600_TEMP_CHAN(INV_ICM42600_GYRO_SCAN_TEMP),
 };
 
 static int inv_icm42600_gyro_read_sensor(struct inv_icm42600_state *st,
@@ -461,8 +464,14 @@ static int inv_icm42600_gyro_read_raw(struct iio_dev 
*indio_dev,
int16_t data;
int ret;
 
-   if (chan->type != IIO_ANGL_VEL)
+   switch (chan->type) {
+   case IIO_ANGL_VEL:
+   break;
+   case IIO_TEMP:
+   return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, 
mask);
+   default:
return -EINVAL;
+   }
 
switch (mask) {
case IIO_CHAN_INFO_RAW:
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
new file mode 100644
index ..213cce1c3111
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+#include "inv_icm42600_temp.h"
+
+static int inv_icm42600_temp_read(struct inv_icm42600_state *st, int16_t *temp)
+{
+   struct device *dev = regmap_get_device(st->map);
+   __be16 *raw;
+   int ret;
+
+   pm_runtime_get_sync(dev);
+   mutex_lock(>lock);
+
+   ret = inv_icm42600_set_temp_conf(st, true, NULL);
+   if (ret)
+   goto exit

[PATCH v4 11/13] iio: imu: inv_icm42600: add accurate timestamping

2020-06-22 Thread Jean-Baptiste Maneyrol
Add a timestamping mechanism for buffer that provides accurate
event timestamps when using watermark. This mechanism estimates
device internal clock by comparing FIFO interrupts delta time and
device elapsed time computed by parsing FIFO data.

Take interrupt timestamp in hard irq handler and add IIO device
specific timestamp structures in device private allocation.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/Makefile |   1 +
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   5 +
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c |  40 +++-
 .../imu/inv_icm42600/inv_icm42600_buffer.c|  28 +++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |  17 +-
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  |  40 +++-
 .../imu/inv_icm42600/inv_icm42600_timestamp.c | 195 ++
 .../imu/inv_icm42600/inv_icm42600_timestamp.h |  85 
 8 files changed, 396 insertions(+), 15 deletions(-)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h

diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
b/drivers/iio/imu/inv_icm42600/Makefile
index 0f49f6df3647..291714d9aa54 100644
--- a/drivers/iio/imu/inv_icm42600/Makefile
+++ b/drivers/iio/imu/inv_icm42600/Makefile
@@ -6,6 +6,7 @@ inv-icm42600-y += inv_icm42600_gyro.o
 inv-icm42600-y += inv_icm42600_accel.o
 inv-icm42600-y += inv_icm42600_temp.o
 inv-icm42600-y += inv_icm42600_buffer.o
+inv-icm42600-y += inv_icm42600_timestamp.o
 
 obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o
 inv-icm42600-i2c-y += inv_icm42600_i2c.o
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index 7b52d92739c3..c0f5059b13b3 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -126,6 +126,7 @@ struct inv_icm42600_suspended {
  *  @indio_accel:  accelerometer IIO device.
  *  @buffer:   data transfer buffer aligned for DMA.
  *  @fifo: FIFO management structure.
+ *  @timestamp:interrupt timestamps.
  */
 struct inv_icm42600_state {
struct mutex lock;
@@ -141,6 +142,10 @@ struct inv_icm42600_state {
struct iio_dev *indio_accel;
uint8_t buffer[2] cacheline_aligned;
struct inv_icm42600_fifo fifo;
+   struct {
+   int64_t gyro;
+   int64_t accel;
+   } timestamp;
 };
 
 /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index fbc029bd6e72..3441b0d61c5d 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -17,6 +17,7 @@
 #include "inv_icm42600.h"
 #include "inv_icm42600_temp.h"
 #include "inv_icm42600_buffer.h"
+#include "inv_icm42600_timestamp.h"
 
 #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)  \
{   \
@@ -50,6 +51,7 @@ enum inv_icm42600_accel_scan {
INV_ICM42600_ACCEL_SCAN_Y,
INV_ICM42600_ACCEL_SCAN_Z,
INV_ICM42600_ACCEL_SCAN_TEMP,
+   INV_ICM42600_ACCEL_SCAN_TIMESTAMP,
 };
 
 static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
@@ -65,15 +67,17 @@ static const struct iio_chan_spec 
inv_icm42600_accel_channels[] = {
INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z,
inv_icm42600_accel_ext_infos),
INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP),
+   IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42600_ACCEL_SCAN_TIMESTAMP),
 };
 
 /*
- * IIO buffer data: size must be a power of 2
- * 8 bytes: 6 bytes acceleration and 2 bytes temperature
+ * IIO buffer data: size must be a power of 2 and timestamp aligned
+ * 16 bytes: 6 bytes acceleration, 2 bytes temperature, 8 bytes timestamp
  */
 struct inv_icm42600_accel_buffer {
struct inv_icm42600_fifo_sensor_data accel;
int16_t temp;
+   int64_t timestamp __aligned(8);
 };
 
 #define INV_ICM42600_SCAN_MASK_ACCEL_3AXIS \
@@ -94,6 +98,7 @@ static int inv_icm42600_accel_update_scan_mode(struct iio_dev 
*indio_dev,
   const unsigned long *scan_mask)
 {
struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+   struct inv_icm42600_timestamp *ts = iio_priv(indio_dev);
struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
unsigned int fifo_en = 0;
unsigned int sleep_temp = 0;
@@ -121,6 +126,7 @@ static int inv_icm42600_accel_update_scan_mode(struct 
iio_dev *indio_dev,
}
 
/* update data FIFO write */
+   inv_icm42600_timestamp_apply_odr(ts, 0, 0, 0);
ret = inv_icm42600_buff

[PATCH v4 10/13] iio: imu: inv_icm42600: add buffer support in iio devices

2020-06-22 Thread Jean-Baptiste Maneyrol
Add all FIFO parsing and reading functions. Add accel and gyro
kfifo buffer and FIFO data parsing. Use device interrupt for
reading data FIFO and launching accel and gyro parsing.

Support hwfifo watermark by multiplexing gyro and accel settings.
Support hwfifo flush.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/Kconfig  |   1 +
 drivers/iio/imu/inv_icm42600/Makefile |   1 +
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   8 +
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 162 -
 .../imu/inv_icm42600/inv_icm42600_buffer.c| 573 ++
 .../imu/inv_icm42600/inv_icm42600_buffer.h|  98 +++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |  30 +
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 162 -
 8 files changed, 1033 insertions(+), 2 deletions(-)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h

diff --git a/drivers/iio/imu/inv_icm42600/Kconfig 
b/drivers/iio/imu/inv_icm42600/Kconfig
index 22390a72f0a3..50cbcfcb6cf1 100644
--- a/drivers/iio/imu/inv_icm42600/Kconfig
+++ b/drivers/iio/imu/inv_icm42600/Kconfig
@@ -2,6 +2,7 @@
 
 config INV_ICM42600
tristate
+   select IIO_BUFFER
 
 config INV_ICM42600_I2C
tristate "InvenSense ICM-426xx I2C driver"
diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
b/drivers/iio/imu/inv_icm42600/Makefile
index 48965824f00c..0f49f6df3647 100644
--- a/drivers/iio/imu/inv_icm42600/Makefile
+++ b/drivers/iio/imu/inv_icm42600/Makefile
@@ -5,6 +5,7 @@ inv-icm42600-y += inv_icm42600_core.o
 inv-icm42600-y += inv_icm42600_gyro.o
 inv-icm42600-y += inv_icm42600_accel.o
 inv-icm42600-y += inv_icm42600_temp.o
+inv-icm42600-y += inv_icm42600_buffer.o
 
 obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o
 inv-icm42600-i2c-y += inv_icm42600_i2c.o
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index 148894c888cc..7b52d92739c3 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -14,6 +14,8 @@
 #include 
 #include 
 
+#include "inv_icm42600_buffer.h"
+
 enum inv_icm42600_chip {
INV_CHIP_ICM42600,
INV_CHIP_ICM42602,
@@ -123,6 +125,7 @@ struct inv_icm42600_suspended {
  *  @indio_gyro:   gyroscope IIO device.
  *  @indio_accel:  accelerometer IIO device.
  *  @buffer:   data transfer buffer aligned for DMA.
+ *  @fifo: FIFO management structure.
  */
 struct inv_icm42600_state {
struct mutex lock;
@@ -137,6 +140,7 @@ struct inv_icm42600_state {
struct iio_dev *indio_gyro;
struct iio_dev *indio_accel;
uint8_t buffer[2] cacheline_aligned;
+   struct inv_icm42600_fifo fifo;
 };
 
 /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
@@ -377,6 +381,10 @@ int inv_icm42600_core_probe(struct regmap *regmap, int 
chip, int irq,
 
 struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st);
 
+int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev);
+
 struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st);
 
+int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev);
+
 #endif
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index 3f214df44093..fbc029bd6e72 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -11,9 +11,12 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "inv_icm42600.h"
 #include "inv_icm42600_temp.h"
+#include "inv_icm42600_buffer.h"
 
 #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)  \
{   \
@@ -64,6 +67,78 @@ static const struct iio_chan_spec 
inv_icm42600_accel_channels[] = {
INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP),
 };
 
+/*
+ * IIO buffer data: size must be a power of 2
+ * 8 bytes: 6 bytes acceleration and 2 bytes temperature
+ */
+struct inv_icm42600_accel_buffer {
+   struct inv_icm42600_fifo_sensor_data accel;
+   int16_t temp;
+};
+
+#define INV_ICM42600_SCAN_MASK_ACCEL_3AXIS \
+   (BIT(INV_ICM42600_ACCEL_SCAN_X) |   \
+   BIT(INV_ICM42600_ACCEL_SCAN_Y) |\
+   BIT(INV_ICM42600_ACCEL_SCAN_Z))
+
+#define INV_ICM42600_SCAN_MASK_TEMPBIT(INV_ICM42600_ACCEL_SCAN_TEMP)
+
+static const unsigned long inv_icm42600_accel_scan_masks[] = {
+   /* 3-axis accel + temperature */
+   INV_ICM42600_SCAN_MASK_ACCEL_3AXIS | INV_ICM42600_SCAN_MASK_TEMP,
+   0,
+};
+
+/* enable accelerometer sensor and FIFO write */
+static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev,
+  

[PATCH v4 01/13] iio: imu: inv_icm42600: add core of new inv_icm42600 driver

2020-06-22 Thread Jean-Baptiste Maneyrol
Core component of a new driver for InvenSense ICM-426xx devices.
It includes registers definition, main probe/setup, and device
utility functions.

ICM-426xx devices are latest generation of 6-axis IMU,
gyroscope+accelerometer and temperature sensor. This device
includes a 2K FIFO, supports I2C/I3C/SPI, and provides
intelligent motion features like pedometer, tilt detection,
and tap detection.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   | 372 ++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  | 634 ++
 2 files changed, 1006 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600.h
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_core.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
new file mode 100644
index ..14c8ef152418
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -0,0 +1,372 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#ifndef INV_ICM42600_H_
+#define INV_ICM42600_H_
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+enum inv_icm42600_chip {
+   INV_CHIP_ICM42600,
+   INV_CHIP_ICM42602,
+   INV_CHIP_ICM42605,
+   INV_CHIP_ICM42622,
+   INV_CHIP_NB,
+};
+
+/* serial bus slew rates */
+enum inv_icm42600_slew_rate {
+   INV_ICM42600_SLEW_RATE_20_60NS,
+   INV_ICM42600_SLEW_RATE_12_36NS,
+   INV_ICM42600_SLEW_RATE_6_18NS,
+   INV_ICM42600_SLEW_RATE_4_12NS,
+   INV_ICM42600_SLEW_RATE_2_6NS,
+   INV_ICM42600_SLEW_RATE_INF_2NS,
+};
+
+enum inv_icm42600_sensor_mode {
+   INV_ICM42600_SENSOR_MODE_OFF,
+   INV_ICM42600_SENSOR_MODE_STANDBY,
+   INV_ICM42600_SENSOR_MODE_LOW_POWER,
+   INV_ICM42600_SENSOR_MODE_LOW_NOISE,
+   INV_ICM42600_SENSOR_MODE_NB,
+};
+
+/* gyroscope fullscale values */
+enum inv_icm42600_gyro_fs {
+   INV_ICM42600_GYRO_FS_2000DPS,
+   INV_ICM42600_GYRO_FS_1000DPS,
+   INV_ICM42600_GYRO_FS_500DPS,
+   INV_ICM42600_GYRO_FS_250DPS,
+   INV_ICM42600_GYRO_FS_125DPS,
+   INV_ICM42600_GYRO_FS_62_5DPS,
+   INV_ICM42600_GYRO_FS_31_25DPS,
+   INV_ICM42600_GYRO_FS_15_625DPS,
+   INV_ICM42600_GYRO_FS_NB,
+};
+
+/* accelerometer fullscale values */
+enum inv_icm42600_accel_fs {
+   INV_ICM42600_ACCEL_FS_16G,
+   INV_ICM42600_ACCEL_FS_8G,
+   INV_ICM42600_ACCEL_FS_4G,
+   INV_ICM42600_ACCEL_FS_2G,
+   INV_ICM42600_ACCEL_FS_NB,
+};
+
+/* ODR suffixed by LN or LP are Low-Noise or Low-Power mode only */
+enum inv_icm42600_odr {
+   INV_ICM42600_ODR_8KHZ_LN = 3,
+   INV_ICM42600_ODR_4KHZ_LN,
+   INV_ICM42600_ODR_2KHZ_LN,
+   INV_ICM42600_ODR_1KHZ_LN,
+   INV_ICM42600_ODR_200HZ,
+   INV_ICM42600_ODR_100HZ,
+   INV_ICM42600_ODR_50HZ,
+   INV_ICM42600_ODR_25HZ,
+   INV_ICM42600_ODR_12_5HZ,
+   INV_ICM42600_ODR_6_25HZ_LP,
+   INV_ICM42600_ODR_3_125HZ_LP,
+   INV_ICM42600_ODR_1_5625HZ_LP,
+   INV_ICM42600_ODR_500HZ,
+   INV_ICM42600_ODR_NB,
+};
+
+enum inv_icm42600_filter {
+   /* Low-Noise mode sensor data filter (3rd order filter by default) */
+   INV_ICM42600_FILTER_BW_ODR_DIV_2,
+
+   /* Low-Power mode sensor data filter (averaging) */
+   INV_ICM42600_FILTER_AVG_1X = 1,
+   INV_ICM42600_FILTER_AVG_16X = 6,
+};
+
+struct inv_icm42600_sensor_conf {
+   int mode;
+   int fs;
+   int odr;
+   int filter;
+};
+#define INV_ICM42600_SENSOR_CONF_INIT  {-1, -1, -1, -1}
+
+struct inv_icm42600_conf {
+   struct inv_icm42600_sensor_conf gyro;
+   struct inv_icm42600_sensor_conf accel;
+   bool temp_en;
+};
+
+struct inv_icm42600_suspended {
+   enum inv_icm42600_sensor_mode gyro;
+   enum inv_icm42600_sensor_mode accel;
+   bool temp;
+};
+
+/**
+ *  struct inv_icm42600_state - driver state variables
+ *  @lock: lock for serializing multiple registers access.
+ *  @chip: chip identifier.
+ *  @name: chip name.
+ *  @map:  regmap pointer.
+ *  @vdd_supply:   VDD voltage regulator for the chip.
+ *  @vddio_supply: I/O voltage regulator for the chip.
+ *  @orientation:  sensor chip orientation relative to main hardware.
+ *  @conf: chip sensors configurations.
+ *  @suspended:suspended sensors configuration.
+ */
+struct inv_icm42600_state {
+   struct mutex lock;
+   enum inv_icm42600_chip chip;
+   const char *name;
+   struct regmap *map;
+   struct regulator *vdd_supply;
+   struct regulator *vddio_supply;
+   struct iio_mount_matrix orientation;
+   struct inv_icm42600_conf conf;
+   struct inv_icm42600_suspended suspended;
+};
+
+/* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
+
+/* Bank selection register, available in all banks */
+#define

[PATCH v4 12/13] dt-bindings: iio: imu: Add inv_icm42600 documentation

2020-06-22 Thread Jean-Baptiste Maneyrol
Document the ICM-426xxx devices devicetree bindings.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../bindings/iio/imu/invensense,icm42600.yaml | 90 +++
 1 file changed, 90 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml

diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml 
b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
new file mode 100644
index ..abd8d25e1136
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
@@ -0,0 +1,90 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/imu/invensense,icm42600.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: InvenSense ICM-426xx Inertial Measurement Unit
+
+maintainers:
+  - Jean-Baptiste Maneyrol 
+
+description: |
+  6-axis MotionTracking device that combines a 3-axis gyroscope and a 3-axis
+  accelerometer.
+
+  It has a configurable host interface that supports I3C, I2C and SPI serial
+  communication, features a 2kB FIFO and 2 programmable interrupts with
+  ultra-low-power wake-on-motion support to minimize system power consumption.
+
+  Other industry-leading features include InvenSense on-chip APEX Motion
+  Processing engine for gesture recognition, activity classification, and
+  pedometer, along with programmable digital filters, and an embedded
+  temperature sensor.
+
+  
https://invensense.tdk.com/wp-content/uploads/2020/03/DS-000292-ICM-42605-v1.4.pdf
+
+properties:
+  compatible:
+enum:
+  - invensense,icm42600
+  - invensense,icm42602
+  - invensense,icm42605
+  - invensense,icm42622
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  drive-open-drain:
+type: boolean
+
+  vdd-supply:
+description: Regulator that provides power to the sensor
+
+  vddio-supply:
+description: Regulator that provides power to the bus
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+examples:
+  - |
+#include 
+#include 
+i2c0 {
+#address-cells = <1>;
+#size-cells = <0>;
+
+icm42605@68 {
+  compatible = "invensense,icm42605";
+  reg = <0x68>;
+  interrupt-parent = <>;
+  interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+  vdd-supply = <>;
+  vddio-supply = <>;
+};
+};
+  - |
+#include 
+#include 
+spi0 {
+#address-cells = <1>;
+#size-cells = <0>;
+
+icm42602@0 {
+  compatible = "invensense,icm42602";
+  reg = <0>;
+  spi-max-frequency = <2400>;
+  spi-cpha;
+  spi-cpol;
+  interrupt-parent = <>;
+  interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+  vdd-supply = <>;
+  vddio-supply = <>;
+};
+};
-- 
2.17.1



[PATCH v4 07/13] iio: imu: add Kconfig and Makefile for inv_icm42600 driver

2020-06-22 Thread Jean-Baptiste Maneyrol
Add 3 modules: inv-icm42600, inv-icm42600-i2c, inv-icm42600-spi.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/Kconfig   |  1 +
 drivers/iio/imu/Makefile  |  1 +
 drivers/iio/imu/inv_icm42600/Kconfig  | 28 +++
 drivers/iio/imu/inv_icm42600/Makefile | 13 +
 4 files changed, 43 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/Kconfig
 create mode 100644 drivers/iio/imu/inv_icm42600/Makefile

diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index fc4123d518bc..f02883b08480 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -91,6 +91,7 @@ config KMX61
  To compile this driver as module, choose M here: the module will
  be called kmx61.
 
+source "drivers/iio/imu/inv_icm42600/Kconfig"
 source "drivers/iio/imu/inv_mpu6050/Kconfig"
 source "drivers/iio/imu/st_lsm6dsx/Kconfig"
 
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index 88b2c4555230..13e9ff442b11 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_FXOS8700) += fxos8700_core.o
 obj-$(CONFIG_FXOS8700_I2C) += fxos8700_i2c.o
 obj-$(CONFIG_FXOS8700_SPI) += fxos8700_spi.o
 
+obj-y += inv_icm42600/
 obj-y += inv_mpu6050/
 
 obj-$(CONFIG_KMX61) += kmx61.o
diff --git a/drivers/iio/imu/inv_icm42600/Kconfig 
b/drivers/iio/imu/inv_icm42600/Kconfig
new file mode 100644
index ..22390a72f0a3
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/Kconfig
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+config INV_ICM42600
+   tristate
+
+config INV_ICM42600_I2C
+   tristate "InvenSense ICM-426xx I2C driver"
+   depends on I2C
+   select INV_ICM42600
+   select REGMAP_I2C
+   help
+ This driver supports the InvenSense ICM-426xx motion tracking
+ devices over I2C.
+
+ This driver can be built as a module. The module will be called
+ inv-icm42600-i2c.
+
+config INV_ICM42600_SPI
+   tristate "InvenSense ICM-426xx SPI driver"
+   depends on SPI_MASTER
+   select INV_ICM42600
+   select REGMAP_SPI
+   help
+ This driver supports the InvenSense ICM-426xx motion tracking
+ devices over SPI.
+
+ This driver can be built as a module. The module will be called
+ inv-icm42600-spi.
diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
b/drivers/iio/imu/inv_icm42600/Makefile
new file mode 100644
index ..48965824f00c
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/Makefile
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+obj-$(CONFIG_INV_ICM42600) += inv-icm42600.o
+inv-icm42600-y += inv_icm42600_core.o
+inv-icm42600-y += inv_icm42600_gyro.o
+inv-icm42600-y += inv_icm42600_accel.o
+inv-icm42600-y += inv_icm42600_temp.o
+
+obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o
+inv-icm42600-i2c-y += inv_icm42600_i2c.o
+
+obj-$(CONFIG_INV_ICM42600_SPI) += inv-icm42600-spi.o
+inv-icm42600-spi-y += inv_icm42600_spi.o
-- 
2.17.1



[PATCH v4 03/13] iio: imu: inv_icm42600: add SPI driver for inv_icm42600 driver

2020-06-22 Thread Jean-Baptiste Maneyrol
Add SPI driver for InvenSense ICM-426xxx devices.

Configure bus signal slew rates as indicated in the datasheet.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../iio/imu/inv_icm42600/inv_icm42600_spi.c   | 99 +++
 1 file changed, 99 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
new file mode 100644
index ..a9c5e2fdbe2a
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 InvenSense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+
+static int inv_icm42600_spi_bus_setup(struct inv_icm42600_state *st)
+{
+   unsigned int mask, val;
+   int ret;
+
+   /* setup interface registers */
+   val = INV_ICM42600_INTF_CONFIG6_I3C_EN |
+ INV_ICM42600_INTF_CONFIG6_I3C_SDR_EN |
+ INV_ICM42600_INTF_CONFIG6_I3C_DDR_EN;
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6,
+INV_ICM42600_INTF_CONFIG6_MASK, val);
+   if (ret)
+   return ret;
+
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4,
+INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0);
+   if (ret)
+   return ret;
+
+   /* set slew rates for I2C and SPI */
+   mask = INV_ICM42600_DRIVE_CONFIG_I2C_MASK |
+  INV_ICM42600_DRIVE_CONFIG_SPI_MASK;
+   val = INV_ICM42600_DRIVE_CONFIG_I2C(INV_ICM42600_SLEW_RATE_20_60NS) |
+ INV_ICM42600_DRIVE_CONFIG_SPI(INV_ICM42600_SLEW_RATE_INF_2NS);
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_DRIVE_CONFIG,
+mask, val);
+   if (ret)
+   return ret;
+
+   /* disable i2c bus */
+   return regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,
+ INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK,
+ 
INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS);
+}
+
+static int inv_icm42600_probe(struct spi_device *spi)
+{
+   const void *match;
+   enum inv_icm42600_chip chip;
+   struct regmap *regmap;
+
+   match = device_get_match_data(>dev);
+   if (!match)
+   return -EINVAL;
+   chip = (enum inv_icm42600_chip)match;
+
+   regmap = devm_regmap_init_spi(spi, _icm42600_regmap_config);
+   if (IS_ERR(regmap))
+   return PTR_ERR(regmap);
+
+   return inv_icm42600_core_probe(regmap, chip, 
inv_icm42600_spi_bus_setup);
+}
+
+static const struct of_device_id inv_icm42600_of_matches[] = {
+   {
+   .compatible = "invensense,icm42600",
+   .data = (void *)INV_CHIP_ICM42600,
+   }, {
+   .compatible = "invensense,icm42602",
+   .data = (void *)INV_CHIP_ICM42602,
+   }, {
+   .compatible = "invensense,icm42605",
+   .data = (void *)INV_CHIP_ICM42605,
+   }, {
+   .compatible = "invensense,icm42622",
+   .data = (void *)INV_CHIP_ICM42622,
+   },
+   {}
+};
+MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches);
+
+static struct spi_driver inv_icm42600_driver = {
+   .driver = {
+   .name = "inv-icm42600-spi",
+   .of_match_table = inv_icm42600_of_matches,
+   .pm = _icm42600_pm_ops,
+   },
+   .probe = inv_icm42600_probe,
+};
+module_spi_driver(inv_icm42600_driver);
+
+MODULE_AUTHOR("InvenSense, Inc.");
+MODULE_DESCRIPTION("InvenSense ICM-426xx SPI driver");
+MODULE_LICENSE("GPL");
-- 
2.17.1



[PATCH v4 02/13] iio: imu: inv_icm42600: add I2C driver for inv_icm42600 driver

2020-06-22 Thread Jean-Baptiste Maneyrol
Add I2C driver for InvenSense ICM-426xxx devices.

Configure bus signal slew rates as indicated in the datasheet.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../iio/imu/inv_icm42600/inv_icm42600_i2c.c   | 100 ++
 1 file changed, 100 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
new file mode 100644
index ..4789cead23b3
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 InvenSense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+
+static int inv_icm42600_i2c_bus_setup(struct inv_icm42600_state *st)
+{
+   unsigned int mask, val;
+   int ret;
+
+   /* setup interface registers */
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6,
+INV_ICM42600_INTF_CONFIG6_MASK,
+INV_ICM42600_INTF_CONFIG6_I3C_EN);
+   if (ret)
+   return ret;
+
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4,
+INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0);
+   if (ret)
+   return ret;
+
+   /* set slew rates for I2C and SPI */
+   mask = INV_ICM42600_DRIVE_CONFIG_I2C_MASK |
+  INV_ICM42600_DRIVE_CONFIG_SPI_MASK;
+   val = INV_ICM42600_DRIVE_CONFIG_I2C(INV_ICM42600_SLEW_RATE_12_36NS) |
+ INV_ICM42600_DRIVE_CONFIG_SPI(INV_ICM42600_SLEW_RATE_12_36NS);
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_DRIVE_CONFIG,
+mask, val);
+   if (ret)
+   return ret;
+
+   /* disable SPI bus */
+   return regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,
+ INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK,
+ 
INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS);
+}
+
+static int inv_icm42600_probe(struct i2c_client *client)
+{
+   const void *match;
+   enum inv_icm42600_chip chip;
+   struct regmap *regmap;
+
+   if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
+   return -ENOTSUPP;
+
+   match = device_get_match_data(>dev);
+   if (!match)
+   return -EINVAL;
+   chip = (enum inv_icm42600_chip)match;
+
+   regmap = devm_regmap_init_i2c(client, _icm42600_regmap_config);
+   if (IS_ERR(regmap))
+   return PTR_ERR(regmap);
+
+   return inv_icm42600_core_probe(regmap, chip, 
inv_icm42600_i2c_bus_setup);
+}
+
+static const struct of_device_id inv_icm42600_of_matches[] = {
+   {
+   .compatible = "invensense,icm42600",
+   .data = (void *)INV_CHIP_ICM42600,
+   }, {
+   .compatible = "invensense,icm42602",
+   .data = (void *)INV_CHIP_ICM42602,
+   }, {
+   .compatible = "invensense,icm42605",
+   .data = (void *)INV_CHIP_ICM42605,
+   }, {
+   .compatible = "invensense,icm42622",
+   .data = (void *)INV_CHIP_ICM42622,
+   },
+   {}
+};
+MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches);
+
+static struct i2c_driver inv_icm42600_driver = {
+   .driver = {
+   .name = "inv-icm42600-i2c",
+   .of_match_table = inv_icm42600_of_matches,
+   .pm = _icm42600_pm_ops,
+   },
+   .probe_new = inv_icm42600_probe,
+};
+module_i2c_driver(inv_icm42600_driver);
+
+MODULE_AUTHOR("InvenSense, Inc.");
+MODULE_DESCRIPTION("InvenSense ICM-426xx I2C driver");
+MODULE_LICENSE("GPL");
-- 
2.17.1



[PATCH v4 00/13] iio: imu: new inv_icm42600 driver

2020-06-22 Thread Jean-Baptiste Maneyrol
Changelog
v1
  -initial patch submission
v2
  - formatting reworks, missing headers, code cleanup ...
  - delete all debug traces
  - add commentaries for better explanation of suspend/resume, timestamp, ...
  - delete i2c/spi table ids keeping only of, and use I2C probe_new function
  - switch calibbias to SI units and add calibias_available attribute
  - use DMA-safe buffer for all regmap_bulk_* calls
  - delete iio trigger usage and setup/handle interrupt in core module
  - add open-drain interrupt support
  - add FIFO on reference counter and buffer postenable/predisable to replace
iio trigger usage
  - check that temperature data is present before copying in buffer
  - add temperature sensor off when fifo is turned off
  - delete timestamp channel reading
  - move timestamp state in IIO device private data
  - allow only 1 ODR change in a batch of data
  - add driver-open-drain in devicetree YAML and delete spi options
v3
  - delete const pointer cast for iio_device_get_drvdata
  - change gyro and accel init to return the allocated iio_dev structure
  - delete manual parent device assignment
  - correct style and improve readability
  - add commentaries about IIO buffer and watermark complex computation
  - add timestamp alignment in IIO buffer structure
  - wrap lines 80 columns for dt bindings
  - add ABI documentation for calibbias values in SI units
v4
  - return high resolution 16 bits temperature as raw data when polled with the
corresponding scale and offset.
  - for data buffer return temperature in the same 16 bits using the same
scale and offset. Convert low resolution temperature FIFO data to high
resolution format.
  - explicitely zero out data buffer before copying to iio buffer.

This series add a new driver for managing InvenSense ICM-426xx 6-axis IMUs.
This next generation of chips includes new generations of 3-axis gyroscope
and 3-axis accelerometer, support of I3C in addition to I2C and SPI, and
intelligent MotionTracking features like pedometer, tilt detection, and
tap detection.

This series is delivering a driver supporting gyroscope, accelerometer and
temperature data, with polling and buffering using hwfifo and watermark,
on I2C and SPI busses.

Gyroscope and accelerometer sensors are completely independent and can have
different ODRs. Since there is only a single FIFO a specific value is used to
mark invalid data. For keeping the device standard we are de-multiplexing data
from the FIFO to 2 IIO devices with 2 buffers, 1 for the accelerometer and 1
for the gyroscope. This architecture also enables to easily turn each sensor
on/off without impacting the other. The device interrupt is used to read the
FIFO and launch parsing of accelerometer and gyroscope data. A complex
timestamping mechanism is added to handle correctly FIFO watermark and dynamic
changes of settings.



Jean-Baptiste Maneyrol (13):
  iio: imu: inv_icm42600: add core of new inv_icm42600 driver
  iio: imu: inv_icm42600: add I2C driver for inv_icm42600 driver
  iio: imu: inv_icm42600: add SPI driver for inv_icm42600 driver
  iio: imu: inv_icm42600: add gyroscope IIO device
  iio: imu: inv_icm42600: add accelerometer IIO device
  iio: imu: inv_icm42600: add temperature sensor support
  iio: imu: add Kconfig and Makefile for inv_icm42600 driver
  Documentation: ABI: add specific icm42600 documentation
  iio: imu: inv_icm42600: add device interrupt
  iio: imu: inv_icm42600: add buffer support in iio devices
  iio: imu: inv_icm42600: add accurate timestamping
  dt-bindings: iio: imu: Add inv_icm42600 documentation
  MAINTAINERS: add entry for inv_icm42600 6-axis imu sensor

 .../ABI/testing/sysfs-bus-iio-icm42600|  20 +
 .../bindings/iio/imu/invensense,icm42600.yaml |  90 ++
 MAINTAINERS   |   8 +
 drivers/iio/imu/Kconfig   |   1 +
 drivers/iio/imu/Makefile  |   1 +
 drivers/iio/imu/inv_icm42600/Kconfig  |  29 +
 drivers/iio/imu/inv_icm42600/Makefile |  15 +
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   | 395 +
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 787 +
 .../imu/inv_icm42600/inv_icm42600_buffer.c| 601 +
 .../imu/inv_icm42600/inv_icm42600_buffer.h|  98 +++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  | 786 +
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 798 ++
 .../iio/imu/inv_icm42600/inv_icm42600_i2c.c   | 101 +++
 .../iio/imu/inv_icm42600/inv_icm42600_spi.c   | 100 +++
 .../iio/imu/inv_icm42600/inv_icm42600_temp.c  |  84 ++
 .../iio/imu/inv_icm42600/inv_icm42600_temp.h  |  30 +
 .../imu/inv_icm42600/inv_icm42600_timestamp.c | 195 +
 .../imu/inv_icm42600/inv_icm42600_timestamp.h |  85 ++
 19 files changed, 4224 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-icm42600
 create mode 100644 
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
 create mode 100644 drivers/iio

Re: [PATCH v3 06/13] iio: imu: inv_icm42600: add temperature sensor support

2020-06-22 Thread Jean-Baptiste Maneyrol
Hi Jonathan,

no problem, I can rework temperature to have the same raw output for both cases 
(with just decreased resolution for the FIFO case).

v4 series is coming soon with the fix.

Thanks,
JB

From: Jonathan Cameron 
Sent: Saturday, June 20, 2020 17:57
To: Jean-Baptiste Maneyrol 
Cc: Lars-Peter Clausen ; robh...@kernel.org 
; r...@kernel.org ; 
mchehab+hua...@kernel.org ; da...@davemloft.net 
; gre...@linuxfoundation.org ; 
linux-...@vger.kernel.org ; 
devicet...@vger.kernel.org ; 
linux-kernel@vger.kernel.org 
Subject: Re: [PATCH v3 06/13] iio: imu: inv_icm42600: add temperature sensor 
support 
 
 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.

On Sun, 14 Jun 2020 20:35:13 +
Jean-Baptiste Maneyrol  wrote:

> Hello Lars,
> 
> for the temperature data, the problem is that temperature in the FIFO (used 
> in buffer) is not in the same format than when reading the register.
> 
> Reading the temperature register return a full precision value on 16 bits. I 
> am using a PROCESSED attribute for it.
> Temperature data in buffer (coming from the FIFO) is on 8 bits in lower 
> precision. It is reported as raw data, thus the need of the offset and scale 
> values.
> 
> So offset and scale values are only for transforming the temperature data 
> from the buffer, and direct read is a full precision already processed in m°C.

That is a problem.  We have no means of describing it in IIO.

If the channel is processed via sysfs the assumption would normally
be that it is processed in the buffer as well. We don't really
have any means of describing the two separately.

In cases where we've seen this before the way around it was to
change the data in the fifo so that the scaling was the same as the
sysfs channel (usually it's just a bit of padding).

Can we do that here?  Looks like the ratio is 1:64 so should
be possible. 



> 
> Thanks for the review,
> JB
> 
> From: Lars-Peter Clausen 
> Sent: Sunday, June 14, 2020 17:10
> To: Jean-Baptiste Maneyrol ; ji...@kernel.org 
> ; robh...@kernel.org ; r...@kernel.org 
> ; mchehab+hua...@kernel.org ; 
> da...@davemloft.net ; gre...@linuxfoundation.org 
> 
> Cc: linux-...@vger.kernel.org ; 
> devicet...@vger.kernel.org ; 
> linux-kernel@vger.kernel.org 
> Subject: Re: [PATCH v3 06/13] iio: imu: inv_icm42600: add temperature sensor 
> support 
>  
>  CAUTION: This email originated from outside of the organization. Please make 
> sure the sender is who they say they are and do not click links or open 
> attachments unless you recognize the sender and know the content is safe.
> 
> On 6/8/20 10:42 PM, Jean-Baptiste Maneyrol wrote:
> > + case IIO_CHAN_INFO_PROCESSED:
> > + ret = iio_device_claim_direct_mode(indio_dev);
> > + if (ret)
> > + return ret;
> > + ret = inv_icm42600_temp_read(st, );
> > + iio_device_release_direct_mode(indio_dev);
> > + if (ret)
> > + return ret;
> > + *val = temp;
> > + return IIO_VAL_INT;
> > + case IIO_CHAN_INFO_SCALE:
> > + *val = 483;
> > + *val2 = 91787;
> > + return IIO_VAL_INT_PLUS_MICRO;
> > + case IIO_CHAN_INFO_OFFSET:
> > + *val = 25000;
> > + return IIO_VAL_INT;  
> 
> If the data is returned processed there is no need to specify scale and 
> offset.
> 
> But since the transformation to turn the data into standard units is a 
> simple linear transform the preferred way to handle this is to return 
> RAW data and specify scale and offset.


Re: [PATCH v3 06/13] iio: imu: inv_icm42600: add temperature sensor support

2020-06-14 Thread Jean-Baptiste Maneyrol
Hello Lars,

for the temperature data, the problem is that temperature in the FIFO (used in 
buffer) is not in the same format than when reading the register.

Reading the temperature register return a full precision value on 16 bits. I am 
using a PROCESSED attribute for it.
Temperature data in buffer (coming from the FIFO) is on 8 bits in lower 
precision. It is reported as raw data, thus the need of the offset and scale 
values.

So offset and scale values are only for transforming the temperature data from 
the buffer, and direct read is a full precision already processed in m°C.

Thanks for the review,
JB

From: Lars-Peter Clausen 
Sent: Sunday, June 14, 2020 17:10
To: Jean-Baptiste Maneyrol ; ji...@kernel.org 
; robh...@kernel.org ; r...@kernel.org 
; mchehab+hua...@kernel.org ; 
da...@davemloft.net ; gre...@linuxfoundation.org 

Cc: linux-...@vger.kernel.org ; 
devicet...@vger.kernel.org ; 
linux-kernel@vger.kernel.org 
Subject: Re: [PATCH v3 06/13] iio: imu: inv_icm42600: add temperature sensor 
support 
 
 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.

On 6/8/20 10:42 PM, Jean-Baptiste Maneyrol wrote:
> + case IIO_CHAN_INFO_PROCESSED:
> + ret = iio_device_claim_direct_mode(indio_dev);
> + if (ret)
> + return ret;
> + ret = inv_icm42600_temp_read(st, );
> + iio_device_release_direct_mode(indio_dev);
> + if (ret)
> + return ret;
> + *val = temp;
> + return IIO_VAL_INT;
> + case IIO_CHAN_INFO_SCALE:
> + *val = 483;
> + *val2 = 91787;
> + return IIO_VAL_INT_PLUS_MICRO;
> + case IIO_CHAN_INFO_OFFSET:
> + *val = 25000;
> + return IIO_VAL_INT;

If the data is returned processed there is no need to specify scale and 
offset.

But since the transformation to turn the data into standard units is a 
simple linear transform the preferred way to handle this is to return 
RAW data and specify scale and offset.


[PATCH v3 10/13] iio: imu: inv_icm42600: add buffer support in iio devices

2020-06-08 Thread Jean-Baptiste Maneyrol
Add all FIFO parsing and reading functions. Add accel and gyro
kfifo buffer and FIFO data parsing. Use device interrupt for
reading data FIFO and launching accel and gyro parsing.

Support hwfifo watermark by multiplexing gyro and accel settings.
Support hwfifo flush.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/Kconfig  |   1 +
 drivers/iio/imu/inv_icm42600/Makefile |   1 +
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   8 +
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 164 -
 .../imu/inv_icm42600/inv_icm42600_buffer.c| 573 ++
 .../imu/inv_icm42600/inv_icm42600_buffer.h|  98 +++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |  30 +
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 164 -
 8 files changed, 1037 insertions(+), 2 deletions(-)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h

diff --git a/drivers/iio/imu/inv_icm42600/Kconfig 
b/drivers/iio/imu/inv_icm42600/Kconfig
index 22390a72f0a3..50cbcfcb6cf1 100644
--- a/drivers/iio/imu/inv_icm42600/Kconfig
+++ b/drivers/iio/imu/inv_icm42600/Kconfig
@@ -2,6 +2,7 @@
 
 config INV_ICM42600
tristate
+   select IIO_BUFFER
 
 config INV_ICM42600_I2C
tristate "InvenSense ICM-426xx I2C driver"
diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
b/drivers/iio/imu/inv_icm42600/Makefile
index 48965824f00c..0f49f6df3647 100644
--- a/drivers/iio/imu/inv_icm42600/Makefile
+++ b/drivers/iio/imu/inv_icm42600/Makefile
@@ -5,6 +5,7 @@ inv-icm42600-y += inv_icm42600_core.o
 inv-icm42600-y += inv_icm42600_gyro.o
 inv-icm42600-y += inv_icm42600_accel.o
 inv-icm42600-y += inv_icm42600_temp.o
+inv-icm42600-y += inv_icm42600_buffer.o
 
 obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o
 inv-icm42600-i2c-y += inv_icm42600_i2c.o
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index 148894c888cc..7b52d92739c3 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -14,6 +14,8 @@
 #include 
 #include 
 
+#include "inv_icm42600_buffer.h"
+
 enum inv_icm42600_chip {
INV_CHIP_ICM42600,
INV_CHIP_ICM42602,
@@ -123,6 +125,7 @@ struct inv_icm42600_suspended {
  *  @indio_gyro:   gyroscope IIO device.
  *  @indio_accel:  accelerometer IIO device.
  *  @buffer:   data transfer buffer aligned for DMA.
+ *  @fifo: FIFO management structure.
  */
 struct inv_icm42600_state {
struct mutex lock;
@@ -137,6 +140,7 @@ struct inv_icm42600_state {
struct iio_dev *indio_gyro;
struct iio_dev *indio_accel;
uint8_t buffer[2] cacheline_aligned;
+   struct inv_icm42600_fifo fifo;
 };
 
 /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
@@ -377,6 +381,10 @@ int inv_icm42600_core_probe(struct regmap *regmap, int 
chip, int irq,
 
 struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st);
 
+int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev);
+
 struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st);
 
+int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev);
+
 #endif
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index 3f214df44093..77cdad99de91 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -11,9 +11,12 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "inv_icm42600.h"
 #include "inv_icm42600_temp.h"
+#include "inv_icm42600_buffer.h"
 
 #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)  \
{   \
@@ -64,6 +67,79 @@ static const struct iio_chan_spec 
inv_icm42600_accel_channels[] = {
INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP),
 };
 
+/*
+ * IIO buffer data: size must be a power of 2
+ * 8 bytes: 7 bytes data (accel 6 + temp 1) + 1 byte padding
+ */
+struct inv_icm42600_accel_buffer {
+   struct inv_icm42600_fifo_sensor_data accel;
+   int8_t temp;
+   uint8_t padding;
+};
+
+#define INV_ICM42600_SCAN_MASK_ACCEL_3AXIS \
+   (BIT(INV_ICM42600_ACCEL_SCAN_X) |   \
+   BIT(INV_ICM42600_ACCEL_SCAN_Y) |\
+   BIT(INV_ICM42600_ACCEL_SCAN_Z))
+
+#define INV_ICM42600_SCAN_MASK_TEMPBIT(INV_ICM42600_ACCEL_SCAN_TEMP)
+
+static const unsigned long inv_icm42600_accel_scan_masks[] = {
+   /* 3-axis accel + temperature */
+   INV_ICM42600_SCAN_MASK_ACCEL_3AXIS | INV_ICM42600_SCAN_MASK_TEMP,
+   0,
+};
+
+/* enable accelerometer sensor and FIFO write */
+static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev,
+ 

[PATCH v3 02/13] iio: imu: inv_icm42600: add I2C driver for inv_icm42600 driver

2020-06-08 Thread Jean-Baptiste Maneyrol
Add I2C driver for InvenSense ICM-426xxx devices.

Configure bus signal slew rates as indicated in the datasheet.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../iio/imu/inv_icm42600/inv_icm42600_i2c.c   | 100 ++
 1 file changed, 100 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
new file mode 100644
index ..4789cead23b3
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 InvenSense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+
+static int inv_icm42600_i2c_bus_setup(struct inv_icm42600_state *st)
+{
+   unsigned int mask, val;
+   int ret;
+
+   /* setup interface registers */
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6,
+INV_ICM42600_INTF_CONFIG6_MASK,
+INV_ICM42600_INTF_CONFIG6_I3C_EN);
+   if (ret)
+   return ret;
+
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4,
+INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0);
+   if (ret)
+   return ret;
+
+   /* set slew rates for I2C and SPI */
+   mask = INV_ICM42600_DRIVE_CONFIG_I2C_MASK |
+  INV_ICM42600_DRIVE_CONFIG_SPI_MASK;
+   val = INV_ICM42600_DRIVE_CONFIG_I2C(INV_ICM42600_SLEW_RATE_12_36NS) |
+ INV_ICM42600_DRIVE_CONFIG_SPI(INV_ICM42600_SLEW_RATE_12_36NS);
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_DRIVE_CONFIG,
+mask, val);
+   if (ret)
+   return ret;
+
+   /* disable SPI bus */
+   return regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,
+ INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK,
+ 
INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS);
+}
+
+static int inv_icm42600_probe(struct i2c_client *client)
+{
+   const void *match;
+   enum inv_icm42600_chip chip;
+   struct regmap *regmap;
+
+   if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
+   return -ENOTSUPP;
+
+   match = device_get_match_data(>dev);
+   if (!match)
+   return -EINVAL;
+   chip = (enum inv_icm42600_chip)match;
+
+   regmap = devm_regmap_init_i2c(client, _icm42600_regmap_config);
+   if (IS_ERR(regmap))
+   return PTR_ERR(regmap);
+
+   return inv_icm42600_core_probe(regmap, chip, 
inv_icm42600_i2c_bus_setup);
+}
+
+static const struct of_device_id inv_icm42600_of_matches[] = {
+   {
+   .compatible = "invensense,icm42600",
+   .data = (void *)INV_CHIP_ICM42600,
+   }, {
+   .compatible = "invensense,icm42602",
+   .data = (void *)INV_CHIP_ICM42602,
+   }, {
+   .compatible = "invensense,icm42605",
+   .data = (void *)INV_CHIP_ICM42605,
+   }, {
+   .compatible = "invensense,icm42622",
+   .data = (void *)INV_CHIP_ICM42622,
+   },
+   {}
+};
+MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches);
+
+static struct i2c_driver inv_icm42600_driver = {
+   .driver = {
+   .name = "inv-icm42600-i2c",
+   .of_match_table = inv_icm42600_of_matches,
+   .pm = _icm42600_pm_ops,
+   },
+   .probe_new = inv_icm42600_probe,
+};
+module_i2c_driver(inv_icm42600_driver);
+
+MODULE_AUTHOR("InvenSense, Inc.");
+MODULE_DESCRIPTION("InvenSense ICM-426xx I2C driver");
+MODULE_LICENSE("GPL");
-- 
2.17.1



[PATCH v3 12/13] dt-bindings: iio: imu: Add inv_icm42600 documentation

2020-06-08 Thread Jean-Baptiste Maneyrol
Document the ICM-426xxx devices devicetree bindings.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../bindings/iio/imu/invensense,icm42600.yaml | 90 +++
 1 file changed, 90 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml

diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml 
b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
new file mode 100644
index ..abd8d25e1136
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
@@ -0,0 +1,90 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/imu/invensense,icm42600.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: InvenSense ICM-426xx Inertial Measurement Unit
+
+maintainers:
+  - Jean-Baptiste Maneyrol 
+
+description: |
+  6-axis MotionTracking device that combines a 3-axis gyroscope and a 3-axis
+  accelerometer.
+
+  It has a configurable host interface that supports I3C, I2C and SPI serial
+  communication, features a 2kB FIFO and 2 programmable interrupts with
+  ultra-low-power wake-on-motion support to minimize system power consumption.
+
+  Other industry-leading features include InvenSense on-chip APEX Motion
+  Processing engine for gesture recognition, activity classification, and
+  pedometer, along with programmable digital filters, and an embedded
+  temperature sensor.
+
+  
https://invensense.tdk.com/wp-content/uploads/2020/03/DS-000292-ICM-42605-v1.4.pdf
+
+properties:
+  compatible:
+enum:
+  - invensense,icm42600
+  - invensense,icm42602
+  - invensense,icm42605
+  - invensense,icm42622
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  drive-open-drain:
+type: boolean
+
+  vdd-supply:
+description: Regulator that provides power to the sensor
+
+  vddio-supply:
+description: Regulator that provides power to the bus
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+examples:
+  - |
+#include 
+#include 
+i2c0 {
+#address-cells = <1>;
+#size-cells = <0>;
+
+icm42605@68 {
+  compatible = "invensense,icm42605";
+  reg = <0x68>;
+  interrupt-parent = <>;
+  interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+  vdd-supply = <>;
+  vddio-supply = <>;
+};
+};
+  - |
+#include 
+#include 
+spi0 {
+#address-cells = <1>;
+#size-cells = <0>;
+
+icm42602@0 {
+  compatible = "invensense,icm42602";
+  reg = <0>;
+  spi-max-frequency = <2400>;
+  spi-cpha;
+  spi-cpol;
+  interrupt-parent = <>;
+  interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+  vdd-supply = <>;
+  vddio-supply = <>;
+};
+};
-- 
2.17.1



[PATCH v3 04/13] iio: imu: inv_icm42600: add gyroscope IIO device

2020-06-08 Thread Jean-Baptiste Maneyrol
Add IIO device for gyroscope sensor with data polling interface.
Attributes: raw, scale, sampling_frequency, calibbias.

Gyroscope in low noise mode.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   6 +
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |   4 +
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 603 ++
 3 files changed, 613 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index 14c8ef152418..d155470d770a 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -120,6 +120,8 @@ struct inv_icm42600_suspended {
  *  @orientation:  sensor chip orientation relative to main hardware.
  *  @conf: chip sensors configurations.
  *  @suspended:suspended sensors configuration.
+ *  @indio_gyro:   gyroscope IIO device.
+ *  @buffer:   data transfer buffer aligned for DMA.
  */
 struct inv_icm42600_state {
struct mutex lock;
@@ -131,6 +133,8 @@ struct inv_icm42600_state {
struct iio_mount_matrix orientation;
struct inv_icm42600_conf conf;
struct inv_icm42600_suspended suspended;
+   struct iio_dev *indio_gyro;
+   uint8_t buffer[2] cacheline_aligned;
 };
 
 /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
@@ -369,4 +373,6 @@ int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, 
unsigned int reg,
 int inv_icm42600_core_probe(struct regmap *regmap, int chip,
inv_icm42600_bus_setup bus_setup);
 
+struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st);
+
 #endif
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
index 2eb25c5f77f8..84e9ff320b3b 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
@@ -509,6 +509,10 @@ int inv_icm42600_core_probe(struct regmap *regmap, int 
chip,
if (ret)
return ret;
 
+   st->indio_gyro = inv_icm42600_gyro_init(st);
+   if (IS_ERR(st->indio_gyro))
+   return PTR_ERR(st->indio_gyro);
+
/* setup runtime power management */
ret = pm_runtime_set_active(dev);
if (ret)
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
new file mode 100644
index ..3875ecbee67e
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
@@ -0,0 +1,603 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+
+#define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info)   \
+   {   \
+   .type = IIO_ANGL_VEL,   \
+   .modified = 1,  \
+   .channel2 = _modifier,  \
+   .info_mask_separate =   \
+   BIT(IIO_CHAN_INFO_RAW) |\
+   BIT(IIO_CHAN_INFO_CALIBBIAS),   \
+   .info_mask_shared_by_type = \
+   BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_type_available =   \
+   BIT(IIO_CHAN_INFO_SCALE) |  \
+   BIT(IIO_CHAN_INFO_CALIBBIAS),   \
+   .info_mask_shared_by_all =  \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   .info_mask_shared_by_all_available =\
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   .scan_index = _index,   \
+   .scan_type = {  \
+   .sign = 's',\
+   .realbits = 16, \
+   .storagebits = 16,  \
+   .endianness = IIO_BE,   \
+   },  \
+   .ext_info = _ext_info,  \
+   }
+
+enum inv_icm42600_gyro_scan {
+   INV_ICM42600_GYRO_SCAN_X,
+   INV_ICM42600_GYRO_SCAN_Y,
+   INV_ICM42600_GYRO_SCAN_Z,
+};
+
+static const struct iio_chan_spec_ext_info inv_icm4

[PATCH v3 03/13] iio: imu: inv_icm42600: add SPI driver for inv_icm42600 driver

2020-06-08 Thread Jean-Baptiste Maneyrol
Add SPI driver for InvenSense ICM-426xxx devices.

Configure bus signal slew rates as indicated in the datasheet.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../iio/imu/inv_icm42600/inv_icm42600_spi.c   | 99 +++
 1 file changed, 99 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
new file mode 100644
index ..a9c5e2fdbe2a
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 InvenSense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+
+static int inv_icm42600_spi_bus_setup(struct inv_icm42600_state *st)
+{
+   unsigned int mask, val;
+   int ret;
+
+   /* setup interface registers */
+   val = INV_ICM42600_INTF_CONFIG6_I3C_EN |
+ INV_ICM42600_INTF_CONFIG6_I3C_SDR_EN |
+ INV_ICM42600_INTF_CONFIG6_I3C_DDR_EN;
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6,
+INV_ICM42600_INTF_CONFIG6_MASK, val);
+   if (ret)
+   return ret;
+
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4,
+INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0);
+   if (ret)
+   return ret;
+
+   /* set slew rates for I2C and SPI */
+   mask = INV_ICM42600_DRIVE_CONFIG_I2C_MASK |
+  INV_ICM42600_DRIVE_CONFIG_SPI_MASK;
+   val = INV_ICM42600_DRIVE_CONFIG_I2C(INV_ICM42600_SLEW_RATE_20_60NS) |
+ INV_ICM42600_DRIVE_CONFIG_SPI(INV_ICM42600_SLEW_RATE_INF_2NS);
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_DRIVE_CONFIG,
+mask, val);
+   if (ret)
+   return ret;
+
+   /* disable i2c bus */
+   return regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,
+ INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK,
+ 
INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS);
+}
+
+static int inv_icm42600_probe(struct spi_device *spi)
+{
+   const void *match;
+   enum inv_icm42600_chip chip;
+   struct regmap *regmap;
+
+   match = device_get_match_data(>dev);
+   if (!match)
+   return -EINVAL;
+   chip = (enum inv_icm42600_chip)match;
+
+   regmap = devm_regmap_init_spi(spi, _icm42600_regmap_config);
+   if (IS_ERR(regmap))
+   return PTR_ERR(regmap);
+
+   return inv_icm42600_core_probe(regmap, chip, 
inv_icm42600_spi_bus_setup);
+}
+
+static const struct of_device_id inv_icm42600_of_matches[] = {
+   {
+   .compatible = "invensense,icm42600",
+   .data = (void *)INV_CHIP_ICM42600,
+   }, {
+   .compatible = "invensense,icm42602",
+   .data = (void *)INV_CHIP_ICM42602,
+   }, {
+   .compatible = "invensense,icm42605",
+   .data = (void *)INV_CHIP_ICM42605,
+   }, {
+   .compatible = "invensense,icm42622",
+   .data = (void *)INV_CHIP_ICM42622,
+   },
+   {}
+};
+MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches);
+
+static struct spi_driver inv_icm42600_driver = {
+   .driver = {
+   .name = "inv-icm42600-spi",
+   .of_match_table = inv_icm42600_of_matches,
+   .pm = _icm42600_pm_ops,
+   },
+   .probe = inv_icm42600_probe,
+};
+module_spi_driver(inv_icm42600_driver);
+
+MODULE_AUTHOR("InvenSense, Inc.");
+MODULE_DESCRIPTION("InvenSense ICM-426xx SPI driver");
+MODULE_LICENSE("GPL");
-- 
2.17.1



[PATCH v3 00/13] iio: imu: new inv_icm42600 driver

2020-06-08 Thread Jean-Baptiste Maneyrol
Changelog
v1
  -initial patch submission
v2
  - formatting reworks, missing headers, code cleanup ...
  - delete all debug traces
  - add commentaries for better explanation of suspend/resume, timestamp, ...
  - delete i2c/spi table ids keeping only of, and use I2C probe_new function
  - switch calibbias to SI units and add calibias_available attribute
  - use DMA-safe buffer for all regmap_bulk_* calls
  - delete iio trigger usage and setup/handle interrupt in core module
  - add open-drain interrupt support
  - add FIFO on reference counter and buffer postenable/predisable to replace
iio trigger usage
  - check that temperature data is present before copying in buffer
  - add temperature sensor off when fifo is turned off
  - delete timestamp channel reading
  - move timestamp state in IIO device private data
  - allow only 1 ODR change in a batch of data
  - add driver-open-drain in devicetree YAML and delete spi options
v3
  - delete const pointer cast for iio_device_get_drvdata
  - change gyro and accel init to return the allocated iio_dev structure
  - delete manual parent device assignment
  - correct style and improve readability
  - add commentaries about IIO buffer and watermark complex computation
  - add timestamp alignment in IIO buffer structure
  - wrap lines 80 columns for dt bindings
  - add ABI documentation for calibbias values in SI units

This series add a new driver for managing InvenSense ICM-426xx 6-axis IMUs.
This next generation of chips includes new generations of 3-axis gyroscope
and 3-axis accelerometer, support of I3C in addition to I2C and SPI, and
intelligent MotionTracking features like pedometer, tilt detection, and
tap detection.

This series is delivering a driver supporting gyroscope, accelerometer and
temperature data, with polling and buffering using hwfifo and watermark,
on I2C and SPI busses.

Gyroscope and accelerometer sensors are completely independent and can have
different ODRs. Since there is only a single FIFO a specific value is used to
mark invalid data. For keeping the device standard we are de-multiplexing data
from the FIFO to 2 IIO devices with 2 buffers, 1 for the accelerometer and 1
for the gyroscope. This architecture also enables to easily turn each sensor
on/off without impacting the other. The device interrupt is used to read the
FIFO and launch parsing of accelerometer and gyroscope data. A complex
timestamping mechanism is added to handle correctly FIFO watermark and dynamic
changes of settings.

Jean-Baptiste Maneyrol (13):
  iio: imu: inv_icm42600: add core of new inv_icm42600 driver
  iio: imu: inv_icm42600: add I2C driver for inv_icm42600 driver
  iio: imu: inv_icm42600: add SPI driver for inv_icm42600 driver
  iio: imu: inv_icm42600: add gyroscope IIO device
  iio: imu: inv_icm42600: add accelerometer IIO device
  iio: imu: inv_icm42600: add temperature sensor support
  iio: imu: add Kconfig and Makefile for inv_icm42600 driver
  Documentation: ABI: add specific icm42600 documentation
  iio: imu: inv_icm42600: add device interrupt
  iio: imu: inv_icm42600: add buffer support in iio devices
  iio: imu: inv_icm42600: add accurate timestamping
  dt-bindings: iio: imu: Add inv_icm42600 documentation
  MAINTAINERS: add entry for inv_icm42600 6-axis imu sensor

 .../ABI/testing/sysfs-bus-iio-icm42600|  20 +
 .../bindings/iio/imu/invensense,icm42600.yaml |  90 ++
 MAINTAINERS   |   8 +
 drivers/iio/imu/Kconfig   |   1 +
 drivers/iio/imu/Makefile  |   1 +
 drivers/iio/imu/inv_icm42600/Kconfig  |  29 +
 drivers/iio/imu/inv_icm42600/Makefile |  15 +
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   | 395 +
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 789 +
 .../imu/inv_icm42600/inv_icm42600_buffer.c| 601 +
 .../imu/inv_icm42600/inv_icm42600_buffer.h|  98 +++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  | 786 +
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 800 ++
 .../iio/imu/inv_icm42600/inv_icm42600_i2c.c   | 101 +++
 .../iio/imu/inv_icm42600/inv_icm42600_spi.c   | 100 +++
 .../iio/imu/inv_icm42600/inv_icm42600_temp.c  |  87 ++
 .../iio/imu/inv_icm42600/inv_icm42600_temp.h  |  30 +
 .../imu/inv_icm42600/inv_icm42600_timestamp.c | 195 +
 .../imu/inv_icm42600/inv_icm42600_timestamp.h |  85 ++
 19 files changed, 4231 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-icm42600
 create mode 100644 
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
 create mode 100644 drivers/iio/imu/inv_icm42600/Kconfig
 create mode 100644 drivers/iio/imu/inv_icm42600/Makefile
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600.h
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h

[PATCH v3 09/13] iio: imu: inv_icm42600: add device interrupt

2020-06-08 Thread Jean-Baptiste Maneyrol
Add INT1 interrupt support. Support interrupt edge and level,
active high or low. Push-pull or open-drain configurations.

Interrupt will be used to read data from the FIFO.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   2 +-
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  | 101 +-
 .../iio/imu/inv_icm42600/inv_icm42600_i2c.c   |   3 +-
 .../iio/imu/inv_icm42600/inv_icm42600_spi.c   |   3 +-
 4 files changed, 105 insertions(+), 4 deletions(-)

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index 3b190461a2b6..148894c888cc 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -372,7 +372,7 @@ int inv_icm42600_set_temp_conf(struct inv_icm42600_state 
*st, bool enable,
 int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg,
 unsigned int writeval, unsigned int *readval);
 
-int inv_icm42600_core_probe(struct regmap *regmap, int chip,
+int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
inv_icm42600_bus_setup bus_setup);
 
 struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st);
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
index a35ff21f50bb..95b2a6d91e5b 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
@@ -9,8 +9,11 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -408,6 +411,82 @@ static int inv_icm42600_setup(struct inv_icm42600_state 
*st,
return inv_icm42600_set_conf(st, hw->conf);
 }
 
+static irqreturn_t inv_icm42600_irq_handler(int irq, void *_data)
+{
+   struct inv_icm42600_state *st = _data;
+   struct device *dev = regmap_get_device(st->map);
+   unsigned int status;
+   int ret;
+
+   mutex_lock(>lock);
+
+   ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, );
+   if (ret)
+   goto out_unlock;
+
+   /* FIFO full */
+   if (status & INV_ICM42600_INT_STATUS_FIFO_FULL)
+   dev_warn(dev, "FIFO full data lost!\n");
+
+out_unlock:
+   mutex_unlock(>lock);
+   return IRQ_HANDLED;
+}
+
+/**
+ * inv_icm42600_irq_init() - initialize int pin and interrupt handler
+ * @st:driver internal state
+ * @irq:   irq number
+ * @irq_type:  irq trigger type
+ * @open_drain:true if irq is open drain, false for push-pull
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+static int inv_icm42600_irq_init(struct inv_icm42600_state *st, int irq,
+int irq_type, bool open_drain)
+{
+   struct device *dev = regmap_get_device(st->map);
+   unsigned int val;
+   int ret;
+
+   /* configure INT1 interrupt: default is active low on edge */
+   switch (irq_type) {
+   case IRQF_TRIGGER_RISING:
+   case IRQF_TRIGGER_HIGH:
+   val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH;
+   break;
+   default:
+   val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW;
+   break;
+   }
+
+   switch (irq_type) {
+   case IRQF_TRIGGER_LOW:
+   case IRQF_TRIGGER_HIGH:
+   val |= INV_ICM42600_INT_CONFIG_INT1_LATCHED;
+   break;
+   default:
+   break;
+   }
+
+   if (!open_drain)
+   val |= INV_ICM42600_INT_CONFIG_INT1_PUSH_PULL;
+
+   ret = regmap_write(st->map, INV_ICM42600_REG_INT_CONFIG, val);
+   if (ret)
+   return ret;
+
+   /* Deassert async reset for proper INT pin operation (cf datasheet) */
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_CONFIG1,
+INV_ICM42600_INT_CONFIG1_ASYNC_RESET, 0);
+   if (ret)
+   return ret;
+
+   return devm_request_threaded_irq(dev, irq, NULL,
+inv_icm42600_irq_handler, irq_type,
+"inv_icm42600", st);
+}
+
 static int inv_icm42600_enable_regulator_vddio(struct inv_icm42600_state *st)
 {
int ret;
@@ -452,11 +531,14 @@ static void inv_icm42600_disable_pm(void *_data)
pm_runtime_disable(dev);
 }
 
-int inv_icm42600_core_probe(struct regmap *regmap, int chip,
+int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
inv_icm42600_bus_setup bus_setup)
 {
struct device *dev = regmap_get_device(regmap);
struct inv_icm42600_state *st;
+   struct irq_data *irq_desc;
+   int irq_type;
+   bool open_drain;
int ret;
 
if (chip < 0 || chip >= INV_CHIP_NB) {
@@ -464,6 +546,19 @@ int inv_icm42600_core_probe(struct reg

[PATCH v3 08/13] Documentation: ABI: add specific icm42600 documentation

2020-06-08 Thread Jean-Baptiste Maneyrol
Hardware offset available as calibscale sysfs attributes are real
physical values exprimed in SI units.

calibscale_available sysfs attributes represents the range of
acceptable values.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../ABI/testing/sysfs-bus-iio-icm42600| 20 +++
 1 file changed, 20 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-bus-iio-icm42600

diff --git a/Documentation/ABI/testing/sysfs-bus-iio-icm42600 
b/Documentation/ABI/testing/sysfs-bus-iio-icm42600
new file mode 100644
index ..0bf1fd4f5bf1
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-bus-iio-icm42600
@@ -0,0 +1,20 @@
+What:  /sys/bus/iio/devices/iio:deviceX/in_accel_x_calibbias
+What:  /sys/bus/iio/devices/iio:deviceX/in_accel_y_calibbias
+What:  /sys/bus/iio/devices/iio:deviceX/in_accel_z_calibbias
+What:  /sys/bus/iio/devices/iio:deviceX/in_anglvel_x_calibbias
+What:  /sys/bus/iio/devices/iio:deviceX/in_anglvel_y_calibbias
+What:  /sys/bus/iio/devices/iio:deviceX/in_anglvel_z_calibbias
+KernelVersion:  5.8
+Contact:linux-...@vger.kernel.org
+Description:
+   Hardware applied calibration offset (assumed to fix production
+   inaccuracies). Values represent a real physical offset expressed
+   in SI units (m/s^2 for accelerometer and rad/s for gyroscope).
+
+What:  /sys/bus/iio/devices/iio:deviceX/in_accel_calibbias_available
+What:  /sys/bus/iio/devices/iio:deviceX/in_anglvel_calibbias_available
+KernelVersion:  5.8
+Contact:linux-...@vger.kernel.org
+Description:
+   Range of available values for hardware offset. Values in SI
+   units (m/s^2 for accelerometer and rad/s for gyroscope).
-- 
2.17.1



[PATCH v3 05/13] iio: imu: inv_icm42600: add accelerometer IIO device

2020-06-08 Thread Jean-Baptiste Maneyrol
Add IIO device for accelerometer sensor with data polling
interface.
Attributes: raw, scale, sampling_frequency, calibbias.

Accelerometer in low noise mode.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   4 +
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 592 ++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |   4 +
 3 files changed, 600 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index d155470d770a..3b190461a2b6 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -121,6 +121,7 @@ struct inv_icm42600_suspended {
  *  @conf: chip sensors configurations.
  *  @suspended:suspended sensors configuration.
  *  @indio_gyro:   gyroscope IIO device.
+ *  @indio_accel:  accelerometer IIO device.
  *  @buffer:   data transfer buffer aligned for DMA.
  */
 struct inv_icm42600_state {
@@ -134,6 +135,7 @@ struct inv_icm42600_state {
struct inv_icm42600_conf conf;
struct inv_icm42600_suspended suspended;
struct iio_dev *indio_gyro;
+   struct iio_dev *indio_accel;
uint8_t buffer[2] cacheline_aligned;
 };
 
@@ -375,4 +377,6 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip,
 
 struct iio_dev *inv_icm42600_gyro_init(struct inv_icm42600_state *st);
 
+struct iio_dev *inv_icm42600_accel_init(struct inv_icm42600_state *st);
+
 #endif
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
new file mode 100644
index ..717c6b0869fc
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -0,0 +1,592 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+
+#define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)  \
+   {   \
+   .type = IIO_ACCEL,  \
+   .modified = 1,  \
+   .channel2 = _modifier,  \
+   .info_mask_separate =   \
+   BIT(IIO_CHAN_INFO_RAW) |\
+   BIT(IIO_CHAN_INFO_CALIBBIAS),   \
+   .info_mask_shared_by_type = \
+   BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_type_available =   \
+   BIT(IIO_CHAN_INFO_SCALE) |  \
+   BIT(IIO_CHAN_INFO_CALIBBIAS),   \
+   .info_mask_shared_by_all =  \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   .info_mask_shared_by_all_available =\
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   .scan_index = _index,   \
+   .scan_type = {  \
+   .sign = 's',\
+   .realbits = 16, \
+   .storagebits = 16,  \
+   .endianness = IIO_BE,   \
+   },  \
+   .ext_info = _ext_info,  \
+   }
+
+enum inv_icm42600_accel_scan {
+   INV_ICM42600_ACCEL_SCAN_X,
+   INV_ICM42600_ACCEL_SCAN_Y,
+   INV_ICM42600_ACCEL_SCAN_Z,
+};
+
+static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
+   IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42600_get_mount_matrix),
+   {},
+};
+
+static const struct iio_chan_spec inv_icm42600_accel_channels[] = {
+   INV_ICM42600_ACCEL_CHAN(IIO_MOD_X, INV_ICM42600_ACCEL_SCAN_X,
+   inv_icm42600_accel_ext_infos),
+   INV_ICM42600_ACCEL_CHAN(IIO_MOD_Y, INV_ICM42600_ACCEL_SCAN_Y,
+   inv_icm42600_accel_ext_infos),
+   INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z,
+   inv_icm42600_accel_ext_infos),
+};
+
+static int inv_icm42600_accel_read_sensor(struct inv_icm42600_state *st,
+ struct iio_chan_spec const *chan,
+ int16_t *val)
+{
+   struct device *dev = regmap_get_devi

[PATCH v3 06/13] iio: imu: inv_icm42600: add temperature sensor support

2020-06-08 Thread Jean-Baptiste Maneyrol
Add temperature channel in gyroscope and accelerometer devices.

Temperature is available in full 16 bits resolution as a processed
channel. Scale and offset attributes are also provided for the low
8 bits resolution raw temperature found in the FIFO.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 11 ++-
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 11 ++-
 .../iio/imu/inv_icm42600/inv_icm42600_temp.c  | 87 +++
 .../iio/imu/inv_icm42600/inv_icm42600_temp.h  | 30 +++
 4 files changed, 137 insertions(+), 2 deletions(-)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index 717c6b0869fc..3f214df44093 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -13,6 +13,7 @@
 #include 
 
 #include "inv_icm42600.h"
+#include "inv_icm42600_temp.h"
 
 #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)  \
{   \
@@ -45,6 +46,7 @@ enum inv_icm42600_accel_scan {
INV_ICM42600_ACCEL_SCAN_X,
INV_ICM42600_ACCEL_SCAN_Y,
INV_ICM42600_ACCEL_SCAN_Z,
+   INV_ICM42600_ACCEL_SCAN_TEMP,
 };
 
 static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
@@ -59,6 +61,7 @@ static const struct iio_chan_spec 
inv_icm42600_accel_channels[] = {
inv_icm42600_accel_ext_infos),
INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z,
inv_icm42600_accel_ext_infos),
+   INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP),
 };
 
 static int inv_icm42600_accel_read_sensor(struct inv_icm42600_state *st,
@@ -450,8 +453,14 @@ static int inv_icm42600_accel_read_raw(struct iio_dev 
*indio_dev,
int16_t data;
int ret;
 
-   if (chan->type != IIO_ACCEL)
+   switch (chan->type) {
+   case IIO_ACCEL:
+   break;
+   case IIO_TEMP:
+   return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, 
mask);
+   default:
return -EINVAL;
+   }
 
switch (mask) {
case IIO_CHAN_INFO_RAW:
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
index 3875ecbee67e..6a0e7661fa48 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
@@ -13,6 +13,7 @@
 #include 
 
 #include "inv_icm42600.h"
+#include "inv_icm42600_temp.h"
 
 #define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info)   \
{   \
@@ -45,6 +46,7 @@ enum inv_icm42600_gyro_scan {
INV_ICM42600_GYRO_SCAN_X,
INV_ICM42600_GYRO_SCAN_Y,
INV_ICM42600_GYRO_SCAN_Z,
+   INV_ICM42600_GYRO_SCAN_TEMP,
 };
 
 static const struct iio_chan_spec_ext_info inv_icm42600_gyro_ext_infos[] = {
@@ -59,6 +61,7 @@ static const struct iio_chan_spec 
inv_icm42600_gyro_channels[] = {
   inv_icm42600_gyro_ext_infos),
INV_ICM42600_GYRO_CHAN(IIO_MOD_Z, INV_ICM42600_GYRO_SCAN_Z,
   inv_icm42600_gyro_ext_infos),
+   INV_ICM42600_TEMP_CHAN(INV_ICM42600_GYRO_SCAN_TEMP),
 };
 
 static int inv_icm42600_gyro_read_sensor(struct inv_icm42600_state *st,
@@ -461,8 +464,14 @@ static int inv_icm42600_gyro_read_raw(struct iio_dev 
*indio_dev,
int16_t data;
int ret;
 
-   if (chan->type != IIO_ANGL_VEL)
+   switch (chan->type) {
+   case IIO_ANGL_VEL:
+   break;
+   case IIO_TEMP:
+   return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, 
mask);
+   default:
return -EINVAL;
+   }
 
switch (mask) {
case IIO_CHAN_INFO_RAW:
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
new file mode 100644
index ..b0871352fe39
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+#include "inv_icm42600_temp.h"
+
+static int inv_icm42600_temp_read(struct inv_icm42600_state *st, int32_t *temp)
+{
+   struct device *dev = regmap_get_device(st->map);
+   int64_t data;
+   __be16 *raw;
+   int16_t val;
+   int ret;
+
+   pm_runtime_get_sync(dev);
+   mutex_lock(>lock);
+
+   ret = inv_icm42600_set_temp_conf(st, true, NULL);
+

[PATCH v3 13/13] MAINTAINERS: add entry for inv_icm42600 6-axis imu sensor

2020-06-08 Thread Jean-Baptiste Maneyrol
Add MAINTAINERS entry for InvenSense ICM-426xx IMU device.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 MAINTAINERS | 8 
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 60ed2963efaa..cd8b5fece94d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8861,6 +8861,14 @@ F:   include/dt-bindings/interconnect/
 F: include/linux/interconnect-provider.h
 F: include/linux/interconnect.h
 
+INVENSENSE ICM-426xx IMU DRIVER
+M: Jean-Baptiste Maneyrol 
+L: linux-...@vger.kernel.org
+S: Maintained
+W  https://invensense.tdk.com/
+F: Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
+F: drivers/iio/imu/inv_icm42600/
+
 INVENSENSE MPU-3050 GYROSCOPE DRIVER
 M: Linus Walleij 
 L: linux-...@vger.kernel.org
-- 
2.17.1



[PATCH v3 07/13] iio: imu: add Kconfig and Makefile for inv_icm42600 driver

2020-06-08 Thread Jean-Baptiste Maneyrol
Add 3 modules: inv-icm42600, inv-icm42600-i2c, inv-icm42600-spi.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/Kconfig   |  1 +
 drivers/iio/imu/Makefile  |  1 +
 drivers/iio/imu/inv_icm42600/Kconfig  | 28 +++
 drivers/iio/imu/inv_icm42600/Makefile | 13 +
 4 files changed, 43 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/Kconfig
 create mode 100644 drivers/iio/imu/inv_icm42600/Makefile

diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index fc4123d518bc..f02883b08480 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -91,6 +91,7 @@ config KMX61
  To compile this driver as module, choose M here: the module will
  be called kmx61.
 
+source "drivers/iio/imu/inv_icm42600/Kconfig"
 source "drivers/iio/imu/inv_mpu6050/Kconfig"
 source "drivers/iio/imu/st_lsm6dsx/Kconfig"
 
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index 88b2c4555230..13e9ff442b11 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_FXOS8700) += fxos8700_core.o
 obj-$(CONFIG_FXOS8700_I2C) += fxos8700_i2c.o
 obj-$(CONFIG_FXOS8700_SPI) += fxos8700_spi.o
 
+obj-y += inv_icm42600/
 obj-y += inv_mpu6050/
 
 obj-$(CONFIG_KMX61) += kmx61.o
diff --git a/drivers/iio/imu/inv_icm42600/Kconfig 
b/drivers/iio/imu/inv_icm42600/Kconfig
new file mode 100644
index ..22390a72f0a3
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/Kconfig
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+config INV_ICM42600
+   tristate
+
+config INV_ICM42600_I2C
+   tristate "InvenSense ICM-426xx I2C driver"
+   depends on I2C
+   select INV_ICM42600
+   select REGMAP_I2C
+   help
+ This driver supports the InvenSense ICM-426xx motion tracking
+ devices over I2C.
+
+ This driver can be built as a module. The module will be called
+ inv-icm42600-i2c.
+
+config INV_ICM42600_SPI
+   tristate "InvenSense ICM-426xx SPI driver"
+   depends on SPI_MASTER
+   select INV_ICM42600
+   select REGMAP_SPI
+   help
+ This driver supports the InvenSense ICM-426xx motion tracking
+ devices over SPI.
+
+ This driver can be built as a module. The module will be called
+ inv-icm42600-spi.
diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
b/drivers/iio/imu/inv_icm42600/Makefile
new file mode 100644
index ..48965824f00c
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/Makefile
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+obj-$(CONFIG_INV_ICM42600) += inv-icm42600.o
+inv-icm42600-y += inv_icm42600_core.o
+inv-icm42600-y += inv_icm42600_gyro.o
+inv-icm42600-y += inv_icm42600_accel.o
+inv-icm42600-y += inv_icm42600_temp.o
+
+obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o
+inv-icm42600-i2c-y += inv_icm42600_i2c.o
+
+obj-$(CONFIG_INV_ICM42600_SPI) += inv-icm42600-spi.o
+inv-icm42600-spi-y += inv_icm42600_spi.o
-- 
2.17.1



[PATCH v3 11/13] iio: imu: inv_icm42600: add accurate timestamping

2020-06-08 Thread Jean-Baptiste Maneyrol
Add a timestamping mechanism for buffer that provides accurate
event timestamps when using watermark. This mechanism estimates
device internal clock by comparing FIFO interrupts delta time and
device elapsed time computed by parsing FIFO data.

Take interrupt timestamp in hard irq handler and add IIO device
specific timestamp structures in device private allocation.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/Makefile |   1 +
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   5 +
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c |  40 +++-
 .../imu/inv_icm42600/inv_icm42600_buffer.c|  28 +++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |  17 +-
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  |  40 +++-
 .../imu/inv_icm42600/inv_icm42600_timestamp.c | 195 ++
 .../imu/inv_icm42600/inv_icm42600_timestamp.h |  85 
 8 files changed, 396 insertions(+), 15 deletions(-)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h

diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
b/drivers/iio/imu/inv_icm42600/Makefile
index 0f49f6df3647..291714d9aa54 100644
--- a/drivers/iio/imu/inv_icm42600/Makefile
+++ b/drivers/iio/imu/inv_icm42600/Makefile
@@ -6,6 +6,7 @@ inv-icm42600-y += inv_icm42600_gyro.o
 inv-icm42600-y += inv_icm42600_accel.o
 inv-icm42600-y += inv_icm42600_temp.o
 inv-icm42600-y += inv_icm42600_buffer.o
+inv-icm42600-y += inv_icm42600_timestamp.o
 
 obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o
 inv-icm42600-i2c-y += inv_icm42600_i2c.o
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index 7b52d92739c3..c0f5059b13b3 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -126,6 +126,7 @@ struct inv_icm42600_suspended {
  *  @indio_accel:  accelerometer IIO device.
  *  @buffer:   data transfer buffer aligned for DMA.
  *  @fifo: FIFO management structure.
+ *  @timestamp:interrupt timestamps.
  */
 struct inv_icm42600_state {
struct mutex lock;
@@ -141,6 +142,10 @@ struct inv_icm42600_state {
struct iio_dev *indio_accel;
uint8_t buffer[2] cacheline_aligned;
struct inv_icm42600_fifo fifo;
+   struct {
+   int64_t gyro;
+   int64_t accel;
+   } timestamp;
 };
 
 /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index 77cdad99de91..e51e15029116 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -17,6 +17,7 @@
 #include "inv_icm42600.h"
 #include "inv_icm42600_temp.h"
 #include "inv_icm42600_buffer.h"
+#include "inv_icm42600_timestamp.h"
 
 #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)  \
{   \
@@ -50,6 +51,7 @@ enum inv_icm42600_accel_scan {
INV_ICM42600_ACCEL_SCAN_Y,
INV_ICM42600_ACCEL_SCAN_Z,
INV_ICM42600_ACCEL_SCAN_TEMP,
+   INV_ICM42600_ACCEL_SCAN_TIMESTAMP,
 };
 
 static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
@@ -65,16 +67,18 @@ static const struct iio_chan_spec 
inv_icm42600_accel_channels[] = {
INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z,
inv_icm42600_accel_ext_infos),
INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP),
+   IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42600_ACCEL_SCAN_TIMESTAMP),
 };
 
 /*
- * IIO buffer data: size must be a power of 2
- * 8 bytes: 7 bytes data (accel 6 + temp 1) + 1 byte padding
+ * IIO buffer data: size must be a power of 2 and timestamp aligned
+ * 16 bytes: 7 bytes data (accel 6 + temp 1) + 1 byte padding + 8 bytes 
timestamp
  */
 struct inv_icm42600_accel_buffer {
struct inv_icm42600_fifo_sensor_data accel;
int8_t temp;
uint8_t padding;
+   int64_t timestamp __aligned(8);
 };
 
 #define INV_ICM42600_SCAN_MASK_ACCEL_3AXIS \
@@ -95,6 +99,7 @@ static int inv_icm42600_accel_update_scan_mode(struct iio_dev 
*indio_dev,
   const unsigned long *scan_mask)
 {
struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+   struct inv_icm42600_timestamp *ts = iio_priv(indio_dev);
struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
unsigned int fifo_en = 0;
unsigned int sleep_temp = 0;
@@ -122,6 +127,7 @@ static int inv_icm42600_accel_update_scan_mode(struct 
iio_dev *indio_dev,
}
 
/* update data FIFO write */
+   inv_icm42600_times

[PATCH v3 01/13] iio: imu: inv_icm42600: add core of new inv_icm42600 driver

2020-06-08 Thread Jean-Baptiste Maneyrol
Core component of a new driver for InvenSense ICM-426xx devices.
It includes registers definition, main probe/setup, and device
utility functions.

ICM-426xx devices are latest generation of 6-axis IMU,
gyroscope+accelerometer and temperature sensor. This device
includes a 2K FIFO, supports I2C/I3C/SPI, and provides
intelligent motion features like pedometer, tilt detection,
and tap detection.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   | 372 ++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  | 634 ++
 2 files changed, 1006 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600.h
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_core.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
new file mode 100644
index ..14c8ef152418
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -0,0 +1,372 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#ifndef INV_ICM42600_H_
+#define INV_ICM42600_H_
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+enum inv_icm42600_chip {
+   INV_CHIP_ICM42600,
+   INV_CHIP_ICM42602,
+   INV_CHIP_ICM42605,
+   INV_CHIP_ICM42622,
+   INV_CHIP_NB,
+};
+
+/* serial bus slew rates */
+enum inv_icm42600_slew_rate {
+   INV_ICM42600_SLEW_RATE_20_60NS,
+   INV_ICM42600_SLEW_RATE_12_36NS,
+   INV_ICM42600_SLEW_RATE_6_18NS,
+   INV_ICM42600_SLEW_RATE_4_12NS,
+   INV_ICM42600_SLEW_RATE_2_6NS,
+   INV_ICM42600_SLEW_RATE_INF_2NS,
+};
+
+enum inv_icm42600_sensor_mode {
+   INV_ICM42600_SENSOR_MODE_OFF,
+   INV_ICM42600_SENSOR_MODE_STANDBY,
+   INV_ICM42600_SENSOR_MODE_LOW_POWER,
+   INV_ICM42600_SENSOR_MODE_LOW_NOISE,
+   INV_ICM42600_SENSOR_MODE_NB,
+};
+
+/* gyroscope fullscale values */
+enum inv_icm42600_gyro_fs {
+   INV_ICM42600_GYRO_FS_2000DPS,
+   INV_ICM42600_GYRO_FS_1000DPS,
+   INV_ICM42600_GYRO_FS_500DPS,
+   INV_ICM42600_GYRO_FS_250DPS,
+   INV_ICM42600_GYRO_FS_125DPS,
+   INV_ICM42600_GYRO_FS_62_5DPS,
+   INV_ICM42600_GYRO_FS_31_25DPS,
+   INV_ICM42600_GYRO_FS_15_625DPS,
+   INV_ICM42600_GYRO_FS_NB,
+};
+
+/* accelerometer fullscale values */
+enum inv_icm42600_accel_fs {
+   INV_ICM42600_ACCEL_FS_16G,
+   INV_ICM42600_ACCEL_FS_8G,
+   INV_ICM42600_ACCEL_FS_4G,
+   INV_ICM42600_ACCEL_FS_2G,
+   INV_ICM42600_ACCEL_FS_NB,
+};
+
+/* ODR suffixed by LN or LP are Low-Noise or Low-Power mode only */
+enum inv_icm42600_odr {
+   INV_ICM42600_ODR_8KHZ_LN = 3,
+   INV_ICM42600_ODR_4KHZ_LN,
+   INV_ICM42600_ODR_2KHZ_LN,
+   INV_ICM42600_ODR_1KHZ_LN,
+   INV_ICM42600_ODR_200HZ,
+   INV_ICM42600_ODR_100HZ,
+   INV_ICM42600_ODR_50HZ,
+   INV_ICM42600_ODR_25HZ,
+   INV_ICM42600_ODR_12_5HZ,
+   INV_ICM42600_ODR_6_25HZ_LP,
+   INV_ICM42600_ODR_3_125HZ_LP,
+   INV_ICM42600_ODR_1_5625HZ_LP,
+   INV_ICM42600_ODR_500HZ,
+   INV_ICM42600_ODR_NB,
+};
+
+enum inv_icm42600_filter {
+   /* Low-Noise mode sensor data filter (3rd order filter by default) */
+   INV_ICM42600_FILTER_BW_ODR_DIV_2,
+
+   /* Low-Power mode sensor data filter (averaging) */
+   INV_ICM42600_FILTER_AVG_1X = 1,
+   INV_ICM42600_FILTER_AVG_16X = 6,
+};
+
+struct inv_icm42600_sensor_conf {
+   int mode;
+   int fs;
+   int odr;
+   int filter;
+};
+#define INV_ICM42600_SENSOR_CONF_INIT  {-1, -1, -1, -1}
+
+struct inv_icm42600_conf {
+   struct inv_icm42600_sensor_conf gyro;
+   struct inv_icm42600_sensor_conf accel;
+   bool temp_en;
+};
+
+struct inv_icm42600_suspended {
+   enum inv_icm42600_sensor_mode gyro;
+   enum inv_icm42600_sensor_mode accel;
+   bool temp;
+};
+
+/**
+ *  struct inv_icm42600_state - driver state variables
+ *  @lock: lock for serializing multiple registers access.
+ *  @chip: chip identifier.
+ *  @name: chip name.
+ *  @map:  regmap pointer.
+ *  @vdd_supply:   VDD voltage regulator for the chip.
+ *  @vddio_supply: I/O voltage regulator for the chip.
+ *  @orientation:  sensor chip orientation relative to main hardware.
+ *  @conf: chip sensors configurations.
+ *  @suspended:suspended sensors configuration.
+ */
+struct inv_icm42600_state {
+   struct mutex lock;
+   enum inv_icm42600_chip chip;
+   const char *name;
+   struct regmap *map;
+   struct regulator *vdd_supply;
+   struct regulator *vddio_supply;
+   struct iio_mount_matrix orientation;
+   struct inv_icm42600_conf conf;
+   struct inv_icm42600_suspended suspended;
+};
+
+/* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
+
+/* Bank selection register, available in all banks */
+#define

Re: --[[SPOOF or PHISHING]]--Re: [PATCH v2 09/12] iio: imu: inv_icm42600: add buffer support in iio devices

2020-06-03 Thread Jean-Baptiste Maneyrol
Hi Jonathan,

something I forgot, about the __packed attribute for the sensor data structure 
struct inv_icm42600_fifo_sensor_data located inside inv_icm42600_buffer.h.

I added it because this structure is used for decoding the FIFO data frame 
which can be unaligned. It is also used for storing data in other modules, but 
__packed attribute should not change anything here.

Thanks,
JB



From: linux-iio-ow...@vger.kernel.org  on 
behalf of Jean-Baptiste Maneyrol 
Sent: Tuesday, June 2, 2020 14:57
To: Jonathan Cameron 
Cc: robh...@kernel.org ; r...@kernel.org ; 
mchehab+hua...@kernel.org ; da...@davemloft.net 
; gre...@linuxfoundation.org ; 
linux-...@vger.kernel.org ; 
devicet...@vger.kernel.org ; 
linux-kernel@vger.kernel.org 
Subject: --[[SPOOF or PHISHING]]--Re: [PATCH v2 09/12] iio: imu: inv_icm42600: 
add buffer support in iio devices 
 
 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.

Hi Jonathan,

I agree that this multiplexed watermark computation value is anything except 
simple and clear to understand.
I will add more documentation about it. And it also triggered a kbuild robot 
issue, because it is using 64 bits modulo without using math64 macros.

For buffer preenable/postenable/..., the sequence I am using currently is:
- preenable -> turn chip on (pm_runtime_get)
- update_scan_mode -> set FIFO en bits configuration (which sensor data is 
going into the fifo)
- hwfifo_watermark -> compute and set watermark value
- postenable -> turn FIFO on (and multiplexed with a FIFO on counter since used 
by accel & gyro)
- predisable -> turn FIFO off (multiplexed with counter)
- postdisable -> turn chip off (pm_runtime_put)

This setting is working well. Good to note that if there is an error when 
enabling the buffer, postdisable will always get called after preenable. So it 
ensures pm_runtime reference counter to be always OK.

Another way would be to only store configuration in internal state with 
update_scan_mode and hwfifo_watermark, and do everything in 
postenable/predisable. This is a possibility, but makes things a little more 
complex.

For hwfifo flush, this is an interesting feature when there is a need to have 
data immediately. Or when there is a need to do a clean change of 
configuration. In Android systems, Android framework is mainly using FIFO flush 
to change the sensor configuration (ODR, watermark) in a clean way. For our 
case with the FIFO interleaved this is a not an issue. If there are samples 
from the 2 sensors, it means the 2 buffers are enabled. And if data is coming 
to the iio buffer sooner than expected, that should not be a problem. The 
limitation I see when the 2 sensors are runnings, is that we will return less 
data than should have been possible. I limit FIFO reading to the provided n 
bytes, so we could read less than n samples of 1 sensor.

Something I have in mind, that would be really interesting to be able to 
set/change watermark value when the buffer is enabled. Otherwise, we are always 
loosing events by turning sensor off when we want to change the value. Is there 
any limitation to work this way, or should it be possible to implement this 
feature in the future ?

Thanks,
JB


From: Jonathan Cameron 
Sent: Sunday, May 31, 2020 14:56
To: Jean-Baptiste Maneyrol 
Cc: robh...@kernel.org ; r...@kernel.org ; 
mchehab+hua...@kernel.org ; da...@davemloft.net 
; gre...@linuxfoundation.org ; 
linux-...@vger.kernel.org ; 
devicet...@vger.kernel.org ; 
linux-kernel@vger.kernel.org 
Subject: Re: [PATCH v2 09/12] iio: imu: inv_icm42600: add buffer support in iio 
devices 
 
 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.

On Wed, 27 May 2020 20:57:08 +0200
Jean-Baptiste Maneyrol  wrote:

> Add all FIFO parsing and reading functions. Add accel and gyro
> kfifo buffer and FIFO data parsing. Use device interrupt for
> reading data FIFO and launching accel and gyro parsing.
> 
> Support hwfifo watermark by multiplexing gyro and accel settings.
> Support hwfifo flush.

Both of these are complex given the interactions of the two sensors
types and to be honest I couldn't figure out exactly what the intent was.
Needs more docs!

Thanks,

Jonathan

> 
> Signed-off-by: Jean-Baptiste Maneyrol 
> ---
>  drivers/iio/imu/inv_icm42600/Kconfig  |   1 +
>  drivers/iio/imu/inv_icm42600/Makefile |   1 +
>  drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   8 +
>  .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 160 -
>  .../imu/inv_icm42600/inv_icm42600_buffer.c    | 555 ++
>  .../imu/inv_icm42600/inv_icm42600_buffer.h    |  98 
>

Re: [PATCH v2 09/12] iio: imu: inv_icm42600: add buffer support in iio devices

2020-06-02 Thread Jean-Baptiste Maneyrol
Hi Jonathan,

I agree that this multiplexed watermark computation value is anything except 
simple and clear to understand.
I will add more documentation about it. And it also triggered a kbuild robot 
issue, because it is using 64 bits modulo without using math64 macros.

For buffer preenable/postenable/..., the sequence I am using currently is:
- preenable -> turn chip on (pm_runtime_get)
- update_scan_mode -> set FIFO en bits configuration (which sensor data is 
going into the fifo)
- hwfifo_watermark -> compute and set watermark value
- postenable -> turn FIFO on (and multiplexed with a FIFO on counter since used 
by accel & gyro)
- predisable -> turn FIFO off (multiplexed with counter)
- postdisable -> turn chip off (pm_runtime_put)

This setting is working well. Good to note that if there is an error when 
enabling the buffer, postdisable will always get called after preenable. So it 
ensures pm_runtime reference counter to be always OK.

Another way would be to only store configuration in internal state with 
update_scan_mode and hwfifo_watermark, and do everything in 
postenable/predisable. This is a possibility, but makes things a little more 
complex.

For hwfifo flush, this is an interesting feature when there is a need to have 
data immediately. Or when there is a need to do a clean change of 
configuration. In Android systems, Android framework is mainly using FIFO flush 
to change the sensor configuration (ODR, watermark) in a clean way. For our 
case with the FIFO interleaved this is a not an issue. If there are samples 
from the 2 sensors, it means the 2 buffers are enabled. And if data is coming 
to the iio buffer sooner than expected, that should not be a problem. The 
limitation I see when the 2 sensors are runnings, is that we will return less 
data than should have been possible. I limit FIFO reading to the provided n 
bytes, so we could read less than n samples of 1 sensor.

Something I have in mind, that would be really interesting to be able to 
set/change watermark value when the buffer is enabled. Otherwise, we are always 
loosing events by turning sensor off when we want to change the value. Is there 
any limitation to work this way, or should it be possible to implement this 
feature in the future ?

Thanks,
JB


From: Jonathan Cameron 
Sent: Sunday, May 31, 2020 14:56
To: Jean-Baptiste Maneyrol 
Cc: robh...@kernel.org ; r...@kernel.org ; 
mchehab+hua...@kernel.org ; da...@davemloft.net 
; gre...@linuxfoundation.org ; 
linux-...@vger.kernel.org ; 
devicet...@vger.kernel.org ; 
linux-kernel@vger.kernel.org 
Subject: Re: [PATCH v2 09/12] iio: imu: inv_icm42600: add buffer support in iio 
devices 
 
 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.

On Wed, 27 May 2020 20:57:08 +0200
Jean-Baptiste Maneyrol  wrote:

> Add all FIFO parsing and reading functions. Add accel and gyro
> kfifo buffer and FIFO data parsing. Use device interrupt for
> reading data FIFO and launching accel and gyro parsing.
> 
> Support hwfifo watermark by multiplexing gyro and accel settings.
> Support hwfifo flush.

Both of these are complex given the interactions of the two sensors
types and to be honest I couldn't figure out exactly what the intent was.
Needs more docs!

Thanks,

Jonathan

> 
> Signed-off-by: Jean-Baptiste Maneyrol 
> ---
>  drivers/iio/imu/inv_icm42600/Kconfig  |   1 +
>  drivers/iio/imu/inv_icm42600/Makefile |   1 +
>  drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   8 +
>  .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 160 -
>  .../imu/inv_icm42600/inv_icm42600_buffer.c    | 555 ++
>  .../imu/inv_icm42600/inv_icm42600_buffer.h    |  98 
>  .../iio/imu/inv_icm42600/inv_icm42600_core.c  |  30 +
>  .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 160 -
>  8 files changed, 1011 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c
>  create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h
> 
> diff --git a/drivers/iio/imu/inv_icm42600/Kconfig 
> b/drivers/iio/imu/inv_icm42600/Kconfig
> index 22390a72f0a3..50cbcfcb6cf1 100644
> --- a/drivers/iio/imu/inv_icm42600/Kconfig
> +++ b/drivers/iio/imu/inv_icm42600/Kconfig
> @@ -2,6 +2,7 @@
>  
>  config INV_ICM42600
>    tristate
> + select IIO_BUFFER
>  
>  config INV_ICM42600_I2C
>    tristate "InvenSense ICM-426xx I2C driver"
> diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
> b/drivers/iio/imu/inv_icm42600/Makefile
> index 48965824f00c..0f49f6df3647 100644
> --- a/drivers/iio/imu/inv_icm42600/Makefile
> +++ b/drivers/iio/imu/inv_icm42600/Makefile
> @@ -5,6 +5,7 @@ inv-icm42600-y += inv_icm42

Re: [PATCH v2 04/12] iio: imu: inv_icm42600: add gyroscope IIO device

2020-06-02 Thread Jean-Baptiste Maneyrol
Hi Jonathan,

for the calibration bias, value is expressed in g unit, fixed, independant from 
any scale value.
So I can switch to g instead of SI unit, but this will still not be like raw 
data which are dependent of the scale value. That's why I used SI units.

Another solution, would be to adapt the value depending on the scale setting. 
So that it will correspond to raw data. But this also invovles complex 
computation.

Tell me what you prefer.

Thanks,
JB

From: Jonathan Cameron 
Sent: Sunday, May 31, 2020 13:54
To: Jean-Baptiste Maneyrol 
Cc: robh...@kernel.org ; r...@kernel.org ; 
mchehab+hua...@kernel.org ; da...@davemloft.net 
; gre...@linuxfoundation.org ; 
linux-...@vger.kernel.org ; 
devicet...@vger.kernel.org ; 
linux-kernel@vger.kernel.org 
Subject: Re: [PATCH v2 04/12] iio: imu: inv_icm42600: add gyroscope IIO device 
 
 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.

On Wed, 27 May 2020 20:57:03 +0200
Jean-Baptiste Maneyrol  wrote:

> Add IIO device for gyroscope sensor with data polling interface.
> Attributes: raw, scale, sampling_frequency, calibbias.
> 
> Gyroscope in low noise mode.
> 
> Signed-off-by: Jean-Baptiste Maneyrol 

Unusual to have a calibration offset specified in output units,
which contributes a lot of the complexity in here.
Normally those are strictly front end (output of some calibration DAC).
So if they have units (and often they don't) I'd expect them to be
the same as _raw.

We need to tidy up the docs on this though as it doesn't express
any sort of preference.  It's hard to be specific as often the calibration
scales are defined - they are just like tweaking a POT on an analog
sensor board.

A few trivial other things inline, including a suggestion to modify
the layering of the driver a tiny bit during probe.

Thanks,

Jonathan

> ---
>  drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   6 +
>  .../iio/imu/inv_icm42600/inv_icm42600_core.c  |   4 +
>  .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 600 ++
>  3 files changed, 610 insertions(+)
>  create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
> 
> diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
> b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
> index 14c8ef152418..c1023d59b37b 100644
> --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
> +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
> @@ -120,6 +120,8 @@ struct inv_icm42600_suspended {
>   *  @orientation:    sensor chip orientation relative to main hardware.
>   *  @conf:   chip sensors configurations.
>   *  @suspended:  suspended sensors configuration.
> + *  @indio_gyro: gyroscope IIO device.
> + *  @buffer: data transfer buffer aligned for DMA.
>   */
>  struct inv_icm42600_state {
>    struct mutex lock;
> @@ -131,6 +133,8 @@ struct inv_icm42600_state {
>    struct iio_mount_matrix orientation;
>    struct inv_icm42600_conf conf;
>    struct inv_icm42600_suspended suspended;
> + struct iio_dev *indio_gyro;
> + uint8_t buffer[2] cacheline_aligned;
>  };
>  
>  /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB 
>*/
> @@ -369,4 +373,6 @@ int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, 
> unsigned int reg,
>  int inv_icm42600_core_probe(struct regmap *regmap, int chip,
>    inv_icm42600_bus_setup bus_setup);
>  
> +int inv_icm42600_gyro_init(struct inv_icm42600_state *st);
> +
>  #endif
> diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c 
> b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
> index 81b171d6782c..dccb7bcc782e 100644
> --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
> +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
> @@ -510,6 +510,10 @@ int inv_icm42600_core_probe(struct regmap *regmap, int 
> chip,
>    if (ret)
>    return ret;
>  
> + ret = inv_icm42600_gyro_init(st);
> + if (ret)
> + return ret;
> +
>    /* setup runtime power management */
>    ret = pm_runtime_set_active(dev);
>    if (ret)
> diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c 
> b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
> new file mode 100644
> index ..9d9672989b23
> --- /dev/null
> +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
> @@ -0,0 +1,600 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2020 Invensense, Inc.
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#

Re: [PATCH v2 01/12] iio: imu: inv_icm42600: add core of new inv_icm42600 driver

2020-06-02 Thread Jean-Baptiste Maneyrol
Hi Jonathan,

I've given my review tag for the const change of iio_device_get_drvdata(). 
Would be perfect to have this cleaned up for the v3.

For vddio regulator you are missing something. In all suspend callbacks (system 
and runtime) I am calling directly regulator_disable to shut vddio off at then 
end. And in all resume callbacks I am calling 
inv_icm42600_enable_regulator_vddio() that is turning vddio regulator back on 
and is sleeping to wait a little for the supply ramp.

Indeed this doesn't look symmetric, but I was not very happy to add a 
inv_icm42600_disable_regulator_vddio() that would just do regulator_disable, or 
copy/paste the sleeping value in all resume handlers.

Tell me what you prefer.

Thanks,
JB

From: linux-iio-ow...@vger.kernel.org  on 
behalf of Jonathan Cameron 
Sent: Sunday, May 31, 2020 13:34
To: Jean-Baptiste Maneyrol 
Cc: robh...@kernel.org ; r...@kernel.org ; 
mchehab+hua...@kernel.org ; da...@davemloft.net 
; gre...@linuxfoundation.org ; 
linux-...@vger.kernel.org ; 
devicet...@vger.kernel.org ; 
linux-kernel@vger.kernel.org 
Subject: Re: [PATCH v2 01/12] iio: imu: inv_icm42600: add core of new 
inv_icm42600 driver 
 
 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.

On Wed, 27 May 2020 20:57:00 +0200
Jean-Baptiste Maneyrol  wrote:

> Core component of a new driver for InvenSense ICM-426xx devices.
> It includes registers definition, main probe/setup, and device
> utility functions.
> 
> ICM-426xx devices are latest generation of 6-axis IMU,
> gyroscope+accelerometer and temperature sensor. This device
> includes a 2K FIFO, supports I2C/I3C/SPI, and provides
> intelligent motion features like pedometer, tilt detection,
> and tap detection.
> 
> Signed-off-by: Jean-Baptiste Maneyrol 

A few things inline.

Either I'm missing something or I'm guessing vddio is not controllable
on your test board.

> ---
>  drivers/iio/imu/inv_icm42600/inv_icm42600.h   | 372 ++
>  .../iio/imu/inv_icm42600/inv_icm42600_core.c  | 635 ++
>  2 files changed, 1007 insertions(+)
>  create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600.h
>  create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
> 

...

> diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c 
> b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
> new file mode 100644
> index ..81b171d6782c
> --- /dev/null
> +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c

> +const struct iio_mount_matrix *
> +inv_icm42600_get_mount_matrix(const struct iio_dev *indio_dev,
> +   const struct iio_chan_spec *chan)
> +{
> + const struct inv_icm42600_state *st =
> + iio_device_get_drvdata((struct iio_dev *)indio_dev);

If you review my patch to the core, I can get that applied and we can drop
the ugly cast from here!

Just waiting for someone to sanity check it.
> +
> + return >orientation;
> +}
...

> +/* Runtime suspend will turn off sensors that are enabled by iio devices. */
> +static int __maybe_unused inv_icm42600_runtime_suspend(struct device *dev)
> +{
> + struct inv_icm42600_state *st = dev_get_drvdata(dev);
> + int ret;
> +
> + mutex_lock(>lock);
> +
> + /* disable all sensors */
> + ret = inv_icm42600_set_pwr_mgmt0(st, INV_ICM42600_SENSOR_MODE_OFF,
> +  INV_ICM42600_SENSOR_MODE_OFF, false,
> +  NULL);
> + if (ret)
> + goto error_unlock;
> +
> + regulator_disable(st->vddio_supply);

Don't seem to turn this on again in runtime_resume..
Why?  Definitely needs at least a comment.

> +
> +error_unlock:
> + mutex_unlock(>lock);
> + return ret;
> +}
> +
> +/* Sensors are enabled by iio devices, no need to turn them back on here. */
> +static int __maybe_unused inv_icm42600_runtime_resume(struct device *dev)
> +{
> + struct inv_icm42600_state *st = dev_get_drvdata(dev);
> + int ret;
> +
> + mutex_lock(>lock);
> +
> + ret = inv_icm42600_enable_regulator_vddio(st);
> +
> + mutex_unlock(>lock);
> + return ret;
> +}
> +
> +const struct dev_pm_ops inv_icm42600_pm_ops = {
> + SET_SYSTEM_SLEEP_PM_OPS(inv_icm42600_suspend, inv_icm42600_resume)
> + SET_RUNTIME_PM_OPS(inv_icm42600_runtime_suspend,
> +    inv_icm42600_runtime_resume, NULL)
> +};
> +EXPORT_SYMBOL_GPL(inv_icm42600_pm_ops);
> +
> +MODULE_AUTHOR("InvenSense, Inc.");
> +MODULE_DESCRIPTION("InvenSense ICM-426xx device driver");
> +MODULE_LICENSE("GPL");


[PATCH v2 11/12] dt-bindings: iio: imu: Add inv_icm42600 documentation

2020-05-27 Thread Jean-Baptiste Maneyrol
Document the ICM-426xxx devices devicetree bindings.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../bindings/iio/imu/invensense,icm42600.yaml | 86 +++
 1 file changed, 86 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml

diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml 
b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
new file mode 100644
index ..c5b046e0ce36
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/imu/invensense,icm42600.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: InvenSense ICM-426xx Inertial Measurement Unit
+
+maintainers:
+  - Jean-Baptiste Maneyrol 
+
+description: |
+  6-axis MotionTracking device that combines a 3-axis gyroscope and a 3-axis 
accelerometer.
+
+  It has a configurable host interface that supports I3C, I2C and SPI serial 
communication, features a 2kB FIFO and
+  2 programmable interrupts with ultra-low-power wake-on-motion support to 
minimize system power consumption.
+
+  Other industry-leading features include InvenSense on-chip APEX Motion 
Processing engine for gesture recognition,
+  activity classification, and pedometer, along with programmable digital 
filters, and an embedded temperature sensor.
+
+  
https://invensense.tdk.com/wp-content/uploads/2020/03/DS-000292-ICM-42605-v1.4.pdf
+
+properties:
+  compatible:
+enum:
+  - invensense,icm42600
+  - invensense,icm42602
+  - invensense,icm42605
+  - invensense,icm42622
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  drive-open-drain:
+type: boolean
+
+  vdd-supply:
+description: Regulator that provides power to the sensor
+
+  vddio-supply:
+description: Regulator that provides power to the bus
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+examples:
+  - |
+#include 
+#include 
+i2c0 {
+#address-cells = <1>;
+#size-cells = <0>;
+
+icm42605@68 {
+  compatible = "invensense,icm42605";
+  reg = <0x68>;
+  interrupt-parent = <>;
+  interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+  vdd-supply = <>;
+  vddio-supply = <>;
+};
+};
+  - |
+#include 
+#include 
+spi0 {
+#address-cells = <1>;
+#size-cells = <0>;
+
+icm42602@0 {
+  compatible = "invensense,icm42602";
+  reg = <0>;
+  spi-max-frequency = <2400>;
+  spi-cpha;
+  spi-cpol;
+  interrupt-parent = <>;
+  interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+  vdd-supply = <>;
+  vddio-supply = <>;
+};
+};
-- 
2.17.1



[PATCH v2 12/12] MAINTAINERS: add entry for inv_icm42600 6-axis imu sensor

2020-05-27 Thread Jean-Baptiste Maneyrol
Add MAINTAINERS entry for InvenSense ICM-426xx IMU device.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 MAINTAINERS | 8 
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 60ed2963efaa..cd8b5fece94d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8861,6 +8861,14 @@ F:   include/dt-bindings/interconnect/
 F: include/linux/interconnect-provider.h
 F: include/linux/interconnect.h
 
+INVENSENSE ICM-426xx IMU DRIVER
+M: Jean-Baptiste Maneyrol 
+L: linux-...@vger.kernel.org
+S: Maintained
+W  https://invensense.tdk.com/
+F: Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
+F: drivers/iio/imu/inv_icm42600/
+
 INVENSENSE MPU-3050 GYROSCOPE DRIVER
 M: Linus Walleij 
 L: linux-...@vger.kernel.org
-- 
2.17.1



[PATCH v2 09/12] iio: imu: inv_icm42600: add buffer support in iio devices

2020-05-27 Thread Jean-Baptiste Maneyrol
Add all FIFO parsing and reading functions. Add accel and gyro
kfifo buffer and FIFO data parsing. Use device interrupt for
reading data FIFO and launching accel and gyro parsing.

Support hwfifo watermark by multiplexing gyro and accel settings.
Support hwfifo flush.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/Kconfig  |   1 +
 drivers/iio/imu/inv_icm42600/Makefile |   1 +
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   8 +
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 160 -
 .../imu/inv_icm42600/inv_icm42600_buffer.c| 555 ++
 .../imu/inv_icm42600/inv_icm42600_buffer.h|  98 
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |  30 +
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 160 -
 8 files changed, 1011 insertions(+), 2 deletions(-)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h

diff --git a/drivers/iio/imu/inv_icm42600/Kconfig 
b/drivers/iio/imu/inv_icm42600/Kconfig
index 22390a72f0a3..50cbcfcb6cf1 100644
--- a/drivers/iio/imu/inv_icm42600/Kconfig
+++ b/drivers/iio/imu/inv_icm42600/Kconfig
@@ -2,6 +2,7 @@
 
 config INV_ICM42600
tristate
+   select IIO_BUFFER
 
 config INV_ICM42600_I2C
tristate "InvenSense ICM-426xx I2C driver"
diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
b/drivers/iio/imu/inv_icm42600/Makefile
index 48965824f00c..0f49f6df3647 100644
--- a/drivers/iio/imu/inv_icm42600/Makefile
+++ b/drivers/iio/imu/inv_icm42600/Makefile
@@ -5,6 +5,7 @@ inv-icm42600-y += inv_icm42600_core.o
 inv-icm42600-y += inv_icm42600_gyro.o
 inv-icm42600-y += inv_icm42600_accel.o
 inv-icm42600-y += inv_icm42600_temp.o
+inv-icm42600-y += inv_icm42600_buffer.o
 
 obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o
 inv-icm42600-i2c-y += inv_icm42600_i2c.o
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index 43749f56426c..4d5811562a61 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -14,6 +14,8 @@
 #include 
 #include 
 
+#include "inv_icm42600_buffer.h"
+
 enum inv_icm42600_chip {
INV_CHIP_ICM42600,
INV_CHIP_ICM42602,
@@ -123,6 +125,7 @@ struct inv_icm42600_suspended {
  *  @indio_gyro:   gyroscope IIO device.
  *  @indio_accel:  accelerometer IIO device.
  *  @buffer:   data transfer buffer aligned for DMA.
+ *  @fifo: FIFO management structure.
  */
 struct inv_icm42600_state {
struct mutex lock;
@@ -137,6 +140,7 @@ struct inv_icm42600_state {
struct iio_dev *indio_gyro;
struct iio_dev *indio_accel;
uint8_t buffer[2] cacheline_aligned;
+   struct inv_icm42600_fifo fifo;
 };
 
 /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
@@ -377,6 +381,10 @@ int inv_icm42600_core_probe(struct regmap *regmap, int 
chip, int irq,
 
 int inv_icm42600_gyro_init(struct inv_icm42600_state *st);
 
+int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev);
+
 int inv_icm42600_accel_init(struct inv_icm42600_state *st);
 
+int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev);
+
 #endif
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index 6a615d7ffb24..c73ce204efc6 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -11,9 +11,12 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 
 #include "inv_icm42600.h"
 #include "inv_icm42600_temp.h"
+#include "inv_icm42600_buffer.h"
 
 #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)  \
{   \
@@ -64,6 +67,76 @@ static const struct iio_chan_spec 
inv_icm42600_accel_channels[] = {
INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP),
 };
 
+/* IIO buffer data: 8 bytes */
+struct inv_icm42600_accel_buffer {
+   struct inv_icm42600_fifo_sensor_data accel;
+   int8_t temp;
+   uint8_t padding;
+};
+
+#define INV_ICM42600_SCAN_MASK_ACCEL_3AXIS \
+   (BIT(INV_ICM42600_ACCEL_SCAN_X) |   \
+   BIT(INV_ICM42600_ACCEL_SCAN_Y) |\
+   BIT(INV_ICM42600_ACCEL_SCAN_Z))
+
+#define INV_ICM42600_SCAN_MASK_TEMPBIT(INV_ICM42600_ACCEL_SCAN_TEMP)
+
+static const unsigned long inv_icm42600_accel_scan_masks[] = {
+   /* 3-axis accel + temperature */
+   INV_ICM42600_SCAN_MASK_ACCEL_3AXIS | INV_ICM42600_SCAN_MASK_TEMP,
+   0,
+};
+
+/* enable accelerometer sensor and FIFO write */
+static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev,
+  const unsigned long *scan_mask)
+{
+   struct inv_icm

[PATCH v2 03/12] iio: imu: inv_icm42600: add SPI driver for inv_icm42600 driver

2020-05-27 Thread Jean-Baptiste Maneyrol
Add SPI driver for InvenSense ICM-426xxx devices.

Configure bus signal slew rates as indicated in the datasheet.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../iio/imu/inv_icm42600/inv_icm42600_spi.c   | 99 +++
 1 file changed, 99 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
new file mode 100644
index ..a9c5e2fdbe2a
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
@@ -0,0 +1,99 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 InvenSense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+
+static int inv_icm42600_spi_bus_setup(struct inv_icm42600_state *st)
+{
+   unsigned int mask, val;
+   int ret;
+
+   /* setup interface registers */
+   val = INV_ICM42600_INTF_CONFIG6_I3C_EN |
+ INV_ICM42600_INTF_CONFIG6_I3C_SDR_EN |
+ INV_ICM42600_INTF_CONFIG6_I3C_DDR_EN;
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6,
+INV_ICM42600_INTF_CONFIG6_MASK, val);
+   if (ret)
+   return ret;
+
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4,
+INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0);
+   if (ret)
+   return ret;
+
+   /* set slew rates for I2C and SPI */
+   mask = INV_ICM42600_DRIVE_CONFIG_I2C_MASK |
+  INV_ICM42600_DRIVE_CONFIG_SPI_MASK;
+   val = INV_ICM42600_DRIVE_CONFIG_I2C(INV_ICM42600_SLEW_RATE_20_60NS) |
+ INV_ICM42600_DRIVE_CONFIG_SPI(INV_ICM42600_SLEW_RATE_INF_2NS);
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_DRIVE_CONFIG,
+mask, val);
+   if (ret)
+   return ret;
+
+   /* disable i2c bus */
+   return regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,
+ INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK,
+ 
INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS);
+}
+
+static int inv_icm42600_probe(struct spi_device *spi)
+{
+   const void *match;
+   enum inv_icm42600_chip chip;
+   struct regmap *regmap;
+
+   match = device_get_match_data(>dev);
+   if (!match)
+   return -EINVAL;
+   chip = (enum inv_icm42600_chip)match;
+
+   regmap = devm_regmap_init_spi(spi, _icm42600_regmap_config);
+   if (IS_ERR(regmap))
+   return PTR_ERR(regmap);
+
+   return inv_icm42600_core_probe(regmap, chip, 
inv_icm42600_spi_bus_setup);
+}
+
+static const struct of_device_id inv_icm42600_of_matches[] = {
+   {
+   .compatible = "invensense,icm42600",
+   .data = (void *)INV_CHIP_ICM42600,
+   }, {
+   .compatible = "invensense,icm42602",
+   .data = (void *)INV_CHIP_ICM42602,
+   }, {
+   .compatible = "invensense,icm42605",
+   .data = (void *)INV_CHIP_ICM42605,
+   }, {
+   .compatible = "invensense,icm42622",
+   .data = (void *)INV_CHIP_ICM42622,
+   },
+   {}
+};
+MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches);
+
+static struct spi_driver inv_icm42600_driver = {
+   .driver = {
+   .name = "inv-icm42600-spi",
+   .of_match_table = inv_icm42600_of_matches,
+   .pm = _icm42600_pm_ops,
+   },
+   .probe = inv_icm42600_probe,
+};
+module_spi_driver(inv_icm42600_driver);
+
+MODULE_AUTHOR("InvenSense, Inc.");
+MODULE_DESCRIPTION("InvenSense ICM-426xx SPI driver");
+MODULE_LICENSE("GPL");
-- 
2.17.1



[PATCH v2 01/12] iio: imu: inv_icm42600: add core of new inv_icm42600 driver

2020-05-27 Thread Jean-Baptiste Maneyrol
Core component of a new driver for InvenSense ICM-426xx devices.
It includes registers definition, main probe/setup, and device
utility functions.

ICM-426xx devices are latest generation of 6-axis IMU,
gyroscope+accelerometer and temperature sensor. This device
includes a 2K FIFO, supports I2C/I3C/SPI, and provides
intelligent motion features like pedometer, tilt detection,
and tap detection.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   | 372 ++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  | 635 ++
 2 files changed, 1007 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600.h
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_core.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
new file mode 100644
index ..14c8ef152418
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -0,0 +1,372 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#ifndef INV_ICM42600_H_
+#define INV_ICM42600_H_
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+enum inv_icm42600_chip {
+   INV_CHIP_ICM42600,
+   INV_CHIP_ICM42602,
+   INV_CHIP_ICM42605,
+   INV_CHIP_ICM42622,
+   INV_CHIP_NB,
+};
+
+/* serial bus slew rates */
+enum inv_icm42600_slew_rate {
+   INV_ICM42600_SLEW_RATE_20_60NS,
+   INV_ICM42600_SLEW_RATE_12_36NS,
+   INV_ICM42600_SLEW_RATE_6_18NS,
+   INV_ICM42600_SLEW_RATE_4_12NS,
+   INV_ICM42600_SLEW_RATE_2_6NS,
+   INV_ICM42600_SLEW_RATE_INF_2NS,
+};
+
+enum inv_icm42600_sensor_mode {
+   INV_ICM42600_SENSOR_MODE_OFF,
+   INV_ICM42600_SENSOR_MODE_STANDBY,
+   INV_ICM42600_SENSOR_MODE_LOW_POWER,
+   INV_ICM42600_SENSOR_MODE_LOW_NOISE,
+   INV_ICM42600_SENSOR_MODE_NB,
+};
+
+/* gyroscope fullscale values */
+enum inv_icm42600_gyro_fs {
+   INV_ICM42600_GYRO_FS_2000DPS,
+   INV_ICM42600_GYRO_FS_1000DPS,
+   INV_ICM42600_GYRO_FS_500DPS,
+   INV_ICM42600_GYRO_FS_250DPS,
+   INV_ICM42600_GYRO_FS_125DPS,
+   INV_ICM42600_GYRO_FS_62_5DPS,
+   INV_ICM42600_GYRO_FS_31_25DPS,
+   INV_ICM42600_GYRO_FS_15_625DPS,
+   INV_ICM42600_GYRO_FS_NB,
+};
+
+/* accelerometer fullscale values */
+enum inv_icm42600_accel_fs {
+   INV_ICM42600_ACCEL_FS_16G,
+   INV_ICM42600_ACCEL_FS_8G,
+   INV_ICM42600_ACCEL_FS_4G,
+   INV_ICM42600_ACCEL_FS_2G,
+   INV_ICM42600_ACCEL_FS_NB,
+};
+
+/* ODR suffixed by LN or LP are Low-Noise or Low-Power mode only */
+enum inv_icm42600_odr {
+   INV_ICM42600_ODR_8KHZ_LN = 3,
+   INV_ICM42600_ODR_4KHZ_LN,
+   INV_ICM42600_ODR_2KHZ_LN,
+   INV_ICM42600_ODR_1KHZ_LN,
+   INV_ICM42600_ODR_200HZ,
+   INV_ICM42600_ODR_100HZ,
+   INV_ICM42600_ODR_50HZ,
+   INV_ICM42600_ODR_25HZ,
+   INV_ICM42600_ODR_12_5HZ,
+   INV_ICM42600_ODR_6_25HZ_LP,
+   INV_ICM42600_ODR_3_125HZ_LP,
+   INV_ICM42600_ODR_1_5625HZ_LP,
+   INV_ICM42600_ODR_500HZ,
+   INV_ICM42600_ODR_NB,
+};
+
+enum inv_icm42600_filter {
+   /* Low-Noise mode sensor data filter (3rd order filter by default) */
+   INV_ICM42600_FILTER_BW_ODR_DIV_2,
+
+   /* Low-Power mode sensor data filter (averaging) */
+   INV_ICM42600_FILTER_AVG_1X = 1,
+   INV_ICM42600_FILTER_AVG_16X = 6,
+};
+
+struct inv_icm42600_sensor_conf {
+   int mode;
+   int fs;
+   int odr;
+   int filter;
+};
+#define INV_ICM42600_SENSOR_CONF_INIT  {-1, -1, -1, -1}
+
+struct inv_icm42600_conf {
+   struct inv_icm42600_sensor_conf gyro;
+   struct inv_icm42600_sensor_conf accel;
+   bool temp_en;
+};
+
+struct inv_icm42600_suspended {
+   enum inv_icm42600_sensor_mode gyro;
+   enum inv_icm42600_sensor_mode accel;
+   bool temp;
+};
+
+/**
+ *  struct inv_icm42600_state - driver state variables
+ *  @lock: lock for serializing multiple registers access.
+ *  @chip: chip identifier.
+ *  @name: chip name.
+ *  @map:  regmap pointer.
+ *  @vdd_supply:   VDD voltage regulator for the chip.
+ *  @vddio_supply: I/O voltage regulator for the chip.
+ *  @orientation:  sensor chip orientation relative to main hardware.
+ *  @conf: chip sensors configurations.
+ *  @suspended:suspended sensors configuration.
+ */
+struct inv_icm42600_state {
+   struct mutex lock;
+   enum inv_icm42600_chip chip;
+   const char *name;
+   struct regmap *map;
+   struct regulator *vdd_supply;
+   struct regulator *vddio_supply;
+   struct iio_mount_matrix orientation;
+   struct inv_icm42600_conf conf;
+   struct inv_icm42600_suspended suspended;
+};
+
+/* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
+
+/* Bank selection register, available in all banks */
+#define

[PATCH v2 08/12] iio: imu: inv_icm42600: add device interrupt

2020-05-27 Thread Jean-Baptiste Maneyrol
Add INT1 interrupt support. Support interrupt edge and level,
active high or low. Push-pull or open-drain configurations.

Interrupt will be used to read data from the FIFO.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |  2 +-
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  | 96 ++-
 .../iio/imu/inv_icm42600/inv_icm42600_i2c.c   |  3 +-
 .../iio/imu/inv_icm42600/inv_icm42600_spi.c   |  3 +-
 4 files changed, 100 insertions(+), 4 deletions(-)

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index c534acae0308..43749f56426c 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -372,7 +372,7 @@ int inv_icm42600_set_temp_conf(struct inv_icm42600_state 
*st, bool enable,
 int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg,
 unsigned int writeval, unsigned int *readval);
 
-int inv_icm42600_core_probe(struct regmap *regmap, int chip,
+int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
inv_icm42600_bus_setup bus_setup);
 
 int inv_icm42600_gyro_init(struct inv_icm42600_state *st);
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
index e7f7835aca9b..246c1eb52231 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
@@ -9,8 +9,11 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -409,6 +412,79 @@ static int inv_icm42600_setup(struct inv_icm42600_state 
*st,
return inv_icm42600_set_conf(st, hw->conf);
 }
 
+static irqreturn_t inv_icm42600_irq_handler(int irq, void *_data)
+{
+   struct inv_icm42600_state *st = _data;
+   struct device *dev = regmap_get_device(st->map);
+   unsigned int status;
+   int ret;
+
+   mutex_lock(>lock);
+
+   ret = regmap_read(st->map, INV_ICM42600_REG_INT_STATUS, );
+   if (ret)
+   goto out_unlock;
+
+   /* FIFO full */
+   if (status & INV_ICM42600_INT_STATUS_FIFO_FULL)
+   dev_warn(dev, "FIFO full data lost!\n");
+
+out_unlock:
+   mutex_unlock(>lock);
+   return IRQ_HANDLED;
+}
+
+/**
+ * inv_icm42600_irq_init() - initialize int pin and interrupt handler
+ * @st:driver internal state
+ * @irq:   irq number
+ * @irq_type:  irq trigger type
+ * @open_drain:true if irq is open drain, false for push-pull
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ */
+static int inv_icm42600_irq_init(struct inv_icm42600_state *st, int irq,
+int irq_type, bool open_drain)
+{
+   struct device *dev = regmap_get_device(st->map);
+   unsigned int val;
+   int ret;
+
+   /* configure INT1 interrupt: default is active low on edge */
+   switch (irq_type) {
+   case IRQF_TRIGGER_RISING:
+   case IRQF_TRIGGER_HIGH:
+   val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_HIGH;
+   break;
+   default:
+   val = INV_ICM42600_INT_CONFIG_INT1_ACTIVE_LOW;
+   break;
+   }
+   switch (irq_type) {
+   case IRQF_TRIGGER_LOW:
+   case IRQF_TRIGGER_HIGH:
+   val |= INV_ICM42600_INT_CONFIG_INT1_LATCHED;
+   break;
+   default:
+   break;
+   }
+   if (!open_drain)
+   val |= INV_ICM42600_INT_CONFIG_INT1_PUSH_PULL;
+   ret = regmap_write(st->map, INV_ICM42600_REG_INT_CONFIG, val);
+   if (ret)
+   return ret;
+
+   /* Deassert async reset for proper INT pin operation (cf datasheet) */
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INT_CONFIG1,
+INV_ICM42600_INT_CONFIG1_ASYNC_RESET, 0);
+   if (ret)
+   return ret;
+
+   return devm_request_threaded_irq(dev, irq, NULL,
+inv_icm42600_irq_handler, irq_type,
+"inv_icm42600", st);
+}
+
 static int inv_icm42600_enable_regulator_vddio(struct inv_icm42600_state *st)
 {
int ret;
@@ -453,11 +529,14 @@ static void inv_icm42600_disable_pm(void *_data)
pm_runtime_disable(dev);
 }
 
-int inv_icm42600_core_probe(struct regmap *regmap, int chip,
+int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
inv_icm42600_bus_setup bus_setup)
 {
struct device *dev = regmap_get_device(regmap);
struct inv_icm42600_state *st;
+   struct irq_data *irq_desc;
+   int irq_type;
+   bool open_drain;
int ret;
 
if (chip < 0 || chip >= INV_CHIP_NB) {
@@ -465,6 +544,17 @@ int inv_icm42600_core_probe(struct reg

[PATCH v2 07/12] iio: imu: add Kconfig and Makefile for inv_icm42600 driver

2020-05-27 Thread Jean-Baptiste Maneyrol
Add 3 modules: inv-icm42600, inv-icm42600-i2c, inv-icm42600-spi.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/Kconfig   |  1 +
 drivers/iio/imu/Makefile  |  1 +
 drivers/iio/imu/inv_icm42600/Kconfig  | 28 +++
 drivers/iio/imu/inv_icm42600/Makefile | 13 +
 4 files changed, 43 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/Kconfig
 create mode 100644 drivers/iio/imu/inv_icm42600/Makefile

diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index fc4123d518bc..f02883b08480 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -91,6 +91,7 @@ config KMX61
  To compile this driver as module, choose M here: the module will
  be called kmx61.
 
+source "drivers/iio/imu/inv_icm42600/Kconfig"
 source "drivers/iio/imu/inv_mpu6050/Kconfig"
 source "drivers/iio/imu/st_lsm6dsx/Kconfig"
 
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index 88b2c4555230..13e9ff442b11 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_FXOS8700) += fxos8700_core.o
 obj-$(CONFIG_FXOS8700_I2C) += fxos8700_i2c.o
 obj-$(CONFIG_FXOS8700_SPI) += fxos8700_spi.o
 
+obj-y += inv_icm42600/
 obj-y += inv_mpu6050/
 
 obj-$(CONFIG_KMX61) += kmx61.o
diff --git a/drivers/iio/imu/inv_icm42600/Kconfig 
b/drivers/iio/imu/inv_icm42600/Kconfig
new file mode 100644
index ..22390a72f0a3
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/Kconfig
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+config INV_ICM42600
+   tristate
+
+config INV_ICM42600_I2C
+   tristate "InvenSense ICM-426xx I2C driver"
+   depends on I2C
+   select INV_ICM42600
+   select REGMAP_I2C
+   help
+ This driver supports the InvenSense ICM-426xx motion tracking
+ devices over I2C.
+
+ This driver can be built as a module. The module will be called
+ inv-icm42600-i2c.
+
+config INV_ICM42600_SPI
+   tristate "InvenSense ICM-426xx SPI driver"
+   depends on SPI_MASTER
+   select INV_ICM42600
+   select REGMAP_SPI
+   help
+ This driver supports the InvenSense ICM-426xx motion tracking
+ devices over SPI.
+
+ This driver can be built as a module. The module will be called
+ inv-icm42600-spi.
diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
b/drivers/iio/imu/inv_icm42600/Makefile
new file mode 100644
index ..48965824f00c
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/Makefile
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+obj-$(CONFIG_INV_ICM42600) += inv-icm42600.o
+inv-icm42600-y += inv_icm42600_core.o
+inv-icm42600-y += inv_icm42600_gyro.o
+inv-icm42600-y += inv_icm42600_accel.o
+inv-icm42600-y += inv_icm42600_temp.o
+
+obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o
+inv-icm42600-i2c-y += inv_icm42600_i2c.o
+
+obj-$(CONFIG_INV_ICM42600_SPI) += inv-icm42600-spi.o
+inv-icm42600-spi-y += inv_icm42600_spi.o
-- 
2.17.1



[PATCH v2 04/12] iio: imu: inv_icm42600: add gyroscope IIO device

2020-05-27 Thread Jean-Baptiste Maneyrol
Add IIO device for gyroscope sensor with data polling interface.
Attributes: raw, scale, sampling_frequency, calibbias.

Gyroscope in low noise mode.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   6 +
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |   4 +
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 600 ++
 3 files changed, 610 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index 14c8ef152418..c1023d59b37b 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -120,6 +120,8 @@ struct inv_icm42600_suspended {
  *  @orientation:  sensor chip orientation relative to main hardware.
  *  @conf: chip sensors configurations.
  *  @suspended:suspended sensors configuration.
+ *  @indio_gyro:   gyroscope IIO device.
+ *  @buffer:   data transfer buffer aligned for DMA.
  */
 struct inv_icm42600_state {
struct mutex lock;
@@ -131,6 +133,8 @@ struct inv_icm42600_state {
struct iio_mount_matrix orientation;
struct inv_icm42600_conf conf;
struct inv_icm42600_suspended suspended;
+   struct iio_dev *indio_gyro;
+   uint8_t buffer[2] cacheline_aligned;
 };
 
 /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
@@ -369,4 +373,6 @@ int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, 
unsigned int reg,
 int inv_icm42600_core_probe(struct regmap *regmap, int chip,
inv_icm42600_bus_setup bus_setup);
 
+int inv_icm42600_gyro_init(struct inv_icm42600_state *st);
+
 #endif
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
index 81b171d6782c..dccb7bcc782e 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
@@ -510,6 +510,10 @@ int inv_icm42600_core_probe(struct regmap *regmap, int 
chip,
if (ret)
return ret;
 
+   ret = inv_icm42600_gyro_init(st);
+   if (ret)
+   return ret;
+
/* setup runtime power management */
ret = pm_runtime_set_active(dev);
if (ret)
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
new file mode 100644
index ..9d9672989b23
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
@@ -0,0 +1,600 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+
+#define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info)   \
+   {   \
+   .type = IIO_ANGL_VEL,   \
+   .modified = 1,  \
+   .channel2 = _modifier,  \
+   .info_mask_separate =   \
+   BIT(IIO_CHAN_INFO_RAW) |\
+   BIT(IIO_CHAN_INFO_CALIBBIAS),   \
+   .info_mask_shared_by_type = \
+   BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_type_available =   \
+   BIT(IIO_CHAN_INFO_SCALE) |  \
+   BIT(IIO_CHAN_INFO_CALIBBIAS),   \
+   .info_mask_shared_by_all =  \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   .info_mask_shared_by_all_available =\
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   .scan_index = _index,   \
+   .scan_type = {  \
+   .sign = 's',\
+   .realbits = 16, \
+   .storagebits = 16,  \
+   .endianness = IIO_BE,   \
+   },  \
+   .ext_info = _ext_info,  \
+   }
+
+enum inv_icm42600_gyro_scan {
+   INV_ICM42600_GYRO_SCAN_X,
+   INV_ICM42600_GYRO_SCAN_Y,
+   INV_ICM42600_GYRO_SCAN_Z,
+};
+
+static const struct iio_chan_spec_ext_info inv_icm42600_gyro_ext_infos[] = {
+   IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42600_get_mo

[PATCH v2 00/12] iio: imu: new inv_icm42600 driver

2020-05-27 Thread Jean-Baptiste Maneyrol
Changelog
v1
  -initial patch submission
v2
  - formatting reworks, missing headers, code cleanup ...
  - delete all debug traces
  - add commentaries for better explanation of suspend/resume, timestamp, ...
  - delete i2c/spi table ids keeping only of, and use I2C probe_new function
  - switch calibbias to SI units and add calibias_available attribute
  - use DMA-safe buffer for all regmap_bulk_* calls
  - delete iio trigger usage and setup/handle interrupt in core module
  - add open-drain interrupt support
  - add FIFO on reference counter and buffer postenable/predisable to replace
iio trigger usage
  - check that temperature data is present before copying in buffer
  - add temperature sensor off when fifo is turned off
  - delete timestamp channel reading
  - move timestamp state in IIO device private data
  - allow only 1 ODR change in a batch of data
  - add driver-open-drain in devicetree YAML and delete spi options

This series add a new driver for managing InvenSense ICM-426xx 6-axis IMUs.
This next generation of chips includes new generations of 3-axis gyroscope
and 3-axis accelerometer, support of I3C in addition to I2C and SPI, and
intelligent MotionTracking features like pedometer, tilt detection, and
tap detection.

This series is delivering a driver supporting gyroscope, accelerometer and
temperature data, with polling and buffering using hwfifo and watermark,
on I2C and SPI busses.

Gyroscope and accelerometer sensors are completely independent and can have
different ODRs. Since there is only a single FIFO a specific value is used to
mark invalid data. For keeping the device standard we are de-multiplexing data
from the FIFO to 2 IIO devices with 2 buffers, 1 for the accelerometer and 1
for the gyroscope. This architecture also enables to easily turn each sensor
on/off without impacting the other. The device interrupt is used to read the
FIFO and launch parsing of accelerometer and gyroscope data. A complex
timestamping mechanism is added to handle correctly FIFO watermark and dynamic
changes of settings.

Jean-Baptiste Maneyrol (12):
  iio: imu: inv_icm42600: add core of new inv_icm42600 driver
  iio: imu: inv_icm42600: add I2C driver for inv_icm42600 driver
  iio: imu: inv_icm42600: add SPI driver for inv_icm42600 driver
  iio: imu: inv_icm42600: add gyroscope IIO device
  iio: imu: inv_icm42600: add accelerometer IIO device
  iio: imu: inv_icm42600: add temperature sensor support
  iio: imu: add Kconfig and Makefile for inv_icm42600 driver
  iio: imu: inv_icm42600: add device interrupt
  iio: imu: inv_icm42600: add buffer support in iio devices
  iio: imu: inv_icm42600: add accurate timestamping
  dt-bindings: iio: imu: Add inv_icm42600 documentation
  MAINTAINERS: add entry for inv_icm42600 6-axis imu sensor

 .../bindings/iio/imu/invensense,icm42600.yaml |  86 ++
 MAINTAINERS   |   8 +
 drivers/iio/imu/Kconfig   |   1 +
 drivers/iio/imu/Makefile  |   1 +
 drivers/iio/imu/inv_icm42600/Kconfig  |  29 +
 drivers/iio/imu/inv_icm42600/Makefile |  15 +
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   | 395 +
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 784 +
 .../imu/inv_icm42600/inv_icm42600_buffer.c| 583 +
 .../imu/inv_icm42600/inv_icm42600_buffer.h|  98 +++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  | 782 +
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 795 ++
 .../iio/imu/inv_icm42600/inv_icm42600_i2c.c   | 101 +++
 .../iio/imu/inv_icm42600/inv_icm42600_spi.c   | 100 +++
 .../iio/imu/inv_icm42600/inv_icm42600_temp.c  |  87 ++
 .../iio/imu/inv_icm42600/inv_icm42600_temp.h  |  30 +
 .../imu/inv_icm42600/inv_icm42600_timestamp.c | 195 +
 .../imu/inv_icm42600/inv_icm42600_timestamp.h |  85 ++
 18 files changed, 4175 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
 create mode 100644 drivers/iio/imu/inv_icm42600/Kconfig
 create mode 100644 drivers/iio/imu/inv_icm42600/Makefile
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600.h
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h

-- 
2.17.1



[PATCH v2 10/12] iio: imu: inv_icm42600: add accurate timestamping

2020-05-27 Thread Jean-Baptiste Maneyrol
Add a timestamping mechanism for buffer that provides accurate
event timestamps when using watermark. This mechanism estimates
device internal clock by comparing FIFO interrupts delta time and
device elapsed time computed by parsing FIFO data.

Take interrupt timestamp in hard irq handler and add IIO device
specific timestamp structures in device private allocation.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/Makefile |   1 +
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   5 +
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c |  40 +++-
 .../imu/inv_icm42600/inv_icm42600_buffer.c|  28 +++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |  17 +-
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  |  40 +++-
 .../imu/inv_icm42600/inv_icm42600_timestamp.c | 195 ++
 .../imu/inv_icm42600/inv_icm42600_timestamp.h |  85 
 8 files changed, 398 insertions(+), 13 deletions(-)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h

diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
b/drivers/iio/imu/inv_icm42600/Makefile
index 0f49f6df3647..291714d9aa54 100644
--- a/drivers/iio/imu/inv_icm42600/Makefile
+++ b/drivers/iio/imu/inv_icm42600/Makefile
@@ -6,6 +6,7 @@ inv-icm42600-y += inv_icm42600_gyro.o
 inv-icm42600-y += inv_icm42600_accel.o
 inv-icm42600-y += inv_icm42600_temp.o
 inv-icm42600-y += inv_icm42600_buffer.o
+inv-icm42600-y += inv_icm42600_timestamp.o
 
 obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o
 inv-icm42600-i2c-y += inv_icm42600_i2c.o
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index 4d5811562a61..2de0dd7675fb 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -126,6 +126,7 @@ struct inv_icm42600_suspended {
  *  @indio_accel:  accelerometer IIO device.
  *  @buffer:   data transfer buffer aligned for DMA.
  *  @fifo: FIFO management structure.
+ *  @timestamp:interrupt timestamps.
  */
 struct inv_icm42600_state {
struct mutex lock;
@@ -141,6 +142,10 @@ struct inv_icm42600_state {
struct iio_dev *indio_accel;
uint8_t buffer[2] cacheline_aligned;
struct inv_icm42600_fifo fifo;
+   struct {
+   int64_t gyro;
+   int64_t accel;
+   } timestamp;
 };
 
 /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index c73ce204efc6..ec1d124c1471 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -17,6 +17,7 @@
 #include "inv_icm42600.h"
 #include "inv_icm42600_temp.h"
 #include "inv_icm42600_buffer.h"
+#include "inv_icm42600_timestamp.h"
 
 #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)  \
{   \
@@ -50,6 +51,7 @@ enum inv_icm42600_accel_scan {
INV_ICM42600_ACCEL_SCAN_Y,
INV_ICM42600_ACCEL_SCAN_Z,
INV_ICM42600_ACCEL_SCAN_TEMP,
+   INV_ICM42600_ACCEL_SCAN_TIMESTAMP,
 };
 
 static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
@@ -65,13 +67,15 @@ static const struct iio_chan_spec 
inv_icm42600_accel_channels[] = {
INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z,
inv_icm42600_accel_ext_infos),
INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP),
+   IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42600_ACCEL_SCAN_TIMESTAMP),
 };
 
-/* IIO buffer data: 8 bytes */
+/* IIO buffer data: 16 bytes */
 struct inv_icm42600_accel_buffer {
struct inv_icm42600_fifo_sensor_data accel;
int8_t temp;
uint8_t padding;
+   int64_t timestamp;
 };
 
 #define INV_ICM42600_SCAN_MASK_ACCEL_3AXIS \
@@ -92,6 +96,7 @@ static int inv_icm42600_accel_update_scan_mode(struct iio_dev 
*indio_dev,
   const unsigned long *scan_mask)
 {
struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+   struct inv_icm42600_timestamp *ts = iio_priv(indio_dev);
struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
unsigned int fifo_en = 0;
unsigned int sleep_temp = 0;
@@ -119,6 +124,7 @@ static int inv_icm42600_accel_update_scan_mode(struct 
iio_dev *indio_dev,
}
 
/* update data FIFO write */
+   inv_icm42600_timestamp_apply_odr(ts, 0, 0, 0);
ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en);
if (ret)
goto out_unlock;
@@ -299,9 +305,11 @@ static int inv_icm42600_accel_read_odr(struct 
inv_icm42600_state

[PATCH v2 02/12] iio: imu: inv_icm42600: add I2C driver for inv_icm42600 driver

2020-05-27 Thread Jean-Baptiste Maneyrol
Add I2C driver for InvenSense ICM-426xxx devices.

Configure bus signal slew rates as indicated in the datasheet.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../iio/imu/inv_icm42600/inv_icm42600_i2c.c   | 100 ++
 1 file changed, 100 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
new file mode 100644
index ..4789cead23b3
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 InvenSense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+
+static int inv_icm42600_i2c_bus_setup(struct inv_icm42600_state *st)
+{
+   unsigned int mask, val;
+   int ret;
+
+   /* setup interface registers */
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6,
+INV_ICM42600_INTF_CONFIG6_MASK,
+INV_ICM42600_INTF_CONFIG6_I3C_EN);
+   if (ret)
+   return ret;
+
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4,
+INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY, 0);
+   if (ret)
+   return ret;
+
+   /* set slew rates for I2C and SPI */
+   mask = INV_ICM42600_DRIVE_CONFIG_I2C_MASK |
+  INV_ICM42600_DRIVE_CONFIG_SPI_MASK;
+   val = INV_ICM42600_DRIVE_CONFIG_I2C(INV_ICM42600_SLEW_RATE_12_36NS) |
+ INV_ICM42600_DRIVE_CONFIG_SPI(INV_ICM42600_SLEW_RATE_12_36NS);
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_DRIVE_CONFIG,
+mask, val);
+   if (ret)
+   return ret;
+
+   /* disable SPI bus */
+   return regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,
+ INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK,
+ 
INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS);
+}
+
+static int inv_icm42600_probe(struct i2c_client *client)
+{
+   const void *match;
+   enum inv_icm42600_chip chip;
+   struct regmap *regmap;
+
+   if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
+   return -ENOTSUPP;
+
+   match = device_get_match_data(>dev);
+   if (!match)
+   return -EINVAL;
+   chip = (enum inv_icm42600_chip)match;
+
+   regmap = devm_regmap_init_i2c(client, _icm42600_regmap_config);
+   if (IS_ERR(regmap))
+   return PTR_ERR(regmap);
+
+   return inv_icm42600_core_probe(regmap, chip, 
inv_icm42600_i2c_bus_setup);
+}
+
+static const struct of_device_id inv_icm42600_of_matches[] = {
+   {
+   .compatible = "invensense,icm42600",
+   .data = (void *)INV_CHIP_ICM42600,
+   }, {
+   .compatible = "invensense,icm42602",
+   .data = (void *)INV_CHIP_ICM42602,
+   }, {
+   .compatible = "invensense,icm42605",
+   .data = (void *)INV_CHIP_ICM42605,
+   }, {
+   .compatible = "invensense,icm42622",
+   .data = (void *)INV_CHIP_ICM42622,
+   },
+   {}
+};
+MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches);
+
+static struct i2c_driver inv_icm42600_driver = {
+   .driver = {
+   .name = "inv-icm42600-i2c",
+   .of_match_table = inv_icm42600_of_matches,
+   .pm = _icm42600_pm_ops,
+   },
+   .probe_new = inv_icm42600_probe,
+};
+module_i2c_driver(inv_icm42600_driver);
+
+MODULE_AUTHOR("InvenSense, Inc.");
+MODULE_DESCRIPTION("InvenSense ICM-426xx I2C driver");
+MODULE_LICENSE("GPL");
-- 
2.17.1



[PATCH v2 05/12] iio: imu: inv_icm42600: add accelerometer IIO device

2020-05-27 Thread Jean-Baptiste Maneyrol
Add IIO device for accelerometer sensor with data polling
interface.
Attributes: raw, scale, sampling_frequency, calibbias.

Accelerometer in low noise mode.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   4 +
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 589 ++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |   4 +
 3 files changed, 597 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index c1023d59b37b..c534acae0308 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -121,6 +121,7 @@ struct inv_icm42600_suspended {
  *  @conf: chip sensors configurations.
  *  @suspended:suspended sensors configuration.
  *  @indio_gyro:   gyroscope IIO device.
+ *  @indio_accel:  accelerometer IIO device.
  *  @buffer:   data transfer buffer aligned for DMA.
  */
 struct inv_icm42600_state {
@@ -134,6 +135,7 @@ struct inv_icm42600_state {
struct inv_icm42600_conf conf;
struct inv_icm42600_suspended suspended;
struct iio_dev *indio_gyro;
+   struct iio_dev *indio_accel;
uint8_t buffer[2] cacheline_aligned;
 };
 
@@ -375,4 +377,6 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip,
 
 int inv_icm42600_gyro_init(struct inv_icm42600_state *st);
 
+int inv_icm42600_accel_init(struct inv_icm42600_state *st);
+
 #endif
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
new file mode 100644
index ..7620ce1958e0
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -0,0 +1,589 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+
+#define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)  \
+   {   \
+   .type = IIO_ACCEL,  \
+   .modified = 1,  \
+   .channel2 = _modifier,  \
+   .info_mask_separate =   \
+   BIT(IIO_CHAN_INFO_RAW) |\
+   BIT(IIO_CHAN_INFO_CALIBBIAS),   \
+   .info_mask_shared_by_type = \
+   BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_type_available =   \
+   BIT(IIO_CHAN_INFO_SCALE) |  \
+   BIT(IIO_CHAN_INFO_CALIBBIAS),   \
+   .info_mask_shared_by_all =  \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   .info_mask_shared_by_all_available =\
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   .scan_index = _index,   \
+   .scan_type = {  \
+   .sign = 's',\
+   .realbits = 16, \
+   .storagebits = 16,  \
+   .endianness = IIO_BE,   \
+   },  \
+   .ext_info = _ext_info,  \
+   }
+
+enum inv_icm42600_accel_scan {
+   INV_ICM42600_ACCEL_SCAN_X,
+   INV_ICM42600_ACCEL_SCAN_Y,
+   INV_ICM42600_ACCEL_SCAN_Z,
+};
+
+static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
+   IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42600_get_mount_matrix),
+   {},
+};
+
+static const struct iio_chan_spec inv_icm42600_accel_channels[] = {
+   INV_ICM42600_ACCEL_CHAN(IIO_MOD_X, INV_ICM42600_ACCEL_SCAN_X,
+   inv_icm42600_accel_ext_infos),
+   INV_ICM42600_ACCEL_CHAN(IIO_MOD_Y, INV_ICM42600_ACCEL_SCAN_Y,
+   inv_icm42600_accel_ext_infos),
+   INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z,
+   inv_icm42600_accel_ext_infos),
+};
+
+static int inv_icm42600_accel_read_sensor(struct inv_icm42600_state *st,
+ struct iio_chan_spec const *chan,
+ int16_t *val)
+{
+   struct device *dev = regmap_get_device(st->map);
+

[PATCH v2 06/12] iio: imu: inv_icm42600: add temperature sensor support

2020-05-27 Thread Jean-Baptiste Maneyrol
Add temperature channel in gyroscope and accelerometer devices.

Temperature is available in full 16 bits resolution as a processed
channel. Scale and offset attributes are also provided for the low
8 bits resolution raw temperature found in the FIFO.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 11 ++-
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 11 ++-
 .../iio/imu/inv_icm42600/inv_icm42600_temp.c  | 87 +++
 .../iio/imu/inv_icm42600/inv_icm42600_temp.h  | 30 +++
 4 files changed, 137 insertions(+), 2 deletions(-)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index 7620ce1958e0..6a615d7ffb24 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -13,6 +13,7 @@
 #include 
 
 #include "inv_icm42600.h"
+#include "inv_icm42600_temp.h"
 
 #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)  \
{   \
@@ -45,6 +46,7 @@ enum inv_icm42600_accel_scan {
INV_ICM42600_ACCEL_SCAN_X,
INV_ICM42600_ACCEL_SCAN_Y,
INV_ICM42600_ACCEL_SCAN_Z,
+   INV_ICM42600_ACCEL_SCAN_TEMP,
 };
 
 static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
@@ -59,6 +61,7 @@ static const struct iio_chan_spec 
inv_icm42600_accel_channels[] = {
inv_icm42600_accel_ext_infos),
INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z,
inv_icm42600_accel_ext_infos),
+   INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP),
 };
 
 static int inv_icm42600_accel_read_sensor(struct inv_icm42600_state *st,
@@ -450,8 +453,14 @@ static int inv_icm42600_accel_read_raw(struct iio_dev 
*indio_dev,
int16_t data;
int ret;
 
-   if (chan->type != IIO_ACCEL)
+   switch (chan->type) {
+   case IIO_ACCEL:
+   break;
+   case IIO_TEMP:
+   return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, 
mask);
+   default:
return -EINVAL;
+   }
 
switch (mask) {
case IIO_CHAN_INFO_RAW:
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
index 9d9672989b23..38654e0d217b 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
@@ -13,6 +13,7 @@
 #include 
 
 #include "inv_icm42600.h"
+#include "inv_icm42600_temp.h"
 
 #define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info)   \
{   \
@@ -45,6 +46,7 @@ enum inv_icm42600_gyro_scan {
INV_ICM42600_GYRO_SCAN_X,
INV_ICM42600_GYRO_SCAN_Y,
INV_ICM42600_GYRO_SCAN_Z,
+   INV_ICM42600_GYRO_SCAN_TEMP,
 };
 
 static const struct iio_chan_spec_ext_info inv_icm42600_gyro_ext_infos[] = {
@@ -59,6 +61,7 @@ static const struct iio_chan_spec 
inv_icm42600_gyro_channels[] = {
   inv_icm42600_gyro_ext_infos),
INV_ICM42600_GYRO_CHAN(IIO_MOD_Z, INV_ICM42600_GYRO_SCAN_Z,
   inv_icm42600_gyro_ext_infos),
+   INV_ICM42600_TEMP_CHAN(INV_ICM42600_GYRO_SCAN_TEMP),
 };
 
 static int inv_icm42600_gyro_read_sensor(struct inv_icm42600_state *st,
@@ -461,8 +464,14 @@ static int inv_icm42600_gyro_read_raw(struct iio_dev 
*indio_dev,
int16_t data;
int ret;
 
-   if (chan->type != IIO_ANGL_VEL)
+   switch (chan->type) {
+   case IIO_ANGL_VEL:
+   break;
+   case IIO_TEMP:
+   return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, 
mask);
+   default:
return -EINVAL;
+   }
 
switch (mask) {
case IIO_CHAN_INFO_RAW:
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
new file mode 100644
index ..b0871352fe39
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+#include "inv_icm42600_temp.h"
+
+static int inv_icm42600_temp_read(struct inv_icm42600_state *st, int32_t *temp)
+{
+   struct device *dev = regmap_get_device(st->map);
+   int64_t data;
+   __be16 *raw;
+   int16_t val;
+   int ret;
+
+   pm_runtime_get_sync(dev);
+   mutex_lock(>lock);
+
+   ret = inv_icm42600_set_temp_conf(st, true, NULL);
+

Re: [PATCH 10/12] iio: imu: inv_icm42600: add accurate timestamping

2020-05-18 Thread Jean-Baptiste Maneyrol
Hi Jonathan,

reading timestamp register is here mainly because we can do it, and this is the 
only way to have the full 20 bits resolution.
But it is not very useful indeed. I will delete it.

I am not using timestamp stored inside the FIFO, because it is only present 
when having both accel and gyro on. There is no timestamp data for a single 
sensor, which is really too bad. That would have been helpful.

I will add more documentation about it. It is not that tricky, but need more 
deep explanations.

New series V2 is in preparation. And again my apologizes for ruining the mail 
text formatting.

Thanks,
JB


From: Jonathan Cameron 

Sent: Friday, May 8, 2020 16:42

To: Jean-Baptiste Maneyrol 

Cc: ji...@kernel.org ; robh...@kernel.org 
; r...@kernel.org ; 
mchehab+hua...@kernel.org ; da...@davemloft.net 
; gre...@linuxfoundation.org ;
 linux-...@vger.kernel.org ; 
devicet...@vger.kernel.org ; 
linux-kernel@vger.kernel.org 

Subject: Re: [PATCH 10/12] iio: imu: inv_icm42600: add accurate timestamping

 


 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.



On Thu, 7 May 2020 16:42:20 +0200

Jean-Baptiste Maneyrol  wrote:



> Add a timestamp channel with processed value that returns full

> precision 20 bits timestamp.

> 

> Add a timestamping mechanism for buffer that provides accurate

> event timestamps when using watermark. This mechanism estimates

> device internal clock by comparing FIFO interrupts delta time and

> corresponding device elapsed time computed by parsing FIFO data.



Yikes. That is complex.  Hmm. I always get lost in the maths in these

timestamp patches so my review may be a little superficial.



However a bit more in the way of docs would be good here.



The sysfs read of timestamp is unusual and I'm not really sure what it is for.

The delays in a sysfs read of that value are likely to be enough that it's

that useful for anything.



Also, do we make use of the timestamps within the fifo records?



J





> 

> Signed-off-by: Jean-Baptiste Maneyrol 

> ---

>  drivers/iio/imu/inv_icm42600/Makefile |   1 +

>  drivers/iio/imu/inv_icm42600/inv_icm42600.h   |  10 +-

>  .../iio/imu/inv_icm42600/inv_icm42600_accel.c |  32 ++-

>  .../imu/inv_icm42600/inv_icm42600_buffer.c    |  28 +-

>  .../iio/imu/inv_icm42600/inv_icm42600_core.c  |   6 +

>  .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  |  32 ++-

>  .../imu/inv_icm42600/inv_icm42600_timestamp.c | 246 ++

>  .../imu/inv_icm42600/inv_icm42600_timestamp.h |  82 ++

>  8 files changed, 421 insertions(+), 16 deletions(-)

>  create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c

>  create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h

> 

> diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
> b/drivers/iio/imu/inv_icm42600/Makefile

> index d6732118010c..1197b545a682 100644

> --- a/drivers/iio/imu/inv_icm42600/Makefile

> +++ b/drivers/iio/imu/inv_icm42600/Makefile

> @@ -7,6 +7,7 @@ inv-icm42600-y += inv_icm42600_accel.o

>  inv-icm42600-y += inv_icm42600_temp.o

>  inv-icm42600-y += inv_icm42600_trigger.o

>  inv-icm42600-y += inv_icm42600_buffer.o

> +inv-icm42600-y += inv_icm42600_timestamp.o

>  

>  obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o

>  inv-icm42600-i2c-y += inv_icm42600_i2c.o

> diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
> b/drivers/iio/imu/inv_icm42600/inv_icm42600.h

> index 947ca4dd245b..e15eddafe009 100644

> --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h

> +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h

> @@ -16,6 +16,7 @@

>  #include 

>  

>  #include "inv_icm42600_buffer.h"

> +#include "inv_icm42600_timestamp.h"

>  

>  enum inv_icm42600_chip {

>    INV_CHIP_ICM42600,

> @@ -127,6 +128,7 @@ struct inv_icm42600_suspended {

>   *  @indio_accel:    accelerometer IIO device.

>   *  @trigger:    device internal interrupt trigger

>   *  @fifo:   FIFO management structure.

> + *  @timestamp:  timestamp management structure.

>   */

>  struct inv_icm42600_state {

>    struct mutex lock;

> @@ -142,6 +144,10 @@ struct inv_icm42600_state {

>    struct iio_dev *indio_accel;

>    struct iio_trigger *trigger;

>    struct inv_icm42600_fifo fifo;

> + struct {

> + struct inv_icm42600_timestamp gyro;

> + struct inv_icm42600_timestamp accel;

> + } timestamp;

>  };

>  

>  /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB 
>*/

> @@ -382,11 +388,11 @@ int inv_icm42600_core_probe(struct regmap *regm

Re: [PATCH 08/12] iio: imu: inv_icm42600: add device interrupt trigger

2020-05-18 Thread Jean-Baptiste Maneyrol
Hi Jonathan,

you're right, making a trigger is not very useful.

I will move this code to the buffer file or rename the file, and replace the 
triggered buffer setup in iio devices.

Thanks,
JB


From: Jonathan Cameron 

Sent: Friday, May 8, 2020 16:22

To: Jean-Baptiste Maneyrol 

Cc: ji...@kernel.org ; robh...@kernel.org 
; r...@kernel.org ; 
mchehab+hua...@kernel.org ; da...@davemloft.net 
; gre...@linuxfoundation.org ;
 linux-...@vger.kernel.org ; 
devicet...@vger.kernel.org ; 
linux-kernel@vger.kernel.org 

Subject: Re: [PATCH 08/12] iio: imu: inv_icm42600: add device interrupt trigger

 


 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.



On Thu, 7 May 2020 16:42:18 +0200

Jean-Baptiste Maneyrol  wrote:



> Add INT1 interrupt support and use it as an iio trigger.

> Support interrupt edge and level, active high or low.

> Push-pull configuration only.

> 

> Trigger enables FIFO and will be useful with buffer support.

> 

> Signed-off-by: Jean-Baptiste Maneyrol 



So it's an odd trigger... But you check its only used for the

device itself which stops that being visible to anyone.



The open question in my mind is why we need a trigger at all?

If there is no advantage we don't need to expose that.  Can just

directly call the buffer functions from the interrupt handler.



It's perfectly acceptable to not have a trigger exposed if:

* It would only be useful for the device providing it.

* You don't need to use it to select between various options.



For some of the other fifo devices IIRC we do support other

triggers but if you don't provide one the local fifo is used.



Here I don't think we actually support other triggers though we

don't prevent them being used? So even simpler.

With the complex interleaved fifo I suspect it would be hard

to support other triggers anyway except in a trivial poll like

mode so probably not of interest to anyone...



J 



> ---

>  drivers/iio/imu/inv_icm42600/Kconfig  |   1 +

>  drivers/iio/imu/inv_icm42600/Makefile |   1 +

>  drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   8 +-

>  .../iio/imu/inv_icm42600/inv_icm42600_core.c  |  19 +-

>  .../iio/imu/inv_icm42600/inv_icm42600_i2c.c   |   2 +-

>  .../iio/imu/inv_icm42600/inv_icm42600_spi.c   |   2 +-

>  .../imu/inv_icm42600/inv_icm42600_trigger.c   | 177 ++

>  7 files changed, 206 insertions(+), 4 deletions(-)

>  create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_trigger.c

> 

> diff --git a/drivers/iio/imu/inv_icm42600/Kconfig 
> b/drivers/iio/imu/inv_icm42600/Kconfig

> index 22390a72f0a3..7b3eaeb2aa4a 100644

> --- a/drivers/iio/imu/inv_icm42600/Kconfig

> +++ b/drivers/iio/imu/inv_icm42600/Kconfig

> @@ -2,6 +2,7 @@

>  

>  config INV_ICM42600

>    tristate

> + select IIO_TRIGGER

>  

>  config INV_ICM42600_I2C

>    tristate "InvenSense ICM-426xx I2C driver"

> diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
> b/drivers/iio/imu/inv_icm42600/Makefile

> index 48965824f00c..e1f2aacbe888 100644

> --- a/drivers/iio/imu/inv_icm42600/Makefile

> +++ b/drivers/iio/imu/inv_icm42600/Makefile

> @@ -5,6 +5,7 @@ inv-icm42600-y += inv_icm42600_core.o

>  inv-icm42600-y += inv_icm42600_gyro.o

>  inv-icm42600-y += inv_icm42600_accel.o

>  inv-icm42600-y += inv_icm42600_temp.o

> +inv-icm42600-y += inv_icm42600_trigger.o

>  

>  obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o

>  inv-icm42600-i2c-y += inv_icm42600_i2c.o

> diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
> b/drivers/iio/imu/inv_icm42600/inv_icm42600.h

> index bc963b3d1800..175c1f67faee 100644

> --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h

> +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h

> @@ -13,6 +13,7 @@

>  #include 

>  #include 

>  #include 

> +#include 

>  

>  enum inv_icm42600_chip {

>    INV_CHIP_ICM42600,

> @@ -122,6 +123,7 @@ struct inv_icm42600_suspended {

>   *  @suspended:  suspended sensors configuration.

>   *  @indio_gyro: gyroscope IIO device.

>   *  @indio_accel:    accelerometer IIO device.

> + *  @trigger:    device internal interrupt trigger

>   */

>  struct inv_icm42600_state {

>    struct mutex lock;

> @@ -135,6 +137,7 @@ struct inv_icm42600_state {

>    struct inv_icm42600_suspended suspended;

>    struct iio_dev *indio_gyro;

>    struct iio_dev *indio_accel;

> + struct iio_trigger *trigger;

>  };

>  

>  /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB 
>*/

> @@ -370,11 +373,14 @@ int inv_icm42600_set_temp_conf(stru

Re: [PATCH 04/12] iio: imu: inv_icm42600: add gyroscope IIO device

2020-05-18 Thread Jean-Baptiste Maneyrol
Hi Jonathan,

I agree with all comments.

For regmap_bulk_read, by looking at source code it doesn't seem to requires 
specific alignment, except if bus read callback is expecting that. But I can 
see numerous drivers calling regmap_bulk_read with a data buffer on the stack 
and not particularly aligned.

And we definitely can read calibration offset registers while running, the lock 
is indeed not needed.

Thanks,
JB



From: Jonathan Cameron 

Sent: Friday, May 8, 2020 16:01

To: Jean-Baptiste Maneyrol 

Cc: ji...@kernel.org ; robh...@kernel.org 
; r...@kernel.org ; 
mchehab+hua...@kernel.org ; da...@davemloft.net 
; gre...@linuxfoundation.org ;
 linux-...@vger.kernel.org ; 
devicet...@vger.kernel.org ; 
linux-kernel@vger.kernel.org 

Subject: Re: [PATCH 04/12] iio: imu: inv_icm42600: add gyroscope IIO device

 


 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.



On Thu, 7 May 2020 16:42:14 +0200

Jean-Baptiste Maneyrol  wrote:



> Add IIO device for gyroscope sensor with data polling interface.

> Attributes: raw, scale, sampling_frequency, calibbias.

> 

> Gyroscope in low noise mode.

> 

> Signed-off-by: Jean-Baptiste Maneyrol 

Few trivial things and questions inline.



J



> ---

>  drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   4 +

>  .../iio/imu/inv_icm42600/inv_icm42600_core.c  |   5 +

>  .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 549 ++

>  3 files changed, 558 insertions(+)

>  create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c

> 

> diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
> b/drivers/iio/imu/inv_icm42600/inv_icm42600.h

> index 8da4c8249aed..ca41a9d6404a 100644

> --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h

> +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h

> @@ -120,6 +120,7 @@ struct inv_icm42600_suspended {

>   *  @orientation:    sensor chip orientation relative to main hardware.

>   *  @conf:   chip sensors configurations.

>   *  @suspended:  suspended sensors configuration.

> + *  @indio_gyro: gyroscope IIO device.

>   */

>  struct inv_icm42600_state {

>    struct mutex lock;

> @@ -131,6 +132,7 @@ struct inv_icm42600_state {

>    struct iio_mount_matrix orientation;

>    struct inv_icm42600_conf conf;

>    struct inv_icm42600_suspended suspended;

> + struct iio_dev *indio_gyro;

>  };

>  

>  /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB 
>*/

> @@ -369,4 +371,6 @@ int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, 
> unsigned int reg,

>  int inv_icm42600_core_probe(struct regmap *regmap, int chip,

>    inv_icm42600_bus_setup bus_setup);

>  

> +int inv_icm42600_gyro_init(struct inv_icm42600_state *st);

> +

>  #endif

> diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c 
> b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c

> index 35bdf4f9d31e..151257652ce6 100644

> --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c

> +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c

> @@ -503,6 +503,11 @@ int inv_icm42600_core_probe(struct regmap *regmap, int 
> chip,

>    if (ret)

>    return ret;

>  

> + /* create and init gyroscope iio device */



'Kind' of obvious from function name?   Maybe drop the comment?



> + ret = inv_icm42600_gyro_init(st);

> + if (ret)

> + return ret;

> +

>    /* setup runtime power management */

>    ret = pm_runtime_set_active(dev);

>    if (ret)

> diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c 
> b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c

> new file mode 100644

> index ..74aa2b5fa611

> --- /dev/null

> +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c

> @@ -0,0 +1,549 @@

> +// SPDX-License-Identifier: GPL-2.0-or-later

> +/*

> + * Copyright (C) 2020 Invensense, Inc.

> + */

> +

> +#include 

> +#include 

> +#include 

> +#include 

> +#include 

> +#include 

> +#include 

> +

> +#include "inv_icm42600.h"

> +

> +#define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info) \

> + {   \

> + .type = IIO_ANGL_VEL,   \

> + .modified = 1,  \

> + .channel2 = _modifier,  \

> + .info_mask_separate = 

Re: [PATCH 09/12] iio: imu: inv_icm42600: add buffer support in iio devices

2020-05-18 Thread Jean-Baptiste Maneyrol
Hi Jonathan,

no problem with the comments.

fifo_decode_packet will move to source code, 

For the following sleep comment:
> + if (sleep_gyro > sleep_temp)
> + sleep = sleep_gyro;
> + else
> + sleep = sleep_temp;
> + if (sleep)
> + msleep(sleep);

    if (sleep_gyro > sleep_temp)
    msleep(sleep_gyro);
    else
msleep(sleep_temp);

I am using an intermediate local variable to avoid a call to msleep(0) which is 
in fact sleeping for real for 1 jiffies as far as I understand. So is it OK to 
keep it as is?

Thanks,
JB



From: Jonathan Cameron 

Sent: Friday, May 8, 2020 16:19

To: Jean-Baptiste Maneyrol 

Cc: ji...@kernel.org ; robh...@kernel.org 
; r...@kernel.org ; 
mchehab+hua...@kernel.org ; da...@davemloft.net 
; gre...@linuxfoundation.org ;
 linux-...@vger.kernel.org ; 
devicet...@vger.kernel.org ; 
linux-kernel@vger.kernel.org 

Subject: Re: [PATCH 09/12] iio: imu: inv_icm42600: add buffer support in iio 
devices

 


 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.



On Thu, 7 May 2020 16:42:19 +0200

Jean-Baptiste Maneyrol  wrote:



> Use triggered buffer by parsing FIFO data read in device trigger.

> Support hwfifo watermark by multiplexing gyro and accel settings.

> Support hwfifo flush.

> 

> Simply use interrupt timestamp first.

> 

> Signed-off-by: Jean-Baptiste Maneyrol 

> ---

>  drivers/iio/imu/inv_icm42600/Kconfig  |   3 +-

>  drivers/iio/imu/inv_icm42600/Makefile |   1 +

>  drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   8 +

>  .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 183 +

>  .../imu/inv_icm42600/inv_icm42600_buffer.c    | 353 ++

>  .../imu/inv_icm42600/inv_icm42600_buffer.h    | 162 

>  .../iio/imu/inv_icm42600/inv_icm42600_core.c  |  23 ++

>  .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 183 +

>  .../imu/inv_icm42600/inv_icm42600_trigger.c   |  15 +-

>  9 files changed, 928 insertions(+), 3 deletions(-)

>  create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c

>  create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h

> 

> diff --git a/drivers/iio/imu/inv_icm42600/Kconfig 
> b/drivers/iio/imu/inv_icm42600/Kconfig

> index 7b3eaeb2aa4a..8c0969319c49 100644

> --- a/drivers/iio/imu/inv_icm42600/Kconfig

> +++ b/drivers/iio/imu/inv_icm42600/Kconfig

> @@ -2,7 +2,8 @@

>  

>  config INV_ICM42600

>    tristate

> - select IIO_TRIGGER

> + select IIO_BUFFER

> + select IIO_TRIGGERED_BUFFER

>  

>  config INV_ICM42600_I2C

>    tristate "InvenSense ICM-426xx I2C driver"

> diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
> b/drivers/iio/imu/inv_icm42600/Makefile

> index e1f2aacbe888..d6732118010c 100644

> --- a/drivers/iio/imu/inv_icm42600/Makefile

> +++ b/drivers/iio/imu/inv_icm42600/Makefile

> @@ -6,6 +6,7 @@ inv-icm42600-y += inv_icm42600_gyro.o

>  inv-icm42600-y += inv_icm42600_accel.o

>  inv-icm42600-y += inv_icm42600_temp.o

>  inv-icm42600-y += inv_icm42600_trigger.o

> +inv-icm42600-y += inv_icm42600_buffer.o

>  

>  obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o

>  inv-icm42600-i2c-y += inv_icm42600_i2c.o

> diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
> b/drivers/iio/imu/inv_icm42600/inv_icm42600.h

> index 175c1f67faee..947ca4dd245b 100644

> --- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h

> +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h

> @@ -15,6 +15,8 @@

>  #include 

>  #include 

>  

> +#include "inv_icm42600_buffer.h"

> +

>  enum inv_icm42600_chip {

>    INV_CHIP_ICM42600,

>    INV_CHIP_ICM42602,

> @@ -124,6 +126,7 @@ struct inv_icm42600_suspended {

>   *  @indio_gyro: gyroscope IIO device.

>   *  @indio_accel:    accelerometer IIO device.

>   *  @trigger:    device internal interrupt trigger

> + *  @fifo:   FIFO management structure.

>   */

>  struct inv_icm42600_state {

>    struct mutex lock;

> @@ -138,6 +141,7 @@ struct inv_icm42600_state {

>    struct iio_dev *indio_gyro;

>    struct iio_dev *indio_accel;

>    struct iio_trigger *trigger;

> + struct inv_icm42600_fifo fifo;

>  };

>  

>  /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB 
>*/

> @@ -378,8 +382,12 @@ int inv_icm42600_core_probe(struct regmap *regmap, int 
> chip, int irq,

>  

>  int inv_icm42600_gyro_init(struct inv_icm42600_state *st);

>  

> +

Re: [PATCH 02/12] iio: imu: inv_icm42600: add I2C driver for inv_icm42600 driver

2020-05-18 Thread Jean-Baptiste Maneyrol
Hi Jonathan,

I am using generic device_get_match_data because I was thinking it was now the 
way to go. But since only of is supported with the driver, I can switch to 
using of_device_get_match_data instead.

Tell me what do you think is better.

I could definitely use the new probe interface indeed, good idea.

Thanks,
JB



From: Jonathan Cameron 

Sent: Friday, May 8, 2020 15:44

To: Jean-Baptiste Maneyrol 

Cc: ji...@kernel.org ; robh...@kernel.org 
; r...@kernel.org ; 
mchehab+hua...@kernel.org ; da...@davemloft.net 
; gre...@linuxfoundation.org ;
 linux-...@vger.kernel.org ; 
devicet...@vger.kernel.org ; 
linux-kernel@vger.kernel.org 

Subject: Re: [PATCH 02/12] iio: imu: inv_icm42600: add I2C driver for 
inv_icm42600 driver

 


 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.



On Thu, 7 May 2020 16:42:12 +0200

Jean-Baptiste Maneyrol  wrote:



> Add I2C driver for InvenSense ICM-426xxx devices.

> 

> Configure bus signal slew rates as indicated in the datasheet.

> 

> Signed-off-by: Jean-Baptiste Maneyrol 

Some incoherent rambling inline. + a few comments



Jonathan



> ---

>  .../iio/imu/inv_icm42600/inv_icm42600_i2c.c   | 117 ++

>  1 file changed, 117 insertions(+)

>  create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c

> 

> diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c 
> b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c

> new file mode 100644

> index ..b61f993beacf

> --- /dev/null

> +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c

> @@ -0,0 +1,117 @@

> +// SPDX-License-Identifier: GPL-2.0-or-later

> +/*

> + * Copyright (C) 2020 InvenSense, Inc.

> + */

> +

> +#include 

> +#include 

> +#include 

> +#include 

> +#include 



Why?  Looks like you need the table and the device property stuff neither

of which are in that file.



linux/mod_devicetable.h

linux/property.h





> +

> +#include "inv_icm42600.h"

> +

> +static int inv_icm42600_i2c_bus_setup(struct inv_icm42600_state *st)

> +{

> + unsigned int mask, val;

> + int ret;

> +

> + /* setup interface registers */

> + mask = INV_ICM42600_INTF_CONFIG6_MASK;

> + val = INV_ICM42600_INTF_CONFIG6_I3C_EN;

> + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6,

> +  mask, val);



I'd put the values inline where they are simple like these rather than

using local variables.



> + if (ret)

> + return ret;

> +

> + mask = INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY;

> + val = 0;

> + ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4,

> +  mask, val);

> + if (ret)

> + return ret;

> +

> + /* set slew rates for I2C and SPI */

> + mask = INV_ICM42600_DRIVE_CONFIG_I2C_MASK |

> +    INV_ICM42600_DRIVE_CONFIG_SPI_MASK;

> + val = INV_ICM42600_DRIVE_CONFIG_I2C(INV_ICM42600_SLEW_RATE_12_36NS) |

> +   INV_ICM42600_DRIVE_CONFIG_SPI(INV_ICM42600_SLEW_RATE_12_36NS);

> + ret = regmap_update_bits(st->map, INV_ICM42600_REG_DRIVE_CONFIG,

> +  mask, val);

> + if (ret)

> + return ret;

> +

> + /* disable SPI bus */

> + mask = INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK;

> + val = INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS;

> + return regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,

> +   mask, val);

> +}

> +

> +static int inv_icm42600_probe(struct i2c_client *client,

> +   const struct i2c_device_id *id)

> +{

> + const void *match;

> + enum inv_icm42600_chip chip;

> + struct regmap *regmap;

> +

> + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))

> + return -ENOTSUPP;

> +

> + match = device_get_match_data(>dev);



Hmm. Annoyingly if one were to call the of specific option

of i2c_of_match_device it would handle the old style i2c match just fine without

needing special handling.  However, it would fail to handle PRP0001 ACPI.



Rather feels like there should be something similar for

device_get_match_data so we could use the probe_new version of i2c device

probing.



Oh well. I guess thats a separate question for another day ;)



Mind you can we actually probe this driver via the sysfs route?

If not why do we need to handle the non firmware case at all?

 

> + if (match)

> + chip = (enum inv_icm42600_chip)match;

> +

Re: [PATCH 01/12] iio: imu: inv_icm42600: add core of new inv_icm42600 driver

2020-05-18 Thread Jean-Baptiste Maneyrol
Hi Jonathan,

thanks for the feedbacks, I'm sorry but I will not be able to have a correct 
email formatting to respond you inline.

No problem with all the comments. For iio_device_get_drvdata, it would make 
more sense to use a const struct iio_dev * as argument. I am obliged to do the 
pointer conversion since iio_get_mount_matrix requires the use of a const 
struct iio_dev *.

For resume/suspend, I will add commentaries to explain what it is really doing 
and for which purpose. Sensor states save and restore will remain in this 
patch, since it makes more sense to have it as a core functionnality, as much 
as gyro/accel turn on/off.

Thanks.
JB


From: linux-iio-ow...@vger.kernel.org  on 
behalf of Jonathan Cameron 

Sent: Friday, May 8, 2020 15:28

To: Jean-Baptiste Maneyrol 

Cc: ji...@kernel.org ; robh...@kernel.org 
; r...@kernel.org ; 
mchehab+hua...@kernel.org ; da...@davemloft.net 
; gre...@linuxfoundation.org ;
 linux-...@vger.kernel.org ; 
devicet...@vger.kernel.org ; 
linux-kernel@vger.kernel.org 

Subject: Re: [PATCH 01/12] iio: imu: inv_icm42600: add core of new inv_icm42600 
driver

 


 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.



On Thu, 7 May 2020 16:42:11 +0200

Jean-Baptiste Maneyrol  wrote:



> Core component of a new driver for InvenSense ICM-426xx devices.

> It includes registers definition, main probe/setup, and device

> utility functions.

> 

> ICM-426xx devices are latest generation of 6-axis IMU,

> gyroscope+accelerometer and temperature sensor. This device

> includes a 2K FIFO, supports I2C/I3C/SPI, and provides

> intelligent motion features like pedometer, tilt detection,

> and tap detection.

> 

> Signed-off-by: Jean-Baptiste Maneyrol 



Hi Jean-Baptiste,



A few minor things inline.



Thanks,



Jonathan



> ---

>  drivers/iio/imu/inv_icm42600/inv_icm42600.h   | 372 +++

>  .../iio/imu/inv_icm42600/inv_icm42600_core.c  | 618 ++

>  2 files changed, 990 insertions(+)

>  create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600.h

>  create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_core.c

> 

> diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
> b/drivers/iio/imu/inv_icm42600/inv_icm42600.h

> new file mode 100644

> index ..8da4c8249aed

> --- /dev/null

> +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h

> @@ -0,0 +1,372 @@

> +/* SPDX-License-Identifier: GPL-2.0-or-later */

> +/*

> + * Copyright (C) 2020 Invensense, Inc.

> + */

> +

> +#ifndef INV_ICM42600_H_

> +#define INV_ICM42600_H_

> +

> +#include 

> +#include 

> +#include 

> +#include 

> +#include 

> +#include 

> +#include 

> +

> +enum inv_icm42600_chip {

> + INV_CHIP_ICM42600,

> + INV_CHIP_ICM42602,

> + INV_CHIP_ICM42605,

> + INV_CHIP_ICM42622,

> + INV_CHIP_NB,

> +};

> +

> +/* serial bus slew rates */

> +enum inv_icm42600_slew_rate {

> + INV_ICM42600_SLEW_RATE_20_60NS,

> + INV_ICM42600_SLEW_RATE_12_36NS,

> + INV_ICM42600_SLEW_RATE_6_18NS,

> + INV_ICM42600_SLEW_RATE_4_12NS,

> + INV_ICM42600_SLEW_RATE_2_6NS,

> + INV_ICM42600_SLEW_RATE_INF_2NS,

> +};

> +

> +enum inv_icm42600_sensor_mode {

> + INV_ICM42600_SENSOR_MODE_OFF,

> + INV_ICM42600_SENSOR_MODE_STANDBY,

> + INV_ICM42600_SENSOR_MODE_LOW_POWER,

> + INV_ICM42600_SENSOR_MODE_LOW_NOISE,

> + INV_ICM42600_SENSOR_MODE_NB,

> +};

> +

> +/* gyroscope fullscale values */

> +enum inv_icm42600_gyro_fs {

> + INV_ICM42600_GYRO_FS_2000DPS,

> + INV_ICM42600_GYRO_FS_1000DPS,

> + INV_ICM42600_GYRO_FS_500DPS,

> + INV_ICM42600_GYRO_FS_250DPS,

> + INV_ICM42600_GYRO_FS_125DPS,

> + INV_ICM42600_GYRO_FS_62_5DPS,

> + INV_ICM42600_GYRO_FS_31_25DPS,

> + INV_ICM42600_GYRO_FS_15_625DPS,

> + INV_ICM42600_GYRO_FS_NB,

> +};

> +

> +/* accelerometer fullscale values */

> +enum inv_icm42600_accel_fs {

> + INV_ICM42600_ACCEL_FS_16G,

> + INV_ICM42600_ACCEL_FS_8G,

> + INV_ICM42600_ACCEL_FS_4G,

> + INV_ICM42600_ACCEL_FS_2G,

> + INV_ICM42600_ACCEL_FS_NB,

> +};

> +

> +/* ODR suffixed by LN or LP are Low-Noise or Low-Power mode only */

> +enum inv_icm42600_odr {

> + INV_ICM42600_ODR_8KHZ_LN = 3,

> + INV_ICM42600_ODR_4KHZ_LN,

> + INV_ICM42600_ODR_2KHZ_LN,

> + INV_ICM42600_ODR_1KHZ_LN,

> + INV_ICM42600_ODR_200HZ,

> + INV_ICM42600_ODR_100HZ,

> + INV_ICM42600_ODR_50HZ,

> + INV_ICM42600_ODR_25HZ,

> + INV_ICM42600_ODR_12

[PATCH 03/12] iio: imu: inv_icm42600: add SPI driver for inv_icm42600 driver

2020-05-07 Thread Jean-Baptiste Maneyrol
Add SPI driver for InvenSense ICM-426xxx devices.

Configure bus signal slew rates as indicated in the datasheet.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../iio/imu/inv_icm42600/inv_icm42600_spi.c   | 117 ++
 1 file changed, 117 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
new file mode 100644
index ..835ced68a3a3
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 InvenSense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+
+static int inv_icm42600_spi_bus_setup(struct inv_icm42600_state *st)
+{
+   unsigned int mask, val;
+   int ret;
+
+   /* setup interface registers */
+   mask = INV_ICM42600_INTF_CONFIG6_MASK;
+   val = INV_ICM42600_INTF_CONFIG6_I3C_EN |
+ INV_ICM42600_INTF_CONFIG6_I3C_SDR_EN |
+ INV_ICM42600_INTF_CONFIG6_I3C_DDR_EN;
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6,
+mask, val);
+   if (ret)
+   return ret;
+
+   mask = INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY;
+   val = 0;
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4,
+mask, val);
+   if (ret)
+   return ret;
+
+   /* set slew rates for I2C and SPI */
+   mask = INV_ICM42600_DRIVE_CONFIG_I2C_MASK |
+  INV_ICM42600_DRIVE_CONFIG_SPI_MASK;
+   val = INV_ICM42600_DRIVE_CONFIG_I2C(INV_ICM42600_SLEW_RATE_20_60NS) |
+ INV_ICM42600_DRIVE_CONFIG_SPI(INV_ICM42600_SLEW_RATE_INF_2NS);
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_DRIVE_CONFIG,
+mask, val);
+   if (ret)
+   return ret;
+
+   /* disable i2c bus */
+   mask = INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK;
+   val = INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS;
+   return regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,
+ mask, val);
+}
+
+static int inv_icm42600_probe(struct spi_device *spi)
+{
+   const void *match;
+   const struct spi_device_id *spi_id;
+   enum inv_icm42600_chip chip;
+   struct regmap *regmap;
+
+   match = device_get_match_data(>dev);
+   spi_id = spi_get_device_id(spi);
+   if (match)
+   chip = (enum inv_icm42600_chip)match;
+   else if (spi_id)
+   chip = (enum inv_icm42600_chip)spi_id->driver_data;
+   else
+   return -EINVAL;
+
+   regmap = devm_regmap_init_spi(spi, _icm42600_regmap_config);
+   if (IS_ERR(regmap))
+   return PTR_ERR(regmap);
+
+   return inv_icm42600_core_probe(regmap, chip,
+  inv_icm42600_spi_bus_setup);
+}
+
+static const struct of_device_id inv_icm42600_of_matches[] = {
+   {
+   .compatible = "invensense,icm42600",
+   .data = (void *)INV_CHIP_ICM42600,
+   }, {
+   .compatible = "invensense,icm42602",
+   .data = (void *)INV_CHIP_ICM42602,
+   }, {
+   .compatible = "invensense,icm42605",
+   .data = (void *)INV_CHIP_ICM42605,
+   }, {
+   .compatible = "invensense,icm42622",
+   .data = (void *)INV_CHIP_ICM42622,
+   },
+   {}
+};
+MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches);
+
+static const struct spi_device_id inv_icm42600_ids[] = {
+   {"icm42600", INV_CHIP_ICM42600},
+   {"icm42602", INV_CHIP_ICM42602},
+   {"icm42605", INV_CHIP_ICM42605},
+   {"icm42622", INV_CHIP_ICM42622},
+   {}
+};
+MODULE_DEVICE_TABLE(spi, inv_icm42600_ids);
+
+static struct spi_driver inv_icm42600_driver = {
+   .probe = inv_icm42600_probe,
+   .id_table = inv_icm42600_ids,
+   .driver = {
+   .of_match_table = inv_icm42600_of_matches,
+   .name = "inv-icm42600-spi",
+   .pm = _icm42600_pm_ops,
+   },
+};
+module_spi_driver(inv_icm42600_driver);
+
+MODULE_AUTHOR("InvenSense, Inc.");
+MODULE_DESCRIPTION("InvenSense ICM-426xx SPI driver");
+MODULE_LICENSE("GPL");
-- 
2.17.1



[PATCH 05/12] iio: imu: inv_icm42600: add accelerometer IIO device

2020-05-07 Thread Jean-Baptiste Maneyrol
Add IIO device for accelerometer sensor with data polling
interface.
Attributes: raw, scale, sampling_frequency, calibbias.

Accelerometer in low noise mode.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   4 +
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 537 ++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |   5 +
 3 files changed, 546 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index ca41a9d6404a..bc963b3d1800 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -121,6 +121,7 @@ struct inv_icm42600_suspended {
  *  @conf: chip sensors configurations.
  *  @suspended:suspended sensors configuration.
  *  @indio_gyro:   gyroscope IIO device.
+ *  @indio_accel:  accelerometer IIO device.
  */
 struct inv_icm42600_state {
struct mutex lock;
@@ -133,6 +134,7 @@ struct inv_icm42600_state {
struct inv_icm42600_conf conf;
struct inv_icm42600_suspended suspended;
struct iio_dev *indio_gyro;
+   struct iio_dev *indio_accel;
 };
 
 /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
@@ -373,4 +375,6 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip,
 
 int inv_icm42600_gyro_init(struct inv_icm42600_state *st);
 
+int inv_icm42600_accel_init(struct inv_icm42600_state *st);
+
 #endif
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
new file mode 100644
index ..397e3d0fd42b
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -0,0 +1,537 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+
+#define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)  \
+   {   \
+   .type = IIO_ACCEL,  \
+   .modified = 1,  \
+   .channel2 = _modifier,  \
+   .info_mask_separate =   \
+   BIT(IIO_CHAN_INFO_RAW) |\
+   BIT(IIO_CHAN_INFO_CALIBBIAS),   \
+   .info_mask_shared_by_type = \
+   BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_type_available =   \
+   BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_all =  \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   .info_mask_shared_by_all_available =\
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   .scan_index = _index,   \
+   .scan_type = {  \
+   .sign = 's',\
+   .realbits = 16, \
+   .storagebits = 16,  \
+   .shift = 0, \
+   .endianness = IIO_BE,   \
+   },  \
+   .ext_info = _ext_info,  \
+   }
+
+enum inv_icm42600_accel_scan {
+   INV_ICM42600_ACCEL_SCAN_X,
+   INV_ICM42600_ACCEL_SCAN_Y,
+   INV_ICM42600_ACCEL_SCAN_Z,
+};
+
+static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
+   IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42600_get_mount_matrix),
+   {},
+};
+
+static const struct iio_chan_spec inv_icm42600_accel_channels[] = {
+   INV_ICM42600_ACCEL_CHAN(IIO_MOD_X, INV_ICM42600_ACCEL_SCAN_X,
+   inv_icm42600_accel_ext_infos),
+   INV_ICM42600_ACCEL_CHAN(IIO_MOD_Y, INV_ICM42600_ACCEL_SCAN_Y,
+   inv_icm42600_accel_ext_infos),
+   INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z,
+   inv_icm42600_accel_ext_infos),
+};
+
+static int inv_icm42600_accel_read_sensor(struct inv_icm42600_state *st,
+ struct iio_chan_spec const *chan,
+ int16_t *val)
+{
+   struct device *dev = regmap_get_device(st->map);
+   struct inv_icm42600_sen

[PATCH 09/12] iio: imu: inv_icm42600: add buffer support in iio devices

2020-05-07 Thread Jean-Baptiste Maneyrol
Use triggered buffer by parsing FIFO data read in device trigger.
Support hwfifo watermark by multiplexing gyro and accel settings.
Support hwfifo flush.

Simply use interrupt timestamp first.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/Kconfig  |   3 +-
 drivers/iio/imu/inv_icm42600/Makefile |   1 +
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   8 +
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 183 +
 .../imu/inv_icm42600/inv_icm42600_buffer.c| 353 ++
 .../imu/inv_icm42600/inv_icm42600_buffer.h| 162 
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |  23 ++
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 183 +
 .../imu/inv_icm42600/inv_icm42600_trigger.c   |  15 +-
 9 files changed, 928 insertions(+), 3 deletions(-)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h

diff --git a/drivers/iio/imu/inv_icm42600/Kconfig 
b/drivers/iio/imu/inv_icm42600/Kconfig
index 7b3eaeb2aa4a..8c0969319c49 100644
--- a/drivers/iio/imu/inv_icm42600/Kconfig
+++ b/drivers/iio/imu/inv_icm42600/Kconfig
@@ -2,7 +2,8 @@
 
 config INV_ICM42600
tristate
-   select IIO_TRIGGER
+   select IIO_BUFFER
+   select IIO_TRIGGERED_BUFFER
 
 config INV_ICM42600_I2C
tristate "InvenSense ICM-426xx I2C driver"
diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
b/drivers/iio/imu/inv_icm42600/Makefile
index e1f2aacbe888..d6732118010c 100644
--- a/drivers/iio/imu/inv_icm42600/Makefile
+++ b/drivers/iio/imu/inv_icm42600/Makefile
@@ -6,6 +6,7 @@ inv-icm42600-y += inv_icm42600_gyro.o
 inv-icm42600-y += inv_icm42600_accel.o
 inv-icm42600-y += inv_icm42600_temp.o
 inv-icm42600-y += inv_icm42600_trigger.o
+inv-icm42600-y += inv_icm42600_buffer.o
 
 obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o
 inv-icm42600-i2c-y += inv_icm42600_i2c.o
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index 175c1f67faee..947ca4dd245b 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -15,6 +15,8 @@
 #include 
 #include 
 
+#include "inv_icm42600_buffer.h"
+
 enum inv_icm42600_chip {
INV_CHIP_ICM42600,
INV_CHIP_ICM42602,
@@ -124,6 +126,7 @@ struct inv_icm42600_suspended {
  *  @indio_gyro:   gyroscope IIO device.
  *  @indio_accel:  accelerometer IIO device.
  *  @trigger:  device internal interrupt trigger
+ *  @fifo: FIFO management structure.
  */
 struct inv_icm42600_state {
struct mutex lock;
@@ -138,6 +141,7 @@ struct inv_icm42600_state {
struct iio_dev *indio_gyro;
struct iio_dev *indio_accel;
struct iio_trigger *trigger;
+   struct inv_icm42600_fifo fifo;
 };
 
 /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
@@ -378,8 +382,12 @@ int inv_icm42600_core_probe(struct regmap *regmap, int 
chip, int irq,
 
 int inv_icm42600_gyro_init(struct inv_icm42600_state *st);
 
+int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev, int64_t ts);
+
 int inv_icm42600_accel_init(struct inv_icm42600_state *st);
 
+int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev, int64_t ts);
+
 int inv_icm42600_trigger_init(struct inv_icm42600_state *st, int irq,
  int irq_type);
 
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index 74dac5f283d4..4206be54d057 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -10,9 +10,13 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
 
 #include "inv_icm42600.h"
 #include "inv_icm42600_temp.h"
+#include "inv_icm42600_buffer.h"
 
 #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)  \
{   \
@@ -46,6 +50,7 @@ enum inv_icm42600_accel_scan {
INV_ICM42600_ACCEL_SCAN_Y,
INV_ICM42600_ACCEL_SCAN_Z,
INV_ICM42600_ACCEL_SCAN_TEMP,
+   INV_ICM42600_ACCEL_SCAN_TIMESTAMP,
 };
 
 static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
@@ -61,8 +66,100 @@ static const struct iio_chan_spec 
inv_icm42600_accel_channels[] = {
INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z,
inv_icm42600_accel_ext_infos),
INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP),
+   IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42600_ACCEL_SCAN_TIMESTAMP),
 };
 
+/* IIO buffer data */
+struct inv_icm42600_accel_buffer {
+   struct inv_icm42600_fifo_sensor_data accel;
+   int8_t temp;
+   int64_t timestamp;
+};
+
+#define INV_ICM42600_SCAN_MASK_ACCEL_3AXIS   

[PATCH 08/12] iio: imu: inv_icm42600: add device interrupt trigger

2020-05-07 Thread Jean-Baptiste Maneyrol
Add INT1 interrupt support and use it as an iio trigger.
Support interrupt edge and level, active high or low.
Push-pull configuration only.

Trigger enables FIFO and will be useful with buffer support.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/Kconfig  |   1 +
 drivers/iio/imu/inv_icm42600/Makefile |   1 +
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   8 +-
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |  19 +-
 .../iio/imu/inv_icm42600/inv_icm42600_i2c.c   |   2 +-
 .../iio/imu/inv_icm42600/inv_icm42600_spi.c   |   2 +-
 .../imu/inv_icm42600/inv_icm42600_trigger.c   | 177 ++
 7 files changed, 206 insertions(+), 4 deletions(-)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_trigger.c

diff --git a/drivers/iio/imu/inv_icm42600/Kconfig 
b/drivers/iio/imu/inv_icm42600/Kconfig
index 22390a72f0a3..7b3eaeb2aa4a 100644
--- a/drivers/iio/imu/inv_icm42600/Kconfig
+++ b/drivers/iio/imu/inv_icm42600/Kconfig
@@ -2,6 +2,7 @@
 
 config INV_ICM42600
tristate
+   select IIO_TRIGGER
 
 config INV_ICM42600_I2C
tristate "InvenSense ICM-426xx I2C driver"
diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
b/drivers/iio/imu/inv_icm42600/Makefile
index 48965824f00c..e1f2aacbe888 100644
--- a/drivers/iio/imu/inv_icm42600/Makefile
+++ b/drivers/iio/imu/inv_icm42600/Makefile
@@ -5,6 +5,7 @@ inv-icm42600-y += inv_icm42600_core.o
 inv-icm42600-y += inv_icm42600_gyro.o
 inv-icm42600-y += inv_icm42600_accel.o
 inv-icm42600-y += inv_icm42600_temp.o
+inv-icm42600-y += inv_icm42600_trigger.o
 
 obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o
 inv-icm42600-i2c-y += inv_icm42600_i2c.o
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index bc963b3d1800..175c1f67faee 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 enum inv_icm42600_chip {
INV_CHIP_ICM42600,
@@ -122,6 +123,7 @@ struct inv_icm42600_suspended {
  *  @suspended:suspended sensors configuration.
  *  @indio_gyro:   gyroscope IIO device.
  *  @indio_accel:  accelerometer IIO device.
+ *  @trigger:  device internal interrupt trigger
  */
 struct inv_icm42600_state {
struct mutex lock;
@@ -135,6 +137,7 @@ struct inv_icm42600_state {
struct inv_icm42600_suspended suspended;
struct iio_dev *indio_gyro;
struct iio_dev *indio_accel;
+   struct iio_trigger *trigger;
 };
 
 /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
@@ -370,11 +373,14 @@ int inv_icm42600_set_temp_conf(struct inv_icm42600_state 
*st, bool enable,
 int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, unsigned int reg,
 unsigned int writeval, unsigned int *readval);
 
-int inv_icm42600_core_probe(struct regmap *regmap, int chip,
+int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
inv_icm42600_bus_setup bus_setup);
 
 int inv_icm42600_gyro_init(struct inv_icm42600_state *st);
 
 int inv_icm42600_accel_init(struct inv_icm42600_state *st);
 
+int inv_icm42600_trigger_init(struct inv_icm42600_state *st, int irq,
+ int irq_type);
+
 #endif
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
index 4e33f263d3ea..1102c54396e3 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
@@ -447,11 +447,13 @@ static void inv_icm42600_disable_pm(void *_data)
pm_runtime_disable(dev);
 }
 
-int inv_icm42600_core_probe(struct regmap *regmap, int chip,
+int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
inv_icm42600_bus_setup bus_setup)
 {
struct device *dev = regmap_get_device(regmap);
struct inv_icm42600_state *st;
+   struct irq_data *irq_desc;
+   int irq_type;
int ret;
 
BUILD_BUG_ON(ARRAY_SIZE(inv_icm42600_hw) != INV_CHIP_NB);
@@ -460,6 +462,16 @@ int inv_icm42600_core_probe(struct regmap *regmap, int 
chip,
return -ENODEV;
}
 
+   /* get irq data, set trigger falling by default */
+   irq_desc = irq_get_irq_data(irq);
+   if (!irq_desc) {
+   dev_err(dev, "could not find IRQ %d\n", irq);
+   return -EINVAL;
+   }
+   irq_type = irqd_get_trigger_type(irq_desc);
+   if (!irq_type)
+   irq_type = IRQF_TRIGGER_FALLING;
+
st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
if (!st)
return -ENOMEM;
@@ -503,6 +515,11 @@ int inv_icm42600_core_probe(struct regmap *regmap, int 
chip,
if (ret)
return ret;
 
+   /* setup interrupt trigger */
+   ret = inv_icm42600_trigger_in

[PATCH 02/12] iio: imu: inv_icm42600: add I2C driver for inv_icm42600 driver

2020-05-07 Thread Jean-Baptiste Maneyrol
Add I2C driver for InvenSense ICM-426xxx devices.

Configure bus signal slew rates as indicated in the datasheet.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../iio/imu/inv_icm42600/inv_icm42600_i2c.c   | 117 ++
 1 file changed, 117 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
new file mode 100644
index ..b61f993beacf
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 InvenSense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+
+static int inv_icm42600_i2c_bus_setup(struct inv_icm42600_state *st)
+{
+   unsigned int mask, val;
+   int ret;
+
+   /* setup interface registers */
+   mask = INV_ICM42600_INTF_CONFIG6_MASK;
+   val = INV_ICM42600_INTF_CONFIG6_I3C_EN;
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG6,
+mask, val);
+   if (ret)
+   return ret;
+
+   mask = INV_ICM42600_INTF_CONFIG4_I3C_BUS_ONLY;
+   val = 0;
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG4,
+mask, val);
+   if (ret)
+   return ret;
+
+   /* set slew rates for I2C and SPI */
+   mask = INV_ICM42600_DRIVE_CONFIG_I2C_MASK |
+  INV_ICM42600_DRIVE_CONFIG_SPI_MASK;
+   val = INV_ICM42600_DRIVE_CONFIG_I2C(INV_ICM42600_SLEW_RATE_12_36NS) |
+ INV_ICM42600_DRIVE_CONFIG_SPI(INV_ICM42600_SLEW_RATE_12_36NS);
+   ret = regmap_update_bits(st->map, INV_ICM42600_REG_DRIVE_CONFIG,
+mask, val);
+   if (ret)
+   return ret;
+
+   /* disable SPI bus */
+   mask = INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_MASK;
+   val = INV_ICM42600_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS;
+   return regmap_update_bits(st->map, INV_ICM42600_REG_INTF_CONFIG0,
+ mask, val);
+}
+
+static int inv_icm42600_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+   const void *match;
+   enum inv_icm42600_chip chip;
+   struct regmap *regmap;
+
+   if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
+   return -ENOTSUPP;
+
+   match = device_get_match_data(>dev);
+   if (match)
+   chip = (enum inv_icm42600_chip)match;
+   else if (id)
+   chip = (enum inv_icm42600_chip)id->driver_data;
+   else
+   return -EINVAL;
+
+   regmap = devm_regmap_init_i2c(client, _icm42600_regmap_config);
+   if (IS_ERR(regmap))
+   return PTR_ERR(regmap);
+
+   return inv_icm42600_core_probe(regmap, chip,
+  inv_icm42600_i2c_bus_setup);
+}
+
+static const struct of_device_id inv_icm42600_of_matches[] = {
+   {
+   .compatible = "invensense,icm42600",
+   .data = (void *)INV_CHIP_ICM42600,
+   }, {
+   .compatible = "invensense,icm42602",
+   .data = (void *)INV_CHIP_ICM42602,
+   }, {
+   .compatible = "invensense,icm42605",
+   .data = (void *)INV_CHIP_ICM42605,
+   }, {
+   .compatible = "invensense,icm42622",
+   .data = (void *)INV_CHIP_ICM42622,
+   },
+   {}
+};
+MODULE_DEVICE_TABLE(of, inv_icm42600_of_matches);
+
+static const struct i2c_device_id inv_icm42600_ids[] = {
+   {"icm42600", INV_CHIP_ICM42600},
+   {"icm42602", INV_CHIP_ICM42602},
+   {"icm42605", INV_CHIP_ICM42605},
+   {"icm42622", INV_CHIP_ICM42622},
+   {}
+};
+MODULE_DEVICE_TABLE(i2c, inv_icm42600_ids);
+
+static struct i2c_driver inv_icm42600_driver = {
+   .probe = inv_icm42600_probe,
+   .id_table = inv_icm42600_ids,
+   .driver = {
+   .of_match_table = inv_icm42600_of_matches,
+   .name = "inv-icm42600-i2c",
+   .pm = _icm42600_pm_ops,
+   },
+};
+module_i2c_driver(inv_icm42600_driver);
+
+MODULE_AUTHOR("InvenSense, Inc.");
+MODULE_DESCRIPTION("InvenSense ICM-426xx I2C driver");
+MODULE_LICENSE("GPL");
-- 
2.17.1



[PATCH 00/12] iio: imu: new inv_icm42600 driver

2020-05-07 Thread Jean-Baptiste Maneyrol
This series add a new driver for managing InvenSense ICM-426xx 6-axis IMUs.
This next generation of chips includes new generations of 3-axis gyroscope
and 3-axis accelerometer, support of I3C in addition to I2C and SPI, and
intelligent MotionTracking features like pedometer, tilt detection, and
tap detection.

This series is delivering a driver supporting gyroscope, accelerometer and
temperature data, with polling and buffering using hwfifo and watermark,
on I2C and SPI busses.

Gyroscope and accelerometer sensors are completely independent and can have
different ODRs. Since there is only a single FIFO a specific value is used to
mark invalid data. For keeping the device standard we are de-multiplexing data
from the FIFO to 2 IIO devices with 2 buffers, 1 for the accelerometer and 1
for the gyroscope. This architecture also enables to easily turn each sensor
on/off without impacting the other. The IIO devices are using triggered buffer
as sub-interrupts of the device iio trigger using the interrupt pin. A complex
timestamping mechanism is added to handle correctly FIFO watermark and dynamic
changes.

Jean-Baptiste Maneyrol (12):
  iio: imu: inv_icm42600: add core of new inv_icm42600 driver
  iio: imu: inv_icm42600: add I2C driver for inv_icm42600 driver
  iio: imu: inv_icm42600: add SPI driver for inv_icm42600 driver
  iio: imu: inv_icm42600: add gyroscope IIO device
  iio: imu: inv_icm42600: add accelerometer IIO device
  iio: imu: inv_icm42600: add temperature sensor support
  iio: imu: add Kconfig and Makefile for inv_icm42600 driver
  iio: imu: inv_icm42600: add device interrupt trigger
  iio: imu: inv_icm42600: add buffer support in iio devices
  iio: imu: inv_icm42600: add accurate timestamping
  dt-bindings: iio: imu: Add inv_icm42600 documentation
  MAINTAINERS: add entry for inv_icm42600 6-axis imu sensor

 .../bindings/iio/imu/invensense,icm42600.yaml |  90 +++
 MAINTAINERS   |   8 +
 drivers/iio/imu/Kconfig   |   1 +
 drivers/iio/imu/Makefile  |   1 +
 drivers/iio/imu/inv_icm42600/Kconfig  |  30 +
 drivers/iio/imu/inv_icm42600/Makefile |  16 +
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   | 400 +
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 752 +
 .../imu/inv_icm42600/inv_icm42600_buffer.c| 373 +
 .../imu/inv_icm42600/inv_icm42600_buffer.h| 162 
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  | 674 +++
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 764 ++
 .../iio/imu/inv_icm42600/inv_icm42600_i2c.c   | 117 +++
 .../iio/imu/inv_icm42600/inv_icm42600_spi.c   | 117 +++
 .../iio/imu/inv_icm42600/inv_icm42600_temp.c  |  86 ++
 .../iio/imu/inv_icm42600/inv_icm42600_temp.h  |  32 +
 .../imu/inv_icm42600/inv_icm42600_timestamp.c | 246 ++
 .../imu/inv_icm42600/inv_icm42600_timestamp.h |  82 ++
 .../imu/inv_icm42600/inv_icm42600_trigger.c   | 188 +
 19 files changed, 4139 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
 create mode 100644 drivers/iio/imu/inv_icm42600/Kconfig
 create mode 100644 drivers/iio/imu/inv_icm42600/Makefile
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600.h
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.h
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_trigger.c

-- 
2.17.1



[PATCH 06/12] iio: imu: inv_icm42600: add temperature sensor support

2020-05-07 Thread Jean-Baptiste Maneyrol
Add temperature channel in gyroscope and accelerometer devices.

Temperature is available in full 16 bits resolution as a processed
channel. Scale and offset attributes are also provided for the low
8 bits resolution raw temperature found in the FIFO.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 12 ++-
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 12 ++-
 .../iio/imu/inv_icm42600/inv_icm42600_temp.c  | 86 +++
 .../iio/imu/inv_icm42600/inv_icm42600_temp.h  | 32 +++
 4 files changed, 140 insertions(+), 2 deletions(-)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index 397e3d0fd42b..74dac5f283d4 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -12,6 +12,7 @@
 #include 
 
 #include "inv_icm42600.h"
+#include "inv_icm42600_temp.h"
 
 #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)  \
{   \
@@ -44,6 +45,7 @@ enum inv_icm42600_accel_scan {
INV_ICM42600_ACCEL_SCAN_X,
INV_ICM42600_ACCEL_SCAN_Y,
INV_ICM42600_ACCEL_SCAN_Z,
+   INV_ICM42600_ACCEL_SCAN_TEMP,
 };
 
 static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
@@ -58,6 +60,7 @@ static const struct iio_chan_spec 
inv_icm42600_accel_channels[] = {
inv_icm42600_accel_ext_infos),
INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z,
inv_icm42600_accel_ext_infos),
+   INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP),
 };
 
 static int inv_icm42600_accel_read_sensor(struct inv_icm42600_state *st,
@@ -394,8 +397,15 @@ static int inv_icm42600_accel_read_raw(struct iio_dev 
*indio_dev,
int16_t data;
int ret;
 
-   if (chan->type != IIO_ACCEL)
+   switch (chan->type) {
+   case IIO_ACCEL:
+   break;
+   case IIO_TEMP:
+   return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2,
+ mask);
+   default:
return -EINVAL;
+   }
 
switch (mask) {
case IIO_CHAN_INFO_RAW:
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
index 74aa2b5fa611..c0164ab2830e 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
@@ -12,6 +12,7 @@
 #include 
 
 #include "inv_icm42600.h"
+#include "inv_icm42600_temp.h"
 
 #define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info)   \
{   \
@@ -44,6 +45,7 @@ enum inv_icm42600_gyro_scan {
INV_ICM42600_GYRO_SCAN_X,
INV_ICM42600_GYRO_SCAN_Y,
INV_ICM42600_GYRO_SCAN_Z,
+   INV_ICM42600_GYRO_SCAN_TEMP,
 };
 
 static const struct iio_chan_spec_ext_info inv_icm42600_gyro_ext_infos[] = {
@@ -58,6 +60,7 @@ static const struct iio_chan_spec 
inv_icm42600_gyro_channels[] = {
   inv_icm42600_gyro_ext_infos),
INV_ICM42600_GYRO_CHAN(IIO_MOD_Z, INV_ICM42600_GYRO_SCAN_Z,
   inv_icm42600_gyro_ext_infos),
+   INV_ICM42600_TEMP_CHAN(INV_ICM42600_GYRO_SCAN_TEMP),
 };
 
 static int inv_icm42600_gyro_read_sensor(struct inv_icm42600_state *st,
@@ -406,8 +409,15 @@ static int inv_icm42600_gyro_read_raw(struct iio_dev 
*indio_dev,
int16_t data;
int ret;
 
-   if (chan->type != IIO_ANGL_VEL)
+   switch (chan->type) {
+   case IIO_ANGL_VEL:
+   break;
+   case IIO_TEMP:
+   return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2,
+ mask);
+   default:
return -EINVAL;
+   }
 
switch (mask) {
case IIO_CHAN_INFO_RAW:
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
new file mode 100644
index ..e5407b17c407
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
@@ -0,0 +1,86 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+#include "inv_icm42600_temp.h"
+
+static int inv_icm42600_temp_read(struct inv_icm42600_state *st, int32_t *temp)
+{
+   struct device *dev = regmap_get_device(st->map);
+   __be16 raw;
+   int16_t val;
+   int64_t data;
+   int ret;
+
+   pm_runtime_get_sync(dev);
+   m

[PATCH 11/12] dt-bindings: iio: imu: Add inv_icm42600 documentation

2020-05-07 Thread Jean-Baptiste Maneyrol
Document the ICM-426xxx devices devicetree bindings.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 .../bindings/iio/imu/invensense,icm42600.yaml | 90 +++
 1 file changed, 90 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml

diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml 
b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
new file mode 100644
index ..a7175f6543fa
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
@@ -0,0 +1,90 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/imu/invensense,icm42600.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: InvenSense ICM-426xx Inertial Measurement Unit
+
+maintainers:
+  - Jean-Baptiste Maneyrol 
+
+description: |
+  6-axis MotionTracking device that combines a 3-axis gyroscope and a 3-axis 
accelerometer.
+
+  It has a configurable host interface that supports I3C, I2C and SPI serial 
communication, features a 2kB FIFO and
+  2 programmable interrupts with ultra-low-power wake-on-motion support to 
minimize system power consumption.
+
+  Other industry-leading features include InvenSense on-chip APEX Motion 
Processing engine for gesture recognition,
+  activity classification, and pedometer, along with programmable digital 
filters, and an embedded temperature sensor.
+
+  
https://invensense.tdk.com/wp-content/uploads/2020/03/DS-000292-ICM-42605-v1.4.pdf
+
+properties:
+  compatible:
+enum:
+  - invensense,icm42600
+  - invensense,icm42602
+  - invensense,icm42605
+  - invensense,icm42622
+
+  reg:
+maxItems: 1
+
+  interrupts:
+maxItems: 1
+
+  spi-cpha: true
+
+  spi-cpol: true
+
+  spi-max-frequency:
+maxItems: 1
+
+  vdd-supply:
+description: Regulator that provides power to the sensor
+
+  vddio-supply:
+description: Regulator that provides power to the bus
+
+required:
+  - compatible
+  - reg
+  - interrupts
+
+examples:
+  - |
+#include 
+#include 
+i2c0 {
+#address-cells = <1>;
+#size-cells = <0>;
+
+icm42605@68 {
+  compatible = "invensense,icm42605";
+  reg = <0x68>;
+  interrupt-parent = <>;
+  interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+  vdd-supply = <>;
+  vddio-supply = <>;
+};
+};
+  - |
+#include 
+#include 
+spi0 {
+#address-cells = <1>;
+#size-cells = <0>;
+
+icm42602@0 {
+  compatible = "invensense,icm42602";
+  reg = <0>;
+  spi-max-frequency = <2400>;
+  spi-cpha;
+  spi-cpol;
+  interrupt-parent = <>;
+  interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+  vdd-supply = <>;
+  vddio-supply = <>;
+};
+};
-- 
2.17.1



[PATCH 10/12] iio: imu: inv_icm42600: add accurate timestamping

2020-05-07 Thread Jean-Baptiste Maneyrol
Add a timestamp channel with processed value that returns full
precision 20 bits timestamp.

Add a timestamping mechanism for buffer that provides accurate
event timestamps when using watermark. This mechanism estimates
device internal clock by comparing FIFO interrupts delta time and
corresponding device elapsed time computed by parsing FIFO data.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/Makefile |   1 +
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |  10 +-
 .../iio/imu/inv_icm42600/inv_icm42600_accel.c |  32 ++-
 .../imu/inv_icm42600/inv_icm42600_buffer.c|  28 +-
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |   6 +
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  |  32 ++-
 .../imu/inv_icm42600/inv_icm42600_timestamp.c | 246 ++
 .../imu/inv_icm42600/inv_icm42600_timestamp.h |  82 ++
 8 files changed, 421 insertions(+), 16 deletions(-)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.c
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_timestamp.h

diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
b/drivers/iio/imu/inv_icm42600/Makefile
index d6732118010c..1197b545a682 100644
--- a/drivers/iio/imu/inv_icm42600/Makefile
+++ b/drivers/iio/imu/inv_icm42600/Makefile
@@ -7,6 +7,7 @@ inv-icm42600-y += inv_icm42600_accel.o
 inv-icm42600-y += inv_icm42600_temp.o
 inv-icm42600-y += inv_icm42600_trigger.o
 inv-icm42600-y += inv_icm42600_buffer.o
+inv-icm42600-y += inv_icm42600_timestamp.o
 
 obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o
 inv-icm42600-i2c-y += inv_icm42600_i2c.o
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index 947ca4dd245b..e15eddafe009 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -16,6 +16,7 @@
 #include 
 
 #include "inv_icm42600_buffer.h"
+#include "inv_icm42600_timestamp.h"
 
 enum inv_icm42600_chip {
INV_CHIP_ICM42600,
@@ -127,6 +128,7 @@ struct inv_icm42600_suspended {
  *  @indio_accel:  accelerometer IIO device.
  *  @trigger:  device internal interrupt trigger
  *  @fifo: FIFO management structure.
+ *  @timestamp:timestamp management structure.
  */
 struct inv_icm42600_state {
struct mutex lock;
@@ -142,6 +144,10 @@ struct inv_icm42600_state {
struct iio_dev *indio_accel;
struct iio_trigger *trigger;
struct inv_icm42600_fifo fifo;
+   struct {
+   struct inv_icm42600_timestamp gyro;
+   struct inv_icm42600_timestamp accel;
+   } timestamp;
 };
 
 /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
@@ -382,11 +388,11 @@ int inv_icm42600_core_probe(struct regmap *regmap, int 
chip, int irq,
 
 int inv_icm42600_gyro_init(struct inv_icm42600_state *st);
 
-int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev, int64_t ts);
+int inv_icm42600_gyro_parse_fifo(struct iio_dev *indio_dev);
 
 int inv_icm42600_accel_init(struct inv_icm42600_state *st);
 
-int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev, int64_t ts);
+int inv_icm42600_accel_parse_fifo(struct iio_dev *indio_dev);
 
 int inv_icm42600_trigger_init(struct inv_icm42600_state *st, int irq,
  int irq_type);
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index 4206be54d057..ac140c824c03 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -17,6 +17,7 @@
 #include "inv_icm42600.h"
 #include "inv_icm42600_temp.h"
 #include "inv_icm42600_buffer.h"
+#include "inv_icm42600_timestamp.h"
 
 #define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info)  \
{   \
@@ -66,7 +67,7 @@ static const struct iio_chan_spec 
inv_icm42600_accel_channels[] = {
INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z,
inv_icm42600_accel_ext_infos),
INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP),
-   IIO_CHAN_SOFT_TIMESTAMP(INV_ICM42600_ACCEL_SCAN_TIMESTAMP),
+   INV_ICM42600_TIMESTAMP_CHAN(INV_ICM42600_ACCEL_SCAN_TIMESTAMP),
 };
 
 /* IIO buffer data */
@@ -94,14 +95,20 @@ static irqreturn_t inv_icm42600_accel_handler(int irq, void 
*_data)
struct iio_poll_func *pf = _data;
struct iio_dev *indio_dev = pf->indio_dev;
struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
+   struct inv_icm42600_timestamp *ts = >timestamp.accel;
const size_t fifo_nb = st->fifo.nb.total;
+   const size_t accel_nb = st->fifo.nb.accel;
+   const uint32_t fifo_period = st->fifo.period;
int ret;
 
/* exit if no sample */
if (fifo_nb == 0)
  

[PATCH 01/12] iio: imu: inv_icm42600: add core of new inv_icm42600 driver

2020-05-07 Thread Jean-Baptiste Maneyrol
Core component of a new driver for InvenSense ICM-426xx devices.
It includes registers definition, main probe/setup, and device
utility functions.

ICM-426xx devices are latest generation of 6-axis IMU,
gyroscope+accelerometer and temperature sensor. This device
includes a 2K FIFO, supports I2C/I3C/SPI, and provides
intelligent motion features like pedometer, tilt detection,
and tap detection.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   | 372 +++
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  | 618 ++
 2 files changed, 990 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600.h
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_core.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
new file mode 100644
index ..8da4c8249aed
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -0,0 +1,372 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#ifndef INV_ICM42600_H_
+#define INV_ICM42600_H_
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+enum inv_icm42600_chip {
+   INV_CHIP_ICM42600,
+   INV_CHIP_ICM42602,
+   INV_CHIP_ICM42605,
+   INV_CHIP_ICM42622,
+   INV_CHIP_NB,
+};
+
+/* serial bus slew rates */
+enum inv_icm42600_slew_rate {
+   INV_ICM42600_SLEW_RATE_20_60NS,
+   INV_ICM42600_SLEW_RATE_12_36NS,
+   INV_ICM42600_SLEW_RATE_6_18NS,
+   INV_ICM42600_SLEW_RATE_4_12NS,
+   INV_ICM42600_SLEW_RATE_2_6NS,
+   INV_ICM42600_SLEW_RATE_INF_2NS,
+};
+
+enum inv_icm42600_sensor_mode {
+   INV_ICM42600_SENSOR_MODE_OFF,
+   INV_ICM42600_SENSOR_MODE_STANDBY,
+   INV_ICM42600_SENSOR_MODE_LOW_POWER,
+   INV_ICM42600_SENSOR_MODE_LOW_NOISE,
+   INV_ICM42600_SENSOR_MODE_NB,
+};
+
+/* gyroscope fullscale values */
+enum inv_icm42600_gyro_fs {
+   INV_ICM42600_GYRO_FS_2000DPS,
+   INV_ICM42600_GYRO_FS_1000DPS,
+   INV_ICM42600_GYRO_FS_500DPS,
+   INV_ICM42600_GYRO_FS_250DPS,
+   INV_ICM42600_GYRO_FS_125DPS,
+   INV_ICM42600_GYRO_FS_62_5DPS,
+   INV_ICM42600_GYRO_FS_31_25DPS,
+   INV_ICM42600_GYRO_FS_15_625DPS,
+   INV_ICM42600_GYRO_FS_NB,
+};
+
+/* accelerometer fullscale values */
+enum inv_icm42600_accel_fs {
+   INV_ICM42600_ACCEL_FS_16G,
+   INV_ICM42600_ACCEL_FS_8G,
+   INV_ICM42600_ACCEL_FS_4G,
+   INV_ICM42600_ACCEL_FS_2G,
+   INV_ICM42600_ACCEL_FS_NB,
+};
+
+/* ODR suffixed by LN or LP are Low-Noise or Low-Power mode only */
+enum inv_icm42600_odr {
+   INV_ICM42600_ODR_8KHZ_LN = 3,
+   INV_ICM42600_ODR_4KHZ_LN,
+   INV_ICM42600_ODR_2KHZ_LN,
+   INV_ICM42600_ODR_1KHZ_LN,
+   INV_ICM42600_ODR_200HZ,
+   INV_ICM42600_ODR_100HZ,
+   INV_ICM42600_ODR_50HZ,
+   INV_ICM42600_ODR_25HZ,
+   INV_ICM42600_ODR_12_5HZ,
+   INV_ICM42600_ODR_6_25HZ_LP,
+   INV_ICM42600_ODR_3_125HZ_LP,
+   INV_ICM42600_ODR_1_5625HZ_LP,
+   INV_ICM42600_ODR_500HZ,
+   INV_ICM42600_ODR_NB,
+};
+
+enum inv_icm42600_filter {
+   /* Low-Noise mode sensor data filter (3rd order filter by default) */
+   INV_ICM42600_FILTER_BW_ODR_DIV_2,
+
+   /* Low-Power mode sensor data filter (averaging) */
+   INV_ICM42600_FILTER_AVG_1X = 1,
+   INV_ICM42600_FILTER_AVG_16X = 6,
+};
+
+struct inv_icm42600_sensor_conf {
+   int mode;
+   int fs;
+   int odr;
+   int filter;
+};
+#define INV_ICM42600_SENSOR_CONF_INIT  {-1, -1, -1, -1}
+
+struct inv_icm42600_conf {
+   struct inv_icm42600_sensor_conf gyro;
+   struct inv_icm42600_sensor_conf accel;
+   bool temp_en;
+};
+
+struct inv_icm42600_suspended {
+   enum inv_icm42600_sensor_mode gyro;
+   enum inv_icm42600_sensor_mode accel;
+   bool temp;
+};
+
+/*
+ *  struct inv_icm42600_state - driver state variables
+ *  @lock: chip access lock.
+ *  @chip: chip identifier.
+ *  @name: chip name.
+ *  @map:  regmap pointer.
+ *  @vdd_supply:   VDD voltage regulator for the chip.
+ *  @vddio_supply: I/O voltage regulator for the chip.
+ *  @orientation:  sensor chip orientation relative to main hardware.
+ *  @conf: chip sensors configurations.
+ *  @suspended:suspended sensors configuration.
+ */
+struct inv_icm42600_state {
+   struct mutex lock;
+   enum inv_icm42600_chip chip;
+   const char *name;
+   struct regmap *map;
+   struct regulator *vdd_supply;
+   struct regulator *vddio_supply;
+   struct iio_mount_matrix orientation;
+   struct inv_icm42600_conf conf;
+   struct inv_icm42600_suspended suspended;
+};
+
+/* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
+
+/* Bank selection register, available in all banks */
+#define INV_ICM42600_REG_BANK_SEL

[PATCH 12/12] MAINTAINERS: add entry for inv_icm42600 6-axis imu sensor

2020-05-07 Thread Jean-Baptiste Maneyrol
Add MAINTAINERS entry for InvenSense ICM-426xx IMU device.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 MAINTAINERS | 8 
 1 file changed, 8 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 10eb348c801c..1714390e2721 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8864,6 +8864,14 @@ F:   include/dt-bindings/interconnect/
 F: include/linux/interconnect-provider.h
 F: include/linux/interconnect.h
 
+INVENSENSE ICM-426xx IMU DRIVER
+M: Jean-Baptiste Maneyrol 
+L: linux-...@vger.kernel.org
+S: Maintained
+W  https://invensense.tdk.com/
+F: Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
+F: drivers/iio/imu/inv_icm42600/
+
 INVENSENSE MPU-3050 GYROSCOPE DRIVER
 M: Linus Walleij 
 L: linux-...@vger.kernel.org
-- 
2.17.1



[PATCH 07/12] iio: imu: add Kconfig and Makefile for inv_icm42600 driver

2020-05-07 Thread Jean-Baptiste Maneyrol
Add 3 modules: inv-icm42600, inv-icm42600-i2c, inv-icm42600-spi.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/Kconfig   |  1 +
 drivers/iio/imu/Makefile  |  1 +
 drivers/iio/imu/inv_icm42600/Kconfig  | 28 +++
 drivers/iio/imu/inv_icm42600/Makefile | 13 +
 4 files changed, 43 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/Kconfig
 create mode 100644 drivers/iio/imu/inv_icm42600/Makefile

diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index fc4123d518bc..f02883b08480 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -91,6 +91,7 @@ config KMX61
  To compile this driver as module, choose M here: the module will
  be called kmx61.
 
+source "drivers/iio/imu/inv_icm42600/Kconfig"
 source "drivers/iio/imu/inv_mpu6050/Kconfig"
 source "drivers/iio/imu/st_lsm6dsx/Kconfig"
 
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index 88b2c4555230..13e9ff442b11 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_FXOS8700) += fxos8700_core.o
 obj-$(CONFIG_FXOS8700_I2C) += fxos8700_i2c.o
 obj-$(CONFIG_FXOS8700_SPI) += fxos8700_spi.o
 
+obj-y += inv_icm42600/
 obj-y += inv_mpu6050/
 
 obj-$(CONFIG_KMX61) += kmx61.o
diff --git a/drivers/iio/imu/inv_icm42600/Kconfig 
b/drivers/iio/imu/inv_icm42600/Kconfig
new file mode 100644
index ..22390a72f0a3
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/Kconfig
@@ -0,0 +1,28 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+config INV_ICM42600
+   tristate
+
+config INV_ICM42600_I2C
+   tristate "InvenSense ICM-426xx I2C driver"
+   depends on I2C
+   select INV_ICM42600
+   select REGMAP_I2C
+   help
+ This driver supports the InvenSense ICM-426xx motion tracking
+ devices over I2C.
+
+ This driver can be built as a module. The module will be called
+ inv-icm42600-i2c.
+
+config INV_ICM42600_SPI
+   tristate "InvenSense ICM-426xx SPI driver"
+   depends on SPI_MASTER
+   select INV_ICM42600
+   select REGMAP_SPI
+   help
+ This driver supports the InvenSense ICM-426xx motion tracking
+ devices over SPI.
+
+ This driver can be built as a module. The module will be called
+ inv-icm42600-spi.
diff --git a/drivers/iio/imu/inv_icm42600/Makefile 
b/drivers/iio/imu/inv_icm42600/Makefile
new file mode 100644
index ..48965824f00c
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/Makefile
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+obj-$(CONFIG_INV_ICM42600) += inv-icm42600.o
+inv-icm42600-y += inv_icm42600_core.o
+inv-icm42600-y += inv_icm42600_gyro.o
+inv-icm42600-y += inv_icm42600_accel.o
+inv-icm42600-y += inv_icm42600_temp.o
+
+obj-$(CONFIG_INV_ICM42600_I2C) += inv-icm42600-i2c.o
+inv-icm42600-i2c-y += inv_icm42600_i2c.o
+
+obj-$(CONFIG_INV_ICM42600_SPI) += inv-icm42600-spi.o
+inv-icm42600-spi-y += inv_icm42600_spi.o
-- 
2.17.1



[PATCH 04/12] iio: imu: inv_icm42600: add gyroscope IIO device

2020-05-07 Thread Jean-Baptiste Maneyrol
Add IIO device for gyroscope sensor with data polling interface.
Attributes: raw, scale, sampling_frequency, calibbias.

Gyroscope in low noise mode.

Signed-off-by: Jean-Baptiste Maneyrol 
---
 drivers/iio/imu/inv_icm42600/inv_icm42600.h   |   4 +
 .../iio/imu/inv_icm42600/inv_icm42600_core.c  |   5 +
 .../iio/imu/inv_icm42600/inv_icm42600_gyro.c  | 549 ++
 3 files changed, 558 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c

diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600.h 
b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
index 8da4c8249aed..ca41a9d6404a 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600.h
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600.h
@@ -120,6 +120,7 @@ struct inv_icm42600_suspended {
  *  @orientation:  sensor chip orientation relative to main hardware.
  *  @conf: chip sensors configurations.
  *  @suspended:suspended sensors configuration.
+ *  @indio_gyro:   gyroscope IIO device.
  */
 struct inv_icm42600_state {
struct mutex lock;
@@ -131,6 +132,7 @@ struct inv_icm42600_state {
struct iio_mount_matrix orientation;
struct inv_icm42600_conf conf;
struct inv_icm42600_suspended suspended;
+   struct iio_dev *indio_gyro;
 };
 
 /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
@@ -369,4 +371,6 @@ int inv_icm42600_debugfs_reg(struct iio_dev *indio_dev, 
unsigned int reg,
 int inv_icm42600_core_probe(struct regmap *regmap, int chip,
inv_icm42600_bus_setup bus_setup);
 
+int inv_icm42600_gyro_init(struct inv_icm42600_state *st);
+
 #endif
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
index 35bdf4f9d31e..151257652ce6 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
@@ -503,6 +503,11 @@ int inv_icm42600_core_probe(struct regmap *regmap, int 
chip,
if (ret)
return ret;
 
+   /* create and init gyroscope iio device */
+   ret = inv_icm42600_gyro_init(st);
+   if (ret)
+   return ret;
+
/* setup runtime power management */
ret = pm_runtime_set_active(dev);
if (ret)
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c 
b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
new file mode 100644
index ..74aa2b5fa611
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
@@ -0,0 +1,549 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2020 Invensense, Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "inv_icm42600.h"
+
+#define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info)   \
+   {   \
+   .type = IIO_ANGL_VEL,   \
+   .modified = 1,  \
+   .channel2 = _modifier,  \
+   .info_mask_separate =   \
+   BIT(IIO_CHAN_INFO_RAW) |\
+   BIT(IIO_CHAN_INFO_CALIBBIAS),   \
+   .info_mask_shared_by_type = \
+   BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_type_available =   \
+   BIT(IIO_CHAN_INFO_SCALE),   \
+   .info_mask_shared_by_all =  \
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   .info_mask_shared_by_all_available =\
+   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
+   .scan_index = _index,   \
+   .scan_type = {  \
+   .sign = 's',\
+   .realbits = 16, \
+   .storagebits = 16,  \
+   .shift = 0, \
+   .endianness = IIO_BE,   \
+   },  \
+   .ext_info = _ext_info,  \
+   }
+
+enum inv_icm42600_gyro_scan {
+   INV_ICM42600_GYRO_SCAN_X,
+   INV_ICM42600_GYRO_SCAN_Y,
+   INV_ICM42600_GYRO_SCAN_Z,
+};
+
+static const struct iio_chan_spec_ext_info inv_icm42600_gyro_ext_infos[] = {
+   IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42600_get_mount_matrix),
+   {},
+};
+
+static const struct iio

Re: ICM20602 buffer issues with the inv_mpu6050 driver

2019-05-23 Thread Jean-Baptiste Maneyrol
Hi Andreea,

I understand the issue now. The problem is that temperature data are always 
present in the FIFO. Even when the attribute is disabled. This is a limitation 
of this chip and cannot be changed on the hardware side.

When temp attribute is disabled while accel and gyro are on, the iio buffer is 
expecting to have 12 bytes with accel + gyro data. But the driver will still 
provides 14 bytes with temperature in the middle since the FIFO will contain 
that. Always enabling temperature attribute on userspace will solve this issue, 
but that's certainly not the best.

A correct solution would be to enforce temperature data in iio buffer by having 
the temp attribute always enabled and read-only in userspace. That would 
reflect correctly the chip capabilities. But I don't know if this is feasible. 
A workaround would be to add data post-processing in the driver and delete temp 
data when it is disabled. But I don't like this kind of workaround because that 
goes against iio buffer design principle.

Hope this help you.

Best regards,
Jean-Baptiste Maneyrol

From: Andreea Lutac 
Sent: Thursday, May 23, 2019 11:44
To: Jean-Baptiste Maneyrol
Cc: stev...@skydio.com; ji...@kernel.org; knaac...@gmx.de; l...@metafoo.de; 
pme...@pmeerw.net; linux-...@vger.kernel.org; linux-kernel@vger.kernel.org
Subject: Re: ICM20602 buffer issues with the inv_mpu6050 driver
 
 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.

Hi Jean-Baptiste and Stepan,

Thanks so much for the replies and the advice. I've dug a bit deeper into this 
and added a few printk statements to the driver, as suggested by Stepan. It 
looks like the device is getting recognized correctly as ICM20602 and the 
buffer is being filled with 14 bytes as expected.

But I've identified some strange behaviour regarding the temperature channeI. 
If I manually enable all 7 scan elements and read 14 bytes from the device 
file, the readings appear correct and change accordingly when I move the chip 
around. However, if I set in_temp_en set to 0 (with everything else still 
enabled) and read 12 bytes, the buffer doesn't seem to acknowledge this change 
and shift the gyro values up, instead getting only the first 12 bytes (accel_x, 
accel_y, accel_z, temp, gyro_x, gyro_y), without gyro_z. So this is why it 
looks as if temp is replacing gyro_x.
I made a pastebin here with some of the (unconverted) values I got while 
testing these cases: 
https://urldefense.proofpoint.com/v2/url?u=https-3A__pastebin.com_BYVqDNch=DwIFaQ=WoJWtq5JV8YrKnzRxvD8NxmTP_1wxfE0prPmo0NeZwg=4jiDX_1brsSWfCjfA6Ovj1d4h9MF8q7Xk5aBwG28mVk=sbkHiUlsj8pOWjf2iTq5CXEFvv-MNyqBKOqCjxOj9kc=Pmb23R-DoTj9hDwYk3qqiUfOCUWbtfpVQjUZ1lajeFI=

Attempting the same reads with my C++ program via libiio always results in only 
the first 12 bytes being read, as for some strange reason libiio fails to 
enable the temperature channel, so iio_device_get_sample_size() is always 12 
and it's actually gyro_z that I can't get to.

I'll try to look through the code that is supposed to enable a channel and see 
why it's not succeeding via libiio. Do you have any clue as to which bit of 
code does the adjustment of the buffer values according to which channels are 
enabled? Is this done in the driver or deeper in the kernel?

Thanks once again for the help!
Best regards,
Andreea

On Wednesday, May 22, 2019 16:33 CEST, Jean-Baptiste Maneyrol 
 wrote:

> Hello,
>
> I had a look inside the driver to verify the buffer implementation. It looks 
> correct to me. I don't see where the problem can come from. I am sorry I 
> don't have a setup currently to test in live.
>
> For sure you can have a different result by reading the buffer through the 
> char device file compared to reading the raw sysfs entry. The buffer is 
> taking the data from the FIFO and the raw sysfs from the sensor data 
> registers.
>
> You can perhaps test value 1 by 1 in the buffer, and verify the correctness 
> of every attributes. If you can also send a complete buffer log that would be 
> helpful.
> Every data is 2 bytes long and in the following order: accel_x, accel_y, 
> accel_z, temp, gyro_x, gyro_y, gyro_z
>
> Best regards,
> JB Maneyrol
>
> From: Andreea Lutac 
> Sent: Tuesday, May 21, 2019 12:40
> Cc: Jean-Baptiste Maneyrol; stev...@skydio.com; ji...@kernel.org; 
> knaac...@gmx.de; l...@metafoo.de; pme...@pmeerw.net; 
> linux-...@vger.kernel.org; linux-kernel@vger.kernel.org
> Subject: ICM20602 buffer issues with the inv_mpu6050 driver
>  
> Hello,
>
> I've been trying to get some data samples from the ICM20602 IMU using the 
> mpu6050 driver which recently added support for it, but I'm encountering an 
> issue with the ordering of the data in the FIFO.
> According to the specs

Re: ICM20602 buffer issues with the inv_mpu6050 driver

2019-05-22 Thread Jean-Baptiste Maneyrol
Hello,

I had a look inside the driver to verify the buffer implementation. It looks 
correct to me. I don't see where the problem can come from. I am sorry I don't 
have a setup currently to test in live.

For sure you can have a different result by reading the buffer through the char 
device file compared to reading the raw sysfs entry. The buffer is taking the 
data from the FIFO and the raw sysfs from the sensor data registers.

You can perhaps test value 1 by 1 in the buffer, and verify the correctness of 
every attributes. If you can also send a complete buffer log that would be 
helpful.
Every data is 2 bytes long and in the following order: accel_x, accel_y, 
accel_z, temp, gyro_x, gyro_y, gyro_z

Best regards,
JB Maneyrol

From: Andreea Lutac 
Sent: Tuesday, May 21, 2019 12:40
Cc: Jean-Baptiste Maneyrol; stev...@skydio.com; ji...@kernel.org; 
knaac...@gmx.de; l...@metafoo.de; pme...@pmeerw.net; linux-...@vger.kernel.org; 
linux-kernel@vger.kernel.org
Subject: ICM20602 buffer issues with the inv_mpu6050 driver
 
Hello,

I've been trying to get some data samples from the ICM20602 IMU using the 
mpu6050 driver which recently added support for it, but I'm encountering an 
issue with the ordering of the data in the FIFO.
According to the specs of the device, if the accel and gyro XYZ channels are 
enabled, then the hardware FIFO is filled with 14 bytes corresponding to the 
following channels: accel_x, accel_y, accel_z, temp, anglvel_x, anglvel_y, 
anglvel_z. However, when reading out the buffer, the value I get for anglvel_x 
seems to actually be the temperature. This  occurs both when reading with 
iio_channel_read (via libiio) and also if I read directly from /dev/iio:device 
with only in_anglvel_x_en set. But in_anglvel_x_raw reports correct values, 
which made me suspect that maybe somewhere in the driver this interleaved temp 
channel is not accounted for in the buffer structure.

I had a look at the driver code and inv_mpu6050_read_fifo() in particular, but 
I can't identify anything amiss. I've applied the recent patch that added the 
extra 2 temperature bytes ( ), but the problem persists. So far I've tried 
changing the size of the data buffer, defined in inv_mpu_iio.h:

/* 6 + 6 round up and plus 8 */
#define INV_MPU6050_OUTPUT_DATA_SIZE 24

from 24 to 32, according to the intuition that 24 corresponds to readings 
without temperature (i.e. 6 bytes for accel, rounded up to 8 + 6 bytes for 
gyro, rounded up to 8 + 8 bytes for the timestamp = 24) and thus another 8 
bytes would be needed, but that doesn't seem to have solved it.

I'm quite new to driver development though, so I think there might be something 
I'm not getting. I would be really grateful if anyone could shed some light 
over what's happening here or give some advice as to what I could be doing 
wrong.

Best regards,
Andreea Lutac



Re: [PATCH v2] iio: imu: mpu6050: Fix FIFO layout for ICM20602

2019-04-08 Thread Jean-Baptiste Maneyrol
Hello,

overall looks good for me.

I would just prefer to change the define name for temperature to 
INV_ICM20602_SCAN_TEMP. It is the chip temperature that can be used for 
temperature compensation for both accel and gyro data.

But it is really just a details.

Best regards,
Jean-Baptiste Maneyrol


From: Jonathan Cameron 
Sent: Sunday, April 7, 2019 13:45
To: stev...@skydio.com
Cc: Jean-Baptiste Maneyrol; Hartmut Knaack; Lars-Peter Clausen; Peter 
Meerwald-Stadler; Martin Kelly; Jonathan Marek; Brian Masney; Randolph Maaßen; 
Douglas Fischer; linux-...@vger.kernel.org; linux-kernel@vger.kernel.org
Subject: Re: [PATCH v2] iio: imu: mpu6050: Fix FIFO layout for ICM20602
 
 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.

On Tue,  2 Apr 2019 23:28:56 -0700
stev...@skydio.com wrote:

> From: Steve Moskovchenko 
>
> The MPU6050 driver has recently gained support for the
> ICM20602 IMU, which is very similar to MPU6xxx. However,
> the ICM20602's FIFO data specifically includes temperature
> readings, which were not present on MPU6xxx parts. As a
> result, the driver will under-read the ICM20602's FIFO
> register, causing the same (partial) sample to be returned
> for all reads, until the FIFO overflows.
>
> Fix this by adding a table of scan elements specifically
> for the ICM20602, which takes the extra temperature data
> into consideration.
>
> While we're at it, fix the temperature offset and scaling
> on ICM20602, since it uses different scale/offset constants
> than the rest of the MPU6xxx devices.
>
> Signed-off-by: Steve Moskovchenko 
I'd like a reviewed-by or acked-by from Jean-Baptiste on this before
I take it.

thanks,

Jonathan

> ---
> v2: Read temperature when running in accel-only mode, too.
>
>  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 46 --
>  drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h  | 20 +-
>  drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c |  3 ++
>  3 files changed, 64 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c 
> b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> index 650de0fefb7b..fedd3f2b0135 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> @@ -471,7 +471,10 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
>    return IIO_VAL_INT_PLUS_MICRO;
>    case IIO_TEMP:
>    *val = 0;
> - *val2 = INV_MPU6050_TEMP_SCALE;
> + if (st->chip_type == INV_ICM20602)
> + *val2 = INV_ICM20602_TEMP_SCALE;
> + else
> + *val2 = INV_MPU6050_TEMP_SCALE;
> 
>    return IIO_VAL_INT_PLUS_MICRO;
>    default:
> @@ -480,7 +483,10 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
>    case IIO_CHAN_INFO_OFFSET:
>    switch (chan->type) {
>    case IIO_TEMP:
> - *val = INV_MPU6050_TEMP_OFFSET;
> + if (st->chip_type == INV_ICM20602)
> + *val = INV_ICM20602_TEMP_OFFSET;
> + else
> + *val = INV_MPU6050_TEMP_OFFSET;
> 
>    return IIO_VAL_INT;
>    default:
> @@ -845,6 +851,32 @@ static const struct iio_chan_spec inv_mpu_channels[] = {
>    INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z),
>  };
> 
> +static const struct iio_chan_spec inv_icm20602_channels[] = {
> + IIO_CHAN_SOFT_TIMESTAMP(INV_ICM20602_SCAN_TIMESTAMP),
> + {
> + .type = IIO_TEMP,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW)
> + | BIT(IIO_CHAN_INFO_OFFSET)
> + | BIT(IIO_CHAN_INFO_SCALE),
> + .scan_index = INV_ICM20602_SCAN_GYRO_TEMP,
> + .scan_type = {
> + .sign = 's',
> + .realbits = 16,
> + .storagebits = 16,
> + .shift = 0,
> + .endianness = IIO_BE,
> +  },
> + },
> +
> + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_X, INV_ICM20602_SCAN_GYRO_X),
> + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Y, INV_ICM20602_SCAN_GYRO_Y),
> + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_MOD_Z, INV_ICM20602_SCAN_GYRO_Z),
> +
> + INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Y, INV_ICM20602_SCAN_ACCL_Y),
> + INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD

Re: [PATCH] iio: imu: mpu6050: Fix FIFO layout for ICM20602

2019-04-01 Thread Jean-Baptiste Maneyrol
Hello,

it is right that temperature is always put inside the FIFO with this chip.

But beware that it should also be the case when accelerometer only is enabled. 
The FIFO should contain accel data + temp. You can easily verify that by 
looking at the size of a sample inside the FIFO when only accelerometer is 
enabled (should be 8 instead of 6).

If this is confirmed, you need to modify your code to handle this case 
correctly.

Best regards,
Jean-Baptiste Maneyrol



From: Jonathan Cameron 
Sent: Saturday, March 30, 2019 19:29
To: stev...@skydio.com
Cc: gai...@gaireg.de; Hartmut Knaack; Lars-Peter Clausen; Peter 
Meerwald-Stadler; Jean-Baptiste Maneyrol; Martin Kelly; Jonathan Marek; Brian 
Masney; Rob Herring; Douglas Fischer; linux-...@vger.kernel.org; 
linux-kernel@vger.kernel.org; Randolph Maaßen
Subject: Re: [PATCH] iio: imu: mpu6050: Fix FIFO layout for ICM20602
 
 CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.

On Tue, 26 Mar 2019 02:01:45 -0700
stev...@skydio.com wrote:
+CC Randolph, who I think introduced the support.

> From: Steve Moskovchenko 
>
> The MPU6050 driver has recently gained support for the
> ICM20602 IMU, which is very similar to MPU6xxx. However,
> the ICM20602's Gyro data specifically includes temperature
> readings, which were not present on MPU6xxx parts. As a
> result, the driver will under-read the ICM20602's FIFO
> register, causing the same (partial) sample to be returned
> for all reads, until the FIFO overflows.
>
> Fix this by adding a table of scan elements speciically for
> the ICM20602, which takes the extra temperature data into
> consideration.
>
> While we're at it, fix the temperature offset and scaling
> on ICM20602, since it uses different scale/offset constants
> than the rest of the MPU6xxx devices.
>
> Signed-off-by: Steve Moskovchenko 
Hi Steve

This all looks sensible to me.  Ideally should have had a fixes tag.

If no one shouts in the next few days I'll pick this up and add one.
Give me a poke if I seem to have forgotten it in a week or so.

Thanks,

Jonathan


> ---
>  drivers/iio/imu/inv_mpu6050/inv_mpu_core.c | 46 --
>  drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h  | 20 +-
>  drivers/iio/imu/inv_mpu6050/inv_mpu_ring.c |  8 +++-
>  3 files changed, 67 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c 
> b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> index 650de0fefb7b..fedd3f2b0135 100644
> --- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> +++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
> @@ -471,7 +471,10 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
>    return IIO_VAL_INT_PLUS_MICRO;
>    case IIO_TEMP:
>    *val = 0;
> - *val2 = INV_MPU6050_TEMP_SCALE;
> + if (st->chip_type == INV_ICM20602)
> + *val2 = INV_ICM20602_TEMP_SCALE;
> + else
> + *val2 = INV_MPU6050_TEMP_SCALE;
> 
>    return IIO_VAL_INT_PLUS_MICRO;
>    default:
> @@ -480,7 +483,10 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
>    case IIO_CHAN_INFO_OFFSET:
>    switch (chan->type) {
>    case IIO_TEMP:
> - *val = INV_MPU6050_TEMP_OFFSET;
> + if (st->chip_type == INV_ICM20602)
> + *val = INV_ICM20602_TEMP_OFFSET;
> + else
> + *val = INV_MPU6050_TEMP_OFFSET;
> 
>    return IIO_VAL_INT;
>    default:
> @@ -845,6 +851,32 @@ static const struct iio_chan_spec inv_mpu_channels[] = {
>    INV_MPU6050_CHAN(IIO_ACCEL, IIO_MOD_Z, INV_MPU6050_SCAN_ACCL_Z),
>  };
> 
> +static const struct iio_chan_spec inv_icm20602_channels[] = {
> + IIO_CHAN_SOFT_TIMESTAMP(INV_ICM20602_SCAN_TIMESTAMP),
> + {
> + .type = IIO_TEMP,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW)
> + | BIT(IIO_CHAN_INFO_OFFSET)
> + | BIT(IIO_CHAN_INFO_SCALE),
> + .scan_index = INV_ICM20602_SCAN_GYRO_TEMP,
> + .scan_type = {
> + .sign = 's',
> + .realbits = 16,
> + .storagebits = 16,
> + .shift = 0,
> + .endianness = IIO_BE,
> +  },
> + },
> +
> + INV_MPU6050_CHAN(IIO_ANGL_VEL, IIO_

Re: [PATCH 2/3] iio: imu: mpu6050: add support for regulator framework

2018-07-11 Thread Jean-Baptiste Maneyrol
Hello,

I really don't like the idea to have regulator handled inside the driver. I 
know this was done like that before for Nexus 5, but I think now this is 
something that can be done using dts only.
Does anyone know if there is a way with dts to handle regulator automatically 
and prevent the use in the driver? That would be a good idea to search how this 
handled for other drivers.

Anyway, you are enforcing regulator use in your code. It doesn't seem the code 
will work when there is no regulator declared in the dts, which is the case for 
the majority of configurations. We should at least make it optional.

Thanks for the contribution.
JB


From: Brian Masney 
Sent: Wednesday, July 11, 2018 03:09
To: ji...@kernel.org; robh...@kernel.org; mark.rutl...@arm.com; 
andy.gr...@linaro.org; david.br...@linaro.org; linux-...@vger.kernel.org; 
devicet...@vger.kernel.org; linux-kernel@vger.kernel.org; 
linux-arm-...@vger.kernel.org; linux-...@vger.kernel.org
Cc: jonat...@marek.ca; Jean-Baptiste Maneyrol; knaac...@gmx.de; 
l...@metafoo.de; pme...@pmeerw.net; mke...@xevo.com; fischerdougl...@gmail.com; 
bs...@kde.org; ctatlo...@gmail.com; masn...@onstation.org
Subject: [PATCH 2/3] iio: imu: mpu6050: add support for regulator framework
  

CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.


This patch adds support for the regulator framework to the mpu6050
driver.

Signed-off-by: Brian Masney 
Signed-off-by: Jonathan Marek 
---
This is a variation of Jonathan Marek's patch from postmarketOS
https://gitlab.com/postmarketOS/linux-postmarketos/commit/b8ad1ec1859c8bbcbce94944b3f4dd68f8f9fc37
with the following changes:

- Stripped out 6515 variant code. (See my previous patch in this series)
- Add the regulator to the mpu core instead of only the i2c variant.
- Add error handling.
- Release the regulator on suspend, device remove, etc.
- Device tree documentation.

 .../bindings/iio/imu/inv_mpu6050.txt  |  1 +
 drivers/iio/imu/inv_mpu6050/inv_mpu_core.c    | 57 +--
 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c |  2 +-
 drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h |  3 +
 drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c |  9 +++
 5 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt 
b/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt
index b7def51c8ad9..d39907b12a46 100644
--- a/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt
+++ b/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt
@@ -21,6 +21,7 @@ Required properties:
   bindings.

 Optional properties:
+ - vddio-supply: regulator phandle for VDDIO supply
  - mount-matrix: an optional 3x3 mounting rotation matrix
  - i2c-gate node.  These devices also support an auxiliary i2c bus.  This is
    simple enough to be described using the i2c-gate binding. See
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c 
b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 12c1b9507007..ec276b7bcc69 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "inv_mpu_iio.h"

 /*
@@ -926,6 +927,19 @@ static int inv_check_and_setup_chip(struct 
inv_mpu6050_state *st)
    return result;
 }

+static int inv_mpu_core_enable_regulator(struct inv_mpu6050_state *st)
+{
+   int result;
+
+   result = regulator_enable(st->vddio_supply);
+   if (result == 0) {
+   /* Give the device a little bit of time to start up. */
+   usleep_range(35000, 7);
+   }
+
+   return result;
+}
+
 int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
    int (*inv_mpu_bus_setup)(struct iio_dev *), int chip_type)
 {
@@ -990,15 +1004,28 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, 
const char *name,
    return -EINVAL;
    }

+   st->vddio_supply = devm_regulator_get_optional(dev, "vddio");
+   if (IS_ERR(st->vddio_supply)) {
+   if (PTR_ERR(st->vddio_supply) != -EPROBE_DEFER)
+   dev_err(dev, "Failed to get vddio regulator %d\n",
+   (int)PTR_ERR(st->vddio_supply));
+
+   return PTR_ERR(st->vddio_supply);
+   }
+
+   result = inv_mpu_core_enable_regulator(st);
+   if (result)
+   return result;
+
    /* power is turned on inside check chip type*/
    result = inv_check_and_setup_chip(st);
    if (result)
-   return result;
+   goto out_disable_regulator;

    result = inv_mpu6050_init_config(indio_dev);
    if (result) {
    dev_err(dev, "Could not initialize device.\n&q

Re: [PATCH 2/3] iio: imu: mpu6050: add support for regulator framework

2018-07-11 Thread Jean-Baptiste Maneyrol
Hello,

I really don't like the idea to have regulator handled inside the driver. I 
know this was done like that before for Nexus 5, but I think now this is 
something that can be done using dts only.
Does anyone know if there is a way with dts to handle regulator automatically 
and prevent the use in the driver? That would be a good idea to search how this 
handled for other drivers.

Anyway, you are enforcing regulator use in your code. It doesn't seem the code 
will work when there is no regulator declared in the dts, which is the case for 
the majority of configurations. We should at least make it optional.

Thanks for the contribution.
JB


From: Brian Masney 
Sent: Wednesday, July 11, 2018 03:09
To: ji...@kernel.org; robh...@kernel.org; mark.rutl...@arm.com; 
andy.gr...@linaro.org; david.br...@linaro.org; linux-...@vger.kernel.org; 
devicet...@vger.kernel.org; linux-kernel@vger.kernel.org; 
linux-arm-...@vger.kernel.org; linux-...@vger.kernel.org
Cc: jonat...@marek.ca; Jean-Baptiste Maneyrol; knaac...@gmx.de; 
l...@metafoo.de; pme...@pmeerw.net; mke...@xevo.com; fischerdougl...@gmail.com; 
bs...@kde.org; ctatlo...@gmail.com; masn...@onstation.org
Subject: [PATCH 2/3] iio: imu: mpu6050: add support for regulator framework
  

CAUTION: This email originated from outside of the organization. Please make 
sure the sender is who they say they are and do not click links or open 
attachments unless you recognize the sender and know the content is safe.


This patch adds support for the regulator framework to the mpu6050
driver.

Signed-off-by: Brian Masney 
Signed-off-by: Jonathan Marek 
---
This is a variation of Jonathan Marek's patch from postmarketOS
https://gitlab.com/postmarketOS/linux-postmarketos/commit/b8ad1ec1859c8bbcbce94944b3f4dd68f8f9fc37
with the following changes:

- Stripped out 6515 variant code. (See my previous patch in this series)
- Add the regulator to the mpu core instead of only the i2c variant.
- Add error handling.
- Release the regulator on suspend, device remove, etc.
- Device tree documentation.

 .../bindings/iio/imu/inv_mpu6050.txt  |  1 +
 drivers/iio/imu/inv_mpu6050/inv_mpu_core.c    | 57 +--
 drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c |  2 +-
 drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h |  3 +
 drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c |  9 +++
 5 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt 
b/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt
index b7def51c8ad9..d39907b12a46 100644
--- a/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt
+++ b/Documentation/devicetree/bindings/iio/imu/inv_mpu6050.txt
@@ -21,6 +21,7 @@ Required properties:
   bindings.

 Optional properties:
+ - vddio-supply: regulator phandle for VDDIO supply
  - mount-matrix: an optional 3x3 mounting rotation matrix
  - i2c-gate node.  These devices also support an auxiliary i2c bus.  This is
    simple enough to be described using the i2c-gate binding. See
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c 
b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 12c1b9507007..ec276b7bcc69 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "inv_mpu_iio.h"

 /*
@@ -926,6 +927,19 @@ static int inv_check_and_setup_chip(struct 
inv_mpu6050_state *st)
    return result;
 }

+static int inv_mpu_core_enable_regulator(struct inv_mpu6050_state *st)
+{
+   int result;
+
+   result = regulator_enable(st->vddio_supply);
+   if (result == 0) {
+   /* Give the device a little bit of time to start up. */
+   usleep_range(35000, 7);
+   }
+
+   return result;
+}
+
 int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
    int (*inv_mpu_bus_setup)(struct iio_dev *), int chip_type)
 {
@@ -990,15 +1004,28 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, 
const char *name,
    return -EINVAL;
    }

+   st->vddio_supply = devm_regulator_get_optional(dev, "vddio");
+   if (IS_ERR(st->vddio_supply)) {
+   if (PTR_ERR(st->vddio_supply) != -EPROBE_DEFER)
+   dev_err(dev, "Failed to get vddio regulator %d\n",
+   (int)PTR_ERR(st->vddio_supply));
+
+   return PTR_ERR(st->vddio_supply);
+   }
+
+   result = inv_mpu_core_enable_regulator(st);
+   if (result)
+   return result;
+
    /* power is turned on inside check chip type*/
    result = inv_check_and_setup_chip(st);
    if (result)
-   return result;
+   goto out_disable_regulator;

    result = inv_mpu6050_init_config(indio_dev);
    if (result) {
    dev_err(dev, "Could not initialize device.\n&q