diff options
author | Peter Meerwald <pmeerw@pmeerw.net> | 2014-10-01 07:03:00 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2014-01-11 06:12:44 -0500 |
commit | 049973b23a6c77186dae45f708cdc0aa52b3a09e (patch) | |
tree | 7e61a880881046745e19d5e53eb14c20d20850b8 /drivers/iio/humidity | |
parent | 4c45b1a80ee9c85aee13445b85fd55541ec26d27 (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/Kconfig | 10 | ||||
-rw-r--r-- | drivers/iio/humidity/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/humidity/si7005.c | 189 |
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 | ||
15 | config 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 | |||
15 | endmenu | 25 | endmenu |
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 | ||
5 | obj-$(CONFIG_DHT11) += dht11.o | 5 | obj-$(CONFIG_DHT11) += dht11.o |
6 | obj-$(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 | |||
36 | struct si7005_data { | ||
37 | struct i2c_client *client; | ||
38 | struct mutex lock; | ||
39 | u8 config; | ||
40 | }; | ||
41 | |||
42 | static 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 | |||
70 | done: | ||
71 | mutex_unlock(&data->lock); | ||
72 | |||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | static 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 | |||
112 | static 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 | |||
125 | static const struct iio_info si7005_info = { | ||
126 | .read_raw = si7005_read_raw, | ||
127 | .driver_module = THIS_MODULE, | ||
128 | }; | ||
129 | |||
130 | static 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 | |||
171 | static const struct i2c_device_id si7005_id[] = { | ||
172 | { "si7005", 0 }, | ||
173 | { } | ||
174 | }; | ||
175 | MODULE_DEVICE_TABLE(i2c, si7005_id); | ||
176 | |||
177 | static 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 | }; | ||
185 | module_i2c_driver(si7005_driver); | ||
186 | |||
187 | MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>"); | ||
188 | MODULE_DESCRIPTION("Silabs Si7005 humidity and temperature sensor driver"); | ||
189 | MODULE_LICENSE("GPL"); | ||