Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+35 −27
Original line number Original line Diff line number Diff line
@@ -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)
	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,
		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 = {
	.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)
		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;