Skip to contentSkip to conversation

Add Invensense ICM42607

PATCH Superseded Chris Morgan 6 participants 36 messages Jun 15 – Jun 24 1 message not in the archive

Subsystems (4)

v13 of 21 Superseded Latest is v21 →

lore
Share & tools
lore
#0 lore raw

v13 cover Add Invensense ICM42607

From: Chris Morgan <[email protected]>

Add support for the ICM42607 IMU. This sensor shares the same functionality but a different register layout with the existing ICM42600.

This driver should work with the ICM42607 and ICM42607P over both I2C and SPI, however only the ICM42607P over I2C could be tested.

Changes Since V1:
- Instead of creating a new driver, merged with the existing inv_icm42600 driver. This necessitated adding some code to the existing driver to permit using a different register layout for the same functionality.
- Split changes up a bit more to decrease the size of the individual patches. Note that patch 0004 is still pretty hefty; if I need to split further I may need to create some temporary stub functions.
- Used guard() and PM_RUNTIME_ACQUIRE_AUTOSUSPEND() on the new functions per Jonathan's recommendations.

Changes Since V2:
- Went back to using a new driver on advice from Invensense engineer.
- Further split changes up into smaller chunks of functionality. Note still that the largest patch is approximately 900 lines, and that while the driver compiles cleanly at each commit it is not able to drive the hardware until the commit that adds the Interrupt (as it also adds the Makefile).
- Change the error to a warning when the devicetree binding does not match the hardware ID.
- Dropped the ack on the devicetree bindings, as I am creating a new file (for a new driver) instead of modifying the existing one.

Changes Since V3:
- Numerous small fixes (too many to list here). Thank you to everyone who provided feedback.
- Split power management additions into an additional commit to break things up further.
- Consolidated devicetree documentation in existing invensense,icm42600.yaml file.
- Removed most of the FIELD_PREP from header file to c files to make code easier to read.
- Changed scale values to 2D arrays for Gyro and Accelerometer.
- Removed IIO_CHAN_INFO_CALIBBIAS attribute.

Changes Since V4:
- Additional numerous small fixes, thank you again for all the feedback.
- Dropped power control API and instead run device in low noise mode.
- Split devicetree bindings into two distinct changes.
- Reordered adding of enums and structs to main header file so that they are only brought in when needed.
- Stopped using enum for driver data and instead am using pointer to device specific driver data.

Changes Since V5:
- Corrected use of "dev_warn_probe" to just "dev_warn".
- Fixed some return scenarios which would unconditionally return 0 when an error was present.
- Corrected use of max() to min() for bounds checking. max() was incorrect.
- Fixed using "st->conf.accel.odr" in the gyroscope function. It should have been "st->conf.gyro.odr" which it now is.
- Additional small fixes suggested by "sashiko.dev".
- Added a regmap cache. I used the datasheet to try and determine which registers might change without explicit writes.

Changes Since V6:
- Corrected additional errors identified by sashiko.dev, mostly fixing potential deadlocks, missing calls for pm runtime, and potential overflow issues.

Changes Since V7:
- Dropped Wake on Movement patches, since some of the functionality was only available for a device on which I cannot test.
- Dropped support for SPI 3-Wire mode, since it complicated the bus setup (and I lack the hardware to test such features anyway).
- Fixed a few additional bugs identified by sashiko.dev bot.

Changes Since V8:
- Added back IRQ dropped accidentally when dropping wake on movement patches.
- Dropped "Reviewed-By" tag on patch 2 because of substantial changes made to devicetree binding documentation.
- Additional small fixes as suggested.

Changes Since V9:
- Removed interrupts (and buffers) from the driver. I previously was unable to detect deadlocks because it turns out my IRQ was not even wired correctly in my device.
- Updated devicetree binding commits to make interrupts optional for users of the icm42607 driver.

Changes Since V10:
- Explicitly specified enum values in header file.
- Removed additional dead code for buffer handling.
- Cleaned up headers.
- Added additional locks as requested by sashiko.dev bot.

Changes Since V11:
- Since driver has shrunk in size considerably, moved i2c bits into first code commit. This ensures that the very first commit with code can now be compiled. The commit after that adds SPI support as it was in the previous versions.
- Used pahole to optimize inv_icm42607_state. Reordering elements reduced size in memory from 384 bytes to 256 bytes.
- Added a map of all readable registers and all writeable registers according to the datasheet.
- Added back some missing headers pointed out by the maintainers.
- Added FIELD_PREP in a few more places to make the code more obvious on what it's doing.
- Added a comment to the power management code to note that temperature sensor being enabled doesn't matter as the clocks are off by default when the gyro and accel channels are off.
- Removed iio_device_claim_direct() calls since it was no longer needed.
- Fixed shared_by_all attributes for temperature sensor.
- Additional miscellanous fixes as requested.

Changes Since V12:
- Removed aligned buffer from inv_icm42607_state struct as we do not currently have the need for it.
- Corrected the order of the odr values in the accel and gyro files as the values were out of order (the place in the array corresponds to the register value).
- Stopped setting the clock value depending upon the temp config. The datasheet advised to keep using the default value.
- Corrected logic when changing between states. We only need to pause when a sensor changes from off to an on state or when the gyro changes from an on state to off.
- Added missing includes for several files.

Chris Morgan (9):
dt-bindings: iio: imu: icm42600: Add mount-matrix to icm42600
dt-bindings: iio: imu: icm42600: Add icm42607
iio: imu: inv_icm42607: Add inv_icm42607 Core Driver
iio: imu: inv_icm42607: Add SPI For icm42607
iio: imu: inv_icm42607: Add PM support for icm42607
iio: imu: inv_icm42607: Add Temp Support in icm42607
iio: imu: inv_icm42607: Add Accelerometer for icm42607
iio: imu: inv_icm42607: Add Gyroscope to icm42607
arm64: dts: rockchip: Add icm42607p IMU for RG-DS

 .../bindings/iio/imu/invensense,icm42600.yaml |  20 +-
 .../dts/rockchip/rk3568-anbernic-rg-ds.dts    |   8 +-
 drivers/iio/imu/Kconfig                       |   1 +
 drivers/iio/imu/Makefile                      |   1 +
 drivers/iio/imu/inv_icm42607/Kconfig          |  30 +
 drivers/iio/imu/inv_icm42607/Makefile         |  13 +
 drivers/iio/imu/inv_icm42607/inv_icm42607.h   | 410 +++++++++++++
 .../iio/imu/inv_icm42607/inv_icm42607_accel.c | 373 ++++++++++++
 .../iio/imu/inv_icm42607/inv_icm42607_core.c  | 546 ++++++++++++++++++
 .../iio/imu/inv_icm42607/inv_icm42607_gyro.c  | 369 ++++++++++++
 .../iio/imu/inv_icm42607/inv_icm42607_i2c.c   |  98 ++++
 .../iio/imu/inv_icm42607/inv_icm42607_spi.c   | 108 ++++
 .../iio/imu/inv_icm42607/inv_icm42607_temp.c  |  81 +++
 .../iio/imu/inv_icm42607/inv_icm42607_temp.h  |  37 ++
 14 files changed, 2093 insertions(+), 2 deletions(-)
 create mode 100644 drivers/iio/imu/inv_icm42607/Kconfig
 create mode 100644 drivers/iio/imu/inv_icm42607/Makefile
 create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607.h
 create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c
 create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
 create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c
 create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c
 create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c
 create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c
 create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_temp.h
Signature · 1 line
2.43.0
#1 lore raw

PATCH v13 1/9 dt-bindings: iio: imu: icm42600: Add mount-matrix to icm42600

From: Chris Morgan <[email protected]>

Add mount-matrix attribute to schema. This attribute has been supported since the first revision of this driver, but was not documented.

---
 .../devicetree/bindings/iio/imu/invensense,icm42600.yaml        | 2 ++
 1 file changed, 2 insertions(+)
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +2 -0
index 119e28a833fd..9b2af104f186 100644
@@ -53,6 +53,8 @@ properties:
   drive-open-drain:
     type: boolean
 
+  mount-matrix: true
+
   vdd-supply:
     description: Regulator that provides power to the sensor
 
Signature · 1 line
2.43.0
#2 lore raw

PATCH v13 2/9 dt-bindings: iio: imu: icm42600: Add icm42607

In reply to Chris Morgan

From: Chris Morgan <[email protected]>

Add the ICM42607 and ICM42607P inertial measurement unit.

This device is functionally very similar to the icm42600 series with a very different register layout. The driver does not require an interrupt for these specific chip revisions.

---
 .../bindings/iio/imu/invensense,icm42600.yaml  | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +17 -1
index 9b2af104f186..81b6e85decd5 100644
@@ -30,6 +30,8 @@ properties:
       - invensense,icm42600
       - invensense,icm42602
       - invensense,icm42605
+      - invensense,icm42607
+      - invensense,icm42607p
       - invensense,icm42622
       - invensense,icm42631
       - invensense,icm42686
@@ -67,10 +69,24 @@ properties:
 required:
   - compatible
   - reg
-  - interrupts
 
 allOf:
   - $ref: /schemas/spi/spi-peripheral-props.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - invensense,icm42600
+              - invensense,icm42602
+              - invensense,icm42605
+              - invensense,icm42622
+              - invensense,icm42631
+              - invensense,icm42686
+              - invensense,icm42688
+    then:
+      required:
+        - interrupts
 
 unevaluatedProperties: false
 
Signature · 1 line
2.43.0
maintainer
#3 lore raw

Re: [PATCH V13 2/9] dt-bindings: iio: imu: icm42600: Add icm42607

Quoted 7 lines · On Mon, 15 Jun 2026 12:25:45 -0500 Chris Morgan <[email protected]> wrote:

From: Chris Morgan <[email protected]>

Add the ICM42607 and ICM42607P inertial measurement unit.

This device is functionally very similar to the icm42600 series with a very different register layout. The driver does not require an interrupt for these specific chip revisions.

This talks about how they are different from other parts already supported, but I think we need something on how they are different from each other.

I'm kind of assuming one is a subset of the other? If that is the case the ideal might be the more complex part falling back to the simpler one.

Thanks,

Jonathan

Quoted 46 lines
---
 .../bindings/iio/imu/invensense,icm42600.yaml  | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +17 -1
index 9b2af104f186..81b6e85decd5 100644
@@ -30,6 +30,8 @@ properties:
       - invensense,icm42600
       - invensense,icm42602
       - invensense,icm42605
+      - invensense,icm42607
+      - invensense,icm42607p
       - invensense,icm42622
       - invensense,icm42631
       - invensense,icm42686
@@ -67,10 +69,24 @@ properties:
 required:
   - compatible
   - reg
-  - interrupts
 
 allOf:
   - $ref: /schemas/spi/spi-peripheral-props.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - invensense,icm42600
+              - invensense,icm42602
+              - invensense,icm42605
+              - invensense,icm42622
+              - invensense,icm42631
+              - invensense,icm42686
+              - invensense,icm42688
+    then:
+      required:
+        - interrupts
 
 unevaluatedProperties: false
 
#4 lore raw

Re: [PATCH V13 2/9] dt-bindings: iio: imu: icm42600: Add icm42607

Hello Chris and Jonathan,

concerning dt bindings, my initial understanding was that we had a file per driver. But here, Chris is doing a new driver for icm42607 while adding new bindings here.

Does it means we don't have 1 binding file per driver, and there is no need to create a new binding file for inv_icm42607 driver?

Despite the naming, icm42607 chips are a complete new design very different than all other icm42600 chips. It using similar IPs for things like the FIFO, but all other parts are different. Especially, it doesn't use banks for registers access but indirect access delegated to the chip internals for accessing certain registers.

Thanks,
JB

Quoted 51 lines

From: Chris Morgan <[email protected]>

Add the ICM42607 and ICM42607P inertial measurement unit.

This device is functionally very similar to the icm42600 series with a very different register layout. The driver does not require an interrupt for these specific chip revisions.

---
.../bindings/iio/imu/invensense,icm42600.yaml | 18 +++++++++++++++++-

1 file changed, 17 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +2 -0
index 9b2af104f186..81b6e85decd5 100644
@@ -30,6 +30,8 @@ properties:
      - invensense,icm42600
      - invensense,icm42602
      - invensense,icm42605
+      - invensense,icm42607
+      - invensense,icm42607p
      - invensense,icm42622
      - invensense,icm42631
      - invensense,icm42686
@@ -67,10 +69,24 @@ properties:

required:
- compatible
- reg
- - interrupts

allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#

Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +15 -0
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - invensense,icm42600
+              - invensense,icm42602
+              - invensense,icm42605
+              - invensense,icm42622
+              - invensense,icm42631
+              - invensense,icm42686
+              - invensense,icm42688
+    then:
+      required:
+        - interrupts
Quoted 4 lines

unevaluatedProperties: false

Signature · 1 line
2.43.0

_______________________________________________
Linux-rockchip mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-rockchip

maintainer
#5 lore raw

Re: [PATCH V13 2/9] dt-bindings: iio: imu: icm42600: Add icm42607

Quoted 8 lines · On Mon, 22 Jun 2026 09:23:28 +0000 Jean-Baptiste Maneyrol…

Hello Chris and Jonathan,

concerning dt bindings, my initial understanding was that we had a file per driver. But here, Chris is doing a new driver for icm42607 while adding new bindings here.

Does it means we don't have 1 binding file per driver, and there is no need to create a new binding file for inv_icm42607 driver?

Yes. We often combine bindings when there is a lot of duplication and only a few device specific rules are needed to describe the new parts.

Jonathan

Quoted 65 lines

Despite the naming, icm42607 chips are a complete new design very different than all other icm42600 chips. It using similar IPs for things like the FIFO, but all other parts are different. Especially, it doesn't use banks for registers access but indirect access delegated to the chip internals for accessing certain registers.

Thanks,
JB

Quoted 55 lines

From: Chris Morgan <[email protected]>

Add the ICM42607 and ICM42607P inertial measurement unit.

This device is functionally very similar to the icm42600 series with a very different register layout. The driver does not require an interrupt for these specific chip revisions.

---
.../bindings/iio/imu/invensense,icm42600.yaml | 18 +++++++++++++++++-

1 file changed, 17 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +2 -0
index 9b2af104f186..81b6e85decd5 100644
@@ -30,6 +30,8 @@ properties:
      - invensense,icm42600
      - invensense,icm42602
      - invensense,icm42605
+      - invensense,icm42607
+      - invensense,icm42607p
      - invensense,icm42622
      - invensense,icm42631
      - invensense,icm42686
@@ -67,10 +69,24 @@ properties:

required:
- compatible
- reg
- - interrupts

allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#

Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +15 -0
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - invensense,icm42600
+              - invensense,icm42602
+              - invensense,icm42605
+              - invensense,icm42622
+              - invensense,icm42631
+              - invensense,icm42686
+              - invensense,icm42688
+    then:
+      required:
+        - interrupts

unevaluatedProperties: false

Signature · 1 line
2.43.  
#6 lore raw

Re: [PATCH V13 2/9] dt-bindings: iio: imu: icm42600: Add icm42607

In reply to Jean-Baptiste Maneyrol
Quoted 6 lines · Jean-Baptiste Maneyrol

Hello Chris and Jonathan,

concerning dt bindings, my initial understanding was that we had a file per driver. But here, Chris is doing a new driver for icm42607 while adding new bindings here.

Quoted 8 lines

Does it means we don't have 1 binding file per driver, and there is no need to create a new binding file for inv_icm42607 driver?

Despite the naming, icm42607 chips are a complete new design very different than all other icm42600 chips. It using similar IPs for things like the FIFO, but all other parts are different. Especially, it doesn't use banks for registers access but indirect access delegated to the chip internals for accessing certain registers.

For what it's worth I'm not using any of those registers in the driver currently; from what I see in the datasheets I was able to find on the web the 42607p doesn't do the indirect register access (again unless I'm misreading). To be fair I don't have any other icm42607 chips to test against. The 42607c does appear to do such register access.

Thank you,
Chris

Quoted 59 lines

Thanks,
JB

Quoted 55 lines

From: Chris Morgan <[email protected]>

Add the ICM42607 and ICM42607P inertial measurement unit.

This device is functionally very similar to the icm42600 series with a very different register layout. The driver does not require an interrupt for these specific chip revisions.

---
.../bindings/iio/imu/invensense,icm42600.yaml | 18 +++++++++++++++++-

1 file changed, 17 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +2 -0
index 9b2af104f186..81b6e85decd5 100644
@@ -30,6 +30,8 @@ properties:
      - invensense,icm42600
      - invensense,icm42602
      - invensense,icm42605
+      - invensense,icm42607
+      - invensense,icm42607p
      - invensense,icm42622
      - invensense,icm42631
      - invensense,icm42686
@@ -67,10 +69,24 @@ properties:

required:
- compatible
- reg
- - interrupts

allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#

Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +15 -0
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - invensense,icm42600
+              - invensense,icm42602
+              - invensense,icm42605
+              - invensense,icm42622
+              - invensense,icm42631
+              - invensense,icm42686
+              - invensense,icm42688
+    then:
+      required:
+        - interrupts

unevaluatedProperties: false

Signature · 1 line
2.43.0
#7 lore raw

Re: [PATCH V13 2/9] dt-bindings: iio: imu: icm42600: Add icm42607

Quoted 31 lines

From: Chris Morgan <[email protected]>
Sent: Tuesday, June 23, 2026 02:06
To: Jean-Baptiste Maneyrol
Cc: Jonathan Cameron; Chris Morgan; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Krzysztof Kozlowski
Subject: Re: [PATCH V13 2/9] dt-bindings: iio: imu: icm42600: Add icm42607

