aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/syslib/prom_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc/syslib/prom_init.c')
-rw-r--r--arch/ppc/syslib/prom_init.c1011
1 files changed, 0 insertions, 1011 deletions
diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c
deleted file mode 100644
index df14422ae1c..00000000000
--- a/arch/ppc/syslib/prom_init.c
+++ /dev/null
@@ -1,1011 +0,0 @@
1/*
2 * Note that prom_init() and anything called from prom_init()
3 * may be running at an address that is different from the address
4 * that it was linked at. References to static data items are
5 * handled by compiling this file with -mrelocatable-lib.
6 */
7
8#include <linux/config.h>
9#include <linux/kernel.h>
10#include <linux/string.h>
11#include <linux/init.h>
12#include <linux/threads.h>
13#include <linux/spinlock.h>
14#include <linux/ioport.h>
15#include <linux/pci.h>
16#include <linux/slab.h>
17#include <linux/bitops.h>
18
19#include <asm/sections.h>
20#include <asm/prom.h>
21#include <asm/page.h>
22#include <asm/irq.h>
23#include <asm/io.h>
24#include <asm/smp.h>
25#include <asm/bootx.h>
26#include <asm/system.h>
27#include <asm/mmu.h>
28#include <asm/pgtable.h>
29#include <asm/bootinfo.h>
30#include <asm/btext.h>
31#include <asm/pci-bridge.h>
32#include <asm/open_pic.h>
33#include <asm/cacheflush.h>
34
35#ifdef CONFIG_LOGO_LINUX_CLUT224
36#include <linux/linux_logo.h>
37extern const struct linux_logo logo_linux_clut224;
38#endif
39
40/*
41 * Properties whose value is longer than this get excluded from our
42 * copy of the device tree. This way we don't waste space storing
43 * things like "driver,AAPL,MacOS,PowerPC" properties. But this value
44 * does need to be big enough to ensure that we don't lose things
45 * like the interrupt-map property on a PCI-PCI bridge.
46 */
47#define MAX_PROPERTY_LENGTH 4096
48
49#ifndef FB_MAX /* avoid pulling in all of the fb stuff */
50#define FB_MAX 8
51#endif
52
53#define ALIGNUL(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
54
55typedef u32 prom_arg_t;
56
57struct prom_args {
58 const char *service;
59 int nargs;
60 int nret;
61 prom_arg_t args[10];
62};
63
64struct pci_address {
65 unsigned a_hi;
66 unsigned a_mid;
67 unsigned a_lo;
68};
69
70struct pci_reg_property {
71 struct pci_address addr;
72 unsigned size_hi;
73 unsigned size_lo;
74};
75
76struct pci_range {
77 struct pci_address addr;
78 unsigned phys;
79 unsigned size_hi;
80 unsigned size_lo;
81};
82
83struct isa_reg_property {
84 unsigned space;
85 unsigned address;
86 unsigned size;
87};
88
89struct pci_intr_map {
90 struct pci_address addr;
91 unsigned dunno;
92 phandle int_ctrler;
93 unsigned intr;
94};
95
96static void prom_exit(void);
97static int call_prom(const char *service, int nargs, int nret, ...);
98static int call_prom_ret(const char *service, int nargs, int nret,
99 prom_arg_t *rets, ...);
100static void prom_print_hex(unsigned int v);
101static int prom_set_color(ihandle ih, int i, int r, int g, int b);
102static int prom_next_node(phandle *nodep);
103static unsigned long check_display(unsigned long mem);
104static void setup_disp_fake_bi(ihandle dp);
105static unsigned long copy_device_tree(unsigned long mem_start,
106 unsigned long mem_end);
107static unsigned long inspect_node(phandle node, struct device_node *dad,
108 unsigned long mem_start, unsigned long mem_end,
109 struct device_node ***allnextpp);
110static void prom_hold_cpus(unsigned long mem);
111static void prom_instantiate_rtas(void);
112static void * early_get_property(unsigned long base, unsigned long node,
113 char *prop);
114
115prom_entry prom __initdata;
116ihandle prom_chosen __initdata;
117ihandle prom_stdout __initdata;
118
119static char *prom_display_paths[FB_MAX] __initdata;
120static phandle prom_display_nodes[FB_MAX] __initdata;
121static unsigned int prom_num_displays __initdata;
122static ihandle prom_disp_node __initdata;
123char *of_stdout_device __initdata;
124
125unsigned int rtas_data; /* physical pointer */
126unsigned int rtas_entry; /* physical pointer */
127unsigned int rtas_size;
128unsigned int old_rtas;
129
130boot_infos_t *boot_infos;
131char *bootpath;
132char *bootdevice;
133struct device_node *allnodes;
134
135extern char *klimit;
136
137static void __init
138prom_exit(void)
139{
140 struct prom_args args;
141
142 args.service = "exit";
143 args.nargs = 0;
144 args.nret = 0;
145 prom(&args);
146 for (;;) /* should never get here */
147 ;
148}
149
150static int __init
151call_prom(const char *service, int nargs, int nret, ...)
152{
153 va_list list;
154 int i;
155 struct prom_args prom_args;
156
157 prom_args.service = service;
158 prom_args.nargs = nargs;
159 prom_args.nret = nret;
160 va_start(list, nret);
161 for (i = 0; i < nargs; ++i)
162 prom_args.args[i] = va_arg(list, prom_arg_t);
163 va_end(list);
164 for (i = 0; i < nret; ++i)
165 prom_args.args[i + nargs] = 0;
166 prom(&prom_args);
167 return prom_args.args[nargs];
168}
169
170static int __init
171call_prom_ret(const char *service, int nargs, int nret, prom_arg_t *rets, ...)
172{
173 va_list list;
174 int i;
175 struct prom_args prom_args;
176
177 prom_args.service = service;
178 prom_args.nargs = nargs;
179 prom_args.nret = nret;
180 va_start(list, rets);
181 for (i = 0; i < nargs; ++i)
182 prom_args.args[i] = va_arg(list, int);
183 va_end(list);
184 for (i = 0; i < nret; ++i)
185 prom_args.args[i + nargs] = 0;
186 prom(&prom_args);
187 for (i = 1; i < nret; ++i)
188 rets[i-1] = prom_args.args[nargs + i];
189 return prom_args.args[nargs];
190}
191
192void __init
193prom_print(const char *msg)
194{
195 const char *p, *q;
196
197 if (prom_stdout == 0)
198 return;
199
200 for (p = msg; *p != 0; p = q) {
201 for (q = p; *q != 0 && *q != '\n'; ++q)
202 ;
203 if (q > p)
204 call_prom("write", 3, 1, prom_stdout, p, q - p);
205 if (*q != 0) {
206 ++q;
207 call_prom("write", 3, 1, prom_stdout, "\r\n", 2);
208 }
209 }
210}
211
212static void __init
213prom_print_hex(unsigned int v)
214{
215 char buf[16];
216 int i, c;
217
218 for (i = 0; i < 8; ++i) {
219 c = (v >> ((7-i)*4)) & 0xf;
220 c += (c >= 10)? ('a' - 10): '0';
221 buf[i] = c;
222 }
223 buf[i] = ' ';
224 buf[i+1] = 0;
225 prom_print(buf);
226}
227
228static int __init
229prom_set_color(ihandle ih, int i, int r, int g, int b)
230{
231 return call_prom("call-method", 6, 1, "color!", ih, i, b, g, r);
232}
233
234static int __init
235prom_next_node(phandle *nodep)
236{
237 phandle node;
238
239 if ((node = *nodep) != 0
240 && (*nodep = call_prom("child", 1, 1, node)) != 0)
241 return 1;
242 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
243 return 1;
244 for (;;) {
245 if ((node = call_prom("parent", 1, 1, node)) == 0)
246 return 0;
247 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
248 return 1;
249 }
250}
251
252#ifdef CONFIG_POWER4
253/*
254 * Set up a hash table with a set of entries in it to map the
255 * first 64MB of RAM. This is used on 64-bit machines since
256 * some of them don't have BATs.
257 */
258
259static inline void make_pte(unsigned long htab, unsigned int hsize,
260 unsigned int va, unsigned int pa, int mode)
261{
262 unsigned int *pteg;
263 unsigned int hash, i, vsid;
264
265 vsid = ((va >> 28) * 0x111) << 12;
266 hash = ((va ^ vsid) >> 5) & 0x7fff80;
267 pteg = (unsigned int *)(htab + (hash & (hsize - 1)));
268 for (i = 0; i < 8; ++i, pteg += 4) {
269 if ((pteg[1] & 1) == 0) {
270 pteg[1] = vsid | ((va >> 16) & 0xf80) | 1;
271 pteg[3] = pa | mode;
272 break;
273 }
274 }
275}
276
277extern unsigned long _SDR1;
278extern PTE *Hash;
279extern unsigned long Hash_size;
280
281static void __init
282prom_alloc_htab(void)
283{
284 unsigned int hsize;
285 unsigned long htab;
286 unsigned int addr;
287
288 /*
289 * Because of OF bugs we can't use the "claim" client
290 * interface to allocate memory for the hash table.
291 * This code is only used on 64-bit PPCs, and the only
292 * 64-bit PPCs at the moment are RS/6000s, and their
293 * OF is based at 0xc00000 (the 12M point), so we just
294 * arbitrarily use the 0x800000 - 0xc00000 region for the
295 * hash table.
296 * -- paulus.
297 */
298 hsize = 4 << 20; /* POWER4 has no BATs */
299 htab = (8 << 20);
300 call_prom("claim", 3, 1, htab, hsize, 0);
301 Hash = (void *)(htab + KERNELBASE);
302 Hash_size = hsize;
303 _SDR1 = htab + __ilog2(hsize) - 18;
304
305 /*
306 * Put in PTEs for the first 64MB of RAM
307 */
308 memset((void *)htab, 0, hsize);
309 for (addr = 0; addr < 0x4000000; addr += 0x1000)
310 make_pte(htab, hsize, addr + KERNELBASE, addr,
311 _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX);
312#if 0 /* DEBUG stuff mapping the SCC */
313 make_pte(htab, hsize, 0x80013000, 0x80013000,
314 _PAGE_ACCESSED | _PAGE_NO_CACHE | _PAGE_GUARDED | PP_RWXX);
315#endif
316}
317#endif /* CONFIG_POWER4 */
318
319
320/*
321 * If we have a display that we don't know how to drive,
322 * we will want to try to execute OF's open method for it
323 * later. However, OF will probably fall over if we do that
324 * we've taken over the MMU.
325 * So we check whether we will need to open the display,
326 * and if so, open it now.
327 */
328static unsigned long __init
329check_display(unsigned long mem)
330{
331 phandle node;
332 ihandle ih;
333 int i, j;
334 char type[16], *path;
335 static unsigned char default_colors[] = {
336 0x00, 0x00, 0x00,
337 0x00, 0x00, 0xaa,
338 0x00, 0xaa, 0x00,
339 0x00, 0xaa, 0xaa,
340 0xaa, 0x00, 0x00,
341 0xaa, 0x00, 0xaa,
342 0xaa, 0xaa, 0x00,
343 0xaa, 0xaa, 0xaa,
344 0x55, 0x55, 0x55,
345 0x55, 0x55, 0xff,
346 0x55, 0xff, 0x55,
347 0x55, 0xff, 0xff,
348 0xff, 0x55, 0x55,
349 0xff, 0x55, 0xff,
350 0xff, 0xff, 0x55,
351 0xff, 0xff, 0xff
352 };
353 const unsigned char *clut;
354
355 prom_disp_node = 0;
356
357 for (node = 0; prom_next_node(&node); ) {
358 type[0] = 0;
359 call_prom("getprop", 4, 1, node, "device_type",
360 type, sizeof(type));
361 if (strcmp(type, "display") != 0)
362 continue;
363 /* It seems OF doesn't null-terminate the path :-( */
364 path = (char *) mem;
365 memset(path, 0, 256);
366 if (call_prom("package-to-path", 3, 1, node, path, 255) < 0)
367 continue;
368
369 /*
370 * If this display is the device that OF is using for stdout,
371 * move it to the front of the list.
372 */
373 mem += strlen(path) + 1;
374 i = prom_num_displays++;
375 if (of_stdout_device != 0 && i > 0
376 && strcmp(of_stdout_device, path) == 0) {
377 for (; i > 0; --i) {
378 prom_display_paths[i]
379 = prom_display_paths[i-1];
380 prom_display_nodes[i]
381 = prom_display_nodes[i-1];
382 }
383 }
384 prom_display_paths[i] = path;
385 prom_display_nodes[i] = node;
386 if (i == 0)
387 prom_disp_node = node;
388 if (prom_num_displays >= FB_MAX)
389 break;
390 }
391
392 for (j=0; j<prom_num_displays; j++) {
393 path = prom_display_paths[j];
394 node = prom_display_nodes[j];
395 prom_print("opening display ");
396 prom_print(path);
397 ih = call_prom("open", 1, 1, path);
398 if (ih == 0 || ih == (ihandle) -1) {
399 prom_print("... failed\n");
400 for (i=j+1; i<prom_num_displays; i++) {
401 prom_display_paths[i-1] = prom_display_paths[i];
402 prom_display_nodes[i-1] = prom_display_nodes[i];
403 }
404 if (--prom_num_displays > 0) {
405 prom_disp_node = prom_display_nodes[j];
406 j--;
407 } else
408 prom_disp_node = 0;
409 continue;
410 } else {
411 prom_print("... ok\n");
412 call_prom("setprop", 4, 1, node, "linux,opened", 0, 0);
413
414 /*
415 * Setup a usable color table when the appropriate
416 * method is available.
417 * Should update this to use set-colors.
418 */
419 clut = default_colors;
420 for (i = 0; i < 32; i++, clut += 3)
421 if (prom_set_color(ih, i, clut[0], clut[1],
422 clut[2]) != 0)
423 break;
424
425#ifdef CONFIG_LOGO_LINUX_CLUT224
426 clut = PTRRELOC(logo_linux_clut224.clut);
427 for (i = 0; i < logo_linux_clut224.clutsize;
428 i++, clut += 3)
429 if (prom_set_color(ih, i + 32, clut[0],
430 clut[1], clut[2]) != 0)
431 break;
432#endif /* CONFIG_LOGO_LINUX_CLUT224 */
433 }
434 }
435
436 if (prom_stdout) {
437 phandle p;
438 p = call_prom("instance-to-package", 1, 1, prom_stdout);
439 if (p && p != -1) {
440 type[0] = 0;
441 call_prom("getprop", 4, 1, p, "device_type",
442 type, sizeof(type));
443 if (strcmp(type, "display") == 0)
444 call_prom("setprop", 4, 1, p, "linux,boot-display",
445 0, 0);
446 }
447 }
448
449 return ALIGNUL(mem);
450}
451
452/* This function will enable the early boot text when doing OF booting. This
453 * way, xmon output should work too
454 */
455static void __init
456setup_disp_fake_bi(ihandle dp)
457{
458#ifdef CONFIG_BOOTX_TEXT
459 int width = 640, height = 480, depth = 8, pitch;
460 unsigned address;
461 struct pci_reg_property addrs[8];
462 int i, naddrs;
463 char name[32];
464 char *getprop = "getprop";
465
466 prom_print("Initializing fake screen: ");
467
468 memset(name, 0, sizeof(name));
469 call_prom(getprop, 4, 1, dp, "name", name, sizeof(name));
470 name[sizeof(name)-1] = 0;
471 prom_print(name);
472 prom_print("\n");
473 call_prom(getprop, 4, 1, dp, "width", &width, sizeof(width));
474 call_prom(getprop, 4, 1, dp, "height", &height, sizeof(height));
475 call_prom(getprop, 4, 1, dp, "depth", &depth, sizeof(depth));
476 pitch = width * ((depth + 7) / 8);
477 call_prom(getprop, 4, 1, dp, "linebytes",
478 &pitch, sizeof(pitch));
479 if (pitch == 1)
480 pitch = 0x1000; /* for strange IBM display */
481 address = 0;
482 call_prom(getprop, 4, 1, dp, "address",
483 &address, sizeof(address));
484 if (address == 0) {
485 /* look for an assigned address with a size of >= 1MB */
486 naddrs = call_prom(getprop, 4, 1, dp, "assigned-addresses",
487 addrs, sizeof(addrs));
488 naddrs /= sizeof(struct pci_reg_property);
489 for (i = 0; i < naddrs; ++i) {
490 if (addrs[i].size_lo >= (1 << 20)) {
491 address = addrs[i].addr.a_lo;
492 /* use the BE aperture if possible */
493 if (addrs[i].size_lo >= (16 << 20))
494 address += (8 << 20);
495 break;
496 }
497 }
498 if (address == 0) {
499 prom_print("Failed to get address\n");
500 return;
501 }
502 }
503 /* kludge for valkyrie */
504 if (strcmp(name, "valkyrie") == 0)
505 address += 0x1000;
506
507#ifdef CONFIG_POWER4
508#if CONFIG_TASK_SIZE > 0x80000000
509#error CONFIG_TASK_SIZE cannot be above 0x80000000 with BOOTX_TEXT on G5
510#endif
511 {
512 extern boot_infos_t disp_bi;
513 unsigned long va, pa, i, offset;
514 va = 0x90000000;
515 pa = address & 0xfffff000ul;
516 offset = address & 0x00000fff;
517
518 for (i=0; i<0x4000; i++) {
519 make_pte((unsigned long)Hash - KERNELBASE, Hash_size, va, pa,
520 _PAGE_ACCESSED | _PAGE_NO_CACHE |
521 _PAGE_GUARDED | PP_RWXX);
522 va += 0x1000;
523 pa += 0x1000;
524 }
525 btext_setup_display(width, height, depth, pitch, 0x90000000 | offset);
526 disp_bi.dispDeviceBase = (u8 *)address;
527 }
528#else /* CONFIG_POWER4 */
529 btext_setup_display(width, height, depth, pitch, address);
530 btext_prepare_BAT();
531#endif /* CONFIG_POWER4 */
532#endif /* CONFIG_BOOTX_TEXT */
533}
534
535/*
536 * Make a copy of the device tree from the PROM.
537 */
538static unsigned long __init
539copy_device_tree(unsigned long mem_start, unsigned long mem_end)
540{
541 phandle root;
542 unsigned long new_start;
543 struct device_node **allnextp;
544
545 root = call_prom("peer", 1, 1, (phandle)0);
546 if (root == (phandle)0) {
547 prom_print("couldn't get device tree root\n");
548 prom_exit();
549 }
550 allnextp = &allnodes;
551 mem_start = ALIGNUL(mem_start);
552 new_start = inspect_node(root, NULL, mem_start, mem_end, &allnextp);
553 *allnextp = NULL;
554 return new_start;
555}
556
557static unsigned long __init
558inspect_node(phandle node, struct device_node *dad,
559 unsigned long mem_start, unsigned long mem_end,
560 struct device_node ***allnextpp)
561{
562 int l;
563 phandle child;
564 struct device_node *np;
565 struct property *pp, **prev_propp;
566 char *prev_name, *namep;
567 unsigned char *valp;
568
569 np = (struct device_node *) mem_start;
570 mem_start += sizeof(struct device_node);
571 memset(np, 0, sizeof(*np));
572 np->node = node;
573 **allnextpp = PTRUNRELOC(np);
574 *allnextpp = &np->allnext;
575 if (dad != 0) {
576 np->parent = PTRUNRELOC(dad);
577 /* we temporarily use the `next' field as `last_child'. */
578 if (dad->next == 0)
579 dad->child = PTRUNRELOC(np);
580 else
581 dad->next->sibling = PTRUNRELOC(np);
582 dad->next = np;
583 }
584
585 /* get and store all properties */
586 prev_propp = &np->properties;
587 prev_name = "";
588 for (;;) {
589 pp = (struct property *) mem_start;
590 namep = (char *) (pp + 1);
591 pp->name = PTRUNRELOC(namep);
592 if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0)
593 break;
594 mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
595 prev_name = namep;
596 valp = (unsigned char *) mem_start;
597 pp->value = PTRUNRELOC(valp);
598 pp->length = call_prom("getprop", 4, 1, node, namep,
599 valp, mem_end - mem_start);
600 if (pp->length < 0)
601 continue;
602#ifdef MAX_PROPERTY_LENGTH
603 if (pp->length > MAX_PROPERTY_LENGTH)
604 continue; /* ignore this property */
605#endif
606 mem_start = ALIGNUL(mem_start + pp->length);
607 *prev_propp = PTRUNRELOC(pp);
608 prev_propp = &pp->next;
609 }
610 if (np->node != 0) {
611 /* Add a "linux,phandle" property" */
612 pp = (struct property *) mem_start;
613 *prev_propp = PTRUNRELOC(pp);
614 prev_propp = &pp->next;
615 namep = (char *) (pp + 1);
616 pp->name = PTRUNRELOC(namep);
617 strcpy(namep, "linux,phandle");
618 mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
619 pp->value = (unsigned char *) PTRUNRELOC(&np->node);
620 pp->length = sizeof(np->node);
621 }
622 *prev_propp = NULL;
623
624 /* get the node's full name */
625 l = call_prom("package-to-path", 3, 1, node,
626 mem_start, mem_end - mem_start);
627 if (l >= 0) {
628 char *p, *ep;
629
630 np->full_name = PTRUNRELOC((char *) mem_start);
631 *(char *)(mem_start + l) = 0;
632 /* Fixup an Apple bug where they have bogus \0 chars in the
633 * middle of the path in some properties
634 */
635 for (p = (char *)mem_start, ep = p + l; p < ep; p++)
636 if ((*p) == '\0') {
637 memmove(p, p+1, ep - p);
638 ep--;
639 }
640 mem_start = ALIGNUL(mem_start + l + 1);
641 }
642
643 /* do all our children */
644 child = call_prom("child", 1, 1, node);
645 while (child != 0) {
646 mem_start = inspect_node(child, np, mem_start, mem_end,
647 allnextpp);
648 child = call_prom("peer", 1, 1, child);
649 }
650
651 return mem_start;
652}
653
654unsigned long smp_chrp_cpu_nr __initdata = 0;
655
656/*
657 * With CHRP SMP we need to use the OF to start the other
658 * processors so we can't wait until smp_boot_cpus (the OF is
659 * trashed by then) so we have to put the processors into
660 * a holding pattern controlled by the kernel (not OF) before
661 * we destroy the OF.
662 *
663 * This uses a chunk of high memory, puts some holding pattern
664 * code there and sends the other processors off to there until
665 * smp_boot_cpus tells them to do something. We do that by using
666 * physical address 0x0. The holding pattern checks that address
667 * until its cpu # is there, when it is that cpu jumps to
668 * __secondary_start(). smp_boot_cpus() takes care of setting those
669 * values.
670 *
671 * We also use physical address 0x4 here to tell when a cpu
672 * is in its holding pattern code.
673 *
674 * -- Cort
675 *
676 * Note that we have to do this if we have more than one CPU,
677 * even if this is a UP kernel. Otherwise when we trash OF
678 * the other CPUs will start executing some random instructions
679 * and crash the system. -- paulus
680 */
681static void __init
682prom_hold_cpus(unsigned long mem)
683{
684 extern void __secondary_hold(void);
685 unsigned long i;
686 int cpu;
687 phandle node;
688 char type[16], *path;
689 unsigned int reg;
690
691 /*
692 * XXX: hack to make sure we're chrp, assume that if we're
693 * chrp we have a device_type property -- Cort
694 */
695 node = call_prom("finddevice", 1, 1, "/");
696 if (call_prom("getprop", 4, 1, node,
697 "device_type", type, sizeof(type)) <= 0)
698 return;
699
700 /* copy the holding pattern code to someplace safe (0) */
701 /* the holding pattern is now within the first 0x100
702 bytes of the kernel image -- paulus */
703 memcpy((void *)0, _stext, 0x100);
704 flush_icache_range(0, 0x100);
705
706 /* look for cpus */
707 *(unsigned long *)(0x0) = 0;
708 asm volatile("dcbf 0,%0": : "r" (0) : "memory");
709 for (node = 0; prom_next_node(&node); ) {
710 type[0] = 0;
711 call_prom("getprop", 4, 1, node, "device_type",
712 type, sizeof(type));
713 if (strcmp(type, "cpu") != 0)
714 continue;
715 path = (char *) mem;
716 memset(path, 0, 256);
717 if (call_prom("package-to-path", 3, 1, node, path, 255) < 0)
718 continue;
719 reg = -1;
720 call_prom("getprop", 4, 1, node, "reg", &reg, sizeof(reg));
721 cpu = smp_chrp_cpu_nr++;
722#ifdef CONFIG_SMP
723 smp_hw_index[cpu] = reg;
724#endif /* CONFIG_SMP */
725 /* XXX: hack - don't start cpu 0, this cpu -- Cort */
726 if (cpu == 0)
727 continue;
728 prom_print("starting cpu ");
729 prom_print(path);
730 *(ulong *)(0x4) = 0;
731 call_prom("start-cpu", 3, 0, node,
732 (char *)__secondary_hold - _stext, cpu);
733 prom_print("...");
734 for ( i = 0 ; (i < 10000) && (*(ulong *)(0x4) == 0); i++ )
735 ;
736 if (*(ulong *)(0x4) == cpu)
737 prom_print("ok\n");
738 else {
739 prom_print("failed: ");
740 prom_print_hex(*(ulong *)0x4);
741 prom_print("\n");
742 }
743 }
744}
745
746static void __init
747prom_instantiate_rtas(void)
748{
749 ihandle prom_rtas;
750 prom_arg_t result;
751
752 prom_rtas = call_prom("finddevice", 1, 1, "/rtas");
753 if (prom_rtas == -1)
754 return;
755
756 rtas_size = 0;
757 call_prom("getprop", 4, 1, prom_rtas,
758 "rtas-size", &rtas_size, sizeof(rtas_size));
759 prom_print("instantiating rtas");
760 if (rtas_size == 0) {
761 rtas_data = 0;
762 } else {
763 /*
764 * Ask OF for some space for RTAS.
765 * Actually OF has bugs so we just arbitrarily
766 * use memory at the 6MB point.
767 */
768 rtas_data = 6 << 20;
769 prom_print(" at ");
770 prom_print_hex(rtas_data);
771 }
772
773 prom_rtas = call_prom("open", 1, 1, "/rtas");
774 prom_print("...");
775 rtas_entry = 0;
776 if (call_prom_ret("call-method", 3, 2, &result,
777 "instantiate-rtas", prom_rtas, rtas_data) == 0)
778 rtas_entry = result;
779 if ((rtas_entry == -1) || (rtas_entry == 0))
780 prom_print(" failed\n");
781 else
782 prom_print(" done\n");
783}
784
785/*
786 * We enter here early on, when the Open Firmware prom is still
787 * handling exceptions and the MMU hash table for us.
788 */
789unsigned long __init
790prom_init(int r3, int r4, prom_entry pp)
791{
792 unsigned long mem;
793 ihandle prom_mmu;
794 unsigned long offset = reloc_offset();
795 int i, l;
796 char *p, *d;
797 unsigned long phys;
798 prom_arg_t result[3];
799 char model[32];
800 phandle node;
801 int rc;
802
803 /* Default */
804 phys = (unsigned long) &_stext;
805
806 /* First get a handle for the stdout device */
807 prom = pp;
808 prom_chosen = call_prom("finddevice", 1, 1, "/chosen");
809 if (prom_chosen == -1)
810 prom_exit();
811 if (call_prom("getprop", 4, 1, prom_chosen, "stdout",
812 &prom_stdout, sizeof(prom_stdout)) <= 0)
813 prom_exit();
814
815 /* Get the full OF pathname of the stdout device */
816 mem = (unsigned long) klimit + offset;
817 p = (char *) mem;
818 memset(p, 0, 256);
819 call_prom("instance-to-path", 3, 1, prom_stdout, p, 255);
820 of_stdout_device = p;
821 mem += strlen(p) + 1;
822
823 /* Get the boot device and translate it to a full OF pathname. */
824 p = (char *) mem;
825 l = call_prom("getprop", 4, 1, prom_chosen, "bootpath", p, 1<<20);
826 if (l > 0) {
827 p[l] = 0; /* should already be null-terminated */
828 bootpath = PTRUNRELOC(p);
829 mem += l + 1;
830 d = (char *) mem;
831 *d = 0;
832 call_prom("canon", 3, 1, p, d, 1<<20);
833 bootdevice = PTRUNRELOC(d);
834 mem = ALIGNUL(mem + strlen(d) + 1);
835 }
836
837 prom_instantiate_rtas();
838
839#ifdef CONFIG_POWER4
840 /*
841 * Find out how much memory we have and allocate a
842 * suitably-sized hash table.
843 */
844 prom_alloc_htab();
845#endif
846 mem = check_display(mem);
847
848 prom_print("copying OF device tree...");
849 mem = copy_device_tree(mem, mem + (1<<20));
850 prom_print("done\n");
851
852 prom_hold_cpus(mem);
853
854 klimit = (char *) (mem - offset);
855
856 node = call_prom("finddevice", 1, 1, "/");
857 rc = call_prom("getprop", 4, 1, node, "model", model, sizeof(model));
858 if (rc > 0 && !strncmp (model, "Pegasos", 7)
859 && strncmp (model, "Pegasos2", 8)) {
860 /* Pegasos 1 has a broken translate method in the OF,
861 * and furthermore the BATs are mapped 1:1 so the phys
862 * address calculated above is correct, so let's use
863 * it directly.
864 */
865 } else if (offset == 0) {
866 /* If we are already running at 0xc0000000, we assume we were
867 * loaded by an OF bootloader which did set a BAT for us.
868 * This breaks OF translate so we force phys to be 0.
869 */
870 prom_print("(already at 0xc0000000) phys=0\n");
871 phys = 0;
872 } else if (call_prom("getprop", 4, 1, prom_chosen, "mmu",
873 &prom_mmu, sizeof(prom_mmu)) <= 0) {
874 prom_print(" no MMU found\n");
875 } else if (call_prom_ret("call-method", 4, 4, result, "translate",
876 prom_mmu, &_stext, 1) != 0) {
877 prom_print(" (translate failed)\n");
878 } else {
879 /* We assume the phys. address size is 3 cells */
880 phys = result[2];
881 }
882
883 if (prom_disp_node != 0)
884 setup_disp_fake_bi(prom_disp_node);
885
886 /* Use quiesce call to get OF to shut down any devices it's using */
887 prom_print("Calling quiesce ...\n");
888 call_prom("quiesce", 0, 0);
889
890 /* Relocate various pointers which will be used once the
891 kernel is running at the address it was linked at. */
892 for (i = 0; i < prom_num_displays; ++i)
893 prom_display_paths[i] = PTRUNRELOC(prom_display_paths[i]);
894
895#ifdef CONFIG_SERIAL_CORE_CONSOLE
896 /* Relocate the of stdout for console autodetection */
897 of_stdout_device = PTRUNRELOC(of_stdout_device);
898#endif
899
900 prom_print("returning 0x");
901 prom_print_hex(phys);
902 prom_print("from prom_init\n");
903 prom_stdout = 0;
904
905 return phys;
906}
907
908/*
909 * early_get_property is used to access the device tree image prepared
910 * by BootX very early on, before the pointers in it have been relocated.
911 */
912static void * __init
913early_get_property(unsigned long base, unsigned long node, char *prop)
914{
915 struct device_node *np = (struct device_node *)(base + node);
916 struct property *pp;
917
918 for (pp = np->properties; pp != 0; pp = pp->next) {
919 pp = (struct property *) (base + (unsigned long)pp);
920 if (strcmp((char *)((unsigned long)pp->name + base),
921 prop) == 0) {
922 return (void *)((unsigned long)pp->value + base);
923 }
924 }
925 return NULL;
926}
927
928/* Is boot-info compatible ? */
929#define BOOT_INFO_IS_COMPATIBLE(bi) ((bi)->compatible_version <= BOOT_INFO_VERSION)
930#define BOOT_INFO_IS_V2_COMPATIBLE(bi) ((bi)->version >= 2)
931#define BOOT_INFO_IS_V4_COMPATIBLE(bi) ((bi)->version >= 4)
932
933void __init
934bootx_init(unsigned long r4, unsigned long phys)
935{
936 boot_infos_t *bi = (boot_infos_t *) r4;
937 unsigned long space;
938 unsigned long ptr, x;
939 char *model;
940
941 boot_infos = PTRUNRELOC(bi);
942 if (!BOOT_INFO_IS_V2_COMPATIBLE(bi))
943 bi->logicalDisplayBase = NULL;
944
945#ifdef CONFIG_BOOTX_TEXT
946 btext_init(bi);
947
948 /*
949 * Test if boot-info is compatible. Done only in config
950 * CONFIG_BOOTX_TEXT since there is nothing much we can do
951 * with an incompatible version, except display a message
952 * and eventually hang the processor...
953 *
954 * I'll try to keep enough of boot-info compatible in the
955 * future to always allow display of this message;
956 */
957 if (!BOOT_INFO_IS_COMPATIBLE(bi)) {
958 btext_drawstring(" !!! WARNING - Incompatible version of BootX !!!\n\n\n");
959 btext_flushscreen();
960 }
961#endif /* CONFIG_BOOTX_TEXT */
962
963 /* New BootX enters kernel with MMU off, i/os are not allowed
964 here. This hack will have been done by the boostrap anyway.
965 */
966 if (bi->version < 4) {
967 /*
968 * XXX If this is an iMac, turn off the USB controller.
969 */
970 model = (char *) early_get_property
971 (r4 + bi->deviceTreeOffset, 4, "model");
972 if (model
973 && (strcmp(model, "iMac,1") == 0
974 || strcmp(model, "PowerMac1,1") == 0)) {
975 out_le32((unsigned *)0x80880008, 1); /* XXX */
976 }
977 }
978
979 /* Move klimit to enclose device tree, args, ramdisk, etc... */
980 if (bi->version < 5) {
981 space = bi->deviceTreeOffset + bi->deviceTreeSize;
982 if (bi->ramDisk)
983 space = bi->ramDisk + bi->ramDiskSize;
984 } else
985 space = bi->totalParamsSize;
986 klimit = PTRUNRELOC((char *) bi + space);
987
988 /* New BootX will have flushed all TLBs and enters kernel with
989 MMU switched OFF, so this should not be useful anymore.
990 */
991 if (bi->version < 4) {
992 /*
993 * Touch each page to make sure the PTEs for them
994 * are in the hash table - the aim is to try to avoid
995 * getting DSI exceptions while copying the kernel image.
996 */
997 for (ptr = ((unsigned long) &_stext) & PAGE_MASK;
998 ptr < (unsigned long)bi + space; ptr += PAGE_SIZE)
999 x = *(volatile unsigned long *)ptr;
1000 }
1001
1002#ifdef CONFIG_BOOTX_TEXT
1003 /*
1004 * Note that after we call btext_prepare_BAT, we can't do
1005 * prom_draw*, flushscreen or clearscreen until we turn the MMU
1006 * on, since btext_prepare_BAT sets disp_bi.logicalDisplayBase
1007 * to a virtual address.
1008 */
1009 btext_prepare_BAT();
1010#endif
1011}