aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio
diff options
context:
space:
mode:
authorGuenter Roeck <linux@roeck-us.net>2013-02-07 12:09:00 -0500
committerJonathan Cameron <jic23@kernel.org>2013-03-16 06:17:59 -0400
commit17d82b47a215ded05ee3fb8d93b7c1269dbe0083 (patch)
tree9c97b48bad7e01d1450fa8e53a7cb4e688b3d41f /drivers/iio
parentcddc1424f39e7c04045a6431eaf13a003fb8335a (diff)
iio: Add OF support
Provide bindings and parse OF data during initialization. Signed-off-by: Guenter Roeck <linux@roeck-us.net> Reviewed-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r--drivers/iio/iio_core.h1
-rw-r--r--drivers/iio/industrialio-core.c8
-rw-r--r--drivers/iio/inkern.c171
3 files changed, 178 insertions, 2 deletions
diff --git a/drivers/iio/iio_core.h b/drivers/iio/iio_core.h
index f652e6ae5a35..05c1b74502a3 100644
--- a/drivers/iio/iio_core.h
+++ b/drivers/iio/iio_core.h
@@ -18,6 +18,7 @@
18struct iio_chan_spec; 18struct iio_chan_spec;
19struct iio_dev; 19struct iio_dev;
20 20
21extern struct device_type iio_device_type;
21 22
22int __iio_add_chan_devattr(const char *postfix, 23int __iio_add_chan_devattr(const char *postfix,
23 struct iio_chan_spec const *chan, 24 struct iio_chan_spec const *chan,
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 8848f16c547b..6d8b02785647 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -847,7 +847,7 @@ static void iio_dev_release(struct device *device)
847 kfree(indio_dev); 847 kfree(indio_dev);
848} 848}
849 849
850static struct device_type iio_dev_type = { 850struct device_type iio_device_type = {
851 .name = "iio_device", 851 .name = "iio_device",
852 .release = iio_dev_release, 852 .release = iio_dev_release,
853}; 853};
@@ -869,7 +869,7 @@ struct iio_dev *iio_device_alloc(int sizeof_priv)
869 869
870 if (dev) { 870 if (dev) {
871 dev->dev.groups = dev->groups; 871 dev->dev.groups = dev->groups;
872 dev->dev.type = &iio_dev_type; 872 dev->dev.type = &iio_device_type;
873 dev->dev.bus = &iio_bus_type; 873 dev->dev.bus = &iio_bus_type;
874 device_initialize(&dev->dev); 874 device_initialize(&dev->dev);
875 dev_set_drvdata(&dev->dev, (void *)dev); 875 dev_set_drvdata(&dev->dev, (void *)dev);
@@ -960,6 +960,10 @@ int iio_device_register(struct iio_dev *indio_dev)
960{ 960{
961 int ret; 961 int ret;
962 962
963 /* If the calling driver did not initialize of_node, do it here */
964 if (!indio_dev->dev.of_node && indio_dev->dev.parent)
965 indio_dev->dev.of_node = indio_dev->dev.parent->of_node;
966
963 /* configure elements for the chrdev */ 967 /* configure elements for the chrdev */
964 indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id); 968 indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id);
965 969
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index b289915b8469..795d100b4c36 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -10,6 +10,7 @@
10#include <linux/export.h> 10#include <linux/export.h>
11#include <linux/slab.h> 11#include <linux/slab.h>
12#include <linux/mutex.h> 12#include <linux/mutex.h>
13#include <linux/of.h>
13 14
14#include <linux/iio/iio.h> 15#include <linux/iio/iio.h>
15#include "iio_core.h" 16#include "iio_core.h"
@@ -92,6 +93,164 @@ static const struct iio_chan_spec
92 return chan; 93 return chan;
93} 94}
94 95
96#ifdef CONFIG_OF
97
98static int iio_dev_node_match(struct device *dev, void *data)
99{
100 return dev->of_node == data && dev->type == &iio_device_type;
101}
102
103static int __of_iio_channel_get(struct iio_channel *channel,
104 struct device_node *np, int index)
105{
106 struct device *idev;
107 struct iio_dev *indio_dev;
108 int err;
109 struct of_phandle_args iiospec;
110
111 err = of_parse_phandle_with_args(np, "io-channels",
112 "#io-channel-cells",
113 index, &iiospec);
114 if (err)
115 return err;
116
117 idev = bus_find_device(&iio_bus_type, NULL, iiospec.np,
118 iio_dev_node_match);
119 of_node_put(iiospec.np);
120 if (idev == NULL)
121 return -EPROBE_DEFER;
122
123 indio_dev = dev_to_iio_dev(idev);
124 channel->indio_dev = indio_dev;
125 index = iiospec.args_count ? iiospec.args[0] : 0;
126 if (index >= indio_dev->num_channels) {
127 return -EINVAL;
128 goto err_put;
129 }
130 channel->channel = &indio_dev->channels[index];
131
132 return 0;
133
134err_put:
135 iio_device_put(indio_dev);
136 return err;
137}
138
139static struct iio_channel *of_iio_channel_get(struct device_node *np, int index)
140{
141 struct iio_channel *channel;
142 int err;
143
144 if (index < 0)
145 return ERR_PTR(-EINVAL);
146
147 channel = kzalloc(sizeof(*channel), GFP_KERNEL);
148 if (channel == NULL)
149 return ERR_PTR(-ENOMEM);
150
151 err = __of_iio_channel_get(channel, np, index);
152 if (err)
153 goto err_free_channel;
154
155 return channel;
156
157err_free_channel:
158 kfree(channel);
159 return ERR_PTR(err);
160}
161
162static struct iio_channel *of_iio_channel_get_by_name(struct device_node *np,
163 const char *name)
164{
165 struct iio_channel *chan = NULL;
166
167 /* Walk up the tree of devices looking for a matching iio channel */
168 while (np) {
169 int index = 0;
170
171 /*
172 * For named iio channels, first look up the name in the
173 * "io-channel-names" property. If it cannot be found, the
174 * index will be an error code, and of_iio_channel_get()
175 * will fail.
176 */
177 if (name)
178 index = of_property_match_string(np, "io-channel-names",
179 name);
180 chan = of_iio_channel_get(np, index);
181 if (!IS_ERR(chan))
182 break;
183 else if (name && index >= 0) {
184 pr_err("ERROR: could not get IIO channel %s:%s(%i)\n",
185 np->full_name, name ? name : "", index);
186 return chan;
187 }
188
189 /*
190 * No matching IIO channel found on this node.
191 * If the parent node has a "io-channel-ranges" property,
192 * then we can try one of its channels.
193 */
194 np = np->parent;
195 if (np && !of_get_property(np, "io-channel-ranges", NULL))
196 break;
197 }
198 return chan;
199}
200
201static struct iio_channel *of_iio_channel_get_all(struct device *dev)
202{
203 struct iio_channel *chans;
204 int i, mapind, nummaps = 0;
205 int ret;
206
207 do {
208 ret = of_parse_phandle_with_args(dev->of_node,
209 "io-channels",
210 "#io-channel-cells",
211 nummaps, NULL);
212 if (ret < 0)
213 break;
214 } while (++nummaps);
215
216 if (nummaps == 0) /* no error, return NULL to search map table */
217 return NULL;
218
219 /* NULL terminated array to save passing size */
220 chans = kcalloc(nummaps + 1, sizeof(*chans), GFP_KERNEL);
221 if (chans == NULL)
222 return ERR_PTR(-ENOMEM);
223
224 /* Search for OF matches */
225 for (mapind = 0; mapind < nummaps; mapind++) {
226 ret = __of_iio_channel_get(&chans[mapind], dev->of_node,
227 mapind);
228 if (ret)
229 goto error_free_chans;
230 }
231 return chans;
232
233error_free_chans:
234 for (i = 0; i < mapind; i++)
235 iio_device_put(chans[i].indio_dev);
236 kfree(chans);
237 return ERR_PTR(ret);
238}
239
240#else /* CONFIG_OF */
241
242static inline struct iio_channel *
243of_iio_channel_get_by_name(struct device_node *np, const char *name)
244{
245 return NULL;
246}
247
248static inline struct iio_channel *of_iio_channel_get_all(struct device *dev)
249{
250 return NULL;
251}
252
253#endif /* CONFIG_OF */
95 254
96static struct iio_channel *iio_channel_get_sys(const char *name, 255static struct iio_channel *iio_channel_get_sys(const char *name,
97 const char *channel_name) 256 const char *channel_name)
@@ -150,7 +309,14 @@ struct iio_channel *iio_channel_get(struct device *dev,
150 const char *channel_name) 309 const char *channel_name)
151{ 310{
152 const char *name = dev ? dev_name(dev) : NULL; 311 const char *name = dev ? dev_name(dev) : NULL;
312 struct iio_channel *channel;
153 313
314 if (dev) {
315 channel = of_iio_channel_get_by_name(dev->of_node,
316 channel_name);
317 if (channel != NULL)
318 return channel;
319 }
154 return iio_channel_get_sys(name, channel_name); 320 return iio_channel_get_sys(name, channel_name);
155} 321}
156EXPORT_SYMBOL_GPL(iio_channel_get); 322EXPORT_SYMBOL_GPL(iio_channel_get);
@@ -173,6 +339,11 @@ struct iio_channel *iio_channel_get_all(struct device *dev)
173 339
174 if (dev == NULL) 340 if (dev == NULL)
175 return ERR_PTR(-EINVAL); 341 return ERR_PTR(-EINVAL);
342
343 chans = of_iio_channel_get_all(dev);
344 if (chans)
345 return chans;
346
176 name = dev_name(dev); 347 name = dev_name(dev);
177 348
178 mutex_lock(&iio_map_list_lock); 349 mutex_lock(&iio_map_list_lock);