2 * Procedures for creating, accessing and interpreting the device tree.
4 * Paul Mackerras August 1996.
5 * Copyright (C) 1996-2005 Paul Mackerras.
7 * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
8 * {engebret|bergner}@us.ibm.com
10 * Adapted for sparc64 by David S. Miller davem@davemloft.net
12 * Adapter for i386/OLPC by Andres Salomon <dilinger@debian.org>
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version
17 * 2 of the License, or (at your option) any later version.
20 #include <linux/kernel.h>
21 #include <linux/types.h>
22 #include <linux/string.h>
24 #include <linux/bootmem.h>
25 #include <linux/module.h>
30 * XXX: This is very much a stub; right now we're keeping 2 device trees
31 * in memory (one for promfs, and one here). That will not remain
35 static struct device_node
*allnodes
;
37 /* use when traversing tree through the allnext, child, sibling,
38 * or parent members of struct device_node.
40 static DEFINE_RWLOCK(devtree_lock
);
42 int of_device_is_compatible(const struct device_node
*device
,
48 cp
= of_get_property(device
, "compatible", &cplen
);
52 if (strncmp(cp
, compat
, strlen(compat
)) == 0)
61 EXPORT_SYMBOL(of_device_is_compatible
);
63 struct device_node
*of_get_parent(const struct device_node
*node
)
65 struct device_node
*np
;
74 EXPORT_SYMBOL(of_get_parent
);
76 struct device_node
*of_get_next_child(const struct device_node
*node
,
77 struct device_node
*prev
)
79 struct device_node
*next
;
81 next
= prev
? prev
->sibling
: node
->child
;
82 for (; next
!= 0; next
= next
->sibling
) {
88 EXPORT_SYMBOL(of_get_next_child
);
90 struct device_node
*of_find_node_by_path(const char *path
)
92 struct device_node
*np
= allnodes
;
94 for (; np
!= 0; np
= np
->allnext
) {
95 if (np
->full_name
!= 0 && strcmp(np
->full_name
, path
) == 0)
101 EXPORT_SYMBOL(of_find_node_by_path
);
103 struct device_node
*of_find_node_by_phandle(phandle handle
)
105 struct device_node
*np
;
107 for (np
= allnodes
; np
!= 0; np
= np
->allnext
)
108 if (np
->node
== handle
)
113 EXPORT_SYMBOL(of_find_node_by_phandle
);
115 struct device_node
*of_find_node_by_name(struct device_node
*from
,
118 struct device_node
*np
;
120 np
= from
? from
->allnext
: allnodes
;
121 for (; np
!= NULL
; np
= np
->allnext
)
122 if (np
->name
!= NULL
&& strcmp(np
->name
, name
) == 0)
127 EXPORT_SYMBOL(of_find_node_by_name
);
129 struct device_node
*of_find_node_by_type(struct device_node
*from
,
132 struct device_node
*np
;
134 np
= from
? from
->allnext
: allnodes
;
135 for (; np
!= 0; np
= np
->allnext
)
136 if (np
->type
!= 0 && strcmp(np
->type
, type
) == 0)
141 EXPORT_SYMBOL(of_find_node_by_type
);
143 struct device_node
*of_find_compatible_node(struct device_node
*from
,
144 const char *type
, const char *compatible
)
146 struct device_node
*np
;
148 np
= from
? from
->allnext
: allnodes
;
149 for (; np
!= 0; np
= np
->allnext
) {
151 && !(np
->type
!= 0 && strcmp(np
->type
, type
) == 0))
153 if (of_device_is_compatible(np
, compatible
))
159 EXPORT_SYMBOL(of_find_compatible_node
);
161 struct property
*of_find_property(const struct device_node
*np
,
167 for (pp
= np
->properties
; pp
!= 0; pp
= pp
->next
) {
168 if (strcasecmp(pp
->name
, name
) == 0) {
176 EXPORT_SYMBOL(of_find_property
);
179 * Find a property with a given name for a given node
180 * and return the value.
182 const void *of_get_property(const struct device_node
*np
, const char *name
,
185 struct property
*pp
= of_find_property(np
,name
,lenp
);
186 return pp
? pp
->value
: NULL
;
188 EXPORT_SYMBOL(of_get_property
);
190 int of_getintprop_default(struct device_node
*np
, const char *name
, int def
)
192 struct property
*prop
;
195 prop
= of_find_property(np
, name
, &len
);
196 if (!prop
|| len
!= 4)
199 return *(int *) prop
->value
;
201 EXPORT_SYMBOL(of_getintprop_default
);
203 int of_n_addr_cells(struct device_node
*np
)
209 ip
= of_get_property(np
, "#address-cells", NULL
);
212 } while (np
->parent
);
213 /* No #address-cells property for the root node, default to 2 */
216 EXPORT_SYMBOL(of_n_addr_cells
);
218 int of_n_size_cells(struct device_node
*np
)
224 ip
= of_get_property(np
, "#size-cells", NULL
);
227 } while (np
->parent
);
228 /* No #size-cells property for the root node, default to 1 */
231 EXPORT_SYMBOL(of_n_size_cells
);
233 int of_set_property(struct device_node
*dp
, const char *name
, void *val
, int len
)
237 EXPORT_SYMBOL(of_set_property
);
239 static unsigned int prom_early_allocated
;
241 static void * __init
prom_early_alloc(unsigned long size
)
245 ret
= kmalloc(size
, GFP_KERNEL
);
247 memset(ret
, 0, size
);
249 printk(KERN_ERR
"ACK! couldn't allocate prom memory!\n");
251 prom_early_allocated
+= size
;
256 static int is_root_node(const struct device_node
*dp
)
261 return (dp
->parent
== NULL
);
264 static char * __init
build_path_component(struct device_node
*dp
)
269 if (ofw("package-to-path", 3, 1, dp
->node
, NULL
, 0, &pathlen
)) {
270 printk(KERN_ERR
"PROM: unable to get path name from OFW!\n");
273 n
= prom_early_alloc(pathlen
+ 1);
274 if (ofw("package-to-path", 3, 1, dp
->node
, n
, pathlen
+1, &pathlen
))
275 printk(KERN_ERR
"PROM: unable to get path name from OFW\n");
277 if ((i
= strrchr(n
, '/')))
278 n
= ++i
; /* we only want the file name */
282 static char * __init
build_full_name(struct device_node
*dp
)
284 int len
, ourlen
, plen
;
287 plen
= strlen(dp
->parent
->full_name
);
288 ourlen
= strlen(dp
->path_component_name
);
289 len
= ourlen
+ plen
+ 2;
291 n
= prom_early_alloc(len
);
292 strcpy(n
, dp
->parent
->full_name
);
293 if (!is_root_node(dp
->parent
)) {
294 strcpy(n
+ plen
, "/");
297 strcpy(n
+ plen
, dp
->path_component_name
);
302 static struct property
* __init
build_one_prop(phandle node
, char *prev
, char *special_name
, void *special_val
, int special_len
)
304 static struct property
*tmp
= NULL
;
309 memset(p
, 0, sizeof(*p
) + 32);
312 p
= prom_early_alloc(sizeof(struct property
) + 32);
315 p
->name
= (char *) (p
+ 1);
317 strcpy(p
->name
, special_name
);
318 p
->length
= special_len
;
319 p
->value
= prom_early_alloc(special_len
);
320 memcpy(p
->value
, special_val
, special_len
);
324 if (ofw("nextprop", 3, 1, node
, "", p
->name
, &fl
)) {
325 printk(KERN_ERR
"PROM: %s: nextprop failed!\n", __func__
);
329 if (ofw("nextprop", 3, 1, node
, prev
, p
->name
, &fl
)) {
330 printk(KERN_ERR
"PROM: %s: nextprop failed!\n", __func__
);
334 if (strlen(p
->name
) == 0 || fl
!= 1) {
338 if (ofw("getproplen", 2, 1, node
, p
->name
, &p
->length
)) {
339 printk(KERN_ERR
"PROM: %s: getproplen failed!\n", __func__
);
342 if (p
->length
<= 0) {
345 p
->value
= prom_early_alloc(p
->length
+ 1);
346 if (ofw("getprop", 4, 1, node
, p
->name
, p
->value
, p
->length
, &p
->length
)) {
347 printk(KERN_ERR
"PROM: %s: getprop failed!\n", __func__
);
350 ((unsigned char *)p
->value
)[p
->length
] = '\0';
356 static struct property
* __init
build_prop_list(phandle node
)
358 struct property
*head
, *tail
;
360 head
= tail
= build_one_prop(node
, NULL
,
361 ".node", &node
, sizeof(node
));
363 tail
->next
= build_one_prop(node
, NULL
, NULL
, NULL
, 0);
366 tail
->next
= build_one_prop(node
, tail
->name
,
374 static char * __init
get_one_property(phandle node
, const char *name
)
376 char *buf
= "<NULL>";
379 if (ofw("getproplen", 2, 1, node
, name
, &len
)) {
380 printk(KERN_ERR
"PROM: %s: getproplen failed!\n", __func__
);
384 buf
= prom_early_alloc(len
);
385 if (ofw("getprop", 4, 1, node
, name
, buf
, len
, &len
)) {
386 printk(KERN_ERR
"PROM: %s: getprop failed!\n", __func__
);
394 static struct device_node
* __init
create_node(phandle node
, struct device_node
*parent
)
396 struct device_node
*dp
;
401 dp
= prom_early_alloc(sizeof(*dp
));
404 kref_init(&dp
->kref
);
406 dp
->name
= get_one_property(node
, "name");
407 dp
->type
= get_one_property(node
, "device_type");
410 dp
->properties
= build_prop_list(node
);
415 static struct device_node
* __init
build_tree(struct device_node
*parent
, phandle node
, struct device_node
***nextp
)
417 struct device_node
*ret
= NULL
, *prev_sibling
= NULL
;
418 struct device_node
*dp
;
422 dp
= create_node(node
, parent
);
427 prev_sibling
->sibling
= dp
;
434 *nextp
= &dp
->allnext
;
436 dp
->path_component_name
= build_path_component(dp
);
437 dp
->full_name
= build_full_name(dp
);
439 if (ofw("child", 1, 1, node
, &child
)) {
440 printk(KERN_ERR
"PROM: %s: fetching child failed!\n", __func__
);
443 dp
->child
= build_tree(dp
, child
, nextp
);
445 if (ofw("peer", 1, 1, node
, &node
)) {
446 printk(KERN_ERR
"PROM: %s: fetching peer failed!\n", __func__
);
454 static phandle root_node
;
456 void __init
prom_build_devicetree(void)
458 struct device_node
**nextp
;
461 if (ofw("peer", 1, 1, 0, &root_node
)) {
462 printk(KERN_ERR
"PROM: unable to get root node from OFW!\n");
466 allnodes
= create_node(root_node
, NULL
);
467 allnodes
->path_component_name
= "";
468 allnodes
->full_name
= "/";
470 nextp
= &allnodes
->allnext
;
471 if (ofw("child", 1, 1, allnodes
->node
, &child
)) {
472 printk(KERN_ERR
"PROM: unable to get child node from OFW!\n");
475 allnodes
->child
= build_tree(allnodes
, child
, &nextp
);
476 printk("PROM: Built device tree with %u bytes of memory.\n",
477 prom_early_allocated
);
This page took 0.071166 seconds and 5 git commands to generate.