1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <linux/module.h>
20#include <linux/of.h>
21#include <linux/spinlock.h>
22
23struct device_node *allnodes;
24
25
26
27
28DEFINE_RWLOCK(devtree_lock);
29
30int of_n_addr_cells(struct device_node *np)
31{
32 const int *ip;
33
34 do {
35 if (np->parent)
36 np = np->parent;
37 ip = of_get_property(np, "#address-cells", NULL);
38 if (ip)
39 return *ip;
40 } while (np->parent);
41
42 return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
43}
44EXPORT_SYMBOL(of_n_addr_cells);
45
46int of_n_size_cells(struct device_node *np)
47{
48 const int *ip;
49
50 do {
51 if (np->parent)
52 np = np->parent;
53 ip = of_get_property(np, "#size-cells", NULL);
54 if (ip)
55 return *ip;
56 } while (np->parent);
57
58 return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
59}
60EXPORT_SYMBOL(of_n_size_cells);
61
62struct property *of_find_property(const struct device_node *np,
63 const char *name,
64 int *lenp)
65{
66 struct property *pp;
67
68 if (!np)
69 return NULL;
70
71 read_lock(&devtree_lock);
72 for (pp = np->properties; pp != 0; pp = pp->next) {
73 if (of_prop_cmp(pp->name, name) == 0) {
74 if (lenp != 0)
75 *lenp = pp->length;
76 break;
77 }
78 }
79 read_unlock(&devtree_lock);
80
81 return pp;
82}
83EXPORT_SYMBOL(of_find_property);
84
85
86
87
88
89const void *of_get_property(const struct device_node *np, const char *name,
90 int *lenp)
91{
92 struct property *pp = of_find_property(np, name, lenp);
93
94 return pp ? pp->value : NULL;
95}
96EXPORT_SYMBOL(of_get_property);
97
98
99
100
101int of_device_is_compatible(const struct device_node *device,
102 const char *compat)
103{
104 const char* cp;
105 int cplen, l;
106
107 cp = of_get_property(device, "compatible", &cplen);
108 if (cp == NULL)
109 return 0;
110 while (cplen > 0) {
111 if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
112 return 1;
113 l = strlen(cp) + 1;
114 cp += l;
115 cplen -= l;
116 }
117
118 return 0;
119}
120EXPORT_SYMBOL(of_device_is_compatible);
121
122
123
124
125
126
127
128
129
130int of_device_is_available(const struct device_node *device)
131{
132 const char *status;
133 int statlen;
134
135 status = of_get_property(device, "status", &statlen);
136 if (status == NULL)
137 return 1;
138
139 if (statlen > 0) {
140 if (!strcmp(status, "okay") || !strcmp(status, "ok"))
141 return 1;
142 }
143
144 return 0;
145}
146EXPORT_SYMBOL(of_device_is_available);
147
148
149
150
151
152
153
154
155struct device_node *of_get_parent(const struct device_node *node)
156{
157 struct device_node *np;
158
159 if (!node)
160 return NULL;
161
162 read_lock(&devtree_lock);
163 np = of_node_get(node->parent);
164 read_unlock(&devtree_lock);
165 return np;
166}
167EXPORT_SYMBOL(of_get_parent);
168
169
170
171
172
173
174
175
176
177
178
179
180struct device_node *of_get_next_parent(struct device_node *node)
181{
182 struct device_node *parent;
183
184 if (!node)
185 return NULL;
186
187 read_lock(&devtree_lock);
188 parent = of_node_get(node->parent);
189 of_node_put(node);
190 read_unlock(&devtree_lock);
191 return parent;
192}
193
194
195
196
197
198
199
200
201
202struct device_node *of_get_next_child(const struct device_node *node,
203 struct device_node *prev)
204{
205 struct device_node *next;
206
207 read_lock(&devtree_lock);
208 next = prev ? prev->sibling : node->child;
209 for (; next; next = next->sibling)
210 if (of_node_get(next))
211 break;
212 of_node_put(prev);
213 read_unlock(&devtree_lock);
214 return next;
215}
216EXPORT_SYMBOL(of_get_next_child);
217
218
219
220
221
222
223
224
225struct device_node *of_find_node_by_path(const char *path)
226{
227 struct device_node *np = allnodes;
228
229 read_lock(&devtree_lock);
230 for (; np; np = np->allnext) {
231 if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
232 && of_node_get(np))
233 break;
234 }
235 read_unlock(&devtree_lock);
236 return np;
237}
238EXPORT_SYMBOL(of_find_node_by_path);
239
240
241
242
243
244
245
246
247
248
249
250
251struct device_node *of_find_node_by_name(struct device_node *from,
252 const char *name)
253{
254 struct device_node *np;
255
256 read_lock(&devtree_lock);
257 np = from ? from->allnext : allnodes;
258 for (; np; np = np->allnext)
259 if (np->name && (of_node_cmp(np->name, name) == 0)
260 && of_node_get(np))
261 break;
262 of_node_put(from);
263 read_unlock(&devtree_lock);
264 return np;
265}
266EXPORT_SYMBOL(of_find_node_by_name);
267
268
269
270
271
272
273
274
275
276
277
278
279
280struct device_node *of_find_node_by_type(struct device_node *from,
281 const char *type)
282{
283 struct device_node *np;
284
285 read_lock(&devtree_lock);
286 np = from ? from->allnext : allnodes;
287 for (; np; np = np->allnext)
288 if (np->type && (of_node_cmp(np->type, type) == 0)
289 && of_node_get(np))
290 break;
291 of_node_put(from);
292 read_unlock(&devtree_lock);
293 return np;
294}
295EXPORT_SYMBOL(of_find_node_by_type);
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311struct device_node *of_find_compatible_node(struct device_node *from,
312 const char *type, const char *compatible)
313{
314 struct device_node *np;
315
316 read_lock(&devtree_lock);
317 np = from ? from->allnext : allnodes;
318 for (; np; np = np->allnext) {
319 if (type
320 && !(np->type && (of_node_cmp(np->type, type) == 0)))
321 continue;
322 if (of_device_is_compatible(np, compatible) && of_node_get(np))
323 break;
324 }
325 of_node_put(from);
326 read_unlock(&devtree_lock);
327 return np;
328}
329EXPORT_SYMBOL(of_find_compatible_node);
330
331
332
333
334
335
336
337
338const struct of_device_id *of_match_node(const struct of_device_id *matches,
339 const struct device_node *node)
340{
341 while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
342 int match = 1;
343 if (matches->name[0])
344 match &= node->name
345 && !strcmp(matches->name, node->name);
346 if (matches->type[0])
347 match &= node->type
348 && !strcmp(matches->type, node->type);
349 if (matches->compatible[0])
350 match &= of_device_is_compatible(node,
351 matches->compatible);
352 if (match)
353 return matches;
354 matches++;
355 }
356 return NULL;
357}
358EXPORT_SYMBOL(of_match_node);
359
360
361
362
363
364
365
366
367
368
369
370
371
372struct device_node *of_find_matching_node(struct device_node *from,
373 const struct of_device_id *matches)
374{
375 struct device_node *np;
376
377 read_lock(&devtree_lock);
378 np = from ? from->allnext : allnodes;
379 for (; np; np = np->allnext) {
380 if (of_match_node(matches, np) && of_node_get(np))
381 break;
382 }
383 of_node_put(from);
384 read_unlock(&devtree_lock);
385 return np;
386}
387EXPORT_SYMBOL(of_find_matching_node);
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408struct of_modalias_table {
409 char *of_device;
410 char *modalias;
411};
412static struct of_modalias_table of_modalias_table[] = {
413 { "fsl,mcu-mpc8349emitx", "mcu-mpc8349emitx" },
414};
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432int of_modalias_node(struct device_node *node, char *modalias, int len)
433{
434 int i, cplen;
435 const char *compatible;
436 const char *p;
437
438
439 for (i = 0; i < ARRAY_SIZE(of_modalias_table); i++) {
440 compatible = of_modalias_table[i].of_device;
441 if (!of_device_is_compatible(node, compatible))
442 continue;
443 strlcpy(modalias, of_modalias_table[i].modalias, len);
444 return 0;
445 }
446
447 compatible = of_get_property(node, "compatible", &cplen);
448 if (!compatible)
449 return -ENODEV;
450
451
452 p = strchr(compatible, ',');
453 if (!p)
454 return -ENODEV;
455 p++;
456 strlcpy(modalias, p, len);
457 return 0;
458}
459EXPORT_SYMBOL_GPL(of_modalias_node);
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491int of_parse_phandles_with_args(struct device_node *np, const char *list_name,
492 const char *cells_name, int index,
493 struct device_node **out_node,
494 const void **out_args)
495{
496 int ret = -EINVAL;
497 const u32 *list;
498 const u32 *list_end;
499 int size;
500 int cur_index = 0;
501 struct device_node *node = NULL;
502 const void *args;
503
504 list = of_get_property(np, list_name, &size);
505 if (!list) {
506 ret = -ENOENT;
507 goto err0;
508 }
509 list_end = list + size / sizeof(*list);
510
511 while (list < list_end) {
512 const u32 *cells;
513 const phandle *phandle;
514
515 phandle = list;
516 args = list + 1;
517
518
519 if (!*phandle) {
520 list++;
521 goto next;
522 }
523
524 node = of_find_node_by_phandle(*phandle);
525 if (!node) {
526 pr_debug("%s: could not find phandle\n",
527 np->full_name);
528 goto err0;
529 }
530
531 cells = of_get_property(node, cells_name, &size);
532 if (!cells || size != sizeof(*cells)) {
533 pr_debug("%s: could not get %s for %s\n",
534 np->full_name, cells_name, node->full_name);
535 goto err1;
536 }
537
538
539 list += 1 + *cells;
540 if (list > list_end) {
541 pr_debug("%s: insufficient arguments length\n",
542 np->full_name);
543 goto err1;
544 }
545next:
546 if (cur_index == index)
547 break;
548
549 of_node_put(node);
550 node = NULL;
551 cur_index++;
552 }
553
554 if (!node) {
555 ret = -ENOENT;
556 goto err0;
557 }
558
559 *out_node = node;
560 *out_args = args;
561
562 return 0;
563err1:
564 of_node_put(node);
565err0:
566 pr_debug("%s failed with status %d\n", __func__, ret);
567 return ret;
568}
569EXPORT_SYMBOL(of_parse_phandles_with_args);
570