xref: /openbmc/linux/arch/sparc/kernel/prom_common.c (revision dfa76060be85dd48d3803bc26f6a6d2e93e812f0)
1*dfa76060SDavid S. Miller /* prom_common.c: OF device tree support common code.
2*dfa76060SDavid S. Miller  *
3*dfa76060SDavid S. Miller  * Paul Mackerras	August 1996.
4*dfa76060SDavid S. Miller  * Copyright (C) 1996-2005 Paul Mackerras.
5*dfa76060SDavid S. Miller  *
6*dfa76060SDavid S. Miller  *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
7*dfa76060SDavid S. Miller  *    {engebret|bergner}@us.ibm.com
8*dfa76060SDavid S. Miller  *
9*dfa76060SDavid S. Miller  *  Adapted for sparc by David S. Miller davem@davemloft.net
10*dfa76060SDavid S. Miller  *
11*dfa76060SDavid S. Miller  *      This program is free software; you can redistribute it and/or
12*dfa76060SDavid S. Miller  *      modify it under the terms of the GNU General Public License
13*dfa76060SDavid S. Miller  *      as published by the Free Software Foundation; either version
14*dfa76060SDavid S. Miller  *      2 of the License, or (at your option) any later version.
15*dfa76060SDavid S. Miller  */
16*dfa76060SDavid S. Miller 
17*dfa76060SDavid S. Miller #include <linux/kernel.h>
18*dfa76060SDavid S. Miller #include <linux/module.h>
19*dfa76060SDavid S. Miller #include <linux/errno.h>
20*dfa76060SDavid S. Miller #include <linux/mutex.h>
21*dfa76060SDavid S. Miller #include <linux/slab.h>
22*dfa76060SDavid S. Miller #include <linux/of.h>
23*dfa76060SDavid S. Miller #include <asm/prom.h>
24*dfa76060SDavid S. Miller #include <asm/oplib.h>
25*dfa76060SDavid S. Miller 
26*dfa76060SDavid S. Miller #include "prom.h"
27*dfa76060SDavid S. Miller 
28*dfa76060SDavid S. Miller struct device_node *of_find_node_by_phandle(phandle handle)
29*dfa76060SDavid S. Miller {
30*dfa76060SDavid S. Miller 	struct device_node *np;
31*dfa76060SDavid S. Miller 
32*dfa76060SDavid S. Miller 	for (np = allnodes; np; np = np->allnext)
33*dfa76060SDavid S. Miller 		if (np->node == handle)
34*dfa76060SDavid S. Miller 			break;
35*dfa76060SDavid S. Miller 
36*dfa76060SDavid S. Miller 	return np;
37*dfa76060SDavid S. Miller }
38*dfa76060SDavid S. Miller EXPORT_SYMBOL(of_find_node_by_phandle);
39*dfa76060SDavid S. Miller 
40*dfa76060SDavid S. Miller int of_getintprop_default(struct device_node *np, const char *name, int def)
41*dfa76060SDavid S. Miller {
42*dfa76060SDavid S. Miller 	struct property *prop;
43*dfa76060SDavid S. Miller 	int len;
44*dfa76060SDavid S. Miller 
45*dfa76060SDavid S. Miller 	prop = of_find_property(np, name, &len);
46*dfa76060SDavid S. Miller 	if (!prop || len != 4)
47*dfa76060SDavid S. Miller 		return def;
48*dfa76060SDavid S. Miller 
49*dfa76060SDavid S. Miller 	return *(int *) prop->value;
50*dfa76060SDavid S. Miller }
51*dfa76060SDavid S. Miller EXPORT_SYMBOL(of_getintprop_default);
52*dfa76060SDavid S. Miller 
53*dfa76060SDavid S. Miller DEFINE_MUTEX(of_set_property_mutex);
54*dfa76060SDavid S. Miller EXPORT_SYMBOL(of_set_property_mutex);
55*dfa76060SDavid S. Miller 
56*dfa76060SDavid S. Miller int of_set_property(struct device_node *dp, const char *name, void *val, int len)
57*dfa76060SDavid S. Miller {
58*dfa76060SDavid S. Miller 	struct property **prevp;
59*dfa76060SDavid S. Miller 	void *new_val;
60*dfa76060SDavid S. Miller 	int err;
61*dfa76060SDavid S. Miller 
62*dfa76060SDavid S. Miller 	new_val = kmalloc(len, GFP_KERNEL);
63*dfa76060SDavid S. Miller 	if (!new_val)
64*dfa76060SDavid S. Miller 		return -ENOMEM;
65*dfa76060SDavid S. Miller 
66*dfa76060SDavid S. Miller 	memcpy(new_val, val, len);
67*dfa76060SDavid S. Miller 
68*dfa76060SDavid S. Miller 	err = -ENODEV;
69*dfa76060SDavid S. Miller 
70*dfa76060SDavid S. Miller 	write_lock(&devtree_lock);
71*dfa76060SDavid S. Miller 	prevp = &dp->properties;
72*dfa76060SDavid S. Miller 	while (*prevp) {
73*dfa76060SDavid S. Miller 		struct property *prop = *prevp;
74*dfa76060SDavid S. Miller 
75*dfa76060SDavid S. Miller 		if (!strcasecmp(prop->name, name)) {
76*dfa76060SDavid S. Miller 			void *old_val = prop->value;
77*dfa76060SDavid S. Miller 			int ret;
78*dfa76060SDavid S. Miller 
79*dfa76060SDavid S. Miller 			mutex_lock(&of_set_property_mutex);
80*dfa76060SDavid S. Miller 			ret = prom_setprop(dp->node, name, val, len);
81*dfa76060SDavid S. Miller 			mutex_unlock(&of_set_property_mutex);
82*dfa76060SDavid S. Miller 
83*dfa76060SDavid S. Miller 			err = -EINVAL;
84*dfa76060SDavid S. Miller 			if (ret >= 0) {
85*dfa76060SDavid S. Miller 				prop->value = new_val;
86*dfa76060SDavid S. Miller 				prop->length = len;
87*dfa76060SDavid S. Miller 
88*dfa76060SDavid S. Miller 				if (OF_IS_DYNAMIC(prop))
89*dfa76060SDavid S. Miller 					kfree(old_val);
90*dfa76060SDavid S. Miller 
91*dfa76060SDavid S. Miller 				OF_MARK_DYNAMIC(prop);
92*dfa76060SDavid S. Miller 
93*dfa76060SDavid S. Miller 				err = 0;
94*dfa76060SDavid S. Miller 			}
95*dfa76060SDavid S. Miller 			break;
96*dfa76060SDavid S. Miller 		}
97*dfa76060SDavid S. Miller 		prevp = &(*prevp)->next;
98*dfa76060SDavid S. Miller 	}
99*dfa76060SDavid S. Miller 	write_unlock(&devtree_lock);
100*dfa76060SDavid S. Miller 
101*dfa76060SDavid S. Miller 	/* XXX Upate procfs if necessary... */
102*dfa76060SDavid S. Miller 
103*dfa76060SDavid S. Miller 	return err;
104*dfa76060SDavid S. Miller }
105*dfa76060SDavid S. Miller EXPORT_SYMBOL(of_set_property);
106*dfa76060SDavid S. Miller 
107*dfa76060SDavid S. Miller int of_find_in_proplist(const char *list, const char *match, int len)
108*dfa76060SDavid S. Miller {
109*dfa76060SDavid S. Miller 	while (len > 0) {
110*dfa76060SDavid S. Miller 		int l;
111*dfa76060SDavid S. Miller 
112*dfa76060SDavid S. Miller 		if (!strcmp(list, match))
113*dfa76060SDavid S. Miller 			return 1;
114*dfa76060SDavid S. Miller 		l = strlen(list) + 1;
115*dfa76060SDavid S. Miller 		list += l;
116*dfa76060SDavid S. Miller 		len -= l;
117*dfa76060SDavid S. Miller 	}
118*dfa76060SDavid S. Miller 	return 0;
119*dfa76060SDavid S. Miller }
120*dfa76060SDavid S. Miller EXPORT_SYMBOL(of_find_in_proplist);
121*dfa76060SDavid S. Miller 
122