From 94e65519abde01cbffb9c538a4598f6a50bc86d1 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Wed, 7 Jan 2015 13:22:49 +0100 Subject: [PATCH] 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 Signed-off-by: Harald Geyer Signed-off-by: Jonathan Cameron --- drivers/iio/humidity/dht11.c | 62 ++++++++++++++++++++---------------- 1 file 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 @@ #define DHT11_DATA_VALID_TIME 2000000000 /* 2s in ns */ -#define DHT11_EDGES_PREAMBLE 4 +#define DHT11_EDGES_PREAMBLE 2 #define DHT11_BITS_PER_READ 40 +/* + * Note that when reading the sensor actually 84 edges are detected, but + * since the last edge is not significant, we only store 83: + */ #define DHT11_EDGES_PER_READ (2*DHT11_BITS_PER_READ + DHT11_EDGES_PREAMBLE + 1) /* Data transmission timing (nano seconds) */ @@ -140,6 +144,27 @@ static int dht11_decode(struct dht11 *dht11, int offset) return 0; } +/* + * IRQ handler called on GPIO edges + */ +static irqreturn_t dht11_handle_irq(int irq, void *data) +{ + struct iio_dev *iio = data; + struct dht11 *dht11 = iio_priv(iio); + + /* TODO: Consider making the handler safe for IRQ sharing */ + if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) { + dht11->edges[dht11->num_edges].ts = iio_get_time_ns(); + dht11->edges[dht11->num_edges++].value = + gpio_get_value(dht11->gpio); + + if (dht11->num_edges >= DHT11_EDGES_PER_READ) + complete(&dht11->completion); + } + + return IRQ_HANDLED; +} + static int dht11_read_raw(struct iio_dev *iio_dev, const struct iio_chan_spec *chan, int *val, int *val2, long m) @@ -160,8 +185,17 @@ static int dht11_read_raw(struct iio_dev *iio_dev, if (ret) goto err; + ret = request_irq(dht11->irq, dht11_handle_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + iio_dev->name, iio_dev); + if (ret) + goto err; + ret = wait_for_completion_killable_timeout(&dht11->completion, HZ); + + free_irq(dht11->irq, iio_dev); + if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) { dev_err(&iio_dev->dev, "Only %d signal edges detected\n", @@ -197,27 +231,6 @@ static const struct iio_info dht11_iio_info = { .read_raw = dht11_read_raw, }; -/* - * IRQ handler called on GPIO edges -*/ -static irqreturn_t dht11_handle_irq(int irq, void *data) -{ - struct iio_dev *iio = data; - struct dht11 *dht11 = iio_priv(iio); - - /* TODO: Consider making the handler safe for IRQ sharing */ - if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) { - dht11->edges[dht11->num_edges].ts = iio_get_time_ns(); - dht11->edges[dht11->num_edges++].value = - gpio_get_value(dht11->gpio); - - if (dht11->num_edges >= DHT11_EDGES_PER_READ) - complete(&dht11->completion); - } - - return IRQ_HANDLED; -} - static const struct iio_chan_spec dht11_chan_spec[] = { { .type = IIO_TEMP, .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), }, @@ -260,11 +273,6 @@ static int dht11_probe(struct platform_device *pdev) dev_err(dev, "GPIO %d has no interrupt\n", dht11->gpio); return -EINVAL; } - ret = devm_request_irq(dev, dht11->irq, dht11_handle_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - pdev->name, iio); - if (ret) - return ret; dht11->timestamp = iio_get_time_ns() - DHT11_DATA_VALID_TIME - 1; dht11->num_edges = -1;