aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Muir <john@jmuir.com>2016-12-01 21:32:41 -0500
committerGuenter Roeck <linux@roeck-us.net>2016-12-10 00:54:25 -0500
commit66e1c91713396734f8cf778a2fc5212876c04bc0 (patch)
treebcc4661fa3206bb761cc5391f99d862505fabea3
parent3a412d5e4a1c831723d0aaf305f1cf9a78ad9c90 (diff)
hwmon: Add Texas Instruments TMP108 temperature sensor driver.
Add support for the TI TMP108 temperature sensor with some device configuration parameters. Signed-off-by: John Muir <john@jmuir.com> [groeck: Initialize of_match_table] Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--Documentation/hwmon/tmp10836
-rw-r--r--drivers/hwmon/Kconfig11
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/tmp108.c469
4 files changed, 517 insertions, 0 deletions
diff --git a/Documentation/hwmon/tmp108 b/Documentation/hwmon/tmp108
new file mode 100644
index 000000000000..25802df23010
--- /dev/null
+++ b/Documentation/hwmon/tmp108
@@ -0,0 +1,36 @@
1Kernel driver tmp108
2====================
3
4Supported chips:
5 * Texas Instruments TMP108
6 Prefix: 'tmp108'
7 Addresses scanned: none
8 Datasheet: http://www.ti.com/product/tmp108
9
10Author:
11 John Muir <john@jmuir.com>
12
13Description
14-----------
15
16The Texas Instruments TMP108 implements one temperature sensor. An alert pin
17can be set when temperatures exceed minimum or maximum values plus or minus a
18hysteresis value. (This driver does not support interrupts for the alert pin,
19and the device runs in comparator mode.)
20
21The sensor is accurate to 0.75C over the range of -25 to +85 C, and to 1.0
22degree from -40 to +125 C. Resolution of the sensor is 0.0625 degree. The
23operating temperature has a minimum of -55 C and a maximum of +150 C.
24Hysteresis values can be set to 0, 1, 2, or 4C.
25
26The TMP108 has a programmable update rate that can select between 8, 4, 1, and
270.5 Hz.
28
29By default the TMP108 reads the temperature continuously. To conserve power,
30the TMP108 has a one-shot mode where the device is normally shut-down. When a
31one shot is requested the temperature is read, the result can be retrieved,
32and then the device is shut down automatically. (This driver only supports
33continuous mode.)
34
35The driver provides the common sysfs-interface for temperatures (see
36Documentation/hwmon/sysfs-interface under Temperatures).
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 1adda8a5adce..190d270b20a2 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1602,6 +1602,17 @@ config SENSORS_TMP103
1602 This driver can also be built as a module. If so, the module 1602 This driver can also be built as a module. If so, the module
1603 will be called tmp103. 1603 will be called tmp103.
1604 1604
1605config SENSORS_TMP108
1606 tristate "Texas Instruments TMP108"
1607 depends on I2C
1608 select REGMAP_I2C
1609 help
1610 If you say yes here you get support for Texas Instruments TMP108
1611 sensor chips.
1612
1613 This driver can also be built as a module. If so, the module
1614 will be called tmp108.
1615
1605config SENSORS_TMP401 1616config SENSORS_TMP401
1606 tristate "Texas Instruments TMP401 and compatibles" 1617 tristate "Texas Instruments TMP401 and compatibles"
1607 depends on I2C 1618 depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index c651f0f1d047..d2cb7e804a0f 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -153,6 +153,7 @@ obj-$(CONFIG_SENSORS_TC74) += tc74.o
153obj-$(CONFIG_SENSORS_THMC50) += thmc50.o 153obj-$(CONFIG_SENSORS_THMC50) += thmc50.o
154obj-$(CONFIG_SENSORS_TMP102) += tmp102.o 154obj-$(CONFIG_SENSORS_TMP102) += tmp102.o
155obj-$(CONFIG_SENSORS_TMP103) += tmp103.o 155obj-$(CONFIG_SENSORS_TMP103) += tmp103.o
156obj-$(CONFIG_SENSORS_TMP108) += tmp108.o
156obj-$(CONFIG_SENSORS_TMP401) += tmp401.o 157obj-$(CONFIG_SENSORS_TMP401) += tmp401.o
157obj-$(CONFIG_SENSORS_TMP421) += tmp421.o 158obj-$(CONFIG_SENSORS_TMP421) += tmp421.o
158obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o 159obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o
diff --git a/drivers/hwmon/tmp108.c b/drivers/hwmon/tmp108.c
new file mode 100644
index 000000000000..91bb94639286
--- /dev/null
+++ b/drivers/hwmon/tmp108.c
@@ -0,0 +1,469 @@
1/* Texas Instruments TMP108 SMBus temperature sensor driver
2 *
3 * Copyright (C) 2016 John Muir <john@jmuir.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#include <linux/delay.h>
17#include <linux/device.h>
18#include <linux/err.h>
19#include <linux/hwmon.h>
20#include <linux/hwmon-sysfs.h>
21#include <linux/module.h>
22#include <linux/mutex.h>
23#include <linux/of.h>
24#include <linux/i2c.h>
25#include <linux/init.h>
26#include <linux/jiffies.h>
27#include <linux/regmap.h>
28#include <linux/slab.h>
29
30#define DRIVER_NAME "tmp108"
31
32#define TMP108_REG_TEMP 0x00
33#define TMP108_REG_CONF 0x01
34#define TMP108_REG_TLOW 0x02
35#define TMP108_REG_THIGH 0x03
36
37#define TMP108_TEMP_MIN_MC -50000 /* Minimum millicelcius. */
38#define TMP108_TEMP_MAX_MC 127937 /* Maximum millicelcius. */
39
40/* Configuration register bits.
41 * Note: these bit definitions are byte swapped.
42 */
43#define TMP108_CONF_M0 0x0100 /* Sensor mode. */
44#define TMP108_CONF_M1 0x0200
45#define TMP108_CONF_TM 0x0400 /* Thermostat mode. */
46#define TMP108_CONF_FL 0x0800 /* Watchdog flag - TLOW */
47#define TMP108_CONF_FH 0x1000 /* Watchdog flag - THIGH */
48#define TMP108_CONF_CR0 0x2000 /* Conversion rate. */
49#define TMP108_CONF_CR1 0x4000
50#define TMP108_CONF_ID 0x8000
51#define TMP108_CONF_HYS0 0x0010 /* Hysteresis. */
52#define TMP108_CONF_HYS1 0x0020
53#define TMP108_CONF_POL 0x0080 /* Polarity of alert. */
54
55/* Defaults set by the hardware upon reset. */
56#define TMP108_CONF_DEFAULTS (TMP108_CONF_CR0 | TMP108_CONF_TM |\
57 TMP108_CONF_HYS0 | TMP108_CONF_M1)
58/* These bits are read-only. */
59#define TMP108_CONF_READ_ONLY (TMP108_CONF_FL | TMP108_CONF_FH |\
60 TMP108_CONF_ID)
61
62#define TMP108_CONF_MODE_MASK (TMP108_CONF_M0|TMP108_CONF_M1)
63#define TMP108_MODE_SHUTDOWN 0x0000
64#define TMP108_MODE_ONE_SHOT TMP108_CONF_M0
65#define TMP108_MODE_CONTINUOUS TMP108_CONF_M1 /* Default */
66 /* When M1 is set, M0 is ignored. */
67
68#define TMP108_CONF_CONVRATE_MASK (TMP108_CONF_CR0|TMP108_CONF_CR1)
69#define TMP108_CONVRATE_0P25HZ 0x0000
70#define TMP108_CONVRATE_1HZ TMP108_CONF_CR0 /* Default */
71#define TMP108_CONVRATE_4HZ TMP108_CONF_CR1
72#define TMP108_CONVRATE_16HZ (TMP108_CONF_CR0|TMP108_CONF_CR1)
73
74#define TMP108_CONF_HYSTERESIS_MASK (TMP108_CONF_HYS0|TMP108_CONF_HYS1)
75#define TMP108_HYSTERESIS_0C 0x0000
76#define TMP108_HYSTERESIS_1C TMP108_CONF_HYS0 /* Default */
77#define TMP108_HYSTERESIS_2C TMP108_CONF_HYS1
78#define TMP108_HYSTERESIS_4C (TMP108_CONF_HYS0|TMP108_CONF_HYS1)
79
80#define TMP108_CONVERSION_TIME_MS 30 /* in milli-seconds */
81
82struct tmp108 {
83 struct regmap *regmap;
84 u16 orig_config;
85 unsigned long ready_time;
86};
87
88/* convert 12-bit TMP108 register value to milliCelsius */
89static inline int tmp108_temp_reg_to_mC(s16 val)
90{
91 return (val & ~0x0f) * 1000 / 256;
92}
93
94/* convert milliCelsius to left adjusted 12-bit TMP108 register value */
95static inline u16 tmp108_mC_to_temp_reg(int val)
96{
97 return (val * 256) / 1000;
98}
99
100static int tmp108_read(struct device *dev, enum hwmon_sensor_types type,
101 u32 attr, int channel, long *temp)
102{
103 struct tmp108 *tmp108 = dev_get_drvdata(dev);
104 unsigned int regval;
105 int err, hyst;
106
107 if (type == hwmon_chip) {
108 if (attr == hwmon_chip_update_interval) {
109 err = regmap_read(tmp108->regmap, TMP108_REG_CONF,
110 &regval);
111 if (err < 0)
112 return err;
113 switch (regval & TMP108_CONF_CONVRATE_MASK) {
114 case TMP108_CONVRATE_0P25HZ:
115 default:
116 *temp = 4000;
117 break;
118 case TMP108_CONVRATE_1HZ:
119 *temp = 1000;
120 break;
121 case TMP108_CONVRATE_4HZ:
122 *temp = 250;
123 break;
124 case TMP108_CONVRATE_16HZ:
125 *temp = 63;
126 break;
127 }
128 return 0;
129 }
130 return -EOPNOTSUPP;
131 }
132
133 switch (attr) {
134 case hwmon_temp_input:
135 /* Is it too early to return a conversion ? */
136 if (time_before(jiffies, tmp108->ready_time)) {
137 dev_dbg(dev, "%s: Conversion not ready yet..\n",
138 __func__);
139 return -EAGAIN;
140 }
141 err = regmap_read(tmp108->regmap, TMP108_REG_TEMP, &regval);
142 if (err < 0)
143 return err;
144 *temp = tmp108_temp_reg_to_mC(regval);
145 break;
146 case hwmon_temp_min:
147 case hwmon_temp_max:
148 err = regmap_read(tmp108->regmap, attr == hwmon_temp_min ?
149 TMP108_REG_TLOW : TMP108_REG_THIGH, &regval);
150 if (err < 0)
151 return err;
152 *temp = tmp108_temp_reg_to_mC(regval);
153 break;
154 case hwmon_temp_min_alarm:
155 case hwmon_temp_max_alarm:
156 err = regmap_read(tmp108->regmap, TMP108_REG_CONF, &regval);
157 if (err < 0)
158 return err;
159 *temp = !!(regval & (attr == hwmon_temp_min_alarm ?
160 TMP108_CONF_FL : TMP108_CONF_FH));
161 break;
162 case hwmon_temp_min_hyst:
163 case hwmon_temp_max_hyst:
164 err = regmap_read(tmp108->regmap, TMP108_REG_CONF, &regval);
165 if (err < 0)
166 return err;
167 switch (regval & TMP108_CONF_HYSTERESIS_MASK) {
168 case TMP108_HYSTERESIS_0C:
169 default:
170 hyst = 0;
171 break;
172 case TMP108_HYSTERESIS_1C:
173 hyst = 1000;
174 break;
175 case TMP108_HYSTERESIS_2C:
176 hyst = 2000;
177 break;
178 case TMP108_HYSTERESIS_4C:
179 hyst = 4000;
180 break;
181 }
182 err = regmap_read(tmp108->regmap, attr == hwmon_temp_min_hyst ?
183 TMP108_REG_TLOW : TMP108_REG_THIGH, &regval);
184 if (err < 0)
185 return err;
186 *temp = tmp108_temp_reg_to_mC(regval);
187 if (attr == hwmon_temp_min_hyst)
188 *temp += hyst;
189 else
190 *temp -= hyst;
191 break;
192 default:
193 return -EOPNOTSUPP;
194 }
195
196 return 0;
197}
198
199static int tmp108_write(struct device *dev, enum hwmon_sensor_types type,
200 u32 attr, int channel, long temp)
201{
202 struct tmp108 *tmp108 = dev_get_drvdata(dev);
203 u32 regval, mask;
204 int err;
205
206 if (type == hwmon_chip) {
207 if (attr == hwmon_chip_update_interval) {
208 if (temp < 156)
209 mask = TMP108_CONVRATE_16HZ;
210 else if (temp < 625)
211 mask = TMP108_CONVRATE_4HZ;
212 else if (temp < 2500)
213 mask = TMP108_CONVRATE_1HZ;
214 else
215 mask = TMP108_CONVRATE_0P25HZ;
216 return regmap_update_bits(tmp108->regmap,
217 TMP108_REG_CONF,
218 TMP108_CONF_CONVRATE_MASK,
219 mask);
220 }
221 return -EOPNOTSUPP;
222 }
223
224 switch (attr) {
225 case hwmon_temp_min:
226 case hwmon_temp_max:
227 temp = clamp_val(temp, TMP108_TEMP_MIN_MC, TMP108_TEMP_MAX_MC);
228 return regmap_write(tmp108->regmap,
229 attr == hwmon_temp_min ?
230 TMP108_REG_TLOW : TMP108_REG_THIGH,
231 tmp108_mC_to_temp_reg(temp));
232 case hwmon_temp_min_hyst:
233 case hwmon_temp_max_hyst:
234 temp = clamp_val(temp, TMP108_TEMP_MIN_MC, TMP108_TEMP_MAX_MC);
235 err = regmap_read(tmp108->regmap,
236 attr == hwmon_temp_min_hyst ?
237 TMP108_REG_TLOW : TMP108_REG_THIGH,
238 &regval);
239 if (err < 0)
240 return err;
241 if (attr == hwmon_temp_min_hyst)
242 temp -= tmp108_temp_reg_to_mC(regval);
243 else
244 temp = tmp108_temp_reg_to_mC(regval) - temp;
245 if (temp < 500)
246 mask = TMP108_HYSTERESIS_0C;
247 else if (temp < 1500)
248 mask = TMP108_HYSTERESIS_1C;
249 else if (temp < 3000)
250 mask = TMP108_HYSTERESIS_2C;
251 else
252 mask = TMP108_HYSTERESIS_4C;
253 return regmap_update_bits(tmp108->regmap, TMP108_REG_CONF,
254 TMP108_CONF_HYSTERESIS_MASK, mask);
255 default:
256 return -EOPNOTSUPP;
257 }
258}
259
260static umode_t tmp108_is_visible(const void *data, enum hwmon_sensor_types type,
261 u32 attr, int channel)
262{
263 if (type == hwmon_chip && attr == hwmon_chip_update_interval)
264 return 0644;
265
266 if (type != hwmon_temp)
267 return 0;
268
269 switch (attr) {
270 case hwmon_temp_input:
271 case hwmon_temp_min_alarm:
272 case hwmon_temp_max_alarm:
273 return 0444;
274 case hwmon_temp_min:
275 case hwmon_temp_max:
276 case hwmon_temp_min_hyst:
277 case hwmon_temp_max_hyst:
278 return 0644;
279 default:
280 return 0;
281 }
282}
283
284static u32 tmp108_chip_config[] = {
285 HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL,
286 0
287};
288
289static const struct hwmon_channel_info tmp108_chip = {
290 .type = hwmon_chip,
291 .config = tmp108_chip_config,
292};
293
294static u32 tmp108_temp_config[] = {
295 HWMON_T_INPUT | HWMON_T_MAX | HWMON_T_MIN | HWMON_T_MIN_HYST
296 | HWMON_T_MAX_HYST | HWMON_T_MIN_ALARM | HWMON_T_MAX_ALARM,
297 0
298};
299
300static const struct hwmon_channel_info tmp108_temp = {
301 .type = hwmon_temp,
302 .config = tmp108_temp_config,
303};
304
305static const struct hwmon_channel_info *tmp108_info[] = {
306 &tmp108_chip,
307 &tmp108_temp,
308 NULL
309};
310
311static const struct hwmon_ops tmp108_hwmon_ops = {
312 .is_visible = tmp108_is_visible,
313 .read = tmp108_read,
314 .write = tmp108_write,
315};
316
317static const struct hwmon_chip_info tmp108_chip_info = {
318 .ops = &tmp108_hwmon_ops,
319 .info = tmp108_info,
320};
321
322static void tmp108_restore_config(void *data)
323{
324 struct tmp108 *tmp108 = data;
325
326 regmap_write(tmp108->regmap, TMP108_REG_CONF, tmp108->orig_config);
327}
328
329static bool tmp108_is_writeable_reg(struct device *dev, unsigned int reg)
330{
331 return reg != TMP108_REG_TEMP;
332}
333
334static bool tmp108_is_volatile_reg(struct device *dev, unsigned int reg)
335{
336 /* Configuration register must be volatile to enable FL and FH. */
337 return reg == TMP108_REG_TEMP || reg == TMP108_REG_CONF;
338}
339
340static const struct regmap_config tmp108_regmap_config = {
341 .reg_bits = 8,
342 .val_bits = 16,
343 .max_register = TMP108_REG_THIGH,
344 .writeable_reg = tmp108_is_writeable_reg,
345 .volatile_reg = tmp108_is_volatile_reg,
346 .val_format_endian = REGMAP_ENDIAN_BIG,
347 .cache_type = REGCACHE_RBTREE,
348 .use_single_rw = true,
349};
350
351static int tmp108_probe(struct i2c_client *client,
352 const struct i2c_device_id *id)
353{
354 struct device *dev = &client->dev;
355 struct device *hwmon_dev;
356 struct tmp108 *tmp108;
357 int err;
358 u32 config;
359
360 if (!i2c_check_functionality(client->adapter,
361 I2C_FUNC_SMBUS_WORD_DATA)) {
362 dev_err(dev,
363 "adapter doesn't support SMBus word transactions\n");
364 return -ENODEV;
365 }
366
367 tmp108 = devm_kzalloc(dev, sizeof(*tmp108), GFP_KERNEL);
368 if (!tmp108)
369 return -ENOMEM;
370
371 dev_set_drvdata(dev, tmp108);
372
373 tmp108->regmap = devm_regmap_init_i2c(client, &tmp108_regmap_config);
374 if (IS_ERR(tmp108->regmap)) {
375 err = PTR_ERR(tmp108->regmap);
376 dev_err(dev, "regmap init failed: %d", err);
377 return err;
378 }
379
380 err = regmap_read(tmp108->regmap, TMP108_REG_CONF, &config);
381 if (err < 0) {
382 dev_err(dev, "error reading config register: %d", err);
383 return err;
384 }
385 tmp108->orig_config = config;
386
387 /* Only continuous mode is supported. */
388 config &= ~TMP108_CONF_MODE_MASK;
389 config |= TMP108_MODE_CONTINUOUS;
390
391 /* Only comparator mode is supported. */
392 config &= ~TMP108_CONF_TM;
393
394 err = regmap_write(tmp108->regmap, TMP108_REG_CONF, config);
395 if (err < 0) {
396 dev_err(dev, "error writing config register: %d", err);
397 return err;
398 }
399
400 tmp108->ready_time = jiffies;
401 if ((tmp108->orig_config & TMP108_CONF_MODE_MASK) ==
402 TMP108_MODE_SHUTDOWN)
403 tmp108->ready_time +=
404 msecs_to_jiffies(TMP108_CONVERSION_TIME_MS);
405
406 err = devm_add_action_or_reset(dev, tmp108_restore_config, tmp108);
407 if (err) {
408 dev_err(dev, "add action or reset failed: %d", err);
409 return err;
410 }
411
412 hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
413 tmp108,
414 &tmp108_chip_info,
415 NULL);
416 return PTR_ERR_OR_ZERO(hwmon_dev);
417}
418
419static int __maybe_unused tmp108_suspend(struct device *dev)
420{
421 struct tmp108 *tmp108 = dev_get_drvdata(dev);
422
423 return regmap_update_bits(tmp108->regmap, TMP108_REG_CONF,
424 TMP108_CONF_MODE_MASK, TMP108_MODE_SHUTDOWN);
425}
426
427static int __maybe_unused tmp108_resume(struct device *dev)
428{
429 struct tmp108 *tmp108 = dev_get_drvdata(dev);
430 int err;
431
432 err = regmap_update_bits(tmp108->regmap, TMP108_REG_CONF,
433 TMP108_CONF_MODE_MASK, TMP108_MODE_CONTINUOUS);
434 tmp108->ready_time = jiffies +
435 msecs_to_jiffies(TMP108_CONVERSION_TIME_MS);
436 return err;
437}
438
439static SIMPLE_DEV_PM_OPS(tmp108_dev_pm_ops, tmp108_suspend, tmp108_resume);
440
441static const struct i2c_device_id tmp108_i2c_ids[] = {
442 { "tmp108", 0 },
443 { }
444};
445MODULE_DEVICE_TABLE(i2c, tmp108_i2c_ids);
446
447#ifdef CONFIG_OF
448static const struct of_device_id tmp108_of_ids[] = {
449 { .compatible = "ti,tmp108", },
450 {}
451};
452MODULE_DEVICE_TABLE(of, tmp108_of_ids);
453#endif
454
455static struct i2c_driver tmp108_driver = {
456 .driver = {
457 .name = DRIVER_NAME,
458 .pm = &tmp108_dev_pm_ops,
459 .of_match_table = of_match_ptr(tmp108_of_ids),
460 },
461 .probe = tmp108_probe,
462 .id_table = tmp108_i2c_ids,
463};
464
465module_i2c_driver(tmp108_driver);
466
467MODULE_AUTHOR("John Muir <john@jmuir.com>");
468MODULE_DESCRIPTION("Texas Instruments TMP108 temperature sensor driver");
469MODULE_LICENSE("GPL");