On Mon, Jun 22, 2026 at 09: 23: 28AM +0000, Jean-Baptiste Maneyrol wrote: > Hello Chris and Jonathan, > > concerning dt bindings, my initial understanding was that we had a file per > driver. But here, Chris is doing a new driver for ZjQcmQRYFpfptBannerStart
This Message Is From an External Sender
This message came from outside your organization.

ZjQcmQRYFpfptBannerEnd

Quoted 6 lines · Jean-Baptiste Maneyrol

Hello Chris and Jonathan,

concerning dt bindings, my initial understanding was that we had a file per driver. But here, Chris is doing a new driver for icm42607 while adding new bindings here.

Quoted 8 lines

Does it means we don't have 1 binding file per driver, and there is no need to create a new binding file for inv_icm42607 driver?

Despite the naming, icm42607 chips are a complete new design very different than all other icm42600 chips. It using similar IPs for things like the FIFO, but all other parts are different. Especially, it doesn't use banks for registers access but indirect access delegated to the chip internals for accessing certain registers.

Quoted 8 lines

For what it's worth I'm not using any of those registers in the driver currently; from what I see in the datasheets I was able to find on the web the 42607p doesn't do the indirect register access (again unless I'm misreading). To be fair I don't have any other icm42607 chips to test against. The 42607c does appear to do such register access.

Thank you,
Chris

Hello Chris,

here is a link to download ICM-42670-P datasheet, this chip is completely similar to ICM-42607-P:
https://www.invensense.tdk.com/en-us/download-resource/ds-000451-icm-42670-p-datasheet

Indirect register access is required when you want to use the FIFO for configuring which data is stored inside or when you want to update gyro/accel hardware offsets (calibbias iio attribute usually). Also required for a lot of more complex internal chip configuration.

I didn't had a chance to look at your driver currently. I hope to be able to have a look soon.

I can you give the figures for the required maximum sleep time for accel and gyro startups and stops. Usually, they are not provided in datasheet (only mean values).

Thanks for your work,
JB

Quoted 56 lines
Quoted 56 lines

Thanks,
JB

Quoted 51 lines

From: Chris Morgan <[email protected]>

Add the ICM42607 and ICM42607P inertial measurement unit.

This device is functionally very similar to the icm42600 series with a very different register layout. The driver does not require an interrupt for these specific chip revisions.

---
.../bindings/iio/imu/invensense,icm42600.yaml | 18 +++++++++++++++++-

1 file changed, 17 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +2 -0
index 9b2af104f186..81b6e85decd5 100644
@@ -30,6 +30,8 @@ properties:
      - invensense,icm42600
      - invensense,icm42602
      - invensense,icm42605
+      - invensense,icm42607
+      - invensense,icm42607p
      - invensense,icm42622
      - invensense,icm42631
      - invensense,icm42686
@@ -67,10 +69,24 @@ properties:

required:
- compatible
- reg
- - interrupts

allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#

Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +15 -0
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - invensense,icm42600
+              - invensense,icm42602
+              - invensense,icm42605
+              - invensense,icm42622
+              - invensense,icm42631
+              - invensense,icm42686
+              - invensense,icm42688
+    then:
+      required:
+        - interrupts
Quoted 6 lines
Quoted 4 lines
Quoted 4 lines

unevaluatedProperties: false

--
2.43.0

________________________________________
From: Chris Morgan <[email protected]>
Sent: Tuesday, June 23, 2026 02:06
To: Jean-Baptiste Maneyrol
Cc: Jonathan Cameron; Chris Morgan; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Krzysztof Kozlowski
Subject: Re: [PATCH V13 2/9] dt-bindings: iio: imu: icm42600: Add icm42607

On Mon, Jun 22, 2026 at 09: 23: 28AM +0000, Jean-Baptiste Maneyrol wrote: > Hello Chris and Jonathan, > > concerning dt bindings, my initial understanding was that we had a file per > driver. But here, Chris is doing a new driver for ZjQcmQRYFpfptBannerStart
This Message Is From an External Sender
This message came from outside your organization.

ZjQcmQRYFpfptBannerEnd

Quoted 6 lines · Jean-Baptiste Maneyrol

Hello Chris and Jonathan,

concerning dt bindings, my initial understanding was that we had a file per driver. But here, Chris is doing a new driver for icm42607 while adding new bindings here.

Quoted 8 lines

Does it means we don't have 1 binding file per driver, and there is no need to create a new binding file for inv_icm42607 driver?

Despite the naming, icm42607 chips are a complete new design very different than all other icm42600 chips. It using similar IPs for things like the FIFO, but all other parts are different. Especially, it doesn't use banks for registers access but indirect access delegated to the chip internals for accessing certain registers.

For what it's worth I'm not using any of those registers in the driver currently; from what I see in the datasheets I was able to find on the web the 42607p doesn't do the indirect register access (again unless I'm misreading). To be fair I don't have any other icm42607 chips to test against. The 42607c does appear to do such register access.

Thank you,
Chris

Quoted 55 lines

Thanks,
JB

Quoted 51 lines

From: Chris Morgan <[email protected]>

Add the ICM42607 and ICM42607P inertial measurement unit.

This device is functionally very similar to the icm42600 series with a very different register layout. The driver does not require an interrupt for these specific chip revisions.

---
.../bindings/iio/imu/invensense,icm42600.yaml | 18 +++++++++++++++++-

1 file changed, 17 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +2 -0
index 9b2af104f186..81b6e85decd5 100644
@@ -30,6 +30,8 @@ properties:
      - invensense,icm42600
      - invensense,icm42602
      - invensense,icm42605
+      - invensense,icm42607
+      - invensense,icm42607p
      - invensense,icm42622
      - invensense,icm42631
      - invensense,icm42686
@@ -67,10 +69,24 @@ properties:

required:
- compatible
- reg
- - interrupts

allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#

Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +15 -0
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - invensense,icm42600
+              - invensense,icm42602
+              - invensense,icm42605
+              - invensense,icm42622
+              - invensense,icm42631
+              - invensense,icm42686
+              - invensense,icm42688
+    then:
+      required:
+        - interrupts
Quoted 4 lines
Quoted 4 lines

unevaluatedProperties: false

--
2.43.0

_______________________________________________
Linux-rockchip mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-rockchip

#8 lore raw

Re: [PATCH V13 2/9] dt-bindings: iio: imu: icm42600: Add icm42607

Quoted 54 lines · Jean-Baptiste Maneyrol
Quoted 31 lines

From: Chris Morgan <[email protected]>
Sent: Tuesday, June 23, 2026 02:06
To: Jean-Baptiste Maneyrol
Cc: Jonathan Cameron; Chris Morgan; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Krzysztof Kozlowski
Subject: Re: [PATCH V13 2/9] dt-bindings: iio: imu: icm42600: Add icm42607

On Mon, Jun 22, 2026 at 09: 23: 28AM +0000, Jean-Baptiste Maneyrol wrote: > Hello Chris and Jonathan, > > concerning dt bindings, my initial understanding was that we had a file per > driver. But here, Chris is doing a new driver for ZjQcmQRYFpfptBannerStart
This Message Is From an External Sender
This message came from outside your organization.

ZjQcmQRYFpfptBannerEnd

Quoted 6 lines · Jean-Baptiste Maneyrol

Hello Chris and Jonathan,

concerning dt bindings, my initial understanding was that we had a file per driver. But here, Chris is doing a new driver for icm42607 while adding new bindings here.

Quoted 8 lines

Does it means we don't have 1 binding file per driver, and there is no need to create a new binding file for inv_icm42607 driver?

Despite the naming, icm42607 chips are a complete new design very different than all other icm42600 chips. It using similar IPs for things like the FIFO, but all other parts are different. Especially, it doesn't use banks for registers access but indirect access delegated to the chip internals for accessing certain registers.

Quoted 8 lines

For what it's worth I'm not using any of those registers in the driver currently; from what I see in the datasheets I was able to find on the web the 42607p doesn't do the indirect register access (again unless I'm misreading). To be fair I don't have any other icm42607 chips to test against. The 42607c does appear to do such register access.

Thank you,
Chris

Hello Chris,

here is a link to download ICM-42670-P datasheet, this chip is completely similar to ICM-42607-P:
https://www.invensense.tdk.com/en-us/download-resource/ds-000451-icm-42670-p-datasheet

Indirect register access is required when you want to use the FIFO for configuring which data is stored inside or when you want to update gyro/accel hardware offsets (calibbias iio attribute usually). Also required for a lot of more complex internal chip configuration.

I didn't had a chance to look at your driver currently. I hope to be able to have a look soon.

Quoted 6 lines

I can you give the figures for the required maximum sleep time for accel and gyro startups and stops. Usually, they are not provided in datasheet (only mean values).

Thanks for your work,
JB

I guess I had an older or inaccurate datasheet because mine didn't list any of the additional user banks for the 42607p, only for the 42607c.

As of right now I'm not using any of those additional registers, my main goal all along has just been to get the accelerometer working honestly, and so far using things like monitor-sensor this driver seems to be outputting what I expect. I'm not using any of the fifo buffers, wom, or apex stuff currently either as it turns out my implementation doesn't even have an interrupt as best I can tell, I couldn't get any output on the designated IRQ line suggesting it probably wasn't used.

I'm currently using the mean values from the datasheet for the startup times (10ms for the accelerometer, 30ms for the gyroscope). I had a misreading in earlier versions for the temp sensor of 77ms, but looking at the datasheet again it appears it should be 77us. Since the temp sensor needs one of the gyro or accel enabled to be read I'm just not messing with the startup time at all and relying on the longer startup times of the accel or gyro. In the latest version (not pushed yet as I'm still refactoring stuff) I am tracking the timestamp of the gyro start to ensure it has been on at least 45ms before it is shut off, as the datasheet also says minimum run time is 45ms.

If you see anything else let me know, I'm happy to get any help I can.

Thank you,
Chris

Quoted 164 lines
Quoted 57 lines
Quoted 57 lines

Thanks,
JB

Quoted 51 lines

From: Chris Morgan <[email protected]>

Add the ICM42607 and ICM42607P inertial measurement unit.

This device is functionally very similar to the icm42600 series with a very different register layout. The driver does not require an interrupt for these specific chip revisions.

---
.../bindings/iio/imu/invensense,icm42600.yaml | 18 +++++++++++++++++-

1 file changed, 17 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +2 -0
index 9b2af104f186..81b6e85decd5 100644
@@ -30,6 +30,8 @@ properties:
      - invensense,icm42600
      - invensense,icm42602
      - invensense,icm42605
+      - invensense,icm42607
+      - invensense,icm42607p
      - invensense,icm42622
      - invensense,icm42631
      - invensense,icm42686
@@ -67,10 +69,24 @@ properties:

required:
- compatible
- reg
- - interrupts

allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#

Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +15 -0
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - invensense,icm42600
+              - invensense,icm42602
+              - invensense,icm42605
+              - invensense,icm42622
+              - invensense,icm42631
+              - invensense,icm42686
+              - invensense,icm42688
+    then:
+      required:
+        - interrupts
Quoted 6 lines
Quoted 4 lines
Quoted 4 lines

unevaluatedProperties: false

--
2.43.0

________________________________________
From: Chris Morgan <[email protected]>
Sent: Tuesday, June 23, 2026 02:06
To: Jean-Baptiste Maneyrol
Cc: Jonathan Cameron; Chris Morgan; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; [email protected]; Krzysztof Kozlowski
Subject: Re: [PATCH V13 2/9] dt-bindings: iio: imu: icm42600: Add icm42607

On Mon, Jun 22, 2026 at 09: 23: 28AM +0000, Jean-Baptiste Maneyrol wrote: > Hello Chris and Jonathan, > > concerning dt bindings, my initial understanding was that we had a file per > driver. But here, Chris is doing a new driver for ZjQcmQRYFpfptBannerStart
This Message Is From an External Sender
This message came from outside your organization.

ZjQcmQRYFpfptBannerEnd

Quoted 6 lines · Jean-Baptiste Maneyrol

Hello Chris and Jonathan,

concerning dt bindings, my initial understanding was that we had a file per driver. But here, Chris is doing a new driver for icm42607 while adding new bindings here.

Quoted 8 lines

Does it means we don't have 1 binding file per driver, and there is no need to create a new binding file for inv_icm42607 driver?

Despite the naming, icm42607 chips are a complete new design very different than all other icm42600 chips. It using similar IPs for things like the FIFO, but all other parts are different. Especially, it doesn't use banks for registers access but indirect access delegated to the chip internals for accessing certain registers.

For what it's worth I'm not using any of those registers in the driver currently; from what I see in the datasheets I was able to find on the web the 42607p doesn't do the indirect register access (again unless I'm misreading). To be fair I don't have any other icm42607 chips to test against. The 42607c does appear to do such register access.

Thank you,
Chris

Quoted 59 lines

Thanks,
JB

Quoted 55 lines

From: Chris Morgan <[email protected]>

Add the ICM42607 and ICM42607P inertial measurement unit.

This device is functionally very similar to the icm42600 series with a very different register layout. The driver does not require an interrupt for these specific chip revisions.

---
.../bindings/iio/imu/invensense,icm42600.yaml | 18 +++++++++++++++++-

1 file changed, 17 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +2 -0
index 9b2af104f186..81b6e85decd5 100644
@@ -30,6 +30,8 @@ properties:
      - invensense,icm42600
      - invensense,icm42602
      - invensense,icm42605
+      - invensense,icm42607
+      - invensense,icm42607p
      - invensense,icm42622
      - invensense,icm42631
      - invensense,icm42686
@@ -67,10 +69,24 @@ properties:

required:
- compatible
- reg
- - interrupts

allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#

Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml +15 -0
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - invensense,icm42600
+              - invensense,icm42602
+              - invensense,icm42605
+              - invensense,icm42622
+              - invensense,icm42631
+              - invensense,icm42686
+              - invensense,icm42688
+    then:
+      required:
+        - interrupts

unevaluatedProperties: false

--
2.43.0

#9 lore raw

PATCH v13 3/9 iio: imu: inv_icm42607: Add inv_icm42607 Core Driver

In reply to Chris Morgan

From: Chris Morgan <[email protected]>

Add the core component of a new inv_icm42607 driver. This includes a few setup functions and the full register definition in the header file, as well as the bits necessary to compile and probe the device when used on an i2c bus.

---
 drivers/iio/imu/Kconfig                       |   1 +
 drivers/iio/imu/Makefile                      |   1 +
 drivers/iio/imu/inv_icm42607/Kconfig          |  18 +
 drivers/iio/imu/inv_icm42607/Makefile         |   7 +
 drivers/iio/imu/inv_icm42607/inv_icm42607.h   | 347 ++++++++++++++++++
 .../iio/imu/inv_icm42607/inv_icm42607_core.c  | 280 ++++++++++++++
 .../iio/imu/inv_icm42607/inv_icm42607_i2c.c   |  97 +++++
 7 files changed, 751 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42607/Kconfig
 create mode 100644 drivers/iio/imu/inv_icm42607/Makefile
 create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607.h
 create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
 create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c
drivers/iio/imu/Kconfig +1 -0
index 7e0181c27bb6..8bab4616be20 100644
@@ -109,6 +109,7 @@ config KMX61
 	  be called kmx61.
 
 source "drivers/iio/imu/inv_icm42600/Kconfig"
+source "drivers/iio/imu/inv_icm42607/Kconfig"
 source "drivers/iio/imu/inv_icm45600/Kconfig"
 source "drivers/iio/imu/inv_mpu6050/Kconfig"
 
drivers/iio/imu/Makefile +1 -0
index 13fb7846e9c9..3268dc2371ae 100644
@@ -25,6 +25,7 @@ obj-$(CONFIG_FXOS8700_I2C) += fxos8700_i2c.o
 obj-$(CONFIG_FXOS8700_SPI) += fxos8700_spi.o
 
 obj-y += inv_icm42600/
+obj-y += inv_icm42607/
 obj-y += inv_icm45600/
 obj-y += inv_mpu6050/
 
drivers/iio/imu/inv_icm42607/Kconfig new file +18 -0
new file mode 100644
index 000000000000..083c212087ab
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+config INV_ICM42607
+	tristate
+	select IIO_BUFFER
+	select IIO_INV_SENSORS_TIMESTAMP
+
+config INV_ICM42607_I2C
+	tristate "InvenSense ICM-42607 I2C driver"
+	depends on I2C
+	select INV_ICM42607
+	select REGMAP_I2C
+	help
+	  This driver supports the InvenSense ICM-42607 motion tracking
+	  device over I2C.
+
+	  This driver can be built as a module. The module will be called
+	  inv-icm42607-i2c.
drivers/iio/imu/inv_icm42607/Makefile new file +7 -0
new file mode 100644
index 000000000000..32046e2727d7
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+obj-$(CONFIG_INV_ICM42607) += inv-icm42607.o
+inv-icm42607-y += inv_icm42607_core.o
+
+obj-$(CONFIG_INV_ICM42607_I2C) += inv-icm42607-i2c.o
+inv-icm42607-i2c-y += inv_icm42607_i2c.o
drivers/iio/imu/inv_icm42607/inv_icm42607.h new file +347 -0

347 lines not on this page · raw message

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c new file +280 -0

280 lines not on this page · raw message

drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c new file +97 -0

97 lines not on this page · raw message

Signature · 1 line
2.43.0
#10 lore raw

Re: [PATCH V13 3/9] iio: imu: inv_icm42607: Add inv_icm42607 Core Driver

Quoted 4 lines · Chris Morgan

Add the core component of a new inv_icm42607 driver. This includes a few setup functions and the full register definition in the header file, as well as the bits necessary to compile and probe the device when used on an i2c bus.

