Commit 94e65519 authored by Richard Weinberger's avatar Richard Weinberger Committed by Jonathan Cameron

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: default avatarRichard Weinberger <richard@nod.at>
Signed-off-by: default avatarHarald Geyer <harald@ccbib.org>
Signed-off-by: default avatarJonathan Cameron <jic23@kernel.org>
parent 004bc530
...@@ -40,8 +40,12 @@ ...@@ -40,8 +40,12 @@
#define DHT11_DATA_VALID_TIME 2000000000 /* 2s in ns */ #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 #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) #define DHT11_EDGES_PER_READ (2*DHT11_BITS_PER_READ + DHT11_EDGES_PREAMBLE + 1)
/* Data transmission timing (nano seconds) */ /* Data transmission timing (nano seconds) */
...@@ -140,6 +144,27 @@ static int dht11_decode(struct dht11 *dht11, int offset) ...@@ -140,6 +144,27 @@ static int dht11_decode(struct dht11 *dht11, int offset)
return 0; 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, static int dht11_read_raw(struct iio_dev *iio_dev,
const struct iio_chan_spec *chan, const struct iio_chan_spec *chan,
int *val, int *val2, long m) int *val, int *val2, long m)
...@@ -160,8 +185,17 @@ static int dht11_read_raw(struct iio_dev *iio_dev, ...@@ -160,8 +185,17 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
if (ret) if (ret)
goto err; 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, ret = wait_for_completion_killable_timeout(&dht11->completion,
HZ); HZ);
free_irq(dht11->irq, iio_dev);
if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) { if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) {
dev_err(&iio_dev->dev, dev_err(&iio_dev->dev,
"Only %d signal edges detected\n", "Only %d signal edges detected\n",
...@@ -197,27 +231,6 @@ static const struct iio_info dht11_iio_info = { ...@@ -197,27 +231,6 @@ static const struct iio_info dht11_iio_info = {
.read_raw = dht11_read_raw, .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[] = { static const struct iio_chan_spec dht11_chan_spec[] = {
{ .type = IIO_TEMP, { .type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), }, .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), },
...@@ -260,11 +273,6 @@ static int dht11_probe(struct platform_device *pdev) ...@@ -260,11 +273,6 @@ static int dht11_probe(struct platform_device *pdev)
dev_err(dev, "GPIO %d has no interrupt\n", dht11->gpio); dev_err(dev, "GPIO %d has no interrupt\n", dht11->gpio);
return -EINVAL; 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->timestamp = iio_get_time_ns() - DHT11_DATA_VALID_TIME - 1;
dht11->num_edges = -1; dht11->num_edges = -1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment