aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Weinberger <richard@nod.at>2015-01-07 07:22:49 -0500
committerJonathan Cameron <jic23@kernel.org>2015-01-10 06:16:32 -0500
commit94e65519abde01cbffb9c538a4598f6a50bc86d1 (patch)
tree6ef7dfd558f974ce53b734df3833cdb58292859e
parent004bc530341a40536494431cf665504f8ee70266 (diff)
iio: dht11: IRQ fixes
Since setting irq-enabled GPIOs into output state is not supported by all GPIO controllers, we need to disable the irq while requesting sensor data. As side effect we lose a tiny bit of functionality: Some wiring problems can't be concluded from log messages anymore. Signed-off-by: Richard Weinberger <richard@nod.at> Signed-off-by: Harald Geyer <harald@ccbib.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r--drivers/iio/humidity/dht11.c62
1 files changed, 35 insertions, 27 deletions
diff --git a/drivers/iio/humidity/dht11.c b/drivers/iio/humidity/dht11.c
index 7717f5c3395b..7d79a1ac5f5f 100644
--- a/drivers/iio/humidity/dht11.c
+++ b/drivers/iio/humidity/dht11.c
@@ -40,8 +40,12 @@
40 40
41#define DHT11_DATA_VALID_TIME 2000000000 /* 2s in ns */ 41#define DHT11_DATA_VALID_TIME 2000000000 /* 2s in ns */
42 42
43#define DHT11_EDGES_PREAMBLE 4 43#define DHT11_EDGES_PREAMBLE 2
44#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 */
45#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)
46 50
47/* Data transmission timing (nano seconds) */ 51/* Data transmission timing (nano seconds) */
@@ -140,6 +144,27 @@ static int dht11_decode(struct dht11 *dht11, int offset)
140 return 0; 144 return 0;
141} 145}
142 146
147/*
148 * IRQ handler called on GPIO edges
149 */
150static 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
143static int dht11_read_raw(struct iio_dev *iio_dev, 168static int dht11_read_raw(struct iio_dev *iio_dev,
144 const struct iio_chan_spec *chan, 169 const struct iio_chan_spec *chan,
145 int *val, int *val2, long m) 170 int *val, int *val2, long m)
@@ -160,8 +185,17 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
160 if (ret) 185 if (ret)
161 goto err; 186 goto err;
162 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
163 ret = wait_for_completion_killable_timeout(&dht11->completion, 194 ret = wait_for_completion_killable_timeout(&dht11->completion,
164 HZ); 195 HZ);
196
197 free_irq(dht11->irq, iio_dev);
198
165 if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) { 199 if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) {
166 dev_err(&iio_dev->dev, 200 dev_err(&iio_dev->dev,
167 "Only %d signal edges detected\n", 201 "Only %d signal edges detected\n",
@@ -197,27 +231,6 @@ static const struct iio_info dht11_iio_info = {
197 .read_raw = dht11_read_raw, 231 .read_raw = dht11_read_raw,
198}; 232};
199 233
200/*
201 * IRQ handler called on GPIO edges
202*/
203static irqreturn_t dht11_handle_irq(int irq, void *data)
204{
205 struct iio_dev *iio = data;
206 struct dht11 *dht11 = iio_priv(iio);
207
208 /* TODO: Consider making the handler safe for IRQ sharing */
209 if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) {
210 dht11->edges[dht11->num_edges].ts = iio_get_time_ns();
211 dht11->edges[dht11->num_edges++].value =
212 gpio_get_value(dht11->gpio);
213
214 if (dht11->num_edges >= DHT11_EDGES_PER_READ)
215 complete(&dht11->completion);
216 }
217
218 return IRQ_HANDLED;
219}
220
221static const struct iio_chan_spec dht11_chan_spec[] = { 234static const struct iio_chan_spec dht11_chan_spec[] = {
222 { .type = IIO_TEMP, 235 { .type = IIO_TEMP,
223 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), }, 236 .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), },
@@ -260,11 +273,6 @@ static int dht11_probe(struct platform_device *pdev)
260 dev_err(dev, "GPIO %d has no interrupt\n", dht11->gpio); 273 dev_err(dev, "GPIO %d has no interrupt\n", dht11->gpio);
261 return -EINVAL; 274 return -EINVAL;
262 } 275 }
263 ret = devm_request_irq(dev, dht11->irq, dht11_handle_irq,
264 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
265 pdev->name, iio);
266 if (ret)
267 return ret;
268 276
269 dht11->timestamp = iio_get_time_ns() - DHT11_DATA_VALID_TIME - 1; 277 dht11->timestamp = iio_get_time_ns() - DHT11_DATA_VALID_TIME - 1;
270 dht11->num_edges = -1; 278 dht11->num_edges = -1;