...

drivers/iio/imu/inv_icm42607/inv_icm42607.h line 15

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607.h new file +10 -0
+#ifndef INV_ICM42607_H_
+#define INV_ICM42607_H_
+
+#include <linux/bits.h>
+#include <linux/iio/iio.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/time.h>
+#include <linux/types.h>

+ asm/byteorder.h // cpu_to_le16()

...

drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c line 14

Quoted 9 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c new file +9 -0
+#include <linux/bitfield.h>
+#include <linux/dev_printk.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+

Single blank line is enough.

Quoted 1 line

+#include "inv_icm42607.h"

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#11 lore raw

PATCH v13 4/9 iio: imu: inv_icm42607: Add SPI For icm42607

In reply to Chris Morgan

From: Chris Morgan <[email protected]>

Add SPI driver support for InvenSense ICM-42607 devices.

---
 drivers/iio/imu/inv_icm42607/Kconfig          |  12 ++
 drivers/iio/imu/inv_icm42607/Makefile         |   3 +
 .../iio/imu/inv_icm42607/inv_icm42607_spi.c   | 107 ++++++++++++++++++
 3 files changed, 122 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c
drivers/iio/imu/inv_icm42607/Kconfig +12 -0
index 083c212087ab..23f461f57afc 100644
@@ -16,3 +16,15 @@ config INV_ICM42607_I2C
 
 	  This driver can be built as a module. The module will be called
 	  inv-icm42607-i2c.
+
+config INV_ICM42607_SPI
+	tristate "InvenSense ICM-42607 SPI driver"
+	depends on SPI_MASTER
+	select INV_ICM42607
+	select REGMAP_SPI
+	help
+	  This driver supports the InvenSense ICM-42607 motion tracking
+	  device over SPI.
+
+	  This driver can be built as a module. The module will be called
+	  inv-icm42607-spi.
drivers/iio/imu/inv_icm42607/Makefile +3 -0
index 32046e2727d7..be109102e203 100644
@@ -5,3 +5,6 @@ inv-icm42607-y += inv_icm42607_core.o
 
 obj-$(CONFIG_INV_ICM42607_I2C) += inv-icm42607-i2c.o
 inv-icm42607-i2c-y += inv_icm42607_i2c.o
+
+obj-$(CONFIG_INV_ICM42607_SPI) += inv-icm42607-spi.o
+inv-icm42607-spi-y += inv_icm42607_spi.o
drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c new file +107 -0

107 lines not on this page · raw message

Signature · 1 line
2.43.0
#12 lore raw

PATCH v13 5/9 iio: imu: inv_icm42607: Add PM support for icm42607

In reply to Chris Morgan

From: Chris Morgan <[email protected]>

Add power management support for the ICM42607 device driver.

---
 drivers/iio/imu/inv_icm42607/inv_icm42607.h   |  18 +++
 .../iio/imu/inv_icm42607/inv_icm42607_core.c  | 139 ++++++++++++++++++
 .../iio/imu/inv_icm42607/inv_icm42607_i2c.c   |   1 +
 .../iio/imu/inv_icm42607/inv_icm42607_spi.c   |   1 +
 4 files changed, 159 insertions(+)
drivers/iio/imu/inv_icm42607/inv_icm42607.h +18 -0
index a6a58571935f..4f4f541027dc 100644
@@ -9,6 +9,7 @@
 #include <linux/bits.h>
 #include <linux/iio/iio.h>
 #include <linux/mutex.h>
+#include <linux/pm.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/time.h>
@@ -105,12 +106,20 @@ struct inv_icm42607_hw {
 	u8 whoami;
 };
 
+struct inv_icm42607_suspended {
+	enum inv_icm42607_sensor_mode gyro;
+	enum inv_icm42607_sensor_mode accel;
+	bool temp;
+};
+
 /**
  *  struct inv_icm42607_state - driver state variables
  *  @hw:		Hardware specific data.
  *  @lock:		lock for serializing multiple registers access.
  *  @map:		regmap pointer.
  *  @vddio_supply:	I/O voltage regulator for the chip.
+ *  @vddio_en:		I/O voltage status for runtime PM.
+ *  @suspended:		suspended sensors configuration.
  *  @conf:		chip sensors configurations.
  *  @orientation:	sensor chip orientation relative to main hardware.
  */
@@ -119,6 +128,8 @@ struct inv_icm42607_state {
 	struct mutex lock;
 	struct regmap *map;
 	struct regulator *vddio_supply;
+	bool vddio_en;
+	struct inv_icm42607_suspended suspended;
 	struct inv_icm42607_conf conf;
 	struct iio_mount_matrix orientation;
 };
