Skip to content

Commit

Permalink
iio: imu: inv_icm42600: add temperature sensor support
Browse files Browse the repository at this point in the history
Add temperature channel in gyroscope and accelerometer devices.

Temperature is available in full 16 bits resolution when reading
register and in low 8 bits resolution in the FIFO. Return full
precision raw temperature with corresponding scale and offset.

Signed-off-by: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
  • Loading branch information
Jean-Baptiste Maneyrol authored and Jonathan Cameron committed Jun 27, 2020
1 parent a47c1cd commit bc3eb02
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 2 deletions.
11 changes: 10 additions & 1 deletion drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/iio/iio.h>

#include "inv_icm42600.h"
#include "inv_icm42600_temp.h"

#define INV_ICM42600_ACCEL_CHAN(_modifier, _index, _ext_info) \
{ \
Expand Down Expand Up @@ -45,6 +46,7 @@ enum inv_icm42600_accel_scan {
INV_ICM42600_ACCEL_SCAN_X,
INV_ICM42600_ACCEL_SCAN_Y,
INV_ICM42600_ACCEL_SCAN_Z,
INV_ICM42600_ACCEL_SCAN_TEMP,
};

static const struct iio_chan_spec_ext_info inv_icm42600_accel_ext_infos[] = {
Expand All @@ -59,6 +61,7 @@ static const struct iio_chan_spec inv_icm42600_accel_channels[] = {
inv_icm42600_accel_ext_infos),
INV_ICM42600_ACCEL_CHAN(IIO_MOD_Z, INV_ICM42600_ACCEL_SCAN_Z,
inv_icm42600_accel_ext_infos),
INV_ICM42600_TEMP_CHAN(INV_ICM42600_ACCEL_SCAN_TEMP),
};

static int inv_icm42600_accel_read_sensor(struct inv_icm42600_state *st,
Expand Down Expand Up @@ -450,8 +453,14 @@ static int inv_icm42600_accel_read_raw(struct iio_dev *indio_dev,
int16_t data;
int ret;

if (chan->type != IIO_ACCEL)
switch (chan->type) {
case IIO_ACCEL:
break;
case IIO_TEMP:
return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, mask);
default:
return -EINVAL;
}

switch (mask) {
case IIO_CHAN_INFO_RAW:
Expand Down
11 changes: 10 additions & 1 deletion drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <linux/iio/iio.h>

#include "inv_icm42600.h"
#include "inv_icm42600_temp.h"

#define INV_ICM42600_GYRO_CHAN(_modifier, _index, _ext_info) \
{ \
Expand Down Expand Up @@ -45,6 +46,7 @@ enum inv_icm42600_gyro_scan {
INV_ICM42600_GYRO_SCAN_X,
INV_ICM42600_GYRO_SCAN_Y,
INV_ICM42600_GYRO_SCAN_Z,
INV_ICM42600_GYRO_SCAN_TEMP,
};

static const struct iio_chan_spec_ext_info inv_icm42600_gyro_ext_infos[] = {
Expand All @@ -59,6 +61,7 @@ static const struct iio_chan_spec inv_icm42600_gyro_channels[] = {
inv_icm42600_gyro_ext_infos),
INV_ICM42600_GYRO_CHAN(IIO_MOD_Z, INV_ICM42600_GYRO_SCAN_Z,
inv_icm42600_gyro_ext_infos),
INV_ICM42600_TEMP_CHAN(INV_ICM42600_GYRO_SCAN_TEMP),
};

static int inv_icm42600_gyro_read_sensor(struct inv_icm42600_state *st,
Expand Down Expand Up @@ -461,8 +464,14 @@ static int inv_icm42600_gyro_read_raw(struct iio_dev *indio_dev,
int16_t data;
int ret;

if (chan->type != IIO_ANGL_VEL)
switch (chan->type) {
case IIO_ANGL_VEL:
break;
case IIO_TEMP:
return inv_icm42600_temp_read_raw(indio_dev, chan, val, val2, mask);
default:
return -EINVAL;
}

switch (mask) {
case IIO_CHAN_INFO_RAW:
Expand Down
84 changes: 84 additions & 0 deletions drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2020 Invensense, Inc.
*/

#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/mutex.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/iio/iio.h>

#include "inv_icm42600.h"
#include "inv_icm42600_temp.h"

static int inv_icm42600_temp_read(struct inv_icm42600_state *st, int16_t *temp)
{
struct device *dev = regmap_get_device(st->map);
__be16 *raw;
int ret;

pm_runtime_get_sync(dev);
mutex_lock(&st->lock);

ret = inv_icm42600_set_temp_conf(st, true, NULL);
if (ret)
goto exit;

raw = (__be16 *)&st->buffer[0];
ret = regmap_bulk_read(st->map, INV_ICM42600_REG_TEMP_DATA, raw, sizeof(*raw));
if (ret)
goto exit;

*temp = (int16_t)be16_to_cpup(raw);
if (*temp == INV_ICM42600_DATA_INVALID)
ret = -EINVAL;

exit:
mutex_unlock(&st->lock);
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);

return ret;
}

int inv_icm42600_temp_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
{
struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
int16_t temp;
int ret;

if (chan->type != IIO_TEMP)
return -EINVAL;

switch (mask) {
case IIO_CHAN_INFO_RAW:
ret = iio_device_claim_direct_mode(indio_dev);
if (ret)
return ret;
ret = inv_icm42600_temp_read(st, &temp);
iio_device_release_direct_mode(indio_dev);
if (ret)
return ret;
*val = temp;
return IIO_VAL_INT;
/*
* T°C = (temp / 132.48) + 25
* Tm°C = 1000 * ((temp * 100 / 13248) + 25)
* scale: 100000 / 13248 ~= 7.548309
* offset: 25000
*/
case IIO_CHAN_INFO_SCALE:
*val = 7;
*val2 = 548309;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_OFFSET:
*val = 25000;
return IIO_VAL_INT;
default:
return -EINVAL;
}
}
30 changes: 30 additions & 0 deletions drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2020 Invensense, Inc.
*/

#ifndef INV_ICM42600_TEMP_H_
#define INV_ICM42600_TEMP_H_

#include <linux/iio/iio.h>

#define INV_ICM42600_TEMP_CHAN(_index) \
{ \
.type = IIO_TEMP, \
.info_mask_separate = \
BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_OFFSET) | \
BIT(IIO_CHAN_INFO_SCALE), \
.scan_index = _index, \
.scan_type = { \
.sign = 's', \
.realbits = 16, \
.storagebits = 16, \
}, \
}

int inv_icm42600_temp_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask);

#endif

0 comments on commit bc3eb02

Please sign in to comment.