* [PATCH V14 5/9] iio: imu: inv_icm42607: Add PM support for icm42607
From: Chris Morgan @ 2026-06-24 18:23 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: <20260624182350.50467-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 | 17 ++
.../iio/imu/inv_icm42607/inv_icm42607_core.c | 146 ++++++++++++++++++
.../iio/imu/inv_icm42607/inv_icm42607_i2c.c | 1 +
.../iio/imu/inv_icm42607/inv_icm42607_spi.c | 1 +
4 files changed, 165 insertions(+)
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607.h b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
index 88d35323bade..219cfcf7ac99 100644
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607.h
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
@@ -10,6 +10,7 @@
#include <linux/bits.h>
#include <linux/iio/iio.h>
#include <linux/mutex.h>
+#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/time.h>
@@ -118,12 +119,19 @@ struct inv_icm42607_hw {
u8 whoami;
};
+struct inv_icm42607_suspended {
+ enum inv_icm42607_sensor_mode gyro;
+ enum inv_icm42607_sensor_mode accel;
+};
+
/**
* struct inv_icm42607_state - driver state variables
* @hw: Hardware specific data.
* @lock: lock for serializing multiple registers access.
* @map: regmap pointer.
* @vddio_supply: I/O voltage regulator for the chip.
+ * @vddio_en: I/O voltage status for runtime PM.
+ * @suspended: suspended sensors configuration.
* @conf: chip sensors configurations.
* @orientation: sensor chip orientation relative to main hardware.
*/
@@ -132,6 +140,8 @@ struct inv_icm42607_state {
struct mutex lock;
struct regmap *map;
struct regulator *vddio_supply;
+ bool vddio_en;
+ struct inv_icm42607_suspended suspended;
struct inv_icm42607_conf conf;
struct iio_mount_matrix orientation;
};
@@ -351,11 +361,18 @@ struct inv_icm42607_state {
#define INV_ICM42607_GYRO_STOP_TIME_US (45 * USEC_PER_MSEC)
#define INV_ICM42607_TEMP_STARTUP_TIME_US 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 9b82a0499d35..ad23386a37b7 100644
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
@@ -4,16 +4,20 @@
*/
#include <linux/bitfield.h>
+#include <linux/cleanup.h>
#include <linux/delay.h>
#include <linux/dev_printk.h>
#include <linux/device/devres.h>
#include <linux/err.h>
#include <linux/iio/iio.h>
+#include <linux/ktime.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>
+#include <linux/timekeeping.h>
#include <linux/types.h>
#include "inv_icm42607.h"
@@ -102,6 +106,71 @@ 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)
+{
+ unsigned int oldaccel, oldgyro;
+ unsigned int sleepval_us = 0;
+ unsigned int val;
+ s64 disable_wait;
+ int ret;
+
+ ret = regmap_read(st->map, INV_ICM42607_REG_PWR_MGMT0, &val);
+ if (ret)
+ return ret;
+
+ oldaccel = FIELD_GET(INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK, val);
+ oldgyro = FIELD_GET(INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK, val);
+
+ if (gyro == oldgyro && accel == oldaccel)
+ return 0;
+
+ /*
+ * Datasheet on page 14.26 says we need to ensure the gyro sensor is on
+ * for a minimum of 45ms. So if we transition from an on state to an
+ * off state make sure at least 45ms have passed before power off and
+ * wait if it hasn't.
+ */
+ if (!gyro && oldgyro) {
+ disable_wait = ktime_us_delta(st->conf.gyro_stop,
+ ktime_get_real());
+ disable_wait = clamp(disable_wait, 0,
+ INV_ICM42607_GYRO_STOP_TIME_US);
+ fsleep(disable_wait);
+ }
+
+ val = FIELD_PREP(INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK, gyro);
+ val |= FIELD_PREP(INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK, accel);
+ ret = regmap_write(st->map, INV_ICM42607_REG_PWR_MGMT0, val);
+ if (ret)
+ return ret;
+
+ /*
+ * If a state change occurs from off to on, sleep for the startup
+ * time of the sensor, unless a sleep_ms is specified. Since more
+ * than one sensor can be transitioned from off to on, select the
+ * maximum time from each of the sensors changing from off to on.
+ * The startup time for the temp sensor is considerably smaller
+ * than the startup time for the other sensors and one or more are
+ * required to be on for the temp sensor to function, so any start
+ * delay should be enough.
+ */
+ if (accel && !oldaccel)
+ sleepval_us = max(sleepval_us, INV_ICM42607_ACCEL_STARTUP_TIME_US);
+
+ if (gyro && !oldgyro) {
+ sleepval_us = max(sleepval_us, INV_ICM42607_GYRO_STARTUP_TIME_US);
+ /* Track the earliest we can turn off the gyroscope. */
+ st->conf.gyro_stop = ktime_add_us(ktime_get_real(),
+ INV_ICM42607_GYRO_STOP_TIME_US);
+ }
+
+ fsleep(sleepval_us);
+
+ return 0;
+}
+
static int inv_icm42607_set_init_conf(struct inv_icm42607_state *st,
const struct inv_icm42607_conf *conf)
{
@@ -214,12 +283,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;
}
@@ -227,7 +301,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,
@@ -242,6 +321,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;
@@ -277,10 +358,75 @@ 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;
+
+ return inv_icm42607_set_pwr_mgmt0(st, INV_ICM42607_SENSOR_MODE_OFF,
+ INV_ICM42607_SENSOR_MODE_OFF);
+}
+
+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);
+}
+
+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-42607 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 bde931752eb8..aed04be28528 100644
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c
@@ -85,6 +85,7 @@ static struct i2c_driver inv_icm42607_driver = {
.driver = {
.name = "inv-icm42607-i2c",
.of_match_table = inv_icm42607_of_matches,
+ .pm = pm_ptr(&inv_icm42607_pm_ops),
},
.id_table = inv_icm42607_id,
.probe = inv_icm42607_probe,
diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c
index 6072ed7adc86..137cd34582d8 100644
--- a/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c
@@ -95,6 +95,7 @@ static struct spi_driver inv_icm42607_driver = {
.driver = {
.name = "inv-icm42607-spi",
.of_match_table = inv_icm42607_of_matches,
+ .pm = pm_ptr(&inv_icm42607_pm_ops),
},
.id_table = inv_icm42607_spi_id_table,
.probe = inv_icm42607_probe,
--
2.43.0
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related
* [PATCH V14 3/9] iio: imu: inv_icm42607: Add inv_icm42607 Core Driver
From: Chris Morgan @ 2026-06-24 18:23 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: <20260624182350.50467-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, as well as the bits necessary to compile and probe the
device when used on an i2c bus.
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
---
drivers/iio/imu/Kconfig | 1 +
drivers/iio/imu/Makefile | 1 +
drivers/iio/imu/inv_icm42607/Kconfig | 18 +
drivers/iio/imu/inv_icm42607/Makefile | 7 +
drivers/iio/imu/inv_icm42607/inv_icm42607.h | 364 ++++++++++++++++++
.../iio/imu/inv_icm42607/inv_icm42607_core.c | 286 ++++++++++++++
.../iio/imu/inv_icm42607/inv_icm42607_i2c.c | 97 +++++
7 files changed, 774 insertions(+)
create mode 100644 drivers/iio/imu/inv_icm42607/Kconfig
create mode 100644 drivers/iio/imu/inv_icm42607/Makefile
create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607.h
create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c
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..083c212087ab
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/Kconfig
@@ -0,0 +1,18 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+config INV_ICM42607
+ tristate
+ select IIO_BUFFER
+ select IIO_INV_SENSORS_TIMESTAMP
+
+config INV_ICM42607_I2C
+ tristate "InvenSense ICM-42607 I2C driver"
+ depends on I2C
+ select INV_ICM42607
+ select REGMAP_I2C
+ help
+ This driver supports the InvenSense ICM-42607 motion tracking
+ device over I2C.
+
+ This driver can be built as a module. The module will be called
+ inv-icm42607-i2c.
diff --git a/drivers/iio/imu/inv_icm42607/Makefile b/drivers/iio/imu/inv_icm42607/Makefile
new file mode 100644
index 000000000000..32046e2727d7
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+obj-$(CONFIG_INV_ICM42607) += inv-icm42607.o
+inv-icm42607-y += inv_icm42607_core.o
+
+obj-$(CONFIG_INV_ICM42607_I2C) += inv-icm42607-i2c.o
+inv-icm42607-i2c-y += inv_icm42607_i2c.o
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..88d35323bade
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
@@ -0,0 +1,364 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2026 InvenSense, Inc.
+ */
+
+#ifndef INV_ICM42607_H_
+#define INV_ICM42607_H_
+
+#include <asm/byteorder.h>
+#include <linux/bits.h>
+#include <linux/iio/iio.h>
+#include <linux/mutex.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/time.h>
+#include <linux/types.h>
+
+/*
+ * 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,
+ 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
+};
+
+/* Temperature sensor data filter (bandwidth) */
+enum inv_icm42607_temp_filter_bw {
+ INV_ICM42607_TEMP_FILTER_BYPASS = 0,
+ INV_ICM42607_TEMP_FILTER_BW_180HZ = 1,
+ INV_ICM42607_TEMP_FILTER_BW_72HZ = 2,
+ INV_ICM42607_TEMP_FILTER_BW_34HZ = 3,
+ INV_ICM42607_TEMP_FILTER_BW_16HZ = 4,
+ INV_ICM42607_TEMP_FILTER_BW_8HZ = 5,
+ INV_ICM42607_TEMP_FILTER_BW_4HZ = 6,
+ /* value 7 also corresponds to 4Hz */
+};
+
+/* 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;
+ ktime_t gyro_stop; /* earliest time to stop the gyro */
+};
+
+struct inv_icm42607_hw {
+ const char *name;
+ const struct inv_icm42607_conf *conf;
+ u8 whoami;
+};
+
+/**
+ * struct inv_icm42607_state - driver state variables
+ * @hw: Hardware specific data.
+ * @lock: lock for serializing multiple registers access.
+ * @map: regmap pointer.
+ * @vddio_supply: I/O voltage regulator for the chip.
+ * @conf: chip sensors configurations.
+ * @orientation: sensor chip orientation relative to main hardware.
+ */
+struct inv_icm42607_state {
+ const struct inv_icm42607_hw *hw;
+ struct mutex lock;
+ struct regmap *map;
+ struct regulator *vddio_supply;
+ struct inv_icm42607_conf conf;
+ struct iio_mount_matrix orientation;
+};
+
+/* 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 2
+#define INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS 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_WHOAMI 0x75
+#define INV_ICM42607P_WHOAMI 0x60
+#define INV_ICM42607_WHOAMI 0x67
+
+/*
+ * Timings as listed in section 3 of datasheet, all values listed in datasheet
+ * in ms except temp startup time... setting all values in us and using
+ * USEC_PER_MSEC to convert from values displayed in datasheet.
+ */
+#define INV_ICM42607_POWER_UP_TIME_US (100 * USEC_PER_MSEC)
+#define INV_ICM42607_RESET_TIME_US (1 * USEC_PER_MSEC)
+#define INV_ICM42607_ACCEL_STARTUP_TIME_US (10 * USEC_PER_MSEC)
+#define INV_ICM42607_GYRO_STARTUP_TIME_US (30 * USEC_PER_MSEC)
+#define INV_ICM42607_GYRO_STOP_TIME_US (45 * USEC_PER_MSEC)
+#define INV_ICM42607_TEMP_STARTUP_TIME_US 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..9b82a0499d35
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
@@ -0,0 +1,286 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 InvenSense, Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/dev_printk.h>
+#include <linux/device/devres.h>
+#include <linux/err.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 <linux/types.h>
+
+#include "inv_icm42607.h"
+
+static bool inv_icm42607_is_readable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case INV_ICM42607_REG_MCLK_RDY ... INV_ICM42607_REG_INT_CONFIG:
+ case INV_ICM42607_REG_TEMP_DATA1 ... INV_ICM42607_REG_TMST_FSYNCL:
+ case INV_ICM42607_REG_APEX_DATA4 ... INV_ICM42607_REG_INTF_CONFIG1:
+ case INV_ICM42607_REG_INT_STATUS_DRDY ... INV_ICM42607_REG_FIFO_DATA:
+ case INV_ICM42607_REG_WHOAMI:
+ return true;
+ }
+
+ return false;
+}
+
+static bool inv_icm42607_is_writeable_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case INV_ICM42607_REG_DEVICE_CONFIG ... INV_ICM42607_REG_INT_CONFIG:
+ case INV_ICM42607_REG_PWR_MGMT0 ... INV_ICM42607_REG_INT_SOURCE4:
+ case INV_ICM42607_REG_INTF_CONFIG0 ... INV_ICM42607_REG_INTF_CONFIG1:
+ return true;
+ }
+
+ return false;
+}
+
+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,
+ .writeable_reg = inv_icm42607_is_writeable_reg,
+ .readable_reg = inv_icm42607_is_readable_reg,
+ .volatile_reg = inv_icm42607_is_volatile_reg,
+ .max_register = INV_ICM42607_REG_WHOAMI,
+ .cache_type = REGCACHE_MAPLE,
+};
+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,
+ },
+};
+
+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_init_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);
+ 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;
+
+ val = FIELD_PREP(INV_ICM42607_TEMP_CONFIG0_FILTER_MASK,
+ INV_ICM42607_TEMP_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;
+
+ 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(1 * 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,
+ 1 * USEC_PER_MSEC, 10 * USEC_PER_MSEC);
+ 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;
+
+ val = FIELD_PREP(INV_ICM42607_INTF_CONFIG1_CLKSEL_MASK,
+ INV_ICM42607_INTF_CONFIG1_CLKSEL_PLL);
+ ret = regmap_update_bits(st->map, INV_ICM42607_REG_INTF_CONFIG1,
+ INV_ICM42607_INTF_CONFIG1_CLKSEL_MASK,
+ val);
+ if (ret)
+ return ret;
+
+ return inv_icm42607_set_init_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-42607 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
new file mode 100644
index 000000000000..bde931752eb8
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 InvenSense, Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/dev_printk.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+
+#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;
+
+ val = FIELD_PREP(INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK,
+ INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_SPI_DIS);
+ return regmap_update_bits(st->map, INV_ICM42607_REG_INTF_CONFIG0,
+ INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK,
+ val);
+}
+
+static int inv_icm42607_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ const struct inv_icm42607_hw *hw;
+ struct regmap *regmap;
+
+ hw = i2c_get_match_data(client);
+ if (!hw)
+ return dev_err_probe(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(dev, PTR_ERR(regmap),
+ "Failed to register i2c regmap\n");
+
+ 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-42607 I2C driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_ICM42607");
--
2.43.0
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related
* [PATCH V14 4/9] iio: imu: inv_icm42607: Add SPI For icm42607
From: Chris Morgan @ 2026-06-24 18:23 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: <20260624182350.50467-1-macroalpha82@gmail.com>
From: Chris Morgan <macromorgan@hotmail.com>
Add SPI driver support for InvenSense ICM-42607 devices.
Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
---
drivers/iio/imu/inv_icm42607/Kconfig | 12 ++
drivers/iio/imu/inv_icm42607/Makefile | 3 +
.../iio/imu/inv_icm42607/inv_icm42607_spi.c | 107 ++++++++++++++++++
3 files changed, 122 insertions(+)
create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c
diff --git a/drivers/iio/imu/inv_icm42607/Kconfig b/drivers/iio/imu/inv_icm42607/Kconfig
index 083c212087ab..23f461f57afc 100644
--- a/drivers/iio/imu/inv_icm42607/Kconfig
+++ b/drivers/iio/imu/inv_icm42607/Kconfig
@@ -16,3 +16,15 @@ config INV_ICM42607_I2C
This driver can be built as a module. The module will be called
inv-icm42607-i2c.
+
+config INV_ICM42607_SPI
+ tristate "InvenSense ICM-42607 SPI driver"
+ depends on SPI_MASTER
+ select INV_ICM42607
+ select REGMAP_SPI
+ help
+ This driver supports the InvenSense ICM-42607 motion tracking
+ device over SPI.
+
+ This driver can be built as a module. The module will be called
+ inv-icm42607-spi.
diff --git a/drivers/iio/imu/inv_icm42607/Makefile b/drivers/iio/imu/inv_icm42607/Makefile
index 32046e2727d7..be109102e203 100644
--- a/drivers/iio/imu/inv_icm42607/Makefile
+++ b/drivers/iio/imu/inv_icm42607/Makefile
@@ -5,3 +5,6 @@ inv-icm42607-y += inv_icm42607_core.o
obj-$(CONFIG_INV_ICM42607_I2C) += inv-icm42607-i2c.o
inv-icm42607-i2c-y += inv_icm42607_i2c.o
+
+obj-$(CONFIG_INV_ICM42607_SPI) += inv-icm42607-spi.o
+inv-icm42607-spi-y += inv_icm42607_spi.o
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..6072ed7adc86
--- /dev/null
+++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2026 InvenSense, Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/dev_printk.h>
+#include <linux/err.h>
+#include <linux/mod_devicetable.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;
+
+ val = FIELD_PREP(INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK,
+ INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_I2C_DIS);
+ return regmap_update_bits(st->map, INV_ICM42607_REG_INTF_CONFIG0,
+ INV_ICM42607_INTF_CONFIG0_UI_SIFS_CFG_MASK,
+ val);
+}
+
+static int inv_icm42607_probe(struct spi_device *spi)
+{
+ const struct inv_icm42607_hw *hw;
+ struct device *dev = &spi->dev;
+ struct regmap *regmap;
+
+ hw = spi_get_device_match_data(spi);
+ if (!hw)
+ return dev_err_probe(dev, -ENODEV, "Failed to get SPI data\n");
+
+ if (spi->mode & SPI_3WIRE)
+ return dev_err_probe(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(dev, PTR_ERR(regmap),
+ "Failed to register spi regmap\n");
+
+ 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-42607 SPI driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_ICM42607");
--
2.43.0
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related
* [PATCH V14 2/9] dt-bindings: iio: imu: icm42600: Add icm42607
From: Chris Morgan @ 2026-06-24 18:23 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: <20260624182350.50467-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
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related
* [PATCH V14 1/9] dt-bindings: iio: imu: icm42600: Add mount-matrix
From: Chris Morgan @ 2026-06-24 18:23 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: <20260624182350.50467-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
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related
* [PATCH V14 0/9] Add Invensense ICM42607
From: Chris Morgan @ 2026-06-24 18:23 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
From: Chris Morgan <macromorgan@hotmail.com>
Add support for the ICM42607 IMU. This sensor shares the same
functionality but a different register layout with the existing
ICM42600.
This driver should work with the ICM42607 and ICM42607P over both I2C
and SPI, however only the ICM42607P over I2C could be tested.
Changes Since V1:
- Instead of creating a new driver, merged with the existing inv_icm42600
driver. This necessitated adding some code to the existing driver to
permit using a different register layout for the same functionality.
- Split changes up a bit more to decrease the size of the individual
patches. Note that patch 0004 is still pretty hefty; if I need to split
further I may need to create some temporary stub functions.
- Used guard() and PM_RUNTIME_ACQUIRE_AUTOSUSPEND() on the new functions
per Jonathan's recommendations.
Changes Since V2:
- Went back to using a new driver on advice from Invensense engineer.
- Further split changes up into smaller chunks of functionality. Note
still that the largest patch is approximately 900 lines, and that while
the driver compiles cleanly at each commit it is not able to drive the
hardware until the commit that adds the Interrupt (as it also adds the
Makefile).
- Change the error to a warning when the devicetree binding does not match
the hardware ID.
- Dropped the ack on the devicetree bindings, as I am creating a new file
(for a new driver) instead of modifying the existing one.
Changes Since V3:
- Numerous small fixes (too many to list here). Thank you to everyone who
provided feedback.
- Split power management additions into an additional commit to break
things up further.
- Consolidated devicetree documentation in existing
invensense,icm42600.yaml file.
- Removed most of the FIELD_PREP from header file to c files to make code
easier to read.
- Changed scale values to 2D arrays for Gyro and Accelerometer.
- Removed IIO_CHAN_INFO_CALIBBIAS attribute.
Changes Since V4:
- Additional numerous small fixes, thank you again for all the feedback.
- Dropped power control API and instead run device in low noise mode.
- Split devicetree bindings into two distinct changes.
- Reordered adding of enums and structs to main header file so that they
are only brought in when needed.
- Stopped using enum for driver data and instead am using pointer to
device specific driver data.
Changes Since V5:
- Corrected use of "dev_warn_probe" to just "dev_warn".
- Fixed some return scenarios which would unconditionally return 0
when an error was present.
- Corrected use of max() to min() for bounds checking. max() was
incorrect.
- Fixed using "st->conf.accel.odr" in the gyroscope function. It
should have been "st->conf.gyro.odr" which it now is.
- Additional small fixes suggested by "sashiko.dev".
- Added a regmap cache. I used the datasheet to try and determine
which registers might change without explicit writes.
Changes Since V6:
- Corrected additional errors identified by sashiko.dev, mostly
fixing potential deadlocks, missing calls for pm runtime, and
potential overflow issues.
Changes Since V7:
- Dropped Wake on Movement patches, since some of the functionality
was only available for a device on which I cannot test.
- Dropped support for SPI 3-Wire mode, since it complicated the
bus setup (and I lack the hardware to test such features anyway).
- Fixed a few additional bugs identified by sashiko.dev bot.
Changes Since V8:
- Added back IRQ dropped accidentally when dropping wake on movement
patches.
- Dropped "Reviewed-By" tag on patch 2 because of substantial changes
made to devicetree binding documentation.
- Additional small fixes as suggested.
Changes Since V9:
- Removed interrupts (and buffers) from the driver. I previously was
unable to detect deadlocks because it turns out my IRQ was not even
wired correctly in my device.
- Updated devicetree binding commits to make interrupts optional for
users of the icm42607 driver.
Changes Since V10:
- Explicitly specified enum values in header file.
- Removed additional dead code for buffer handling.
- Cleaned up headers.
- Added additional locks as requested by sashiko.dev bot.
Changes Since V11:
- Since driver has shrunk in size considerably, moved i2c bits into
first code commit. This ensures that the very first commit with code
can now be compiled. The commit after that adds SPI support as it
was in the previous versions.
- Used pahole to optimize inv_icm42607_state. Reordering elements
reduced size in memory from 384 bytes to 256 bytes.
- Added a map of all readable registers and all writeable registers
according to the datasheet.
- Added back some missing headers pointed out by the maintainers.
- Added FIELD_PREP in a few more places to make the code more
obvious on what it's doing.
- Added a comment to the power management code to note that
temperature sensor being enabled doesn't matter as the clocks
are off by default when the gyro and accel channels are off.
- Removed iio_device_claim_direct() calls since it was no longer
needed.
- Fixed shared_by_all attributes for temperature sensor.
- Additional miscellanous fixes as requested.
Changes Since V12:
- Removed aligned buffer from inv_icm42607_state struct as we do not
currently have the need for it.
- Corrected the order of the odr values in the accel and gyro files
as the values were out of order (the place in the array corresponds
to the register value).
- Stopped setting the clock value depending upon the temp config. The
datasheet advised to keep using the default value.
- Corrected logic when changing between states. We only need to pause
when a sensor changes from off to an on state or when the gyro
changes from an on state to off.
- Added missing includes for several files.
Changes Since V13:
- Refactored inv_icm42607_set_accel_conf() and
inv_icm42607_set_gyro_conf() into a single function.
- Refactored inv_icm42607_accel_read_sensor() and
inv_icm42607_gyro_read_sensor() into a single function.
- Merged inv_icm42607_set_temp_conf() into initial init function
since it only really needs to be called once.
- Saved adding temp sensor for last and updated
inv_icm42607_temp_read() to either confirm other sensors are already
enabled or enable the accelerometer so it can get a reading.
- Updated inv_icm42607_set_pwr_mgmt0() so that it does not update the
sensor mode and forcibly keep the sensor enabled.
- Added inv_icm42607_temp_filter_bw enums since it appears to use
different values than the accel or gyro sensor.
- Set the temp startup time from 77ms to 77us, as I previously misread
the datasheet.
- Additional minor fixes.
Chris Morgan (9):
dt-bindings: iio: imu: icm42600: Add mount-matrix
dt-bindings: iio: imu: icm42600: Add icm42607
iio: imu: inv_icm42607: Add inv_icm42607 Core Driver
iio: imu: inv_icm42607: Add SPI For icm42607
iio: imu: inv_icm42607: Add PM support for icm42607
iio: imu: inv_icm42607: Add Accelerometer for icm42607
iio: imu: inv_icm42607: Add Gyroscope to icm42607
iio: imu: inv_icm42607: Add Temp Support in icm42607
arm64: dts: rockchip: Add icm42607p IMU for RG-DS
.../bindings/iio/imu/invensense,icm42600.yaml | 20 +-
.../dts/rockchip/rk3568-anbernic-rg-ds.dts | 8 +-
drivers/iio/imu/Kconfig | 1 +
drivers/iio/imu/Makefile | 1 +
drivers/iio/imu/inv_icm42607/Kconfig | 30 +
drivers/iio/imu/inv_icm42607/Makefile | 13 +
drivers/iio/imu/inv_icm42607/inv_icm42607.h | 423 ++++++++++++
.../iio/imu/inv_icm42607/inv_icm42607_accel.c | 317 +++++++++
.../iio/imu/inv_icm42607/inv_icm42607_core.c | 606 ++++++++++++++++++
.../iio/imu/inv_icm42607/inv_icm42607_gyro.c | 313 +++++++++
.../iio/imu/inv_icm42607/inv_icm42607_i2c.c | 98 +++
.../iio/imu/inv_icm42607/inv_icm42607_spi.c | 108 ++++
.../iio/imu/inv_icm42607/inv_icm42607_temp.c | 99 +++
.../iio/imu/inv_icm42607/inv_icm42607_temp.h | 37 ++
14 files changed, 2072 insertions(+), 2 deletions(-)
create mode 100644 drivers/iio/imu/inv_icm42607/Kconfig
create mode 100644 drivers/iio/imu/inv_icm42607/Makefile
create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607.h
create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c
create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c
create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_i2c.c
create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_spi.c
create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c
create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_temp.h
--
2.43.0
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply
* Re: [PATCH v17 01/28] drm/amd/display: Remove unnecessary SIGNAL_TYPE_HDMI_TYPE_A check
From: Harry Wentland @ 2026-06-24 17:15 UTC (permalink / raw)
To: Nicolas Frattaroli, Leo Li, Rodrigo Siqueira, Alex Deucher,
Christian König, David Airlie, Simona Vetter,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Andrzej Hajda, Neil Armstrong, Robert Foss, Laurent Pinchart,
Jonas Karlman, Jernej Skrabec, Sandy Huang, Heiko Stübner,
Andy Yan, Jani Nikula, Rodrigo Vivi, Joonas Lahtinen,
Tvrtko Ursulin, Dmitry Baryshkov, Sascha Hauer, Rob Herring,
Jonathan Corbet, Shuah Khan, Daniel Stone
Cc: kernel, amd-gfx, dri-devel, linux-kernel, linux-arm-kernel,
linux-rockchip, intel-gfx, intel-xe, linux-doc, wayland-devel,
Werner Sembach, Andri Yngvason
In-Reply-To: <20260609-color-format-v17-1-35739b5782cc@collabora.com>
On 2026-06-09 08:43, Nicolas Frattaroli wrote:
> From: Werner Sembach <wse@tuxedocomputers.com>
>
> Remove unnecessary SIGNAL_TYPE_HDMI_TYPE_A check that was performed in the
> drm_mode_is_420_only() case, but not in the drm_mode_is_420_also() &&
> force_yuv420_output case.
>
> Without further knowledge if YCbCr 4:2:0 is supported outside of HDMI,
> there is no reason to use RGB when the display
> reports drm_mode_is_420_only() even on a non HDMI connection.
>
> This patch also moves both checks in the same if-case. This eliminates an
> extra else-if-case.
>
> Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
> Signed-off-by: Andri Yngvason <andri@yngvason.is>
> Tested-by: Andri Yngvason <andri@yngvason.is>
> Reviewed-by: Daniel Stone <daniel@fooishbar.org>
> Signed-off-by: Nicolas Frattaroli <nicolas.frattaroli@collabora.com>
Reviewed-by: Harry Wentland <harry.wentland@amd.com>
Harry
> ---
> drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 9 +++------
> 1 file changed, 3 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index ba7f98a87808..dfe97897127c 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -6917,12 +6917,9 @@ static void fill_stream_properties_from_drm_display_mode(
> timing_out->v_border_top = 0;
> timing_out->v_border_bottom = 0;
> /* TODO: un-hardcode */
> - if (drm_mode_is_420_only(info, mode_in)
> - && stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
> - timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
> - else if (drm_mode_is_420_also(info, mode_in)
> - && aconnector
> - && aconnector->force_yuv420_output)
> + if (drm_mode_is_420_only(info, mode_in) ||
> + (aconnector && aconnector->force_yuv420_output &&
> + drm_mode_is_420_also(info, mode_in)))
> timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
> else if ((connector->display_info.color_formats & BIT(DRM_OUTPUT_COLOR_FORMAT_YCBCR422))
> && aconnector
>
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply
* Re: [PATCH V13 5/9] iio: imu: inv_icm42607: Add PM support for icm42607
From: Chris Morgan @ 2026-06-24 17:04 UTC (permalink / raw)
To: Jonathan Cameron
Cc: Chris Morgan, linux-iio, andy, nuno.sa, dlechner,
jean-baptiste.maneyrol, linux-rockchip, devicetree, heiko,
conor+dt, krzk+dt, robh, andriy.shevchenko
In-Reply-To: <20260624160651.03645da7@jic23-huawei>
On Wed, Jun 24, 2026 at 04:06:51PM +0100, Jonathan Cameron wrote:
> On Tue, 23 Jun 2026 13:08:02 -0500
> Chris Morgan <macromorgan@hotmail.com> wrote:
>
> > On Mon, Jun 22, 2026 at 09:34:10PM -0500, Chris Morgan wrote:
> > > On Sun, Jun 21, 2026 at 06:19:48PM +0100, Jonathan Cameron wrote:
> > > > On Mon, 15 Jun 2026 12:25:48 -0500
> > > > Chris Morgan <macroalpha82@gmail.com> wrote:
> > > >
> > > > > From: Chris Morgan <macromorgan@hotmail.com>
> > > > >
> > > > > Add power management support for the ICM42607 device driver.
> > > > >
> > > > > Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
> > > > A few things from taking a look at the sashiko report:
> > > > https://sashiko.dev/#/patchset/20260615172554.160910-1-macroalpha82%40gmail.com
> > > >
> > > > > ---
> > > > > drivers/iio/imu/inv_icm42607/inv_icm42607.h | 18 +++
> > > > > .../iio/imu/inv_icm42607/inv_icm42607_core.c | 139 ++++++++++++++++++
> > > > > .../iio/imu/inv_icm42607/inv_icm42607_i2c.c | 1 +
> > > > > .../iio/imu/inv_icm42607/inv_icm42607_spi.c | 1 +
> > > > > 4 files changed, 159 insertions(+)
> > > > >
> > > > > diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607.h b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
> > > > > index a6a58571935f..4f4f541027dc 100644
> > > > > --- a/drivers/iio/imu/inv_icm42607/inv_icm42607.h
> > > > > +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
> > > >
> > > > > @@ -334,11 +345,18 @@ struct inv_icm42607_state {
> > > > > #define INV_ICM42607_GYRO_STOP_TIME_MS 45
> > > > > #define INV_ICM42607_TEMP_STARTUP_TIME_MS 77
> > > > >
> > > > > +/*
> > > > > + * Suspend delay assumed from other icm42600 series device, not
> > > > > + * documented in datasheet.
> > > > > + */
> > > > > +#define INV_ICM42607_SUSPEND_DELAY_MS (2 * USEC_PER_MSEC)
> > > >
> > > > Sashiko had a valid comment on this. MSEC_PER_SEC seems more
> > > > appropriate given this is 2 seconds in milli seconds.
> > > >
> > > > > +
> > > > > 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 4b8e19091786..64f5d263de4f 100644
> > > > > --- a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
> > > > > +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
> > > > > @@ -4,6 +4,7 @@
> > > > > */
> > > > >
> > > > > #include <linux/bitfield.h>
> > > > > +#include <linux/cleanup.h>
> > > > > #include <linux/delay.h>
> > > > > #include <linux/dev_printk.h>
> > > > > #include <linux/device/devres.h>
> > > > > @@ -11,6 +12,7 @@
> > > > > #include <linux/iio/iio.h>
> > > > > #include <linux/module.h>
> > > > > #include <linux/mutex.h>
> > > > > +#include <linux/pm_runtime.h>
> > > > > #include <linux/regmap.h>
> > > > > #include <linux/regulator/consumer.h>
> > > > > #include <linux/time.h>
> > > > > @@ -103,6 +105,63 @@ const struct inv_icm42607_hw inv_icm42607p_hw_data = {
> > > > > };
> > > > > EXPORT_SYMBOL_NS_GPL(inv_icm42607p_hw_data, "IIO_ICM42607");
> > > > >
> > > > > +static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st,
> > > > > + enum inv_icm42607_sensor_mode gyro,
> > > > > + enum inv_icm42607_sensor_mode accel,
> > > > > + bool temp, unsigned int *sleep_ms)
> > > > > +{
> > > > > + enum inv_icm42607_sensor_mode oldaccel = st->conf.accel.mode;
> > > > > + enum inv_icm42607_sensor_mode oldgyro = st->conf.gyro.mode;
> > > > > + bool oldtemp = st->conf.temp_en;
> > > > > + unsigned int sleepval_ms;
> > > > > + unsigned int val;
> > > > > + int ret;
> > > > > +
> > > > > + if (gyro == oldgyro && accel == oldaccel && temp == oldtemp)
> > > > > + return 0;
> > > > > +
> > > > > + /*
> > > > > + * Datasheet on page 14.26 says we need to ensure the gyro sensor is on
> > > > > + * for a minimum of 45ms. So if we transition from an on state to an
> > > > > + * off state wait 45ms to ensure a sufficient pause before power off.
> > > >
> > > > Sashiko commented on this.. I think what we could do with adding to the
> > > > comment is what the path is that didn't pass through this function which would
> > > > ensure we have been on for 30 of this msecs already.
> > >
> > > I'm going to track whatever time the gyro started, and then if less
> > > than 45ms has elapsed just pause the remaining amount of time.
> > >
> > > >
> > > > > + */
> > > > > + if (!gyro && oldgyro)
> > > > > + fsleep(INV_ICM42607_GYRO_STOP_TIME_MS * USEC_PER_MSEC);
> > > > > +
> > > > > + val = FIELD_PREP(INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK, gyro);
> > > > > + val |= FIELD_PREP(INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK, accel);
> > > > > + ret = regmap_write(st->map, INV_ICM42607_REG_PWR_MGMT0, val);
> > > > > + if (ret)
> > > > > + return ret;
> > > > > +
> > > > > + st->conf.gyro.mode = gyro;
> > > > > + st->conf.accel.mode = accel;
> > > > > + st->conf.temp_en = temp;
> > > > > +
> > > > > + /*
> > > > > + * If a state change occurs from off to on, sleep for the startup
> > > > > + * time of the sensor, unless a sleep_ms is specified. Since more
> > > > > + * than one sensor can be transitioned from off to on, select the
> > > > > + * maximum time from each of the sensors changing from off to on.
> > > > > + */
> > > > > + sleepval_ms = 0;
> > > > > + if (temp && !oldtemp)
> > > > > + sleepval_ms = max(sleepval_ms, INV_ICM42607_TEMP_STARTUP_TIME_MS);
> > > > > +
> > > > > + if (accel && !oldaccel)
> > > > > + sleepval_ms = max(sleepval_ms, INV_ICM42607_ACCEL_STARTUP_TIME_MS);
> > > > > +
> > > > > + if (gyro && !oldgyro)
> > > > > + sleepval_ms = max(sleepval_ms, INV_ICM42607_GYRO_STARTUP_TIME_MS);
> > > > > +
> > > > > + if (sleep_ms)
> > > > > + *sleep_ms = sleepval_ms;
> > > > > + else if (sleepval_ms)
> > > > > + fsleep(sleepval_ms * USEC_PER_MSEC);
> > > > > +
> > > > > + return 0;
> > > > > +}
> > > >
> > > > >
> > > > > int inv_icm42607_core_probe(struct regmap *regmap,
> > > > > @@ -236,6 +305,8 @@ int inv_icm42607_core_probe(struct regmap *regmap,
> > > > > if (!st)
> > > > > return -ENOMEM;
> > > > >
> > > > > + dev_set_drvdata(dev, st);
> > > > > +
> > > > > ret = devm_mutex_init(dev, &st->lock);
> > > > > if (ret)
> > > > > return ret;
> > > > > @@ -271,10 +342,78 @@ int inv_icm42607_core_probe(struct regmap *regmap,
> > > > > if (ret)
> > > > > return ret;
> > > > >
> > > > > + ret = devm_pm_runtime_set_active_enabled(dev);
> > > > > + if (ret)
> > > > > + return ret;
> > > > > +
> > > > > + pm_runtime_set_autosuspend_delay(dev, INV_ICM42607_SUSPEND_DELAY_MS);
> > > > > + pm_runtime_use_autosuspend(dev);
> > > > Sashiko does put out some stuff here. Please take a look and work out or
> > > > test if it is right (I think not but haven't checked that carefully!)
> > > > From a quick look I think that the auto disabling of autosuspend does a
> > > > rpm_idle() that should result in it suspending...
> > > >
> > >
> > > I see a few other drivers adding one more call to
> > > devm_pm_runtime_enable() so I'm going to see how that works out.
> >
> > Obviously that didn't work, but digging in much deeper into the PM code
> > I see that devm_pm_runtime_set_active_enabled() returns
> > devm_pm_runtime_enable(), which sets devm_add_action_or_reset() on
> > pm_runtime_disable_action(), which calls
> > pm_runtime_dont_use_autosuspend() and pm_runtime_disable(). Shouldn't
> > this work, or am I missing something? Basically when the driver
> > detaches shouldn't this chain end up calling
> > pm_runtime_dont_use_autosuspend()?
> Agreed. That was how I read things. The only thing I didn't entirely
> confirm (states involved were fiddly enough I'd want to check it
> with the actual driver!) was that pm_runtime_dont_use_autosuspend()
> ends up calling rpm_idle() in this case.
>
> Jonathan
I dropped in a dev_warn on the rpm_idle() and can confirm when I
unbound the driver it called rpm_idle(). So... yes?
Chris
>
> >
> > Thank you,
> > Chris
> >
> > >
> > > >
> > > > > +
> > > > > return 0;
> > > > > }
> > > > > EXPORT_SYMBOL_NS_GPL(inv_icm42607_core_probe, "IIO_ICM42607");
> > >
> > > Thank you,
> > > Chris
>
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply
* [PATCH v2 4/4] media: qcom: camss: use fwnode_graph_for_each_endpoint_scoped() to simplify code
From: Frank.Li @ 2026-06-24 17:00 UTC (permalink / raw)
To: Andy Shevchenko, Daniel Scally, Heikki Krogerus, Sakari Ailus,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Mauro Carvalho Chehab, Dafna Hirschfeld, Laurent Pinchart,
Heiko Stuebner, Bryan O'Donoghue, Vladimir Zapolskiy,
Loic Poulain
Cc: driver-core, linux-acpi, linux-kernel, linux-media,
linux-rockchip, linux-arm-kernel, linux-arm-msm, imx, Guoniu Zhou,
Frank Li, Guoniu Zhou
In-Reply-To: <20260624-fw_scoped-v2-0-0a8db472af4a@nxp.com>
From: Frank Li <Frank.Li@nxp.com>
Use fwnode_graph_for_each_endpoint_scoped() to simplify code.
No functional changes.
Reviewed-by: Guoniu Zhou <guoniu.zhou@oss.nxp.com>
Reviewed-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v2
- fix typo simplify
- collect andy, gouniou and loic's review tags
---
drivers/media/platform/qcom/camss/camss.c | 17 +++++------------
1 file changed, 5 insertions(+), 12 deletions(-)
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index 2123f6388e3d7..23f3cc30a15a5 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -4793,30 +4793,23 @@ static int camss_parse_endpoint_node(struct device *dev,
static int camss_parse_ports(struct camss *camss)
{
struct device *dev = camss->dev;
- struct fwnode_handle *fwnode = dev_fwnode(dev), *ep;
+ struct fwnode_handle *fwnode = dev_fwnode(dev);
int ret;
- fwnode_graph_for_each_endpoint(fwnode, ep) {
+ fwnode_graph_for_each_endpoint_scoped(fwnode, ep) {
struct camss_async_subdev *csd;
csd = v4l2_async_nf_add_fwnode_remote(&camss->notifier, ep,
typeof(*csd));
- if (IS_ERR(csd)) {
- ret = PTR_ERR(csd);
- goto err_cleanup;
- }
+ if (IS_ERR(csd))
+ return PTR_ERR(csd);
ret = camss_parse_endpoint_node(dev, ep, csd);
if (ret < 0)
- goto err_cleanup;
+ return ret;
}
return 0;
-
-err_cleanup:
- fwnode_handle_put(ep);
-
- return ret;
}
/*
--
2.43.0
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related
* [PATCH v2 3/4] media: rkisp1: use fwnode_graph_for_each_endpoint_scoped() to simplify code
From: Frank.Li @ 2026-06-24 17:00 UTC (permalink / raw)
To: Andy Shevchenko, Daniel Scally, Heikki Krogerus, Sakari Ailus,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Mauro Carvalho Chehab, Dafna Hirschfeld, Laurent Pinchart,
Heiko Stuebner, Bryan O'Donoghue, Vladimir Zapolskiy,
Loic Poulain
Cc: driver-core, linux-acpi, linux-kernel, linux-media,
linux-rockchip, linux-arm-kernel, linux-arm-msm, imx, Guoniu Zhou,
Frank Li
In-Reply-To: <20260624-fw_scoped-v2-0-0a8db472af4a@nxp.com>
From: Frank Li <Frank.Li@nxp.com>
Use fwnode_graph_for_each_endpoint_scoped() to simplify code.
No functional changes.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Andy: Keep original code because too much break. and I am working on more
generally solution, so the whole function can be replaced.
---
drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
index 1791c02a40ae1..f90e01301943c 100644
--- a/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
+++ b/drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c
@@ -187,7 +187,6 @@ static int rkisp1_subdev_notifier_register(struct rkisp1_device *rkisp1)
{
struct v4l2_async_notifier *ntf = &rkisp1->notifier;
struct fwnode_handle *fwnode = dev_fwnode(rkisp1->dev);
- struct fwnode_handle *ep;
unsigned int index = 0;
int ret = 0;
@@ -195,7 +194,7 @@ static int rkisp1_subdev_notifier_register(struct rkisp1_device *rkisp1)
ntf->ops = &rkisp1_subdev_notifier_ops;
- fwnode_graph_for_each_endpoint(fwnode, ep) {
+ fwnode_graph_for_each_endpoint_scoped(fwnode, ep) {
struct fwnode_handle *port;
struct v4l2_fwnode_endpoint vep = { };
struct rkisp1_sensor_async *rk_asd;
@@ -286,7 +285,6 @@ static int rkisp1_subdev_notifier_register(struct rkisp1_device *rkisp1)
}
if (ret) {
- fwnode_handle_put(ep);
v4l2_async_nf_cleanup(ntf);
return ret;
}
--
2.43.0
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related
* [PATCH v2 2/4] media: mc: use fwnode_graph_for_each_endpoint_scoped() to simpilfy code
From: Frank.Li @ 2026-06-24 17:00 UTC (permalink / raw)
To: Andy Shevchenko, Daniel Scally, Heikki Krogerus, Sakari Ailus,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Mauro Carvalho Chehab, Dafna Hirschfeld, Laurent Pinchart,
Heiko Stuebner, Bryan O'Donoghue, Vladimir Zapolskiy,
Loic Poulain
Cc: driver-core, linux-acpi, linux-kernel, linux-media,
linux-rockchip, linux-arm-kernel, linux-arm-msm, imx, Guoniu Zhou,
Frank Li, Guoniu Zhou
In-Reply-To: <20260624-fw_scoped-v2-0-0a8db472af4a@nxp.com>
From: Frank Li <Frank.Li@nxp.com>
Use cleanup helper fwnode_graph_for_each_endpoint_scoped() to simpilfy
code.
Reviewed-by: Guoniu Zhou <guoniu.zhou@oss.nxp.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
drivers/media/v4l2-core/v4l2-mc.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c
index 937d358697e19..5d7fcd67dc42e 100644
--- a/drivers/media/v4l2-core/v4l2-mc.c
+++ b/drivers/media/v4l2-core/v4l2-mc.c
@@ -324,12 +324,10 @@ EXPORT_SYMBOL_GPL(v4l_vb2q_enable_media_source);
int v4l2_create_fwnode_links_to_pad(struct v4l2_subdev *src_sd,
struct media_pad *sink, u32 flags)
{
- struct fwnode_handle *endpoint;
-
if (!(sink->flags & MEDIA_PAD_FL_SINK))
return -EINVAL;
- fwnode_graph_for_each_endpoint(src_sd->fwnode, endpoint) {
+ fwnode_graph_for_each_endpoint_scoped(src_sd->fwnode, endpoint) {
struct fwnode_handle *remote_ep;
int src_idx, sink_idx, ret;
struct media_pad *src;
@@ -397,7 +395,6 @@ int v4l2_create_fwnode_links_to_pad(struct v4l2_subdev *src_sd,
src_sd->entity.name, src_idx,
sink->entity->name, sink_idx, ret);
- fwnode_handle_put(endpoint);
return ret;
}
}
--
2.43.0
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related
* [PATCH v2 1/4] device property: Introduce fwnode_graph_for_each_endpoint_scoped()
From: Frank.Li @ 2026-06-24 17:00 UTC (permalink / raw)
To: Andy Shevchenko, Daniel Scally, Heikki Krogerus, Sakari Ailus,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Mauro Carvalho Chehab, Dafna Hirschfeld, Laurent Pinchart,
Heiko Stuebner, Bryan O'Donoghue, Vladimir Zapolskiy,
Loic Poulain
Cc: driver-core, linux-acpi, linux-kernel, linux-media,
linux-rockchip, linux-arm-kernel, linux-arm-msm, imx, Guoniu Zhou,
Frank Li, Guoniu Zhou
In-Reply-To: <20260624-fw_scoped-v2-0-0a8db472af4a@nxp.com>
From: Frank Li <Frank.Li@nxp.com>
Similar to recently propose for_each_child_of_node_scoped() this new
version of the loop macro instantiates a new local struct fwnode_handle *
that uses the __free(fwnode_handle) auto cleanup handling so that if a
reference to a node is held on early exit from the loop the reference will
be released. If the loop runs to completion, the child pointer will be NULL
and no action will be taken.
The reason this is useful is that it removes the need for
fwnode_handle_put() on early loop exits. If there is a need to retain the
reference, then return_ptr(child) or no_free_ptr(child) may be used to
safely disable the auto cleanup.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Guoniu Zhou <guoniu.zhou@oss.nxp.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v2
- collect Andy and Guoniu's reviewed-by tags
- fix indention
- remove extra space in commit message
---
include/linux/property.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/include/linux/property.h b/include/linux/property.h
index 14c304db46648..d51824c13d2cc 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -545,6 +545,11 @@ unsigned int fwnode_graph_get_endpoint_count(const struct fwnode_handle *fwnode,
for (child = fwnode_graph_get_next_endpoint(fwnode, NULL); child; \
child = fwnode_graph_get_next_endpoint(fwnode, child))
+#define fwnode_graph_for_each_endpoint_scoped(fwnode, child) \
+ for (struct fwnode_handle *child __free(fwnode_handle) = \
+ fwnode_graph_get_next_endpoint(fwnode, NULL); \
+ child; child = fwnode_graph_get_next_endpoint(fwnode, child))
+
int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
struct fwnode_endpoint *endpoint);
--
2.43.0
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related
* [PATCH v2 0/4] media: add and use fwnode_graph_for_each_endpoint_scoped()
From: Frank.Li @ 2026-06-24 17:00 UTC (permalink / raw)
To: Andy Shevchenko, Daniel Scally, Heikki Krogerus, Sakari Ailus,
Greg Kroah-Hartman, Rafael J. Wysocki, Danilo Krummrich,
Mauro Carvalho Chehab, Dafna Hirschfeld, Laurent Pinchart,
Heiko Stuebner, Bryan O'Donoghue, Vladimir Zapolskiy,
Loic Poulain
Cc: driver-core, linux-acpi, linux-kernel, linux-media,
linux-rockchip, linux-arm-kernel, linux-arm-msm, imx, Guoniu Zhou,
Frank Li, Guoniu Zhou
Add new helper macro fwnode_graph_for_each_endpoint_scoped() and use it
simplify media code.
Typical example should qualcomm's driver (camss.c), the v4l2_mc.c and
rkisp1-dev.c only silience improvement.
Anyways, *_for_each_*_scoped() already use widely and make code clean.
Build test only.
Sakari Ailus:
when I try to improve the patch
"Add common helper library for 1-to-1 subdev registration", I found need
camss.c pattern, so I create this small improvement firstly.
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Changes in v2:
- colllect review by tags
- fix typo and indent.
- see each patch's change log.
- Link to v1: https://patch.msgid.link/20260622-fw_scoped-v1-0-a37d0aac0a68@nxp.com
---
Frank Li (4):
device property: Introduce fwnode_graph_for_each_endpoint_scoped()
media: mc: use fwnode_graph_for_each_endpoint_scoped() to simpilfy code
media: rkisp1: use fwnode_graph_for_each_endpoint_scoped() to simplify code
media: qcom: camss: use fwnode_graph_for_each_endpoint_scoped() to simplify code
drivers/media/platform/qcom/camss/camss.c | 17 +++++------------
drivers/media/platform/rockchip/rkisp1/rkisp1-dev.c | 4 +---
drivers/media/v4l2-core/v4l2-mc.c | 5 +----
include/linux/property.h | 5 +++++
4 files changed, 12 insertions(+), 19 deletions(-)
---
base-commit: 3ce97bd3c4f18608335e709c24d6a40e7036cab8
change-id: 20260620-fw_scoped-5dab644510a1
Best regards,
--
Frank Li <Frank.Li@nxp.com>
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply
* Re: [PATCH 1/7] dt-bindings: vendor-prefixes: add alientek
From: Conor Dooley @ 2026-06-24 16:38 UTC (permalink / raw)
To: Yanan He
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, David Wu, Maxime Coquelin, Alexandre Torgue,
devicetree, linux-kernel, linux-arm-kernel, linux-rockchip,
netdev, linux-stm32
In-Reply-To: <20260624-rv1126-alientek-dlrv1126-v1-1-5aef608a3f64@gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 75 bytes --]
Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 170 bytes --]
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply
* Re: [PATCH 2/7] dt-bindings: arm: rockchip: Add Alientek DLRV1126
From: Conor Dooley @ 2026-06-24 16:37 UTC (permalink / raw)
To: Yanan He
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, David Wu, Maxime Coquelin, Alexandre Torgue,
devicetree, linux-kernel, linux-arm-kernel, linux-rockchip,
netdev, linux-stm32
In-Reply-To: <20260624-rv1126-alientek-dlrv1126-v1-2-5aef608a3f64@gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 75 bytes --]
Acked-by: Conor Dooley <conor.dooley@microchip.com>
pw-bot: not-applicable
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 170 bytes --]
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply
* Re: [PATCH 3/7] dt-bindings: net: rockchip-dwmac: Allow 9 clocks
From: Conor Dooley @ 2026-06-24 16:37 UTC (permalink / raw)
To: Yanan He
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, David Wu, Maxime Coquelin, Alexandre Torgue,
devicetree, linux-kernel, linux-arm-kernel, linux-rockchip,
netdev, linux-stm32
In-Reply-To: <20260624-rv1126-alientek-dlrv1126-v1-3-5aef608a3f64@gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 64 bytes --]
Per Heiko's comments,
pw-bot: changes-requested
Cheers,
Conor.
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
[-- Attachment #2: Type: text/plain, Size: 170 bytes --]
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply
* Re: [PATCH 7/7] ARM: dts: rockchip: Add Alientek DLRV1126
From: Andrew Lunn @ 2026-06-24 15:44 UTC (permalink / raw)
To: Yanan He
Cc: robh, krzk+dt, conor+dt, heiko, andrew+netdev, davem, edumazet,
kuba, pabeni, david.wu, mcoquelin.stm32, alexandre.torgue,
devicetree, linux-kernel, linux-arm-kernel, linux-rockchip,
netdev, linux-stm32
In-Reply-To: <20260624-rv1126-alientek-dlrv1126-v1-7-dc42d99f75a7@gmail.com>
> The board consists of a CLRV1126F core module and a DLRV1126 carrier
> board. The core module contains the RV1126 SoC, eMMC and RK809 PMIC,
> while the carrier board provides Ethernet, SD card, AP6212 WiFi and
> Bluetooth, PCF8563 RTC, ADC keys, GPIO LEDs and audio connectors.
>
> The board has been tested with Ethernet/NFS boot, eMMC, SD card, SDIO
> WiFi enumeration, Bluetooth LE scanning, RTC, ADC keys, GPIO LEDs and
> RK809 audio card registration.
Ah, here is the networking nodes. But why was it not threaded to the
rest of the series?
> +&gmac {
> + phy-mode = "rgmii";
> + clock_in_out = "input";
> + assigned-clocks = <&cru CLK_GMAC_SRC>, <&cru CLK_GMAC_TX_RX>,
> + <&cru CLK_GMAC_ETHERNET_OUT>;
> + assigned-clock-parents = <&cru CLK_GMAC_SRC_M1>,
> + <&cru RGMII_MODE_CLK>;
> + assigned-clock-rates = <125000000>, <0>, <25000000>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&rgmiim1_miim &rgmiim1_bus2 &rgmiim1_bus4
> + &clk_out_ethernetm1_pins>;
> + tx_delay = <0x2a>;
> + rx_delay = <0x1a>;
As i predicted, this is wrong.
https://elixir.bootlin.com/linux/v6.15/source/Documentation/devicetree/bindings/net/ethernet-controller.yaml#L287
Please try removing rx_delay, rx_delay and setting phy-mode to
rgmii-id.
Andrew
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply
* Re: [PATCH 6/7] ARM: dts: rockchip: Add RV1126 I2C5
From: Andrew Lunn @ 2026-06-24 15:42 UTC (permalink / raw)
To: Yanan He
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, David Wu, Maxime Coquelin, Alexandre Torgue,
devicetree, linux-kernel, linux-arm-kernel, linux-rockchip,
netdev, linux-stm32
In-Reply-To: <20260624-rv1126-alientek-dlrv1126-v1-6-5aef608a3f64@gmail.com>
On Wed, Jun 24, 2026 at 04:44:43PM +0800, Yanan He wrote:
> The controller is present in the SoC and can be used by boards for
> external peripherals, such as an RTC on the Alientek DLRV1126 carrier
> board.
This has nothing to do with networking, so please post it separately.
What i would actually like to see is the patch adding networking
nodes, because my guess is, you have the RGMII delays wrong.
Andrew
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply
* Re: [PATCH 4/7] net: stmmac: dwmac-rk: Enable refout clock for RGMII
From: Andrew Lunn @ 2026-06-24 15:39 UTC (permalink / raw)
To: Yanan He
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner,
Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, David Wu, Maxime Coquelin, Alexandre Torgue,
devicetree, linux-kernel, linux-arm-kernel, linux-rockchip,
netdev, linux-stm32
In-Reply-To: <20260624-rv1126-alientek-dlrv1126-v1-4-5aef608a3f64@gmail.com>
On Wed, Jun 24, 2026 at 04:44:41PM +0800, Yanan He wrote:
> Some Rockchip GMAC integrations use clk_mac_refout as an external PHY
> reference clock even when the MAC is configured for RGMII.
>
> RV1126 boards can route CLK_GMAC_ETHERNET_OUT to the external PHY as a
> 25 MHz reference clock. If the driver does not acquire and enable this
> clock in RGMII mode, the common clock framework may disable it as unused
> and the PHY can lose its reference clock.
>
> Enable the refout clock handling for RGMII in addition to RMII.
>
> Signed-off-by: Yanan He <grumpycat921013@gmail.com>
> ---
> drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> index 8d7042e68926..f6fdc0c5b475 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
> @@ -1112,7 +1112,8 @@ static int rk_gmac_clk_init(struct plat_stmmacenet_data *plat)
> bsp_priv->clk_enabled = false;
>
> bsp_priv->num_clks = ARRAY_SIZE(rk_clocks);
> - if (phy_iface == PHY_INTERFACE_MODE_RMII)
> + if (phy_iface == PHY_INTERFACE_MODE_RMII ||
> + phy_iface == PHY_INTERFACE_MODE_RGMII)
Apart from Heiko commenting that this patch is completely wrong, there
are 4 RGMII modes, not one. You should of used
phy_interface_mode_is_rgmii().
Andrew
---
pw-bot: cr
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply
* Re: [PATCH v1] ASoC: rockchip: rockchip_sai: #include <linux/platform_device.h> explicitly
From: Mark Brown @ 2026-06-24 12:01 UTC (permalink / raw)
To: Nicolas Frattaroli, Liam Girdwood, Jaroslav Kysela, Takashi Iwai,
Uwe Kleine-König (The Capable Hub)
Cc: Heiko Stuebner, linux-rockchip, linux-sound, linux-arm-kernel,
linux-kernel
In-Reply-To: <20260624083708.254517-2-u.kleine-koenig@baylibre.com>
On Wed, 24 Jun 2026 10:37:07 +0200, Uwe Kleine-König (The Capable Hub) wrote:
> ASoC: rockchip: rockchip_sai: #include <linux/platform_device.h> explicitly
Applied to
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-7.2
Thanks!
[1/1] ASoC: rockchip: rockchip_sai: #include <linux/platform_device.h> explicitly
https://git.kernel.org/broonie/sound/c/83d53eca7e55
All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying
to this mail.
Thanks,
Mark
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply
* Re: [PATCH V13 5/9] iio: imu: inv_icm42607: Add PM support for icm42607
From: Jonathan Cameron @ 2026-06-24 15:06 UTC (permalink / raw)
To: Chris Morgan
Cc: Chris Morgan, linux-iio, andy, nuno.sa, dlechner,
jean-baptiste.maneyrol, linux-rockchip, devicetree, heiko,
conor+dt, krzk+dt, robh, andriy.shevchenko
In-Reply-To: <PH0PR19MB99733833C502FDB1FA4927B8DEA5EE2@PH0PR19MB997338.namprd19.prod.outlook.com>
On Tue, 23 Jun 2026 13:08:02 -0500
Chris Morgan <macromorgan@hotmail.com> wrote:
> On Mon, Jun 22, 2026 at 09:34:10PM -0500, Chris Morgan wrote:
> > On Sun, Jun 21, 2026 at 06:19:48PM +0100, Jonathan Cameron wrote:
> > > On Mon, 15 Jun 2026 12:25:48 -0500
> > > Chris Morgan <macroalpha82@gmail.com> wrote:
> > >
> > > > From: Chris Morgan <macromorgan@hotmail.com>
> > > >
> > > > Add power management support for the ICM42607 device driver.
> > > >
> > > > Signed-off-by: Chris Morgan <macromorgan@hotmail.com>
> > > A few things from taking a look at the sashiko report:
> > > https://sashiko.dev/#/patchset/20260615172554.160910-1-macroalpha82%40gmail.com
> > >
> > > > ---
> > > > drivers/iio/imu/inv_icm42607/inv_icm42607.h | 18 +++
> > > > .../iio/imu/inv_icm42607/inv_icm42607_core.c | 139 ++++++++++++++++++
> > > > .../iio/imu/inv_icm42607/inv_icm42607_i2c.c | 1 +
> > > > .../iio/imu/inv_icm42607/inv_icm42607_spi.c | 1 +
> > > > 4 files changed, 159 insertions(+)
> > > >
> > > > diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607.h b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
> > > > index a6a58571935f..4f4f541027dc 100644
> > > > --- a/drivers/iio/imu/inv_icm42607/inv_icm42607.h
> > > > +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607.h
> > >
> > > > @@ -334,11 +345,18 @@ struct inv_icm42607_state {
> > > > #define INV_ICM42607_GYRO_STOP_TIME_MS 45
> > > > #define INV_ICM42607_TEMP_STARTUP_TIME_MS 77
> > > >
> > > > +/*
> > > > + * Suspend delay assumed from other icm42600 series device, not
> > > > + * documented in datasheet.
> > > > + */
> > > > +#define INV_ICM42607_SUSPEND_DELAY_MS (2 * USEC_PER_MSEC)
> > >
> > > Sashiko had a valid comment on this. MSEC_PER_SEC seems more
> > > appropriate given this is 2 seconds in milli seconds.
> > >
> > > > +
> > > > 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 4b8e19091786..64f5d263de4f 100644
> > > > --- a/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
> > > > +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_core.c
> > > > @@ -4,6 +4,7 @@
> > > > */
> > > >
> > > > #include <linux/bitfield.h>
> > > > +#include <linux/cleanup.h>
> > > > #include <linux/delay.h>
> > > > #include <linux/dev_printk.h>
> > > > #include <linux/device/devres.h>
> > > > @@ -11,6 +12,7 @@
> > > > #include <linux/iio/iio.h>
> > > > #include <linux/module.h>
> > > > #include <linux/mutex.h>
> > > > +#include <linux/pm_runtime.h>
> > > > #include <linux/regmap.h>
> > > > #include <linux/regulator/consumer.h>
> > > > #include <linux/time.h>
> > > > @@ -103,6 +105,63 @@ const struct inv_icm42607_hw inv_icm42607p_hw_data = {
> > > > };
> > > > EXPORT_SYMBOL_NS_GPL(inv_icm42607p_hw_data, "IIO_ICM42607");
> > > >
> > > > +static int inv_icm42607_set_pwr_mgmt0(struct inv_icm42607_state *st,
> > > > + enum inv_icm42607_sensor_mode gyro,
> > > > + enum inv_icm42607_sensor_mode accel,
> > > > + bool temp, unsigned int *sleep_ms)
> > > > +{
> > > > + enum inv_icm42607_sensor_mode oldaccel = st->conf.accel.mode;
> > > > + enum inv_icm42607_sensor_mode oldgyro = st->conf.gyro.mode;
> > > > + bool oldtemp = st->conf.temp_en;
> > > > + unsigned int sleepval_ms;
> > > > + unsigned int val;
> > > > + int ret;
> > > > +
> > > > + if (gyro == oldgyro && accel == oldaccel && temp == oldtemp)
> > > > + return 0;
> > > > +
> > > > + /*
> > > > + * Datasheet on page 14.26 says we need to ensure the gyro sensor is on
> > > > + * for a minimum of 45ms. So if we transition from an on state to an
> > > > + * off state wait 45ms to ensure a sufficient pause before power off.
> > >
> > > Sashiko commented on this.. I think what we could do with adding to the
> > > comment is what the path is that didn't pass through this function which would
> > > ensure we have been on for 30 of this msecs already.
> >
> > I'm going to track whatever time the gyro started, and then if less
> > than 45ms has elapsed just pause the remaining amount of time.
> >
> > >
> > > > + */
> > > > + if (!gyro && oldgyro)
> > > > + fsleep(INV_ICM42607_GYRO_STOP_TIME_MS * USEC_PER_MSEC);
> > > > +
> > > > + val = FIELD_PREP(INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK, gyro);
> > > > + val |= FIELD_PREP(INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK, accel);
> > > > + ret = regmap_write(st->map, INV_ICM42607_REG_PWR_MGMT0, val);
> > > > + if (ret)
> > > > + return ret;
> > > > +
> > > > + st->conf.gyro.mode = gyro;
> > > > + st->conf.accel.mode = accel;
> > > > + st->conf.temp_en = temp;
> > > > +
> > > > + /*
> > > > + * If a state change occurs from off to on, sleep for the startup
> > > > + * time of the sensor, unless a sleep_ms is specified. Since more
> > > > + * than one sensor can be transitioned from off to on, select the
> > > > + * maximum time from each of the sensors changing from off to on.
> > > > + */
> > > > + sleepval_ms = 0;
> > > > + if (temp && !oldtemp)
> > > > + sleepval_ms = max(sleepval_ms, INV_ICM42607_TEMP_STARTUP_TIME_MS);
> > > > +
> > > > + if (accel && !oldaccel)
> > > > + sleepval_ms = max(sleepval_ms, INV_ICM42607_ACCEL_STARTUP_TIME_MS);
> > > > +
> > > > + if (gyro && !oldgyro)
> > > > + sleepval_ms = max(sleepval_ms, INV_ICM42607_GYRO_STARTUP_TIME_MS);
> > > > +
> > > > + if (sleep_ms)
> > > > + *sleep_ms = sleepval_ms;
> > > > + else if (sleepval_ms)
> > > > + fsleep(sleepval_ms * USEC_PER_MSEC);
> > > > +
> > > > + return 0;
> > > > +}
> > >
> > > >
> > > > int inv_icm42607_core_probe(struct regmap *regmap,
> > > > @@ -236,6 +305,8 @@ int inv_icm42607_core_probe(struct regmap *regmap,
> > > > if (!st)
> > > > return -ENOMEM;
> > > >
> > > > + dev_set_drvdata(dev, st);
> > > > +
> > > > ret = devm_mutex_init(dev, &st->lock);
> > > > if (ret)
> > > > return ret;
> > > > @@ -271,10 +342,78 @@ int inv_icm42607_core_probe(struct regmap *regmap,
> > > > if (ret)
> > > > return ret;
> > > >
> > > > + ret = devm_pm_runtime_set_active_enabled(dev);
> > > > + if (ret)
> > > > + return ret;
> > > > +
> > > > + pm_runtime_set_autosuspend_delay(dev, INV_ICM42607_SUSPEND_DELAY_MS);
> > > > + pm_runtime_use_autosuspend(dev);
> > > Sashiko does put out some stuff here. Please take a look and work out or
> > > test if it is right (I think not but haven't checked that carefully!)
> > > From a quick look I think that the auto disabling of autosuspend does a
> > > rpm_idle() that should result in it suspending...
> > >
> >
> > I see a few other drivers adding one more call to
> > devm_pm_runtime_enable() so I'm going to see how that works out.
>
> Obviously that didn't work, but digging in much deeper into the PM code
> I see that devm_pm_runtime_set_active_enabled() returns
> devm_pm_runtime_enable(), which sets devm_add_action_or_reset() on
> pm_runtime_disable_action(), which calls
> pm_runtime_dont_use_autosuspend() and pm_runtime_disable(). Shouldn't
> this work, or am I missing something? Basically when the driver
> detaches shouldn't this chain end up calling
> pm_runtime_dont_use_autosuspend()?
Agreed. That was how I read things. The only thing I didn't entirely
confirm (states involved were fiddly enough I'd want to check it
with the actual driver!) was that pm_runtime_dont_use_autosuspend()
ends up calling rpm_idle() in this case.
Jonathan
>
> Thank you,
> Chris
>
> >
> > >
> > > > +
> > > > return 0;
> > > > }
> > > > EXPORT_SYMBOL_NS_GPL(inv_icm42607_core_probe, "IIO_ICM42607");
> >
> > Thank you,
> > Chris
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply
* Re: (subset) [PATCH v7 00/30] Add HDMI 2.0 support to DW HDMI QP TX
From: Luca Ceresoli @ 2026-06-24 14:08 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Sandy Huang,
Heiko Stübner, Andy Yan, Daniel Stone, Dave Stevenson,
Maíra Canal, Raspberry Pi Kernel Maintenance,
Cristian Ciocaltea
Cc: kernel, dri-devel, linux-kernel, linux-arm-kernel, linux-rockchip,
Dmitry Baryshkov, Diederik de Haas, Maud Spierings
In-Reply-To: <20260602-dw-hdmi-qp-scramb-v7-0-445eb54ee1ed@collabora.com>
On Tue, 02 Jun 2026 01:44:00 +0300, Cristian Ciocaltea wrote:
> Enable HDMI 2.0 display modes (e.g. 4K@60Hz) on the Synopsys DW HDMI QP
> TX controller, as found in Rockchip RK3576 & RK3588 SoCs, by adding SCDC
> management for high TMDS clock ratio and scrambling.
>
> Since SCDC state is lost on sink disconnects, the bridge driver needs to
> trigger a CRTC reset during connector detection. To support this, the
> series introduces the connector and bridge scrambling infrastructure
> (patches 1-8), wires it up through the bridge connector layer with an
> atomic-aware detect_ctx hook (patches 9-11), then implements the SCDC
> scrambling feature in the DW HDMI QP bridge driver (patches 12-15).
>
> [...]
Applied, thanks!
[01/30] drm/fb-helper: Remove unused local variable in hotplug_event()
commit: cdeb2ccd993ed8647adbbda2c3b103aa717fd6f7
Best regards,
--
Luca Ceresoli, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply
* Re: [PATCH] clk: rockchip: rk3588: don't disable unused I2S MCLK output gates
From: Sebastian Reichel @ 2026-06-24 13:42 UTC (permalink / raw)
To: Daniele Briguglio
Cc: Michael Turquette, Stephen Boyd, Heiko Stuebner, linux-clk,
linux-arm-kernel, linux-rockchip, linux-kernel, Diederik de Haas,
Nicolas Frattaroli, Ricardo Pardini
In-Reply-To: <20260624123914.1767374-1-hello@superkali.me>
[-- Attachment #1.1: Type: text/plain, Size: 3905 bytes --]
Hi,
On Wed, Jun 24, 2026 at 02:39:14PM +0200, Daniele Briguglio wrote:
> No in-tree board references these gates yet. Boards drive the codec
> MCLK through the parent I2S*_8CH_MCLKOUT, and now that the gates are
> managed clocks, clk_disable_unused() turns them off at boot. On a board
> that relied on firmware leaving the output enabled, that cuts the MCLK
> and analog audio stops working.
>
> Mark the four gates CLK_IGNORE_UNUSED so an unreferenced gate keeps the
> state firmware left. A board that wants the kernel to own the gate can
> reference I2S*_8CH_MCLKOUT_TO_IO from DT instead.
>
> Fixes: 02b9b0bb6269 ("clk: rockchip: rk3588: add GATE_GRF clocks for I2S MCLK output to IO")
> Reported-by: Diederik de Haas <diederik@cknow-tech.com>
> Closes: https://lore.kernel.org/linux-rockchip/DJGDSS875DDO.22TYPVYK5X8KZ@cknow-tech.com/
> Tested-by: Diederik de Haas <diederik@cknow-tech.com>
> Signed-off-by: Daniele Briguglio <hello@superkali.me>
> ---
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Greetings,
-- Sebastian
> drivers/clk/rockchip/clk-rk3588.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c
> index 2ba9976654c..86953f9ffee 100644
> --- a/drivers/clk/rockchip/clk-rk3588.c
> +++ b/drivers/clk/rockchip/clk-rk3588.c
> @@ -895,7 +895,7 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
> MUX(I2S2_2CH_MCLKOUT, "i2s2_2ch_mclkout", i2s2_2ch_mclkout_p, CLK_SET_RATE_PARENT,
> RK3588_CLKSEL_CON(30), 2, 1, MFLAGS),
> GATE_GRF(I2S2_2CH_MCLKOUT_TO_IO, "i2s2_2ch_mclkout_to_io", "i2s2_2ch_mclkout",
> - 0, RK3588_SYSGRF_SOC_CON6, 2, GFLAGS, grf_type_sys),
> + CLK_IGNORE_UNUSED, RK3588_SYSGRF_SOC_CON6, 2, GFLAGS, grf_type_sys),
>
> COMPOSITE(CLK_I2S3_2CH_SRC, "clk_i2s3_2ch_src", gpll_aupll_p, 0,
> RK3588_CLKSEL_CON(30), 8, 1, MFLAGS, 3, 5, DFLAGS,
> @@ -912,7 +912,7 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
> MUX(I2S3_2CH_MCLKOUT, "i2s3_2ch_mclkout", i2s3_2ch_mclkout_p, CLK_SET_RATE_PARENT,
> RK3588_CLKSEL_CON(32), 2, 1, MFLAGS),
> GATE_GRF(I2S3_2CH_MCLKOUT_TO_IO, "i2s3_2ch_mclkout_to_io", "i2s3_2ch_mclkout",
> - 0, RK3588_SYSGRF_SOC_CON6, 7, GFLAGS, grf_type_sys),
> + CLK_IGNORE_UNUSED, RK3588_SYSGRF_SOC_CON6, 7, GFLAGS, grf_type_sys),
> GATE(PCLK_ACDCDIG, "pclk_acdcdig", "pclk_audio_root", 0,
> RK3588_CLKGATE_CON(7), 11, GFLAGS),
> GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_audio_root", 0,
> @@ -942,7 +942,7 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
> MUX(I2S0_8CH_MCLKOUT, "i2s0_8ch_mclkout", i2s0_8ch_mclkout_p, CLK_SET_RATE_PARENT,
> RK3588_CLKSEL_CON(28), 2, 2, MFLAGS),
> GATE_GRF(I2S0_8CH_MCLKOUT_TO_IO, "i2s0_8ch_mclkout_to_io", "i2s0_8ch_mclkout",
> - 0, RK3588_SYSGRF_SOC_CON6, 0, GFLAGS, grf_type_sys),
> + CLK_IGNORE_UNUSED, RK3588_SYSGRF_SOC_CON6, 0, GFLAGS, grf_type_sys),
>
> GATE(HCLK_PDM1, "hclk_pdm1", "hclk_audio_root", 0,
> RK3588_CLKGATE_CON(9), 6, GFLAGS),
> @@ -2229,7 +2229,7 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
> MUX(I2S1_8CH_MCLKOUT, "i2s1_8ch_mclkout", i2s1_8ch_mclkout_p, CLK_SET_RATE_PARENT,
> RK3588_PMU_CLKSEL_CON(9), 2, 2, MFLAGS),
> GATE_GRF(I2S1_8CH_MCLKOUT_TO_IO, "i2s1_8ch_mclkout_to_io", "i2s1_8ch_mclkout",
> - 0, RK3588_SYSGRF_SOC_CON6, 1, GFLAGS, grf_type_sys),
> + CLK_IGNORE_UNUSED, RK3588_SYSGRF_SOC_CON6, 1, GFLAGS, grf_type_sys),
> GATE(PCLK_PMU1, "pclk_pmu1", "pclk_pmu0_root", CLK_IS_CRITICAL,
> RK3588_PMU_CLKGATE_CON(1), 0, GFLAGS),
> GATE(CLK_DDR_FAIL_SAFE, "clk_ddr_fail_safe", "clk_pmu0", CLK_IGNORE_UNUSED,
>
> base-commit: 7edfb7fb58ee058298e18fde76a6077ef17d19d8
> --
> 2.47.3
>
>
[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
[-- Attachment #2: Type: text/plain, Size: 170 bytes --]
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply
* [PATCH] clk: rockchip: rk3588: don't disable unused I2S MCLK output gates
From: Daniele Briguglio @ 2026-06-24 12:39 UTC (permalink / raw)
To: Michael Turquette, Stephen Boyd, Heiko Stuebner
Cc: linux-clk, linux-arm-kernel, linux-rockchip, linux-kernel,
Diederik de Haas, Nicolas Frattaroli, Ricardo Pardini
No in-tree board references these gates yet. Boards drive the codec
MCLK through the parent I2S*_8CH_MCLKOUT, and now that the gates are
managed clocks, clk_disable_unused() turns them off at boot. On a board
that relied on firmware leaving the output enabled, that cuts the MCLK
and analog audio stops working.
Mark the four gates CLK_IGNORE_UNUSED so an unreferenced gate keeps the
state firmware left. A board that wants the kernel to own the gate can
reference I2S*_8CH_MCLKOUT_TO_IO from DT instead.
Fixes: 02b9b0bb6269 ("clk: rockchip: rk3588: add GATE_GRF clocks for I2S MCLK output to IO")
Reported-by: Diederik de Haas <diederik@cknow-tech.com>
Closes: https://lore.kernel.org/linux-rockchip/DJGDSS875DDO.22TYPVYK5X8KZ@cknow-tech.com/
Tested-by: Diederik de Haas <diederik@cknow-tech.com>
Signed-off-by: Daniele Briguglio <hello@superkali.me>
---
drivers/clk/rockchip/clk-rk3588.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c
index 2ba9976654c..86953f9ffee 100644
--- a/drivers/clk/rockchip/clk-rk3588.c
+++ b/drivers/clk/rockchip/clk-rk3588.c
@@ -895,7 +895,7 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
MUX(I2S2_2CH_MCLKOUT, "i2s2_2ch_mclkout", i2s2_2ch_mclkout_p, CLK_SET_RATE_PARENT,
RK3588_CLKSEL_CON(30), 2, 1, MFLAGS),
GATE_GRF(I2S2_2CH_MCLKOUT_TO_IO, "i2s2_2ch_mclkout_to_io", "i2s2_2ch_mclkout",
- 0, RK3588_SYSGRF_SOC_CON6, 2, GFLAGS, grf_type_sys),
+ CLK_IGNORE_UNUSED, RK3588_SYSGRF_SOC_CON6, 2, GFLAGS, grf_type_sys),
COMPOSITE(CLK_I2S3_2CH_SRC, "clk_i2s3_2ch_src", gpll_aupll_p, 0,
RK3588_CLKSEL_CON(30), 8, 1, MFLAGS, 3, 5, DFLAGS,
@@ -912,7 +912,7 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
MUX(I2S3_2CH_MCLKOUT, "i2s3_2ch_mclkout", i2s3_2ch_mclkout_p, CLK_SET_RATE_PARENT,
RK3588_CLKSEL_CON(32), 2, 1, MFLAGS),
GATE_GRF(I2S3_2CH_MCLKOUT_TO_IO, "i2s3_2ch_mclkout_to_io", "i2s3_2ch_mclkout",
- 0, RK3588_SYSGRF_SOC_CON6, 7, GFLAGS, grf_type_sys),
+ CLK_IGNORE_UNUSED, RK3588_SYSGRF_SOC_CON6, 7, GFLAGS, grf_type_sys),
GATE(PCLK_ACDCDIG, "pclk_acdcdig", "pclk_audio_root", 0,
RK3588_CLKGATE_CON(7), 11, GFLAGS),
GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_audio_root", 0,
@@ -942,7 +942,7 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
MUX(I2S0_8CH_MCLKOUT, "i2s0_8ch_mclkout", i2s0_8ch_mclkout_p, CLK_SET_RATE_PARENT,
RK3588_CLKSEL_CON(28), 2, 2, MFLAGS),
GATE_GRF(I2S0_8CH_MCLKOUT_TO_IO, "i2s0_8ch_mclkout_to_io", "i2s0_8ch_mclkout",
- 0, RK3588_SYSGRF_SOC_CON6, 0, GFLAGS, grf_type_sys),
+ CLK_IGNORE_UNUSED, RK3588_SYSGRF_SOC_CON6, 0, GFLAGS, grf_type_sys),
GATE(HCLK_PDM1, "hclk_pdm1", "hclk_audio_root", 0,
RK3588_CLKGATE_CON(9), 6, GFLAGS),
@@ -2229,7 +2229,7 @@ static struct rockchip_clk_branch rk3588_early_clk_branches[] __initdata = {
MUX(I2S1_8CH_MCLKOUT, "i2s1_8ch_mclkout", i2s1_8ch_mclkout_p, CLK_SET_RATE_PARENT,
RK3588_PMU_CLKSEL_CON(9), 2, 2, MFLAGS),
GATE_GRF(I2S1_8CH_MCLKOUT_TO_IO, "i2s1_8ch_mclkout_to_io", "i2s1_8ch_mclkout",
- 0, RK3588_SYSGRF_SOC_CON6, 1, GFLAGS, grf_type_sys),
+ CLK_IGNORE_UNUSED, RK3588_SYSGRF_SOC_CON6, 1, GFLAGS, grf_type_sys),
GATE(PCLK_PMU1, "pclk_pmu1", "pclk_pmu0_root", CLK_IS_CRITICAL,
RK3588_PMU_CLKGATE_CON(1), 0, GFLAGS),
GATE(CLK_DDR_FAIL_SAFE, "clk_ddr_fail_safe", "clk_pmu0", CLK_IGNORE_UNUSED,
base-commit: 7edfb7fb58ee058298e18fde76a6077ef17d19d8
--
2.47.3
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ permalink raw reply related
* Re: [PATCH v4 5/5] clk: rockchip: rk3588: add GATE_GRF clocks for I2S MCLK output to IO
From: Daniele Briguglio @ 2026-06-24 12:20 UTC (permalink / raw)
To: Heiko Stuebner, Diederik de Haas, Michael Turquette, Stephen Boyd,
Rob Herring, Krzysztof Kozlowski, Conor Dooley
Cc: Nicolas Frattaroli, linux-clk, devicetree, linux-arm-kernel,
linux-rockchip, linux-kernel, Ricardo Pardini
In-Reply-To: <2008560.6tgchFWduM@diego>
Hi Heiko,
> Care to send a patch for that change? :-)
Will do. I was only waiting for your call on the approach before sending,
so I'll get it out shortly.
Best regards,
Daniele
_______________________________________________
Linux-rockchip mailing list
Linux-rockchip@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-rockchip
^ 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