]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/hwmon/shtc1.c
qed: Align TLVs
[karo-tx-linux.git] / drivers / hwmon / shtc1.c
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) */
29 static const unsigned char shtc1_cmd_measure_blocking_hpm[]    = { 0x7C, 0xA2 };
30 static const unsigned char shtc1_cmd_measure_nonblocking_hpm[] = { 0x78, 0x66 };
31
32 /* commands (low precision mode) */
33 static const unsigned char shtc1_cmd_measure_blocking_lpm[]    = { 0x64, 0x58 };
34 static const unsigned char shtc1_cmd_measure_nonblocking_lpm[] = { 0x60, 0x9c };
35
36 /* command for reading the ID register */
37 static 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
50 struct 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
65 static 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 */
95 static 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
126 out:
127         mutex_unlock(&data->update_lock);
128
129         return ret == 0 ? data : ERR_PTR(ret);
130 }
131
132 static 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
143 static 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
153 static DEVICE_ATTR_RO(temp1_input);
154 static DEVICE_ATTR_RO(humidity1_input);
155
156 static struct attribute *shtc1_attrs[] = {
157         &dev_attr_temp1_input.attr,
158         &dev_attr_humidity1_input.attr,
159         NULL
160 };
161
162 ATTRIBUTE_GROUPS(shtc1);
163
164 static 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
180 static 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 */
234 static const struct i2c_device_id shtc1_id[] = {
235         { "shtc1", 0 },
236         { "shtw1", 0 },
237         { }
238 };
239 MODULE_DEVICE_TABLE(i2c, shtc1_id);
240
241 static struct i2c_driver shtc1_i2c_driver = {
242         .driver.name  = "shtc1",
243         .probe        = shtc1_probe,
244         .id_table     = shtc1_id,
245 };
246
247 module_i2c_driver(shtc1_i2c_driver);
248
249 MODULE_AUTHOR("Johannes Winkelmann <johannes.winkelmann@sensirion.com>");
250 MODULE_DESCRIPTION("Sensirion SHTC1 humidity and temperature sensor driver");
251 MODULE_LICENSE("GPL");