^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * tmp007.c - Support for TI TMP007 IR thermopile sensor with integrated math engine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2017 Manivannan Sadhasivam <manivannanece23@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Driver for the Texas Instruments I2C 16-bit IR thermopile sensor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * (7-bit I2C slave address (0x40 - 0x47), changeable via ADR pins)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Note:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * 1. This driver assumes that the sensor has been calibrated beforehand
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * 2. Limit threshold events are enabled at the start
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * 3. Operating mode: INT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/mod_devicetable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/iio/sysfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/iio/events.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define TMP007_TDIE 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define TMP007_CONFIG 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define TMP007_TOBJECT 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define TMP007_STATUS 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define TMP007_STATUS_MASK 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define TMP007_TOBJ_HIGH_LIMIT 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define TMP007_TOBJ_LOW_LIMIT 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define TMP007_TDIE_HIGH_LIMIT 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define TMP007_TDIE_LOW_LIMIT 0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define TMP007_MANUFACTURER_ID 0x1e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define TMP007_DEVICE_ID 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define TMP007_CONFIG_CONV_EN BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define TMP007_CONFIG_TC_EN BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define TMP007_CONFIG_CR_MASK GENMASK(11, 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define TMP007_CONFIG_ALERT_EN BIT(8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define TMP007_CONFIG_CR_SHIFT 9
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* Status register flags */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define TMP007_STATUS_ALERT BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define TMP007_STATUS_CONV_READY BIT(14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define TMP007_STATUS_OHF BIT(13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define TMP007_STATUS_OLF BIT(12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define TMP007_STATUS_LHF BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define TMP007_STATUS_LLF BIT(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define TMP007_STATUS_DATA_VALID BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define TMP007_MANUFACTURER_MAGIC 0x5449
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define TMP007_DEVICE_MAGIC 0x0078
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define TMP007_TEMP_SHIFT 2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct tmp007_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) u16 config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) u16 status_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static const int tmp007_avgs[5][2] = { {4, 0}, {2, 0}, {1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {0, 500000}, {0, 250000} };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static int tmp007_read_temperature(struct tmp007_data *data, u8 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) s32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int tries = 50;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) while (tries-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) ret = i2c_smbus_read_word_swapped(data->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) TMP007_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if ((ret & TMP007_STATUS_CONV_READY) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) !(ret & TMP007_STATUS_DATA_VALID))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) msleep(100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (tries < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) return i2c_smbus_read_word_swapped(data->client, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) static int tmp007_powerdown(struct tmp007_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) data->config & ~TMP007_CONFIG_CONV_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static int tmp007_read_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct iio_chan_spec const *channel, int *val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) int *val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) struct tmp007_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) s32 ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) int conv_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) case IIO_CHAN_INFO_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) switch (channel->channel2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) case IIO_MOD_TEMP_AMBIENT: /* LSB: 0.03125 degree Celsius */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) ret = i2c_smbus_read_word_swapped(data->client, TMP007_TDIE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) case IIO_MOD_TEMP_OBJECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ret = tmp007_read_temperature(data, TMP007_TOBJECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) *val = sign_extend32(ret, 15) >> TMP007_TEMP_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) case IIO_CHAN_INFO_SCALE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) *val = 31;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) *val2 = 250000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) return IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) case IIO_CHAN_INFO_SAMP_FREQ:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) conv_rate = (data->config & TMP007_CONFIG_CR_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) >> TMP007_CONFIG_CR_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) *val = tmp007_avgs[conv_rate][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) *val2 = tmp007_avgs[conv_rate][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) return IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static int tmp007_write_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct iio_chan_spec const *channel, int val,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) int val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct tmp007_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) u16 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (mask == IIO_CHAN_INFO_SAMP_FREQ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) for (i = 0; i < ARRAY_SIZE(tmp007_avgs); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if ((val == tmp007_avgs[i][0]) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) (val2 == tmp007_avgs[i][1])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) tmp = data->config & ~TMP007_CONFIG_CR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) tmp |= (i << TMP007_CONFIG_CR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return i2c_smbus_write_word_swapped(data->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) TMP007_CONFIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) data->config = tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static irqreturn_t tmp007_interrupt_handler(int irq, void *private)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) struct iio_dev *indio_dev = private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) struct tmp007_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if ((ret < 0) || !(ret & (TMP007_STATUS_OHF | TMP007_STATUS_OLF |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) TMP007_STATUS_LHF | TMP007_STATUS_LLF)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return IRQ_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) if (ret & TMP007_STATUS_OHF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) iio_push_event(indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) IIO_MOD_TEMP_OBJECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) IIO_EV_DIR_RISING),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) iio_get_time_ns(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (ret & TMP007_STATUS_OLF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) iio_push_event(indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) IIO_MOD_TEMP_OBJECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) IIO_EV_DIR_FALLING),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) iio_get_time_ns(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (ret & TMP007_STATUS_LHF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) iio_push_event(indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) IIO_MOD_TEMP_AMBIENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) IIO_EV_DIR_RISING),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) iio_get_time_ns(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (ret & TMP007_STATUS_LLF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) iio_push_event(indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) IIO_MOD_EVENT_CODE(IIO_TEMP, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) IIO_MOD_TEMP_AMBIENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) IIO_EV_DIR_FALLING),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) iio_get_time_ns(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) static int tmp007_write_event_config(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) const struct iio_chan_spec *chan, enum iio_event_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) enum iio_event_direction dir, int state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct tmp007_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) unsigned int status_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) switch (chan->channel2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) case IIO_MOD_TEMP_AMBIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (dir == IIO_EV_DIR_RISING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) status_mask = TMP007_STATUS_LHF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) status_mask = TMP007_STATUS_LLF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) case IIO_MOD_TEMP_OBJECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (dir == IIO_EV_DIR_RISING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) status_mask = TMP007_STATUS_OHF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) status_mask = TMP007_STATUS_OLF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) ret |= status_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) ret &= ~status_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) data->status_mask = ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static int tmp007_read_event_config(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) const struct iio_chan_spec *chan, enum iio_event_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) enum iio_event_direction dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct tmp007_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) unsigned int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) switch (chan->channel2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) case IIO_MOD_TEMP_AMBIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (dir == IIO_EV_DIR_RISING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) mask = TMP007_STATUS_LHF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) mask = TMP007_STATUS_LLF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) case IIO_MOD_TEMP_OBJECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (dir == IIO_EV_DIR_RISING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) mask = TMP007_STATUS_OHF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) mask = TMP007_STATUS_OLF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) return !!(data->status_mask & mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static int tmp007_read_thresh(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) const struct iio_chan_spec *chan, enum iio_event_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) enum iio_event_direction dir, enum iio_event_info info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) int *val, int *val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct tmp007_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) switch (chan->channel2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) case IIO_MOD_TEMP_AMBIENT: /* LSB: 0.5 degree Celsius */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) if (dir == IIO_EV_DIR_RISING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) reg = TMP007_TDIE_HIGH_LIMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) reg = TMP007_TDIE_LOW_LIMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) case IIO_MOD_TEMP_OBJECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (dir == IIO_EV_DIR_RISING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) reg = TMP007_TOBJ_HIGH_LIMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) reg = TMP007_TOBJ_LOW_LIMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ret = i2c_smbus_read_word_swapped(data->client, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* Shift length 7 bits = 6(15:6) + 1(0.5 LSB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) *val = sign_extend32(ret, 15) >> 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) static int tmp007_write_thresh(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) const struct iio_chan_spec *chan, enum iio_event_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) enum iio_event_direction dir, enum iio_event_info info,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) int val, int val2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct tmp007_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) switch (chan->channel2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) case IIO_MOD_TEMP_AMBIENT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (dir == IIO_EV_DIR_RISING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) reg = TMP007_TDIE_HIGH_LIMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) reg = TMP007_TDIE_LOW_LIMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) case IIO_MOD_TEMP_OBJECT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (dir == IIO_EV_DIR_RISING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) reg = TMP007_TOBJ_HIGH_LIMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) reg = TMP007_TOBJ_LOW_LIMIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) /* Full scale threshold value is +/- 256 degree Celsius */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (val < -256 || val > 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /* Shift length 7 bits = 6(15:6) + 1(0.5 LSB) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return i2c_smbus_write_word_swapped(data->client, reg, (val << 7));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static IIO_CONST_ATTR(sampling_frequency_available, "4 2 1 0.5 0.25");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) static struct attribute *tmp007_attributes[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) &iio_const_attr_sampling_frequency_available.dev_attr.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) static const struct attribute_group tmp007_attribute_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) .attrs = tmp007_attributes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) static const struct iio_event_spec tmp007_obj_event[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) .type = IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) .dir = IIO_EV_DIR_RISING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) .mask_separate = BIT(IIO_EV_INFO_VALUE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) BIT(IIO_EV_INFO_ENABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) .type = IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) .dir = IIO_EV_DIR_FALLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) .mask_separate = BIT(IIO_EV_INFO_VALUE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) BIT(IIO_EV_INFO_ENABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static const struct iio_event_spec tmp007_die_event[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) .type = IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) .dir = IIO_EV_DIR_RISING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) .mask_separate = BIT(IIO_EV_INFO_VALUE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) BIT(IIO_EV_INFO_ENABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) .type = IIO_EV_TYPE_THRESH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) .dir = IIO_EV_DIR_FALLING,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) .mask_separate = BIT(IIO_EV_INFO_VALUE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) BIT(IIO_EV_INFO_ENABLE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) static const struct iio_chan_spec tmp007_channels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) .type = IIO_TEMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) .modified = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) .channel2 = IIO_MOD_TEMP_AMBIENT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) BIT(IIO_CHAN_INFO_SCALE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) .event_spec = tmp007_die_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) .num_event_specs = ARRAY_SIZE(tmp007_die_event),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) .type = IIO_TEMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) .modified = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) .channel2 = IIO_MOD_TEMP_OBJECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) BIT(IIO_CHAN_INFO_SCALE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) .event_spec = tmp007_obj_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) .num_event_specs = ARRAY_SIZE(tmp007_obj_event),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) static const struct iio_info tmp007_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) .read_raw = tmp007_read_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) .write_raw = tmp007_write_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) .read_event_config = tmp007_read_event_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) .write_event_config = tmp007_write_event_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) .read_event_value = tmp007_read_thresh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) .write_event_value = tmp007_write_thresh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) .attrs = &tmp007_attribute_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) static bool tmp007_identify(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) int manf_id, dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) manf_id = i2c_smbus_read_word_swapped(client, TMP007_MANUFACTURER_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (manf_id < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) dev_id = i2c_smbus_read_word_swapped(client, TMP007_DEVICE_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (dev_id < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) return (manf_id == TMP007_MANUFACTURER_MAGIC && dev_id == TMP007_DEVICE_MAGIC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) static int tmp007_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) const struct i2c_device_id *tmp007_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) struct tmp007_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (!tmp007_identify(client)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) dev_err(&client->dev, "TMP007 not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (!indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) i2c_set_clientdata(client, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) data->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) mutex_init(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) indio_dev->name = "tmp007";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) indio_dev->modes = INDIO_DIRECT_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) indio_dev->info = &tmp007_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) indio_dev->channels = tmp007_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) indio_dev->num_channels = ARRAY_SIZE(tmp007_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * Set Configuration register:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * 1. Conversion ON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * 2. ALERT enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) * 3. Transient correction enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) ret = i2c_smbus_read_word_swapped(data->client, TMP007_CONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) data->config = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) data->config |= (TMP007_CONFIG_CONV_EN | TMP007_CONFIG_ALERT_EN | TMP007_CONFIG_TC_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) ret = i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) data->config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) * Only the following flags can activate ALERT pin. Data conversion/validity flags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * flags can still be polled for getting temperature data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) * Set Status Mask register:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) * 1. Object temperature high limit enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) * 2. Object temperature low limit enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * 3. TDIE temperature high limit enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) * 4. TDIE temperature low limit enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) ret = i2c_smbus_read_word_swapped(data->client, TMP007_STATUS_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) goto error_powerdown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) data->status_mask = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) data->status_mask |= (TMP007_STATUS_OHF | TMP007_STATUS_OLF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) | TMP007_STATUS_LHF | TMP007_STATUS_LLF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) ret = i2c_smbus_write_word_swapped(data->client, TMP007_STATUS_MASK, data->status_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) goto error_powerdown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (client->irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) ret = devm_request_threaded_irq(&client->dev, client->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) NULL, tmp007_interrupt_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) tmp007_id->name, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) dev_err(&client->dev, "irq request error %d\n", -ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) goto error_powerdown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) return iio_device_register(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) error_powerdown:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) tmp007_powerdown(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) static int tmp007_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) struct iio_dev *indio_dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) struct tmp007_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) iio_device_unregister(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) tmp007_powerdown(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) static int tmp007_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) struct tmp007_data *data = iio_priv(i2c_get_clientdata(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) to_i2c_client(dev)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return tmp007_powerdown(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) static int tmp007_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) struct tmp007_data *data = iio_priv(i2c_get_clientdata(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) to_i2c_client(dev)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) return i2c_smbus_write_word_swapped(data->client, TMP007_CONFIG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) data->config | TMP007_CONFIG_CONV_EN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) static SIMPLE_DEV_PM_OPS(tmp007_pm_ops, tmp007_suspend, tmp007_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) static const struct of_device_id tmp007_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) { .compatible = "ti,tmp007", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) { },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) MODULE_DEVICE_TABLE(of, tmp007_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) static const struct i2c_device_id tmp007_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) { "tmp007", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) MODULE_DEVICE_TABLE(i2c, tmp007_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) static struct i2c_driver tmp007_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) .name = "tmp007",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) .of_match_table = tmp007_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) .pm = &tmp007_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) .probe = tmp007_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) .remove = tmp007_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) .id_table = tmp007_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) module_i2c_driver(tmp007_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) MODULE_AUTHOR("Manivannan Sadhasivam <manivannanece23@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) MODULE_DESCRIPTION("TI TMP007 IR thermopile sensor driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) MODULE_LICENSE("GPL");