From: Remi Buisson <remi.buisson@tdk.com>
Add I2C driver for InvenSense ICM-456000 devices.
Signed-off-by: Remi Buisson <remi.buisson@tdk.com>
---
drivers/iio/imu/inv_icm45600/Kconfig | 21 ++++++
drivers/iio/imu/inv_icm45600/Makefile | 3 +
drivers/iio/imu/inv_icm45600/inv_icm45600_i2c.c | 98 +++++++++++++++++++++++++
3 files changed, 122 insertions(+)
diff --git a/drivers/iio/imu/inv_icm45600/Kconfig b/drivers/iio/imu/inv_icm45600/Kconfig
index ea0a8d20cba26549b74105fa6fdbca1ddb222633..5b044a954e952ffa8e44507eea42872e1f3161bc 100644
--- a/drivers/iio/imu/inv_icm45600/Kconfig
+++ b/drivers/iio/imu/inv_icm45600/Kconfig
@@ -5,3 +5,24 @@ config INV_ICM45600
select IIO_BUFFER
select IIO_KFIFO_BUF
select IIO_INV_SENSORS_TIMESTAMP
+
+config INV_ICM45600_I2C
+ tristate "InvenSense ICM-456xx I2C driver"
+ depends on I2C
+ select INV_ICM45600
+ select REGMAP_I2C
+ help
+ This driver supports the InvenSense ICM-456xx motion tracking
+ devices over I2C.
+ Supported devices:
+ - ICM-45605
+ - ICM-45606
+ - ICM-45608
+ - ICM-45634
+ - ICM-45686
+ - ICM-45687
+ - ICM-45688-P
+ - ICM-45689
+
+ This driver can be built as a module. The module will be called
+ inv-icm45600-i2c.
diff --git a/drivers/iio/imu/inv_icm45600/Makefile b/drivers/iio/imu/inv_icm45600/Makefile
index e34553d2b74dc46bb0f533d2bd0875655f91c781..c43e5d6ad3a2ddbd666d77630015c440e740d969 100644
--- a/drivers/iio/imu/inv_icm45600/Makefile
+++ b/drivers/iio/imu/inv_icm45600/Makefile
@@ -5,3 +5,6 @@ inv-icm45600-y += inv_icm45600_core.o
inv-icm45600-y += inv_icm45600_buffer.o
inv-icm45600-y += inv_icm45600_gyro.o
inv-icm45600-y += inv_icm45600_accel.o
+
+obj-$(CONFIG_INV_ICM45600_I2C) += inv-icm45600-i2c.o
+inv-icm45600-i2c-y += inv_icm45600_i2c.o
diff --git a/drivers/iio/imu/inv_icm45600/inv_icm45600_i2c.c b/drivers/iio/imu/inv_icm45600/inv_icm45600_i2c.c
new file mode 100644
index 0000000000000000000000000000000000000000..5ebc18121a11f8ad576efb4d4cf80091c13af31d
--- /dev/null
+++ b/drivers/iio/imu/inv_icm45600/inv_icm45600_i2c.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* Copyright (C) 2025 InvenSense, Inc. */
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regmap.h>
+
+#include "inv_icm45600.h"
+
+static const struct regmap_config inv_icm45600_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int inv_icm45600_probe(struct i2c_client *client)
+{
+ const struct inv_icm45600_chip_info *chip_info;
+ struct regmap *regmap;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
+ return -ENODEV;
+
+ chip_info = device_get_match_data(&client->dev);
+ if (!chip_info)
+ return -ENODEV;
+
+ regmap = devm_regmap_init_i2c(client, &inv_icm45600_regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return inv_icm45600_core_probe(regmap, chip_info, true, NULL);
+}
+
+/*
+ * The device id table is used to identify which device is
+ * supported by this driver.
+ */
+static const struct i2c_device_id inv_icm45600_id[] = {
+ { "icm45605", (kernel_ulong_t)&inv_icm45605_chip_info },
+ { "icm45606", (kernel_ulong_t)&inv_icm45606_chip_info },
+ { "icm45608", (kernel_ulong_t)&inv_icm45608_chip_info },
+ { "icm45634", (kernel_ulong_t)&inv_icm45634_chip_info },
+ { "icm45686", (kernel_ulong_t)&inv_icm45686_chip_info },
+ { "icm45687", (kernel_ulong_t)&inv_icm45687_chip_info },
+ { "icm45688p", (kernel_ulong_t)&inv_icm45688p_chip_info },
+ { "icm45689", (kernel_ulong_t)&inv_icm45689_chip_info },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, inv_icm45600_id);
+
+static const struct of_device_id inv_icm45600_of_matches[] = {
+ {
+ .compatible = "invensense,icm45605",
+ .data = &inv_icm45605_chip_info,
+ }, {
+ .compatible = "invensense,icm45606",
+ .data = &inv_icm45606_chip_info,
+ }, {
+ .compatible = "invensense,icm45608",
+ .data = &inv_icm45608_chip_info,
+ }, {
+ .compatible = "invensense,icm45634",
+ .data = &inv_icm45634_chip_info,
+ }, {
+ .compatible = "invensense,icm45686",
+ .data = &inv_icm45686_chip_info,
+ }, {
+ .compatible = "invensense,icm45687",
+ .data = &inv_icm45687_chip_info,
+ }, {
+ .compatible = "invensense,icm45688p",
+ .data = &inv_icm45688p_chip_info,
+ }, {
+ .compatible = "invensense,icm45689",
+ .data = &inv_icm45689_chip_info,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, inv_icm45600_of_matches);
+
+static struct i2c_driver inv_icm45600_driver = {
+ .driver = {
+ .name = "inv-icm45600-i2c",
+ .of_match_table = inv_icm45600_of_matches,
+ .pm = pm_ptr(&inv_icm45600_pm_ops),
+ },
+ .id_table = inv_icm45600_id,
+ .probe = inv_icm45600_probe,
+};
+module_i2c_driver(inv_icm45600_driver);
+
+MODULE_AUTHOR("InvenSense, Inc.");
+MODULE_DESCRIPTION("InvenSense ICM-456xx I2C driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_ICM45600");
--
2.34.1
Hi Remi,
kernel test robot noticed the following build warnings:
[auto build test WARNING on f8f559752d573a051a984adda8d2d1464f92f954]
url: https://github.com/intel-lab-lkp/linux/commits/Remi-Buisson-via-B4-Relay/dt-bindings-iio-imu-Add-inv_icm45600/20250814-170722
base: f8f559752d573a051a984adda8d2d1464f92f954
patch link: https://lore.kernel.org/r/20250814-add_newport_driver-v4-6-4464b6600972%40tdk.com
patch subject: [PATCH v4 6/9] iio: imu: inv_icm45600: add I2C driver for inv_icm45600 driver
config: s390-allmodconfig (https://download.01.org/0day-ci/archive/20250815/202508151941.BweGaEVT-lkp@intel.com/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250815/202508151941.BweGaEVT-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202508151941.BweGaEVT-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/iio/imu/inv_icm45600/inv_icm45600_core.c:908:12: warning: result of comparison of constant 32768 with expression of type 's16' (aka 'short') is always false [-Wtautological-constant-out-of-range-compare]
908 | if (*temp == INV_ICM45600_DATA_INVALID)
| ~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iio/imu/inv_icm45600/inv_icm45600_core.c:785:12: warning: unused function 'inv_icm45600_suspend' [-Wunused-function]
785 | static int inv_icm45600_suspend(struct device *dev)
| ^~~~~~~~~~~~~~~~~~~~
drivers/iio/imu/inv_icm45600/inv_icm45600_core.c:820:12: warning: unused function 'inv_icm45600_resume' [-Wunused-function]
820 | static int inv_icm45600_resume(struct device *dev)
| ^~~~~~~~~~~~~~~~~~~
drivers/iio/imu/inv_icm45600/inv_icm45600_core.c:860:12: warning: unused function 'inv_icm45600_runtime_suspend' [-Wunused-function]
860 | static int inv_icm45600_runtime_suspend(struct device *dev)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/iio/imu/inv_icm45600/inv_icm45600_core.c:879:12: warning: unused function 'inv_icm45600_runtime_resume' [-Wunused-function]
879 | static int inv_icm45600_runtime_resume(struct device *dev)
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
5 warnings generated.
vim +908 drivers/iio/imu/inv_icm45600/inv_icm45600_core.c
8891b99381240f Remi Buisson 2025-08-14 887
2570c7e48ace35 Remi Buisson 2025-08-14 888 static int _inv_icm45600_temp_read(struct inv_icm45600_state *st, s16 *temp)
2570c7e48ace35 Remi Buisson 2025-08-14 889 {
2570c7e48ace35 Remi Buisson 2025-08-14 890 struct inv_icm45600_sensor_conf conf = INV_ICM45600_SENSOR_CONF_KEEP_VALUES;
2570c7e48ace35 Remi Buisson 2025-08-14 891 int ret;
2570c7e48ace35 Remi Buisson 2025-08-14 892
2570c7e48ace35 Remi Buisson 2025-08-14 893 /* Make sure a sensor is on. */
2570c7e48ace35 Remi Buisson 2025-08-14 894 if (st->conf.gyro.mode == INV_ICM45600_SENSOR_MODE_OFF &&
2570c7e48ace35 Remi Buisson 2025-08-14 895 st->conf.accel.mode == INV_ICM45600_SENSOR_MODE_OFF) {
2570c7e48ace35 Remi Buisson 2025-08-14 896 conf.mode = INV_ICM45600_SENSOR_MODE_LOW_POWER;
2570c7e48ace35 Remi Buisson 2025-08-14 897 ret = inv_icm45600_set_accel_conf(st, &conf, NULL);
2570c7e48ace35 Remi Buisson 2025-08-14 898 if (ret)
2570c7e48ace35 Remi Buisson 2025-08-14 899 return ret;
2570c7e48ace35 Remi Buisson 2025-08-14 900 }
2570c7e48ace35 Remi Buisson 2025-08-14 901
2570c7e48ace35 Remi Buisson 2025-08-14 902 ret = regmap_bulk_read(st->map, INV_ICM45600_REG_TEMP_DATA,
2570c7e48ace35 Remi Buisson 2025-08-14 903 &st->buffer.u16, sizeof(st->buffer.u16));
2570c7e48ace35 Remi Buisson 2025-08-14 904 if (ret)
2570c7e48ace35 Remi Buisson 2025-08-14 905 return ret;
2570c7e48ace35 Remi Buisson 2025-08-14 906
2570c7e48ace35 Remi Buisson 2025-08-14 907 *temp = (s16)le16_to_cpup(&st->buffer.u16);
2570c7e48ace35 Remi Buisson 2025-08-14 @908 if (*temp == INV_ICM45600_DATA_INVALID)
2570c7e48ace35 Remi Buisson 2025-08-14 909 return -EINVAL;
2570c7e48ace35 Remi Buisson 2025-08-14 910
2570c7e48ace35 Remi Buisson 2025-08-14 911 return 0;
2570c7e48ace35 Remi Buisson 2025-08-14 912 }
2570c7e48ace35 Remi Buisson 2025-08-14 913
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
On Fri, 15 Aug 2025 19:31:38 +0800
kernel test robot <lkp@intel.com> wrote:
> Hi Remi,
>
> kernel test robot noticed the following build warnings:
>
> [auto build test WARNING on f8f559752d573a051a984adda8d2d1464f92f954]
>
> url: https://github.com/intel-lab-lkp/linux/commits/Remi-Buisson-via-B4-Relay/dt-bindings-iio-imu-Add-inv_icm45600/20250814-170722
> base: f8f559752d573a051a984adda8d2d1464f92f954
> patch link: https://lore.kernel.org/r/20250814-add_newport_driver-v4-6-4464b6600972%40tdk.com
> patch subject: [PATCH v4 6/9] iio: imu: inv_icm45600: add I2C driver for inv_icm45600 driver
> config: s390-allmodconfig (https://download.01.org/0day-ci/archive/20250815/202508151941.BweGaEVT-lkp@intel.com/config)
> compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250815/202508151941.BweGaEVT-lkp@intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202508151941.BweGaEVT-lkp@intel.com/
>
> All warnings (new ones prefixed by >>):
>
> >> drivers/iio/imu/inv_icm45600/inv_icm45600_core.c:908:12: warning: result of comparison of constant 32768 with expression of type 's16' (aka 'short') is always false [-Wtautological-constant-out-of-range-compare]
> 908 | if (*temp == INV_ICM45600_DATA_INVALID)
> | ~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~
That one will need fixing up.
> drivers/iio/imu/inv_icm45600/inv_icm45600_core.c:785:12: warning: unused function 'inv_icm45600_suspend' [-Wunused-function]
> 785 | static int inv_icm45600_suspend(struct device *dev)
> | ^~~~~~~~~~~~~~~~~~~~
These too me a minute. You have the deprecated functions for actually filling in
+EXPORT_NS_GPL_DEV_PM_OPS(inv_icm45600_pm_ops, IIO_ICM45600) = {
+ SET_SYSTEM_SLEEP_PM_OPS(inv_icm45600_suspend, inv_icm45600_resume)
+ SET_RUNTIME_PM_OPS(inv_icm45600_runtime_suspend,
+ inv_icm45600_runtime_resume, NULL)
+};
+
should be
+EXPORT_NS_GPL_DEV_PM_OPS(inv_icm45600_pm_ops, IIO_ICM45600) = {
+ SYSTEM_SLEEP_PM_OPS(inv_icm45600_suspend, inv_icm45600_resume)
+ RUNTIME_PM_OPS(inv_icm45600_runtime_suspend,
+ inv_icm45600_runtime_resume, NULL)
+};
+
Or use _DEFINE_DEV_PM_OPS() to set all this.
> drivers/iio/imu/inv_icm45600/inv_icm45600_core.c:820:12: warning: unused function 'inv_icm45600_resume' [-Wunused-function]
> 820 | static int inv_icm45600_resume(struct device *dev)
> | ^~~~~~~~~~~~~~~~~~~
> drivers/iio/imu/inv_icm45600/inv_icm45600_core.c:860:12: warning: unused function 'inv_icm45600_runtime_suspend' [-Wunused-function]
> 860 | static int inv_icm45600_runtime_suspend(struct device *dev)
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
> drivers/iio/imu/inv_icm45600/inv_icm45600_core.c:879:12: warning: unused function 'inv_icm45600_runtime_resume' [-Wunused-function]
> 879 | static int inv_icm45600_runtime_resume(struct device *dev)
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~
> 5 warnings generated.
>
>
> vim +908 drivers/iio/imu/inv_icm45600/inv_icm45600_core.c
>
> 8891b99381240f Remi Buisson 2025-08-14 887
> 2570c7e48ace35 Remi Buisson 2025-08-14 888 static int _inv_icm45600_temp_read(struct inv_icm45600_state *st, s16 *temp)
> 2570c7e48ace35 Remi Buisson 2025-08-14 889 {
> 2570c7e48ace35 Remi Buisson 2025-08-14 890 struct inv_icm45600_sensor_conf conf = INV_ICM45600_SENSOR_CONF_KEEP_VALUES;
> 2570c7e48ace35 Remi Buisson 2025-08-14 891 int ret;
> 2570c7e48ace35 Remi Buisson 2025-08-14 892
> 2570c7e48ace35 Remi Buisson 2025-08-14 893 /* Make sure a sensor is on. */
> 2570c7e48ace35 Remi Buisson 2025-08-14 894 if (st->conf.gyro.mode == INV_ICM45600_SENSOR_MODE_OFF &&
> 2570c7e48ace35 Remi Buisson 2025-08-14 895 st->conf.accel.mode == INV_ICM45600_SENSOR_MODE_OFF) {
> 2570c7e48ace35 Remi Buisson 2025-08-14 896 conf.mode = INV_ICM45600_SENSOR_MODE_LOW_POWER;
> 2570c7e48ace35 Remi Buisson 2025-08-14 897 ret = inv_icm45600_set_accel_conf(st, &conf, NULL);
> 2570c7e48ace35 Remi Buisson 2025-08-14 898 if (ret)
> 2570c7e48ace35 Remi Buisson 2025-08-14 899 return ret;
> 2570c7e48ace35 Remi Buisson 2025-08-14 900 }
> 2570c7e48ace35 Remi Buisson 2025-08-14 901
> 2570c7e48ace35 Remi Buisson 2025-08-14 902 ret = regmap_bulk_read(st->map, INV_ICM45600_REG_TEMP_DATA,
> 2570c7e48ace35 Remi Buisson 2025-08-14 903 &st->buffer.u16, sizeof(st->buffer.u16));
> 2570c7e48ace35 Remi Buisson 2025-08-14 904 if (ret)
> 2570c7e48ace35 Remi Buisson 2025-08-14 905 return ret;
> 2570c7e48ace35 Remi Buisson 2025-08-14 906
> 2570c7e48ace35 Remi Buisson 2025-08-14 907 *temp = (s16)le16_to_cpup(&st->buffer.u16);
> 2570c7e48ace35 Remi Buisson 2025-08-14 @908 if (*temp == INV_ICM45600_DATA_INVALID)
> 2570c7e48ace35 Remi Buisson 2025-08-14 909 return -EINVAL;
> 2570c7e48ace35 Remi Buisson 2025-08-14 910
> 2570c7e48ace35 Remi Buisson 2025-08-14 911 return 0;
> 2570c7e48ace35 Remi Buisson 2025-08-14 912 }
> 2570c7e48ace35 Remi Buisson 2025-08-14 913
>
© 2016 - 2026 Red Hat, Inc.