Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: temperature: add driver support for ti tmp117

TMP117 is a Digital temperature sensor with integrated Non-Volatile memory.
Add support for tmp117 driver in iio subsystem.

Datasheet: https://www.ti.com/lit/gpn/tmp117
Signed-off-by: Puranjay Mohan <puranjay12@gmail.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Reviewed-by: Lars-Peter Clausen <lars@metafoo.de>
Link: https://lore.kernel.org/r/20210407182147.77221-3-puranjay12@gmail.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Puranjay Mohan and committed by
Jonathan Cameron
df041e73 5e713b25

+203
+7
MAINTAINERS
··· 18094 18094 F: Documentation/hwmon/tps23861.rst 18095 18095 F: drivers/hwmon/tps23861.c 18096 18096 18097 + TEXAS INSTRUMENTS' TMP117 TEMPERATURE SENSOR DRIVER 18098 + M: Puranjay Mohan <puranjay12@gmail.com> 18099 + L: linux-iio@vger.kernel.org 18100 + S: Supported 18101 + F: Documentation/devicetree/bindings/iio/temperature/ti,tmp117.yaml 18102 + F: drivers/iio/temperature/tmp117.c 18103 + 18097 18104 THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER 18098 18105 M: Hans Verkuil <hverkuil@xs4all.nl> 18099 18106 L: linux-media@vger.kernel.org
+10
drivers/iio/temperature/Kconfig
··· 96 96 This driver can also be built as a module. If so, the module will 97 97 be called tmp007. 98 98 99 + config TMP117 100 + tristate "TMP117 Digital temperature sensor with integrated NV memory" 101 + depends on I2C 102 + help 103 + If you say yes here you get support for the Texas Instruments 104 + TMP117 Digital temperature sensor with integrated NV memory. 105 + 106 + This driver can also be built as a module. If so, the module will 107 + be called tmp117. 108 + 99 109 config TSYS01 100 110 tristate "Measurement Specialties TSYS01 temperature sensor using I2C bus connection" 101 111 depends on I2C
+1
drivers/iio/temperature/Makefile
··· 12 12 obj-$(CONFIG_MLX90632) += mlx90632.o 13 13 obj-$(CONFIG_TMP006) += tmp006.o 14 14 obj-$(CONFIG_TMP007) += tmp007.o 15 + obj-$(CONFIG_TMP117) += tmp117.o 15 16 obj-$(CONFIG_TSYS01) += tsys01.o 16 17 obj-$(CONFIG_TSYS02D) += tsys02d.o
+185
drivers/iio/temperature/tmp117.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Digital temperature sensor with integrated Non-volatile memory 4 + * Copyright (c) 2021 Puranjay Mohan <puranjay12@gmail.com> 5 + * 6 + * Driver for the Texas Instruments TMP117 Temperature Sensor 7 + * (7-bit I2C slave address (0x48 - 0x4B), changeable via ADD pins) 8 + * 9 + * Note: This driver assumes that the sensor has been calibrated beforehand. 10 + */ 11 + 12 + #include <linux/err.h> 13 + #include <linux/i2c.h> 14 + #include <linux/module.h> 15 + #include <linux/bitops.h> 16 + #include <linux/types.h> 17 + #include <linux/kernel.h> 18 + #include <linux/limits.h> 19 + 20 + #include <linux/iio/iio.h> 21 + 22 + #define TMP117_REG_TEMP 0x0 23 + #define TMP117_REG_CFGR 0x1 24 + #define TMP117_REG_HIGH_LIM 0x2 25 + #define TMP117_REG_LOW_LIM 0x3 26 + #define TMP117_REG_EEPROM_UL 0x4 27 + #define TMP117_REG_EEPROM1 0x5 28 + #define TMP117_REG_EEPROM2 0x6 29 + #define TMP117_REG_TEMP_OFFSET 0x7 30 + #define TMP117_REG_EEPROM3 0x8 31 + #define TMP117_REG_DEVICE_ID 0xF 32 + 33 + #define TMP117_RESOLUTION_10UC 78125 34 + #define TMP117_DEVICE_ID 0x0117 35 + #define MICRODEGREE_PER_10MILLIDEGREE 10000 36 + 37 + struct tmp117_data { 38 + struct i2c_client *client; 39 + s16 calibbias; 40 + }; 41 + 42 + static int tmp117_read_raw(struct iio_dev *indio_dev, 43 + struct iio_chan_spec const *channel, int *val, 44 + int *val2, long mask) 45 + { 46 + struct tmp117_data *data = iio_priv(indio_dev); 47 + s32 ret; 48 + 49 + switch (mask) { 50 + case IIO_CHAN_INFO_RAW: 51 + ret = i2c_smbus_read_word_swapped(data->client, 52 + TMP117_REG_TEMP); 53 + if (ret < 0) 54 + return ret; 55 + *val = sign_extend32(ret, 15); 56 + return IIO_VAL_INT; 57 + 58 + case IIO_CHAN_INFO_CALIBBIAS: 59 + ret = i2c_smbus_read_word_swapped(data->client, 60 + TMP117_REG_TEMP_OFFSET); 61 + if (ret < 0) 62 + return ret; 63 + *val = sign_extend32(ret, 15); 64 + return IIO_VAL_INT; 65 + 66 + case IIO_CHAN_INFO_SCALE: 67 + /* 68 + * Conversion from 10s of uC to mC 69 + * as IIO reports temperature in mC 70 + */ 71 + *val = TMP117_RESOLUTION_10UC / MICRODEGREE_PER_10MILLIDEGREE; 72 + *val2 = (TMP117_RESOLUTION_10UC % 73 + MICRODEGREE_PER_10MILLIDEGREE) * 100; 74 + 75 + return IIO_VAL_INT_PLUS_MICRO; 76 + 77 + default: 78 + return -EINVAL; 79 + } 80 + } 81 + 82 + static int tmp117_write_raw(struct iio_dev *indio_dev, 83 + struct iio_chan_spec const *channel, int val, 84 + int val2, long mask) 85 + { 86 + struct tmp117_data *data = iio_priv(indio_dev); 87 + s16 off; 88 + 89 + switch (mask) { 90 + case IIO_CHAN_INFO_CALIBBIAS: 91 + off = clamp_t(int, val, S16_MIN, S16_MAX); 92 + if (off == data->calibbias) 93 + return 0; 94 + data->calibbias = off; 95 + return i2c_smbus_write_word_swapped(data->client, 96 + TMP117_REG_TEMP_OFFSET, off); 97 + 98 + default: 99 + return -EINVAL; 100 + } 101 + } 102 + 103 + static const struct iio_chan_spec tmp117_channels[] = { 104 + { 105 + .type = IIO_TEMP, 106 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 107 + BIT(IIO_CHAN_INFO_CALIBBIAS) | BIT(IIO_CHAN_INFO_SCALE), 108 + }, 109 + }; 110 + 111 + static const struct iio_info tmp117_info = { 112 + .read_raw = tmp117_read_raw, 113 + .write_raw = tmp117_write_raw, 114 + }; 115 + 116 + static int tmp117_identify(struct i2c_client *client) 117 + { 118 + int dev_id; 119 + 120 + dev_id = i2c_smbus_read_word_swapped(client, TMP117_REG_DEVICE_ID); 121 + if (dev_id < 0) 122 + return dev_id; 123 + if (dev_id != TMP117_DEVICE_ID) { 124 + dev_err(&client->dev, "TMP117 not found\n"); 125 + return -ENODEV; 126 + } 127 + return 0; 128 + } 129 + 130 + static int tmp117_probe(struct i2c_client *client) 131 + { 132 + struct tmp117_data *data; 133 + struct iio_dev *indio_dev; 134 + int ret; 135 + 136 + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) 137 + return -EOPNOTSUPP; 138 + 139 + ret = tmp117_identify(client); 140 + if (ret < 0) 141 + return ret; 142 + 143 + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 144 + if (!indio_dev) 145 + return -ENOMEM; 146 + 147 + data = iio_priv(indio_dev); 148 + data->client = client; 149 + data->calibbias = 0; 150 + 151 + indio_dev->name = "tmp117"; 152 + indio_dev->modes = INDIO_DIRECT_MODE; 153 + indio_dev->info = &tmp117_info; 154 + 155 + indio_dev->channels = tmp117_channels; 156 + indio_dev->num_channels = ARRAY_SIZE(tmp117_channels); 157 + 158 + return devm_iio_device_register(&client->dev, indio_dev); 159 + } 160 + 161 + static const struct of_device_id tmp117_of_match[] = { 162 + { .compatible = "ti,tmp117", }, 163 + { } 164 + }; 165 + MODULE_DEVICE_TABLE(of, tmp117_of_match); 166 + 167 + static const struct i2c_device_id tmp117_id[] = { 168 + { "tmp117", 0 }, 169 + { } 170 + }; 171 + MODULE_DEVICE_TABLE(i2c, tmp117_id); 172 + 173 + static struct i2c_driver tmp117_driver = { 174 + .driver = { 175 + .name = "tmp117", 176 + .of_match_table = tmp117_of_match, 177 + }, 178 + .probe_new = tmp117_probe, 179 + .id_table = tmp117_id, 180 + }; 181 + module_i2c_driver(tmp117_driver); 182 + 183 + MODULE_AUTHOR("Puranjay Mohan <puranjay12@gmail.com>"); 184 + MODULE_DESCRIPTION("TI TMP117 Temperature sensor driver"); 185 + MODULE_LICENSE("GPL");