lkml.org 
[lkml]   [2020]   [May]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 06/12] iio: imu: inv_icm42600: add temperature sensor support
    Date
    Add temperature channel in gyroscope and accelerometer devices.

    Temperature is available in full 16 bits resolution as a processed
    channel. Scale and offset attributes are also provided for the low
    8 bits resolution raw temperature found in the FIFO.

    Signed-off-by: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
    ---
    .../iio/imu/inv_icm42600/inv_icm42600_accel.c | 11 ++-
    .../iio/imu/inv_icm42600/inv_icm42600_gyro.c | 11 ++-
    .../iio/imu/inv_icm42600/inv_icm42600_temp.c | 87 +++++++++++++++++++
    .../iio/imu/inv_icm42600/inv_icm42600_temp.h | 30 +++++++
    4 files changed, 137 insertions(+), 2 deletions(-)
    create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
    create mode 100644 drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h

    diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
    index 7620ce1958e0..6a615d7ffb24 100644
    --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
    +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
    @@ -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) \
    { \
    @@ -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[] = {
    @@ -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,
    @@ -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:
    diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
    index 9d9672989b23..38654e0d217b 100644
    --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
    +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
    @@ -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) \
    { \
    @@ -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[] = {
    @@ -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,
    @@ -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:
    diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
    new file mode 100644
    index 000000000000..b0871352fe39
    --- /dev/null
    +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.c
    @@ -0,0 +1,87 @@
    +// 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/math64.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, int32_t *temp)
    +{
    + struct device *dev = regmap_get_device(st->map);
    + int64_t data;
    + __be16 *raw;
    + int16_t val;
    + 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;
    +
    + val = (int16_t)be16_to_cpup(raw);
    + if (val == INV_ICM42600_DATA_INVALID) {
    + ret = -EINVAL;
    + goto exit;
    + }
    + /*
    + * T°C = (val / 132.48) + 25 = ((val * 100) / 13248) + 25
    + * Tm°C = (val * 100 * 1000) / 13248 + 25000
    + */
    + data = (int64_t)(val) * 100LL * 1000LL;
    + *temp = div_s64(data, 13248) + 25000;
    +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);
    + int32_t temp;
    + int ret;
    +
    + if (chan->type != IIO_TEMP)
    + return -EINVAL;
    +
    + switch (mask) {
    + case IIO_CHAN_INFO_PROCESSED:
    + 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;
    + case IIO_CHAN_INFO_SCALE:
    + *val = 483;
    + *val2 = 91787;
    + return IIO_VAL_INT_PLUS_MICRO;
    + case IIO_CHAN_INFO_OFFSET:
    + *val = 25000;
    + return IIO_VAL_INT;
    + default:
    + return -EINVAL;
    + }
    +}
    diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h
    new file mode 100644
    index 000000000000..2c3a932faa94
    --- /dev/null
    +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_temp.h
    @@ -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_PROCESSED) | \
    + BIT(IIO_CHAN_INFO_OFFSET) | \
    + BIT(IIO_CHAN_INFO_SCALE), \
    + .scan_index = _index, \
    + .scan_type = { \
    + .sign = 's', \
    + .realbits = 8, \
    + .storagebits = 8, \
    + }, \
    + }
    +
    +int inv_icm42600_temp_read_raw(struct iio_dev *indio_dev,
    + struct iio_chan_spec const *chan,
    + int *val, int *val2, long mask);
    +
    +#endif
    --
    2.17.1
    \
     
     \ /
      Last update: 2020-05-27 20:59    [W:6.100 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site