aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/syslib/prom.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/ppc/syslib/prom.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/ppc/syslib/prom.c')
-rw-r--r--arch/ppc/syslib/prom.c1447
1 files changed, 1447 insertions, 0 deletions
diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c
new file mode 100644
index 000000000000..2c64ed627475
--- /dev/null
+++ b/arch/ppc/syslib/prom.c
@@ -0,0 +1,1447 @@
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/version.h>
17#include <linux/threads.h>
18#include <linux/spinlock.h>
19#include <linux/ioport.h>
20#include <linux/pci.h>
21#include <linux/slab.h>
22#include <linux/bitops.h>
23
24#include <asm/sections.h>
25#include <asm/prom.h>
26#include <asm/page.h>
27#include <asm/processor.h>
28#include <asm/irq.h>
29#include <asm/io.h>
30#include <asm/smp.h>
31#include <asm/bootx.h>
32#include <asm/system.h>
33#include <asm/mmu.h>
34#include <asm/pgtable.h>
35#include <asm/bootinfo.h>
36#include <asm/btext.h>
37#include <asm/pci-bridge.h>
38#include <asm/open_pic.h>
39
40
41struct pci_address {
42 unsigned a_hi;
43 unsigned a_mid;
44 unsigned a_lo;
45};
46
47struct pci_reg_property {
48 struct pci_address addr;
49 unsigned size_hi;
50 unsigned size_lo;
51};
52
53struct isa_reg_property {
54 unsigned space;
55 unsigned address;
56 unsigned size;
57};
58
59typedef unsigned long interpret_func(struct device_node *, unsigned long,
60 int, int);
61static interpret_func interpret_pci_props;
62static interpret_func interpret_dbdma_props;
63static interpret_func interpret_isa_props;
64static interpret_func interpret_macio_props;
65static interpret_func interpret_root_props;
66
67extern char *klimit;
68
69/* Set for a newworld or CHRP machine */
70int use_of_interrupt_tree;
71struct device_node *dflt_interrupt_controller;
72int num_interrupt_controllers;
73
74int pmac_newworld;
75
76extern unsigned int rtas_entry; /* physical pointer */
77
78extern struct device_node *allnodes;
79
80static unsigned long finish_node(struct device_node *, unsigned long,
81 interpret_func *, int, int);
82static unsigned long finish_node_interrupts(struct device_node *, unsigned long);
83static struct device_node *find_phandle(phandle);
84
85extern void enter_rtas(void *);
86void phys_call_rtas(int, int, int, ...);
87
88extern char cmd_line[512]; /* XXX */
89extern boot_infos_t *boot_infos;
90unsigned long dev_tree_size;
91
92void __openfirmware
93phys_call_rtas(int service, int nargs, int nret, ...)
94{
95 va_list list;
96 union {
97 unsigned long words[16];
98 double align;
99 } u;
100 void (*rtas)(void *, unsigned long);
101 int i;
102
103 u.words[0] = service;
104 u.words[1] = nargs;
105 u.words[2] = nret;
106 va_start(list, nret);
107 for (i = 0; i < nargs; ++i)
108 u.words[i+3] = va_arg(list, unsigned long);
109 va_end(list);
110
111 rtas = (void (*)(void *, unsigned long)) rtas_entry;
112 rtas(&u, rtas_data);
113}
114
115/*
116 * finish_device_tree is called once things are running normally
117 * (i.e. with text and data mapped to the address they were linked at).
118 * It traverses the device tree and fills in the name, type,
119 * {n_}addrs and {n_}intrs fields of each node.
120 */
121void __init
122finish_device_tree(void)
123{
124 unsigned long mem = (unsigned long) klimit;
125 struct device_node *np;
126
127 /* All newworld pmac machines and CHRPs now use the interrupt tree */
128 for (np = allnodes; np != NULL; np = np->allnext) {
129 if (get_property(np, "interrupt-parent", NULL)) {
130 use_of_interrupt_tree = 1;
131 break;
132 }
133 }
134 if (_machine == _MACH_Pmac && use_of_interrupt_tree)
135 pmac_newworld = 1;
136
137#ifdef CONFIG_BOOTX_TEXT
138 if (boot_infos && pmac_newworld) {
139 prom_print("WARNING ! BootX/miBoot booting is not supported on this machine\n");
140 prom_print(" You should use an Open Firmware bootloader\n");
141 }
142#endif /* CONFIG_BOOTX_TEXT */
143
144 if (use_of_interrupt_tree) {
145 /*
146 * We want to find out here how many interrupt-controller
147 * nodes there are, and if we are booted from BootX,
148 * we need a pointer to the first (and hopefully only)
149 * such node. But we can't use find_devices here since
150 * np->name has not been set yet. -- paulus
151 */
152 int n = 0;
153 char *name, *ic;
154 int iclen;
155
156 for (np = allnodes; np != NULL; np = np->allnext) {
157 ic = get_property(np, "interrupt-controller", &iclen);
158 name = get_property(np, "name", NULL);
159 /* checking iclen makes sure we don't get a false
160 match on /chosen.interrupt_controller */
161 if ((name != NULL
162 && strcmp(name, "interrupt-controller") == 0)
163 || (ic != NULL && iclen == 0 && strcmp(name, "AppleKiwi"))) {
164 if (n == 0)
165 dflt_interrupt_controller = np;
166 ++n;
167 }
168 }
169 num_interrupt_controllers = n;
170 }
171
172 mem = finish_node(allnodes, mem, NULL, 1, 1);
173 dev_tree_size = mem - (unsigned long) allnodes;
174 klimit = (char *) mem;
175}
176
177static unsigned long __init
178finish_node(struct device_node *np, unsigned long mem_start,
179 interpret_func *ifunc, int naddrc, int nsizec)
180{
181 struct device_node *child;
182 int *ip;
183
184 np->name = get_property(np, "name", NULL);
185 np->type = get_property(np, "device_type", NULL);
186
187 if (!np->name)
188 np->name = "<NULL>";
189 if (!np->type)
190 np->type = "<NULL>";
191
192 /* get the device addresses and interrupts */
193 if (ifunc != NULL)
194 mem_start = ifunc(np, mem_start, naddrc, nsizec);
195
196 if (use_of_interrupt_tree)
197 mem_start = finish_node_interrupts(np, mem_start);
198
199 /* Look for #address-cells and #size-cells properties. */
200 ip = (int *) get_property(np, "#address-cells", NULL);
201 if (ip != NULL)
202 naddrc = *ip;
203 ip = (int *) get_property(np, "#size-cells", NULL);
204 if (ip != NULL)
205 nsizec = *ip;
206
207 if (np->parent == NULL)
208 ifunc = interpret_root_props;
209 else if (np->type == 0)
210 ifunc = NULL;
211 else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci"))
212 ifunc = interpret_pci_props;
213 else if (!strcmp(np->type, "dbdma"))
214 ifunc = interpret_dbdma_props;
215 else if (!strcmp(np->type, "mac-io")
216 || ifunc == interpret_macio_props)
217 ifunc = interpret_macio_props;
218 else if (!strcmp(np->type, "isa"))
219 ifunc = interpret_isa_props;
220 else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3"))
221 ifunc = interpret_root_props;
222 else if (!((ifunc == interpret_dbdma_props
223 || ifunc == interpret_macio_props)
224 && (!strcmp(np->type, "escc")
225 || !strcmp(np->type, "media-bay"))))
226 ifunc = NULL;
227
228 /* if we were booted from BootX, convert the full name */
229 if (boot_infos
230 && strncmp(np->full_name, "Devices:device-tree", 19) == 0) {
231 if (np->full_name[19] == 0) {
232 strcpy(np->full_name, "/");
233 } else if (np->full_name[19] == ':') {
234 char *p = np->full_name + 19;
235 np->full_name = p;
236 for (; *p; ++p)
237 if (*p == ':')
238 *p = '/';
239 }
240 }
241
242 for (child = np->child; child != NULL; child = child->sibling)
243 mem_start = finish_node(child, mem_start, ifunc,
244 naddrc, nsizec);
245
246 return mem_start;
247}
248
249/*
250 * Find the interrupt parent of a node.
251 */
252static struct device_node * __init
253intr_parent(struct device_node *p)
254{
255 phandle *parp;
256
257 parp = (phandle *) get_property(p, "interrupt-parent", NULL);
258 if (parp == NULL)
259 return p->parent;
260 p = find_phandle(*parp);
261 if (p != NULL)
262 return p;
263 /*
264 * On a powermac booted with BootX, we don't get to know the
265 * phandles for any nodes, so find_phandle will return NULL.
266 * Fortunately these machines only have one interrupt controller
267 * so there isn't in fact any ambiguity. -- paulus
268 */
269 if (num_interrupt_controllers == 1)
270 p = dflt_interrupt_controller;
271 return p;
272}
273
274/*
275 * Find out the size of each entry of the interrupts property
276 * for a node.
277 */
278static int __init
279prom_n_intr_cells(struct device_node *np)
280{
281 struct device_node *p;
282 unsigned int *icp;
283
284 for (p = np; (p = intr_parent(p)) != NULL; ) {
285 icp = (unsigned int *)
286 get_property(p, "#interrupt-cells", NULL);
287 if (icp != NULL)
288 return *icp;
289 if (get_property(p, "interrupt-controller", NULL) != NULL
290 || get_property(p, "interrupt-map", NULL) != NULL) {
291 printk("oops, node %s doesn't have #interrupt-cells\n",
292 p->full_name);
293 return 1;
294 }
295 }
296 printk("prom_n_intr_cells failed for %s\n", np->full_name);
297 return 1;
298}
299
300/*
301 * Map an interrupt from a device up to the platform interrupt
302 * descriptor.
303 */
304static int __init
305map_interrupt(unsigned int **irq, struct device_node **ictrler,
306 struct device_node *np, unsigned int *ints, int nintrc)
307{
308 struct device_node *p, *ipar;
309 unsigned int *imap, *imask, *ip;
310 int i, imaplen, match;
311 int newintrc = 1, newaddrc = 1;
312 unsigned int *reg;
313 int naddrc;
314
315 reg = (unsigned int *) get_property(np, "reg", NULL);
316 naddrc = prom_n_addr_cells(np);
317 p = intr_parent(np);
318 while (p != NULL) {
319 if (get_property(p, "interrupt-controller", NULL) != NULL)
320 /* this node is an interrupt controller, stop here */
321 break;
322 imap = (unsigned int *)
323 get_property(p, "interrupt-map", &imaplen);
324 if (imap == NULL) {
325 p = intr_parent(p);
326 continue;
327 }
328 imask = (unsigned int *)
329 get_property(p, "interrupt-map-mask", NULL);
330 if (imask == NULL) {
331 printk("oops, %s has interrupt-map but no mask\n",
332 p->full_name);
333 return 0;
334 }
335 imaplen /= sizeof(unsigned int);
336 match = 0;
337 ipar = NULL;
338 while (imaplen > 0 && !match) {
339 /* check the child-interrupt field */
340 match = 1;
341 for (i = 0; i < naddrc && match; ++i)
342 match = ((reg[i] ^ imap[i]) & imask[i]) == 0;
343 for (; i < naddrc + nintrc && match; ++i)
344 match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0;
345 imap += naddrc + nintrc;
346 imaplen -= naddrc + nintrc;
347 /* grab the interrupt parent */
348 ipar = find_phandle((phandle) *imap++);
349 --imaplen;
350 if (ipar == NULL && num_interrupt_controllers == 1)
351 /* cope with BootX not giving us phandles */
352 ipar = dflt_interrupt_controller;
353 if (ipar == NULL) {
354 printk("oops, no int parent %x in map of %s\n",
355 imap[-1], p->full_name);
356 return 0;
357 }
358 /* find the parent's # addr and intr cells */
359 ip = (unsigned int *)
360 get_property(ipar, "#interrupt-cells", NULL);
361 if (ip == NULL) {
362 printk("oops, no #interrupt-cells on %s\n",
363 ipar->full_name);
364 return 0;
365 }
366 newintrc = *ip;
367 ip = (unsigned int *)
368 get_property(ipar, "#address-cells", NULL);
369 newaddrc = (ip == NULL)? 0: *ip;
370 imap += newaddrc + newintrc;
371 imaplen -= newaddrc + newintrc;
372 }
373 if (imaplen < 0) {
374 printk("oops, error decoding int-map on %s, len=%d\n",
375 p->full_name, imaplen);
376 return 0;
377 }
378 if (!match) {
379 printk("oops, no match in %s int-map for %s\n",
380 p->full_name, np->full_name);
381 return 0;
382 }
383 p = ipar;
384 naddrc = newaddrc;
385 nintrc = newintrc;
386 ints = imap - nintrc;
387 reg = ints - naddrc;
388 }
389 if (p == NULL)
390 printk("hmmm, int tree for %s doesn't have ctrler\n",
391 np->full_name);
392 *irq = ints;
393 *ictrler = p;
394 return nintrc;
395}
396
397/*
398 * New version of finish_node_interrupts.
399 */
400static unsigned long __init
401finish_node_interrupts(struct device_node *np, unsigned long mem_start)
402{
403 unsigned int *ints;
404 int intlen, intrcells;
405 int i, j, n, offset;
406 unsigned int *irq;
407 struct device_node *ic;
408
409 ints = (unsigned int *) get_property(np, "interrupts", &intlen);
410 if (ints == NULL)
411 return mem_start;
412 intrcells = prom_n_intr_cells(np);
413 intlen /= intrcells * sizeof(unsigned int);
414 np->n_intrs = intlen;
415 np->intrs = (struct interrupt_info *) mem_start;
416 mem_start += intlen * sizeof(struct interrupt_info);
417
418 for (i = 0; i < intlen; ++i) {
419 np->intrs[i].line = 0;
420 np->intrs[i].sense = 1;
421 n = map_interrupt(&irq, &ic, np, ints, intrcells);
422 if (n <= 0)
423 continue;
424 offset = 0;
425 /*
426 * On a CHRP we have an 8259 which is subordinate to
427 * the openpic in the interrupt tree, but we want the
428 * openpic's interrupt numbers offsetted, not the 8259's.
429 * So we apply the offset if the controller is at the
430 * root of the interrupt tree, i.e. has no interrupt-parent.
431 * This doesn't cope with the general case of multiple
432 * cascaded interrupt controllers, but then neither will
433 * irq.c at the moment either. -- paulus
434 * The G5 triggers that code, I add a machine test. On
435 * those machines, we want to offset interrupts from the
436 * second openpic by 128 -- BenH
437 */
438 if (_machine != _MACH_Pmac && num_interrupt_controllers > 1
439 && ic != NULL
440 && get_property(ic, "interrupt-parent", NULL) == NULL)
441 offset = 16;
442 else if (_machine == _MACH_Pmac && num_interrupt_controllers > 1
443 && ic != NULL && ic->parent != NULL) {
444 char *name = get_property(ic->parent, "name", NULL);
445 if (name && !strcmp(name, "u3"))
446 offset = 128;
447 }
448
449 np->intrs[i].line = irq[0] + offset;
450 if (n > 1)
451 np->intrs[i].sense = irq[1];
452 if (n > 2) {
453 printk("hmmm, got %d intr cells for %s:", n,
454 np->full_name);
455 for (j = 0; j < n; ++j)
456 printk(" %d", irq[j]);
457 printk("\n");
458 }
459 ints += intrcells;
460 }
461
462 return mem_start;
463}
464
465/*
466 * When BootX makes a copy of the device tree from the MacOS
467 * Name Registry, it is in the format we use but all of the pointers
468 * are offsets from the start of the tree.
469 * This procedure updates the pointers.
470 */
471void __init
472relocate_nodes(void)
473{
474 unsigned long base;
475 struct device_node *np;
476 struct property *pp;
477
478#define ADDBASE(x) (x = (typeof (x))((x)? ((unsigned long)(x) + base): 0))
479
480 base = (unsigned long) boot_infos + boot_infos->deviceTreeOffset;
481 allnodes = (struct device_node *)(base + 4);
482 for (np = allnodes; np != 0; np = np->allnext) {
483 ADDBASE(np->full_name);
484 ADDBASE(np->properties);
485 ADDBASE(np->parent);
486 ADDBASE(np->child);
487 ADDBASE(np->sibling);
488 ADDBASE(np->allnext);
489 for (pp = np->properties; pp != 0; pp = pp->next) {
490 ADDBASE(pp->name);
491 ADDBASE(pp->value);
492 ADDBASE(pp->next);
493 }
494 }
495}
496
497int
498prom_n_addr_cells(struct device_node* np)
499{
500 int* ip;
501 do {
502 if (np->parent)
503 np = np->parent;
504 ip = (int *) get_property(np, "#address-cells", NULL);
505 if (ip != NULL)
506 return *ip;
507 } while (np->parent);
508 /* No #address-cells property for the root node, default to 1 */
509 return 1;
510}
511
512int
513prom_n_size_cells(struct device_node* np)
514{
515 int* ip;
516 do {
517 if (np->parent)
518 np = np->parent;
519 ip = (int *) get_property(np, "#size-cells", NULL);
520 if (ip != NULL)
521 return *ip;
522 } while (np->parent);
523 /* No #size-cells property for the root node, default to 1 */
524 return 1;
525}
526
527static unsigned long __init
528map_addr(struct device_node *np, unsigned long space, unsigned long addr)
529{
530 int na;
531 unsigned int *ranges;
532 int rlen = 0;
533 unsigned int type;
534
535 type = (space >> 24) & 3;
536 if (type == 0)
537 return addr;
538
539 while ((np = np->parent) != NULL) {
540 if (strcmp(np->type, "pci") != 0)
541 continue;
542 /* PCI bridge: map the address through the ranges property */
543 na = prom_n_addr_cells(np);
544 ranges = (unsigned int *) get_property(np, "ranges", &rlen);
545 while ((rlen -= (na + 5) * sizeof(unsigned int)) >= 0) {
546 if (((ranges[0] >> 24) & 3) == type
547 && ranges[2] <= addr
548 && addr - ranges[2] < ranges[na+4]) {
549 /* ok, this matches, translate it */
550 addr += ranges[na+2] - ranges[2];
551 break;
552 }
553 ranges += na + 5;
554 }
555 }
556 return addr;
557}
558
559static unsigned long __init
560interpret_pci_props(struct device_node *np, unsigned long mem_start,
561 int naddrc, int nsizec)
562{
563 struct address_range *adr;
564 struct pci_reg_property *pci_addrs;
565 int i, l, *ip;
566
567 pci_addrs = (struct pci_reg_property *)
568 get_property(np, "assigned-addresses", &l);
569 if (pci_addrs != 0 && l >= sizeof(struct pci_reg_property)) {
570 i = 0;
571 adr = (struct address_range *) mem_start;
572 while ((l -= sizeof(struct pci_reg_property)) >= 0) {
573 adr[i].space = pci_addrs[i].addr.a_hi;
574 adr[i].address = map_addr(np, pci_addrs[i].addr.a_hi,
575 pci_addrs[i].addr.a_lo);
576 adr[i].size = pci_addrs[i].size_lo;
577 ++i;
578 }
579 np->addrs = adr;
580 np->n_addrs = i;
581 mem_start += i * sizeof(struct address_range);
582 }
583
584 if (use_of_interrupt_tree)
585 return mem_start;
586
587 ip = (int *) get_property(np, "AAPL,interrupts", &l);
588 if (ip == 0 && np->parent)
589 ip = (int *) get_property(np->parent, "AAPL,interrupts", &l);
590 if (ip == 0)
591 ip = (int *) get_property(np, "interrupts", &l);
592 if (ip != 0) {
593 np->intrs = (struct interrupt_info *) mem_start;
594 np->n_intrs = l / sizeof(int);
595 mem_start += np->n_intrs * sizeof(struct interrupt_info);
596 for (i = 0; i < np->n_intrs; ++i) {
597 np->intrs[i].line = *ip++;
598 np->intrs[i].sense = 1;
599 }
600 }
601
602 return mem_start;
603}
604
605static unsigned long __init
606interpret_dbdma_props(struct device_node *np, unsigned long mem_start,
607 int naddrc, int nsizec)
608{
609 struct reg_property *rp;
610 struct address_range *adr;
611 unsigned long base_address;
612 int i, l, *ip;
613 struct device_node *db;
614
615 base_address = 0;
616 for (db = np->parent; db != NULL; db = db->parent) {
617 if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) {
618 base_address = db->addrs[0].address;
619 break;
620 }
621 }
622
623 rp = (struct reg_property *) get_property(np, "reg", &l);
624 if (rp != 0 && l >= sizeof(struct reg_property)) {
625 i = 0;
626 adr = (struct address_range *) mem_start;
627 while ((l -= sizeof(struct reg_property)) >= 0) {
628 adr[i].space = 2;
629 adr[i].address = rp[i].address + base_address;
630 adr[i].size = rp[i].size;
631 ++i;
632 }
633 np->addrs = adr;
634 np->n_addrs = i;
635 mem_start += i * sizeof(struct address_range);
636 }
637
638 if (use_of_interrupt_tree)
639 return mem_start;
640
641 ip = (int *) get_property(np, "AAPL,interrupts", &l);
642 if (ip == 0)
643 ip = (int *) get_property(np, "interrupts", &l);
644 if (ip != 0) {
645 np->intrs = (struct interrupt_info *) mem_start;
646 np->n_intrs = l / sizeof(int);
647 mem_start += np->n_intrs * sizeof(struct interrupt_info);
648 for (i = 0; i < np->n_intrs; ++i) {
649 np->intrs[i].line = *ip++;
650 np->intrs[i].sense = 1;
651 }
652 }
653
654 return mem_start;
655}
656
657static unsigned long __init
658interpret_macio_props(struct device_node *np, unsigned long mem_start,
659 int naddrc, int nsizec)
660{
661 struct reg_property *rp;
662 struct address_range *adr;
663 unsigned long base_address;
664 int i, l, *ip;
665 struct device_node *db;
666
667 base_address = 0;
668 for (db = np->parent; db != NULL; db = db->parent) {
669 if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) {
670 base_address = db->addrs[0].address;
671 break;
672 }
673 }
674
675 rp = (struct reg_property *) get_property(np, "reg", &l);
676 if (rp != 0 && l >= sizeof(struct reg_property)) {
677 i = 0;
678 adr = (struct address_range *) mem_start;
679 while ((l -= sizeof(struct reg_property)) >= 0) {
680 adr[i].space = 2;
681 adr[i].address = rp[i].address + base_address;
682 adr[i].size = rp[i].size;
683 ++i;
684 }
685 np->addrs = adr;
686 np->n_addrs = i;
687 mem_start += i * sizeof(struct address_range);
688 }
689
690 if (use_of_interrupt_tree)
691 return mem_start;
692
693 ip = (int *) get_property(np, "interrupts", &l);
694 if (ip == 0)
695 ip = (int *) get_property(np, "AAPL,interrupts", &l);
696 if (ip != 0) {
697 np->intrs = (struct interrupt_info *) mem_start;
698 np->n_intrs = l / sizeof(int);
699 for (i = 0; i < np->n_intrs; ++i) {
700 np->intrs[i].line = *ip++;
701 np->intrs[i].sense = 1;
702 }
703 mem_start += np->n_intrs * sizeof(struct interrupt_info);
704 }
705
706 return mem_start;
707}
708
709static unsigned long __init
710interpret_isa_props(struct device_node *np, unsigned long mem_start,
711 int naddrc, int nsizec)
712{
713 struct isa_reg_property *rp;
714 struct address_range *adr;
715 int i, l, *ip;
716
717 rp = (struct isa_reg_property *) get_property(np, "reg", &l);
718 if (rp != 0 && l >= sizeof(struct isa_reg_property)) {
719 i = 0;
720 adr = (struct address_range *) mem_start;
721 while ((l -= sizeof(struct reg_property)) >= 0) {
722 adr[i].space = rp[i].space;
723 adr[i].address = rp[i].address
724 + (adr[i].space? 0: _ISA_MEM_BASE);
725 adr[i].size = rp[i].size;
726 ++i;
727 }
728 np->addrs = adr;
729 np->n_addrs = i;
730 mem_start += i * sizeof(struct address_range);
731 }
732
733 if (use_of_interrupt_tree)
734 return mem_start;
735
736 ip = (int *) get_property(np, "interrupts", &l);
737 if (ip != 0) {
738 np->intrs = (struct interrupt_info *) mem_start;
739 np->n_intrs = l / (2 * sizeof(int));
740 mem_start += np->n_intrs * sizeof(struct interrupt_info);
741 for (i = 0; i < np->n_intrs; ++i) {
742 np->intrs[i].line = *ip++;
743 np->intrs[i].sense = *ip++;
744 }
745 }
746
747 return mem_start;
748}
749
750static unsigned long __init
751interpret_root_props(struct device_node *np, unsigned long mem_start,
752 int naddrc, int nsizec)
753{
754 struct address_range *adr;
755 int i, l, *ip;
756 unsigned int *rp;
757 int rpsize = (naddrc + nsizec) * sizeof(unsigned int);
758
759 rp = (unsigned int *) get_property(np, "reg", &l);
760 if (rp != 0 && l >= rpsize) {
761 i = 0;
762 adr = (struct address_range *) mem_start;
763 while ((l -= rpsize) >= 0) {
764 adr[i].space = (naddrc >= 2? rp[naddrc-2]: 2);
765 adr[i].address = rp[naddrc - 1];
766 adr[i].size = rp[naddrc + nsizec - 1];
767 ++i;
768 rp += naddrc + nsizec;
769 }
770 np->addrs = adr;
771 np->n_addrs = i;
772 mem_start += i * sizeof(struct address_range);
773 }
774
775 if (use_of_interrupt_tree)
776 return mem_start;
777
778 ip = (int *) get_property(np, "AAPL,interrupts", &l);
779 if (ip == 0)
780 ip = (int *) get_property(np, "interrupts", &l);
781 if (ip != 0) {
782 np->intrs = (struct interrupt_info *) mem_start;
783 np->n_intrs = l / sizeof(int);
784 mem_start += np->n_intrs * sizeof(struct interrupt_info);
785 for (i = 0; i < np->n_intrs; ++i) {
786 np->intrs[i].line = *ip++;
787 np->intrs[i].sense = 1;
788 }
789 }
790
791 return mem_start;
792}
793
794/*
795 * Work out the sense (active-low level / active-high edge)
796 * of each interrupt from the device tree.
797 */
798void __init
799prom_get_irq_senses(unsigned char *senses, int off, int max)
800{
801 struct device_node *np;
802 int i, j;
803
804 /* default to level-triggered */
805 memset(senses, 1, max - off);
806 if (!use_of_interrupt_tree)
807 return;
808
809 for (np = allnodes; np != 0; np = np->allnext) {
810 for (j = 0; j < np->n_intrs; j++) {
811 i = np->intrs[j].line;
812 if (i >= off && i < max) {
813 if (np->intrs[j].sense == 1)
814 senses[i-off] = (IRQ_SENSE_LEVEL
815 | IRQ_POLARITY_NEGATIVE);
816 else
817 senses[i-off] = (IRQ_SENSE_EDGE
818 | IRQ_POLARITY_POSITIVE);
819 }
820 }
821 }
822}
823
824/*
825 * Construct and return a list of the device_nodes with a given name.
826 */
827struct device_node *
828find_devices(const char *name)
829{
830 struct device_node *head, **prevp, *np;
831
832 prevp = &head;
833 for (np = allnodes; np != 0; np = np->allnext) {
834 if (np->name != 0 && strcasecmp(np->name, name) == 0) {
835 *prevp = np;
836 prevp = &np->next;
837 }
838 }
839 *prevp = NULL;
840 return head;
841}
842
843/*
844 * Construct and return a list of the device_nodes with a given type.
845 */
846struct device_node *
847find_type_devices(const char *type)
848{
849 struct device_node *head, **prevp, *np;
850
851 prevp = &head;
852 for (np = allnodes; np != 0; np = np->allnext) {
853 if (np->type != 0 && strcasecmp(np->type, type) == 0) {
854 *prevp = np;
855 prevp = &np->next;
856 }
857 }
858 *prevp = NULL;
859 return head;
860}
861
862/*
863 * Returns all nodes linked together
864 */
865struct device_node * __openfirmware
866find_all_nodes(void)
867{
868 struct device_node *head, **prevp, *np;
869
870 prevp = &head;
871 for (np = allnodes; np != 0; np = np->allnext) {
872 *prevp = np;
873 prevp = &np->next;
874 }
875 *prevp = NULL;
876 return head;
877}
878
879/* Checks if the given "compat" string matches one of the strings in
880 * the device's "compatible" property
881 */
882int
883device_is_compatible(struct device_node *device, const char *compat)
884{
885 const char* cp;
886 int cplen, l;
887
888 cp = (char *) get_property(device, "compatible", &cplen);
889 if (cp == NULL)
890 return 0;
891 while (cplen > 0) {
892 if (strncasecmp(cp, compat, strlen(compat)) == 0)
893 return 1;
894 l = strlen(cp) + 1;
895 cp += l;
896 cplen -= l;
897 }
898
899 return 0;
900}
901
902
903/*
904 * Indicates whether the root node has a given value in its
905 * compatible property.
906 */
907int
908machine_is_compatible(const char *compat)
909{
910 struct device_node *root;
911
912 root = find_path_device("/");
913 if (root == 0)
914 return 0;
915 return device_is_compatible(root, compat);
916}
917
918/*
919 * Construct and return a list of the device_nodes with a given type
920 * and compatible property.
921 */
922struct device_node *
923find_compatible_devices(const char *type, const char *compat)
924{
925 struct device_node *head, **prevp, *np;
926
927 prevp = &head;
928 for (np = allnodes; np != 0; np = np->allnext) {
929 if (type != NULL
930 && !(np->type != 0 && strcasecmp(np->type, type) == 0))
931 continue;
932 if (device_is_compatible(np, compat)) {
933 *prevp = np;
934 prevp = &np->next;
935 }
936 }
937 *prevp = NULL;
938 return head;
939}
940
941/*
942 * Find the device_node with a given full_name.
943 */
944struct device_node *
945find_path_device(const char *path)
946{
947 struct device_node *np;
948
949 for (np = allnodes; np != 0; np = np->allnext)
950 if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
951 return np;
952 return NULL;
953}
954
955/*******
956 *
957 * New implementation of the OF "find" APIs, return a refcounted
958 * object, call of_node_put() when done. Currently, still lacks
959 * locking as old implementation, this is beeing done for ppc64.
960 *
961 * Note that property management will need some locking as well,
962 * this isn't dealt with yet
963 *
964 *******/
965
966/**
967 * of_find_node_by_name - Find a node by it's "name" property
968 * @from: The node to start searching from or NULL, the node
969 * you pass will not be searched, only the next one
970 * will; typically, you pass what the previous call
971 * returned. of_node_put() will be called on it
972 * @name: The name string to match against
973 *
974 * Returns a node pointer with refcount incremented, use
975 * of_node_put() on it when done.
976 */
977struct device_node *of_find_node_by_name(struct device_node *from,
978 const char *name)
979{
980 struct device_node *np = from ? from->allnext : allnodes;
981
982 for (; np != 0; np = np->allnext)
983 if (np->name != 0 && strcasecmp(np->name, name) == 0)
984 break;
985 if (from)
986 of_node_put(from);
987 return of_node_get(np);
988}
989
990/**
991 * of_find_node_by_type - Find a node by it's "device_type" property
992 * @from: The node to start searching from or NULL, the node
993 * you pass will not be searched, only the next one
994 * will; typically, you pass what the previous call
995 * returned. of_node_put() will be called on it
996 * @name: The type string to match against
997 *
998 * Returns a node pointer with refcount incremented, use
999 * of_node_put() on it when done.
1000 */
1001struct device_node *of_find_node_by_type(struct device_node *from,
1002 const char *type)
1003{
1004 struct device_node *np = from ? from->allnext : allnodes;
1005
1006 for (; np != 0; np = np->allnext)
1007 if (np->type != 0 && strcasecmp(np->type, type) == 0)
1008 break;
1009 if (from)
1010 of_node_put(from);
1011 return of_node_get(np);
1012}
1013
1014/**
1015 * of_find_compatible_node - Find a node based on type and one of the
1016 * tokens in it's "compatible" property
1017 * @from: The node to start searching from or NULL, the node
1018 * you pass will not be searched, only the next one
1019 * will; typically, you pass what the previous call
1020 * returned. of_node_put() will be called on it
1021 * @type: The type string to match "device_type" or NULL to ignore
1022 * @compatible: The string to match to one of the tokens in the device
1023 * "compatible" list.
1024 *
1025 * Returns a node pointer with refcount incremented, use
1026 * of_node_put() on it when done.
1027 */
1028struct device_node *of_find_compatible_node(struct device_node *from,
1029 const char *type, const char *compatible)
1030{
1031 struct device_node *np = from ? from->allnext : allnodes;
1032
1033 for (; np != 0; np = np->allnext) {
1034 if (type != NULL
1035 && !(np->type != 0 && strcasecmp(np->type, type) == 0))
1036 continue;
1037 if (device_is_compatible(np, compatible))
1038 break;
1039 }
1040 if (from)
1041 of_node_put(from);
1042 return of_node_get(np);
1043}
1044
1045/**
1046 * of_find_node_by_path - Find a node matching a full OF path
1047 * @path: The full path to match
1048 *
1049 * Returns a node pointer with refcount incremented, use
1050 * of_node_put() on it when done.
1051 */
1052struct device_node *of_find_node_by_path(const char *path)
1053{
1054 struct device_node *np = allnodes;
1055
1056 for (; np != 0; np = np->allnext)
1057 if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0)
1058 break;
1059 return of_node_get(np);
1060}
1061
1062/**
1063 * of_find_all_nodes - Get next node in global list
1064 * @prev: Previous node or NULL to start iteration
1065 * of_node_put() will be called on it
1066 *
1067 * Returns a node pointer with refcount incremented, use
1068 * of_node_put() on it when done.
1069 */
1070struct device_node *of_find_all_nodes(struct device_node *prev)
1071{
1072 return of_node_get(prev ? prev->allnext : allnodes);
1073}
1074
1075/**
1076 * of_get_parent - Get a node's parent if any
1077 * @node: Node to get parent
1078 *
1079 * Returns a node pointer with refcount incremented, use
1080 * of_node_put() on it when done.
1081 */
1082struct device_node *of_get_parent(const struct device_node *node)
1083{
1084 return node ? of_node_get(node->parent) : NULL;
1085}
1086
1087/**
1088 * of_get_next_child - Iterate a node childs
1089 * @node: parent node
1090 * @prev: previous child of the parent node, or NULL to get first
1091 *
1092 * Returns a node pointer with refcount incremented, use
1093 * of_node_put() on it when done.
1094 */
1095struct device_node *of_get_next_child(const struct device_node *node,
1096 struct device_node *prev)
1097{
1098 struct device_node *next = prev ? prev->sibling : node->child;
1099
1100 for (; next != 0; next = next->sibling)
1101 if (of_node_get(next))
1102 break;
1103 if (prev)
1104 of_node_put(prev);
1105 return next;
1106}
1107
1108/**
1109 * of_node_get - Increment refcount of a node
1110 * @node: Node to inc refcount, NULL is supported to
1111 * simplify writing of callers
1112 *
1113 * Returns the node itself or NULL if gone. Current implementation
1114 * does nothing as we don't yet do dynamic node allocation on ppc32
1115 */
1116struct device_node *of_node_get(struct device_node *node)
1117{
1118 return node;
1119}
1120
1121/**
1122 * of_node_put - Decrement refcount of a node
1123 * @node: Node to dec refcount, NULL is supported to
1124 * simplify writing of callers
1125 *
1126 * Current implementation does nothing as we don't yet do dynamic node
1127 * allocation on ppc32
1128 */
1129void of_node_put(struct device_node *node)
1130{
1131}
1132
1133/*
1134 * Find the device_node with a given phandle.
1135 */
1136static struct device_node * __init
1137find_phandle(phandle ph)
1138{
1139 struct device_node *np;
1140
1141 for (np = allnodes; np != 0; np = np->allnext)
1142 if (np->node == ph)
1143 return np;
1144 return NULL;
1145}
1146
1147/*
1148 * Find a property with a given name for a given node
1149 * and return the value.
1150 */
1151unsigned char *
1152get_property(struct device_node *np, const char *name, int *lenp)
1153{
1154 struct property *pp;
1155
1156 for (pp = np->properties; pp != 0; pp = pp->next)
1157 if (pp->name != NULL && strcmp(pp->name, name) == 0) {
1158 if (lenp != 0)
1159 *lenp = pp->length;
1160 return pp->value;
1161 }
1162 return NULL;
1163}
1164
1165/*
1166 * Add a property to a node
1167 */
1168void __openfirmware
1169prom_add_property(struct device_node* np, struct property* prop)
1170{
1171 struct property **next = &np->properties;
1172
1173 prop->next = NULL;
1174 while (*next)
1175 next = &(*next)->next;
1176 *next = prop;
1177}
1178
1179/* I quickly hacked that one, check against spec ! */
1180static inline unsigned long __openfirmware
1181bus_space_to_resource_flags(unsigned int bus_space)
1182{
1183 u8 space = (bus_space >> 24) & 0xf;
1184 if (space == 0)
1185 space = 0x02;
1186 if (space == 0x02)
1187 return IORESOURCE_MEM;
1188 else if (space == 0x01)
1189 return IORESOURCE_IO;
1190 else {
1191 printk(KERN_WARNING "prom.c: bus_space_to_resource_flags(), space: %x\n",
1192 bus_space);
1193 return 0;
1194 }
1195}
1196
1197static struct resource* __openfirmware
1198find_parent_pci_resource(struct pci_dev* pdev, struct address_range *range)
1199{
1200 unsigned long mask;
1201 int i;
1202
1203 /* Check this one */
1204 mask = bus_space_to_resource_flags(range->space);
1205 for (i=0; i<DEVICE_COUNT_RESOURCE; i++) {
1206 if ((pdev->resource[i].flags & mask) == mask &&
1207 pdev->resource[i].start <= range->address &&
1208 pdev->resource[i].end > range->address) {
1209 if ((range->address + range->size - 1) > pdev->resource[i].end) {
1210 /* Add better message */
1211 printk(KERN_WARNING "PCI/OF resource overlap !\n");
1212 return NULL;
1213 }
1214 break;
1215 }
1216 }
1217 if (i == DEVICE_COUNT_RESOURCE)
1218 return NULL;
1219 return &pdev->resource[i];
1220}
1221
1222/*
1223 * Request an OF device resource. Currently handles child of PCI devices,
1224 * or other nodes attached to the root node. Ultimately, put some
1225 * link to resources in the OF node.
1226 */
1227struct resource* __openfirmware
1228request_OF_resource(struct device_node* node, int index, const char* name_postfix)
1229{
1230 struct pci_dev* pcidev;
1231 u8 pci_bus, pci_devfn;
1232 unsigned long iomask;
1233 struct device_node* nd;
1234 struct resource* parent;
1235 struct resource *res = NULL;
1236 int nlen, plen;
1237
1238 if (index >= node->n_addrs)
1239 goto fail;
1240
1241 /* Sanity check on bus space */
1242 iomask = bus_space_to_resource_flags(node->addrs[index].space);
1243 if (iomask & IORESOURCE_MEM)
1244 parent = &iomem_resource;
1245 else if (iomask & IORESOURCE_IO)
1246 parent = &ioport_resource;
1247 else
1248 goto fail;
1249
1250 /* Find a PCI parent if any */
1251 nd = node;
1252 pcidev = NULL;
1253 while(nd) {
1254 if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
1255 pcidev = pci_find_slot(pci_bus, pci_devfn);
1256 if (pcidev) break;
1257 nd = nd->parent;
1258 }
1259 if (pcidev)
1260 parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
1261 if (!parent) {
1262 printk(KERN_WARNING "request_OF_resource(%s), parent not found\n",
1263 node->name);
1264 goto fail;
1265 }
1266
1267 res = __request_region(parent, node->addrs[index].address, node->addrs[index].size, NULL);
1268 if (!res)
1269 goto fail;
1270 nlen = strlen(node->name);
1271 plen = name_postfix ? strlen(name_postfix) : 0;
1272 res->name = (const char *)kmalloc(nlen+plen+1, GFP_KERNEL);
1273 if (res->name) {
1274 strcpy((char *)res->name, node->name);
1275 if (plen)
1276 strcpy((char *)res->name+nlen, name_postfix);
1277 }
1278 return res;
1279fail:
1280 return NULL;
1281}
1282
1283int __openfirmware
1284release_OF_resource(struct device_node* node, int index)
1285{
1286 struct pci_dev* pcidev;
1287 u8 pci_bus, pci_devfn;
1288 unsigned long iomask, start, end;
1289 struct device_node* nd;
1290 struct resource* parent;
1291 struct resource *res = NULL;
1292
1293 if (index >= node->n_addrs)
1294 return -EINVAL;
1295
1296 /* Sanity check on bus space */
1297 iomask = bus_space_to_resource_flags(node->addrs[index].space);
1298 if (iomask & IORESOURCE_MEM)
1299 parent = &iomem_resource;
1300 else if (iomask & IORESOURCE_IO)
1301 parent = &ioport_resource;
1302 else
1303 return -EINVAL;
1304
1305 /* Find a PCI parent if any */
1306 nd = node;
1307 pcidev = NULL;
1308 while(nd) {
1309 if (!pci_device_from_OF_node(nd, &pci_bus, &pci_devfn))
1310 pcidev = pci_find_slot(pci_bus, pci_devfn);
1311 if (pcidev) break;
1312 nd = nd->parent;
1313 }
1314 if (pcidev)
1315 parent = find_parent_pci_resource(pcidev, &node->addrs[index]);
1316 if (!parent) {
1317 printk(KERN_WARNING "release_OF_resource(%s), parent not found\n",
1318 node->name);
1319 return -ENODEV;
1320 }
1321
1322 /* Find us in the parent and its childs */
1323 res = parent->child;
1324 start = node->addrs[index].address;
1325 end = start + node->addrs[index].size - 1;
1326 while (res) {
1327 if (res->start == start && res->end == end &&
1328 (res->flags & IORESOURCE_BUSY))
1329 break;
1330 if (res->start <= start && res->end >= end)
1331 res = res->child;
1332 else
1333 res = res->sibling;
1334 }
1335 if (!res)
1336 return -ENODEV;
1337
1338 if (res->name) {
1339 kfree(res->name);
1340 res->name = NULL;
1341 }
1342 release_resource(res);
1343 kfree(res);
1344
1345 return 0;
1346}
1347
1348#if 0
1349void __openfirmware
1350print_properties(struct device_node *np)
1351{
1352 struct property *pp;
1353 char *cp;
1354 int i, n;
1355
1356 for (pp = np->properties; pp != 0; pp = pp->next) {
1357 printk(KERN_INFO "%s", pp->name);
1358 for (i = strlen(pp->name); i < 16; ++i)
1359 printk(" ");
1360 cp = (char *) pp->value;
1361 for (i = pp->length; i > 0; --i, ++cp)
1362 if ((i > 1 && (*cp < 0x20 || *cp > 0x7e))
1363 || (i == 1 && *cp != 0))
1364 break;
1365 if (i == 0 && pp->length > 1) {
1366 /* looks like a string */
1367 printk(" %s\n", (char *) pp->value);
1368 } else {
1369 /* dump it in hex */
1370 n = pp->length;
1371 if (n > 64)
1372 n = 64;
1373 if (pp->length % 4 == 0) {
1374 unsigned int *p = (unsigned int *) pp->value;
1375
1376 n /= 4;
1377 for (i = 0; i < n; ++i) {
1378 if (i != 0 && (i % 4) == 0)
1379 printk("\n ");
1380 printk(" %08x", *p++);
1381 }
1382 } else {
1383 unsigned char *bp = pp->value;
1384
1385 for (i = 0; i < n; ++i) {
1386 if (i != 0 && (i % 16) == 0)
1387 printk("\n ");
1388 printk(" %02x", *bp++);
1389 }
1390 }
1391 printk("\n");
1392 if (pp->length > 64)
1393 printk(" ... (length = %d)\n",
1394 pp->length);
1395 }
1396 }
1397}
1398#endif
1399
1400static DEFINE_SPINLOCK(rtas_lock);
1401
1402/* this can be called after setup -- Cort */
1403int __openfirmware
1404call_rtas(const char *service, int nargs, int nret,
1405 unsigned long *outputs, ...)
1406{
1407 va_list list;
1408 int i;
1409 unsigned long s;
1410 struct device_node *rtas;
1411 int *tokp;
1412 union {
1413 unsigned long words[16];
1414 double align;
1415 } u;
1416
1417 rtas = find_devices("rtas");
1418 if (rtas == NULL)
1419 return -1;
1420 tokp = (int *) get_property(rtas, service, NULL);
1421 if (tokp == NULL) {
1422 printk(KERN_ERR "No RTAS service called %s\n", service);
1423 return -1;
1424 }
1425 u.words[0] = *tokp;
1426 u.words[1] = nargs;
1427 u.words[2] = nret;
1428 va_start(list, outputs);
1429 for (i = 0; i < nargs; ++i)
1430 u.words[i+3] = va_arg(list, unsigned long);
1431 va_end(list);
1432
1433 /*
1434 * RTAS doesn't use floating point.
1435 * Or at least, according to the CHRP spec we enter RTAS
1436 * with FP disabled, and it doesn't change the FP registers.
1437 * -- paulus.
1438 */
1439 spin_lock_irqsave(&rtas_lock, s);
1440 enter_rtas((void *)__pa(&u));
1441 spin_unlock_irqrestore(&rtas_lock, s);
1442
1443 if (nret > 1 && outputs != NULL)
1444 for (i = 0; i < nret-1; ++i)
1445 outputs[i] = u.words[i+nargs+4];
1446 return u.words[nargs+3];
1447}