All of lore.kernel.org
 help / color / mirror / Atom feed
* Querry on IIO/ADC DT based consumer device probe
@ 2012-10-05  9:07 Naveen Krishna Ch
  2012-10-05 11:35 ` Jonathan Cameron
  2012-11-08 16:53 ` Alban Bedel
  0 siblings, 2 replies; 5+ messages in thread
From: Naveen Krishna Ch @ 2012-10-05  9:07 UTC (permalink / raw)
  To: linux-iio, jic23

Hello All,

I'm trying to add an ADC driver under IIO/ADC.
Machine is DT based so, passing the ADC device as tree node and
consumer devices (thermistors) as child nodes via DT.

I don't find a frame work to parse the child nodes and probe them like
I2C does using of/of_i2c.c

The DT snippet:
       adc@12D10000 {
                thermistor@3 {
                        compatible = "ntc,ncp15wb473";
                        consumer-name = "ntc,ncp15wb473";
                        consumer-channel = "adc-3";
                        pullup-uV = <1800000>;
                        pullup-ohm = <47000>;
                        pulldown-ohm = <0>;
                        connected-positive;
                };

                thermistor@4 {
                        compatible = "ntc,ncp15wb473";
                        consumer-name = "ntc,ncp15wb473";
                        consumer-channel = "adc-4";
                        pullup-uV = <1800000>;
                        pullup-ohm = <47000>;
                        pulldown-ohm = <0>;
                        connected-positive;
                };
    };