@@ -334,11 +345,18 @@ struct inv_icm42607_state {
 #define INV_ICM42607_GYRO_STOP_TIME_MS			45
 #define INV_ICM42607_TEMP_STARTUP_TIME_MS		77
 
+/*
+ * Suspend delay assumed from other icm42600 series device, not
+ * documented in datasheet.
+ */
+#define INV_ICM42607_SUSPEND_DELAY_MS			(2 * USEC_PER_MSEC)
+
 typedef int (*inv_icm42607_bus_setup)(struct inv_icm42607_state *);
 
 extern const struct regmap_config inv_icm42607_regmap_config;
 extern const struct inv_icm42607_hw inv_icm42607_hw_data;
 extern const struct inv_icm42607_hw inv_icm42607p_hw_data;
+extern const struct dev_pm_ops inv_icm42607_pm_ops;
 
 int inv_icm42607_core_probe(struct regmap *regmap,
 			    const struct inv_icm42607_hw *hw,
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +139 -0

192 lines not on this page · raw message

drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c +1 -0
index bde931752eb8..aed04be28528 100644
@@ -85,6 +85,7 @@ static struct i2c_driver inv_icm42607_driver = {
 	.driver = {
 		.name = "inv-icm42607-i2c",
 		.of_match_table = inv_icm42607_of_matches,
+		.pm = pm_ptr(&inv_icm42607_pm_ops),
 	},
 	.id_table = inv_icm42607_id,
 	.probe = inv_icm42607_probe,
drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c +1 -0
index 6072ed7adc86..137cd34582d8 100644
@@ -95,6 +95,7 @@ static struct spi_driver inv_icm42607_driver = {
 	.driver = {
 		.name = "inv-icm42607-spi",
 		.of_match_table = inv_icm42607_of_matches,
+		.pm = pm_ptr(&inv_icm42607_pm_ops),
 	},
 	.id_table = inv_icm42607_spi_id_table,
 	.probe = inv_icm42607_probe,
Signature · 1 line
2.43.0
#13 lore raw

Re: [PATCH V13 5/9] iio: imu: inv_icm42607: Add PM support for icm42607

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider: - [High] Missing synchronous suspend during driver unbind leaves hardware sensors powered on and leaking…

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Missing synchronous suspend during driver unbind leaves hardware sensors powered on and leaking power.
- [Medium] Unconditional 45ms sleep during gyro power-off injects unnecessary delay on every suspend transition.
- [Low] Incorrect constant used for defining the autosuspend delay.
--

commit c053e5ed4a86d71f412c402ec80e9602b6677c2a
Author: Chris Morgan <[email protected]>

iio: imu: inv_icm42607: Add PM support for icm42607

Add power management support for the ICM42607 device driver.

Quoted 3 lines
drivers/iio/imu/inv_icm42607/inv_icm42607.h +0 -0

[ ... ]

drivers/iio/imu/inv_icm42607/inv_icm42607.h struct inv_icm42607_state { · line 352

Quoted 9 lines
drivers/iio/imu/inv_icm42607/inv_icm42607.h +5 -0
@@ -334,11 +345,18 @@ struct inv_icm42607_state {
 #define INV_ICM42607_GYRO_STOP_TIME_MS			45
 #define INV_ICM42607_TEMP_STARTUP_TIME_MS		77
 
+/*
+ * Suspend delay assumed from other icm42600 series device, not
+ * documented in datasheet.
+ */
+#define INV_ICM42607_SUSPEND_DELAY_MS			(2 * USEC_PER_MSEC)

[Severity: Low]
Is this using the correct conversion macro? While (2 * USEC_PER_MSEC) evaluates to 2000, USEC_PER_MSEC means microseconds per millisecond. Using it to convert seconds to milliseconds is semantically confusing. Should this be 2 * MSEC_PER_SEC or just the literal 2000?

Quoted 7 lines
drivers/iio/imu/inv_icm42607/inv_icm42607.h +1 -0
+
 typedef int (*inv_icm42607_bus_setup)(struct inv_icm42607_state *);
 
 extern const struct regmap_config inv_icm42607_regmap_config;
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +0 -0

[ ... ]

Quoted 16 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +12 -0
@@ -103,6 +105,63 @@ const struct inv_icm42607_hw inv_icm42607p_hw_data = {
 };
 EXPORT_SYMBOL_NS_GPL(inv_icm42607p_hw_data, "IIO_ICM42607");
 
+static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st,
+				      enum inv_icm42607_sensor_mode gyro,
+				      enum inv_icm42607_sensor_mode accel,
+				      bool temp, unsigned int *sleep_ms)
+{
+	enum inv_icm42607_sensor_mode oldaccel = st->conf.accel.mode;
+	enum inv_icm42607_sensor_mode oldgyro = st->conf.gyro.mode;
+	bool oldtemp = st->conf.temp_en;
+	unsigned int sleepval_ms;
+	unsigned int val;
+	int ret;
+

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c const struct inv_icm42607_hw inv_icm42607p_hw_data = { · line 129

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +10 -0
+	if (gyro == oldgyro && accel == oldaccel && temp == oldtemp)
+		return 0;
+
+	/*
+	 * Datasheet on page 14.26 says we need to ensure the gyro sensor is on
+	 * for a minimum of 45ms. So if we transition from an on state to an
+	 * off state wait 45ms to ensure a sufficient pause before power off.
+	 */
+	if (!gyro && oldgyro)
+		fsleep(INV_ICM42607_GYRO_STOP_TIME_MS * USEC_PER_MSEC);

[Severity: Medium]
Does this inject a 45ms delay into every runtime suspend transition?

The code unconditionally sleeps for 45ms when turning off the gyro. If the datasheet requires the gyro to remain ON for a minimum of 45ms after power-on, wouldn't it be better to track the power-on timestamp instead of delaying every power-off sequence, even if the gyro has been active for hours?

Quoted 3 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +3 -0
+
+	val = FIELD_PREP(INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK, gyro);
+	val |= FIELD_PREP(INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK, accel);

[ ... ]

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c int inv_icm42607_core_probe(struct regmap *regmap, · line 353

Quoted 13 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +7 -0
@@ -271,10 +342,78 @@ int inv_icm42607_core_probe(struct regmap *regmap,
 	if (ret)
 		return ret;
 
+	ret = devm_pm_runtime_set_active_enabled(dev);
+	if (ret)
+		return ret;
+
+	pm_runtime_set_autosuspend_delay(dev, INV_ICM42607_SUSPEND_DELAY_MS);
+	pm_runtime_use_autosuspend(dev);
+
 	return 0;
 }

[Severity: High]
Does this code leak power on unbind?

Since autosuspend is used, the device doesn't suspend synchronously when pm_runtime_put_sync() is called by the driver core on removal. Instead, an async autosuspend is queued.

When the devres cleanup action invokes pm_runtime_disable(), the pending autosuspend work is cancelled, meaning inv_icm42607_runtime_suspend() is never executed.

If the sensors remain fully powered on in the PWR_MGMT0 register, and the vddio regulator is shared with other devices, will this cause a permanent power leak? Would adding a driver remove callback that calls pm_runtime_dont_use_autosuspend() or pm_runtime_put_sync_suspend() ensure the device powers down synchronously?

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
maintainer
#14 lore raw

Re: [PATCH V13 5/9] iio: imu: inv_icm42607: Add PM support for icm42607

In reply to Chris Morgan
Quoted 5 lines · On Mon, 15 Jun 2026 12:25:48 -0500 Chris Morgan <[email protected]> wrote:

From: Chris Morgan <[email protected]>

Add power management support for the ICM42607 device driver.

A few things from taking a look at the sashiko report:
https://sashiko.dev/#/patchset/20260615172554.160910-1-macroalpha82%40gmail.com

Quoted 13 lines
---
 drivers/iio/imu/inv_icm42607/inv_icm42607.h   |  18 +++
 .../iio/imu/inv_icm42607/inv_icm42607_core.c  | 139 ++++++++++++++++++
 .../iio/imu/inv_icm42607/inv_icm42607_i2c.c   |   1 +
 .../iio/imu/inv_icm42607/inv_icm42607_spi.c   |   1 +
 4 files changed, 159 insertions(+)
drivers/iio/imu/inv_icm42607/inv_icm42607.h +0 -0
index a6a58571935f..4f4f541027dc 100644

drivers/iio/imu/inv_icm42607/inv_icm42607.h struct inv_icm42607_state { · line 352

Quoted 8 lines
drivers/iio/imu/inv_icm42607/inv_icm42607.h +5 -0
@@ -334,11 +345,18 @@ struct inv_icm42607_state {
 #define INV_ICM42607_GYRO_STOP_TIME_MS			45
 #define INV_ICM42607_TEMP_STARTUP_TIME_MS		77
 
+/*
+ * Suspend delay assumed from other icm42600 series device, not
+ * documented in datasheet.
+ */
+#define INV_ICM42607_SUSPEND_DELAY_MS			(2 * USEC_PER_MSEC)

Sashiko had a valid comment on this. MSEC_PER_SEC seems more appropriate given this is 2 seconds in milli seconds.

Quoted 43 lines
drivers/iio/imu/inv_icm42607/inv_icm42607.h +2 -0
+
 typedef int (*inv_icm42607_bus_setup)(struct inv_icm42607_state *);
 
 extern const struct regmap_config inv_icm42607_regmap_config;
 extern const struct inv_icm42607_hw inv_icm42607_hw_data;
 extern const struct inv_icm42607_hw inv_icm42607p_hw_data;
+extern const struct dev_pm_ops inv_icm42607_pm_ops;
 
 int inv_icm42607_core_probe(struct regmap *regmap,
 			    const struct inv_icm42607_hw *hw,
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +11 -0
index 4b8e19091786..64f5d263de4f 100644
@@ -4,6 +4,7 @@
  */
 
 #include <linux/bitfield.h>
+#include <linux/cleanup.h>
 #include <linux/delay.h>
 #include <linux/dev_printk.h>
 #include <linux/device/devres.h>
@@ -11,6 +12,7 @@
 #include <linux/iio/iio.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/time.h>
@@ -103,6 +105,63 @@ const struct inv_icm42607_hw inv_icm42607p_hw_data = {
 };
 EXPORT_SYMBOL_NS_GPL(inv_icm42607p_hw_data, "IIO_ICM42607");
 
+static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st,
+				      enum inv_icm42607_sensor_mode gyro,
+				      enum inv_icm42607_sensor_mode accel,
+				      bool temp, unsigned int *sleep_ms)
+{
+	enum inv_icm42607_sensor_mode oldaccel = st->conf.accel.mode;
+	enum inv_icm42607_sensor_mode oldgyro = st->conf.gyro.mode;
+	bool oldtemp = st->conf.temp_en;
+	unsigned int sleepval_ms;

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c const struct inv_icm42607_hw inv_icm42607p_hw_data = { · line 126

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +10 -0
+	unsigned int val;
+	int ret;
+
+	if (gyro == oldgyro && accel == oldaccel && temp == oldtemp)
+		return 0;
+
+	/*
+	 * Datasheet on page 14.26 says we need to ensure the gyro sensor is on
+	 * for a minimum of 45ms. So if we transition from an on state to an
+	 * off state wait 45ms to ensure a sufficient pause before power off.

Sashiko commented on this.. I think what we could do with adding to the comment is what the path is that didn't pass through this function which would ensure we have been on for 30 of this msecs already.

Quoted 50 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +39 -0
+	 */
+	if (!gyro && oldgyro)
+		fsleep(INV_ICM42607_GYRO_STOP_TIME_MS * USEC_PER_MSEC);
+
+	val = FIELD_PREP(INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK, gyro);
+	val |= FIELD_PREP(INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK, accel);
+	ret = regmap_write(st->map, INV_ICM42607_REG_PWR_MGMT0, val);
+	if (ret)
+		return ret;
+
+	st->conf.gyro.mode = gyro;
+	st->conf.accel.mode = accel;
+	st->conf.temp_en = temp;
+
+	/*
+	 * If a state change occurs from off to on, sleep for the startup
+	 * time of the sensor, unless a sleep_ms is specified. Since more
+	 * than one sensor can be transitioned from off to on, select the
+	 * maximum time from each of the sensors changing from off to on.
+	 */
+	sleepval_ms = 0;
+	if (temp && !oldtemp)
+		sleepval_ms = max(sleepval_ms, INV_ICM42607_TEMP_STARTUP_TIME_MS);
+
+	if (accel && !oldaccel)
+		sleepval_ms = max(sleepval_ms, INV_ICM42607_ACCEL_STARTUP_TIME_MS);
+
+	if (gyro && !oldgyro)
+		sleepval_ms = max(sleepval_ms, INV_ICM42607_GYRO_STARTUP_TIME_MS);
+
+	if (sleep_ms)
+		*sleep_ms = sleepval_ms;
+	else if (sleepval_ms)
+		fsleep(sleepval_ms * USEC_PER_MSEC);
+
+	return 0;
+}
 
 
 int inv_icm42607_core_probe(struct regmap *regmap,
@@ -236,6 +305,8 @@ int inv_icm42607_core_probe(struct regmap *regmap,
 	if (!st)
 		return -ENOMEM;
 
+	dev_set_drvdata(dev, st);
+
 	ret = devm_mutex_init(dev, &st->lock);
 	if (ret)
 		return ret;

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c int inv_icm42607_core_probe(struct regmap *regmap, · line 350

Quoted 9 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +6 -0
@@ -271,10 +342,78 @@ int inv_icm42607_core_probe(struct regmap *regmap,
 	if (ret)
 		return ret;
 
+	ret = devm_pm_runtime_set_active_enabled(dev);
+	if (ret)
+		return ret;
+
+	pm_runtime_set_autosuspend_delay(dev, INV_ICM42607_SUSPEND_DELAY_MS);
+	pm_runtime_use_autosuspend(dev);

Sashiko does put out some stuff here. Please take a look and work out or test if it is right (I think not but haven't checked that carefully!) From a quick look I think that the auto disabling of autosuspend does a rpm_idle() that should result in it suspending...

Quoted 4 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +1 -0
+
 	return 0;
 }
 EXPORT_SYMBOL_NS_GPL(inv_icm42607_core_probe, "IIO_ICM42607");
#15 lore raw

Re: [PATCH V13 5/9] iio: imu: inv_icm42607: Add PM support for icm42607

Quoted 85 lines · Jonathan Cameron
Quoted 5 lines · On Mon, 15 Jun 2026 12:25:48 -0500 Chris Morgan <[email protected]> wrote:

From: Chris Morgan <[email protected]>

Add power management support for the ICM42607 device driver.

A few things from taking a look at the sashiko report:
https://sashiko.dev/#/patchset/20260615172554.160910-1-macroalpha82%40gmail.com

Quoted 13 lines
---
 drivers/iio/imu/inv_icm42607/inv_icm42607.h   |  18 +++
 .../iio/imu/inv_icm42607/inv_icm42607_core.c  | 139 ++++++++++++++++++
 .../iio/imu/inv_icm42607/inv_icm42607_i2c.c   |   1 +
 .../iio/imu/inv_icm42607/inv_icm42607_spi.c   |   1 +
 4 files changed, 159 insertions(+)
drivers/iio/imu/inv_icm42607/inv_icm42607.h +0 -0
index a6a58571935f..4f4f541027dc 100644

drivers/iio/imu/inv_icm42607/inv_icm42607.h struct inv_icm42607_state { · line 352

Quoted 8 lines
drivers/iio/imu/inv_icm42607/inv_icm42607.h +5 -0
@@ -334,11 +345,18 @@ struct inv_icm42607_state {
 #define INV_ICM42607_GYRO_STOP_TIME_MS			45
 #define INV_ICM42607_TEMP_STARTUP_TIME_MS		77
 
+/*
+ * Suspend delay assumed from other icm42600 series device, not
+ * documented in datasheet.
+ */
+#define INV_ICM42607_SUSPEND_DELAY_MS			(2 * USEC_PER_MSEC)

Sashiko had a valid comment on this. MSEC_PER_SEC seems more appropriate given this is 2 seconds in milli seconds.

Quoted 49 lines
drivers/iio/imu/inv_icm42607/inv_icm42607.h +2 -0
+
 typedef int (*inv_icm42607_bus_setup)(struct inv_icm42607_state *);
 
 extern const struct regmap_config inv_icm42607_regmap_config;
 extern const struct inv_icm42607_hw inv_icm42607_hw_data;
 extern const struct inv_icm42607_hw inv_icm42607p_hw_data;
+extern const struct dev_pm_ops inv_icm42607_pm_ops;
 
 int inv_icm42607_core_probe(struct regmap *regmap,
 			    const struct inv_icm42607_hw *hw,
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +17 -0
index 4b8e19091786..64f5d263de4f 100644
@@ -4,6 +4,7 @@
  */
 
 #include <linux/bitfield.h>
+#include <linux/cleanup.h>
 #include <linux/delay.h>
 #include <linux/dev_printk.h>
 #include <linux/device/devres.h>
@@ -11,6 +12,7 @@
 #include <linux/iio/iio.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/time.h>
@@ -103,6 +105,63 @@ const struct inv_icm42607_hw inv_icm42607p_hw_data = {
 };
 EXPORT_SYMBOL_NS_GPL(inv_icm42607p_hw_data, "IIO_ICM42607");
 
+static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st,
+				      enum inv_icm42607_sensor_mode gyro,
+				      enum inv_icm42607_sensor_mode accel,
+				      bool temp, unsigned int *sleep_ms)
+{
+	enum inv_icm42607_sensor_mode oldaccel = st->conf.accel.mode;
+	enum inv_icm42607_sensor_mode oldgyro = st->conf.gyro.mode;
+	bool oldtemp = st->conf.temp_en;
+	unsigned int sleepval_ms;
+	unsigned int val;
+	int ret;
+
+	if (gyro == oldgyro && accel == oldaccel && temp == oldtemp)
+		return 0;
+
Quoted 8 lines

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c const struct inv_icm42607_hw inv_icm42607p_hw_data = { · line 126

Quoted 4 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +4 -0
+	/*
+	 * Datasheet on page 14.26 says we need to ensure the gyro sensor is on
+	 * for a minimum of 45ms. So if we transition from an on state to an
+	 * off state wait 45ms to ensure a sufficient pause before power off.

Sashiko commented on this.. I think what we could do with adding to the comment is what the path is that didn't pass through this function which would ensure we have been on for 30 of this msecs already.

I'm going to track whatever time the gyro started, and then if less than 45ms has elapsed just pause the remaining amount of time.

Quoted 54 lines
Quoted 54 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +39 -0
+	 */
+	if (!gyro && oldgyro)
+		fsleep(INV_ICM42607_GYRO_STOP_TIME_MS * USEC_PER_MSEC);
+
+	val = FIELD_PREP(INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK, gyro);
+	val |= FIELD_PREP(INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK, accel);
+	ret = regmap_write(st->map, INV_ICM42607_REG_PWR_MGMT0, val);
+	if (ret)
+		return ret;
+
+	st->conf.gyro.mode = gyro;
+	st->conf.accel.mode = accel;
+	st->conf.temp_en = temp;
+
+	/*
+	 * If a state change occurs from off to on, sleep for the startup
+	 * time of the sensor, unless a sleep_ms is specified. Since more
+	 * than one sensor can be transitioned from off to on, select the
+	 * maximum time from each of the sensors changing from off to on.
+	 */
+	sleepval_ms = 0;
+	if (temp && !oldtemp)
+		sleepval_ms = max(sleepval_ms, INV_ICM42607_TEMP_STARTUP_TIME_MS);
+
+	if (accel && !oldaccel)
+		sleepval_ms = max(sleepval_ms, INV_ICM42607_ACCEL_STARTUP_TIME_MS);
+
+	if (gyro && !oldgyro)
+		sleepval_ms = max(sleepval_ms, INV_ICM42607_GYRO_STARTUP_TIME_MS);
+
+	if (sleep_ms)
+		*sleep_ms = sleepval_ms;
+	else if (sleepval_ms)
+		fsleep(sleepval_ms * USEC_PER_MSEC);
+
+	return 0;
+}
 
 
 int inv_icm42607_core_probe(struct regmap *regmap,
@@ -236,6 +305,8 @@ int inv_icm42607_core_probe(struct regmap *regmap,
 	if (!st)
 		return -ENOMEM;
 
+	dev_set_drvdata(dev, st);
+
 	ret = devm_mutex_init(dev, &st->lock);
 	if (ret)
 		return ret;
@@ -271,10 +342,78 @@ int inv_icm42607_core_probe(struct regmap *regmap,
 	if (ret)
 		return ret;
 
Quoted 11 lines

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c int inv_icm42607_core_probe(struct regmap *regmap, · line 350

Quoted 6 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +6 -0
+	ret = devm_pm_runtime_set_active_enabled(dev);
+	if (ret)
+		return ret;
+
+	pm_runtime_set_autosuspend_delay(dev, INV_ICM42607_SUSPEND_DELAY_MS);
+	pm_runtime_use_autosuspend(dev);

Sashiko does put out some stuff here. Please take a look and work out or test if it is right (I think not but haven't checked that carefully!) From a quick look I think that the auto disabling of autosuspend does a rpm_idle() that should result in it suspending...

I see a few other drivers adding one more call to devm_pm_runtime_enable() so I'm going to see how that works out.

Quoted 5 lines

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c int inv_icm42607_core_probe(struct regmap *regmap, · line 354

Quoted 5 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +1 -0
+
 	return 0;
 }
 EXPORT_SYMBOL_NS_GPL(inv_icm42607_core_probe, "IIO_ICM42607");

Thank you,
Chris

A message that is not in the archive (sent off-list or not yet received): [email protected]

#17 lore raw

Re: [PATCH V13 5/9] iio: imu: inv_icm42607: Add PM support for icm42607

Quoted 164 lines · Chris Morgan
Quoted 85 lines · Jonathan Cameron
Quoted 5 lines · On Mon, 15 Jun 2026 12:25:48 -0500 Chris Morgan <[email protected]> wrote:

From: Chris Morgan <[email protected]>

Add power management support for the ICM42607 device driver.

A few things from taking a look at the sashiko report:
https://sashiko.dev/#/patchset/20260615172554.160910-1-macroalpha82%40gmail.com

Quoted 13 lines
---
 drivers/iio/imu/inv_icm42607/inv_icm42607.h   |  18 +++
 .../iio/imu/inv_icm42607/inv_icm42607_core.c  | 139 ++++++++++++++++++
 .../iio/imu/inv_icm42607/inv_icm42607_i2c.c   |   1 +
 .../iio/imu/inv_icm42607/inv_icm42607_spi.c   |   1 +
 4 files changed, 159 insertions(+)
drivers/iio/imu/inv_icm42607/inv_icm42607.h +0 -0
index a6a58571935f..4f4f541027dc 100644

drivers/iio/imu/inv_icm42607/inv_icm42607.h struct inv_icm42607_state { · line 352

Quoted 8 lines
drivers/iio/imu/inv_icm42607/inv_icm42607.h +5 -0
@@ -334,11 +345,18 @@ struct inv_icm42607_state {
 #define INV_ICM42607_GYRO_STOP_TIME_MS			45
 #define INV_ICM42607_TEMP_STARTUP_TIME_MS		77
 
+/*
+ * Suspend delay assumed from other icm42600 series device, not
+ * documented in datasheet.
+ */
+#define INV_ICM42607_SUSPEND_DELAY_MS			(2 * USEC_PER_MSEC)

Sashiko had a valid comment on this. MSEC_PER_SEC seems more appropriate given this is 2 seconds in milli seconds.

Quoted 49 lines
drivers/iio/imu/inv_icm42607/inv_icm42607.h +2 -0
+
 typedef int (*inv_icm42607_bus_setup)(struct inv_icm42607_state *);
 
 extern const struct regmap_config inv_icm42607_regmap_config;
 extern const struct inv_icm42607_hw inv_icm42607_hw_data;
 extern const struct inv_icm42607_hw inv_icm42607p_hw_data;
+extern const struct dev_pm_ops inv_icm42607_pm_ops;
 
 int inv_icm42607_core_probe(struct regmap *regmap,
 			    const struct inv_icm42607_hw *hw,
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +17 -0
index 4b8e19091786..64f5d263de4f 100644
@@ -4,6 +4,7 @@
  */
 
 #include <linux/bitfield.h>
+#include <linux/cleanup.h>
 #include <linux/delay.h>
 #include <linux/dev_printk.h>
 #include <linux/device/devres.h>
@@ -11,6 +12,7 @@
 #include <linux/iio/iio.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/time.h>
@@ -103,6 +105,63 @@ const struct inv_icm42607_hw inv_icm42607p_hw_data = {
 };
 EXPORT_SYMBOL_NS_GPL(inv_icm42607p_hw_data, "IIO_ICM42607");
 
+static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st,
+				      enum inv_icm42607_sensor_mode gyro,
+				      enum inv_icm42607_sensor_mode accel,
+				      bool temp, unsigned int *sleep_ms)
+{
+	enum inv_icm42607_sensor_mode oldaccel = st->conf.accel.mode;
+	enum inv_icm42607_sensor_mode oldgyro = st->conf.gyro.mode;
+	bool oldtemp = st->conf.temp_en;
+	unsigned int sleepval_ms;
+	unsigned int val;
+	int ret;
+
+	if (gyro == oldgyro && accel == oldaccel && temp == oldtemp)
+		return 0;
+
Quoted 8 lines

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c const struct inv_icm42607_hw inv_icm42607p_hw_data = { · line 126

Quoted 4 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +4 -0
+	/*
+	 * Datasheet on page 14.26 says we need to ensure the gyro sensor is on
+	 * for a minimum of 45ms. So if we transition from an on state to an
+	 * off state wait 45ms to ensure a sufficient pause before power off.

Sashiko commented on this.. I think what we could do with adding to the comment is what the path is that didn't pass through this function which would ensure we have been on for 30 of this msecs already.

I'm going to track whatever time the gyro started, and then if less than 45ms has elapsed just pause the remaining amount of time.

Quoted 54 lines
Quoted 54 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +39 -0
+	 */
+	if (!gyro && oldgyro)
+		fsleep(INV_ICM42607_GYRO_STOP_TIME_MS * USEC_PER_MSEC);
+
+	val = FIELD_PREP(INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK, gyro);
+	val |= FIELD_PREP(INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK, accel);
+	ret = regmap_write(st->map, INV_ICM42607_REG_PWR_MGMT0, val);
+	if (ret)
+		return ret;
+
+	st->conf.gyro.mode = gyro;
+	st->conf.accel.mode = accel;
+	st->conf.temp_en = temp;
+
+	/*
+	 * If a state change occurs from off to on, sleep for the startup
+	 * time of the sensor, unless a sleep_ms is specified. Since more
+	 * than one sensor can be transitioned from off to on, select the
+	 * maximum time from each of the sensors changing from off to on.
+	 */
+	sleepval_ms = 0;
+	if (temp && !oldtemp)
+		sleepval_ms = max(sleepval_ms, INV_ICM42607_TEMP_STARTUP_TIME_MS);
+
+	if (accel && !oldaccel)
+		sleepval_ms = max(sleepval_ms, INV_ICM42607_ACCEL_STARTUP_TIME_MS);
+
+	if (gyro && !oldgyro)
+		sleepval_ms = max(sleepval_ms, INV_ICM42607_GYRO_STARTUP_TIME_MS);
+
+	if (sleep_ms)
+		*sleep_ms = sleepval_ms;
+	else if (sleepval_ms)
+		fsleep(sleepval_ms * USEC_PER_MSEC);
+
+	return 0;
+}
 
 
 int inv_icm42607_core_probe(struct regmap *regmap,
@@ -236,6 +305,8 @@ int inv_icm42607_core_probe(struct regmap *regmap,
 	if (!st)
 		return -ENOMEM;
 
+	dev_set_drvdata(dev, st);
+
 	ret = devm_mutex_init(dev, &st->lock);
 	if (ret)
 		return ret;
@@ -271,10 +342,78 @@ int inv_icm42607_core_probe(struct regmap *regmap,
 	if (ret)
 		return ret;
 
Quoted 11 lines

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c int inv_icm42607_core_probe(struct regmap *regmap, · line 350

Quoted 6 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +6 -0
+	ret = devm_pm_runtime_set_active_enabled(dev);
+	if (ret)
+		return ret;
+
+	pm_runtime_set_autosuspend_delay(dev, INV_ICM42607_SUSPEND_DELAY_MS);
+	pm_runtime_use_autosuspend(dev);

Sashiko does put out some stuff here. Please take a look and work out or test if it is right (I think not but haven't checked that carefully!) From a quick look I think that the auto disabling of autosuspend does a rpm_idle() that should result in it suspending...

Quoted 2 lines

I see a few other drivers adding one more call to devm_pm_runtime_enable() so I'm going to see how that works out.

Obviously that didn't work, but digging in much deeper into the PM code I see that devm_pm_runtime_set_active_enabled() returns devm_pm_runtime_enable(), which sets devm_add_action_or_reset() on pm_runtime_disable_action(), which calls pm_runtime_dont_use_autosuspend() and pm_runtime_disable(). Shouldn't this work, or am I missing something? Basically when the driver detaches shouldn't this chain end up calling pm_runtime_dont_use_autosuspend()?

Thank you,
Chris

Quoted 9 lines
Quoted 6 lines

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c int inv_icm42607_core_probe(struct regmap *regmap, · line 354

Quoted 6 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +1 -0
+
 	return 0;
 }
 EXPORT_SYMBOL_NS_GPL(inv_icm42607_core_probe, "IIO_ICM42607");

Thank you,
Chris

maintainer
#18 lore raw

Re: [PATCH V13 5/9] iio: imu: inv_icm42607: Add PM support for icm42607

Quoted 168 lines · On Tue, 23 Jun 2026 13:08:02 -0500 Chris Morgan <[email protected]> wrote:
Quoted 164 lines · Chris Morgan
Quoted 85 lines · Jonathan Cameron
Quoted 5 lines · On Mon, 15 Jun 2026 12:25:48 -0500 Chris Morgan <[email protected]> wrote:

From: Chris Morgan <[email protected]>

Add power management support for the ICM42607 device driver.

A few things from taking a look at the sashiko report:
https://sashiko.dev/#/patchset/20260615172554.160910-1-macroalpha82%40gmail.com

Quoted 13 lines
---
 drivers/iio/imu/inv_icm42607/inv_icm42607.h   |  18 +++
 .../iio/imu/inv_icm42607/inv_icm42607_core.c  | 139 ++++++++++++++++++
 .../iio/imu/inv_icm42607/inv_icm42607_i2c.c   |   1 +
 .../iio/imu/inv_icm42607/inv_icm42607_spi.c   |   1 +
 4 files changed, 159 insertions(+)
drivers/iio/imu/inv_icm42607/inv_icm42607.h +0 -0
index a6a58571935f..4f4f541027dc 100644

drivers/iio/imu/inv_icm42607/inv_icm42607.h struct inv_icm42607_state { · line 352

Quoted 8 lines
drivers/iio/imu/inv_icm42607/inv_icm42607.h +5 -0
@@ -334,11 +345,18 @@ struct inv_icm42607_state {
 #define INV_ICM42607_GYRO_STOP_TIME_MS			45
 #define INV_ICM42607_TEMP_STARTUP_TIME_MS		77
 
+/*
+ * Suspend delay assumed from other icm42600 series device, not
+ * documented in datasheet.
+ */
+#define INV_ICM42607_SUSPEND_DELAY_MS			(2 * USEC_PER_MSEC)  

Sashiko had a valid comment on this. MSEC_PER_SEC seems more appropriate given this is 2 seconds in milli seconds.

Quoted 49 lines
drivers/iio/imu/inv_icm42607/inv_icm42607.h +2 -0
+
 typedef int (*inv_icm42607_bus_setup)(struct inv_icm42607_state *);
 
 extern const struct regmap_config inv_icm42607_regmap_config;
 extern const struct inv_icm42607_hw inv_icm42607_hw_data;
 extern const struct inv_icm42607_hw inv_icm42607p_hw_data;
+extern const struct dev_pm_ops inv_icm42607_pm_ops;
 
 int inv_icm42607_core_probe(struct regmap *regmap,
 			    const struct inv_icm42607_hw *hw,
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +17 -0
index 4b8e19091786..64f5d263de4f 100644
@@ -4,6 +4,7 @@
  */
 
 #include <linux/bitfield.h>
+#include <linux/cleanup.h>
 #include <linux/delay.h>
 #include <linux/dev_printk.h>
 #include <linux/device/devres.h>
@@ -11,6 +12,7 @@
 #include <linux/iio/iio.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/time.h>
@@ -103,6 +105,63 @@ const struct inv_icm42607_hw inv_icm42607p_hw_data = {
 };
 EXPORT_SYMBOL_NS_GPL(inv_icm42607p_hw_data, "IIO_ICM42607");
 
+static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st,
+				      enum inv_icm42607_sensor_mode gyro,
+				      enum inv_icm42607_sensor_mode accel,
+				      bool temp, unsigned int *sleep_ms)
+{
+	enum inv_icm42607_sensor_mode oldaccel = st->conf.accel.mode;
+	enum inv_icm42607_sensor_mode oldgyro = st->conf.gyro.mode;
+	bool oldtemp = st->conf.temp_en;
+	unsigned int sleepval_ms;
+	unsigned int val;
+	int ret;
+
+	if (gyro == oldgyro && accel == oldaccel && temp == oldtemp)
+		return 0;
+
Quoted 8 lines

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c const struct inv_icm42607_hw inv_icm42607p_hw_data = { · line 126

Quoted 4 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +4 -0
+	/*
+	 * Datasheet on page 14.26 says we need to ensure the gyro sensor is on
+	 * for a minimum of 45ms. So if we transition from an on state to an
+	 * off state wait 45ms to ensure a sufficient pause before power off.  

Sashiko commented on this.. I think what we could do with adding to the comment is what the path is that didn't pass through this function which would ensure we have been on for 30 of this msecs already.

I'm going to track whatever time the gyro started, and then if less than 45ms has elapsed just pause the remaining amount of time.

Quoted 54 lines
Quoted 54 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +39 -0
+	 */
+	if (!gyro && oldgyro)
+		fsleep(INV_ICM42607_GYRO_STOP_TIME_MS * USEC_PER_MSEC);
+
+	val = FIELD_PREP(INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK, gyro);
+	val |= FIELD_PREP(INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK, accel);
+	ret = regmap_write(st->map, INV_ICM42607_REG_PWR_MGMT0, val);
+	if (ret)
+		return ret;
+
+	st->conf.gyro.mode = gyro;
+	st->conf.accel.mode = accel;
+	st->conf.temp_en = temp;
+
+	/*
+	 * If a state change occurs from off to on, sleep for the startup
+	 * time of the sensor, unless a sleep_ms is specified. Since more
+	 * than one sensor can be transitioned from off to on, select the
+	 * maximum time from each of the sensors changing from off to on.
+	 */
+	sleepval_ms = 0;
+	if (temp && !oldtemp)
+		sleepval_ms = max(sleepval_ms, INV_ICM42607_TEMP_STARTUP_TIME_MS);
+
+	if (accel && !oldaccel)
+		sleepval_ms = max(sleepval_ms, INV_ICM42607_ACCEL_STARTUP_TIME_MS);
+
+	if (gyro && !oldgyro)
+		sleepval_ms = max(sleepval_ms, INV_ICM42607_GYRO_STARTUP_TIME_MS);
+
+	if (sleep_ms)
+		*sleep_ms = sleepval_ms;
+	else if (sleepval_ms)
+		fsleep(sleepval_ms * USEC_PER_MSEC);
+
+	return 0;
+}  
 
 
 int inv_icm42607_core_probe(struct regmap *regmap,
@@ -236,6 +305,8 @@ int inv_icm42607_core_probe(struct regmap *regmap,
 	if (!st)
 		return -ENOMEM;
 
+	dev_set_drvdata(dev, st);
+
 	ret = devm_mutex_init(dev, &st->lock);
 	if (ret)
 		return ret;
@@ -271,10 +342,78 @@ int inv_icm42607_core_probe(struct regmap *regmap,
 	if (ret)
 		return ret;
 
Quoted 11 lines

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c int inv_icm42607_core_probe(struct regmap *regmap, · line 350

Quoted 6 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +6 -0
+	ret = devm_pm_runtime_set_active_enabled(dev);
+	if (ret)
+		return ret;
+
+	pm_runtime_set_autosuspend_delay(dev, INV_ICM42607_SUSPEND_DELAY_MS);
+	pm_runtime_use_autosuspend(dev);  

Sashiko does put out some stuff here. Please take a look and work out or test if it is right (I think not but haven't checked that carefully!) From a quick look I think that the auto disabling of autosuspend does a rpm_idle() that should result in it suspending...

Quoted 2 lines

I see a few other drivers adding one more call to devm_pm_runtime_enable() so I'm going to see how that works out.

Quoted 8 lines

Obviously that didn't work, but digging in much deeper into the PM code I see that devm_pm_runtime_set_active_enabled() returns devm_pm_runtime_enable(), which sets devm_add_action_or_reset() on pm_runtime_disable_action(), which calls pm_runtime_dont_use_autosuspend() and pm_runtime_disable(). Shouldn't this work, or am I missing something? Basically when the driver detaches shouldn't this chain end up calling pm_runtime_dont_use_autosuspend()?

Agreed. That was how I read things. The only thing I didn't entirely confirm (states involved were fiddly enough I'd want to check it with the actual driver!) was that pm_runtime_dont_use_autosuspend() ends up calling rpm_idle() in this case.

Jonathan

Quoted 13 lines

Thank you,
Chris

Quoted 9 lines
Quoted 6 lines

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c int inv_icm42607_core_probe(struct regmap *regmap, · line 354

Quoted 6 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +1 -0
+
 	return 0;
 }
 EXPORT_SYMBOL_NS_GPL(inv_icm42607_core_probe, "IIO_ICM42607");  

Thank you,
Chris

#19 lore raw

Re: [PATCH V13 5/9] iio: imu: inv_icm42607: Add PM support for icm42607

Quoted 179 lines · Jonathan Cameron
Quoted 168 lines · On Tue, 23 Jun 2026 13:08:02 -0500 Chris Morgan <[email protected]> wrote:
Quoted 164 lines · Chris Morgan
Quoted 85 lines · Jonathan Cameron
Quoted 5 lines · On Mon, 15 Jun 2026 12:25:48 -0500 Chris Morgan <[email protected]> wrote:

From: Chris Morgan <[email protected]>

Add power management support for the ICM42607 device driver.

A few things from taking a look at the sashiko report:
https://sashiko.dev/#/patchset/20260615172554.160910-1-macroalpha82%40gmail.com

Quoted 13 lines
---
 drivers/iio/imu/inv_icm42607/inv_icm42607.h   |  18 +++
 .../iio/imu/inv_icm42607/inv_icm42607_core.c  | 139 ++++++++++++++++++
 .../iio/imu/inv_icm42607/inv_icm42607_i2c.c   |   1 +
 .../iio/imu/inv_icm42607/inv_icm42607_spi.c   |   1 +
 4 files changed, 159 insertions(+)
drivers/iio/imu/inv_icm42607/inv_icm42607.h +0 -0
index a6a58571935f..4f4f541027dc 100644

drivers/iio/imu/inv_icm42607/inv_icm42607.h struct inv_icm42607_state { · line 352

Quoted 8 lines
drivers/iio/imu/inv_icm42607/inv_icm42607.h +5 -0
@@ -334,11 +345,18 @@ struct inv_icm42607_state {
 #define INV_ICM42607_GYRO_STOP_TIME_MS			45
 #define INV_ICM42607_TEMP_STARTUP_TIME_MS		77
 
+/*
+ * Suspend delay assumed from other icm42600 series device, not
+ * documented in datasheet.
+ */
+#define INV_ICM42607_SUSPEND_DELAY_MS			(2 * USEC_PER_MSEC)  

Sashiko had a valid comment on this. MSEC_PER_SEC seems more appropriate given this is 2 seconds in milli seconds.

Quoted 49 lines
drivers/iio/imu/inv_icm42607/inv_icm42607.h +2 -0
+
 typedef int (*inv_icm42607_bus_setup)(struct inv_icm42607_state *);
 
 extern const struct regmap_config inv_icm42607_regmap_config;
 extern const struct inv_icm42607_hw inv_icm42607_hw_data;
 extern const struct inv_icm42607_hw inv_icm42607p_hw_data;
+extern const struct dev_pm_ops inv_icm42607_pm_ops;
 
 int inv_icm42607_core_probe(struct regmap *regmap,
 			    const struct inv_icm42607_hw *hw,
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +17 -0
index 4b8e19091786..64f5d263de4f 100644
@@ -4,6 +4,7 @@
  */
 
 #include <linux/bitfield.h>
+#include <linux/cleanup.h>
 #include <linux/delay.h>
 #include <linux/dev_printk.h>
 #include <linux/device/devres.h>
@@ -11,6 +12,7 @@
 #include <linux/iio/iio.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
 #include <linux/time.h>
@@ -103,6 +105,63 @@ const struct inv_icm42607_hw inv_icm42607p_hw_data = {
 };
 EXPORT_SYMBOL_NS_GPL(inv_icm42607p_hw_data, "IIO_ICM42607");
 
+static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st,
+				      enum inv_icm42607_sensor_mode gyro,
+				      enum inv_icm42607_sensor_mode accel,
+				      bool temp, unsigned int *sleep_ms)
+{
+	enum inv_icm42607_sensor_mode oldaccel = st->conf.accel.mode;
+	enum inv_icm42607_sensor_mode oldgyro = st->conf.gyro.mode;
+	bool oldtemp = st->conf.temp_en;
+	unsigned int sleepval_ms;
+	unsigned int val;
+	int ret;
+
+	if (gyro == oldgyro && accel == oldaccel && temp == oldtemp)
+		return 0;
+
Quoted 8 lines

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c const struct inv_icm42607_hw inv_icm42607p_hw_data = { · line 126

Quoted 4 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +4 -0
+	/*
+	 * Datasheet on page 14.26 says we need to ensure the gyro sensor is on
+	 * for a minimum of 45ms. So if we transition from an on state to an
+	 * off state wait 45ms to ensure a sufficient pause before power off.  

Sashiko commented on this.. I think what we could do with adding to the comment is what the path is that didn't pass through this function which would ensure we have been on for 30 of this msecs already.

I'm going to track whatever time the gyro started, and then if less than 45ms has elapsed just pause the remaining amount of time.

Quoted 54 lines
Quoted 54 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +39 -0
+	 */
+	if (!gyro && oldgyro)
+		fsleep(INV_ICM42607_GYRO_STOP_TIME_MS * USEC_PER_MSEC);
+
+	val = FIELD_PREP(INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK, gyro);
+	val |= FIELD_PREP(INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK, accel);
+	ret = regmap_write(st->map, INV_ICM42607_REG_PWR_MGMT0, val);
+	if (ret)
+		return ret;
+
+	st->conf.gyro.mode = gyro;
+	st->conf.accel.mode = accel;
+	st->conf.temp_en = temp;
+
+	/*
+	 * If a state change occurs from off to on, sleep for the startup
+	 * time of the sensor, unless a sleep_ms is specified. Since more
+	 * than one sensor can be transitioned from off to on, select the
+	 * maximum time from each of the sensors changing from off to on.
+	 */
+	sleepval_ms = 0;
+	if (temp && !oldtemp)
+		sleepval_ms = max(sleepval_ms, INV_ICM42607_TEMP_STARTUP_TIME_MS);
+
+	if (accel && !oldaccel)
+		sleepval_ms = max(sleepval_ms, INV_ICM42607_ACCEL_STARTUP_TIME_MS);
+
+	if (gyro && !oldgyro)
+		sleepval_ms = max(sleepval_ms, INV_ICM42607_GYRO_STARTUP_TIME_MS);
+
+	if (sleep_ms)
+		*sleep_ms = sleepval_ms;
+	else if (sleepval_ms)
+		fsleep(sleepval_ms * USEC_PER_MSEC);
+
+	return 0;
+}  
 
 
 int inv_icm42607_core_probe(struct regmap *regmap,
@@ -236,6 +305,8 @@ int inv_icm42607_core_probe(struct regmap *regmap,
 	if (!st)
 		return -ENOMEM;
 
+	dev_set_drvdata(dev, st);
+
 	ret = devm_mutex_init(dev, &st->lock);
 	if (ret)
 		return ret;
@@ -271,10 +342,78 @@ int inv_icm42607_core_probe(struct regmap *regmap,
 	if (ret)
 		return ret;
 
Quoted 11 lines

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c int inv_icm42607_core_probe(struct regmap *regmap, · line 350

Quoted 6 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +6 -0
+	ret = devm_pm_runtime_set_active_enabled(dev);
+	if (ret)
+		return ret;
+
+	pm_runtime_set_autosuspend_delay(dev, INV_ICM42607_SUSPEND_DELAY_MS);
+	pm_runtime_use_autosuspend(dev);  

Sashiko does put out some stuff here. Please take a look and work out or test if it is right (I think not but haven't checked that carefully!) From a quick look I think that the auto disabling of autosuspend does a rpm_idle() that should result in it suspending...

Quoted 2 lines

I see a few other drivers adding one more call to devm_pm_runtime_enable() so I'm going to see how that works out.

Quoted 8 lines

Obviously that didn't work, but digging in much deeper into the PM code I see that devm_pm_runtime_set_active_enabled() returns devm_pm_runtime_enable(), which sets devm_add_action_or_reset() on pm_runtime_disable_action(), which calls pm_runtime_dont_use_autosuspend() and pm_runtime_disable(). Shouldn't this work, or am I missing something? Basically when the driver detaches shouldn't this chain end up calling pm_runtime_dont_use_autosuspend()?

Quoted 6 lines

Agreed. That was how I read things. The only thing I didn't entirely confirm (states involved were fiddly enough I'd want to check it with the actual driver!) was that pm_runtime_dont_use_autosuspend() ends up calling rpm_idle() in this case.

Jonathan

I dropped in a dev_warn on the rpm_idle() and can confirm when I unbound the driver it called rpm_idle(). So... yes?

Chris

Quoted 15 lines
Quoted 14 lines

Thank you,
Chris

Quoted 9 lines
Quoted 6 lines

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c int inv_icm42607_core_probe(struct regmap *regmap, · line 354

Quoted 6 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +1 -0
+
 	return 0;
 }
 EXPORT_SYMBOL_NS_GPL(inv_icm42607_core_probe, "IIO_ICM42607");  

Thank you,
Chris

#20 lore raw

PATCH v13 6/9 iio: imu: inv_icm42607: Add Temp Support in icm42607

In reply to Chris Morgan

From: Chris Morgan <[email protected]>

Add functions for reading temperature sensor data.

---
 drivers/iio/imu/inv_icm42607/Makefile         |  1 +
 drivers/iio/imu/inv_icm42607/inv_icm42607.h   |  3 +
 .../iio/imu/inv_icm42607/inv_icm42607_core.c  | 18 +++++
 .../iio/imu/inv_icm42607/inv_icm42607_temp.c  | 81 +++++++++++++++++++
 .../iio/imu/inv_icm42607/inv_icm42607_temp.h  | 37 +++++++++
 5 files changed, 140 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c
 create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_temp.h
drivers/iio/imu/inv_icm42607/Makefile +1 -0
index be109102e203..c04953ed42ce 100644
@@ -2,6 +2,7 @@
 
 obj-$(CONFIG_INV_ICM42607) += inv-icm42607.o
 inv-icm42607-y += inv_icm42607_core.o
+inv-icm42607-y += inv_icm42607_temp.o
 
 obj-$(CONFIG_INV_ICM42607_I2C) += inv-icm42607-i2c.o
 inv-icm42607-i2c-y += inv_icm42607_i2c.o
drivers/iio/imu/inv_icm42607/inv_icm42607.h +3 -0
index 4f4f541027dc..726b836582a2 100644
@@ -358,6 +358,9 @@ extern const struct inv_icm42607_hw inv_icm42607_hw_data;
 extern const struct inv_icm42607_hw inv_icm42607p_hw_data;
 extern const struct dev_pm_ops inv_icm42607_pm_ops;
 
+int inv_icm42607_set_temp_conf(struct inv_icm42607_state *st, bool enable,
+			       unsigned int *sleep_ms);
+
 int inv_icm42607_core_probe(struct regmap *regmap,
 			    const struct inv_icm42607_hw *hw,
 			    inv_icm42607_bus_setup bus_setup);
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +18 -0
index 64f5d263de4f..644cd7f821b9 100644
@@ -162,6 +162,24 @@ static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st,
 	return 0;
 }
 
+int inv_icm42607_set_temp_conf(struct inv_icm42607_state *st, bool enable,
+			       unsigned int *sleep_ms)
+{
+	unsigned int val;
+	int ret;
+
+	val = FIELD_PREP(INV_ICM42607_TEMP_CONFIG0_FILTER_MASK,
+			 INV_ICM42607_FILTER_BW_34HZ);
+	ret = regmap_update_bits(st->map, INV_ICM42607_REG_TEMP_CONFIG0,
+				 INV_ICM42607_TEMP_CONFIG0_FILTER_MASK, val);
+	if (ret)
+		return ret;
+
+	return inv_icm42607_set_pwr_mgmt0(st, st->conf.gyro.mode,
+					  st->conf.accel.mode, enable,
+					  sleep_ms);
+}
+
 static int inv_icm42607_set_conf(struct inv_icm42607_state *st,
 				 const struct inv_icm42607_conf *conf)
 {
drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c new file +81 -0

81 lines not on this page · raw message

drivers/iio/imu/inv_icm42607/inv_icm42607_temp.h new file +37 -0
new file mode 100644
index 000000000000..cb7b460ffb44
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2026 InvenSense, Inc.
+ */
+
+#ifndef INV_ICM42607_TEMP_H_
+#define INV_ICM42607_TEMP_H_
+
+#include <linux/bitops.h>
+
+struct iio_dev;
+struct iio_chan_spec;
+
+#define INV_ICM42607_TEMP_CHAN(_index)				\
+{								\
+	.type = IIO_TEMP,					\
+	.info_mask_separate =					\
+		BIT(IIO_CHAN_INFO_RAW) |			\
+		BIT(IIO_CHAN_INFO_OFFSET) |			\
+		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,				\
+	},							\
+}
+
+int inv_icm42607_temp_read_raw(struct iio_dev *indio_dev,
+			       struct iio_chan_spec const *chan,
+			       int *val, int *val2, long mask);
+
+#endif
Signature · 1 line
2.43.0
#21 lore raw

Re: [PATCH V13 6/9] iio: imu: inv_icm42607: Add Temp Support in icm42607

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [High] Prematurely mutating the temperature software state before calling the power management configuration bypasses state change detection, skipping the mandatory startup delay and causing reads of uninitialized data.

Pre-existing issues:
- [High] The temperature sensor read fails (returns -EINVAL) when the gyroscope and accelerometer are off because the device is placed in Sleep mode instead of Idle mode, disabling the internal RC oscillator. --

commit d36f0c461ef9d5076de90b75b6238be45c35148d
Author: Chris Morgan <[email protected]>
Subject: iio: imu: inv_icm42607: Add Temp Support in icm42607

Add functions for reading temperature sensor data.

[ ... ]

Quoted 4 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +0 -0
index 64f5d263de4f2..644cd7f821b92 100644

[ ... ]

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +6 -0
@@ -162,6 +162,24 @@ static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st,
 	return 0;
 }
 
+int inv_icm42607_set_temp_conf(struct inv_icm42607_state *st, bool enable,
+			       unsigned int *sleep_ms)
+{
+	unsigned int val;
+	int ret;
+

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st, · line 180

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +10 -0
+	val = FIELD_PREP(INV_ICM42607_TEMP_CONFIG0_FILTER_MASK,
+			 INV_ICM42607_FILTER_BW_34HZ);
+	ret = regmap_update_bits(st->map, INV_ICM42607_REG_TEMP_CONFIG0,
+				 INV_ICM42607_TEMP_CONFIG0_FILTER_MASK, val);
+	if (ret)
+		return ret;
+
+	return inv_icm42607_set_pwr_mgmt0(st, st->conf.gyro.mode,
+					  st->conf.accel.mode, enable,
+					  sleep_ms);

[Severity: High]
This is a pre-existing issue, but will this temperature read fail with -EINVAL if the gyroscope and accelerometer are off?

Looking at inv_icm42607_set_pwr_mgmt0(), it constructs the PWR_MGMT0 register value using only the gyro and accel mode masks:

    val = FIELD_PREP(INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK, gyro);
    val |= FIELD_PREP(INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK, accel);
    ret = regmap_write(st->map, INV_ICM42607_REG_PWR_MGMT0, val);

If both gyro and accel are off, val is 0, which places the device in Sleep mode instead of Idle mode. The internal RC oscillator required for temperature reads is disabled, causing the data register to return 0x8000 (INV_ICM42607_DATA_INVALID).

Should the IDLE bit be set when temp is true and the other sensors are inactive?

Quoted 2 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +2 -0
+}
+

[ ... ]

Quoted 5 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c new file +0 -0
new file mode 100644
index 0000000000000..9a60e1a478b08

[ ... ]

Quoted 5 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c new file +5 -0
+static int inv_icm42607_temp_read(struct inv_icm42607_state *st, s16 *temp)
+{
+	struct device *dev = regmap_get_device(st->map);
+	u8 raw[2];
+	int ret;

drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c line 33

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c new file +10 -0
+
+	PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
+	guard(mutex)(&st->lock);
+
+	st->conf.temp_en = true;
+	ret = inv_icm42607_set_temp_conf(st, st->conf.temp_en, NULL);

[Severity: High]
Does setting st->conf.temp_en to true before this call bypass the hardware configuration and startup delay?

Because st->conf.temp_en is mutated before the call, when inv_icm42607_set_temp_conf() calls inv_icm42607_set_pwr_mgmt0(), it will evaluate the state transition like this:

    bool oldtemp = st->conf.temp_en;
    ...
    if (gyro == oldgyro && accel == oldaccel && temp == oldtemp)
        return 0;

Since temp and oldtemp are now both true, the function returns early without writing to the power management register or waiting for the startup delay. Could this lead to reading uninitialized or desynchronized data?

Quoted 8 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c new file +8 -0
+	st->conf.temp_en = false;
+	if (ret)
+		return ret;
+
+	ret = regmap_bulk_read(st->map, INV_ICM42607_REG_TEMP_DATA1,
+			       raw, sizeof(raw));
+	if (ret)
+		return ret;

[ ... ]

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=6
maintainer
#22 lore raw

Re: [PATCH V13 6/9] iio: imu: inv_icm42607: Add Temp Support in icm42607

In reply to Chris Morgan
Quoted 5 lines · On Mon, 15 Jun 2026 12:25:49 -0500 Chris Morgan <[email protected]> wrote:

From: Chris Morgan <[email protected]>

Add functions for reading temperature sensor data.

Another sashiko reported thing. I'd definitely have missed this one and I think it is correct.

When I get caught up I'll post a thread to see if people feel we should generally just ask for Sashiko to reply on list.

Jonathan

Quoted 36 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +17 -0
index 64f5d263de4f..644cd7f821b9 100644
@@ -162,6 +162,24 @@ static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st,
 	return 0;
 }
 
+int inv_icm42607_set_temp_conf(struct inv_icm42607_state *st, bool enable,
+			       unsigned int *sleep_ms)
+{
+	unsigned int val;
+	int ret;
+
+	val = FIELD_PREP(INV_ICM42607_TEMP_CONFIG0_FILTER_MASK,
+			 INV_ICM42607_FILTER_BW_34HZ);
+	ret = regmap_update_bits(st->map, INV_ICM42607_REG_TEMP_CONFIG0,
+				 INV_ICM42607_TEMP_CONFIG0_FILTER_MASK, val);
+	if (ret)
+		return ret;
+
+	return inv_icm42607_set_pwr_mgmt0(st, st->conf.gyro.mode,
+					  st->conf.accel.mode, enable,
+					  sleep_ms);
+}
 
drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c new file +4 -0
new file mode 100644
index 000000000000..9a60e1a478b0
 
+static int inv_icm42607_temp_read(struct inv_icm42607_state *st, s16 *temp)
+{
+	struct device *dev = regmap_get_device(st->map);
+	u8 raw[2];

drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c line 32

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c new file +10 -0
+	int ret;
+
+	PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
+	guard(mutex)(&st->lock);
+
+	st->conf.temp_en = true;

Sashiko points out (seems right) that this sets the internal state before the power management routine expects it to be set. So why is this here as opposed to just passing true into the function that follows?

Quoted 16 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c new file +16 -0
+	ret = inv_icm42607_set_temp_conf(st, st->conf.temp_en, NULL);
+	st->conf.temp_en = false;
+	if (ret)
+		return ret;
+
+	ret = regmap_bulk_read(st->map, INV_ICM42607_REG_TEMP_DATA1,
+			       raw, sizeof(raw));
+	if (ret)
+		return ret;
+
+	*temp = get_unaligned_be16(raw);
+	if (*temp == INV_ICM42607_DATA_INVALID)
+		return -EINVAL;
+
+	return 0;
+}
#23 lore raw

Re: [PATCH V13 6/9] iio: imu: inv_icm42607: Add Temp Support in icm42607

Quoted 60 lines · Jonathan Cameron
Quoted 5 lines · On Mon, 15 Jun 2026 12:25:49 -0500 Chris Morgan <[email protected]> wrote:

From: Chris Morgan <[email protected]>

Add functions for reading temperature sensor data.

Another sashiko reported thing. I'd definitely have missed this one and I think it is correct.

When I get caught up I'll post a thread to see if people feel we should generally just ask for Sashiko to reply on list.

Jonathan

Quoted 43 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +17 -0
index 64f5d263de4f..644cd7f821b9 100644
@@ -162,6 +162,24 @@ static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st,
 	return 0;
 }
 
+int inv_icm42607_set_temp_conf(struct inv_icm42607_state *st, bool enable,
+			       unsigned int *sleep_ms)
+{
+	unsigned int val;
+	int ret;
+
+	val = FIELD_PREP(INV_ICM42607_TEMP_CONFIG0_FILTER_MASK,
+			 INV_ICM42607_FILTER_BW_34HZ);
+	ret = regmap_update_bits(st->map, INV_ICM42607_REG_TEMP_CONFIG0,
+				 INV_ICM42607_TEMP_CONFIG0_FILTER_MASK, val);
+	if (ret)
+		return ret;
+
+	return inv_icm42607_set_pwr_mgmt0(st, st->conf.gyro.mode,
+					  st->conf.accel.mode, enable,
+					  sleep_ms);
+}
 
drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c new file +11 -0
new file mode 100644
index 000000000000..9a60e1a478b0
 
+static int inv_icm42607_temp_read(struct inv_icm42607_state *st, s16 *temp)
+{
+	struct device *dev = regmap_get_device(st->map);
+	u8 raw[2];
+	int ret;
+
+	PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
Quoted 8 lines

drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c line 32

Quoted 3 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c new file +3 -0
+	guard(mutex)(&st->lock);
+
+	st->conf.temp_en = true;

Sashiko points out (seems right) that this sets the internal state before the power management routine expects it to be set. So why is this here as opposed to just passing true into the function that follows?

I'm going to take setting of state out of the power management function entirely, as well as killing off any "temp_en" since technically there is nothing to enable on the temp sensor. I'll do a check when you try to read the temp to see if any sensors are on and if none are then I will power up the accel sensor (since it uses about 5x less power than the gyro per the datasheet).

Quoted 17 lines
Quoted 7 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c new file +6 -0
+	ret = inv_icm42607_set_temp_conf(st, st->conf.temp_en, NULL);
+	st->conf.temp_en = false;
+	if (ret)
+		return ret;
+
+	ret = regmap_bulk_read(st->map, INV_ICM42607_REG_TEMP_DATA1,

drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c line 48

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c new file +10 -0
+			       raw, sizeof(raw));
+	if (ret)
+		return ret;
+
+	*temp = get_unaligned_be16(raw);
+	if (*temp == INV_ICM42607_DATA_INVALID)
+		return -EINVAL;
+
+	return 0;
+}

Thank you,
Chris

#24 lore raw

PATCH v13 7/9 iio: imu: inv_icm42607: Add Accelerometer for icm42607

In reply to Chris Morgan

From: Chris Morgan <[email protected]>

Add icm42607 accelerometer sensor for icm42607.

---
 drivers/iio/imu/inv_icm42607/Makefile         |   1 +
 drivers/iio/imu/inv_icm42607/inv_icm42607.h   |  34 ++
 .../iio/imu/inv_icm42607/inv_icm42607_accel.c | 373 ++++++++++++++++++
 .../iio/imu/inv_icm42607/inv_icm42607_core.c  |  61 +++
 4 files changed, 469 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c
drivers/iio/imu/inv_icm42607/Makefile +1 -0
index c04953ed42ce..d74b23b1e1be 100644
@@ -2,6 +2,7 @@
 
 obj-$(CONFIG_INV_ICM42607) += inv-icm42607.o
 inv-icm42607-y += inv_icm42607_core.o
+inv-icm42607-y += inv_icm42607_accel.o
 inv-icm42607-y += inv_icm42607_temp.o
 
 obj-$(CONFIG_INV_ICM42607_I2C) += inv-icm42607-i2c.o
drivers/iio/imu/inv_icm42607/inv_icm42607.h +34 -0
index 726b836582a2..c71d667dadb7 100644
@@ -86,6 +86,17 @@ enum inv_icm42607_filter_bw {
 	INV_ICM42607_FILTER_BW_NB
 };
 
+/* Low-Power mode sensor data filter (averaging) */
+enum inv_icm42607_filter_avg {
+	INV_ICM42607_FILTER_AVG_2X = 0,
+	INV_ICM42607_FILTER_AVG_4X = 1,
+	INV_ICM42607_FILTER_AVG_8X = 2,
+	INV_ICM42607_FILTER_AVG_16X = 3,
+	INV_ICM42607_FILTER_AVG_32X = 4,
+	INV_ICM42607_FILTER_AVG_64X = 5,
+	/* values 6 and 7 also correspond to 64x. */
+};
+
 /* Signed so that negative values can signify an invalid condition. */
 struct inv_icm42607_sensor_conf {
 	int mode;
@@ -93,6 +104,7 @@ struct inv_icm42607_sensor_conf {
 	int odr;
 	int filter;
 };
+#define INV_ICM42607_SENSOR_CONF_INIT		{ -1, -1, -1, -1 }
 
 struct inv_icm42607_conf {
 	struct inv_icm42607_sensor_conf gyro;
@@ -117,6 +129,7 @@ struct inv_icm42607_suspended {
  *  @hw:		Hardware specific data.
  *  @lock:		lock for serializing multiple registers access.
  *  @map:		regmap pointer.
+ *  @indio_accel:	accelerometer IIO device.
  *  @vddio_supply:	I/O voltage regulator for the chip.
  *  @vddio_en:		I/O voltage status for runtime PM.
  *  @suspended:		suspended sensors configuration.
@@ -127,6 +140,7 @@ struct inv_icm42607_state {
 	const struct inv_icm42607_hw *hw;
 	struct mutex lock;
 	struct regmap *map;
+	struct iio_dev *indio_accel;
 	struct regulator *vddio_supply;
 	bool vddio_en;
 	struct inv_icm42607_suspended suspended;
@@ -134,6 +148,16 @@ struct inv_icm42607_state {
 	struct iio_mount_matrix orientation;
 };
 
+/**
+ * struct inv_icm42607_sensor_state - sensor state variables
+ * @power_mode:		sensor requested power mode (for common frequencies)
+ * @filter:		sensor filter.
+ */
+struct inv_icm42607_sensor_state {
+	enum inv_icm42607_sensor_mode power_mode;
+	int filter;
+};
+
 /* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
 
 /* Register Map for User Bank 0 */
@@ -358,6 +382,14 @@ extern const struct inv_icm42607_hw inv_icm42607_hw_data;
 extern const struct inv_icm42607_hw inv_icm42607p_hw_data;
 extern const struct dev_pm_ops inv_icm42607_pm_ops;
 
+const struct iio_mount_matrix *
+inv_icm42607_get_mount_matrix(struct iio_dev *indio_dev,
+			      const struct iio_chan_spec *chan);
+
+int inv_icm42607_set_accel_conf(struct inv_icm42607_state *st,
+				struct inv_icm42607_sensor_conf *conf,
+				unsigned int *sleep_ms);
+
 int inv_icm42607_set_temp_conf(struct inv_icm42607_state *st, bool enable,
 			       unsigned int *sleep_ms);
 
@@ -365,4 +397,6 @@ int inv_icm42607_core_probe(struct regmap *regmap,
 			    const struct inv_icm42607_hw *hw,
 			    inv_icm42607_bus_setup bus_setup);
 
+struct iio_dev *inv_icm42607_accel_init(struct inv_icm42607_state *st);
+
 #endif
drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c new file +373 -0

373 lines not on this page · raw message

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +61 -0

79 lines not on this page · raw message

Signature · 1 line
2.43.0
#25 lore raw

Re: [PATCH V13 7/9] iio: imu: inv_icm42607: Add Accelerometer for icm42607

Quoted 1 line · Chris Morgan

Add icm42607 accelerometer sensor for icm42607.

...

drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c line 195

Quoted 11 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c new file +11 -0
+static int inv_icm42607_accel_read_odr(struct inv_icm42607_state *st,
+				       int *val, int *val2)
+{
+	unsigned int odr;
+	unsigned int i;
+
+	guard(mutex)(&st->lock);
+
+	odr = st->conf.accel.odr;
+
+	for (i = 5; i < ARRAY_SIZE(inv_icm42607_accel_odr); ++i) {

Same comment stays. Why pre-increment?

Quoted 11 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c new file +11 -0
+		if (i == odr)
+			break;
+	}
+	if (i >= ARRAY_SIZE(inv_icm42607_accel_odr))
+		return -EINVAL;
+
+	*val = inv_icm42607_accel_odr[i][0];
+	*val2 = inv_icm42607_accel_odr[i][1];
+
+	return IIO_VAL_INT_PLUS_MICRO;
+}

...

drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c line 217

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c new file +10 -0
+static int inv_icm42607_accel_write_odr(struct iio_dev *indio_dev,
+					int val, int val2)
+{
+	struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT;
+	struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev);
+	struct device *dev = regmap_get_device(st->map);
+	unsigned int idx;
+	int ret;
+
+	for (idx = 5; idx < ARRAY_SIZE(inv_icm42607_accel_odr); ++idx) {

Ditto.

Quoted 18 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c new file +18 -0
+		if (val == inv_icm42607_accel_odr[idx][0] &&
+		    val2 == inv_icm42607_accel_odr[idx][1])
+			break;
+	}
+	if (idx >= ARRAY_SIZE(inv_icm42607_accel_odr))
+		return -EINVAL;
+
+	conf.odr = idx;
+
+	PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
+	guard(mutex)(&st->lock);
+
+	return inv_icm42607_set_accel_conf(st, &conf, NULL);
+}

...

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st, · line 183

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +10 -0
+int inv_icm42607_set_accel_conf(struct inv_icm42607_state *st,
+				struct inv_icm42607_sensor_conf *conf,
+				unsigned int *sleep_ms)
+{
+	struct inv_icm42607_sensor_conf *oldconf = &st->conf.accel;
+	unsigned int val;
+	int ret;
+
+	if (conf->mode < 0)
+		conf->mode = oldconf->mode;

Also as per below.

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st, · line 189

Quoted 7 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +6 -0
+	if (conf->fs < 0)
+		conf->fs = oldconf->fs;
+	if (conf->odr < 0)
+		conf->odr = oldconf->odr;
 
+	if (conf->filter < 0)
+		conf->filter = oldconf->filter;

This conditional is not immediately used below...

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st, · line 199

Quoted 9 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +9 -0
+	if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) {
+		val = FIELD_PREP(INV_ICM42607_ACCEL_CONFIG0_FS_SEL_MASK, conf->fs);
+		val |= FIELD_PREP(INV_ICM42607_ACCEL_CONFIG0_ODR_MASK, conf->odr);
+		ret = regmap_write(st->map, INV_ICM42607_REG_ACCEL_CONFIG0, val);
+		if (ret)
+			return ret;
+		oldconf->fs = conf->fs;
+		oldconf->odr = conf->odr;
+	}

...you can move it here.

Quoted 19 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +19 -0
+	if (conf->filter != oldconf->filter) {
+		if (conf->mode == INV_ICM42607_SENSOR_MODE_LOW_POWER) {
+			val = FIELD_PREP(INV_ICM42607_ACCEL_CONFIG1_AVG_MASK, conf->filter);
+			ret = regmap_update_bits(st->map, INV_ICM42607_REG_ACCEL_CONFIG1,
+						 INV_ICM42607_ACCEL_CONFIG1_AVG_MASK, val);
+		} else {
+			val = FIELD_PREP(INV_ICM42607_ACCEL_CONFIG1_FILTER_MASK,
+					 conf->filter);
+			ret = regmap_update_bits(st->map, INV_ICM42607_REG_ACCEL_CONFIG1,
+						 INV_ICM42607_ACCEL_CONFIG1_FILTER_MASK, val);
+		}
+		if (ret)
+			return ret;
+		oldconf->filter = conf->filter;
+	}
+
+	return inv_icm42607_set_pwr_mgmt0(st, st->conf.gyro.mode, conf->mode,
+					  st->conf.temp_en, sleep_ms);
+}
Signature · 2 lines
With Best Regards,
Andy Shevchenko
maintainer
#26 lore raw

Re: [PATCH V13 7/9] iio: imu: inv_icm42607: Add Accelerometer for icm42607

In reply to Chris Morgan
Quoted 5 lines · On Mon, 15 Jun 2026 12:25:50 -0500 Chris Morgan <[email protected]> wrote:

From: Chris Morgan <[email protected]>

Add icm42607 accelerometer sensor for icm42607.

FWIW I think this has the same issue as the gyro patch around management of the cache of what is enabled, but this one sashiko gave a clean bill of health...

:)

#27 lore raw

PATCH v13 8/9 iio: imu: inv_icm42607: Add Gyroscope to icm42607

In reply to Chris Morgan

From: Chris Morgan <[email protected]>

Add gyroscope functions to the icm42607 driver.

---
 drivers/iio/imu/inv_icm42607/Makefile         |   1 +
 drivers/iio/imu/inv_icm42607/inv_icm42607.h   |   8 +
 .../iio/imu/inv_icm42607/inv_icm42607_core.c  |  48 +++
 .../iio/imu/inv_icm42607/inv_icm42607_gyro.c  | 369 ++++++++++++++++++
 4 files changed, 426 insertions(+)
 create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c
drivers/iio/imu/inv_icm42607/Makefile +1 -0
index d74b23b1e1be..7b907e019601 100644
@@ -2,6 +2,7 @@
 
 obj-$(CONFIG_INV_ICM42607) += inv-icm42607.o
 inv-icm42607-y += inv_icm42607_core.o
+inv-icm42607-y += inv_icm42607_gyro.o
 inv-icm42607-y += inv_icm42607_accel.o
 inv-icm42607-y += inv_icm42607_temp.o
 
drivers/iio/imu/inv_icm42607/inv_icm42607.h +8 -0
index c71d667dadb7..ab529e6191f6 100644
@@ -130,6 +130,7 @@ struct inv_icm42607_suspended {
  *  @lock:		lock for serializing multiple registers access.
  *  @map:		regmap pointer.
  *  @indio_accel:	accelerometer IIO device.
+ *  @indio_gyro:	gyroscope IIO device.
  *  @vddio_supply:	I/O voltage regulator for the chip.
  *  @vddio_en:		I/O voltage status for runtime PM.
  *  @suspended:		suspended sensors configuration.
@@ -141,6 +142,7 @@ struct inv_icm42607_state {
 	struct mutex lock;
 	struct regmap *map;
 	struct iio_dev *indio_accel;
+	struct iio_dev *indio_gyro;
 	struct regulator *vddio_supply;
 	bool vddio_en;
 	struct inv_icm42607_suspended suspended;
@@ -390,6 +392,10 @@ int inv_icm42607_set_accel_conf(struct inv_icm42607_state *st,
 				struct inv_icm42607_sensor_conf *conf,
 				unsigned int *sleep_ms);
 
+int inv_icm42607_set_gyro_conf(struct inv_icm42607_state *st,
+			       struct inv_icm42607_sensor_conf *conf,
+			       unsigned int *sleep_ms);
+
 int inv_icm42607_set_temp_conf(struct inv_icm42607_state *st, bool enable,
 			       unsigned int *sleep_ms);
 
@@ -397,6 +403,8 @@ int inv_icm42607_core_probe(struct regmap *regmap,
 			    const struct inv_icm42607_hw *hw,
 			    inv_icm42607_bus_setup bus_setup);
 
+struct iio_dev *inv_icm42607_gyro_init(struct inv_icm42607_state *st);
+
 struct iio_dev *inv_icm42607_accel_init(struct inv_icm42607_state *st);
 
 #endif
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +48 -0

60 lines not on this page · raw message

drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +369 -0

369 lines not on this page · raw message

Signature · 1 line
2.43.0
#28 lore raw

Re: [PATCH V13 8/9] iio: imu: inv_icm42607: Add Gyroscope to icm42607

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Medium] The gyro sensor state is not reverted after a raw read, causing it to remain permanently enabled…

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The gyro sensor state is not reverted after a raw read, causing it to remain permanently enabled during all future active PM states. --

commit 608315b9e755ed3de8730d6f1fc3e2dc0c68b7a5
Author: Chris Morgan <[email protected]>

iio: imu: inv_icm42607: Add Gyroscope to icm42607

This commit adds gyroscope functions and IIO device registration to the icm42607 driver.

Quoted 5 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +0 -0
new file mode 100644
index 0000000000000..ef73560b39d73

[ ... ]

Quoted 11 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +11 -0
+static int inv_icm42607_gyro_read_sensor(struct iio_dev *indio_dev,
+					 struct iio_chan_spec const *chan,
+					 s16 *val)
+{
+	struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT;
+	struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev);
+	struct inv_icm42607_sensor_state *gyro_st = iio_priv(indio_dev);
+	struct device *dev = regmap_get_device(st->map);
+	unsigned int reg;
+	u8 data[2];
+	int ret;

[ ... ]

Quoted 15 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +15 -0
+	PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
+	guard(mutex)(&st->lock);
+
+	/* enable gyro sensor */
+	conf.mode = gyro_st->power_mode;
+	conf.filter = gyro_st->filter;
+	ret = inv_icm42607_set_gyro_conf(st, &conf, NULL);
+	if (ret)
+		return ret;
+
+	/* read gyro register data */

drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c line 116

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +10 -0
+	ret = regmap_bulk_read(st->map, reg, data, sizeof(data));
+	if (ret)
+		return ret;
+
+	*val = get_unaligned_be16(data);
+	if (*val == INV_ICM42607_DATA_INVALID)
+		return -EINVAL;
+
+	return 0;
+}

[Severity: Medium]
Does this leave the gyroscope permanently enabled after a raw read?

The function enables the gyro by setting conf.mode = gyro_st->power_mode and calling inv_icm42607_set_gyro_conf(), but does not appear to revert it to an off state before returning.

When the device later autosuspends, inv_icm42607_runtime_suspend() saves this active state into st->suspended.gyro. On every subsequent PM resume, inv_icm42607_runtime_resume() will restore the gyro to ON.

Could this cause an unnecessary 45ms startup delay and waste power during all future active PM states?

Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=8
#29 lore raw

Re: [PATCH V13 8/9] iio: imu: inv_icm42607: Add Gyroscope to icm42607

In reply to Chris Morgan
Quoted 1 line · Chris Morgan

Add gyroscope functions to the icm42607 driver.

...

Quoted 6 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +6 -0
+int inv_icm42607_set_gyro_conf(struct inv_icm42607_state *st,
+			       struct inv_icm42607_sensor_conf *conf,
+			       unsigned int *sleep_ms)
+{
+	struct inv_icm42607_sensor_conf *oldconf = &st->conf.gyro;
+	unsigned int val;

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c int inv_icm42607_set_accel_conf(struct inv_icm42607_state *st, · line 236

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +10 -0
+	int ret;
+
+	if (conf->mode < 0)
+		conf->mode = oldconf->mode;
+	if (conf->fs < 0)
+		conf->fs = oldconf->fs;
+	if (conf->odr < 0)
+		conf->odr = oldconf->odr;
+	if (conf->filter < 0)
+		conf->filter = oldconf->filter;

Same comment as per previous patch. But looking at this, can you rather have a helper that answers the below two questions? Something like

void _assign_conf(..., bool *write_odr, bool *write_filter)

{
	...
}

EXPORT_...

in the core driver? But wight both approaches and choose either existing one (as in this patch series) or what I suggested.

Quoted 25 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +25 -0
+	if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) {
+		val = FIELD_PREP(INV_ICM42607_GYRO_CONFIG0_FS_SEL_MASK,
+				 conf->fs);
+		val |= FIELD_PREP(INV_ICM42607_GYRO_CONFIG0_ODR_MASK,
+				  conf->odr);
+		ret = regmap_write(st->map, INV_ICM42607_REG_GYRO_CONFIG0, val);
+		if (ret)
+			return ret;
+		oldconf->fs = conf->fs;
+		oldconf->odr = conf->odr;
+	}
+
+	if (conf->filter != oldconf->filter) {
+		val = FIELD_PREP(INV_ICM42607_GYRO_CONFIG1_FILTER_MASK,
+				 conf->filter);
+		ret = regmap_update_bits(st->map, INV_ICM42607_REG_GYRO_CONFIG1,
+					 INV_ICM42607_GYRO_CONFIG1_FILTER_MASK, val);
+		if (ret)
+			return ret;
+		oldconf->filter = conf->filter;
+	}
+
+	return inv_icm42607_set_pwr_mgmt0(st, conf->mode, st->conf.accel.mode,
+					  st->conf.temp_en, sleep_ms);
+}

...

drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c line 191

Quoted 9 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +9 -0
+{
+	unsigned int odr;
+	unsigned int i;
+
+	guard(mutex)(&st->lock);
+
+	odr = st->conf.gyro.odr;
+
+	for (i = 5; i < ARRAY_SIZE(inv_icm42607_gyro_odr); ++i) {

Same comment, why pre-increment?

Quoted 12 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +12 -0
+		if (i == odr)
+			break;
+	}
+	if (i >= ARRAY_SIZE(inv_icm42607_gyro_odr))
+		return -EINVAL;
+
+	*val = inv_icm42607_gyro_odr[i][0];
+	*val2 = inv_icm42607_gyro_odr[i][1];
+
+	return IIO_VAL_INT_PLUS_MICRO;
+}
+

drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c line 213

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +10 -0
+static int inv_icm42607_gyro_write_odr(struct iio_dev *indio_dev,
+				       int val, int val2)
+{
+	struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev);
+	struct device *dev = regmap_get_device(st->map);
+	unsigned int idx;
+	struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT;
+	int ret;
+
+	for (idx = 5; idx < ARRAY_SIZE(inv_icm42607_gyro_odr); ++idx) {

Ditto.

Quoted 8 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +8 -0
+		if (val == inv_icm42607_gyro_odr[idx][0] &&
+		    val2 == inv_icm42607_gyro_odr[idx][1])
+			break;
+	}
+	if (idx >= ARRAY_SIZE(inv_icm42607_gyro_odr))
+		return -EINVAL;
+
+	conf.odr = idx;

drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c line 231

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +10 -0
+
+	PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
+	guard(mutex)(&st->lock);
+
+	return inv_icm42607_set_gyro_conf(st, &conf, NULL);
+}

Can be some of the code deduplicated between gyro and accel?

Signature · 2 lines
With Best Regards,
Andy Shevchenko
#30 lore raw

Re: [PATCH V13 8/9] iio: imu: inv_icm42607: Add Gyroscope to icm42607

Quoted 26 lines · Andy Shevchenko
Quoted 1 line · Chris Morgan

Add gyroscope functions to the icm42607 driver.

...

Quoted 6 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +6 -0
+int inv_icm42607_set_gyro_conf(struct inv_icm42607_state *st,
+			       struct inv_icm42607_sensor_conf *conf,
+			       unsigned int *sleep_ms)
+{
+	struct inv_icm42607_sensor_conf *oldconf = &st->conf.gyro;
+	unsigned int val;

drivers/iio/imu/inv_icm42607/inv_icm42607_core.c int inv_icm42607_set_accel_conf(struct inv_icm42607_state *st, · line 236

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +10 -0
+	int ret;
+
+	if (conf->mode < 0)
+		conf->mode = oldconf->mode;
+	if (conf->fs < 0)
+		conf->fs = oldconf->fs;
+	if (conf->odr < 0)
+		conf->odr = oldconf->odr;
+	if (conf->filter < 0)
+		conf->filter = oldconf->filter;

Same comment as per previous patch. But looking at this, can you rather have a helper that answers the below two questions? Something like

Quoted 8 lines

void _assign_conf(..., bool *write_odr, bool *write_filter)

{
	...
}

EXPORT_...

in the core driver? But wight both approaches and choose either existing one (as in this patch series) or what I suggested.

In the core driver, I was going to do something like this:

static void inv_icm42607_update_config(struct inv_icm42607_sensor_conf *conf,
struct inv_icm42607_sensor_conf *oldconf, bool *config0, bool *config1)

{
        if (conf->mode < 0)
                conf->mode = oldconf->mode;
        if (conf->fs < 0)
                conf->fs = oldconf->fs;
        if (conf->odr < 0)
                conf->odr = oldconf->odr;
        if (conf->filter < 0)
                conf->filter = oldconf->filter;

        if (conf->fs != oldconf->fs || conf->odr != oldconf->odr)
                *config0 = true;

        if (conf->filter != oldconf->filter)
                *config1 = true;
}

So the step of copying stuff for sanity checking as well as checking if I need to update config0 or config1 registers is handled here, and I can simply check the values of config0 and config1 with an if to determine if I need to call to write to the registers.

Quoted 29 lines
Quoted 26 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +25 -0
+	if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) {
+		val = FIELD_PREP(INV_ICM42607_GYRO_CONFIG0_FS_SEL_MASK,
+				 conf->fs);
+		val |= FIELD_PREP(INV_ICM42607_GYRO_CONFIG0_ODR_MASK,
+				  conf->odr);
+		ret = regmap_write(st->map, INV_ICM42607_REG_GYRO_CONFIG0, val);
+		if (ret)
+			return ret;
+		oldconf->fs = conf->fs;
+		oldconf->odr = conf->odr;
+	}
+
+	if (conf->filter != oldconf->filter) {
+		val = FIELD_PREP(INV_ICM42607_GYRO_CONFIG1_FILTER_MASK,
+				 conf->filter);
+		ret = regmap_update_bits(st->map, INV_ICM42607_REG_GYRO_CONFIG1,
+					 INV_ICM42607_GYRO_CONFIG1_FILTER_MASK, val);
+		if (ret)
+			return ret;
+		oldconf->filter = conf->filter;
+	}
+
+	return inv_icm42607_set_pwr_mgmt0(st, conf->mode, st->conf.accel.mode,
+					  st->conf.temp_en, sleep_ms);
+}

...

Quoted 11 lines

drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c line 191

Quoted 9 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +9 -0
+{
+	unsigned int odr;
+	unsigned int i;
+
+	guard(mutex)(&st->lock);
+
+	odr = st->conf.gyro.odr;
+
+	for (i = 5; i < ARRAY_SIZE(inv_icm42607_gyro_odr); ++i) {

Same comment, why pre-increment?

I could not brain on this day, I had the dumb.
I'll fix it. :-)

Quoted 38 lines
Quoted 13 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +12 -0
+		if (i == odr)
+			break;
+	}
+	if (i >= ARRAY_SIZE(inv_icm42607_gyro_odr))
+		return -EINVAL;
+
+	*val = inv_icm42607_gyro_odr[i][0];
+	*val2 = inv_icm42607_gyro_odr[i][1];
+
+	return IIO_VAL_INT_PLUS_MICRO;
+}
+

drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c line 213

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +10 -0
+static int inv_icm42607_gyro_write_odr(struct iio_dev *indio_dev,
+				       int val, int val2)
+{
+	struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev);
+	struct device *dev = regmap_get_device(st->map);
+	unsigned int idx;
+	struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT;
+	int ret;
+
+	for (idx = 5; idx < ARRAY_SIZE(inv_icm42607_gyro_odr); ++idx) {

Ditto.

Quoted 12 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +12 -0
+		if (val == inv_icm42607_gyro_odr[idx][0] &&
+		    val2 == inv_icm42607_gyro_odr[idx][1])
+			break;
+	}
+	if (idx >= ARRAY_SIZE(inv_icm42607_gyro_odr))
+		return -EINVAL;
+
+	conf.odr = idx;
+
+	PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
Quoted 8 lines

drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c line 168

Quoted 6 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +6 -0
+		return ret;
+
+	guard(mutex)(&st->lock);
+
+	return inv_icm42607_set_gyro_conf(st, &conf, NULL);
+}

Can be some of the code deduplicated between gyro and accel?

Probably a fair amount, but the deduplication will likely need to be undone somewhat if we get buffer, WoM or apex support added back (I don't have any devices with such functionality, so if anyone will do it then it won't be me). I can refactor more if you want, or we can keep it split like this to make it easy if someone else wants to tackle the buffers/IRQs stuff later? Your call.

Quoted 6 lines
Signature · 3 lines
-- 
With Best Regards,
Andy Shevchenko

Thank you,
Chris

#31 lore raw

Re: [PATCH V13 8/9] iio: imu: inv_icm42607: Add Gyroscope to icm42607

Quoted 2 lines · Chris Morgan
Quoted 1 line · Andy Shevchenko

On Mon, Jun 15, 2026 at 12:25:51PM -0500, Chris Morgan wrote:

...

Quoted 8 lines
Quoted 1 line

Can be some of the code deduplicated between gyro and accel?

Probably a fair amount, but the deduplication will likely need to be undone somewhat if we get buffer, WoM or apex support added back (I don't have any devices with such functionality, so if anyone will do it then it won't be me). I can refactor more if you want, or we can keep it split like this to make it easy if someone else wants to tackle the buffers/IRQs stuff later? Your call.

Just asking. Jonathan, David, Nuno, what's your opinion on this? Personal opinion is to avoid solving the issues that do not exist. If you are not committing into those features, let's not prepare driver for them right now.

Signature · 2 lines
With Best Regards,
Andy Shevchenko
maintainer
#32 lore raw

Re: [PATCH V13 8/9] iio: imu: inv_icm42607: Add Gyroscope to icm42607

Quoted 15 lines · On Tue, 23 Jun 2026 09:52:36 +0300 Andy Shevchenko…
Quoted 2 lines · Chris Morgan
Quoted 1 line · Andy Shevchenko

On Mon, Jun 15, 2026 at 12:25:51PM -0500, Chris Morgan wrote:

...

Quoted 8 lines
Quoted 1 line

Can be some of the code deduplicated between gyro and accel?

Probably a fair amount, but the deduplication will likely need to be undone somewhat if we get buffer, WoM or apex support added back (I don't have any devices with such functionality, so if anyone will do it then it won't be me). I can refactor more if you want, or we can keep it split like this to make it easy if someone else wants to tackle the buffers/IRQs stuff later? Your call.

Quoted 5 lines

Just asking. Jonathan, David, Nuno, what's your opinion on this? Personal opinion is to avoid solving the issues that do not exist. If you are not committing into those features, let's not prepare driver for them right now.

Agreed. My only exception to this is normally when someone tells me they have the code and plan to post a follow up set very shortly. Then I get a bit more relaxed as they chances of 'preparing' for the future being relevant become much higher!

Jonathan

#33 lore raw

Re: [PATCH V13 8/9] iio: imu: inv_icm42607: Add Gyroscope to icm42607

Quoted 23 lines · Jonathan Cameron
Quoted 15 lines · On Tue, 23 Jun 2026 09:52:36 +0300 Andy Shevchenko…
Quoted 2 lines · Chris Morgan
Quoted 1 line · Andy Shevchenko

On Mon, Jun 15, 2026 at 12:25:51PM -0500, Chris Morgan wrote:

...

Quoted 8 lines
Quoted 1 line

Can be some of the code deduplicated between gyro and accel?

Probably a fair amount, but the deduplication will likely need to be undone somewhat if we get buffer, WoM or apex support added back (I don't have any devices with such functionality, so if anyone will do it then it won't be me). I can refactor more if you want, or we can keep it split like this to make it easy if someone else wants to tackle the buffers/IRQs stuff later? Your call.

Quoted 5 lines

Just asking. Jonathan, David, Nuno, what's your opinion on this? Personal opinion is to avoid solving the issues that do not exist. If you are not committing into those features, let's not prepare driver for them right now.

Quoted 6 lines

Agreed. My only exception to this is normally when someone tells me they have the code and plan to post a follow up set very shortly. Then I get a bit more relaxed as they chances of 'preparing' for the future being relevant become much higher!

Jonathan

Okay, I'll refactor a bit more then and resubmit in another week or two.

Thanks,
Chris

maintainer
#34 lore raw

Re: [PATCH V13 8/9] iio: imu: inv_icm42607: Add Gyroscope to icm42607

In reply to Chris Morgan
Quoted 5 lines · On Mon, 15 Jun 2026 12:25:51 -0500 Chris Morgan <[email protected]> wrote:

From: Chris Morgan <[email protected]>

Add gyroscope functions to the icm42607 driver.

There is another bit of sashiko stuff in here. Please take a look
https://sashiko.dev/#/patchset/20260615172554.160910-1-macroalpha82%40gmail.com

I think it is correct about there being a path in which the gyro ends up always enabled along side anything else after the first read.

In general there seems to be a bit of mix on whether the caller or the power management function should be responsible for the caching of state.

I know you look at Sashiko so I could just have waited a bit, but I was reviewing anyway so took a look and having done that might as well highlight some stuff!

Jonathan

Quoted 87 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +42 -0
index eb239987a1ce..23ca7529825c 100644
@@ -218,6 +218,49 @@ int inv_icm42607_set_accel_conf(struct inv_icm42607_state *st,
 					  st->conf.temp_en, sleep_ms);
 }
 
+int inv_icm42607_set_gyro_conf(struct inv_icm42607_state *st,
+			       struct inv_icm42607_sensor_conf *conf,
+			       unsigned int *sleep_ms)
+{
+	struct inv_icm42607_sensor_conf *oldconf = &st->conf.gyro;
+	unsigned int val;
+	int ret;
+
+	if (conf->mode < 0)
+		conf->mode = oldconf->mode;
+	if (conf->fs < 0)
+		conf->fs = oldconf->fs;
+	if (conf->odr < 0)
+		conf->odr = oldconf->odr;
+	if (conf->filter < 0)
+		conf->filter = oldconf->filter;
+
+	if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) {
+		val = FIELD_PREP(INV_ICM42607_GYRO_CONFIG0_FS_SEL_MASK,
+				 conf->fs);
+		val |= FIELD_PREP(INV_ICM42607_GYRO_CONFIG0_ODR_MASK,
+				  conf->odr);
+		ret = regmap_write(st->map, INV_ICM42607_REG_GYRO_CONFIG0, val);
+		if (ret)
+			return ret;
+		oldconf->fs = conf->fs;
+		oldconf->odr = conf->odr;
+	}
+
+	if (conf->filter != oldconf->filter) {
+		val = FIELD_PREP(INV_ICM42607_GYRO_CONFIG1_FILTER_MASK,
+				 conf->filter);
+		ret = regmap_update_bits(st->map, INV_ICM42607_REG_GYRO_CONFIG1,
+					 INV_ICM42607_GYRO_CONFIG1_FILTER_MASK, val);
+		if (ret)
+			return ret;
+		oldconf->filter = conf->filter;
+	}
+
+	return inv_icm42607_set_pwr_mgmt0(st, conf->mode, st->conf.accel.mode,
+					  st->conf.temp_en, sleep_ms);
+}
 
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +30 -0
new file mode 100644
index 000000000000..ef73560b39d7
 
+static int inv_icm42607_gyro_read_sensor(struct iio_dev *indio_dev,
+					 struct iio_chan_spec const *chan,
+					 s16 *val)
+{
+	struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT;
+	struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev);
+	struct inv_icm42607_sensor_state *gyro_st = iio_priv(indio_dev);
+	struct device *dev = regmap_get_device(st->map);
+	unsigned int reg;
+	u8 data[2];
+	int ret;
+
+	if (chan->type != IIO_ANGL_VEL)
+		return -EINVAL;
+
+	switch (chan->channel2) {
+	case IIO_MOD_X:
+		reg = INV_ICM42607_REG_GYRO_DATA_X1;
+		break;
+	case IIO_MOD_Y:
+		reg = INV_ICM42607_REG_GYRO_DATA_Y1;
+		break;
+	case IIO_MOD_Z:
+		reg = INV_ICM42607_REG_GYRO_DATA_Z1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);

drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c line 102

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +10 -0
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
+	guard(mutex)(&st->lock);
+
+	/* enable gyro sensor */
+	conf.mode = gyro_st->power_mode;
+	conf.filter = gyro_st->filter;
+	ret = inv_icm42607_set_gyro_conf(st, &conf, NULL);

The sashiko report is basically:

This turns it on, and runtime pm will turn it off but the state cached ends up such that it is turned on again for any runtime pm resume.

Quoted 14 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +14 -0
+	if (ret)
+		return ret;
+
+	/* read gyro register data */
+	ret = regmap_bulk_read(st->map, reg, data, sizeof(data));
+	if (ret)
+		return ret;
+
+	*val = get_unaligned_be16(data);
+	if (*val == INV_ICM42607_DATA_INVALID)
+		return -EINVAL;
+
+	return 0;
+}
#35 lore raw

Re: [PATCH V13 8/9] iio: imu: inv_icm42607: Add Gyroscope to icm42607

Quoted 125 lines · Jonathan Cameron
Quoted 5 lines · On Mon, 15 Jun 2026 12:25:51 -0500 Chris Morgan <[email protected]> wrote:

From: Chris Morgan <[email protected]>

Add gyroscope functions to the icm42607 driver.

There is another bit of sashiko stuff in here. Please take a look
https://sashiko.dev/#/patchset/20260615172554.160910-1-macroalpha82%40gmail.com

I think it is correct about there being a path in which the gyro ends up always enabled along side anything else after the first read.

In general there seems to be a bit of mix on whether the caller or the power management function should be responsible for the caching of state.

I know you look at Sashiko so I could just have waited a bit, but I was reviewing anyway so took a look and having done that might as well highlight some stuff!

Jonathan

Quoted 87 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_core.c +42 -0
index eb239987a1ce..23ca7529825c 100644
@@ -218,6 +218,49 @@ int inv_icm42607_set_accel_conf(struct inv_icm42607_state *st,
 					  st->conf.temp_en, sleep_ms);
 }
 
+int inv_icm42607_set_gyro_conf(struct inv_icm42607_state *st,
+			       struct inv_icm42607_sensor_conf *conf,
+			       unsigned int *sleep_ms)
+{
+	struct inv_icm42607_sensor_conf *oldconf = &st->conf.gyro;
+	unsigned int val;
+	int ret;
+
+	if (conf->mode < 0)
+		conf->mode = oldconf->mode;
+	if (conf->fs < 0)
+		conf->fs = oldconf->fs;
+	if (conf->odr < 0)
+		conf->odr = oldconf->odr;
+	if (conf->filter < 0)
+		conf->filter = oldconf->filter;
+
+	if (conf->fs != oldconf->fs || conf->odr != oldconf->odr) {
+		val = FIELD_PREP(INV_ICM42607_GYRO_CONFIG0_FS_SEL_MASK,
+				 conf->fs);
+		val |= FIELD_PREP(INV_ICM42607_GYRO_CONFIG0_ODR_MASK,
+				  conf->odr);
+		ret = regmap_write(st->map, INV_ICM42607_REG_GYRO_CONFIG0, val);
+		if (ret)
+			return ret;
+		oldconf->fs = conf->fs;
+		oldconf->odr = conf->odr;
+	}
+
+	if (conf->filter != oldconf->filter) {
+		val = FIELD_PREP(INV_ICM42607_GYRO_CONFIG1_FILTER_MASK,
+				 conf->filter);
+		ret = regmap_update_bits(st->map, INV_ICM42607_REG_GYRO_CONFIG1,
+					 INV_ICM42607_GYRO_CONFIG1_FILTER_MASK, val);
+		if (ret)
+			return ret;
+		oldconf->filter = conf->filter;
+	}
+
+	return inv_icm42607_set_pwr_mgmt0(st, conf->mode, st->conf.accel.mode,
+					  st->conf.temp_en, sleep_ms);
+}
 
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +30 -0
new file mode 100644
index 000000000000..ef73560b39d7
 
+static int inv_icm42607_gyro_read_sensor(struct iio_dev *indio_dev,
+					 struct iio_chan_spec const *chan,
+					 s16 *val)
+{
+	struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT;
+	struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev);
+	struct inv_icm42607_sensor_state *gyro_st = iio_priv(indio_dev);
+	struct device *dev = regmap_get_device(st->map);
+	unsigned int reg;
+	u8 data[2];
+	int ret;
+
+	if (chan->type != IIO_ANGL_VEL)
+		return -EINVAL;
+
+	switch (chan->channel2) {
+	case IIO_MOD_X:
+		reg = INV_ICM42607_REG_GYRO_DATA_X1;
+		break;
+	case IIO_MOD_Y:
+		reg = INV_ICM42607_REG_GYRO_DATA_Y1;
+		break;
+	case IIO_MOD_Z:
+		reg = INV_ICM42607_REG_GYRO_DATA_Z1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);

drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c line 102

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +10 -0
+	ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+	if (ret)
+		return ret;
+
+	guard(mutex)(&st->lock);
+
+	/* enable gyro sensor */
+	conf.mode = gyro_st->power_mode;
+	conf.filter = gyro_st->filter;
+	ret = inv_icm42607_set_gyro_conf(st, &conf, NULL);

The sashiko report is basically:

Quoted 3 lines

This turns it on, and runtime pm will turn it off but the state cached ends up such that it is turned on again for any runtime pm resume.

Yep, for this and for the accel sensor it looks like it gets stuck on. I've revamped this code for the next round and so far it looks like the sensor is powering down correctly.

Quoted 16 lines
Quoted 5 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +4 -0
+	if (ret)
+		return ret;
+
+	/* read gyro register data */

drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c line 116

Quoted 10 lines
drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c new file +10 -0
+	ret = regmap_bulk_read(st->map, reg, data, sizeof(data));
+	if (ret)
+		return ret;
+
+	*val = get_unaligned_be16(data);
+	if (*val == INV_ICM42607_DATA_INVALID)
+		return -EINVAL;
+
+	return 0;
+}

Thank you,
Chris

#36 lore raw

PATCH v13 9/9 arm64: dts: rockchip: Add icm42607p IMU for RG-DS

In reply to Chris Morgan

From: Chris Morgan <[email protected]>

Add the Invensense ICM42607P IMU for the Anbernic RG-DS. Mount-matrix was tested with iio-sensor-proxy and reports correct orientation.

---
 arch/arm64/boot/dts/rockchip/rk3568-anbernic-rg-ds.dts | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
arch/arm64/boot/dts/rockchip/rk3568-anbernic-rg-ds.dts +7 -1
index 8d906ab02c5f..b770bfd5268d 100644
@@ -871,7 +871,13 @@ aw87391_pa_r: audio-codec@5b {
 		sound-name-prefix = "Right Amp";
 	};
 
-	/* invensense,icm42607p at 0x68 */
+	icm42607p: imu@68 {
+		compatible = "invensense,icm42607p";
+		reg = <0x68>;
+		mount-matrix = "-1", "0", "0",
+			       "0", "1", "0",
+			       "0", "0", "-1";
+	};
 };
 
 &i2c3 {
Signature · 1 line
2.43.0