aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/syslib
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2006-03-27 18:22:10 -0500
committerPaul Mackerras <paulus@samba.org>2006-03-27 18:22:10 -0500
commit0a26b1364f14852bc9a51db0ca63c5250c775627 (patch)
tree83422473cb4bf4c450012cded06288a0dc6abedf /arch/ppc/syslib
parentff2e6d7e27cf1f757ab0d97e1a9e46de47152a0e (diff)
ppc: Remove CHRP, POWER3 and POWER4 support from arch/ppc
32-bit CHRP machines are now supported only in arch/powerpc, as are all 64-bit PowerPC processors. This means that we don't use Open Firmware on any platform in arch/ppc any more. This makes PReP support a single-platform option like every other platform support option in arch/ppc now, thus CONFIG_PPC_MULTIPLATFORM is gone from arch/ppc. CONFIG_PPC_PREP is the option that selects PReP support and is generally what has replaced CONFIG_PPC_MULTIPLATFORM within arch/ppc. _machine is all but dead now, being #defined to 0. Updated Makefiles, comments and Kconfig options generally to reflect these changes. Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/ppc/syslib')
-rw-r--r--arch/ppc/syslib/Makefile2
-rw-r--r--arch/ppc/syslib/open_pic.c2
-rw-r--r--arch/ppc/syslib/prom.c1429
-rw-r--r--arch/ppc/syslib/prom_init.c1011
4 files changed, 1 insertions, 2443 deletions
diff --git a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
index 5cb62c6a51c8..490749ca88f9 100644
--- a/arch/ppc/syslib/Makefile
+++ b/arch/ppc/syslib/Makefile
@@ -38,8 +38,6 @@ endif
38obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \ 38obj-$(CONFIG_8xx) += m8xx_setup.o ppc8xx_pic.o $(wdt-mpc8xx-y) \
39 ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o 39 ppc_sys.o mpc8xx_devices.o mpc8xx_sys.o
40obj-$(CONFIG_PCI_QSPAN) += qspan_pci.o 40obj-$(CONFIG_PCI_QSPAN) += qspan_pci.o
41obj-$(CONFIG_PPC_OF) += prom_init.o prom.o
42obj-$(CONFIG_PPC_CHRP) += open_pic.o
43obj-$(CONFIG_PPC_PREP) += open_pic.o todc_time.o 41obj-$(CONFIG_PPC_PREP) += open_pic.o todc_time.o
44obj-$(CONFIG_BAMBOO) += pci_auto.o todc_time.o 42obj-$(CONFIG_BAMBOO) += pci_auto.o todc_time.o
45obj-$(CONFIG_CPCI690) += todc_time.o pci_auto.o 43obj-$(CONFIG_CPCI690) += todc_time.o pci_auto.o
diff --git a/arch/ppc/syslib/open_pic.c b/arch/ppc/syslib/open_pic.c
index 38e5b93fbe41..70456c8f998c 100644
--- a/arch/ppc/syslib/open_pic.c
+++ b/arch/ppc/syslib/open_pic.c
@@ -216,7 +216,7 @@ static void openpic_safe_writefield(volatile u_int __iomem *addr, u_int mask,
216u_int openpic_read_IPI(volatile u_int __iomem * addr) 216u_int openpic_read_IPI(volatile u_int __iomem * addr)
217{ 217{
218 u_int val = 0; 218 u_int val = 0;
219#if defined(OPENPIC_BIG_ENDIAN) || defined(CONFIG_POWER3) 219#if defined(OPENPIC_BIG_ENDIAN)
220 val = in_be32(addr); 220 val = in_be32(addr);
221#else 221#else
222 val = in_le32(addr); 222 val = in_le32(addr);
diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c
deleted file mode 100644
index 482f837fd373..000000000000
--- a/arch/ppc/syslib/prom.c
+++ /dev/null
@@ -1,1429 +0,0 @@
1/*
2 * Procedures for interfacing to the Open Firmware PROM on
3 * Power Macintosh computers.
4 *
5 * In particular, we are interested in the device tree
6 * and in using some of its services (exit, write to stdout).
7 *
8 * Paul Mackerras August 1996.
9 * Copyright (C) 1996 Paul Mackerras.
10 */
11#include <stdarg.h>
12#include <linux/config.h>
13#include <linux/kernel.h>
14#include <linux/string.h>
15#include <linux/init.h>
16#include <linux/threads.h>
17#include <linux/spinlock.h>
18#include <linux/ioport.h>
19#include <linux/pci.h>
20#include <linux/slab.h>
21#include <linux/bitops.h>
22
23#include <asm/sections.h>
24#include <asm/prom.h>
25#include <asm/page.h>
26#include <asm/processor.h>
27#include <asm/irq.h>
28#include <asm/io.h>
29#include <asm/smp.h>
30#include <asm/bootx.h>
31#include <asm/system.h>
32#include <asm/mmu.h>
33#include <asm/pgtable.h>
34#include <asm/bootinfo.h>
35#include <asm/btext.h>
36#include <asm/pci-bridge.h>
37#include <asm/open_pic.h>
38
39
40struct pci_address {
41 unsigned a_hi;
42 unsigned a_mid;
43 unsigned a_lo;
44};
45
46struct pci_reg_property {
47 struct pci_address addr;
48 unsigned size_hi;
49 unsigned size_lo;
50};
51
52struct isa_reg_property {
53 unsigned space;
54 unsigned address;
55 unsigned size;
56};
57
58typedef unsigned long interpret_func(struct device_node *, unsigned long,
59 int, int);
60static interpret_func interpret_pci_props;
61static interpret_func interpret_dbdma_props;
62static interpret_func interpret_isa_props;
63static interpret_func interpret_macio_props;
64static interpret_func interpret_root_props;
65
66extern char *klimit;
67
68/* Set for a newworld or CHRP machine */
69int use_of_interrupt_tree;
70struct device_node *dflt_interrupt_controller;
71int num_interrupt_controllers;
72
73extern unsigned int rtas_entry; /* physical pointer */
74
75extern struct device_node *allnodes;
76
77static unsigned long finish_node(struct device_node *, unsigned long,
78 interpret_func *, int, int);
79static unsigned long finish_node_interrupts(struct device_node *, unsigned long);
80static struct device_node *find_phandle(phandle);
81
82extern void enter_rtas(void *);
83void phys_call_rtas(int, int, int, ...);
84
85extern char cmd_line[512]; /* XXX */
86extern boot_infos_t *boot_infos;
87unsigned long dev_tree_size;
88
89void
90phys_call_rtas(int service, int nargs, int nret, ...)
91{
92 va_list list;
93 union {
94 unsigned long words[16];
95 double align;
96 } u;
97 void (*rtas)(void *, unsigned long);
98 int i;
99
100 u.words[0] = service;
101 u.words[1] = nargs;
102 u.words[2] = nret;
103 va_start(list, nret);
104 for (i = 0; i < nargs; ++i)
105 u.words[i+3] = va_arg(list, unsigned long);
106 va_end(list);
107
108 rtas = (void (*)(void *, unsigned long)) rtas_entry;
109 rtas(&u, rtas_data);
110}
111
112/*
113 * finish_device_tree is called once things are running normally
114 * (i.e. with text and data mapped to the address they were linked at).
115 * It traverses the device tree and fills in the name, type,
116 * {n_}addrs and {n_}intrs fields of each node.
117 */
118void __init
119finish_device_tree(void)
120{
121 unsigned long mem = (unsigned long) klimit;
122 struct device_node *np;
123
124 /* All CHRPs now use the interrupt tree */
125 for (np = allnodes; np != NULL; np = np->allnext) {
126 if (get_property(np, "interrupt-parent", NULL)) {
127 use_of_interrupt_tree = 1;
128 break;
129 }
130 }
131
132 if (use_of_interrupt_tree) {
133 /*
134 * We want to find out here how many interrupt-controller
135 * nodes there are, and if we are booted from BootX,
136 * we need a pointer to the first (and hopefully only)
137 * such node. But we can't use find_devices here since
138 * np->name has not been set yet. -- paulus
139 */
140 int n = 0;
141 char *name, *ic;
142 int iclen;
143
144 for (np = allnodes; np != NULL; np = np->allnext) {
145 ic = get_property(np, "interrupt-controller", &iclen);
146 name = get_property(np, "name", NULL);
147 /* checking iclen makes sure we don't get a false
148 match on /chosen.interrupt_controller */
149 if ((name != NULL
150 && strcmp(name, "interrupt-controller") == 0)
151 || (ic != NULL && iclen == 0 && strcmp(name, "AppleKiwi"))) {
152 if (n == 0)
153 dflt_interrupt_controller = np;
154 ++n;
155 }
156 }
157 num_interrupt_controllers = n;
158 }
159
160 mem = finish_node(allnodes, mem, NULL, 1, 1);
161 dev_tree_size = mem - (unsigned long) allnodes;
162 klimit = (char *) mem;
163}
164
165static unsigned long __init
166finish_node(struct device_node *np, unsigned long mem_start,
167 interpret_func *ifunc, int naddrc, int nsizec)
168{
169 struct device_node *child;
170 int *ip;
171
172 np->name = get_property(np, "name", NULL);
173 np->type = get_property(np, "device_type", NULL);
174
175 if (!np->name)
176 np->name = "<NULL>";
177 if (!np->type)
178 np->type = "<NULL>";
179
180 /* get the device addresses and interrupts */
181 if (ifunc != NULL)
182 mem_start = ifunc(np, mem_start, naddrc, nsizec);
183
184 if (use_of_interrupt_tree)
185 mem_start = finish_node_interrupts(np, mem_start);
186
187 /* Look for #address-cells and #size-cells properties. */
188 ip = (int *) get_property(np, "#address-cells", NULL);
189 if (ip != NULL)
190 naddrc = *ip;
191 ip = (int *) get_property(np, "#size-cells", NULL);
192 if (ip != NULL)
193 nsizec = *ip;
194
195 if (np->parent == NULL)
196 ifunc = interpret_root_props;
197 else if (np->type == 0)
198 ifunc = NULL;
199 else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))
200 ifunc = interpret_pci_props;
201 else if (!strcmp(np->type, "dbdma"))
202 ifunc = interpret_dbdma_props;
203 else if (!strcmp(np->type, "mac-io")
204 || ifunc == interpret_macio_props)
205 ifunc = interpret_macio_props;
206 else if (!strcmp(np->type, "isa"))
207 ifunc = interpret_isa_props;
208 else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3"))
209 ifunc = interpret_root_props;
210 else if (!((ifunc == interpret_dbdma_props
211 || ifunc == interpret_macio_props)
212 && (!strcmp(np->type, "escc")
213 || !strcmp(np->type, "media-bay"))))
214 ifunc = NULL;
215
216 /* if we were booted from BootX, convert the full name */
217 if (boot_infos
218 && strncmp(np->full_name, "Devices:device-tree", 19) == 0) {
219 if (np->full_name[19] == 0) {
220 strcpy(np->full_name, "/");
221 } else if (np->full_name[19] == ':') {
222 char *p = np->full_name + 19;
223 np->full_name = p;
224 for (; *p; ++p)
225 if (*p == ':')
226 *p = '/';
227 }
228 }
229
230 for (child = np->child; child != NULL; child = child->sibling)
231 mem_start = finish_node(child, mem_start, ifunc,
232 naddrc, nsizec);
233
234 return mem_start;
235}
236
237/*
238 * Find the interrupt parent of a node.
239 */
240static struct device_node * __init
241intr_parent(struct device_node *p)
242{
243 phandle *parp;
244
245 parp = (phandle *) get_property(p, "interrupt-parent", NULL);
246 if (parp == NULL)
247 return p->parent;
248 p = find_phandle(*parp);
249 if (p != NULL)
250 return p;
251 /*
252 * On a powermac booted with BootX, we don't get to know the
253 * phandles for any nodes, so find_phandle will return NULL.
254 * Fortunately these machines only have one interrupt controller
255 * so there isn't in fact any ambiguity. -- paulus
256 */
257 if (num_interrupt_controllers == 1)
258 p = dflt_interrupt_controller;
259 return p;
260}
261
262/*
263 * Find out the size of each entry of the interrupts property
264 * for a node.
265 */
266static int __init
267prom_n_intr_cells(struct device_node *np)
268{
269 struct device_node *p;
270 unsigned int *icp;
271
272 for (p = np; (p = intr_parent(p)) != NULL; ) {
273 icp = (unsigned int *)
274 get_property(p, "#interrupt-cells", NULL);
275 if (icp != NULL)
276 return *icp;
277 if (get_property(p, "interrupt-controller", NULL) != NULL
278 || get_property(p, "interrupt-map", NULL) != NULL) {
279 printk("oops, node %s doesn't have #interrupt-cells\n",
280 p->full_name);
281 return 1;
282 }
283 }
284 printk("prom_n_intr_cells failed for %s\n", np->full_name);
285 return 1;
286}
287
288/*
289 * Map an interrupt from a device up to the platform interrupt
290 * descriptor.
291 */
292static int __init
293map_interrupt(unsigned int **irq, struct device_node **ictrler,
294 struct device_node *np, unsigned int *ints, int nintrc)
295{
296 struct device_node *p, *ipar;
297 unsigned int *imap, *imask, *ip;
298 int i, imaplen, match;
299 int newintrc = 1, newaddrc = 1;
300 unsigned int *reg;
301 int naddrc;
302
303 reg = (unsigned int *) get_property(np, "reg", NULL);
304 naddrc = prom_n_addr_cells(np);
305 p = intr_parent(np);
306 while (p != NULL) {
307 if (get_property(p, "interrupt-controller", NULL) != NULL)
308 /* this node is an interrupt controller, stop here */
309 break;
310 imap = (unsigned int *)
311 get_property(p, "interrupt-map", &imaplen);
312 if (imap == NULL) {
313 p = intr_parent(p);
314 continue;
315 }
316 imask = (unsigned int *)
317 get_property(p, "interrupt-map-mask", NULL);
318 if (imask == NULL) {
319 printk("oops, %s has interrupt-map but no mask\n",
320 p->full_name);
321 return 0;
322 }
323 imaplen /= sizeof(unsigned int);
324 match = 0;
325 ipar = NULL;
326 while (imaplen > 0 && !match) {
327 /* check the child-interrupt field */
328 match = 1;
329 for (i = 0; i < naddrc && match; ++i)
330 match = ((reg[i] ^ imap[i]) & imask[i]) == 0;
331 for (; i < naddrc + nintrc && match; ++i)
332 match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0;
333 imap += naddrc + nintrc;
334 imaplen -= naddrc + nintrc;
335 /* grab the interrupt parent */
336 ipar = find_phandle((phandle) *imap++);
337 --imaplen;
338 if (ipar == NULL && num_interrupt_controllers == 1)
339 /* cope with BootX not giving us phandles */
340 ipar = dflt_interrupt_controller;
341 if (ipar == NULL) {
342 printk("oops, no int parent %x in map of %s\n",
343 imap[-1], p->full_name);
344 return 0;
345 }
346 /* find the parent's # addr and intr cells */
347 ip = (unsigned int *)
348 get_property(ipar, "#interrupt-cells", NULL);
349 if (ip == NULL) {
350 printk("oops, no #interrupt-cells on %s\n",
351 ipar->full_name);
352 return 0;
353 }
354 newintrc = *ip;
355 ip = (unsigned int *)
356 get_property(ipar, "#address-cells", NULL);
357 newaddrc = (ip == NULL)? 0: *ip;
358 imap += newaddrc + newintrc;
359 imaplen -= newaddrc + newintrc;
360 }
361 if (imaplen < 0) {
362 printk("oops, error decoding int-map on %s, len=%d\n",
363 p->full_name, imaplen);
364 return 0;
365 }
366 if (!match) {
367 printk("oops, no match in %s int-map for %s\n",
368 p->full_name, np->full_name);
369 return 0;
370 }
371 p = ipar;
372 naddrc = newaddrc;
373 nintrc = newintrc;
374 ints = imap - nintrc;
375 reg = ints - naddrc;
376 }
377 if (p == NULL)
378 printk("hmmm, int tree for %s doesn't have ctrler\n",
379 np->full_name);
380 *irq = ints;
381 *ictrler = p;
382 return nintrc;
383}
384
385/*
386 * New version of finish_node_interrupts.
387 */
388static unsigned long __init
389finish_node_interrupts(struct device_node *np, unsigned long mem_start)
390{
391 unsigned int *ints;
392 int intlen, intrcells;
393 int i, j, n, offset;
394 unsigned int *irq;
395 struct device_node *ic;
396
397 ints = (unsigned int *) get_property(np, "interrupts", &intlen);
398 if (ints == NULL)
399 return mem_start;
400 intrcells = prom_n_intr_cells(np);
401 intlen /= intrcells * sizeof(unsigned int);
402 np->n_intrs = intlen;
403 np->intrs = (struct interrupt_info *) mem_start;
404 mem_start += intlen * sizeof(struct interrupt_info);
405
406 for (i = 0; i < intlen; ++i) {
407 np->intrs[i].line = 0;
408 np->intrs[i].sense = 1;
409 n = map_interrupt(&irq, &ic, np, ints, intrcells);
410 if (n <= 0)
411 continue;
412 offset = 0;
413 /*
414 * On a CHRP we have an 8259 which is subordinate to
415 * the openpic in the interrupt tree, but we want the
416 * openpic's interrupt numbers offsetted, not the 8259's.
417 * So we apply the offset if the controller is at the
418 * root of the interrupt tree, i.e. has no interrupt-parent.
419 * This doesn't cope with the general case of multiple
420 * cascaded interrupt controllers, but then neither will
421 * irq.c at the moment either. -- paulus
422 * The G5 triggers that code, I add a machine test. On
423 * those machines, we want to offset interrupts from the
424 * second openpic by 128 -- BenH
425 */
426 if (num_interrupt_controllers > 1
427 && ic != NULL
428 && get_property(ic, "interrupt-parent", NULL) == NULL)
429 offset = 16;
430
431 np->intrs[i].line = irq[0] + offset;
432 if (n > 1)
433 np->intrs[i].sense = irq[1];
434 if (n > 2) {
435 printk("hmmm, got %d intr cells for %s:", n,
436 np->full_name);
437 for (j = 0; j < n; ++j)
438 printk(" %d", irq[j]);
439 printk("\n");
440 }
441 ints += intrcells;
442 }
443
444 return mem_start;
445}
446
447/*
448 * When BootX makes a copy of the device tree from the MacOS
449 * Name Registry, it is in the format we use but all of the pointers
450 * are offsets from the start of the tree.
451 * This procedure updates the pointers.
452 */
453void __init
454relocate_nodes(void)
455{
456 unsigned long base;
457 struct device_node *np;
458 struct property *pp;
459
460#define ADDBASE(x) (x = (typeof (x))((x)? ((unsigned long)(x) + base): 0))
461
462 base = (unsigned long) boot_infos + boot_infos->deviceTreeOffset;
463 allnodes = (struct device_node *)(base + 4);
464 for (np = allnodes; np != 0; np = np->allnext) {
465 ADDBASE(np->full_name);
466 ADDBASE(np->properties);
467 ADDBASE(np->parent);
468 ADDBASE(np->child);
469 ADDBASE(np->sibling);
470 ADDBASE(np->allnext);
471 for (pp = np->properties; pp != 0; pp = pp->next) {
472 ADDBASE(pp->name);
473 ADDBASE(pp->value);
474 ADDBASE(pp->next);
475 }
476 }
477}
478
479int
480prom_n_addr_cells(struct device_node* np)
481{
482 int* ip;
483 do {
484 if (np->parent)
485 np = np->parent;
486 ip = (int *) get_property(np, "#address-cells", NULL);
487 if (ip != NULL)
488 return *ip;
489 } while (np->parent);
490 /* No #address-cells property for the root node, default to 1 */
491 return 1;
492}
493
494int
495prom_n_size_cells(struct device_node* np)
496{
497 int* ip;
498 do {
499 if (np->parent)
500 np = np->parent;
501 ip = (int *) get_property(np, "#size-cells", NULL);
502 if (ip != NULL)
503 return *ip;
504 } while (np->parent);
505 /* No #size-cells property for the root node, default to 1 */
506 return 1;
507}
508
509static unsigned long __init
510map_addr(struct device_node *np, unsigned long space, unsigned long addr)
511{
512 int na;
513 unsigned int *ranges;
514 int rlen = 0;
515 unsigned int type;
516
517 type = (space >> 24) & 3;
518 if (type == 0)
519 return addr;
520
521 while ((np = np->parent) != NULL) {
522 if (strcmp(np->type, "pci") != 0)
523 continue;
524 /* PCI bridge: map the address through the ranges property */
525 na = prom_n_addr_cells(np);
526 ranges = (unsigned int *) get_property(np, "ranges", &rlen);
527 while ((rlen -= (na + 5) * sizeof(unsigned int)) >= 0) {
528 if (((ranges[0] >> 24) & 3) == type
529 && ranges[2] <= addr
530 && addr - ranges[2] < ranges[na+4]) {
531 /* ok, this matches, translate it */
532 addr += ranges[na+2] - ranges[2];
533 break;
534 }
535 ranges += na + 5;
536 }
537 }
538 return addr;
539}
540
541static unsigned long __init
542interpret_pci_props(struct device_node *np, unsigned long mem_start,
543 int naddrc, int nsizec)
544{
545 struct address_range *adr;
546 struct pci_reg_property *pci_addrs;
547 int i, l, *ip;
548
549 pci_addrs = (struct pci_reg_property *)
550 get_property(np, "assigned-addresses", &l);
551 if (pci_addrs != 0 && l >= sizeof(struct pci_reg_property)) {
552 i = 0;
553 adr = (struct address_range *) mem_start;
554 while ((l -= sizeof(struct pci_reg_property)) >= 0) {
555 adr[i].space = pci_addrs[i].addr.a_hi;
556 adr[i].address = map_addr(np, pci_addrs[i].addr.a_hi,
557 pci_addrs[i].addr.a_lo);
558 adr[i].size = pci_addrs[i].size_lo;
559 ++i;
560 }
561 np->addrs = adr;
562 np->n_addrs = i;
563 mem_start += i * sizeof(struct address_range);
564 }
565
566 if (use_of_interrupt_tree)
567 return mem_start;
568
569 ip = (int *) get_property(np, "AAPL,interrupts", &l);
570 if (ip == 0 && np->parent)
571 ip = (int *) get_property(np->parent, "AAPL,interrupts", &l);
572 if (ip == 0)
573 ip = (int *) get_property(np, "interrupts", &l);
574 if (ip != 0) {
575 np->intrs = (struct interrupt_info *) mem_start;
576 np->n_intrs = l / sizeof(int);
577 mem_start += np->n_intrs * sizeof(struct interrupt_info);
578 for (i = 0; i < np->n_intrs; ++i) {
579 np->intrs[i].line = *ip++;
580 np->intrs[i].sense = 1;
581 }
582 }
583
584 return mem_start;
585}
586
587static unsigned long __init
588interpret_dbdma_props(struct device_node *np, unsigned long mem_start,
589 int naddrc, int nsizec)
590{
591 struct reg_property *rp;
592 struct address_range *adr;
593 unsigned long base_address;
594 int i, l, *ip;
595 struct device_node *db;
596
597 base_address = 0;
598 for (db = np->parent; db != NULL; db = db->parent) {
599 if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) {
600 base_address = db->addrs[0].address;
601 break;
602 }
603 }
604
605 rp = (struct reg_property *) get_property(np, "reg", &l);
606 if (rp != 0 && l >= sizeof(struct reg_property)) {
607 i = 0;
608 adr = (struct address_range *) mem_start;
609 while ((l -= sizeof(struct reg_property)) >= 0) {
610 adr[i].space = 2;
611 adr[i].address = rp[i].address + base_address;
612 adr[i].size = rp[i].size;
613 ++i;
614 }
615 np->addrs = adr;
616 np->n_addrs = i;
617 mem_start += i * sizeof(struct address_range);
618 }
619
620 if (use_of_interrupt_tree)
621 return mem_start;
622
623 ip = (int *) get_property(np, "AAPL,interrupts", &l);
624 if (ip == 0)
625 ip = (int *) get_property(np, "interrupts", &l);
626 if (ip != 0) {
627 np->intrs = (struct interrupt_info *) mem_start;
628 np->n_intrs = l / sizeof(int);
629 mem_start += np->n_intrs * sizeof(struct interrupt_info);
630 for (i = 0; i < np->n_intrs; ++i) {
631 np->intrs[i].line = *ip++;
632 np->intrs[i].sense = 1;
633 }
634 }
635
636 return mem_start;
637}
638
639static unsigned long __init
640interpret_macio_props(struct device_node *np, unsigned long mem_start,
641 int naddrc, int nsizec)
642{
643 struct reg_property *rp;
644 struct address_range *adr;
645 unsigned long base_address;
646 int i, l, *ip;
647 struct device_node *db;
648
649 base_address = 0;
650 for (db = np->parent; db != NULL; db = db->parent) {
651 if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) {
652 base_address = db->addrs[0].address;
653 break;
654 }
655 }
656
657 rp = (struct reg_property *) get_property(np, "reg", &l);
658 if (rp != 0 && l >= sizeof(struct reg_property)) {
659 i = 0;
660 adr = (struct address_range *) mem_start;
661 while ((l -= sizeof(struct reg_property)) >= 0) {
662 adr[i].space = 2;
663 adr[i].address = rp[i].address + base_address;
664 adr[i].size = rp[i].size;
665 ++i;
666 }
667 np->addrs = adr;
668 np->n_addrs = i;
669 mem_start += i * sizeof(struct address_range);
670 }
671
672 if (use_of_interrupt_tree)
673 return mem_start;
674
675 ip = (int *) get_property(np, "interrupts", &l);
676 if (ip == 0)
677 ip = (int *) get_property(np, "AAPL,interrupts", &l);
678 if (ip != 0) {
679 np->intrs = (struct interrupt_info *) mem_start;
680 np->n_intrs = l / sizeof(int);
681 for (i = 0; i < np->n_intrs; ++i) {
682 np->intrs[i].line = *ip++;
683 np->intrs[i].sense = 1;
684 }
685 mem_start += np->n_intrs * sizeof(struct interrupt_info);
686 }
687
688 return mem_start;
689}
690
691static unsigned long __init
692interpret_isa_props(struct device_node *np, unsigned long mem_start,
693 int naddrc, int nsizec)
694{
695 struct isa_reg_property *rp;
696 struct address_range *adr;
697 int i, l, *ip;
698
699 rp = (struct isa_reg_property *) get_property(np, "reg", &l);
700 if (rp != 0 && l >= sizeof(struct isa_reg_property)) {
701 i = 0;
702 adr = (struct address_range *) mem_start;
703 while ((l -= sizeof(struct reg_property)) >= 0) {
704 adr[i].space = rp[i].space;
705 adr[i].address = rp[i].address
706 + (adr[i].space? 0: _ISA_MEM_BASE);
707 adr[i].size = rp[i].size;
708 ++i;
709 }
710 np->addrs = adr;
711 np->n_addrs = i;
712 mem_start += i * sizeof(struct address_range);
713 }
714
715 if (use_of_interrupt_tree)
716 return mem_start;
717
718 ip = (int *) get_property(np, "interrupts", &l);
719 if (ip != 0) {
720 np->intrs = (struct interrupt_info *) mem_start;
721 np->n_intrs = l / (2 * sizeof(int));
722 mem_start += np->n_intrs * sizeof(struct interrupt_info);
723 for (i = 0; i < np->n_intrs; ++i) {
724 np->intrs[i].line = *ip++;
725 np->intrs[i].sense = *ip++;
726 }
727 }
728
729 return mem_start;
730}
731
732static unsigned long __init
733interpret_root_props(struct device_node *np, unsigned long mem_start,
734 int naddrc, int nsizec)
735{
736 struct address_range *adr;
737 int i, l, *ip;
738 unsigned int *rp;
739 int rpsize = (naddrc + nsizec) * sizeof(unsigned int);
740
741 rp = (unsigned int *) get_property(np, "reg", &l);
742 if (rp != 0 && l >= rpsize) {
743 i = 0;
744 adr = (struct address_range *) mem_start;
745 while ((l -= rpsize) >= 0) {
746 adr[i].space = (naddrc >= 2? rp[naddrc-2]: 2);
747 adr[i].address = rp[naddrc - 1];
748 adr[i].size = rp[naddrc + nsizec - 1];
749 ++i;
750 rp += naddrc + nsizec;
751 }
752 np->addrs = adr;
753 np->n_addrs = i;
754 mem_start += i * sizeof(struct address_range);
755 }
756
757 if (use_of_interrupt_tree)
758 return mem_start;
759
760 ip = (int *) get_property(np, "AAPL,interrupts", &l);
761 if (ip == 0)
762 ip = (int *) get_property(np, "interrupts", &l);
763 if (ip != 0) {
764 np->intrs = (struct interrupt_info *) mem_start;
765 np->n_intrs = l / sizeof(int);
766 mem_start += np->n_intrs * sizeof(struct interrupt_info);
767 for (i = 0; i < np->n_intrs; ++i) {
768 np->intrs[i].line = *ip++;
769 np->intrs[i].sense = 1;
770 }
771 }
772
773 return mem_start;
774}
775
776/*
777 * Work out the sense (active-low level / active-high edge)
778 * of each interrupt from the device tree.
779 */
780void __init
781prom_get_irq_senses(unsigned char *senses, int off, int max)
782{
783 struct device_node *np;
784 int i, j;
785
786 /* default to level-triggered */
787 memset(senses, 1, max - off);
788 if (!use_of_interrupt_tree)
789 return;
790
791 for (np = allnodes; np != 0; np = np->allnext) {
792 for (j = 0; j < np->n_intrs; j++) {
793 i = np->intrs[j].line;
794 if (i >= off && i < max) {
795 if (np->intrs[j].sense == 1)
796 senses[i-off] = (IRQ_SENSE_LEVEL
797 | IRQ_POLARITY_NEGATIVE);
798 else
799 senses[i-off] = (IRQ_SENSE_EDGE
800 | IRQ_POLARITY_POSITIVE);
801 }
802 }
803 }
804}
805
806/*
807 * Construct and return a list of the device_nodes with a given name.
808 */
809struct device_node *
810find_devices(const char *name)
811{
812 struct device_node *head, **prevp, *np;
813
814 prevp = &head;
815 for (np = allnodes; np != 0; np = np->allnext) {
816 if (np->name != 0 && strcasecmp(np->name, name) == 0) {
817 *prevp = np;
818 prevp = &np->next;
819 }
820 }
821 *prevp = NULL;
822 return head;
823}
824
825/*
826 * Construct and return a list of the device_nodes with a given type.
827 */
828struct device_node *
829find_type_devices(const char *type)
830{
831 struct device_node *head, **prevp, *np;
832
833 prevp = &head;
834 for (np = allnodes; np != 0; np = np->allnext) {
835 if (np->type != 0 && strcasecmp(np->type, type) == 0) {
836 *prevp = np;
837 prevp = &np->next;
838 }
839 }
840 *prevp = NULL;
841 return head;
842}
843
844/*
845 * Returns all nodes linked together
846 */
847struct device_node *
848find_all_nodes(void)
849{
850 struct device_node *head, **prevp, *np;
851
852 prevp = &head;
853 for (np = allnodes; np != 0; np = np->allnext) {
854 *prevp = np;
855 prevp = &np->next;
856 }
857 *prevp = NULL;
858 return head;
859}
860
861/* Checks if the given "compat" string matches one of the strings in
862 * the device's "compatible" property
863 */
864int
865device_is_compatible(struct device_node *device, const char *compat)
866{
867 const char* cp;
868 int cplen, l;
869
870 cp = (char *) get_property(device, "compatible", &cplen);
871 if (cp == NULL)
872 return 0;
873 while (cplen > 0) {
874 if (strncasecmp(cp, compat, strlen(compat)) == 0)
875 return 1;
876 l = strlen(cp) + 1;
877 cp += l;
878 cplen -= l;
879 }
880
881 return 0;
882}
883
884
885/*
886 * Indicates whether the root node has a given value in its
887 * compatible property.
888 */
889int
890machine_is_compatible(const char *compat)
891{
892 struct device_node *root;
893
894 root = find_path_device("/");
895 if (root == 0)
896 return 0;
897 return device_is_compatible(root, compat);
898}
899
900/*
901 * Construct and return a list of the device_nodes with a given type
902 * and compatible property.
903 */
904struct device_node *
905find_compatible_devices(const char *type, const char *compat)
906{
907 struct device_node *head, **prevp, *np;
908
909 prevp = &head;
910 for (np = allnodes; np != 0; np = np->allnext) {
911 if (type != NULL
912 && !(np->type != 0 && strcasecmp(np->type, type) == 0))
913 continue;
914 if (device_is_compatible(np, compat)) {
915 *prevp = np;
916 prevp = &np->next;
917 }
918 }
919 *prevp = NULL;
920 return head;
921}
922
923/*
924 * Find the device_node with a given full_name.
925 */
926struct device_node *
927find_path_device(const char *path)
928{
929 struct device_node *np;
930
931 for (np = allnodes; np != 0; np = np->allnext)
932 if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
933 return np;
934 return NULL;
935}
936
937/*******
938 *
939 * New implementation of the OF "find" APIs, return a refcounted
940 * object, call of_node_put() when done. Currently, still lacks
941 * locking as old implementation, this is beeing done for ppc64.
942 *
943 * Note that property management will need some locking as well,
944 * this isn't dealt with yet
945 *
946 *******/
947
948/**
949 * of_find_node_by_name - Find a node by it's "name" property
950 * @from: The node to start searching from or NULL, the node
951 * you pass will not be searched, only the next one
952 * will; typically, you pass what the previous call
953 * returned. of_node_put() will be called on it
954 * @name: The name string to match against
955 *
956 * Returns a node pointer with refcount incremented, use
957 * of_node_put() on it when done.
958 */
959struct device_node *of_find_node_by_name(struct device_node *from,
960 const char *name)
961{
962 struct device_node *np = from ? from->allnext : allnodes;
963
964 for (; np != 0; np = np->allnext)
965 if (np->name != 0 && strcasecmp(np->name, name) == 0)
966 break;
967 if (from)
968 of_node_put(from);
969 return of_node_get(np);
970}
971
972/**
973 * of_find_node_by_type - Find a node by it's "device_type" property
974 * @from: The node to start searching from or NULL, the node
975 * you pass will not be searched, only the next one
976 * will; typically, you pass what the previous call
977 * returned. of_node_put() will be called on it
978 * @name: The type string to match against
979 *
980 * Returns a node pointer with refcount incremented, use
981 * of_node_put() on it when done.
982 */
983struct device_node *of_find_node_by_type(struct device_node *from,
984 const char *type)
985{
986 struct device_node *np = from ? from->allnext : allnodes;
987
988 for (; np != 0; np = np->allnext)
989 if (np->type != 0 && strcasecmp(np->type, type) == 0)
990 break;
991 if (from)
992 of_node_put(from);
993 return of_node_get(np);
994}
995
996/**
997 * of_find_compatible_node - Find a node based on type and one of the
998 * tokens in it's "compatible" property
999 * @from: The node to start searching from or NULL, the node
1000 * you pass will not be searched, only the next one
1001 * will; typically, you pass what the previous call
1002 * returned. of_node_put() will be called on it
1003 * @type: The type string to match "device_type" or NULL to ignore
1004 * @compatible: The string to match to one of the tokens in the device
1005 * "compatible" list.
1006 *
1007 * Returns a node pointer with refcount incremented, use
1008 * of_node_put() on it when done.
1009 */
1010struct device_node *of_find_compatible_node(struct device_node *from,
1011 const char *type, const char *compatible)
1012{
1013 struct device_node *np = from ? from->allnext : allnodes;
1014
1015 for (; np != 0; np = np->allnext) {
1016 if (type != NULL
1017 && !(np->type != 0 && strcasecmp(np->type, type) == 0))
1018 continue;
1019 if (device_is_compatible(np, compatible))
1020 break;
1021 }
1022 if (from)
1023 of_node_put(from);
1024 return of_node_get(np);
1025}
1026
1027/**
1028 * of_find_node_by_path - Find a node matching a full OF path
1029 * @path: The full path to match
1030 *
1031 * Returns a node pointer with refcount incremented, use
1032 * of_node_put() on it when done.
1033 */
1034struct device_node *of_find_node_by_path(const char *path)
1035{
1036 struct device_node *np = allnodes;
1037
1038 for (; np != 0; np = np->allnext)
1039 if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
1040 break;
1041 return of_node_get(np);
1042}
1043
1044/**
1045 * of_find_all_nodes - Get next node in global list
1046 * @prev: Previous node or NULL to start iteration
1047 * of_node_put() will be called on it
1048 *
1049 * Returns a node pointer with refcount incremented, use
1050 * of_node_put() on it when done.
1051 */
1052struct device_node *of_find_all_nodes(struct device_node *prev)
1053{
1054 return of_node_get(prev ? prev->allnext : allnodes);
1055}
1056
1057/**
1058 * of_get_parent - Get a node's parent if any
1059 * @node: Node to get parent
1060 *
1061 * Returns a node pointer with refcount incremented, use
1062 * of_node_put() on it when done.
1063 */
1064struct device_node *of_get_parent(const struct device_node *node)
1065{
1066 return node ? of_node_get(node->parent) : NULL;
1067}
1068
1069/**
1070 * of_get_next_child - Iterate a node childs
1071 * @node: parent node
1072 * @prev: previous child of the parent node, or NULL to get first
1073 *
1074 * Returns a node pointer with refcount incremented, use
1075 * of_node_put() on it when done.
1076 */
1077struct device_node *of_get_next_child(const struct device_node *node,
1078 struct device_node *prev)
1079{
1080 struct device_node *next = prev ? prev->sibling : node->child;
1081
1082 for (; next != 0; next = next->sibling)
1083 if (of_node_get(next))
1084 break;
1085 if (prev)
1086 of_node_put(prev);
1087 return next;
1088}
1089
1090/**
1091 * of_node_get - Increment refcount of a node
1092 * @node: Node to inc refcount, NULL is supported to
1093 * simplify writing of callers
1094 *
1095 * Returns the node itself or NULL if gone. Current implementation
1096 * does nothing as we don't yet do dynamic node allocation on ppc32
1097 */
1098struct device_node *of_node_get(struct device_node *node)
1099{
1100 return node;
1101}
1102
1103/**
1104 * of_node_put - Decrement refcount of a node
1105 * @node: Node to dec refcount, NULL is supported to
1106 * simplify writing of callers
1107 *
1108 * Current implementation does nothing as we don't yet do dynamic node
1109 * allocation on ppc32
1110 */
1111void of_node_put(struct device_node *node)
1112{
1113}
1114
1115/*
1116 * Find the device_node with a given phandle.
1117 */
1118static struct device_node * __init
1119find_phandle(phandle ph)
1120{
1121 struct device_node *np;
1122
1123 for (np = allnodes; np != 0; np = np->allnext)
1124 if (np->node == ph)
1125 return np;
1126 return NULL;
1127}
1128
1129/*
1130 * Find a property with a given name for a given node
1131 * and return the value.
1132 */
1133unsigned char *
1134get_property(struct device_node *np, const char *name, int *lenp)
1135{
1136 struct property *pp;
1137
1138 for (pp = np->properties; pp != 0; pp = pp->next)
1139 if (pp->name != NULL && strcmp(pp->name, name) == 0) {
1140 if (lenp != 0)
1141 *lenp = pp->length;
1142 return pp->value;
1143 }
1144 return NULL;
1145}
1146
1147/*
1148 * Add a property to a node
1149 */
1150int
1151prom_add_property(struct device_node* np, struct property* prop)
1152{
1153 struct property **next = &np->properties;
1154
1155 prop->next = NULL;
1156 while (*next)
1157 next = &(*next)->next;
1158 *next = prop;
1159
1160 return 0;
1161}
1162
1163/* I quickly hacked that one, check against spec ! */
1164static inline unsigned long
1165bus_space_to_resource_flags(unsigned int bus_space)
1166{
1167 u8 space = (bus_space >> 24) & 0xf;
1168 if (space == 0)
1169 space = 0x02;
1170 if (space == 0x02)
1171 return IORESOURCE_MEM;
1172 else if (space == 0x01)
1173 return IORESOURCE_IO;
1174 else {
1175 printk(KERN_WARNING "prom.c: bus_space_to_resource_flags(), space: %x\n",
1176 bus_space);
1177 return 0;
1178 }
1179}
1180
1181static struct resource*
1182find_parent_pci_resource(struct pci_dev* pdev, struct address_range *range)
1183{
1184 unsigned long mask;
1185 int i;
1186
1187 /* Check this one */
1188 mask = bus_space_to_resource_flags(range->space);
1189 for (i=0; i<DEVICE_COUNT_RESOURCE; i++) {
1190 if ((pdev->resource[i].flags & mask) == mask &&
1191 pdev->resource[i].start <= range->address &&
1192 pdev->resource[i].end > range->address) {
1193 if ((range->address + range->size - 1) > pdev->resource[i].end) {
1194 /* Add better message */
1195 printk(KERN_WARNING "PCI/OF resource overlap !\n");
1196 return NULL;
1197 }
1198 break;
1199 }
1200 }
1201 if (i == DEVICE_COUNT_RESOURCE)
1202 return NULL;
1203 return &pdev->resource[i];
1204}
1205
1206/*
1207 * Request an OF device resource. Currently handles child of PCI devices,
1208 * or other nodes attached to the root node. Ultimately, put some
1209 * link to resources in the OF node.
1210 */
1211struct resource*
1212request_OF_resource(struct device_node* node, int index, const char* name_postfix)
1213{
1214 struct pci_dev* pcidev;
1215 u8 pci_bus, pci_devfn;
1216 unsigned long iomask;
1217 struct device_node* nd;
1218 struct resource* parent;
1219 struct resource *res = NULL;
1220 int nlen, plen;
1221
1222 if (index >= node->n_addrs)
1223 goto fail;
1224
1225 /* Sanity check on bus space */
1226 iomask = bus_space_to_resource_flags(node->addrs[index].space);
1227 if (iomask & IORESOURCE_MEM)
1228 parent = &iomem_resource;
1229 else if (iomask & IORESOURCE_IO)
1230 parent = &ioport_resource;
1231 else
1232 goto fail;
1233
1234 /* Find a PCI parent if any */
1235 nd = node;
1236 pcidev = NULL;
1237 while(nd) {
1238 if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
1239 pcidev = pci_find_slot(pci_bus, pci_devfn);
1240 if (pcidev) break;
1241 nd = nd->parent;
1242 }
1243 if (pcidev)
1244 parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
1245 if (!parent) {
1246 printk(KERN_WARNING "request_OF_resource(%s), parent not found\n",
1247 node->name);
1248 goto fail;
1249 }
1250
1251 res = __request_region(parent, node->addrs[index].address, node->addrs[index].size, NULL);
1252 if (!res)
1253 goto fail;
1254 nlen = strlen(node->name);
1255 plen = name_postfix ? strlen(name_postfix) : 0;
1256 res->name = (const char *)kmalloc(nlen+plen+1, GFP_KERNEL);
1257 if (res->name) {
1258 strcpy((char *)res->name, node->name);
1259 if (plen)
1260 strcpy((char *)res->name+nlen, name_postfix);
1261 }
1262 return res;
1263fail:
1264 return NULL;
1265}
1266
1267int
1268release_OF_resource(struct device_node* node, int index)
1269{
1270 struct pci_dev* pcidev;
1271 u8 pci_bus, pci_devfn;
1272 unsigned long iomask, start, end;
1273 struct device_node* nd;
1274 struct resource* parent;
1275 struct resource *res = NULL;
1276
1277 if (index >= node->n_addrs)
1278 return -EINVAL;
1279
1280 /* Sanity check on bus space */
1281 iomask = bus_space_to_resource_flags(node->addrs[index].space);
1282 if (iomask & IORESOURCE_MEM)
1283 parent = &iomem_resource;
1284 else if (iomask & IORESOURCE_IO)
1285 parent = &ioport_resource;
1286 else
1287 return -EINVAL;
1288
1289 /* Find a PCI parent if any */
1290 nd = node;
1291 pcidev = NULL;
1292 while(nd) {
1293 if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
1294 pcidev = pci_find_slot(pci_bus, pci_devfn);
1295 if (pcidev) break;
1296 nd = nd->parent;
1297 }
1298 if (pcidev)
1299 parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
1300 if (!parent) {
1301 printk(KERN_WARNING "release_OF_resource(%s), parent not found\n",
1302 node->name);
1303 return -ENODEV;
1304 }
1305
1306 /* Find us in the parent and its childs */
1307 res = parent->child;
1308 start = node->addrs[index].address;
1309 end = start + node->addrs[index].size - 1;
1310 while (res) {
1311 if (res->start == start && res->end == end &&
1312 (res->flags & IORESOURCE_BUSY))
1313 break;
1314 if (res->start <= start && res->end >= end)
1315 res = res->child;
1316 else
1317 res = res->sibling;
1318 }
1319 if (!res)
1320 return -ENODEV;
1321
1322 kfree(res->name);
1323 res->name = NULL;
1324 release_resource(res);
1325 kfree(res);
1326
1327 return 0;
1328}
1329
1330#if 0
1331void
1332print_properties(struct device_node *np)
1333{
1334 struct property *pp;
1335 char *cp;
1336 int i, n;
1337
1338 for (pp = np->properties; pp != 0; pp = pp->next) {
1339 printk(KERN_INFO "%s", pp->name);
1340 for (i = strlen(pp->name); i < 16; ++i)
1341 printk(" ");
1342 cp = (char *) pp->value;
1343 for (i = pp->length; i > 0; --i, ++cp)
1344 if ((i > 1 && (*cp < 0x20 || *cp > 0x7e))
1345 || (i == 1 && *cp != 0))
1346 break;
1347 if (i == 0 && pp->length > 1) {
1348 /* looks like a string */
1349 printk(" %s\n", (char *) pp->value);
1350 } else {
1351 /* dump it in hex */
1352 n = pp->length;
1353 if (n > 64)
1354 n = 64;
1355 if (pp->length % 4 == 0) {
1356 unsigned int *p = (unsigned int *) pp->value;
1357
1358 n /= 4;
1359 for (i = 0; i < n; ++i) {
1360 if (i != 0 && (i % 4) == 0)
1361 printk("\n ");
1362 printk(" %08x", *p++);
1363 }
1364 } else {
1365 unsigned char *bp = pp->value;
1366
1367 for (i = 0; i < n; ++i) {
1368 if (i != 0 && (i % 16) == 0)
1369 printk("\n ");
1370 printk(" %02x", *bp++);
1371 }
1372 }
1373 printk("\n");
1374 if (pp->length > 64)
1375 printk(" ... (length = %d)\n",
1376 pp->length);
1377 }
1378 }
1379}
1380#endif
1381
1382static DEFINE_SPINLOCK(rtas_lock);
1383
1384/* this can be called after setup -- Cort */
1385int
1386call_rtas(const char *service, int nargs, int nret,
1387 unsigned long *outputs, ...)
1388{
1389 va_list list;
1390 int i;
1391 unsigned long s;
1392 struct device_node *rtas;
1393 int *tokp;
1394 union {
1395 unsigned long words[16];
1396 double align;
1397 } u;
1398
1399 rtas = find_devices("rtas");
1400 if (rtas == NULL)
1401 return -1;
1402 tokp = (int *) get_property(rtas, service, NULL);
1403 if (tokp == NULL) {
1404 printk(KERN_ERR "No RTAS service called %s\n", service);
1405 return -1;
1406 }
1407 u.words[0] = *tokp;
1408 u.words[1] = nargs;
1409 u.words[2] = nret;
1410 va_start(list, outputs);
1411 for (i = 0; i < nargs; ++i)
1412 u.words[i+3] = va_arg(list, unsigned long);
1413 va_end(list);
1414
1415 /*
1416 * RTAS doesn't use floating point.
1417 * Or at least, according to the CHRP spec we enter RTAS
1418 * with FP disabled, and it doesn't change the FP registers.
1419 * -- paulus.
1420 */
1421 spin_lock_irqsave(&rtas_lock, s);
1422 enter_rtas((void *)__pa(&u));
1423 spin_unlock_irqrestore(&rtas_lock, s);
1424
1425 if (nret > 1 && outputs != NULL)
1426 for (i = 0; i < nret-1; ++i)
1427 outputs[i] = u.words[i+nargs+4];
1428 return u.words[nargs+3];
1429}
diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c
deleted file mode 100644
index df14422ae1c6..000000000000
--- a/arch/ppc/syslib/prom_init.c
+++ /dev/null
@@ -1,1011 +0,0 @@
1/*
2 * Note that prom_init() and anything called from prom_init()
3 * may be running at an address that is different from the address
4 * that it was linked at. References to static data items are
5 * handled by compiling this file with -mrelocatable-lib.
6 */
7
8#include <linux/config.h>
9#include <linux/kernel.h>
10#include <linux/string.h>
11#include <linux/init.h>
12#include <linux/threads.h>
13#include <linux/spinlock.h>
14#include <linux/ioport.h>
15#include <linux/pci.h>
16#include <linux/slab.h>
17#include <linux/bitops.h>
18
19#include <asm/sections.h>
20#include <asm/prom.h>
21#include <asm/page.h>
22#include <asm/irq.h>
23#include <asm/io.h>
24#include <asm/smp.h>
25#include <asm/bootx.h>
26#include <asm/system.h>
27#include <asm/mmu.h>
28#include <asm/pgtable.h>
29#include <asm/bootinfo.h>
30#include <asm/btext.h>
31#include <asm/pci-bridge.h>
32#include <asm/open_pic.h>
33#include <asm/cacheflush.h>
34
35#ifdef CONFIG_LOGO_LINUX_CLUT224
36#include <linux/linux_logo.h>
37extern const struct linux_logo logo_linux_clut224;
38#endif
39
40/*
41 * Properties whose value is longer than this get excluded from our
42 * copy of the device tree. This way we don't waste space storing
43 * things like "driver,AAPL,MacOS,PowerPC" properties. But this value
44 * does need to be big enough to ensure that we don't lose things
45 * like the interrupt-map property on a PCI-PCI bridge.
46 */
47#define MAX_PROPERTY_LENGTH 4096
48
49#ifndef FB_MAX /* avoid pulling in all of the fb stuff */
50#define FB_MAX 8
51#endif
52
53#define ALIGNUL(x) (((x) + sizeof(unsigned long)-1) & -sizeof(unsigned long))
54
55typedef u32 prom_arg_t;
56
57struct prom_args {
58 const char *service;
59 int nargs;
60 int nret;
61 prom_arg_t args[10];
62};
63
64struct pci_address {
65 unsigned a_hi;
66 unsigned a_mid;
67 unsigned a_lo;
68};
69
70struct pci_reg_property {
71 struct pci_address addr;
72 unsigned size_hi;
73 unsigned size_lo;
74};
75
76struct pci_range {
77 struct pci_address addr;
78 unsigned phys;
79 unsigned size_hi;
80 unsigned size_lo;
81};
82
83struct isa_reg_property {
84 unsigned space;
85 unsigned address;
86 unsigned size;
87};
88
89struct pci_intr_map {
90 struct pci_address addr;
91 unsigned dunno;
92 phandle int_ctrler;
93 unsigned intr;
94};
95
96static void prom_exit(void);
97static int call_prom(const char *service, int nargs, int nret, ...);
98static int call_prom_ret(const char *service, int nargs, int nret,
99 prom_arg_t *rets, ...);
100static void prom_print_hex(unsigned int v);
101static int prom_set_color(ihandle ih, int i, int r, int g, int b);
102static int prom_next_node(phandle *nodep);
103static unsigned long check_display(unsigned long mem);
104static void setup_disp_fake_bi(ihandle dp);
105static unsigned long copy_device_tree(unsigned long mem_start,
106 unsigned long mem_end);
107static unsigned long inspect_node(phandle node, struct device_node *dad,
108 unsigned long mem_start, unsigned long mem_end,
109 struct device_node ***allnextpp);
110static void prom_hold_cpus(unsigned long mem);
111static void prom_instantiate_rtas(void);
112static void * early_get_property(unsigned long base, unsigned long node,
113 char *prop);
114
115prom_entry prom __initdata;
116ihandle prom_chosen __initdata;
117ihandle prom_stdout __initdata;
118
119static char *prom_display_paths[FB_MAX] __initdata;
120static phandle prom_display_nodes[FB_MAX] __initdata;
121static unsigned int prom_num_displays __initdata;
122static ihandle prom_disp_node __initdata;
123char *of_stdout_device __initdata;
124
125unsigned int rtas_data; /* physical pointer */
126unsigned int rtas_entry; /* physical pointer */
127unsigned int rtas_size;
128unsigned int old_rtas;
129
130boot_infos_t *boot_infos;
131char *bootpath;
132char *bootdevice;
133struct device_node *allnodes;
134
135extern char *klimit;
136
137static void __init
138prom_exit(void)
139{
140 struct prom_args args;
141
142 args.service = "exit";
143 args.nargs = 0;
144 args.nret = 0;
145 prom(&args);
146 for (;;) /* should never get here */
147 ;
148}
149
150static int __init
151call_prom(const char *service, int nargs, int nret, ...)
152{
153 va_list list;
154 int i;
155 struct prom_args prom_args;
156
157 prom_args.service = service;
158 prom_args.nargs = nargs;
159 prom_args.nret = nret;
160 va_start(list, nret);
161 for (i = 0; i < nargs; ++i)
162 prom_args.args[i] = va_arg(list, prom_arg_t);
163 va_end(list);
164 for (i = 0; i < nret; ++i)
165 prom_args.args[i + nargs] = 0;
166 prom(&prom_args);
167 return prom_args.args[nargs];
168}
169
170static int __init
171call_prom_ret(const char *service, int nargs, int nret, prom_arg_t *rets, ...)
172{
173 va_list list;
174 int i;
175 struct prom_args prom_args;
176
177 prom_args.service = service;
178 prom_args.nargs = nargs;
179 prom_args.nret = nret;
180 va_start(list, rets);
181 for (i = 0; i < nargs; ++i)
182 prom_args.args[i] = va_arg(list, int);
183 va_end(list);
184 for (i = 0; i < nret; ++i)
185 prom_args.args[i + nargs] = 0;
186 prom(&prom_args);
187 for (i = 1; i < nret; ++i)
188 rets[i-1] = prom_args.args[nargs + i];
189 return prom_args.args[nargs];
190}
191
192void __init
193prom_print(const char *msg)
194{
195 const char *p, *q;
196
197 if (prom_stdout == 0)
198 return;
199
200 for (p = msg; *p != 0; p = q) {
201 for (q = p; *q != 0 && *q != '\n'; ++q)
202 ;
203 if (q > p)
204 call_prom("write", 3, 1, prom_stdout, p, q - p);
205 if (*q != 0) {
206 ++q;
207 call_prom("write", 3, 1, prom_stdout, "\r\n", 2);
208 }
209 }
210}
211
212static void __init
213prom_print_hex(unsigned int v)
214{
215 char buf[16];
216 int i, c;
217
218 for (i = 0; i < 8; ++i) {
219 c = (v >> ((7-i)*4)) & 0xf;
220 c += (c >= 10)? ('a' - 10): '0';
221 buf[i] = c;
222 }
223 buf[i] = ' ';
224 buf[i+1] = 0;
225 prom_print(buf);
226}
227
228static int __init
229prom_set_color(ihandle ih, int i, int r, int g, int b)
230{
231 return call_prom("call-method", 6, 1, "color!", ih, i, b, g, r);
232}
233
234static int __init
235prom_next_node(phandle *nodep)
236{
237 phandle node;
238
239 if ((node = *nodep) != 0
240 && (*nodep = call_prom("child", 1, 1, node)) != 0)
241 return 1;
242 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
243 return 1;
244 for (;;) {
245 if ((node = call_prom("parent", 1, 1, node)) == 0)
246 return 0;
247 if ((*nodep = call_prom("peer", 1, 1, node)) != 0)
248 return 1;
249 }
250}
251
252#ifdef CONFIG_POWER4
253/*
254 * Set up a hash table with a set of entries in it to map the
255 * first 64MB of RAM. This is used on 64-bit machines since
256 * some of them don't have BATs.
257 */
258
259static inline void make_pte(unsigned long htab, unsigned int hsize,
260 unsigned int va, unsigned int pa, int mode)
261{
262 unsigned int *pteg;
263 unsigned int hash, i, vsid;
264
265 vsid = ((va >> 28) * 0x111) << 12;
266 hash = ((va ^ vsid) >> 5) & 0x7fff80;
267 pteg = (unsigned int *)(htab + (hash & (hsize - 1)));
268 for (i = 0; i < 8; ++i, pteg += 4) {
269 if ((pteg[1] & 1) == 0) {
270 pteg[1] = vsid | ((va >> 16) & 0xf80) | 1;
271 pteg[3] = pa | mode;
272 break;
273 }
274 }
275}
276
277extern unsigned long _SDR1;
278extern PTE *Hash;
279extern unsigned long Hash_size;
280
281static void __init
282prom_alloc_htab(void)
283{
284 unsigned int hsize;
285 unsigned long htab;
286 unsigned int addr;
287
288 /*
289 * Because of OF bugs we can't use the "claim" client
290 * interface to allocate memory for the hash table.
291 * This code is only used on 64-bit PPCs, and the only
292 * 64-bit PPCs at the moment are RS/6000s, and their
293 * OF is based at 0xc00000 (the 12M point), so we just
294 * arbitrarily use the 0x800000 - 0xc00000 region for the
295 * hash table.
296 * -- paulus.
297 */
298 hsize = 4 << 20; /* POWER4 has no BATs */
299 htab = (8 << 20);
300 call_prom("claim", 3, 1, htab, hsize, 0);
301 Hash = (void *)(htab + KERNELBASE);
302 Hash_size = hsize;
303 _SDR1 = htab + __ilog2(hsize) - 18;
304
305 /*
306 * Put in PTEs for the first 64MB of RAM
307 */
308 memset((void *)htab, 0, hsize);
309 for (addr = 0; addr < 0x4000000; addr += 0x1000)
310 make_pte(htab, hsize, addr + KERNELBASE, addr,
311 _PAGE_ACCESSED | _PAGE_COHERENT | PP_RWXX);
312#if 0 /* DEBUG stuff mapping the SCC */
313 make_pte(htab, hsize, 0x80013000, 0x80013000,
314 _PAGE_ACCESSED | _PAGE_NO_CACHE | _PAGE_GUARDED | PP_RWXX);
315#endif
316}
317#endif /* CONFIG_POWER4 */
318
319
320/*
321 * If we have a display that we don't know how to drive,
322 * we will want to try to execute OF's open method for it
323 * later. However, OF will probably fall over if we do that
324 * we've taken over the MMU.
325 * So we check whether we will need to open the display,
326 * and if so, open it now.
327 */
328static unsigned long __init
329check_display(unsigned long mem)
330{
331 phandle node;
332 ihandle ih;
333 int i, j;
334 char type[16], *path;
335 static unsigned char default_colors[] = {
336 0x00, 0x00, 0x00,
337 0x00, 0x00, 0xaa,
338 0x00, 0xaa, 0x00,
339 0x00, 0xaa, 0xaa,
340 0xaa, 0x00, 0x00,
341 0xaa, 0x00, 0xaa,
342 0xaa, 0xaa, 0x00,
343 0xaa, 0xaa, 0xaa,
344 0x55, 0x55, 0x55,
345 0x55, 0x55, 0xff,
346 0x55, 0xff, 0x55,
347 0x55, 0xff, 0xff,
348 0xff, 0x55, 0x55,
349 0xff, 0x55, 0xff,
350 0xff, 0xff, 0x55,
351 0xff, 0xff, 0xff
352 };
353 const unsigned char *clut;
354
355 prom_disp_node = 0;
356
357 for (node = 0; prom_next_node(&node); ) {
358 type[0] = 0;
359 call_prom("getprop", 4, 1, node, "device_type",
360 type, sizeof(type));
361 if (strcmp(type, "display") != 0)
362 continue;
363 /* It seems OF doesn't null-terminate the path :-( */
364 path = (char *) mem;
365 memset(path, 0, 256);
366 if (call_prom("package-to-path", 3, 1, node, path, 255) < 0)
367 continue;
368
369 /*
370 * If this display is the device that OF is using for stdout,
371 * move it to the front of the list.
372 */
373 mem += strlen(path) + 1;
374 i = prom_num_displays++;
375 if (of_stdout_device != 0 && i > 0
376 && strcmp(of_stdout_device, path) == 0) {
377 for (; i > 0; --i) {
378 prom_display_paths[i]
379 = prom_display_paths[i-1];
380 prom_display_nodes[i]
381 = prom_display_nodes[i-1];
382 }
383 }
384 prom_display_paths[i] = path;
385 prom_display_nodes[i] = node;
386 if (i == 0)
387 prom_disp_node = node;
388 if (prom_num_displays >= FB_MAX)
389 break;
390 }
391
392 for (j=0; j<prom_num_displays; j++) {
393 path = prom_display_paths[j];
394 node = prom_display_nodes[j];
395 prom_print("opening display ");
396 prom_print(path);
397 ih = call_prom("open", 1, 1, path);
398 if (ih == 0 || ih == (ihandle) -1) {
399 prom_print("... failed\n");
400 for (i=j+1; i<prom_num_displays; i++) {
401 prom_display_paths[i-1] = prom_display_paths[i];
402 prom_display_nodes[i-1] = prom_display_nodes[i];
403 }
404 if (--prom_num_displays > 0) {
405 prom_disp_node = prom_display_nodes[j];
406 j--;
407 } else
408 prom_disp_node = 0;
409 continue;
410 } else {
411 prom_print("... ok\n");
412 call_prom("setprop", 4, 1, node, "linux,opened", 0, 0);
413
414 /*
415 * Setup a usable color table when the appropriate
416 * method is available.
417 * Should update this to use set-colors.
418 */
419 clut = default_colors;
420 for (i = 0; i < 32; i++, clut += 3)
421 if (prom_set_color(ih, i, clut[0], clut[1],
422 clut[2]) != 0)
423 break;
424
425#ifdef CONFIG_LOGO_LINUX_CLUT224
426 clut = PTRRELOC(logo_linux_clut224.clut);
427 for (i = 0; i < logo_linux_clut224.clutsize;
428 i++, clut += 3)
429 if (prom_set_color(ih, i + 32, clut[0],
430 clut[1], clut[2]) != 0)
431 break;
432#endif /* CONFIG_LOGO_LINUX_CLUT224 */
433 }
434 }
435
436 if (prom_stdout) {
437 phandle p;
438 p = call_prom("instance-to-package", 1, 1, prom_stdout);
439 if (p && p != -1) {
440 type[0] = 0;
441 call_prom("getprop", 4, 1, p, "device_type",
442 type, sizeof(type));
443 if (strcmp(type, "display") == 0)
444 call_prom("setprop", 4, 1, p, "linux,boot-display",
445 0, 0);
446 }
447 }
448
449 return ALIGNUL(mem);
450}
451
452/* This function will enable the early boot text when doing OF booting. This
453 * way, xmon output should work too
454 */
455static void __init
456setup_disp_fake_bi(ihandle dp)
457{
458#ifdef CONFIG_BOOTX_TEXT
459 int width = 640, height = 480, depth = 8, pitch;
460 unsigned address;
461 struct pci_reg_property addrs[8];
462 int i, naddrs;
463 char name[32];
464 char *getprop = "getprop";
465
466 prom_print("Initializing fake screen: ");
467
468 memset(name, 0, sizeof(name));
469 call_prom(getprop, 4, 1, dp, "name", name, sizeof(name));
470 name[sizeof(name)-1] = 0;
471 prom_print(name);
472 prom_print("\n");
473 call_prom(getprop, 4, 1, dp, "width", &width, sizeof(width));
474 call_prom(getprop, 4, 1, dp, "height", &height, sizeof(height));
475 call_prom(getprop, 4, 1, dp, "depth", &depth, sizeof(depth));
476 pitch = width * ((depth + 7) / 8);
477 call_prom(getprop, 4, 1, dp, "linebytes",
478 &pitch, sizeof(pitch));
479 if (pitch == 1)
480 pitch = 0x1000; /* for strange IBM display */
481 address = 0;
482 call_prom(getprop, 4, 1, dp, "address",
483 &address, sizeof(address));
484 if (address == 0) {
485 /* look for an assigned address with a size of >= 1MB */
486 naddrs = call_prom(getprop, 4, 1, dp, "assigned-addresses",
487 addrs, sizeof(addrs));
488 naddrs /= sizeof(struct pci_reg_property);
489 for (i = 0; i < naddrs; ++i) {
490 if (addrs[i].size_lo >= (1 << 20)) {
491 address = addrs[i].addr.a_lo;
492 /* use the BE aperture if possible */
493 if (addrs[i].size_lo >= (16 << 20))
494 address += (8 << 20);
495 break;
496 }
497 }
498 if (address == 0) {
499 prom_print("Failed to get address\n");
500 return;
501 }
502 }
503 /* kludge for valkyrie */
504 if (strcmp(name, "valkyrie") == 0)
505 address += 0x1000;
506
507#ifdef CONFIG_POWER4
508#if CONFIG_TASK_SIZE > 0x80000000
509#error CONFIG_TASK_SIZE cannot be above 0x80000000 with BOOTX_TEXT on G5
510#endif
511 {
512 extern boot_infos_t disp_bi;
513 unsigned long va, pa, i, offset;
514 va = 0x90000000;
515 pa = address & 0xfffff000ul;
516 offset = address & 0x00000fff;
517
518 for (i=0; i<0x4000; i++) {
519 make_pte((unsigned long)Hash - KERNELBASE, Hash_size, va, pa,
520 _PAGE_ACCESSED | _PAGE_NO_CACHE |
521 _PAGE_GUARDED | PP_RWXX);
522 va += 0x1000;
523 pa += 0x1000;
524 }
525 btext_setup_display(width, height, depth, pitch, 0x90000000 | offset);
526 disp_bi.dispDeviceBase = (u8 *)address;
527 }
528#else /* CONFIG_POWER4 */
529 btext_setup_display(width, height, depth, pitch, address);
530 btext_prepare_BAT();
531#endif /* CONFIG_POWER4 */
532#endif /* CONFIG_BOOTX_TEXT */
533}
534
535/*
536 * Make a copy of the device tree from the PROM.
537 */
538static unsigned long __init
539copy_device_tree(unsigned long mem_start, unsigned long mem_end)
540{
541 phandle root;
542 unsigned long new_start;
543 struct device_node **allnextp;
544
545 root = call_prom("peer", 1, 1, (phandle)0);
546 if (root == (phandle)0) {
547 prom_print("couldn't get device tree root\n");
548 prom_exit();
549 }
550 allnextp = &allnodes;
551 mem_start = ALIGNUL(mem_start);
552 new_start = inspect_node(root, NULL, mem_start, mem_end, &allnextp);
553 *allnextp = NULL;
554 return new_start;
555}
556
557static unsigned long __init
558inspect_node(phandle node, struct device_node *dad,
559 unsigned long mem_start, unsigned long mem_end,
560 struct device_node ***allnextpp)
561{
562 int l;
563 phandle child;
564 struct device_node *np;
565 struct property *pp, **prev_propp;
566 char *prev_name, *namep;
567 unsigned char *valp;
568
569 np = (struct device_node *) mem_start;
570 mem_start += sizeof(struct device_node);
571 memset(np, 0, sizeof(*np));
572 np->node = node;
573 **allnextpp = PTRUNRELOC(np);
574 *allnextpp = &np->allnext;
575 if (dad != 0) {
576 np->parent = PTRUNRELOC(dad);
577 /* we temporarily use the `next' field as `last_child'. */
578 if (dad->next == 0)
579 dad->child = PTRUNRELOC(np);
580 else
581 dad->next->sibling = PTRUNRELOC(np);
582 dad->next = np;
583 }
584
585 /* get and store all properties */
586 prev_propp = &np->properties;
587 prev_name = "";
588 for (;;) {
589 pp = (struct property *) mem_start;
590 namep = (char *) (pp + 1);
591 pp->name = PTRUNRELOC(namep);
592 if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0)
593 break;
594 mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
595 prev_name = namep;
596 valp = (unsigned char *) mem_start;
597 pp->value = PTRUNRELOC(valp);
598 pp->length = call_prom("getprop", 4, 1, node, namep,
599 valp, mem_end - mem_start);
600 if (pp->length < 0)
601 continue;
602#ifdef MAX_PROPERTY_LENGTH
603 if (pp->length > MAX_PROPERTY_LENGTH)
604 continue; /* ignore this property */
605#endif
606 mem_start = ALIGNUL(mem_start + pp->length);
607 *prev_propp = PTRUNRELOC(pp);
608 prev_propp = &pp->next;
609 }
610 if (np->node != 0) {
611 /* Add a "linux,phandle" property" */
612 pp = (struct property *) mem_start;
613 *prev_propp = PTRUNRELOC(pp);
614 prev_propp = &pp->next;
615 namep = (char *) (pp + 1);
616 pp->name = PTRUNRELOC(namep);
617 strcpy(namep, "linux,phandle");
618 mem_start = ALIGNUL((unsigned long)namep + strlen(namep) + 1);
619 pp->value = (unsigned char *) PTRUNRELOC(&np->node);
620 pp->length = sizeof(np->node);
621 }
622 *prev_propp = NULL;
623
624 /* get the node's full name */
625 l = call_prom("package-to-path", 3, 1, node,
626 mem_start, mem_end - mem_start);
627 if (l >= 0) {
628 char *p, *ep;
629
630 np->full_name = PTRUNRELOC((char *) mem_start);
631 *(char *)(mem_start + l) = 0;
632 /* Fixup an Apple bug where they have bogus \0 chars in the
633 * middle of the path in some properties
634 */
635 for (p = (char *)mem_start, ep = p + l; p < ep; p++)
636 if ((*p) == '\0') {
637 memmove(p, p+1, ep - p);
638 ep--;
639 }
640 mem_start = ALIGNUL(mem_start + l + 1);
641 }
642
643 /* do all our children */
644 child = call_prom("child", 1, 1, node);
645 while (child != 0) {
646 mem_start = inspect_node(child, np, mem_start, mem_end,
647 allnextpp);
648 child = call_prom("peer", 1, 1, child);
649 }
650
651 return mem_start;
652}
653
654unsigned long smp_chrp_cpu_nr __initdata = 0;
655
656/*
657 * With CHRP SMP we need to use the OF to start the other
658 * processors so we can't wait until smp_boot_cpus (the OF is
659 * trashed by then) so we have to put the processors into
660 * a holding pattern controlled by the kernel (not OF) before
661 * we destroy the OF.
662 *
663 * This uses a chunk of high memory, puts some holding pattern
664 * code there and sends the other processors off to there until
665 * smp_boot_cpus tells them to do something. We do that by using
666 * physical address 0x0. The holding pattern checks that address
667 * until its cpu # is there, when it is that cpu jumps to
668 * __secondary_start(). smp_boot_cpus() takes care of setting those
669 * values.
670 *
671 * We also use physical address 0x4 here to tell when a cpu
672 * is in its holding pattern code.
673 *
674 * -- Cort
675 *
676 * Note that we have to do this if we have more than one CPU,
677 * even if this is a UP kernel. Otherwise when we trash OF
678 * the other CPUs will start executing some random instructions
679 * and crash the system. -- paulus
680 */
681static void __init
682prom_hold_cpus(unsigned long mem)
683{
684 extern void __secondary_hold(void);
685 unsigned long i;
686 int cpu;
687 phandle node;
688 char type[16], *path;
689 unsigned int reg;
690
691 /*
692 * XXX: hack to make sure we're chrp, assume that if we're
693 * chrp we have a device_type property -- Cort
694 */
695 node = call_prom("finddevice", 1, 1, "/");
696 if (call_prom("getprop", 4, 1, node,
697 "device_type", type, sizeof(type)) <= 0)
698 return;
699
700 /* copy the holding pattern code to someplace safe (0) */
701 /* the holding pattern is now within the first 0x100
702 bytes of the kernel image -- paulus */
703 memcpy((void *)0, _stext, 0x100);
704 flush_icache_range(0, 0x100);
705
706 /* look for cpus */
707 *(unsigned long *)(0x0) = 0;
708 asm volatile("dcbf 0,%0": : "r" (0) : "memory");
709 for (node = 0; prom_next_node(&node); ) {
710 type[0] = 0;
711 call_prom("getprop", 4, 1, node, "device_type",
712 type, sizeof(type));
713 if (strcmp(type, "cpu") != 0)
714 continue;
715 path = (char *) mem;
716 memset(path, 0, 256);
717 if (call_prom("package-to-path", 3, 1, node, path, 255) < 0)
718 continue;
719 reg = -1;
720 call_prom("getprop", 4, 1, node, "reg", &reg, sizeof(reg));
721 cpu = smp_chrp_cpu_nr++;
722#ifdef CONFIG_SMP
723 smp_hw_index[cpu] = reg;
724#endif /* CONFIG_SMP */
725 /* XXX: hack - don't start cpu 0, this cpu -- Cort */
726 if (cpu == 0)
727 continue;
728 prom_print("starting cpu ");
729 prom_print(path);
730 *(ulong *)(0x4) = 0;
731 call_prom("start-cpu", 3, 0, node,
732 (char *)__secondary_hold - _stext, cpu);
733 prom_print("...");
734 for ( i = 0 ; (i < 10000) && (*(ulong *)(0x4) == 0); i++ )
735 ;
736 if (*(ulong *)(0x4) == cpu)
737 prom_print("ok\n");
738 else {
739 prom_print("failed: ");
740 prom_print_hex(*(ulong *)0x4);
741 prom_print("\n");
742 }
743 }
744}
745
746static void __init
747prom_instantiate_rtas(void)
748{
749 ihandle prom_rtas;
750 prom_arg_t result;
751
752 prom_rtas = call_prom("finddevice", 1, 1, "/rtas");
753 if (prom_rtas == -1)
754 return;
755
756 rtas_size = 0;
757 call_prom("getprop", 4, 1, prom_rtas,
758 "rtas-size", &rtas_size, sizeof(rtas_size));
759 prom_print("instantiating rtas");
760 if (rtas_size == 0) {
761 rtas_data = 0;
762 } else {
763 /*
764 * Ask OF for some space for RTAS.
765 * Actually OF has bugs so we just arbitrarily
766 * use memory at the 6MB point.
767 */
768 rtas_data = 6 << 20;
769 prom_print(" at ");
770 prom_print_hex(rtas_data);
771 }
772
773 prom_rtas = call_prom("open", 1, 1, "/rtas");
774 prom_print("...");
775 rtas_entry = 0;
776 if (call_prom_ret("call-method", 3, 2, &result,
777 "instantiate-rtas", prom_rtas, rtas_data) == 0)
778 rtas_entry = result;
779 if ((rtas_entry == -1) || (rtas_entry == 0))
780 prom_print(" failed\n");
781 else
782 prom_print(" done\n");
783}
784
785/*
786 * We enter here early on, when the Open Firmware prom is still
787 * handling exceptions and the MMU hash table for us.
788 */
789unsigned long __init
790prom_init(int r3, int r4, prom_entry pp)
791{
792 unsigned long mem;
793 ihandle prom_mmu;
794 unsigned long offset = reloc_offset();
795 int i, l;
796 char *p, *d;
797 unsigned long phys;
798 prom_arg_t result[3];
799 char model[32];
800 phandle node;
801 int rc;
802
803 /* Default */
804 phys = (unsigned long) &_stext;
805
806 /* First get a handle for the stdout device */
807 prom = pp;
808 prom_chosen = call_prom("finddevice", 1, 1, "/chosen");
809 if (prom_chosen == -1)
810 prom_exit();
811 if (call_prom("getprop", 4, 1, prom_chosen, "stdout",
812 &prom_stdout, sizeof(prom_stdout)) <= 0)
813 prom_exit();
814
815 /* Get the full OF pathname of the stdout device */
816 mem = (unsigned long) klimit + offset;
817 p = (char *) mem;
818 memset(p, 0, 256);
819 call_prom("instance-to-path", 3, 1, prom_stdout, p, 255);
820 of_stdout_device = p;
821 mem += strlen(p) + 1;
822
823 /* Get the boot device and translate it to a full OF pathname. */
824 p = (char *) mem;
825 l = call_prom("getprop", 4, 1, prom_chosen, "bootpath", p, 1<<20);
826 if (l > 0) {
827 p[l] = 0; /* should already be null-terminated */
828 bootpath = PTRUNRELOC(p);
829 mem += l + 1;
830 d = (char *) mem;
831 *d = 0;
832 call_prom("canon", 3, 1, p, d, 1<<20);
833 bootdevice = PTRUNRELOC(d);
834 mem = ALIGNUL(mem + strlen(d) + 1);
835 }
836
837 prom_instantiate_rtas();
838
839#ifdef CONFIG_POWER4
840 /*
841 * Find out how much memory we have and allocate a
842 * suitably-sized hash table.
843 */
844 prom_alloc_htab();
845#endif
846 mem = check_display(mem);
847
848 prom_print("copying OF device tree...");
849 mem = copy_device_tree(mem, mem + (1<<20));
850 prom_print("done\n");
851
852 prom_hold_cpus(mem);
853
854 klimit = (char *) (mem - offset);
855
856 node = call_prom("finddevice", 1, 1, "/");
857 rc = call_prom("getprop", 4, 1, node, "model", model, sizeof(model));
858 if (rc > 0 && !strncmp (model, "Pegasos", 7)
859 && strncmp (model, "Pegasos2", 8)) {
860 /* Pegasos 1 has a broken translate method in the OF,
861 * and furthermore the BATs are mapped 1:1 so the phys
862 * address calculated above is correct, so let's use
863 * it directly.
864 */
865 } else if (offset == 0) {
866 /* If we are already running at 0xc0000000, we assume we were
867 * loaded by an OF bootloader which did set a BAT for us.
868 * This breaks OF translate so we force phys to be 0.
869 */
870 prom_print("(already at 0xc0000000) phys=0\n");
871 phys = 0;
872 } else if (call_prom("getprop", 4, 1, prom_chosen, "mmu",
873 &prom_mmu, sizeof(prom_mmu)) <= 0) {
874 prom_print(" no MMU found\n");
875 } else if (call_prom_ret("call-method", 4, 4, result, "translate",
876 prom_mmu, &_stext, 1) != 0) {
877 prom_print(" (translate failed)\n");
878 } else {
879 /* We assume the phys. address size is 3 cells */
880 phys = result[2];
881 }
882
883 if (prom_disp_node != 0)
884 setup_disp_fake_bi(prom_disp_node);
885
886 /* Use quiesce call to get OF to shut down any devices it's using */
887 prom_print("Calling quiesce ...\n");
888 call_prom("quiesce", 0, 0);
889
890 /* Relocate various pointers which will be used once the
891 kernel is running at the address it was linked at. */
892 for (i = 0; i < prom_num_displays; ++i)
893 prom_display_paths[i] = PTRUNRELOC(prom_display_paths[i]);
894
895#ifdef CONFIG_SERIAL_CORE_CONSOLE
896 /* Relocate the of stdout for console autodetection */
897 of_stdout_device = PTRUNRELOC(of_stdout_device);
898#endif
899
900 prom_print("returning 0x");
901 prom_print_hex(phys);
902 prom_print("from prom_init\n");
903 prom_stdout = 0;
904
905 return phys;
906}
907
908/*
909 * early_get_property is used to access the device tree image prepared
910 * by BootX very early on, before the pointers in it have been relocated.
911 */
912static void * __init
913early_get_property(unsigned long base, unsigned long node, char *prop)
914{
915 struct device_node *np = (struct device_node *)(base + node);
916 struct property *pp;
917
918 for (pp = np->properties; pp != 0; pp = pp->next) {
919 pp = (struct property *) (base + (unsigned long)pp);
920 if (strcmp((char *)((unsigned long)pp->name + base),
921 prop) == 0) {
922 return (void *)((unsigned long)pp->value + base);
923 }
924 }
925 return NULL;
926}
927
928/* Is boot-info compatible ? */
929#define BOOT_INFO_IS_COMPATIBLE(bi) ((bi)->compatible_version <= BOOT_INFO_VERSION)
930#define BOOT_INFO_IS_V2_COMPATIBLE(bi) ((bi)->version >= 2)
931#define BOOT_INFO_IS_V4_COMPATIBLE(bi) ((bi)->version >= 4)
932
933void __init
934bootx_init(unsigned long r4, unsigned long phys)
935{
936 boot_infos_t *bi = (boot_infos_t *) r4;
937 unsigned long space;
938 unsigned long ptr, x;
939 char *model;
940
941 boot_infos = PTRUNRELOC(bi);
942 if (!BOOT_INFO_IS_V2_COMPATIBLE(bi))
943 bi->logicalDisplayBase = NULL;
944
945#ifdef CONFIG_BOOTX_TEXT
946 btext_init(bi);
947
948 /*
949 * Test if boot-info is compatible. Done only in config
950 * CONFIG_BOOTX_TEXT since there is nothing much we can do
951 * with an incompatible version, except display a message
952 * and eventually hang the processor...
953 *
954 * I'll try to keep enough of boot-info compatible in the
955 * future to always allow display of this message;
956 */
957 if (!BOOT_INFO_IS_COMPATIBLE(bi)) {
958 btext_drawstring(" !!! WARNING - Incompatible version of BootX !!!\n\n\n");
959 btext_flushscreen();
960 }
961#endif /* CONFIG_BOOTX_TEXT */
962
963 /* New BootX enters kernel with MMU off, i/os are not allowed
964 here. This hack will have been done by the boostrap anyway.
965 */
966 if (bi->version < 4) {
967 /*
968 * XXX If this is an iMac, turn off the USB controller.
969 */
970 model = (char *) early_get_property
971 (r4 + bi->deviceTreeOffset, 4, "model");
972 if (model
973 && (strcmp(model, "iMac,1") == 0
974 || strcmp(model, "PowerMac1,1") == 0)) {
975 out_le32((unsigned *)0x80880008, 1); /* XXX */
976 }
977 }
978
979 /* Move klimit to enclose device tree, args, ramdisk, etc... */
980 if (bi->version < 5) {
981 space = bi->deviceTreeOffset + bi->deviceTreeSize;
982 if (bi->ramDisk)
983 space = bi->ramDisk + bi->ramDiskSize;
984 } else
985 space = bi->totalParamsSize;
986 klimit = PTRUNRELOC((char *) bi + space);
987
988 /* New BootX will have flushed all TLBs and enters kernel with
989 MMU switched OFF, so this should not be useful anymore.
990 */
991 if (bi->version < 4) {
992 /*
993 * Touch each page to make sure the PTEs for them
994 * are in the hash table - the aim is to try to avoid
995 * getting DSI exceptions while copying the kernel image.
996 */
997 for (ptr = ((unsigned long) &_stext) & PAGE_MASK;
998 ptr < (unsigned long)bi + space; ptr += PAGE_SIZE)
999 x = *(volatile unsigned long *)ptr;
1000 }
1001
1002#ifdef CONFIG_BOOTX_TEXT
1003 /*
1004 * Note that after we call btext_prepare_BAT, we can't do
1005 * prom_draw*, flushscreen or clearscreen until we turn the MMU
1006 * on, since btext_prepare_BAT sets disp_bi.logicalDisplayBase
1007 * to a virtual address.
1008 */
1009 btext_prepare_BAT();
1010#endif
1011}