aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/microblaze/Kconfig1
-rw-r--r--arch/microblaze/include/asm/prom.h1
-rw-r--r--arch/microblaze/kernel/of_platform.c2
-rw-r--r--arch/microblaze/kernel/prom.c710
-rw-r--r--arch/powerpc/Kconfig1
-rw-r--r--arch/powerpc/kernel/of_platform.c2
-rw-r--r--arch/powerpc/kernel/prom.c724
-rw-r--r--arch/powerpc/platforms/cell/spu_manage.c6
-rw-r--r--arch/powerpc/platforms/powermac/pfunc_core.c2
-rw-r--r--arch/sparc/kernel/devices.c2
-rw-r--r--arch/sparc/kernel/of_device_32.c2
-rw-r--r--arch/sparc/kernel/of_device_64.c2
-rw-r--r--arch/sparc/kernel/prom_common.c8
-rw-r--r--arch/sparc/kernel/smp_64.c2
-rw-r--r--drivers/of/Kconfig4
-rw-r--r--drivers/of/Makefile1
-rw-r--r--drivers/of/base.c212
-rw-r--r--drivers/of/fdt.c528
-rw-r--r--drivers/sbus/char/openprom.c10
-rw-r--r--drivers/video/aty/atyfb_base.c2
-rw-r--r--include/linux/of.h15
-rw-r--r--include/linux/of_fdt.h31
-rw-r--r--sound/aoa/fabrics/layout.c2
23 files changed, 822 insertions, 1448 deletions
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index cd5837e298b2..b008168ae946 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -130,6 +130,7 @@ config CMDLINE_FORCE
130 130
131config OF 131config OF
132 def_bool y 132 def_bool y
133 select OF_FLATTREE
133 134
134config PROC_DEVICETREE 135config PROC_DEVICETREE
135 bool "Support for device tree in /proc" 136 bool "Support for device tree in /proc"
diff --git a/arch/microblaze/include/asm/prom.h b/arch/microblaze/include/asm/prom.h
index ef3ec1d6ceb3..07d1063f9aae 100644
--- a/arch/microblaze/include/asm/prom.h
+++ b/arch/microblaze/include/asm/prom.h
@@ -37,7 +37,6 @@ extern struct device_node *of_chosen;
37 37
38#define HAVE_ARCH_DEVTREE_FIXUPS 38#define HAVE_ARCH_DEVTREE_FIXUPS
39 39
40extern struct device_node *allnodes; /* temporary while merging */
41extern rwlock_t devtree_lock; /* temporary while merging */ 40extern rwlock_t devtree_lock; /* temporary while merging */
42 41
43/* For updating the device tree at runtime */ 42/* For updating the device tree at runtime */
diff --git a/arch/microblaze/kernel/of_platform.c b/arch/microblaze/kernel/of_platform.c
index acf4574d0f18..1c6d684996d7 100644
--- a/arch/microblaze/kernel/of_platform.c
+++ b/arch/microblaze/kernel/of_platform.c
@@ -185,7 +185,7 @@ EXPORT_SYMBOL(of_find_device_by_node);
185static int of_dev_phandle_match(struct device *dev, void *data) 185static int of_dev_phandle_match(struct device *dev, void *data)
186{ 186{
187 phandle *ph = data; 187 phandle *ph = data;
188 return to_of_device(dev)->node->linux_phandle == *ph; 188 return to_of_device(dev)->node->phandle == *ph;
189} 189}
190 190
191struct of_device *of_find_device_by_phandle(phandle ph) 191struct of_device *of_find_device_by_phandle(phandle ph)
diff --git a/arch/microblaze/kernel/prom.c b/arch/microblaze/kernel/prom.c
index b817df172aa9..6eff83a71218 100644
--- a/arch/microblaze/kernel/prom.c
+++ b/arch/microblaze/kernel/prom.c
@@ -42,400 +42,9 @@
42#include <asm/sections.h> 42#include <asm/sections.h>
43#include <asm/pci-bridge.h> 43#include <asm/pci-bridge.h>
44 44
45static int __initdata dt_root_addr_cells;
46static int __initdata dt_root_size_cells;
47
48typedef u32 cell_t;
49
50static struct boot_param_header *initial_boot_params;
51
52/* export that to outside world */ 45/* export that to outside world */
53struct device_node *of_chosen; 46struct device_node *of_chosen;
54 47
55static inline char *find_flat_dt_string(u32 offset)
56{
57 return ((char *)initial_boot_params) +
58 initial_boot_params->off_dt_strings + offset;
59}
60
61/**
62 * This function is used to scan the flattened device-tree, it is
63 * used to extract the memory informations at boot before we can
64 * unflatten the tree
65 */
66int __init of_scan_flat_dt(int (*it)(unsigned long node,
67 const char *uname, int depth,
68 void *data),
69 void *data)
70{
71 unsigned long p = ((unsigned long)initial_boot_params) +
72 initial_boot_params->off_dt_struct;
73 int rc = 0;
74 int depth = -1;
75
76 do {
77 u32 tag = *((u32 *)p);
78 char *pathp;
79
80 p += 4;
81 if (tag == OF_DT_END_NODE) {
82 depth--;
83 continue;
84 }
85 if (tag == OF_DT_NOP)
86 continue;
87 if (tag == OF_DT_END)
88 break;
89 if (tag == OF_DT_PROP) {
90 u32 sz = *((u32 *)p);
91 p += 8;
92 if (initial_boot_params->version < 0x10)
93 p = _ALIGN(p, sz >= 8 ? 8 : 4);
94 p += sz;
95 p = _ALIGN(p, 4);
96 continue;
97 }
98 if (tag != OF_DT_BEGIN_NODE) {
99 printk(KERN_WARNING "Invalid tag %x scanning flattened"
100 " device tree !\n", tag);
101 return -EINVAL;
102 }
103 depth++;
104 pathp = (char *)p;
105 p = _ALIGN(p + strlen(pathp) + 1, 4);
106 if ((*pathp) == '/') {
107 char *lp, *np;
108 for (lp = NULL, np = pathp; *np; np++)
109 if ((*np) == '/')
110 lp = np+1;
111 if (lp != NULL)
112 pathp = lp;
113 }
114 rc = it(p, pathp, depth, data);
115 if (rc != 0)
116 break;
117 } while (1);
118
119 return rc;
120}
121
122unsigned long __init of_get_flat_dt_root(void)
123{
124 unsigned long p = ((unsigned long)initial_boot_params) +
125 initial_boot_params->off_dt_struct;
126
127 while (*((u32 *)p) == OF_DT_NOP)
128 p += 4;
129 BUG_ON(*((u32 *)p) != OF_DT_BEGIN_NODE);
130 p += 4;
131 return _ALIGN(p + strlen((char *)p) + 1, 4);
132}
133
134/**
135 * This function can be used within scan_flattened_dt callback to get
136 * access to properties
137 */
138void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
139 unsigned long *size)
140{
141 unsigned long p = node;
142
143 do {
144 u32 tag = *((u32 *)p);
145 u32 sz, noff;
146 const char *nstr;
147
148 p += 4;
149 if (tag == OF_DT_NOP)
150 continue;
151 if (tag != OF_DT_PROP)
152 return NULL;
153
154 sz = *((u32 *)p);
155 noff = *((u32 *)(p + 4));
156 p += 8;
157 if (initial_boot_params->version < 0x10)
158 p = _ALIGN(p, sz >= 8 ? 8 : 4);
159
160 nstr = find_flat_dt_string(noff);
161 if (nstr == NULL) {
162 printk(KERN_WARNING "Can't find property index"
163 " name !\n");
164 return NULL;
165 }
166 if (strcmp(name, nstr) == 0) {
167 if (size)
168 *size = sz;
169 return (void *)p;
170 }
171 p += sz;
172 p = _ALIGN(p, 4);
173 } while (1);
174}
175
176int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
177{
178 const char *cp;
179 unsigned long cplen, l;
180
181 cp = of_get_flat_dt_prop(node, "compatible", &cplen);
182 if (cp == NULL)
183 return 0;
184 while (cplen > 0) {
185 if (strncasecmp(cp, compat, strlen(compat)) == 0)
186 return 1;
187 l = strlen(cp) + 1;
188 cp += l;
189 cplen -= l;
190 }
191
192 return 0;
193}
194
195static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
196 unsigned long align)
197{
198 void *res;
199
200 *mem = _ALIGN(*mem, align);
201 res = (void *)*mem;
202 *mem += size;
203
204 return res;
205}
206
207static unsigned long __init unflatten_dt_node(unsigned long mem,
208 unsigned long *p,
209 struct device_node *dad,
210 struct device_node ***allnextpp,
211 unsigned long fpsize)
212{
213 struct device_node *np;
214 struct property *pp, **prev_pp = NULL;
215 char *pathp;
216 u32 tag;
217 unsigned int l, allocl;
218 int has_name = 0;
219 int new_format = 0;
220
221 tag = *((u32 *)(*p));
222 if (tag != OF_DT_BEGIN_NODE) {
223 printk("Weird tag at start of node: %x\n", tag);
224 return mem;
225 }
226 *p += 4;
227 pathp = (char *)*p;
228 l = allocl = strlen(pathp) + 1;
229 *p = _ALIGN(*p + l, 4);
230
231 /* version 0x10 has a more compact unit name here instead of the full
232 * path. we accumulate the full path size using "fpsize", we'll rebuild
233 * it later. We detect this because the first character of the name is
234 * not '/'.
235 */
236 if ((*pathp) != '/') {
237 new_format = 1;
238 if (fpsize == 0) {
239 /* root node: special case. fpsize accounts for path
240 * plus terminating zero. root node only has '/', so
241 * fpsize should be 2, but we want to avoid the first
242 * level nodes to have two '/' so we use fpsize 1 here
243 */
244 fpsize = 1;
245 allocl = 2;
246 } else {
247 /* account for '/' and path size minus terminal 0
248 * already in 'l'
249 */
250 fpsize += l;
251 allocl = fpsize;
252 }
253 }
254
255 np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
256 __alignof__(struct device_node));
257 if (allnextpp) {
258 memset(np, 0, sizeof(*np));
259 np->full_name = ((char *)np) + sizeof(struct device_node);
260 if (new_format) {
261 char *p2 = np->full_name;
262 /* rebuild full path for new format */
263 if (dad && dad->parent) {
264 strcpy(p2, dad->full_name);
265#ifdef DEBUG
266 if ((strlen(p2) + l + 1) != allocl) {
267 pr_debug("%s: p: %d, l: %d, a: %d\n",
268 pathp, (int)strlen(p2),
269 l, allocl);
270 }
271#endif
272 p2 += strlen(p2);
273 }
274 *(p2++) = '/';
275 memcpy(p2, pathp, l);
276 } else
277 memcpy(np->full_name, pathp, l);
278 prev_pp = &np->properties;
279 **allnextpp = np;
280 *allnextpp = &np->allnext;
281 if (dad != NULL) {
282 np->parent = dad;
283 /* we temporarily use the next field as `last_child'*/
284 if (dad->next == NULL)
285 dad->child = np;
286 else
287 dad->next->sibling = np;
288 dad->next = np;
289 }
290 kref_init(&np->kref);
291 }
292 while (1) {
293 u32 sz, noff;
294 char *pname;
295
296 tag = *((u32 *)(*p));
297 if (tag == OF_DT_NOP) {
298 *p += 4;
299 continue;
300 }
301 if (tag != OF_DT_PROP)
302 break;
303 *p += 4;
304 sz = *((u32 *)(*p));
305 noff = *((u32 *)((*p) + 4));
306 *p += 8;
307 if (initial_boot_params->version < 0x10)
308 *p = _ALIGN(*p, sz >= 8 ? 8 : 4);
309
310 pname = find_flat_dt_string(noff);
311 if (pname == NULL) {
312 printk(KERN_INFO
313 "Can't find property name in list !\n");
314 break;
315 }
316 if (strcmp(pname, "name") == 0)
317 has_name = 1;
318 l = strlen(pname) + 1;
319 pp = unflatten_dt_alloc(&mem, sizeof(struct property),
320 __alignof__(struct property));
321 if (allnextpp) {
322 if (strcmp(pname, "linux,phandle") == 0) {
323 np->node = *((u32 *)*p);
324 if (np->linux_phandle == 0)
325 np->linux_phandle = np->node;
326 }
327 if (strcmp(pname, "ibm,phandle") == 0)
328 np->linux_phandle = *((u32 *)*p);
329 pp->name = pname;
330 pp->length = sz;
331 pp->value = (void *)*p;
332 *prev_pp = pp;
333 prev_pp = &pp->next;
334 }
335 *p = _ALIGN((*p) + sz, 4);
336 }
337 /* with version 0x10 we may not have the name property, recreate
338 * it here from the unit name if absent
339 */
340 if (!has_name) {
341 char *p1 = pathp, *ps = pathp, *pa = NULL;
342 int sz;
343
344 while (*p1) {
345 if ((*p1) == '@')
346 pa = p1;
347 if ((*p1) == '/')
348 ps = p1 + 1;
349 p1++;
350 }
351 if (pa < ps)
352 pa = p1;
353 sz = (pa - ps) + 1;
354 pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
355 __alignof__(struct property));
356 if (allnextpp) {
357 pp->name = "name";
358 pp->length = sz;
359 pp->value = pp + 1;
360 *prev_pp = pp;
361 prev_pp = &pp->next;
362 memcpy(pp->value, ps, sz - 1);
363 ((char *)pp->value)[sz - 1] = 0;
364 pr_debug("fixed up name for %s -> %s\n", pathp,
365 (char *)pp->value);
366 }
367 }
368 if (allnextpp) {
369 *prev_pp = NULL;
370 np->name = of_get_property(np, "name", NULL);
371 np->type = of_get_property(np, "device_type", NULL);
372
373 if (!np->name)
374 np->name = "<NULL>";
375 if (!np->type)
376 np->type = "<NULL>";
377 }
378 while (tag == OF_DT_BEGIN_NODE) {
379 mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);
380 tag = *((u32 *)(*p));
381 }
382 if (tag != OF_DT_END_NODE) {
383 printk(KERN_INFO "Weird tag at end of node: %x\n", tag);
384 return mem;
385 }
386 *p += 4;
387 return mem;
388}
389
390/**
391 * unflattens the device-tree passed by the firmware, creating the
392 * tree of struct device_node. It also fills the "name" and "type"
393 * pointers of the nodes so the normal device-tree walking functions
394 * can be used (this used to be done by finish_device_tree)
395 */
396void __init unflatten_device_tree(void)
397{
398 unsigned long start, mem, size;
399 struct device_node **allnextp = &allnodes;
400
401 pr_debug(" -> unflatten_device_tree()\n");
402
403 /* First pass, scan for size */
404 start = ((unsigned long)initial_boot_params) +
405 initial_boot_params->off_dt_struct;
406 size = unflatten_dt_node(0, &start, NULL, NULL, 0);
407 size = (size | 3) + 1;
408
409 pr_debug(" size is %lx, allocating...\n", size);
410
411 /* Allocate memory for the expanded device tree */
412 mem = lmb_alloc(size + 4, __alignof__(struct device_node));
413 mem = (unsigned long) __va(mem);
414
415 ((u32 *)mem)[size / 4] = 0xdeadbeef;
416
417 pr_debug(" unflattening %lx...\n", mem);
418
419 /* Second pass, do actual unflattening */
420 start = ((unsigned long)initial_boot_params) +
421 initial_boot_params->off_dt_struct;
422 unflatten_dt_node(mem, &start, NULL, &allnextp, 0);
423 if (*((u32 *)start) != OF_DT_END)
424 printk(KERN_WARNING "Weird tag at end of tree: %08x\n",
425 *((u32 *)start));
426 if (((u32 *)mem)[size / 4] != 0xdeadbeef)
427 printk(KERN_WARNING "End of tree marker overwritten: %08x\n",
428 ((u32 *)mem)[size / 4]);
429 *allnextp = NULL;
430
431 /* Get pointer to OF "/chosen" node for use everywhere */
432 of_chosen = of_find_node_by_path("/chosen");
433 if (of_chosen == NULL)
434 of_chosen = of_find_node_by_path("/chosen@0");
435
436 pr_debug(" <- unflatten_device_tree()\n");
437}
438
439#define early_init_dt_scan_drconf_memory(node) 0 48#define early_init_dt_scan_drconf_memory(node) 0
440 49
441static int __init early_init_dt_scan_cpus(unsigned long node, 50static int __init early_init_dt_scan_cpus(unsigned long node,
@@ -499,116 +108,16 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
499 return 0; 108 return 0;
500} 109}
501 110
502#ifdef CONFIG_BLK_DEV_INITRD 111void __init early_init_dt_scan_chosen_arch(unsigned long node)
503static void __init early_init_dt_check_for_initrd(unsigned long node)
504{ 112{
505 unsigned long l; 113 /* No Microblaze specific code here */
506 u32 *prop;
507
508 pr_debug("Looking for initrd properties... ");
509
510 prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l);
511 if (prop) {
512 initrd_start = (unsigned long)
513 __va((u32)of_read_ulong(prop, l/4));
514
515 prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l);
516 if (prop) {
517 initrd_end = (unsigned long)
518 __va((u32)of_read_ulong(prop, 1/4));
519 initrd_below_start_ok = 1;
520 } else {
521 initrd_start = 0;
522 }
523 }
524
525 pr_debug("initrd_start=0x%lx initrd_end=0x%lx\n",
526 initrd_start, initrd_end);
527}
528#else
529static inline void early_init_dt_check_for_initrd(unsigned long node)
530{
531}
532#endif /* CONFIG_BLK_DEV_INITRD */
533
534static int __init early_init_dt_scan_chosen(unsigned long node,
535 const char *uname, int depth, void *data)
536{
537 unsigned long l;
538 char *p;
539
540 pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
541
542 if (depth != 1 ||
543 (strcmp(uname, "chosen") != 0 &&
544 strcmp(uname, "chosen@0") != 0))
545 return 0;
546
547#ifdef CONFIG_KEXEC
548 lprop = (u64 *)of_get_flat_dt_prop(node,
549 "linux,crashkernel-base", NULL);
550 if (lprop)
551 crashk_res.start = *lprop;
552
553 lprop = (u64 *)of_get_flat_dt_prop(node,
554 "linux,crashkernel-size", NULL);
555 if (lprop)
556 crashk_res.end = crashk_res.start + *lprop - 1;
557#endif
558
559 early_init_dt_check_for_initrd(node);
560
561 /* Retreive command line */
562 p = of_get_flat_dt_prop(node, "bootargs", &l);
563 if (p != NULL && l > 0)
564 strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE));
565
566#ifdef CONFIG_CMDLINE
567#ifndef CONFIG_CMDLINE_FORCE
568 if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
569#endif
570 strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
571#endif /* CONFIG_CMDLINE */
572
573 pr_debug("Command line is: %s\n", cmd_line);
574
575 /* break now */
576 return 1;
577}
578
579static int __init early_init_dt_scan_root(unsigned long node,
580 const char *uname, int depth, void *data)
581{
582 u32 *prop;
583
584 if (depth != 0)
585 return 0;
586
587 prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
588 dt_root_size_cells = (prop == NULL) ? 1 : *prop;
589 pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells);
590
591 prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
592 dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
593 pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);
594
595 /* break now */
596 return 1;
597}
598
599static u64 __init dt_mem_next_cell(int s, cell_t **cellp)
600{
601 cell_t *p = *cellp;
602
603 *cellp = p + s;
604 return of_read_number(p, s);
605} 114}
606 115
607static int __init early_init_dt_scan_memory(unsigned long node, 116static int __init early_init_dt_scan_memory(unsigned long node,
608 const char *uname, int depth, void *data) 117 const char *uname, int depth, void *data)
609{ 118{
610 char *type = of_get_flat_dt_prop(node, "device_type", NULL); 119 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
611 cell_t *reg, *endp; 120 __be32 *reg, *endp;
612 unsigned long l; 121 unsigned long l;
613 122
614 /* Look for the ibm,dynamic-reconfiguration-memory node */ 123 /* Look for the ibm,dynamic-reconfiguration-memory node */
@@ -627,13 +136,13 @@ static int __init early_init_dt_scan_memory(unsigned long node,
627 } else if (strcmp(type, "memory") != 0) 136 } else if (strcmp(type, "memory") != 0)
628 return 0; 137 return 0;
629 138
630 reg = (cell_t *)of_get_flat_dt_prop(node, "linux,usable-memory", &l); 139 reg = (__be32 *)of_get_flat_dt_prop(node, "linux,usable-memory", &l);
631 if (reg == NULL) 140 if (reg == NULL)
632 reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); 141 reg = (__be32 *)of_get_flat_dt_prop(node, "reg", &l);
633 if (reg == NULL) 142 if (reg == NULL)
634 return 0; 143 return 0;
635 144
636 endp = reg + (l / sizeof(cell_t)); 145 endp = reg + (l / sizeof(__be32));
637 146
638 pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", 147 pr_debug("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",
639 uname, l, reg[0], reg[1], reg[2], reg[3]); 148 uname, l, reg[0], reg[1], reg[2], reg[3]);
@@ -809,24 +318,6 @@ void __init early_init_devtree(void *params)
809 pr_debug(" <- early_init_devtree()\n"); 318 pr_debug(" <- early_init_devtree()\n");
810} 319}
811 320
812/**
813 * Indicates whether the root node has a given value in its
814 * compatible property.
815 */
816int machine_is_compatible(const char *compat)
817{
818 struct device_node *root;
819 int rc = 0;
820
821 root = of_find_node_by_path("/");
822 if (root) {
823 rc = of_device_is_compatible(root, compat);
824 of_node_put(root);
825 }
826 return rc;
827}
828EXPORT_SYMBOL(machine_is_compatible);
829
830/******* 321/*******
831 * 322 *
832 * New implementation of the OF "find" APIs, return a refcounted 323 * New implementation of the OF "find" APIs, return a refcounted
@@ -851,7 +342,7 @@ struct device_node *of_find_node_by_phandle(phandle handle)
851 342
852 read_lock(&devtree_lock); 343 read_lock(&devtree_lock);
853 for (np = allnodes; np != NULL; np = np->allnext) 344 for (np = allnodes; np != NULL; np = np->allnext)
854 if (np->linux_phandle == handle) 345 if (np->phandle == handle)
855 break; 346 break;
856 of_node_get(np); 347 of_node_get(np);
857 read_unlock(&devtree_lock); 348 read_unlock(&devtree_lock);
@@ -859,80 +350,6 @@ struct device_node *of_find_node_by_phandle(phandle handle)
859} 350}
860EXPORT_SYMBOL(of_find_node_by_phandle); 351EXPORT_SYMBOL(of_find_node_by_phandle);
861 352
862/**
863 * of_node_get - Increment refcount of a node
864 * @node: Node to inc refcount, NULL is supported to
865 * simplify writing of callers
866 *
867 * Returns node.
868 */
869struct device_node *of_node_get(struct device_node *node)
870{
871 if (node)
872 kref_get(&node->kref);
873 return node;
874}
875EXPORT_SYMBOL(of_node_get);
876
877static inline struct device_node *kref_to_device_node(struct kref *kref)
878{
879 return container_of(kref, struct device_node, kref);
880}
881
882/**
883 * of_node_release - release a dynamically allocated node
884 * @kref: kref element of the node to be released
885 *
886 * In of_node_put() this function is passed to kref_put()
887 * as the destructor.
888 */
889static void of_node_release(struct kref *kref)
890{
891 struct device_node *node = kref_to_device_node(kref);
892 struct property *prop = node->properties;
893
894 /* We should never be releasing nodes that haven't been detached. */
895 if (!of_node_check_flag(node, OF_DETACHED)) {
896 printk(KERN_INFO "WARNING: Bad of_node_put() on %s\n",
897 node->full_name);
898 dump_stack();
899 kref_init(&node->kref);
900 return;
901 }
902
903 if (!of_node_check_flag(node, OF_DYNAMIC))
904 return;
905
906 while (prop) {
907 struct property *next = prop->next;
908 kfree(prop->name);
909 kfree(prop->value);
910 kfree(prop);
911 prop = next;
912
913 if (!prop) {
914 prop = node->deadprops;
915 node->deadprops = NULL;
916 }
917 }
918 kfree(node->full_name);
919 kfree(node->data);
920 kfree(node);
921}
922
923/**
924 * of_node_put - Decrement refcount of a node
925 * @node: Node to dec refcount, NULL is supported to
926 * simplify writing of callers
927 *
928 */
929void of_node_put(struct device_node *node)
930{
931 if (node)
932 kref_put(&node->kref, of_node_release);
933}
934EXPORT_SYMBOL(of_node_put);
935
936/* 353/*
937 * Plug a device node into the tree and global list. 354 * Plug a device node into the tree and global list.
938 */ 355 */
@@ -992,119 +409,6 @@ out_unlock:
992 write_unlock_irqrestore(&devtree_lock, flags); 409 write_unlock_irqrestore(&devtree_lock, flags);
993} 410}
994 411
995/*
996 * Add a property to a node
997 */
998int prom_add_property(struct device_node *np, struct property *prop)
999{
1000 struct property **next;
1001 unsigned long flags;
1002
1003 prop->next = NULL;
1004 write_lock_irqsave(&devtree_lock, flags);
1005 next = &np->properties;
1006 while (*next) {
1007 if (strcmp(prop->name, (*next)->name) == 0) {
1008 /* duplicate ! don't insert it */
1009 write_unlock_irqrestore(&devtree_lock, flags);
1010 return -1;
1011 }
1012 next = &(*next)->next;
1013 }
1014 *next = prop;
1015 write_unlock_irqrestore(&devtree_lock, flags);
1016
1017#ifdef CONFIG_PROC_DEVICETREE
1018 /* try to add to proc as well if it was initialized */
1019 if (np->pde)
1020 proc_device_tree_add_prop(np->pde, prop);
1021#endif /* CONFIG_PROC_DEVICETREE */
1022
1023 return 0;
1024}
1025
1026/*
1027 * Remove a property from a node. Note that we don't actually
1028 * remove it, since we have given out who-knows-how-many pointers
1029 * to the data using get-property. Instead we just move the property
1030 * to the "dead properties" list, so it won't be found any more.
1031 */
1032int prom_remove_property(struct device_node *np, struct property *prop)
1033{
1034 struct property **next;
1035 unsigned long flags;
1036 int found = 0;
1037
1038 write_lock_irqsave(&devtree_lock, flags);
1039 next = &np->properties;
1040 while (*next) {
1041 if (*next == prop) {
1042 /* found the node */
1043 *next = prop->next;
1044 prop->next = np->deadprops;
1045 np->deadprops = prop;
1046 found = 1;
1047 break;
1048 }
1049 next = &(*next)->next;
1050 }
1051 write_unlock_irqrestore(&devtree_lock, flags);
1052
1053 if (!found)
1054 return -ENODEV;
1055
1056#ifdef CONFIG_PROC_DEVICETREE
1057 /* try to remove the proc node as well */
1058 if (np->pde)
1059 proc_device_tree_remove_prop(np->pde, prop);
1060#endif /* CONFIG_PROC_DEVICETREE */
1061
1062 return 0;
1063}
1064
1065/*
1066 * Update a property in a node. Note that we don't actually
1067 * remove it, since we have given out who-knows-how-many pointers
1068 * to the data using get-property. Instead we just move the property
1069 * to the "dead properties" list, and add the new property to the
1070 * property list
1071 */
1072int prom_update_property(struct device_node *np,
1073 struct property *newprop,
1074 struct property *oldprop)
1075{
1076 struct property **next;
1077 unsigned long flags;
1078 int found = 0;
1079
1080 write_lock_irqsave(&devtree_lock, flags);
1081 next = &np->properties;
1082 while (*next) {
1083 if (*next == oldprop) {
1084 /* found the node */
1085 newprop->next = oldprop->next;
1086 *next = newprop;
1087 oldprop->next = np->deadprops;
1088 np->deadprops = oldprop;
1089 found = 1;
1090 break;
1091 }
1092 next = &(*next)->next;
1093 }
1094 write_unlock_irqrestore(&devtree_lock, flags);
1095
1096 if (!found)
1097 return -ENODEV;
1098
1099#ifdef CONFIG_PROC_DEVICETREE
1100 /* try to add to proc as well if it was initialized */
1101 if (np->pde)
1102 proc_device_tree_update_prop(np->pde, newprop, oldprop);
1103#endif /* CONFIG_PROC_DEVICETREE */
1104
1105 return 0;
1106}
1107
1108#if defined(CONFIG_DEBUG_FS) && defined(DEBUG) 412#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
1109static struct debugfs_blob_wrapper flat_dt_blob; 413static struct debugfs_blob_wrapper flat_dt_blob;
1110 414
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index ba3948c70072..50c9af43e017 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -173,6 +173,7 @@ config PPC_OF
173 173
174config OF 174config OF
175 def_bool y 175 def_bool y
176 select OF_FLATTREE
176 177
177config PPC_UDBG_16550 178config PPC_UDBG_16550
178 bool 179 bool
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index 1a4fc0d11a03..666d08db319e 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -214,7 +214,7 @@ EXPORT_SYMBOL(of_find_device_by_node);
214static int of_dev_phandle_match(struct device *dev, void *data) 214static int of_dev_phandle_match(struct device *dev, void *data)
215{ 215{
216 phandle *ph = data; 216 phandle *ph = data;
217 return to_of_device(dev)->node->linux_phandle == *ph; 217 return to_of_device(dev)->node->phandle == *ph;
218} 218}
219 219
220struct of_device *of_find_device_by_phandle(phandle ph) 220struct of_device *of_find_device_by_phandle(phandle ph)
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 4ec300862466..1ed2ec2ea05b 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -61,365 +61,17 @@
61#define DBG(fmt...) 61#define DBG(fmt...)
62#endif 62#endif
63 63
64
65static int __initdata dt_root_addr_cells;
66static int __initdata dt_root_size_cells;
67
68#ifdef CONFIG_PPC64 64#ifdef CONFIG_PPC64
69int __initdata iommu_is_off; 65int __initdata iommu_is_off;
70int __initdata iommu_force_on; 66int __initdata iommu_force_on;
71unsigned long tce_alloc_start, tce_alloc_end; 67unsigned long tce_alloc_start, tce_alloc_end;
72#endif 68#endif
73 69
74typedef u32 cell_t;
75
76#if 0
77static struct boot_param_header *initial_boot_params __initdata;
78#else
79struct boot_param_header *initial_boot_params;
80#endif
81
82extern struct device_node *allnodes; /* temporary while merging */
83
84extern rwlock_t devtree_lock; /* temporary while merging */ 70extern rwlock_t devtree_lock; /* temporary while merging */
85 71
86/* export that to outside world */ 72/* export that to outside world */
87struct device_node *of_chosen; 73struct device_node *of_chosen;
88 74
89static inline char *find_flat_dt_string(u32 offset)
90{
91 return ((char *)initial_boot_params) +
92 initial_boot_params->off_dt_strings + offset;
93}
94
95/**
96 * This function is used to scan the flattened device-tree, it is
97 * used to extract the memory informations at boot before we can
98 * unflatten the tree
99 */
100int __init of_scan_flat_dt(int (*it)(unsigned long node,
101 const char *uname, int depth,
102 void *data),
103 void *data)
104{
105 unsigned long p = ((unsigned long)initial_boot_params) +
106 initial_boot_params->off_dt_struct;
107 int rc = 0;
108 int depth = -1;
109
110 do {
111 u32 tag = *((u32 *)p);
112 char *pathp;
113
114 p += 4;
115 if (tag == OF_DT_END_NODE) {
116 depth --;
117 continue;
118 }
119 if (tag == OF_DT_NOP)
120 continue;
121 if (tag == OF_DT_END)
122 break;
123 if (tag == OF_DT_PROP) {
124 u32 sz = *((u32 *)p);
125 p += 8;
126 if (initial_boot_params->version < 0x10)
127 p = _ALIGN(p, sz >= 8 ? 8 : 4);
128 p += sz;
129 p = _ALIGN(p, 4);
130 continue;
131 }
132 if (tag != OF_DT_BEGIN_NODE) {
133 printk(KERN_WARNING "Invalid tag %x scanning flattened"
134 " device tree !\n", tag);
135 return -EINVAL;
136 }
137 depth++;
138 pathp = (char *)p;
139 p = _ALIGN(p + strlen(pathp) + 1, 4);
140 if ((*pathp) == '/') {
141 char *lp, *np;
142 for (lp = NULL, np = pathp; *np; np++)
143 if ((*np) == '/')
144 lp = np+1;
145 if (lp != NULL)
146 pathp = lp;
147 }
148 rc = it(p, pathp, depth, data);
149 if (rc != 0)
150 break;
151 } while(1);
152
153 return rc;
154}
155
156unsigned long __init of_get_flat_dt_root(void)
157{
158 unsigned long p = ((unsigned long)initial_boot_params) +
159 initial_boot_params->off_dt_struct;
160
161 while(*((u32 *)p) == OF_DT_NOP)
162 p += 4;
163 BUG_ON (*((u32 *)p) != OF_DT_BEGIN_NODE);
164 p += 4;
165 return _ALIGN(p + strlen((char *)p) + 1, 4);
166}
167
168/**
169 * This function can be used within scan_flattened_dt callback to get
170 * access to properties
171 */
172void* __init of_get_flat_dt_prop(unsigned long node, const char *name,
173 unsigned long *size)
174{
175 unsigned long p = node;
176
177 do {
178 u32 tag = *((u32 *)p);
179 u32 sz, noff;
180 const char *nstr;
181
182 p += 4;
183 if (tag == OF_DT_NOP)
184 continue;
185 if (tag != OF_DT_PROP)
186 return NULL;
187
188 sz = *((u32 *)p);
189 noff = *((u32 *)(p + 4));
190 p += 8;
191 if (initial_boot_params->version < 0x10)
192 p = _ALIGN(p, sz >= 8 ? 8 : 4);
193
194 nstr = find_flat_dt_string(noff);
195 if (nstr == NULL) {
196 printk(KERN_WARNING "Can't find property index"
197 " name !\n");
198 return NULL;
199 }
200 if (strcmp(name, nstr) == 0) {
201 if (size)
202 *size = sz;
203 return (void *)p;
204 }
205 p += sz;
206 p = _ALIGN(p, 4);
207 } while(1);
208}
209
210int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
211{
212 const char* cp;
213 unsigned long cplen, l;
214
215 cp = of_get_flat_dt_prop(node, "compatible", &cplen);
216 if (cp == NULL)
217 return 0;
218 while (cplen > 0) {
219 if (strncasecmp(cp, compat, strlen(compat)) == 0)
220 return 1;
221 l = strlen(cp) + 1;
222 cp += l;
223 cplen -= l;
224 }
225
226 return 0;
227}
228
229static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
230 unsigned long align)
231{
232 void *res;
233
234 *mem = _ALIGN(*mem, align);
235 res = (void *)*mem;
236 *mem += size;
237
238 return res;
239}
240
241static unsigned long __init unflatten_dt_node(unsigned long mem,
242 unsigned long *p,
243 struct device_node *dad,
244 struct device_node ***allnextpp,
245 unsigned long fpsize)
246{
247 struct device_node *np;
248 struct property *pp, **prev_pp = NULL;
249 char *pathp;
250 u32 tag;
251 unsigned int l, allocl;
252 int has_name = 0;
253 int new_format = 0;
254
255 tag = *((u32 *)(*p));
256 if (tag != OF_DT_BEGIN_NODE) {
257 printk("Weird tag at start of node: %x\n", tag);
258 return mem;
259 }
260 *p += 4;
261 pathp = (char *)*p;
262 l = allocl = strlen(pathp) + 1;
263 *p = _ALIGN(*p + l, 4);
264
265 /* version 0x10 has a more compact unit name here instead of the full
266 * path. we accumulate the full path size using "fpsize", we'll rebuild
267 * it later. We detect this because the first character of the name is
268 * not '/'.
269 */
270 if ((*pathp) != '/') {
271 new_format = 1;
272 if (fpsize == 0) {
273 /* root node: special case. fpsize accounts for path
274 * plus terminating zero. root node only has '/', so
275 * fpsize should be 2, but we want to avoid the first
276 * level nodes to have two '/' so we use fpsize 1 here
277 */
278 fpsize = 1;
279 allocl = 2;
280 } else {
281 /* account for '/' and path size minus terminal 0
282 * already in 'l'
283 */
284 fpsize += l;
285 allocl = fpsize;
286 }
287 }
288
289
290 np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
291 __alignof__(struct device_node));
292 if (allnextpp) {
293 memset(np, 0, sizeof(*np));
294 np->full_name = ((char*)np) + sizeof(struct device_node);
295 if (new_format) {
296 char *p = np->full_name;
297 /* rebuild full path for new format */
298 if (dad && dad->parent) {
299 strcpy(p, dad->full_name);
300#ifdef DEBUG
301 if ((strlen(p) + l + 1) != allocl) {
302 DBG("%s: p: %d, l: %d, a: %d\n",
303 pathp, (int)strlen(p), l, allocl);
304 }
305#endif
306 p += strlen(p);
307 }
308 *(p++) = '/';
309 memcpy(p, pathp, l);
310 } else
311 memcpy(np->full_name, pathp, l);
312 prev_pp = &np->properties;
313 **allnextpp = np;
314 *allnextpp = &np->allnext;
315 if (dad != NULL) {
316 np->parent = dad;
317 /* we temporarily use the next field as `last_child'*/
318 if (dad->next == 0)
319 dad->child = np;
320 else
321 dad->next->sibling = np;
322 dad->next = np;
323 }
324 kref_init(&np->kref);
325 }
326 while(1) {
327 u32 sz, noff;
328 char *pname;
329
330 tag = *((u32 *)(*p));
331 if (tag == OF_DT_NOP) {
332 *p += 4;
333 continue;
334 }
335 if (tag != OF_DT_PROP)
336 break;
337 *p += 4;
338 sz = *((u32 *)(*p));
339 noff = *((u32 *)((*p) + 4));
340 *p += 8;
341 if (initial_boot_params->version < 0x10)
342 *p = _ALIGN(*p, sz >= 8 ? 8 : 4);
343
344 pname = find_flat_dt_string(noff);
345 if (pname == NULL) {
346 printk("Can't find property name in list !\n");
347 break;
348 }
349 if (strcmp(pname, "name") == 0)
350 has_name = 1;
351 l = strlen(pname) + 1;
352 pp = unflatten_dt_alloc(&mem, sizeof(struct property),
353 __alignof__(struct property));
354 if (allnextpp) {
355 if (strcmp(pname, "linux,phandle") == 0) {
356 np->node = *((u32 *)*p);
357 if (np->linux_phandle == 0)
358 np->linux_phandle = np->node;
359 }
360 if (strcmp(pname, "ibm,phandle") == 0)
361 np->linux_phandle = *((u32 *)*p);
362 pp->name = pname;
363 pp->length = sz;
364 pp->value = (void *)*p;
365 *prev_pp = pp;
366 prev_pp = &pp->next;
367 }
368 *p = _ALIGN((*p) + sz, 4);
369 }
370 /* with version 0x10 we may not have the name property, recreate
371 * it here from the unit name if absent
372 */
373 if (!has_name) {
374 char *p = pathp, *ps = pathp, *pa = NULL;
375 int sz;
376
377 while (*p) {
378 if ((*p) == '@')
379 pa = p;
380 if ((*p) == '/')
381 ps = p + 1;
382 p++;
383 }
384 if (pa < ps)
385 pa = p;
386 sz = (pa - ps) + 1;
387 pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
388 __alignof__(struct property));
389 if (allnextpp) {
390 pp->name = "name";
391 pp->length = sz;
392 pp->value = pp + 1;
393 *prev_pp = pp;
394 prev_pp = &pp->next;
395 memcpy(pp->value, ps, sz - 1);
396 ((char *)pp->value)[sz - 1] = 0;
397 DBG("fixed up name for %s -> %s\n", pathp,
398 (char *)pp->value);
399 }
400 }
401 if (allnextpp) {
402 *prev_pp = NULL;
403 np->name = of_get_property(np, "name", NULL);
404 np->type = of_get_property(np, "device_type", NULL);
405
406 if (!np->name)
407 np->name = "<NULL>";
408 if (!np->type)
409 np->type = "<NULL>";
410 }
411 while (tag == OF_DT_BEGIN_NODE) {
412 mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);
413 tag = *((u32 *)(*p));
414 }
415 if (tag != OF_DT_END_NODE) {
416 printk("Weird tag at end of node: %x\n", tag);
417 return mem;
418 }
419 *p += 4;
420 return mem;
421}
422
423static int __init early_parse_mem(char *p) 75static int __init early_parse_mem(char *p)
424{ 76{
425 if (!p) 77 if (!p)
@@ -459,54 +111,6 @@ static void __init move_device_tree(void)
459 DBG("<- move_device_tree\n"); 111 DBG("<- move_device_tree\n");
460} 112}
461 113
462/**
463 * unflattens the device-tree passed by the firmware, creating the
464 * tree of struct device_node. It also fills the "name" and "type"
465 * pointers of the nodes so the normal device-tree walking functions
466 * can be used (this used to be done by finish_device_tree)
467 */
468void __init unflatten_device_tree(void)
469{
470 unsigned long start, mem, size;
471 struct device_node **allnextp = &allnodes;
472
473 DBG(" -> unflatten_device_tree()\n");
474
475 /* First pass, scan for size */
476 start = ((unsigned long)initial_boot_params) +
477 initial_boot_params->off_dt_struct;
478 size = unflatten_dt_node(0, &start, NULL, NULL, 0);
479 size = (size | 3) + 1;
480
481 DBG(" size is %lx, allocating...\n", size);
482
483 /* Allocate memory for the expanded device tree */
484 mem = lmb_alloc(size + 4, __alignof__(struct device_node));
485 mem = (unsigned long) __va(mem);
486
487 ((u32 *)mem)[size / 4] = 0xdeadbeef;
488
489 DBG(" unflattening %lx...\n", mem);
490
491 /* Second pass, do actual unflattening */
492 start = ((unsigned long)initial_boot_params) +
493 initial_boot_params->off_dt_struct;
494 unflatten_dt_node(mem, &start, NULL, &allnextp, 0);
495 if (*((u32 *)start) != OF_DT_END)
496 printk(KERN_WARNING "Weird tag at end of tree: %08x\n", *((u32 *)start));
497 if (((u32 *)mem)[size / 4] != 0xdeadbeef)
498 printk(KERN_WARNING "End of tree marker overwritten: %08x\n",
499 ((u32 *)mem)[size / 4] );
500 *allnextp = NULL;
501
502 /* Get pointer to OF "/chosen" node for use everywhere */
503 of_chosen = of_find_node_by_path("/chosen");
504 if (of_chosen == NULL)
505 of_chosen = of_find_node_by_path("/chosen@0");
506
507 DBG(" <- unflatten_device_tree()\n");
508}
509
510/* 114/*
511 * ibm,pa-features is a per-cpu property that contains a string of 115 * ibm,pa-features is a per-cpu property that contains a string of
512 * attribute descriptors, each of which has a 2 byte header plus up 116 * attribute descriptors, each of which has a 2 byte header plus up
@@ -763,48 +367,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
763 return 0; 367 return 0;
764} 368}
765 369
766#ifdef CONFIG_BLK_DEV_INITRD 370void __init early_init_dt_scan_chosen_arch(unsigned long node)
767static void __init early_init_dt_check_for_initrd(unsigned long node)
768{
769 unsigned long l;
770 u32 *prop;
771
772 DBG("Looking for initrd properties... ");
773
774 prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l);
775 if (prop) {
776 initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4));
777
778 prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l);
779 if (prop) {
780 initrd_end = (unsigned long)
781 __va(of_read_ulong(prop, l/4));
782 initrd_below_start_ok = 1;
783 } else {
784 initrd_start = 0;
785 }
786 }
787
788 DBG("initrd_start=0x%lx initrd_end=0x%lx\n", initrd_start, initrd_end);
789}
790#else
791static inline void early_init_dt_check_for_initrd(unsigned long node)
792{
793}
794#endif /* CONFIG_BLK_DEV_INITRD */
795
796static int __init early_init_dt_scan_chosen(unsigned long node,
797 const char *uname, int depth, void *data)
798{ 371{
799 unsigned long *lprop; 372 unsigned long *lprop;
800 unsigned long l;
801 char *p;
802
803 DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
804
805 if (depth != 1 ||
806 (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
807 return 0;
808 373
809#ifdef CONFIG_PPC64 374#ifdef CONFIG_PPC64
810 /* check if iommu is forced on or off */ 375 /* check if iommu is forced on or off */
@@ -815,17 +380,17 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
815#endif 380#endif
816 381
817 /* mem=x on the command line is the preferred mechanism */ 382 /* mem=x on the command line is the preferred mechanism */
818 lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); 383 lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL);
819 if (lprop) 384 if (lprop)
820 memory_limit = *lprop; 385 memory_limit = *lprop;
821 386
822#ifdef CONFIG_PPC64 387#ifdef CONFIG_PPC64
823 lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); 388 lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL);
824 if (lprop) 389 if (lprop)
825 tce_alloc_start = *lprop; 390 tce_alloc_start = *lprop;
826 lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); 391 lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL);
827 if (lprop) 392 if (lprop)
828 tce_alloc_end = *lprop; 393 tce_alloc_end = *lprop;
829#endif 394#endif
830 395
831#ifdef CONFIG_KEXEC 396#ifdef CONFIG_KEXEC
@@ -837,51 +402,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
837 if (lprop) 402 if (lprop)
838 crashk_res.end = crashk_res.start + *lprop - 1; 403 crashk_res.end = crashk_res.start + *lprop - 1;
839#endif 404#endif
840
841 early_init_dt_check_for_initrd(node);
842
843 /* Retreive command line */
844 p = of_get_flat_dt_prop(node, "bootargs", &l);
845 if (p != NULL && l > 0)
846 strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE));
847
848#ifdef CONFIG_CMDLINE
849 if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
850 strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
851#endif /* CONFIG_CMDLINE */
852
853 DBG("Command line is: %s\n", cmd_line);
854
855 /* break now */
856 return 1;
857}
858
859static int __init early_init_dt_scan_root(unsigned long node,
860 const char *uname, int depth, void *data)
861{
862 u32 *prop;
863
864 if (depth != 0)
865 return 0;
866
867 prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
868 dt_root_size_cells = (prop == NULL) ? 1 : *prop;
869 DBG("dt_root_size_cells = %x\n", dt_root_size_cells);
870
871 prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
872 dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
873 DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells);
874
875 /* break now */
876 return 1;
877}
878
879static u64 __init dt_mem_next_cell(int s, cell_t **cellp)
880{
881 cell_t *p = *cellp;
882
883 *cellp = p + s;
884 return of_read_number(p, s);
885} 405}
886 406
887#ifdef CONFIG_PPC_PSERIES 407#ifdef CONFIG_PPC_PSERIES
@@ -893,22 +413,22 @@ static u64 __init dt_mem_next_cell(int s, cell_t **cellp)
893 */ 413 */
894static int __init early_init_dt_scan_drconf_memory(unsigned long node) 414static int __init early_init_dt_scan_drconf_memory(unsigned long node)
895{ 415{
896 cell_t *dm, *ls, *usm; 416 __be32 *dm, *ls, *usm;
897 unsigned long l, n, flags; 417 unsigned long l, n, flags;
898 u64 base, size, lmb_size; 418 u64 base, size, lmb_size;
899 unsigned int is_kexec_kdump = 0, rngs; 419 unsigned int is_kexec_kdump = 0, rngs;
900 420
901 ls = of_get_flat_dt_prop(node, "ibm,lmb-size", &l); 421 ls = of_get_flat_dt_prop(node, "ibm,lmb-size", &l);
902 if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t)) 422 if (ls == NULL || l < dt_root_size_cells * sizeof(__be32))
903 return 0; 423 return 0;
904 lmb_size = dt_mem_next_cell(dt_root_size_cells, &ls); 424 lmb_size = dt_mem_next_cell(dt_root_size_cells, &ls);
905 425
906 dm = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l); 426 dm = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l);
907 if (dm == NULL || l < sizeof(cell_t)) 427 if (dm == NULL || l < sizeof(__be32))
908 return 0; 428 return 0;
909 429
910 n = *dm++; /* number of entries */ 430 n = *dm++; /* number of entries */
911 if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(cell_t)) 431 if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(__be32))
912 return 0; 432 return 0;
913 433
914 /* check if this is a kexec/kdump kernel. */ 434 /* check if this is a kexec/kdump kernel. */
@@ -967,7 +487,7 @@ static int __init early_init_dt_scan_memory(unsigned long node,
967 const char *uname, int depth, void *data) 487 const char *uname, int depth, void *data)
968{ 488{
969 char *type = of_get_flat_dt_prop(node, "device_type", NULL); 489 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
970 cell_t *reg, *endp; 490 __be32 *reg, *endp;
971 unsigned long l; 491 unsigned long l;
972 492
973 /* Look for the ibm,dynamic-reconfiguration-memory node */ 493 /* Look for the ibm,dynamic-reconfiguration-memory node */
@@ -992,7 +512,7 @@ static int __init early_init_dt_scan_memory(unsigned long node,
992 if (reg == NULL) 512 if (reg == NULL)
993 return 0; 513 return 0;
994 514
995 endp = reg + (l / sizeof(cell_t)); 515 endp = reg + (l / sizeof(__be32));
996 516
997 DBG("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", 517 DBG("memory scan node %s, reg size %ld, data: %x %x %x %x,\n",
998 uname, l, reg[0], reg[1], reg[2], reg[3]); 518 uname, l, reg[0], reg[1], reg[2], reg[3]);
@@ -1234,25 +754,6 @@ void __init early_init_devtree(void *params)
1234 DBG(" <- early_init_devtree()\n"); 754 DBG(" <- early_init_devtree()\n");
1235} 755}
1236 756
1237
1238/**
1239 * Indicates whether the root node has a given value in its
1240 * compatible property.
1241 */
1242int machine_is_compatible(const char *compat)
1243{
1244 struct device_node *root;
1245 int rc = 0;
1246
1247 root = of_find_node_by_path("/");
1248 if (root) {
1249 rc = of_device_is_compatible(root, compat);
1250 of_node_put(root);
1251 }
1252 return rc;
1253}
1254EXPORT_SYMBOL(machine_is_compatible);
1255
1256/******* 757/*******
1257 * 758 *
1258 * New implementation of the OF "find" APIs, return a refcounted 759 * New implementation of the OF "find" APIs, return a refcounted
@@ -1277,7 +778,7 @@ struct device_node *of_find_node_by_phandle(phandle handle)
1277 778
1278 read_lock(&devtree_lock); 779 read_lock(&devtree_lock);
1279 for (np = allnodes; np != 0; np = np->allnext) 780 for (np = allnodes; np != 0; np = np->allnext)
1280 if (np->linux_phandle == handle) 781 if (np->phandle == handle)
1281 break; 782 break;
1282 of_node_get(np); 783 of_node_get(np);
1283 read_unlock(&devtree_lock); 784 read_unlock(&devtree_lock);
@@ -1316,79 +817,6 @@ struct device_node *of_find_next_cache_node(struct device_node *np)
1316 return NULL; 817 return NULL;
1317} 818}
1318 819
1319/**
1320 * of_node_get - Increment refcount of a node
1321 * @node: Node to inc refcount, NULL is supported to
1322 * simplify writing of callers
1323 *
1324 * Returns node.
1325 */
1326struct device_node *of_node_get(struct device_node *node)
1327{
1328 if (node)
1329 kref_get(&node->kref);
1330 return node;
1331}
1332EXPORT_SYMBOL(of_node_get);
1333
1334static inline struct device_node * kref_to_device_node(struct kref *kref)
1335{
1336 return container_of(kref, struct device_node, kref);
1337}
1338
1339/**
1340 * of_node_release - release a dynamically allocated node
1341 * @kref: kref element of the node to be released
1342 *
1343 * In of_node_put() this function is passed to kref_put()
1344 * as the destructor.
1345 */
1346static void of_node_release(struct kref *kref)
1347{
1348 struct device_node *node = kref_to_device_node(kref);
1349 struct property *prop = node->properties;
1350
1351 /* We should never be releasing nodes that haven't been detached. */
1352 if (!of_node_check_flag(node, OF_DETACHED)) {
1353 printk("WARNING: Bad of_node_put() on %s\n", node->full_name);
1354 dump_stack();
1355 kref_init(&node->kref);
1356 return;
1357 }
1358
1359 if (!of_node_check_flag(node, OF_DYNAMIC))
1360 return;
1361
1362 while (prop) {
1363 struct property *next = prop->next;
1364 kfree(prop->name);
1365 kfree(prop->value);
1366 kfree(prop);
1367 prop = next;
1368
1369 if (!prop) {
1370 prop = node->deadprops;
1371 node->deadprops = NULL;
1372 }
1373 }
1374 kfree(node->full_name);
1375 kfree(node->data);
1376 kfree(node);
1377}
1378
1379/**
1380 * of_node_put - Decrement refcount of a node
1381 * @node: Node to dec refcount, NULL is supported to
1382 * simplify writing of callers
1383 *
1384 */
1385void of_node_put(struct device_node *node)
1386{
1387 if (node)
1388 kref_put(&node->kref, of_node_release);
1389}
1390EXPORT_SYMBOL(of_node_put);
1391
1392/* 820/*
1393 * Plug a device node into the tree and global list. 821 * Plug a device node into the tree and global list.
1394 */ 822 */
@@ -1479,9 +907,9 @@ static int of_finish_dynamic_node(struct device_node *node)
1479 if (machine_is(powermac)) 907 if (machine_is(powermac))
1480 return -ENODEV; 908 return -ENODEV;
1481 909
1482 /* fix up new node's linux_phandle field */ 910 /* fix up new node's phandle field */
1483 if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL))) 911 if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL)))
1484 node->linux_phandle = *ibm_phandle; 912 node->phandle = *ibm_phandle;
1485 913
1486out: 914out:
1487 of_node_put(parent); 915 of_node_put(parent);
@@ -1520,120 +948,6 @@ static int __init prom_reconfig_setup(void)
1520__initcall(prom_reconfig_setup); 948__initcall(prom_reconfig_setup);
1521#endif 949#endif
1522 950
1523/*
1524 * Add a property to a node
1525 */
1526int prom_add_property(struct device_node* np, struct property* prop)
1527{
1528 struct property **next;
1529 unsigned long flags;
1530
1531 prop->next = NULL;
1532 write_lock_irqsave(&devtree_lock, flags);
1533 next = &np->properties;
1534 while (*next) {
1535 if (strcmp(prop->name, (*next)->name) == 0) {
1536 /* duplicate ! don't insert it */
1537 write_unlock_irqrestore(&devtree_lock, flags);
1538 return -1;
1539 }
1540 next = &(*next)->next;
1541 }
1542 *next = prop;
1543 write_unlock_irqrestore(&devtree_lock, flags);
1544
1545#ifdef CONFIG_PROC_DEVICETREE
1546 /* try to add to proc as well if it was initialized */
1547 if (np->pde)
1548 proc_device_tree_add_prop(np->pde, prop);
1549#endif /* CONFIG_PROC_DEVICETREE */
1550
1551 return 0;
1552}
1553
1554/*
1555 * Remove a property from a node. Note that we don't actually
1556 * remove it, since we have given out who-knows-how-many pointers
1557 * to the data using get-property. Instead we just move the property
1558 * to the "dead properties" list, so it won't be found any more.
1559 */
1560int prom_remove_property(struct device_node *np, struct property *prop)
1561{
1562 struct property **next;
1563 unsigned long flags;
1564 int found = 0;
1565
1566 write_lock_irqsave(&devtree_lock, flags);
1567 next = &np->properties;
1568 while (*next) {
1569 if (*next == prop) {
1570 /* found the node */
1571 *next = prop->next;
1572 prop->next = np->deadprops;
1573 np->deadprops = prop;
1574 found = 1;
1575 break;
1576 }
1577 next = &(*next)->next;
1578 }
1579 write_unlock_irqrestore(&devtree_lock, flags);
1580
1581 if (!found)
1582 return -ENODEV;
1583
1584#ifdef CONFIG_PROC_DEVICETREE
1585 /* try to remove the proc node as well */
1586 if (np->pde)
1587 proc_device_tree_remove_prop(np->pde, prop);
1588#endif /* CONFIG_PROC_DEVICETREE */
1589
1590 return 0;
1591}
1592
1593/*
1594 * Update a property in a node. Note that we don't actually
1595 * remove it, since we have given out who-knows-how-many pointers
1596 * to the data using get-property. Instead we just move the property
1597 * to the "dead properties" list, and add the new property to the
1598 * property list
1599 */
1600int prom_update_property(struct device_node *np,
1601 struct property *newprop,
1602 struct property *oldprop)
1603{
1604 struct property **next;
1605 unsigned long flags;
1606 int found = 0;
1607
1608 write_lock_irqsave(&devtree_lock, flags);
1609 next = &np->properties;
1610 while (*next) {
1611 if (*next == oldprop) {
1612 /* found the node */
1613 newprop->next = oldprop->next;
1614 *next = newprop;
1615 oldprop->next = np->deadprops;
1616 np->deadprops = oldprop;
1617 found = 1;
1618 break;
1619 }
1620 next = &(*next)->next;
1621 }
1622 write_unlock_irqrestore(&devtree_lock, flags);
1623
1624 if (!found)
1625 return -ENODEV;
1626
1627#ifdef CONFIG_PROC_DEVICETREE
1628 /* try to add to proc as well if it was initialized */
1629 if (np->pde)
1630 proc_device_tree_update_prop(np->pde, newprop, oldprop);
1631#endif /* CONFIG_PROC_DEVICETREE */
1632
1633 return 0;
1634}
1635
1636
1637/* Find the device node for a given logical cpu number, also returns the cpu 951/* Find the device node for a given logical cpu number, also returns the cpu
1638 * local thread number (index in ibm,interrupt-server#s) if relevant and 952 * local thread number (index in ibm,interrupt-server#s) if relevant and
1639 * asked for (non NULL) 953 * asked for (non NULL)
diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c
index 4c506c1463cd..891f18e337a2 100644
--- a/arch/powerpc/platforms/cell/spu_manage.c
+++ b/arch/powerpc/platforms/cell/spu_manage.c
@@ -457,7 +457,7 @@ neighbour_spu(int cbe, struct device_node *target, struct device_node *avoid)
457 continue; 457 continue;
458 vic_handles = of_get_property(spu_dn, "vicinity", &lenp); 458 vic_handles = of_get_property(spu_dn, "vicinity", &lenp);
459 for (i=0; i < (lenp / sizeof(phandle)); i++) { 459 for (i=0; i < (lenp / sizeof(phandle)); i++) {
460 if (vic_handles[i] == target->linux_phandle) 460 if (vic_handles[i] == target->phandle)
461 return spu; 461 return spu;
462 } 462 }
463 } 463 }
@@ -499,7 +499,7 @@ static void init_affinity_node(int cbe)
499 499
500 if (strcmp(name, "spe") == 0) { 500 if (strcmp(name, "spe") == 0) {
501 spu = devnode_spu(cbe, vic_dn); 501 spu = devnode_spu(cbe, vic_dn);
502 avoid_ph = last_spu_dn->linux_phandle; 502 avoid_ph = last_spu_dn->phandle;
503 } else { 503 } else {
504 /* 504 /*
505 * "mic-tm" and "bif0" nodes do not have 505 * "mic-tm" and "bif0" nodes do not have
@@ -514,7 +514,7 @@ static void init_affinity_node(int cbe)
514 last_spu->has_mem_affinity = 1; 514 last_spu->has_mem_affinity = 1;
515 spu->has_mem_affinity = 1; 515 spu->has_mem_affinity = 1;
516 } 516 }
517 avoid_ph = vic_dn->linux_phandle; 517 avoid_ph = vic_dn->phandle;
518 } 518 }
519 519
520 list_add_tail(&spu->aff_list, &last_spu->aff_list); 520 list_add_tail(&spu->aff_list, &last_spu->aff_list);
diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c
index 96d5ce50364e..ede49e78a8da 100644
--- a/arch/powerpc/platforms/powermac/pfunc_core.c
+++ b/arch/powerpc/platforms/powermac/pfunc_core.c
@@ -842,7 +842,7 @@ struct pmf_function *__pmf_find_function(struct device_node *target,
842 list_for_each_entry(func, &dev->functions, link) { 842 list_for_each_entry(func, &dev->functions, link) {
843 if (name && strcmp(name, func->name)) 843 if (name && strcmp(name, func->name))
844 continue; 844 continue;
845 if (func->phandle && target->node != func->phandle) 845 if (func->phandle && target->phandle != func->phandle)
846 continue; 846 continue;
847 if ((func->flags & flags) == 0) 847 if ((func->flags & flags) == 0)
848 continue; 848 continue;
diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c
index b171ae8de90d..b062de9424a4 100644
--- a/arch/sparc/kernel/devices.c
+++ b/arch/sparc/kernel/devices.c
@@ -59,7 +59,7 @@ static int __cpu_find_by(int (*compare)(int, int, void *), void *compare_arg,
59 59
60 cur_inst = 0; 60 cur_inst = 0;
61 for_each_node_by_type(dp, "cpu") { 61 for_each_node_by_type(dp, "cpu") {
62 int err = check_cpu_node(dp->node, &cur_inst, 62 int err = check_cpu_node(dp->phandle, &cur_inst,
63 compare, compare_arg, 63 compare, compare_arg,
64 prom_node, mid); 64 prom_node, mid);
65 if (!err) { 65 if (!err) {
diff --git a/arch/sparc/kernel/of_device_32.c b/arch/sparc/kernel/of_device_32.c
index 4c26eb59e742..09138d403c7f 100644
--- a/arch/sparc/kernel/of_device_32.c
+++ b/arch/sparc/kernel/of_device_32.c
@@ -433,7 +433,7 @@ build_resources:
433 if (!parent) 433 if (!parent)
434 dev_set_name(&op->dev, "root"); 434 dev_set_name(&op->dev, "root");
435 else 435 else
436 dev_set_name(&op->dev, "%08x", dp->node); 436 dev_set_name(&op->dev, "%08x", dp->phandle);
437 437
438 if (of_device_register(op)) { 438 if (of_device_register(op)) {
439 printk("%s: Could not register of device.\n", 439 printk("%s: Could not register of device.\n",
diff --git a/arch/sparc/kernel/of_device_64.c b/arch/sparc/kernel/of_device_64.c
index 0a6f2d1798d1..b3d4cb5d21b3 100644
--- a/arch/sparc/kernel/of_device_64.c
+++ b/arch/sparc/kernel/of_device_64.c
@@ -676,7 +676,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
676 if (!parent) 676 if (!parent)
677 dev_set_name(&op->dev, "root"); 677 dev_set_name(&op->dev, "root");
678 else 678 else
679 dev_set_name(&op->dev, "%08x", dp->node); 679 dev_set_name(&op->dev, "%08x", dp->phandle);
680 680
681 if (of_device_register(op)) { 681 if (of_device_register(op)) {
682 printk("%s: Could not register of device.\n", 682 printk("%s: Could not register of device.\n",
diff --git a/arch/sparc/kernel/prom_common.c b/arch/sparc/kernel/prom_common.c
index d80a65d9e893..5832e13dfeeb 100644
--- a/arch/sparc/kernel/prom_common.c
+++ b/arch/sparc/kernel/prom_common.c
@@ -42,7 +42,7 @@ struct device_node *of_find_node_by_phandle(phandle handle)
42 struct device_node *np; 42 struct device_node *np;
43 43
44 for (np = allnodes; np; np = np->allnext) 44 for (np = allnodes; np; np = np->allnext)
45 if (np->node == handle) 45 if (np->phandle == handle)
46 break; 46 break;
47 47
48 return np; 48 return np;
@@ -89,7 +89,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
89 void *old_val = prop->value; 89 void *old_val = prop->value;
90 int ret; 90 int ret;
91 91
92 ret = prom_setprop(dp->node, name, val, len); 92 ret = prom_setprop(dp->phandle, name, val, len);
93 93
94 err = -EINVAL; 94 err = -EINVAL;
95 if (ret >= 0) { 95 if (ret >= 0) {
@@ -236,7 +236,7 @@ static struct device_node * __init prom_create_node(phandle node,
236 236
237 dp->name = get_one_property(node, "name"); 237 dp->name = get_one_property(node, "name");
238 dp->type = get_one_property(node, "device_type"); 238 dp->type = get_one_property(node, "device_type");
239 dp->node = node; 239 dp->phandle = node;
240 240
241 dp->properties = build_prop_list(node); 241 dp->properties = build_prop_list(node);
242 242
@@ -313,7 +313,7 @@ void __init prom_build_devicetree(void)
313 313
314 nextp = &allnodes->allnext; 314 nextp = &allnodes->allnext;
315 allnodes->child = prom_build_tree(allnodes, 315 allnodes->child = prom_build_tree(allnodes,
316 prom_getchild(allnodes->node), 316 prom_getchild(allnodes->phandle),
317 &nextp); 317 &nextp);
318 of_console_init(); 318 of_console_init();
319 319
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index aa36223497b9..eb14844a0021 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -370,7 +370,7 @@ static int __cpuinit smp_boot_one_cpu(unsigned int cpu)
370 } else { 370 } else {
371 struct device_node *dp = of_find_node_by_cpuid(cpu); 371 struct device_node *dp = of_find_node_by_cpuid(cpu);
372 372
373 prom_startcpu(dp->node, entry, cookie); 373 prom_startcpu(dp->phandle, entry, cookie);
374 } 374 }
375 375
376 for (timeout = 0; timeout < 50000; timeout++) { 376 for (timeout = 0; timeout < 50000; timeout++) {
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index d2fa27c5c1b2..462825e03123 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -1,3 +1,7 @@
1config OF_FLATTREE
2 bool
3 depends on OF
4
1config OF_DEVICE 5config OF_DEVICE
2 def_bool y 6 def_bool y
3 depends on OF && (SPARC || PPC_OF || MICROBLAZE) 7 depends on OF && (SPARC || PPC_OF || MICROBLAZE)
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index bdfb5f5d4b06..f232cc98ce00 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -1,4 +1,5 @@
1obj-y = base.o 1obj-y = base.o
2obj-$(CONFIG_OF_FLATTREE) += fdt.o
2obj-$(CONFIG_OF_DEVICE) += device.o platform.o 3obj-$(CONFIG_OF_DEVICE) += device.o platform.o
3obj-$(CONFIG_OF_GPIO) += gpio.o 4obj-$(CONFIG_OF_GPIO) += gpio.o
4obj-$(CONFIG_OF_I2C) += of_i2c.o 5obj-$(CONFIG_OF_I2C) += of_i2c.o
diff --git a/drivers/of/base.c b/drivers/of/base.c
index e6627b2320f1..cf89ee6253f3 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -60,6 +60,81 @@ int of_n_size_cells(struct device_node *np)
60} 60}
61EXPORT_SYMBOL(of_n_size_cells); 61EXPORT_SYMBOL(of_n_size_cells);
62 62
63#if !defined(CONFIG_SPARC) /* SPARC doesn't do ref counting (yet) */
64/**
65 * of_node_get - Increment refcount of a node
66 * @node: Node to inc refcount, NULL is supported to
67 * simplify writing of callers
68 *
69 * Returns node.
70 */
71struct device_node *of_node_get(struct device_node *node)
72{
73 if (node)
74 kref_get(&node->kref);
75 return node;
76}
77EXPORT_SYMBOL(of_node_get);
78
79static inline struct device_node *kref_to_device_node(struct kref *kref)
80{
81 return container_of(kref, struct device_node, kref);
82}
83
84/**
85 * of_node_release - release a dynamically allocated node
86 * @kref: kref element of the node to be released
87 *
88 * In of_node_put() this function is passed to kref_put()
89 * as the destructor.
90 */
91static void of_node_release(struct kref *kref)
92{
93 struct device_node *node = kref_to_device_node(kref);
94 struct property *prop = node->properties;
95
96 /* We should never be releasing nodes that haven't been detached. */
97 if (!of_node_check_flag(node, OF_DETACHED)) {
98 pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name);
99 dump_stack();
100 kref_init(&node->kref);
101 return;
102 }
103
104 if (!of_node_check_flag(node, OF_DYNAMIC))
105 return;
106
107 while (prop) {
108 struct property *next = prop->next;
109 kfree(prop->name);
110 kfree(prop->value);
111 kfree(prop);
112 prop = next;
113
114 if (!prop) {
115 prop = node->deadprops;
116 node->deadprops = NULL;
117 }
118 }
119 kfree(node->full_name);
120 kfree(node->data);
121 kfree(node);
122}
123
124/**
125 * of_node_put - Decrement refcount of a node
126 * @node: Node to dec refcount, NULL is supported to
127 * simplify writing of callers
128 *
129 */
130void of_node_put(struct device_node *node)
131{
132 if (node)
133 kref_put(&node->kref, of_node_release);
134}
135EXPORT_SYMBOL(of_node_put);
136#endif /* !CONFIG_SPARC */
137
63struct property *of_find_property(const struct device_node *np, 138struct property *of_find_property(const struct device_node *np,
64 const char *name, 139 const char *name,
65 int *lenp) 140 int *lenp)
@@ -144,6 +219,27 @@ int of_device_is_compatible(const struct device_node *device,
144EXPORT_SYMBOL(of_device_is_compatible); 219EXPORT_SYMBOL(of_device_is_compatible);
145 220
146/** 221/**
222 * machine_is_compatible - Test root of device tree for a given compatible value
223 * @compat: compatible string to look for in root node's compatible property.
224 *
225 * Returns true if the root node has the given value in its
226 * compatible property.
227 */
228int machine_is_compatible(const char *compat)
229{
230 struct device_node *root;
231 int rc = 0;
232
233 root = of_find_node_by_path("/");
234 if (root) {
235 rc = of_device_is_compatible(root, compat);
236 of_node_put(root);
237 }
238 return rc;
239}
240EXPORT_SYMBOL(machine_is_compatible);
241
242/**
147 * of_device_is_available - check if a device is available for use 243 * of_device_is_available - check if a device is available for use
148 * 244 *
149 * @device: Node to check for availability 245 * @device: Node to check for availability
@@ -658,3 +754,119 @@ err0:
658 return ret; 754 return ret;
659} 755}
660EXPORT_SYMBOL(of_parse_phandles_with_args); 756EXPORT_SYMBOL(of_parse_phandles_with_args);
757
758/**
759 * prom_add_property - Add a property to a node
760 */
761int prom_add_property(struct device_node *np, struct property *prop)
762{
763 struct property **next;
764 unsigned long flags;
765
766 prop->next = NULL;
767 write_lock_irqsave(&devtree_lock, flags);
768 next = &np->properties;
769 while (*next) {
770 if (strcmp(prop->name, (*next)->name) == 0) {
771 /* duplicate ! don't insert it */
772 write_unlock_irqrestore(&devtree_lock, flags);
773 return -1;
774 }
775 next = &(*next)->next;
776 }
777 *next = prop;
778 write_unlock_irqrestore(&devtree_lock, flags);
779
780#ifdef CONFIG_PROC_DEVICETREE
781 /* try to add to proc as well if it was initialized */
782 if (np->pde)
783 proc_device_tree_add_prop(np->pde, prop);
784#endif /* CONFIG_PROC_DEVICETREE */
785
786 return 0;
787}
788
789/**
790 * prom_remove_property - Remove a property from a node.
791 *
792 * Note that we don't actually remove it, since we have given out
793 * who-knows-how-many pointers to the data using get-property.
794 * Instead we just move the property to the "dead properties"
795 * list, so it won't be found any more.
796 */
797int prom_remove_property(struct device_node *np, struct property *prop)
798{
799 struct property **next;
800 unsigned long flags;
801 int found = 0;
802
803 write_lock_irqsave(&devtree_lock, flags);
804 next = &np->properties;
805 while (*next) {
806 if (*next == prop) {
807 /* found the node */
808 *next = prop->next;
809 prop->next = np->deadprops;
810 np->deadprops = prop;
811 found = 1;
812 break;
813 }
814 next = &(*next)->next;
815 }
816 write_unlock_irqrestore(&devtree_lock, flags);
817
818 if (!found)
819 return -ENODEV;
820
821#ifdef CONFIG_PROC_DEVICETREE
822 /* try to remove the proc node as well */
823 if (np->pde)
824 proc_device_tree_remove_prop(np->pde, prop);
825#endif /* CONFIG_PROC_DEVICETREE */
826
827 return 0;
828}
829
830/*
831 * prom_update_property - Update a property in a node.
832 *
833 * Note that we don't actually remove it, since we have given out
834 * who-knows-how-many pointers to the data using get-property.
835 * Instead we just move the property to the "dead properties" list,
836 * and add the new property to the property list
837 */
838int prom_update_property(struct device_node *np,
839 struct property *newprop,
840 struct property *oldprop)
841{
842 struct property **next;
843 unsigned long flags;
844 int found = 0;
845
846 write_lock_irqsave(&devtree_lock, flags);
847 next = &np->properties;
848 while (*next) {
849 if (*next == oldprop) {
850 /* found the node */
851 newprop->next = oldprop->next;
852 *next = newprop;
853 oldprop->next = np->deadprops;
854 np->deadprops = oldprop;
855 found = 1;
856 break;
857 }
858 next = &(*next)->next;
859 }
860 write_unlock_irqrestore(&devtree_lock, flags);
861
862 if (!found)
863 return -ENODEV;
864
865#ifdef CONFIG_PROC_DEVICETREE
866 /* try to add to proc as well if it was initialized */
867 if (np->pde)
868 proc_device_tree_update_prop(np->pde, newprop, oldprop);
869#endif /* CONFIG_PROC_DEVICETREE */
870
871 return 0;
872}
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
new file mode 100644
index 000000000000..7f8861121a31
--- /dev/null
+++ b/drivers/of/fdt.c
@@ -0,0 +1,528 @@
1/*
2 * Functions for working with the Flattened Device Tree data format
3 *
4 * Copyright 2009 Benjamin Herrenschmidt, IBM Corp
5 * benh@kernel.crashing.org
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
10 */
11
12#include <linux/kernel.h>
13#include <linux/lmb.h>
14#include <linux/initrd.h>
15#include <linux/of.h>
16#include <linux/of_fdt.h>
17
18#ifdef CONFIG_PPC
19#include <asm/machdep.h>
20#endif /* CONFIG_PPC */
21
22int __initdata dt_root_addr_cells;
23int __initdata dt_root_size_cells;
24
25struct boot_param_header *initial_boot_params;
26
27char *find_flat_dt_string(u32 offset)
28{
29 return ((char *)initial_boot_params) +
30 initial_boot_params->off_dt_strings + offset;
31}
32
33/**
34 * of_scan_flat_dt - scan flattened tree blob and call callback on each.
35 * @it: callback function
36 * @data: context data pointer
37 *
38 * This function is used to scan the flattened device-tree, it is
39 * used to extract the memory information at boot before we can
40 * unflatten the tree
41 */
42int __init of_scan_flat_dt(int (*it)(unsigned long node,
43 const char *uname, int depth,
44 void *data),
45 void *data)
46{
47 unsigned long p = ((unsigned long)initial_boot_params) +
48 initial_boot_params->off_dt_struct;
49 int rc = 0;
50 int depth = -1;
51
52 do {
53 u32 tag = *((u32 *)p);
54 char *pathp;
55
56 p += 4;
57 if (tag == OF_DT_END_NODE) {
58 depth--;
59 continue;
60 }
61 if (tag == OF_DT_NOP)
62 continue;
63 if (tag == OF_DT_END)
64 break;
65 if (tag == OF_DT_PROP) {
66 u32 sz = *((u32 *)p);
67 p += 8;
68 if (initial_boot_params->version < 0x10)
69 p = _ALIGN(p, sz >= 8 ? 8 : 4);
70 p += sz;
71 p = _ALIGN(p, 4);
72 continue;
73 }
74 if (tag != OF_DT_BEGIN_NODE) {
75 pr_err("Invalid tag %x in flat device tree!\n", tag);
76 return -EINVAL;
77 }
78 depth++;
79 pathp = (char *)p;
80 p = _ALIGN(p + strlen(pathp) + 1, 4);
81 if ((*pathp) == '/') {
82 char *lp, *np;
83 for (lp = NULL, np = pathp; *np; np++)
84 if ((*np) == '/')
85 lp = np+1;
86 if (lp != NULL)
87 pathp = lp;
88 }
89 rc = it(p, pathp, depth, data);
90 if (rc != 0)
91 break;
92 } while (1);
93
94 return rc;
95}
96
97/**
98 * of_get_flat_dt_root - find the root node in the flat blob
99 */
100unsigned long __init of_get_flat_dt_root(void)
101{
102 unsigned long p = ((unsigned long)initial_boot_params) +
103 initial_boot_params->off_dt_struct;
104
105 while (*((u32 *)p) == OF_DT_NOP)
106 p += 4;
107 BUG_ON(*((u32 *)p) != OF_DT_BEGIN_NODE);
108 p += 4;
109 return _ALIGN(p + strlen((char *)p) + 1, 4);
110}
111
112/**
113 * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr
114 *
115 * This function can be used within scan_flattened_dt callback to get
116 * access to properties
117 */
118void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
119 unsigned long *size)
120{
121 unsigned long p = node;
122
123 do {
124 u32 tag = *((u32 *)p);
125 u32 sz, noff;
126 const char *nstr;
127
128 p += 4;
129 if (tag == OF_DT_NOP)
130 continue;
131 if (tag != OF_DT_PROP)
132 return NULL;
133
134 sz = *((u32 *)p);
135 noff = *((u32 *)(p + 4));
136 p += 8;
137 if (initial_boot_params->version < 0x10)
138 p = _ALIGN(p, sz >= 8 ? 8 : 4);
139
140 nstr = find_flat_dt_string(noff);
141 if (nstr == NULL) {
142 pr_warning("Can't find property index name !\n");
143 return NULL;
144 }
145 if (strcmp(name, nstr) == 0) {
146 if (size)
147 *size = sz;
148 return (void *)p;
149 }
150 p += sz;
151 p = _ALIGN(p, 4);
152 } while (1);
153}
154
155/**
156 * of_flat_dt_is_compatible - Return true if given node has compat in compatible list
157 * @node: node to test
158 * @compat: compatible string to compare with compatible list.
159 */
160int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
161{
162 const char *cp;
163 unsigned long cplen, l;
164
165 cp = of_get_flat_dt_prop(node, "compatible", &cplen);
166 if (cp == NULL)
167 return 0;
168 while (cplen > 0) {
169 if (strncasecmp(cp, compat, strlen(compat)) == 0)
170 return 1;
171 l = strlen(cp) + 1;
172 cp += l;
173 cplen -= l;
174 }
175
176 return 0;
177}
178
179static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
180 unsigned long align)
181{
182 void *res;
183
184 *mem = _ALIGN(*mem, align);
185 res = (void *)*mem;
186 *mem += size;
187
188 return res;
189}
190
191/**
192 * unflatten_dt_node - Alloc and populate a device_node from the flat tree
193 * @p: pointer to node in flat tree
194 * @dad: Parent struct device_node
195 * @allnextpp: pointer to ->allnext from last allocated device_node
196 * @fpsize: Size of the node path up at the current depth.
197 */
198unsigned long __init unflatten_dt_node(unsigned long mem,
199 unsigned long *p,
200 struct device_node *dad,
201 struct device_node ***allnextpp,
202 unsigned long fpsize)
203{
204 struct device_node *np;
205 struct property *pp, **prev_pp = NULL;
206 char *pathp;
207 u32 tag;
208 unsigned int l, allocl;
209 int has_name = 0;
210 int new_format = 0;
211
212 tag = *((u32 *)(*p));
213 if (tag != OF_DT_BEGIN_NODE) {
214 pr_err("Weird tag at start of node: %x\n", tag);
215 return mem;
216 }
217 *p += 4;
218 pathp = (char *)*p;
219 l = allocl = strlen(pathp) + 1;
220 *p = _ALIGN(*p + l, 4);
221
222 /* version 0x10 has a more compact unit name here instead of the full
223 * path. we accumulate the full path size using "fpsize", we'll rebuild
224 * it later. We detect this because the first character of the name is
225 * not '/'.
226 */
227 if ((*pathp) != '/') {
228 new_format = 1;
229 if (fpsize == 0) {
230 /* root node: special case. fpsize accounts for path
231 * plus terminating zero. root node only has '/', so
232 * fpsize should be 2, but we want to avoid the first
233 * level nodes to have two '/' so we use fpsize 1 here
234 */
235 fpsize = 1;
236 allocl = 2;
237 } else {
238 /* account for '/' and path size minus terminal 0
239 * already in 'l'
240 */
241 fpsize += l;
242 allocl = fpsize;
243 }
244 }
245
246 np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
247 __alignof__(struct device_node));
248 if (allnextpp) {
249 memset(np, 0, sizeof(*np));
250 np->full_name = ((char *)np) + sizeof(struct device_node);
251 if (new_format) {
252 char *fn = np->full_name;
253 /* rebuild full path for new format */
254 if (dad && dad->parent) {
255 strcpy(fn, dad->full_name);
256#ifdef DEBUG
257 if ((strlen(fn) + l + 1) != allocl) {
258 pr_debug("%s: p: %d, l: %d, a: %d\n",
259 pathp, (int)strlen(fn),
260 l, allocl);
261 }
262#endif
263 fn += strlen(fn);
264 }
265 *(fn++) = '/';
266 memcpy(fn, pathp, l);
267 } else
268 memcpy(np->full_name, pathp, l);
269 prev_pp = &np->properties;
270 **allnextpp = np;
271 *allnextpp = &np->allnext;
272 if (dad != NULL) {
273 np->parent = dad;
274 /* we temporarily use the next field as `last_child'*/
275 if (dad->next == NULL)
276 dad->child = np;
277 else
278 dad->next->sibling = np;
279 dad->next = np;
280 }
281 kref_init(&np->kref);
282 }
283 while (1) {
284 u32 sz, noff;
285 char *pname;
286
287 tag = *((u32 *)(*p));
288 if (tag == OF_DT_NOP) {
289 *p += 4;
290 continue;
291 }
292 if (tag != OF_DT_PROP)
293 break;
294 *p += 4;
295 sz = *((u32 *)(*p));
296 noff = *((u32 *)((*p) + 4));
297 *p += 8;
298 if (initial_boot_params->version < 0x10)
299 *p = _ALIGN(*p, sz >= 8 ? 8 : 4);
300
301 pname = find_flat_dt_string(noff);
302 if (pname == NULL) {
303 pr_info("Can't find property name in list !\n");
304 break;
305 }
306 if (strcmp(pname, "name") == 0)
307 has_name = 1;
308 l = strlen(pname) + 1;
309 pp = unflatten_dt_alloc(&mem, sizeof(struct property),
310 __alignof__(struct property));
311 if (allnextpp) {
312 if (strcmp(pname, "linux,phandle") == 0) {
313 if (np->phandle == 0)
314 np->phandle = *((u32 *)*p);
315 }
316 if (strcmp(pname, "ibm,phandle") == 0)
317 np->phandle = *((u32 *)*p);
318 pp->name = pname;
319 pp->length = sz;
320 pp->value = (void *)*p;
321 *prev_pp = pp;
322 prev_pp = &pp->next;
323 }
324 *p = _ALIGN((*p) + sz, 4);
325 }
326 /* with version 0x10 we may not have the name property, recreate
327 * it here from the unit name if absent
328 */
329 if (!has_name) {
330 char *p1 = pathp, *ps = pathp, *pa = NULL;
331 int sz;
332
333 while (*p1) {
334 if ((*p1) == '@')
335 pa = p1;
336 if ((*p1) == '/')
337 ps = p1 + 1;
338 p1++;
339 }
340 if (pa < ps)
341 pa = p1;
342 sz = (pa - ps) + 1;
343 pp = unflatten_dt_alloc(&mem, sizeof(struct property) + sz,
344 __alignof__(struct property));
345 if (allnextpp) {
346 pp->name = "name";
347 pp->length = sz;
348 pp->value = pp + 1;
349 *prev_pp = pp;
350 prev_pp = &pp->next;
351 memcpy(pp->value, ps, sz - 1);
352 ((char *)pp->value)[sz - 1] = 0;
353 pr_debug("fixed up name for %s -> %s\n", pathp,
354 (char *)pp->value);
355 }
356 }
357 if (allnextpp) {
358 *prev_pp = NULL;
359 np->name = of_get_property(np, "name", NULL);
360 np->type = of_get_property(np, "device_type", NULL);
361
362 if (!np->name)
363 np->name = "<NULL>";
364 if (!np->type)
365 np->type = "<NULL>";
366 }
367 while (tag == OF_DT_BEGIN_NODE) {
368 mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize);
369 tag = *((u32 *)(*p));
370 }
371 if (tag != OF_DT_END_NODE) {
372 pr_err("Weird tag at end of node: %x\n", tag);
373 return mem;
374 }
375 *p += 4;
376 return mem;
377}
378
379#ifdef CONFIG_BLK_DEV_INITRD
380/**
381 * early_init_dt_check_for_initrd - Decode initrd location from flat tree
382 * @node: reference to node containing initrd location ('chosen')
383 */
384void __init early_init_dt_check_for_initrd(unsigned long node)
385{
386 unsigned long len;
387 u32 *prop;
388
389 pr_debug("Looking for initrd properties... ");
390
391 prop = of_get_flat_dt_prop(node, "linux,initrd-start", &len);
392 if (prop) {
393 initrd_start = (unsigned long)
394 __va(of_read_ulong(prop, len/4));
395
396 prop = of_get_flat_dt_prop(node, "linux,initrd-end", &len);
397 if (prop) {
398 initrd_end = (unsigned long)
399 __va(of_read_ulong(prop, len/4));
400 initrd_below_start_ok = 1;
401 } else {
402 initrd_start = 0;
403 }
404 }
405
406 pr_debug("initrd_start=0x%lx initrd_end=0x%lx\n",
407 initrd_start, initrd_end);
408}
409#else
410inline void early_init_dt_check_for_initrd(unsigned long node)
411{
412}
413#endif /* CONFIG_BLK_DEV_INITRD */
414
415/**
416 * early_init_dt_scan_root - fetch the top level address and size cells
417 */
418int __init early_init_dt_scan_root(unsigned long node, const char *uname,
419 int depth, void *data)
420{
421 u32 *prop;
422
423 if (depth != 0)
424 return 0;
425
426 prop = of_get_flat_dt_prop(node, "#size-cells", NULL);
427 dt_root_size_cells = (prop == NULL) ? 1 : *prop;
428 pr_debug("dt_root_size_cells = %x\n", dt_root_size_cells);
429
430 prop = of_get_flat_dt_prop(node, "#address-cells", NULL);
431 dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
432 pr_debug("dt_root_addr_cells = %x\n", dt_root_addr_cells);
433
434 /* break now */
435 return 1;
436}
437
438u64 __init dt_mem_next_cell(int s, u32 **cellp)
439{
440 u32 *p = *cellp;
441
442 *cellp = p + s;
443 return of_read_number(p, s);
444}
445
446int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
447 int depth, void *data)
448{
449 unsigned long l;
450 char *p;
451
452 pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
453
454 if (depth != 1 ||
455 (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
456 return 0;
457
458 early_init_dt_check_for_initrd(node);
459
460 /* Retreive command line */
461 p = of_get_flat_dt_prop(node, "bootargs", &l);
462 if (p != NULL && l > 0)
463 strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE));
464
465#ifdef CONFIG_CMDLINE
466#ifndef CONFIG_CMDLINE_FORCE
467 if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
468#endif
469 strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
470#endif /* CONFIG_CMDLINE */
471
472 early_init_dt_scan_chosen_arch(node);
473
474 pr_debug("Command line is: %s\n", cmd_line);
475
476 /* break now */
477 return 1;
478}
479
480/**
481 * unflatten_device_tree - create tree of device_nodes from flat blob
482 *
483 * unflattens the device-tree passed by the firmware, creating the
484 * tree of struct device_node. It also fills the "name" and "type"
485 * pointers of the nodes so the normal device-tree walking functions
486 * can be used.
487 */
488void __init unflatten_device_tree(void)
489{
490 unsigned long start, mem, size;
491 struct device_node **allnextp = &allnodes;
492
493 pr_debug(" -> unflatten_device_tree()\n");
494
495 /* First pass, scan for size */
496 start = ((unsigned long)initial_boot_params) +
497 initial_boot_params->off_dt_struct;
498 size = unflatten_dt_node(0, &start, NULL, NULL, 0);
499 size = (size | 3) + 1;
500
501 pr_debug(" size is %lx, allocating...\n", size);
502
503 /* Allocate memory for the expanded device tree */
504 mem = lmb_alloc(size + 4, __alignof__(struct device_node));
505 mem = (unsigned long) __va(mem);
506
507 ((u32 *)mem)[size / 4] = 0xdeadbeef;
508
509 pr_debug(" unflattening %lx...\n", mem);
510
511 /* Second pass, do actual unflattening */
512 start = ((unsigned long)initial_boot_params) +
513 initial_boot_params->off_dt_struct;
514 unflatten_dt_node(mem, &start, NULL, &allnextp, 0);
515 if (*((u32 *)start) != OF_DT_END)
516 pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start));
517 if (((u32 *)mem)[size / 4] != 0xdeadbeef)
518 pr_warning("End of tree marker overwritten: %08x\n",
519 ((u32 *)mem)[size / 4]);
520 *allnextp = NULL;
521
522 /* Get pointer to OF "/chosen" node for use everywhere */
523 of_chosen = of_find_node_by_path("/chosen");
524 if (of_chosen == NULL)
525 of_chosen = of_find_node_by_path("/chosen@0");
526
527 pr_debug(" <- unflatten_device_tree()\n");
528}
diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c
index 75ac19b1192f..fc2f676e984d 100644
--- a/drivers/sbus/char/openprom.c
+++ b/drivers/sbus/char/openprom.c
@@ -233,7 +233,7 @@ static int opromnext(void __user *argp, unsigned int cmd, struct device_node *dp
233 233
234 ph = 0; 234 ph = 0;
235 if (dp) 235 if (dp)
236 ph = dp->node; 236 ph = dp->phandle;
237 237
238 data->current_node = dp; 238 data->current_node = dp;
239 *((int *) op->oprom_array) = ph; 239 *((int *) op->oprom_array) = ph;
@@ -256,7 +256,7 @@ static int oprompci2node(void __user *argp, struct device_node *dp, struct openp
256 256
257 dp = pci_device_to_OF_node(pdev); 257 dp = pci_device_to_OF_node(pdev);
258 data->current_node = dp; 258 data->current_node = dp;
259 *((int *)op->oprom_array) = dp->node; 259 *((int *)op->oprom_array) = dp->phandle;
260 op->oprom_size = sizeof(int); 260 op->oprom_size = sizeof(int);
261 err = copyout(argp, op, bufsize + sizeof(int)); 261 err = copyout(argp, op, bufsize + sizeof(int));
262 262
@@ -273,7 +273,7 @@ static int oprompath2node(void __user *argp, struct device_node *dp, struct open
273 273
274 dp = of_find_node_by_path(op->oprom_array); 274 dp = of_find_node_by_path(op->oprom_array);
275 if (dp) 275 if (dp)
276 ph = dp->node; 276 ph = dp->phandle;
277 data->current_node = dp; 277 data->current_node = dp;
278 *((int *)op->oprom_array) = ph; 278 *((int *)op->oprom_array) = ph;
279 op->oprom_size = sizeof(int); 279 op->oprom_size = sizeof(int);
@@ -540,7 +540,7 @@ static int opiocgetnext(unsigned int cmd, void __user *argp)
540 } 540 }
541 } 541 }
542 if (dp) 542 if (dp)
543 nd = dp->node; 543 nd = dp->phandle;
544 if (copy_to_user(argp, &nd, sizeof(phandle))) 544 if (copy_to_user(argp, &nd, sizeof(phandle)))
545 return -EFAULT; 545 return -EFAULT;
546 546
@@ -570,7 +570,7 @@ static int openprom_bsd_ioctl(struct inode * inode, struct file * file,
570 case OPIOCGETOPTNODE: 570 case OPIOCGETOPTNODE:
571 BUILD_BUG_ON(sizeof(phandle) != sizeof(int)); 571 BUILD_BUG_ON(sizeof(phandle) != sizeof(int));
572 572
573 if (copy_to_user(argp, &options_node->node, sizeof(phandle))) 573 if (copy_to_user(argp, &options_node->phandle, sizeof(phandle)))
574 return -EFAULT; 574 return -EFAULT;
575 575
576 return 0; 576 return 0;
diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
index 1ddeb4c34763..5f1b5807a48f 100644
--- a/drivers/video/aty/atyfb_base.c
+++ b/drivers/video/aty/atyfb_base.c
@@ -3104,7 +3104,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev,
3104 } 3104 }
3105 3105
3106 dp = pci_device_to_OF_node(pdev); 3106 dp = pci_device_to_OF_node(pdev);
3107 if (node == dp->node) { 3107 if (node == dp->phandle) {
3108 struct fb_var_screeninfo *var = &default_var; 3108 struct fb_var_screeninfo *var = &default_var;
3109 unsigned int N, P, Q, M, T, R; 3109 unsigned int N, P, Q, M, T, R;
3110 u32 v_total, h_total; 3110 u32 v_total, h_total;
diff --git a/include/linux/of.h b/include/linux/of.h
index e7facd8fbce8..dbabf86e0b7a 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -39,10 +39,7 @@ struct of_irq_controller;
39struct device_node { 39struct device_node {
40 const char *name; 40 const char *name;
41 const char *type; 41 const char *type;
42 phandle node; 42 phandle phandle;
43#if !defined(CONFIG_SPARC)
44 phandle linux_phandle;
45#endif
46 char *full_name; 43 char *full_name;
47 44
48 struct property *properties; 45 struct property *properties;
@@ -63,6 +60,9 @@ struct device_node {
63#endif 60#endif
64}; 61};
65 62
63/* Pointer for first entry in chain of all nodes. */
64extern struct device_node *allnodes;
65
66static inline int of_node_check_flag(struct device_node *n, unsigned long flag) 66static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
67{ 67{
68 return test_bit(flag, &n->_flags); 68 return test_bit(flag, &n->_flags);
@@ -110,14 +110,11 @@ static inline u64 of_read_number(const u32 *cell, int size)
110} 110}
111 111
112/* Like of_read_number, but we want an unsigned long result */ 112/* Like of_read_number, but we want an unsigned long result */
113#ifdef CONFIG_PPC32
114static inline unsigned long of_read_ulong(const u32 *cell, int size) 113static inline unsigned long of_read_ulong(const u32 *cell, int size)
115{ 114{
116 return cell[size-1]; 115 /* toss away upper bits if unsigned long is smaller than u64 */
116 return of_read_number(cell, size);
117} 117}
118#else
119#define of_read_ulong(cell, size) of_read_number(cell, size)
120#endif
121 118
122#include <asm/prom.h> 119#include <asm/prom.h>
123 120
diff --git a/include/linux/of_fdt.h b/include/linux/of_fdt.h
index 41d432b13553..8118d4559dd5 100644
--- a/include/linux/of_fdt.h
+++ b/include/linux/of_fdt.h
@@ -57,16 +57,29 @@ struct boot_param_header {
57 u32 dt_struct_size; /* size of the DT structure block */ 57 u32 dt_struct_size; /* size of the DT structure block */
58}; 58};
59 59
60/* TBD: Temporary export of fdt globals - remove when code fully merged */
61extern int __initdata dt_root_addr_cells;
62extern int __initdata dt_root_size_cells;
63extern struct boot_param_header *initial_boot_params;
64
60/* For scanning the flat device-tree at boot time */ 65/* For scanning the flat device-tree at boot time */
61extern int __init of_scan_flat_dt(int (*it)(unsigned long node, 66extern char *find_flat_dt_string(u32 offset);
62 const char *uname, int depth, 67extern int of_scan_flat_dt(int (*it)(unsigned long node, const char *uname,
63 void *data), 68 int depth, void *data),
64 void *data); 69 void *data);
65extern void __init *of_get_flat_dt_prop(unsigned long node, const char *name, 70extern void *of_get_flat_dt_prop(unsigned long node, const char *name,
66 unsigned long *size); 71 unsigned long *size);
67extern int __init of_flat_dt_is_compatible(unsigned long node, 72extern int of_flat_dt_is_compatible(unsigned long node, const char *name);
68 const char *name); 73extern unsigned long of_get_flat_dt_root(void);
69extern unsigned long __init of_get_flat_dt_root(void); 74extern void early_init_dt_scan_chosen_arch(unsigned long node);
75extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,
76 int depth, void *data);
77extern void early_init_dt_check_for_initrd(unsigned long node);
78extern u64 dt_mem_next_cell(int s, u32 **cellp);
79
80/* Early flat tree scan hooks */
81extern int early_init_dt_scan_root(unsigned long node, const char *uname,
82 int depth, void *data);
70 83
71/* Other Prototypes */ 84/* Other Prototypes */
72extern void finish_device_tree(void); 85extern void finish_device_tree(void);
diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c
index 586965f9605f..7a437da05646 100644
--- a/sound/aoa/fabrics/layout.c
+++ b/sound/aoa/fabrics/layout.c
@@ -768,7 +768,7 @@ static int check_codec(struct aoa_codec *codec,
768 "required property %s not present\n", propname); 768 "required property %s not present\n", propname);
769 return -ENODEV; 769 return -ENODEV;
770 } 770 }
771 if (*ref != codec->node->linux_phandle) { 771 if (*ref != codec->node->phandle) {
772 printk(KERN_INFO "snd-aoa-fabric-layout: " 772 printk(KERN_INFO "snd-aoa-fabric-layout: "
773 "%s doesn't match!\n", propname); 773 "%s doesn't match!\n", propname);
774 return -ENODEV; 774 return -ENODEV;