blob: 9979919cdf9297c1481091151caca0a401ea6a94 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 *
3 *
4 * Procedures for interfacing to Open Firmware.
5 *
6 * Paul Mackerras August 1996.
7 * Copyright (C) 1996 Paul Mackerras.
8 *
9 * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
10 * {engebret|bergner}@us.ibm.com
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version
15 * 2 of the License, or (at your option) any later version.
16 */
17
18#undef DEBUG_PROM
19
20#include <stdarg.h>
21#include <linux/config.h>
22#include <linux/kernel.h>
23#include <linux/string.h>
24#include <linux/init.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070025#include <linux/threads.h>
26#include <linux/spinlock.h>
27#include <linux/types.h>
28#include <linux/pci.h>
29#include <linux/proc_fs.h>
30#include <linux/stringify.h>
31#include <linux/delay.h>
32#include <linux/initrd.h>
33#include <linux/bitops.h>
34#include <asm/prom.h>
35#include <asm/rtas.h>
36#include <asm/abs_addr.h>
37#include <asm/page.h>
38#include <asm/processor.h>
39#include <asm/irq.h>
40#include <asm/io.h>
41#include <asm/smp.h>
42#include <asm/system.h>
43#include <asm/mmu.h>
44#include <asm/pgtable.h>
45#include <asm/pci.h>
46#include <asm/iommu.h>
47#include <asm/bootinfo.h>
48#include <asm/ppcdebug.h>
49#include <asm/btext.h>
50#include <asm/sections.h>
51#include <asm/machdep.h>
52
53#ifdef CONFIG_LOGO_LINUX_CLUT224
54#include <linux/linux_logo.h>
55extern const struct linux_logo logo_linux_clut224;
56#endif
57
58/*
59 * Properties whose value is longer than this get excluded from our
60 * copy of the device tree. This value does need to be big enough to
61 * ensure that we don't lose things like the interrupt-map property
62 * on a PCI-PCI bridge.
63 */
64#define MAX_PROPERTY_LENGTH (1UL * 1024 * 1024)
65
66/*
67 * Eventually bump that one up
68 */
69#define DEVTREE_CHUNK_SIZE 0x100000
70
71/*
72 * This is the size of the local memory reserve map that gets copied
73 * into the boot params passed to the kernel. That size is totally
74 * flexible as the kernel just reads the list until it encounters an
75 * entry with size 0, so it can be changed without breaking binary
76 * compatibility
77 */
78#define MEM_RESERVE_MAP_SIZE 8
79
80/*
81 * prom_init() is called very early on, before the kernel text
82 * and data have been mapped to KERNELBASE. At this point the code
83 * is running at whatever address it has been loaded at, so
84 * references to extern and static variables must be relocated
85 * explicitly. The procedure reloc_offset() returns the address
86 * we're currently running at minus the address we were linked at.
87 * (Note that strings count as static variables.)
88 *
89 * Because OF may have mapped I/O devices into the area starting at
90 * KERNELBASE, particularly on CHRP machines, we can't safely call
91 * OF once the kernel has been mapped to KERNELBASE. Therefore all
92 * OF calls should be done within prom_init(), and prom_init()
93 * and all routines called within it must be careful to relocate
94 * references as necessary.
95 *
96 * Note that the bss is cleared *after* prom_init runs, so we have
97 * to make sure that any static or extern variables it accesses
98 * are put in the data segment.
99 */
100
101
102#define PROM_BUG() do { \
103 prom_printf("kernel BUG at %s line 0x%x!\n", \
104 RELOC(__FILE__), __LINE__); \
105 __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \
106} while (0)
107
108#ifdef DEBUG_PROM
109#define prom_debug(x...) prom_printf(x)
110#else
111#define prom_debug(x...)
112#endif
113
114
115typedef u32 prom_arg_t;
116
117struct prom_args {
118 u32 service;
119 u32 nargs;
120 u32 nret;
121 prom_arg_t args[10];
122 prom_arg_t *rets; /* Pointer to return values in args[16]. */
123};
124
125struct prom_t {
126 unsigned long entry;
127 ihandle root;
128 ihandle chosen;
129 int cpu;
130 ihandle stdout;
131 ihandle disp_node;
132 struct prom_args args;
133 unsigned long version;
134 unsigned long root_size_cells;
135 unsigned long root_addr_cells;
136};
137
138struct pci_reg_property {
139 struct pci_address addr;
140 u32 size_hi;
141 u32 size_lo;
142};
143
144struct mem_map_entry {
145 u64 base;
146 u64 size;
147};
148
149typedef u32 cell_t;
150
151extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
152
153extern void enter_prom(struct prom_args *args, unsigned long entry);
154extern void copy_and_flush(unsigned long dest, unsigned long src,
155 unsigned long size, unsigned long offset);
156
157extern unsigned long klimit;
158
159/* prom structure */
160static struct prom_t __initdata prom;
161
162#define PROM_SCRATCH_SIZE 256
163
164static char __initdata of_stdout_device[256];
165static char __initdata prom_scratch[PROM_SCRATCH_SIZE];
166
167static unsigned long __initdata dt_header_start;
168static unsigned long __initdata dt_struct_start, dt_struct_end;
169static unsigned long __initdata dt_string_start, dt_string_end;
170
171static unsigned long __initdata prom_initrd_start, prom_initrd_end;
172
173static int __initdata iommu_force_on;
174static int __initdata ppc64_iommu_off;
175static int __initdata of_platform;
176
177static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
178
179static unsigned long __initdata prom_memory_limit;
180static unsigned long __initdata prom_tce_alloc_start;
181static unsigned long __initdata prom_tce_alloc_end;
182
183static unsigned long __initdata alloc_top;
184static unsigned long __initdata alloc_top_high;
185static unsigned long __initdata alloc_bottom;
186static unsigned long __initdata rmo_top;
187static unsigned long __initdata ram_top;
188
189static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE];
190static int __initdata mem_reserve_cnt;
191
192static cell_t __initdata regbuf[1024];
193
194
195#define MAX_CPU_THREADS 2
196
197/* TO GO */
198#ifdef CONFIG_HMT
199struct {
200 unsigned int pir;
201 unsigned int threadid;
202} hmt_thread_data[NR_CPUS];
203#endif /* CONFIG_HMT */
204
205/*
206 * This are used in calls to call_prom. The 4th and following
207 * arguments to call_prom should be 32-bit values. 64 bit values
208 * are truncated to 32 bits (and fortunately don't get interpreted
209 * as two arguments).
210 */
211#define ADDR(x) (u32) ((unsigned long)(x) - offset)
212
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +1000213/*
214 * Error results ... some OF calls will return "-1" on error, some
215 * will return 0, some will return either. To simplify, here are
216 * macros to use with any ihandle or phandle return value to check if
217 * it is valid
218 */
219
220#define PROM_ERROR (-1u)
221#define PHANDLE_VALID(p) ((p) != 0 && (p) != PROM_ERROR)
222#define IHANDLE_VALID(i) ((i) != 0 && (i) != PROM_ERROR)
223
224
Linus Torvalds1da177e2005-04-16 15:20:36 -0700225/* This is the one and *ONLY* place where we actually call open
226 * firmware from, since we need to make sure we're running in 32b
227 * mode when we do. We switch back to 64b mode upon return.
228 */
229
Linus Torvalds1da177e2005-04-16 15:20:36 -0700230static int __init call_prom(const char *service, int nargs, int nret, ...)
231{
232 int i;
233 unsigned long offset = reloc_offset();
234 struct prom_t *_prom = PTRRELOC(&prom);
235 va_list list;
236
237 _prom->args.service = ADDR(service);
238 _prom->args.nargs = nargs;
239 _prom->args.nret = nret;
240 _prom->args.rets = (prom_arg_t *)&(_prom->args.args[nargs]);
241
242 va_start(list, nret);
243 for (i=0; i < nargs; i++)
244 _prom->args.args[i] = va_arg(list, prom_arg_t);
245 va_end(list);
246
247 for (i=0; i < nret ;i++)
248 _prom->args.rets[i] = 0;
249
250 enter_prom(&_prom->args, _prom->entry);
251
252 return (nret > 0) ? _prom->args.rets[0] : 0;
253}
254
255
256static unsigned int __init prom_claim(unsigned long virt, unsigned long size,
257 unsigned long align)
258{
259 return (unsigned int)call_prom("claim", 3, 1,
260 (prom_arg_t)virt, (prom_arg_t)size,
261 (prom_arg_t)align);
262}
263
264static void __init prom_print(const char *msg)
265{
266 const char *p, *q;
267 unsigned long offset = reloc_offset();
268 struct prom_t *_prom = PTRRELOC(&prom);
269
270 if (_prom->stdout == 0)
271 return;
272
273 for (p = msg; *p != 0; p = q) {
274 for (q = p; *q != 0 && *q != '\n'; ++q)
275 ;
276 if (q > p)
277 call_prom("write", 3, 1, _prom->stdout, p, q - p);
278 if (*q == 0)
279 break;
280 ++q;
281 call_prom("write", 3, 1, _prom->stdout, ADDR("\r\n"), 2);
282 }
283}
284
285
286static void __init prom_print_hex(unsigned long val)
287{
288 unsigned long offset = reloc_offset();
289 int i, nibbles = sizeof(val)*2;
290 char buf[sizeof(val)*2+1];
291 struct prom_t *_prom = PTRRELOC(&prom);
292
293 for (i = nibbles-1; i >= 0; i--) {
294 buf[i] = (val & 0xf) + '0';
295 if (buf[i] > '9')
296 buf[i] += ('a'-'0'-10);
297 val >>= 4;
298 }
299 buf[nibbles] = '\0';
300 call_prom("write", 3, 1, _prom->stdout, buf, nibbles);
301}
302
303
304static void __init prom_printf(const char *format, ...)
305{
306 unsigned long offset = reloc_offset();
307 const char *p, *q, *s;
308 va_list args;
309 unsigned long v;
310 struct prom_t *_prom = PTRRELOC(&prom);
311
312 va_start(args, format);
313 for (p = PTRRELOC(format); *p != 0; p = q) {
314 for (q = p; *q != 0 && *q != '\n' && *q != '%'; ++q)
315 ;
316 if (q > p)
317 call_prom("write", 3, 1, _prom->stdout, p, q - p);
318 if (*q == 0)
319 break;
320 if (*q == '\n') {
321 ++q;
322 call_prom("write", 3, 1, _prom->stdout,
323 ADDR("\r\n"), 2);
324 continue;
325 }
326 ++q;
327 if (*q == 0)
328 break;
329 switch (*q) {
330 case 's':
331 ++q;
332 s = va_arg(args, const char *);
333 prom_print(s);
334 break;
335 case 'x':
336 ++q;
337 v = va_arg(args, unsigned long);
338 prom_print_hex(v);
339 break;
340 }
341 }
342}
343
344
345static void __init __attribute__((noreturn)) prom_panic(const char *reason)
346{
347 unsigned long offset = reloc_offset();
348
349 prom_print(PTRRELOC(reason));
350 /* ToDo: should put up an SRC here */
351 call_prom("exit", 0, 0);
352
353 for (;;) /* should never get here */
354 ;
355}
356
357
358static int __init prom_next_node(phandle *nodep)
359{
360 phandle node;
361
362 if ((node = *nodep) != 0
363 && (*nodep = call_prom("child", 1, 1, node)) != 0)
364 return 1;
365 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
366 return 1;
367 for (;;) {
368 if ((node = call_prom("parent", 1, 1, node)) == 0)
369 return 0;
370 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
371 return 1;
372 }
373}
374
375static int __init prom_getprop(phandle node, const char *pname,
376 void *value, size_t valuelen)
377{
378 unsigned long offset = reloc_offset();
379
380 return call_prom("getprop", 4, 1, node, ADDR(pname),
381 (u32)(unsigned long) value, (u32) valuelen);
382}
383
384static int __init prom_getproplen(phandle node, const char *pname)
385{
386 unsigned long offset = reloc_offset();
387
388 return call_prom("getproplen", 2, 1, node, ADDR(pname));
389}
390
391static int __init prom_setprop(phandle node, const char *pname,
392 void *value, size_t valuelen)
393{
394 unsigned long offset = reloc_offset();
395
396 return call_prom("setprop", 4, 1, node, ADDR(pname),
397 (u32)(unsigned long) value, (u32) valuelen);
398}
399
400/* We can't use the standard versions because of RELOC headaches. */
401#define isxdigit(c) (('0' <= (c) && (c) <= '9') \
402 || ('a' <= (c) && (c) <= 'f') \
403 || ('A' <= (c) && (c) <= 'F'))
404
405#define isdigit(c) ('0' <= (c) && (c) <= '9')
406#define islower(c) ('a' <= (c) && (c) <= 'z')
407#define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c))
408
409unsigned long prom_strtoul(const char *cp, const char **endp)
410{
411 unsigned long result = 0, base = 10, value;
412
413 if (*cp == '0') {
414 base = 8;
415 cp++;
416 if (toupper(*cp) == 'X') {
417 cp++;
418 base = 16;
419 }
420 }
421
422 while (isxdigit(*cp) &&
423 (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) {
424 result = result * base + value;
425 cp++;
426 }
427
428 if (endp)
429 *endp = cp;
430
431 return result;
432}
433
434unsigned long prom_memparse(const char *ptr, const char **retptr)
435{
436 unsigned long ret = prom_strtoul(ptr, retptr);
437 int shift = 0;
438
439 /*
440 * We can't use a switch here because GCC *may* generate a
441 * jump table which won't work, because we're not running at
442 * the address we're linked at.
443 */
444 if ('G' == **retptr || 'g' == **retptr)
445 shift = 30;
446
447 if ('M' == **retptr || 'm' == **retptr)
448 shift = 20;
449
450 if ('K' == **retptr || 'k' == **retptr)
451 shift = 10;
452
453 if (shift) {
454 ret <<= shift;
455 (*retptr)++;
456 }
457
458 return ret;
459}
460
461/*
462 * Early parsing of the command line passed to the kernel, used for
463 * "mem=x" and the options that affect the iommu
464 */
465static void __init early_cmdline_parse(void)
466{
467 unsigned long offset = reloc_offset();
468 struct prom_t *_prom = PTRRELOC(&prom);
469 char *opt, *p;
470 int l = 0;
471
472 RELOC(prom_cmd_line[0]) = 0;
473 p = RELOC(prom_cmd_line);
474 if ((long)_prom->chosen > 0)
475 l = prom_getprop(_prom->chosen, "bootargs", p, COMMAND_LINE_SIZE-1);
476#ifdef CONFIG_CMDLINE
477 if (l == 0) /* dbl check */
478 strlcpy(RELOC(prom_cmd_line),
479 RELOC(CONFIG_CMDLINE), sizeof(prom_cmd_line));
480#endif /* CONFIG_CMDLINE */
481 prom_printf("command line: %s\n", RELOC(prom_cmd_line));
482
483 opt = strstr(RELOC(prom_cmd_line), RELOC("iommu="));
484 if (opt) {
485 prom_printf("iommu opt is: %s\n", opt);
486 opt += 6;
487 while (*opt && *opt == ' ')
488 opt++;
489 if (!strncmp(opt, RELOC("off"), 3))
490 RELOC(ppc64_iommu_off) = 1;
491 else if (!strncmp(opt, RELOC("force"), 5))
492 RELOC(iommu_force_on) = 1;
493 }
494
495 opt = strstr(RELOC(prom_cmd_line), RELOC("mem="));
496 if (opt) {
497 opt += 4;
498 RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt);
499 /* Align to 16 MB == size of large page */
500 RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000);
501 }
502}
503
504/*
Paul Mackerras66faf982005-05-01 08:58:45 -0700505 * To tell the firmware what our capabilities are, we have to pass
506 * it a fake 32-bit ELF header containing a couple of PT_NOTE sections
507 * that contain structures that contain the actual values.
508 */
509static struct fake_elf {
510 Elf32_Ehdr elfhdr;
511 Elf32_Phdr phdr[2];
512 struct chrpnote {
513 u32 namesz;
514 u32 descsz;
515 u32 type;
516 char name[8]; /* "PowerPC" */
517 struct chrpdesc {
518 u32 real_mode;
519 u32 real_base;
520 u32 real_size;
521 u32 virt_base;
522 u32 virt_size;
523 u32 load_base;
524 } chrpdesc;
525 } chrpnote;
526 struct rpanote {
527 u32 namesz;
528 u32 descsz;
529 u32 type;
530 char name[24]; /* "IBM,RPA-Client-Config" */
531 struct rpadesc {
532 u32 lpar_affinity;
533 u32 min_rmo_size;
534 u32 min_rmo_percent;
535 u32 max_pft_size;
536 u32 splpar;
537 u32 min_load;
538 u32 new_mem_def;
539 u32 ignore_me;
540 } rpadesc;
541 } rpanote;
542} fake_elf = {
543 .elfhdr = {
544 .e_ident = { 0x7f, 'E', 'L', 'F',
545 ELFCLASS32, ELFDATA2MSB, EV_CURRENT },
546 .e_type = ET_EXEC, /* yeah right */
547 .e_machine = EM_PPC,
548 .e_version = EV_CURRENT,
549 .e_phoff = offsetof(struct fake_elf, phdr),
550 .e_phentsize = sizeof(Elf32_Phdr),
551 .e_phnum = 2
552 },
553 .phdr = {
554 [0] = {
555 .p_type = PT_NOTE,
556 .p_offset = offsetof(struct fake_elf, chrpnote),
557 .p_filesz = sizeof(struct chrpnote)
558 }, [1] = {
559 .p_type = PT_NOTE,
560 .p_offset = offsetof(struct fake_elf, rpanote),
561 .p_filesz = sizeof(struct rpanote)
562 }
563 },
564 .chrpnote = {
565 .namesz = sizeof("PowerPC"),
566 .descsz = sizeof(struct chrpdesc),
567 .type = 0x1275,
568 .name = "PowerPC",
569 .chrpdesc = {
570 .real_mode = ~0U, /* ~0 means "don't care" */
571 .real_base = ~0U,
572 .real_size = ~0U,
573 .virt_base = ~0U,
574 .virt_size = ~0U,
575 .load_base = ~0U
576 },
577 },
578 .rpanote = {
579 .namesz = sizeof("IBM,RPA-Client-Config"),
580 .descsz = sizeof(struct rpadesc),
581 .type = 0x12759999,
582 .name = "IBM,RPA-Client-Config",
583 .rpadesc = {
584 .lpar_affinity = 0,
585 .min_rmo_size = 64, /* in megabytes */
586 .min_rmo_percent = 0,
587 .max_pft_size = 48, /* 2^48 bytes max PFT size */
588 .splpar = 1,
589 .min_load = ~0U,
590 .new_mem_def = 0
591 }
592 }
593};
594
595static void __init prom_send_capabilities(void)
596{
597 unsigned long offset = reloc_offset();
598 ihandle elfloader;
Paul Mackerras66faf982005-05-01 08:58:45 -0700599
600 elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader"));
601 if (elfloader == 0) {
602 prom_printf("couldn't open /packages/elf-loader\n");
603 return;
604 }
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +1000605 call_prom("call-method", 3, 1, ADDR("process-elf-header"),
Paul Mackerras66faf982005-05-01 08:58:45 -0700606 elfloader, ADDR(&fake_elf));
607 call_prom("close", 1, 0, elfloader);
608}
609
610/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 * Memory allocation strategy... our layout is normally:
612 *
613 * at 14Mb or more we vmlinux, then a gap and initrd. In some rare cases, initrd
614 * might end up beeing before the kernel though. We assume this won't override
615 * the final kernel at 0, we have no provision to handle that in this version,
616 * but it should hopefully never happen.
617 *
618 * alloc_top is set to the top of RMO, eventually shrink down if the TCEs overlap
619 * alloc_bottom is set to the top of kernel/initrd
620 *
621 * from there, allocations are done that way : rtas is allocated topmost, and
622 * the device-tree is allocated from the bottom. We try to grow the device-tree
623 * allocation as we progress. If we can't, then we fail, we don't currently have
624 * a facility to restart elsewhere, but that shouldn't be necessary neither
625 *
626 * Note that calls to reserve_mem have to be done explicitely, memory allocated
627 * with either alloc_up or alloc_down isn't automatically reserved.
628 */
629
630
631/*
632 * Allocates memory in the RMO upward from the kernel/initrd
633 *
634 * When align is 0, this is a special case, it means to allocate in place
635 * at the current location of alloc_bottom or fail (that is basically
636 * extending the previous allocation). Used for the device-tree flattening
637 */
638static unsigned long __init alloc_up(unsigned long size, unsigned long align)
639{
640 unsigned long offset = reloc_offset();
641 unsigned long base = _ALIGN_UP(RELOC(alloc_bottom), align);
642 unsigned long addr = 0;
643
644 prom_debug("alloc_up(%x, %x)\n", size, align);
645 if (RELOC(ram_top) == 0)
646 prom_panic("alloc_up() called with mem not initialized\n");
647
648 if (align)
649 base = _ALIGN_UP(RELOC(alloc_bottom), align);
650 else
651 base = RELOC(alloc_bottom);
652
653 for(; (base + size) <= RELOC(alloc_top);
654 base = _ALIGN_UP(base + 0x100000, align)) {
655 prom_debug(" trying: 0x%x\n\r", base);
656 addr = (unsigned long)prom_claim(base, size, 0);
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +1000657 if (addr != PROM_ERROR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658 break;
659 addr = 0;
660 if (align == 0)
661 break;
662 }
663 if (addr == 0)
664 return 0;
665 RELOC(alloc_bottom) = addr;
666
667 prom_debug(" -> %x\n", addr);
668 prom_debug(" alloc_bottom : %x\n", RELOC(alloc_bottom));
669 prom_debug(" alloc_top : %x\n", RELOC(alloc_top));
670 prom_debug(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
671 prom_debug(" rmo_top : %x\n", RELOC(rmo_top));
672 prom_debug(" ram_top : %x\n", RELOC(ram_top));
673
674 return addr;
675}
676
677/*
678 * Allocates memory downard, either from top of RMO, or if highmem
679 * is set, from the top of RAM. Note that this one doesn't handle
680 * failures. In does claim memory if highmem is not set.
681 */
682static unsigned long __init alloc_down(unsigned long size, unsigned long align,
683 int highmem)
684{
685 unsigned long offset = reloc_offset();
686 unsigned long base, addr = 0;
687
688 prom_debug("alloc_down(%x, %x, %s)\n", size, align,
689 highmem ? RELOC("(high)") : RELOC("(low)"));
690 if (RELOC(ram_top) == 0)
691 prom_panic("alloc_down() called with mem not initialized\n");
692
693 if (highmem) {
694 /* Carve out storage for the TCE table. */
695 addr = _ALIGN_DOWN(RELOC(alloc_top_high) - size, align);
696 if (addr <= RELOC(alloc_bottom))
697 return 0;
698 else {
699 /* Will we bump into the RMO ? If yes, check out that we
700 * didn't overlap existing allocations there, if we did,
701 * we are dead, we must be the first in town !
702 */
703 if (addr < RELOC(rmo_top)) {
704 /* Good, we are first */
705 if (RELOC(alloc_top) == RELOC(rmo_top))
706 RELOC(alloc_top) = RELOC(rmo_top) = addr;
707 else
708 return 0;
709 }
710 RELOC(alloc_top_high) = addr;
711 }
712 goto bail;
713 }
714
715 base = _ALIGN_DOWN(RELOC(alloc_top) - size, align);
716 for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) {
717 prom_debug(" trying: 0x%x\n\r", base);
718 addr = (unsigned long)prom_claim(base, size, 0);
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +1000719 if (addr != PROM_ERROR)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720 break;
721 addr = 0;
722 }
723 if (addr == 0)
724 return 0;
725 RELOC(alloc_top) = addr;
726
727 bail:
728 prom_debug(" -> %x\n", addr);
729 prom_debug(" alloc_bottom : %x\n", RELOC(alloc_bottom));
730 prom_debug(" alloc_top : %x\n", RELOC(alloc_top));
731 prom_debug(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
732 prom_debug(" rmo_top : %x\n", RELOC(rmo_top));
733 prom_debug(" ram_top : %x\n", RELOC(ram_top));
734
735 return addr;
736}
737
738/*
739 * Parse a "reg" cell
740 */
741static unsigned long __init prom_next_cell(int s, cell_t **cellp)
742{
743 cell_t *p = *cellp;
744 unsigned long r = 0;
745
746 /* Ignore more than 2 cells */
747 while (s > 2) {
748 p++;
749 s--;
750 }
751 while (s) {
752 r <<= 32;
753 r |= *(p++);
754 s--;
755 }
756
757 *cellp = p;
758 return r;
759}
760
761/*
762 * Very dumb function for adding to the memory reserve list, but
763 * we don't need anything smarter at this point
764 *
765 * XXX Eventually check for collisions. They should NEVER happen
766 * if problems seem to show up, it would be a good start to track
767 * them down.
768 */
769static void reserve_mem(unsigned long base, unsigned long size)
770{
771 unsigned long offset = reloc_offset();
772 unsigned long top = base + size;
773 unsigned long cnt = RELOC(mem_reserve_cnt);
774
775 if (size == 0)
776 return;
777
778 /* We need to always keep one empty entry so that we
779 * have our terminator with "size" set to 0 since we are
780 * dumb and just copy this entire array to the boot params
781 */
782 base = _ALIGN_DOWN(base, PAGE_SIZE);
783 top = _ALIGN_UP(top, PAGE_SIZE);
784 size = top - base;
785
786 if (cnt >= (MEM_RESERVE_MAP_SIZE - 1))
787 prom_panic("Memory reserve map exhausted !\n");
788 RELOC(mem_reserve_map)[cnt].base = base;
789 RELOC(mem_reserve_map)[cnt].size = size;
790 RELOC(mem_reserve_cnt) = cnt + 1;
791}
792
793/*
794 * Initialize memory allocation mecanism, parse "memory" nodes and
795 * obtain that way the top of memory and RMO to setup out local allocator
796 */
797static void __init prom_init_mem(void)
798{
799 phandle node;
800 char *path, type[64];
801 unsigned int plen;
802 cell_t *p, *endp;
803 unsigned long offset = reloc_offset();
804 struct prom_t *_prom = PTRRELOC(&prom);
805
806 /*
807 * We iterate the memory nodes to find
808 * 1) top of RMO (first node)
809 * 2) top of memory
810 */
811 prom_debug("root_addr_cells: %x\n", (long)_prom->root_addr_cells);
812 prom_debug("root_size_cells: %x\n", (long)_prom->root_size_cells);
813
814 prom_debug("scanning memory:\n");
815 path = RELOC(prom_scratch);
816
817 for (node = 0; prom_next_node(&node); ) {
818 type[0] = 0;
819 prom_getprop(node, "device_type", type, sizeof(type));
820
821 if (strcmp(type, RELOC("memory")))
822 continue;
823
824 plen = prom_getprop(node, "reg", RELOC(regbuf), sizeof(regbuf));
825 if (plen > sizeof(regbuf)) {
826 prom_printf("memory node too large for buffer !\n");
827 plen = sizeof(regbuf);
828 }
829 p = RELOC(regbuf);
830 endp = p + (plen / sizeof(cell_t));
831
832#ifdef DEBUG_PROM
833 memset(path, 0, PROM_SCRATCH_SIZE);
834 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
835 prom_debug(" node %s :\n", path);
836#endif /* DEBUG_PROM */
837
838 while ((endp - p) >= (_prom->root_addr_cells + _prom->root_size_cells)) {
839 unsigned long base, size;
840
841 base = prom_next_cell(_prom->root_addr_cells, &p);
842 size = prom_next_cell(_prom->root_size_cells, &p);
843
844 if (size == 0)
845 continue;
846 prom_debug(" %x %x\n", base, size);
847 if (base == 0)
848 RELOC(rmo_top) = size;
849 if ((base + size) > RELOC(ram_top))
850 RELOC(ram_top) = base + size;
851 }
852 }
853
854 RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(klimit) - offset + 0x4000);
855
856 /* Check if we have an initrd after the kernel, if we do move our bottom
857 * point to after it
858 */
859 if (RELOC(prom_initrd_start)) {
860 if (RELOC(prom_initrd_end) > RELOC(alloc_bottom))
861 RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(prom_initrd_end));
862 }
863
864 /*
865 * If prom_memory_limit is set we reduce the upper limits *except* for
866 * alloc_top_high. This must be the real top of RAM so we can put
867 * TCE's up there.
868 */
869
870 RELOC(alloc_top_high) = RELOC(ram_top);
871
872 if (RELOC(prom_memory_limit)) {
873 if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) {
874 prom_printf("Ignoring mem=%x <= alloc_bottom.\n",
875 RELOC(prom_memory_limit));
876 RELOC(prom_memory_limit) = 0;
877 } else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) {
878 prom_printf("Ignoring mem=%x >= ram_top.\n",
879 RELOC(prom_memory_limit));
880 RELOC(prom_memory_limit) = 0;
881 } else {
882 RELOC(ram_top) = RELOC(prom_memory_limit);
883 RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit));
884 }
885 }
886
887 /*
888 * Setup our top alloc point, that is top of RMO or top of
889 * segment 0 when running non-LPAR.
890 */
891 if ( RELOC(of_platform) == PLATFORM_PSERIES_LPAR )
892 RELOC(alloc_top) = RELOC(rmo_top);
893 else
Olof Johansson7fea82a2005-08-28 21:42:10 -0500894 /* Some RS64 machines have buggy firmware where claims up at 1GB
895 * fails. Cap at 768MB as a workaround. Still plenty of room.
896 */
897 RELOC(alloc_top) = RELOC(rmo_top) = min(0x30000000ul, RELOC(ram_top));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700898
899 prom_printf("memory layout at init:\n");
900 prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit));
901 prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom));
902 prom_printf(" alloc_top : %x\n", RELOC(alloc_top));
903 prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
904 prom_printf(" rmo_top : %x\n", RELOC(rmo_top));
905 prom_printf(" ram_top : %x\n", RELOC(ram_top));
906}
907
908
909/*
910 * Allocate room for and instanciate RTAS
911 */
912static void __init prom_instantiate_rtas(void)
913{
914 unsigned long offset = reloc_offset();
915 struct prom_t *_prom = PTRRELOC(&prom);
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +1000916 phandle rtas_node;
917 ihandle rtas_inst;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918 u32 base, entry = 0;
919 u32 size = 0;
920
921 prom_debug("prom_instantiate_rtas: start...\n");
922
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +1000923 rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
924 prom_debug("rtas_node: %x\n", rtas_node);
925 if (!PHANDLE_VALID(rtas_node))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926 return;
927
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +1000928 prom_getprop(rtas_node, "rtas-size", &size, sizeof(size));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700929 if (size == 0)
930 return;
931
932 base = alloc_down(size, PAGE_SIZE, 0);
933 if (base == 0) {
934 prom_printf("RTAS allocation failed !\n");
935 return;
936 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700937
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +1000938 rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
939 if (!IHANDLE_VALID(rtas_inst)) {
940 prom_printf("opening rtas package failed");
941 return;
942 }
943
944 prom_printf("instantiating rtas at 0x%x ...", base);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945
946 if (call_prom("call-method", 3, 2,
947 ADDR("instantiate-rtas"),
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +1000948 rtas_inst, base) != PROM_ERROR) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 entry = (long)_prom->args.rets[1];
950 }
951 if (entry == 0) {
952 prom_printf(" failed\n");
953 return;
954 }
955 prom_printf(" done\n");
956
957 reserve_mem(base, size);
958
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +1000959 prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base));
960 prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961
962 prom_debug("rtas base = 0x%x\n", base);
963 prom_debug("rtas entry = 0x%x\n", entry);
964 prom_debug("rtas size = 0x%x\n", (long)size);
965
966 prom_debug("prom_instantiate_rtas: end...\n");
967}
968
969
970/*
971 * Allocate room for and initialize TCE tables
972 */
973static void __init prom_initialize_tce_table(void)
974{
975 phandle node;
976 ihandle phb_node;
977 unsigned long offset = reloc_offset();
978 char compatible[64], type[64], model[64];
979 char *path = RELOC(prom_scratch);
980 u64 base, align;
981 u32 minalign, minsize;
982 u64 tce_entry, *tce_entryp;
983 u64 local_alloc_top, local_alloc_bottom;
984 u64 i;
985
986 if (RELOC(ppc64_iommu_off))
987 return;
988
989 prom_debug("starting prom_initialize_tce_table\n");
990
991 /* Cache current top of allocs so we reserve a single block */
992 local_alloc_top = RELOC(alloc_top_high);
993 local_alloc_bottom = local_alloc_top;
994
995 /* Search all nodes looking for PHBs. */
996 for (node = 0; prom_next_node(&node); ) {
997 compatible[0] = 0;
998 type[0] = 0;
999 model[0] = 0;
1000 prom_getprop(node, "compatible",
1001 compatible, sizeof(compatible));
1002 prom_getprop(node, "device_type", type, sizeof(type));
1003 prom_getprop(node, "model", model, sizeof(model));
1004
1005 if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL))
1006 continue;
1007
1008 /* Keep the old logic in tack to avoid regression. */
1009 if (compatible[0] != 0) {
1010 if ((strstr(compatible, RELOC("python")) == NULL) &&
1011 (strstr(compatible, RELOC("Speedwagon")) == NULL) &&
1012 (strstr(compatible, RELOC("Winnipeg")) == NULL))
1013 continue;
1014 } else if (model[0] != 0) {
1015 if ((strstr(model, RELOC("ython")) == NULL) &&
1016 (strstr(model, RELOC("peedwagon")) == NULL) &&
1017 (strstr(model, RELOC("innipeg")) == NULL))
1018 continue;
1019 }
1020
1021 if (prom_getprop(node, "tce-table-minalign", &minalign,
1022 sizeof(minalign)) == PROM_ERROR)
1023 minalign = 0;
1024 if (prom_getprop(node, "tce-table-minsize", &minsize,
1025 sizeof(minsize)) == PROM_ERROR)
1026 minsize = 4UL << 20;
1027
1028 /*
1029 * Even though we read what OF wants, we just set the table
1030 * size to 4 MB. This is enough to map 2GB of PCI DMA space.
1031 * By doing this, we avoid the pitfalls of trying to DMA to
1032 * MMIO space and the DMA alias hole.
1033 *
1034 * On POWER4, firmware sets the TCE region by assuming
1035 * each TCE table is 8MB. Using this memory for anything
1036 * else will impact performance, so we always allocate 8MB.
1037 * Anton
1038 */
1039 if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p))
1040 minsize = 8UL << 20;
1041 else
1042 minsize = 4UL << 20;
1043
1044 /* Align to the greater of the align or size */
1045 align = max(minalign, minsize);
1046 base = alloc_down(minsize, align, 1);
1047 if (base == 0)
1048 prom_panic("ERROR, cannot find space for TCE table.\n");
1049 if (base < local_alloc_bottom)
1050 local_alloc_bottom = base;
1051
1052 /* Save away the TCE table attributes for later use. */
1053 prom_setprop(node, "linux,tce-base", &base, sizeof(base));
1054 prom_setprop(node, "linux,tce-size", &minsize, sizeof(minsize));
1055
1056 /* It seems OF doesn't null-terminate the path :-( */
1057 memset(path, 0, sizeof(path));
1058 /* Call OF to setup the TCE hardware */
1059 if (call_prom("package-to-path", 3, 1, node,
1060 path, PROM_SCRATCH_SIZE-1) == PROM_ERROR) {
1061 prom_printf("package-to-path failed\n");
1062 }
1063
1064 prom_debug("TCE table: %s\n", path);
1065 prom_debug("\tnode = 0x%x\n", node);
1066 prom_debug("\tbase = 0x%x\n", base);
1067 prom_debug("\tsize = 0x%x\n", minsize);
1068
1069 /* Initialize the table to have a one-to-one mapping
1070 * over the allocated size.
1071 */
1072 tce_entryp = (unsigned long *)base;
1073 for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
1074 tce_entry = (i << PAGE_SHIFT);
1075 tce_entry |= 0x3;
1076 *tce_entryp = tce_entry;
1077 }
1078
1079 prom_printf("opening PHB %s", path);
1080 phb_node = call_prom("open", 1, 1, path);
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +10001081 if (phb_node == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 prom_printf("... failed\n");
1083 else
1084 prom_printf("... done\n");
1085
1086 call_prom("call-method", 6, 0, ADDR("set-64-bit-addressing"),
1087 phb_node, -1, minsize,
1088 (u32) base, (u32) (base >> 32));
1089 call_prom("close", 1, 0, phb_node);
1090 }
1091
1092 reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
1093
1094 if (RELOC(prom_memory_limit)) {
1095 /*
1096 * We align the start to a 16MB boundary so we can map the TCE area
1097 * using large pages if possible. The end should be the top of RAM
1098 * so no need to align it.
1099 */
1100 RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom, 0x1000000);
1101 RELOC(prom_tce_alloc_end) = local_alloc_top;
1102 }
1103
1104 /* Flag the first invalid entry */
1105 prom_debug("ending prom_initialize_tce_table\n");
1106}
1107
1108/*
1109 * With CHRP SMP we need to use the OF to start the other
1110 * processors so we can't wait until smp_boot_cpus (the OF is
1111 * trashed by then) so we have to put the processors into
1112 * a holding pattern controlled by the kernel (not OF) before
1113 * we destroy the OF.
1114 *
1115 * This uses a chunk of low memory, puts some holding pattern
1116 * code there and sends the other processors off to there until
1117 * smp_boot_cpus tells them to do something. The holding pattern
1118 * checks that address until its cpu # is there, when it is that
1119 * cpu jumps to __secondary_start(). smp_boot_cpus() takes care
1120 * of setting those values.
1121 *
1122 * We also use physical address 0x4 here to tell when a cpu
1123 * is in its holding pattern code.
1124 *
1125 * Fixup comment... DRENG / PPPBBB - Peter
1126 *
1127 * -- Cort
1128 */
1129static void __init prom_hold_cpus(void)
1130{
1131 unsigned long i;
1132 unsigned int reg;
1133 phandle node;
1134 unsigned long offset = reloc_offset();
1135 char type[64];
1136 int cpuid = 0;
1137 unsigned int interrupt_server[MAX_CPU_THREADS];
1138 unsigned int cpu_threads, hw_cpu_num;
1139 int propsize;
1140 extern void __secondary_hold(void);
1141 extern unsigned long __secondary_hold_spinloop;
1142 extern unsigned long __secondary_hold_acknowledge;
1143 unsigned long *spinloop
1144 = (void *)virt_to_abs(&__secondary_hold_spinloop);
1145 unsigned long *acknowledge
1146 = (void *)virt_to_abs(&__secondary_hold_acknowledge);
1147 unsigned long secondary_hold
1148 = virt_to_abs(*PTRRELOC((unsigned long *)__secondary_hold));
1149 struct prom_t *_prom = PTRRELOC(&prom);
1150
1151 prom_debug("prom_hold_cpus: start...\n");
1152 prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop);
1153 prom_debug(" 1) *spinloop = 0x%x\n", *spinloop);
1154 prom_debug(" 1) acknowledge = 0x%x\n",
1155 (unsigned long)acknowledge);
1156 prom_debug(" 1) *acknowledge = 0x%x\n", *acknowledge);
1157 prom_debug(" 1) secondary_hold = 0x%x\n", secondary_hold);
1158
1159 /* Set the common spinloop variable, so all of the secondary cpus
1160 * will block when they are awakened from their OF spinloop.
1161 * This must occur for both SMP and non SMP kernels, since OF will
1162 * be trashed when we move the kernel.
1163 */
1164 *spinloop = 0;
1165
1166#ifdef CONFIG_HMT
1167 for (i=0; i < NR_CPUS; i++) {
1168 RELOC(hmt_thread_data)[i].pir = 0xdeadbeef;
1169 }
1170#endif
1171 /* look for cpus */
1172 for (node = 0; prom_next_node(&node); ) {
1173 type[0] = 0;
1174 prom_getprop(node, "device_type", type, sizeof(type));
1175 if (strcmp(type, RELOC("cpu")) != 0)
1176 continue;
1177
1178 /* Skip non-configured cpus. */
1179 if (prom_getprop(node, "status", type, sizeof(type)) > 0)
1180 if (strcmp(type, RELOC("okay")) != 0)
1181 continue;
1182
1183 reg = -1;
1184 prom_getprop(node, "reg", &reg, sizeof(reg));
1185
1186 prom_debug("\ncpuid = 0x%x\n", cpuid);
1187 prom_debug("cpu hw idx = 0x%x\n", reg);
1188
1189 /* Init the acknowledge var which will be reset by
1190 * the secondary cpu when it awakens from its OF
1191 * spinloop.
1192 */
1193 *acknowledge = (unsigned long)-1;
1194
1195 propsize = prom_getprop(node, "ibm,ppc-interrupt-server#s",
1196 &interrupt_server,
1197 sizeof(interrupt_server));
1198 if (propsize < 0) {
1199 /* no property. old hardware has no SMT */
1200 cpu_threads = 1;
1201 interrupt_server[0] = reg; /* fake it with phys id */
1202 } else {
1203 /* We have a threaded processor */
1204 cpu_threads = propsize / sizeof(u32);
1205 if (cpu_threads > MAX_CPU_THREADS) {
1206 prom_printf("SMT: too many threads!\n"
1207 "SMT: found %x, max is %x\n",
1208 cpu_threads, MAX_CPU_THREADS);
1209 cpu_threads = 1; /* ToDo: panic? */
1210 }
1211 }
1212
1213 hw_cpu_num = interrupt_server[0];
1214 if (hw_cpu_num != _prom->cpu) {
1215 /* Primary Thread of non-boot cpu */
1216 prom_printf("%x : starting cpu hw idx %x... ", cpuid, reg);
1217 call_prom("start-cpu", 3, 0, node,
1218 secondary_hold, reg);
1219
1220 for ( i = 0 ; (i < 100000000) &&
1221 (*acknowledge == ((unsigned long)-1)); i++ )
1222 mb();
1223
1224 if (*acknowledge == reg) {
1225 prom_printf("done\n");
1226 /* We have to get every CPU out of OF,
1227 * even if we never start it. */
1228 if (cpuid >= NR_CPUS)
1229 goto next;
1230 } else {
1231 prom_printf("failed: %x\n", *acknowledge);
1232 }
1233 }
1234#ifdef CONFIG_SMP
1235 else
1236 prom_printf("%x : boot cpu %x\n", cpuid, reg);
1237#endif
1238next:
1239#ifdef CONFIG_SMP
1240 /* Init paca for secondary threads. They start later. */
1241 for (i=1; i < cpu_threads; i++) {
1242 cpuid++;
1243 if (cpuid >= NR_CPUS)
1244 continue;
1245 }
1246#endif /* CONFIG_SMP */
1247 cpuid++;
1248 }
1249#ifdef CONFIG_HMT
1250 /* Only enable HMT on processors that provide support. */
1251 if (__is_processor(PV_PULSAR) ||
1252 __is_processor(PV_ICESTAR) ||
1253 __is_processor(PV_SSTAR)) {
1254 prom_printf(" starting secondary threads\n");
1255
1256 for (i = 0; i < NR_CPUS; i += 2) {
1257 if (!cpu_online(i))
1258 continue;
1259
1260 if (i == 0) {
1261 unsigned long pir = mfspr(SPRN_PIR);
1262 if (__is_processor(PV_PULSAR)) {
1263 RELOC(hmt_thread_data)[i].pir =
1264 pir & 0x1f;
1265 } else {
1266 RELOC(hmt_thread_data)[i].pir =
1267 pir & 0x3ff;
1268 }
1269 }
1270 }
1271 } else {
1272 prom_printf("Processor is not HMT capable\n");
1273 }
1274#endif
1275
1276 if (cpuid > NR_CPUS)
1277 prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS)
1278 ") exceeded: ignoring extras\n");
1279
1280 prom_debug("prom_hold_cpus: end...\n");
1281}
1282
1283
1284static void __init prom_init_client_services(unsigned long pp)
1285{
1286 unsigned long offset = reloc_offset();
1287 struct prom_t *_prom = PTRRELOC(&prom);
1288
1289 /* Get a handle to the prom entry point before anything else */
1290 _prom->entry = pp;
1291
1292 /* Init default value for phys size */
1293 _prom->root_size_cells = 1;
1294 _prom->root_addr_cells = 2;
1295
1296 /* get a handle for the stdout device */
1297 _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +10001298 if (!PHANDLE_VALID(_prom->chosen))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001299 prom_panic("cannot find chosen"); /* msg won't be printed :( */
1300
1301 /* get device tree root */
1302 _prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +10001303 if (!PHANDLE_VALID(_prom->root))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 prom_panic("cannot find device tree root"); /* msg won't be printed :( */
1305}
1306
1307static void __init prom_init_stdout(void)
1308{
1309 unsigned long offset = reloc_offset();
1310 struct prom_t *_prom = PTRRELOC(&prom);
1311 char *path = RELOC(of_stdout_device);
1312 char type[16];
1313 u32 val;
1314
1315 if (prom_getprop(_prom->chosen, "stdout", &val, sizeof(val)) <= 0)
1316 prom_panic("cannot find stdout");
1317
1318 _prom->stdout = val;
1319
1320 /* Get the full OF pathname of the stdout device */
1321 memset(path, 0, 256);
1322 call_prom("instance-to-path", 3, 1, _prom->stdout, path, 255);
1323 val = call_prom("instance-to-package", 1, 1, _prom->stdout);
1324 prom_setprop(_prom->chosen, "linux,stdout-package", &val, sizeof(val));
1325 prom_printf("OF stdout device is: %s\n", RELOC(of_stdout_device));
1326 prom_setprop(_prom->chosen, "linux,stdout-path",
1327 RELOC(of_stdout_device), strlen(RELOC(of_stdout_device))+1);
1328
1329 /* If it's a display, note it */
1330 memset(type, 0, sizeof(type));
1331 prom_getprop(val, "device_type", type, sizeof(type));
1332 if (strcmp(type, RELOC("display")) == 0) {
1333 _prom->disp_node = val;
1334 prom_setprop(val, "linux,boot-display", NULL, 0);
1335 }
1336}
1337
1338static void __init prom_close_stdin(void)
1339{
1340 unsigned long offset = reloc_offset();
1341 struct prom_t *_prom = PTRRELOC(&prom);
1342 ihandle val;
1343
1344 if (prom_getprop(_prom->chosen, "stdin", &val, sizeof(val)) > 0)
1345 call_prom("close", 1, 0, val);
1346}
1347
1348static int __init prom_find_machine_type(void)
1349{
1350 unsigned long offset = reloc_offset();
1351 struct prom_t *_prom = PTRRELOC(&prom);
1352 char compat[256];
1353 int len, i = 0;
1354 phandle rtas;
1355
1356 len = prom_getprop(_prom->root, "compatible",
1357 compat, sizeof(compat)-1);
1358 if (len > 0) {
1359 compat[len] = 0;
1360 while (i < len) {
1361 char *p = &compat[i];
1362 int sl = strlen(p);
1363 if (sl == 0)
1364 break;
1365 if (strstr(p, RELOC("Power Macintosh")) ||
1366 strstr(p, RELOC("MacRISC4")))
1367 return PLATFORM_POWERMAC;
1368 if (strstr(p, RELOC("Momentum,Maple")))
1369 return PLATFORM_MAPLE;
1370 i += sl + 1;
1371 }
1372 }
1373 /* Default to pSeries. We need to know if we are running LPAR */
1374 rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
Nathan Lynch8be3de32005-06-03 14:25:25 -05001375 if (PHANDLE_VALID(rtas)) {
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +10001376 int x = prom_getproplen(rtas, "ibm,hypertas-functions");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001377 if (x != PROM_ERROR) {
1378 prom_printf("Hypertas detected, assuming LPAR !\n");
1379 return PLATFORM_PSERIES_LPAR;
1380 }
1381 }
1382 return PLATFORM_PSERIES;
1383}
1384
1385static int __init prom_set_color(ihandle ih, int i, int r, int g, int b)
1386{
1387 unsigned long offset = reloc_offset();
1388
1389 return call_prom("call-method", 6, 1, ADDR("color!"), ih, i, b, g, r);
1390}
1391
1392/*
1393 * If we have a display that we don't know how to drive,
1394 * we will want to try to execute OF's open method for it
1395 * later. However, OF will probably fall over if we do that
1396 * we've taken over the MMU.
1397 * So we check whether we will need to open the display,
1398 * and if so, open it now.
1399 */
1400static void __init prom_check_displays(void)
1401{
1402 unsigned long offset = reloc_offset();
1403 struct prom_t *_prom = PTRRELOC(&prom);
1404 char type[16], *path;
1405 phandle node;
1406 ihandle ih;
1407 int i;
1408
1409 static unsigned char default_colors[] = {
1410 0x00, 0x00, 0x00,
1411 0x00, 0x00, 0xaa,
1412 0x00, 0xaa, 0x00,
1413 0x00, 0xaa, 0xaa,
1414 0xaa, 0x00, 0x00,
1415 0xaa, 0x00, 0xaa,
1416 0xaa, 0xaa, 0x00,
1417 0xaa, 0xaa, 0xaa,
1418 0x55, 0x55, 0x55,
1419 0x55, 0x55, 0xff,
1420 0x55, 0xff, 0x55,
1421 0x55, 0xff, 0xff,
1422 0xff, 0x55, 0x55,
1423 0xff, 0x55, 0xff,
1424 0xff, 0xff, 0x55,
1425 0xff, 0xff, 0xff
1426 };
1427 const unsigned char *clut;
1428
1429 prom_printf("Looking for displays\n");
1430 for (node = 0; prom_next_node(&node); ) {
1431 memset(type, 0, sizeof(type));
1432 prom_getprop(node, "device_type", type, sizeof(type));
1433 if (strcmp(type, RELOC("display")) != 0)
1434 continue;
1435
1436 /* It seems OF doesn't null-terminate the path :-( */
1437 path = RELOC(prom_scratch);
1438 memset(path, 0, PROM_SCRATCH_SIZE);
1439
1440 /*
1441 * leave some room at the end of the path for appending extra
1442 * arguments
1443 */
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +10001444 if (call_prom("package-to-path", 3, 1, node, path,
1445 PROM_SCRATCH_SIZE-10) == PROM_ERROR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001446 continue;
1447 prom_printf("found display : %s, opening ... ", path);
1448
1449 ih = call_prom("open", 1, 1, path);
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +10001450 if (ih == 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001451 prom_printf("failed\n");
1452 continue;
1453 }
1454
1455 /* Success */
1456 prom_printf("done\n");
1457 prom_setprop(node, "linux,opened", NULL, 0);
1458
1459 /*
1460 * stdout wasn't a display node, pick the first we can find
1461 * for btext
1462 */
1463 if (_prom->disp_node == 0)
1464 _prom->disp_node = node;
1465
1466 /* Setup a useable color table when the appropriate
1467 * method is available. Should update this to set-colors */
1468 clut = RELOC(default_colors);
1469 for (i = 0; i < 32; i++, clut += 3)
1470 if (prom_set_color(ih, i, clut[0], clut[1],
1471 clut[2]) != 0)
1472 break;
1473
1474#ifdef CONFIG_LOGO_LINUX_CLUT224
1475 clut = PTRRELOC(RELOC(logo_linux_clut224.clut));
1476 for (i = 0; i < RELOC(logo_linux_clut224.clutsize); i++, clut += 3)
1477 if (prom_set_color(ih, i + 32, clut[0], clut[1],
1478 clut[2]) != 0)
1479 break;
1480#endif /* CONFIG_LOGO_LINUX_CLUT224 */
1481 }
1482}
1483
1484
1485/* Return (relocated) pointer to this much memory: moves initrd if reqd. */
1486static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end,
1487 unsigned long needed, unsigned long align)
1488{
1489 unsigned long offset = reloc_offset();
1490 void *ret;
1491
1492 *mem_start = _ALIGN(*mem_start, align);
1493 while ((*mem_start + needed) > *mem_end) {
1494 unsigned long room, chunk;
1495
1496 prom_debug("Chunk exhausted, claiming more at %x...\n",
1497 RELOC(alloc_bottom));
1498 room = RELOC(alloc_top) - RELOC(alloc_bottom);
1499 if (room > DEVTREE_CHUNK_SIZE)
1500 room = DEVTREE_CHUNK_SIZE;
1501 if (room < PAGE_SIZE)
1502 prom_panic("No memory for flatten_device_tree (no room)");
1503 chunk = alloc_up(room, 0);
1504 if (chunk == 0)
1505 prom_panic("No memory for flatten_device_tree (claim failed)");
1506 *mem_end = RELOC(alloc_top);
1507 }
1508
1509 ret = (void *)*mem_start;
1510 *mem_start += needed;
1511
1512 return ret;
1513}
1514
1515#define dt_push_token(token, mem_start, mem_end) \
1516 do { *((u32 *)make_room(mem_start, mem_end, 4, 4)) = token; } while(0)
1517
1518static unsigned long __init dt_find_string(char *str)
1519{
1520 unsigned long offset = reloc_offset();
1521 char *s, *os;
1522
1523 s = os = (char *)RELOC(dt_string_start);
1524 s += 4;
1525 while (s < (char *)RELOC(dt_string_end)) {
1526 if (strcmp(s, str) == 0)
1527 return s - os;
1528 s += strlen(s) + 1;
1529 }
1530 return 0;
1531}
1532
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +10001533/*
1534 * The Open Firmware 1275 specification states properties must be 31 bytes or
1535 * less, however not all firmwares obey this. Make it 64 bytes to be safe.
1536 */
1537#define MAX_PROPERTY_NAME 64
1538
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001539static void __init scan_dt_build_strings(phandle node,
1540 unsigned long *mem_start,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 unsigned long *mem_end)
1542{
1543 unsigned long offset = reloc_offset();
1544 char *prev_name, *namep, *sstart;
1545 unsigned long soff;
1546 phandle child;
1547
1548 sstart = (char *)RELOC(dt_string_start);
1549
1550 /* get and store all property names */
1551 prev_name = RELOC("");
1552 for (;;) {
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +10001553 /* 64 is max len of name including nul. */
1554 namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001555 if (call_prom("nextprop", 3, 1, node, prev_name, namep) != 1) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556 /* No more nodes: unwind alloc */
1557 *mem_start = (unsigned long)namep;
1558 break;
1559 }
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001560
1561 /* skip "name" */
1562 if (strcmp(namep, RELOC("name")) == 0) {
1563 *mem_start = (unsigned long)namep;
1564 prev_name = RELOC("name");
1565 continue;
1566 }
1567 /* get/create string entry */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568 soff = dt_find_string(namep);
1569 if (soff != 0) {
1570 *mem_start = (unsigned long)namep;
1571 namep = sstart + soff;
1572 } else {
1573 /* Trim off some if we can */
1574 *mem_start = (unsigned long)namep + strlen(namep) + 1;
1575 RELOC(dt_string_end) = *mem_start;
1576 }
1577 prev_name = namep;
1578 }
1579
1580 /* do all our children */
1581 child = call_prom("child", 1, 1, node);
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001582 while (child != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583 scan_dt_build_strings(child, mem_start, mem_end);
1584 child = call_prom("peer", 1, 1, child);
1585 }
1586}
1587
1588static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
1589 unsigned long *mem_end)
1590{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001591 phandle child;
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001592 char *namep, *prev_name, *sstart, *p, *ep, *lp, *path;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001593 unsigned long soff;
1594 unsigned char *valp;
1595 unsigned long offset = reloc_offset();
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001596 static char pname[MAX_PROPERTY_NAME];
1597 int l;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598
1599 dt_push_token(OF_DT_BEGIN_NODE, mem_start, mem_end);
1600
1601 /* get the node's full name */
1602 namep = (char *)*mem_start;
1603 l = call_prom("package-to-path", 3, 1, node,
1604 namep, *mem_end - *mem_start);
1605 if (l >= 0) {
1606 /* Didn't fit? Get more room. */
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001607 if ((l+1) > (*mem_end - *mem_start)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001608 namep = make_room(mem_start, mem_end, l+1, 1);
1609 call_prom("package-to-path", 3, 1, node, namep, l);
1610 }
1611 namep[l] = '\0';
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001612
Benjamin Herrenschmidt44e46652005-06-01 14:54:25 +10001613 /* Fixup an Apple bug where they have bogus \0 chars in the
1614 * middle of the path in some properties
1615 */
1616 for (p = namep, ep = namep + l; p < ep; p++)
1617 if (*p == '\0') {
1618 memmove(p, p+1, ep - p);
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001619 ep--; l--; p--;
Benjamin Herrenschmidt44e46652005-06-01 14:54:25 +10001620 }
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001621
1622 /* now try to extract the unit name in that mess */
1623 for (p = namep, lp = NULL; *p; p++)
1624 if (*p == '/')
1625 lp = p + 1;
1626 if (lp != NULL)
1627 memmove(namep, lp, strlen(lp) + 1);
1628 *mem_start = _ALIGN(((unsigned long) namep) +
1629 strlen(namep) + 1, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001630 }
1631
1632 /* get it again for debugging */
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001633 path = RELOC(prom_scratch);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634 memset(path, 0, PROM_SCRATCH_SIZE);
1635 call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-1);
1636
1637 /* get and store all properties */
1638 prev_name = RELOC("");
1639 sstart = (char *)RELOC(dt_string_start);
1640 for (;;) {
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001641 if (call_prom("nextprop", 3, 1, node, prev_name,
1642 RELOC(pname)) != 1)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001643 break;
1644
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001645 /* skip "name" */
1646 if (strcmp(RELOC(pname), RELOC("name")) == 0) {
1647 prev_name = RELOC("name");
1648 continue;
1649 }
1650
Linus Torvalds1da177e2005-04-16 15:20:36 -07001651 /* find string offset */
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001652 soff = dt_find_string(RELOC(pname));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001653 if (soff == 0) {
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001654 prom_printf("WARNING: Can't find string index for"
1655 " <%s>, node %s\n", RELOC(pname), path);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656 break;
1657 }
1658 prev_name = sstart + soff;
1659
1660 /* get length */
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001661 l = call_prom("getproplen", 2, 1, node, RELOC(pname));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001662
1663 /* sanity checks */
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +10001664 if (l == PROM_ERROR)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665 continue;
1666 if (l > MAX_PROPERTY_LENGTH) {
1667 prom_printf("WARNING: ignoring large property ");
1668 /* It seems OF doesn't null-terminate the path :-( */
1669 prom_printf("[%s] ", path);
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001670 prom_printf("%s length 0x%x\n", RELOC(pname), l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001671 continue;
1672 }
1673
1674 /* push property head */
1675 dt_push_token(OF_DT_PROP, mem_start, mem_end);
1676 dt_push_token(l, mem_start, mem_end);
1677 dt_push_token(soff, mem_start, mem_end);
1678
1679 /* push property content */
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001680 valp = make_room(mem_start, mem_end, l, 4);
1681 call_prom("getprop", 4, 1, node, RELOC(pname), valp, l);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682 *mem_start = _ALIGN(*mem_start, 4);
1683 }
1684
1685 /* Add a "linux,phandle" property. */
1686 soff = dt_find_string(RELOC("linux,phandle"));
1687 if (soff == 0)
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001688 prom_printf("WARNING: Can't find string index for"
1689 " <linux-phandle> node %s\n", path);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 else {
1691 dt_push_token(OF_DT_PROP, mem_start, mem_end);
1692 dt_push_token(4, mem_start, mem_end);
1693 dt_push_token(soff, mem_start, mem_end);
1694 valp = make_room(mem_start, mem_end, 4, 4);
1695 *(u32 *)valp = node;
1696 }
1697
1698 /* do all our children */
1699 child = call_prom("child", 1, 1, node);
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001700 while (child != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701 scan_dt_build_struct(child, mem_start, mem_end);
1702 child = call_prom("peer", 1, 1, child);
1703 }
1704
1705 dt_push_token(OF_DT_END_NODE, mem_start, mem_end);
1706}
1707
1708static void __init flatten_device_tree(void)
1709{
1710 phandle root;
1711 unsigned long offset = reloc_offset();
1712 unsigned long mem_start, mem_end, room;
1713 struct boot_param_header *hdr;
1714 char *namep;
1715 u64 *rsvmap;
1716
1717 /*
1718 * Check how much room we have between alloc top & bottom (+/- a
1719 * few pages), crop to 4Mb, as this is our "chuck" size
1720 */
1721 room = RELOC(alloc_top) - RELOC(alloc_bottom) - 0x4000;
1722 if (room > DEVTREE_CHUNK_SIZE)
1723 room = DEVTREE_CHUNK_SIZE;
1724 prom_debug("starting device tree allocs at %x\n", RELOC(alloc_bottom));
1725
1726 /* Now try to claim that */
1727 mem_start = (unsigned long)alloc_up(room, PAGE_SIZE);
1728 if (mem_start == 0)
1729 prom_panic("Can't allocate initial device-tree chunk\n");
1730 mem_end = RELOC(alloc_top);
1731
1732 /* Get root of tree */
1733 root = call_prom("peer", 1, 1, (phandle)0);
1734 if (root == (phandle)0)
1735 prom_panic ("couldn't get device tree root\n");
1736
1737 /* Build header and make room for mem rsv map */
1738 mem_start = _ALIGN(mem_start, 4);
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001739 hdr = make_room(&mem_start, &mem_end,
1740 sizeof(struct boot_param_header), 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001741 RELOC(dt_header_start) = (unsigned long)hdr;
1742 rsvmap = make_room(&mem_start, &mem_end, sizeof(mem_reserve_map), 8);
1743
1744 /* Start of strings */
1745 mem_start = PAGE_ALIGN(mem_start);
1746 RELOC(dt_string_start) = mem_start;
1747 mem_start += 4; /* hole */
1748
1749 /* Add "linux,phandle" in there, we'll need it */
1750 namep = make_room(&mem_start, &mem_end, 16, 1);
1751 strcpy(namep, RELOC("linux,phandle"));
1752 mem_start = (unsigned long)namep + strlen(namep) + 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753
1754 /* Build string array */
1755 prom_printf("Building dt strings...\n");
1756 scan_dt_build_strings(root, &mem_start, &mem_end);
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001757 RELOC(dt_string_end) = mem_start;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758
1759 /* Build structure */
1760 mem_start = PAGE_ALIGN(mem_start);
1761 RELOC(dt_struct_start) = mem_start;
1762 prom_printf("Building dt structure...\n");
1763 scan_dt_build_struct(root, &mem_start, &mem_end);
1764 dt_push_token(OF_DT_END, &mem_start, &mem_end);
1765 RELOC(dt_struct_end) = PAGE_ALIGN(mem_start);
1766
1767 /* Finish header */
1768 hdr->magic = OF_DT_HEADER;
1769 hdr->totalsize = RELOC(dt_struct_end) - RELOC(dt_header_start);
1770 hdr->off_dt_struct = RELOC(dt_struct_start) - RELOC(dt_header_start);
1771 hdr->off_dt_strings = RELOC(dt_string_start) - RELOC(dt_header_start);
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001772 hdr->dt_strings_size = RELOC(dt_string_end) - RELOC(dt_string_start);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773 hdr->off_mem_rsvmap = ((unsigned long)rsvmap) - RELOC(dt_header_start);
1774 hdr->version = OF_DT_VERSION;
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001775 /* Version 16 is not backward compatible */
1776 hdr->last_comp_version = 0x10;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777
1778 /* Reserve the whole thing and copy the reserve map in, we
1779 * also bump mem_reserve_cnt to cause further reservations to
1780 * fail since it's too late.
1781 */
1782 reserve_mem(RELOC(dt_header_start), hdr->totalsize);
1783 memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map));
1784
1785#ifdef DEBUG_PROM
1786 {
1787 int i;
1788 prom_printf("reserved memory map:\n");
1789 for (i = 0; i < RELOC(mem_reserve_cnt); i++)
1790 prom_printf(" %x - %x\n", RELOC(mem_reserve_map)[i].base,
1791 RELOC(mem_reserve_map)[i].size);
1792 }
1793#endif
1794 RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE;
1795
1796 prom_printf("Device tree strings 0x%x -> 0x%x\n",
1797 RELOC(dt_string_start), RELOC(dt_string_end));
1798 prom_printf("Device tree struct 0x%x -> 0x%x\n",
1799 RELOC(dt_struct_start), RELOC(dt_struct_end));
1800
Benjamin Herrenschmidt1263cc62005-05-23 10:03:52 +10001801}
1802
1803
1804static void __init fixup_device_tree(void)
1805{
1806 unsigned long offset = reloc_offset();
1807 phandle u3, i2c, mpic;
1808 u32 u3_rev;
1809 u32 interrupts[2];
1810 u32 parent;
1811
1812 /* Some G5s have a missing interrupt definition, fix it up here */
1813 u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +10001814 if (!PHANDLE_VALID(u3))
Benjamin Herrenschmidt1263cc62005-05-23 10:03:52 +10001815 return;
1816 i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +10001817 if (!PHANDLE_VALID(i2c))
Benjamin Herrenschmidt1263cc62005-05-23 10:03:52 +10001818 return;
1819 mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +10001820 if (!PHANDLE_VALID(mpic))
Benjamin Herrenschmidt1263cc62005-05-23 10:03:52 +10001821 return;
1822
1823 /* check if proper rev of u3 */
Benjamin Herrenschmidt1e86d1c2005-06-02 14:11:37 +10001824 if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
1825 == PROM_ERROR)
Benjamin Herrenschmidt1263cc62005-05-23 10:03:52 +10001826 return;
Benjamin Herrenschmidte62b8b22005-08-10 11:12:09 +02001827 if (u3_rev != 0x35 && u3_rev != 0x37)
Benjamin Herrenschmidt1263cc62005-05-23 10:03:52 +10001828 return;
1829 /* does it need fixup ? */
1830 if (prom_getproplen(i2c, "interrupts") > 0)
1831 return;
Benjamin Herrenschmidt34153fa2005-08-09 10:36:34 +02001832
1833 prom_printf("fixing up bogus interrupts for u3 i2c...\n");
1834
Benjamin Herrenschmidt1263cc62005-05-23 10:03:52 +10001835 /* interrupt on this revision of u3 is number 0 and level */
1836 interrupts[0] = 0;
1837 interrupts[1] = 1;
1838 prom_setprop(i2c, "interrupts", &interrupts, sizeof(interrupts));
1839 parent = (u32)mpic;
1840 prom_setprop(i2c, "interrupt-parent", &parent, sizeof(parent));
1841}
1842
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843
1844static void __init prom_find_boot_cpu(void)
1845{
1846 unsigned long offset = reloc_offset();
1847 struct prom_t *_prom = PTRRELOC(&prom);
1848 u32 getprop_rval;
1849 ihandle prom_cpu;
1850 phandle cpu_pkg;
1851
1852 if (prom_getprop(_prom->chosen, "cpu", &prom_cpu, sizeof(prom_cpu)) <= 0)
1853 prom_panic("cannot find boot cpu");
1854
1855 cpu_pkg = call_prom("instance-to-package", 1, 1, prom_cpu);
1856
1857 prom_setprop(cpu_pkg, "linux,boot-cpu", NULL, 0);
1858 prom_getprop(cpu_pkg, "reg", &getprop_rval, sizeof(getprop_rval));
1859 _prom->cpu = getprop_rval;
1860
1861 prom_debug("Booting CPU hw index = 0x%x\n", _prom->cpu);
1862}
1863
1864static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
1865{
1866#ifdef CONFIG_BLK_DEV_INITRD
1867 unsigned long offset = reloc_offset();
1868 struct prom_t *_prom = PTRRELOC(&prom);
1869
1870 if ( r3 && r4 && r4 != 0xdeadbeef) {
1871 u64 val;
1872
1873 RELOC(prom_initrd_start) = (r3 >= KERNELBASE) ? __pa(r3) : r3;
1874 RELOC(prom_initrd_end) = RELOC(prom_initrd_start) + r4;
1875
1876 val = (u64)RELOC(prom_initrd_start);
1877 prom_setprop(_prom->chosen, "linux,initrd-start", &val, sizeof(val));
1878 val = (u64)RELOC(prom_initrd_end);
1879 prom_setprop(_prom->chosen, "linux,initrd-end", &val, sizeof(val));
1880
1881 reserve_mem(RELOC(prom_initrd_start),
1882 RELOC(prom_initrd_end) - RELOC(prom_initrd_start));
1883
1884 prom_debug("initrd_start=0x%x\n", RELOC(prom_initrd_start));
1885 prom_debug("initrd_end=0x%x\n", RELOC(prom_initrd_end));
1886 }
1887#endif /* CONFIG_BLK_DEV_INITRD */
1888}
1889
1890/*
1891 * We enter here early on, when the Open Firmware prom is still
1892 * handling exceptions and the MMU hash table for us.
1893 */
1894
1895unsigned long __init prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
1896 unsigned long r6, unsigned long r7)
1897{
1898 unsigned long offset = reloc_offset();
1899 struct prom_t *_prom = PTRRELOC(&prom);
1900 unsigned long phys = KERNELBASE - offset;
1901 u32 getprop_rval;
1902
1903 /*
1904 * First zero the BSS
1905 */
1906 memset(PTRRELOC(&__bss_start), 0, __bss_stop - __bss_start);
1907
1908 /*
1909 * Init interface to Open Firmware, get some node references,
1910 * like /chosen
1911 */
1912 prom_init_client_services(pp);
1913
1914 /*
1915 * Init prom stdout device
1916 */
1917 prom_init_stdout();
1918 prom_debug("klimit=0x%x\n", RELOC(klimit));
1919 prom_debug("offset=0x%x\n", offset);
1920
1921 /*
1922 * Check for an initrd
1923 */
1924 prom_check_initrd(r3, r4);
1925
1926 /*
1927 * Get default machine type. At this point, we do not differenciate
1928 * between pSeries SMP and pSeries LPAR
1929 */
1930 RELOC(of_platform) = prom_find_machine_type();
1931 getprop_rval = RELOC(of_platform);
1932 prom_setprop(_prom->chosen, "linux,platform",
1933 &getprop_rval, sizeof(getprop_rval));
1934
1935 /*
Paul Mackerras05fda3b1d2005-05-31 17:01:11 +10001936 * On pSeries, inform the firmware about our capabilities
1937 */
1938 if (RELOC(of_platform) & PLATFORM_PSERIES)
1939 prom_send_capabilities();
1940
1941 /*
Arnd Bergmannfef1c772005-06-23 09:43:37 +10001942 * On pSeries and BPA, copy the CPU hold code
Linus Torvalds1da177e2005-04-16 15:20:36 -07001943 */
Arnd Bergmannfef1c772005-06-23 09:43:37 +10001944 if (RELOC(of_platform) & (PLATFORM_PSERIES | PLATFORM_BPA))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001945 copy_and_flush(0, KERNELBASE - offset, 0x100, 0);
1946
1947 /*
1948 * Get memory cells format
1949 */
1950 getprop_rval = 1;
1951 prom_getprop(_prom->root, "#size-cells",
1952 &getprop_rval, sizeof(getprop_rval));
1953 _prom->root_size_cells = getprop_rval;
1954 getprop_rval = 2;
1955 prom_getprop(_prom->root, "#address-cells",
1956 &getprop_rval, sizeof(getprop_rval));
1957 _prom->root_addr_cells = getprop_rval;
1958
1959 /*
1960 * Do early parsing of command line
1961 */
1962 early_cmdline_parse();
1963
1964 /*
1965 * Initialize memory management within prom_init
1966 */
1967 prom_init_mem();
1968
1969 /*
1970 * Determine which cpu is actually running right _now_
1971 */
1972 prom_find_boot_cpu();
1973
1974 /*
1975 * Initialize display devices
1976 */
1977 prom_check_displays();
1978
1979 /*
1980 * Initialize IOMMU (TCE tables) on pSeries. Do that before anything else
1981 * that uses the allocator, we need to make sure we get the top of memory
1982 * available for us here...
1983 */
1984 if (RELOC(of_platform) == PLATFORM_PSERIES)
1985 prom_initialize_tce_table();
1986
1987 /*
1988 * On non-powermacs, try to instantiate RTAS and puts all CPUs
1989 * in spin-loops. PowerMacs don't have a working RTAS and use
1990 * a different way to spin CPUs
1991 */
1992 if (RELOC(of_platform) != PLATFORM_POWERMAC) {
1993 prom_instantiate_rtas();
1994 prom_hold_cpus();
1995 }
1996
1997 /*
1998 * Fill in some infos for use by the kernel later on
1999 */
2000 if (RELOC(ppc64_iommu_off))
2001 prom_setprop(_prom->chosen, "linux,iommu-off", NULL, 0);
2002
2003 if (RELOC(iommu_force_on))
2004 prom_setprop(_prom->chosen, "linux,iommu-force-on", NULL, 0);
2005
2006 if (RELOC(prom_memory_limit))
2007 prom_setprop(_prom->chosen, "linux,memory-limit",
2008 PTRRELOC(&prom_memory_limit), sizeof(RELOC(prom_memory_limit)));
2009
2010 if (RELOC(prom_tce_alloc_start)) {
2011 prom_setprop(_prom->chosen, "linux,tce-alloc-start",
2012 PTRRELOC(&prom_tce_alloc_start), sizeof(RELOC(prom_tce_alloc_start)));
2013 prom_setprop(_prom->chosen, "linux,tce-alloc-end",
2014 PTRRELOC(&prom_tce_alloc_end), sizeof(RELOC(prom_tce_alloc_end)));
2015 }
2016
2017 /*
Benjamin Herrenschmidt1263cc62005-05-23 10:03:52 +10002018 * Fixup any known bugs in the device-tree
2019 */
2020 fixup_device_tree();
2021
2022 /*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002023 * Now finally create the flattened device-tree
2024 */
2025 prom_printf("copying OF device tree ...\n");
2026 flatten_device_tree();
2027
2028 /* in case stdin is USB and still active on IBM machines... */
2029 prom_close_stdin();
2030
2031 /*
2032 * Call OF "quiesce" method to shut down pending DMA's from
2033 * devices etc...
2034 */
2035 prom_printf("Calling quiesce ...\n");
2036 call_prom("quiesce", 0, 0);
2037
2038 /*
2039 * And finally, call the kernel passing it the flattened device
2040 * tree and NULL as r5, thus triggering the new entry point which
2041 * is common to us and kexec
2042 */
2043 prom_printf("returning from prom_init\n");
2044 prom_debug("->dt_header_start=0x%x\n", RELOC(dt_header_start));
2045 prom_debug("->phys=0x%x\n", phys);
2046
2047 __start(RELOC(dt_header_start), phys, 0);
2048
2049 return 0;
2050}
2051