diff options
author | Guenter Roeck <linux@roeck-us.net> | 2013-02-07 12:09:00 -0500 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2013-03-16 06:17:59 -0400 |
commit | 17d82b47a215ded05ee3fb8d93b7c1269dbe0083 (patch) | |
tree | 9c97b48bad7e01d1450fa8e53a7cb4e688b3d41f /drivers/iio | |
parent | cddc1424f39e7c04045a6431eaf13a003fb8335a (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.h | 1 | ||||
-rw-r--r-- | drivers/iio/industrialio-core.c | 8 | ||||
-rw-r--r-- | drivers/iio/inkern.c | 171 |
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 @@ | |||
18 | struct iio_chan_spec; | 18 | struct iio_chan_spec; |
19 | struct iio_dev; | 19 | struct iio_dev; |
20 | 20 | ||
21 | extern struct device_type iio_device_type; | ||
21 | 22 | ||
22 | int __iio_add_chan_devattr(const char *postfix, | 23 | int __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 | ||
850 | static struct device_type iio_dev_type = { | 850 | struct 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 | |||
98 | static int iio_dev_node_match(struct device *dev, void *data) | ||
99 | { | ||
100 | return dev->of_node == data && dev->type == &iio_device_type; | ||
101 | } | ||
102 | |||
103 | static 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 | |||
134 | err_put: | ||
135 | iio_device_put(indio_dev); | ||
136 | return err; | ||
137 | } | ||
138 | |||
139 | static 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 | |||
157 | err_free_channel: | ||
158 | kfree(channel); | ||
159 | return ERR_PTR(err); | ||
160 | } | ||
161 | |||
162 | static 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 | |||
201 | static 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 | |||
233 | error_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 | |||
242 | static inline struct iio_channel * | ||
243 | of_iio_channel_get_by_name(struct device_node *np, const char *name) | ||
244 | { | ||
245 | return NULL; | ||
246 | } | ||
247 | |||
248 | static inline struct iio_channel *of_iio_channel_get_all(struct device *dev) | ||
249 | { | ||
250 | return NULL; | ||
251 | } | ||
252 | |||
253 | #endif /* CONFIG_OF */ | ||
95 | 254 | ||
96 | static struct iio_channel *iio_channel_get_sys(const char *name, | 255 | static 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 | } |
156 | EXPORT_SYMBOL_GPL(iio_channel_get); | 322 | EXPORT_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); |