1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (C) 2020 Invensense, Inc. |
4 | */ |
5 | |
6 | #include <linux/kernel.h> |
7 | #include <linux/device.h> |
8 | #include <linux/mutex.h> |
9 | #include <linux/pm_runtime.h> |
10 | #include <linux/regmap.h> |
11 | #include <linux/iio/iio.h> |
12 | |
13 | #include "inv_icm42600.h" |
14 | #include "inv_icm42600_temp.h" |
15 | |
16 | static int inv_icm42600_temp_read(struct inv_icm42600_state *st, int16_t *temp) |
17 | { |
18 | struct device *dev = regmap_get_device(map: st->map); |
19 | __be16 *raw; |
20 | int ret; |
21 | |
22 | pm_runtime_get_sync(dev); |
23 | mutex_lock(&st->lock); |
24 | |
25 | ret = inv_icm42600_set_temp_conf(st, enable: true, NULL); |
26 | if (ret) |
27 | goto exit; |
28 | |
29 | raw = (__be16 *)&st->buffer[0]; |
30 | ret = regmap_bulk_read(map: st->map, INV_ICM42600_REG_TEMP_DATA, val: raw, val_count: sizeof(*raw)); |
31 | if (ret) |
32 | goto exit; |
33 | |
34 | *temp = (int16_t)be16_to_cpup(p: raw); |
35 | if (*temp == INV_ICM42600_DATA_INVALID) |
36 | ret = -EINVAL; |
37 | |
38 | exit: |
39 | mutex_unlock(lock: &st->lock); |
40 | pm_runtime_mark_last_busy(dev); |
41 | pm_runtime_put_autosuspend(dev); |
42 | |
43 | return ret; |
44 | } |
45 | |
46 | int inv_icm42600_temp_read_raw(struct iio_dev *indio_dev, |
47 | struct iio_chan_spec const *chan, |
48 | int *val, int *val2, long mask) |
49 | { |
50 | struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); |
51 | int16_t temp; |
52 | int ret; |
53 | |
54 | if (chan->type != IIO_TEMP) |
55 | return -EINVAL; |
56 | |
57 | switch (mask) { |
58 | case IIO_CHAN_INFO_RAW: |
59 | ret = iio_device_claim_direct_mode(indio_dev); |
60 | if (ret) |
61 | return ret; |
62 | ret = inv_icm42600_temp_read(st, temp: &temp); |
63 | iio_device_release_direct_mode(indio_dev); |
64 | if (ret) |
65 | return ret; |
66 | *val = temp; |
67 | return IIO_VAL_INT; |
68 | /* |
69 | * T°C = (temp / 132.48) + 25 |
70 | * Tm°C = 1000 * ((temp * 100 / 13248) + 25) |
71 | * scale: 100000 / 13248 ~= 7.548309 |
72 | * offset: 25000 |
73 | */ |
74 | case IIO_CHAN_INFO_SCALE: |
75 | *val = 7; |
76 | *val2 = 548309; |
77 | return IIO_VAL_INT_PLUS_MICRO; |
78 | case IIO_CHAN_INFO_OFFSET: |
79 | *val = 25000; |
80 | return IIO_VAL_INT; |
81 | default: |
82 | return -EINVAL; |
83 | } |
84 | } |
85 | |