* [PATCH V11 1/9] dt-bindings: iio: imu: icm42600: Add mount-matrix to icm42600
From: Chris Morgan @ 2026-06-10 17:54 UTC (permalink / raw)
To: linux-iio
Cc: andy, nuno.sa, dlechner, jic23, jean-baptiste.maneyrol,
linux-rockchip, devicetree, heiko, conor+dt, krzk+dt, robh,
andriy.shevchenko, Chris Morgan, Krzysztof Kozlowski
In-Reply-To: <20260610175455.19006-1-macroalpha82@gmail.com>
From: Chris Morgan <macromorgan@hotmail.com>
Add mount-matrix attribute to schema. This attribute has been supported
since the first revision of this driver, but was not documented.
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
.../devicetree/bindings/iio/imu/invensense,icm42600.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
index 119e28a833fd..9b2af104f186 100644
--- a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
+++ b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
@@ -53,6 +53,8 @@ properties:
drive-open-drain:
type: boolean
+ mount-matrix: true
+
vdd-supply:
description: Regulator that provides power to the sensor
--
2.43.0
^ permalink raw reply related
* [PATCH V11 2/9] dt-bindings: iio: imu: icm42600: Add icm42607
From: Chris Morgan @ 2026-06-10 17:54 UTC (permalink / raw)
To: linux-iio
Cc: andy, nuno.sa, dlechner, jic23, jean-baptiste.maneyrol,
linux-rockchip, devicetree, heiko, conor+dt, krzk+dt, robh,
andriy.shevchenko, Chris Morgan, Krzysztof Kozlowski
In-Reply-To: <20260610175455.19006-1-macroalpha82@gmail.com>
From: Chris Morgan <macromorgan@hotmail.com>
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.
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
.../bindings/iio/imu/invensense,icm42600.yaml | 18 +++++++++++++++++-
1 file changed, 17 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
index 9b2af104f186..81b6e85decd5 100644
--- a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
+++ b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
@@ -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
--
2.43.0
^ permalink raw reply related
* [PATCH V11 3/9] iio: imu: inv_icm42607: Add inv_icm42607 Core Driver
From: Chris Morgan @ 2026-06-10 17:54 UTC (permalink / raw)
To: linux-iio
Cc: andy, nuno.sa, dlechner, jic23, jean-baptiste.maneyrol,
linux-rockchip, devicetree, heiko, conor+dt, krzk+dt, robh,
andriy.shevchenko, Chris Morgan
In-Reply-To: <20260610175455.19006-1-macroalpha82@gmail.com>
From: Chris Morgan <macromorgan@hotmail.com>
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.
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
---
drivers/iio/imu/inv_icm42607/inv_icm42607.h | 334 ++++++++++++++++++
.../iio/imu/inv_icm42607/inv_icm42607_core.c | 197 +++++++++++
2 files changed, 531 insertions(+)
create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607.h
create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607.h b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
new file mode 100644
index 000000000000..716fc0f1c3fd
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
@@ -0,0 +1,334 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2026 InvenSense, Inc.
+ */
+
+#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/types.h>
+
+enum inv_icm42607_sensor_mode {
+ INV_ICM42607_SENSOR_MODE_OFF = 0,
+ INV_ICM42607_SENSOR_MODE_STANDBY = 1,
+ INV_ICM42607_SENSOR_MODE_LOW_POWER = 2,
+ INV_ICM42607_SENSOR_MODE_LOW_NOISE = 3,
+ INV_ICM42607_SENSOR_MODE_NB
+};
+
+/* gyroscope fullscale values */
+enum inv_icm42607_gyro_fs {
+ INV_ICM42607_GYRO_FS_2000DPS = 0,
+ INV_ICM42607_GYRO_FS_1000DPS = 1,
+ INV_ICM42607_GYRO_FS_500DPS = 2,
+ INV_ICM42607_GYRO_FS_250DPS = 3,
+ INV_ICM42607_GYRO_FS_NB
+};
+
+/* accelerometer fullscale values */
+enum inv_icm42607_accel_fs {
+ INV_ICM42607_ACCEL_FS_16G = 0,
+ INV_ICM42607_ACCEL_FS_8G = 1,
+ INV_ICM42607_ACCEL_FS_4G = 2,
+ INV_ICM42607_ACCEL_FS_2G = 3,
+ INV_ICM42607_ACCEL_FS_NB
+};
+
+/* ODR values - Note Gyro does not support ODR less than 12.5Hz */
+enum inv_icm42607_odr {
+ INV_ICM42607_ODR_1600HZ = 5,
+ INV_ICM42607_ODR_800HZ = 6,
+ INV_ICM42607_ODR_400HZ = 7,
+ INV_ICM42607_ODR_200HZ = 8,
+ INV_ICM42607_ODR_100HZ = 9,
+ INV_ICM42607_ODR_50HZ = 10,
+ INV_ICM42607_ODR_25HZ = 11,
+ INV_ICM42607_ODR_12_5HZ = 12,
+ INV_ICM42607_ODR_6_25HZ_LP = 13,
+ INV_ICM42607_ODR_3_125HZ_LP = 14,
+ INV_ICM42607_ODR_1_5625HZ_LP = 15,
+ INV_ICM42607_ODR_NB
+};
+
+/* Low-Noise mode sensor data filter (bandwidth) */
+enum inv_icm42607_filter_bw {
+ INV_ICM42607_FILTER_BYPASS = 0,
+ INV_ICM42607_FILTER_BW_180HZ = 1,
+ INV_ICM42607_FILTER_BW_121HZ = 2,
+ INV_ICM42607_FILTER_BW_73HZ = 3,
+ INV_ICM42607_FILTER_BW_53HZ = 4,
+ INV_ICM42607_FILTER_BW_34HZ = 5,
+ INV_ICM42607_FILTER_BW_25HZ = 6,
+ INV_ICM42607_FILTER_BW_16HZ = 7,
+ INV_ICM42607_FILTER_BW_NB
+};
+
+/* Signed so that negative values can signify an invalid condition. */
+struct inv_icm42607_sensor_conf {
+ int mode;
+ int fs;
+ int odr;
+ int filter;
+};
+
+struct inv_icm42607_conf {
+ struct inv_icm42607_sensor_conf gyro;
+ struct inv_icm42607_sensor_conf accel;
+ bool temp_en;
+};
+
+struct inv_icm42607_hw {
+ u8 whoami;
+ const char *name;
+ const struct inv_icm42607_conf *conf;
+};
+
+/**
+ * struct inv_icm42607_state - driver state variables
+ * @lock: lock for serializing multiple registers access.
+ * @hw: Hardware specific data.
+ * @map: regmap pointer.
+ * @vddio_supply: I/O voltage regulator for the chip.
+ * @orientation: sensor chip orientation relative to main hardware.
+ * @conf: chip sensors configurations.
+ */
+struct inv_icm42607_state {
+ struct mutex lock;
+ const struct inv_icm42607_hw *hw;
+ struct regmap *map;
+ struct regulator *vddio_supply;
+ struct iio_mount_matrix orientation;
+ struct inv_icm42607_conf conf;
+};
+
+/* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
+
+/* Register Map for User Bank 0 */
+#define INV_ICM42607_REG_MCLK_RDY 0x00
+
+#define INV_ICM42607_REG_DEVICE_CONFIG 0x01
+#define INV_ICM42607_DEVICE_CONFIG_SPI_AP_4WIRE BIT(2)
+#define INV_ICM42607_DEVICE_CONFIG_SPI_MODE BIT(0)
+
+#define INV_ICM42607_REG_SIGNAL_PATH_RESET 0x02
+#define INV_ICM42607_SIGNAL_PATH_RESET_SOFT_RESET BIT(4)
+#define INV_ICM42607_SIGNAL_PATH_RESET_FIFO_FLUSH BIT(2)
+
+#define INV_ICM42607_REG_DRIVE_CONFIG1 0x03
+#define INV_ICM42607_DRIVE_CONFIG1_I3C_DDR_MASK GENMASK(5, 3)
+#define INV_ICM42607_DRIVE_CONFIG1_I3C_SDR_MASK GENMASK(2, 0)
+
+#define INV_ICM42607_REG_DRIVE_CONFIG2 0x04
+#define INV_ICM42607_DRIVE_CONFIG2_I2C_MASK GENMASK(5, 3)
+#define INV_ICM42607_DRIVE_CONFIG2_ALL_MASK GENMASK(2, 0)
+
+#define INV_ICM42607_REG_DRIVE_CONFIG3 0x05
+#define INV_ICM42607_DRIVE_CONFIG3_SPI_MASK GENMASK(2, 0)
+
+#define INV_ICM42607_REG_INT_CONFIG 0x06
+#define INV_ICM42607_INT_CONFIG_INT2_LATCHED BIT(5)
+#define INV_ICM42607_INT_CONFIG_INT2_PUSH_PULL BIT(4)
+#define INV_ICM42607_INT_CONFIG_INT2_ACTIVE_HIGH BIT(3)
+#define INV_ICM42607_INT_CONFIG_INT2_ACTIVE_LOW 0x00
+#define INV_ICM42607_INT_CONFIG_INT1_LATCHED BIT(2)
+#define INV_ICM42607_INT_CONFIG_INT1_PUSH_PULL BIT(1)
+#define INV_ICM42607_INT_CONFIG_INT1_ACTIVE_HIGH BIT(0)
+#define INV_ICM42607_INT_CONFIG_INT1_ACTIVE_LOW 0x00
+
+/* all sensor data are 16 bits (2 registers wide) in big-endian */
+#define INV_ICM42607_REG_TEMP_DATA1 0x09
+#define INV_ICM42607_REG_TEMP_DATA0 0x0A
+#define INV_ICM42607_REG_ACCEL_DATA_X1 0x0B
+#define INV_ICM42607_REG_ACCEL_DATA_X0 0x0C
+#define INV_ICM42607_REG_ACCEL_DATA_Y1 0x0D
+#define INV_ICM42607_REG_ACCEL_DATA_Y0 0x0E
+#define INV_ICM42607_REG_ACCEL_DATA_Z1 0x0F
+#define INV_ICM42607_REG_ACCEL_DATA_Z0 0x10
+#define INV_ICM42607_REG_GYRO_DATA_X1 0x11
+#define INV_ICM42607_REG_GYRO_DATA_X0 0x12
+#define INV_ICM42607_REG_GYRO_DATA_Y1 0x13
+#define INV_ICM42607_REG_GYRO_DATA_Y0 0x14
+#define INV_ICM42607_REG_GYRO_DATA_Z1 0x15
+#define INV_ICM42607_REG_GYRO_DATA_Z0 0x16
+#define INV_ICM42607_DATA_INVALID -32768
+
+#define INV_ICM42607_REG_TMST_FSYNCH 0x17
+#define INV_ICM42607_REG_TMST_FSYNCL 0x18
+
+/* APEX Data Registers */
+#define INV_ICM42607_REG_APEX_DATA0 0x31
+#define INV_ICM42607_REG_APEX_DATA1 0x32
+#define INV_ICM42607_REG_APEX_DATA2 0x33
+#define INV_ICM42607_REG_APEX_DATA3 0x34
+#define INV_ICM42607_REG_APEX_DATA4 0x1D
+#define INV_ICM42607_REG_APEX_DATA5 0x1E
+
+#define INV_ICM42607_REG_PWR_MGMT0 0x1F
+#define INV_ICM42607_PWR_MGMT0_ACCEL_LP_CLK_SEL BIT(7)
+#define INV_ICM42607_PWR_MGMT0_IDLE BIT(4)
+#define INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK GENMASK(3, 2)
+#define INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK GENMASK(1, 0)
+
+#define INV_ICM42607_REG_GYRO_CONFIG0 0x20
+#define INV_ICM42607_GYRO_CONFIG0_FS_SEL_MASK GENMASK(6, 5)
+#define INV_ICM42607_GYRO_CONFIG0_ODR_MASK GENMASK(3, 0)
+
+#define INV_ICM42607_REG_ACCEL_CONFIG0 0x21
+#define INV_ICM42607_ACCEL_CONFIG0_FS_SEL_MASK GENMASK(6, 5)
+#define INV_ICM42607_ACCEL_CONFIG0_ODR_MASK GENMASK(3, 0)
+
+#define INV_ICM42607_REG_TEMP_CONFIG0 0x22
+#define INV_ICM42607_TEMP_CONFIG0_FILTER_MASK GENMASK(6, 4)
+
+#define INV_ICM42607_REG_GYRO_CONFIG1 0x23
+#define INV_ICM42607_GYRO_CONFIG1_FILTER_MASK GENMASK(2, 0)
+
+#define INV_ICM42607_REG_ACCEL_CONFIG1 0x24
+#define INV_ICM42607_ACCEL_CONFIG1_AVG_MASK GENMASK(6, 4)
+#define INV_ICM42607_ACCEL_CONFIG1_FILTER_MASK GENMASK(2, 0)
+
+#define INV_ICM42607_REG_APEX_CONFIG0 0x25
+#define INV_ICM42607_APEX_CONFIG0_DMP_POWER_SAVE_EN BIT(3)
+#define INV_ICM42607_APEX_CONFIG0_DMP_INIT_EN BIT(2)
+#define INV_ICM42607_APEX_CONFIG0_DMP_MEM_RESET_EN BIT(0)
+
+#define INV_ICM42607_REG_APEX_CONFIG1 0x26
+#define INV_ICM42607_APEX_CONFIG1_SMD_ENABLE BIT(6)
+#define INV_ICM42607_APEX_CONFIG1_FF_ENABLE BIT(5)
+#define INV_ICM42607_APEX_CONFIG1_TILT_ENABLE BIT(4)
+#define INV_ICM42607_APEX_CONFIG1_PED_ENABLE BIT(3)
+#define INV_ICM42607_APEX_CONFIG1_DMP_ODR_MASK GENMASK(1, 0)
+
+#define INV_ICM42607_REG_WOM_CONFIG 0x27
+#define INV_ICM42607_WOM_CONFIG_INT_DUR_MASK GENMASK(4, 3)
+#define INV_ICM42607_WOM_CONFIG_INT_MODE BIT(2)
+#define INV_ICM42607_WOM_CONFIG_MODE BIT(1)
+#define INV_ICM42607_WOM_CONFIG_EN BIT(0)
+
+#define INV_ICM42607_REG_FIFO_CONFIG1 0x28
+#define INV_ICM42607_FIFO_CONFIG1_MODE BIT(1)
+#define INV_ICM42607_FIFO_CONFIG1_BYPASS BIT(0)
+
+#define INV_ICM42607_REG_FIFO_CONFIG2 0x29
+#define INV_ICM42607_REG_FIFO_CONFIG3 0x2A
+#define INV_ICM42607_FIFO_WATERMARK_VAL(_wm) \
+ cpu_to_le16((_wm) & GENMASK(11, 0))
+/* FIFO is 2048 bytes, let 12 samples for reading latency */
+#define INV_ICM42607_FIFO_WATERMARK_MAX (2048 - 12 * 16)
+#define INV_ICM42607_FIFO_1SENSOR_PACKET_SIZE 8
+#define INV_ICM42607_FIFO_2SENSORS_PACKET_SIZE 16
+
+#define INV_ICM42607_REG_INT_SOURCE0 0x2B
+#define INV_ICM42607_INT_SOURCE0_ST_INT1_EN BIT(7)
+#define INV_ICM42607_INT_SOURCE0_FSYNC_INT1_EN BIT(6)
+#define INV_ICM42607_INT_SOURCE0_PLL_RDY_INT1_EN BIT(5)
+#define INV_ICM42607_INT_SOURCE0_RESET_DONE_INT1_EN BIT(4)
+#define INV_ICM42607_INT_SOURCE0_DRDY_INT1_EN BIT(3)
+#define INV_ICM42607_INT_SOURCE0_FIFO_THS_INT1_EN BIT(2)
+#define INV_ICM42607_INT_SOURCE0_FIFO_FULL_INT1_EN BIT(1)
+#define INV_ICM42607_INT_SOURCE0_AGC_RDY_INT1_EN BIT(0)
+
+#define INV_ICM42607_REG_INT_SOURCE1 0x2C
+#define INV_ICM42607_INT_SOURCE1_I3C_ERROR_INT1_EN BIT(6)
+#define INV_ICM42607_INT_SOURCE1_SMD_INT1_EN BIT(3)
+#define INV_ICM42607_INT_SOURCE1_WOM_INT1_EN GENMASK(2, 0)
+
+#define INV_ICM42607_REG_INT_SOURCE3 0x2D
+#define INV_ICM42607_INT_SOURCE3_ST_INT2_EN BIT(7)
+#define INV_ICM42607_INT_SOURCE3_FSYNC_INT2_EN BIT(6)
+#define INV_ICM42607_INT_SOURCE3_PLL_RDY_INT2_EN BIT(5)
+#define INV_ICM42607_INT_SOURCE3_RESET_DONE_INT2_EN BIT(4)
+#define INV_ICM42607_INT_SOURCE3_DRDY_INT2_EN BIT(3)
+#define INV_ICM42607_INT_SOURCE3_FIFO_THS_INT2_EN BIT(2)
+#define INV_ICM42607_INT_SOURCE3_FIFO_FULL_INT2_EN BIT(1)
+#define INV_ICM42607_INT_SOURCE3_AGC_RDY_INT2_EN BIT(0)
+
+#define INV_ICM42607_REG_INT_SOURCE4 0x2E
+#define INV_ICM42607_INT_SOURCE4_I3C_ERROR_INT2_EN BIT(6)
+#define INV_ICM42607_INT_SOURCE4_SMD_INT2_EN BIT(3)
+#define INV_ICM42607_INT_SOURCE4_WOM_Z_INT2_EN BIT(2)
+#define INV_ICM42607_INT_SOURCE4_WOM_Y_INT2_EN BIT(1)
+#define INV_ICM42607_INT_SOURCE4_WOM_X_INT2_EN BIT(0)
+
+#define INV_ICM42607_REG_FIFO_LOST_PKT0 0x2F
+#define INV_ICM42607_REG_FIFO_LOST_PKT1 0x30
+
+#define INV_ICM42607_REG_INTF_CONFIG0 0x35
+#define INV_ICM42607_INTF_CONFIG0_FIFO_COUNT_FORMAT BIT(6)
+#define INV_ICM42607_INTF_CONFIG0_FIFO_COUNT_ENDIAN BIT(5)
+#define INV_ICM42607_INTF_CONFIG0_SENSOR_DATA_ENDIAN BIT(4)
+#define INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK GENMASK(1, 0)
+#define INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS \
+ FIELD_PREP(INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK, 2)
+#define INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS \
+ FIELD_PREP(INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK, 3)
+
+#define INV_ICM42607_REG_INTF_CONFIG1 0x36
+#define INV_ICM42607_INTF_CONFIG1_I3C_SDR_EN BIT(3)
+#define INV_ICM42607_INTF_CONFIG1_I3C_DDR_EN BIT(2)
+#define INV_ICM42607_INTF_CONFIG1_CLKSEL_MASK GENMASK(1, 0)
+#define INV_ICM42607_INTF_CONFIG1_CLKSEL_INT 0
+#define INV_ICM42607_INTF_CONFIG1_CLKSEL_PLL 1
+#define INV_ICM42607_INTF_CONFIG1_CLKSEL_OFF 2
+
+#define INV_ICM42607_REG_INT_STATUS_DRDY 0x39
+#define INV_ICM42607_INT_STATUS_DRDY_DATA_RDY BIT(0)
+
+#define INV_ICM42607_REG_INT_STATUS 0x3A
+#define INV_ICM42607_INT_STATUS_ST BIT(7)
+#define INV_ICM42607_INT_STATUS_FSYNC BIT(6)
+#define INV_ICM42607_INT_STATUS_PLL_RDY BIT(5)
+#define INV_ICM42607_INT_STATUS_RESET_DONE BIT(4)
+#define INV_ICM42607_INT_STATUS_FIFO_THS BIT(2)
+#define INV_ICM42607_INT_STATUS_FIFO_FULL BIT(1)
+#define INV_ICM42607_INT_STATUS_AGC_RDY BIT(0)
+
+#define INV_ICM42607_REG_INT_STATUS2 0x3B
+#define INV_ICM42607_INT_STATUS2_SMD BIT(3)
+#define INV_ICM42607_INT_STATUS2_WOM_INT GENMASK(2, 0)
+
+#define INV_ICM42607_REG_INT_STATUS3 0x3C
+#define INV_ICM42607_INT_STATUS3_STEP_DET BIT(5)
+#define INV_ICM42607_INT_STATUS3_STEP_CNT_OVF BIT(4)
+#define INV_ICM42607_INT_STATUS3_TILT_DET BIT(3)
+#define INV_ICM42607_INT_STATUS3_FF_DET BIT(2)
+
+/*
+ * FIFO access registers
+ * FIFO count is 16 bits (2 registers) big-endian
+ * FIFO data is a continuous read register to read FIFO content
+ */
+#define INV_ICM42607_REG_FIFO_COUNTH 0x3D
+#define INV_ICM42607_REG_FIFO_COUNTL 0x3E
+#define INV_ICM42607_REG_FIFO_DATA 0x3F
+
+#define INV_ICM42607_REG_ACCEL_WOM_X_THR 0x4b
+#define INV_ICM42607_REG_ACCEL_WOM_Y_THR 0x4c
+#define INV_ICM42607_REG_ACCEL_WOM_Z_THR 0x4d
+
+#define INV_ICM42607_REG_WHOAMI 0x75
+#define INV_ICM42607P_WHOAMI 0x60
+#define INV_ICM42607_WHOAMI 0x67
+
+/* Timings as listed in section 3 of datasheet */
+#define INV_ICM42607_POWER_UP_TIME_US 100000
+#define INV_ICM42607_RESET_TIME_MS 1
+#define INV_ICM42607_ACCEL_STARTUP_TIME_MS 10
+#define INV_ICM42607_GYRO_STARTUP_TIME_MS 30
+#define INV_ICM42607_TEMP_STARTUP_TIME_MS 77
+
+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;
+
+int inv_icm42607_core_probe(struct regmap *regmap,
+ const struct inv_icm42607_hw *hw,
+ inv_icm42607_bus_setup bus_setup);
+
+#endif
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
new file mode 100644
index 000000000000..334264120b42
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 InvenSense, Inc.
+ */
+
+#include <linux/delay.h>
+#include <linux/dev_printk.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/time.h>
+
+#include "inv_icm42607.h"
+
+static int inv_icm42607_set_conf(struct inv_icm42607_state *st,
+ const struct inv_icm42607_conf *conf)
+{
+ unsigned int val;
+ int ret;
+
+ val = FIELD_PREP(INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK, conf->gyro.mode);
+ val |= FIELD_PREP(INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK, conf->accel.mode);
+ /*
+ * No temperature enable reg in datasheet, but BSP driver selected RC
+ * oscillator clock in LP mode when temperature was disabled.
+ */
+ if (!conf->temp_en)
+ val |= INV_ICM42607_PWR_MGMT0_ACCEL_LP_CLK_SEL;
+ ret = regmap_write(st->map, INV_ICM42607_REG_PWR_MGMT0, val);
+ if (ret)
+ return ret;
+
+ val = FIELD_PREP(INV_ICM42607_GYRO_CONFIG0_FS_SEL_MASK, conf->gyro.fs);
+ val |= FIELD_PREP(INV_ICM42607_GYRO_CONFIG0_ODR_MASK, conf->gyro.odr);
+ ret = regmap_write(st->map, INV_ICM42607_REG_GYRO_CONFIG0, val);
+ if (ret)
+ return ret;
+
+ val = FIELD_PREP(INV_ICM42607_ACCEL_CONFIG0_FS_SEL_MASK, conf->accel.fs);
+ val |= FIELD_PREP(INV_ICM42607_ACCEL_CONFIG0_ODR_MASK, conf->accel.odr);
+ ret = regmap_write(st->map, INV_ICM42607_REG_ACCEL_CONFIG0, val);
+ if (ret)
+ return ret;
+
+ val = FIELD_PREP(INV_ICM42607_GYRO_CONFIG1_FILTER_MASK, conf->gyro.filter);
+ ret = regmap_update_bits(st->map, INV_ICM42607_REG_GYRO_CONFIG1,
+ INV_ICM42607_GYRO_CONFIG1_FILTER_MASK, val);
+ if (ret)
+ return ret;
+
+ val = FIELD_PREP(INV_ICM42607_ACCEL_CONFIG1_FILTER_MASK, conf->accel.filter);
+ ret = regmap_update_bits(st->map, INV_ICM42607_REG_ACCEL_CONFIG1,
+ INV_ICM42607_ACCEL_CONFIG1_FILTER_MASK, val);
+ if (ret)
+ return ret;
+
+ st->conf = *conf;
+
+ return 0;
+}
+
+static int inv_icm42607_setup(struct inv_icm42607_state *st,
+ inv_icm42607_bus_setup inv_icm42607_bus_setup)
+{
+ const struct device *dev = regmap_get_device(st->map);
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(st->map, INV_ICM42607_REG_WHOAMI, &val);
+ if (ret)
+ return ret;
+
+ /* Warn, but don't fail. */
+ if (val != st->hw->whoami)
+ dev_warn(dev, "Unknown whoami %#02x expected %#02x (%s)\n",
+ val, st->hw->whoami, st->hw->name);
+
+ ret = regmap_write(st->map, INV_ICM42607_REG_SIGNAL_PATH_RESET,
+ INV_ICM42607_SIGNAL_PATH_RESET_SOFT_RESET);
+ if (ret)
+ return ret;
+
+ fsleep(INV_ICM42607_RESET_TIME_MS * USEC_PER_MSEC);
+
+ /*
+ * No polling interval specified in datasheet, so use reset time as
+ * polling interval and 10x reset time as timeout period.
+ */
+ ret = regmap_read_poll_timeout(st->map, INV_ICM42607_REG_INT_STATUS,
+ val, val & INV_ICM42607_INT_STATUS_RESET_DONE,
+ (INV_ICM42607_RESET_TIME_MS * USEC_PER_MSEC),
+ (INV_ICM42607_RESET_TIME_MS * USEC_PER_MSEC * 10));
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "reset error, reset done bit not set\n");
+
+ /* Sync the regcache again after a reset. */
+ regcache_mark_dirty(st->map);
+ ret = regcache_sync(st->map);
+ if (ret)
+ return ret;
+
+ ret = inv_icm42607_bus_setup(st);
+ if (ret)
+ return ret;
+
+ ret = regmap_set_bits(st->map, INV_ICM42607_REG_INTF_CONFIG0,
+ INV_ICM42607_INTF_CONFIG0_SENSOR_DATA_ENDIAN);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(st->map, INV_ICM42607_REG_INTF_CONFIG1,
+ INV_ICM42607_INTF_CONFIG1_CLKSEL_MASK,
+ INV_ICM42607_INTF_CONFIG1_CLKSEL_PLL);
+ if (ret)
+ return ret;
+
+ return inv_icm42607_set_conf(st, st->hw->conf);
+}
+
+static int inv_icm42607_enable_vddio_reg(struct inv_icm42607_state *st)
+{
+ int ret;
+
+ ret = regulator_enable(st->vddio_supply);
+ if (ret)
+ return ret;
+
+ fsleep(INV_ICM42607_POWER_UP_TIME_US);
+
+ return 0;
+}
+
+static void inv_icm42607_disable_vddio_reg(void *_data)
+{
+ struct inv_icm42607_state *st = _data;
+
+ regulator_disable(st->vddio_supply);
+}
+
+int inv_icm42607_core_probe(struct regmap *regmap,
+ const struct inv_icm42607_hw *hw,
+ inv_icm42607_bus_setup inv_icm42607_bus_setup)
+{
+ struct device *dev = regmap_get_device(regmap);
+ struct inv_icm42607_state *st;
+ int ret;
+
+ st = devm_kzalloc(dev, sizeof(*st), GFP_KERNEL);
+ if (!st)
+ return -ENOMEM;
+
+ ret = devm_mutex_init(dev, &st->lock);
+ if (ret)
+ return ret;
+
+ st->hw = hw;
+ st->map = regmap;
+
+ ret = iio_read_mount_matrix(dev, &st->orientation);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to retrieve mounting matrix\n");
+
+ ret = devm_regulator_get_enable(dev, "vdd");
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to get vdd regulator\n");
+
+ st->vddio_supply = devm_regulator_get(dev, "vddio");
+ if (IS_ERR(st->vddio_supply))
+ return dev_err_probe(dev, PTR_ERR(st->vddio_supply),
+ "Failed to get vddio regulator\n");
+
+ ret = inv_icm42607_enable_vddio_reg(st);
+ if (ret)
+ return ret;
+
+ ret = devm_add_action_or_reset(dev, inv_icm42607_disable_vddio_reg, st);
+ if (ret)
+ return ret;
+
+ /* Setup chip registers (includes WHOAMI check, reset check, bus setup) */
+ ret = inv_icm42607_setup(st, inv_icm42607_bus_setup);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(inv_icm42607_core_probe, "IIO_ICM42607");
+
+MODULE_AUTHOR("InvenSense, Inc.");
+MODULE_DESCRIPTION("InvenSense ICM-42607x device driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_INV_SENSORS_TIMESTAMP");
--
2.43.0
^ permalink raw reply related
* [PATCH V11 4/9] iio: imu: inv_icm42607: Add I2C and SPI For icm42607
From: Chris Morgan @ 2026-06-10 17:54 UTC (permalink / raw)
To: linux-iio
Cc: andy, nuno.sa, dlechner, jic23, jean-baptiste.maneyrol,
linux-rockchip, devicetree, heiko, conor+dt, krzk+dt, robh,
andriy.shevchenko, Chris Morgan
In-Reply-To: <20260610175455.19006-1-macroalpha82@gmail.com>
From: Chris Morgan <macromorgan@hotmail.com>
Add I2C and SPI driver support for InvenSense ICM-42607 devices.
Add necessary Kconfig and Makefile to allow building of (incomplete)
driver.
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
---
drivers/iio/imu/Kconfig | 1 +
drivers/iio/imu/Makefile | 1 +
drivers/iio/imu/inv_icm42607/Kconfig | 30 +++++
drivers/iio/imu/inv_icm42607/Makefile | 10 ++
drivers/iio/imu/inv_icm42607/inv_icm42607.h | 16 +++
.../iio/imu/inv_icm42607/inv_icm42607_core.c | 57 ++++++++++
.../iio/imu/inv_icm42607/inv_icm42607_i2c.c | 92 ++++++++++++++++
.../iio/imu/inv_icm42607/inv_icm42607_spi.c | 104 ++++++++++++++++++
8 files changed, 311 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_i2c.c
create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index 7e0181c27bb6..8bab4616be20 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -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"
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index 13fb7846e9c9..3268dc2371ae 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -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/
diff --git a/drivers/iio/imu/inv_icm42607/Kconfig b/drivers/iio/imu/inv_icm42607/Kconfig
new file mode 100644
index 000000000000..7ba64e6e8d80
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/Kconfig
@@ -0,0 +1,30 @@
+# 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-42607X 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.
+
+config INV_ICM42607_SPI
+ tristate "InvenSense ICM-42607X 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.
diff --git a/drivers/iio/imu/inv_icm42607/Makefile b/drivers/iio/imu/inv_icm42607/Makefile
new file mode 100644
index 000000000000..be109102e203
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/Makefile
@@ -0,0 +1,10 @@
+# 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
+
+obj-$(CONFIG_INV_ICM42607_SPI) += inv-icm42607-spi.o
+inv-icm42607-spi-y += inv_icm42607_spi.o
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607.h b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
index 716fc0f1c3fd..743a15fb1b89 100644
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607.h
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
@@ -12,6 +12,22 @@
#include <linux/regmap.h>
#include <linux/types.h>
+/*
+ * Serial bus slew rates. Rates are expressed as range between the two
+ * values with the midpoint as the typical rate. For the final value of
+ * 2ns, 2ns is considered the max value with no expressed minimum or
+ * typical value.
+ */
+enum inv_icm42607_slew_rate {
+ INV_ICM42607_SLEW_RATE_20_60NS = 0,
+ INV_ICM42607_SLEW_RATE_12_36NS = 1,
+ INV_ICM42607_SLEW_RATE_6_19NS = 2,
+ INV_ICM42607_SLEW_RATE_4_14NS = 3,
+ INV_ICM42607_SLEW_RATE_2_6NS = 4,
+ INV_ICM42607_SLEW_RATE_2NS = 5,
+ INV_ICM42607_SLEW_RATE_NB
+};
+
enum inv_icm42607_sensor_mode {
INV_ICM42607_SENSOR_MODE_OFF = 0,
INV_ICM42607_SENSOR_MODE_STANDBY = 1,
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
index 334264120b42..26dc09bbeaed 100644
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
@@ -14,6 +14,63 @@
#include "inv_icm42607.h"
+static bool inv_icm42607_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case INV_ICM42607_REG_MCLK_RDY:
+ case INV_ICM42607_REG_SIGNAL_PATH_RESET:
+ case INV_ICM42607_REG_TEMP_DATA1 ... INV_ICM42607_REG_APEX_DATA5:
+ case INV_ICM42607_REG_APEX_CONFIG0:
+ case INV_ICM42607_REG_FIFO_CONFIG2 ... INV_ICM42607_REG_FIFO_CONFIG3:
+ case INV_ICM42607_REG_FIFO_LOST_PKT0 ... INV_ICM42607_REG_APEX_DATA3:
+ case INV_ICM42607_REG_INT_STATUS_DRDY:
+ case INV_ICM42607_REG_INT_STATUS ... INV_ICM42607_REG_FIFO_DATA:
+ return true;
+ }
+
+ return false;
+}
+
+const struct regmap_config inv_icm42607_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = INV_ICM42607_REG_WHOAMI,
+ .cache_type = REGCACHE_MAPLE,
+ .volatile_reg = inv_icm42607_is_volatile_reg,
+};
+EXPORT_SYMBOL_NS_GPL(inv_icm42607_regmap_config, "IIO_ICM42607");
+
+/* chip initial default configuration */
+static const struct inv_icm42607_conf inv_icm42607_default_conf = {
+ .gyro = {
+ .mode = INV_ICM42607_SENSOR_MODE_OFF,
+ .fs = INV_ICM42607_GYRO_FS_1000DPS,
+ .odr = INV_ICM42607_ODR_100HZ,
+ .filter = INV_ICM42607_FILTER_BW_25HZ,
+ },
+ .accel = {
+ .mode = INV_ICM42607_SENSOR_MODE_OFF,
+ .fs = INV_ICM42607_ACCEL_FS_4G,
+ .odr = INV_ICM42607_ODR_100HZ,
+ .filter = INV_ICM42607_FILTER_BW_25HZ,
+ },
+ .temp_en = false,
+};
+
+const struct inv_icm42607_hw inv_icm42607_hw_data = {
+ .whoami = INV_ICM42607_WHOAMI,
+ .name = "icm42607",
+ .conf = &inv_icm42607_default_conf,
+};
+EXPORT_SYMBOL_NS_GPL(inv_icm42607_hw_data, "IIO_ICM42607");
+
+const struct inv_icm42607_hw inv_icm42607p_hw_data = {
+ .whoami = INV_ICM42607P_WHOAMI,
+ .name = "icm42607p",
+ .conf = &inv_icm42607_default_conf,
+};
+EXPORT_SYMBOL_NS_GPL(inv_icm42607p_hw_data, "IIO_ICM42607");
+
static int inv_icm42607_set_conf(struct inv_icm42607_state *st,
const struct inv_icm42607_conf *conf)
{
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c
new file mode 100644
index 000000000000..2946d5465853
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 InvenSense, Inc.
+ */
+
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include "inv_icm42607.h"
+
+static int inv_icm42607_i2c_bus_setup(struct inv_icm42607_state *st)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_clear_bits(st->map, INV_ICM42607_REG_INTF_CONFIG1,
+ INV_ICM42607_INTF_CONFIG1_I3C_DDR_EN |
+ INV_ICM42607_INTF_CONFIG1_I3C_SDR_EN);
+ if (ret)
+ return ret;
+
+ val = FIELD_PREP(INV_ICM42607_DRIVE_CONFIG2_I2C_MASK,
+ INV_ICM42607_SLEW_RATE_12_36NS);
+ ret = regmap_update_bits(st->map, INV_ICM42607_REG_DRIVE_CONFIG2,
+ INV_ICM42607_DRIVE_CONFIG2_I2C_MASK, val);
+ if (ret)
+ return ret;
+
+ return regmap_update_bits(st->map, INV_ICM42607_REG_INTF_CONFIG0,
+ INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK,
+ INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS);
+}
+
+static int inv_icm42607_probe(struct i2c_client *client)
+{
+ const struct inv_icm42607_hw *hw;
+ struct regmap *regmap;
+
+ hw = i2c_get_match_data(client);
+ if (!hw)
+ return dev_err_probe(&client->dev, -ENODEV,
+ "Failed to get i2c data\n");
+
+ regmap = devm_regmap_init_i2c(client, &inv_icm42607_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(&client->dev, PTR_ERR(regmap),
+ "Failed to register i2c regmap %ld\n",
+ PTR_ERR(regmap));
+
+ return inv_icm42607_core_probe(regmap, hw, inv_icm42607_i2c_bus_setup);
+}
+
+static const struct i2c_device_id inv_icm42607_id[] = {
+ {
+ .name = "icm42607",
+ .driver_data = (kernel_ulong_t)&inv_icm42607_hw_data
+ }, {
+ .name = "icm42607p",
+ .driver_data = (kernel_ulong_t)&inv_icm42607p_hw_data
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, inv_icm42607_id);
+
+static const struct of_device_id inv_icm42607_of_matches[] = {
+ {
+ .compatible = "invensense,icm42607",
+ .data = &inv_icm42607_hw_data,
+ }, {
+ .compatible = "invensense,icm42607p",
+ .data = &inv_icm42607p_hw_data,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, inv_icm42607_of_matches);
+
+static struct i2c_driver inv_icm42607_driver = {
+ .driver = {
+ .name = "inv-icm42607-i2c",
+ .of_match_table = inv_icm42607_of_matches,
+ },
+ .id_table = inv_icm42607_id,
+ .probe = inv_icm42607_probe,
+};
+module_i2c_driver(inv_icm42607_driver);
+
+MODULE_AUTHOR("InvenSense, Inc.");
+MODULE_DESCRIPTION("InvenSense ICM-42607x I2C driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_ICM42607");
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c
new file mode 100644
index 000000000000..3485777ac5b6
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 InvenSense, Inc.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#include "inv_icm42607.h"
+
+static int inv_icm42607_spi_bus_setup(struct inv_icm42607_state *st)
+{
+ unsigned int val;
+ int ret;
+
+ /* Only support 4-wire mode for now. */
+ ret = regmap_set_bits(st->map, INV_ICM42607_REG_DEVICE_CONFIG,
+ INV_ICM42607_DEVICE_CONFIG_SPI_AP_4WIRE);
+ if (ret)
+ return ret;
+
+ ret = regmap_clear_bits(st->map, INV_ICM42607_REG_INTF_CONFIG1,
+ INV_ICM42607_INTF_CONFIG1_I3C_DDR_EN |
+ INV_ICM42607_INTF_CONFIG1_I3C_SDR_EN);
+ if (ret)
+ return ret;
+
+ val = FIELD_PREP(INV_ICM42607_DRIVE_CONFIG3_SPI_MASK,
+ INV_ICM42607_SLEW_RATE_2NS);
+ ret = regmap_update_bits(st->map, INV_ICM42607_REG_DRIVE_CONFIG3,
+ INV_ICM42607_DRIVE_CONFIG3_SPI_MASK, val);
+ if (ret)
+ return ret;
+
+ return regmap_update_bits(st->map, INV_ICM42607_REG_INTF_CONFIG0,
+ INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK,
+ INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS);
+}
+
+static int inv_icm42607_probe(struct spi_device *spi)
+{
+ const struct inv_icm42607_hw *hw;
+ struct regmap *regmap;
+
+ hw = spi_get_device_match_data(spi);
+ if (!hw)
+ return dev_err_probe(&spi->dev, -ENODEV,
+ "Failed to get SPI data\n");
+
+ if (spi->mode & SPI_3WIRE)
+ return dev_err_probe(&spi->dev, -ENODEV,
+ "SPI 3-wire mode not supported\n");
+
+ regmap = devm_regmap_init_spi(spi, &inv_icm42607_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(&spi->dev, PTR_ERR(regmap),
+ "Failed to register spi regmap %ld\n",
+ PTR_ERR(regmap));
+
+ return inv_icm42607_core_probe(regmap, hw,
+ inv_icm42607_spi_bus_setup);
+}
+
+static const struct spi_device_id inv_icm42607_spi_id_table[] = {
+ {
+ .name = "icm42607",
+ .driver_data = (kernel_ulong_t)&inv_icm42607_hw_data
+ }, {
+ .name = "icm42607p",
+ .driver_data = (kernel_ulong_t)&inv_icm42607p_hw_data
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, inv_icm42607_spi_id_table);
+
+static const struct of_device_id inv_icm42607_of_matches[] = {
+ {
+ .compatible = "invensense,icm42607",
+ .data = &inv_icm42607_hw_data,
+ },
+ {
+ .compatible = "invensense,icm42607p",
+ .data = &inv_icm42607p_hw_data,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, inv_icm42607_of_matches);
+
+static struct spi_driver inv_icm42607_driver = {
+ .driver = {
+ .name = "inv-icm42607-spi",
+ .of_match_table = inv_icm42607_of_matches,
+ },
+ .id_table = inv_icm42607_spi_id_table,
+ .probe = inv_icm42607_probe,
+};
+module_spi_driver(inv_icm42607_driver);
+
+MODULE_AUTHOR("InvenSense, Inc.");
+MODULE_DESCRIPTION("InvenSense ICM-42607x SPI driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_ICM42607");
--
2.43.0
^ permalink raw reply related
* [PATCH V11 5/9] iio: imu: inv_icm42607: Add PM support for icm42607
From: Chris Morgan @ 2026-06-10 17:54 UTC (permalink / raw)
To: linux-iio
Cc: andy, nuno.sa, dlechner, jic23, jean-baptiste.maneyrol,
linux-rockchip, devicetree, heiko, conor+dt, krzk+dt, robh,
andriy.shevchenko, Chris Morgan
In-Reply-To: <20260610175455.19006-1-macroalpha82@gmail.com>
From: Chris Morgan <macromorgan@hotmail.com>
Add power management support for the ICM42607 device driver.
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
---
drivers/iio/imu/inv_icm42607/inv_icm42607.h | 18 +++
.../iio/imu/inv_icm42607/inv_icm42607_core.c | 125 ++++++++++++++++++
.../iio/imu/inv_icm42607/inv_icm42607_i2c.c | 1 +
.../iio/imu/inv_icm42607/inv_icm42607_spi.c | 1 +
4 files changed, 145 insertions(+)
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607.h b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
index 743a15fb1b89..1f1397eaa00e 100644
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607.h
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
@@ -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/types.h>
@@ -103,22 +104,32 @@ struct inv_icm42607_hw {
const struct inv_icm42607_conf *conf;
};
+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
* @lock: lock for serializing multiple registers access.
* @hw: Hardware specific data.
* @map: regmap pointer.
* @vddio_supply: I/O voltage regulator for the chip.
+ * @vddio_en: I/O voltage status for runtime PM.
* @orientation: sensor chip orientation relative to main hardware.
* @conf: chip sensors configurations.
+ * @suspended: suspended sensors configuration.
*/
struct inv_icm42607_state {
struct mutex lock;
const struct inv_icm42607_hw *hw;
struct regmap *map;
struct regulator *vddio_supply;
+ bool vddio_en;
struct iio_mount_matrix orientation;
struct inv_icm42607_conf conf;
+ struct inv_icm42607_suspended suspended;
};
/* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
@@ -337,11 +348,18 @@ struct inv_icm42607_state {
#define INV_ICM42607_GYRO_STARTUP_TIME_MS 30
#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 2000
+
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,
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
index 26dc09bbeaed..5e1f924a3e34 100644
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
@@ -8,6 +8,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>
@@ -71,6 +72,51 @@ 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 oldgyro = st->conf.gyro.mode;
+ enum inv_icm42607_sensor_mode oldaccel = st->conf.accel.mode;
+ bool oldtemp = st->conf.temp_en;
+ unsigned int sleepval;
+ unsigned int val;
+ int ret;
+
+ if (gyro == oldgyro && accel == oldaccel && temp == oldtemp)
+ return 0;
+
+ val = FIELD_PREP(INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK, gyro);
+ val |= FIELD_PREP(INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK, accel);
+ if (!temp)
+ val |= INV_ICM42607_PWR_MGMT0_ACCEL_LP_CLK_SEL;
+ 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;
+
+ sleepval = 0;
+ if (temp && !oldtemp)
+ sleepval = max(sleepval, INV_ICM42607_TEMP_STARTUP_TIME_MS);
+
+ if (accel != oldaccel)
+ sleepval = max(sleepval, INV_ICM42607_ACCEL_STARTUP_TIME_MS);
+
+ if (gyro != oldgyro)
+ sleepval = max(sleepval, INV_ICM42607_GYRO_STARTUP_TIME_MS);
+
+ if (sleep_ms)
+ *sleep_ms = sleepval;
+ else if (sleepval)
+ fsleep(sleepval * USEC_PER_MSEC);
+
+ return 0;
+}
+
static int inv_icm42607_set_conf(struct inv_icm42607_state *st,
const struct inv_icm42607_conf *conf)
{
@@ -181,12 +227,17 @@ static int inv_icm42607_enable_vddio_reg(struct inv_icm42607_state *st)
{
int ret;
+ if (st->vddio_en)
+ return 0;
+
ret = regulator_enable(st->vddio_supply);
if (ret)
return ret;
fsleep(INV_ICM42607_POWER_UP_TIME_US);
+ st->vddio_en = true;
+
return 0;
}
@@ -194,7 +245,12 @@ static void inv_icm42607_disable_vddio_reg(void *_data)
{
struct inv_icm42607_state *st = _data;
+ if (!st->vddio_en)
+ return;
+
regulator_disable(st->vddio_supply);
+
+ st->vddio_en = false;
}
int inv_icm42607_core_probe(struct regmap *regmap,
@@ -209,6 +265,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;
@@ -244,10 +302,77 @@ 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;
}
EXPORT_SYMBOL_NS_GPL(inv_icm42607_core_probe, "IIO_ICM42607");
+static int inv_icm42607_suspend(struct device *dev)
+{
+ struct inv_icm42607_state *st = dev_get_drvdata(dev);
+ int ret;
+
+ ret = pm_runtime_force_suspend(dev);
+ if (ret)
+ return ret;
+
+ inv_icm42607_disable_vddio_reg(st);
+
+ return 0;
+}
+
+static int inv_icm42607_resume(struct device *dev)
+{
+ struct inv_icm42607_state *st = dev_get_drvdata(dev);
+ int ret;
+
+ ret = inv_icm42607_enable_vddio_reg(st);
+ if (ret)
+ return ret;
+
+ return pm_runtime_force_resume(dev);
+}
+
+static int inv_icm42607_runtime_suspend(struct device *dev)
+{
+ struct inv_icm42607_state *st = dev_get_drvdata(dev);
+
+ guard(mutex)(&st->lock);
+
+ /* save sensors state */
+ st->suspended.gyro = st->conf.gyro.mode;
+ st->suspended.accel = st->conf.accel.mode;
+ st->suspended.temp = st->conf.temp_en;
+
+ return inv_icm42607_set_pwr_mgmt0(st, INV_ICM42607_SENSOR_MODE_OFF,
+ INV_ICM42607_SENSOR_MODE_OFF, false,
+ NULL);
+}
+
+static int inv_icm42607_runtime_resume(struct device *dev)
+{
+ struct inv_icm42607_state *st = dev_get_drvdata(dev);
+
+ guard(mutex)(&st->lock);
+
+ /* restore sensors state */
+ return inv_icm42607_set_pwr_mgmt0(st, st->suspended.gyro,
+ st->suspended.accel,
+ st->suspended.temp, NULL);
+}
+
+EXPORT_NS_GPL_DEV_PM_OPS(inv_icm42607_pm_ops, IIO_ICM42607) = {
+ SYSTEM_SLEEP_PM_OPS(inv_icm42607_suspend, inv_icm42607_resume)
+ RUNTIME_PM_OPS(inv_icm42607_runtime_suspend,
+ inv_icm42607_runtime_resume, NULL)
+};
+
MODULE_AUTHOR("InvenSense, Inc.");
MODULE_DESCRIPTION("InvenSense ICM-42607x device driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c
index 2946d5465853..0c2ff8e12643 100644
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c
@@ -80,6 +80,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,
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c
index 3485777ac5b6..1a7f6b0fa86b 100644
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c
@@ -92,6 +92,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,
--
2.43.0
^ permalink raw reply related
* [PATCH V11 6/9] iio: imu: inv_icm42607: Add Temp Support in icm42607
From: Chris Morgan @ 2026-06-10 17:54 UTC (permalink / raw)
To: linux-iio
Cc: andy, nuno.sa, dlechner, jic23, jean-baptiste.maneyrol,
linux-rockchip, devicetree, heiko, conor+dt, krzk+dt, robh,
andriy.shevchenko, Chris Morgan
In-Reply-To: <20260610175455.19006-1-macroalpha82@gmail.com>
From: Chris Morgan <macromorgan@hotmail.com>
Add functions for reading temperature sensor data.
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
---
drivers/iio/imu/inv_icm42607/Makefile | 1 +
drivers/iio/imu/inv_icm42607/inv_icm42607.h | 5 ++
.../iio/imu/inv_icm42607/inv_icm42607_core.c | 18 ++++
.../iio/imu/inv_icm42607/inv_icm42607_temp.c | 82 +++++++++++++++++++
.../iio/imu/inv_icm42607/inv_icm42607_temp.h | 33 ++++++++
5 files changed, 139 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
diff --git a/drivers/iio/imu/inv_icm42607/Makefile b/drivers/iio/imu/inv_icm42607/Makefile
index be109102e203..c04953ed42ce 100644
--- a/drivers/iio/imu/inv_icm42607/Makefile
+++ b/drivers/iio/imu/inv_icm42607/Makefile
@@ -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
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607.h b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
index 1f1397eaa00e..1246a92edffc 100644
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607.h
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
@@ -120,6 +120,7 @@ struct inv_icm42607_suspended {
* @orientation: sensor chip orientation relative to main hardware.
* @conf: chip sensors configurations.
* @suspended: suspended sensors configuration.
+ * @buffer: data transfer buffer aligned for DMA.
*/
struct inv_icm42607_state {
struct mutex lock;
@@ -130,6 +131,7 @@ struct inv_icm42607_state {
struct iio_mount_matrix orientation;
struct inv_icm42607_conf conf;
struct inv_icm42607_suspended suspended;
+ __be16 buffer[3] __aligned(IIO_DMA_MINALIGN);
};
/* Virtual register addresses: @bank on MSB (4 upper bits), @address on LSB */
@@ -361,6 +363,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);
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
index 5e1f924a3e34..88e3a064434b 100644
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
@@ -117,6 +117,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)
{
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c
new file mode 100644
index 000000000000..55260082a19e
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c
@@ -0,0 +1,82 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 InvenSense, Inc.
+ */
+
+#include <linux/device.h>
+#include <linux/iio/iio.h>
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include "inv_icm42607.h"
+#include "inv_icm42607_temp.h"
+
+static int inv_icm42607_temp_read(struct inv_icm42607_state *st, s16 *temp)
+{
+ struct device *dev = regmap_get_device(st->map);
+ __be16 *raw;
+ int ret;
+
+ PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);
+ ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&st->lock);
+
+ ret = inv_icm42607_set_temp_conf(st, true, NULL);
+ if (ret)
+ return ret;
+
+ raw = &st->buffer[0];
+ ret = regmap_bulk_read(st->map, INV_ICM42607_REG_TEMP_DATA1,
+ raw, sizeof(*raw));
+ if (ret)
+ return ret;
+
+ *temp = be16_to_cpup(raw);
+ if (*temp == INV_ICM42607_DATA_INVALID)
+ return -EINVAL;
+
+ return 0;
+}
+
+int inv_icm42607_temp_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev);
+ s16 temp;
+ int ret;
+
+ if (chan->type != IIO_TEMP)
+ return -EINVAL;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (!iio_device_claim_direct(indio_dev))
+ return -EBUSY;
+ ret = inv_icm42607_temp_read(st, &temp);
+ iio_device_release_direct(indio_dev);
+ if (ret)
+ return ret;
+ *val = temp;
+ return IIO_VAL_INT;
+ /*
+ * T°C = (temp / 128) + 25
+ * Tm°C = 1000 * ((temp * 100 / 12800) + 25)
+ * scale: 100000 / 12800 ~= 7.8125
+ * offset: 3200
+ */
+ case IIO_CHAN_INFO_SCALE:
+ *val = 7;
+ *val2 = 812500000;
+ return IIO_VAL_INT_PLUS_NANO;
+ case IIO_CHAN_INFO_OFFSET:
+ *val = 3200;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.h b/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.h
new file mode 100644
index 000000000000..e03924e30866
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.h
@@ -0,0 +1,33 @@
+/* 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), \
+ .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
--
2.43.0
^ permalink raw reply related
* [PATCH V11 7/9] iio: imu: inv_icm42607: Add Accelerometer for icm42607
From: Chris Morgan @ 2026-06-10 17:54 UTC (permalink / raw)
To: linux-iio
Cc: andy, nuno.sa, dlechner, jic23, jean-baptiste.maneyrol,
linux-rockchip, devicetree, heiko, conor+dt, krzk+dt, robh,
andriy.shevchenko, Chris Morgan
In-Reply-To: <20260610175455.19006-1-macroalpha82@gmail.com>
From: Chris Morgan <macromorgan@hotmail.com>
Add icm42607 accelerometer sensor for icm42607.
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
---
drivers/iio/imu/inv_icm42607/Makefile | 1 +
drivers/iio/imu/inv_icm42607/inv_icm42607.h | 34 ++
.../iio/imu/inv_icm42607/inv_icm42607_accel.c | 379 ++++++++++++++++++
.../iio/imu/inv_icm42607/inv_icm42607_core.c | 61 +++
4 files changed, 475 insertions(+)
create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c
diff --git a/drivers/iio/imu/inv_icm42607/Makefile b/drivers/iio/imu/inv_icm42607/Makefile
index c04953ed42ce..d74b23b1e1be 100644
--- a/drivers/iio/imu/inv_icm42607/Makefile
+++ b/drivers/iio/imu/inv_icm42607/Makefile
@@ -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
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607.h b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
index 1246a92edffc..52f047d96eb4 100644
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607.h
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
@@ -84,6 +84,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;
@@ -91,6 +102,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;
@@ -120,6 +132,7 @@ struct inv_icm42607_suspended {
* @orientation: sensor chip orientation relative to main hardware.
* @conf: chip sensors configurations.
* @suspended: suspended sensors configuration.
+ * @indio_accel: accelerometer IIO device.
* @buffer: data transfer buffer aligned for DMA.
*/
struct inv_icm42607_state {
@@ -131,9 +144,20 @@ struct inv_icm42607_state {
struct iio_mount_matrix orientation;
struct inv_icm42607_conf conf;
struct inv_icm42607_suspended suspended;
+ struct iio_dev *indio_accel;
__be16 buffer[3] __aligned(IIO_DMA_MINALIGN);
};
+/**
+ * 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 */
@@ -363,6 +387,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);
@@ -370,4 +402,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
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c
new file mode 100644
index 000000000000..cb60bb5ecc14
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c
@@ -0,0 +1,379 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 InvenSense, Inc.
+ */
+
+#include <linux/iio/iio.h>
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include "inv_icm42607.h"
+#include "inv_icm42607_temp.h"
+
+#define INV_ICM42607_ACCEL_CHAN(_modifier, _index, _ext_info) \
+{ \
+ .type = IIO_ACCEL, \
+ .modified = 1, \
+ .channel2 = _modifier, \
+ .info_mask_separate = \
+ BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_type_available = \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .info_mask_shared_by_all_available = \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = _index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_BE, \
+ }, \
+ .ext_info = _ext_info, \
+}
+
+enum inv_icm42607_accel_scan {
+ INV_ICM42607_ACCEL_SCAN_X,
+ INV_ICM42607_ACCEL_SCAN_Y,
+ INV_ICM42607_ACCEL_SCAN_Z,
+ INV_ICM42607_ACCEL_SCAN_TEMP,
+};
+
+static const struct iio_chan_spec_ext_info inv_icm42607_accel_ext_infos[] = {
+ IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42607_get_mount_matrix),
+ { }
+};
+
+static const struct iio_chan_spec inv_icm42607_accel_channels[] = {
+ INV_ICM42607_ACCEL_CHAN(IIO_MOD_X, INV_ICM42607_ACCEL_SCAN_X,
+ inv_icm42607_accel_ext_infos),
+ INV_ICM42607_ACCEL_CHAN(IIO_MOD_Y, INV_ICM42607_ACCEL_SCAN_Y,
+ inv_icm42607_accel_ext_infos),
+ INV_ICM42607_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42607_ACCEL_SCAN_Z,
+ inv_icm42607_accel_ext_infos),
+ INV_ICM42607_TEMP_CHAN(INV_ICM42607_ACCEL_SCAN_TEMP),
+};
+
+static int inv_icm42607_accel_read_sensor(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ s16 *val)
+{
+ struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev);
+ struct inv_icm42607_sensor_state *accel_st = iio_priv(indio_dev);
+ struct device *dev = regmap_get_device(st->map);
+ struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT;
+ unsigned int reg;
+ __be16 *data;
+ int ret;
+
+ if (chan->type != IIO_ACCEL)
+ return -EINVAL;
+
+ switch (chan->channel2) {
+ case IIO_MOD_X:
+ reg = INV_ICM42607_REG_ACCEL_DATA_X1;
+ break;
+ case IIO_MOD_Y:
+ reg = INV_ICM42607_REG_ACCEL_DATA_Y1;
+ break;
+ case IIO_MOD_Z:
+ reg = INV_ICM42607_REG_ACCEL_DATA_Z1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);
+ ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&st->lock);
+
+ /* enable accel sensor */
+ conf.mode = accel_st->power_mode;
+ conf.filter = accel_st->filter;
+ ret = inv_icm42607_set_accel_conf(st, &conf, NULL);
+ if (ret)
+ return ret;
+
+ /* read accel register data */
+ data = &st->buffer[0];
+ ret = regmap_bulk_read(st->map, reg, data, sizeof(*data));
+ if (ret)
+ return ret;
+
+ *val = be16_to_cpup(data);
+ if (*val == INV_ICM42607_DATA_INVALID)
+ return -EINVAL;
+
+ return 0;
+}
+
+static const int inv_icm42607_accel_scale_nano[][2] = {
+ [INV_ICM42607_ACCEL_FS_16G] = { 0, 4788403 },
+ [INV_ICM42607_ACCEL_FS_8G] = { 0, 2394202 },
+ [INV_ICM42607_ACCEL_FS_4G] = { 0, 1197101 },
+ [INV_ICM42607_ACCEL_FS_2G] = { 0, 598550 }
+};
+
+static int inv_icm42607_accel_read_scale(struct iio_dev *indio_dev,
+ int *val, int *val2)
+{
+ struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev);
+ unsigned int idx;
+
+ guard(mutex)(&st->lock);
+
+ idx = st->conf.accel.fs;
+
+ *val = inv_icm42607_accel_scale_nano[idx][0];
+ *val2 = inv_icm42607_accel_scale_nano[idx][1];
+ return IIO_VAL_INT_PLUS_NANO;
+}
+
+static int inv_icm42607_accel_write_scale(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);
+ size_t scales_len = ARRAY_SIZE(inv_icm42607_accel_scale_nano);
+ struct device *dev = regmap_get_device(st->map);
+ unsigned int idx;
+ int ret;
+
+ for (idx = 0; idx < scales_len; idx++) {
+ if (val == inv_icm42607_accel_scale_nano[idx][0] &&
+ val2 == inv_icm42607_accel_scale_nano[idx][1])
+ break;
+ }
+ if (idx >= scales_len)
+ return -EINVAL;
+
+ conf.fs = 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);
+}
+
+/* IIO format int + micro , values 0-5 reserved. */
+static const int inv_icm42607_accel_odr[][2] = {
+ [INV_ICM42607_ODR_1_5625HZ_LP] = { 1, 562500 },
+ [INV_ICM42607_ODR_3_125HZ_LP] = { 3, 125000 },
+ [INV_ICM42607_ODR_6_25HZ_LP] = { 6, 250000 },
+ [INV_ICM42607_ODR_12_5HZ] = { 12, 500000 },
+ [INV_ICM42607_ODR_25HZ] = { 25, 0 },
+ [INV_ICM42607_ODR_50HZ] = { 50, 0 },
+ [INV_ICM42607_ODR_100HZ] = { 100, 0 },
+ [INV_ICM42607_ODR_200HZ] = { 200, 0 },
+ [INV_ICM42607_ODR_400HZ] = { 400, 0 },
+ [INV_ICM42607_ODR_800HZ] = { 800, 0 },
+ [INV_ICM42607_ODR_1600HZ] = { 1600, 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) {
+ 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;
+}
+
+static int inv_icm42607_accel_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_accel_odr); ++idx) {
+ 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);
+
+ ret = inv_icm42607_set_accel_conf(st, &conf, NULL);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int inv_icm42607_accel_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev);
+ s16 data;
+ int ret;
+
+ switch (chan->type) {
+ case IIO_ACCEL:
+ break;
+ case IIO_TEMP:
+ return inv_icm42607_temp_read_raw(indio_dev, chan, val, val2, mask);
+ default:
+ return -EINVAL;
+ }
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (!iio_device_claim_direct(indio_dev))
+ return -EBUSY;
+ ret = inv_icm42607_accel_read_sensor(indio_dev, chan, &data);
+ iio_device_release_direct(indio_dev);
+ if (ret)
+ return ret;
+ *val = data;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ return inv_icm42607_accel_read_scale(indio_dev, val, val2);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return inv_icm42607_accel_read_odr(st, val, val2);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int inv_icm42607_accel_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals,
+ int *type, int *length, long mask)
+{
+ if (chan->type != IIO_ACCEL)
+ return -EINVAL;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ *vals = (const int *)inv_icm42607_accel_scale_nano;
+ *type = IIO_VAL_INT_PLUS_NANO;
+ *length = ARRAY_SIZE(inv_icm42607_accel_scale_nano) * 2;
+ return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *vals = (const int *)inv_icm42607_accel_odr[5];
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ *length = (ARRAY_SIZE(inv_icm42607_accel_odr) - 5) * 2;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int inv_icm42607_accel_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ int ret;
+
+ if (chan->type != IIO_ACCEL)
+ return -EINVAL;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ if (!iio_device_claim_direct(indio_dev))
+ return -EBUSY;
+ ret = inv_icm42607_accel_write_scale(indio_dev, val, val2);
+ iio_device_release_direct(indio_dev);
+ return ret;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return inv_icm42607_accel_write_odr(indio_dev, val, val2);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int inv_icm42607_accel_write_raw_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ long mask)
+{
+ if (chan->type != IIO_ACCEL)
+ return -EINVAL;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ return IIO_VAL_INT_PLUS_NANO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info inv_icm42607_accel_info = {
+ .read_raw = inv_icm42607_accel_read_raw,
+ .read_avail = inv_icm42607_accel_read_avail,
+ .write_raw = inv_icm42607_accel_write_raw,
+ .write_raw_get_fmt = inv_icm42607_accel_write_raw_get_fmt,
+};
+
+struct iio_dev *inv_icm42607_accel_init(struct inv_icm42607_state *st)
+{
+ struct device *dev = regmap_get_device(st->map);
+ const char *name;
+ struct inv_icm42607_sensor_state *accel_st;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ name = devm_kasprintf(dev, GFP_KERNEL, "%s-accel", st->hw->name);
+ if (!name)
+ return ERR_PTR(-ENOMEM);
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*accel_st));
+ if (!indio_dev)
+ return ERR_PTR(-ENOMEM);
+ accel_st = iio_priv(indio_dev);
+
+ accel_st->power_mode = INV_ICM42607_SENSOR_MODE_LOW_NOISE;
+ accel_st->filter = INV_ICM42607_FILTER_BW_73HZ;
+
+ iio_device_set_drvdata(indio_dev, st);
+ indio_dev->name = name;
+ indio_dev->info = &inv_icm42607_accel_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = inv_icm42607_accel_channels;
+ indio_dev->num_channels = ARRAY_SIZE(inv_icm42607_accel_channels);
+
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return indio_dev;
+}
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
index 88e3a064434b..96e170b10aa4 100644
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
@@ -72,6 +72,15 @@ const struct inv_icm42607_hw inv_icm42607p_hw_data = {
};
EXPORT_SYMBOL_NS_GPL(inv_icm42607p_hw_data, "IIO_ICM42607");
+const struct iio_mount_matrix *
+inv_icm42607_get_mount_matrix(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan)
+{
+ const struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev);
+
+ return &st->orientation;
+}
+
static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st,
enum inv_icm42607_sensor_mode gyro,
enum inv_icm42607_sensor_mode accel,
@@ -117,6 +126,53 @@ static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st,
return 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;
+ 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_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;
+ }
+
+ 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);
+}
+
int inv_icm42607_set_temp_conf(struct inv_icm42607_state *st, bool enable,
unsigned int *sleep_ms)
{
@@ -327,6 +383,11 @@ int inv_icm42607_core_probe(struct regmap *regmap,
pm_runtime_set_autosuspend_delay(dev, INV_ICM42607_SUSPEND_DELAY_MS);
pm_runtime_use_autosuspend(dev);
+ /* Initialize IIO device for Accel */
+ st->indio_accel = inv_icm42607_accel_init(st);
+ if (IS_ERR(st->indio_accel))
+ return PTR_ERR(st->indio_accel);
+
return 0;
}
EXPORT_SYMBOL_NS_GPL(inv_icm42607_core_probe, "IIO_ICM42607");
--
2.43.0
^ permalink raw reply related
* [PATCH V11 8/9] iio: imu: inv_icm42607: Add Gyroscope to icm42607
From: Chris Morgan @ 2026-06-10 17:54 UTC (permalink / raw)
To: linux-iio
Cc: andy, nuno.sa, dlechner, jic23, jean-baptiste.maneyrol,
linux-rockchip, devicetree, heiko, conor+dt, krzk+dt, robh,
andriy.shevchenko, Chris Morgan
In-Reply-To: <20260610175455.19006-1-macroalpha82@gmail.com>
From: Chris Morgan <macromorgan@hotmail.com>
Add gyroscope functions to the icm42607 driver.
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
---
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
diff --git a/drivers/iio/imu/inv_icm42607/Makefile b/drivers/iio/imu/inv_icm42607/Makefile
index d74b23b1e1be..7b907e019601 100644
--- a/drivers/iio/imu/inv_icm42607/Makefile
+++ b/drivers/iio/imu/inv_icm42607/Makefile
@@ -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
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607.h b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
index 52f047d96eb4..df30503807c8 100644
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607.h
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
@@ -132,6 +132,7 @@ struct inv_icm42607_suspended {
* @orientation: sensor chip orientation relative to main hardware.
* @conf: chip sensors configurations.
* @suspended: suspended sensors configuration.
+ * @indio_gyro: gyroscope IIO device.
* @indio_accel: accelerometer IIO device.
* @buffer: data transfer buffer aligned for DMA.
*/
@@ -144,6 +145,7 @@ struct inv_icm42607_state {
struct iio_mount_matrix orientation;
struct inv_icm42607_conf conf;
struct inv_icm42607_suspended suspended;
+ struct iio_dev *indio_gyro;
struct iio_dev *indio_accel;
__be16 buffer[3] __aligned(IIO_DMA_MINALIGN);
};
@@ -395,6 +397,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);
@@ -402,6 +408,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
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
index 96e170b10aa4..99ae67f826bc 100644
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
@@ -173,6 +173,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);
+}
+
int inv_icm42607_set_temp_conf(struct inv_icm42607_state *st, bool enable,
unsigned int *sleep_ms)
{
@@ -388,6 +431,11 @@ int inv_icm42607_core_probe(struct regmap *regmap,
if (IS_ERR(st->indio_accel))
return PTR_ERR(st->indio_accel);
+ /* Initialize IIO device for Gyro */
+ st->indio_gyro = inv_icm42607_gyro_init(st);
+ if (IS_ERR(st->indio_gyro))
+ return PTR_ERR(st->indio_gyro);
+
return 0;
}
EXPORT_SYMBOL_NS_GPL(inv_icm42607_core_probe, "IIO_ICM42607");
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c
new file mode 100644
index 000000000000..8cabebe2e96b
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c
@@ -0,0 +1,369 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 InvenSense, Inc.
+ */
+
+#include <linux/iio/iio.h>
+#include <linux/mutex.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include "inv_icm42607.h"
+#include "inv_icm42607_temp.h"
+
+#define INV_ICM42607_GYRO_CHAN(_modifier, _index, _ext_info) \
+{ \
+ .type = IIO_ANGL_VEL, \
+ .modified = 1, \
+ .channel2 = _modifier, \
+ .info_mask_separate = \
+ BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = _index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_BE, \
+ }, \
+ .ext_info = _ext_info, \
+}
+
+enum inv_icm42607_gyro_scan {
+ INV_ICM42607_GYRO_SCAN_X,
+ INV_ICM42607_GYRO_SCAN_Y,
+ INV_ICM42607_GYRO_SCAN_Z,
+ INV_ICM42607_GYRO_SCAN_TEMP,
+};
+
+static const struct iio_chan_spec_ext_info inv_icm42607_gyro_ext_infos[] = {
+ IIO_MOUNT_MATRIX(IIO_SHARED_BY_ALL, inv_icm42607_get_mount_matrix),
+ { }
+};
+
+static const struct iio_chan_spec inv_icm42607_gyro_channels[] = {
+ INV_ICM42607_GYRO_CHAN(IIO_MOD_X, INV_ICM42607_GYRO_SCAN_X,
+ inv_icm42607_gyro_ext_infos),
+ INV_ICM42607_GYRO_CHAN(IIO_MOD_Y, INV_ICM42607_GYRO_SCAN_Y,
+ inv_icm42607_gyro_ext_infos),
+ INV_ICM42607_GYRO_CHAN(IIO_MOD_Z, INV_ICM42607_GYRO_SCAN_Z,
+ inv_icm42607_gyro_ext_infos),
+ INV_ICM42607_TEMP_CHAN(INV_ICM42607_GYRO_SCAN_TEMP),
+};
+
+static int inv_icm42607_gyro_read_sensor(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ s16 *val)
+{
+ 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);
+ struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT;
+ unsigned int reg;
+ __be16 *data;
+ 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);
+ ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&st->lock);
+
+ /* enable gyro sensor */
+ conf.mode = gyro_st->power_mode;
+ ret = inv_icm42607_set_gyro_conf(st, &conf, NULL);
+ if (ret)
+ return ret;
+
+ /* read gyro register data */
+ data = &st->buffer[0];
+ ret = regmap_bulk_read(st->map, reg, data, sizeof(*data));
+ if (ret)
+ return ret;
+
+ *val = be16_to_cpup(data);
+ if (*val == INV_ICM42607_DATA_INVALID)
+ return -EINVAL;
+
+ return 0;
+}
+
+static const int inv_icm42607_gyro_scale_nano[][2] = {
+ [INV_ICM42607_GYRO_FS_2000DPS] = { 0, 1065264 },
+ [INV_ICM42607_GYRO_FS_1000DPS] = { 0, 532632 },
+ [INV_ICM42607_GYRO_FS_500DPS] = { 0, 266316 },
+ [INV_ICM42607_GYRO_FS_250DPS] = { 0, 133158 },
+};
+
+static int inv_icm42607_gyro_read_scale(struct iio_dev *indio_dev,
+ int *val, int *val2)
+{
+ struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev);
+ unsigned int idx;
+
+ guard(mutex)(&st->lock);
+
+ idx = st->conf.gyro.fs;
+
+ *val = inv_icm42607_gyro_scale_nano[idx][0];
+ *val2 = inv_icm42607_gyro_scale_nano[idx][1];
+ return IIO_VAL_INT_PLUS_NANO;
+}
+
+static int inv_icm42607_gyro_write_scale(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;
+ size_t scales_len = ARRAY_SIZE(inv_icm42607_gyro_scale_nano);
+ int ret;
+
+ for (idx = 0; idx < scales_len; idx++) {
+ if (val == inv_icm42607_gyro_scale_nano[idx][0] &&
+ val2 == inv_icm42607_gyro_scale_nano[idx][1])
+ break;
+ }
+ if (idx >= scales_len)
+ return -EINVAL;
+
+ conf.fs = 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_gyro_conf(st, &conf, NULL);
+}
+
+static const int inv_icm42607_gyro_odr[][2] = {
+ [INV_ICM42607_ODR_12_5HZ] = { 12, 500000 },
+ [INV_ICM42607_ODR_25HZ] = { 25, 0 },
+ [INV_ICM42607_ODR_50HZ] = { 50, 0 },
+ [INV_ICM42607_ODR_100HZ] = { 100, 0 },
+ [INV_ICM42607_ODR_200HZ] = { 200, 0 },
+ [INV_ICM42607_ODR_400HZ] = { 400, 0 },
+ [INV_ICM42607_ODR_800HZ] = { 800, 0 },
+ [INV_ICM42607_ODR_1600HZ] = { 1600, 0 },
+};
+
+static int inv_icm42607_gyro_read_odr(struct inv_icm42607_state *st,
+ int *val, int *val2)
+{
+ 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) {
+ 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;
+}
+
+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) {
+ 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)
+ return ret;
+
+ guard(mutex)(&st->lock);
+
+ ret = inv_icm42607_set_gyro_conf(st, &conf, NULL);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int inv_icm42607_gyro_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev);
+ s16 data;
+ int ret;
+
+ switch (chan->type) {
+ case IIO_ANGL_VEL:
+ break;
+ case IIO_TEMP:
+ return inv_icm42607_temp_read_raw(indio_dev, chan, val, val2, mask);
+ default:
+ return -EINVAL;
+ }
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (!iio_device_claim_direct(indio_dev))
+ return -EBUSY;
+ ret = inv_icm42607_gyro_read_sensor(indio_dev, chan, &data);
+ iio_device_release_direct(indio_dev);
+ if (ret)
+ return ret;
+ *val = data;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ return inv_icm42607_gyro_read_scale(indio_dev, val, val2);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return inv_icm42607_gyro_read_odr(st, val, val2);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int inv_icm42607_gyro_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals,
+ int *type, int *length, long mask)
+{
+ if (chan->type != IIO_ANGL_VEL)
+ return -EINVAL;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ *vals = (const int *)inv_icm42607_gyro_scale_nano;
+ *type = IIO_VAL_INT_PLUS_NANO;
+ *length = ARRAY_SIZE(inv_icm42607_gyro_scale_nano) * 2;
+ return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *vals = (const int *)inv_icm42607_gyro_odr[5];
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ *length = (ARRAY_SIZE(inv_icm42607_gyro_odr) - 5) * 2;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int inv_icm42607_gyro_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ int ret;
+
+ if (chan->type != IIO_ANGL_VEL)
+ return -EINVAL;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ if (!iio_device_claim_direct(indio_dev))
+ return -EBUSY;
+ ret = inv_icm42607_gyro_write_scale(indio_dev, val, val2);
+ iio_device_release_direct(indio_dev);
+ return ret;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return inv_icm42607_gyro_write_odr(indio_dev, val, val2);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int inv_icm42607_gyro_write_raw_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ long mask)
+{
+ if (chan->type != IIO_ANGL_VEL)
+ return -EINVAL;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ return IIO_VAL_INT_PLUS_NANO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info inv_icm42607_gyro_info = {
+ .read_raw = inv_icm42607_gyro_read_raw,
+ .read_avail = inv_icm42607_gyro_read_avail,
+ .write_raw = inv_icm42607_gyro_write_raw,
+ .write_raw_get_fmt = inv_icm42607_gyro_write_raw_get_fmt,
+};
+
+struct iio_dev *inv_icm42607_gyro_init(struct inv_icm42607_state *st)
+{
+ struct device *dev = regmap_get_device(st->map);
+ const char *name;
+ struct inv_icm42607_sensor_state *gyro_st;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ name = devm_kasprintf(dev, GFP_KERNEL, "%s-gyro", st->hw->name);
+ if (!name)
+ return ERR_PTR(-ENOMEM);
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*gyro_st));
+ if (!indio_dev)
+ return ERR_PTR(-ENOMEM);
+ gyro_st = iio_priv(indio_dev);
+
+ gyro_st->power_mode = INV_ICM42607_SENSOR_MODE_LOW_NOISE;
+
+ iio_device_set_drvdata(indio_dev, st);
+ indio_dev->name = name;
+ indio_dev->info = &inv_icm42607_gyro_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = inv_icm42607_gyro_channels;
+ indio_dev->num_channels = ARRAY_SIZE(inv_icm42607_gyro_channels);
+
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return indio_dev;
+}
--
2.43.0
^ permalink raw reply related
* [PATCH V11 9/9] arm64: dts: rockchip: Add icm42607p IMU for RG-DS
From: Chris Morgan @ 2026-06-10 17:54 UTC (permalink / raw)
To: linux-iio
Cc: andy, nuno.sa, dlechner, jic23, jean-baptiste.maneyrol,
linux-rockchip, devicetree, heiko, conor+dt, krzk+dt, robh,
andriy.shevchenko, Chris Morgan
In-Reply-To: <20260610175455.19006-1-macroalpha82@gmail.com>
From: Chris Morgan <macromorgan@hotmail.com>
Add the Invensense ICM42607P IMU for the Anbernic RG-DS. Mount-matrix
was tested with iio-sensor-proxy and reports correct orientation.
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
---
arch/arm64/boot/dts/rockchip/rk3568-anbernic-rg-ds.dts | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-anbernic-rg-ds.dts b/arch/arm64/boot/dts/rockchip/rk3568-anbernic-rg-ds.dts
index 8d906ab02c5f..b770bfd5268d 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-anbernic-rg-ds.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-anbernic-rg-ds.dts
@@ -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 {
--
2.43.0
^ permalink raw reply related
* Re: [PATCH 04/12] clk: qcom: gcc-mdm9607: Fix BIMC PLL definition
From: Stephan Gerhold @ 2026-06-10 17:58 UTC (permalink / raw)
To: Taniya Das
Cc: Bjorn Andersson, Michael Turquette, Stephen Boyd, Georgi Djakov,
Shawn Guo, Bryan O'Donoghue, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, linux-clk,
linux-kernel, devicetree
In-Reply-To: <022fb465-df10-4d95-a05c-1ff8e59558c1@oss.qualcomm.com>
On Wed, Jun 10, 2026 at 10:43:12PM +0530, Taniya Das wrote:
> On 6/9/2026 7:44 PM, Stephan Gerhold wrote:
> > The gcc-mdm9607 driver was originally based on gcc-msm8916, but a closer
> > match nowadays is gcc-msm8909. Looking at the differences between
> > gcc-mdm9607 and gcc-msm8909, there is quite some confusion around the
> > definitions for the BIMC PLL.
> >
> > It turns out the BIMC PLL on MDM9607 is actually an Alpha PLL just like on
> > MSM8909. We can vote for it using BIT(2), which explains why BIT(3) was
> > used for GPLL2.
>
> BIMC PLL is never controlled from High Level OS (APSS). These are
> controlled by other subsystems and voting should be via the ICC for BW
> requirements.
>
The driver doesn't really control the BIMC PLL here, the PLL is defined
with fixed/shared/read-only ops so it mostly just exists to model the
clock tree properly and have the clock rate readable for the PLL itself
and any downstream consumers.
There are multiple drivers that do it like this (e.g. gcc-msm8916,
gcc-msm8939), is there a reason why we should drop this?
Thanks,
Stephan
^ permalink raw reply
* Re: [PATCH 12/12] clk: qcom: gcc-mdm9607: Drop redundant register update during probe
From: Stephan Gerhold @ 2026-06-10 18:02 UTC (permalink / raw)
To: Taniya Das
Cc: Bjorn Andersson, Michael Turquette, Stephen Boyd, Georgi Djakov,
Shawn Guo, Bryan O'Donoghue, Konrad Dybcio, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-arm-msm, linux-clk,
linux-kernel, devicetree
In-Reply-To: <ad9a18e0-c2a5-4a6e-a9f3-677e923b495f@oss.qualcomm.com>
On Wed, Jun 10, 2026 at 11:01:34PM +0530, Taniya Das wrote:
> On 6/9/2026 7:44 PM, Stephan Gerhold wrote:
> > From: Stephan Gerhold <stephan@gerhold.net>
> >
> > GPLL0 is pretty much guaranteed to be already on (and voted) during boot,
> > since it's used by the CPU and also various other components such as UART.
> > We also vote for this bit in the actual GPLL0 definition, which will be set
> > as soon as any driver in the kernel requires using the GPLL0 clock.
> >
> > All in all, this makes separately voting for GPLL0 during probe redundant,
> > especially because the "acpuclock" in the comment is a downstream construct
> > that does not exist in upstream.
> >
> > Signed-off-by: Stephan Gerhold <stephan@gerhold.net>
> > ---
> > drivers/clk/qcom/gcc-mdm9607.c | 11 +----------
> > 1 file changed, 1 insertion(+), 10 deletions(-)
> >
> > diff --git a/drivers/clk/qcom/gcc-mdm9607.c b/drivers/clk/qcom/gcc-mdm9607.c
> > index 0bd4c12483cd..ce78ebc8ffec 100644
> > --- a/drivers/clk/qcom/gcc-mdm9607.c
> > +++ b/drivers/clk/qcom/gcc-mdm9607.c
> > @@ -1565,16 +1565,7 @@ MODULE_DEVICE_TABLE(of, gcc_mdm9607_match_table);
> >
> > static int gcc_mdm9607_probe(struct platform_device *pdev)
> > {
> > - struct regmap *regmap;
> > -
> > - regmap = qcom_cc_map(pdev, &gcc_mdm9607_desc);
> > - if (IS_ERR(regmap))
> > - return PTR_ERR(regmap);
> > -
> > - /* Vote for GPLL0 to turn on. Needed by acpuclock. */
> > - regmap_update_bits(regmap, 0x45000, BIT(0), BIT(0));
>
> This was to ensure that the (APCS_GPLL_ENA_VOTE) vote indeed has a vote
> from CPU. AFAIR, the boot up was not using this particular PLL vote
> register and no piggy backing for the GPLL vote.
>
Hm, I'm not sure when this would be the case. The original LK bootloader
source code also sets this bit when enabling GPLL-related clocks, so I'm
not sure when/why this bit would be missing.
Either way, I don't think it will make a difference in practice, since
it's pretty much guaranteed that one of the later clock enable sequences
(UART, USB, ...) is going to vote for GPLL0 as well.
Thanks,
Stephan
^ permalink raw reply
* Re: [PATCH 1/3] dt-bindings: media: qcom,qcm2290-venus: document shikra Iris compatible
From: Vikash Garodia @ 2026-06-10 18:08 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Bryan O'Donoghue, Dikshita Agarwal, Mauro Carvalho Chehab,
Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jorge Ramirez-Ortiz, Bjorn Andersson, Konrad Dybcio,
linux-arm-msm, linux-media, devicetree, linux-kernel
In-Reply-To: <20260610-flexible-badger-of-dignity-bbaea0@quoll>
On 6/10/2026 2:47 PM, Krzysztof Kozlowski wrote:
> On Tue, Jun 09, 2026 at 09:45:40PM +0530, Vikash Garodia wrote:
>> Document the iris video accelerator used on shikra platforms by adding
>> the qcom,shikra-iris compatible.
>>
>> Although QCM2290 and shikra share the same video hardware and overall
>> integration, their SMMU programming differs. QCM2290 exposes separate
>> stream IDs for the video hardware and the Xtensa path, requiring two
>> explicit IOMMU entries, whereas shikra uses a masked SMR to collapse
>> equivalent stream IDs into a single mapping. Due to QCM2290’s SID layout
>> and Xtensa isolation requirements, such SMR masking is not applicable on
>> QCM2290 platforms.
>> Since shikra uses the same video hardware as QCM2290 and shares the same
>> programming model and capabilities, it is added as a fallback compatible
>> to qcom,qcm2290-venus, with conditional handling to allow either one or
>> two IOMMU entries.
>>
>> Signed-off-by: Vikash Garodia <vikash.garodia@oss.qualcomm.com>
>> ---
>> .../bindings/media/qcom,qcm2290-venus.yaml | 20 ++++++++++++++++----
>> 1 file changed, 16 insertions(+), 4 deletions(-)
>>
>> diff --git a/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml b/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml
>> index 5977e7d0a71b4fb5681f1c2094439c251366f01f..895533b9756690d075fd7729e3f805c8e72ff0df 100644
>> --- a/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml
>> +++ b/Documentation/devicetree/bindings/media/qcom,qcm2290-venus.yaml
>> @@ -15,12 +15,27 @@ description:
>>
>> allOf:
>> - $ref: qcom,venus-common.yaml#
>> + - if:
>> + properties:
>> + compatible:
>> + contains:
>> + const: qcom,shikra-iris
>> + then:
>> + properties:
>> + iommus:
>> + maxItems: 1
>> + else:
>> + properties:
>> + iommus:
>> + maxItems: 2
>
> allOf goes to the end, after required: block. See example-schema.
>
Ack
>
>>
>> properties:
>> compatible:
>> oneOf:
>> - items:
>> - - const: qcom,sm6115-venus
>> + - enum:
>> + - qcom,sm6115-venus
>> + - qcom,shikra-iris
>
> Messed order.
>
Ack
>> - const: qcom,qcm2290-venus
>> - const: qcom,qcm2290-venus
>
> Best regards,
> Krzysztof
>
^ permalink raw reply
* Re: [PATCH V11 7/9] iio: imu: inv_icm42607: Add Accelerometer for icm42607
From: sashiko-bot @ 2026-06-10 18:10 UTC (permalink / raw)
To: Chris Morgan; +Cc: devicetree, robh, conor+dt
In-Reply-To: <20260610175455.19006-8-macroalpha82@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Missing `iio_device_claim_direct()` protection when changing the sampling frequency (ODR) in `inv_icm42607_accel_write_raw()`.
--
commit 09acc28167411b3db95fd7b8d7918637d445b62b
Author: Chris Morgan <macromorgan@hotmail.com>
iio: imu: inv_icm42607: Add Accelerometer for icm42607
This commit adds support for the accelerometer sensor to the icm42607
driver.
> diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c
> new file mode 100644
> --- /dev/null
> +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c
[ ... ]
> +static int inv_icm42607_accel_write_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + int val, int val2, long mask)
> +{
> + int ret;
> +
> + if (chan->type != IIO_ACCEL)
> + return -EINVAL;
> +
> + switch (mask) {
> + case IIO_CHAN_INFO_SCALE:
> + if (!iio_device_claim_direct(indio_dev))
> + return -EBUSY;
> + ret = inv_icm42607_accel_write_scale(indio_dev, val, val2);
> + iio_device_release_direct(indio_dev);
> + return ret;
> + case IIO_CHAN_INFO_SAMP_FREQ:
> + return inv_icm42607_accel_write_odr(indio_dev, val, val2);
[Severity: Medium]
Should this IIO_CHAN_INFO_SAMP_FREQ case be protected by
iio_device_claim_direct() and iio_device_release_direct() similar to the
IIO_CHAN_INFO_SCALE case above it?
While the driver currently only supports INDIO_DIRECT_MODE, omitting the lock
here leaves the state management inconsistent. If buffered mode is added in
the future, modifying the sampling frequency while the buffer is actively
streaming could lead to stream breakage or corrupted timestamps.
> + default:
> + return -EINVAL;
> + }
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610175455.19006-1-macroalpha82@gmail.com?part=7
^ permalink raw reply
* Re: [PATCH V11 3/9] iio: imu: inv_icm42607: Add inv_icm42607 Core Driver
From: sashiko-bot @ 2026-06-10 18:11 UTC (permalink / raw)
To: Chris Morgan; +Cc: robh, devicetree, conor+dt
In-Reply-To: <20260610175455.19006-4-macroalpha82@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Incorrect use of `regcache_sync()` in probe writes to the read-only WHOAMI register and executes before bus setup.
--
commit 40cc0df3cdc00863249296cfd5a6b946f44cff13
Author: Chris Morgan <macromorgan@hotmail.com>
iio: imu: inv_icm42607: Add inv_icm42607 Core Driver
This commit adds the core component of a new inv_icm42607 driver. It includes
the initial setup functions and full register definitions for the device.
> diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
> --- /dev/null
> +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
[ ... ]
> +static int inv_icm42607_setup(struct inv_icm42607_state *st,
> + inv_icm42607_bus_setup inv_icm42607_bus_setup)
> +{
> + const struct device *dev = regmap_get_device(st->map);
> + unsigned int val;
> + int ret;
> +
> + ret = regmap_read(st->map, INV_ICM42607_REG_WHOAMI, &val);
> + if (ret)
> + return ret;
[ ... ]
> + /* Sync the regcache again after a reset. */
> + regcache_mark_dirty(st->map);
> + ret = regcache_sync(st->map);
> + if (ret)
> + return ret;
[Severity: Medium]
Will regcache_sync() attempt to write the cached value back to the read-only
WHOAMI register here?
Since WHOAMI is read earlier in this function and is not marked as volatile in
inv_icm42607_regmap_config, its value is cached. Because the regmap_config
lacks a writeable_reg or wr_table definition, regmap assumes all non-volatile
registers are writable.
Could this unintended write to a read-only register cause a bus NACK or
unexpected hardware behavior, especially since it occurs before
inv_icm42607_bus_setup() configures bus-specific settings?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610175455.19006-1-macroalpha82@gmail.com?part=3
^ permalink raw reply
* Re: [PATCH V11 8/9] iio: imu: inv_icm42607: Add Gyroscope to icm42607
From: sashiko-bot @ 2026-06-10 18:14 UTC (permalink / raw)
To: Chris Morgan; +Cc: devicetree, conor+dt, robh
In-Reply-To: <20260610175455.19006-9-macroalpha82@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] Missing `_available` info masks in `INV_ICM42607_GYRO_CHAN` makes `read_avail` dead code and hides capabilities from userspace.
- [Medium] Missing `iio_device_claim_direct()` protection when writing sampling frequency.
--
commit 85b10db1767bd36f30119bab0e0a4f4f63966fc3
Author: Chris Morgan <macromorgan@hotmail.com>
iio: imu: inv_icm42607: Add Gyroscope to icm42607
Add gyroscope functions to the icm42607 driver.
> diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c
> new file mode 100644
> index 0000000000000..8cabebe2e96b1
> --- /dev/null
> +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c
> @@ -0,0 +1,369 @@
[ ... ]
> +#define INV_ICM42607_GYRO_CHAN(_modifier, _index, _ext_info) \
> +{ \
> + .type = IIO_ANGL_VEL, \
> + .modified = 1, \
> + .channel2 = _modifier, \
> + .info_mask_separate = \
> + BIT(IIO_CHAN_INFO_RAW), \
> + .info_mask_shared_by_type = \
> + BIT(IIO_CHAN_INFO_SCALE), \
> + .info_mask_shared_by_all = \
> + BIT(IIO_CHAN_INFO_SAMP_FREQ), \
[Severity: Medium]
Will userspace be able to discover the available scales and frequencies?
Since .info_mask_shared_by_type_available and
.info_mask_shared_by_all_available are not included in this macro, it
appears the IIO core will never query inv_icm42607_gyro_read_avail(),
leaving that function as dead code.
> + .scan_index = _index, \
> + .scan_type = { \
[ ... ]
> +static int inv_icm42607_gyro_write_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + int val, int val2, long mask)
> +{
> + int ret;
> +
> + if (chan->type != IIO_ANGL_VEL)
> + return -EINVAL;
> +
> + switch (mask) {
> + case IIO_CHAN_INFO_SCALE:
> + if (!iio_device_claim_direct(indio_dev))
> + return -EBUSY;
> + ret = inv_icm42607_gyro_write_scale(indio_dev, val, val2);
> + iio_device_release_direct(indio_dev);
> + return ret;
> + case IIO_CHAN_INFO_SAMP_FREQ:
> + return inv_icm42607_gyro_write_odr(indio_dev, val, val2);
[Severity: Medium]
Is it safe to write the sampling frequency without claiming direct mode here?
It looks like IIO_CHAN_INFO_SAMP_FREQ bypasses iio_device_claim_direct(),
meaning it could potentially be modified concurrently with active IIO data
buffering.
> + default:
> + return -EINVAL;
> + }
> +}
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610175455.19006-1-macroalpha82@gmail.com?part=8
^ permalink raw reply
* Re: [PATCH V11 6/9] iio: imu: inv_icm42607: Add Temp Support in icm42607
From: sashiko-bot @ 2026-06-10 18:15 UTC (permalink / raw)
To: Chris Morgan; +Cc: conor+dt, devicetree, robh
In-Reply-To: <20260610175455.19006-7-macroalpha82@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The temperature sensor is permanently enabled after the first read, causing continuous power drain, preventing low-power accelerometer clocks, and forcing unnecessary startup delays on subsequent sensor reads.
--
commit 910deb05735ec6ed5869092361616349ba5cc0f7
Author: Chris Morgan <macromorgan@hotmail.com>
iio: imu: inv_icm42607: Add Temp Support in icm42607
Add functions for reading temperature sensor data.
> diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c
> new file mode 100644
> index 0000000000000..55260082a19ed
> --- /dev/null
> +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c
[ ... ]
> +static int inv_icm42607_temp_read(struct inv_icm42607_state *st, s16 *temp)
> +{
> + struct device *dev = regmap_get_device(st->map);
> + __be16 *raw;
> + int ret;
> +
> + PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);
> + ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
> + if (ret)
> + return ret;
> +
> + guard(mutex)(&st->lock);
> +
> + ret = inv_icm42607_set_temp_conf(st, true, NULL);
> + if (ret)
> + return ret;
> +
> + raw = &st->buffer[0];
> + ret = regmap_bulk_read(st->map, INV_ICM42607_REG_TEMP_DATA1,
> + raw, sizeof(*raw));
> + if (ret)
> + return ret;
> +
> + *temp = be16_to_cpup(raw);
> + if (*temp == INV_ICM42607_DATA_INVALID)
> + return -EINVAL;
> +
> + return 0;
> +}
[Severity: Medium]
Does this leave the temperature sensor permanently enabled?
Looking at inv_icm42607_temp_read(), the sensor is enabled with
inv_icm42607_set_temp_conf(st, true, NULL) but is never disabled before the
function returns on either the success or error paths.
Because st->conf.temp_en remains true, it seems this would prevent the
setting of the INV_ICM42607_PWR_MGMT0_ACCEL_LP_CLK_SEL bit in
inv_icm42607_set_pwr_mgmt0(), permanently disabling the accelerometer
low-power clock.
Would this also force a 77ms startup delay on every subsequent pm_runtime
resume?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610175455.19006-1-macroalpha82@gmail.com?part=6
^ permalink raw reply
* Re: [PATCH V11 4/9] iio: imu: inv_icm42607: Add I2C and SPI For icm42607
From: sashiko-bot @ 2026-06-10 18:25 UTC (permalink / raw)
To: Chris Morgan; +Cc: conor+dt, robh, devicetree
In-Reply-To: <20260610175455.19006-5-macroalpha82@gmail.com>
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Missing `<linux/bitfield.h>` include for the `FIELD_PREP` macro.
--
commit 20b53f9fe7967725a7d83e31eaa40543016b6759
Author: Chris Morgan <macromorgan@hotmail.com>
iio: imu: inv_icm42607: Add I2C and SPI For icm42607
Add I2C and SPI driver support for InvenSense ICM-42607 devices.
Add necessary Kconfig and Makefile to allow building of (incomplete)
driver.
> diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c
> new file mode 100644
> index 0000000000000..2946d54658535
> --- /dev/null
> +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c
> @@ -0,0 +1,92 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2026 InvenSense, Inc.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/i2c.h>
> +#include <linux/module.h>
> +#include <linux/regmap.h>
> +
> +#include "inv_icm42607.h"
> +
> +static int inv_icm42607_i2c_bus_setup(struct inv_icm42607_state *st)
> +{
> + unsigned int val;
> + int ret;
[ ... ]
> + ret = regmap_clear_bits(st->map, INV_ICM42607_REG_INTF_CONFIG1,
> + INV_ICM42607_INTF_CONFIG1_I3C_DDR_EN |
> + INV_ICM42607_INTF_CONFIG1_I3C_SDR_EN);
> + if (ret)
> + return ret;
> +
> + val = FIELD_PREP(INV_ICM42607_DRIVE_CONFIG2_I2C_MASK,
> + INV_ICM42607_SLEW_RATE_12_36NS);
[Severity: Low]
Does this code require including <linux/bitfield.h>?
This driver, along with inv_icm42607_spi.c, inv_icm42607_core.c, and macro
definitions in inv_icm42607.h heavily use FIELD_PREP(), but the bitfield
header isn't included here or in the shared header. Will this result in
implicit declaration or undefined macro errors during compilation?
[ ... ]
> diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c
> new file mode 100644
> index 0000000000000..3485777ac5b6e
> --- /dev/null
> +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c
[ ... ]
> + ret = regmap_clear_bits(st->map, INV_ICM42607_REG_INTF_CONFIG1,
> + INV_ICM42607_INTF_CONFIG1_I3C_DDR_EN |
> + INV_ICM42607_INTF_CONFIG1_I3C_SDR_EN);
> + if (ret)
> + return ret;
> +
> + val = FIELD_PREP(INV_ICM42607_DRIVE_CONFIG3_SPI_MASK,
> + INV_ICM42607_SLEW_RATE_2NS);
[Severity: Low]
Similar to the I2C driver, should <linux/bitfield.h> be included for this
FIELD_PREP() usage?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610175455.19006-1-macroalpha82@gmail.com?part=4
^ permalink raw reply
* Re: [PATCH v2 2/2] iio: pressure: ms5637: Add variant specific temperature compensation
From: Andy Shevchenko @ 2026-06-10 18:37 UTC (permalink / raw)
To: Louis Adamian
Cc: Jonathan Cameron, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
David Lechner, Nuno Sá, Andy Shevchenko, linux-iio,
devicetree, linux-kernel
In-Reply-To: <20260610020458.104818-3-adamianlouis@gmail.com>
On Tue, Jun 09, 2026 at 10:04:58PM -0400, Louis Adamian wrote:
> Add correct temperature compensation for ms5637-30BA, MS5803-01BA,02BA,
> 05BA, 14BA, 30BA, MS5837-30BA. The temperature compensation formula is
> shared across these sensors but with different constants. Add
> ms_tp_comp_consts to capture these per-device differences. Add pressure
> variant specific pressure scale variable.
Is there SPI driver? If so, why only i2c is affected?
...
> +/* apply second order temperature compensation */
> +static void ms_tp_compensate(const struct ms_tp_comp_consts *c,
> + s32 temp, s32 dt, s64 *t2, s64 *off2, s64 *sens2)
> +{
> + if (temp < 2000) {
> + s64 tmp = (s64)temp - 2000;
Why casting?
> +
> + *t2 = (c->low_t2_multiplier * ((s64)dt * (s64)dt)) >>
> + c->low_t2_shift;
> + *off2 = (c->low_off2_multiplier * tmp * tmp) >>
> + c->low_off2_shift;
> + *sens2 = (c->low_sens2_multiplier * tmp * tmp) >>
> + c->low_sens2_shift;
> + if (temp < -1500) {
> + s64 tmp_vlow = (s64)temp + 1500;
Missing blank line. But Q here is why tmp can't be used here?
> + *off2 += c->vlow_off2_multiplier * tmp_vlow * tmp_vlow;
> + *sens2 +=
> + c->vlow_sens2_multiplier * tmp_vlow * tmp_vlow;
Make it one line.
> + }
> + } else {
> + *sens2 = 0;
> + if (c->has_vhigh_temp && temp > 4500)
> + *sens2 -= (((s64)temp - 4500) * ((s64)temp - 4500)) >> 3;
Here...
> + *t2 = (c->high_t2_multiplier * ((s64)dt * (s64)dt)) >>
> + c->high_t2_shift;
> + *off2 = (c->high_off2_multiplier *
> + ((s64)temp - 2000) * ((s64)temp - 2000)) >>
...and here you may also use tmp, just make it global to the function.
> + c->high_off2_shift;
> + }
> +}
Overall this all needs a good comment or even comments to explain all
calculations with the references to the respective sections / tables / pages
in the datasheet.
...
> int ms_sensors_read_temp_and_pressure(struct ms_tp_dev *dev_data,
> s32 dt, temp;
> s64 off, sens, t2, off2, sens2;
> u16 *prom = dev_data->prom, delay;
> + const struct ms_tp_comp_consts *c = dev_data->comp_consts;
Try to keep more or less reversed xmas tree order.
...
> * struct ms_tp_dev - Temperature/Pressure sensor device structure
> * @client: i2c client
> * @prom: array of PROM coefficients used for conversion. Added element
> * for CRC computation
> * @res_index: index to selected sensor resolution
> + * @comp_consts: temperature compensation constants
> */
> struct ms_tp_dev {
> struct i2c_client *client;
> const struct ms_tp_hw_data *hw;
> u16 prom[MS_SENSORS_TP_PROM_WORDS_NB];
> u8 res_index;
> + const struct ms_tp_comp_consts *comp_consts;
Please, check with `pahole` if this is the best layout.
> };
> struct ms_tp_data {
> const char *name;
> const struct ms_tp_hw_data *hw;
> + const struct ms_tp_comp_consts *comp_consts;
> };
Can this be simply embedded into ms_tp_dev (and copied there if required)?
...
> case IIO_PRESSURE: /* in kPa */
> - *val = pressure / 1000;
> - *val2 = (pressure % 1000) * 1000;
> + *val = pressure / dev_data->comp_consts->press_scale;
> + *val2 = (pressure %
> + (s64)dev_data->comp_consts->press_scale) *
> + (1000000 / dev_data->comp_consts->press_scale);
MICRO (might need units.h)?
> return IIO_VAL_INT_PLUS_MICRO;
...
Have you considered to prepare the infrastructure in one patch and add
the actual compensation data tables in another?
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v5 0/4] dt-bindings: automated coding style check for DTS examples
From: Rob Herring @ 2026-06-10 18:38 UTC (permalink / raw)
To: Daniel Golle
Cc: Krzysztof Kozlowski, Conor Dooley, Nathan Chancellor,
Nicolas Schier, Saravana Kannan, Ping-Ke Shih, Andy Shevchenko,
David Sterba, Bryan O'Donoghue, Hariharan Basuthkar,
Jeff Hugo, Filipe Manana, Bitterblue Smith, Wei Yang,
Takashi Iwai, Aurabindo Pillai, Chih-Kang Chang, David Lechner,
Miguel Ojeda, Gary Guo, Tamir Duberstein, Thomas Weißschuh,
Pagadala Yesu Anjaneyulu, Bartosz Golaszewski,
Jorge Ramirez-Ortiz, Masahiro Yamada, Guenter Roeck,
Aleksander Jan Bajkowski, Boris Burkov, Blake Jones,
Jonathan Corbet, Mauro Carvalho Chehab, devicetree, linux-kernel,
linux-kbuild
In-Reply-To: <cover.1779908995.git.daniel@makrotopia.org>
On Wed, May 27, 2026 at 08:31:59PM +0100, Daniel Golle wrote:
> Documentation/devicetree/bindings/dts-coding-style.rst documents
> the style expected of DT examples and source files, but nothing
> existing actually enforces it. dtc tolerates arbitrary whitespace,
> yamllint only sees the YAML envelope and not the DTS content
> inside literal block scalars, and so reviewers spend cycles
> flagging issues that tooling could catch.
>
> Add scripts/dtc/dt-check-style, a Python tool that checks DTS
> coding style on YAML binding examples and on .dts/.dtsi/.dtso
> source files. Rules live in a small declarative registry; each
> rule is tagged 'relaxed' (default) or 'strict' (opt-in for new
> submissions). Promoting a rule from strict to relaxed is a
> one-line edit once the tree catches up.
>
> Relaxed mode covers trailing whitespace, tab characters in YAML
> examples, mixed tab+space indents, unclosed /* block comments,
> and the per-input-type indent character (1 tab for
> .dts/.dtsi/.dtso). It is zero-violation on the current tree and
> runs as part of dt_binding_check_one, so no new warnings appear
> in `make dt_binding_check`.
>
> Strict mode adds indent unit and depth consistency; blank-line
> policy (no consecutive blanks or blanks at body edges; required
> blank line before each child node and before "status"); property
> ordering by canonical bucket (compatible, reg/reg-names, ranges,
> standard, vendor, status) with declarative within-bucket pairing
> rules (<x>-names follows <x>, pinctrl-names follows the last
> pinctrl-N) and natural-sort fallback; sibling node ordering by
> unit address or natural-sort name; line length (80 columns);
> continuation alignment of multi-line property values under the
> first '<' or '"' after the '='; lowercase hex literals and unit
> addresses; no whitespace padding inside <...>; closing-brace
> placement; and unused-label detection (skipped for .dtsi/.dtso
> since labels there are exported to includers/applies-to).
> Together these constrain a DT structure to a single canonical
> rendering modulo the author's choice of when to wrap properties
> for readability. Comments are intentionally out of scope. Strict
> mode is opt-in, intended for use by checkpatch.pl in a follow-up
> series.
>
> The tool reads file paths from @argfile and parallelises across
> CPUs via -j N. With no -j given it picks up $PARALLELISM (set by
> scripts/jobserver-exec from the GNU make jobserver) and falls
> back to os.cpu_count() otherwise. Running as one Python
> invocation amortises the ruamel.yaml import across the whole
> tree -- ~2s on a 32-CPU host vs ~28s sequential. ruamel.yaml is
> the only non-stdlib dependency, already required by dtschema.
>
> A selftest under scripts/dtc/dt-style-selftest/ pairs good/ and
> bad/ fixtures with expected output so rule behaviour can be
> exercised independently of the full tree via the
> dt_style_selftest top-level make target.
> ---
> v1: https://lore.kernel.org/all/cover.1776700167.git.daniel@makrotopia.org/
> v2: https://lore.kernel.org/all/cover.1777471439.git.daniel@makrotopia.org/
> v3: https://lore.kernel.org/all/cover.1778454442.git.daniel@makrotopia.org/
> v4: https://lore.kernel.org/all/cover.1779472837.git.daniel@makrotopia.org/
>
> Changes since v4:
> - dt-check-style: parser robustness fixes from a sashiko.dev
> AI review (multi-line CPP macros, "/* ... */ code" on one
> line, "}; };" depth tracking, malformed unit addresses,
> labels inside strings and on digit-leading node names,
> unclosed /* on PROPERTY lines)
> - dt-check-style: new relaxed-mode rule unclosed-block-comment
> - new patch: scripts/jobserver-exec propagates child exit
> status (prereq so chk_style errors stay reported)
> - selftest: add fixtures covering the parser fixes
> - selftest: move SPDX header to "// SPDX-..." on line 1 in
> the three .dts fixtures (checkpatch)
>
> Changes since v3:
> - dt-check-style: accept node and property names that begin
> with a digit (the DT spec permits names like 1wire@10)
> - dt-check-style: strip trailing // and /* */ comments before
> line classification, so a trailing comment on a node-open or
> property line no longer causes misclassification
> - dt-check-style: continuation-alignment compares display
> columns (tabs expanded to 8) instead of raw string length,
> removing many false positives on tab-indented .dts files
> - dt-check-style: value-whitespace flags only whitespace directly
> inside the brackets (after '<', before '>'), on single- and
> multi-line cell lists; it no longer flags inter-value spacing,
> which is often deliberate column alignment
> - Makefile: build the @argfile with mktemp and remove it, so no
> stale .tmp_.dt-style.checked is left in the build tree
> - run.sh: drop bash-only process substitution (POSIX sh now)
> and check the checker's exit status
> - selftest: add fixtures for the above (digit-leading nodes,
> trailing comments, multi-line cell arrays, tab+space aligned
> continuations) and update yaml-value-ws for the reworked
> value-whitespace rule
>
> Changes since v2:
> - route findings to stderr so a quiet dt_binding_check produces
> no output (Rob)
> - switch the Makefile recipe from mktemp to Kbuild's
> $(tmp-target) so build output stays inside the build folder
> (Nathan)
> - collapse the recipe's exit-handling tail into the familiar
> "&& touch $@ || true" pattern, matching cmd_chk_bindings;
> keeps future warnings non-fatal (Rob, Nathan)
> - explain in patch 3/4 why the recipe uses an explicit
> $(PYTHON3) prefix where the neighbouring recipes call their
> scripts directly (Rob)
> - append a trailing newline to every expected/*.txt selftest
> fixture (Rob)
> - restore the trailing whitespace inside yaml-trailing-ws.yaml
> that had been silently stripped during re-application, so the
> selftest actually exercises the trailing-whitespace rule
>
> Changes since v1:
> - rules declared in a registry tagged relaxed/strict; default
> relaxed mode is zero-violation on the current tree
> - tool now also accepts .dts/.dtsi/.dtso files directly (with a
> tab-indent variant); unused-labels skipped for .dtsi/.dtso
> where labels are exported to includers/applies-to
> - renamed dt-check-example-style -> dt-check-style
> - added -j N with $PARALLELISM (jobserver) awareness
> - dropped node-name [a-z0-9-] check (Rob: better as a meta-schema)
> - property-order rebuilt around buckets + declarative pairing
> rules plus natural-sort fallback
> - added child-name-order, required-blank-lines, hex-case,
> unit-address-format, value-whitespace, node-close-alone,
> line-length and continuation-alignment to strict mode
> - new selftest patch (Krzysztof: "would be happy to see at
> least a few test cases for it")
>
> Default relaxed mode is zero-violation on the current tree.
>
> Strict-mode violation counts on a current tree (5506 YAML
> bindings, 6530 in-tree .dts/.dtsi/.dtso under arch/):
>
> rule yaml dts
> property-order 14554 245000
> continuation-alignment 1857 93536
> indent-consistent 1562 48720
> required-blank-lines 1876 48563
> line-length 105 26322
> child-name-order 667 16821
> mixed-indent-chars 0 13294
> unused-labels 3611 11628
> child-address-order 63 4076
> blank-lines 82 1866
> node-close-alone 38 774
> value-whitespace 38 715
> hex-case 78 669
> indent-unit-dts -- 190
> unit-address-format 5 39
> trailing-whitespace 0 10
> indent-unit-strict 1492 --
> indent-unit 179 --
>
> (YAML and DTS columns reflect the rules that apply to each input
> type; e.g. indent-unit-strict is YAML-only since .dts files use
> tabs, indent-unit-dts is the equivalent DTS-only check.
> unused-labels is skipped for .dtsi/.dtso since labels there are
> exported to includers/applies-to.)
>
> The script was written with generous help from Claude Opus 4.7,
> since my Python is even worse than my DTS coding style.
>
> Daniel Golle (4):
> dt-bindings: add DTS style checker
> scripts/jobserver-exec: propagate child exit status
> dt-bindings: wire style checker into dt_binding_check
> dt-bindings: add self-test fixtures for style checker
>
> Documentation/devicetree/bindings/Makefile | 19 +-
> Makefile | 6 +
> scripts/dtc/dt-check-style | 1192 +++++++++++++++++
> .../dtc/dt-style-selftest/bad/dts-spaces.dts | 12 +
> .../bad/yaml-child-addr-order.yaml | 41 +
> .../bad/yaml-child-name-order.yaml | 37 +
> .../bad/yaml-cont-align.yaml | 30 +
> .../bad/yaml-digit-node-order.yaml | 37 +
> .../dt-style-selftest/bad/yaml-hex-case.yaml | 29 +
> .../bad/yaml-indent-strict.yaml | 29 +
> .../bad/yaml-label-in-string.yaml | 30 +
> .../bad/yaml-line-length.yaml | 29 +
> .../bad/yaml-mixed-indent.yaml | 29 +
> .../bad/yaml-multi-close.yaml | 35 +
> .../bad/yaml-node-close.yaml | 31 +
> .../bad/yaml-prop-order.yaml | 29 +
> .../bad/yaml-prop-pairing.yaml | 33 +
> .../bad/yaml-required-blank.yaml | 33 +
> .../dtc/dt-style-selftest/bad/yaml-tab.yaml | 29 +
> .../bad/yaml-trailing-comment.yaml | 26 +
> .../bad/yaml-trailing-ws.yaml | 29 +
> .../bad/yaml-unclosed-comment.yaml | 30 +
> .../bad/yaml-unit-addr-prefix.yaml | 29 +
> .../dt-style-selftest/bad/yaml-unit-addr.yaml | 29 +
> .../bad/yaml-unused-label.yaml | 29 +
> .../bad/yaml-value-ws-multiline.yaml | 27 +
> .../dt-style-selftest/bad/yaml-value-ws.yaml | 29 +
> .../expected/dts-spaces.dts.txt | 2 +
> .../expected/yaml-child-addr-order.yaml.txt | 2 +
> .../expected/yaml-child-name-order.yaml.txt | 2 +
> .../expected/yaml-cont-align.yaml.txt | 2 +
> .../expected/yaml-digit-node-order.yaml.txt | 2 +
> .../expected/yaml-hex-case.yaml.txt | 2 +
> .../expected/yaml-indent-strict.yaml.txt | 2 +
> .../expected/yaml-label-in-string.yaml.txt | 2 +
> .../expected/yaml-line-length.yaml.txt | 2 +
> .../expected/yaml-mixed-indent.yaml.txt | 3 +
> .../expected/yaml-multi-close.yaml.txt | 3 +
> .../expected/yaml-node-close.yaml.txt | 2 +
> .../expected/yaml-prop-order.yaml.txt | 2 +
> .../expected/yaml-prop-pairing.yaml.txt | 3 +
> .../expected/yaml-required-blank.yaml.txt | 3 +
> .../expected/yaml-tab.yaml.txt | 2 +
> .../expected/yaml-trailing-comment.yaml.txt | 2 +
> .../expected/yaml-trailing-ws.yaml.txt | 2 +
> .../expected/yaml-unclosed-comment.yaml.txt | 2 +
> .../expected/yaml-unit-addr-prefix.yaml.txt | 2 +
> .../expected/yaml-unit-addr.yaml.txt | 2 +
> .../expected/yaml-unused-label.yaml.txt | 2 +
> .../expected/yaml-value-ws-multiline.yaml.txt | 2 +
> .../expected/yaml-value-ws.yaml.txt | 2 +
> .../dt-style-selftest/good/dts-cont-align.dts | 26 +
> .../dtc/dt-style-selftest/good/dts-tab.dts | 29 +
> .../dt-style-selftest/good/yaml-4space.yaml | 41 +
> .../good/yaml-tricky-parsing.yaml | 57 +
> scripts/dtc/dt-style-selftest/run.sh | 71 +
> scripts/jobserver-exec | 4 +-
> 57 files changed, 2214 insertions(+), 4 deletions(-)
> create mode 100755 scripts/dtc/dt-check-style
> create mode 100644 scripts/dtc/dt-style-selftest/bad/dts-spaces.dts
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-child-addr-order.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-child-name-order.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-cont-align.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-digit-node-order.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-hex-case.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-indent-strict.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-label-in-string.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-line-length.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-mixed-indent.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-multi-close.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-node-close.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-prop-order.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-prop-pairing.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-required-blank.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-tab.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-trailing-comment.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-trailing-ws.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-unclosed-comment.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-unit-addr-prefix.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-unit-addr.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-unused-label.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-value-ws-multiline.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/bad/yaml-value-ws.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/expected/dts-spaces.dts.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-child-addr-order.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-child-name-order.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-cont-align.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-digit-node-order.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-hex-case.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-indent-strict.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-label-in-string.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-line-length.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-mixed-indent.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-multi-close.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-node-close.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-prop-order.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-prop-pairing.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-required-blank.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-tab.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-trailing-comment.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-trailing-ws.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-unclosed-comment.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-unit-addr-prefix.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-unit-addr.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-unused-label.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-value-ws-multiline.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/expected/yaml-value-ws.yaml.txt
> create mode 100644 scripts/dtc/dt-style-selftest/good/dts-cont-align.dts
> create mode 100644 scripts/dtc/dt-style-selftest/good/dts-tab.dts
> create mode 100644 scripts/dtc/dt-style-selftest/good/yaml-4space.yaml
> create mode 100644 scripts/dtc/dt-style-selftest/good/yaml-tricky-parsing.yaml
> create mode 100755 scripts/dtc/dt-style-selftest/run.sh
Applied, thanks!
Rob
^ permalink raw reply
* Re: [PATCH v4 07/14] mfd: lm3533: Switch sysfs_create_group() to device_add_group()
From: Andy Shevchenko @ 2026-06-10 18:47 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Lee Jones, Daniel Thompson, Jingoo Han, Pavel Machek, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jonathan Cameron,
David Lechner, Nuno Sá, Andy Shevchenko, Helge Deller,
Johan Hovold, dri-devel, linux-leds, devicetree, linux-kernel,
linux-iio, linux-fbdev
In-Reply-To: <CAPVz0n2+27QVeWNgPm3PH6V2Ceuym6sbMtUrh7hSHe9PcRmfMA@mail.gmail.com>
On Wed, Jun 10, 2026 at 05:38:38PM +0300, Svyatoslav Ryhel wrote:
> вт, 9 черв. 2026 р. о 22:14 Andy Shevchenko <andriy.shevchenko@intel.com> пише:
> > On Sat, Jun 06, 2026 at 07:57:31AM +0300, Svyatoslav Ryhel wrote:
> > > Switch from sysfs_create_group() to device_add_group() including device
> > > managed where appropriate.
> >
> > This should use .dev_groups member of struct device_driver.
>
> Specify pls, device_add_group literally uses dev_groups, I don't
> understand what is wrong.
dev_groups of the struct device_driver. It means that the data should be
static and be available before driver probe is called.
...
> > > + ret = devm_device_add_group(&bd->dev, &lm3533_bl_attribute_group);
> >
> > This will make Greg KH very grumpy. (For the record, original code as well
> > but it already is in upstream. So, thanks for trying to address this, just
> > needs a bit more of work.)
>
> In the prev iteration YOU asked to me to adjust this. I have adjusted
> and now you say that this is not appropriate. I will just drop this
> commit altogether.
Yes, and I still tell that this is the way to fix that issue.
You can even do it yourself in a few clicks (hint: `git log --grep` is the tool
of the day): 93afe8ba9b01 ("ACPI: TAD: Use dev_groups in struct device_driver").
This is an example of what I meant.
> > > + if (ret < 0)
> > > + return dev_err_probe(&pdev->dev, ret,
> > > + "failed to create sysfs attributes\n");
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH next v2] drivers/of/overlay: Use memcpy() to copy known length strings
From: Rob Herring (Arm) @ 2026-06-10 18:48 UTC (permalink / raw)
To: David Laight
Cc: Saravana Kannan, devicetree, linux-hardening, Arnd Bergmann,
linux-kernel, Kees Cook
In-Reply-To: <20260608185121.22331-1-david.laight.linux@gmail.com>
On Mon, 08 Jun 2026 19:51:21 +0100, David Laight wrote:
> Avoid calls to strcpy().
> The lengths of the strings have been used for the kzalloc(), replace
> the strcpy() calls with memcpy() using the known lengths.
>
> Signed-off-by: David Laight <david.laight.linux@gmail.com>
> ---
>
> v2: Improve commit message
>
> This is one of a group of patches that remove potentially unbounded
> strcpy() calls.
>
> They are mostly replaced by strscpy() or, when strlen() has just been
> called, with memcpy() (usually including the '\0').
>
> Calls with copy string literals into arrays are left unchanged.
> They are safe and easily detected as such.
>
> The changes were made by getting the compiler to detect the calls and
> then fixing the code by hand.
>
> Note that all the changes are only compile tested.
>
> Some Makefiles were changed to allow files to contain strcpy().
> As well as 'difficult to fix' files, this included 'show' functions
> as they really need to use sysfs_emit() or seq_printf().
>
> All the patches are being sent individually to avoid very long cc lists.
> Apologies for the terse commit messages and likely unexpected tags.
> (There are about 100 patches in total.)
>
> drivers/of/overlay.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
Applied, thanks!
^ permalink raw reply
* Re: [PATCH v4 10/14] mfd: lm3533: Set DMA mask
From: Andy Shevchenko @ 2026-06-10 18:51 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Lee Jones, Daniel Thompson, Jingoo Han, Pavel Machek, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jonathan Cameron,
David Lechner, Nuno Sá, Andy Shevchenko, Helge Deller,
Johan Hovold, dri-devel, linux-leds, devicetree, linux-kernel,
linux-iio, linux-fbdev
In-Reply-To: <CAPVz0n01ymfYGH+_MgfHvWqzg+tczLi8E-1q=rZ5cHu+uJrpdg@mail.gmail.com>
On Wed, Jun 10, 2026 at 05:40:56PM +0300, Svyatoslav Ryhel wrote:
> вт, 9 черв. 2026 р. о 22:17 Andy Shevchenko <andriy.shevchenko@intel.com> пише:
> > On Sat, Jun 06, 2026 at 07:57:34AM +0300, Svyatoslav Ryhel wrote:
> > > Missing coherent_dma_mask assigning triggers the following warning in
> > > dmesg:
> > >
> > > [ 3.287872] platform lm3533-backlight.0: DMA mask not set
> > >
> > > Since this warning might be elevated to an error in the future, set
> > > coherent_dma_mask to zero because both the core and cells do not utilize
> > > DMA.
> >
> > Hmm... I am not sure about this. The entire kernel has only two drivers that
> > do that, and thanks to their commit messages one of them pointed out to the
> > commit from 2018. So, if no other devices suffer from this, I think it has to
> > be a better way of achieving the same.
>
> If mfd framework warns that DMA mask is not set then this must be
> addressed. Why then there is such warning at the first place if mask
> can be just skipped. Then warning would be just a debug message. What
> is warning today can become error tomorrow.
It's there for 8 years. And only a few drivers explicitly nullify it.
I think doing this patch one should really understand what's going on.
(Note, I'm not that person, it's my gut feelings based on the experience
and the above statistics.) MFD creates a lot of platform devices for
which DMA mask is set automatically. So, why is it not set properly for
this device?
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v4 14/14] video: leds: backlight: lm3533: Support getting LED sources from DT
From: Andy Shevchenko @ 2026-06-10 18:54 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Lee Jones, Daniel Thompson, Jingoo Han, Pavel Machek, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jonathan Cameron,
David Lechner, Nuno Sá, Andy Shevchenko, Helge Deller,
Johan Hovold, dri-devel, linux-leds, devicetree, linux-kernel,
linux-iio, linux-fbdev
In-Reply-To: <CAPVz0n0m+i7wexfC0BWwvdOuJxDk_=x+EpxEbNmoHN1AsEmfNg@mail.gmail.com>
On Wed, Jun 10, 2026 at 05:45:28PM +0300, Svyatoslav Ryhel wrote:
> вт, 9 черв. 2026 р. о 22:23 Andy Shevchenko <andriy.shevchenko@intel.com> пише:
> > On Sat, Jun 06, 2026 at 07:57:38AM +0300, Svyatoslav Ryhel wrote:
> > > Add Control Bank to HVLED/LVLED muxing support based on the led-sources
> > > defined in the device tree.
...
> > > + int ret, i;
> >
> > No need to add 'i'.
>
> This is personal preference as well. There is no strict rule that
> iteration variable must be defined strictly in the for loop.
This is a preference by Linus who is the leader of the project.
Also in IIO we have some set of maintainer preferences.
> > > + for (i = 0; i < led->num_leds; i++) {
> >
> > for (unsigned int i = 0; i < led->num_leds; i++) {
> >
> > > + if (led->leds[i] >= LM3533_LVCTRLBANK_MAX)
> > > + continue;
> > > +
> > > + output_cfg_shift = led->leds[i] * 2;
> > > + output_cfg_val |= led->id << output_cfg_shift;
> > > + output_cfg_mask |= OUTPUT_LVLED_MASK << output_cfg_shift;
> > > + }
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: (subset) [PATCH v4 0/3] Reserve eDMA channels 0-1 for V2X
From: Frank.Li @ 2026-06-10 19:08 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
Sascha Hauer, Pengutronix Kernel Team, Fabio Estevam, Peng Fan,
Ye Li, Joy Zou
Cc: Frank Li, devicetree, imx, linux-arm-kernel, linux-kernel,
Laurentiu Mihalcea
In-Reply-To: <20260211-b4-imx95-v2x-v4-0-10852754b267@nxp.com>
From: Frank Li <Frank.Li@nxp.com>
On Wed, 11 Feb 2026 17:28:23 +0800, Joy Zou wrote:
Applied, thanks!
[1/3] dt-bindings: dma: fsl-edma: add dma-channel-mask property description
commit: edc448e785891cca747e21c6595e050d3d3fa434
Vnod have not picked it for the long time. I picked it to make reflect the
correct settings for i.mx
Best regards,
--
Frank Li <Frank.Li@nxp.com>
^ permalink raw reply
* Re: (subset) [PATCH v2 00/15] var-som-6ul: improve support for variants
From: Frank.Li @ 2026-06-10 19:18 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, andrzej.hajda, neil.armstrong, rfoss,
Laurent.pinchart, jonas, jernej.skrabec, maarten.lankhorst,
mripard, tzimmermann, airlied, simona, s.hauer, kernel, festevam,
shawnguo, laurent.pinchart+renesas, antonin.godard,
Hugo Villeneuve
Cc: Frank Li, devicetree, linux-kernel, dri-devel, imx,
linux-arm-kernel, Hugo Villeneuve
In-Reply-To: <20260305180651.1827087-1-hugo@hugovil.com>
From: Frank Li <Frank.Li@nxp.com>
On Thu, 05 Mar 2026 13:06:15 -0500, Hugo Villeneuve wrote:
> From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
>
> Hello,
> this patch series improves support for Variscite VAR-SOM-6UL based boards.
>
> The first two patches fix DT/dmesg warnings.
>
> [...]
Applied, thanks!
[14/15] dt-bindings: display/lvds-codec: add ti,sn65lvds93
commit: bd584193a91ef2e190a2cf19f9320387fda1a21d
Other dts part already picked by me. This binding have not picked by
subsystem mainatiner by twice ping. I picked it to avoid CHECK_DTB warnings.
Best regards,
--
Frank Li <Frank.Li@nxp.com>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox