aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/prom.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/prom.c')
-rw-r--r--arch/powerpc/kernel/prom.c913
1 files changed, 52 insertions, 861 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index d4405b95bfaa..05131d634e73 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -43,6 +43,7 @@
43#include <asm/smp.h> 43#include <asm/smp.h>
44#include <asm/system.h> 44#include <asm/system.h>
45#include <asm/mmu.h> 45#include <asm/mmu.h>
46#include <asm/paca.h>
46#include <asm/pgtable.h> 47#include <asm/pgtable.h>
47#include <asm/pci.h> 48#include <asm/pci.h>
48#include <asm/iommu.h> 49#include <asm/iommu.h>
@@ -61,365 +62,12 @@
61#define DBG(fmt...) 62#define DBG(fmt...)
62#endif 63#endif
63 64
64
65static int __initdata dt_root_addr_cells;
66static int __initdata dt_root_size_cells;
67
68#ifdef CONFIG_PPC64 65#ifdef CONFIG_PPC64
69int __initdata iommu_is_off; 66int __initdata iommu_is_off;
70int __initdata iommu_force_on; 67int __initdata iommu_force_on;
71unsigned long tce_alloc_start, tce_alloc_end; 68unsigned long tce_alloc_start, tce_alloc_end;
72#endif 69#endif
73 70
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 */
85
86/* export that to outside world */
87struct device_node *of_chosen;
88
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) 71static int __init early_parse_mem(char *p)
424{ 72{
425 if (!p) 73 if (!p)
@@ -446,7 +94,7 @@ static void __init move_device_tree(void)
446 DBG("-> move_device_tree\n"); 94 DBG("-> move_device_tree\n");
447 95
448 start = __pa(initial_boot_params); 96 start = __pa(initial_boot_params);
449 size = initial_boot_params->totalsize; 97 size = be32_to_cpu(initial_boot_params->totalsize);
450 98
451 if ((memory_limit && (start + size) > memory_limit) || 99 if ((memory_limit && (start + size) > memory_limit) ||
452 overlaps_crashkernel(start, size)) { 100 overlaps_crashkernel(start, size)) {
@@ -459,54 +107,6 @@ static void __init move_device_tree(void)
459 DBG("<- move_device_tree\n"); 107 DBG("<- move_device_tree\n");
460} 108}
461 109
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/* 110/*
511 * ibm,pa-features is a per-cpu property that contains a string of 111 * 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 112 * attribute descriptors, each of which has a 2 byte header plus up
@@ -763,48 +363,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
763 return 0; 363 return 0;
764} 364}
765 365
766#ifdef CONFIG_BLK_DEV_INITRD 366void __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{ 367{
799 unsigned long *lprop; 368 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 369
809#ifdef CONFIG_PPC64 370#ifdef CONFIG_PPC64
810 /* check if iommu is forced on or off */ 371 /* check if iommu is forced on or off */
@@ -815,17 +376,17 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
815#endif 376#endif
816 377
817 /* mem=x on the command line is the preferred mechanism */ 378 /* mem=x on the command line is the preferred mechanism */
818 lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); 379 lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL);
819 if (lprop) 380 if (lprop)
820 memory_limit = *lprop; 381 memory_limit = *lprop;
821 382
822#ifdef CONFIG_PPC64 383#ifdef CONFIG_PPC64
823 lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); 384 lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-start", NULL);
824 if (lprop) 385 if (lprop)
825 tce_alloc_start = *lprop; 386 tce_alloc_start = *lprop;
826 lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); 387 lprop = of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL);
827 if (lprop) 388 if (lprop)
828 tce_alloc_end = *lprop; 389 tce_alloc_end = *lprop;
829#endif 390#endif
830 391
831#ifdef CONFIG_KEXEC 392#ifdef CONFIG_KEXEC
@@ -837,51 +398,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
837 if (lprop) 398 if (lprop)
838 crashk_res.end = crashk_res.start + *lprop - 1; 399 crashk_res.end = crashk_res.start + *lprop - 1;
839#endif 400#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} 401}
886 402
887#ifdef CONFIG_PPC_PSERIES 403#ifdef CONFIG_PPC_PSERIES
@@ -893,22 +409,22 @@ static u64 __init dt_mem_next_cell(int s, cell_t **cellp)
893 */ 409 */
894static int __init early_init_dt_scan_drconf_memory(unsigned long node) 410static int __init early_init_dt_scan_drconf_memory(unsigned long node)
895{ 411{
896 cell_t *dm, *ls, *usm; 412 __be32 *dm, *ls, *usm;
897 unsigned long l, n, flags; 413 unsigned long l, n, flags;
898 u64 base, size, lmb_size; 414 u64 base, size, lmb_size;
899 unsigned int is_kexec_kdump = 0, rngs; 415 unsigned int is_kexec_kdump = 0, rngs;
900 416
901 ls = of_get_flat_dt_prop(node, "ibm,lmb-size", &l); 417 ls = of_get_flat_dt_prop(node, "ibm,lmb-size", &l);
902 if (ls == NULL || l < dt_root_size_cells * sizeof(cell_t)) 418 if (ls == NULL || l < dt_root_size_cells * sizeof(__be32))
903 return 0; 419 return 0;
904 lmb_size = dt_mem_next_cell(dt_root_size_cells, &ls); 420 lmb_size = dt_mem_next_cell(dt_root_size_cells, &ls);
905 421
906 dm = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l); 422 dm = of_get_flat_dt_prop(node, "ibm,dynamic-memory", &l);
907 if (dm == NULL || l < sizeof(cell_t)) 423 if (dm == NULL || l < sizeof(__be32))
908 return 0; 424 return 0;
909 425
910 n = *dm++; /* number of entries */ 426 n = *dm++; /* number of entries */
911 if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(cell_t)) 427 if (l < (n * (dt_root_addr_cells + 4) + 1) * sizeof(__be32))
912 return 0; 428 return 0;
913 429
914 /* check if this is a kexec/kdump kernel. */ 430 /* check if this is a kexec/kdump kernel. */
@@ -963,65 +479,47 @@ static int __init early_init_dt_scan_drconf_memory(unsigned long node)
963#define early_init_dt_scan_drconf_memory(node) 0 479#define early_init_dt_scan_drconf_memory(node) 0
964#endif /* CONFIG_PPC_PSERIES */ 480#endif /* CONFIG_PPC_PSERIES */
965 481
966static int __init early_init_dt_scan_memory(unsigned long node, 482static int __init early_init_dt_scan_memory_ppc(unsigned long node,
967 const char *uname, int depth, void *data) 483 const char *uname,
484 int depth, void *data)
968{ 485{
969 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
970 cell_t *reg, *endp;
971 unsigned long l;
972
973 /* Look for the ibm,dynamic-reconfiguration-memory node */
974 if (depth == 1 && 486 if (depth == 1 &&
975 strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0) 487 strcmp(uname, "ibm,dynamic-reconfiguration-memory") == 0)
976 return early_init_dt_scan_drconf_memory(node); 488 return early_init_dt_scan_drconf_memory(node);
489
490 return early_init_dt_scan_memory(node, uname, depth, data);
491}
977 492
978 /* We are scanning "memory" nodes only */ 493void __init early_init_dt_add_memory_arch(u64 base, u64 size)
979 if (type == NULL) { 494{
980 /* 495#if defined(CONFIG_PPC64)
981 * The longtrail doesn't have a device_type on the 496 if (iommu_is_off) {
982 * /memory node, so look for the node called /memory@0. 497 if (base >= 0x80000000ul)
983 */ 498 return;
984 if (depth != 1 || strcmp(uname, "memory@0") != 0) 499 if ((base + size) > 0x80000000ul)
985 return 0; 500 size = 0x80000000ul - base;
986 } else if (strcmp(type, "memory") != 0) 501 }
987 return 0; 502#endif
988
989 reg = of_get_flat_dt_prop(node, "linux,usable-memory", &l);
990 if (reg == NULL)
991 reg = of_get_flat_dt_prop(node, "reg", &l);
992 if (reg == NULL)
993 return 0;
994
995 endp = reg + (l / sizeof(cell_t));
996
997 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]);
999
1000 while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) {
1001 u64 base, size;
1002 503
1003 base = dt_mem_next_cell(dt_root_addr_cells, &reg); 504 lmb_add(base, size);
1004 size = dt_mem_next_cell(dt_root_size_cells, &reg);
1005 505
1006 if (size == 0) 506 memstart_addr = min((u64)memstart_addr, base);
1007 continue; 507}
1008 DBG(" - %llx , %llx\n", (unsigned long long)base,
1009 (unsigned long long)size);
1010#ifdef CONFIG_PPC64
1011 if (iommu_is_off) {
1012 if (base >= 0x80000000ul)
1013 continue;
1014 if ((base + size) > 0x80000000ul)
1015 size = 0x80000000ul - base;
1016 }
1017#endif
1018 lmb_add(base, size);
1019 508
1020 memstart_addr = min((u64)memstart_addr, base); 509u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
1021 } 510{
511 return lmb_alloc(size, align);
512}
1022 513
1023 return 0; 514#ifdef CONFIG_BLK_DEV_INITRD
515void __init early_init_dt_setup_initrd_arch(unsigned long start,
516 unsigned long end)
517{
518 initrd_start = (unsigned long)__va(start);
519 initrd_end = (unsigned long)__va(end);
520 initrd_below_start_ok = 1;
1024} 521}
522#endif
1025 523
1026static void __init early_reserve_mem(void) 524static void __init early_reserve_mem(void)
1027{ 525{
@@ -1186,7 +684,7 @@ void __init early_init_devtree(void *params)
1186 /* Scan memory nodes and rebuild LMBs */ 684 /* Scan memory nodes and rebuild LMBs */
1187 lmb_init(); 685 lmb_init();
1188 of_scan_flat_dt(early_init_dt_scan_root, NULL); 686 of_scan_flat_dt(early_init_dt_scan_root, NULL);
1189 of_scan_flat_dt(early_init_dt_scan_memory, NULL); 687 of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL);
1190 688
1191 /* Save command line for /proc/cmdline and then parse parameters */ 689 /* Save command line for /proc/cmdline and then parse parameters */
1192 strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE); 690 strlcpy(boot_command_line, cmd_line, COMMAND_LINE_SIZE);
@@ -1224,6 +722,8 @@ void __init early_init_devtree(void *params)
1224 * FIXME .. and the initrd too? */ 722 * FIXME .. and the initrd too? */
1225 move_device_tree(); 723 move_device_tree();
1226 724
725 allocate_pacas();
726
1227 DBG("Scanning CPUs ...\n"); 727 DBG("Scanning CPUs ...\n");
1228 728
1229 /* Retreive CPU related informations from the flat tree 729 /* Retreive CPU related informations from the flat tree
@@ -1234,25 +734,6 @@ void __init early_init_devtree(void *params)
1234 DBG(" <- early_init_devtree()\n"); 734 DBG(" <- early_init_devtree()\n");
1235} 735}
1236 736
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/******* 737/*******
1257 * 738 *
1258 * New implementation of the OF "find" APIs, return a refcounted 739 * New implementation of the OF "find" APIs, return a refcounted
@@ -1265,27 +746,6 @@ EXPORT_SYMBOL(machine_is_compatible);
1265 *******/ 746 *******/
1266 747
1267/** 748/**
1268 * of_find_node_by_phandle - Find a node given a phandle
1269 * @handle: phandle of the node to find
1270 *
1271 * Returns a node pointer with refcount incremented, use
1272 * of_node_put() on it when done.
1273 */
1274struct device_node *of_find_node_by_phandle(phandle handle)
1275{
1276 struct device_node *np;
1277
1278 read_lock(&devtree_lock);
1279 for (np = allnodes; np != 0; np = np->allnext)
1280 if (np->linux_phandle == handle)
1281 break;
1282 of_node_get(np);
1283 read_unlock(&devtree_lock);
1284 return np;
1285}
1286EXPORT_SYMBOL(of_find_node_by_phandle);
1287
1288/**
1289 * of_find_next_cache_node - Find a node's subsidiary cache 749 * of_find_next_cache_node - Find a node's subsidiary cache
1290 * @np: node of type "cpu" or "cache" 750 * @np: node of type "cpu" or "cache"
1291 * 751 *
@@ -1316,161 +776,6 @@ struct device_node *of_find_next_cache_node(struct device_node *np)
1316 return NULL; 776 return NULL;
1317} 777}
1318 778
1319/**
1320 * of_find_all_nodes - Get next node in global list
1321 * @prev: Previous node or NULL to start iteration
1322 * of_node_put() will be called on it
1323 *
1324 * Returns a node pointer with refcount incremented, use
1325 * of_node_put() on it when done.
1326 */
1327struct device_node *of_find_all_nodes(struct device_node *prev)
1328{
1329 struct device_node *np;
1330
1331 read_lock(&devtree_lock);
1332 np = prev ? prev->allnext : allnodes;
1333 for (; np != 0; np = np->allnext)
1334 if (of_node_get(np))
1335 break;
1336 of_node_put(prev);
1337 read_unlock(&devtree_lock);
1338 return np;
1339}
1340EXPORT_SYMBOL(of_find_all_nodes);
1341
1342/**
1343 * of_node_get - Increment refcount of a node
1344 * @node: Node to inc refcount, NULL is supported to
1345 * simplify writing of callers
1346 *
1347 * Returns node.
1348 */
1349struct device_node *of_node_get(struct device_node *node)
1350{
1351 if (node)
1352 kref_get(&node->kref);
1353 return node;
1354}
1355EXPORT_SYMBOL(of_node_get);
1356
1357static inline struct device_node * kref_to_device_node(struct kref *kref)
1358{
1359 return container_of(kref, struct device_node, kref);
1360}
1361
1362/**
1363 * of_node_release - release a dynamically allocated node
1364 * @kref: kref element of the node to be released
1365 *
1366 * In of_node_put() this function is passed to kref_put()
1367 * as the destructor.
1368 */
1369static void of_node_release(struct kref *kref)
1370{
1371 struct device_node *node = kref_to_device_node(kref);
1372 struct property *prop = node->properties;
1373
1374 /* We should never be releasing nodes that haven't been detached. */
1375 if (!of_node_check_flag(node, OF_DETACHED)) {
1376 printk("WARNING: Bad of_node_put() on %s\n", node->full_name);
1377 dump_stack();
1378 kref_init(&node->kref);
1379 return;
1380 }
1381
1382 if (!of_node_check_flag(node, OF_DYNAMIC))
1383 return;
1384
1385 while (prop) {
1386 struct property *next = prop->next;
1387 kfree(prop->name);
1388 kfree(prop->value);
1389 kfree(prop);
1390 prop = next;
1391
1392 if (!prop) {
1393 prop = node->deadprops;
1394 node->deadprops = NULL;
1395 }
1396 }
1397 kfree(node->full_name);
1398 kfree(node->data);
1399 kfree(node);
1400}
1401
1402/**
1403 * of_node_put - Decrement refcount of a node
1404 * @node: Node to dec refcount, NULL is supported to
1405 * simplify writing of callers
1406 *
1407 */
1408void of_node_put(struct device_node *node)
1409{
1410 if (node)
1411 kref_put(&node->kref, of_node_release);
1412}
1413EXPORT_SYMBOL(of_node_put);
1414
1415/*
1416 * Plug a device node into the tree and global list.
1417 */
1418void of_attach_node(struct device_node *np)
1419{
1420 unsigned long flags;
1421
1422 write_lock_irqsave(&devtree_lock, flags);
1423 np->sibling = np->parent->child;
1424 np->allnext = allnodes;
1425 np->parent->child = np;
1426 allnodes = np;
1427 write_unlock_irqrestore(&devtree_lock, flags);
1428}
1429
1430/*
1431 * "Unplug" a node from the device tree. The caller must hold
1432 * a reference to the node. The memory associated with the node
1433 * is not freed until its refcount goes to zero.
1434 */
1435void of_detach_node(struct device_node *np)
1436{
1437 struct device_node *parent;
1438 unsigned long flags;
1439
1440 write_lock_irqsave(&devtree_lock, flags);
1441
1442 parent = np->parent;
1443 if (!parent)
1444 goto out_unlock;
1445
1446 if (allnodes == np)
1447 allnodes = np->allnext;
1448 else {
1449 struct device_node *prev;
1450 for (prev = allnodes;
1451 prev->allnext != np;
1452 prev = prev->allnext)
1453 ;
1454 prev->allnext = np->allnext;
1455 }
1456
1457 if (parent->child == np)
1458 parent->child = np->sibling;
1459 else {
1460 struct device_node *prevsib;
1461 for (prevsib = np->parent->child;
1462 prevsib->sibling != np;
1463 prevsib = prevsib->sibling)
1464 ;
1465 prevsib->sibling = np->sibling;
1466 }
1467
1468 of_node_set_flag(np, OF_DETACHED);
1469
1470out_unlock:
1471 write_unlock_irqrestore(&devtree_lock, flags);
1472}
1473
1474#ifdef CONFIG_PPC_PSERIES 779#ifdef CONFIG_PPC_PSERIES
1475/* 780/*
1476 * Fix up the uninitialized fields in a new device node: 781 * Fix up the uninitialized fields in a new device node:
@@ -1502,9 +807,9 @@ static int of_finish_dynamic_node(struct device_node *node)
1502 if (machine_is(powermac)) 807 if (machine_is(powermac))
1503 return -ENODEV; 808 return -ENODEV;
1504 809
1505 /* fix up new node's linux_phandle field */ 810 /* fix up new node's phandle field */
1506 if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL))) 811 if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL)))
1507 node->linux_phandle = *ibm_phandle; 812 node->phandle = *ibm_phandle;
1508 813
1509out: 814out:
1510 of_node_put(parent); 815 of_node_put(parent);
@@ -1543,120 +848,6 @@ static int __init prom_reconfig_setup(void)
1543__initcall(prom_reconfig_setup); 848__initcall(prom_reconfig_setup);
1544#endif 849#endif
1545 850
1546/*
1547 * Add a property to a node
1548 */
1549int prom_add_property(struct device_node* np, struct property* prop)
1550{
1551 struct property **next;
1552 unsigned long flags;
1553
1554 prop->next = NULL;
1555 write_lock_irqsave(&devtree_lock, flags);
1556 next = &np->properties;
1557 while (*next) {
1558 if (strcmp(prop->name, (*next)->name) == 0) {
1559 /* duplicate ! don't insert it */
1560 write_unlock_irqrestore(&devtree_lock, flags);
1561 return -1;
1562 }
1563 next = &(*next)->next;
1564 }
1565 *next = prop;
1566 write_unlock_irqrestore(&devtree_lock, flags);
1567
1568#ifdef CONFIG_PROC_DEVICETREE
1569 /* try to add to proc as well if it was initialized */
1570 if (np->pde)
1571 proc_device_tree_add_prop(np->pde, prop);
1572#endif /* CONFIG_PROC_DEVICETREE */
1573
1574 return 0;
1575}
1576
1577/*
1578 * Remove a property from a node. Note that we don't actually
1579 * remove it, since we have given out who-knows-how-many pointers
1580 * to the data using get-property. Instead we just move the property
1581 * to the "dead properties" list, so it won't be found any more.
1582 */
1583int prom_remove_property(struct device_node *np, struct property *prop)
1584{
1585 struct property **next;
1586 unsigned long flags;
1587 int found = 0;
1588
1589 write_lock_irqsave(&devtree_lock, flags);
1590 next = &np->properties;
1591 while (*next) {
1592 if (*next == prop) {
1593 /* found the node */
1594 *next = prop->next;
1595 prop->next = np->deadprops;
1596 np->deadprops = prop;
1597 found = 1;
1598 break;
1599 }
1600 next = &(*next)->next;
1601 }
1602 write_unlock_irqrestore(&devtree_lock, flags);
1603
1604 if (!found)
1605 return -ENODEV;
1606
1607#ifdef CONFIG_PROC_DEVICETREE
1608 /* try to remove the proc node as well */
1609 if (np->pde)
1610 proc_device_tree_remove_prop(np->pde, prop);
1611#endif /* CONFIG_PROC_DEVICETREE */
1612
1613 return 0;
1614}
1615
1616/*
1617 * Update a property in a node. Note that we don't actually
1618 * remove it, since we have given out who-knows-how-many pointers
1619 * to the data using get-property. Instead we just move the property
1620 * to the "dead properties" list, and add the new property to the
1621 * property list
1622 */
1623int prom_update_property(struct device_node *np,
1624 struct property *newprop,
1625 struct property *oldprop)
1626{
1627 struct property **next;
1628 unsigned long flags;
1629 int found = 0;
1630
1631 write_lock_irqsave(&devtree_lock, flags);
1632 next = &np->properties;
1633 while (*next) {
1634 if (*next == oldprop) {
1635 /* found the node */
1636 newprop->next = oldprop->next;
1637 *next = newprop;
1638 oldprop->next = np->deadprops;
1639 np->deadprops = oldprop;
1640 found = 1;
1641 break;
1642 }
1643 next = &(*next)->next;
1644 }
1645 write_unlock_irqrestore(&devtree_lock, flags);
1646
1647 if (!found)
1648 return -ENODEV;
1649
1650#ifdef CONFIG_PROC_DEVICETREE
1651 /* try to add to proc as well if it was initialized */
1652 if (np->pde)
1653 proc_device_tree_update_prop(np->pde, newprop, oldprop);
1654#endif /* CONFIG_PROC_DEVICETREE */
1655
1656 return 0;
1657}
1658
1659
1660/* Find the device node for a given logical cpu number, also returns the cpu 851/* Find the device node for a given logical cpu number, also returns the cpu
1661 * local thread number (index in ibm,interrupt-server#s) if relevant and 852 * local thread number (index in ibm,interrupt-server#s) if relevant and
1662 * asked for (non NULL) 853 * asked for (non NULL)