aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Barksdale <dbarksdale@uplogix.com>2014-09-29 14:28:55 -0400
committerJonathan Cameron <jic23@kernel.org>2014-10-04 07:43:30 -0400
commit064a74637ccdee608eb898ea3e3847b142b261c6 (patch)
tree339d2db469982d4af35c53804c802ecbac54a654
parentef0d5454930aa687ac2c2337107391f1389aa0f1 (diff)
IIO: add si7020 driver
This patch adds support to the Industrial IO subsystem for the Silicon Labs Si7013/20/21 Relative Humidity and Temperature Sensors. Website: http://www.silabs.com/products/sensors/humidity-sensors/Pages/si7013-20-21.aspx These are i2c devices which measure relative humidity and temperature and all use the same protocol. The Si7013 has an additional input with programmable linearization which is not supported because that's complicated and I didn't need it. Signed-off-by: David Barksdale <dbarksdale@uplogix.com> -- Changes since v1: * Renamed to si7020 and replaced Si701x/2x with Si7013/20/21. * Removed unneeded mutex. * Pre-computed floating-point constant expressions. * Removed address_list and I2C_CLASS_HWMON. Changes since v2: * Return correct raw sensor values. * Rename dev variable to indio_dev. * Issue a software reset command during probe. * Un-broke string literal. Changes since v3: * enum changed to #define Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r--drivers/iio/humidity/Kconfig10
-rw-r--r--drivers/iio/humidity/Makefile1
-rw-r--r--drivers/iio/humidity/si7020.c163
3 files changed, 174 insertions, 0 deletions
diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig
index e116bd8dd0e4..4813b793b9f7 100644
--- a/drivers/iio/humidity/Kconfig
+++ b/drivers/iio/humidity/Kconfig
@@ -22,4 +22,14 @@ config SI7005
22 To compile this driver as a module, choose M here: the module 22 To compile this driver as a module, choose M here: the module
23 will be called si7005. 23 will be called si7005.
24 24
25config SI7020
26 tristate "Si7013/20/21 Relative Humidity and Temperature Sensors"
27 depends on I2C
28 help
29 Say yes here to build support for the Silicon Labs Si7013/20/21
30 Relative Humidity and Temperature Sensors.
31
32 To compile this driver as a module, choose M here: the module
33 will be called si7020.
34
25endmenu 35endmenu
diff --git a/drivers/iio/humidity/Makefile b/drivers/iio/humidity/Makefile
index e3f3d942e646..86e2d26e9f4d 100644
--- a/drivers/iio/humidity/Makefile
+++ b/drivers/iio/humidity/Makefile
@@ -4,3 +4,4 @@
4 4
5obj-$(CONFIG_DHT11) += dht11.o 5obj-$(CONFIG_DHT11) += dht11.o
6obj-$(CONFIG_SI7005) += si7005.o 6obj-$(CONFIG_SI7005) += si7005.o
7obj-$(CONFIG_SI7020) += si7020.o
diff --git a/drivers/iio/humidity/si7020.c b/drivers/iio/humidity/si7020.c
new file mode 100644
index 000000000000..e336af713f20
--- /dev/null
+++ b/drivers/iio/humidity/si7020.c
@@ -0,0 +1,163 @@
1/*
2 * si7020.c - Silicon Labs Si7013/20/21 Relative Humidity and Temp Sensors
3 * Copyright (c) 2013,2014 Uplogix, Inc.
4 * David Barksdale <dbarksdale@uplogix.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16/*
17 * The Silicon Labs Si7013/20/21 Relative Humidity and Temperature Sensors
18 * are i2c devices which have an identical programming interface for
19 * measuring relative humidity and temperature. The Si7013 has an additional
20 * temperature input which this driver does not support.
21 *
22 * Data Sheets:
23 * Si7013: http://www.silabs.com/Support%20Documents/TechnicalDocs/Si7013.pdf
24 * Si7020: http://www.silabs.com/Support%20Documents/TechnicalDocs/Si7020.pdf
25 * Si7021: http://www.silabs.com/Support%20Documents/TechnicalDocs/Si7021.pdf
26 */
27
28#include <linux/delay.h>
29#include <linux/i2c.h>
30#include <linux/module.h>
31#include <linux/slab.h>
32#include <linux/sysfs.h>
33
34#include <linux/iio/iio.h>
35#include <linux/iio/sysfs.h>
36
37/* Measure Relative Humidity, Hold Master Mode */
38#define SI7020CMD_RH_HOLD 0xE5
39/* Measure Temperature, Hold Master Mode */
40#define SI7020CMD_TEMP_HOLD 0xE3
41/* Software Reset */
42#define SI7020CMD_RESET 0xFE
43
44static int si7020_read_raw(struct iio_dev *indio_dev,
45 struct iio_chan_spec const *chan, int *val,
46 int *val2, long mask)
47{
48 struct i2c_client **client = iio_priv(indio_dev);
49 int ret;
50
51 switch (mask) {
52 case IIO_CHAN_INFO_RAW:
53 ret = i2c_smbus_read_word_data(*client,
54 chan->type == IIO_TEMP ?
55 SI7020CMD_TEMP_HOLD :
56 SI7020CMD_RH_HOLD);
57 if (ret < 0)
58 return ret;
59 if (chan->type == IIO_TEMP)
60 *val = ret >> 2;
61 else
62 *val = (ret & 0x3FFF) >> 2;
63 return IIO_VAL_INT;
64 case IIO_CHAN_INFO_SCALE:
65 if (chan->type == IIO_TEMP)
66 *val = 175720; /* = 175.72 * 1000 */
67 else
68 *val = 125 * 1000;
69 *val2 = 65536 >> 2;
70 return IIO_VAL_FRACTIONAL;
71 case IIO_CHAN_INFO_OFFSET:
72 /*
73 * Since iio_convert_raw_to_processed_unlocked assumes offset
74 * is an integer we have to round these values and lose
75 * accuracy.
76 * Relative humidity will be 0.0032959% too high and
77 * temperature will be 0.00277344 degrees too high.
78 * This is no big deal because it's within the accuracy of the
79 * sensor.
80 */
81 if (chan->type == IIO_TEMP)
82 *val = -4368; /* = -46.85 * (65536 >> 2) / 175.72 */
83 else
84 *val = -786; /* = -6 * (65536 >> 2) / 125 */
85 return IIO_VAL_INT;
86 default:
87 break;
88 }
89
90 return -EINVAL;
91}
92
93static const struct iio_chan_spec si7020_channels[] = {
94 {
95 .type = IIO_HUMIDITYRELATIVE,
96 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
97 BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET),
98 },
99 {
100 .type = IIO_TEMP,
101 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
102 BIT(IIO_CHAN_INFO_SCALE) | BIT(IIO_CHAN_INFO_OFFSET),
103 }
104};
105
106static const struct iio_info si7020_info = {
107 .read_raw = si7020_read_raw,
108 .driver_module = THIS_MODULE,
109};
110
111static int si7020_probe(struct i2c_client *client,
112 const struct i2c_device_id *id)
113{
114 struct iio_dev *indio_dev;
115 struct i2c_client **data;
116 int ret;
117
118 if (!i2c_check_functionality(client->adapter,
119 I2C_FUNC_SMBUS_WRITE_BYTE |
120 I2C_FUNC_SMBUS_READ_WORD_DATA))
121 return -ENODEV;
122
123 /* Reset device, loads default settings. */
124 ret = i2c_smbus_write_byte(client, SI7020CMD_RESET);
125 if (ret < 0)
126 return ret;
127 /* Wait the maximum power-up time after software reset. */
128 msleep(15);
129
130 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*client));
131 if (!indio_dev)
132 return -ENOMEM;
133
134 data = iio_priv(indio_dev);
135 *data = client;
136 i2c_set_clientdata(client, indio_dev);
137
138 indio_dev->dev.parent = &client->dev;
139 indio_dev->name = dev_name(&client->dev);
140 indio_dev->modes = INDIO_DIRECT_MODE;
141 indio_dev->info = &si7020_info;
142 indio_dev->channels = si7020_channels;
143 indio_dev->num_channels = ARRAY_SIZE(si7020_channels);
144
145 return devm_iio_device_register(&client->dev, indio_dev);
146}
147
148static const struct i2c_device_id si7020_id[] = {
149 { "si7020", 0 },
150 { }
151};
152MODULE_DEVICE_TABLE(i2c, si7020_id);
153
154static struct i2c_driver si7020_driver = {
155 .driver.name = "si7020",
156 .probe = si7020_probe,
157 .id_table = si7020_id,
158};
159
160module_i2c_driver(si7020_driver);
161MODULE_DESCRIPTION("Silicon Labs Si7013/20/21 Relative Humidity and Temperature Sensors");
162MODULE_AUTHOR("David Barksdale <dbarksdale@uplogix.com>");
163MODULE_LICENSE("GPL");