]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/sparc/kernel/prom.c
Consolidate of_get_next_child
[karo-tx-linux.git] / arch / sparc / 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 sparc32 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 extern rwlock_t devtree_lock;   /* temporary while merging */
31
32 struct device_node *of_find_node_by_path(const char *path)
33 {
34         struct device_node *np = allnodes;
35
36         for (; np != 0; np = np->allnext) {
37                 if (np->full_name != 0 && strcmp(np->full_name, path) == 0)
38                         break;
39         }
40
41         return np;
42 }
43 EXPORT_SYMBOL(of_find_node_by_path);
44
45 struct device_node *of_find_node_by_phandle(phandle handle)
46 {
47         struct device_node *np;
48
49         for (np = allnodes; np != 0; np = np->allnext)
50                 if (np->node == handle)
51                         break;
52
53         return np;
54 }
55 EXPORT_SYMBOL(of_find_node_by_phandle);
56
57 struct device_node *of_find_node_by_name(struct device_node *from,
58         const char *name)
59 {
60         struct device_node *np;
61
62         np = from ? from->allnext : allnodes;
63         for (; np != NULL; np = np->allnext)
64                 if (np->name != NULL && strcmp(np->name, name) == 0)
65                         break;
66
67         return np;
68 }
69 EXPORT_SYMBOL(of_find_node_by_name);
70
71 struct device_node *of_find_node_by_type(struct device_node *from,
72         const char *type)
73 {
74         struct device_node *np;
75
76         np = from ? from->allnext : allnodes;
77         for (; np != 0; np = np->allnext)
78                 if (np->type != 0 && strcmp(np->type, type) == 0)
79                         break;
80
81         return np;
82 }
83 EXPORT_SYMBOL(of_find_node_by_type);
84
85 struct device_node *of_find_compatible_node(struct device_node *from,
86         const char *type, const char *compatible)
87 {
88         struct device_node *np;
89
90         np = from ? from->allnext : allnodes;
91         for (; np != 0; np = np->allnext) {
92                 if (type != NULL
93                     && !(np->type != 0 && strcmp(np->type, type) == 0))
94                         continue;
95                 if (of_device_is_compatible(np, compatible))
96                         break;
97         }
98
99         return np;
100 }
101 EXPORT_SYMBOL(of_find_compatible_node);
102
103 int of_getintprop_default(struct device_node *np, const char *name, int def)
104 {
105         struct property *prop;
106         int len;
107
108         prop = of_find_property(np, name, &len);
109         if (!prop || len != 4)
110                 return def;
111
112         return *(int *) prop->value;
113 }
114 EXPORT_SYMBOL(of_getintprop_default);
115
116 int of_set_property(struct device_node *dp, const char *name, void *val, int len)
117 {
118         struct property **prevp;
119         void *new_val;
120         int err;
121
122         new_val = kmalloc(len, GFP_KERNEL);
123         if (!new_val)
124                 return -ENOMEM;
125
126         memcpy(new_val, val, len);
127
128         err = -ENODEV;
129
130         write_lock(&devtree_lock);
131         prevp = &dp->properties;
132         while (*prevp) {
133                 struct property *prop = *prevp;
134
135                 if (!strcasecmp(prop->name, name)) {
136                         void *old_val = prop->value;
137                         int ret;
138
139                         ret = prom_setprop(dp->node, (char *) name, val, len);
140                         err = -EINVAL;
141                         if (ret >= 0) {
142                                 prop->value = new_val;
143                                 prop->length = len;
144
145                                 if (OF_IS_DYNAMIC(prop))
146                                         kfree(old_val);
147
148                                 OF_MARK_DYNAMIC(prop);
149
150                                 err = 0;
151                         }
152                         break;
153                 }
154                 prevp = &(*prevp)->next;
155         }
156         write_unlock(&devtree_lock);
157
158         /* XXX Upate procfs if necessary... */
159
160         return err;
161 }
162 EXPORT_SYMBOL(of_set_property);
163
164 static unsigned int prom_early_allocated;
165
166 static void * __init prom_early_alloc(unsigned long size)
167 {
168         void *ret;
169
170         ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
171         if (ret != NULL)
172                 memset(ret, 0, size);
173
174         prom_early_allocated += size;
175
176         return ret;
177 }
178
179 static int is_root_node(const struct device_node *dp)
180 {
181         if (!dp)
182                 return 0;
183
184         return (dp->parent == NULL);
185 }
186
187 /* The following routines deal with the black magic of fully naming a
188  * node.
189  *
190  * Certain well known named nodes are just the simple name string.
191  *
192  * Actual devices have an address specifier appended to the base name
193  * string, like this "foo@addr".  The "addr" can be in any number of
194  * formats, and the platform plus the type of the node determine the
195  * format and how it is constructed.
196  *
197  * For children of the ROOT node, the naming convention is fixed and
198  * determined by whether this is a sun4u or sun4v system.
199  *
200  * For children of other nodes, it is bus type specific.  So
201  * we walk up the tree until we discover a "device_type" property
202  * we recognize and we go from there.
203  */
204 static void __init sparc32_path_component(struct device_node *dp, char *tmp_buf)
205 {
206         struct linux_prom_registers *regs;
207         struct property *rprop;
208
209         rprop = of_find_property(dp, "reg", NULL);
210         if (!rprop)
211                 return;
212
213         regs = rprop->value;
214         sprintf(tmp_buf, "%s@%x,%x",
215                 dp->name,
216                 regs->which_io, regs->phys_addr);
217 }
218
219 /* "name@slot,offset"  */
220 static void __init sbus_path_component(struct device_node *dp, char *tmp_buf)
221 {
222         struct linux_prom_registers *regs;
223         struct property *prop;
224
225         prop = of_find_property(dp, "reg", NULL);
226         if (!prop)
227                 return;
228
229         regs = prop->value;
230         sprintf(tmp_buf, "%s@%x,%x",
231                 dp->name,
232                 regs->which_io,
233                 regs->phys_addr);
234 }
235
236 /* "name@devnum[,func]" */
237 static void __init pci_path_component(struct device_node *dp, char *tmp_buf)
238 {
239         struct linux_prom_pci_registers *regs;
240         struct property *prop;
241         unsigned int devfn;
242
243         prop = of_find_property(dp, "reg", NULL);
244         if (!prop)
245                 return;
246
247         regs = prop->value;
248         devfn = (regs->phys_hi >> 8) & 0xff;
249         if (devfn & 0x07) {
250                 sprintf(tmp_buf, "%s@%x,%x",
251                         dp->name,
252                         devfn >> 3,
253                         devfn & 0x07);
254         } else {
255                 sprintf(tmp_buf, "%s@%x",
256                         dp->name,
257                         devfn >> 3);
258         }
259 }
260
261 /* "name@addrhi,addrlo" */
262 static void __init ebus_path_component(struct device_node *dp, char *tmp_buf)
263 {
264         struct linux_prom_registers *regs;
265         struct property *prop;
266
267         prop = of_find_property(dp, "reg", NULL);
268         if (!prop)
269                 return;
270
271         regs = prop->value;
272
273         sprintf(tmp_buf, "%s@%x,%x",
274                 dp->name,
275                 regs->which_io, regs->phys_addr);
276 }
277
278 static void __init __build_path_component(struct device_node *dp, char *tmp_buf)
279 {
280         struct device_node *parent = dp->parent;
281
282         if (parent != NULL) {
283                 if (!strcmp(parent->type, "pci") ||
284                     !strcmp(parent->type, "pciex"))
285                         return pci_path_component(dp, tmp_buf);
286                 if (!strcmp(parent->type, "sbus"))
287                         return sbus_path_component(dp, tmp_buf);
288                 if (!strcmp(parent->type, "ebus"))
289                         return ebus_path_component(dp, tmp_buf);
290
291                 /* "isa" is handled with platform naming */
292         }
293
294         /* Use platform naming convention.  */
295         return sparc32_path_component(dp, tmp_buf);
296 }
297
298 static char * __init build_path_component(struct device_node *dp)
299 {
300         char tmp_buf[64], *n;
301
302         tmp_buf[0] = '\0';
303         __build_path_component(dp, tmp_buf);
304         if (tmp_buf[0] == '\0')
305                 strcpy(tmp_buf, dp->name);
306
307         n = prom_early_alloc(strlen(tmp_buf) + 1);
308         strcpy(n, tmp_buf);
309
310         return n;
311 }
312
313 static char * __init build_full_name(struct device_node *dp)
314 {
315         int len, ourlen, plen;
316         char *n;
317
318         plen = strlen(dp->parent->full_name);
319         ourlen = strlen(dp->path_component_name);
320         len = ourlen + plen + 2;
321
322         n = prom_early_alloc(len);
323         strcpy(n, dp->parent->full_name);
324         if (!is_root_node(dp->parent)) {
325                 strcpy(n + plen, "/");
326                 plen++;
327         }
328         strcpy(n + plen, dp->path_component_name);
329
330         return n;
331 }
332
333 static unsigned int unique_id;
334
335 static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len)
336 {
337         static struct property *tmp = NULL;
338         struct property *p;
339         int len;
340         const char *name;
341
342         if (tmp) {
343                 p = tmp;
344                 memset(p, 0, sizeof(*p) + 32);
345                 tmp = NULL;
346         } else {
347                 p = prom_early_alloc(sizeof(struct property) + 32);
348                 p->unique_id = unique_id++;
349         }
350
351         p->name = (char *) (p + 1);
352         if (special_name) {
353                 strcpy(p->name, special_name);
354                 p->length = special_len;
355                 p->value = prom_early_alloc(special_len);
356                 memcpy(p->value, special_val, special_len);
357         } else {
358                 if (prev == NULL) {
359                         name = prom_firstprop(node, NULL);
360                 } else {
361                         name = prom_nextprop(node, prev, NULL);
362                 }
363                 if (strlen(name) == 0) {
364                         tmp = p;
365                         return NULL;
366                 }
367                 strcpy(p->name, name);
368                 p->length = prom_getproplen(node, p->name);
369                 if (p->length <= 0) {
370                         p->length = 0;
371                 } else {
372                         p->value = prom_early_alloc(p->length + 1);
373                         len = prom_getproperty(node, p->name, p->value,
374                                                p->length);
375                         if (len <= 0)
376                                 p->length = 0;
377                         ((unsigned char *)p->value)[p->length] = '\0';
378                 }
379         }
380         return p;
381 }
382
383 static struct property * __init build_prop_list(phandle node)
384 {
385         struct property *head, *tail;
386
387         head = tail = build_one_prop(node, NULL,
388                                      ".node", &node, sizeof(node));
389
390         tail->next = build_one_prop(node, NULL, NULL, NULL, 0);
391         tail = tail->next;
392         while(tail) {
393                 tail->next = build_one_prop(node, tail->name,
394                                             NULL, NULL, 0);
395                 tail = tail->next;
396         }
397
398         return head;
399 }
400
401 static char * __init get_one_property(phandle node, char *name)
402 {
403         char *buf = "<NULL>";
404         int len;
405
406         len = prom_getproplen(node, name);
407         if (len > 0) {
408                 buf = prom_early_alloc(len);
409                 len = prom_getproperty(node, name, buf, len);
410         }
411
412         return buf;
413 }
414
415 static struct device_node * __init create_node(phandle node)
416 {
417         struct device_node *dp;
418
419         if (!node)
420                 return NULL;
421
422         dp = prom_early_alloc(sizeof(*dp));
423         dp->unique_id = unique_id++;
424
425         kref_init(&dp->kref);
426
427         dp->name = get_one_property(node, "name");
428         dp->type = get_one_property(node, "device_type");
429         dp->node = node;
430
431         /* Build interrupts later... */
432
433         dp->properties = build_prop_list(node);
434
435         return dp;
436 }
437
438 static struct device_node * __init build_tree(struct device_node *parent, phandle node, struct device_node ***nextp)
439 {
440         struct device_node *dp;
441
442         dp = create_node(node);
443         if (dp) {
444                 *(*nextp) = dp;
445                 *nextp = &dp->allnext;
446
447                 dp->parent = parent;
448                 dp->path_component_name = build_path_component(dp);
449                 dp->full_name = build_full_name(dp);
450
451                 dp->child = build_tree(dp, prom_getchild(node), nextp);
452
453                 dp->sibling = build_tree(parent, prom_getsibling(node), nextp);
454         }
455
456         return dp;
457 }
458
459 void __init prom_build_devicetree(void)
460 {
461         struct device_node **nextp;
462
463         allnodes = create_node(prom_root_node);
464         allnodes->path_component_name = "";
465         allnodes->full_name = "/";
466
467         nextp = &allnodes->allnext;
468         allnodes->child = build_tree(allnodes,
469                                      prom_getchild(allnodes->node),
470                                      &nextp);
471         printk("PROM: Built device tree with %u bytes of memory.\n",
472                prom_early_allocated);
473 }