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

hwmon: Driver for TI TMP103 temperature sensor

Driver for the TI TMP103.

The TI TMP103 is similar to the TMP102. It differs from the TMP102
by having only 8 bit registers.

Signed-off-by: Heiko Schocher <hs@denx.de>
[linux@roeck-us.net: Select REGMAP_I2C in Kconfig]
Signed-off-by: Guenter Roeck <linux@roeck-us.net>

authored by

Heiko Schocher and committed by
Guenter Roeck
d17a7dca 49153b09

+246
+1
Documentation/devicetree/bindings/i2c/trivial-devices.txt
··· 83 83 taos,tsl2550 Ambient Light Sensor with SMBUS/Two Wire Serial Interface 84 84 ti,tsc2003 I2C Touch-Screen Controller 85 85 ti,tmp102 Low Power Digital Temperature Sensor with SMBUS/Two Wire Serial Interface 86 + ti,tmp103 Low Power Digital Temperature Sensor with SMBUS/Two Wire Serial Interface 86 87 ti,tmp275 Digital Temperature Sensor 87 88 winbond,wpct301 i2c trusted platform module (TPM)
+28
Documentation/hwmon/tmp103
··· 1 + Kernel driver tmp103 2 + ==================== 3 + 4 + Supported chips: 5 + * Texas Instruments TMP103 6 + Prefix: 'tmp103' 7 + Addresses scanned: none 8 + Product info and datasheet: http://www.ti.com/product/tmp103 9 + 10 + Author: 11 + Heiko Schocher <hs@denx.de> 12 + 13 + Description 14 + ----------- 15 + 16 + The TMP103 is a digital output temperature sensor in a four-ball 17 + wafer chip-scale package (WCSP). The TMP103 is capable of reading 18 + temperatures to a resolution of 1°C. The TMP103 is specified for 19 + operation over a temperature range of –40°C to +125°C. 20 + 21 + Resolution: 8 Bits 22 + Accuracy: ±1°C Typ (–10°C to +100°C) 23 + 24 + The driver provides the common sysfs-interface for temperatures (see 25 + Documentation/hwmon/sysfs-interface under Temperatures). 26 + 27 + Please refer how to instantiate this driver: 28 + Documentation/i2c/instantiating-devices
+11
drivers/hwmon/Kconfig
··· 1405 1405 This driver can also be built as a module. If so, the module 1406 1406 will be called tmp102. 1407 1407 1408 + config SENSORS_TMP103 1409 + tristate "Texas Instruments TMP103" 1410 + depends on I2C 1411 + select REGMAP_I2C 1412 + help 1413 + If you say yes here you get support for Texas Instruments TMP103 1414 + sensor chips. 1415 + 1416 + This driver can also be built as a module. If so, the module 1417 + will be called tmp103. 1418 + 1408 1419 config SENSORS_TMP401 1409 1420 tristate "Texas Instruments TMP401 and compatibles" 1410 1421 depends on I2C
+1
drivers/hwmon/Makefile
··· 136 136 obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o 137 137 obj-$(CONFIG_SENSORS_THMC50) += thmc50.o 138 138 obj-$(CONFIG_SENSORS_TMP102) += tmp102.o 139 + obj-$(CONFIG_SENSORS_TMP103) += tmp103.o 139 140 obj-$(CONFIG_SENSORS_TMP401) += tmp401.o 140 141 obj-$(CONFIG_SENSORS_TMP421) += tmp421.o 141 142 obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o
+205
drivers/hwmon/tmp103.c
··· 1 + /* 2 + * Texas Instruments TMP103 SMBus temperature sensor driver 3 + * Copyright (C) 2014 Heiko Schocher <hs@denx.de> 4 + * 5 + * Based on: 6 + * Texas Instruments TMP102 SMBus temperature sensor driver 7 + * 8 + * Copyright (C) 2010 Steven King <sfking@fdwdc.com> 9 + * 10 + * This program is free software; you can redistribute it and/or modify 11 + * it under the terms of the GNU General Public License as published by 12 + * the Free Software Foundation; either version 2 of the License, or 13 + * (at your option) any later version. 14 + * 15 + * This program is distributed in the hope that it will be useful, 16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 + * GNU General Public License for more details. 19 + * 20 + */ 21 + 22 + #include <linux/module.h> 23 + #include <linux/init.h> 24 + #include <linux/slab.h> 25 + #include <linux/i2c.h> 26 + #include <linux/hwmon.h> 27 + #include <linux/hwmon-sysfs.h> 28 + #include <linux/err.h> 29 + #include <linux/mutex.h> 30 + #include <linux/device.h> 31 + #include <linux/jiffies.h> 32 + #include <linux/regmap.h> 33 + 34 + #define TMP103_TEMP_REG 0x00 35 + #define TMP103_CONF_REG 0x01 36 + #define TMP103_TLOW_REG 0x02 37 + #define TMP103_THIGH_REG 0x03 38 + 39 + #define TMP103_CONF_M0 0x01 40 + #define TMP103_CONF_M1 0x02 41 + #define TMP103_CONF_LC 0x04 42 + #define TMP103_CONF_FL 0x08 43 + #define TMP103_CONF_FH 0x10 44 + #define TMP103_CONF_CR0 0x20 45 + #define TMP103_CONF_CR1 0x40 46 + #define TMP103_CONF_ID 0x80 47 + #define TMP103_CONF_SD (TMP103_CONF_M1) 48 + #define TMP103_CONF_SD_MASK (TMP103_CONF_M0 | TMP103_CONF_M1) 49 + 50 + #define TMP103_CONFIG (TMP103_CONF_CR1 | TMP103_CONF_M1) 51 + #define TMP103_CONFIG_MASK (TMP103_CONF_CR0 | TMP103_CONF_CR1 | \ 52 + TMP103_CONF_M0 | TMP103_CONF_M1) 53 + 54 + static inline int tmp103_reg_to_mc(s8 val) 55 + { 56 + return val * 1000; 57 + } 58 + 59 + static inline u8 tmp103_mc_to_reg(int val) 60 + { 61 + return DIV_ROUND_CLOSEST(val, 1000); 62 + } 63 + 64 + static ssize_t tmp103_show_temp(struct device *dev, 65 + struct device_attribute *attr, 66 + char *buf) 67 + { 68 + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); 69 + struct regmap *regmap = dev_get_drvdata(dev); 70 + unsigned int regval; 71 + int ret; 72 + 73 + ret = regmap_read(regmap, sda->index, &regval); 74 + if (ret < 0) 75 + return ret; 76 + 77 + return sprintf(buf, "%d\n", tmp103_reg_to_mc(regval)); 78 + } 79 + 80 + static ssize_t tmp103_set_temp(struct device *dev, 81 + struct device_attribute *attr, 82 + const char *buf, size_t count) 83 + { 84 + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); 85 + struct regmap *regmap = dev_get_drvdata(dev); 86 + long val; 87 + int ret; 88 + 89 + if (kstrtol(buf, 10, &val) < 0) 90 + return -EINVAL; 91 + 92 + val = clamp_val(val, -55000, 127000); 93 + ret = regmap_write(regmap, sda->index, tmp103_mc_to_reg(val)); 94 + return ret ? ret : count; 95 + } 96 + 97 + static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp103_show_temp, NULL , 98 + TMP103_TEMP_REG); 99 + 100 + static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, tmp103_show_temp, 101 + tmp103_set_temp, TMP103_TLOW_REG); 102 + 103 + static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp103_show_temp, 104 + tmp103_set_temp, TMP103_THIGH_REG); 105 + 106 + static struct attribute *tmp103_attrs[] = { 107 + &sensor_dev_attr_temp1_input.dev_attr.attr, 108 + &sensor_dev_attr_temp1_min.dev_attr.attr, 109 + &sensor_dev_attr_temp1_max.dev_attr.attr, 110 + NULL 111 + }; 112 + ATTRIBUTE_GROUPS(tmp103); 113 + 114 + static bool tmp103_regmap_is_volatile(struct device *dev, unsigned int reg) 115 + { 116 + return reg == TMP103_TEMP_REG; 117 + } 118 + 119 + static struct regmap_config tmp103_regmap_config = { 120 + .reg_bits = 8, 121 + .val_bits = 8, 122 + .max_register = TMP103_THIGH_REG, 123 + .volatile_reg = tmp103_regmap_is_volatile, 124 + }; 125 + 126 + static int tmp103_probe(struct i2c_client *client, 127 + const struct i2c_device_id *id) 128 + { 129 + struct device *dev = &client->dev; 130 + struct device *hwmon_dev; 131 + struct regmap *regmap; 132 + int ret; 133 + 134 + if (!i2c_check_functionality(client->adapter, 135 + I2C_FUNC_SMBUS_BYTE_DATA)) { 136 + dev_err(&client->dev, 137 + "adapter doesn't support SMBus byte transactions\n"); 138 + return -ENODEV; 139 + } 140 + 141 + regmap = devm_regmap_init_i2c(client, &tmp103_regmap_config); 142 + if (IS_ERR(regmap)) { 143 + dev_err(dev, "failed to allocate register map\n"); 144 + return PTR_ERR(regmap); 145 + } 146 + 147 + ret = regmap_update_bits(regmap, TMP103_CONF_REG, TMP103_CONFIG_MASK, 148 + TMP103_CONFIG); 149 + if (ret < 0) { 150 + dev_err(&client->dev, "error writing config register\n"); 151 + return ret; 152 + } 153 + 154 + hwmon_dev = hwmon_device_register_with_groups(dev, client->name, 155 + regmap, tmp103_groups); 156 + return PTR_ERR_OR_ZERO(hwmon_dev); 157 + } 158 + 159 + #ifdef CONFIG_PM 160 + static int tmp103_suspend(struct device *dev) 161 + { 162 + struct regmap *regmap = dev_get_drvdata(dev); 163 + 164 + return regmap_update_bits(regmap, TMP103_CONF_REG, 165 + TMP103_CONF_SD_MASK, 0); 166 + } 167 + 168 + static int tmp103_resume(struct device *dev) 169 + { 170 + struct regmap *regmap = dev_get_drvdata(dev); 171 + 172 + return regmap_update_bits(regmap, TMP103_CONF_REG, 173 + TMP103_CONF_SD_MASK, TMP103_CONF_SD); 174 + } 175 + 176 + static const struct dev_pm_ops tmp103_dev_pm_ops = { 177 + .suspend = tmp103_suspend, 178 + .resume = tmp103_resume, 179 + }; 180 + 181 + #define TMP103_DEV_PM_OPS (&tmp103_dev_pm_ops) 182 + #else 183 + #define TMP103_DEV_PM_OPS NULL 184 + #endif /* CONFIG_PM */ 185 + 186 + static const struct i2c_device_id tmp103_id[] = { 187 + { "tmp103", 0 }, 188 + { } 189 + }; 190 + MODULE_DEVICE_TABLE(i2c, tmp103_id); 191 + 192 + static struct i2c_driver tmp103_driver = { 193 + .driver = { 194 + .name = "tmp103", 195 + .pm = TMP103_DEV_PM_OPS, 196 + }, 197 + .probe = tmp103_probe, 198 + .id_table = tmp103_id, 199 + }; 200 + 201 + module_i2c_driver(tmp103_driver); 202 + 203 + MODULE_AUTHOR("Heiko Schocher <hs@denx.de>"); 204 + MODULE_DESCRIPTION("Texas Instruments TMP103 temperature sensor driver"); 205 + MODULE_LICENSE("GPL");