xref: /openbmc/linux/arch/sparc/kernel/prom_common.c (revision fd589a8f)
1 /* prom_common.c: OF device tree support common code.
2  *
3  * Paul Mackerras	August 1996.
4  * Copyright (C) 1996-2005 Paul Mackerras.
5  *
6  *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
7  *    {engebret|bergner}@us.ibm.com
8  *
9  *  Adapted for sparc by David S. Miller davem@davemloft.net
10  *
11  *      This program is free software; you can redistribute it and/or
12  *      modify it under the terms of the GNU General Public License
13  *      as published by the Free Software Foundation; either version
14  *      2 of the License, or (at your option) any later version.
15  */
16 
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/errno.h>
20 #include <linux/mutex.h>
21 #include <linux/slab.h>
22 #include <linux/of.h>
23 #include <asm/prom.h>
24 #include <asm/oplib.h>
25 #include <asm/leon.h>
26 
27 #include "prom.h"
28 
29 void (*prom_build_more)(struct device_node *dp, struct device_node ***nextp);
30 
31 struct device_node *of_console_device;
32 EXPORT_SYMBOL(of_console_device);
33 
34 char *of_console_path;
35 EXPORT_SYMBOL(of_console_path);
36 
37 char *of_console_options;
38 EXPORT_SYMBOL(of_console_options);
39 
40 struct device_node *of_find_node_by_phandle(phandle handle)
41 {
42 	struct device_node *np;
43 
44 	for (np = allnodes; np; np = np->allnext)
45 		if (np->node == handle)
46 			break;
47 
48 	return np;
49 }
50 EXPORT_SYMBOL(of_find_node_by_phandle);
51 
52 int of_getintprop_default(struct device_node *np, const char *name, int def)
53 {
54 	struct property *prop;
55 	int len;
56 
57 	prop = of_find_property(np, name, &len);
58 	if (!prop || len != 4)
59 		return def;
60 
61 	return *(int *) prop->value;
62 }
63 EXPORT_SYMBOL(of_getintprop_default);
64 
65 DEFINE_MUTEX(of_set_property_mutex);
66 EXPORT_SYMBOL(of_set_property_mutex);
67 
68 int of_set_property(struct device_node *dp, const char *name, void *val, int len)
69 {
70 	struct property **prevp;
71 	void *new_val;
72 	int err;
73 
74 	new_val = kmalloc(len, GFP_KERNEL);
75 	if (!new_val)
76 		return -ENOMEM;
77 
78 	memcpy(new_val, val, len);
79 
80 	err = -ENODEV;
81 
82 	write_lock(&devtree_lock);
83 	prevp = &dp->properties;
84 	while (*prevp) {
85 		struct property *prop = *prevp;
86 
87 		if (!strcasecmp(prop->name, name)) {
88 			void *old_val = prop->value;
89 			int ret;
90 
91 			mutex_lock(&of_set_property_mutex);
92 			ret = prom_setprop(dp->node, name, val, len);
93 			mutex_unlock(&of_set_property_mutex);
94 
95 			err = -EINVAL;
96 			if (ret >= 0) {
97 				prop->value = new_val;
98 				prop->length = len;
99 
100 				if (OF_IS_DYNAMIC(prop))
101 					kfree(old_val);
102 
103 				OF_MARK_DYNAMIC(prop);
104 
105 				err = 0;
106 			}
107 			break;
108 		}
109 		prevp = &(*prevp)->next;
110 	}
111 	write_unlock(&devtree_lock);
112 
113 	/* XXX Upate procfs if necessary... */
114 
115 	return err;
116 }
117 EXPORT_SYMBOL(of_set_property);
118 
119 int of_find_in_proplist(const char *list, const char *match, int len)
120 {
121 	while (len > 0) {
122 		int l;
123 
124 		if (!strcmp(list, match))
125 			return 1;
126 		l = strlen(list) + 1;
127 		list += l;
128 		len -= l;
129 	}
130 	return 0;
131 }
132 EXPORT_SYMBOL(of_find_in_proplist);
133 
134 unsigned int prom_unique_id;
135 
136 static struct property * __init build_one_prop(phandle node, char *prev,
137 					       char *special_name,
138 					       void *special_val,
139 					       int special_len)
140 {
141 	static struct property *tmp = NULL;
142 	struct property *p;
143 	const char *name;
144 
145 	if (tmp) {
146 		p = tmp;
147 		memset(p, 0, sizeof(*p) + 32);
148 		tmp = NULL;
149 	} else {
150 		p = prom_early_alloc(sizeof(struct property) + 32);
151 		p->unique_id = prom_unique_id++;
152 	}
153 
154 	p->name = (char *) (p + 1);
155 	if (special_name) {
156 		strcpy(p->name, special_name);
157 		p->length = special_len;
158 		p->value = prom_early_alloc(special_len);
159 		memcpy(p->value, special_val, special_len);
160 	} else {
161 		if (prev == NULL) {
162 			name = prom_firstprop(node, p->name);
163 		} else {
164 			name = prom_nextprop(node, prev, p->name);
165 		}
166 
167 		if (!name || strlen(name) == 0) {
168 			tmp = p;
169 			return NULL;
170 		}
171 #ifdef CONFIG_SPARC32
172 		strcpy(p->name, name);
173 #endif
174 		p->length = prom_getproplen(node, p->name);
175 		if (p->length <= 0) {
176 			p->length = 0;
177 		} else {
178 			int len;
179 
180 			p->value = prom_early_alloc(p->length + 1);
181 			len = prom_getproperty(node, p->name, p->value,
182 					       p->length);
183 			if (len <= 0)
184 				p->length = 0;
185 			((unsigned char *)p->value)[p->length] = '\0';
186 		}
187 	}
188 	return p;
189 }
190 
191 static struct property * __init build_prop_list(phandle node)
192 {
193 	struct property *head, *tail;
194 
195 	head = tail = build_one_prop(node, NULL,
196 				     ".node", &node, sizeof(node));
197 
198 	tail->next = build_one_prop(node, NULL, NULL, NULL, 0);
199 	tail = tail->next;
200 	while(tail) {
201 		tail->next = build_one_prop(node, tail->name,
202 					    NULL, NULL, 0);
203 		tail = tail->next;
204 	}
205 
206 	return head;
207 }
208 
209 static char * __init get_one_property(phandle node, const char *name)
210 {
211 	char *buf = "<NULL>";
212 	int len;
213 
214 	len = prom_getproplen(node, name);
215 	if (len > 0) {
216 		buf = prom_early_alloc(len);
217 		len = prom_getproperty(node, name, buf, len);
218 	}
219 
220 	return buf;
221 }
222 
223 static struct device_node * __init prom_create_node(phandle node,
224 						    struct device_node *parent)
225 {
226 	struct device_node *dp;
227 
228 	if (!node)
229 		return NULL;
230 
231 	dp = prom_early_alloc(sizeof(*dp));
232 	dp->unique_id = prom_unique_id++;
233 	dp->parent = parent;
234 
235 	kref_init(&dp->kref);
236 
237 	dp->name = get_one_property(node, "name");
238 	dp->type = get_one_property(node, "device_type");
239 	dp->node = node;
240 
241 	dp->properties = build_prop_list(node);
242 
243 	irq_trans_init(dp);
244 
245 	return dp;
246 }
247 
248 char * __init build_full_name(struct device_node *dp)
249 {
250 	int len, ourlen, plen;
251 	char *n;
252 
253 	plen = strlen(dp->parent->full_name);
254 	ourlen = strlen(dp->path_component_name);
255 	len = ourlen + plen + 2;
256 
257 	n = prom_early_alloc(len);
258 	strcpy(n, dp->parent->full_name);
259 	if (!is_root_node(dp->parent)) {
260 		strcpy(n + plen, "/");
261 		plen++;
262 	}
263 	strcpy(n + plen, dp->path_component_name);
264 
265 	return n;
266 }
267 
268 static struct device_node * __init prom_build_tree(struct device_node *parent,
269 						   phandle node,
270 						   struct device_node ***nextp)
271 {
272 	struct device_node *ret = NULL, *prev_sibling = NULL;
273 	struct device_node *dp;
274 
275 	while (1) {
276 		dp = prom_create_node(node, parent);
277 		if (!dp)
278 			break;
279 
280 		if (prev_sibling)
281 			prev_sibling->sibling = dp;
282 
283 		if (!ret)
284 			ret = dp;
285 		prev_sibling = dp;
286 
287 		*(*nextp) = dp;
288 		*nextp = &dp->allnext;
289 
290 		dp->path_component_name = build_path_component(dp);
291 		dp->full_name = build_full_name(dp);
292 
293 		dp->child = prom_build_tree(dp, prom_getchild(node), nextp);
294 
295 		if (prom_build_more)
296 			prom_build_more(dp, nextp);
297 
298 		node = prom_getsibling(node);
299 	}
300 
301 	return ret;
302 }
303 
304 unsigned int prom_early_allocated __initdata;
305 
306 void __init prom_build_devicetree(void)
307 {
308 	struct device_node **nextp;
309 
310 	allnodes = prom_create_node(prom_root_node, NULL);
311 	allnodes->path_component_name = "";
312 	allnodes->full_name = "/";
313 
314 	nextp = &allnodes->allnext;
315 	allnodes->child = prom_build_tree(allnodes,
316 					  prom_getchild(allnodes->node),
317 					  &nextp);
318 	of_console_init();
319 
320 	printk("PROM: Built device tree with %u bytes of memory.\n",
321 	       prom_early_allocated);
322 }
323