xref: /openbmc/linux/drivers/of/base.c (revision 9a6b2e58)
197e873e5SStephen Rothwell /*
297e873e5SStephen Rothwell  * Procedures for creating, accessing and interpreting the device tree.
397e873e5SStephen Rothwell  *
497e873e5SStephen Rothwell  * Paul Mackerras	August 1996.
597e873e5SStephen Rothwell  * Copyright (C) 1996-2005 Paul Mackerras.
697e873e5SStephen Rothwell  *
797e873e5SStephen Rothwell  *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
897e873e5SStephen Rothwell  *    {engebret|bergner}@us.ibm.com
997e873e5SStephen Rothwell  *
1097e873e5SStephen Rothwell  *  Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net
1197e873e5SStephen Rothwell  *
12e91edcf5SGrant Likely  *  Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and
13e91edcf5SGrant Likely  *  Grant Likely.
1497e873e5SStephen Rothwell  *
1597e873e5SStephen Rothwell  *      This program is free software; you can redistribute it and/or
1697e873e5SStephen Rothwell  *      modify it under the terms of the GNU General Public License
1797e873e5SStephen Rothwell  *      as published by the Free Software Foundation; either version
1897e873e5SStephen Rothwell  *      2 of the License, or (at your option) any later version.
1997e873e5SStephen Rothwell  */
2097e873e5SStephen Rothwell #include <linux/module.h>
2197e873e5SStephen Rothwell #include <linux/of.h>
22581b605aSStephen Rothwell #include <linux/spinlock.h>
235a0e3ad6STejun Heo #include <linux/slab.h>
24a9f2f63aSJeremy Kerr #include <linux/proc_fs.h>
25581b605aSStephen Rothwell 
261ef4d424SStephen Rothwell struct device_node *allnodes;
27fc0bdae4SGrant Likely struct device_node *of_chosen;
281ef4d424SStephen Rothwell 
29581b605aSStephen Rothwell /* use when traversing tree through the allnext, child, sibling,
30581b605aSStephen Rothwell  * or parent members of struct device_node.
31581b605aSStephen Rothwell  */
32581b605aSStephen Rothwell DEFINE_RWLOCK(devtree_lock);
3397e873e5SStephen Rothwell 
3497e873e5SStephen Rothwell int of_n_addr_cells(struct device_node *np)
3597e873e5SStephen Rothwell {
3697e873e5SStephen Rothwell 	const int *ip;
3797e873e5SStephen Rothwell 
3897e873e5SStephen Rothwell 	do {
3997e873e5SStephen Rothwell 		if (np->parent)
4097e873e5SStephen Rothwell 			np = np->parent;
4197e873e5SStephen Rothwell 		ip = of_get_property(np, "#address-cells", NULL);
4297e873e5SStephen Rothwell 		if (ip)
4333714881SJeremy Kerr 			return be32_to_cpup(ip);
4497e873e5SStephen Rothwell 	} while (np->parent);
4597e873e5SStephen Rothwell 	/* No #address-cells property for the root node */
4697e873e5SStephen Rothwell 	return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
4797e873e5SStephen Rothwell }
4897e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_addr_cells);
4997e873e5SStephen Rothwell 
5097e873e5SStephen Rothwell int of_n_size_cells(struct device_node *np)
5197e873e5SStephen Rothwell {
5297e873e5SStephen Rothwell 	const int *ip;
5397e873e5SStephen Rothwell 
5497e873e5SStephen Rothwell 	do {
5597e873e5SStephen Rothwell 		if (np->parent)
5697e873e5SStephen Rothwell 			np = np->parent;
5797e873e5SStephen Rothwell 		ip = of_get_property(np, "#size-cells", NULL);
5897e873e5SStephen Rothwell 		if (ip)
5933714881SJeremy Kerr 			return be32_to_cpup(ip);
6097e873e5SStephen Rothwell 	} while (np->parent);
6197e873e5SStephen Rothwell 	/* No #size-cells property for the root node */
6297e873e5SStephen Rothwell 	return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
6397e873e5SStephen Rothwell }
6497e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_size_cells);
6597e873e5SStephen Rothwell 
66923f7e30SGrant Likely #if !defined(CONFIG_SPARC)   /* SPARC doesn't do ref counting (yet) */
67923f7e30SGrant Likely /**
68923f7e30SGrant Likely  *	of_node_get - Increment refcount of a node
69923f7e30SGrant Likely  *	@node:	Node to inc refcount, NULL is supported to
70923f7e30SGrant Likely  *		simplify writing of callers
71923f7e30SGrant Likely  *
72923f7e30SGrant Likely  *	Returns node.
73923f7e30SGrant Likely  */
74923f7e30SGrant Likely struct device_node *of_node_get(struct device_node *node)
75923f7e30SGrant Likely {
76923f7e30SGrant Likely 	if (node)
77923f7e30SGrant Likely 		kref_get(&node->kref);
78923f7e30SGrant Likely 	return node;
79923f7e30SGrant Likely }
80923f7e30SGrant Likely EXPORT_SYMBOL(of_node_get);
81923f7e30SGrant Likely 
82923f7e30SGrant Likely static inline struct device_node *kref_to_device_node(struct kref *kref)
83923f7e30SGrant Likely {
84923f7e30SGrant Likely 	return container_of(kref, struct device_node, kref);
85923f7e30SGrant Likely }
86923f7e30SGrant Likely 
87923f7e30SGrant Likely /**
88923f7e30SGrant Likely  *	of_node_release - release a dynamically allocated node
89923f7e30SGrant Likely  *	@kref:  kref element of the node to be released
90923f7e30SGrant Likely  *
91923f7e30SGrant Likely  *	In of_node_put() this function is passed to kref_put()
92923f7e30SGrant Likely  *	as the destructor.
93923f7e30SGrant Likely  */
94923f7e30SGrant Likely static void of_node_release(struct kref *kref)
95923f7e30SGrant Likely {
96923f7e30SGrant Likely 	struct device_node *node = kref_to_device_node(kref);
97923f7e30SGrant Likely 	struct property *prop = node->properties;
98923f7e30SGrant Likely 
99923f7e30SGrant Likely 	/* We should never be releasing nodes that haven't been detached. */
100923f7e30SGrant Likely 	if (!of_node_check_flag(node, OF_DETACHED)) {
101923f7e30SGrant Likely 		pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name);
102923f7e30SGrant Likely 		dump_stack();
103923f7e30SGrant Likely 		kref_init(&node->kref);
104923f7e30SGrant Likely 		return;
105923f7e30SGrant Likely 	}
106923f7e30SGrant Likely 
107923f7e30SGrant Likely 	if (!of_node_check_flag(node, OF_DYNAMIC))
108923f7e30SGrant Likely 		return;
109923f7e30SGrant Likely 
110923f7e30SGrant Likely 	while (prop) {
111923f7e30SGrant Likely 		struct property *next = prop->next;
112923f7e30SGrant Likely 		kfree(prop->name);
113923f7e30SGrant Likely 		kfree(prop->value);
114923f7e30SGrant Likely 		kfree(prop);
115923f7e30SGrant Likely 		prop = next;
116923f7e30SGrant Likely 
117923f7e30SGrant Likely 		if (!prop) {
118923f7e30SGrant Likely 			prop = node->deadprops;
119923f7e30SGrant Likely 			node->deadprops = NULL;
120923f7e30SGrant Likely 		}
121923f7e30SGrant Likely 	}
122923f7e30SGrant Likely 	kfree(node->full_name);
123923f7e30SGrant Likely 	kfree(node->data);
124923f7e30SGrant Likely 	kfree(node);
125923f7e30SGrant Likely }
126923f7e30SGrant Likely 
127923f7e30SGrant Likely /**
128923f7e30SGrant Likely  *	of_node_put - Decrement refcount of a node
129923f7e30SGrant Likely  *	@node:	Node to dec refcount, NULL is supported to
130923f7e30SGrant Likely  *		simplify writing of callers
131923f7e30SGrant Likely  *
132923f7e30SGrant Likely  */
133923f7e30SGrant Likely void of_node_put(struct device_node *node)
134923f7e30SGrant Likely {
135923f7e30SGrant Likely 	if (node)
136923f7e30SGrant Likely 		kref_put(&node->kref, of_node_release);
137923f7e30SGrant Likely }
138923f7e30SGrant Likely EXPORT_SYMBOL(of_node_put);
139923f7e30SGrant Likely #endif /* !CONFIG_SPARC */
140923f7e30SGrant Likely 
141581b605aSStephen Rothwell struct property *of_find_property(const struct device_node *np,
142581b605aSStephen Rothwell 				  const char *name,
143581b605aSStephen Rothwell 				  int *lenp)
144581b605aSStephen Rothwell {
145581b605aSStephen Rothwell 	struct property *pp;
146581b605aSStephen Rothwell 
14764e4566fSTimur Tabi 	if (!np)
14864e4566fSTimur Tabi 		return NULL;
14964e4566fSTimur Tabi 
150581b605aSStephen Rothwell 	read_lock(&devtree_lock);
151581b605aSStephen Rothwell 	for (pp = np->properties; pp != 0; pp = pp->next) {
152581b605aSStephen Rothwell 		if (of_prop_cmp(pp->name, name) == 0) {
153581b605aSStephen Rothwell 			if (lenp != 0)
154581b605aSStephen Rothwell 				*lenp = pp->length;
155581b605aSStephen Rothwell 			break;
156581b605aSStephen Rothwell 		}
157581b605aSStephen Rothwell 	}
158581b605aSStephen Rothwell 	read_unlock(&devtree_lock);
159581b605aSStephen Rothwell 
160581b605aSStephen Rothwell 	return pp;
161581b605aSStephen Rothwell }
162581b605aSStephen Rothwell EXPORT_SYMBOL(of_find_property);
163581b605aSStephen Rothwell 
164e91edcf5SGrant Likely /**
165e91edcf5SGrant Likely  * of_find_all_nodes - Get next node in global list
166e91edcf5SGrant Likely  * @prev:	Previous node or NULL to start iteration
167e91edcf5SGrant Likely  *		of_node_put() will be called on it
168e91edcf5SGrant Likely  *
169e91edcf5SGrant Likely  * Returns a node pointer with refcount incremented, use
170e91edcf5SGrant Likely  * of_node_put() on it when done.
171e91edcf5SGrant Likely  */
172e91edcf5SGrant Likely struct device_node *of_find_all_nodes(struct device_node *prev)
173e91edcf5SGrant Likely {
174e91edcf5SGrant Likely 	struct device_node *np;
175e91edcf5SGrant Likely 
176e91edcf5SGrant Likely 	read_lock(&devtree_lock);
177e91edcf5SGrant Likely 	np = prev ? prev->allnext : allnodes;
178e91edcf5SGrant Likely 	for (; np != NULL; np = np->allnext)
179e91edcf5SGrant Likely 		if (of_node_get(np))
180e91edcf5SGrant Likely 			break;
181e91edcf5SGrant Likely 	of_node_put(prev);
182e91edcf5SGrant Likely 	read_unlock(&devtree_lock);
183e91edcf5SGrant Likely 	return np;
184e91edcf5SGrant Likely }
185e91edcf5SGrant Likely EXPORT_SYMBOL(of_find_all_nodes);
186e91edcf5SGrant Likely 
18797e873e5SStephen Rothwell /*
18897e873e5SStephen Rothwell  * Find a property with a given name for a given node
18997e873e5SStephen Rothwell  * and return the value.
19097e873e5SStephen Rothwell  */
19197e873e5SStephen Rothwell const void *of_get_property(const struct device_node *np, const char *name,
19297e873e5SStephen Rothwell 			 int *lenp)
19397e873e5SStephen Rothwell {
19497e873e5SStephen Rothwell 	struct property *pp = of_find_property(np, name, lenp);
19597e873e5SStephen Rothwell 
19697e873e5SStephen Rothwell 	return pp ? pp->value : NULL;
19797e873e5SStephen Rothwell }
19897e873e5SStephen Rothwell EXPORT_SYMBOL(of_get_property);
1990081cbc3SStephen Rothwell 
2000081cbc3SStephen Rothwell /** Checks if the given "compat" string matches one of the strings in
2010081cbc3SStephen Rothwell  * the device's "compatible" property
2020081cbc3SStephen Rothwell  */
2030081cbc3SStephen Rothwell int of_device_is_compatible(const struct device_node *device,
2040081cbc3SStephen Rothwell 		const char *compat)
2050081cbc3SStephen Rothwell {
2060081cbc3SStephen Rothwell 	const char* cp;
2070081cbc3SStephen Rothwell 	int cplen, l;
2080081cbc3SStephen Rothwell 
2090081cbc3SStephen Rothwell 	cp = of_get_property(device, "compatible", &cplen);
2100081cbc3SStephen Rothwell 	if (cp == NULL)
2110081cbc3SStephen Rothwell 		return 0;
2120081cbc3SStephen Rothwell 	while (cplen > 0) {
2130081cbc3SStephen Rothwell 		if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
2140081cbc3SStephen Rothwell 			return 1;
2150081cbc3SStephen Rothwell 		l = strlen(cp) + 1;
2160081cbc3SStephen Rothwell 		cp += l;
2170081cbc3SStephen Rothwell 		cplen -= l;
2180081cbc3SStephen Rothwell 	}
2190081cbc3SStephen Rothwell 
2200081cbc3SStephen Rothwell 	return 0;
2210081cbc3SStephen Rothwell }
2220081cbc3SStephen Rothwell EXPORT_SYMBOL(of_device_is_compatible);
223e679c5f4SStephen Rothwell 
224e679c5f4SStephen Rothwell /**
22571a157e8SGrant Likely  * of_machine_is_compatible - Test root of device tree for a given compatible value
2261f43cfb9SGrant Likely  * @compat: compatible string to look for in root node's compatible property.
2271f43cfb9SGrant Likely  *
2281f43cfb9SGrant Likely  * Returns true if the root node has the given value in its
2291f43cfb9SGrant Likely  * compatible property.
2301f43cfb9SGrant Likely  */
23171a157e8SGrant Likely int of_machine_is_compatible(const char *compat)
2321f43cfb9SGrant Likely {
2331f43cfb9SGrant Likely 	struct device_node *root;
2341f43cfb9SGrant Likely 	int rc = 0;
2351f43cfb9SGrant Likely 
2361f43cfb9SGrant Likely 	root = of_find_node_by_path("/");
2371f43cfb9SGrant Likely 	if (root) {
2381f43cfb9SGrant Likely 		rc = of_device_is_compatible(root, compat);
2391f43cfb9SGrant Likely 		of_node_put(root);
2401f43cfb9SGrant Likely 	}
2411f43cfb9SGrant Likely 	return rc;
2421f43cfb9SGrant Likely }
24371a157e8SGrant Likely EXPORT_SYMBOL(of_machine_is_compatible);
2441f43cfb9SGrant Likely 
2451f43cfb9SGrant Likely /**
246834d97d4SJosh Boyer  *  of_device_is_available - check if a device is available for use
247834d97d4SJosh Boyer  *
248834d97d4SJosh Boyer  *  @device: Node to check for availability
249834d97d4SJosh Boyer  *
250834d97d4SJosh Boyer  *  Returns 1 if the status property is absent or set to "okay" or "ok",
251834d97d4SJosh Boyer  *  0 otherwise
252834d97d4SJosh Boyer  */
253834d97d4SJosh Boyer int of_device_is_available(const struct device_node *device)
254834d97d4SJosh Boyer {
255834d97d4SJosh Boyer 	const char *status;
256834d97d4SJosh Boyer 	int statlen;
257834d97d4SJosh Boyer 
258834d97d4SJosh Boyer 	status = of_get_property(device, "status", &statlen);
259834d97d4SJosh Boyer 	if (status == NULL)
260834d97d4SJosh Boyer 		return 1;
261834d97d4SJosh Boyer 
262834d97d4SJosh Boyer 	if (statlen > 0) {
263834d97d4SJosh Boyer 		if (!strcmp(status, "okay") || !strcmp(status, "ok"))
264834d97d4SJosh Boyer 			return 1;
265834d97d4SJosh Boyer 	}
266834d97d4SJosh Boyer 
267834d97d4SJosh Boyer 	return 0;
268834d97d4SJosh Boyer }
269834d97d4SJosh Boyer EXPORT_SYMBOL(of_device_is_available);
270834d97d4SJosh Boyer 
271834d97d4SJosh Boyer /**
272e679c5f4SStephen Rothwell  *	of_get_parent - Get a node's parent if any
273e679c5f4SStephen Rothwell  *	@node:	Node to get parent
274e679c5f4SStephen Rothwell  *
275e679c5f4SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
276e679c5f4SStephen Rothwell  *	of_node_put() on it when done.
277e679c5f4SStephen Rothwell  */
278e679c5f4SStephen Rothwell struct device_node *of_get_parent(const struct device_node *node)
279e679c5f4SStephen Rothwell {
280e679c5f4SStephen Rothwell 	struct device_node *np;
281e679c5f4SStephen Rothwell 
282e679c5f4SStephen Rothwell 	if (!node)
283e679c5f4SStephen Rothwell 		return NULL;
284e679c5f4SStephen Rothwell 
285e679c5f4SStephen Rothwell 	read_lock(&devtree_lock);
286e679c5f4SStephen Rothwell 	np = of_node_get(node->parent);
287e679c5f4SStephen Rothwell 	read_unlock(&devtree_lock);
288e679c5f4SStephen Rothwell 	return np;
289e679c5f4SStephen Rothwell }
290e679c5f4SStephen Rothwell EXPORT_SYMBOL(of_get_parent);
291d1cd355aSStephen Rothwell 
292d1cd355aSStephen Rothwell /**
293f4eb0107SMichael Ellerman  *	of_get_next_parent - Iterate to a node's parent
294f4eb0107SMichael Ellerman  *	@node:	Node to get parent of
295f4eb0107SMichael Ellerman  *
296f4eb0107SMichael Ellerman  * 	This is like of_get_parent() except that it drops the
297f4eb0107SMichael Ellerman  * 	refcount on the passed node, making it suitable for iterating
298f4eb0107SMichael Ellerman  * 	through a node's parents.
299f4eb0107SMichael Ellerman  *
300f4eb0107SMichael Ellerman  *	Returns a node pointer with refcount incremented, use
301f4eb0107SMichael Ellerman  *	of_node_put() on it when done.
302f4eb0107SMichael Ellerman  */
303f4eb0107SMichael Ellerman struct device_node *of_get_next_parent(struct device_node *node)
304f4eb0107SMichael Ellerman {
305f4eb0107SMichael Ellerman 	struct device_node *parent;
306f4eb0107SMichael Ellerman 
307f4eb0107SMichael Ellerman 	if (!node)
308f4eb0107SMichael Ellerman 		return NULL;
309f4eb0107SMichael Ellerman 
310f4eb0107SMichael Ellerman 	read_lock(&devtree_lock);
311f4eb0107SMichael Ellerman 	parent = of_node_get(node->parent);
312f4eb0107SMichael Ellerman 	of_node_put(node);
313f4eb0107SMichael Ellerman 	read_unlock(&devtree_lock);
314f4eb0107SMichael Ellerman 	return parent;
315f4eb0107SMichael Ellerman }
316f4eb0107SMichael Ellerman 
317f4eb0107SMichael Ellerman /**
318d1cd355aSStephen Rothwell  *	of_get_next_child - Iterate a node childs
319d1cd355aSStephen Rothwell  *	@node:	parent node
320d1cd355aSStephen Rothwell  *	@prev:	previous child of the parent node, or NULL to get first
321d1cd355aSStephen Rothwell  *
322d1cd355aSStephen Rothwell  *	Returns a node pointer with refcount incremented, use
323d1cd355aSStephen Rothwell  *	of_node_put() on it when done.
324d1cd355aSStephen Rothwell  */
325d1cd355aSStephen Rothwell struct device_node *of_get_next_child(const struct device_node *node,
326d1cd355aSStephen Rothwell 	struct device_node *prev)
327d1cd355aSStephen Rothwell {
328d1cd355aSStephen Rothwell 	struct device_node *next;
329d1cd355aSStephen Rothwell 
330d1cd355aSStephen Rothwell 	read_lock(&devtree_lock);
331d1cd355aSStephen Rothwell 	next = prev ? prev->sibling : node->child;
332d1cd355aSStephen Rothwell 	for (; next; next = next->sibling)
333d1cd355aSStephen Rothwell 		if (of_node_get(next))
334d1cd355aSStephen Rothwell 			break;
335d1cd355aSStephen Rothwell 	of_node_put(prev);
336d1cd355aSStephen Rothwell 	read_unlock(&devtree_lock);
337d1cd355aSStephen Rothwell 	return next;
338d1cd355aSStephen Rothwell }
339d1cd355aSStephen Rothwell EXPORT_SYMBOL(of_get_next_child);
3401ef4d424SStephen Rothwell 
3411ef4d424SStephen Rothwell /**
3421ef4d424SStephen Rothwell  *	of_find_node_by_path - Find a node matching a full OF path
3431ef4d424SStephen Rothwell  *	@path:	The full path to match
3441ef4d424SStephen Rothwell  *
3451ef4d424SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
3461ef4d424SStephen Rothwell  *	of_node_put() on it when done.
3471ef4d424SStephen Rothwell  */
3481ef4d424SStephen Rothwell struct device_node *of_find_node_by_path(const char *path)
3491ef4d424SStephen Rothwell {
3501ef4d424SStephen Rothwell 	struct device_node *np = allnodes;
3511ef4d424SStephen Rothwell 
3521ef4d424SStephen Rothwell 	read_lock(&devtree_lock);
3531ef4d424SStephen Rothwell 	for (; np; np = np->allnext) {
3541ef4d424SStephen Rothwell 		if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
3551ef4d424SStephen Rothwell 		    && of_node_get(np))
3561ef4d424SStephen Rothwell 			break;
3571ef4d424SStephen Rothwell 	}
3581ef4d424SStephen Rothwell 	read_unlock(&devtree_lock);
3591ef4d424SStephen Rothwell 	return np;
3601ef4d424SStephen Rothwell }
3611ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_path);
3621ef4d424SStephen Rothwell 
3631ef4d424SStephen Rothwell /**
3641ef4d424SStephen Rothwell  *	of_find_node_by_name - Find a node by its "name" property
3651ef4d424SStephen Rothwell  *	@from:	The node to start searching from or NULL, the node
3661ef4d424SStephen Rothwell  *		you pass will not be searched, only the next one
3671ef4d424SStephen Rothwell  *		will; typically, you pass what the previous call
3681ef4d424SStephen Rothwell  *		returned. of_node_put() will be called on it
3691ef4d424SStephen Rothwell  *	@name:	The name string to match against
3701ef4d424SStephen Rothwell  *
3711ef4d424SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
3721ef4d424SStephen Rothwell  *	of_node_put() on it when done.
3731ef4d424SStephen Rothwell  */
3741ef4d424SStephen Rothwell struct device_node *of_find_node_by_name(struct device_node *from,
3751ef4d424SStephen Rothwell 	const char *name)
3761ef4d424SStephen Rothwell {
3771ef4d424SStephen Rothwell 	struct device_node *np;
3781ef4d424SStephen Rothwell 
3791ef4d424SStephen Rothwell 	read_lock(&devtree_lock);
3801ef4d424SStephen Rothwell 	np = from ? from->allnext : allnodes;
3811ef4d424SStephen Rothwell 	for (; np; np = np->allnext)
3821ef4d424SStephen Rothwell 		if (np->name && (of_node_cmp(np->name, name) == 0)
3831ef4d424SStephen Rothwell 		    && of_node_get(np))
3841ef4d424SStephen Rothwell 			break;
3851ef4d424SStephen Rothwell 	of_node_put(from);
3861ef4d424SStephen Rothwell 	read_unlock(&devtree_lock);
3871ef4d424SStephen Rothwell 	return np;
3881ef4d424SStephen Rothwell }
3891ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_name);
3901ef4d424SStephen Rothwell 
3911ef4d424SStephen Rothwell /**
3921ef4d424SStephen Rothwell  *	of_find_node_by_type - Find a node by its "device_type" property
3931ef4d424SStephen Rothwell  *	@from:	The node to start searching from, or NULL to start searching
3941ef4d424SStephen Rothwell  *		the entire device tree. The node you pass will not be
3951ef4d424SStephen Rothwell  *		searched, only the next one will; typically, you pass
3961ef4d424SStephen Rothwell  *		what the previous call returned. of_node_put() will be
3971ef4d424SStephen Rothwell  *		called on from for you.
3981ef4d424SStephen Rothwell  *	@type:	The type string to match against
3991ef4d424SStephen Rothwell  *
4001ef4d424SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
4011ef4d424SStephen Rothwell  *	of_node_put() on it when done.
4021ef4d424SStephen Rothwell  */
4031ef4d424SStephen Rothwell struct device_node *of_find_node_by_type(struct device_node *from,
4041ef4d424SStephen Rothwell 	const char *type)
4051ef4d424SStephen Rothwell {
4061ef4d424SStephen Rothwell 	struct device_node *np;
4071ef4d424SStephen Rothwell 
4081ef4d424SStephen Rothwell 	read_lock(&devtree_lock);
4091ef4d424SStephen Rothwell 	np = from ? from->allnext : allnodes;
4101ef4d424SStephen Rothwell 	for (; np; np = np->allnext)
4111ef4d424SStephen Rothwell 		if (np->type && (of_node_cmp(np->type, type) == 0)
4121ef4d424SStephen Rothwell 		    && of_node_get(np))
4131ef4d424SStephen Rothwell 			break;
4141ef4d424SStephen Rothwell 	of_node_put(from);
4151ef4d424SStephen Rothwell 	read_unlock(&devtree_lock);
4161ef4d424SStephen Rothwell 	return np;
4171ef4d424SStephen Rothwell }
4181ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_type);
4191ef4d424SStephen Rothwell 
4201ef4d424SStephen Rothwell /**
4211ef4d424SStephen Rothwell  *	of_find_compatible_node - Find a node based on type and one of the
4221ef4d424SStephen Rothwell  *                                tokens in its "compatible" property
4231ef4d424SStephen Rothwell  *	@from:		The node to start searching from or NULL, the node
4241ef4d424SStephen Rothwell  *			you pass will not be searched, only the next one
4251ef4d424SStephen Rothwell  *			will; typically, you pass what the previous call
4261ef4d424SStephen Rothwell  *			returned. of_node_put() will be called on it
4271ef4d424SStephen Rothwell  *	@type:		The type string to match "device_type" or NULL to ignore
4281ef4d424SStephen Rothwell  *	@compatible:	The string to match to one of the tokens in the device
4291ef4d424SStephen Rothwell  *			"compatible" list.
4301ef4d424SStephen Rothwell  *
4311ef4d424SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
4321ef4d424SStephen Rothwell  *	of_node_put() on it when done.
4331ef4d424SStephen Rothwell  */
4341ef4d424SStephen Rothwell struct device_node *of_find_compatible_node(struct device_node *from,
4351ef4d424SStephen Rothwell 	const char *type, const char *compatible)
4361ef4d424SStephen Rothwell {
4371ef4d424SStephen Rothwell 	struct device_node *np;
4381ef4d424SStephen Rothwell 
4391ef4d424SStephen Rothwell 	read_lock(&devtree_lock);
4401ef4d424SStephen Rothwell 	np = from ? from->allnext : allnodes;
4411ef4d424SStephen Rothwell 	for (; np; np = np->allnext) {
4421ef4d424SStephen Rothwell 		if (type
4431ef4d424SStephen Rothwell 		    && !(np->type && (of_node_cmp(np->type, type) == 0)))
4441ef4d424SStephen Rothwell 			continue;
4451ef4d424SStephen Rothwell 		if (of_device_is_compatible(np, compatible) && of_node_get(np))
4461ef4d424SStephen Rothwell 			break;
4471ef4d424SStephen Rothwell 	}
4481ef4d424SStephen Rothwell 	of_node_put(from);
4491ef4d424SStephen Rothwell 	read_unlock(&devtree_lock);
4501ef4d424SStephen Rothwell 	return np;
4511ef4d424SStephen Rothwell }
4521ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_compatible_node);
453283029d1SGrant Likely 
454283029d1SGrant Likely /**
4551e291b14SMichael Ellerman  *	of_find_node_with_property - Find a node which has a property with
4561e291b14SMichael Ellerman  *                                   the given name.
4571e291b14SMichael Ellerman  *	@from:		The node to start searching from or NULL, the node
4581e291b14SMichael Ellerman  *			you pass will not be searched, only the next one
4591e291b14SMichael Ellerman  *			will; typically, you pass what the previous call
4601e291b14SMichael Ellerman  *			returned. of_node_put() will be called on it
4611e291b14SMichael Ellerman  *	@prop_name:	The name of the property to look for.
4621e291b14SMichael Ellerman  *
4631e291b14SMichael Ellerman  *	Returns a node pointer with refcount incremented, use
4641e291b14SMichael Ellerman  *	of_node_put() on it when done.
4651e291b14SMichael Ellerman  */
4661e291b14SMichael Ellerman struct device_node *of_find_node_with_property(struct device_node *from,
4671e291b14SMichael Ellerman 	const char *prop_name)
4681e291b14SMichael Ellerman {
4691e291b14SMichael Ellerman 	struct device_node *np;
4701e291b14SMichael Ellerman 	struct property *pp;
4711e291b14SMichael Ellerman 
4721e291b14SMichael Ellerman 	read_lock(&devtree_lock);
4731e291b14SMichael Ellerman 	np = from ? from->allnext : allnodes;
4741e291b14SMichael Ellerman 	for (; np; np = np->allnext) {
4751e291b14SMichael Ellerman 		for (pp = np->properties; pp != 0; pp = pp->next) {
4761e291b14SMichael Ellerman 			if (of_prop_cmp(pp->name, prop_name) == 0) {
4771e291b14SMichael Ellerman 				of_node_get(np);
4781e291b14SMichael Ellerman 				goto out;
4791e291b14SMichael Ellerman 			}
4801e291b14SMichael Ellerman 		}
4811e291b14SMichael Ellerman 	}
4821e291b14SMichael Ellerman out:
4831e291b14SMichael Ellerman 	of_node_put(from);
4841e291b14SMichael Ellerman 	read_unlock(&devtree_lock);
4851e291b14SMichael Ellerman 	return np;
4861e291b14SMichael Ellerman }
4871e291b14SMichael Ellerman EXPORT_SYMBOL(of_find_node_with_property);
4881e291b14SMichael Ellerman 
4891e291b14SMichael Ellerman /**
490283029d1SGrant Likely  * of_match_node - Tell if an device_node has a matching of_match structure
491283029d1SGrant Likely  *	@matches:	array of of device match structures to search in
492283029d1SGrant Likely  *	@node:		the of device structure to match against
493283029d1SGrant Likely  *
494283029d1SGrant Likely  *	Low level utility function used by device matching.
495283029d1SGrant Likely  */
496283029d1SGrant Likely const struct of_device_id *of_match_node(const struct of_device_id *matches,
497283029d1SGrant Likely 					 const struct device_node *node)
498283029d1SGrant Likely {
499283029d1SGrant Likely 	while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
500283029d1SGrant Likely 		int match = 1;
501283029d1SGrant Likely 		if (matches->name[0])
502283029d1SGrant Likely 			match &= node->name
503283029d1SGrant Likely 				&& !strcmp(matches->name, node->name);
504283029d1SGrant Likely 		if (matches->type[0])
505283029d1SGrant Likely 			match &= node->type
506283029d1SGrant Likely 				&& !strcmp(matches->type, node->type);
507283029d1SGrant Likely 		if (matches->compatible[0])
508283029d1SGrant Likely 			match &= of_device_is_compatible(node,
509283029d1SGrant Likely 						matches->compatible);
510283029d1SGrant Likely 		if (match)
511283029d1SGrant Likely 			return matches;
512283029d1SGrant Likely 		matches++;
513283029d1SGrant Likely 	}
514283029d1SGrant Likely 	return NULL;
515283029d1SGrant Likely }
516283029d1SGrant Likely EXPORT_SYMBOL(of_match_node);
517283029d1SGrant Likely 
518283029d1SGrant Likely /**
519283029d1SGrant Likely  *	of_find_matching_node - Find a node based on an of_device_id match
520283029d1SGrant Likely  *				table.
521283029d1SGrant Likely  *	@from:		The node to start searching from or NULL, the node
522283029d1SGrant Likely  *			you pass will not be searched, only the next one
523283029d1SGrant Likely  *			will; typically, you pass what the previous call
524283029d1SGrant Likely  *			returned. of_node_put() will be called on it
525283029d1SGrant Likely  *	@matches:	array of of device match structures to search in
526283029d1SGrant Likely  *
527283029d1SGrant Likely  *	Returns a node pointer with refcount incremented, use
528283029d1SGrant Likely  *	of_node_put() on it when done.
529283029d1SGrant Likely  */
530283029d1SGrant Likely struct device_node *of_find_matching_node(struct device_node *from,
531283029d1SGrant Likely 					  const struct of_device_id *matches)
532283029d1SGrant Likely {
533283029d1SGrant Likely 	struct device_node *np;
534283029d1SGrant Likely 
535283029d1SGrant Likely 	read_lock(&devtree_lock);
536283029d1SGrant Likely 	np = from ? from->allnext : allnodes;
537283029d1SGrant Likely 	for (; np; np = np->allnext) {
538283029d1SGrant Likely 		if (of_match_node(matches, np) && of_node_get(np))
539283029d1SGrant Likely 			break;
540283029d1SGrant Likely 	}
541283029d1SGrant Likely 	of_node_put(from);
542283029d1SGrant Likely 	read_unlock(&devtree_lock);
543283029d1SGrant Likely 	return np;
544283029d1SGrant Likely }
545283029d1SGrant Likely EXPORT_SYMBOL(of_find_matching_node);
5463f07af49SGrant Likely 
5473f07af49SGrant Likely /**
5483f07af49SGrant Likely  * of_modalias_node - Lookup appropriate modalias for a device node
5493f07af49SGrant Likely  * @node:	pointer to a device tree node
5503f07af49SGrant Likely  * @modalias:	Pointer to buffer that modalias value will be copied into
5513f07af49SGrant Likely  * @len:	Length of modalias value
5523f07af49SGrant Likely  *
5532ffe8c5fSGrant Likely  * Based on the value of the compatible property, this routine will attempt
5542ffe8c5fSGrant Likely  * to choose an appropriate modalias value for a particular device tree node.
5552ffe8c5fSGrant Likely  * It does this by stripping the manufacturer prefix (as delimited by a ',')
5562ffe8c5fSGrant Likely  * from the first entry in the compatible list property.
5573f07af49SGrant Likely  *
5582ffe8c5fSGrant Likely  * This routine returns 0 on success, <0 on failure.
5593f07af49SGrant Likely  */
5603f07af49SGrant Likely int of_modalias_node(struct device_node *node, char *modalias, int len)
5613f07af49SGrant Likely {
5622ffe8c5fSGrant Likely 	const char *compatible, *p;
5632ffe8c5fSGrant Likely 	int cplen;
5643f07af49SGrant Likely 
5653f07af49SGrant Likely 	compatible = of_get_property(node, "compatible", &cplen);
5662ffe8c5fSGrant Likely 	if (!compatible || strlen(compatible) > cplen)
5673f07af49SGrant Likely 		return -ENODEV;
5683f07af49SGrant Likely 	p = strchr(compatible, ',');
5692ffe8c5fSGrant Likely 	strlcpy(modalias, p ? p + 1 : compatible, len);
5703f07af49SGrant Likely 	return 0;
5713f07af49SGrant Likely }
5723f07af49SGrant Likely EXPORT_SYMBOL_GPL(of_modalias_node);
5733f07af49SGrant Likely 
57464b60e09SAnton Vorontsov /**
57589751a7cSJeremy Kerr  * of_find_node_by_phandle - Find a node given a phandle
57689751a7cSJeremy Kerr  * @handle:	phandle of the node to find
57789751a7cSJeremy Kerr  *
57889751a7cSJeremy Kerr  * Returns a node pointer with refcount incremented, use
57989751a7cSJeremy Kerr  * of_node_put() on it when done.
58089751a7cSJeremy Kerr  */
58189751a7cSJeremy Kerr struct device_node *of_find_node_by_phandle(phandle handle)
58289751a7cSJeremy Kerr {
58389751a7cSJeremy Kerr 	struct device_node *np;
58489751a7cSJeremy Kerr 
58589751a7cSJeremy Kerr 	read_lock(&devtree_lock);
58689751a7cSJeremy Kerr 	for (np = allnodes; np; np = np->allnext)
58789751a7cSJeremy Kerr 		if (np->phandle == handle)
58889751a7cSJeremy Kerr 			break;
58989751a7cSJeremy Kerr 	of_node_get(np);
59089751a7cSJeremy Kerr 	read_unlock(&devtree_lock);
59189751a7cSJeremy Kerr 	return np;
59289751a7cSJeremy Kerr }
59389751a7cSJeremy Kerr EXPORT_SYMBOL(of_find_node_by_phandle);
59489751a7cSJeremy Kerr 
59589751a7cSJeremy Kerr /**
596739649c5SGrant Likely  * of_parse_phandle - Resolve a phandle property to a device_node pointer
597739649c5SGrant Likely  * @np: Pointer to device node holding phandle property
598739649c5SGrant Likely  * @phandle_name: Name of property holding a phandle value
599739649c5SGrant Likely  * @index: For properties holding a table of phandles, this is the index into
600739649c5SGrant Likely  *         the table
601739649c5SGrant Likely  *
602739649c5SGrant Likely  * Returns the device_node pointer with refcount incremented.  Use
603739649c5SGrant Likely  * of_node_put() on it when done.
604739649c5SGrant Likely  */
605739649c5SGrant Likely struct device_node *
606739649c5SGrant Likely of_parse_phandle(struct device_node *np, const char *phandle_name, int index)
607739649c5SGrant Likely {
6089a6b2e58SGrant Likely 	const __be32 *phandle;
609739649c5SGrant Likely 	int size;
610739649c5SGrant Likely 
611739649c5SGrant Likely 	phandle = of_get_property(np, phandle_name, &size);
612739649c5SGrant Likely 	if ((!phandle) || (size < sizeof(*phandle) * (index + 1)))
613739649c5SGrant Likely 		return NULL;
614739649c5SGrant Likely 
6159a6b2e58SGrant Likely 	return of_find_node_by_phandle(be32_to_cpup(phandle + index));
616739649c5SGrant Likely }
617739649c5SGrant Likely EXPORT_SYMBOL(of_parse_phandle);
618739649c5SGrant Likely 
619739649c5SGrant Likely /**
62064b60e09SAnton Vorontsov  * of_parse_phandles_with_args - Find a node pointed by phandle in a list
62164b60e09SAnton Vorontsov  * @np:		pointer to a device tree node containing a list
62264b60e09SAnton Vorontsov  * @list_name:	property name that contains a list
62364b60e09SAnton Vorontsov  * @cells_name:	property name that specifies phandles' arguments count
62464b60e09SAnton Vorontsov  * @index:	index of a phandle to parse out
6257736a3dbSAnton Vorontsov  * @out_node:	optional pointer to device_node struct pointer (will be filled)
6267736a3dbSAnton Vorontsov  * @out_args:	optional pointer to arguments pointer (will be filled)
62764b60e09SAnton Vorontsov  *
62864b60e09SAnton Vorontsov  * This function is useful to parse lists of phandles and their arguments.
62964b60e09SAnton Vorontsov  * Returns 0 on success and fills out_node and out_args, on error returns
63064b60e09SAnton Vorontsov  * appropriate errno value.
63164b60e09SAnton Vorontsov  *
63264b60e09SAnton Vorontsov  * Example:
63364b60e09SAnton Vorontsov  *
63464b60e09SAnton Vorontsov  * phandle1: node1 {
63564b60e09SAnton Vorontsov  * 	#list-cells = <2>;
63664b60e09SAnton Vorontsov  * }
63764b60e09SAnton Vorontsov  *
63864b60e09SAnton Vorontsov  * phandle2: node2 {
63964b60e09SAnton Vorontsov  * 	#list-cells = <1>;
64064b60e09SAnton Vorontsov  * }
64164b60e09SAnton Vorontsov  *
64264b60e09SAnton Vorontsov  * node3 {
64364b60e09SAnton Vorontsov  * 	list = <&phandle1 1 2 &phandle2 3>;
64464b60e09SAnton Vorontsov  * }
64564b60e09SAnton Vorontsov  *
64664b60e09SAnton Vorontsov  * To get a device_node of the `node2' node you may call this:
64764b60e09SAnton Vorontsov  * of_parse_phandles_with_args(node3, "list", "#list-cells", 2, &node2, &args);
64864b60e09SAnton Vorontsov  */
64964b60e09SAnton Vorontsov int of_parse_phandles_with_args(struct device_node *np, const char *list_name,
65064b60e09SAnton Vorontsov 				const char *cells_name, int index,
65164b60e09SAnton Vorontsov 				struct device_node **out_node,
65264b60e09SAnton Vorontsov 				const void **out_args)
65364b60e09SAnton Vorontsov {
65464b60e09SAnton Vorontsov 	int ret = -EINVAL;
65533714881SJeremy Kerr 	const __be32 *list;
65633714881SJeremy Kerr 	const __be32 *list_end;
65764b60e09SAnton Vorontsov 	int size;
65864b60e09SAnton Vorontsov 	int cur_index = 0;
65964b60e09SAnton Vorontsov 	struct device_node *node = NULL;
6607736a3dbSAnton Vorontsov 	const void *args = NULL;
66164b60e09SAnton Vorontsov 
66264b60e09SAnton Vorontsov 	list = of_get_property(np, list_name, &size);
66364b60e09SAnton Vorontsov 	if (!list) {
66464b60e09SAnton Vorontsov 		ret = -ENOENT;
66564b60e09SAnton Vorontsov 		goto err0;
66664b60e09SAnton Vorontsov 	}
66764b60e09SAnton Vorontsov 	list_end = list + size / sizeof(*list);
66864b60e09SAnton Vorontsov 
66964b60e09SAnton Vorontsov 	while (list < list_end) {
67033714881SJeremy Kerr 		const __be32 *cells;
6719a6b2e58SGrant Likely 		phandle phandle;
67264b60e09SAnton Vorontsov 
6739a6b2e58SGrant Likely 		phandle = be32_to_cpup(list++);
674c1bb7c6dSAnton Vorontsov 		args = list;
67564b60e09SAnton Vorontsov 
67664b60e09SAnton Vorontsov 		/* one cell hole in the list = <>; */
6779a6b2e58SGrant Likely 		if (!phandle)
67864b60e09SAnton Vorontsov 			goto next;
67964b60e09SAnton Vorontsov 
6809a6b2e58SGrant Likely 		node = of_find_node_by_phandle(phandle);
68164b60e09SAnton Vorontsov 		if (!node) {
68264b60e09SAnton Vorontsov 			pr_debug("%s: could not find phandle\n",
68364b60e09SAnton Vorontsov 				 np->full_name);
68464b60e09SAnton Vorontsov 			goto err0;
68564b60e09SAnton Vorontsov 		}
68664b60e09SAnton Vorontsov 
68764b60e09SAnton Vorontsov 		cells = of_get_property(node, cells_name, &size);
68864b60e09SAnton Vorontsov 		if (!cells || size != sizeof(*cells)) {
68964b60e09SAnton Vorontsov 			pr_debug("%s: could not get %s for %s\n",
69064b60e09SAnton Vorontsov 				 np->full_name, cells_name, node->full_name);
69164b60e09SAnton Vorontsov 			goto err1;
69264b60e09SAnton Vorontsov 		}
69364b60e09SAnton Vorontsov 
69433714881SJeremy Kerr 		list += be32_to_cpup(cells);
69564b60e09SAnton Vorontsov 		if (list > list_end) {
69664b60e09SAnton Vorontsov 			pr_debug("%s: insufficient arguments length\n",
69764b60e09SAnton Vorontsov 				 np->full_name);
69864b60e09SAnton Vorontsov 			goto err1;
69964b60e09SAnton Vorontsov 		}
70064b60e09SAnton Vorontsov next:
70164b60e09SAnton Vorontsov 		if (cur_index == index)
70264b60e09SAnton Vorontsov 			break;
70364b60e09SAnton Vorontsov 
70464b60e09SAnton Vorontsov 		of_node_put(node);
70564b60e09SAnton Vorontsov 		node = NULL;
7067736a3dbSAnton Vorontsov 		args = NULL;
70764b60e09SAnton Vorontsov 		cur_index++;
70864b60e09SAnton Vorontsov 	}
70964b60e09SAnton Vorontsov 
71064b60e09SAnton Vorontsov 	if (!node) {
7117736a3dbSAnton Vorontsov 		/*
7127736a3dbSAnton Vorontsov 		 * args w/o node indicates that the loop above has stopped at
7137736a3dbSAnton Vorontsov 		 * the 'hole' cell. Report this differently.
7147736a3dbSAnton Vorontsov 		 */
7157736a3dbSAnton Vorontsov 		if (args)
7167736a3dbSAnton Vorontsov 			ret = -EEXIST;
7177736a3dbSAnton Vorontsov 		else
71864b60e09SAnton Vorontsov 			ret = -ENOENT;
71964b60e09SAnton Vorontsov 		goto err0;
72064b60e09SAnton Vorontsov 	}
72164b60e09SAnton Vorontsov 
7227736a3dbSAnton Vorontsov 	if (out_node)
72364b60e09SAnton Vorontsov 		*out_node = node;
7247736a3dbSAnton Vorontsov 	if (out_args)
72564b60e09SAnton Vorontsov 		*out_args = args;
72664b60e09SAnton Vorontsov 
72764b60e09SAnton Vorontsov 	return 0;
72864b60e09SAnton Vorontsov err1:
72964b60e09SAnton Vorontsov 	of_node_put(node);
73064b60e09SAnton Vorontsov err0:
73164b60e09SAnton Vorontsov 	pr_debug("%s failed with status %d\n", __func__, ret);
73264b60e09SAnton Vorontsov 	return ret;
73364b60e09SAnton Vorontsov }
73464b60e09SAnton Vorontsov EXPORT_SYMBOL(of_parse_phandles_with_args);
73502af11b0SGrant Likely 
73602af11b0SGrant Likely /**
73702af11b0SGrant Likely  * prom_add_property - Add a property to a node
73802af11b0SGrant Likely  */
73902af11b0SGrant Likely int prom_add_property(struct device_node *np, struct property *prop)
74002af11b0SGrant Likely {
74102af11b0SGrant Likely 	struct property **next;
74202af11b0SGrant Likely 	unsigned long flags;
74302af11b0SGrant Likely 
74402af11b0SGrant Likely 	prop->next = NULL;
74502af11b0SGrant Likely 	write_lock_irqsave(&devtree_lock, flags);
74602af11b0SGrant Likely 	next = &np->properties;
74702af11b0SGrant Likely 	while (*next) {
74802af11b0SGrant Likely 		if (strcmp(prop->name, (*next)->name) == 0) {
74902af11b0SGrant Likely 			/* duplicate ! don't insert it */
75002af11b0SGrant Likely 			write_unlock_irqrestore(&devtree_lock, flags);
75102af11b0SGrant Likely 			return -1;
75202af11b0SGrant Likely 		}
75302af11b0SGrant Likely 		next = &(*next)->next;
75402af11b0SGrant Likely 	}
75502af11b0SGrant Likely 	*next = prop;
75602af11b0SGrant Likely 	write_unlock_irqrestore(&devtree_lock, flags);
75702af11b0SGrant Likely 
75802af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE
75902af11b0SGrant Likely 	/* try to add to proc as well if it was initialized */
76002af11b0SGrant Likely 	if (np->pde)
76102af11b0SGrant Likely 		proc_device_tree_add_prop(np->pde, prop);
76202af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */
76302af11b0SGrant Likely 
76402af11b0SGrant Likely 	return 0;
76502af11b0SGrant Likely }
76602af11b0SGrant Likely 
76702af11b0SGrant Likely /**
76802af11b0SGrant Likely  * prom_remove_property - Remove a property from a node.
76902af11b0SGrant Likely  *
77002af11b0SGrant Likely  * Note that we don't actually remove it, since we have given out
77102af11b0SGrant Likely  * who-knows-how-many pointers to the data using get-property.
77202af11b0SGrant Likely  * Instead we just move the property to the "dead properties"
77302af11b0SGrant Likely  * list, so it won't be found any more.
77402af11b0SGrant Likely  */
77502af11b0SGrant Likely int prom_remove_property(struct device_node *np, struct property *prop)
77602af11b0SGrant Likely {
77702af11b0SGrant Likely 	struct property **next;
77802af11b0SGrant Likely 	unsigned long flags;
77902af11b0SGrant Likely 	int found = 0;
78002af11b0SGrant Likely 
78102af11b0SGrant Likely 	write_lock_irqsave(&devtree_lock, flags);
78202af11b0SGrant Likely 	next = &np->properties;
78302af11b0SGrant Likely 	while (*next) {
78402af11b0SGrant Likely 		if (*next == prop) {
78502af11b0SGrant Likely 			/* found the node */
78602af11b0SGrant Likely 			*next = prop->next;
78702af11b0SGrant Likely 			prop->next = np->deadprops;
78802af11b0SGrant Likely 			np->deadprops = prop;
78902af11b0SGrant Likely 			found = 1;
79002af11b0SGrant Likely 			break;
79102af11b0SGrant Likely 		}
79202af11b0SGrant Likely 		next = &(*next)->next;
79302af11b0SGrant Likely 	}
79402af11b0SGrant Likely 	write_unlock_irqrestore(&devtree_lock, flags);
79502af11b0SGrant Likely 
79602af11b0SGrant Likely 	if (!found)
79702af11b0SGrant Likely 		return -ENODEV;
79802af11b0SGrant Likely 
79902af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE
80002af11b0SGrant Likely 	/* try to remove the proc node as well */
80102af11b0SGrant Likely 	if (np->pde)
80202af11b0SGrant Likely 		proc_device_tree_remove_prop(np->pde, prop);
80302af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */
80402af11b0SGrant Likely 
80502af11b0SGrant Likely 	return 0;
80602af11b0SGrant Likely }
80702af11b0SGrant Likely 
80802af11b0SGrant Likely /*
80902af11b0SGrant Likely  * prom_update_property - Update a property in a node.
81002af11b0SGrant Likely  *
81102af11b0SGrant Likely  * Note that we don't actually remove it, since we have given out
81202af11b0SGrant Likely  * who-knows-how-many pointers to the data using get-property.
81302af11b0SGrant Likely  * Instead we just move the property to the "dead properties" list,
81402af11b0SGrant Likely  * and add the new property to the property list
81502af11b0SGrant Likely  */
81602af11b0SGrant Likely int prom_update_property(struct device_node *np,
81702af11b0SGrant Likely 			 struct property *newprop,
81802af11b0SGrant Likely 			 struct property *oldprop)
81902af11b0SGrant Likely {
82002af11b0SGrant Likely 	struct property **next;
82102af11b0SGrant Likely 	unsigned long flags;
82202af11b0SGrant Likely 	int found = 0;
82302af11b0SGrant Likely 
82402af11b0SGrant Likely 	write_lock_irqsave(&devtree_lock, flags);
82502af11b0SGrant Likely 	next = &np->properties;
82602af11b0SGrant Likely 	while (*next) {
82702af11b0SGrant Likely 		if (*next == oldprop) {
82802af11b0SGrant Likely 			/* found the node */
82902af11b0SGrant Likely 			newprop->next = oldprop->next;
83002af11b0SGrant Likely 			*next = newprop;
83102af11b0SGrant Likely 			oldprop->next = np->deadprops;
83202af11b0SGrant Likely 			np->deadprops = oldprop;
83302af11b0SGrant Likely 			found = 1;
83402af11b0SGrant Likely 			break;
83502af11b0SGrant Likely 		}
83602af11b0SGrant Likely 		next = &(*next)->next;
83702af11b0SGrant Likely 	}
83802af11b0SGrant Likely 	write_unlock_irqrestore(&devtree_lock, flags);
83902af11b0SGrant Likely 
84002af11b0SGrant Likely 	if (!found)
84102af11b0SGrant Likely 		return -ENODEV;
84202af11b0SGrant Likely 
84302af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE
84402af11b0SGrant Likely 	/* try to add to proc as well if it was initialized */
84502af11b0SGrant Likely 	if (np->pde)
84602af11b0SGrant Likely 		proc_device_tree_update_prop(np->pde, newprop, oldprop);
84702af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */
84802af11b0SGrant Likely 
84902af11b0SGrant Likely 	return 0;
85002af11b0SGrant Likely }
851fcdeb7feSGrant Likely 
852fcdeb7feSGrant Likely #if defined(CONFIG_OF_DYNAMIC)
853fcdeb7feSGrant Likely /*
854fcdeb7feSGrant Likely  * Support for dynamic device trees.
855fcdeb7feSGrant Likely  *
856fcdeb7feSGrant Likely  * On some platforms, the device tree can be manipulated at runtime.
857fcdeb7feSGrant Likely  * The routines in this section support adding, removing and changing
858fcdeb7feSGrant Likely  * device tree nodes.
859fcdeb7feSGrant Likely  */
860fcdeb7feSGrant Likely 
861fcdeb7feSGrant Likely /**
862fcdeb7feSGrant Likely  * of_attach_node - Plug a device node into the tree and global list.
863fcdeb7feSGrant Likely  */
864fcdeb7feSGrant Likely void of_attach_node(struct device_node *np)
865fcdeb7feSGrant Likely {
866fcdeb7feSGrant Likely 	unsigned long flags;
867fcdeb7feSGrant Likely 
868fcdeb7feSGrant Likely 	write_lock_irqsave(&devtree_lock, flags);
869fcdeb7feSGrant Likely 	np->sibling = np->parent->child;
870fcdeb7feSGrant Likely 	np->allnext = allnodes;
871fcdeb7feSGrant Likely 	np->parent->child = np;
872fcdeb7feSGrant Likely 	allnodes = np;
873fcdeb7feSGrant Likely 	write_unlock_irqrestore(&devtree_lock, flags);
874fcdeb7feSGrant Likely }
875fcdeb7feSGrant Likely 
876fcdeb7feSGrant Likely /**
877fcdeb7feSGrant Likely  * of_detach_node - "Unplug" a node from the device tree.
878fcdeb7feSGrant Likely  *
879fcdeb7feSGrant Likely  * The caller must hold a reference to the node.  The memory associated with
880fcdeb7feSGrant Likely  * the node is not freed until its refcount goes to zero.
881fcdeb7feSGrant Likely  */
882fcdeb7feSGrant Likely void of_detach_node(struct device_node *np)
883fcdeb7feSGrant Likely {
884fcdeb7feSGrant Likely 	struct device_node *parent;
885fcdeb7feSGrant Likely 	unsigned long flags;
886fcdeb7feSGrant Likely 
887fcdeb7feSGrant Likely 	write_lock_irqsave(&devtree_lock, flags);
888fcdeb7feSGrant Likely 
889fcdeb7feSGrant Likely 	parent = np->parent;
890fcdeb7feSGrant Likely 	if (!parent)
891fcdeb7feSGrant Likely 		goto out_unlock;
892fcdeb7feSGrant Likely 
893fcdeb7feSGrant Likely 	if (allnodes == np)
894fcdeb7feSGrant Likely 		allnodes = np->allnext;
895fcdeb7feSGrant Likely 	else {
896fcdeb7feSGrant Likely 		struct device_node *prev;
897fcdeb7feSGrant Likely 		for (prev = allnodes;
898fcdeb7feSGrant Likely 		     prev->allnext != np;
899fcdeb7feSGrant Likely 		     prev = prev->allnext)
900fcdeb7feSGrant Likely 			;
901fcdeb7feSGrant Likely 		prev->allnext = np->allnext;
902fcdeb7feSGrant Likely 	}
903fcdeb7feSGrant Likely 
904fcdeb7feSGrant Likely 	if (parent->child == np)
905fcdeb7feSGrant Likely 		parent->child = np->sibling;
906fcdeb7feSGrant Likely 	else {
907fcdeb7feSGrant Likely 		struct device_node *prevsib;
908fcdeb7feSGrant Likely 		for (prevsib = np->parent->child;
909fcdeb7feSGrant Likely 		     prevsib->sibling != np;
910fcdeb7feSGrant Likely 		     prevsib = prevsib->sibling)
911fcdeb7feSGrant Likely 			;
912fcdeb7feSGrant Likely 		prevsib->sibling = np->sibling;
913fcdeb7feSGrant Likely 	}
914fcdeb7feSGrant Likely 
915fcdeb7feSGrant Likely 	of_node_set_flag(np, OF_DETACHED);
916fcdeb7feSGrant Likely 
917fcdeb7feSGrant Likely out_unlock:
918fcdeb7feSGrant Likely 	write_unlock_irqrestore(&devtree_lock, flags);
919fcdeb7feSGrant Likely }
920fcdeb7feSGrant Likely #endif /* defined(CONFIG_OF_DYNAMIC) */
921fcdeb7feSGrant Likely 
922