Parsing snippet:
 for_each_child_of_node(node, client_node) {
                char *channel, *label = NULL;

                if (of_property_read_string(client_node,
"consumer-channel", &channel) != 0) {
                        dev_err(&pdev->dev, "Missing consumer-channel
property in the DT.\n");
                        return -EINVAL;
                }

                client_map[i].consumer_channel = channel;
                label = "lable-adc";      //TODO
                client_map[i].adc_channel_label = label;


                if (of_property_read_string(client_node,
"consumer-name", &client_map[i].consumer_dev_name) != 0) {
                        dev_err(&pdev->dev, "Missing consumer-name
property in the DT.\n");
                        return -EINVAL;
                }

                i++;
        }

Can some one suggest a way to get the consumer thermistor driver to
get probed from iio framework via DT.
Kindly, point me towards any existing framework to do the same.

-- 
Shine bright,
(: Nav :)

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Querry on IIO/ADC DT based consumer device probe
  2012-10-05  9:07 Querry on IIO/ADC DT based consumer device probe Naveen Krishna Ch
@ 2012-10-05 11:35 ` Jonathan Cameron
  2012-11-08 16:53 ` Alban Bedel
  1 sibling, 0 replies; 5+ messages in thread
From: Jonathan Cameron @ 2012-10-05 11:35 UTC (permalink / raw)
  To: Naveen Krishna Ch; +Cc: linux-iio, jic23

On 05/10/12 10:07, Naveen Krishna Ch wrote:
> Hello All,
>
> I'm trying to add an ADC driver under IIO/ADC.
> Machine is DT based so, passing the ADC device as tree node and
> consumer devices (thermistors) as child nodes via DT.
>
> I don't find a frame work to parse the child nodes and probe them like
> I2C does using of/of_i2c.c
>
> The DT snippet:
>         adc@12D10000 {
>                  thermistor@3 {
>                          compatible = "ntc,ncp15wb473";
>                          consumer-name = "ntc,ncp15wb473";
>                          consumer-channel = "adc-3";
>                          pullup-uV = <1800000>;
>                          pullup-ohm = <47000>;
>                          pulldown-ohm = <0>;
>                          connected-positive;
>                  };
>
>                  thermistor@4 {
>                          compatible = "ntc,ncp15wb473";
>                          consumer-name = "ntc,ncp15wb473";
>                          consumer-channel = "adc-4";
>                          pullup-uV = <1800000>;
>                          pullup-ohm = <47000>;
>                          pulldown-ohm = <0>;
>                          connected-positive;
>                  };
>      };
>
> Parsing snippet:
>   for_each_child_of_node(node, client_node) {
>                  char *channel, *label = NULL;
>
>                  if (of_property_read_string(client_node,
> "consumer-channel", &channel) != 0) {
>                          dev_err(&pdev->dev, "Missing consumer-channel
> property in the DT.\n");
>                          return -EINVAL;
>                  }
>
>                  client_map[i].consumer_channel = channel;
>                  label = "lable-adc";      //TODO
>                  client_map[i].adc_channel_label = label;
>
>
>                  if (of_property_read_string(client_node,
> "consumer-name", &client_map[i].consumer_dev_name) != 0) {
>                          dev_err(&pdev->dev, "Missing consumer-name
> property in the DT.\n");
>                          return -EINVAL;
>                  }
>
>                  i++;
>          }
>
> Can some one suggest a way to get the consumer thermistor driver to
> get probed from iio framework via DT.
> Kindly, point me towards any existing framework to do the same.

Sorry, I don't think anyone has implemented a device tree version yet.
Just comes down to no one until you having needed it. Feel free to
send patches!


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Querry on IIO/ADC DT based consumer device probe
  2012-10-05  9:07 Querry on IIO/ADC DT based consumer device probe Naveen Krishna Ch
  2012-10-05 11:35 ` Jonathan Cameron
@ 2012-11-08 16:53 ` Alban Bedel
  2012-11-09 14:48     ` Lars-Peter Clausen
  1 sibling, 1 reply; 5+ messages in thread
From: Alban Bedel @ 2012-11-08 16:53 UTC (permalink / raw)
  To: linux-iio

On Fri, 5 Oct 2012 14:37:01 +0530
Naveen Krishna Ch
<naveenkrishna.ch@gmail.com> wrote:

> Hello All,
> 
> I'm trying to add an ADC driver under IIO/ADC.
> Machine is DT based so, passing the ADC device as tree node and
> consumer devices (thermistors) as child nodes via DT.
> 
> I don't find a frame work to parse the child nodes and probe them like
> I2C does using of/of_i2c.c

Here is my take at DT support in IIO, I wanted to submit that later on
after some more test and cleanup but you can see if it help you.

Alban

>From 15decde13239f09101673b08aa0bd7e67e970b3c Mon Sep 17 00:00:00 2001
From: Alban Bedel <alban.bedel@avionic-design.de>
Date: Thu, 18 Oct 2012 17:07:29 +0200
Subject: [PATCH] IIO: Add basic DT/devm support for in kernel users

Signed-off-by: Alban Bedel <alban.bedel@avionic-design.de>
---
 .../devicetree/bindings/iio/iio-channel.txt        |   27 ++++
 drivers/iio/inkern.c                               |  154 ++++++++++++++++++++
 include/linux/iio/consumer.h                       |   63 ++++++++
 3 files changed, 244 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/iio/iio-channel.txt

diff --git a/Documentation/devicetree/bindings/iio/iio-channel.txt b/Documentation/devicetree/bindings/iio/iio-channel.txt
new file mode 100644
index 0000000..dc894f4
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/iio-channel.txt
@@ -0,0 +1,27 @@
+Specifying IIO channels for devices
+===================================
+
+1) iio-channels property
+------------------------
+
+Nodes that makes use of IIO channels should specify them using one or more
+properties, each containing a iio-channels-list':
+
+	iio-channel-list ::= <single-iio-channel> [iio-channel-list]
+	single-iio-channel ::= <iio-channel-phandle> <iio-channel-specifier>
+	iio-channel-phandle : phandle to iio-channel controller node
+	iio-channel-specifier : Array of #iio-channel-cells specifying
+	                        specific IIO channel (controller specific)
+
+GPIO properties should be named "[<name>-]iio-channels".  Exact
+meaning of each gpios property must be documented in the device tree
+binding for each device.
+
+2) iio device nodes
+------------------------
+
+Every IIO device must have #iio-channel-cells contain the size of the
+iio-channel-specifier.
+
+Currently #iio-channel-cells will always be 1 but this will most
+propably change in the future.
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index 6d5194f..5986ef5 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -10,6 +10,7 @@
 #include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
+#include <linux/of.h>
 
 #include <linux/iio/iio.h>
 #include "iio_core.h"
@@ -404,3 +405,156 @@ err_unlock:
 	return ret;
 }
 EXPORT_SYMBOL_GPL(iio_get_channel_type);
+
+#ifdef CONFIG_OF
+static int of_dev_node_match(struct device *dev, void *data)
+{
+        return dev->parent ? dev->parent->of_node == data : 0;
+}
+
+int __of_get_named_iio_channel(struct iio_channel* channel,
+			       struct device_node *np,
+			       const char *propname,
+			       int index)
+{
+	struct device *dev;
+	struct of_phandle_args ph;
+	struct iio_dev *indio_dev;
+	int ret, channel_id = -1;
+
+	ret = of_parse_phandle_with_args(np, propname, "#iio-channel-cells",
+					 index, &ph);
+	if (ret)
+		return ret;
+
+	dev = bus_find_device(&iio_bus_type, NULL, ph.np,
+			      of_dev_node_match);
+	if (!dev)
+		return -EPROBE_DEFER;
+
+	if (ph.args_count > 0)
+		channel_id = ph.args[0];
+
+	indio_dev = dev_to_iio_dev(dev);
+	if (channel_id < 0 || channel_id >= indio_dev->num_channels)
+		return -EINVAL;
+
+	iio_device_get(indio_dev);
+	channel->indio_dev = indio_dev;
+	channel->channel = &indio_dev->channels[channel_id];
+
+	return 0;
+}
+
+/**
+ * of_get_iio_channel() - get a iio channel from a device tree property
+ * @np:           Device node to get the channel from
+ * @propname:     The property to read
+ * @index:        Index of the channel
+ */
+struct iio_channel* of_get_named_iio_channel(struct device_node *np,
+                                             const char *propname,
+                                             int index)
+{
+	struct iio_channel* channel;
+	int ret;
+
+	channel = kzalloc(sizeof(*channel), GFP_KERNEL);
+	if (!channel)
+		return ERR_PTR(-ENOMEM);
+
+	ret = __of_get_named_iio_channel(channel, np, propname, index);
+	if (ret) {
+		kfree(channel);
+		return ERR_PTR(ret);
+	}
+	return channel;
+}
+
+EXPORT_SYMBOL_GPL(of_get_named_iio_channel);
+
+struct iio_channel* of_get_named_all_iio_channels(struct device_node *np,
+						  const char *propname)
+{
+	int ret, i, cnt;
+	struct iio_channel* channels;
+
+	cnt = of_iio_channel_named_count(np, propname);
+	if (cnt == 0)
+		return NULL;
+
+	channels = kzalloc((cnt+1) * sizeof(*channels), GFP_KERNEL);
+	if (!channels)
+		return ERR_PTR(-ENOMEM);
+
+	for (i = 0 ; i < cnt ; i += 1) {
+		ret = __of_get_named_iio_channel(&channels[i],
+						 np, propname, i);
+		if (ret)
+			break;
+	}
+
+	if (ret) {
+		for ( ; i >= 0 ; i -= 1)
+			iio_device_put(channels[i].indio_dev);
+		kfree(channels);
+		return ERR_PTR(ret);
+	}
+
+	return channels;
+
+}
+EXPORT_SYMBOL_GPL(of_get_named_all_iio_channels);
+
+unsigned int of_iio_channel_named_count(struct device_node *np,
+					const char *propname)
+{
+        unsigned int cnt = 0;
+
+        do {
+                int ret;
+
+                ret = of_parse_phandle_with_args(np, propname, "#iio-channel-cells",
+                                                 cnt, NULL);
+                /* A hole in the gpios = <> counts anyway. */
+                if (ret < 0 && ret != -EEXIST)
+                        break;
+        } while (++cnt);
+
+        return cnt;
+
+}
+EXPORT_SYMBOL_GPL(of_iio_channel_named_count);
+
+struct iio_channel_devres {
+	struct iio_channel*	channel;
+};
+
+static void devm_iio_channel_release(struct device *dev, void *res)
+{
+	struct iio_channel_devres *dr = res;
+	iio_channel_release(dr->channel);
+}
+
+struct iio_channel* devm_iio_channel_get(struct device* dev, int index)
+{
+	struct iio_channel_devres *dr;
+	struct iio_channel *channel;
+
+	channel = of_get_iio_channel(dev->of_node, index);
+	if (IS_ERR(channel))
+		return channel;
+
+	dr = devres_alloc(devm_iio_channel_release, sizeof(*dr), GFP_KERNEL);
+	if (!dr) {
+		iio_channel_release(channel);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	dr->channel = channel;
+	devres_add(dev, dr);
+	return dr->channel;
+}
+EXPORT_SYMBOL_GPL(devm_iio_channel_get);
+
+#endif
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
index e4ff665..e2f958a 100644
--- a/include/linux/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -131,4 +131,67 @@ int iio_read_channel_scale(struct iio_channel *chan, int *val,
 int iio_convert_raw_to_processed(struct iio_channel *chan, int raw,
 	int *processed, unsigned int scale);
 
+#ifdef CONFIG_OF
+struct iio_channel* of_get_named_iio_channel(struct device_node *np,
+                                             const char *propname,
+                                             int index);
+
+struct iio_channel* of_get_named_all_iio_channels(struct device_node *np,
+						  const char *propname);
+
+unsigned int of_iio_channel_named_count(struct device_node *np,
+					const char *propname);
+
+#else
+struct iio_channel* of_get_named_iio_channel(struct device_node *np,
+                                             const char *propname,
+                                             int index)
+{
+	return ERR_PTR(-ENODEV);
+}
+
+struct iio_channel* of_get_named_all_iio_channels(struct device_node *np,
+						  const char *propname)
+{
+	return ERR_PTR(-ENODEV);
+}
+
+unsigned int of_iio_channel_named_count(struct device_node *np,
+					const char *propname)
+{
+	return 0;
+}
+#endif
+
+/**
+ * of_get_iio_channel() - get a iio channel from the device tree
+ * @np:           Device node to get the channel from
+ * @index:        Index of the channel
+ */
+static inline struct iio_channel* of_get_iio_channel(struct device_node *np,
+						     int index)
+{
+	return of_get_named_iio_channel(np, "iio-channels", index);
+}
+
+/**
+ * of_get_all_iio_channels() - get a iio channel from the device tree
+ * @np:           Device node to get the channel from
+ */
+static inline struct iio_channel* of_get_all_iio_channels(struct device_node *np)
+{
+	return of_get_named_all_iio_channels(np, "iio-channels");
+}
+
+/**
+ * of_get_iio_channel() - get the number of iio channel from the device tree
+ * @np:           Device node to get the number of channel from
+ */
+static inline unsigned int of_iio_channel_count(struct device_node *np)
+{
+	return of_iio_channel_named_count(np, "iio-channels");
+}
+
+struct iio_channel* devm_iio_channel_get(struct device* dev, int index);
+
 #endif
-- 
1.7.0.4




^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: Querry on IIO/ADC DT based consumer device probe
@ 2012-11-09 14:48     ` Lars-Peter Clausen
  0 siblings, 0 replies; 5+ messages in thread
From: Lars-Peter Clausen @ 2012-11-09 14:48 UTC (permalink / raw)
  To: Alban Bedel; +Cc: linux-iio, devicetree-discuss

On 11/08/2012 05:53 PM, Alban Bedel wrote:
> On Fri, 5 Oct 2012 14:37:01 +0530
> Naveen Krishna Ch
> <naveenkrishna.ch@gmail.com> wrote:
> 
>> Hello All,
>>
>> I'm trying to add an ADC driver under IIO/ADC.
>> Machine is DT based so, passing the ADC device as tree node and
>> consumer devices (thermistors) as child nodes via DT.
>>
>> I don't find a frame work to parse the child nodes and probe them like
>> I2C does using of/of_i2c.c
> 
> Here is my take at DT support in IIO, I wanted to submit that later on
> after some more test and cleanup but you can see if it help you.
> 
> Alban
> 
> From 15decde13239f09101673b08aa0bd7e67e970b3c Mon Sep 17 00:00:00 2001
> From: Alban Bedel <alban.bedel@avionic-design.de>
> Date: Thu, 18 Oct 2012 17:07:29 +0200
> Subject: [PATCH] IIO: Add basic DT/devm support for in kernel users
> 
> Signed-off-by: Alban Bedel <alban.bedel@avionic-design.de>
> ---
>  .../devicetree/bindings/iio/iio-channel.txt        |   27 ++++
>  drivers/iio/inkern.c                               |  154 ++++++++++++++++++++
>  include/linux/iio/consumer.h                       |   63 ++++++++
>  3 files changed, 244 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/iio/iio-channel.txt
> 
> diff --git a/Documentation/devicetree/bindings/iio/iio-channel.txt b/Documentation/devicetree/bindings/iio/iio-channel.txt
> new file mode 100644
> index 0000000..dc894f4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/iio-channel.txt
> @@ -0,0 +1,27 @@
> +Specifying IIO channels for devices
> +===================================
> +
> +1) iio-channels property
> +------------------------
> +
> +Nodes that makes use of IIO channels should specify them using one or more
> +properties, each containing a iio-channels-list':
> +
> +	iio-channel-list ::= <single-iio-channel> [iio-channel-list]
> +	single-iio-channel ::= <iio-channel-phandle> <iio-channel-specifier>
> +	iio-channel-phandle : phandle to iio-channel controller node
> +	iio-channel-specifier : Array of #iio-channel-cells specifying
> +	                        specific IIO channel (controller specific)

I'd prefer something that is more in sync with what we have for other
subsystems which have a provider-consumer relationship, like for example the
clk and dma frameworks. Something like:

iio-channels = <&phandle1 &phandle2>;
iio-channel-names = "voltage", "current";

Also there is another major issue here. Devicetree is supposed to be
operating system independent, IIO on the other hand is a Linux specific
term. I'm not sure though yet what could be used instead. Maybe just
'io-...'. I've put the devicetree list on Cc.

> +
> +GPIO properties should be named "[<name>-]iio-channels".  Exact

IIO ;)

> +meaning of each gpios property must be documented in the device tree
> +binding for each device.
> +
> +2) iio device nodes
> +------------------------
> +
> +Every IIO device must have #iio-channel-cells contain the size of the
> +iio-channel-specifier.
> +
> +Currently #iio-channel-cells will always be 1 but this will most
> +propably change in the future.
> diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
> index 6d5194f..5986ef5 100644
> --- a/drivers/iio/inkern.c
> +++ b/drivers/iio/inkern.c
> @@ -10,6 +10,7 @@
>  #include <linux/export.h>
>  #include <linux/slab.h>
>  #include <linux/mutex.h>
> +#include <linux/of.h>
>  
>  #include <linux/iio/iio.h>
>  #include "iio_core.h"
> @@ -404,3 +405,156 @@ err_unlock:
>  	return ret;
>  }
>  EXPORT_SYMBOL_GPL(iio_get_channel_type);
> +
> +#ifdef CONFIG_OF
> +static int of_dev_node_match(struct device *dev, void *data)
> +{
> +        return dev->parent ? dev->parent->of_node == data : 0;
> +}
> +
> +int __of_get_named_iio_channel(struct iio_channel* channel,
> +			       struct device_node *np,
> +			       const char *propname,
> +			       int index)
> +{
> +	struct device *dev;
> +	struct of_phandle_args ph;
> +	struct iio_dev *indio_dev;
> +	int ret, channel_id = -1;
> +
> +	ret = of_parse_phandle_with_args(np, propname, "#iio-channel-cells",
> +					 index, &ph);
> +	if (ret)
> +		return ret;
> +
> +	dev = bus_find_device(&iio_bus_type, NULL, ph.np,
> +			      of_dev_node_match);
> +	if (!dev)
> +		return -EPROBE_DEFER;
> +
> +	if (ph.args_count > 0)
> +		channel_id = ph.args[0];
> +
> +	indio_dev = dev_to_iio_dev(dev);
> +	if (channel_id < 0 || channel_id >= indio_dev->num_channels)
> +		return -EINVAL;
> +
> +	iio_device_get(indio_dev);
> +	channel->indio_dev = indio_dev;
> +	channel->channel = &indio_dev->channels[channel_id];
> +
> +	return 0;
> +}
> +
> +/**
> + * of_get_iio_channel() - get a iio channel from a device tree property
> + * @np:           Device node to get the channel from
> + * @propname:     The property to read
> + * @index:        Index of the channel
> + */
> +struct iio_channel* of_get_named_iio_channel(struct device_node *np,
> +                                             const char *propname,
> +                                             int index)
> +{
> +	struct iio_channel* channel;
> +	int ret;
> +
> +	channel = kzalloc(sizeof(*channel), GFP_KERNEL);
> +	if (!channel)
> +		return ERR_PTR(-ENOMEM);
> +
> +	ret = __of_get_named_iio_channel(channel, np, propname, index);
> +	if (ret) {
> +		kfree(channel);
> +		return ERR_PTR(ret);
> +	}
> +	return channel;
> +}
> +
> +EXPORT_SYMBOL_GPL(of_get_named_iio_channel);
> +
> +struct iio_channel* of_get_named_all_iio_channels(struct device_node *np,
> +						  const char *propname)
> +{
> +	int ret, i, cnt;
> +	struct iio_channel* channels;
> +
> +	cnt = of_iio_channel_named_count(np, propname);
> +	if (cnt == 0)
> +		return NULL;
> +
> +	channels = kzalloc((cnt+1) * sizeof(*channels), GFP_KERNEL);
> +	if (!channels)
> +		return ERR_PTR(-ENOMEM);
> +
> +	for (i = 0 ; i < cnt ; i += 1) {
> +		ret = __of_get_named_iio_channel(&channels[i],
> +						 np, propname, i);
> +		if (ret)
> +			break;
> +	}
> +
> +	if (ret) {
> +		for ( ; i >= 0 ; i -= 1)
> +			iio_device_put(channels[i].indio_dev);
> +		kfree(channels);
> +		return ERR_PTR(ret);
> +	}
> +
> +	return channels;
> +
> +}
> +EXPORT_SYMBOL_GPL(of_get_named_all_iio_channels);
> +
> +unsigned int of_iio_channel_named_count(struct device_node *np,
> +					const char *propname)
> +{
> +        unsigned int cnt = 0;
> +
> +        do {
> +                int ret;
> +
> +                ret = of_parse_phandle_with_args(np, propname, "#iio-channel-cells",
> +                                                 cnt, NULL);
> +                /* A hole in the gpios = <> counts anyway. */
> +                if (ret < 0 && ret != -EEXIST)
> +                        break;
> +        } while (++cnt);
> +
> +        return cnt;
> +
> +}
> +EXPORT_SYMBOL_GPL(of_iio_channel_named_count);
> +
> +struct iio_channel_devres {
> +	struct iio_channel*	channel;
> +};
> +
> +static void devm_iio_channel_release(struct device *dev, void *res)
> +{
> +	struct iio_channel_devres *dr = res;
> +	iio_channel_release(dr->channel);
> +}
> +
> +struct iio_channel* devm_iio_channel_get(struct device* dev, int index)
> +{
> +	struct iio_channel_devres *dr;
> +	struct iio_channel *channel;
> +
> +	channel = of_get_iio_channel(dev->of_node, index);
> +	if (IS_ERR(channel))
> +		return channel;
> +
> +	dr = devres_alloc(devm_iio_channel_release, sizeof(*dr), GFP_KERNEL);
> +	if (!dr) {
> +		iio_channel_release(channel);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	dr->channel = channel;
> +	devres_add(dev, dr);
> +	return dr->channel;
> +}
> +EXPORT_SYMBOL_GPL(devm_iio_channel_get);
> +
> +#endif
> diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
> index e4ff665..e2f958a 100644
> --- a/include/linux/iio/consumer.h
> +++ b/include/linux/iio/consumer.h
> @@ -131,4 +131,67 @@ int iio_read_channel_scale(struct iio_channel *chan, int *val,
>  int iio_convert_raw_to_processed(struct iio_channel *chan, int raw,
>  	int *processed, unsigned int scale);
>  
> +#ifdef CONFIG_OF
> +struct iio_channel* of_get_named_iio_channel(struct device_node *np,
> +                                             const char *propname,
> +                                             int index);
> +
> +struct iio_channel* of_get_named_all_iio_channels(struct device_node *np,
> +						  const char *propname);
> +
> +unsigned int of_iio_channel_named_count(struct device_node *np,
> +					const char *propname);
> +
> +#else
> +struct iio_channel* of_get_named_iio_channel(struct device_node *np,
> +                                             const char *propname,
> +                                             int index)
> +{
> +	return ERR_PTR(-ENODEV);
> +}
> +
> +struct iio_channel* of_get_named_all_iio_channels(struct device_node *np,
> +						  const char *propname)
> +{
> +	return ERR_PTR(-ENODEV);
> +}
> +
> +unsigned int of_iio_channel_named_count(struct device_node *np,
> +					const char *propname)
> +{
> +	return 0;
> +}
> +#endif
> +
> +/**
> + * of_get_iio_channel() - get a iio channel from the device tree
> + * @np:           Device node to get the channel from
> + * @index:        Index of the channel
> + */
> +static inline struct iio_channel* of_get_iio_channel(struct device_node *np,
> +						     int index)
> +{
> +	return of_get_named_iio_channel(np, "iio-channels", index);
> +}
> +
> +/**
> + * of_get_all_iio_channels() - get a iio channel from the device tree
> + * @np:           Device node to get the channel from
> + */
> +static inline struct iio_channel* of_get_all_iio_channels(struct device_node *np)
> +{
> +	return of_get_named_all_iio_channels(np, "iio-channels");
> +}
> +
> +/**
> + * of_get_iio_channel() - get the number of iio channel from the device tree
> + * @np:           Device node to get the number of channel from
> + */
> +static inline unsigned int of_iio_channel_count(struct device_node *np)
> +{
> +	return of_iio_channel_named_count(np, "iio-channels");
> +}
> +
> +struct iio_channel* devm_iio_channel_get(struct device* dev, int index);
> +
>  #endif


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Querry on IIO/ADC DT based consumer device probe
@ 2012-11-09 14:48     ` Lars-Peter Clausen
  0 siblings, 0 replies; 5+ messages in thread
From: Lars-Peter Clausen @ 2012-11-09 14:48 UTC (permalink / raw)
  To: Alban Bedel
  Cc: linux-iio-u79uwXL29TY76Z2rM5mHXA,
	devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ

On 11/08/2012 05:53 PM, Alban Bedel wrote:
> On Fri, 5 Oct 2012 14:37:01 +0530
> Naveen Krishna Ch
> <naveenkrishna.ch-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> 
>> Hello All,
>>
>> I'm trying to add an ADC driver under IIO/ADC.
>> Machine is DT based so, passing the ADC device as tree node and
>> consumer devices (thermistors) as child nodes via DT.
>>
>> I don't find a frame work to parse the child nodes and probe them like
>> I2C does using of/of_i2c.c
> 
> Here is my take at DT support in IIO, I wanted to submit that later on
> after some more test and cleanup but you can see if it help you.
> 
> Alban
> 
> From 15decde13239f09101673b08aa0bd7e67e970b3c Mon Sep 17 00:00:00 2001
> From: Alban Bedel <alban.bedel-RM9K5IK7kjKj5M59NBduVrNAH6kLmebB@public.gmane.org>
> Date: Thu, 18 Oct 2012 17:07:29 +0200
> Subject: [PATCH] IIO: Add basic DT/devm support for in kernel users
> 
> Signed-off-by: Alban Bedel <alban.bedel-RM9K5IK7kjKj5M59NBduVrNAH6kLmebB@public.gmane.org>
> ---
>  .../devicetree/bindings/iio/iio-channel.txt        |   27 ++++
>  drivers/iio/inkern.c                               |  154 ++++++++++++++++++++
>  include/linux/iio/consumer.h                       |   63 ++++++++
>  3 files changed, 244 insertions(+), 0 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/iio/iio-channel.txt
> 
> diff --git a/Documentation/devicetree/bindings/iio/iio-channel.txt b/Documentation/devicetree/bindings/iio/iio-channel.txt
> new file mode 100644
> index 0000000..dc894f4
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iio/iio-channel.txt
> @@ -0,0 +1,27 @@
> +Specifying IIO channels for devices
> +===================================
> +
> +1) iio-channels property
> +------------------------
> +
> +Nodes that makes use of IIO channels should specify them using one or more
> +properties, each containing a iio-channels-list':
> +
> +	iio-channel-list ::= <single-iio-channel> [iio-channel-list]
> +	single-iio-channel ::= <iio-channel-phandle> <iio-channel-specifier>
> +	iio-channel-phandle : phandle to iio-channel controller node
> +	iio-channel-specifier : Array of #iio-channel-cells specifying
> +	                        specific IIO channel (controller specific)

I'd prefer something that is more in sync with what we have for other
subsystems which have a provider-consumer relationship, like for example the
clk and dma frameworks. Something like:

iio-channels = <&phandle1 &phandle2>;
iio-channel-names = "voltage", "current";

Also there is another major issue here. Devicetree is supposed to be
operating system independent, IIO on the other hand is a Linux specific
term. I'm not sure though yet what could be used instead. Maybe just
'io-...'. I've put the devicetree list on Cc.

> +
> +GPIO properties should be named "[<name>-]iio-channels".  Exact

IIO ;)

> +meaning of each gpios property must be documented in the device tree
> +binding for each device.
> +
> +2) iio device nodes
> +------------------------
> +
> +Every IIO device must have #iio-channel-cells contain the size of the
> +iio-channel-specifier.
> +
> +Currently #iio-channel-cells will always be 1 but this will most
> +propably change in the future.
> diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
> index 6d5194f..5986ef5 100644
> --- a/drivers/iio/inkern.c
> +++ b/drivers/iio/inkern.c
> @@ -10,6 +10,7 @@
>  #include <linux/export.h>
>  #include <linux/slab.h>
>  #include <linux/mutex.h>
> +#include <linux/of.h>
>  
>  #include <linux/iio/iio.h>
>  #include "iio_core.h"
> @@ -404,3 +405,156 @@ err_unlock:
>  	return ret;
>  }
>  EXPORT_SYMBOL_GPL(iio_get_channel_type);
> +
> +#ifdef CONFIG_OF
> +static int of_dev_node_match(struct device *dev, void *data)
> +{
> +        return dev->parent ? dev->parent->of_node == data : 0;
> +}
> +
> +int __of_get_named_iio_channel(struct iio_channel* channel,
> +			       struct device_node *np,
> +			       const char *propname,
> +			       int index)
> +{
> +	struct device *dev;
> +	struct of_phandle_args ph;
> +	struct iio_dev *indio_dev;
> +	int ret, channel_id = -1;
> +
> +	ret = of_parse_phandle_with_args(np, propname, "#iio-channel-cells",
> +					 index, &ph);
> +	if (ret)
> +		return ret;
> +
> +	dev = bus_find_device(&iio_bus_type, NULL, ph.np,
> +			      of_dev_node_match);
> +	if (!dev)
> +		return -EPROBE_DEFER;
> +
> +	if (ph.args_count > 0)
> +		channel_id = ph.args[0];
> +
> +	indio_dev = dev_to_iio_dev(dev);
> +	if (channel_id < 0 || channel_id >= indio_dev->num_channels)
> +		return -EINVAL;
> +
> +	iio_device_get(indio_dev);
> +	channel->indio_dev = indio_dev;
> +	channel->channel = &indio_dev->channels[channel_id];
> +
> +	return 0;
> +}
> +
> +/**
> + * of_get_iio_channel() - get a iio channel from a device tree property
> + * @np:           Device node to get the channel from
> + * @propname:     The property to read
> + * @index:        Index of the channel
> + */
> +struct iio_channel* of_get_named_iio_channel(struct device_node *np,
> +                                             const char *propname,
> +                                             int index)
> +{
> +	struct iio_channel* channel;
> +	int ret;
> +
> +	channel = kzalloc(sizeof(*channel), GFP_KERNEL);
> +	if (!channel)
> +		return ERR_PTR(-ENOMEM);
> +
> +	ret = __of_get_named_iio_channel(channel, np, propname, index);
> +	if (ret) {
> +		kfree(channel);
> +		return ERR_PTR(ret);
> +	}
> +	return channel;
> +}
> +
> +EXPORT_SYMBOL_GPL(of_get_named_iio_channel);
> +
> +struct iio_channel* of_get_named_all_iio_channels(struct device_node *np,
> +						  const char *propname)
> +{
> +	int ret, i, cnt;
> +	struct iio_channel* channels;
> +
> +	cnt = of_iio_channel_named_count(np, propname);
> +	if (cnt == 0)
> +		return NULL;
> +
> +	channels = kzalloc((cnt+1) * sizeof(*channels), GFP_KERNEL);
> +	if (!channels)
> +		return ERR_PTR(-ENOMEM);
> +
> +	for (i = 0 ; i < cnt ; i += 1) {
> +		ret = __of_get_named_iio_channel(&channels[i],
> +						 np, propname, i);
> +		if (ret)
> +			break;
> +	}
> +
> +	if (ret) {
> +		for ( ; i >= 0 ; i -= 1)
> +			iio_device_put(channels[i].indio_dev);
> +		kfree(channels);
> +		return ERR_PTR(ret);
> +	}
> +
> +	return channels;
> +
> +}
> +EXPORT_SYMBOL_GPL(of_get_named_all_iio_channels);
> +
> +unsigned int of_iio_channel_named_count(struct device_node *np,
> +					const char *propname)
> +{
> +        unsigned int cnt = 0;
> +
> +        do {
> +                int ret;
> +
> +                ret = of_parse_phandle_with_args(np, propname, "#iio-channel-cells",
> +                                                 cnt, NULL);
> +                /* A hole in the gpios = <> counts anyway. */
> +                if (ret < 0 && ret != -EEXIST)
> +                        break;
> +        } while (++cnt);
> +
> +        return cnt;
> +
> +}
> +EXPORT_SYMBOL_GPL(of_iio_channel_named_count);
> +
> +struct iio_channel_devres {
> +	struct iio_channel*	channel;
> +};
> +
> +static void devm_iio_channel_release(struct device *dev, void *res)
> +{
> +	struct iio_channel_devres *dr = res;
> +	iio_channel_release(dr->channel);
> +}
> +
> +struct iio_channel* devm_iio_channel_get(struct device* dev, int index)
> +{
> +	struct iio_channel_devres *dr;
> +	struct iio_channel *channel;
> +
> +	channel = of_get_iio_channel(dev->of_node, index);
> +	if (IS_ERR(channel))
> +		return channel;
> +
> +	dr = devres_alloc(devm_iio_channel_release, sizeof(*dr), GFP_KERNEL);
> +	if (!dr) {
> +		iio_channel_release(channel);
> +		return ERR_PTR(-ENOMEM);
> +	}
> +
> +	dr->channel = channel;
> +	devres_add(dev, dr);
> +	return dr->channel;
> +}
> +EXPORT_SYMBOL_GPL(devm_iio_channel_get);
> +
> +#endif
> diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
> index e4ff665..e2f958a 100644
> --- a/include/linux/iio/consumer.h
> +++ b/include/linux/iio/consumer.h
> @@ -131,4 +131,67 @@ int iio_read_channel_scale(struct iio_channel *chan, int *val,
>  int iio_convert_raw_to_processed(struct iio_channel *chan, int raw,
>  	int *processed, unsigned int scale);
>  
> +#ifdef CONFIG_OF
> +struct iio_channel* of_get_named_iio_channel(struct device_node *np,
> +                                             const char *propname,
> +                                             int index);
> +
> +struct iio_channel* of_get_named_all_iio_channels(struct device_node *np,
> +						  const char *propname);
> +
> +unsigned int of_iio_channel_named_count(struct device_node *np,
> +					const char *propname);
> +
> +#else
> +struct iio_channel* of_get_named_iio_channel(struct device_node *np,
> +                                             const char *propname,
> +                                             int index)
> +{
> +	return ERR_PTR(-ENODEV);
> +}
> +
> +struct iio_channel* of_get_named_all_iio_channels(struct device_node *np,
> +						  const char *propname)
> +{
> +	return ERR_PTR(-ENODEV);
> +}
> +
> +unsigned int of_iio_channel_named_count(struct device_node *np,
> +					const char *propname)
> +{
> +	return 0;
> +}
> +#endif
> +
> +/**
> + * of_get_iio_channel() - get a iio channel from the device tree
> + * @np:           Device node to get the channel from
> + * @index:        Index of the channel
> + */
> +static inline struct iio_channel* of_get_iio_channel(struct device_node *np,
> +						     int index)
> +{
> +	return of_get_named_iio_channel(np, "iio-channels", index);
> +}
> +
> +/**
> + * of_get_all_iio_channels() - get a iio channel from the device tree
> + * @np:           Device node to get the channel from
> + */
> +static inline struct iio_channel* of_get_all_iio_channels(struct device_node *np)
> +{
> +	return of_get_named_all_iio_channels(np, "iio-channels");
> +}
> +
> +/**
> + * of_get_iio_channel() - get the number of iio channel from the device tree
> + * @np:           Device node to get the number of channel from
> + */
> +static inline unsigned int of_iio_channel_count(struct device_node *np)
> +{
> +	return of_iio_channel_named_count(np, "iio-channels");
> +}
> +
> +struct iio_channel* devm_iio_channel_get(struct device* dev, int index);
> +
>  #endif

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-11-09 14:48 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-10-05  9:07 Querry on IIO/ADC DT based consumer device probe Naveen Krishna Ch
2012-10-05 11:35 ` Jonathan Cameron
2012-11-08 16:53 ` Alban Bedel
2012-11-09 14:48   ` Lars-Peter Clausen
2012-11-09 14:48     ` Lars-Peter Clausen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.