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