[PATCH V19 8/9] iio: imu: inv_icm42607: Add Temp Support in icm42607
Jonathan Cameron
jic23 at kernel.org
Fri Jul 24 17:20:02 PDT 2026
On Wed, 22 Jul 2026 10:39:39 -0500
Chris Morgan <macroalpha82 at gmail.com> wrote:
> From: Chris Morgan <macromorgan at hotmail.com>
>
> Add functions for reading temperature sensor data.
>
> Signed-off-by: Chris Morgan <macromorgan at hotmail.com>
I think this is now Chris beats sashiko. It is now confused
about the temperature channel handling but it looks fine to me.
It is complex, so fair enough you confused the poor thing ;)
Jonathan
> ---
> drivers/iio/imu/inv_icm42607/Makefile | 1 +
> .../iio/imu/inv_icm42607/inv_icm42607_accel.c | 8 ++
> .../iio/imu/inv_icm42607/inv_icm42607_gyro.c | 8 ++
> .../iio/imu/inv_icm42607/inv_icm42607_temp.c | 98 +++++++++++++++++++
> .../iio/imu/inv_icm42607/inv_icm42607_temp.h | 38 +++++++
> 5 files changed, 153 insertions(+)
> create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c
> create mode 100644 drivers/iio/imu/inv_icm42607/inv_icm42607_temp.h
>
> diff --git a/drivers/iio/imu/inv_icm42607/Makefile b/drivers/iio/imu/inv_icm42607/Makefile
> index 8e73385c8f4b..7b907e019601 100644
> --- a/drivers/iio/imu/inv_icm42607/Makefile
> +++ b/drivers/iio/imu/inv_icm42607/Makefile
> @@ -4,6 +4,7 @@ obj-$(CONFIG_INV_ICM42607) += inv-icm42607.o
> inv-icm42607-y += inv_icm42607_core.o
> inv-icm42607-y += inv_icm42607_gyro.o
> inv-icm42607-y += inv_icm42607_accel.o
> +inv-icm42607-y += inv_icm42607_temp.o
>
> 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_accel.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c
> index f563c7708420..0b3f035c2da0 100644
> --- a/drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c
> +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_accel.c
> @@ -15,6 +15,7 @@
> #include <linux/types.h>
>
> #include "inv_icm42607.h"
> +#include "inv_icm42607_temp.h"
>
> #define INV_ICM42607_ACCEL_CHAN(_modifier, _index, _ext_info) \
> { \
> @@ -40,6 +41,7 @@ enum inv_icm42607_accel_scan {
> INV_ICM42607_ACCEL_SCAN_X,
> INV_ICM42607_ACCEL_SCAN_Y,
> INV_ICM42607_ACCEL_SCAN_Z,
> + INV_ICM42607_ACCEL_SCAN_TEMP,
> };
>
> static const struct iio_chan_spec_ext_info inv_icm42607_accel_ext_infos[] = {
> @@ -54,6 +56,7 @@ static const struct iio_chan_spec inv_icm42607_accel_channels[] = {
> inv_icm42607_accel_ext_infos),
> INV_ICM42607_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42607_ACCEL_SCAN_Z,
> inv_icm42607_accel_ext_infos),
> + INV_ICM42607_TEMP_CHAN(INV_ICM42607_ACCEL_SCAN_TEMP),
> };
>
> static const int inv_icm42607_accel_scale_nano[][2] = {
> @@ -187,6 +190,11 @@ static int inv_icm42607_accel_read_raw(struct iio_dev *indio_dev,
> switch (chan->type) {
> case IIO_ACCEL:
> break;
> + case IIO_TEMP:
> + if (mask != IIO_CHAN_INFO_SAMP_FREQ)
> + return inv_icm42607_temp_read_raw(indio_dev, chan,
> + val, val2, mask);
> + break;
> default:
> return -EINVAL;
> }
> diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c
> index b68d4d6f5c3f..5b4683c2dd1e 100644
> --- a/drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c
> +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_gyro.c
> @@ -15,6 +15,7 @@
> #include <linux/types.h>
>
> #include "inv_icm42607.h"
> +#include "inv_icm42607_temp.h"
>
> #define INV_ICM42607_GYRO_CHAN(_modifier, _index, _ext_info) \
> { \
> @@ -40,6 +41,7 @@ enum inv_icm42607_gyro_scan {
> INV_ICM42607_GYRO_SCAN_X,
> INV_ICM42607_GYRO_SCAN_Y,
> INV_ICM42607_GYRO_SCAN_Z,
> + INV_ICM42607_GYRO_SCAN_TEMP,
> };
>
> static const struct iio_chan_spec_ext_info inv_icm42607_gyro_ext_infos[] = {
> @@ -54,6 +56,7 @@ static const struct iio_chan_spec inv_icm42607_gyro_channels[] = {
> inv_icm42607_gyro_ext_infos),
> INV_ICM42607_GYRO_CHAN(IIO_MOD_Z, INV_ICM42607_GYRO_SCAN_Z,
> inv_icm42607_gyro_ext_infos),
> + INV_ICM42607_TEMP_CHAN(INV_ICM42607_GYRO_SCAN_TEMP),
> };
>
> static const int inv_icm42607_gyro_scale_nano[][2] = {
> @@ -184,6 +187,11 @@ static int inv_icm42607_gyro_read_raw(struct iio_dev *indio_dev,
> switch (chan->type) {
> case IIO_ANGL_VEL:
> break;
> + case IIO_TEMP:
> + if (mask != IIO_CHAN_INFO_SAMP_FREQ)
> + return inv_icm42607_temp_read_raw(indio_dev, chan,
> + val, val2, mask);
> + break;
> default:
> return -EINVAL;
> }
> diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c b/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c
> new file mode 100644
> index 000000000000..8681ef2b49e2
> --- /dev/null
> +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.c
> @@ -0,0 +1,98 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * Copyright (C) 2026 InvenSense, Inc.
> + */
> +
> +#include <linux/cleanup.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/iio/iio.h>
> +#include <linux/mutex.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/regmap.h>
> +#include <linux/types.h>
> +#include <linux/unaligned.h>
> +
> +#include "inv_icm42607.h"
> +#include "inv_icm42607_temp.h"
> +
> +static int inv_icm42607_temp_read(struct inv_icm42607_state *st, s16 *temp)
> +{
> + struct inv_icm42607_sensor_conf conf = INV_ICM42607_SENSOR_CONF_INIT;
> + struct device *dev = regmap_get_device(st->map);
> + int ret, gyro_mode, accel_mode;
> + unsigned int val;
> + u8 raw[2];
> +
> + PM_RUNTIME_ACQUIRE_AUTOSUSPEND(dev, pm);
> + ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
> + if (ret)
> + return ret;
> +
> + guard(mutex)(&st->lock);
> +
> + /*
> + * Check if both the gyro and accel are off and if so, enable one
> + * of them. The temp sensor cannot be read if both the gyro and
> + * accel sensor are off. Prefer to enable the accel over the gyro
> + * as the datasheet says the gyro uses 5x more power and it has
> + * a minimum run time of 45ms.
> + */
> + ret = regmap_read(st->map, INV_ICM42607_REG_PWR_MGMT0, &val);
> + if (ret)
> + return ret;
> +
> + accel_mode = FIELD_GET(INV_ICM42607_PWR_MGMT0_ACCEL_MODE_MASK, val);
> + gyro_mode = FIELD_GET(INV_ICM42607_PWR_MGMT0_GYRO_MODE_MASK, val);
> + if (!gyro_mode && !accel_mode) {
> + /* enable accel sensor */
> + conf.mode = INV_ICM42607_SENSOR_MODE_LOW_NOISE;
> + ret = inv_icm42607_set_sensor_conf(st, &conf, IIO_ACCEL);
> + if (ret)
> + return ret;
> + }
> +
> + ret = regmap_bulk_read(st->map, INV_ICM42607_REG_TEMP_DATA1,
> + raw, sizeof(raw));
> + if (ret)
> + return ret;
> +
> + *temp = get_unaligned_be16(raw);
> + if (*temp == INV_ICM42607_DATA_INVALID)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +int inv_icm42607_temp_read_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + int *val, int *val2, long mask)
> +{
> + struct inv_icm42607_state *st = iio_device_get_drvdata(indio_dev);
> + s16 temp;
> + int ret;
> +
> + switch (mask) {
> + case IIO_CHAN_INFO_RAW:
> + ret = inv_icm42607_temp_read(st, &temp);
> + if (ret)
> + return ret;
> + *val = temp;
> + return IIO_VAL_INT;
> + /*
> + * T°C = (temp / 128) + 25
> + * Tm°C = 1000 * ((temp * 100 / 12800) + 25)
> + * scale: 100000 / 12800 ~= 7.8125
> + * offset: 3200
> + */
> + case IIO_CHAN_INFO_SCALE:
> + *val = 7;
> + *val2 = 812500000;
> + return IIO_VAL_INT_PLUS_NANO;
> + case IIO_CHAN_INFO_OFFSET:
> + *val = 3200;
> + return IIO_VAL_INT;
> + default:
> + return -EINVAL;
> + }
> +}
> diff --git a/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.h b/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.h
> new file mode 100644
> index 000000000000..18499b4d0b94
> --- /dev/null
> +++ b/drivers/iio/imu/inv_icm42607/inv_icm42607_temp.h
> @@ -0,0 +1,38 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2026 InvenSense, Inc.
> + */
> +
> +#ifndef INV_ICM42607_TEMP_H_
> +#define INV_ICM42607_TEMP_H_
> +
> +#include <linux/bitops.h>
> +
> +struct iio_dev;
> +struct iio_chan_spec;
> +
> +#define INV_ICM42607_TEMP_CHAN(_index) \
> +{ \
> + .type = IIO_TEMP, \
> + .info_mask_separate = \
> + BIT(IIO_CHAN_INFO_RAW) | \
> + BIT(IIO_CHAN_INFO_OFFSET) | \
> + BIT(IIO_CHAN_INFO_SCALE), \
> + .info_mask_shared_by_all = \
> + BIT(IIO_CHAN_INFO_SAMP_FREQ), \
> + .info_mask_shared_by_all_available = \
> + BIT(IIO_CHAN_INFO_SAMP_FREQ), \
> + .scan_index = _index, \
> + .scan_type = { \
> + .sign = 's', \
> + .realbits = 16, \
> + .storagebits = 16, \
> + .endianness = IIO_BE, \
> + }, \
> +}
> +
> +int inv_icm42607_temp_read_raw(struct iio_dev *indio_dev,
> + struct iio_chan_spec const *chan,
> + int *val, int *val2, long mask);
> +
> +#endif
More information about the Linux-rockchip
mailing list