direct-io.hg

view xen/arch/powerpc/boot_of.c @ 12959:d6b44cb7d2c9

[POWERPC][XEN] Ignore device tree nodes missing "device_type".
The latest release of SLOF is missing mandatory "device_type" properties for
the ISA and system-controller busses. Work around it by just printing a warning
and continuing.
CC: Segher Boessenkool <segher@kernel.crashing.org>
Signed-off-by: Amos Waterland <apw@us.ibm.com>
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Hollis Blanchard <hollisb@us.ibm.com>
date Tue Nov 21 15:25:02 2006 -0600 (2006-11-21)
parents 020fc58ba873
children 5909f57c8c39
line source
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15 *
16 * Copyright (C) IBM Corp. 2005, 2006
17 *
18 * Authors: Jimi Xenidis <jimix@watson.ibm.com>
19 * Hollis Blanchard <hollisb@us.ibm.com>
20 */
22 #include <xen/config.h>
23 #include <xen/init.h>
24 #include <xen/lib.h>
25 #include <xen/multiboot.h>
26 #include <xen/version.h>
27 #include <xen/spinlock.h>
28 #include <xen/serial.h>
29 #include <xen/time.h>
30 #include <xen/sched.h>
31 #include <asm/page.h>
32 #include <asm/io.h>
33 #include "exceptions.h"
34 #include "of-devtree.h"
35 #include "oftree.h"
36 #include "rtas.h"
38 /* Secondary processors use this for handshaking with main processor. */
39 volatile unsigned int __spin_ack;
41 static ulong of_vec;
42 static ulong of_msr;
43 static int of_out;
45 extern char builtin_cmdline[];
46 extern struct ns16550_defaults ns16550;
48 #undef OF_DEBUG
50 #ifdef OF_DEBUG
51 #define DBG(args...) of_printf(args)
52 #else
53 #define DBG(args...)
54 #endif
56 #define of_panic(MSG...) \
57 do { of_printf(MSG); of_printf("\nHANG\n"); for (;;); } while (0)
59 struct of_service {
60 u32 ofs_service;
61 u32 ofs_nargs;
62 u32 ofs_nrets;
63 u32 ofs_args[10];
64 };
66 static int bof_chosen;
68 static struct of_service s;
70 static int __init of_call(
71 const char *service, u32 nargs, u32 nrets, s32 rets[], ...)
72 {
73 int rc;
75 if (of_vec != 0) {
76 va_list args;
77 int i;
79 memset(&s, 0, sizeof (s));
80 s.ofs_service = (ulong)service;
81 s.ofs_nargs = nargs;
82 s.ofs_nrets = nrets;
83 s.ofs_nargs = nargs;
85 /* copy all the params into the args array */
86 va_start(args, rets);
88 for (i = 0; i < nargs; i++) {
89 s.ofs_args[i] = va_arg(args, u32);
90 }
92 va_end(args);
94 rc = prom_call(&s, 0, of_vec, of_msr);
96 /* yes always to the copy, just in case */
97 for (i = 0; i < nrets; i++) {
98 rets[i] = s.ofs_args[i + nargs];
99 }
100 } else {
101 rc = OF_FAILURE;
102 }
103 return rc;
104 }
106 /* popular OF methods */
107 static int __init _of_write(int ih, const char *addr, u32 len)
108 {
109 int rets[1] = { OF_FAILURE };
110 if (of_call("write", 3, 1, rets, ih, addr, len) == OF_FAILURE) {
111 return OF_FAILURE;
112 }
113 return rets[0];
114 }
116 /* popular OF methods */
117 static int __init of_write(int ih, const char *addr, u32 len)
118 {
119 int rc;
120 int i = 0;
121 int sum = 0;
123 while (i < len) {
124 if (addr[i] == '\n') {
125 if (i > 0) {
126 rc = _of_write(ih, addr, i);
127 if (rc == OF_FAILURE)
128 return rc;
129 sum += rc;
130 }
131 rc = _of_write(ih, "\r\n", 2);
132 if (rc == OF_FAILURE)
133 return rc;
134 sum += rc;
135 i++;
136 addr += i;
137 len -= i;
138 i = 0;
139 continue;
140 }
141 i++;
142 }
143 if (len > 0) {
144 rc = _of_write(ih, addr, len);
145 if (rc == OF_FAILURE)
146 return rc;
147 sum += rc;
148 }
150 return sum;
151 }
153 static int of_printf(const char *fmt, ...)
154 __attribute__ ((format (printf, 1, 2)));
155 static int __init of_printf(const char *fmt, ...)
156 {
157 static char buf[1024];
158 va_list args;
159 int sz;
161 if (of_out == 0) {
162 return OF_FAILURE;
163 }
165 va_start(args, fmt);
167 sz = vsnprintf(buf, sizeof (buf), fmt, args);
168 if (sz <= sizeof (buf)) {
169 of_write(of_out, buf, sz);
170 } else {
171 static const char trunc[] = "\n(TRUNCATED)\n";
173 sz = sizeof (buf);
174 of_write(of_out, buf, sz);
175 of_write(of_out, trunc, sizeof (trunc));
176 }
177 return sz;
178 }
180 static int __init of_finddevice(const char *devspec)
181 {
182 int rets[1] = { OF_FAILURE };
184 of_call("finddevice", 1, 1, rets, devspec);
185 if (rets[0] == OF_FAILURE) {
186 DBG("finddevice %s -> FAILURE %d\n",devspec,rets[0]);
187 return OF_FAILURE;
188 }
189 DBG("finddevice %s -> %d\n",devspec, rets[0]);
190 return rets[0];
191 }
193 static int __init of_getprop(int ph, const char *name, void *buf, u32 buflen)
194 {
195 int rets[1] = { OF_FAILURE };
197 of_call("getprop", 4, 1, rets, ph, name, buf, buflen);
199 if (rets[0] == OF_FAILURE) {
200 DBG("getprop 0x%x %s -> FAILURE\n", ph, name);
201 return OF_FAILURE;
202 }
204 DBG("getprop 0x%x %s -> 0x%x (%s)\n", ph, name, rets[0], (char *)buf);
205 return rets[0];
206 }
208 static int __init of_setprop(
209 int ph, const char *name, const void *buf, u32 buflen)
210 {
211 int rets[1] = { OF_FAILURE };
213 of_call("setprop", 4, 1, rets, ph, name, buf, buflen);
215 if (rets[0] == OF_FAILURE) {
216 DBG("setprop 0x%x %s -> FAILURE\n", ph, name);
217 return OF_FAILURE;
218 }
220 DBG("setprop 0x%x %s -> %s\n", ph, name, (char *)buf);
221 return rets[0];
222 }
224 /*
225 * returns 0 if there are no children (of spec)
226 */
227 static int __init of_getchild(int ph)
228 {
229 int rets[1] = { OF_FAILURE };
231 of_call("child", 1, 1, rets, ph);
232 DBG("getchild 0x%x -> 0x%x\n", ph, rets[0]);
234 return rets[0];
235 }
237 /*
238 * returns 0 is there are no peers
239 */
240 static int __init of_getpeer(int ph)
241 {
242 int rets[1] = { OF_FAILURE };
244 of_call("peer", 1, 1, rets, ph);
245 DBG("getpeer 0x%x -> 0x%x\n", ph, rets[0]);
247 return rets[0];
248 }
250 static int __init of_getproplen(int ph, const char *name)
251 {
252 int rets[1] = { OF_FAILURE };
254 of_call("getproplen", 2, 1, rets, ph, name);
255 if (rets[0] == OF_FAILURE) {
256 DBG("getproplen 0x%x %s -> FAILURE\n", ph, name);
257 return OF_FAILURE;
258 }
259 DBG("getproplen 0x%x %s -> 0x%x\n", ph, name, rets[0]);
260 return rets[0];
261 }
263 static int __init of_package_to_path(int ph, char *buffer, u32 buflen)
264 {
265 int rets[1] = { OF_FAILURE };
267 of_call("package-to-path", 3, 1, rets, ph, buffer, buflen);
268 if (rets[0] == OF_FAILURE) {
269 DBG("%s 0x%x -> FAILURE\n", __func__, ph);
270 return OF_FAILURE;
271 }
272 DBG("%s 0x%x %s -> 0x%x\n", __func__, ph, buffer, rets[0]);
273 if (rets[0] <= buflen)
274 buffer[rets[0]] = '\0';
275 return rets[0];
276 }
278 static int __init of_nextprop(int ph, const char *name, void *buf)
279 {
280 int rets[1] = { OF_FAILURE };
282 of_call("nextprop", 3, 1, rets, ph, name, buf);
284 if (rets[0] == OF_FAILURE) {
285 DBG("nextprop 0x%x %s -> FAILURE\n", ph, name);
286 return OF_FAILURE;
287 }
289 DBG("nextprop 0x%x %s -> %s\n", ph, name, (char *)buf);
290 return rets[0];
291 }
293 static int __init of_instance_to_path(int ih, char *buffer, u32 buflen)
294 {
295 int rets[1] = { OF_FAILURE };
297 if (of_call("instance-to-path", 3, 1, rets, ih, buffer, buflen)
298 == OF_FAILURE)
299 return OF_FAILURE;
301 if (rets[0] <= buflen)
302 buffer[rets[0]] = '\0';
303 return rets[0];
304 }
306 static int __init of_start_cpu(int cpu, u32 pc, u32 reg)
307 {
308 int ret;
310 ret = of_call("start-cpu", 3, 0, NULL, cpu, pc, reg);
312 return ret;
313 }
315 static void __init of_test(const char *of_method_name)
316 {
317 int rets[1] = { OF_FAILURE };
319 of_call("test", 1, 1, rets, of_method_name);
320 if (rets[0] == OF_FAILURE ) {
321 of_printf("Warning: possibly no OF method %s.\n"
322 "(Ignore this warning on PIBS.)\n", of_method_name);
323 }
324 }
326 static int __init of_claim(u32 virt, u32 size, u32 align)
327 {
328 int rets[1] = { OF_FAILURE };
330 of_call("claim", 3, 1, rets, virt, size, align);
331 if (rets[0] == OF_FAILURE) {
332 DBG("%s 0x%08x 0x%08x 0x%08x -> FAIL\n", __func__, virt, size, align);
333 return OF_FAILURE;
334 }
336 DBG("%s 0x%08x 0x%08x 0x%08x -> 0x%08x\n", __func__, virt, size, align,
337 rets[0]);
338 return rets[0];
339 }
341 static int __init of_instance_to_package(int ih)
342 {
343 int rets[1] = { OF_FAILURE };
345 of_call("instance-to-package", 1, 1, rets, ih);
346 if (rets[0] == OF_FAILURE)
347 return OF_FAILURE;
349 return rets[0];
350 }
352 static int __init of_getparent(int ph)
353 {
354 int rets[1] = { OF_FAILURE };
356 of_call("parent", 1, 1, rets, ph);
358 DBG("getparent 0x%x -> 0x%x\n", ph, rets[0]);
359 return rets[0];
360 }
362 static int __init of_open(const char *devspec)
363 {
364 int rets[1] = { OF_FAILURE };
366 of_call("open", 1, 1, rets, devspec);
367 return rets[0];
368 }
370 static void boot_of_probemem(multiboot_info_t *mbi)
371 {
372 int root;
373 int p;
374 u32 addr_cells = 1;
375 u32 size_cells = 1;
376 int rc;
377 int mcount = 0;
378 static memory_map_t mmap[16];
380 root = of_finddevice("/");
381 p = of_getchild(root);
383 /* code is writen to assume sizes of 1 */
384 of_getprop(root, "#address-cells", &addr_cells, sizeof (addr_cells));
385 of_getprop(root, "#size-cells", &size_cells, sizeof (size_cells));
386 DBG("%s: address_cells=%d size_cells=%d\n",
387 __func__, addr_cells, size_cells);
389 do {
390 const char memory[] = "memory";
391 char type[32];
393 type[0] = '\0';
395 of_getprop(p, "device_type", type, sizeof (type));
396 if (strncmp(type, memory, sizeof (memory)) == 0) {
397 u32 reg[48];
398 u32 al, ah, ll, lh;
399 int r;
401 rc = of_getprop(p, "reg", reg, sizeof (reg));
402 if (rc == OF_FAILURE) {
403 of_panic("no reg property for memory node: 0x%x.\n", p);
404 }
405 int l = rc/sizeof(u32); /* number reg element */
406 DBG("%s: number of bytes in property 'reg' %d\n",
407 __func__, rc);
409 r = 0;
410 while (r < l) {
411 al = ah = ll = lh = 0;
412 if (addr_cells == 2) {
413 ah = reg[r++];
414 if (r >= l)
415 break; /* partial line. Skip */
416 al = reg[r++];
417 if (r >= l)
418 break; /* partial line. Skip */
419 } else {
420 al = reg[r++];
421 if (r >= l)
422 break; /* partial line. Skip */
423 }
424 if (size_cells == 2) {
425 lh = reg[r++];
426 if (r >= l)
427 break; /* partial line. Skip */
428 ll = reg[r++];
429 } else {
430 ll = reg[r++];
431 }
433 if ((ll != 0) || (lh != 0)) {
434 mmap[mcount].size = 20; /* - size field */
435 mmap[mcount].type = 1; /* Regular ram */
436 mmap[mcount].length_high = lh;
437 mmap[mcount].length_low = ll;
438 mmap[mcount].base_addr_high = ah;
439 mmap[mcount].base_addr_low = al;
440 of_printf("%s: memory 0x%016lx[0x%08lx]\n",
441 __func__,
442 (u64)(((u64)mmap[mcount].base_addr_high << 32)
443 | mmap[mcount].base_addr_low),
444 (u64)(((u64)mmap[mcount].length_high << 32)
445 | mmap[mcount].length_low));
446 ++mcount;
447 }
448 }
449 }
450 p = of_getpeer(p);
451 } while (p != OF_FAILURE && p != 0);
453 if (mcount > 0) {
454 mbi->flags |= MBI_MEMMAP;
455 mbi->mmap_length = sizeof (mmap[0]) * mcount;
456 mbi->mmap_addr = (ulong)mmap;
457 }
458 }
460 static void boot_of_bootargs(multiboot_info_t *mbi)
461 {
462 int rc;
464 if (builtin_cmdline[0] == '\0') {
465 rc = of_getprop(bof_chosen, "bootargs", builtin_cmdline,
466 CONFIG_CMDLINE_SIZE);
467 if (rc > CONFIG_CMDLINE_SIZE)
468 of_panic("bootargs[] not big enough for /chosen/bootargs\n");
469 }
471 mbi->flags |= MBI_CMDLINE;
472 mbi->cmdline = (ulong)builtin_cmdline;
474 of_printf("bootargs = %s\n", builtin_cmdline);
475 }
477 static int save_props(void *m, ofdn_t n, int pkg)
478 {
479 int ret;
480 char name[128];
481 int result = 1;
482 int found_name = 0;
483 int found_device_type = 0;
484 const char name_str[] = "name";
485 const char devtype_str[] = "device_type";
487 /* get first */
488 result = of_nextprop(pkg, 0, name);
490 while (result > 0) {
491 int sz;
492 u64 obj[1024];
494 sz = of_getproplen(pkg, name);
495 if (sz >= 0) {
496 ret = OF_SUCCESS;
497 } else {
498 ret = OF_FAILURE;
499 }
501 if (ret == OF_SUCCESS) {
502 int actual = 0;
503 ofdn_t pos;
505 if (sz > 0) {
506 if (sz > sizeof (obj)) {
507 of_panic("obj array not big enough for 0x%x\n", sz);
508 }
509 actual = of_getprop(pkg, name, obj, sz);
510 if (actual > sz)
511 of_panic("obj too small");
512 }
514 if (strncmp(name, name_str, sizeof(name_str)) == 0) {
515 found_name = 1;
516 }
518 if (strncmp(name, devtype_str, sizeof(devtype_str)) == 0) {
519 found_device_type = 1;
520 }
522 pos = ofd_prop_add(m, n, name, obj, actual);
523 if (pos == 0)
524 of_panic("prop_create");
525 }
527 result = of_nextprop(pkg, name, name);
528 }
530 return 1;
531 }
534 static void do_pkg(void *m, ofdn_t n, int p, char *path, size_t psz)
535 {
536 int pnext;
537 ofdn_t nnext;
538 int sz;
540 retry:
541 save_props(m, n, p);
543 /* do children first */
544 pnext = of_getchild(p);
546 if (pnext != 0) {
547 sz = of_package_to_path(pnext, path, psz);
548 if (sz == OF_FAILURE)
549 of_panic("bad path\n");
551 nnext = ofd_node_child_create(m, n, path, sz);
552 if (nnext == 0)
553 of_panic("out of mem\n");
555 do_pkg(m, nnext, pnext, path, psz);
556 }
558 /* do peer */
559 pnext = of_getpeer(p);
561 if (pnext != 0) {
562 sz = of_package_to_path(pnext, path, psz);
564 nnext = ofd_node_peer_create(m, n, path, sz);
565 if (nnext <= 0)
566 of_panic("out of space in OFD tree.\n");
568 n = nnext;
569 p = pnext;
570 goto retry;
571 }
572 }
574 static int pkg_save(void *mem)
575 {
576 int root;
577 char path[256];
578 int r;
580 path[0]='/';
581 path[1]='\0';
583 /* get root */
584 root = of_getpeer(0);
585 if (root == OF_FAILURE)
586 of_panic("no root package\n");
588 do_pkg(mem, OFD_ROOT, root, path, sizeof(path));
590 r = (((ofdn_t *)mem)[1] + 1) * sizeof (u64);
592 of_printf("%s: saved device tree in 0x%x bytes\n", __func__, r);
594 return r;
595 }
597 static int boot_of_fixup_refs(void *mem)
598 {
599 static const char *fixup_props[] = {
600 "interrupt-parent",
601 };
602 int i;
603 int count = 0;
605 for (i = 0; i < ARRAY_SIZE(fixup_props); i++) {
606 ofdn_t c;
607 const char *name = fixup_props[i];
609 c = ofd_node_find_by_prop(mem, OFD_ROOT, name, NULL, 0);
610 while (c > 0) {
611 const char *path;
612 int rp;
613 int ref;
614 ofdn_t dp;
615 int rc;
616 ofdn_t upd;
617 char ofpath[256];
619 path = ofd_node_path(mem, c);
620 if (path == NULL)
621 of_panic("no path to found prop: %s\n", name);
623 rp = of_finddevice(path);
624 if (rp == OF_FAILURE)
625 of_panic("no real device for: name %s, path %s\n",
626 name, path);
627 /* Note: In theory 0 is a valid node handle but it is highly
628 * unlikely.
629 */
630 if (rp == 0) {
631 of_panic("%s: of_finddevice returns 0 for path %s\n",
632 __func__, path);
633 }
635 rc = of_getprop(rp, name, &ref, sizeof(ref));
636 if ((rc == OF_FAILURE) || (rc == 0))
637 of_panic("no prop: name %s, path %s, device 0x%x\n",
638 name, path, rp);
640 rc = of_package_to_path(ref, ofpath, sizeof (ofpath));
641 if (rc == OF_FAILURE)
642 of_panic("no package: name %s, path %s, device 0x%x,\n"
643 "ref 0x%x\n", name, path, rp, ref);
645 dp = ofd_node_find(mem, ofpath);
646 if (dp <= 0)
647 of_panic("no ofd node for OF node[0x%x]: %s\n",
648 ref, ofpath);
650 ref = dp;
652 upd = ofd_prop_add(mem, c, name, &ref, sizeof(ref));
653 if (upd <= 0)
654 of_panic("update failed: %s\n", name);
656 #ifdef DEBUG
657 of_printf("%s: %s/%s -> %s\n", __func__,
658 path, name, ofpath);
659 #endif
660 ++count;
661 c = ofd_node_find_next(mem, c);
662 }
663 }
664 return count;
665 }
667 static int boot_of_fixup_chosen(void *mem)
668 {
669 int ch;
670 ofdn_t dn;
671 ofdn_t dc;
672 int val;
673 int rc;
674 char ofpath[256];
676 ch = of_finddevice("/chosen");
677 if (ch == OF_FAILURE)
678 of_panic("/chosen not found\n");
680 rc = of_getprop(ch, "cpu", &val, sizeof (val));
682 if (rc != OF_FAILURE) {
683 rc = of_instance_to_path(val, ofpath, sizeof (ofpath));
685 if (rc > 0) {
686 dn = ofd_node_find(mem, ofpath);
687 if (dn <= 0)
688 of_panic("no node for: %s\n", ofpath);
690 ofd_boot_cpu = dn;
691 val = dn;
693 dn = ofd_node_find(mem, "/chosen");
694 if (dn <= 0)
695 of_panic("no /chosen node\n");
697 dc = ofd_prop_add(mem, dn, "cpu", &val, sizeof (val));
698 if (dc <= 0)
699 of_panic("could not fix /chosen/cpu\n");
700 rc = 1;
701 } else {
702 of_printf("*** can't find path to booting cpu, "
703 "SMP is disabled\n");
704 ofd_boot_cpu = -1;
705 }
706 }
707 return rc;
708 }
710 static ulong space_base;
712 /*
713 * The following function is necessary because we cannot depend on all
714 * FW to actually allocate us any space, so we look for it _hoping_
715 * that at least is will fail if we try to claim something that
716 * belongs to FW. This hope does not seem to be true on some version
717 * of PIBS.
718 */
719 static ulong find_space(u32 size, u32 align, multiboot_info_t *mbi)
720 {
721 memory_map_t *map = (memory_map_t *)((ulong)mbi->mmap_addr);
722 ulong eomem = ((u64)map->length_high << 32) | (u64)map->length_low;
723 ulong base;
725 if (size == 0)
726 return 0;
728 if (align == 0)
729 of_panic("cannot call %s() with align of 0\n", __func__);
731 #ifdef BROKEN_CLAIM_WORKAROUND
732 {
733 static int broken_claim;
734 if (!broken_claim) {
735 /* just try and claim it to the FW chosen address */
736 base = of_claim(0, size, align);
737 if (base != OF_FAILURE)
738 return base;
739 of_printf("%s: Firmware does not allocate memory for you\n",
740 __func__);
741 broken_claim = 1;
742 }
743 }
744 #endif
746 of_printf("%s base=0x%016lx eomem=0x%016lx size=0x%08x align=0x%x\n",
747 __func__, space_base, eomem, size, align);
748 base = ALIGN_UP(space_base, PAGE_SIZE);
750 while ((base + size) < rma_size(cpu_default_rma_order_pages())) {
751 if (of_claim(base, size, 0) != OF_FAILURE) {
752 space_base = base + size;
753 return base;
754 }
755 base += (PAGE_SIZE > align) ? PAGE_SIZE : align;
756 }
757 of_panic("Cannot find memory in the RMA\n");
758 }
760 /* PIBS Version 1.05.0000 04/26/2005 has an incorrect /ht/isa/ranges
761 * property. The values are bad, and it doesn't even have the
762 * right number of cells. */
764 static void __init boot_of_fix_maple(void)
765 {
766 int isa;
767 const char *ranges = "ranges";
768 u32 isa_ranges[3];
769 const u32 isa_test[] = { 0x00000001, 0xf4000000, 0x00010000 };
770 const u32 isa_fixed[] = {
771 0x00000001,
772 0x00000000,
773 0x00000000, /* 0xf4000000, matt says this */
774 0x00000000,
775 0x00000000,
776 0x00010000
777 };
779 isa = of_finddevice("/ht@0/isa@4");
780 if (isa != OF_FAILURE) {
781 if (of_getproplen(isa, ranges) == sizeof (isa_test)) {
782 of_getprop(isa, ranges, isa_ranges, sizeof (isa_ranges));
783 if (memcmp(isa_ranges, isa_test, sizeof (isa_test)) == 0) {
784 int rc;
786 of_printf("OF: fixing bogus ISA range on maple\n");
787 rc = of_setprop(isa, ranges, isa_fixed, sizeof (isa_fixed));
788 if (rc == OF_FAILURE) {
789 of_panic("of_setprop() failed\n");
790 }
791 }
792 }
793 }
794 }
796 static int __init boot_of_serial(void *oft)
797 {
798 int n;
799 int p;
800 int rc;
801 u32 val[3];
802 char buf[128];
804 n = of_instance_to_package(of_out);
805 if (n == OF_FAILURE) {
806 of_panic("instance-to-package of /chosen/stdout: failed\n");
807 }
809 /* Prune all serial devices from the device tree, including the
810 * one pointed to by /chosen/stdout, because a guest domain can
811 * initialize them and in so doing corrupt our console output.
812 */
813 for (p = n; p > 0; p = of_getpeer(p)) {
814 char type[32];
816 rc = of_package_to_path(p, buf, sizeof(buf));
817 if (rc == OF_FAILURE)
818 of_panic("package-to-path failed\n");
820 rc = of_getprop(p, "device_type", type, sizeof (type));
821 if (rc == OF_FAILURE) {
822 of_printf("%s: fetching type of `%s' failed\n", __func__, buf);
823 continue;
824 }
826 if (strcmp(type, "serial") != 0)
827 continue;
829 of_printf("pruning `%s' from devtree\n", buf);
830 rc = ofd_prune_path(oft, buf);
831 if (rc < 0)
832 of_panic("prune of `%s' failed\n", buf);
833 }
835 p = of_getparent(n);
836 if (p == OF_FAILURE) {
837 of_panic("no parent for: 0x%x\n", n);
838 }
840 buf[0] = '\0';
841 of_getprop(p, "device_type", buf, sizeof (buf));
842 if (strstr(buf, "isa") == NULL) {
843 of_panic("only ISA UARTS supported\n");
844 }
846 /* should get this from devtree */
847 isa_io_base = 0xf4000000;
848 of_printf("%s: ISA base: 0x%lx\n", __func__, isa_io_base);
850 buf[0] = '\0';
851 of_getprop(n, "device_type", buf, sizeof (buf));
852 if (strstr(buf, "serial") == NULL) {
853 of_panic("only UARTS supported\n");
854 }
856 rc = of_getprop(n, "reg", val, sizeof (val));
857 if (rc == OF_FAILURE) {
858 of_panic("%s: no location for serial port\n", __func__);
859 }
861 ns16550.baud = BAUD_AUTO;
862 ns16550.data_bits = 8;
863 ns16550.parity = 'n';
864 ns16550.stop_bits = 1;
866 rc = of_getprop(n, "interrupts", val, sizeof (val));
867 if (rc == OF_FAILURE) {
868 of_printf("%s: no ISRC, forcing poll mode\n", __func__);
869 ns16550.irq = 0;
870 } else {
871 ns16550.irq = val[0];
872 of_printf("%s: ISRC=0x%x, but forcing poll mode\n",
873 __func__, ns16550.irq);
874 ns16550.irq = 0;
875 }
877 return 1;
878 }
880 static int __init boot_of_rtas(module_t *mod, multiboot_info_t *mbi)
881 {
882 int rtas_node;
883 int rtas_instance;
884 uint size = 0;
885 int res[2];
886 int mem;
887 int ret;
889 rtas_node = of_finddevice("/rtas");
891 if (rtas_node <= 0) {
892 of_printf("No RTAS, Xen has no power control\n");
893 return 0;
894 }
895 of_getprop(rtas_node, "rtas-size", &size, sizeof (size));
896 if (size == 0) {
897 of_printf("RTAS, has no size\n");
898 return 0;
899 }
901 rtas_instance = of_open("/rtas");
902 if (rtas_instance == OF_FAILURE) {
903 of_printf("RTAS, could not open\n");
904 return 0;
905 }
907 size = ALIGN_UP(size, PAGE_SIZE);
909 mem = find_space(size, PAGE_SIZE, mbi);
910 if (mem == 0)
911 of_panic("Could not allocate RTAS tree\n");
913 ret = of_call("call-method", 3, 2, res,
914 "instantiate-rtas", rtas_instance, mem);
915 if (ret == OF_FAILURE) {
916 of_printf("RTAS, could not open\n");
917 return 0;
918 }
920 rtas_entry = res[1];
921 rtas_base = mem;
922 rtas_end = mem + size;
923 rtas_msr = of_msr;
925 mod->mod_start = rtas_base;
926 mod->mod_end = rtas_end;
927 return 1;
928 }
930 static void * __init boot_of_devtree(module_t *mod, multiboot_info_t *mbi)
931 {
932 void *oft;
933 ulong oft_sz = 48 * PAGE_SIZE;
935 /* snapshot the tree */
936 oft = (void*)find_space(oft_sz, PAGE_SIZE, mbi);
937 if (oft == 0)
938 of_panic("Could not allocate OFD tree\n");
940 of_printf("creating oftree\n");
941 of_test("package-to-path");
942 oft = ofd_create(oft, oft_sz);
943 pkg_save(oft);
945 if (ofd_size(oft) > oft_sz)
946 of_panic("Could not fit all of native devtree\n");
948 boot_of_fixup_refs(oft);
949 boot_of_fixup_chosen(oft);
951 if (ofd_size(oft) > oft_sz)
952 of_panic("Could not fit all devtree fixups\n");
954 ofd_walk(oft, OFD_ROOT, /* add_hype_props */ NULL, 2);
956 mod->mod_start = (ulong)oft;
957 mod->mod_end = mod->mod_start + oft_sz;
958 of_printf("%s: devtree mod @ 0x%016x[0x%x]\n", __func__,
959 mod->mod_start, mod->mod_end);
961 return oft;
962 }
964 static void * __init boot_of_module(ulong r3, ulong r4, multiboot_info_t *mbi)
965 {
966 static module_t mods[4];
967 ulong mod0_start;
968 ulong mod0_size;
969 static const char sepr[] = " -- ";
970 extern char dom0_start[] __attribute__ ((weak));
971 extern char dom0_size[] __attribute__ ((weak));
972 const char *p;
973 int mod;
974 void *oft;
976 if ((r3 > 0) && (r4 > 0)) {
977 /* was it handed to us in registers ? */
978 mod0_start = r3;
979 mod0_size = r4;
980 of_printf("%s: Dom0 was loaded and found using r3/r4:"
981 "0x%lx[size 0x%lx]\n",
982 __func__, mod0_start, mod0_size);
983 } else {
984 /* see if it is in the boot params */
985 p = strstr((char *)((ulong)mbi->cmdline), "dom0_start=");
986 if ( p != NULL) {
987 p += 11;
988 mod0_start = simple_strtoul(p, NULL, 0);
990 p = strstr((char *)((ulong)mbi->cmdline), "dom0_size=");
991 p += 10;
992 mod0_size = simple_strtoul(p, NULL, 0);
993 of_printf("%s: Dom0 was loaded and found using cmdline:"
994 "0x%lx[size 0x%lx]\n",
995 __func__, mod0_start, mod0_size);
996 } else if ( ((ulong)dom0_start != 0) && ((ulong)dom0_size != 0) ) {
997 /* was it linked in ? */
999 mod0_start = (ulong)dom0_start;
1000 mod0_size = (ulong)dom0_size;
1001 of_printf("%s: Dom0 is linked in: 0x%lx[size 0x%lx]\n",
1002 __func__, mod0_start, mod0_size);
1003 } else {
1004 mod0_start = (ulong)_end;
1005 mod0_size = 0;
1006 of_printf("%s: FYI Dom0 is unknown, will be caught later\n",
1007 __func__);
1011 if (mod0_size > 0) {
1012 const char *c = (const char *)mod0_start;
1014 of_printf("mod0: %o %c %c %c\n", c[0], c[1], c[2], c[3]);
1017 space_base = (ulong)_end;
1019 mod = 0;
1020 mods[mod].mod_start = mod0_start;
1021 mods[mod].mod_end = mod0_start + mod0_size;
1023 of_printf("%s: dom0 mod @ 0x%016x[0x%x]\n", __func__,
1024 mods[mod].mod_start, mods[mod].mod_end);
1025 p = strstr((char *)(ulong)mbi->cmdline, sepr);
1026 if (p != NULL) {
1027 /* Xen proper should never know about the dom0 args. */
1028 *(char *)p = '\0';
1029 p += sizeof (sepr) - 1;
1030 mods[mod].string = (u32)(ulong)p;
1031 of_printf("%s: dom0 mod string: %s\n", __func__, p);
1034 ++mod;
1035 if (boot_of_rtas(&mods[mod], mbi))
1036 ++mod;
1038 oft = boot_of_devtree(&mods[mod], mbi);
1039 if (oft == NULL)
1040 of_panic("%s: boot_of_devtree failed\n", __func__);
1042 ++mod;
1044 mbi->flags |= MBI_MODULES;
1045 mbi->mods_count = mod;
1046 mbi->mods_addr = (u32)mods;
1048 return oft;
1051 static int __init boot_of_cpus(void)
1053 int cpus_node, cpu_node;
1054 int bootcpu_instance, bootcpu_node;
1055 int logical;
1056 int result;
1057 s32 cpuid;
1058 u32 cpu_clock[2];
1059 extern uint cpu_hard_id[NR_CPUS];
1061 /* Look up which CPU we are running on right now and get all info
1062 * from there */
1063 result = of_getprop(bof_chosen, "cpu",
1064 &bootcpu_instance, sizeof (bootcpu_instance));
1065 if (result == OF_FAILURE)
1066 of_panic("Failed to look up boot cpu instance\n");
1068 bootcpu_node = of_instance_to_package(bootcpu_instance);
1069 if (result == OF_FAILURE)
1070 of_panic("Failed to look up boot cpu package\n");
1072 cpu_node = bootcpu_node;
1074 result = of_getprop(cpu_node, "timebase-frequency", &timebase_freq,
1075 sizeof(timebase_freq));
1076 if (result == OF_FAILURE) {
1077 of_panic("Couldn't get timebase frequency!\n");
1079 of_printf("OF: timebase-frequency = %d Hz\n", timebase_freq);
1081 result = of_getprop(cpu_node, "clock-frequency",
1082 &cpu_clock, sizeof(cpu_clock));
1083 if (result == OF_FAILURE || (result !=4 && result != 8)) {
1084 of_panic("Couldn't get clock frequency!\n");
1086 cpu_khz = cpu_clock[0];
1087 if (result == 8) {
1088 cpu_khz <<= 32;
1089 cpu_khz |= cpu_clock[1];
1091 cpu_khz /= 1000;
1092 of_printf("OF: clock-frequency = %ld KHz\n", cpu_khz);
1094 /* We want a continuous logical cpu number space and we'll make
1095 * the booting CPU logical 0. */
1096 cpu_set(0, cpu_present_map);
1097 cpu_set(0, cpu_online_map);
1098 cpu_set(0, cpu_possible_map);
1100 result = of_getprop(cpu_node, "reg", &cpuid, sizeof(cpuid));
1101 cpu_hard_id[0] = cpuid;
1103 /* Spin up all CPUS, even if there are more than NR_CPUS or we are
1104 * runnign nosmp, because Open Firmware has them spinning on cache
1105 * lines which will eventually be scrubbed, which could lead to
1106 * random CPU activation.
1107 */
1109 /* Find the base of the multi-CPU package node */
1110 cpus_node = of_finddevice("/cpus");
1111 if (cpus_node <= 0) {
1112 of_printf("Single Processor System\n");
1113 return 1;
1115 /* Start with the first child */
1116 cpu_node = of_getchild(cpus_node);
1118 for (logical = 1; cpu_node > 0; logical++) {
1119 unsigned int ping, pong;
1120 unsigned long now, then, timeout;
1122 if (cpu_node == bootcpu_node) {
1123 /* same CPU as boot CPU shich we have already made 0 so
1124 * reduce the logical count */
1125 --logical;
1126 } else {
1127 result = of_getprop(cpu_node, "reg", &cpuid, sizeof(cpuid));
1128 if (result == OF_FAILURE)
1129 of_panic("cpuid lookup failed\n");
1131 cpu_hard_id[logical] = cpuid;
1133 of_printf("spinning up secondary processor #%d: ", logical);
1135 __spin_ack = ~0x0;
1136 ping = __spin_ack;
1137 pong = __spin_ack;
1138 of_printf("ping = 0x%x: ", ping);
1140 mb();
1141 result = of_start_cpu(cpu_node, (ulong)spin_start, logical);
1142 if (result == OF_FAILURE)
1143 of_panic("start cpu failed\n");
1145 /* We will give the secondary processor five seconds to reply. */
1146 then = mftb();
1147 timeout = then + (5 * timebase_freq);
1149 do {
1150 now = mftb();
1151 if (now >= timeout) {
1152 of_printf("BROKEN: ");
1153 break;
1156 mb();
1157 pong = __spin_ack;
1158 } while (pong == ping);
1159 of_printf("pong = 0x%x\n", pong);
1161 if (pong != ping) {
1162 cpu_set(logical, cpu_present_map);
1163 cpu_set(logical, cpu_possible_map);
1166 cpu_node = of_getpeer(cpu_node);
1168 return 1;
1171 multiboot_info_t __init *boot_of_init(
1172 ulong r3, ulong r4, ulong vec, ulong r6, ulong r7, ulong orig_msr)
1174 static multiboot_info_t mbi;
1175 void *oft;
1177 of_vec = vec;
1178 of_msr = orig_msr;
1180 bof_chosen = of_finddevice("/chosen");
1181 of_getprop(bof_chosen, "stdout", &of_out, sizeof (of_out));
1183 of_printf("%s\n", "---------------------------------------------------");
1184 of_printf("OF: Xen/PPC version %d.%d%s (%s@%s) (%s) %s\n",
1185 xen_major_version(), xen_minor_version(), xen_extra_version(),
1186 xen_compile_by(), xen_compile_domain(),
1187 xen_compiler(), xen_compile_date());
1189 of_printf("%s args: 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n"
1190 "boot msr: 0x%lx\n",
1191 __func__,
1192 r3, r4, vec, r6, r7, orig_msr);
1194 if ((vec >= (ulong)_start) && (vec <= (ulong)_end)) {
1195 of_printf("Hmm.. OF[0x%lx] seems to have stepped on our image "
1196 "that ranges: %p .. %p.\n HANG!\n",
1197 vec, _start, _end);
1199 of_printf("%s: _start %p _end %p 0x%lx\n", __func__, _start, _end, r6);
1201 boot_of_fix_maple();
1202 boot_of_probemem(&mbi);
1203 boot_of_bootargs(&mbi);
1204 oft = boot_of_module(r3, r4, &mbi);
1205 boot_of_cpus();
1206 boot_of_serial(oft);
1208 /* end of OF */
1209 of_printf("Quiescing Open Firmware ...\n");
1210 of_call("quiesce", 0, 0, NULL);
1212 return &mbi;
1215 /*
1216 * Local variables:
1217 * mode: C
1218 * c-set-style: "BSD"
1219 * c-basic-offset: 4
1220 * tab-width: 4
1221 * indent-tabs-mode: nil
1222 * End:
1223 */