[PATCH] libata-dev: wait idle after reading the last data block
[sfrench/cifs-2.6.git] / arch / ppc / syslib / prom_init.c
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>
37 extern 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
55 typedef u32 prom_arg_t;
56
57 struct prom_args {
58         const char *service;
59         int nargs;
60         int nret;
61         prom_arg_t args[10];
62 };
63
64 struct pci_address {
65         unsigned a_hi;
66         unsigned a_mid;
67         unsigned a_lo;
68 };
69
70 struct pci_reg_property {
71         struct pci_address addr;
72         unsigned size_hi;
73         unsigned size_lo;
74 };
75
76 struct pci_range {
77         struct pci_address addr;
78         unsigned phys;
79         unsigned size_hi;
80         unsigned size_lo;
81 };
82
83 struct isa_reg_property {
84         unsigned space;
85         unsigned address;
86         unsigned size;
87 };
88
89 struct pci_intr_map {
90         struct pci_address addr;
91         unsigned dunno;
92         phandle int_ctrler;
93         unsigned intr;
94 };
95
96 static void prom_exit(void);
97 static int  call_prom(const char *service, int nargs, int nret, ...);
98 static int  call_prom_ret(const char *service, int nargs, int nret,
99                           prom_arg_t *rets, ...);
100 static void prom_print_hex(unsigned int v);
101 static int  prom_set_color(ihandle ih, int i, int r, int g, int b);
102 static int  prom_next_node(phandle *nodep);
103 static unsigned long check_display(unsigned long mem);
104 static void setup_disp_fake_bi(ihandle dp);
105 static unsigned long copy_device_tree(unsigned long mem_start,
106                                 unsigned long mem_end);
107 static unsigned long inspect_node(phandle node, struct device_node *dad,
108                                 unsigned long mem_start, unsigned long mem_end,
109                                 struct device_node ***allnextpp);
110 static void prom_hold_cpus(unsigned long mem);
111 static void prom_instantiate_rtas(void);
112 static void * early_get_property(unsigned long base, unsigned long node,
113                                 char *prop);
114
115 prom_entry prom __initdata;
116 ihandle prom_chosen __initdata;
117 ihandle prom_stdout __initdata;
118
119 static char *prom_display_paths[FB_MAX] __initdata;
120 static phandle prom_display_nodes[FB_MAX] __initdata;
121 static unsigned int prom_num_displays __initdata;
122 static ihandle prom_disp_node __initdata;
123 char *of_stdout_device __initdata;
124
125 unsigned int rtas_data;   /* physical pointer */
126 unsigned int rtas_entry;  /* physical pointer */
127 unsigned int rtas_size;
128 unsigned int old_rtas;
129
130 boot_infos_t *boot_infos;
131 char *bootpath;
132 char *bootdevice;
133 struct device_node *allnodes;
134
135 extern char *klimit;
136
137 static void __init
138 prom_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
150 static int __init
151 call_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
170 static int __init
171 call_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
192 void __init
193 prom_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
212 static void __init
213 prom_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
228 static int __init
229 prom_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
234 static int __init
235 prom_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
259 static 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
277 extern unsigned long _SDR1;
278 extern PTE *Hash;
279 extern unsigned long Hash_size;
280
281 static void __init
282 prom_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  */
328 static unsigned long __init
329 check_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  */
455 static void __init
456 setup_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  */
538 static unsigned long __init
539 copy_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
557 static unsigned long __init
558 inspect_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
654 unsigned 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  */
681 static void __init
682 prom_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
746 static void __init
747 prom_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  */
789 unsigned long __init
790 prom_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  */
912 static void * __init
913 early_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
933 void __init
934 bootx_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 }