* Re: [PATCH v2 2/2] iio: Add new driver dht11-gpio
[not found] ` <E1VZfrE-0000lZ-Ma-rvrRdOlaWMmli2aaYNgTVBW+3FKk/ZpWT2auq/jSWdo@public.gmane.org>
@ 2013-11-23 11:40 ` Jonathan Cameron
[not found] ` <52909438.8000602-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
0 siblings, 1 reply; 5+ messages in thread
From: Jonathan Cameron @ 2013-11-23 11:40 UTC (permalink / raw)
To: Harald Geyer, linux-iio-u79uwXL29TY76Z2rM5mHXA
Cc: Peter Meerwald, Lars-Peter Clausen,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
On 10/25/13 12:47, Harald Geyer wrote:
> This driver handles DHT11 and DHT22 sensors.
>
> Signed-off-by: Harald Geyer <harald-95f8Dae0BrPYtjvyW6yDsg@public.gmane.org>
Hi Harald,
I'm afraid I completely missed your posting of this version 2.
Do feel free to pester me if I fail to say anything about a patch
for a couple of weeks.
Anyhow
> ---
> changes since v1 (tested on DHT11):
> Add dependency on GPIOLIB
> Prefix all local preprocessor macros with DHT11_
> Rename STARTUP to START_TRANSMISSION
> Remove leading zeros
> Simplify channel disambiguation
> Remove obvious comments
> Make whitespace more consistent
> Strip unnecessary output and simplify error handling
> Fix spelling errors
>
> The v1 patch has been tested with DHT11 and DHT22 hardware.
There are a few redundant bits below that want to be dropped.
The only real issue I have otherwise is with the naming.
I would expect *-gpio to be a driver providing gpios?
Just go with dht11. This applies to the bindings as well.
Also note that policy is now to cc the device tree list for
all patches changing or introducing bindings.
I've cc'd them on this reply.
Thanks,
Jonathan
>
> Thanks,
> Harald
>
> .../bindings/iio/humidity/dht11-gpio.txt | 14 +
> drivers/iio/Kconfig | 1 +
> drivers/iio/Makefile | 1 +
> drivers/iio/humidity/Kconfig | 15 +
> drivers/iio/humidity/Makefile | 5 +
> drivers/iio/humidity/dht11-gpio.c | 325 ++++++++++++++++++++
> 6 files changed, 361 insertions(+), 0 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/iio/humidity/dht11-gpio.txt
> create mode 100644 drivers/iio/humidity/Kconfig
> create mode 100644 drivers/iio/humidity/Makefile
> create mode 100644 drivers/iio/humidity/dht11-gpio.c
>
> diff --git a/Documentation/devicetree/bindings/iio/humidity/dht11-gpio.txt b/Documentation/devicetree/bindings/iio/humidity/dht11-gpio.txt
> new file mode 100644
> index 0000000..ee8fa04
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/humidity/dht11-gpio.txt
> @@ -0,0 +1,14 @@
> +* DHT11 humidity/temperature sensor (and compatibles like DHT22)
> +
> +Required properties:
> + - compatible: Should be "dht11-gpio"
> + - gpios: Should specify the GPIO connected to the sensor's data
> + line, see "gpios property" in
> + Documentation/devicetree/bindings/gpio/gpio.txt.
> +
> +Example:
> +
> +humidity_sensor {
> + compatible = "dht11-gpio";
> + gpios = <&gpio0 6 0>;
> +}
> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
> index 90cf0cd..a5ed882 100644
> --- a/drivers/iio/Kconfig
> +++ b/drivers/iio/Kconfig
> @@ -65,6 +65,7 @@ source "drivers/iio/common/Kconfig"
> source "drivers/iio/dac/Kconfig"
> source "drivers/iio/frequency/Kconfig"
> source "drivers/iio/gyro/Kconfig"
> +source "drivers/iio/humidity/Kconfig"
> source "drivers/iio/imu/Kconfig"
> source "drivers/iio/light/Kconfig"
> source "drivers/iio/magnetometer/Kconfig"
> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
> index bcf7e9e..b3b5096 100644
> --- a/drivers/iio/Makefile
> +++ b/drivers/iio/Makefile
> @@ -18,6 +18,7 @@ obj-y += common/
> obj-y += dac/
> obj-y += gyro/
> obj-y += frequency/
> +obj-y += humidity/
> obj-y += imu/
> obj-y += light/
> obj-y += magnetometer/
> diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig
> new file mode 100644
> index 0000000..bbc44f2
> --- /dev/null
> +++ b/drivers/iio/humidity/Kconfig
> @@ -0,0 +1,15 @@
> +#
> +# humidity sensor drivers
> +#
> +menu "Humidity sensors"
> +
> +config DHT11_GPIO
The _GPIO to my mind would normally imply that this as a driver
providing GPIOs rather than using them.
> + tristate "DHT11 (and compatible sensors) driver"
> + depends on GPIOLIB
> + help
> + This driver supports reading data via a single interrupt
> + generating GPIO line. Currently tested are DHT11 and DHT22.
> + Other sensors should work as well as long as they speak the
> + same protocol.
> +
> +endmenu
> diff --git a/drivers/iio/humidity/Makefile b/drivers/iio/humidity/Makefile
> new file mode 100644
> index 0000000..5e8226f
> --- /dev/null
> +++ b/drivers/iio/humidity/Makefile
> @@ -0,0 +1,5 @@
> +#
> +# Makefile for IIO humidity sensor drivers
> +#
> +
> +obj-$(CONFIG_DHT11_GPIO) += dht11-gpio.o
> diff --git a/drivers/iio/humidity/dht11-gpio.c b/drivers/iio/humidity/dht11-gpio.c
> new file mode 100644
> index 0000000..3bb4d81
> --- /dev/null
> +++ b/drivers/iio/humidity/dht11-gpio.c
> @@ -0,0 +1,325 @@
...
Don't bother with this comment. If anyone wants it they can
add support :)
> +/* TODO?: Support systems without DT? */
> +
> +struct dht11_gpio {
> + struct device *dev;
> +
> + int gpio;
> + int irq;
> +
> + struct completion completion;
> +
> + s64 timestamp;
> + int temperature;
> + int humidity;
> +
> + /* num_edges: -1 means "no transmission in progress" */
> + int num_edges;
> + struct {s64 ts; int value; } edges[DHT11_EDGES_PER_READ];
> +};
> +
This isn't called anywhere and so should be removed from the driver.
> +/*
> + * dht11_edges_print: show the data as actually received by the
> + * driver.
> + * This is dead code, keeping it for now just in case somebody needs
> + * it for porting the driver to new sensor HW, etc.
> + *
> +static void dht11_edges_print(struct dht11_gpio *dht11)
> +{
> + int i;
> +
> + for (i = 1; i < dht11->num_edges; ++i) {
> + pr_err("dht11-gpio: %d: %lld ns %s\n", i,
> + dht11->edges[i].ts - dht11->edges[i-1].ts,
> + dht11->edges[i-1].value ? "high" : "low");
> + }
> +}
> +*/
...
> +static const struct of_device_id dht11_gpio_dt_ids[] = {
> + { .compatible = "dht11-gpio", },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, dht11_gpio_dt_ids);
> +
> +static int dht11_gpio_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *node = dev->of_node;
> + struct dht11_gpio *dht11;
> + struct iio_dev *iio;
> + int ret;
> +
> + iio = devm_iio_device_alloc(dev, sizeof(*dht11));
> + if (!iio) {
> + dev_err(dev, "Failed to allocate IIO device\n");
> + return -ENOMEM;
> + }
> +
> + dht11 = iio_priv(iio);
> + dht11->dev = dev;
> +
> + dht11->gpio = ret = of_get_gpio(node, 0);
> + if (ret < 0)
> + return ret;
> + ret = devm_gpio_request_one(dev, dht11->gpio, GPIOF_IN, pdev->name);
> + if (ret)
> + return ret;
> +
> + dht11->irq = gpio_to_irq(dht11->gpio);
> + if (dht11->irq < 0) {
> + dev_err(dev, "GPIO %d has no interrupt\n", dht11->gpio);
> + return -EINVAL;
> + }
> + ret = devm_request_irq(dev, dht11->irq, dht11_gpio_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;
> +
> + platform_set_drvdata(pdev, iio);
> +
> + init_completion(&dht11->completion);
> + iio->name = pdev->name;
> + iio->dev.parent = &pdev->dev;
> + iio->info = &dht11_gpio_iio_info;
> + iio->modes = INDIO_DIRECT_MODE;
> + iio->channels = dht11_gpio_chan_spec;
> + iio->num_channels = ARRAY_SIZE(dht11_gpio_chan_spec);
> +
> + return iio_device_register(iio);
> +}
> +
Could use the new devm_iio_device_register() call and drop
this boilerplate.
> +static int dht11_gpio_remove(struct platform_device *pdev)
> +{
> + struct iio_dev *iio = platform_get_drvdata(pdev);
> +
> + iio_device_unregister(iio);
> +
> + return 0;
> +}
> +
> +static struct platform_driver dht11_gpio_driver = {
> + .driver = {
> + .name = DRIVER_NAME,
> + .owner = THIS_MODULE,
> + .of_match_table = dht11_gpio_dt_ids,
> + },
> + .probe = dht11_gpio_probe,
> + .remove = dht11_gpio_remove,
> +};
> +
> +module_platform_driver(dht11_gpio_driver);
> +
> +MODULE_AUTHOR("Harald Geyer <harald-95f8Dae0BrPYtjvyW6yDsg@public.gmane.org>");
> +MODULE_DESCRIPTION("DHT11 humidity/temperature sensor driver");
> +MODULE_LICENSE("GPL v2");
> +
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] iio: Add new driver dht11-gpio
[not found] ` <52909438.8000602-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
@ 2013-11-23 17:44 ` Harald Geyer
[not found] ` <E1VkHFl-00012T-4U-rvrRdOlaWMmli2aaYNgTVBW+3FKk/ZpWT2auq/jSWdo@public.gmane.org>
0 siblings, 1 reply; 5+ messages in thread
From: Harald Geyer @ 2013-11-23 17:44 UTC (permalink / raw)
To: Jonathan Cameron
Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, Peter Meerwald,
Lars-Peter Clausen,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Jonathan Cameron writes:
>On 10/25/13 12:47, Harald Geyer wrote:
>> This driver handles DHT11 and DHT22 sensors.
>>
>> Signed-off-by: Harald Geyer <harald-95f8Dae0BrPYtjvyW6yDsg@public.gmane.org>
>
> Hi Harald,
>
> I'm afraid I completely missed your posting of this version 2.
>
> Do feel free to pester me if I fail to say anything about a patch
> for a couple of weeks.
Well, was going to do so in a few days ... :)
> Anyhow
>> ---
>> changes since v1 (tested on DHT11):
>> Add dependency on GPIOLIB
>> Prefix all local preprocessor macros with DHT11_
>> Rename STARTUP to START_TRANSMISSION
>> Remove leading zeros
>> Simplify channel disambiguation
>> Remove obvious comments
>> Make whitespace more consistent
>> Strip unnecessary output and simplify error handling
>> Fix spelling errors
>>
>> The v1 patch has been tested with DHT11 and DHT22 hardware.
> There are a few redundant bits below that want to be dropped.
>
> The only real issue I have otherwise is with the naming.
> I would expect *-gpio to be a driver providing gpios?
At least there are 'leds-gpio' and 'w1-gpio' already.
I was under the impression that drivers providing gpios
start with 'gpio' like 'gpio-mxs' ...
> Just go with dht11. This applies to the bindings as well.
I'm happy to grab 'dht11' but am reluctant to do so because
somebody might write a DHT11 driver using some other IO hardware
then gpio. How would this be called then?
> Also note that policy is now to cc the device tree list for
> all patches changing or introducing bindings.
>
> I've cc'd them on this reply.
Thanks.
> Thanks,
>
> Jonathan
>>
>> Thanks,
>> Harald
>>
>> .../bindings/iio/humidity/dht11-gpio.txt | 14 +
>> drivers/iio/Kconfig | 1 +
>> drivers/iio/Makefile | 1 +
>> drivers/iio/humidity/Kconfig | 15 +
>> drivers/iio/humidity/Makefile | 5 +
>> drivers/iio/humidity/dht11-gpio.c | 325 ++++++++++++++++++++
>> 6 files changed, 361 insertions(+), 0 deletions(-)
>> create mode 100644 Documentation/devicetree/bindings/iio/humidity/dht11-gpio.txt
>> create mode 100644 drivers/iio/humidity/Kconfig
>> create mode 100644 drivers/iio/humidity/Makefile
>> create mode 100644 drivers/iio/humidity/dht11-gpio.c
>>
>> diff --git a/Documentation/devicetree/bindings/iio/humidity/dht11-gpio.txt b/Documentation/devicetree/bindings/iio/humidity/dht11-gpio.txt
>> new file mode 100644
>> index 0000000..ee8fa04
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/iio/humidity/dht11-gpio.txt
>> @@ -0,0 +1,14 @@
>> +* DHT11 humidity/temperature sensor (and compatibles like DHT22)
>> +
>> +Required properties:
>> + - compatible: Should be "dht11-gpio"
>> + - gpios: Should specify the GPIO connected to the sensor's data
>> + line, see "gpios property" in
>> + Documentation/devicetree/bindings/gpio/gpio.txt.
>> +
>> +Example:
>> +
>> +humidity_sensor {
>> + compatible = "dht11-gpio";
>> + gpios = <&gpio0 6 0>;
>> +}
>> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
>> index 90cf0cd..a5ed882 100644
>> --- a/drivers/iio/Kconfig
>> +++ b/drivers/iio/Kconfig
>> @@ -65,6 +65,7 @@ source "drivers/iio/common/Kconfig"
>> source "drivers/iio/dac/Kconfig"
>> source "drivers/iio/frequency/Kconfig"
>> source "drivers/iio/gyro/Kconfig"
>> +source "drivers/iio/humidity/Kconfig"
>> source "drivers/iio/imu/Kconfig"
>> source "drivers/iio/light/Kconfig"
>> source "drivers/iio/magnetometer/Kconfig"
>> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
>> index bcf7e9e..b3b5096 100644
>> --- a/drivers/iio/Makefile
>> +++ b/drivers/iio/Makefile
>> @@ -18,6 +18,7 @@ obj-y += common/
>> obj-y += dac/
>> obj-y += gyro/
>> obj-y += frequency/
>> +obj-y += humidity/
>> obj-y += imu/
>> obj-y += light/
>> obj-y += magnetometer/
>> diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig
>> new file mode 100644
>> index 0000000..bbc44f2
>> --- /dev/null
>> +++ b/drivers/iio/humidity/Kconfig
>> @@ -0,0 +1,15 @@
>> +#
>> +# humidity sensor drivers
>> +#
>> +menu "Humidity sensors"
>> +
>> +config DHT11_GPIO
> The _GPIO to my mind would normally imply that this as a driver
> providing GPIOs rather than using them.
I will change this according to the result of the naming
discussion.
>> + tristate "DHT11 (and compatible sensors) driver"
>> + depends on GPIOLIB
>> + help
>> + This driver supports reading data via a single interrupt
>> + generating GPIO line. Currently tested are DHT11 and DHT22.
>> + Other sensors should work as well as long as they speak the
>> + same protocol.
>> +
>> +endmenu
>> diff --git a/drivers/iio/humidity/Makefile b/drivers/iio/humidity/Makefile
>> new file mode 100644
>> index 0000000..5e8226f
>> --- /dev/null
>> +++ b/drivers/iio/humidity/Makefile
>> @@ -0,0 +1,5 @@
>> +#
>> +# Makefile for IIO humidity sensor drivers
>> +#
>> +
>> +obj-$(CONFIG_DHT11_GPIO) += dht11-gpio.o
>> diff --git a/drivers/iio/humidity/dht11-gpio.c b/drivers/iio/humidity/dht11-gpio.c
>> new file mode 100644
>> index 0000000..3bb4d81
>> --- /dev/null
>> +++ b/drivers/iio/humidity/dht11-gpio.c
>> @@ -0,0 +1,325 @@
> ...
> Don't bother with this comment. If anyone wants it they can
> add support :)
>> +/* TODO?: Support systems without DT? */
Ok.
>> +
>> +struct dht11_gpio {
>> + struct device *dev;
>> +
>> + int gpio;
>> + int irq;
>> +
>> + struct completion completion;
>> +
>> + s64 timestamp;
>> + int temperature;
>> + int humidity;
>> +
>> + /* num_edges: -1 means "no transmission in progress" */
>> + int num_edges;
>> + struct {s64 ts; int value; } edges[DHT11_EDGES_PER_READ];
>> +};
>> +
> This isn't called anywhere and so should be removed from the driver.
I will do so, if you think it's more apropriate. I figured that
commenting it out is like removing but retaining a useful comment.
Maybe prefix the whole comment with asterix to make it more obvious
this actually is a comment?
>> +/*
>> + * dht11_edges_print: show the data as actually received by the
>> + * driver.
>> + * This is dead code, keeping it for now just in case somebody needs
>> + * it for porting the driver to new sensor HW, etc.
>> + *
>> +static void dht11_edges_print(struct dht11_gpio *dht11)
>> +{
>> + int i;
>> +
>> + for (i = 1; i < dht11->num_edges; ++i) {
>> + pr_err("dht11-gpio: %d: %lld ns %s\n", i,
>> + dht11->edges[i].ts - dht11->edges[i-1].ts,
>> + dht11->edges[i-1].value ? "high" : "low");
>> + }
>> +}
>> +*/
> ...
>> +static const struct of_device_id dht11_gpio_dt_ids[] = {
>> + { .compatible = "dht11-gpio", },
>> + { }
>> +};
>> +MODULE_DEVICE_TABLE(of, dht11_gpio_dt_ids);
>> +
>> +static int dht11_gpio_probe(struct platform_device *pdev)
>> +{
>> + struct device *dev = &pdev->dev;
>> + struct device_node *node = dev->of_node;
>> + struct dht11_gpio *dht11;
>> + struct iio_dev *iio;
>> + int ret;
>> +
>> + iio = devm_iio_device_alloc(dev, sizeof(*dht11));
>> + if (!iio) {
>> + dev_err(dev, "Failed to allocate IIO device\n");
>> + return -ENOMEM;
>> + }
>> +
>> + dht11 = iio_priv(iio);
>> + dht11->dev = dev;
>> +
>> + dht11->gpio = ret = of_get_gpio(node, 0);
>> + if (ret < 0)
>> + return ret;
>> + ret = devm_gpio_request_one(dev, dht11->gpio, GPIOF_IN, pdev->name);
>> + if (ret)
>> + return ret;
>> +
>> + dht11->irq = gpio_to_irq(dht11->gpio);
>> + if (dht11->irq < 0) {
>> + dev_err(dev, "GPIO %d has no interrupt\n", dht11->gpio);
>> + return -EINVAL;
>> + }
>> + ret = devm_request_irq(dev, dht11->irq, dht11_gpio_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;
>> +
>> + platform_set_drvdata(pdev, iio);
>> +
>> + init_completion(&dht11->completion);
>> + iio->name = pdev->name;
>> + iio->dev.parent = &pdev->dev;
>> + iio->info = &dht11_gpio_iio_info;
>> + iio->modes = INDIO_DIRECT_MODE;
>> + iio->channels = dht11_gpio_chan_spec;
>> + iio->num_channels = ARRAY_SIZE(dht11_gpio_chan_spec);
>> +
>> + return iio_device_register(iio);
>> +}
>> +
>
> Could use the new devm_iio_device_register() call and drop
> this boilerplate.
Yes, I'll send a v3 with this after the other issues are sorted
out.
Thanks,
Harald
>> +static int dht11_gpio_remove(struct platform_device *pdev)
>> +{
>> + struct iio_dev *iio = platform_get_drvdata(pdev);
>> +
>> + iio_device_unregister(iio);
>> +
>> + return 0;
>> +}
>> +
>> +static struct platform_driver dht11_gpio_driver = {
>> + .driver = {
>> + .name = DRIVER_NAME,
>> + .owner = THIS_MODULE,
>> + .of_match_table = dht11_gpio_dt_ids,
>> + },
>> + .probe = dht11_gpio_probe,
>> + .remove = dht11_gpio_remove,
>> +};
>> +
>> +module_platform_driver(dht11_gpio_driver);
>> +
>> +MODULE_AUTHOR("Harald Geyer <harald-95f8Dae0BrPYtjvyW6yDsg@public.gmane.org>");
>> +MODULE_DESCRIPTION("DHT11 humidity/temperature sensor driver");
>> +MODULE_LICENSE("GPL v2");
>> +
>>
>--
>To unsubscribe from this list: send the line "unsubscribe linux-iio" in
>the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] iio: Add new driver dht11-gpio
[not found] ` <E1VkHFl-00012T-4U-rvrRdOlaWMmli2aaYNgTVBW+3FKk/ZpWT2auq/jSWdo@public.gmane.org>
@ 2013-11-24 18:36 ` Jonathan Cameron
[not found] ` <5292474A.8040101-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
0 siblings, 1 reply; 5+ messages in thread
From: Jonathan Cameron @ 2013-11-24 18:36 UTC (permalink / raw)
To: Harald Geyer
Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, Peter Meerwald,
Lars-Peter Clausen,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
On 11/23/13 17:44, Harald Geyer wrote:
> Jonathan Cameron writes:
>> On 10/25/13 12:47, Harald Geyer wrote:
>>> This driver handles DHT11 and DHT22 sensors.
>>>
>>> Signed-off-by: Harald Geyer <harald-95f8Dae0BrPYtjvyW6yDsg@public.gmane.org>
>>
>> Hi Harald,
>>
>> I'm afraid I completely missed your posting of this version 2.
>>
>> Do feel free to pester me if I fail to say anything about a patch
>> for a couple of weeks.
>
> Well, was going to do so in a few days ... :)
>
>> Anyhow
>>> ---
>>> changes since v1 (tested on DHT11):
>>> Add dependency on GPIOLIB
>>> Prefix all local preprocessor macros with DHT11_
>>> Rename STARTUP to START_TRANSMISSION
>>> Remove leading zeros
>>> Simplify channel disambiguation
>>> Remove obvious comments
>>> Make whitespace more consistent
>>> Strip unnecessary output and simplify error handling
>>> Fix spelling errors
>>>
>>> The v1 patch has been tested with DHT11 and DHT22 hardware.
>> There are a few redundant bits below that want to be dropped.
>>
>> The only real issue I have otherwise is with the naming.
>> I would expect *-gpio to be a driver providing gpios?
>
> At least there are 'leds-gpio' and 'w1-gpio' already.
> I was under the impression that drivers providing gpios
> start with 'gpio' like 'gpio-mxs' ...
Looking at the device tree bindings, this is a mess. Some are gpio-*
and some *-gpio.
>
>> Just go with dht11. This applies to the bindings as well.
>
> I'm happy to grab 'dht11' but am reluctant to do so because
> somebody might write a DHT11 driver using some other IO hardware
> then gpio. How would this be called then?
I would hope that they would rework the driver to support both rather
than starting again.
I would definitely go with just dht11
>
>> Also note that policy is now to cc the device tree list for
>> all patches changing or introducing bindings.
>>
>> I've cc'd them on this reply.
>
> Thanks.
>
>> Thanks,
>>
>> Jonathan
>>>
>>> Thanks,
>>> Harald
>>>
>>> .../bindings/iio/humidity/dht11-gpio.txt | 14 +
>>> drivers/iio/Kconfig | 1 +
>>> drivers/iio/Makefile | 1 +
>>> drivers/iio/humidity/Kconfig | 15 +
>>> drivers/iio/humidity/Makefile | 5 +
>>> drivers/iio/humidity/dht11-gpio.c | 325 ++++++++++++++++++++
>>> 6 files changed, 361 insertions(+), 0 deletions(-)
>>> create mode 100644 Documentation/devicetree/bindings/iio/humidity/dht11-gpio.txt
>>> create mode 100644 drivers/iio/humidity/Kconfig
>>> create mode 100644 drivers/iio/humidity/Makefile
>>> create mode 100644 drivers/iio/humidity/dht11-gpio.c
>>>
>>> diff --git a/Documentation/devicetree/bindings/iio/humidity/dht11-gpio.txt b/Documentation/devicetree/bindings/iio/humidity/dht11-gpio.txt
>>> new file mode 100644
>>> index 0000000..ee8fa04
>>> --- /dev/null
>>> +++ b/Documentation/devicetree/bindings/iio/humidity/dht11-gpio.txt
>>> @@ -0,0 +1,14 @@
>>> +* DHT11 humidity/temperature sensor (and compatibles like DHT22)
>>> +
>>> +Required properties:
>>> + - compatible: Should be "dht11-gpio"
>>> + - gpios: Should specify the GPIO connected to the sensor's data
>>> + line, see "gpios property" in
>>> + Documentation/devicetree/bindings/gpio/gpio.txt.
>>> +
>>> +Example:
>>> +
>>> +humidity_sensor {
>>> + compatible = "dht11-gpio";
>>> + gpios = <&gpio0 6 0>;
>>> +}
>>> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
>>> index 90cf0cd..a5ed882 100644
>>> --- a/drivers/iio/Kconfig
>>> +++ b/drivers/iio/Kconfig
>>> @@ -65,6 +65,7 @@ source "drivers/iio/common/Kconfig"
>>> source "drivers/iio/dac/Kconfig"
>>> source "drivers/iio/frequency/Kconfig"
>>> source "drivers/iio/gyro/Kconfig"
>>> +source "drivers/iio/humidity/Kconfig"
>>> source "drivers/iio/imu/Kconfig"
>>> source "drivers/iio/light/Kconfig"
>>> source "drivers/iio/magnetometer/Kconfig"
>>> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
>>> index bcf7e9e..b3b5096 100644
>>> --- a/drivers/iio/Makefile
>>> +++ b/drivers/iio/Makefile
>>> @@ -18,6 +18,7 @@ obj-y += common/
>>> obj-y += dac/
>>> obj-y += gyro/
>>> obj-y += frequency/
>>> +obj-y += humidity/
>>> obj-y += imu/
>>> obj-y += light/
>>> obj-y += magnetometer/
>>> diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig
>>> new file mode 100644
>>> index 0000000..bbc44f2
>>> --- /dev/null
>>> +++ b/drivers/iio/humidity/Kconfig
>>> @@ -0,0 +1,15 @@
>>> +#
>>> +# humidity sensor drivers
>>> +#
>>> +menu "Humidity sensors"
>>> +
>>> +config DHT11_GPIO
>> The _GPIO to my mind would normally imply that this as a driver
>> providing GPIOs rather than using them.
>
> I will change this according to the result of the naming
> discussion.
>
>>> + tristate "DHT11 (and compatible sensors) driver"
>>> + depends on GPIOLIB
>>> + help
>>> + This driver supports reading data via a single interrupt
>>> + generating GPIO line. Currently tested are DHT11 and DHT22.
>>> + Other sensors should work as well as long as they speak the
>>> + same protocol.
>>> +
>>> +endmenu
>>> diff --git a/drivers/iio/humidity/Makefile b/drivers/iio/humidity/Makefile
>>> new file mode 100644
>>> index 0000000..5e8226f
>>> --- /dev/null
>>> +++ b/drivers/iio/humidity/Makefile
>>> @@ -0,0 +1,5 @@
>>> +#
>>> +# Makefile for IIO humidity sensor drivers
>>> +#
>>> +
>>> +obj-$(CONFIG_DHT11_GPIO) += dht11-gpio.o
>>> diff --git a/drivers/iio/humidity/dht11-gpio.c b/drivers/iio/humidity/dht11-gpio.c
>>> new file mode 100644
>>> index 0000000..3bb4d81
>>> --- /dev/null
>>> +++ b/drivers/iio/humidity/dht11-gpio.c
>>> @@ -0,0 +1,325 @@
>> ...
>> Don't bother with this comment. If anyone wants it they can
>> add support :)
>>> +/* TODO?: Support systems without DT? */
>
> Ok.
>
>>> +
>>> +struct dht11_gpio {
>>> + struct device *dev;
>>> +
>>> + int gpio;
>>> + int irq;
>>> +
>>> + struct completion completion;
>>> +
>>> + s64 timestamp;
>>> + int temperature;
>>> + int humidity;
>>> +
>>> + /* num_edges: -1 means "no transmission in progress" */
>>> + int num_edges;
>>> + struct {s64 ts; int value; } edges[DHT11_EDGES_PER_READ];
>>> +};
>>> +
>> This isn't called anywhere and so should be removed from the driver.
>
> I will do so, if you think it's more apropriate. I figured that
> commenting it out is like removing but retaining a useful comment.
> Maybe prefix the whole comment with asterix to make it more obvious
> this actually is a comment?
>
>>> +/*
>>> + * dht11_edges_print: show the data as actually received by the
>>> + * driver.
>>> + * This is dead code, keeping it for now just in case somebody needs
>>> + * it for porting the driver to new sensor HW, etc.
>>> + *
>>> +static void dht11_edges_print(struct dht11_gpio *dht11)
>>> +{
>>> + int i;
>>> +
>>> + for (i = 1; i < dht11->num_edges; ++i) {
>>> + pr_err("dht11-gpio: %d: %lld ns %s\n", i,
>>> + dht11->edges[i].ts - dht11->edges[i-1].ts,
>>> + dht11->edges[i-1].value ? "high" : "low");
>>> + }
>>> +}
>>> +*/
>> ...
>
>
>
>>> +static const struct of_device_id dht11_gpio_dt_ids[] = {
>>> + { .compatible = "dht11-gpio", },
>>> + { }
>>> +};
>>> +MODULE_DEVICE_TABLE(of, dht11_gpio_dt_ids);
>>> +
>>> +static int dht11_gpio_probe(struct platform_device *pdev)
>>> +{
>>> + struct device *dev = &pdev->dev;
>>> + struct device_node *node = dev->of_node;
>>> + struct dht11_gpio *dht11;
>>> + struct iio_dev *iio;
>>> + int ret;
>>> +
>>> + iio = devm_iio_device_alloc(dev, sizeof(*dht11));
>>> + if (!iio) {
>>> + dev_err(dev, "Failed to allocate IIO device\n");
>>> + return -ENOMEM;
>>> + }
>>> +
>>> + dht11 = iio_priv(iio);
>>> + dht11->dev = dev;
>>> +
>>> + dht11->gpio = ret = of_get_gpio(node, 0);
>>> + if (ret < 0)
>>> + return ret;
>>> + ret = devm_gpio_request_one(dev, dht11->gpio, GPIOF_IN, pdev->name);
>>> + if (ret)
>>> + return ret;
>>> +
>>> + dht11->irq = gpio_to_irq(dht11->gpio);
>>> + if (dht11->irq < 0) {
>>> + dev_err(dev, "GPIO %d has no interrupt\n", dht11->gpio);
>>> + return -EINVAL;
>>> + }
>>> + ret = devm_request_irq(dev, dht11->irq, dht11_gpio_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;
>>> +
>>> + platform_set_drvdata(pdev, iio);
>>> +
>>> + init_completion(&dht11->completion);
>>> + iio->name = pdev->name;
>>> + iio->dev.parent = &pdev->dev;
>>> + iio->info = &dht11_gpio_iio_info;
>>> + iio->modes = INDIO_DIRECT_MODE;
>>> + iio->channels = dht11_gpio_chan_spec;
>>> + iio->num_channels = ARRAY_SIZE(dht11_gpio_chan_spec);
>>> +
>>> + return iio_device_register(iio);
>>> +}
>>> +
>>
>> Could use the new devm_iio_device_register() call and drop
>> this boilerplate.
>
> Yes, I'll send a v3 with this after the other issues are sorted
> out.
>
> Thanks,
> Harald
>
>>> +static int dht11_gpio_remove(struct platform_device *pdev)
>>> +{
>>> + struct iio_dev *iio = platform_get_drvdata(pdev);
>>> +
>>> + iio_device_unregister(iio);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static struct platform_driver dht11_gpio_driver = {
>>> + .driver = {
>>> + .name = DRIVER_NAME,
>>> + .owner = THIS_MODULE,
>>> + .of_match_table = dht11_gpio_dt_ids,
>>> + },
>>> + .probe = dht11_gpio_probe,
>>> + .remove = dht11_gpio_remove,
>>> +};
>>> +
>>> +module_platform_driver(dht11_gpio_driver);
>>> +
>>> +MODULE_AUTHOR("Harald Geyer <harald-95f8Dae0BrPYtjvyW6yDsg@public.gmane.org>");
>>> +MODULE_DESCRIPTION("DHT11 humidity/temperature sensor driver");
>>> +MODULE_LICENSE("GPL v2");
>>> +
>>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
>> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v3 2/2] iio: Add new driver dht11
[not found] ` <5292474A.8040101-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
@ 2013-12-01 15:04 ` Harald Geyer
[not found] ` <E1Vn8Z7-0001H3-5v-rvrRdOlaWMmli2aaYNgTVBW+3FKk/ZpWT2auq/jSWdo@public.gmane.org>
0 siblings, 1 reply; 5+ messages in thread
From: Harald Geyer @ 2013-12-01 15:04 UTC (permalink / raw)
To: Jonathan Cameron
Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, Peter Meerwald,
Lars-Peter Clausen,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
This driver handles DHT11 and DHT22 sensors.
Signed-off-by: Harald Geyer <harald-95f8Dae0BrPYtjvyW6yDsg@public.gmane.org>
---
changes since v2 (tested on DHT22):
Remove some comments
Use devm_iio_device_register()
Rename driver: dht11-gpio -> dht11
Move from INIT_COMPLETION to reinit_completion()
changes since v1 (tested on DHT11):
Add dependency on GPIOLIB
Prefix all local preprocessor macros with DHT11_
Rename STARTUP to START_TRANSMISSION
Remove leading zeros
Simplify channel disambiguation
Remove obvious comments
Make whitespace more consistent
Strip unnecessary output and simplify error handling
Fix spelling errors
The v1 patch has been tested with DHT11 and DHT22 hardware.
Thanks,
Harald
.../devicetree/bindings/iio/humidity/dht11.txt | 14 +
drivers/iio/Kconfig | 1 +
drivers/iio/Makefile | 1 +
drivers/iio/humidity/Kconfig | 15 +
drivers/iio/humidity/Makefile | 5 +
drivers/iio/humidity/dht11.c | 295 ++++++++++++++++++++
6 files changed, 331 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/iio/humidity/dht11.txt
create mode 100644 drivers/iio/humidity/Kconfig
create mode 100644 drivers/iio/humidity/Makefile
create mode 100644 drivers/iio/humidity/dht11.c
diff --git a/Documentation/devicetree/bindings/iio/humidity/dht11.txt b/Documentation/devicetree/bindings/iio/humidity/dht11.txt
new file mode 100644
index 0000000..ecc24c19
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/humidity/dht11.txt
@@ -0,0 +1,14 @@
+* DHT11 humidity/temperature sensor (and compatibles like DHT22)
+
+Required properties:
+ - compatible: Should be "dht11"
+ - gpios: Should specify the GPIO connected to the sensor's data
+ line, see "gpios property" in
+ Documentation/devicetree/bindings/gpio/gpio.txt.
+
+Example:
+
+humidity_sensor {
+ compatible = "dht11";
+ gpios = <&gpio0 6 0>;
+}
diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
index 90cf0cd..a5ed882 100644
--- a/drivers/iio/Kconfig
+++ b/drivers/iio/Kconfig
@@ -65,6 +65,7 @@ source "drivers/iio/common/Kconfig"
source "drivers/iio/dac/Kconfig"
source "drivers/iio/frequency/Kconfig"
source "drivers/iio/gyro/Kconfig"
+source "drivers/iio/humidity/Kconfig"
source "drivers/iio/imu/Kconfig"
source "drivers/iio/light/Kconfig"
source "drivers/iio/magnetometer/Kconfig"
diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
index bcf7e9e..b3b5096 100644
--- a/drivers/iio/Makefile
+++ b/drivers/iio/Makefile
@@ -18,6 +18,7 @@ obj-y += common/
obj-y += dac/
obj-y += gyro/
obj-y += frequency/
+obj-y += humidity/
obj-y += imu/
obj-y += light/
obj-y += magnetometer/
diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig
new file mode 100644
index 0000000..463c4d9
--- /dev/null
+++ b/drivers/iio/humidity/Kconfig
@@ -0,0 +1,15 @@
+#
+# humidity sensor drivers
+#
+menu "Humidity sensors"
+
+config DHT11
+ tristate "DHT11 (and compatible sensors) driver"
+ depends on GPIOLIB
+ help
+ This driver supports reading data via a single interrupt
+ generating GPIO line. Currently tested are DHT11 and DHT22.
+ Other sensors should work as well as long as they speak the
+ same protocol.
+
+endmenu
diff --git a/drivers/iio/humidity/Makefile b/drivers/iio/humidity/Makefile
new file mode 100644
index 0000000..d5d36c0
--- /dev/null
+++ b/drivers/iio/humidity/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for IIO humidity sensor drivers
+#
+
+obj-$(CONFIG_DHT11) += dht11.o
diff --git a/drivers/iio/humidity/dht11.c b/drivers/iio/humidity/dht11.c
new file mode 100644
index 0000000..248f0da
--- /dev/null
+++ b/drivers/iio/humidity/dht11.c
@@ -0,0 +1,295 @@
+/*
+ * DHT11/DHT22 bit banging GPIO driver
+ *
+ * Copyright (c) Harald Geyer <harald-95f8Dae0BrPYtjvyW6yDsg@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/sysfs.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+#include <linux/bitops.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#include <linux/iio/iio.h>
+
+#define DRIVER_NAME "dht11"
+
+#define DHT11_DATA_VALID_TIME 2000000000 /* 2s in ns */
+
+#define DHT11_EDGES_PREAMBLE 4
+#define DHT11_BITS_PER_READ 40
+#define DHT11_EDGES_PER_READ (2*DHT11_BITS_PER_READ + DHT11_EDGES_PREAMBLE + 1)
+
+/* Data transmission timing (nano seconds) */
+#define DHT11_START_TRANSMISSION 18 /* ms */
+#define DHT11_SENSOR_RESPONSE 80000
+#define DHT11_START_BIT 50000
+#define DHT11_DATA_BIT_LOW 27000
+#define DHT11_DATA_BIT_HIGH 70000
+
+struct dht11 {
+ struct device *dev;
+
+ int gpio;
+ int irq;
+
+ struct completion completion;
+
+ s64 timestamp;
+ int temperature;
+ int humidity;
+
+ /* num_edges: -1 means "no transmission in progress" */
+ int num_edges;
+ struct {s64 ts; int value; } edges[DHT11_EDGES_PER_READ];
+};
+
+static unsigned char dht11_decode_byte(int *timing, int threshold)
+{
+ unsigned char ret = 0;
+ int i;
+
+ for (i = 0; i < 8; ++i) {
+ ret <<= 1;
+ if (timing[i] >= threshold)
+ ++ret;
+ }
+
+ return ret;
+}
+
+static int dht11_decode(struct dht11 *dht11, int offset)
+{
+ int i, t, timing[DHT11_BITS_PER_READ], threshold,
+ timeres = DHT11_SENSOR_RESPONSE;
+ unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum;
+
+ /* Calculate timestamp resolution */
+ for (i = 0; i < dht11->num_edges; ++i) {
+ t = dht11->edges[i].ts - dht11->edges[i-1].ts;
+ if (t > 0 && t < timeres)
+ timeres = t;
+ }
+ if (2*timeres > DHT11_DATA_BIT_HIGH) {
+ pr_err("dht11: timeresolution %d too bad for decoding\n",
+ timeres);
+ return -EIO;
+ }
+ threshold = DHT11_DATA_BIT_HIGH / timeres;
+ if (DHT11_DATA_BIT_LOW/timeres + 1 >= threshold)
+ pr_err("dht11: WARNING: decoding ambiguous\n");
+
+ /* scale down with timeres and check validity */
+ for (i = 0; i < DHT11_BITS_PER_READ; ++i) {
+ t = dht11->edges[offset + 2*i + 2].ts -
+ dht11->edges[offset + 2*i + 1].ts;
+ if (!dht11->edges[offset + 2*i + 1].value)
+ return -EIO; /* lost synchronisation */
+ timing[i] = t / timeres;
+ }
+
+ hum_int = dht11_decode_byte(timing, threshold);
+ hum_dec = dht11_decode_byte(&timing[8], threshold);
+ temp_int = dht11_decode_byte(&timing[16], threshold);
+ temp_dec = dht11_decode_byte(&timing[24], threshold);
+ checksum = dht11_decode_byte(&timing[32], threshold);
+
+ if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum)
+ return -EIO;
+
+ dht11->timestamp = iio_get_time_ns();
+ if (hum_int < 20) { /* DHT22 */
+ dht11->temperature = (((temp_int & 0x7f) << 8) + temp_dec) *
+ ((temp_int & 0x80) ? -100 : 100);
+ dht11->humidity = ((hum_int << 8) + hum_dec) * 100;
+ } else if (temp_dec == 0 && hum_dec == 0) { /* DHT11 */
+ dht11->temperature = temp_int * 1000;
+ dht11->humidity = hum_int * 1000;
+ } else {
+ dev_err(dht11->dev,
+ "Don't know how to decode data: %d %d %d %d\n",
+ hum_int, hum_dec, temp_int, temp_dec);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int dht11_read_raw(struct iio_dev *iio_dev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long m)
+{
+ struct dht11 *dht11 = iio_priv(iio_dev);
+ int ret;
+
+ if (dht11->timestamp + DHT11_DATA_VALID_TIME < iio_get_time_ns()) {
+ reinit_completion(&dht11->completion);
+
+ dht11->num_edges = 0;
+ ret = gpio_direction_output(dht11->gpio, 0);
+ if (ret)
+ goto err;
+ msleep(DHT11_START_TRANSMISSION);
+ ret = gpio_direction_input(dht11->gpio);
+ if (ret)
+ goto err;
+
+ ret = wait_for_completion_killable_timeout(&dht11->completion,
+ HZ);
+ if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) {
+ dev_err(&iio_dev->dev,
+ "Only %d signal edges detected\n",
+ dht11->num_edges);
+ ret = -ETIMEDOUT;
+ }
+ if (ret < 0)
+ goto err;
+
+ ret = dht11_decode(dht11,
+ dht11->num_edges == DHT11_EDGES_PER_READ ?
+ DHT11_EDGES_PREAMBLE :
+ DHT11_EDGES_PREAMBLE - 2);
+ if (ret)
+ goto err;
+ }
+
+ ret = IIO_VAL_INT;
+ if (chan->type == IIO_TEMP)
+ *val = dht11->temperature;
+ else if (chan->type == IIO_HUMIDITYRELATIVE)
+ *val = dht11->humidity;
+ else
+ ret = -EINVAL;
+err:
+ dht11->num_edges = -1;
+ return ret;
+}
+
+static const struct iio_info dht11_iio_info = {
+ .driver_module = THIS_MODULE,
+ .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), },
+ { .type = IIO_HUMIDITYRELATIVE,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), }
+};
+
+static const struct of_device_id dht11_dt_ids[] = {
+ { .compatible = "dht11", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, dht11_dt_ids);
+
+static int dht11_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *node = dev->of_node;
+ struct dht11 *dht11;
+ struct iio_dev *iio;
+ int ret;
+
+ iio = devm_iio_device_alloc(dev, sizeof(*dht11));
+ if (!iio) {
+ dev_err(dev, "Failed to allocate IIO device\n");
+ return -ENOMEM;
+ }
+
+ dht11 = iio_priv(iio);
+ dht11->dev = dev;
+
+ dht11->gpio = ret = of_get_gpio(node, 0);
+ if (ret < 0)
+ return ret;
+ ret = devm_gpio_request_one(dev, dht11->gpio, GPIOF_IN, pdev->name);
+ if (ret)
+ return ret;
+
+ dht11->irq = gpio_to_irq(dht11->gpio);
+ if (dht11->irq < 0) {
+ 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;
+
+ platform_set_drvdata(pdev, iio);
+
+ init_completion(&dht11->completion);
+ iio->name = pdev->name;
+ iio->dev.parent = &pdev->dev;
+ iio->info = &dht11_iio_info;
+ iio->modes = INDIO_DIRECT_MODE;
+ iio->channels = dht11_chan_spec;
+ iio->num_channels = ARRAY_SIZE(dht11_chan_spec);
+
+ return devm_iio_device_register(dev, iio);
+}
+
+static struct platform_driver dht11_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = dht11_dt_ids,
+ },
+ .probe = dht11_probe,
+};
+
+module_platform_driver(dht11_driver);
+
+MODULE_AUTHOR("Harald Geyer <harald-95f8Dae0BrPYtjvyW6yDsg@public.gmane.org>");
+MODULE_DESCRIPTION("DHT11 humidity/temperature sensor driver");
+MODULE_LICENSE("GPL v2");
+
--
1.7.2.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v3 2/2] iio: Add new driver dht11
[not found] ` <E1Vn8Z7-0001H3-5v-rvrRdOlaWMmli2aaYNgTVBW+3FKk/ZpWT2auq/jSWdo@public.gmane.org>
@ 2013-12-03 20:19 ` Jonathan Cameron
0 siblings, 0 replies; 5+ messages in thread
From: Jonathan Cameron @ 2013-12-03 20:19 UTC (permalink / raw)
To: Harald Geyer
Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA, Peter Meerwald,
Lars-Peter Clausen,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
On 12/01/13 15:04, Harald Geyer wrote:
> This driver handles DHT11 and DHT22 sensors.
>
> Signed-off-by: Harald Geyer <harald-95f8Dae0BrPYtjvyW6yDsg@public.gmane.org>
Applied with 2 white space at end of line and one two many blank lines at the end of the
file fixed.
Applied to the togreg branch of iio.git (pushed out for now as testing until the
autobuilders are done).
Thanks for your hard work on this 'interesting' device ;)
Peter/Lars, if you want to add an ack/reviewed by then you have a day or two...
Note given it is a trivial binding and has been posted for a lot more than 3 weeks
I'm happy to take this one without and device tree specific feedback...
Jonathan
> ---
> changes since v2 (tested on DHT22):
> Remove some comments
> Use devm_iio_device_register()
> Rename driver: dht11-gpio -> dht11
> Move from INIT_COMPLETION to reinit_completion()
>
> changes since v1 (tested on DHT11):
> Add dependency on GPIOLIB
> Prefix all local preprocessor macros with DHT11_
> Rename STARTUP to START_TRANSMISSION
> Remove leading zeros
> Simplify channel disambiguation
> Remove obvious comments
> Make whitespace more consistent
> Strip unnecessary output and simplify error handling
> Fix spelling errors
>
> The v1 patch has been tested with DHT11 and DHT22 hardware.
>
> Thanks,
> Harald
>
> .../devicetree/bindings/iio/humidity/dht11.txt | 14 +
> drivers/iio/Kconfig | 1 +
> drivers/iio/Makefile | 1 +
> drivers/iio/humidity/Kconfig | 15 +
> drivers/iio/humidity/Makefile | 5 +
> drivers/iio/humidity/dht11.c | 295 ++++++++++++++++++++
> 6 files changed, 331 insertions(+), 0 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/iio/humidity/dht11.txt
> create mode 100644 drivers/iio/humidity/Kconfig
> create mode 100644 drivers/iio/humidity/Makefile
> create mode 100644 drivers/iio/humidity/dht11.c
>
> diff --git a/Documentation/devicetree/bindings/iio/humidity/dht11.txt b/Documentation/devicetree/bindings/iio/humidity/dht11.txt
> new file mode 100644
> index 0000000..ecc24c19
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/humidity/dht11.txt
> @@ -0,0 +1,14 @@
> +* DHT11 humidity/temperature sensor (and compatibles like DHT22)
> +
> +Required properties:
> + - compatible: Should be "dht11"
> + - gpios: Should specify the GPIO connected to the sensor's data
> + line, see "gpios property" in
> + Documentation/devicetree/bindings/gpio/gpio.txt.
> +
> +Example:
> +
> +humidity_sensor {
> + compatible = "dht11";
> + gpios = <&gpio0 6 0>;
> +}
> diff --git a/drivers/iio/Kconfig b/drivers/iio/Kconfig
> index 90cf0cd..a5ed882 100644
> --- a/drivers/iio/Kconfig
> +++ b/drivers/iio/Kconfig
> @@ -65,6 +65,7 @@ source "drivers/iio/common/Kconfig"
> source "drivers/iio/dac/Kconfig"
> source "drivers/iio/frequency/Kconfig"
> source "drivers/iio/gyro/Kconfig"
> +source "drivers/iio/humidity/Kconfig"
> source "drivers/iio/imu/Kconfig"
> source "drivers/iio/light/Kconfig"
> source "drivers/iio/magnetometer/Kconfig"
> diff --git a/drivers/iio/Makefile b/drivers/iio/Makefile
> index bcf7e9e..b3b5096 100644
> --- a/drivers/iio/Makefile
> +++ b/drivers/iio/Makefile
> @@ -18,6 +18,7 @@ obj-y += common/
> obj-y += dac/
> obj-y += gyro/
> obj-y += frequency/
> +obj-y += humidity/
> obj-y += imu/
> obj-y += light/
> obj-y += magnetometer/
> diff --git a/drivers/iio/humidity/Kconfig b/drivers/iio/humidity/Kconfig
> new file mode 100644
> index 0000000..463c4d9
> --- /dev/null
> +++ b/drivers/iio/humidity/Kconfig
> @@ -0,0 +1,15 @@
> +#
> +# humidity sensor drivers
> +#
> +menu "Humidity sensors"
> +
> +config DHT11
> + tristate "DHT11 (and compatible sensors) driver"
> + depends on GPIOLIB
> + help
> + This driver supports reading data via a single interrupt
> + generating GPIO line. Currently tested are DHT11 and DHT22.
> + Other sensors should work as well as long as they speak the
> + same protocol.
> +
> +endmenu
> diff --git a/drivers/iio/humidity/Makefile b/drivers/iio/humidity/Makefile
> new file mode 100644
> index 0000000..d5d36c0
> --- /dev/null
> +++ b/drivers/iio/humidity/Makefile
> @@ -0,0 +1,5 @@
> +#
> +# Makefile for IIO humidity sensor drivers
> +#
> +
> +obj-$(CONFIG_DHT11) += dht11.o
> diff --git a/drivers/iio/humidity/dht11.c b/drivers/iio/humidity/dht11.c
> new file mode 100644
> index 0000000..248f0da
> --- /dev/null
> +++ b/drivers/iio/humidity/dht11.c
> @@ -0,0 +1,295 @@
> +/*
> + * DHT11/DHT22 bit banging GPIO driver
> + *
> + * Copyright (c) Harald Geyer <harald-95f8Dae0BrPYtjvyW6yDsg@public.gmane.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/err.h>
> +#include <linux/interrupt.h>
> +#include <linux/device.h>
> +#include <linux/kernel.h>
> +#include <linux/printk.h>
> +#include <linux/slab.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/sysfs.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/wait.h>
> +#include <linux/bitops.h>
> +#include <linux/completion.h>
> +#include <linux/delay.h>
> +#include <linux/gpio.h>
> +#include <linux/of_gpio.h>
> +
> +#include <linux/iio/iio.h>
> +
> +#define DRIVER_NAME "dht11"
> +
> +#define DHT11_DATA_VALID_TIME 2000000000 /* 2s in ns */
> +
> +#define DHT11_EDGES_PREAMBLE 4
> +#define DHT11_BITS_PER_READ 40
> +#define DHT11_EDGES_PER_READ (2*DHT11_BITS_PER_READ + DHT11_EDGES_PREAMBLE + 1)
> +
> +/* Data transmission timing (nano seconds) */
> +#define DHT11_START_TRANSMISSION 18 /* ms */
> +#define DHT11_SENSOR_RESPONSE 80000
> +#define DHT11_START_BIT 50000
> +#define DHT11_DATA_BIT_LOW 27000
> +#define DHT11_DATA_BIT_HIGH 70000
> +
> +struct dht11 {
> + struct device *dev;
> +
> + int gpio;
> + int irq;
> +
> + struct completion completion;
> +
> + s64 timestamp;
> + int temperature;
> + int humidity;
> +
> + /* num_edges: -1 means "no transmission in progress" */
> + int num_edges;
> + struct {s64 ts; int value; } edges[DHT11_EDGES_PER_READ];
> +};
> +
> +static unsigned char dht11_decode_byte(int *timing, int threshold)
> +{
> + unsigned char ret = 0;
> + int i;
> +
> + for (i = 0; i < 8; ++i) {
> + ret <<= 1;
> + if (timing[i] >= threshold)
> + ++ret;
> + }
> +
> + return ret;
> +}
> +
> +static int dht11_decode(struct dht11 *dht11, int offset)
> +{
> + int i, t, timing[DHT11_BITS_PER_READ], threshold,
> + timeres = DHT11_SENSOR_RESPONSE;
> + unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum;
> +
> + /* Calculate timestamp resolution */
> + for (i = 0; i < dht11->num_edges; ++i) {
> + t = dht11->edges[i].ts - dht11->edges[i-1].ts;
> + if (t > 0 && t < timeres)
> + timeres = t;
> + }
> + if (2*timeres > DHT11_DATA_BIT_HIGH) {
> + pr_err("dht11: timeresolution %d too bad for decoding\n",
> + timeres);
> + return -EIO;
> + }
> + threshold = DHT11_DATA_BIT_HIGH / timeres;
> + if (DHT11_DATA_BIT_LOW/timeres + 1 >= threshold)
> + pr_err("dht11: WARNING: decoding ambiguous\n");
> +
> + /* scale down with timeres and check validity */
> + for (i = 0; i < DHT11_BITS_PER_READ; ++i) {
> + t = dht11->edges[offset + 2*i + 2].ts -
> + dht11->edges[offset + 2*i + 1].ts;
> + if (!dht11->edges[offset + 2*i + 1].value)
> + return -EIO; /* lost synchronisation */
> + timing[i] = t / timeres;
> + }
> +
> + hum_int = dht11_decode_byte(timing, threshold);
> + hum_dec = dht11_decode_byte(&timing[8], threshold);
> + temp_int = dht11_decode_byte(&timing[16], threshold);
> + temp_dec = dht11_decode_byte(&timing[24], threshold);
> + checksum = dht11_decode_byte(&timing[32], threshold);
> +
> + if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum)
> + return -EIO;
> +
> + dht11->timestamp = iio_get_time_ns();
> + if (hum_int < 20) { /* DHT22 */
> + dht11->temperature = (((temp_int & 0x7f) << 8) + temp_dec) *
> + ((temp_int & 0x80) ? -100 : 100);
> + dht11->humidity = ((hum_int << 8) + hum_dec) * 100;
> + } else if (temp_dec == 0 && hum_dec == 0) { /* DHT11 */
> + dht11->temperature = temp_int * 1000;
> + dht11->humidity = hum_int * 1000;
> + } else {
> + dev_err(dht11->dev,
> + "Don't know how to decode data: %d %d %d %d\n",
> + hum_int, hum_dec, temp_int, temp_dec);
> + return -EIO;
> + }
> +
> + return 0;
> +}
> +
> +static int dht11_read_raw(struct iio_dev *iio_dev,
> + const struct iio_chan_spec *chan,
> + int *val, int *val2, long m)
> +{
> + struct dht11 *dht11 = iio_priv(iio_dev);
> + int ret;
> +
> + if (dht11->timestamp + DHT11_DATA_VALID_TIME < iio_get_time_ns()) {
> + reinit_completion(&dht11->completion);
> +
> + dht11->num_edges = 0;
> + ret = gpio_direction_output(dht11->gpio, 0);
> + if (ret)
> + goto err;
> + msleep(DHT11_START_TRANSMISSION);
> + ret = gpio_direction_input(dht11->gpio);
> + if (ret)
> + goto err;
> +
> + ret = wait_for_completion_killable_timeout(&dht11->completion,
> + HZ);
> + if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) {
> + dev_err(&iio_dev->dev,
> + "Only %d signal edges detected\n",
> + dht11->num_edges);
> + ret = -ETIMEDOUT;
> + }
> + if (ret < 0)
> + goto err;
> +
> + ret = dht11_decode(dht11,
> + dht11->num_edges == DHT11_EDGES_PER_READ ?
> + DHT11_EDGES_PREAMBLE :
> + DHT11_EDGES_PREAMBLE - 2);
> + if (ret)
> + goto err;
> + }
> +
> + ret = IIO_VAL_INT;
> + if (chan->type == IIO_TEMP)
> + *val = dht11->temperature;
> + else if (chan->type == IIO_HUMIDITYRELATIVE)
> + *val = dht11->humidity;
> + else
> + ret = -EINVAL;
> +err:
> + dht11->num_edges = -1;
> + return ret;
> +}
> +
> +static const struct iio_info dht11_iio_info = {
> + .driver_module = THIS_MODULE,
> + .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), },
> + { .type = IIO_HUMIDITYRELATIVE,
> + .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), }
> +};
> +
> +static const struct of_device_id dht11_dt_ids[] = {
> + { .compatible = "dht11", },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, dht11_dt_ids);
> +
> +static int dht11_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct device_node *node = dev->of_node;
> + struct dht11 *dht11;
> + struct iio_dev *iio;
> + int ret;
> +
> + iio = devm_iio_device_alloc(dev, sizeof(*dht11));
> + if (!iio) {
> + dev_err(dev, "Failed to allocate IIO device\n");
> + return -ENOMEM;
> + }
> +
> + dht11 = iio_priv(iio);
> + dht11->dev = dev;
> +
> + dht11->gpio = ret = of_get_gpio(node, 0);
> + if (ret < 0)
> + return ret;
> + ret = devm_gpio_request_one(dev, dht11->gpio, GPIOF_IN, pdev->name);
> + if (ret)
> + return ret;
> +
> + dht11->irq = gpio_to_irq(dht11->gpio);
> + if (dht11->irq < 0) {
> + 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;
> +
> + platform_set_drvdata(pdev, iio);
> +
> + init_completion(&dht11->completion);
> + iio->name = pdev->name;
> + iio->dev.parent = &pdev->dev;
> + iio->info = &dht11_iio_info;
> + iio->modes = INDIO_DIRECT_MODE;
> + iio->channels = dht11_chan_spec;
> + iio->num_channels = ARRAY_SIZE(dht11_chan_spec);
> +
> + return devm_iio_device_register(dev, iio);
> +}
> +
> +static struct platform_driver dht11_driver = {
> + .driver = {
> + .name = DRIVER_NAME,
> + .owner = THIS_MODULE,
> + .of_match_table = dht11_dt_ids,
> + },
> + .probe = dht11_probe,
> +};
> +
> +module_platform_driver(dht11_driver);
> +
> +MODULE_AUTHOR("Harald Geyer <harald-95f8Dae0BrPYtjvyW6yDsg@public.gmane.org>");
> +MODULE_DESCRIPTION("DHT11 humidity/temperature sensor driver");
> +MODULE_LICENSE("GPL v2");
> +
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-12-03 20:19 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <E1VYf74-0000gd-5Z@stardust.g4.wien.funkfeuer.at>
[not found] ` <alpine.DEB.2.01.1310222030570.23009@pmeerw.net>
[not found] ` <E1VYiDp-0000pb-1i@stardust.g4.wien.funkfeuer.at>
[not found] ` <alpine.DEB.2.01.1310222210230.23009@pmeerw.net>
[not found] ` <E1VYjUo-0000uN-OY@stardust.g4.wien.funkfeuer.at>
[not found] ` <5267E795.7030804@metafoo.de>
[not found] ` <E1VZfrE-0000lZ-Ma@stardust.g4.wien.funkfeuer.at>
[not found] ` <E1VZfrE-0000lZ-Ma-rvrRdOlaWMmli2aaYNgTVBW+3FKk/ZpWT2auq/jSWdo@public.gmane.org>
2013-11-23 11:40 ` [PATCH v2 2/2] iio: Add new driver dht11-gpio Jonathan Cameron
[not found] ` <52909438.8000602-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-11-23 17:44 ` Harald Geyer
[not found] ` <E1VkHFl-00012T-4U-rvrRdOlaWMmli2aaYNgTVBW+3FKk/ZpWT2auq/jSWdo@public.gmane.org>
2013-11-24 18:36 ` Jonathan Cameron
[not found] ` <5292474A.8040101-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
2013-12-01 15:04 ` [PATCH v3 2/2] iio: Add new driver dht11 Harald Geyer
[not found] ` <E1Vn8Z7-0001H3-5v-rvrRdOlaWMmli2aaYNgTVBW+3FKk/ZpWT2auq/jSWdo@public.gmane.org>
2013-12-03 20:19 ` Jonathan Cameron
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).