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