1 /* - undefined for user space
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 #if 0
19 #define DEBUG_YABOOT
20 #endif
21
22 #if 0
23 #define DEBUG_PROM
24 #endif
25
26 #include <stdarg.h>
27 #include <linux/config.h>
28 #include <linux/kernel.h>
29 #include <linux/string.h>
30 #include <linux/init.h>
31 #include <linux/version.h>
32 #include <linux/threads.h>
33 #include <linux/spinlock.h>
34 #include <linux/blk.h>
35
36 #ifdef DEBUG_YABOOT
37 #define call_yaboot(FUNC,...) \
38 do { \
39 if (FUNC) { \
40 struct prom_t *_prom = PTRRELOC(&prom); \
41 unsigned long prom_entry = _prom->entry;\
42 _prom->entry = (unsigned long)(FUNC); \
43 enter_prom(__VA_ARGS__); \
44 _prom->entry = prom_entry; \
45 } \
46 } while (0)
47 #else
48 #define call_yaboot(FUNC,...) do { ; } while (0)
49 #endif
50
51 #include <asm/init.h>
52 #include <linux/types.h>
53 #include <linux/pci.h>
54 #include <asm/prom.h>
55 #include <asm/rtas.h>
56 #include <asm/lmb.h>
57 #include <asm/abs_addr.h>
58 #include <asm/page.h>
59 #include <asm/processor.h>
60 #include <asm/irq.h>
61 #include <asm/io.h>
62 #include <asm/smp.h>
63 #include <asm/system.h>
64 #include <asm/mmu.h>
65 #include <asm/pgtable.h>
66 #include <asm/bitops.h>
67 #include <asm/naca.h>
68 #include <asm/pci.h>
69 #include "open_pic.h"
70 #include <asm/bootinfo.h>
71 #include <asm/ppcdebug.h>
72
73 #ifdef CONFIG_FB
74 #include <asm/linux_logo.h>
75 #endif
76
77 extern char _end[];
78
79 /*
80 * prom_init() is called very early on, before the kernel text
81 * and data have been mapped to KERNELBASE. At this point the code
82 * is running at whatever address it has been loaded at, so
83 * references to extern and static variables must be relocated
84 * explicitly. The procedure reloc_offset() returns the address
85 * we're currently running at minus the address we were linked at.
86 * (Note that strings count as static variables.)
87 *
88 * Because OF may have mapped I/O devices into the area starting at
89 * KERNELBASE, particularly on CHRP machines, we can't safely call
90 * OF once the kernel has been mapped to KERNELBASE. Therefore all
91 * OF calls should be done within prom_init(), and prom_init()
92 * and all routines called within it must be careful to relocate
93 * references as necessary.
94 *
95 * Note that the bss is cleared *after* prom_init runs, so we have
96 * to make sure that any static or extern variables it accesses
97 * are put in the data segment.
98 */
99
100
101 #define PROM_BUG() do { \
102 prom_print(RELOC("kernel BUG at ")); \
103 prom_print(RELOC(__FILE__)); \
104 prom_print(RELOC(":")); \
105 prom_print_hex(__LINE__); \
106 prom_print(RELOC("!\n")); \
107 __asm__ __volatile__(".long " BUG_ILLEGAL_INSTR); \
108 } while (0)
109
110
111
112 struct pci_reg_property {
113 struct pci_address addr;
114 u32 size_hi;
115 u32 size_lo;
116 };
117
118
119 struct isa_reg_property {
120 u32 space;
121 u32 address;
122 u32 size;
123 };
124
125 struct pci_intr_map {
126 struct pci_address addr;
127 u32 dunno;
128 phandle int_ctrler;
129 u32 intr;
130 };
131
132
133 typedef unsigned long interpret_func(struct device_node *, unsigned long,
134 int, int);
135 #if 0
136 static interpret_func interpret_pci_props;
137 #endif
138 static unsigned long interpret_pci_props(struct device_node *, unsigned long,
139 int, int);
140
141 static interpret_func interpret_isa_props;
142 static interpret_func interpret_root_props;
143
144 #ifndef FB_MAX /* avoid pulling in all of the fb stuff */
145 #define FB_MAX 8
146 #endif
147
148
149 struct prom_t prom = {
150 0, /* entry */
151 0, /* chosen */
152 0, /* cpu */
153 0, /* stdout */
154 0, /* disp_node */
155 {0,0,0,{0},NULL}, /* args */
156 0, /* version */
157 32, /* encode_phys_size */
158 0 /* bi_rec pointer */
159 #ifdef DEBUG_YABOOT
160 ,NULL /* yaboot */
161 #endif
162 };
163
164
165 char *prom_display_paths[FB_MAX] __initdata = { 0, };
166 unsigned int prom_num_displays = 0;
167 char *of_stdout_device = 0;
168
169 extern struct rtas_t rtas;
170 extern unsigned long klimit;
171 extern struct lmb lmb;
172 #ifdef CONFIG_MSCHUNKS
173 extern struct msChunks msChunks;
174 #endif /* CONFIG_MSCHUNKS */
175
176 #define MAX_PHB 16 * 3 // 16 Towers * 3 PHBs/tower
177 struct _of_tce_table of_tce_table[MAX_PHB + 1] = {{0, 0, 0}};
178
179 char *bootpath = 0;
180 char *bootdevice = 0;
181
182 #define MAX_CPU_THREADS 2
183
184 struct device_node *allnodes = 0;
185
186 static unsigned long call_prom(const char *service, int nargs, int nret, ...);
187 static void prom_exit(void);
188 static unsigned long copy_device_tree(unsigned long);
189 static unsigned long inspect_node(phandle, struct device_node *, unsigned long,
190 unsigned long, struct device_node ***);
191 static unsigned long finish_node(struct device_node *, unsigned long,
192 interpret_func *, int, int);
193 static unsigned long finish_node_interrupts(struct device_node *, unsigned long);
194 static unsigned long check_display(unsigned long);
195 static int prom_next_node(phandle *);
196 static struct bi_record * prom_bi_rec_verify(struct bi_record *);
197 static unsigned long prom_bi_rec_reserve(unsigned long);
198 static struct device_node *find_phandle(phandle);
199
200 #ifdef CONFIG_MSCHUNKS
201 static unsigned long prom_initialize_mschunks(unsigned long);
202 #ifdef DEBUG_PROM
203 void prom_dump_mschunks_mapping(void);
204 #endif /* DEBUG_PROM */
205 #endif /* CONFIG_MSCHUNKS */
206 #ifdef DEBUG_PROM
207 void prom_dump_lmb(void);
208 #endif
209
210 extern unsigned long reloc_offset(void);
211
212 extern void enter_prom(void *dummy,...);
213
214 void cacheable_memzero(void *, unsigned int);
215
216 #ifndef CONFIG_CMDLINE
217 #define CONFIG_CMDLINE ""
218 #endif
219 char cmd_line[512] = CONFIG_CMDLINE;
220 unsigned long dev_tree_size;
221
222 #ifdef CONFIG_HMT
223 struct {
224 unsigned int pir;
225 unsigned int threadid;
226 } hmt_thread_data[NR_CPUS] = {0};
227 #endif /* CONFIG_HMT */
228
229 char testString[] = "LINUX\n";
230
231
232 /* This is the one and *ONLY* place where we actually call open
233 * firmware from, since we need to make sure we're running in 32b
234 * mode when we do. We switch back to 64b mode upon return.
235 */
236
237 static unsigned long __init
call_prom(const char * service,int nargs,int nret,...)238 call_prom(const char *service, int nargs, int nret, ...)
239 {
240 int i;
241 unsigned long offset = reloc_offset();
242 struct prom_t *_prom = PTRRELOC(&prom);
243 va_list list;
244
245 _prom->args.service = (u32)LONG_LSW(service);
246 _prom->args.nargs = nargs;
247 _prom->args.nret = nret;
248 _prom->args.rets = (prom_arg_t *)&(_prom->args.args[nargs]);
249
250 va_start(list, nret);
251 for (i=0; i < nargs ;i++)
252 _prom->args.args[i] = (prom_arg_t)LONG_LSW(va_arg(list, unsigned long));
253 va_end(list);
254
255 for (i=0; i < nret ;i++)
256 _prom->args.rets[i] = 0;
257
258 enter_prom(&_prom->args);
259
260 return (unsigned long)((nret > 0) ? _prom->args.rets[0] : 0);
261 }
262
263
264 static void __init
prom_exit()265 prom_exit()
266 {
267 unsigned long offset = reloc_offset();
268
269 call_prom(RELOC("exit"), 0, 0);
270
271 for (;;) /* should never get here */
272 ;
273 }
274
275 void __init
prom_enter(void)276 prom_enter(void)
277 {
278 unsigned long offset = reloc_offset();
279
280 call_prom(RELOC("enter"), 0, 0);
281 }
282
283
284 void __init
prom_print(const char * msg)285 prom_print(const char *msg)
286 {
287 const char *p, *q;
288 unsigned long offset = reloc_offset();
289 struct prom_t *_prom = PTRRELOC(&prom);
290
291 if (_prom->stdout == 0)
292 return;
293
294 for (p = msg; *p != 0; p = q) {
295 for (q = p; *q != 0 && *q != '\n'; ++q)
296 ;
297 if (q > p)
298 call_prom(RELOC("write"), 3, 1, _prom->stdout,
299 p, q - p);
300 if (*q != 0) {
301 ++q;
302 call_prom(RELOC("write"), 3, 1, _prom->stdout,
303 RELOC("\r\n"), 2);
304 }
305 }
306 }
307
308 void
prom_print_hex(unsigned long val)309 prom_print_hex(unsigned long val)
310 {
311 int i, nibbles = sizeof(val)*2;
312 char buf[sizeof(val)*2+1];
313
314 for (i = nibbles-1; i >= 0; i--) {
315 buf[i] = (val & 0xf) + '0';
316 if (buf[i] > '9')
317 buf[i] += ('a'-'0'-10);
318 val >>= 4;
319 }
320 buf[nibbles] = '\0';
321 prom_print(buf);
322 }
323
324 void
prom_print_nl(void)325 prom_print_nl(void)
326 {
327 unsigned long offset = reloc_offset();
328 prom_print(RELOC("\n"));
329 }
330
331
332 static unsigned long
prom_initialize_naca(unsigned long mem)333 prom_initialize_naca(unsigned long mem)
334 {
335 phandle node;
336 char type[64];
337 unsigned long num_cpus = 0;
338 unsigned long offset = reloc_offset();
339 struct prom_t *_prom = PTRRELOC(&prom);
340 struct naca_struct *_naca = RELOC(naca);
341 struct systemcfg *_systemcfg = RELOC(systemcfg);
342
343 /* NOTE: _naca->debug_switch is already initialized. */
344 #ifdef DEBUG_PROM
345 prom_print(RELOC("prom_initialize_naca: start...\n"));
346 #endif
347
348 _naca->pftSize = 0; /* ilog2 of htab size. computed below. */
349
350 for (node = 0; prom_next_node(&node); ) {
351 type[0] = 0;
352 call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
353 type, sizeof(type));
354
355 if (!strcmp(type, RELOC("cpu"))) {
356 num_cpus += 1;
357
358 /* We're assuming *all* of the CPUs have the same
359 * d-cache and i-cache sizes... -Peter
360 */
361 if ( num_cpus == 1 ) {
362 u32 size, lsize, sets;
363
364 call_prom(RELOC("getprop"), 4, 1, node,
365 RELOC("d-cache-size"),
366 &size, sizeof(size));
367
368 call_prom(RELOC("getprop"), 4, 1, node,
369 RELOC("d-cache-line-size"),
370 &lsize, sizeof(lsize));
371
372 _systemcfg->dCacheL1Size = size;
373 _systemcfg->dCacheL1LineSize = lsize;
374 _naca->dCacheL1LogLineSize = __ilog2(lsize);
375 _naca->dCacheL1LinesPerPage = PAGE_SIZE/lsize;
376
377 call_prom(RELOC("getprop"), 4, 1, node,
378 RELOC("i-cache-size"),
379 &size, sizeof(size));
380
381 call_prom(RELOC("getprop"), 4, 1, node,
382 RELOC("i-cache-line-size"),
383 &lsize, sizeof(lsize));
384
385 _systemcfg->iCacheL1Size = size;
386 _systemcfg->iCacheL1LineSize = lsize;
387 _naca->iCacheL1LogLineSize = __ilog2(lsize);
388 _naca->iCacheL1LinesPerPage = PAGE_SIZE/lsize;
389
390 if (_systemcfg->platform == PLATFORM_PSERIES_LPAR) {
391 u32 pft_size[2];
392 call_prom(RELOC("getprop"), 4, 1, node,
393 RELOC("ibm,pft-size"),
394 &pft_size, sizeof(pft_size));
395 /* pft_size[0] is the NUMA CEC cookie */
396 _naca->pftSize = pft_size[1];
397 }
398 }
399 } else if (!strcmp(type, RELOC("serial"))) {
400 phandle isa, pci;
401 struct isa_reg_property reg;
402 union pci_range ranges;
403
404 type[0] = 0;
405 call_prom(RELOC("getprop"), 4, 1, node,
406 RELOC("ibm,aix-loc"), type, sizeof(type));
407
408 if (strcmp(type, RELOC("S1")))
409 continue;
410
411 call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),
412 ®, sizeof(reg));
413
414 isa = call_prom(RELOC("parent"), 1, 1, node);
415 if (!isa)
416 PROM_BUG();
417 pci = call_prom(RELOC("parent"), 1, 1, isa);
418 if (!pci)
419 PROM_BUG();
420
421 call_prom(RELOC("getprop"), 4, 1, pci, RELOC("ranges"),
422 &ranges, sizeof(ranges));
423
424 if ( _prom->encode_phys_size == 32 )
425 _naca->serialPortAddr = ranges.pci32.phys+reg.address;
426 else {
427 _naca->serialPortAddr =
428 ((((unsigned long)ranges.pci64.phys_hi) << 32) |
429 (ranges.pci64.phys_lo)) + reg.address;
430 }
431 }
432 }
433
434 _naca->interrupt_controller = IC_INVALID;
435 for (node = 0; prom_next_node(&node); ) {
436 type[0] = 0;
437 call_prom(RELOC("getprop"), 4, 1, node, RELOC("name"),
438 type, sizeof(type));
439 if (strcmp(type, RELOC("interrupt-controller"))) {
440 continue;
441 }
442 call_prom(RELOC("getprop"), 4, 1, node, RELOC("compatible"),
443 type, sizeof(type));
444 if (strstr(type, RELOC("open-pic"))) {
445 _naca->interrupt_controller = IC_OPEN_PIC;
446 } else if (strstr(type, RELOC("ppc-xicp"))) {
447 _naca->interrupt_controller = IC_PPC_XIC;
448 } else {
449 prom_print(RELOC("prom: failed to recognize interrupt-controller\n"));
450 }
451 break;
452 }
453
454 if (_naca->interrupt_controller == IC_INVALID) {
455 prom_print(RELOC("prom: failed to find interrupt-controller\n"));
456 PROM_BUG();
457 }
458
459 /* We gotta have at least 1 cpu... */
460 if ( (_systemcfg->processorCount = num_cpus) < 1 )
461 PROM_BUG();
462
463 _systemcfg->physicalMemorySize = lmb_phys_mem_size();
464
465 if (_systemcfg->platform == PLATFORM_PSERIES) {
466 unsigned long rnd_mem_size, pteg_count;
467
468 /* round mem_size up to next power of 2 */
469 rnd_mem_size = 1UL << __ilog2(_systemcfg->physicalMemorySize);
470 if (rnd_mem_size < _systemcfg->physicalMemorySize)
471 rnd_mem_size <<= 1;
472
473 /* # pages / 2 */
474 pteg_count = (rnd_mem_size >> (12 + 1));
475
476 _naca->pftSize = __ilog2(pteg_count << 7);
477 }
478
479 if (_naca->pftSize == 0) {
480 prom_print(RELOC("prom: failed to compute pftSize!\n"));
481 PROM_BUG();
482 }
483
484 /*
485 * Hardcode to GP size. I am not sure where to get this info
486 * in general, as there does not appear to be a slb-size OF
487 * entry. At least in Condor and earlier. DRENG
488 */
489 _naca->slb_size = 64;
490
491 /* Add an eye catcher and the systemcfg layout version number */
492 strcpy(_systemcfg->eye_catcher, RELOC("SYSTEMCFG:PPC64"));
493 _systemcfg->version.major = SYSTEMCFG_MAJOR;
494 _systemcfg->version.minor = SYSTEMCFG_MINOR;
495 _systemcfg->processor = _get_PVR();
496
497 #ifdef DEBUG_PROM
498 prom_print(RELOC("systemcfg->processorCount = 0x"));
499 prom_print_hex(_systemcfg->processorCount);
500 prom_print_nl();
501
502 prom_print(RELOC("systemcfg->physicalMemorySize = 0x"));
503 prom_print_hex(_systemcfg->physicalMemorySize);
504 prom_print_nl();
505
506 prom_print(RELOC("naca->pftSize = 0x"));
507 prom_print_hex(_naca->pftSize);
508 prom_print_nl();
509
510 prom_print(RELOC("systemcfg->dCacheL1LineSize = 0x"));
511 prom_print_hex(_systemcfg->dCacheL1LineSize);
512 prom_print_nl();
513
514 prom_print(RELOC("systemcfg->iCacheL1LineSize = 0x"));
515 prom_print_hex(_systemcfg->iCacheL1LineSize);
516 prom_print_nl();
517
518 prom_print(RELOC("naca->serialPortAddr = 0x"));
519 prom_print_hex(_naca->serialPortAddr);
520 prom_print_nl();
521
522 prom_print(RELOC("naca->interrupt_controller = 0x"));
523 prom_print_hex(_naca->interrupt_controller);
524 prom_print_nl();
525
526 prom_print(RELOC("systemcfg->platform = 0x"));
527 prom_print_hex(_systemcfg->platform);
528 prom_print_nl();
529
530 prom_print(RELOC("prom_initialize_naca: end...\n"));
531 #endif
532
533 return mem;
534 }
535
536
537 static unsigned long __init
prom_initialize_lmb(unsigned long mem)538 prom_initialize_lmb(unsigned long mem)
539 {
540 phandle node;
541 char type[64];
542 unsigned long i, offset = reloc_offset();
543 struct prom_t *_prom = PTRRELOC(&prom);
544 union lmb_reg_property reg;
545 unsigned long lmb_base, lmb_size;
546 unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8;
547
548 #ifdef CONFIG_MSCHUNKS
549 unsigned long max_addr = 0;
550 #if 1
551 /* Fix me: 630 3G-4G IO hack here... -Peter (PPPBBB) */
552 unsigned long io_base = 3UL<<30;
553 unsigned long io_size = 1UL<<30;
554 unsigned long have_630 = 1; /* assume we have a 630 */
555
556 #else
557 unsigned long io_base = <real io base here>;
558 unsigned long io_size = <real io size here>;
559 #endif
560 #endif /* CONFIG_MSCHUNKS */
561
562 lmb_init();
563
564 for (node = 0; prom_next_node(&node); ) {
565 type[0] = 0;
566 call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
567 type, sizeof(type));
568
569 if (strcmp(type, RELOC("memory")))
570 continue;
571
572 num_regs = call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),
573 ®, sizeof(reg)) / bytes_per_reg;
574
575 for (i=0; i < num_regs ;i++) {
576 if (_prom->encode_phys_size == 32) {
577 lmb_base = reg.addr32[i].address;
578 lmb_size = reg.addr32[i].size;
579 } else {
580 lmb_base = reg.addr64[i].address;
581 lmb_size = reg.addr64[i].size;
582 }
583
584 #ifdef CONFIG_MSCHUNKS
585 if ( lmb_addrs_overlap(lmb_base,lmb_size,
586 io_base,io_size) ) {
587 /* If we really have dram here, then we don't
588 * have a 630! -Peter
589 */
590 have_630 = 0;
591 }
592 #endif /* CONFIG_MSCHUNKS */
593 if ( lmb_add(lmb_base, lmb_size) < 0 )
594 prom_print(RELOC("Too many LMB's, discarding this one...\n"));
595 #ifdef CONFIG_MSCHUNKS
596 else if ( max_addr < (lmb_base+lmb_size-1) )
597 max_addr = lmb_base+lmb_size-1;
598 #endif /* CONFIG_MSCHUNKS */
599 }
600
601 }
602
603 #ifdef CONFIG_MSCHUNKS
604 if ( have_630 && lmb_addrs_overlap(0,max_addr,io_base,io_size) )
605 lmb_add_io(io_base, io_size);
606 #endif /* CONFIG_MSCHUNKS */
607
608 lmb_analyze();
609 #ifdef DEBUG_PROM
610 prom_dump_lmb();
611 #endif /* DEBUG_PROM */
612
613 #ifdef CONFIG_MSCHUNKS
614 mem = prom_initialize_mschunks(mem);
615 #ifdef DEBUG_PROM
616 prom_dump_mschunks_mapping();
617 #endif /* DEBUG_PROM */
618 #endif /* CONFIG_MSCHUNKS */
619
620 return mem;
621 }
622
623
624 static void __init
prom_instantiate_rtas(void)625 prom_instantiate_rtas(void)
626 {
627 unsigned long offset = reloc_offset();
628 struct prom_t *_prom = PTRRELOC(&prom);
629 struct rtas_t *_rtas = PTRRELOC(&rtas);
630 struct naca_struct *_naca = RELOC(naca);
631 struct systemcfg *_systemcfg = RELOC(systemcfg);
632 ihandle prom_rtas;
633 u32 getprop_rval;
634
635 #ifdef DEBUG_PROM
636 prom_print(RELOC("prom_instantiate_rtas: start...\n"));
637 #endif
638 prom_rtas = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/rtas"));
639 if (prom_rtas != (ihandle) -1) {
640 char hypertas_funcs[1024];
641 int rc;
642
643 if ((rc = call_prom(RELOC("getprop"),
644 4, 1, prom_rtas,
645 RELOC("ibm,hypertas-functions"),
646 hypertas_funcs,
647 sizeof(hypertas_funcs))) > 0) {
648 _systemcfg->platform = PLATFORM_PSERIES_LPAR;
649 }
650
651 call_prom(RELOC("getprop"),
652 4, 1, prom_rtas,
653 RELOC("rtas-size"),
654 &getprop_rval,
655 sizeof(getprop_rval));
656 _rtas->size = getprop_rval;
657 prom_print(RELOC("instantiating rtas"));
658 if (_rtas->size != 0) {
659 unsigned long rtas_region = RTAS_INSTANTIATE_MAX;
660
661 /* Grab some space within the first RTAS_INSTANTIATE_MAX bytes
662 * of physical memory (or within the RMO region) because RTAS
663 * runs in 32-bit mode and relocate off.
664 */
665 if ( _systemcfg->platform == PLATFORM_PSERIES_LPAR ) {
666 struct lmb *_lmb = PTRRELOC(&lmb);
667 rtas_region = min(_lmb->rmo_size, RTAS_INSTANTIATE_MAX);
668 }
669 _rtas->base = lmb_alloc_base(_rtas->size, PAGE_SIZE, rtas_region);
670
671 prom_print(RELOC(" at 0x"));
672 prom_print_hex(_rtas->base);
673
674 prom_rtas = (ihandle)call_prom(RELOC("open"),
675 1, 1, RELOC("/rtas"));
676 prom_print(RELOC("..."));
677
678 if ((long)call_prom(RELOC("call-method"), 3, 2,
679 RELOC("instantiate-rtas"),
680 prom_rtas,
681 _rtas->base) >= 0) {
682 _rtas->entry = (long)_prom->args.rets[1];
683 }
684 }
685
686 if (_rtas->entry <= 0) {
687 prom_print(RELOC(" failed\n"));
688 } else {
689 prom_print(RELOC(" done\n"));
690 }
691
692 #ifdef DEBUG_PROM
693 prom_print(RELOC("rtas->base = 0x"));
694 prom_print_hex(_rtas->base);
695 prom_print_nl();
696 prom_print(RELOC("rtas->entry = 0x"));
697 prom_print_hex(_rtas->entry);
698 prom_print_nl();
699 prom_print(RELOC("rtas->size = 0x"));
700 prom_print_hex(_rtas->size);
701 prom_print_nl();
702 #endif
703 }
704 #ifdef DEBUG_PROM
705 prom_print(RELOC("prom_instantiate_rtas: end...\n"));
706 #endif
707 }
708
prom_strtoul(const char * cp)709 unsigned long prom_strtoul(const char *cp)
710 {
711 unsigned long result = 0,value;
712
713 while (*cp) {
714 value = *cp-'0';
715 result = result*10 + value;
716 cp++;
717 }
718
719 return result;
720 }
721
722
723 #ifdef CONFIG_MSCHUNKS
724 static unsigned long
prom_initialize_mschunks(unsigned long mem)725 prom_initialize_mschunks(unsigned long mem)
726 {
727 unsigned long offset = reloc_offset();
728 struct lmb *_lmb = PTRRELOC(&lmb);
729 struct msChunks *_msChunks = PTRRELOC(&msChunks);
730 unsigned long i, pchunk = 0;
731 unsigned long addr_range = _lmb->memory.size + _lmb->memory.iosize;
732 unsigned long chunk_size = _lmb->memory.lcd_size;
733
734
735 mem = msChunks_alloc(mem, addr_range / chunk_size, chunk_size);
736
737 /* First create phys -> abs mapping for memory/dram */
738 for (i=0; i < _lmb->memory.cnt ;i++) {
739 unsigned long base = _lmb->memory.region[i].base;
740 unsigned long size = _lmb->memory.region[i].size;
741 unsigned long achunk = addr_to_chunk(base);
742 unsigned long end_achunk = addr_to_chunk(base+size);
743
744 if(_lmb->memory.region[i].type != LMB_MEMORY_AREA)
745 continue;
746
747 _lmb->memory.region[i].physbase = chunk_to_addr(pchunk);
748 for (; achunk < end_achunk ;) {
749 PTRRELOC(_msChunks->abs)[pchunk++] = achunk++;
750 }
751 }
752
753 #ifdef CONFIG_MSCHUNKS
754 /* Now create phys -> abs mapping for IO */
755 for (i=0; i < _lmb->memory.cnt ;i++) {
756 unsigned long base = _lmb->memory.region[i].base;
757 unsigned long size = _lmb->memory.region[i].size;
758 unsigned long achunk = addr_to_chunk(base);
759 unsigned long end_achunk = addr_to_chunk(base+size);
760
761 if(_lmb->memory.region[i].type != LMB_IO_AREA)
762 continue;
763
764 _lmb->memory.region[i].physbase = chunk_to_addr(pchunk);
765 for (; achunk < end_achunk ;) {
766 PTRRELOC(_msChunks->abs)[pchunk++] = achunk++;
767 }
768 }
769 #endif /* CONFIG_MSCHUNKS */
770
771 return mem;
772 }
773
774 #ifdef DEBUG_PROM
775 void
prom_dump_mschunks_mapping(void)776 prom_dump_mschunks_mapping(void)
777 {
778 unsigned long offset = reloc_offset();
779 struct msChunks *_msChunks = PTRRELOC(&msChunks);
780 unsigned long chunk;
781
782 prom_print(RELOC("\nprom_dump_mschunks_mapping:\n"));
783 prom_print(RELOC(" msChunks.num_chunks = 0x"));
784 prom_print_hex(_msChunks->num_chunks);
785 prom_print_nl();
786 prom_print(RELOC(" msChunks.chunk_size = 0x"));
787 prom_print_hex(_msChunks->chunk_size);
788 prom_print_nl();
789 prom_print(RELOC(" msChunks.chunk_shift = 0x"));
790 prom_print_hex(_msChunks->chunk_shift);
791 prom_print_nl();
792 prom_print(RELOC(" msChunks.chunk_mask = 0x"));
793 prom_print_hex(_msChunks->chunk_mask);
794 prom_print_nl();
795 prom_print(RELOC(" msChunks.abs = 0x"));
796 prom_print_hex(_msChunks->abs);
797 prom_print_nl();
798
799 prom_print(RELOC(" msChunks mapping:\n"));
800 for(chunk=0; chunk < _msChunks->num_chunks ;chunk++) {
801 prom_print(RELOC(" phys 0x"));
802 prom_print_hex(chunk);
803 prom_print(RELOC(" -> abs 0x"));
804 prom_print_hex(PTRRELOC(_msChunks->abs)[chunk]);
805 prom_print_nl();
806 }
807
808 }
809 #endif /* DEBUG_PROM */
810 #endif /* CONFIG_MSCHUNKS */
811
812 #ifdef DEBUG_PROM
813 void
prom_dump_lmb(void)814 prom_dump_lmb(void)
815 {
816 unsigned long i;
817 unsigned long offset = reloc_offset();
818 struct lmb *_lmb = PTRRELOC(&lmb);
819
820 prom_print(RELOC("\nprom_dump_lmb:\n"));
821 prom_print(RELOC(" memory.cnt = 0x"));
822 prom_print_hex(_lmb->memory.cnt);
823 prom_print_nl();
824 prom_print(RELOC(" memory.size = 0x"));
825 prom_print_hex(_lmb->memory.size);
826 prom_print_nl();
827 prom_print(RELOC(" memory.lcd_size = 0x"));
828 prom_print_hex(_lmb->memory.lcd_size);
829 prom_print_nl();
830 for (i=0; i < _lmb->memory.cnt ;i++) {
831 prom_print(RELOC(" memory.region[0x"));
832 prom_print_hex(i);
833 prom_print(RELOC("].base = 0x"));
834 prom_print_hex(_lmb->memory.region[i].base);
835 prom_print_nl();
836 prom_print(RELOC(" .physbase = 0x"));
837 prom_print_hex(_lmb->memory.region[i].physbase);
838 prom_print_nl();
839 prom_print(RELOC(" .size = 0x"));
840 prom_print_hex(_lmb->memory.region[i].size);
841 prom_print_nl();
842 prom_print(RELOC(" .type = 0x"));
843 prom_print_hex(_lmb->memory.region[i].type);
844 prom_print_nl();
845 }
846
847 prom_print_nl();
848 prom_print(RELOC(" reserved.cnt = 0x"));
849 prom_print_hex(_lmb->reserved.cnt);
850 prom_print_nl();
851 prom_print(RELOC(" reserved.size = 0x"));
852 prom_print_hex(_lmb->reserved.size);
853 prom_print_nl();
854 prom_print(RELOC(" reserved.lcd_size = 0x"));
855 prom_print_hex(_lmb->reserved.lcd_size);
856 prom_print_nl();
857 for (i=0; i < _lmb->reserved.cnt ;i++) {
858 prom_print(RELOC(" reserved.region[0x"));
859 prom_print_hex(i);
860 prom_print(RELOC("].base = 0x"));
861 prom_print_hex(_lmb->reserved.region[i].base);
862 prom_print_nl();
863 prom_print(RELOC(" .physbase = 0x"));
864 prom_print_hex(_lmb->reserved.region[i].physbase);
865 prom_print_nl();
866 prom_print(RELOC(" .size = 0x"));
867 prom_print_hex(_lmb->reserved.region[i].size);
868 prom_print_nl();
869 prom_print(RELOC(" .type = 0x"));
870 prom_print_hex(_lmb->reserved.region[i].type);
871 prom_print_nl();
872 }
873 }
874 #endif /* DEBUG_PROM */
875
876
877 void
prom_initialize_tce_table(void)878 prom_initialize_tce_table(void)
879 {
880 phandle node;
881 ihandle phb_node;
882 unsigned long offset = reloc_offset();
883 char compatible[64], path[64], type[64], model[64];
884 unsigned long i, table = 0;
885 unsigned long base, vbase, align;
886 unsigned int minalign, minsize;
887 struct _of_tce_table *prom_tce_table = RELOC(of_tce_table);
888 unsigned long tce_entry, *tce_entryp;
889
890 #ifdef DEBUG_PROM
891 prom_print(RELOC("starting prom_initialize_tce_table\n"));
892 #endif
893
894 /* Search all nodes looking for PHBs. */
895 for (node = 0; prom_next_node(&node); ) {
896 compatible[0] = 0;
897 type[0] = 0;
898 model[0] = 0;
899 call_prom(RELOC("getprop"), 4, 1, node, RELOC("compatible"),
900 compatible, sizeof(compatible));
901 call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
902 type, sizeof(type));
903 call_prom(RELOC("getprop"), 4, 1, node, RELOC("model"),
904 model, sizeof(model));
905
906 /* Keep the old logic in tack to avoid regression. */
907 if (compatible[0] != 0) {
908 if((strstr(compatible, RELOC("python")) == NULL) &&
909 (strstr(compatible, RELOC("Speedwagon")) == NULL) &&
910 (strstr(compatible, RELOC("Winnipeg")) == NULL))
911 continue;
912 } else if (model[0] != 0) {
913 if ((strstr(model, RELOC("ython")) == NULL) &&
914 (strstr(model, RELOC("peedwagon")) == NULL) &&
915 (strstr(model, RELOC("innipeg")) == NULL))
916 continue;
917 }
918
919 if ((type[0] == 0) || (strstr(type, RELOC("pci")) == NULL)) {
920 continue;
921 }
922
923 if (call_prom(RELOC("getprop"), 4, 1, node,
924 RELOC("tce-table-minalign"), &minalign,
925 sizeof(minalign)) < 0) {
926 minalign = 0;
927 }
928
929 if (call_prom(RELOC("getprop"), 4, 1, node,
930 RELOC("tce-table-minsize"), &minsize,
931 sizeof(minsize)) < 0) {
932 minsize = 4UL << 20;
933 }
934
935 /* Even though we read what OF wants, we just set the table
936 * size to 4 MB. This is enough to map 2GB of PCI DMA space.
937 * By doing this, we avoid the pitfalls of trying to DMA to
938 * MMIO space and the DMA alias hole.
939 */
940 minsize = 8UL << 20;
941
942 /* Align to the greater of the align or size */
943 align = (minalign < minsize) ? minsize : minalign;
944
945 /* Carve out storage for the TCE table. */
946 base = lmb_alloc(minsize, align);
947
948 if ( !base ) {
949 prom_print(RELOC("ERROR, cannot find space for TCE table.\n"));
950 prom_exit();
951 }
952
953 vbase = absolute_to_virt(base);
954
955 /* Save away the TCE table attributes for later use. */
956 prom_tce_table[table].node = node;
957 prom_tce_table[table].base = vbase;
958 prom_tce_table[table].size = minsize;
959
960 #ifdef DEBUG_PROM
961 prom_print(RELOC("TCE table: 0x"));
962 prom_print_hex(table);
963 prom_print_nl();
964
965 prom_print(RELOC("\tnode = 0x"));
966 prom_print_hex(node);
967 prom_print_nl();
968
969 prom_print(RELOC("\tbase = 0x"));
970 prom_print_hex(vbase);
971 prom_print_nl();
972
973 prom_print(RELOC("\tsize = 0x"));
974 prom_print_hex(minsize);
975 prom_print_nl();
976 #endif
977
978 /* Initialize the table to have a one-to-one mapping
979 * over the allocated size.
980 */
981 tce_entryp = (unsigned long *)base;
982 for (i = 0; i < (minsize >> 3) ;tce_entryp++, i++) {
983 tce_entry = (i << PAGE_SHIFT);
984 tce_entry |= 0x3;
985 *tce_entryp = tce_entry;
986 }
987
988 /* Call OF to setup the TCE hardware */
989 if (call_prom(RELOC("package-to-path"), 3, 1, node,
990 path, 255) <= 0) {
991 prom_print(RELOC("package-to-path failed\n"));
992 } else {
993 prom_print(RELOC("opened "));
994 prom_print(path);
995 prom_print_nl();
996 }
997
998 phb_node = (ihandle)call_prom(RELOC("open"), 1, 1, path);
999 if ( (long)phb_node <= 0) {
1000 prom_print(RELOC("open failed\n"));
1001 } else {
1002 prom_print(RELOC("open success\n"));
1003 }
1004 call_prom(RELOC("call-method"), 6, 0,
1005 RELOC("set-64-bit-addressing"),
1006 phb_node,
1007 -1,
1008 minsize,
1009 base & 0xffffffff,
1010 (base >> 32) & 0xffffffff);
1011 call_prom(RELOC("close"), 1, 0, phb_node);
1012
1013 table++;
1014 }
1015
1016 /* Flag the first invalid entry */
1017 prom_tce_table[table].node = 0;
1018 #ifdef DEBUG_PROM
1019 prom_print(RELOC("ending prom_initialize_tce_table\n"));
1020 #endif
1021 }
1022
1023 /*
1024 * With CHRP SMP we need to use the OF to start the other
1025 * processors so we can't wait until smp_boot_cpus (the OF is
1026 * trashed by then) so we have to put the processors into
1027 * a holding pattern controlled by the kernel (not OF) before
1028 * we destroy the OF.
1029 *
1030 * This uses a chunk of low memory, puts some holding pattern
1031 * code there and sends the other processors off to there until
1032 * smp_boot_cpus tells them to do something. The holding pattern
1033 * checks that address until its cpu # is there, when it is that
1034 * cpu jumps to __secondary_start(). smp_boot_cpus() takes care
1035 * of setting those values.
1036 *
1037 * We also use physical address 0x4 here to tell when a cpu
1038 * is in its holding pattern code.
1039 *
1040 * Fixup comment... DRENG / PPPBBB - Peter
1041 *
1042 * -- Cort
1043 */
1044 static void
prom_hold_cpus(unsigned long mem)1045 prom_hold_cpus(unsigned long mem)
1046 {
1047 unsigned long i;
1048 unsigned int reg;
1049 phandle node;
1050 unsigned long offset = reloc_offset();
1051 char type[64], *path;
1052 int cpuid = 0;
1053 unsigned int interrupt_server[MAX_CPU_THREADS];
1054 unsigned int cpu_threads, hw_cpu_num;
1055 int propsize;
1056 extern void __secondary_hold(void);
1057 extern unsigned long __secondary_hold_spinloop;
1058 extern unsigned long __secondary_hold_acknowledge;
1059 unsigned long *spinloop = __v2a(&__secondary_hold_spinloop);
1060 unsigned long *acknowledge = __v2a(&__secondary_hold_acknowledge);
1061 unsigned long secondary_hold = (unsigned long)__v2a(*PTRRELOC((unsigned long *)__secondary_hold));
1062 struct naca_struct *_naca = RELOC(naca);
1063 struct systemcfg *_systemcfg = RELOC(systemcfg);
1064 struct paca_struct *_xPaca = PTRRELOC(&paca[0]);
1065 struct prom_t *_prom = PTRRELOC(&prom);
1066
1067 /* Initially, we must have one active CPU. */
1068 _systemcfg->processorCount = 1;
1069
1070 #ifdef DEBUG_PROM
1071 prom_print(RELOC("prom_hold_cpus: start...\n"));
1072 prom_print(RELOC(" 1) spinloop = 0x"));
1073 prom_print_hex(spinloop);
1074 prom_print_nl();
1075 prom_print(RELOC(" 1) *spinloop = 0x"));
1076 prom_print_hex(*spinloop);
1077 prom_print_nl();
1078 prom_print(RELOC(" 1) acknowledge = 0x"));
1079 prom_print_hex(acknowledge);
1080 prom_print_nl();
1081 prom_print(RELOC(" 1) *acknowledge = 0x"));
1082 prom_print_hex(*acknowledge);
1083 prom_print_nl();
1084 prom_print(RELOC(" 1) secondary_hold = 0x"));
1085 prom_print_hex(secondary_hold);
1086 prom_print_nl();
1087 #endif
1088
1089 /* Set the common spinloop variable, so all of the secondary cpus
1090 * will block when they are awakened from their OF spinloop.
1091 * This must occur for both SMP and non SMP kernels, since OF will
1092 * be trashed when we move the kernel.
1093 */
1094 *spinloop = 0;
1095
1096 #ifdef CONFIG_HMT
1097 for (i=0; i < NR_CPUS; i++) {
1098 RELOC(hmt_thread_data)[i].pir = 0xdeadbeef;
1099 }
1100 #endif
1101 /* look for cpus */
1102 for (node = 0; prom_next_node(&node); ) {
1103 type[0] = 0;
1104 call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
1105 type, sizeof(type));
1106 if (strcmp(type, RELOC("cpu")) != 0)
1107 continue;
1108
1109 /* Skip non-configured cpus. */
1110 call_prom(RELOC("getprop"), 4, 1, node, RELOC("status"),
1111 type, sizeof(type));
1112 if (strcmp(type, RELOC("okay")) != 0)
1113 continue;
1114
1115 reg = -1;
1116 call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"),
1117 ®, sizeof(reg));
1118
1119 path = (char *) mem;
1120 memset(path, 0, 256);
1121 if ((long) call_prom(RELOC("package-to-path"), 3, 1,
1122 node, path, 255) < 0)
1123 continue;
1124
1125 #ifdef DEBUG_PROM
1126 prom_print_nl();
1127 prom_print(RELOC("cpuid = 0x"));
1128 prom_print_hex(cpuid);
1129 prom_print_nl();
1130 prom_print(RELOC("cpu hw idx = 0x"));
1131 prom_print_hex(reg);
1132 prom_print_nl();
1133 #endif
1134 _xPaca[cpuid].xHwProcNum = reg;
1135
1136 /* Init the acknowledge var which will be reset by
1137 * the secondary cpu when it awakens from its OF
1138 * spinloop.
1139 */
1140 *acknowledge = (unsigned long)-1;
1141
1142 propsize = call_prom(RELOC("getprop"), 4, 1, node,
1143 RELOC("ibm,ppc-interrupt-server#s"),
1144 &interrupt_server,
1145 sizeof(interrupt_server));
1146 if (propsize < 0) {
1147 /* no property. old hardware has no SMT */
1148 cpu_threads = 1;
1149 interrupt_server[0] = reg; /* fake it with phys id */
1150 } else {
1151 /* We have a threaded processor */
1152 cpu_threads = propsize / sizeof(u32);
1153 if (cpu_threads > MAX_CPU_THREADS) {
1154 prom_print(RELOC("SMT: too many threads!\nSMT: found "));
1155 prom_print_hex(cpu_threads);
1156 prom_print(RELOC(", max is "));
1157 prom_print_hex(MAX_CPU_THREADS);
1158 prom_print_nl();
1159 cpu_threads = 1; /* ToDo: panic? */
1160 }
1161 }
1162
1163 hw_cpu_num = interrupt_server[0];
1164 if (hw_cpu_num != _prom->cpu) {
1165 /* Primary Thread of non-boot cpu */
1166 prom_print_hex(cpuid);
1167 prom_print(RELOC(" : starting cpu "));
1168 prom_print(path);
1169 prom_print(RELOC(" ... "));
1170 call_prom(RELOC("start-cpu"), 3, 0, node,
1171 secondary_hold, cpuid);
1172
1173 for(i = 0; (i < 100000000) &&
1174 (*acknowledge == ((unsigned long)-1)); i++ );
1175
1176 if (*acknowledge == cpuid) {
1177 prom_print(RELOC("ok\n"));
1178 /* Set the number of active processors. */
1179 _systemcfg->processorCount++;
1180 _xPaca[cpuid].active = 1;
1181 _xPaca[cpuid].available = 1;
1182 } else {
1183 prom_print(RELOC("failed: "));
1184 prom_print_hex(*acknowledge);
1185 prom_print_nl();
1186 /* prom_panic(RELOC("cpu failed to start")); */
1187 }
1188 } else {
1189 prom_print_hex(cpuid);
1190 prom_print(RELOC(" : booting cpu "));
1191 prom_print(path);
1192 prom_print_nl();
1193 }
1194
1195 /* Init paca for secondary threads. They start later. */
1196 for (i=1; i < cpu_threads; i++) {
1197 cpuid++;
1198 _xPaca[cpuid].xHwProcNum = interrupt_server[i];
1199 prom_print_hex(interrupt_server[i]);
1200 prom_print(RELOC(" : preparing thread ... "));
1201 if (_naca->smt_state) {
1202 _xPaca[cpuid].available = 1;
1203 prom_print(RELOC("available"));
1204 } else {
1205 prom_print(RELOC("not available"));
1206 }
1207 prom_print_nl();
1208 }
1209 cpuid++;
1210 }
1211 #ifdef CONFIG_HMT
1212 /* Only enable HMT on processors that provide support. */
1213 if (__is_processor(PV_PULSAR) ||
1214 __is_processor(PV_ICESTAR) ||
1215 __is_processor(PV_SSTAR)) {
1216 prom_print(RELOC(" starting secondary threads\n"));
1217
1218 for (i=0; i < _systemcfg->processorCount ;i++) {
1219 unsigned long threadid = _systemcfg->processorCount*2-1-i;
1220
1221 if (i == 0) {
1222 unsigned long pir = _get_PIR();
1223 if (__is_processor(PV_PULSAR)) {
1224 RELOC(hmt_thread_data)[i].pir =
1225 pir & 0x1f;
1226 } else {
1227 RELOC(hmt_thread_data)[i].pir =
1228 pir & 0x3ff;
1229 }
1230 }
1231
1232 RELOC(hmt_thread_data)[i].threadid = threadid;
1233 #ifdef DEBUG_PROM
1234 prom_print(RELOC(" cpuid 0x"));
1235 prom_print_hex(i);
1236 prom_print(RELOC(" maps to threadid 0x"));
1237 prom_print_hex(threadid);
1238 prom_print_nl();
1239 prom_print(RELOC(" pir 0x"));
1240 prom_print_hex(RELOC(hmt_thread_data)[i].pir);
1241 prom_print_nl();
1242 #endif
1243 _xPaca[threadid].xHwProcNum = _xPaca[i].xHwProcNum+1;
1244 }
1245 _systemcfg->processorCount *= 2;
1246 } else {
1247 prom_print(RELOC("Processor is not HMT capable\n"));
1248 }
1249 #endif
1250
1251 #ifdef DEBUG_PROM
1252 prom_print(RELOC("prom_hold_cpus: end...\n"));
1253 #endif
1254 }
1255
1256 static void
smt_setup(void)1257 smt_setup(void)
1258 {
1259 char *p, *q;
1260 char my_smt_enabled = SMT_DYNAMIC;
1261 unsigned long my_smt_snooze_delay;
1262 ihandle prom_options = NULL;
1263 char option[9];
1264 unsigned long offset = reloc_offset();
1265 struct naca_struct *_naca = RELOC(naca);
1266 char found = 0;
1267
1268 if (strstr(RELOC(cmd_line), RELOC("smt-enabled="))) {
1269 for (q = RELOC(cmd_line); (p = strstr(q, RELOC("smt-enabled="))) != 0; ) {
1270 q = p + 12;
1271 if (p > RELOC(cmd_line) && p[-1] != ' ')
1272 continue;
1273 found = 1;
1274 if (q[0] == 'o' && q[1] == 'f' &&
1275 q[2] == 'f' && (q[3] == ' ' || q[3] == '\0')) {
1276 my_smt_enabled = SMT_OFF;
1277 } else if (q[0]=='o' && q[1] == 'n' &&
1278 (q[2] == ' ' || q[2] == '\0')) {
1279 my_smt_enabled = SMT_ON;
1280 } else {
1281 my_smt_enabled = SMT_DYNAMIC;
1282 }
1283 }
1284 }
1285 if (!found) {
1286 prom_options = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/options"));
1287 if (prom_options != (ihandle) -1) {
1288 call_prom(RELOC("getprop"),
1289 4, 1, prom_options,
1290 RELOC("ibm,smt-enabled"),
1291 option, sizeof(option));
1292 if (option[0] != 0) {
1293 found = 1;
1294 if (!strcmp(option, "off"))
1295 my_smt_enabled = SMT_OFF;
1296 else if (!strcmp(option, "on"))
1297 my_smt_enabled = SMT_ON;
1298 else
1299 my_smt_enabled = SMT_DYNAMIC;
1300 }
1301 }
1302 }
1303
1304 if (!found )
1305 my_smt_enabled = SMT_DYNAMIC; /* default to on */
1306
1307 found = 0;
1308 if (my_smt_enabled) {
1309 if (strstr(RELOC(cmd_line), RELOC("smt-snooze-delay="))) {
1310 for (q = RELOC(cmd_line); (p = strstr(q, RELOC("smt-snooze-delay="))) != 0; ) {
1311 q = p + 17;
1312 if (p > RELOC(cmd_line) && p[-1] != ' ')
1313 continue;
1314 found = 1;
1315 /* Don't use simple_strtoul() because _ctype & others aren't RELOC'd */
1316 my_smt_snooze_delay = 0;
1317 while (*q >= '0' && *q <= '9') {
1318 my_smt_snooze_delay = my_smt_snooze_delay * 10 + *q - '0';
1319 q++;
1320 }
1321 }
1322 }
1323
1324 if (!found) {
1325 prom_options = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/options"));
1326 if (prom_options != (ihandle) -1) {
1327 call_prom(RELOC("getprop"),
1328 4, 1, prom_options,
1329 RELOC("ibm,smt-snooze-delay"),
1330 option, sizeof(option));
1331 if (option[0] != 0) {
1332 found = 1;
1333 /* Don't use simple_strtoul() because _ctype & others aren't RELOC'd */
1334 my_smt_snooze_delay = 0;
1335 q = option;
1336 while (*q >= '0' && *q <= '9') {
1337 my_smt_snooze_delay = my_smt_snooze_delay * 10 + *q - '0';
1338 q++;
1339 }
1340 }
1341 }
1342 }
1343
1344 if (!found) {
1345 my_smt_snooze_delay = 30000; /* default value */
1346 }
1347 } else {
1348 my_smt_snooze_delay = 0; /* default value */
1349 }
1350 _naca->smt_snooze_delay = my_smt_snooze_delay;
1351 _naca->smt_state = my_smt_enabled;
1352 }
1353
1354 #ifdef CONFIG_PPCDBG
1355 extern char *trace_names[]; /* defined in udbg.c -- need a better interface */
1356
parse_ppcdbg_optionlist(const char * cmd,const char * cmdend)1357 void parse_ppcdbg_optionlist(const char *cmd,
1358 const char *cmdend)
1359 {
1360 unsigned long offset = reloc_offset();
1361 char **_trace_names = PTRRELOC(&trace_names[0]);
1362 const char *all = RELOC("all");
1363 struct naca_struct *_naca = RELOC(naca);
1364 const char *p, *pend;
1365 int onoff, i, cmdidx;
1366 unsigned long mask;
1367 char cmdbuf[30];
1368
1369 for (p = cmd, pend = strchr(p, ',');
1370 p < cmdend;
1371 pend = strchr(p, ',')) {
1372 if (pend == NULL || pend > cmdend)
1373 pend = cmdend;
1374 onoff = 1; /* default */
1375 if (*p == '+' || *p == '-') {
1376 /* explicit on or off */
1377 onoff = (*p == '+');
1378 p++;
1379 }
1380 /* parse out p..pend here */
1381 if (pend - p < sizeof(cmdbuf)) {
1382 strncpy(cmdbuf, p, pend - p);
1383 cmdbuf[pend - p] = '\0';
1384 for (cmdidx = -1, i = 0; i < PPCDBG_NUM_FLAGS; i++) {
1385 if (_trace_names[i] &&
1386 (strcmp(PTRRELOC(_trace_names[i]), cmdbuf) == 0)) {
1387 cmdidx = i;
1388 break;
1389 }
1390 }
1391 mask = 0;
1392 if (cmdidx >= 0) {
1393 mask = (1 << cmdidx);
1394 } else if (strcmp(cmdbuf, all) == 0) {
1395 mask = PPCDBG_ALL;
1396 } else {
1397 prom_print(RELOC("ppcdbg: unknown debug: "));
1398 prom_print(cmdbuf);
1399 prom_print_nl();
1400 }
1401 if (mask) {
1402 if (onoff)
1403 _naca->debug_switch |= mask;
1404 else
1405 _naca->debug_switch &= ~mask;
1406 }
1407 }
1408 p = pend+1;
1409 }
1410 }
1411
1412 /*
1413 * Parse ppcdbg= cmdline option.
1414 *
1415 * Option names are listed in <asm/ppcdebug.h> in the trace_names
1416 * table. Multiple names may be listed separated by commas (no whitespace),
1417 * and each option may be preceeded by a + or - to force on or off state.
1418 * The special option "all" may also be used. They are processed strictly
1419 * left to right. Multiple ppcdbg= options are the command line are treated
1420 * as a single option list.
1421 *
1422 * Examples: ppcdbg=phb_init,buswalk
1423 * ppcdbg=all,-mm,-tce
1424 *
1425 * ToDo: add "group" names that map to common combinations of flags.
1426 */
parse_ppcdbg_cmd_line(const char * line)1427 void parse_ppcdbg_cmd_line(const char *line)
1428 {
1429 unsigned long offset = reloc_offset();
1430 const char *ppcdbgopt = RELOC("ppcdbg=");
1431 struct naca_struct *_naca = RELOC(naca);
1432 const char *cmd, *end;
1433
1434 _naca->debug_switch = PPC_DEBUG_DEFAULT; /* | PPCDBG_BUSWALK | PPCDBG_PHBINIT | PPCDBG_MM | PPCDBG_MMINIT | PPCDBG_TCEINIT | PPCDBG_TCE */
1435 cmd = line;
1436 while (cmd && (cmd = strstr(cmd, ppcdbgopt)) != NULL) {
1437 cmd += 7; /* skip ppcdbg= */
1438 for (end = cmd;
1439 *end != '\0' && *end != '\t' && *end != ' ';
1440 end++)
1441 ; /* scan to whitespace or end */
1442 parse_ppcdbg_optionlist(cmd, end);
1443 }
1444 }
1445 #endif /* CONFIG_PPCDBG */
1446
1447
1448 /*
1449 * Do minimal cmd_line parsing for early boot options.
1450 */
1451 static void __init
prom_parse_cmd_line(char * line)1452 prom_parse_cmd_line(char *line)
1453 {
1454 #ifdef CONFIG_PPCDBG
1455 parse_ppcdbg_cmd_line(line);
1456 #endif
1457 }
1458
1459 /*
1460 * We enter here early on, when the Open Firmware prom is still
1461 * handling exceptions and the MMU hash table for us.
1462 */
1463
1464 unsigned long __init
prom_init(unsigned long r3,unsigned long r4,unsigned long pp,unsigned long r6,unsigned long r7,yaboot_debug_t * yaboot)1465 prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
1466 unsigned long r6, unsigned long r7, yaboot_debug_t *yaboot)
1467 {
1468 int chrp = 0;
1469 unsigned long mem;
1470 ihandle prom_mmu, prom_op, prom_root, prom_cpu;
1471 phandle cpu_pkg;
1472 unsigned long offset = reloc_offset();
1473 long l, sz;
1474 char *p, *d;
1475 unsigned long phys;
1476 u32 getprop_rval;
1477 struct systemcfg *_systemcfg = RELOC(systemcfg);
1478 struct paca_struct *_xPaca = PTRRELOC(&paca[0]);
1479 struct prom_t *_prom = PTRRELOC(&prom);
1480 char *_cmd_line = PTRRELOC(&cmd_line[0]);
1481
1482 /* Default machine type. */
1483 _systemcfg->platform = PLATFORM_PSERIES;
1484
1485 /* Get a handle to the prom entry point before anything else */
1486 _prom->entry = pp;
1487 _prom->bi_recs = prom_bi_rec_verify((struct bi_record *)r6);
1488 if ( _prom->bi_recs != NULL ) {
1489 RELOC(klimit) = PTRUNRELOC((unsigned long)_prom->bi_recs + _prom->bi_recs->data[1]);
1490 }
1491
1492 #ifdef DEBUG_YABOOT
1493 call_yaboot(yaboot->dummy,offset>>32,offset&0xffffffff);
1494 call_yaboot(yaboot->printf, RELOC("offset = 0x%08x%08x\n"), LONG_MSW(offset), LONG_LSW(offset));
1495 #endif
1496
1497 /* Default */
1498 phys = KERNELBASE - offset;
1499
1500 #ifdef DEBUG_YABOOT
1501 call_yaboot(yaboot->printf, RELOC("phys = 0x%08x%08x\n"), LONG_MSW(phys), LONG_LSW(phys));
1502 #endif
1503
1504
1505 #ifdef DEBUG_YABOOT
1506 _prom->yaboot = yaboot;
1507 call_yaboot(yaboot->printf, RELOC("pp = 0x%08x%08x\n"), LONG_MSW(pp), LONG_LSW(pp));
1508 call_yaboot(yaboot->printf, RELOC("prom = 0x%08x%08x\n"), LONG_MSW(_prom->entry), LONG_LSW(_prom->entry));
1509 #endif
1510
1511 /* First get a handle for the stdout device */
1512 _prom->chosen = (ihandle)call_prom(RELOC("finddevice"), 1, 1,
1513 RELOC("/chosen"));
1514
1515 #ifdef DEBUG_YABOOT
1516 call_yaboot(yaboot->printf, RELOC("prom->chosen = 0x%08x%08x\n"), LONG_MSW(_prom->chosen), LONG_LSW(_prom->chosen));
1517 #endif
1518
1519 if ((long)_prom->chosen <= 0)
1520 prom_exit();
1521
1522 if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
1523 RELOC("stdout"), &getprop_rval,
1524 sizeof(getprop_rval)) <= 0)
1525 prom_exit();
1526
1527 _prom->stdout = (ihandle)(unsigned long)getprop_rval;
1528
1529 #ifdef DEBUG_YABOOT
1530 if (_prom->stdout == 0) {
1531 call_yaboot(yaboot->printf, RELOC("prom->stdout = 0x%08x%08x\n"), LONG_MSW(_prom->stdout), LONG_LSW(_prom->stdout));
1532 }
1533
1534 call_yaboot(yaboot->printf, RELOC("prom->stdout = 0x%08x%08x\n"), LONG_MSW(_prom->stdout), LONG_LSW(_prom->stdout));
1535 #endif
1536
1537 #ifdef DEBUG_YABOOT
1538 call_yaboot(yaboot->printf, RELOC("Location: 0x11\n"));
1539 #endif
1540
1541 mem = RELOC(klimit) - offset;
1542 #ifdef DEBUG_YABOOT
1543 call_yaboot(yaboot->printf, RELOC("Location: 0x11b\n"));
1544 #endif
1545
1546 /* Get the full OF pathname of the stdout device */
1547 p = (char *) mem;
1548 memset(p, 0, 256);
1549 call_prom(RELOC("instance-to-path"), 3, 1, _prom->stdout, p, 255);
1550 RELOC(of_stdout_device) = PTRUNRELOC(p);
1551 mem += strlen(p) + 1;
1552
1553 getprop_rval = 1;
1554 prom_root = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/"));
1555 if (prom_root != (ihandle)-1) {
1556 call_prom(RELOC("getprop"), 4, 1,
1557 prom_root, RELOC("#size-cells"),
1558 &getprop_rval, sizeof(getprop_rval));
1559 }
1560 _prom->encode_phys_size = (getprop_rval==1) ? 32 : 64;
1561
1562 /* Fetch the cmd_line */
1563 sz = (long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
1564 RELOC("bootargs"), _cmd_line,
1565 sizeof(cmd_line)-1);
1566 if (sz > 0)
1567 _cmd_line[sz] = '\0';
1568 if (sz <=1 )
1569 strcpy(_cmd_line,RELOC(CONFIG_CMDLINE));
1570
1571 prom_parse_cmd_line(_cmd_line);
1572
1573 #ifdef DEBUG_PROM
1574 prom_print(RELOC("DRENG: Detect OF version...\n"));
1575 #endif
1576 /* Find the OF version */
1577 prom_op = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/openprom"));
1578 if (prom_op != (ihandle)-1) {
1579 char model[64];
1580 sz = (long)call_prom(RELOC("getprop"), 4, 1, prom_op,
1581 RELOC("model"), model, 64);
1582 if (sz > 0) {
1583 char *c;
1584 /* hack to skip the ibm chrp firmware # */
1585 if ( strncmp(model,RELOC("IBM"),3) ) {
1586 for (c = model; *c; c++)
1587 if (*c >= '0' && *c <= '9') {
1588 _prom->version = *c - '0';
1589 break;
1590 }
1591 }
1592 else
1593 chrp = 1;
1594 }
1595 }
1596 if (_prom->version >= 3)
1597 prom_print(RELOC("OF Version 3 detected.\n"));
1598
1599
1600 /* Determine which cpu is actually running right _now_ */
1601 if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
1602 RELOC("cpu"), &getprop_rval,
1603 sizeof(getprop_rval)) <= 0)
1604 prom_exit();
1605
1606 prom_cpu = (ihandle)(unsigned long)getprop_rval;
1607 cpu_pkg = call_prom(RELOC("instance-to-package"), 1, 1, prom_cpu);
1608 call_prom(RELOC("getprop"), 4, 1,
1609 cpu_pkg, RELOC("reg"),
1610 &getprop_rval, sizeof(getprop_rval));
1611 _prom->cpu = (int)(unsigned long)getprop_rval;
1612 _xPaca[0].xHwProcNum = _prom->cpu;
1613
1614 #ifdef DEBUG_PROM
1615 prom_print(RELOC("Booting CPU hw index = 0x"));
1616 prom_print_hex(_prom->cpu);
1617 prom_print_nl();
1618 #endif
1619
1620 /* Get the boot device and translate it to a full OF pathname. */
1621 p = (char *) mem;
1622 l = (long) call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
1623 RELOC("bootpath"), p, 1<<20);
1624 if (l > 0) {
1625 p[l] = 0; /* should already be null-terminated */
1626 RELOC(bootpath) = PTRUNRELOC(p);
1627 mem += l + 1;
1628 d = (char *) mem;
1629 *d = 0;
1630 call_prom(RELOC("canon"), 3, 1, p, d, 1<<20);
1631 RELOC(bootdevice) = PTRUNRELOC(d);
1632 mem = DOUBLEWORD_ALIGN(mem + strlen(d) + 1);
1633 }
1634
1635 mem = prom_initialize_lmb(mem);
1636
1637 mem = prom_bi_rec_reserve(mem);
1638
1639 mem = check_display(mem);
1640
1641 prom_instantiate_rtas();
1642
1643 /* Initialize some system info into the Naca early... */
1644 mem = prom_initialize_naca(mem);
1645
1646 smt_setup();
1647
1648 /* If we are on an SMP machine, then we *MUST* do the
1649 * following, regardless of whether we have an SMP
1650 * kernel or not.
1651 */
1652 prom_hold_cpus(mem);
1653
1654 #ifdef DEBUG_PROM
1655 prom_print(RELOC("copying OF device tree...\n"));
1656 #endif
1657 mem = copy_device_tree(mem);
1658
1659 RELOC(klimit) = mem + offset;
1660
1661 lmb_reserve(0, __pa(RELOC(klimit)));
1662
1663 if (_systemcfg->platform == PLATFORM_PSERIES)
1664 prom_initialize_tce_table();
1665
1666 if ((long) call_prom(RELOC("getprop"), 4, 1,
1667 _prom->chosen,
1668 RELOC("mmu"),
1669 &getprop_rval,
1670 sizeof(getprop_rval)) <= 0) {
1671 prom_print(RELOC(" no MMU found\n"));
1672 prom_exit();
1673 }
1674
1675 /* We assume the phys. address size is 3 cells */
1676 prom_mmu = (ihandle)(unsigned long)getprop_rval;
1677
1678 if ((long)call_prom(RELOC("call-method"), 4, 4,
1679 RELOC("translate"),
1680 prom_mmu,
1681 (void *)(KERNELBASE - offset),
1682 (void *)1) != 0) {
1683 prom_print(RELOC(" (translate failed) "));
1684 } else {
1685 prom_print(RELOC(" (translate ok) "));
1686 phys = (unsigned long)_prom->args.rets[3];
1687 }
1688
1689 /* If OpenFirmware version >= 3, then use quiesce call */
1690 if (_prom->version >= 3) {
1691 prom_print(RELOC("Calling quiesce ...\n"));
1692 call_prom(RELOC("quiesce"), 0, 0);
1693 phys = KERNELBASE - offset;
1694 }
1695
1696 prom_print(RELOC("returning from prom_init\n"));
1697 return phys;
1698 }
1699
1700
1701 static int
prom_set_color(ihandle ih,int i,int r,int g,int b)1702 prom_set_color(ihandle ih, int i, int r, int g, int b)
1703 {
1704 unsigned long offset = reloc_offset();
1705
1706 return (int)(long)call_prom(RELOC("call-method"), 6, 1,
1707 RELOC("color!"),
1708 ih,
1709 (void *)(long) i,
1710 (void *)(long) b,
1711 (void *)(long) g,
1712 (void *)(long) r );
1713 }
1714
1715 /*
1716 * If we have a display that we don't know how to drive,
1717 * we will want to try to execute OF's open method for it
1718 * later. However, OF will probably fall over if we do that
1719 * we've taken over the MMU.
1720 * So we check whether we will need to open the display,
1721 * and if so, open it now.
1722 */
1723 static unsigned long __init
check_display(unsigned long mem)1724 check_display(unsigned long mem)
1725 {
1726 phandle node;
1727 ihandle ih;
1728 int i;
1729 unsigned long offset = reloc_offset();
1730 struct prom_t *_prom = PTRRELOC(&prom);
1731 char type[64], *path;
1732 static unsigned char default_colors[] = {
1733 0x00, 0x00, 0x00,
1734 0x00, 0x00, 0xaa,
1735 0x00, 0xaa, 0x00,
1736 0x00, 0xaa, 0xaa,
1737 0xaa, 0x00, 0x00,
1738 0xaa, 0x00, 0xaa,
1739 0xaa, 0xaa, 0x00,
1740 0xaa, 0xaa, 0xaa,
1741 0x55, 0x55, 0x55,
1742 0x55, 0x55, 0xff,
1743 0x55, 0xff, 0x55,
1744 0x55, 0xff, 0xff,
1745 0xff, 0x55, 0x55,
1746 0xff, 0x55, 0xff,
1747 0xff, 0xff, 0x55,
1748 0xff, 0xff, 0xff
1749 };
1750
1751 _prom->disp_node = 0;
1752
1753 for (node = 0; prom_next_node(&node); ) {
1754 type[0] = 0;
1755 call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"),
1756 type, sizeof(type));
1757 if (strcmp(type, RELOC("display")) != 0)
1758 continue;
1759 /* It seems OF doesn't null-terminate the path :-( */
1760 path = (char *) mem;
1761 memset(path, 0, 256);
1762 if ((long) call_prom(RELOC("package-to-path"), 3, 1,
1763 node, path, 255) < 0)
1764 continue;
1765 prom_print(RELOC("opening display "));
1766 prom_print(path);
1767 ih = (ihandle)call_prom(RELOC("open"), 1, 1, path);
1768 if (ih == (ihandle)0 || ih == (ihandle)-1) {
1769 prom_print(RELOC("... failed\n"));
1770 continue;
1771 }
1772 prom_print(RELOC("... ok\n"));
1773
1774 if (_prom->disp_node == 0)
1775 _prom->disp_node = (ihandle)(unsigned long)node;
1776
1777 /* Setup a useable color table when the appropriate
1778 * method is available. Should update this to set-colors */
1779 for (i = 0; i < 32; i++)
1780 if (prom_set_color(ih, i, RELOC(default_colors)[i*3],
1781 RELOC(default_colors)[i*3+1],
1782 RELOC(default_colors)[i*3+2]) != 0)
1783 break;
1784
1785 #ifdef CONFIG_FB
1786 for (i = 0; i < LINUX_LOGO_COLORS; i++)
1787 if (prom_set_color(ih, i + 32,
1788 RELOC(linux_logo_red)[i],
1789 RELOC(linux_logo_green)[i],
1790 RELOC(linux_logo_blue)[i]) != 0)
1791 break;
1792 #endif /* CONFIG_FB */
1793
1794 /*
1795 * If this display is the device that OF is using for stdout,
1796 * move it to the front of the list.
1797 */
1798 mem += strlen(path) + 1;
1799 i = RELOC(prom_num_displays)++;
1800 if (RELOC(of_stdout_device) != 0 && i > 0
1801 && strcmp(PTRRELOC(RELOC(of_stdout_device)), path) == 0) {
1802 for (; i > 0; --i)
1803 RELOC(prom_display_paths[i]) = RELOC(prom_display_paths[i-1]);
1804 }
1805 RELOC(prom_display_paths[i]) = PTRUNRELOC(path);
1806 if (RELOC(prom_num_displays) >= FB_MAX)
1807 break;
1808 }
1809 return DOUBLEWORD_ALIGN(mem);
1810 }
1811
1812 static int __init
prom_next_node(phandle * nodep)1813 prom_next_node(phandle *nodep)
1814 {
1815 phandle node;
1816 unsigned long offset = reloc_offset();
1817
1818 if ((node = *nodep) != 0
1819 && (*nodep = call_prom(RELOC("child"), 1, 1, node)) != 0)
1820 return 1;
1821 if ((*nodep = call_prom(RELOC("peer"), 1, 1, node)) != 0)
1822 return 1;
1823 for (;;) {
1824 if ((node = call_prom(RELOC("parent"), 1, 1, node)) == 0)
1825 return 0;
1826 if ((*nodep = call_prom(RELOC("peer"), 1, 1, node)) != 0)
1827 return 1;
1828 }
1829 }
1830
1831 /*
1832 * Make a copy of the device tree from the PROM.
1833 */
1834 static unsigned long __init
copy_device_tree(unsigned long mem_start)1835 copy_device_tree(unsigned long mem_start)
1836 {
1837 phandle root;
1838 unsigned long new_start;
1839 struct device_node **allnextp;
1840 unsigned long offset = reloc_offset();
1841 unsigned long mem_end = mem_start + (8<<20);
1842
1843 root = call_prom(RELOC("peer"), 1, 1, (phandle)0);
1844 if (root == (phandle)0) {
1845 prom_print(RELOC("couldn't get device tree root\n"));
1846 prom_exit();
1847 }
1848 allnextp = &RELOC(allnodes);
1849 mem_start = DOUBLEWORD_ALIGN(mem_start);
1850 new_start = inspect_node(root, 0, mem_start, mem_end, &allnextp);
1851 *allnextp = 0;
1852 return new_start;
1853 }
1854
1855 __init
1856 static unsigned long
inspect_node(phandle node,struct device_node * dad,unsigned long mem_start,unsigned long mem_end,struct device_node *** allnextpp)1857 inspect_node(phandle node, struct device_node *dad,
1858 unsigned long mem_start, unsigned long mem_end,
1859 struct device_node ***allnextpp)
1860 {
1861 int l;
1862 phandle child;
1863 struct device_node *np;
1864 struct property *pp, **prev_propp;
1865 char *prev_name, *namep;
1866 unsigned char *valp;
1867 unsigned long offset = reloc_offset();
1868
1869 np = (struct device_node *) mem_start;
1870 mem_start += sizeof(struct device_node);
1871 memset(np, 0, sizeof(*np));
1872 np->node = node;
1873 **allnextpp = PTRUNRELOC(np);
1874 *allnextpp = &np->allnext;
1875 if (dad != 0) {
1876 np->parent = PTRUNRELOC(dad);
1877 /* we temporarily use the `next' field as `last_child'. */
1878 if (dad->next == 0)
1879 dad->child = PTRUNRELOC(np);
1880 else
1881 dad->next->sibling = PTRUNRELOC(np);
1882 dad->next = np;
1883 }
1884
1885 /* get and store all properties */
1886 prev_propp = &np->properties;
1887 prev_name = RELOC("");
1888 for (;;) {
1889 pp = (struct property *) mem_start;
1890 namep = (char *) (pp + 1);
1891 pp->name = PTRUNRELOC(namep);
1892 if ((long) call_prom(RELOC("nextprop"), 3, 1, node, prev_name,
1893 namep) <= 0)
1894 break;
1895 mem_start = DOUBLEWORD_ALIGN((unsigned long)namep + strlen(namep) + 1);
1896 prev_name = namep;
1897 valp = (unsigned char *) mem_start;
1898 pp->value = PTRUNRELOC(valp);
1899 pp->length = (int)(long)
1900 call_prom(RELOC("getprop"), 4, 1, node, namep,
1901 valp, mem_end - mem_start);
1902 if (pp->length < 0)
1903 continue;
1904 mem_start = DOUBLEWORD_ALIGN(mem_start + pp->length);
1905 *prev_propp = PTRUNRELOC(pp);
1906 prev_propp = &pp->next;
1907 }
1908
1909 /* Add a "linux_phandle" value */
1910 if (np->node != NULL) {
1911 u32 ibm_phandle = 0;
1912 int len;
1913
1914 /* First see if "ibm,phandle" exists and use its value */
1915 len = (int) call_prom(RELOC("getprop"), 4, 1, node,
1916 RELOC("ibm,phandle"),
1917 &ibm_phandle, sizeof(ibm_phandle));
1918 if (len < 0) {
1919 np->linux_phandle = np->node;
1920 } else {
1921 np->linux_phandle = ibm_phandle;
1922 }
1923 }
1924
1925 *prev_propp = 0;
1926
1927 /* get the node's full name */
1928 l = (long) call_prom(RELOC("package-to-path"), 3, 1, node,
1929 (char *) mem_start, mem_end - mem_start);
1930 if (l >= 0) {
1931 np->full_name = PTRUNRELOC((char *) mem_start);
1932 *(char *)(mem_start + l) = 0;
1933 mem_start = DOUBLEWORD_ALIGN(mem_start + l + 1);
1934 }
1935
1936 /* do all our children */
1937 child = call_prom(RELOC("child"), 1, 1, node);
1938 while (child != (phandle)0) {
1939 mem_start = inspect_node(child, np, mem_start, mem_end,
1940 allnextpp);
1941 child = call_prom(RELOC("peer"), 1, 1, child);
1942 }
1943
1944 return mem_start;
1945 }
1946
1947 /*
1948 * finish_device_tree is called once things are running normally
1949 * (i.e. with text and data mapped to the address they were linked at).
1950 * It traverses the device tree and fills in the name, type,
1951 * {n_}addrs and {n_}intrs fields of each node.
1952 */
1953 void __init
finish_device_tree(void)1954 finish_device_tree(void)
1955 {
1956 unsigned long mem = klimit;
1957
1958 mem = finish_node(allnodes, mem, NULL, 0, 0);
1959 dev_tree_size = mem - (unsigned long) allnodes;
1960
1961 mem = _ALIGN(mem, PAGE_SIZE);
1962 lmb_reserve(__pa(klimit), mem-klimit);
1963
1964 klimit = mem;
1965
1966 rtas.dev = find_devices("rtas");
1967 }
1968
1969 static unsigned long __init
finish_node(struct device_node * np,unsigned long mem_start,interpret_func * ifunc,int naddrc,int nsizec)1970 finish_node(struct device_node *np, unsigned long mem_start,
1971 interpret_func *ifunc, int naddrc, int nsizec)
1972 {
1973 struct device_node *child;
1974 int *ip;
1975
1976 np->name = get_property(np, "name", 0);
1977 np->type = get_property(np, "device_type", 0);
1978
1979 /* get the device addresses and interrupts */
1980 if (ifunc != NULL) {
1981 mem_start = ifunc(np, mem_start, naddrc, nsizec);
1982 }
1983 mem_start = finish_node_interrupts(np, mem_start);
1984
1985 /* Look for #address-cells and #size-cells properties. */
1986 ip = (int *) get_property(np, "#address-cells", 0);
1987 if (ip != NULL)
1988 naddrc = *ip;
1989 ip = (int *) get_property(np, "#size-cells", 0);
1990 if (ip != NULL)
1991 nsizec = *ip;
1992
1993 /* the f50 sets the name to 'display' and 'compatible' to what we
1994 * expect for the name -- Cort
1995 */
1996 ifunc = NULL;
1997 if (!strcmp(np->name, "display"))
1998 np->name = get_property(np, "compatible", 0);
1999
2000 if (!strcmp(np->name, "device-tree") || np->parent == NULL)
2001 ifunc = interpret_root_props;
2002 else if (np->type == 0)
2003 ifunc = NULL;
2004 else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))
2005 ifunc = interpret_pci_props;
2006 else if (!strcmp(np->type, "isa"))
2007 ifunc = interpret_isa_props;
2008
2009 for (child = np->child; child != NULL; child = child->sibling)
2010 mem_start = finish_node(child, mem_start, ifunc,
2011 naddrc, nsizec);
2012
2013 return mem_start;
2014 }
2015
2016 /* This routine walks the interrupt tree for a given device node and gather
2017 * all necessary informations according to the draft interrupt mapping
2018 * for CHRP. The current version was only tested on Apple "Core99" machines
2019 * and may not handle cascaded controllers correctly.
2020 */
2021 __init
2022 static unsigned long
finish_node_interrupts(struct device_node * np,unsigned long mem_start)2023 finish_node_interrupts(struct device_node *np, unsigned long mem_start)
2024 {
2025 /* Finish this node */
2026 unsigned int *isizep, *asizep, *interrupts, *map, *map_mask, *reg;
2027 phandle *parent, map_parent;
2028 struct device_node *node, *parent_node;
2029 int l, isize, ipsize, asize, map_size, regpsize;
2030
2031 /* Currently, we don't look at all nodes with no "interrupts" property */
2032
2033 interrupts = (unsigned int *)get_property(np, "interrupts", &l);
2034 if (interrupts == NULL)
2035 return mem_start;
2036 ipsize = l>>2;
2037
2038 reg = (unsigned int *)get_property(np, "reg", &l);
2039 regpsize = l>>2;
2040
2041 /* We assume default interrupt cell size is 1 (bugus ?) */
2042 isize = 1;
2043 node = np;
2044
2045 do {
2046 /* We adjust the cell size if the current parent contains an #interrupt-cells
2047 * property */
2048 isizep = (unsigned int *)get_property(node, "#interrupt-cells", &l);
2049 if (isizep)
2050 isize = *isizep;
2051
2052 /* We don't do interrupt cascade (ISA) for now, we stop on the first
2053 * controller found
2054 */
2055 if (get_property(node, "interrupt-controller", &l)) {
2056 int i,j;
2057
2058 np->intrs = (struct interrupt_info *) mem_start;
2059 np->n_intrs = ipsize / isize;
2060 mem_start += np->n_intrs * sizeof(struct interrupt_info);
2061 for (i = 0; i < np->n_intrs; ++i) {
2062 np->intrs[i].line = irq_offset_up(*interrupts++);
2063 np->intrs[i].sense = 1;
2064 if (isize > 1)
2065 np->intrs[i].sense = *interrupts++;
2066 for (j=2; j<isize; j++)
2067 interrupts++;
2068 }
2069 return mem_start;
2070 }
2071 /* We lookup for an interrupt-map. This code can only handle one interrupt
2072 * per device in the map. We also don't handle #address-cells in the parent
2073 * I skip the pci node itself here, may not be necessary but I don't like it's
2074 * reg property.
2075 */
2076 if (np != node)
2077 map = (unsigned int *)get_property(node, "interrupt-map", &l);
2078 else
2079 map = NULL;
2080 if (map && l) {
2081 int i, found, temp_isize, temp_asize;
2082 map_size = l>>2;
2083 map_mask = (unsigned int *)get_property(node, "interrupt-map-mask", &l);
2084 asizep = (unsigned int *)get_property(node, "#address-cells", &l);
2085 if (asizep && l == sizeof(unsigned int))
2086 asize = *asizep;
2087 else
2088 asize = 0;
2089 found = 0;
2090 while (map_size>0 && !found) {
2091 found = 1;
2092 for (i=0; i<asize; i++) {
2093 unsigned int mask = map_mask ? map_mask[i] : 0xffffffff;
2094 if (!reg || (i>=regpsize) || ((mask & *map) != (mask & reg[i])))
2095 found = 0;
2096 map++;
2097 map_size--;
2098 }
2099 for (i=0; i<isize; i++) {
2100 unsigned int mask = map_mask ? map_mask[i+asize] : 0xffffffff;
2101 if ((mask & *map) != (mask & interrupts[i]))
2102 found = 0;
2103 map++;
2104 map_size--;
2105 }
2106 map_parent = *((phandle *)map);
2107 map+=1; map_size-=1;
2108 parent_node = find_phandle(map_parent);
2109 temp_isize = isize;
2110 temp_asize = 0;
2111 if (parent_node) {
2112 isizep = (unsigned int *)get_property(parent_node, "#interrupt-cells", &l);
2113 if (isizep)
2114 temp_isize = *isizep;
2115 asizep = (unsigned int *)get_property(parent_node, "#address-cells", &l);
2116 if (asizep && l == sizeof(unsigned int))
2117 temp_asize = *asizep;
2118 }
2119 if (!found) {
2120 map += temp_isize + temp_asize;
2121 map_size -= temp_isize + temp_asize;
2122 }
2123 }
2124 if (found) {
2125 /* Mapped to a new parent. Use the reg and interrupts specified in
2126 * the map as the new search parameters. Then search from the parent.
2127 */
2128 node = parent_node;
2129 reg = map;
2130 regpsize = temp_asize;
2131 interrupts = map + temp_asize;
2132 ipsize = temp_isize;
2133 continue;
2134 }
2135 }
2136 /* We look for an explicit interrupt-parent.
2137 */
2138 parent = (phandle *)get_property(node, "interrupt-parent", &l);
2139 if (parent && (l == sizeof(phandle)) &&
2140 (parent_node = find_phandle(*parent))) {
2141 node = parent_node;
2142 continue;
2143 }
2144 /* Default, get real parent */
2145 node = node->parent;
2146 } while (node);
2147
2148 return mem_start;
2149 }
2150
2151 int
prom_n_addr_cells(struct device_node * np)2152 prom_n_addr_cells(struct device_node* np)
2153 {
2154 int* ip;
2155 do {
2156 if (np->parent)
2157 np = np->parent;
2158 ip = (int *) get_property(np, "#address-cells", 0);
2159 if (ip != NULL)
2160 return *ip;
2161 } while (np->parent);
2162 /* No #address-cells property for the root node, default to 1 */
2163 return 1;
2164 }
2165
2166 int
prom_n_size_cells(struct device_node * np)2167 prom_n_size_cells(struct device_node* np)
2168 {
2169 int* ip;
2170 do {
2171 if (np->parent)
2172 np = np->parent;
2173 ip = (int *) get_property(np, "#size-cells", 0);
2174 if (ip != NULL)
2175 return *ip;
2176 } while (np->parent);
2177 /* No #size-cells property for the root node, default to 1 */
2178 return 1;
2179 }
2180
2181 static unsigned long __init
interpret_pci_props(struct device_node * np,unsigned long mem_start,int naddrc,int nsizec)2182 interpret_pci_props(struct device_node *np, unsigned long mem_start,
2183 int naddrc, int nsizec)
2184 {
2185 struct address_range *adr;
2186 struct pci_reg_property *pci_addrs;
2187 int i, l;
2188
2189 pci_addrs = (struct pci_reg_property *)
2190 get_property(np, "assigned-addresses", &l);
2191 if (pci_addrs != 0 && l >= sizeof(struct pci_reg_property)) {
2192 i = 0;
2193 adr = (struct address_range *) mem_start;
2194 while ((l -= sizeof(struct pci_reg_property)) >= 0) {
2195 adr[i].space = pci_addrs[i].addr.a_hi;
2196 adr[i].address = pci_addrs[i].addr.a_lo;
2197 adr[i].size = pci_addrs[i].size_lo;
2198 ++i;
2199 }
2200 np->addrs = adr;
2201 np->n_addrs = i;
2202 mem_start += i * sizeof(struct address_range);
2203 }
2204 return mem_start;
2205 }
2206
2207 static unsigned long __init
interpret_isa_props(struct device_node * np,unsigned long mem_start,int naddrc,int nsizec)2208 interpret_isa_props(struct device_node *np, unsigned long mem_start,
2209 int naddrc, int nsizec)
2210 {
2211 struct isa_reg_property *rp;
2212 struct address_range *adr;
2213 int i, l;
2214
2215 rp = (struct isa_reg_property *) get_property(np, "reg", &l);
2216 if (rp != 0 && l >= sizeof(struct isa_reg_property)) {
2217 i = 0;
2218 adr = (struct address_range *) mem_start;
2219 while ((l -= sizeof(struct reg_property)) >= 0) {
2220 adr[i].space = rp[i].space;
2221 adr[i].address = rp[i].address
2222 + (adr[i].space? 0: _ISA_MEM_BASE);
2223 adr[i].size = rp[i].size;
2224 ++i;
2225 }
2226 np->addrs = adr;
2227 np->n_addrs = i;
2228 mem_start += i * sizeof(struct address_range);
2229 }
2230
2231 return mem_start;
2232 }
2233
2234 static unsigned long __init
interpret_root_props(struct device_node * np,unsigned long mem_start,int naddrc,int nsizec)2235 interpret_root_props(struct device_node *np, unsigned long mem_start,
2236 int naddrc, int nsizec)
2237 {
2238 struct address_range *adr;
2239 int i, l;
2240 unsigned int *rp;
2241 int rpsize = (naddrc + nsizec) * sizeof(unsigned int);
2242
2243 rp = (unsigned int *) get_property(np, "reg", &l);
2244 if (rp != 0 && l >= rpsize) {
2245 i = 0;
2246 adr = (struct address_range *) mem_start;
2247 while ((l -= rpsize) >= 0) {
2248 adr[i].space = 0;
2249 adr[i].address = rp[naddrc - 1];
2250 adr[i].size = rp[naddrc + nsizec - 1];
2251 ++i;
2252 rp += naddrc + nsizec;
2253 }
2254 np->addrs = adr;
2255 np->n_addrs = i;
2256 mem_start += i * sizeof(struct address_range);
2257 }
2258
2259 return mem_start;
2260 }
2261
2262 /*
2263 * Work out the sense (active-low level / active-high edge)
2264 * of each interrupt from the device tree.
2265 */
2266 void __init
prom_get_irq_senses(unsigned char * senses,int off,int max)2267 prom_get_irq_senses(unsigned char *senses, int off, int max)
2268 {
2269 struct device_node *np;
2270 int i, j;
2271
2272 /* default to level-triggered */
2273 memset(senses, 1, max - off);
2274
2275 for (np = allnodes; np != 0; np = np->allnext) {
2276 for (j = 0; j < np->n_intrs; j++) {
2277 i = np->intrs[j].line;
2278 if (i >= off && i < max)
2279 senses[i-off] = np->intrs[j].sense;
2280 }
2281 }
2282 }
2283
2284 /*
2285 * Construct and return a list of the device_nodes with a given name.
2286 */
2287 struct device_node *
find_devices(const char * name)2288 find_devices(const char *name)
2289 {
2290 struct device_node *head, **prevp, *np;
2291
2292 prevp = &head;
2293 for (np = allnodes; np != 0; np = np->allnext) {
2294 if (np->name != 0 && strcasecmp(np->name, name) == 0) {
2295 *prevp = np;
2296 prevp = &np->next;
2297 }
2298 }
2299 *prevp = 0;
2300 return head;
2301 }
2302
2303 /*
2304 * Construct and return a list of the device_nodes with a given type.
2305 */
2306 struct device_node *
find_type_devices(const char * type)2307 find_type_devices(const char *type)
2308 {
2309 struct device_node *head, **prevp, *np;
2310
2311 prevp = &head;
2312 for (np = allnodes; np != 0; np = np->allnext) {
2313 if (np->type != 0 && strcasecmp(np->type, type) == 0) {
2314 *prevp = np;
2315 prevp = &np->next;
2316 }
2317 }
2318 *prevp = 0;
2319 return head;
2320 }
2321
2322 /*
2323 * Returns all nodes linked together
2324 */
2325 struct device_node * __openfirmware
find_all_nodes(void)2326 find_all_nodes(void)
2327 {
2328 struct device_node *head, **prevp, *np;
2329
2330 prevp = &head;
2331 for (np = allnodes; np != 0; np = np->allnext) {
2332 *prevp = np;
2333 prevp = &np->next;
2334 }
2335 *prevp = 0;
2336 return head;
2337 }
2338
2339 /* Checks if the given "compat" string matches one of the strings in
2340 * the device's "compatible" property
2341 */
2342 int
device_is_compatible(struct device_node * device,const char * compat)2343 device_is_compatible(struct device_node *device, const char *compat)
2344 {
2345 const char* cp;
2346 int cplen, l;
2347
2348 cp = (char *) get_property(device, "compatible", &cplen);
2349 if (cp == NULL)
2350 return 0;
2351 while (cplen > 0) {
2352 if (strncasecmp(cp, compat, strlen(compat)) == 0)
2353 return 1;
2354 l = strlen(cp) + 1;
2355 cp += l;
2356 cplen -= l;
2357 }
2358
2359 return 0;
2360 }
2361
2362
2363 /*
2364 * Indicates whether the root node has a given value in its
2365 * compatible property.
2366 */
2367 int
machine_is_compatible(const char * compat)2368 machine_is_compatible(const char *compat)
2369 {
2370 struct device_node *root;
2371
2372 root = find_path_device("/");
2373 if (root == 0)
2374 return 0;
2375 return device_is_compatible(root, compat);
2376 }
2377
2378 /*
2379 * Construct and return a list of the device_nodes with a given type
2380 * and compatible property.
2381 */
2382 struct device_node *
find_compatible_devices(const char * type,const char * compat)2383 find_compatible_devices(const char *type, const char *compat)
2384 {
2385 struct device_node *head, **prevp, *np;
2386
2387 prevp = &head;
2388 for (np = allnodes; np != 0; np = np->allnext) {
2389 if (type != NULL
2390 && !(np->type != 0 && strcasecmp(np->type, type) == 0))
2391 continue;
2392 if (device_is_compatible(np, compat)) {
2393 *prevp = np;
2394 prevp = &np->next;
2395 }
2396 }
2397 *prevp = 0;
2398 return head;
2399 }
2400
2401 /*
2402 * Find the device_node with a given full_name.
2403 */
2404 struct device_node *
find_path_device(const char * path)2405 find_path_device(const char *path)
2406 {
2407 struct device_node *np;
2408
2409 for (np = allnodes; np != 0; np = np->allnext)
2410 if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
2411 return np;
2412 return NULL;
2413 }
2414
2415 /*
2416 * Find the device_node with a given phandle.
2417 */
2418 static struct device_node * __init
find_phandle(phandle ph)2419 find_phandle(phandle ph)
2420 {
2421 struct device_node *np;
2422
2423 for (np = allnodes; np != 0; np = np->allnext)
2424 if (np->linux_phandle == ph)
2425 return np;
2426 return NULL;
2427 }
2428
2429 /*
2430 * Find a property with a given name for a given node
2431 * and return the value.
2432 */
2433 unsigned char *
get_property(struct device_node * np,const char * name,int * lenp)2434 get_property(struct device_node *np, const char *name, int *lenp)
2435 {
2436 struct property *pp;
2437
2438 for (pp = np->properties; pp != 0; pp = pp->next)
2439 if (strcmp(pp->name, name) == 0) {
2440 if (lenp != 0)
2441 *lenp = pp->length;
2442 return pp->value;
2443 }
2444 return 0;
2445 }
2446
2447 /*
2448 * Add a property to a node
2449 */
2450 void __openfirmware
prom_add_property(struct device_node * np,struct property * prop)2451 prom_add_property(struct device_node* np, struct property* prop)
2452 {
2453 struct property **next = &np->properties;
2454
2455 prop->next = NULL;
2456 while (*next)
2457 next = &(*next)->next;
2458 *next = prop;
2459 }
2460
2461 #if 0
2462 void __openfirmware
2463 print_properties(struct device_node *np)
2464 {
2465 struct property *pp;
2466 char *cp;
2467 int i, n;
2468
2469 for (pp = np->properties; pp != 0; pp = pp->next) {
2470 printk(KERN_INFO "%s", pp->name);
2471 for (i = strlen(pp->name); i < 16; ++i)
2472 printk(" ");
2473 cp = (char *) pp->value;
2474 for (i = pp->length; i > 0; --i, ++cp)
2475 if ((i > 1 && (*cp < 0x20 || *cp > 0x7e))
2476 || (i == 1 && *cp != 0))
2477 break;
2478 if (i == 0 && pp->length > 1) {
2479 /* looks like a string */
2480 printk(" %s\n", (char *) pp->value);
2481 } else {
2482 /* dump it in hex */
2483 n = pp->length;
2484 if (n > 64)
2485 n = 64;
2486 if (pp->length % 4 == 0) {
2487 unsigned int *p = (unsigned int *) pp->value;
2488
2489 n /= 4;
2490 for (i = 0; i < n; ++i) {
2491 if (i != 0 && (i % 4) == 0)
2492 printk("\n ");
2493 printk(" %08x", *p++);
2494 }
2495 } else {
2496 unsigned char *bp = pp->value;
2497
2498 for (i = 0; i < n; ++i) {
2499 if (i != 0 && (i % 16) == 0)
2500 printk("\n ");
2501 printk(" %02x", *bp++);
2502 }
2503 }
2504 printk("\n");
2505 if (pp->length > 64)
2506 printk(" ... (length = %d)\n",
2507 pp->length);
2508 }
2509 }
2510 }
2511 #endif
2512
2513
2514 void __init
abort(void)2515 abort(void)
2516 {
2517 #ifdef CONFIG_XMON
2518 xmon(NULL);
2519 #endif
2520 for (;;)
2521 prom_exit();
2522 }
2523
2524
2525 /* Verify bi_recs are good */
2526 static struct bi_record *
prom_bi_rec_verify(struct bi_record * bi_recs)2527 prom_bi_rec_verify(struct bi_record *bi_recs)
2528 {
2529 struct bi_record *first, *last;
2530
2531 if ( bi_recs == NULL || bi_recs->tag != BI_FIRST )
2532 return NULL;
2533
2534 last = (struct bi_record *)bi_recs->data[0];
2535 if ( last == NULL || last->tag != BI_LAST )
2536 return NULL;
2537
2538 first = (struct bi_record *)last->data[0];
2539 if ( first == NULL || first != bi_recs )
2540 return NULL;
2541
2542 return bi_recs;
2543 }
2544
2545 static unsigned long
prom_bi_rec_reserve(unsigned long mem)2546 prom_bi_rec_reserve(unsigned long mem)
2547 {
2548 unsigned long offset = reloc_offset();
2549 struct prom_t *_prom = PTRRELOC(&prom);
2550 struct bi_record *rec;
2551
2552 if ( _prom->bi_recs != NULL) {
2553
2554 for ( rec=_prom->bi_recs;
2555 rec->tag != BI_LAST;
2556 rec=bi_rec_next(rec) ) {
2557 switch (rec->tag) {
2558 #ifdef CONFIG_BLK_DEV_INITRD
2559 case BI_INITRD:
2560 lmb_reserve(rec->data[0], rec->data[1]);
2561 break;
2562 #endif /* CONFIG_BLK_DEV_INITRD */
2563 }
2564 }
2565 /* The next use of this field will be after relocation
2566 * is enabled, so convert this physical address into a
2567 * virtual address.
2568 */
2569 _prom->bi_recs = PTRUNRELOC(_prom->bi_recs);
2570 }
2571
2572 return mem;
2573 }
2574
2575