aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Pop <Tomas.Pop@sensirion.com>2014-06-05 18:24:19 -0400
committerGuenter Roeck <linux@roeck-us.net>2014-06-12 11:36:48 -0400
commit1a539d372edd9832444e7a3daa710c444c014dc9 (patch)
treeae4029bc700a6f66752276477f00f39cd4b6dee5
parent31e3879127d4db56ad445fd948ca39c393ee65d7 (diff)
hwmon: add support for Sensirion SHTC1 sensor
Add support for Sensirion SHTC1 and compatible temperature and humidity sensors. Signed-off-by: Tomas Pop <tomas.pop@sensirion.com> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--Documentation/hwmon/shtc143
-rw-r--r--drivers/hwmon/Kconfig10
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/shtc1.c251
-rw-r--r--include/linux/platform_data/shtc1.h23
5 files changed, 328 insertions, 0 deletions
diff --git a/Documentation/hwmon/shtc1 b/Documentation/hwmon/shtc1
new file mode 100644
index 000000000000..6b1e05458f0f
--- /dev/null
+++ b/Documentation/hwmon/shtc1
@@ -0,0 +1,43 @@
1Kernel driver shtc1
2===================
3
4Supported chips:
5 * Sensirion SHTC1
6 Prefix: 'shtc1'
7 Addresses scanned: none
8 Datasheet: http://www.sensirion.com/file/datasheet_shtc1
9
10 * Sensirion SHTW1
11 Prefix: 'shtw1'
12 Addresses scanned: none
13 Datasheet: Not publicly available
14
15Author:
16 Johannes Winkelmann <johannes.winkelmann@sensirion.com>
17
18Description
19-----------
20
21This driver implements support for the Sensirion SHTC1 chip, a humidity and
22temperature sensor. Temperature is measured in degrees celsius, relative
23humidity is expressed as a percentage. Driver can be used as well for SHTW1
24chip, which has the same electrical interface.
25
26The device communicates with the I2C protocol. All sensors are set to I2C
27address 0x70. See Documentation/i2c/instantiating-devices for methods to
28instantiate the device.
29
30There are two options configurable by means of shtc1_platform_data:
311. blocking (pull the I2C clock line down while performing the measurement) or
32 non-blocking mode. Blocking mode will guarantee the fastest result but
33 the I2C bus will be busy during that time. By default, non-blocking mode
34 is used. Make sure clock-stretching works properly on your device if you
35 want to use blocking mode.
362. high or low accuracy. High accuracy is used by default and using it is
37 strongly recommended.
38
39sysfs-Interface
40---------------
41
42temp1_input - temperature input
43humidity1_input - humidity input
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 00343166feb1..08531a128f53 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1124,6 +1124,16 @@ config SENSORS_SHT21
1124 This driver can also be built as a module. If so, the module 1124 This driver can also be built as a module. If so, the module
1125 will be called sht21. 1125 will be called sht21.
1126 1126
1127config SENSORS_SHTC1
1128 tristate "Sensiron humidity and temperature sensors. SHTC1 and compat."
1129 depends on I2C
1130 help
1131 If you say yes here you get support for the Sensiron SHTC1 and SHTW1
1132 humidity and temperature sensors.
1133
1134 This driver can also be built as a module. If so, the module
1135 will be called shtc1.
1136
1127config SENSORS_S3C 1137config SENSORS_S3C
1128 tristate "Samsung built-in ADC" 1138 tristate "Samsung built-in ADC"
1129 depends on S3C_ADC 1139 depends on S3C_ADC
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 11798ad7e801..3dc0f02f71d2 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -126,6 +126,7 @@ obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
126obj-$(CONFIG_SENSORS_SCH5636) += sch5636.o 126obj-$(CONFIG_SENSORS_SCH5636) += sch5636.o
127obj-$(CONFIG_SENSORS_SHT15) += sht15.o 127obj-$(CONFIG_SENSORS_SHT15) += sht15.o
128obj-$(CONFIG_SENSORS_SHT21) += sht21.o 128obj-$(CONFIG_SENSORS_SHT21) += sht21.o
129obj-$(CONFIG_SENSORS_SHTC1) += shtc1.o
129obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o 130obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
130obj-$(CONFIG_SENSORS_SMM665) += smm665.o 131obj-$(CONFIG_SENSORS_SMM665) += smm665.o
131obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o 132obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
diff --git a/drivers/hwmon/shtc1.c b/drivers/hwmon/shtc1.c
new file mode 100644
index 000000000000..decd7df995ab
--- /dev/null
+++ b/drivers/hwmon/shtc1.c
@@ -0,0 +1,251 @@
1/* Sensirion SHTC1 humidity and temperature sensor driver
2 *
3 * Copyright (C) 2014 Sensirion AG, Switzerland
4 * Author: Johannes Winkelmann <johannes.winkelmann@sensirion.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/delay.h>
26#include <linux/platform_data/shtc1.h>
27
28/* commands (high precision mode) */
29static const unsigned char shtc1_cmd_measure_blocking_hpm[] = { 0x7C, 0xA2 };
30static const unsigned char shtc1_cmd_measure_nonblocking_hpm[] = { 0x78, 0x66 };
31
32/* commands (low precision mode) */
33static const unsigned char shtc1_cmd_measure_blocking_lpm[] = { 0x64, 0x58 };
34static const unsigned char shtc1_cmd_measure_nonblocking_lpm[] = { 0x60, 0x9c };
35
36/* command for reading the ID register */
37static const unsigned char shtc1_cmd_read_id_reg[] = { 0xef, 0xc8 };
38
39/* constants for reading the ID register */
40#define SHTC1_ID 0x07
41#define SHTC1_ID_REG_MASK 0x1f
42
43/* delays for non-blocking i2c commands, both in us */
44#define SHTC1_NONBLOCKING_WAIT_TIME_HPM 14400
45#define SHTC1_NONBLOCKING_WAIT_TIME_LPM 1000
46
47#define SHTC1_CMD_LENGTH 2
48#define SHTC1_RESPONSE_LENGTH 6
49
50struct shtc1_data {
51 struct i2c_client *client;
52 struct mutex update_lock;
53 bool valid;
54 unsigned long last_updated; /* in jiffies */
55
56 const unsigned char *command;
57 unsigned int nonblocking_wait_time; /* in us */
58
59 struct shtc1_platform_data setup;
60
61 int temperature; /* 1000 * temperature in dgr C */
62 int humidity; /* 1000 * relative humidity in %RH */
63};
64
65static int shtc1_update_values(struct i2c_client *client,
66 struct shtc1_data *data,
67 char *buf, int bufsize)
68{
69 int ret = i2c_master_send(client, data->command, SHTC1_CMD_LENGTH);
70 if (ret != SHTC1_CMD_LENGTH) {
71 dev_err(&client->dev, "failed to send command: %d\n", ret);
72 return ret < 0 ? ret : -EIO;
73 }
74
75 /*
76 * In blocking mode (clock stretching mode) the I2C bus
77 * is blocked for other traffic, thus the call to i2c_master_recv()
78 * will wait until the data is ready. For non blocking mode, we
79 * have to wait ourselves.
80 */
81 if (!data->setup.blocking_io)
82 usleep_range(data->nonblocking_wait_time,
83 data->nonblocking_wait_time + 1000);
84
85 ret = i2c_master_recv(client, buf, bufsize);
86 if (ret != bufsize) {
87 dev_err(&client->dev, "failed to read values: %d\n", ret);
88 return ret < 0 ? ret : -EIO;
89 }
90
91 return 0;
92}
93
94/* sysfs attributes */
95static struct shtc1_data *shtc1_update_client(struct device *dev)
96{
97 struct shtc1_data *data = dev_get_drvdata(dev);
98 struct i2c_client *client = data->client;
99 unsigned char buf[SHTC1_RESPONSE_LENGTH];
100 int val;
101 int ret = 0;
102
103 mutex_lock(&data->update_lock);
104
105 if (time_after(jiffies, data->last_updated + HZ / 10) || !data->valid) {
106 ret = shtc1_update_values(client, data, buf, sizeof(buf));
107 if (ret)
108 goto out;
109
110 /*
111 * From datasheet:
112 * T = -45 + 175 * ST / 2^16
113 * RH = 100 * SRH / 2^16
114 *
115 * Adapted for integer fixed point (3 digit) arithmetic.
116 */
117 val = be16_to_cpup((__be16 *)buf);
118 data->temperature = ((21875 * val) >> 13) - 45000;
119 val = be16_to_cpup((__be16 *)(buf + 3));
120 data->humidity = ((12500 * val) >> 13);
121
122 data->last_updated = jiffies;
123 data->valid = true;
124 }
125
126out:
127 mutex_unlock(&data->update_lock);
128
129 return ret == 0 ? data : ERR_PTR(ret);
130}
131
132static ssize_t temp1_input_show(struct device *dev,
133 struct device_attribute *attr,
134 char *buf)
135{
136 struct shtc1_data *data = shtc1_update_client(dev);
137 if (IS_ERR(data))
138 return PTR_ERR(data);
139
140 return sprintf(buf, "%d\n", data->temperature);
141}
142
143static ssize_t humidity1_input_show(struct device *dev,
144 struct device_attribute *attr, char *buf)
145{
146 struct shtc1_data *data = shtc1_update_client(dev);
147 if (IS_ERR(data))
148 return PTR_ERR(data);
149
150 return sprintf(buf, "%d\n", data->humidity);
151}
152
153static DEVICE_ATTR_RO(temp1_input);
154static DEVICE_ATTR_RO(humidity1_input);
155
156static struct attribute *shtc1_attrs[] = {
157 &dev_attr_temp1_input.attr,
158 &dev_attr_humidity1_input.attr,
159 NULL
160};
161
162ATTRIBUTE_GROUPS(shtc1);
163
164static void shtc1_select_command(struct shtc1_data *data)
165{
166 if (data->setup.high_precision) {
167 data->command = data->setup.blocking_io ?
168 shtc1_cmd_measure_blocking_hpm :
169 shtc1_cmd_measure_nonblocking_hpm;
170 data->nonblocking_wait_time = SHTC1_NONBLOCKING_WAIT_TIME_HPM;
171
172 } else {
173 data->command = data->setup.blocking_io ?
174 shtc1_cmd_measure_blocking_lpm :
175 shtc1_cmd_measure_nonblocking_lpm;
176 data->nonblocking_wait_time = SHTC1_NONBLOCKING_WAIT_TIME_LPM;
177 }
178}
179
180static int shtc1_probe(struct i2c_client *client,
181 const struct i2c_device_id *id)
182{
183 int ret;
184 char id_reg[2];
185 struct shtc1_data *data;
186 struct device *hwmon_dev;
187 struct i2c_adapter *adap = client->adapter;
188 struct device *dev = &client->dev;
189
190 if (!i2c_check_functionality(adap, I2C_FUNC_I2C)) {
191 dev_err(dev, "plain i2c transactions not supported\n");
192 return -ENODEV;
193 }
194
195 ret = i2c_master_send(client, shtc1_cmd_read_id_reg, SHTC1_CMD_LENGTH);
196 if (ret != SHTC1_CMD_LENGTH) {
197 dev_err(dev, "could not send read_id_reg command: %d\n", ret);
198 return ret < 0 ? ret : -ENODEV;
199 }
200 ret = i2c_master_recv(client, id_reg, sizeof(id_reg));
201 if (ret != sizeof(id_reg)) {
202 dev_err(dev, "could not read ID register: %d\n", ret);
203 return -ENODEV;
204 }
205 if ((id_reg[1] & SHTC1_ID_REG_MASK) != SHTC1_ID) {
206 dev_err(dev, "ID register doesn't match\n");
207 return -ENODEV;
208 }
209
210 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
211 if (!data)
212 return -ENOMEM;
213
214 data->setup.blocking_io = false;
215 data->setup.high_precision = true;
216 data->client = client;
217
218 if (client->dev.platform_data)
219 data->setup = *(struct shtc1_platform_data *)dev->platform_data;
220 shtc1_select_command(data);
221 mutex_init(&data->update_lock);
222
223 hwmon_dev = devm_hwmon_device_register_with_groups(dev,
224 client->name,
225 data,
226 shtc1_groups);
227 if (IS_ERR(hwmon_dev))
228 dev_dbg(dev, "unable to register hwmon device\n");
229
230 return PTR_ERR_OR_ZERO(hwmon_dev);
231}
232
233/* device ID table */
234static const struct i2c_device_id shtc1_id[] = {
235 { "shtc1", 0 },
236 { "shtw1", 0 },
237 { }
238};
239MODULE_DEVICE_TABLE(i2c, shtc1_id);
240
241static struct i2c_driver shtc1_i2c_driver = {
242 .driver.name = "shtc1",
243 .probe = shtc1_probe,
244 .id_table = shtc1_id,
245};
246
247module_i2c_driver(shtc1_i2c_driver);
248
249MODULE_AUTHOR("Johannes Winkelmann <johannes.winkelmann@sensirion.com>");
250MODULE_DESCRIPTION("Sensirion SHTC1 humidity and temperature sensor driver");
251MODULE_LICENSE("GPL");
diff --git a/include/linux/platform_data/shtc1.h b/include/linux/platform_data/shtc1.h
new file mode 100644
index 000000000000..7b8c353f7dc8
--- /dev/null
+++ b/include/linux/platform_data/shtc1.h
@@ -0,0 +1,23 @@
1/*
2 * Copyright (C) 2014 Sensirion AG, Switzerland
3 * Author: Johannes Winkelmann <johannes.winkelmann@sensirion.com>
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#ifndef __SHTC1_H_
17#define __SHTC1_H_
18
19struct shtc1_platform_data {
20 bool blocking_io;
21 bool high_precision;
22};
23#endif /* __SHTC1_H_ */