diff options
Diffstat (limited to 'drivers/iio/humidity/dht11.c')
-rw-r--r-- | drivers/iio/humidity/dht11.c | 69 |
1 files changed, 41 insertions, 28 deletions
diff --git a/drivers/iio/humidity/dht11.c b/drivers/iio/humidity/dht11.c index 623c145d8a97..7d79a1ac5f5f 100644 --- a/drivers/iio/humidity/dht11.c +++ b/drivers/iio/humidity/dht11.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/wait.h> | 29 | #include <linux/wait.h> |
30 | #include <linux/bitops.h> | 30 | #include <linux/bitops.h> |
31 | #include <linux/completion.h> | 31 | #include <linux/completion.h> |
32 | #include <linux/mutex.h> | ||
32 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
33 | #include <linux/gpio.h> | 34 | #include <linux/gpio.h> |
34 | #include <linux/of_gpio.h> | 35 | #include <linux/of_gpio.h> |
@@ -39,8 +40,12 @@ | |||
39 | 40 | ||
40 | #define DHT11_DATA_VALID_TIME 2000000000 /* 2s in ns */ | 41 | #define DHT11_DATA_VALID_TIME 2000000000 /* 2s in ns */ |
41 | 42 | ||
42 | #define DHT11_EDGES_PREAMBLE 4 | 43 | #define DHT11_EDGES_PREAMBLE 2 |
43 | #define DHT11_BITS_PER_READ 40 | 44 | #define DHT11_BITS_PER_READ 40 |
45 | /* | ||
46 | * Note that when reading the sensor actually 84 edges are detected, but | ||
47 | * since the last edge is not significant, we only store 83: | ||
48 | */ | ||
44 | #define DHT11_EDGES_PER_READ (2*DHT11_BITS_PER_READ + DHT11_EDGES_PREAMBLE + 1) | 49 | #define DHT11_EDGES_PER_READ (2*DHT11_BITS_PER_READ + DHT11_EDGES_PREAMBLE + 1) |
45 | 50 | ||
46 | /* Data transmission timing (nano seconds) */ | 51 | /* Data transmission timing (nano seconds) */ |
@@ -57,6 +62,7 @@ struct dht11 { | |||
57 | int irq; | 62 | int irq; |
58 | 63 | ||
59 | struct completion completion; | 64 | struct completion completion; |
65 | struct mutex lock; | ||
60 | 66 | ||
61 | s64 timestamp; | 67 | s64 timestamp; |
62 | int temperature; | 68 | int temperature; |
@@ -88,7 +94,7 @@ static int dht11_decode(struct dht11 *dht11, int offset) | |||
88 | unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum; | 94 | unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum; |
89 | 95 | ||
90 | /* Calculate timestamp resolution */ | 96 | /* Calculate timestamp resolution */ |
91 | for (i = 0; i < dht11->num_edges; ++i) { | 97 | for (i = 1; i < dht11->num_edges; ++i) { |
92 | t = dht11->edges[i].ts - dht11->edges[i-1].ts; | 98 | t = dht11->edges[i].ts - dht11->edges[i-1].ts; |
93 | if (t > 0 && t < timeres) | 99 | if (t > 0 && t < timeres) |
94 | timeres = t; | 100 | timeres = t; |
@@ -138,6 +144,27 @@ static int dht11_decode(struct dht11 *dht11, int offset) | |||
138 | return 0; | 144 | return 0; |
139 | } | 145 | } |
140 | 146 | ||
147 | /* | ||
148 | * IRQ handler called on GPIO edges | ||
149 | */ | ||
150 | static irqreturn_t dht11_handle_irq(int irq, void *data) | ||
151 | { | ||
152 | struct iio_dev *iio = data; | ||
153 | struct dht11 *dht11 = iio_priv(iio); | ||
154 | |||
155 | /* TODO: Consider making the handler safe for IRQ sharing */ | ||
156 | if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) { | ||
157 | dht11->edges[dht11->num_edges].ts = iio_get_time_ns(); | ||
158 | dht11->edges[dht11->num_edges++].value = | ||
159 | gpio_get_value(dht11->gpio); | ||
160 | |||
161 | if (dht11->num_edges >= DHT11_EDGES_PER_READ) | ||
162 | complete(&dht11->completion); | ||
163 | } | ||
164 | |||
165 | return IRQ_HANDLED; | ||
166 | } | ||
167 | |||
141 | static int dht11_read_raw(struct iio_dev *iio_dev, | 168 | static int dht11_read_raw(struct iio_dev *iio_dev, |
142 | const struct iio_chan_spec *chan, | 169 | const struct iio_chan_spec *chan, |
143 | int *val, int *val2, long m) | 170 | int *val, int *val2, long m) |
@@ -145,6 +172,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev, | |||
145 | struct dht11 *dht11 = iio_priv(iio_dev); | 172 | struct dht11 *dht11 = iio_priv(iio_dev); |
146 | int ret; | 173 | int ret; |
147 | 174 | ||
175 | mutex_lock(&dht11->lock); | ||
148 | if (dht11->timestamp + DHT11_DATA_VALID_TIME < iio_get_time_ns()) { | 176 | if (dht11->timestamp + DHT11_DATA_VALID_TIME < iio_get_time_ns()) { |
149 | reinit_completion(&dht11->completion); | 177 | reinit_completion(&dht11->completion); |
150 | 178 | ||
@@ -157,8 +185,17 @@ static int dht11_read_raw(struct iio_dev *iio_dev, | |||
157 | if (ret) | 185 | if (ret) |
158 | goto err; | 186 | goto err; |
159 | 187 | ||
188 | ret = request_irq(dht11->irq, dht11_handle_irq, | ||
189 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
190 | iio_dev->name, iio_dev); | ||
191 | if (ret) | ||
192 | goto err; | ||
193 | |||
160 | ret = wait_for_completion_killable_timeout(&dht11->completion, | 194 | ret = wait_for_completion_killable_timeout(&dht11->completion, |
161 | HZ); | 195 | HZ); |
196 | |||
197 | free_irq(dht11->irq, iio_dev); | ||
198 | |||
162 | if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) { | 199 | if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) { |
163 | dev_err(&iio_dev->dev, | 200 | dev_err(&iio_dev->dev, |
164 | "Only %d signal edges detected\n", | 201 | "Only %d signal edges detected\n", |
@@ -185,6 +222,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev, | |||
185 | ret = -EINVAL; | 222 | ret = -EINVAL; |
186 | err: | 223 | err: |
187 | dht11->num_edges = -1; | 224 | dht11->num_edges = -1; |
225 | mutex_unlock(&dht11->lock); | ||
188 | return ret; | 226 | return ret; |
189 | } | 227 | } |
190 | 228 | ||
@@ -193,27 +231,6 @@ static const struct iio_info dht11_iio_info = { | |||
193 | .read_raw = dht11_read_raw, | 231 | .read_raw = dht11_read_raw, |
194 | }; | 232 | }; |
195 | 233 | ||
196 | /* | ||
197 | * IRQ handler called on GPIO edges | ||
198 | */ | ||
199 | static irqreturn_t dht11_handle_irq(int irq, void *data) | ||
200 | { | ||
201 | struct iio_dev *iio = data; | ||
202 | struct dht11 *dht11 = iio_priv(iio); | ||
203 | |||
204 | /* TODO: Consider making the handler safe for IRQ sharing */ | ||
205 | if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) { | ||
206 | dht11->edges[dht11->num_edges].ts = iio_get_time_ns(); | ||
207 | dht11->edges[dht11->num_edges++].value = | ||
208 | gpio_get_value(dht11->gpio); | ||
209 | |||
210 | if (dht11->num_edges >= DHT11_EDGES_PER_READ) | ||
211 | complete(&dht11->completion); | ||
212 | } | ||
213 | |||
214 | return IRQ_HANDLED; | ||
215 | } | ||
216 | |||
217 | static const struct iio_chan_spec dht11_chan_spec[] = { | 234 | static const struct iio_chan_spec dht11_chan_spec[] = { |
218 | { .type = IIO_TEMP, | 235 | { .type = IIO_TEMP, |
219 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), }, | 236 | .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), }, |
@@ -256,11 +273,6 @@ static int dht11_probe(struct platform_device *pdev) | |||
256 | dev_err(dev, "GPIO %d has no interrupt\n", dht11->gpio); | 273 | dev_err(dev, "GPIO %d has no interrupt\n", dht11->gpio); |
257 | return -EINVAL; | 274 | return -EINVAL; |
258 | } | 275 | } |
259 | ret = devm_request_irq(dev, dht11->irq, dht11_handle_irq, | ||
260 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
261 | pdev->name, iio); | ||
262 | if (ret) | ||
263 | return ret; | ||
264 | 276 | ||
265 | dht11->timestamp = iio_get_time_ns() - DHT11_DATA_VALID_TIME - 1; | 277 | dht11->timestamp = iio_get_time_ns() - DHT11_DATA_VALID_TIME - 1; |
266 | dht11->num_edges = -1; | 278 | dht11->num_edges = -1; |
@@ -268,6 +280,7 @@ static int dht11_probe(struct platform_device *pdev) | |||
268 | platform_set_drvdata(pdev, iio); | 280 | platform_set_drvdata(pdev, iio); |
269 | 281 | ||
270 | init_completion(&dht11->completion); | 282 | init_completion(&dht11->completion); |
283 | mutex_init(&dht11->lock); | ||
271 | iio->name = pdev->name; | 284 | iio->name = pdev->name; |
272 | iio->dev.parent = &pdev->dev; | 285 | iio->dev.parent = &pdev->dev; |
273 | iio->info = &dht11_iio_info; | 286 | iio->info = &dht11_iio_info; |