aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/of/fdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/of/fdt.c')
-rw-r--r--drivers/of/fdt.c438
1 files changed, 273 insertions, 165 deletions
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 65da5aec7552..65200af29c52 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -11,10 +11,12 @@
11 11
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/initrd.h> 13#include <linux/initrd.h>
14#include <linux/module.h>
14#include <linux/of.h> 15#include <linux/of.h>
15#include <linux/of_fdt.h> 16#include <linux/of_fdt.h>
16#include <linux/string.h> 17#include <linux/string.h>
17#include <linux/errno.h> 18#include <linux/errno.h>
19#include <linux/slab.h>
18 20
19#ifdef CONFIG_PPC 21#ifdef CONFIG_PPC
20#include <asm/machdep.h> 22#include <asm/machdep.h>
@@ -22,104 +24,19 @@
22 24
23#include <asm/page.h> 25#include <asm/page.h>
24 26
25int __initdata dt_root_addr_cells; 27char *of_fdt_get_string(struct boot_param_header *blob, u32 offset)
26int __initdata dt_root_size_cells;
27
28struct boot_param_header *initial_boot_params;
29
30char *find_flat_dt_string(u32 offset)
31{ 28{
32 return ((char *)initial_boot_params) + 29 return ((char *)blob) +
33 be32_to_cpu(initial_boot_params->off_dt_strings) + offset; 30 be32_to_cpu(blob->off_dt_strings) + offset;
34}
35
36/**
37 * of_scan_flat_dt - scan flattened tree blob and call callback on each.
38 * @it: callback function
39 * @data: context data pointer
40 *
41 * This function is used to scan the flattened device-tree, it is
42 * used to extract the memory information at boot before we can
43 * unflatten the tree
44 */
45int __init of_scan_flat_dt(int (*it)(unsigned long node,
46 const char *uname, int depth,
47 void *data),
48 void *data)
49{
50 unsigned long p = ((unsigned long)initial_boot_params) +
51 be32_to_cpu(initial_boot_params->off_dt_struct);
52 int rc = 0;
53 int depth = -1;
54
55 do {
56 u32 tag = be32_to_cpup((__be32 *)p);
57 char *pathp;
58
59 p += 4;
60 if (tag == OF_DT_END_NODE) {
61 depth--;
62 continue;
63 }
64 if (tag == OF_DT_NOP)
65 continue;
66 if (tag == OF_DT_END)
67 break;
68 if (tag == OF_DT_PROP) {
69 u32 sz = be32_to_cpup((__be32 *)p);
70 p += 8;
71 if (be32_to_cpu(initial_boot_params->version) < 0x10)
72 p = ALIGN(p, sz >= 8 ? 8 : 4);
73 p += sz;
74 p = ALIGN(p, 4);
75 continue;
76 }
77 if (tag != OF_DT_BEGIN_NODE) {
78 pr_err("Invalid tag %x in flat device tree!\n", tag);
79 return -EINVAL;
80 }
81 depth++;
82 pathp = (char *)p;
83 p = ALIGN(p + strlen(pathp) + 1, 4);
84 if ((*pathp) == '/') {
85 char *lp, *np;
86 for (lp = NULL, np = pathp; *np; np++)
87 if ((*np) == '/')
88 lp = np+1;
89 if (lp != NULL)
90 pathp = lp;
91 }
92 rc = it(p, pathp, depth, data);
93 if (rc != 0)
94 break;
95 } while (1);
96
97 return rc;
98}
99
100/**
101 * of_get_flat_dt_root - find the root node in the flat blob
102 */
103unsigned long __init of_get_flat_dt_root(void)
104{
105 unsigned long p = ((unsigned long)initial_boot_params) +
106 be32_to_cpu(initial_boot_params->off_dt_struct);
107
108 while (be32_to_cpup((__be32 *)p) == OF_DT_NOP)
109 p += 4;
110 BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE);
111 p += 4;
112 return ALIGN(p + strlen((char *)p) + 1, 4);
113} 31}
114 32
115/** 33/**
116 * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr 34 * of_fdt_get_property - Given a node in the given flat blob, return
117 * 35 * the property ptr
118 * This function can be used within scan_flattened_dt callback to get
119 * access to properties
120 */ 36 */
121void *__init of_get_flat_dt_prop(unsigned long node, const char *name, 37void *of_fdt_get_property(struct boot_param_header *blob,
122 unsigned long *size) 38 unsigned long node, const char *name,
39 unsigned long *size)
123{ 40{
124 unsigned long p = node; 41 unsigned long p = node;
125 42
@@ -137,10 +54,10 @@ void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
137 sz = be32_to_cpup((__be32 *)p); 54 sz = be32_to_cpup((__be32 *)p);
138 noff = be32_to_cpup((__be32 *)(p + 4)); 55 noff = be32_to_cpup((__be32 *)(p + 4));
139 p += 8; 56 p += 8;
140 if (be32_to_cpu(initial_boot_params->version) < 0x10) 57 if (be32_to_cpu(blob->version) < 0x10)
141 p = ALIGN(p, sz >= 8 ? 8 : 4); 58 p = ALIGN(p, sz >= 8 ? 8 : 4);
142 59
143 nstr = find_flat_dt_string(noff); 60 nstr = of_fdt_get_string(blob, noff);
144 if (nstr == NULL) { 61 if (nstr == NULL) {
145 pr_warning("Can't find property index name !\n"); 62 pr_warning("Can't find property index name !\n");
146 return NULL; 63 return NULL;
@@ -156,21 +73,28 @@ void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
156} 73}
157 74
158/** 75/**
159 * of_flat_dt_is_compatible - Return true if given node has compat in compatible list 76 * of_fdt_is_compatible - Return true if given node from the given blob has
77 * compat in its compatible list
78 * @blob: A device tree blob
160 * @node: node to test 79 * @node: node to test
161 * @compat: compatible string to compare with compatible list. 80 * @compat: compatible string to compare with compatible list.
81 *
82 * On match, returns a non-zero value with smaller values returned for more
83 * specific compatible values.
162 */ 84 */
163int __init of_flat_dt_is_compatible(unsigned long node, const char *compat) 85int of_fdt_is_compatible(struct boot_param_header *blob,
86 unsigned long node, const char *compat)
164{ 87{
165 const char *cp; 88 const char *cp;
166 unsigned long cplen, l; 89 unsigned long cplen, l, score = 0;
167 90
168 cp = of_get_flat_dt_prop(node, "compatible", &cplen); 91 cp = of_fdt_get_property(blob, node, "compatible", &cplen);
169 if (cp == NULL) 92 if (cp == NULL)
170 return 0; 93 return 0;
171 while (cplen > 0) { 94 while (cplen > 0) {
95 score++;
172 if (of_compat_cmp(cp, compat, strlen(compat)) == 0) 96 if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
173 return 1; 97 return score;
174 l = strlen(cp) + 1; 98 l = strlen(cp) + 1;
175 cp += l; 99 cp += l;
176 cplen -= l; 100 cplen -= l;
@@ -179,7 +103,28 @@ int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
179 return 0; 103 return 0;
180} 104}
181 105
182static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size, 106/**
107 * of_fdt_match - Return true if node matches a list of compatible values
108 */
109int of_fdt_match(struct boot_param_header *blob, unsigned long node,
110 const char **compat)
111{
112 unsigned int tmp, score = 0;
113
114 if (!compat)
115 return 0;
116
117 while (*compat) {
118 tmp = of_fdt_is_compatible(blob, node, *compat);
119 if (tmp && (score == 0 || (tmp < score)))
120 score = tmp;
121 compat++;
122 }
123
124 return score;
125}
126
127static void *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
183 unsigned long align) 128 unsigned long align)
184{ 129{
185 void *res; 130 void *res;
@@ -193,16 +138,19 @@ static void *__init unflatten_dt_alloc(unsigned long *mem, unsigned long size,
193 138
194/** 139/**
195 * unflatten_dt_node - Alloc and populate a device_node from the flat tree 140 * unflatten_dt_node - Alloc and populate a device_node from the flat tree
141 * @blob: The parent device tree blob
142 * @mem: Memory chunk to use for allocating device nodes and properties
196 * @p: pointer to node in flat tree 143 * @p: pointer to node in flat tree
197 * @dad: Parent struct device_node 144 * @dad: Parent struct device_node
198 * @allnextpp: pointer to ->allnext from last allocated device_node 145 * @allnextpp: pointer to ->allnext from last allocated device_node
199 * @fpsize: Size of the node path up at the current depth. 146 * @fpsize: Size of the node path up at the current depth.
200 */ 147 */
201unsigned long __init unflatten_dt_node(unsigned long mem, 148static unsigned long unflatten_dt_node(struct boot_param_header *blob,
202 unsigned long *p, 149 unsigned long mem,
203 struct device_node *dad, 150 unsigned long *p,
204 struct device_node ***allnextpp, 151 struct device_node *dad,
205 unsigned long fpsize) 152 struct device_node ***allnextpp,
153 unsigned long fpsize)
206{ 154{
207 struct device_node *np; 155 struct device_node *np;
208 struct property *pp, **prev_pp = NULL; 156 struct property *pp, **prev_pp = NULL;
@@ -283,6 +231,7 @@ unsigned long __init unflatten_dt_node(unsigned long mem,
283 } 231 }
284 kref_init(&np->kref); 232 kref_init(&np->kref);
285 } 233 }
234 /* process properties */
286 while (1) { 235 while (1) {
287 u32 sz, noff; 236 u32 sz, noff;
288 char *pname; 237 char *pname;
@@ -298,10 +247,10 @@ unsigned long __init unflatten_dt_node(unsigned long mem,
298 sz = be32_to_cpup((__be32 *)(*p)); 247 sz = be32_to_cpup((__be32 *)(*p));
299 noff = be32_to_cpup((__be32 *)((*p) + 4)); 248 noff = be32_to_cpup((__be32 *)((*p) + 4));
300 *p += 8; 249 *p += 8;
301 if (be32_to_cpu(initial_boot_params->version) < 0x10) 250 if (be32_to_cpu(blob->version) < 0x10)
302 *p = ALIGN(*p, sz >= 8 ? 8 : 4); 251 *p = ALIGN(*p, sz >= 8 ? 8 : 4);
303 252
304 pname = find_flat_dt_string(noff); 253 pname = of_fdt_get_string(blob, noff);
305 if (pname == NULL) { 254 if (pname == NULL) {
306 pr_info("Can't find property name in list !\n"); 255 pr_info("Can't find property name in list !\n");
307 break; 256 break;
@@ -380,7 +329,8 @@ unsigned long __init unflatten_dt_node(unsigned long mem,
380 if (tag == OF_DT_NOP) 329 if (tag == OF_DT_NOP)
381 *p += 4; 330 *p += 4;
382 else 331 else
383 mem = unflatten_dt_node(mem, p, np, allnextpp, fpsize); 332 mem = unflatten_dt_node(blob, mem, p, np, allnextpp,
333 fpsize);
384 tag = be32_to_cpup((__be32 *)(*p)); 334 tag = be32_to_cpup((__be32 *)(*p));
385 } 335 }
386 if (tag != OF_DT_END_NODE) { 336 if (tag != OF_DT_END_NODE) {
@@ -391,6 +341,211 @@ unsigned long __init unflatten_dt_node(unsigned long mem,
391 return mem; 341 return mem;
392} 342}
393 343
344/**
345 * __unflatten_device_tree - create tree of device_nodes from flat blob
346 *
347 * unflattens a device-tree, creating the
348 * tree of struct device_node. It also fills the "name" and "type"
349 * pointers of the nodes so the normal device-tree walking functions
350 * can be used.
351 * @blob: The blob to expand
352 * @mynodes: The device_node tree created by the call
353 * @dt_alloc: An allocator that provides a virtual address to memory
354 * for the resulting tree
355 */
356static void __unflatten_device_tree(struct boot_param_header *blob,
357 struct device_node **mynodes,
358 void * (*dt_alloc)(u64 size, u64 align))
359{
360 unsigned long start, mem, size;
361 struct device_node **allnextp = mynodes;
362
363 pr_debug(" -> unflatten_device_tree()\n");
364
365 if (!blob) {
366 pr_debug("No device tree pointer\n");
367 return;
368 }
369
370 pr_debug("Unflattening device tree:\n");
371 pr_debug("magic: %08x\n", be32_to_cpu(blob->magic));
372 pr_debug("size: %08x\n", be32_to_cpu(blob->totalsize));
373 pr_debug("version: %08x\n", be32_to_cpu(blob->version));
374
375 if (be32_to_cpu(blob->magic) != OF_DT_HEADER) {
376 pr_err("Invalid device tree blob header\n");
377 return;
378 }
379
380 /* First pass, scan for size */
381 start = ((unsigned long)blob) +
382 be32_to_cpu(blob->off_dt_struct);
383 size = unflatten_dt_node(blob, 0, &start, NULL, NULL, 0);
384 size = (size | 3) + 1;
385
386 pr_debug(" size is %lx, allocating...\n", size);
387
388 /* Allocate memory for the expanded device tree */
389 mem = (unsigned long)
390 dt_alloc(size + 4, __alignof__(struct device_node));
391
392 ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef);
393
394 pr_debug(" unflattening %lx...\n", mem);
395
396 /* Second pass, do actual unflattening */
397 start = ((unsigned long)blob) +
398 be32_to_cpu(blob->off_dt_struct);
399 unflatten_dt_node(blob, mem, &start, NULL, &allnextp, 0);
400 if (be32_to_cpup((__be32 *)start) != OF_DT_END)
401 pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start));
402 if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef)
403 pr_warning("End of tree marker overwritten: %08x\n",
404 be32_to_cpu(((__be32 *)mem)[size / 4]));
405 *allnextp = NULL;
406
407 pr_debug(" <- unflatten_device_tree()\n");
408}
409
410static void *kernel_tree_alloc(u64 size, u64 align)
411{
412 return kzalloc(size, GFP_KERNEL);
413}
414
415/**
416 * of_fdt_unflatten_tree - create tree of device_nodes from flat blob
417 *
418 * unflattens the device-tree passed by the firmware, creating the
419 * tree of struct device_node. It also fills the "name" and "type"
420 * pointers of the nodes so the normal device-tree walking functions
421 * can be used.
422 */
423void of_fdt_unflatten_tree(unsigned long *blob,
424 struct device_node **mynodes)
425{
426 struct boot_param_header *device_tree =
427 (struct boot_param_header *)blob;
428 __unflatten_device_tree(device_tree, mynodes, &kernel_tree_alloc);
429}
430EXPORT_SYMBOL_GPL(of_fdt_unflatten_tree);
431
432/* Everything below here references initial_boot_params directly. */
433int __initdata dt_root_addr_cells;
434int __initdata dt_root_size_cells;
435
436struct boot_param_header *initial_boot_params;
437
438#ifdef CONFIG_OF_EARLY_FLATTREE
439
440/**
441 * of_scan_flat_dt - scan flattened tree blob and call callback on each.
442 * @it: callback function
443 * @data: context data pointer
444 *
445 * This function is used to scan the flattened device-tree, it is
446 * used to extract the memory information at boot before we can
447 * unflatten the tree
448 */
449int __init of_scan_flat_dt(int (*it)(unsigned long node,
450 const char *uname, int depth,
451 void *data),
452 void *data)
453{
454 unsigned long p = ((unsigned long)initial_boot_params) +
455 be32_to_cpu(initial_boot_params->off_dt_struct);
456 int rc = 0;
457 int depth = -1;
458
459 do {
460 u32 tag = be32_to_cpup((__be32 *)p);
461 char *pathp;
462
463 p += 4;
464 if (tag == OF_DT_END_NODE) {
465 depth--;
466 continue;
467 }
468 if (tag == OF_DT_NOP)
469 continue;
470 if (tag == OF_DT_END)
471 break;
472 if (tag == OF_DT_PROP) {
473 u32 sz = be32_to_cpup((__be32 *)p);
474 p += 8;
475 if (be32_to_cpu(initial_boot_params->version) < 0x10)
476 p = ALIGN(p, sz >= 8 ? 8 : 4);
477 p += sz;
478 p = ALIGN(p, 4);
479 continue;
480 }
481 if (tag != OF_DT_BEGIN_NODE) {
482 pr_err("Invalid tag %x in flat device tree!\n", tag);
483 return -EINVAL;
484 }
485 depth++;
486 pathp = (char *)p;
487 p = ALIGN(p + strlen(pathp) + 1, 4);
488 if ((*pathp) == '/') {
489 char *lp, *np;
490 for (lp = NULL, np = pathp; *np; np++)
491 if ((*np) == '/')
492 lp = np+1;
493 if (lp != NULL)
494 pathp = lp;
495 }
496 rc = it(p, pathp, depth, data);
497 if (rc != 0)
498 break;
499 } while (1);
500
501 return rc;
502}
503
504/**
505 * of_get_flat_dt_root - find the root node in the flat blob
506 */
507unsigned long __init of_get_flat_dt_root(void)
508{
509 unsigned long p = ((unsigned long)initial_boot_params) +
510 be32_to_cpu(initial_boot_params->off_dt_struct);
511
512 while (be32_to_cpup((__be32 *)p) == OF_DT_NOP)
513 p += 4;
514 BUG_ON(be32_to_cpup((__be32 *)p) != OF_DT_BEGIN_NODE);
515 p += 4;
516 return ALIGN(p + strlen((char *)p) + 1, 4);
517}
518
519/**
520 * of_get_flat_dt_prop - Given a node in the flat blob, return the property ptr
521 *
522 * This function can be used within scan_flattened_dt callback to get
523 * access to properties
524 */
525void *__init of_get_flat_dt_prop(unsigned long node, const char *name,
526 unsigned long *size)
527{
528 return of_fdt_get_property(initial_boot_params, node, name, size);
529}
530
531/**
532 * of_flat_dt_is_compatible - Return true if given node has compat in compatible list
533 * @node: node to test
534 * @compat: compatible string to compare with compatible list.
535 */
536int __init of_flat_dt_is_compatible(unsigned long node, const char *compat)
537{
538 return of_fdt_is_compatible(initial_boot_params, node, compat);
539}
540
541/**
542 * of_flat_dt_match - Return true if node matches a list of compatible values
543 */
544int __init of_flat_dt_match(unsigned long node, const char **compat)
545{
546 return of_fdt_match(initial_boot_params, node, compat);
547}
548
394#ifdef CONFIG_BLK_DEV_INITRD 549#ifdef CONFIG_BLK_DEV_INITRD
395/** 550/**
396 * early_init_dt_check_for_initrd - Decode initrd location from flat tree 551 * early_init_dt_check_for_initrd - Decode initrd location from flat tree
@@ -515,27 +670,25 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
515 670
516 pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname); 671 pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);
517 672
518 if (depth != 1 || 673 if (depth != 1 || !data ||
519 (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0)) 674 (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
520 return 0; 675 return 0;
521 676
522 early_init_dt_check_for_initrd(node); 677 early_init_dt_check_for_initrd(node);
523 678
524 /* Retreive command line */ 679 /* Retrieve command line */
525 p = of_get_flat_dt_prop(node, "bootargs", &l); 680 p = of_get_flat_dt_prop(node, "bootargs", &l);
526 if (p != NULL && l > 0) 681 if (p != NULL && l > 0)
527 strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE)); 682 strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));
528 683
529#ifdef CONFIG_CMDLINE 684#ifdef CONFIG_CMDLINE
530#ifndef CONFIG_CMDLINE_FORCE 685#ifndef CONFIG_CMDLINE_FORCE
531 if (p == NULL || l == 0 || (l == 1 && (*p) == 0)) 686 if (p == NULL || l == 0 || (l == 1 && (*p) == 0))
532#endif 687#endif
533 strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); 688 strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
534#endif /* CONFIG_CMDLINE */ 689#endif /* CONFIG_CMDLINE */
535 690
536 early_init_dt_scan_chosen_arch(node); 691 pr_debug("Command line is: %s\n", (char*)data);
537
538 pr_debug("Command line is: %s\n", cmd_line);
539 692
540 /* break now */ 693 /* break now */
541 return 1; 694 return 1;
@@ -551,58 +704,13 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
551 */ 704 */
552void __init unflatten_device_tree(void) 705void __init unflatten_device_tree(void)
553{ 706{
554 unsigned long start, mem, size; 707 __unflatten_device_tree(initial_boot_params, &allnodes,
555 struct device_node **allnextp = &allnodes; 708 early_init_dt_alloc_memory_arch);
556
557 pr_debug(" -> unflatten_device_tree()\n");
558
559 if (!initial_boot_params) {
560 pr_debug("No device tree pointer\n");
561 return;
562 }
563
564 pr_debug("Unflattening device tree:\n");
565 pr_debug("magic: %08x\n", be32_to_cpu(initial_boot_params->magic));
566 pr_debug("size: %08x\n", be32_to_cpu(initial_boot_params->totalsize));
567 pr_debug("version: %08x\n", be32_to_cpu(initial_boot_params->version));
568
569 if (be32_to_cpu(initial_boot_params->magic) != OF_DT_HEADER) {
570 pr_err("Invalid device tree blob header\n");
571 return;
572 }
573
574 /* First pass, scan for size */
575 start = ((unsigned long)initial_boot_params) +
576 be32_to_cpu(initial_boot_params->off_dt_struct);
577 size = unflatten_dt_node(0, &start, NULL, NULL, 0);
578 size = (size | 3) + 1;
579
580 pr_debug(" size is %lx, allocating...\n", size);
581
582 /* Allocate memory for the expanded device tree */
583 mem = early_init_dt_alloc_memory_arch(size + 4,
584 __alignof__(struct device_node));
585 mem = (unsigned long) __va(mem);
586
587 ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef);
588
589 pr_debug(" unflattening %lx...\n", mem);
590
591 /* Second pass, do actual unflattening */
592 start = ((unsigned long)initial_boot_params) +
593 be32_to_cpu(initial_boot_params->off_dt_struct);
594 unflatten_dt_node(mem, &start, NULL, &allnextp, 0);
595 if (be32_to_cpup((__be32 *)start) != OF_DT_END)
596 pr_warning("Weird tag at end of tree: %08x\n", *((u32 *)start));
597 if (be32_to_cpu(((__be32 *)mem)[size / 4]) != 0xdeadbeef)
598 pr_warning("End of tree marker overwritten: %08x\n",
599 be32_to_cpu(((__be32 *)mem)[size / 4]));
600 *allnextp = NULL;
601 709
602 /* Get pointer to OF "/chosen" node for use everywhere */ 710 /* Get pointer to OF "/chosen" node for use everywhere */
603 of_chosen = of_find_node_by_path("/chosen"); 711 of_chosen = of_find_node_by_path("/chosen");
604 if (of_chosen == NULL) 712 if (of_chosen == NULL)
605 of_chosen = of_find_node_by_path("/chosen@0"); 713 of_chosen = of_find_node_by_path("/chosen@0");
606
607 pr_debug(" <- unflatten_device_tree()\n");
608} 714}
715
716#endif /* CONFIG_OF_EARLY_FLATTREE */