aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio/humidity
diff options
context:
space:
mode:
authorPeter Meerwald <pmeerw@pmeerw.net>2014-10-01 07:03:00 -0400
committerJonathan Cameron <jic23@kernel.org>2014-01-11 06:12:44 -0500
commit049973b23a6c77186dae45f708cdc0aa52b3a09e (patch)
tree7e61a880881046745e19d5e53eb14c20d20850b8 /drivers/iio/humidity
parent4c45b1a80ee9c85aee13445b85fd55541ec26d27 (diff)
iio: Add si7005 relative humidity and temperature sensor driver
sensor provides 12-bit relative humidity and 14-bit temperature via I2C interface; temperature and linearity compensation is not implemented (yet) driver also supports the Si7015, but not the 2nd generation sensors Si7013/Si7020/Si7021 datasheet is here http://www.silabs.com/Support%20Documents/TechnicalDocs/Si7005.pdf v2: (thanks to Lars-Peter Clausen) * fix coding style * use devm_iio_device_register() * change copyright year to 2014 Signed-off-by: Peter Meerwald <pmeerw@pmeerw.net> Reviewed-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio/humidity')
-rw-r--r--drivers/iio/humidity/Kconfig10
-rw-r--r--drivers/iio/humidity/Makefile1
-rw-r--r--drivers/iio/humidity/si7005.c189
3 files changed, 200 insertions, 0 deletions
diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig
index 463c4d9da79e..e116bd8dd0e4 100644
--- a/drivers/iio/humidity/Kconfig
+++ b/drivers/iio/humidity/Kconfig
@@ -12,4 +12,14 @@ config DHT11
12 Other sensors should work as well as long as they speak the 12 Other sensors should work as well as long as they speak the
13 same protocol. 13 same protocol.
14 14
15config SI7005
16 tristate "SI7005 relative humidity and temperature sensor"
17 depends on I2C
18 help
19 Say yes here to build support for the Silabs Si7005 relative
20 humidity and temperature sensor.
21
22 To compile this driver as a module, choose M here: the module
23 will be called si7005.
24
15endmenu 25endmenu
diff --git a/drivers/iio/humidity/Makefile b/drivers/iio/humidity/Makefile
index d5d36c0c95f9..e3f3d942e646 100644
--- a/drivers/iio/humidity/Makefile
+++ b/drivers/iio/humidity/Makefile
@@ -3,3 +3,4 @@
3# 3#
4 4
5obj-$(CONFIG_DHT11) += dht11.o 5obj-$(CONFIG_DHT11) += dht11.o
6obj-$(CONFIG_SI7005) += si7005.o
diff --git a/drivers/iio/humidity/si7005.c b/drivers/iio/humidity/si7005.c
new file mode 100644
index 000000000000..bdd586e6d955
--- /dev/null
+++ b/drivers/iio/humidity/si7005.c
@@ -0,0 +1,189 @@
1/*
2 * si7005.c - Support for Silabs Si7005 humidity and temperature sensor
3 *
4 * Copyright (c) 2014 Peter Meerwald <pmeerw@pmeerw.net>
5 *
6 * This file is subject to the terms and conditions of version 2 of
7 * the GNU General Public License. See the file COPYING in the main
8 * directory of this archive for more details.
9 *
10 * (7-bit I2C slave address 0x40)
11 *
12 * TODO: heater, fast mode, processed mode (temp. / linearity compensation)
13 */
14
15#include <linux/err.h>
16#include <linux/i2c.h>
17#include <linux/delay.h>
18#include <linux/module.h>
19#include <linux/pm.h>
20
21#include <linux/iio/iio.h>
22#include <linux/iio/sysfs.h>
23
24#define SI7005_STATUS 0x00
25#define SI7005_DATA 0x01 /* 16-bit, MSB */
26#define SI7005_CONFIG 0x03
27#define SI7005_ID 0x11
28
29#define SI7005_STATUS_NRDY BIT(0)
30#define SI7005_CONFIG_TEMP BIT(4)
31#define SI7005_CONFIG_START BIT(0)
32
33#define SI7005_ID_7005 0x50
34#define SI7005_ID_7015 0xf0
35
36struct si7005_data {
37 struct i2c_client *client;
38 struct mutex lock;
39 u8 config;
40};
41
42static int si7005_read_measurement(struct si7005_data *data, bool temp)
43{
44 int tries = 50;
45 int ret;
46
47 mutex_lock(&data->lock);
48
49 ret = i2c_smbus_write_byte_data(data->client, SI7005_CONFIG,
50 data->config | SI7005_CONFIG_START |
51 (temp ? SI7005_CONFIG_TEMP : 0));
52 if (ret < 0)
53 goto done;
54
55 while (tries-- > 0) {
56 msleep(20);
57 ret = i2c_smbus_read_byte_data(data->client, SI7005_STATUS);
58 if (ret < 0)
59 goto done;
60 if (!(ret & SI7005_STATUS_NRDY))
61 break;
62 }
63 if (tries < 0) {
64 ret = -EIO;
65 goto done;
66 }
67
68 ret = i2c_smbus_read_word_swapped(data->client, SI7005_DATA);
69
70done:
71 mutex_unlock(&data->lock);
72
73 return ret;
74}
75
76static int si7005_read_raw(struct iio_dev *indio_dev,
77 struct iio_chan_spec const *chan, int *val,
78 int *val2, long mask)
79{
80 struct si7005_data *data = iio_priv(indio_dev);
81 int ret;
82
83 switch (mask) {
84 case IIO_CHAN_INFO_RAW:
85 ret = si7005_read_measurement(data, chan->type == IIO_TEMP);
86 if (ret < 0)
87 return ret;
88 *val = ret;
89 return IIO_VAL_INT;
90 case IIO_CHAN_INFO_SCALE:
91 if (chan->type == IIO_TEMP) {
92 *val = 7;
93 *val2 = 812500;
94 } else {
95 *val = 3;
96 *val2 = 906250;
97 }
98 return IIO_VAL_INT_PLUS_MICRO;
99 case IIO_CHAN_INFO_OFFSET:
100 if (chan->type == IIO_TEMP)
101 *val = -50 * 32 * 4;
102 else
103 *val = -24 * 16 * 16;
104 return IIO_VAL_INT;
105 default:
106 break;
107 }
108
109 return -EINVAL;
110}
111
112static const struct iio_chan_spec si7005_channels[] = {
113 {
114 .type = IIO_HUMIDITYRELATIVE,
115 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
116 BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET),
117 },
118 {
119 .type = IIO_TEMP,
120 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
121 BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET),
122 }
123};
124
125static const struct iio_info si7005_info = {
126 .read_raw = si7005_read_raw,
127 .driver_module = THIS_MODULE,
128};
129
130static int si7005_probe(struct i2c_client *client,
131 const struct i2c_device_id *id)
132{
133 struct iio_dev *indio_dev;
134 struct si7005_data *data;
135 int ret;
136
137 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA))
138 return -ENODEV;
139
140 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
141 if (!indio_dev)
142 return -ENOMEM;
143
144 data = iio_priv(indio_dev);
145 i2c_set_clientdata(client, indio_dev);
146 data->client = client;
147 mutex_init(&data->lock);
148
149 indio_dev->dev.parent = &client->dev;
150 indio_dev->name = dev_name(&client->dev);
151 indio_dev->modes = INDIO_DIRECT_MODE;
152 indio_dev->info = &si7005_info;
153
154 indio_dev->channels = si7005_channels;
155 indio_dev->num_channels = ARRAY_SIZE(si7005_channels);
156
157 ret = i2c_smbus_read_byte_data(client, SI7005_ID);
158 if (ret < 0)
159 return ret;
160 if (ret != SI7005_ID_7005 && ret != SI7005_ID_7015)
161 return -ENODEV;
162
163 ret = i2c_smbus_read_byte_data(client, SI7005_CONFIG);
164 if (ret < 0)
165 return ret;
166 data->config = ret;
167
168 return devm_iio_device_register(&client->dev, indio_dev);
169}
170
171static const struct i2c_device_id si7005_id[] = {
172 { "si7005", 0 },
173 { }
174};
175MODULE_DEVICE_TABLE(i2c, si7005_id);
176
177static struct i2c_driver si7005_driver = {
178 .driver = {
179 .name = "si7005",
180 .owner = THIS_MODULE,
181 },
182 .probe = si7005_probe,
183 .id_table = si7005_id,
184};
185module_i2c_driver(si7005_driver);
186
187MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
188MODULE_DESCRIPTION("Silabs Si7005 humidity and temperature sensor driver");
189MODULE_LICENSE("GPL");