aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorWilliam Markezana <william.markezana@meas-spec.com>2013-08-29 07:51:42 -0400
committerGuenter Roeck <linux@roeck-us.net>2013-08-29 12:09:12 -0400
commitf060c658b820141f18abd7b71586d628464a03ea (patch)
tree5dfa63c65d7417466eec8fefff33fd892e463ade /drivers/hwmon
parent5407e051354bdd943f6ea66562112c9868d64cf5 (diff)
hwmon: (htu21) Add Measurement Specialties HTU21D support
Signed-off-by: William Markezana <william.markezana@meas-spec.com> [Guenter Roeck - minor formatting changes] Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/Kconfig10
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/htu21.c199
3 files changed, 210 insertions, 0 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 0ff09d8d987b..b3ab9d43bb3e 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -511,6 +511,16 @@ config SENSORS_HIH6130
511 This driver can also be built as a module. If so, the module 511 This driver can also be built as a module. If so, the module
512 will be called hih6130. 512 will be called hih6130.
513 513
514config SENSORS_HTU21
515 tristate "Measurement Specialties HTU21D humidity/temperature sensors"
516 depends on I2C
517 help
518 If you say yes here you get support for the Measurement Specialties
519 HTU21D humidity and temperature sensors.
520
521 This driver can also be built as a module. If so, the module
522 will be called htu21.
523
514config SENSORS_CORETEMP 524config SENSORS_CORETEMP
515 tristate "Intel Core/Core2/Atom temperature sensor" 525 tristate "Intel Core/Core2/Atom temperature sensor"
516 depends on X86 526 depends on X86
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 4f0fb5235f42..ec7cde06eb52 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
65obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o 65obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
66obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o 66obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o
67obj-$(CONFIG_SENSORS_HIH6130) += hih6130.o 67obj-$(CONFIG_SENSORS_HIH6130) += hih6130.o
68obj-$(CONFIG_SENSORS_HTU21) += htu21.o
68obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o 69obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o
69obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o 70obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
70obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o 71obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o
diff --git a/drivers/hwmon/htu21.c b/drivers/hwmon/htu21.c
new file mode 100644
index 000000000000..839086e0e951
--- /dev/null
+++ b/drivers/hwmon/htu21.c
@@ -0,0 +1,199 @@
1/*
2 * Measurement Specialties HTU21D humidity and temperature sensor driver
3 *
4 * Copyright (C) 2013 William Markezana <william.markezana@meas-spec.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/init.h>
20#include <linux/slab.h>
21#include <linux/i2c.h>
22#include <linux/hwmon.h>
23#include <linux/hwmon-sysfs.h>
24#include <linux/err.h>
25#include <linux/mutex.h>
26#include <linux/device.h>
27#include <linux/jiffies.h>
28
29/* HTU21 Commands */
30#define HTU21_T_MEASUREMENT_HM 0xE3
31#define HTU21_RH_MEASUREMENT_HM 0xE5
32
33struct htu21 {
34 struct device *hwmon_dev;
35 struct mutex lock;
36 bool valid;
37 unsigned long last_update;
38 int temperature;
39 int humidity;
40};
41
42static inline int htu21_temp_ticks_to_millicelsius(int ticks)
43{
44 ticks &= ~0x0003; /* clear status bits */
45 /*
46 * Formula T = -46.85 + 175.72 * ST / 2^16 from datasheet p14,
47 * optimized for integer fixed point (3 digits) arithmetic
48 */
49 return ((21965 * ticks) >> 13) - 46850;
50}
51
52static inline int htu21_rh_ticks_to_per_cent_mille(int ticks)
53{
54 ticks &= ~0x0003; /* clear status bits */
55 /*
56 * Formula RH = -6 + 125 * SRH / 2^16 from datasheet p14,
57 * optimized for integer fixed point (3 digits) arithmetic
58 */
59 return ((15625 * ticks) >> 13) - 6000;
60}
61
62static int htu21_update_measurements(struct i2c_client *client)
63{
64 int ret = 0;
65 struct htu21 *htu21 = i2c_get_clientdata(client);
66
67 mutex_lock(&htu21->lock);
68
69 if (time_after(jiffies, htu21->last_update + HZ / 2) ||
70 !htu21->valid) {
71 ret = i2c_smbus_read_word_swapped(client,
72 HTU21_T_MEASUREMENT_HM);
73 if (ret < 0)
74 goto out;
75 htu21->temperature = htu21_temp_ticks_to_millicelsius(ret);
76 ret = i2c_smbus_read_word_swapped(client,
77 HTU21_RH_MEASUREMENT_HM);
78 if (ret < 0)
79 goto out;
80 htu21->humidity = htu21_rh_ticks_to_per_cent_mille(ret);
81 htu21->last_update = jiffies;
82 htu21->valid = true;
83 }
84out:
85 mutex_unlock(&htu21->lock);
86
87 return ret >= 0 ? 0 : ret;
88}
89
90static ssize_t htu21_show_temperature(struct device *dev,
91 struct device_attribute *attr, char *buf)
92{
93 struct i2c_client *client = to_i2c_client(dev);
94 struct htu21 *htu21 = i2c_get_clientdata(client);
95 int ret = htu21_update_measurements(client);
96 if (ret < 0)
97 return ret;
98 return sprintf(buf, "%d\n", htu21->temperature);
99}
100
101static ssize_t htu21_show_humidity(struct device *dev,
102 struct device_attribute *attr, char *buf)
103{
104 struct i2c_client *client = to_i2c_client(dev);
105 struct htu21 *htu21 = i2c_get_clientdata(client);
106 int ret = htu21_update_measurements(client);
107 if (ret < 0)
108 return ret;
109 return sprintf(buf, "%d\n", htu21->humidity);
110}
111
112static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
113 htu21_show_temperature, NULL, 0);
114static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO,
115 htu21_show_humidity, NULL, 0);
116
117static struct attribute *htu21_attributes[] = {
118 &sensor_dev_attr_temp1_input.dev_attr.attr,
119 &sensor_dev_attr_humidity1_input.dev_attr.attr,
120 NULL
121};
122
123static const struct attribute_group htu21_group = {
124 .attrs = htu21_attributes,
125};
126
127static int htu21_probe(struct i2c_client *client,
128 const struct i2c_device_id *id)
129{
130 struct htu21 *htu21;
131 int err;
132
133 if (!i2c_check_functionality(client->adapter,
134 I2C_FUNC_SMBUS_READ_WORD_DATA)) {
135 dev_err(&client->dev,
136 "adapter does not support SMBus word transactions\n");
137 return -ENODEV;
138 }
139
140 htu21 = devm_kzalloc(&client->dev, sizeof(*htu21), GFP_KERNEL);
141 if (!htu21)
142 return -ENOMEM;
143
144 i2c_set_clientdata(client, htu21);
145
146 mutex_init(&htu21->lock);
147
148 err = sysfs_create_group(&client->dev.kobj, &htu21_group);
149 if (err) {
150 dev_dbg(&client->dev, "could not create sysfs files\n");
151 return err;
152 }
153 htu21->hwmon_dev = hwmon_device_register(&client->dev);
154 if (IS_ERR(htu21->hwmon_dev)) {
155 dev_dbg(&client->dev, "unable to register hwmon device\n");
156 err = PTR_ERR(htu21->hwmon_dev);
157 goto error;
158 }
159
160 dev_info(&client->dev, "initialized\n");
161
162 return 0;
163
164error:
165 sysfs_remove_group(&client->dev.kobj, &htu21_group);
166 return err;
167}
168
169static int htu21_remove(struct i2c_client *client)
170{
171 struct htu21 *htu21 = i2c_get_clientdata(client);
172
173 hwmon_device_unregister(htu21->hwmon_dev);
174 sysfs_remove_group(&client->dev.kobj, &htu21_group);
175
176 return 0;
177}
178
179static const struct i2c_device_id htu21_id[] = {
180 { "htu21", 0 },
181 { }
182};
183MODULE_DEVICE_TABLE(i2c, htu21_id);
184
185static struct i2c_driver htu21_driver = {
186 .class = I2C_CLASS_HWMON,
187 .driver = {
188 .name = "htu21",
189 },
190 .probe = htu21_probe,
191 .remove = htu21_remove,
192 .id_table = htu21_id,
193};
194
195module_i2c_driver(htu21_driver);
196
197MODULE_AUTHOR("William Markezana <william.markezana@meas-spec.com>");
198MODULE_DESCRIPTION("MEAS HTU21D humidity and temperature sensor driver");
199MODULE_LICENSE("GPL");