diff options
| author | Richard Weinberger <richard@nod.at> | 2015-01-07 07:22:49 -0500 |
|---|---|---|
| committer | Jonathan Cameron <jic23@kernel.org> | 2015-01-10 06:16:32 -0500 |
| commit | 94e65519abde01cbffb9c538a4598f6a50bc86d1 (patch) | |
| tree | 6ef7dfd558f974ce53b734df3833cdb58292859e | |
| parent | 004bc530341a40536494431cf665504f8ee70266 (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.c | 62 |
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 | */ | ||
| 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 | |||
| 143 | static int dht11_read_raw(struct iio_dev *iio_dev, | 168 | static 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 | */ | ||
| 203 | static 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 | |||
| 221 | static const struct iio_chan_spec dht11_chan_spec[] = { | 234 | static 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; |
