]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/sparc64/kernel/prom.c
[SPARC64]: Use in-kernel PROM tree for EBUS and ISA.
[linux-2.6-omap-h63xx.git] / arch / sparc64 / kernel / prom.c
1 /*
2  * Procedures for creating, accessing and interpreting the device tree.
3  *
4  * Paul Mackerras       August 1996.
5  * Copyright (C) 1996-2005 Paul Mackerras.
6  * 
7  *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
8  *    {engebret|bergner}@us.ibm.com 
9  *
10  *  Adapted for sparc64 by David S. Miller davem@davemloft.net
11  *
12  *      This program is free software; you can redistribute it and/or
13  *      modify it under the terms of the GNU General Public License
14  *      as published by the Free Software Foundation; either version
15  *      2 of the License, or (at your option) any later version.
16  */
17
18 #include <linux/kernel.h>
19 #include <linux/types.h>
20 #include <linux/string.h>
21 #include <linux/mm.h>
22 #include <linux/bootmem.h>
23 #include <linux/module.h>
24
25 #include <asm/prom.h>
26 #include <asm/oplib.h>
27
28 static struct device_node *allnodes;
29
30 struct device_node *of_get_parent(const struct device_node *node)
31 {
32         struct device_node *np;
33
34         if (!node)
35                 return NULL;
36
37         np = node->parent;
38
39         return np;
40 }
41
42 struct device_node *of_get_next_child(const struct device_node *node,
43         struct device_node *prev)
44 {
45         struct device_node *next;
46
47         next = prev ? prev->sibling : node->child;
48         for (; next != 0; next = next->sibling) {
49                 break;
50         }
51
52         return next;
53 }
54
55 struct device_node *of_find_node_by_path(const char *path)
56 {
57         struct device_node *np = allnodes;
58
59         for (; np != 0; np = np->allnext) {
60                 if (np->full_name != 0 && strcmp(np->full_name, path) == 0)
61                         break;
62         }
63
64         return np;
65 }
66 EXPORT_SYMBOL(of_find_node_by_path);
67
68 struct device_node *of_find_node_by_phandle(phandle handle)
69 {
70         struct device_node *np;
71
72         for (np = allnodes; np != 0; np = np->allnext)
73                 if (np->node == handle)
74                         break;
75
76         return np;
77 }
78
79 struct device_node *of_find_node_by_name(struct device_node *from,
80         const char *name)
81 {
82         struct device_node *np;
83
84         np = from ? from->allnext : allnodes;
85         for (; np != NULL; np = np->allnext)
86                 if (np->name != NULL && strcmp(np->name, name) == 0)
87                         break;
88
89         return np;
90 }
91
92 struct device_node *of_find_node_by_type(struct device_node *from,
93         const char *type)
94 {
95         struct device_node *np;
96
97         np = from ? from->allnext : allnodes;
98         for (; np != 0; np = np->allnext)
99                 if (np->type != 0 && strcmp(np->type, type) == 0)
100                         break;
101
102         return np;
103 }
104
105 struct property *of_find_property(struct device_node *np, const char *name,
106                                   int *lenp)
107 {
108         struct property *pp;
109
110         for (pp = np->properties; pp != 0; pp = pp->next) {
111                 if (strcmp(pp->name, name) == 0) {
112                         if (lenp != 0)
113                                 *lenp = pp->length;
114                         break;
115                 }
116         }
117         return pp;
118 }
119 EXPORT_SYMBOL(of_find_property);
120
121 /*
122  * Find a property with a given name for a given node
123  * and return the value.
124  */
125 void *of_get_property(struct device_node *np, const char *name, int *lenp)
126 {
127         struct property *pp = of_find_property(np,name,lenp);
128         return pp ? pp->value : NULL;
129 }
130 EXPORT_SYMBOL(of_get_property);
131
132 int of_getintprop_default(struct device_node *np, const char *name, int def)
133 {
134         struct property *prop;
135         int len;
136
137         prop = of_find_property(np, name, &len);
138         if (!prop || len != 4)
139                 return def;
140
141         return *(int *) prop->value;
142 }
143 EXPORT_SYMBOL(of_getintprop_default);
144
145 static unsigned int prom_early_allocated;
146
147 static void * __init prom_early_alloc(unsigned long size)
148 {
149         void *ret;
150
151         ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
152         if (ret != NULL)
153                 memset(ret, 0, size);
154
155         prom_early_allocated += size;
156
157         return ret;
158 }
159
160 static int is_root_node(const struct device_node *dp)
161 {
162         if (!dp)
163                 return 0;
164
165         return (dp->parent == NULL);
166 }
167
168 /* The following routines deal with the black magic of fully naming a
169  * node.
170  *
171  * Certain well known named nodes are just the simple name string.
172  *
173  * Actual devices have an address specifier appended to the base name
174  * string, like this "foo@addr".  The "addr" can be in any number of
175  * formats, and the platform plus the type of the node determine the
176  * format and how it is constructed.
177  *
178  * For children of the ROOT node, the naming convention is fixed and
179  * determined by whether this is a sun4u or sun4v system.
180  *
181  * For children of other nodes, it is bus type specific.  So
182  * we walk up the tree until we discover a "device_type" property
183  * we recognize and we go from there.
184  *
185  * As an example, the boot device on my workstation has a full path:
186  *
187  *      /pci@1e,600000/ide@d/disk@0,0:c
188  */
189 static void __init sun4v_path_component(struct device_node *dp, char *tmp_buf)
190 {
191         struct linux_prom64_registers *regs;
192         struct property *rprop;
193         u32 high_bits, low_bits, type;
194
195         rprop = of_find_property(dp, "reg", NULL);
196         if (!rprop)
197                 return;
198
199         regs = rprop->value;
200         if (!is_root_node(dp->parent)) {
201                 sprintf(tmp_buf, "%s@%x,%x",
202                         dp->name,
203                         (unsigned int) (regs->phys_addr >> 32UL),
204                         (unsigned int) (regs->phys_addr & 0xffffffffUL));
205                 return;
206         }
207
208         type = regs->phys_addr >> 60UL;
209         high_bits = (regs->phys_addr >> 32UL) & 0x0fffffffUL;
210         low_bits = (regs->phys_addr & 0xffffffffUL);
211
212         if (type == 0 || type == 8) {
213                 const char *prefix = (type == 0) ? "m" : "i";
214
215                 if (low_bits)
216                         sprintf(tmp_buf, "%s@%s%x,%x",
217                                 dp->name, prefix,
218                                 high_bits, low_bits);
219                 else
220                         sprintf(tmp_buf, "%s@%s%x",
221                                 dp->name,
222                                 prefix,
223                                 high_bits);
224         } else if (type == 12) {
225                 sprintf(tmp_buf, "%s@%x",
226                         dp->name, high_bits);
227         }
228 }
229
230 static void __init sun4u_path_component(struct device_node *dp, char *tmp_buf)
231 {
232         struct linux_prom64_registers *regs;
233         struct property *prop;
234
235         prop = of_find_property(dp, "reg", NULL);
236         if (!prop)
237                 return;
238
239         regs = prop->value;
240         if (!is_root_node(dp->parent)) {
241                 sprintf(tmp_buf, "%s@%x,%x",
242                         dp->name,
243                         (unsigned int) (regs->phys_addr >> 32UL),
244                         (unsigned int) (regs->phys_addr & 0xffffffffUL));
245                 return;
246         }
247
248         prop = of_find_property(dp, "upa-portid", NULL);
249         if (!prop)
250                 prop = of_find_property(dp, "portid", NULL);
251         if (prop) {
252                 unsigned long mask = 0xffffffffUL;
253
254                 if (tlb_type >= cheetah)
255                         mask = 0x7fffff;
256
257                 sprintf(tmp_buf, "%s@%x,%x",
258                         dp->name,
259                         *(u32 *)prop->value,
260                         (unsigned int) (regs->phys_addr & mask));
261         }
262 }
263
264 /* "name@slot,offset"  */
265 static void __init sbus_path_component(struct device_node *dp, char *tmp_buf)
266 {
267         struct linux_prom_registers *regs;
268         struct property *prop;
269
270         prop = of_find_property(dp, "reg", NULL);
271         if (!prop)
272                 return;
273
274         regs = prop->value;
275         sprintf(tmp_buf, "%s@%x,%x",
276                 dp->name,
277                 regs->which_io,
278                 regs->phys_addr);
279 }
280
281 /* "name@devnum[,func]" */
282 static void __init pci_path_component(struct device_node *dp, char *tmp_buf)
283 {
284         struct linux_prom_pci_registers *regs;
285         struct property *prop;
286         unsigned int devfn;
287
288         prop = of_find_property(dp, "reg", NULL);
289         if (!prop)
290                 return;
291
292         regs = prop->value;
293         devfn = (regs->phys_hi >> 8) & 0xff;
294         if (devfn & 0x07) {
295                 sprintf(tmp_buf, "%s@%x,%x",
296                         dp->name,
297                         devfn >> 3,
298                         devfn & 0x07);
299         } else {
300                 sprintf(tmp_buf, "%s@%x",
301                         dp->name,
302                         devfn >> 3);
303         }
304 }
305
306 /* "name@UPA_PORTID,offset" */
307 static void __init upa_path_component(struct device_node *dp, char *tmp_buf)
308 {
309         struct linux_prom64_registers *regs;
310         struct property *prop;
311
312         prop = of_find_property(dp, "reg", NULL);
313         if (!prop)
314                 return;
315
316         regs = prop->value;
317
318         prop = of_find_property(dp, "upa-portid", NULL);
319         if (!prop)
320                 return;
321
322         sprintf(tmp_buf, "%s@%x,%x",
323                 dp->name,
324                 *(u32 *) prop->value,
325                 (unsigned int) (regs->phys_addr & 0xffffffffUL));
326 }
327
328 /* "name@reg" */
329 static void __init vdev_path_component(struct device_node *dp, char *tmp_buf)
330 {
331         struct property *prop;
332         u32 *regs;
333
334         prop = of_find_property(dp, "reg", NULL);
335         if (!prop)
336                 return;
337
338         regs = prop->value;
339
340         sprintf(tmp_buf, "%s@%x", dp->name, *regs);
341 }
342
343 /* "name@addrhi,addrlo" */
344 static void __init ebus_path_component(struct device_node *dp, char *tmp_buf)
345 {
346         struct linux_prom64_registers *regs;
347         struct property *prop;
348
349         prop = of_find_property(dp, "reg", NULL);
350         if (!prop)
351                 return;
352
353         regs = prop->value;
354
355         sprintf(tmp_buf, "%s@%x,%x",
356                 dp->name,
357                 (unsigned int) (regs->phys_addr >> 32UL),
358                 (unsigned int) (regs->phys_addr & 0xffffffffUL));
359 }
360
361 /* "name@bus,addr" */
362 static void __init i2c_path_component(struct device_node *dp, char *tmp_buf)
363 {
364         struct property *prop;
365         u32 *regs;
366
367         prop = of_find_property(dp, "reg", NULL);
368         if (!prop)
369                 return;
370
371         regs = prop->value;
372
373         /* This actually isn't right... should look at the #address-cells
374          * property of the i2c bus node etc. etc.
375          */
376         sprintf(tmp_buf, "%s@%x,%x",
377                 dp->name, regs[0], regs[1]);
378 }
379
380 /* "name@reg0[,reg1]" */
381 static void __init usb_path_component(struct device_node *dp, char *tmp_buf)
382 {
383         struct property *prop;
384         u32 *regs;
385
386         prop = of_find_property(dp, "reg", NULL);
387         if (!prop)
388                 return;
389
390         regs = prop->value;
391
392         if (prop->length == sizeof(u32) || regs[1] == 1) {
393                 sprintf(tmp_buf, "%s@%x",
394                         dp->name, regs[0]);
395         } else {
396                 sprintf(tmp_buf, "%s@%x,%x",
397                         dp->name, regs[0], regs[1]);
398         }
399 }
400
401 /* "name@reg0reg1[,reg2reg3]" */
402 static void __init ieee1394_path_component(struct device_node *dp, char *tmp_buf)
403 {
404         struct property *prop;
405         u32 *regs;
406
407         prop = of_find_property(dp, "reg", NULL);
408         if (!prop)
409                 return;
410
411         regs = prop->value;
412
413         if (regs[2] || regs[3]) {
414                 sprintf(tmp_buf, "%s@%08x%08x,%04x%08x",
415                         dp->name, regs[0], regs[1], regs[2], regs[3]);
416         } else {
417                 sprintf(tmp_buf, "%s@%08x%08x",
418                         dp->name, regs[0], regs[1]);
419         }
420 }
421
422 static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
423 {
424         struct device_node *parent = dp->parent;
425
426         if (parent != NULL) {
427                 if (!strcmp(parent->type, "pci") ||
428                     !strcmp(parent->type, "pciex"))
429                         return pci_path_component(dp, tmp_buf);
430                 if (!strcmp(parent->type, "sbus"))
431                         return sbus_path_component(dp, tmp_buf);
432                 if (!strcmp(parent->type, "upa"))
433                         return upa_path_component(dp, tmp_buf);
434                 if (!strcmp(parent->type, "ebus"))
435                         return ebus_path_component(dp, tmp_buf);
436                 if (!strcmp(parent->name, "usb") ||
437                     !strcmp(parent->name, "hub"))
438                         return usb_path_component(dp, tmp_buf);
439                 if (!strcmp(parent->type, "i2c"))
440                         return i2c_path_component(dp, tmp_buf);
441                 if (!strcmp(parent->type, "firewire"))
442                         return ieee1394_path_component(dp, tmp_buf);
443                 if (!strcmp(parent->type, "virtual-devices"))
444                         return vdev_path_component(dp, tmp_buf);
445
446                 /* "isa" is handled with platform naming */
447         }
448
449         /* Use platform naming convention.  */
450         if (tlb_type == hypervisor)
451                 return sun4v_path_component(dp, tmp_buf);
452         else
453                 return sun4u_path_component(dp, tmp_buf);
454 }
455
456 static char * __init build_path_component(struct device_node *dp)
457 {
458         char tmp_buf[64], *n;
459
460         tmp_buf[0] = '\0';
461         __build_path_component(dp, tmp_buf);
462         if (tmp_buf[0] == '\0')
463                 strcpy(tmp_buf, dp->name);
464
465         n = prom_early_alloc(strlen(tmp_buf) + 1);
466         strcpy(n, tmp_buf);
467
468         return n;
469 }
470
471 static char * __init build_full_name(struct device_node *dp)
472 {
473         int len, ourlen, plen;
474         char *n;
475
476         plen = strlen(dp->parent->full_name);
477         ourlen = strlen(dp->path_component_name);
478         len = ourlen + plen + 2;
479
480         n = prom_early_alloc(len);
481         strcpy(n, dp->parent->full_name);
482         if (!is_root_node(dp->parent)) {
483                 strcpy(n + plen, "/");
484                 plen++;
485         }
486         strcpy(n + plen, dp->path_component_name);
487
488         return n;
489 }
490
491 static struct property * __init build_one_prop(phandle node, char *prev)
492 {
493         static struct property *tmp = NULL;
494         struct property *p;
495
496         if (tmp) {
497                 p = tmp;
498                 memset(p, 0, sizeof(*p) + 32);
499                 tmp = NULL;
500         } else
501                 p = prom_early_alloc(sizeof(struct property) + 32);
502
503         p->name = (char *) (p + 1);
504         if (prev == NULL) {
505                 prom_firstprop(node, p->name);
506         } else {
507                 prom_nextprop(node, prev, p->name);
508         }
509         if (strlen(p->name) == 0) {
510                 tmp = p;
511                 return NULL;
512         }
513         p->length = prom_getproplen(node, p->name);
514         if (p->length <= 0) {
515                 p->length = 0;
516         } else {
517                 p->value = prom_early_alloc(p->length);
518                 prom_getproperty(node, p->name, p->value, p->length);
519         }
520         return p;
521 }
522
523 static struct property * __init build_prop_list(phandle node)
524 {
525         struct property *head, *tail;
526
527         head = tail = build_one_prop(node, NULL);
528         while(tail) {
529                 tail->next = build_one_prop(node, tail->name);
530                 tail = tail->next;
531         }
532
533         return head;
534 }
535
536 static char * __init get_one_property(phandle node, const char *name)
537 {
538         char *buf = "<NULL>";
539         int len;
540
541         len = prom_getproplen(node, name);
542         if (len > 0) {
543                 buf = prom_early_alloc(len);
544                 prom_getproperty(node, name, buf, len);
545         }
546
547         return buf;
548 }
549
550 static struct device_node * __init create_node(phandle node)
551 {
552         struct device_node *dp;
553
554         if (!node)
555                 return NULL;
556
557         dp = prom_early_alloc(sizeof(*dp));
558
559         kref_init(&dp->kref);
560
561         dp->name = get_one_property(node, "name");
562         dp->type = get_one_property(node, "device_type");
563         dp->node = node;
564
565         /* Build interrupts later... */
566
567         dp->properties = build_prop_list(node);
568
569         return dp;
570 }
571
572 static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp)
573 {
574         struct device_node *dp;
575
576         dp = create_node(node);
577         if (dp) {
578                 *(*nextp) = dp;
579                 *nextp = &dp->allnext;
580
581                 dp->parent = parent;
582                 dp->path_component_name = build_path_component(dp);
583                 dp->full_name = build_full_name(dp);
584
585                 dp->child = build_tree(dp, prom_getchild(node), nextp);
586
587                 dp->sibling = build_tree(parent, prom_getsibling(node), nextp);
588         }
589
590         return dp;
591 }
592
593 void __init prom_build_devicetree(void)
594 {
595         struct device_node **nextp;
596
597         allnodes = create_node(prom_root_node);
598         allnodes->path_component_name = "";
599         allnodes->full_name = "/";
600
601         nextp = &allnodes->allnext;
602         allnodes->child = build_tree(allnodes,
603                                      prom_getchild(allnodes->node),
604                                      &nextp);
605         printk("PROM: Built device tree with %u bytes of memory.\n",
606                prom_early_allocated);
607 }