xref: /openbmc/linux/drivers/of/base.c (revision 4cd7f7a3)
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  */
20611cad72SShawn Guo #include <linux/ctype.h>
2197e873e5SStephen Rothwell #include <linux/module.h>
2297e873e5SStephen Rothwell #include <linux/of.h>
23581b605aSStephen Rothwell #include <linux/spinlock.h>
245a0e3ad6STejun Heo #include <linux/slab.h>
25a9f2f63aSJeremy Kerr #include <linux/proc_fs.h>
26581b605aSStephen Rothwell 
27611cad72SShawn Guo /**
28611cad72SShawn Guo  * struct alias_prop - Alias property in 'aliases' node
29611cad72SShawn Guo  * @link:	List node to link the structure in aliases_lookup list
30611cad72SShawn Guo  * @alias:	Alias property name
31611cad72SShawn Guo  * @np:		Pointer to device_node that the alias stands for
32611cad72SShawn Guo  * @id:		Index value from end of alias name
33611cad72SShawn Guo  * @stem:	Alias string without the index
34611cad72SShawn Guo  *
35611cad72SShawn Guo  * The structure represents one alias property of 'aliases' node as
36611cad72SShawn Guo  * an entry in aliases_lookup list.
37611cad72SShawn Guo  */
38611cad72SShawn Guo struct alias_prop {
39611cad72SShawn Guo 	struct list_head link;
40611cad72SShawn Guo 	const char *alias;
41611cad72SShawn Guo 	struct device_node *np;
42611cad72SShawn Guo 	int id;
43611cad72SShawn Guo 	char stem[0];
44611cad72SShawn Guo };
45611cad72SShawn Guo 
46611cad72SShawn Guo static LIST_HEAD(aliases_lookup);
47611cad72SShawn Guo 
481ef4d424SStephen Rothwell struct device_node *allnodes;
49fc0bdae4SGrant Likely struct device_node *of_chosen;
50611cad72SShawn Guo struct device_node *of_aliases;
51611cad72SShawn Guo 
52611cad72SShawn Guo static DEFINE_MUTEX(of_aliases_mutex);
531ef4d424SStephen Rothwell 
54581b605aSStephen Rothwell /* use when traversing tree through the allnext, child, sibling,
55581b605aSStephen Rothwell  * or parent members of struct device_node.
56581b605aSStephen Rothwell  */
57581b605aSStephen Rothwell DEFINE_RWLOCK(devtree_lock);
5897e873e5SStephen Rothwell 
5997e873e5SStephen Rothwell int of_n_addr_cells(struct device_node *np)
6097e873e5SStephen Rothwell {
61a9fadeefSJeremy Kerr 	const __be32 *ip;
6297e873e5SStephen Rothwell 
6397e873e5SStephen Rothwell 	do {
6497e873e5SStephen Rothwell 		if (np->parent)
6597e873e5SStephen Rothwell 			np = np->parent;
6697e873e5SStephen Rothwell 		ip = of_get_property(np, "#address-cells", NULL);
6797e873e5SStephen Rothwell 		if (ip)
6833714881SJeremy Kerr 			return be32_to_cpup(ip);
6997e873e5SStephen Rothwell 	} while (np->parent);
7097e873e5SStephen Rothwell 	/* No #address-cells property for the root node */
7197e873e5SStephen Rothwell 	return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
7297e873e5SStephen Rothwell }
7397e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_addr_cells);
7497e873e5SStephen Rothwell 
7597e873e5SStephen Rothwell int of_n_size_cells(struct device_node *np)
7697e873e5SStephen Rothwell {
77a9fadeefSJeremy Kerr 	const __be32 *ip;
7897e873e5SStephen Rothwell 
7997e873e5SStephen Rothwell 	do {
8097e873e5SStephen Rothwell 		if (np->parent)
8197e873e5SStephen Rothwell 			np = np->parent;
8297e873e5SStephen Rothwell 		ip = of_get_property(np, "#size-cells", NULL);
8397e873e5SStephen Rothwell 		if (ip)
8433714881SJeremy Kerr 			return be32_to_cpup(ip);
8597e873e5SStephen Rothwell 	} while (np->parent);
8697e873e5SStephen Rothwell 	/* No #size-cells property for the root node */
8797e873e5SStephen Rothwell 	return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
8897e873e5SStephen Rothwell }
8997e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_size_cells);
9097e873e5SStephen Rothwell 
91923f7e30SGrant Likely #if !defined(CONFIG_SPARC)   /* SPARC doesn't do ref counting (yet) */
92923f7e30SGrant Likely /**
93923f7e30SGrant Likely  *	of_node_get - Increment refcount of a node
94923f7e30SGrant Likely  *	@node:	Node to inc refcount, NULL is supported to
95923f7e30SGrant Likely  *		simplify writing of callers
96923f7e30SGrant Likely  *
97923f7e30SGrant Likely  *	Returns node.
98923f7e30SGrant Likely  */
99923f7e30SGrant Likely struct device_node *of_node_get(struct device_node *node)
100923f7e30SGrant Likely {
101923f7e30SGrant Likely 	if (node)
102923f7e30SGrant Likely 		kref_get(&node->kref);
103923f7e30SGrant Likely 	return node;
104923f7e30SGrant Likely }
105923f7e30SGrant Likely EXPORT_SYMBOL(of_node_get);
106923f7e30SGrant Likely 
107923f7e30SGrant Likely static inline struct device_node *kref_to_device_node(struct kref *kref)
108923f7e30SGrant Likely {
109923f7e30SGrant Likely 	return container_of(kref, struct device_node, kref);
110923f7e30SGrant Likely }
111923f7e30SGrant Likely 
112923f7e30SGrant Likely /**
113923f7e30SGrant Likely  *	of_node_release - release a dynamically allocated node
114923f7e30SGrant Likely  *	@kref:  kref element of the node to be released
115923f7e30SGrant Likely  *
116923f7e30SGrant Likely  *	In of_node_put() this function is passed to kref_put()
117923f7e30SGrant Likely  *	as the destructor.
118923f7e30SGrant Likely  */
119923f7e30SGrant Likely static void of_node_release(struct kref *kref)
120923f7e30SGrant Likely {
121923f7e30SGrant Likely 	struct device_node *node = kref_to_device_node(kref);
122923f7e30SGrant Likely 	struct property *prop = node->properties;
123923f7e30SGrant Likely 
124923f7e30SGrant Likely 	/* We should never be releasing nodes that haven't been detached. */
125923f7e30SGrant Likely 	if (!of_node_check_flag(node, OF_DETACHED)) {
126923f7e30SGrant Likely 		pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name);
127923f7e30SGrant Likely 		dump_stack();
128923f7e30SGrant Likely 		kref_init(&node->kref);
129923f7e30SGrant Likely 		return;
130923f7e30SGrant Likely 	}
131923f7e30SGrant Likely 
132923f7e30SGrant Likely 	if (!of_node_check_flag(node, OF_DYNAMIC))
133923f7e30SGrant Likely 		return;
134923f7e30SGrant Likely 
135923f7e30SGrant Likely 	while (prop) {
136923f7e30SGrant Likely 		struct property *next = prop->next;
137923f7e30SGrant Likely 		kfree(prop->name);
138923f7e30SGrant Likely 		kfree(prop->value);
139923f7e30SGrant Likely 		kfree(prop);
140923f7e30SGrant Likely 		prop = next;
141923f7e30SGrant Likely 
142923f7e30SGrant Likely 		if (!prop) {
143923f7e30SGrant Likely 			prop = node->deadprops;
144923f7e30SGrant Likely 			node->deadprops = NULL;
145923f7e30SGrant Likely 		}
146923f7e30SGrant Likely 	}
147923f7e30SGrant Likely 	kfree(node->full_name);
148923f7e30SGrant Likely 	kfree(node->data);
149923f7e30SGrant Likely 	kfree(node);
150923f7e30SGrant Likely }
151923f7e30SGrant Likely 
152923f7e30SGrant Likely /**
153923f7e30SGrant Likely  *	of_node_put - Decrement refcount of a node
154923f7e30SGrant Likely  *	@node:	Node to dec refcount, NULL is supported to
155923f7e30SGrant Likely  *		simplify writing of callers
156923f7e30SGrant Likely  *
157923f7e30SGrant Likely  */
158923f7e30SGrant Likely void of_node_put(struct device_node *node)
159923f7e30SGrant Likely {
160923f7e30SGrant Likely 	if (node)
161923f7e30SGrant Likely 		kref_put(&node->kref, of_node_release);
162923f7e30SGrant Likely }
163923f7e30SGrant Likely EXPORT_SYMBOL(of_node_put);
164923f7e30SGrant Likely #endif /* !CONFIG_SPARC */
165923f7e30SGrant Likely 
166581b605aSStephen Rothwell struct property *of_find_property(const struct device_node *np,
167581b605aSStephen Rothwell 				  const char *name,
168581b605aSStephen Rothwell 				  int *lenp)
169581b605aSStephen Rothwell {
170581b605aSStephen Rothwell 	struct property *pp;
171581b605aSStephen Rothwell 
17264e4566fSTimur Tabi 	if (!np)
17364e4566fSTimur Tabi 		return NULL;
17464e4566fSTimur Tabi 
175581b605aSStephen Rothwell 	read_lock(&devtree_lock);
176581b605aSStephen Rothwell 	for (pp = np->properties; pp != 0; pp = pp->next) {
177581b605aSStephen Rothwell 		if (of_prop_cmp(pp->name, name) == 0) {
178581b605aSStephen Rothwell 			if (lenp != 0)
179581b605aSStephen Rothwell 				*lenp = pp->length;
180581b605aSStephen Rothwell 			break;
181581b605aSStephen Rothwell 		}
182581b605aSStephen Rothwell 	}
183581b605aSStephen Rothwell 	read_unlock(&devtree_lock);
184581b605aSStephen Rothwell 
185581b605aSStephen Rothwell 	return pp;
186581b605aSStephen Rothwell }
187581b605aSStephen Rothwell EXPORT_SYMBOL(of_find_property);
188581b605aSStephen Rothwell 
189e91edcf5SGrant Likely /**
190e91edcf5SGrant Likely  * of_find_all_nodes - Get next node in global list
191e91edcf5SGrant Likely  * @prev:	Previous node or NULL to start iteration
192e91edcf5SGrant Likely  *		of_node_put() will be called on it
193e91edcf5SGrant Likely  *
194e91edcf5SGrant Likely  * Returns a node pointer with refcount incremented, use
195e91edcf5SGrant Likely  * of_node_put() on it when done.
196e91edcf5SGrant Likely  */
197e91edcf5SGrant Likely struct device_node *of_find_all_nodes(struct device_node *prev)
198e91edcf5SGrant Likely {
199e91edcf5SGrant Likely 	struct device_node *np;
200e91edcf5SGrant Likely 
201e91edcf5SGrant Likely 	read_lock(&devtree_lock);
202e91edcf5SGrant Likely 	np = prev ? prev->allnext : allnodes;
203e91edcf5SGrant Likely 	for (; np != NULL; np = np->allnext)
204e91edcf5SGrant Likely 		if (of_node_get(np))
205e91edcf5SGrant Likely 			break;
206e91edcf5SGrant Likely 	of_node_put(prev);
207e91edcf5SGrant Likely 	read_unlock(&devtree_lock);
208e91edcf5SGrant Likely 	return np;
209e91edcf5SGrant Likely }
210e91edcf5SGrant Likely EXPORT_SYMBOL(of_find_all_nodes);
211e91edcf5SGrant Likely 
21297e873e5SStephen Rothwell /*
21397e873e5SStephen Rothwell  * Find a property with a given name for a given node
21497e873e5SStephen Rothwell  * and return the value.
21597e873e5SStephen Rothwell  */
21697e873e5SStephen Rothwell const void *of_get_property(const struct device_node *np, const char *name,
21797e873e5SStephen Rothwell 			 int *lenp)
21897e873e5SStephen Rothwell {
21997e873e5SStephen Rothwell 	struct property *pp = of_find_property(np, name, lenp);
22097e873e5SStephen Rothwell 
22197e873e5SStephen Rothwell 	return pp ? pp->value : NULL;
22297e873e5SStephen Rothwell }
22397e873e5SStephen Rothwell EXPORT_SYMBOL(of_get_property);
2240081cbc3SStephen Rothwell 
2250081cbc3SStephen Rothwell /** Checks if the given "compat" string matches one of the strings in
2260081cbc3SStephen Rothwell  * the device's "compatible" property
2270081cbc3SStephen Rothwell  */
2280081cbc3SStephen Rothwell int of_device_is_compatible(const struct device_node *device,
2290081cbc3SStephen Rothwell 		const char *compat)
2300081cbc3SStephen Rothwell {
2310081cbc3SStephen Rothwell 	const char* cp;
2320081cbc3SStephen Rothwell 	int cplen, l;
2330081cbc3SStephen Rothwell 
2340081cbc3SStephen Rothwell 	cp = of_get_property(device, "compatible", &cplen);
2350081cbc3SStephen Rothwell 	if (cp == NULL)
2360081cbc3SStephen Rothwell 		return 0;
2370081cbc3SStephen Rothwell 	while (cplen > 0) {
2380081cbc3SStephen Rothwell 		if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
2390081cbc3SStephen Rothwell 			return 1;
2400081cbc3SStephen Rothwell 		l = strlen(cp) + 1;
2410081cbc3SStephen Rothwell 		cp += l;
2420081cbc3SStephen Rothwell 		cplen -= l;
2430081cbc3SStephen Rothwell 	}
2440081cbc3SStephen Rothwell 
2450081cbc3SStephen Rothwell 	return 0;
2460081cbc3SStephen Rothwell }
2470081cbc3SStephen Rothwell EXPORT_SYMBOL(of_device_is_compatible);
248e679c5f4SStephen Rothwell 
249e679c5f4SStephen Rothwell /**
25071a157e8SGrant Likely  * of_machine_is_compatible - Test root of device tree for a given compatible value
2511f43cfb9SGrant Likely  * @compat: compatible string to look for in root node's compatible property.
2521f43cfb9SGrant Likely  *
2531f43cfb9SGrant Likely  * Returns true if the root node has the given value in its
2541f43cfb9SGrant Likely  * compatible property.
2551f43cfb9SGrant Likely  */
25671a157e8SGrant Likely int of_machine_is_compatible(const char *compat)
2571f43cfb9SGrant Likely {
2581f43cfb9SGrant Likely 	struct device_node *root;
2591f43cfb9SGrant Likely 	int rc = 0;
2601f43cfb9SGrant Likely 
2611f43cfb9SGrant Likely 	root = of_find_node_by_path("/");
2621f43cfb9SGrant Likely 	if (root) {
2631f43cfb9SGrant Likely 		rc = of_device_is_compatible(root, compat);
2641f43cfb9SGrant Likely 		of_node_put(root);
2651f43cfb9SGrant Likely 	}
2661f43cfb9SGrant Likely 	return rc;
2671f43cfb9SGrant Likely }
26871a157e8SGrant Likely EXPORT_SYMBOL(of_machine_is_compatible);
2691f43cfb9SGrant Likely 
2701f43cfb9SGrant Likely /**
271834d97d4SJosh Boyer  *  of_device_is_available - check if a device is available for use
272834d97d4SJosh Boyer  *
273834d97d4SJosh Boyer  *  @device: Node to check for availability
274834d97d4SJosh Boyer  *
275834d97d4SJosh Boyer  *  Returns 1 if the status property is absent or set to "okay" or "ok",
276834d97d4SJosh Boyer  *  0 otherwise
277834d97d4SJosh Boyer  */
278834d97d4SJosh Boyer int of_device_is_available(const struct device_node *device)
279834d97d4SJosh Boyer {
280834d97d4SJosh Boyer 	const char *status;
281834d97d4SJosh Boyer 	int statlen;
282834d97d4SJosh Boyer 
283834d97d4SJosh Boyer 	status = of_get_property(device, "status", &statlen);
284834d97d4SJosh Boyer 	if (status == NULL)
285834d97d4SJosh Boyer 		return 1;
286834d97d4SJosh Boyer 
287834d97d4SJosh Boyer 	if (statlen > 0) {
288834d97d4SJosh Boyer 		if (!strcmp(status, "okay") || !strcmp(status, "ok"))
289834d97d4SJosh Boyer 			return 1;
290834d97d4SJosh Boyer 	}
291834d97d4SJosh Boyer 
292834d97d4SJosh Boyer 	return 0;
293834d97d4SJosh Boyer }
294834d97d4SJosh Boyer EXPORT_SYMBOL(of_device_is_available);
295834d97d4SJosh Boyer 
296834d97d4SJosh Boyer /**
297e679c5f4SStephen Rothwell  *	of_get_parent - Get a node's parent if any
298e679c5f4SStephen Rothwell  *	@node:	Node to get parent
299e679c5f4SStephen Rothwell  *
300e679c5f4SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
301e679c5f4SStephen Rothwell  *	of_node_put() on it when done.
302e679c5f4SStephen Rothwell  */
303e679c5f4SStephen Rothwell struct device_node *of_get_parent(const struct device_node *node)
304e679c5f4SStephen Rothwell {
305e679c5f4SStephen Rothwell 	struct device_node *np;
306e679c5f4SStephen Rothwell 
307e679c5f4SStephen Rothwell 	if (!node)
308e679c5f4SStephen Rothwell 		return NULL;
309e679c5f4SStephen Rothwell 
310e679c5f4SStephen Rothwell 	read_lock(&devtree_lock);
311e679c5f4SStephen Rothwell 	np = of_node_get(node->parent);
312e679c5f4SStephen Rothwell 	read_unlock(&devtree_lock);
313e679c5f4SStephen Rothwell 	return np;
314e679c5f4SStephen Rothwell }
315e679c5f4SStephen Rothwell EXPORT_SYMBOL(of_get_parent);
316d1cd355aSStephen Rothwell 
317d1cd355aSStephen Rothwell /**
318f4eb0107SMichael Ellerman  *	of_get_next_parent - Iterate to a node's parent
319f4eb0107SMichael Ellerman  *	@node:	Node to get parent of
320f4eb0107SMichael Ellerman  *
321f4eb0107SMichael Ellerman  * 	This is like of_get_parent() except that it drops the
322f4eb0107SMichael Ellerman  * 	refcount on the passed node, making it suitable for iterating
323f4eb0107SMichael Ellerman  * 	through a node's parents.
324f4eb0107SMichael Ellerman  *
325f4eb0107SMichael Ellerman  *	Returns a node pointer with refcount incremented, use
326f4eb0107SMichael Ellerman  *	of_node_put() on it when done.
327f4eb0107SMichael Ellerman  */
328f4eb0107SMichael Ellerman struct device_node *of_get_next_parent(struct device_node *node)
329f4eb0107SMichael Ellerman {
330f4eb0107SMichael Ellerman 	struct device_node *parent;
331f4eb0107SMichael Ellerman 
332f4eb0107SMichael Ellerman 	if (!node)
333f4eb0107SMichael Ellerman 		return NULL;
334f4eb0107SMichael Ellerman 
335f4eb0107SMichael Ellerman 	read_lock(&devtree_lock);
336f4eb0107SMichael Ellerman 	parent = of_node_get(node->parent);
337f4eb0107SMichael Ellerman 	of_node_put(node);
338f4eb0107SMichael Ellerman 	read_unlock(&devtree_lock);
339f4eb0107SMichael Ellerman 	return parent;
340f4eb0107SMichael Ellerman }
341f4eb0107SMichael Ellerman 
342f4eb0107SMichael Ellerman /**
343d1cd355aSStephen Rothwell  *	of_get_next_child - Iterate a node childs
344d1cd355aSStephen Rothwell  *	@node:	parent node
345d1cd355aSStephen Rothwell  *	@prev:	previous child of the parent node, or NULL to get first
346d1cd355aSStephen Rothwell  *
347d1cd355aSStephen Rothwell  *	Returns a node pointer with refcount incremented, use
348d1cd355aSStephen Rothwell  *	of_node_put() on it when done.
349d1cd355aSStephen Rothwell  */
350d1cd355aSStephen Rothwell struct device_node *of_get_next_child(const struct device_node *node,
351d1cd355aSStephen Rothwell 	struct device_node *prev)
352d1cd355aSStephen Rothwell {
353d1cd355aSStephen Rothwell 	struct device_node *next;
354d1cd355aSStephen Rothwell 
355d1cd355aSStephen Rothwell 	read_lock(&devtree_lock);
356d1cd355aSStephen Rothwell 	next = prev ? prev->sibling : node->child;
357d1cd355aSStephen Rothwell 	for (; next; next = next->sibling)
358d1cd355aSStephen Rothwell 		if (of_node_get(next))
359d1cd355aSStephen Rothwell 			break;
360d1cd355aSStephen Rothwell 	of_node_put(prev);
361d1cd355aSStephen Rothwell 	read_unlock(&devtree_lock);
362d1cd355aSStephen Rothwell 	return next;
363d1cd355aSStephen Rothwell }
364d1cd355aSStephen Rothwell EXPORT_SYMBOL(of_get_next_child);
3651ef4d424SStephen Rothwell 
3661ef4d424SStephen Rothwell /**
3671ef4d424SStephen Rothwell  *	of_find_node_by_path - Find a node matching a full OF path
3681ef4d424SStephen Rothwell  *	@path:	The full path to match
3691ef4d424SStephen Rothwell  *
3701ef4d424SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
3711ef4d424SStephen Rothwell  *	of_node_put() on it when done.
3721ef4d424SStephen Rothwell  */
3731ef4d424SStephen Rothwell struct device_node *of_find_node_by_path(const char *path)
3741ef4d424SStephen Rothwell {
3751ef4d424SStephen Rothwell 	struct device_node *np = allnodes;
3761ef4d424SStephen Rothwell 
3771ef4d424SStephen Rothwell 	read_lock(&devtree_lock);
3781ef4d424SStephen Rothwell 	for (; np; np = np->allnext) {
3791ef4d424SStephen Rothwell 		if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
3801ef4d424SStephen Rothwell 		    && of_node_get(np))
3811ef4d424SStephen Rothwell 			break;
3821ef4d424SStephen Rothwell 	}
3831ef4d424SStephen Rothwell 	read_unlock(&devtree_lock);
3841ef4d424SStephen Rothwell 	return np;
3851ef4d424SStephen Rothwell }
3861ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_path);
3871ef4d424SStephen Rothwell 
3881ef4d424SStephen Rothwell /**
3891ef4d424SStephen Rothwell  *	of_find_node_by_name - Find a node by its "name" property
3901ef4d424SStephen Rothwell  *	@from:	The node to start searching from or NULL, the node
3911ef4d424SStephen Rothwell  *		you pass will not be searched, only the next one
3921ef4d424SStephen Rothwell  *		will; typically, you pass what the previous call
3931ef4d424SStephen Rothwell  *		returned. of_node_put() will be called on it
3941ef4d424SStephen Rothwell  *	@name:	The name string to match against
3951ef4d424SStephen Rothwell  *
3961ef4d424SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
3971ef4d424SStephen Rothwell  *	of_node_put() on it when done.
3981ef4d424SStephen Rothwell  */
3991ef4d424SStephen Rothwell struct device_node *of_find_node_by_name(struct device_node *from,
4001ef4d424SStephen Rothwell 	const char *name)
4011ef4d424SStephen Rothwell {
4021ef4d424SStephen Rothwell 	struct device_node *np;
4031ef4d424SStephen Rothwell 
4041ef4d424SStephen Rothwell 	read_lock(&devtree_lock);
4051ef4d424SStephen Rothwell 	np = from ? from->allnext : allnodes;
4061ef4d424SStephen Rothwell 	for (; np; np = np->allnext)
4071ef4d424SStephen Rothwell 		if (np->name && (of_node_cmp(np->name, name) == 0)
4081ef4d424SStephen Rothwell 		    && of_node_get(np))
4091ef4d424SStephen Rothwell 			break;
4101ef4d424SStephen Rothwell 	of_node_put(from);
4111ef4d424SStephen Rothwell 	read_unlock(&devtree_lock);
4121ef4d424SStephen Rothwell 	return np;
4131ef4d424SStephen Rothwell }
4141ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_name);
4151ef4d424SStephen Rothwell 
4161ef4d424SStephen Rothwell /**
4171ef4d424SStephen Rothwell  *	of_find_node_by_type - Find a node by its "device_type" property
4181ef4d424SStephen Rothwell  *	@from:	The node to start searching from, or NULL to start searching
4191ef4d424SStephen Rothwell  *		the entire device tree. The node you pass will not be
4201ef4d424SStephen Rothwell  *		searched, only the next one will; typically, you pass
4211ef4d424SStephen Rothwell  *		what the previous call returned. of_node_put() will be
4221ef4d424SStephen Rothwell  *		called on from for you.
4231ef4d424SStephen Rothwell  *	@type:	The type string to match against
4241ef4d424SStephen Rothwell  *
4251ef4d424SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
4261ef4d424SStephen Rothwell  *	of_node_put() on it when done.
4271ef4d424SStephen Rothwell  */
4281ef4d424SStephen Rothwell struct device_node *of_find_node_by_type(struct device_node *from,
4291ef4d424SStephen Rothwell 	const char *type)
4301ef4d424SStephen Rothwell {
4311ef4d424SStephen Rothwell 	struct device_node *np;
4321ef4d424SStephen Rothwell 
4331ef4d424SStephen Rothwell 	read_lock(&devtree_lock);
4341ef4d424SStephen Rothwell 	np = from ? from->allnext : allnodes;
4351ef4d424SStephen Rothwell 	for (; np; np = np->allnext)
4361ef4d424SStephen Rothwell 		if (np->type && (of_node_cmp(np->type, type) == 0)
4371ef4d424SStephen Rothwell 		    && of_node_get(np))
4381ef4d424SStephen Rothwell 			break;
4391ef4d424SStephen Rothwell 	of_node_put(from);
4401ef4d424SStephen Rothwell 	read_unlock(&devtree_lock);
4411ef4d424SStephen Rothwell 	return np;
4421ef4d424SStephen Rothwell }
4431ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_type);
4441ef4d424SStephen Rothwell 
4451ef4d424SStephen Rothwell /**
4461ef4d424SStephen Rothwell  *	of_find_compatible_node - Find a node based on type and one of the
4471ef4d424SStephen Rothwell  *                                tokens in its "compatible" property
4481ef4d424SStephen Rothwell  *	@from:		The node to start searching from or NULL, the node
4491ef4d424SStephen Rothwell  *			you pass will not be searched, only the next one
4501ef4d424SStephen Rothwell  *			will; typically, you pass what the previous call
4511ef4d424SStephen Rothwell  *			returned. of_node_put() will be called on it
4521ef4d424SStephen Rothwell  *	@type:		The type string to match "device_type" or NULL to ignore
4531ef4d424SStephen Rothwell  *	@compatible:	The string to match to one of the tokens in the device
4541ef4d424SStephen Rothwell  *			"compatible" list.
4551ef4d424SStephen Rothwell  *
4561ef4d424SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
4571ef4d424SStephen Rothwell  *	of_node_put() on it when done.
4581ef4d424SStephen Rothwell  */
4591ef4d424SStephen Rothwell struct device_node *of_find_compatible_node(struct device_node *from,
4601ef4d424SStephen Rothwell 	const char *type, const char *compatible)
4611ef4d424SStephen Rothwell {
4621ef4d424SStephen Rothwell 	struct device_node *np;
4631ef4d424SStephen Rothwell 
4641ef4d424SStephen Rothwell 	read_lock(&devtree_lock);
4651ef4d424SStephen Rothwell 	np = from ? from->allnext : allnodes;
4661ef4d424SStephen Rothwell 	for (; np; np = np->allnext) {
4671ef4d424SStephen Rothwell 		if (type
4681ef4d424SStephen Rothwell 		    && !(np->type && (of_node_cmp(np->type, type) == 0)))
4691ef4d424SStephen Rothwell 			continue;
4701ef4d424SStephen Rothwell 		if (of_device_is_compatible(np, compatible) && of_node_get(np))
4711ef4d424SStephen Rothwell 			break;
4721ef4d424SStephen Rothwell 	}
4731ef4d424SStephen Rothwell 	of_node_put(from);
4741ef4d424SStephen Rothwell 	read_unlock(&devtree_lock);
4751ef4d424SStephen Rothwell 	return np;
4761ef4d424SStephen Rothwell }
4771ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_compatible_node);
478283029d1SGrant Likely 
479283029d1SGrant Likely /**
4801e291b14SMichael Ellerman  *	of_find_node_with_property - Find a node which has a property with
4811e291b14SMichael Ellerman  *                                   the given name.
4821e291b14SMichael Ellerman  *	@from:		The node to start searching from or NULL, the node
4831e291b14SMichael Ellerman  *			you pass will not be searched, only the next one
4841e291b14SMichael Ellerman  *			will; typically, you pass what the previous call
4851e291b14SMichael Ellerman  *			returned. of_node_put() will be called on it
4861e291b14SMichael Ellerman  *	@prop_name:	The name of the property to look for.
4871e291b14SMichael Ellerman  *
4881e291b14SMichael Ellerman  *	Returns a node pointer with refcount incremented, use
4891e291b14SMichael Ellerman  *	of_node_put() on it when done.
4901e291b14SMichael Ellerman  */
4911e291b14SMichael Ellerman struct device_node *of_find_node_with_property(struct device_node *from,
4921e291b14SMichael Ellerman 	const char *prop_name)
4931e291b14SMichael Ellerman {
4941e291b14SMichael Ellerman 	struct device_node *np;
4951e291b14SMichael Ellerman 	struct property *pp;
4961e291b14SMichael Ellerman 
4971e291b14SMichael Ellerman 	read_lock(&devtree_lock);
4981e291b14SMichael Ellerman 	np = from ? from->allnext : allnodes;
4991e291b14SMichael Ellerman 	for (; np; np = np->allnext) {
5001e291b14SMichael Ellerman 		for (pp = np->properties; pp != 0; pp = pp->next) {
5011e291b14SMichael Ellerman 			if (of_prop_cmp(pp->name, prop_name) == 0) {
5021e291b14SMichael Ellerman 				of_node_get(np);
5031e291b14SMichael Ellerman 				goto out;
5041e291b14SMichael Ellerman 			}
5051e291b14SMichael Ellerman 		}
5061e291b14SMichael Ellerman 	}
5071e291b14SMichael Ellerman out:
5081e291b14SMichael Ellerman 	of_node_put(from);
5091e291b14SMichael Ellerman 	read_unlock(&devtree_lock);
5101e291b14SMichael Ellerman 	return np;
5111e291b14SMichael Ellerman }
5121e291b14SMichael Ellerman EXPORT_SYMBOL(of_find_node_with_property);
5131e291b14SMichael Ellerman 
5141e291b14SMichael Ellerman /**
515283029d1SGrant Likely  * of_match_node - Tell if an device_node has a matching of_match structure
516283029d1SGrant Likely  *	@matches:	array of of device match structures to search in
517283029d1SGrant Likely  *	@node:		the of device structure to match against
518283029d1SGrant Likely  *
519283029d1SGrant Likely  *	Low level utility function used by device matching.
520283029d1SGrant Likely  */
521283029d1SGrant Likely const struct of_device_id *of_match_node(const struct of_device_id *matches,
522283029d1SGrant Likely 					 const struct device_node *node)
523283029d1SGrant Likely {
524a52f07ecSGrant Likely 	if (!matches)
525a52f07ecSGrant Likely 		return NULL;
526a52f07ecSGrant Likely 
527283029d1SGrant Likely 	while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
528283029d1SGrant Likely 		int match = 1;
529283029d1SGrant Likely 		if (matches->name[0])
530283029d1SGrant Likely 			match &= node->name
531283029d1SGrant Likely 				&& !strcmp(matches->name, node->name);
532283029d1SGrant Likely 		if (matches->type[0])
533283029d1SGrant Likely 			match &= node->type
534283029d1SGrant Likely 				&& !strcmp(matches->type, node->type);
535283029d1SGrant Likely 		if (matches->compatible[0])
536283029d1SGrant Likely 			match &= of_device_is_compatible(node,
537283029d1SGrant Likely 						matches->compatible);
538283029d1SGrant Likely 		if (match)
539283029d1SGrant Likely 			return matches;
540283029d1SGrant Likely 		matches++;
541283029d1SGrant Likely 	}
542283029d1SGrant Likely 	return NULL;
543283029d1SGrant Likely }
544283029d1SGrant Likely EXPORT_SYMBOL(of_match_node);
545283029d1SGrant Likely 
546283029d1SGrant Likely /**
547283029d1SGrant Likely  *	of_find_matching_node - Find a node based on an of_device_id match
548283029d1SGrant Likely  *				table.
549283029d1SGrant Likely  *	@from:		The node to start searching from or NULL, the node
550283029d1SGrant Likely  *			you pass will not be searched, only the next one
551283029d1SGrant Likely  *			will; typically, you pass what the previous call
552283029d1SGrant Likely  *			returned. of_node_put() will be called on it
553283029d1SGrant Likely  *	@matches:	array of of device match structures to search in
554283029d1SGrant Likely  *
555283029d1SGrant Likely  *	Returns a node pointer with refcount incremented, use
556283029d1SGrant Likely  *	of_node_put() on it when done.
557283029d1SGrant Likely  */
558283029d1SGrant Likely struct device_node *of_find_matching_node(struct device_node *from,
559283029d1SGrant Likely 					  const struct of_device_id *matches)
560283029d1SGrant Likely {
561283029d1SGrant Likely 	struct device_node *np;
562283029d1SGrant Likely 
563283029d1SGrant Likely 	read_lock(&devtree_lock);
564283029d1SGrant Likely 	np = from ? from->allnext : allnodes;
565283029d1SGrant Likely 	for (; np; np = np->allnext) {
566283029d1SGrant Likely 		if (of_match_node(matches, np) && of_node_get(np))
567283029d1SGrant Likely 			break;
568283029d1SGrant Likely 	}
569283029d1SGrant Likely 	of_node_put(from);
570283029d1SGrant Likely 	read_unlock(&devtree_lock);
571283029d1SGrant Likely 	return np;
572283029d1SGrant Likely }
573283029d1SGrant Likely EXPORT_SYMBOL(of_find_matching_node);
5743f07af49SGrant Likely 
5753f07af49SGrant Likely /**
5763f07af49SGrant Likely  * of_modalias_node - Lookup appropriate modalias for a device node
5773f07af49SGrant Likely  * @node:	pointer to a device tree node
5783f07af49SGrant Likely  * @modalias:	Pointer to buffer that modalias value will be copied into
5793f07af49SGrant Likely  * @len:	Length of modalias value
5803f07af49SGrant Likely  *
5812ffe8c5fSGrant Likely  * Based on the value of the compatible property, this routine will attempt
5822ffe8c5fSGrant Likely  * to choose an appropriate modalias value for a particular device tree node.
5832ffe8c5fSGrant Likely  * It does this by stripping the manufacturer prefix (as delimited by a ',')
5842ffe8c5fSGrant Likely  * from the first entry in the compatible list property.
5853f07af49SGrant Likely  *
5862ffe8c5fSGrant Likely  * This routine returns 0 on success, <0 on failure.
5873f07af49SGrant Likely  */
5883f07af49SGrant Likely int of_modalias_node(struct device_node *node, char *modalias, int len)
5893f07af49SGrant Likely {
5902ffe8c5fSGrant Likely 	const char *compatible, *p;
5912ffe8c5fSGrant Likely 	int cplen;
5923f07af49SGrant Likely 
5933f07af49SGrant Likely 	compatible = of_get_property(node, "compatible", &cplen);
5942ffe8c5fSGrant Likely 	if (!compatible || strlen(compatible) > cplen)
5953f07af49SGrant Likely 		return -ENODEV;
5963f07af49SGrant Likely 	p = strchr(compatible, ',');
5972ffe8c5fSGrant Likely 	strlcpy(modalias, p ? p + 1 : compatible, len);
5983f07af49SGrant Likely 	return 0;
5993f07af49SGrant Likely }
6003f07af49SGrant Likely EXPORT_SYMBOL_GPL(of_modalias_node);
6013f07af49SGrant Likely 
60264b60e09SAnton Vorontsov /**
60389751a7cSJeremy Kerr  * of_find_node_by_phandle - Find a node given a phandle
60489751a7cSJeremy Kerr  * @handle:	phandle of the node to find
60589751a7cSJeremy Kerr  *
60689751a7cSJeremy Kerr  * Returns a node pointer with refcount incremented, use
60789751a7cSJeremy Kerr  * of_node_put() on it when done.
60889751a7cSJeremy Kerr  */
60989751a7cSJeremy Kerr struct device_node *of_find_node_by_phandle(phandle handle)
61089751a7cSJeremy Kerr {
61189751a7cSJeremy Kerr 	struct device_node *np;
61289751a7cSJeremy Kerr 
61389751a7cSJeremy Kerr 	read_lock(&devtree_lock);
61489751a7cSJeremy Kerr 	for (np = allnodes; np; np = np->allnext)
61589751a7cSJeremy Kerr 		if (np->phandle == handle)
61689751a7cSJeremy Kerr 			break;
61789751a7cSJeremy Kerr 	of_node_get(np);
61889751a7cSJeremy Kerr 	read_unlock(&devtree_lock);
61989751a7cSJeremy Kerr 	return np;
62089751a7cSJeremy Kerr }
62189751a7cSJeremy Kerr EXPORT_SYMBOL(of_find_node_by_phandle);
62289751a7cSJeremy Kerr 
62389751a7cSJeremy Kerr /**
6240e373639SRob Herring  * of_property_read_u32_array - Find and read an array of 32 bit integers
6250e373639SRob Herring  * from a property.
6260e373639SRob Herring  *
627a3b85363SThomas Abraham  * @np:		device node from which the property value is to be read.
628a3b85363SThomas Abraham  * @propname:	name of the property to be searched.
629a3b85363SThomas Abraham  * @out_value:	pointer to return value, modified only if return value is 0.
630a3b85363SThomas Abraham  *
6310e373639SRob Herring  * Search for a property in a device node and read 32-bit value(s) from
632a3b85363SThomas Abraham  * it. Returns 0 on success, -EINVAL if the property does not exist,
633a3b85363SThomas Abraham  * -ENODATA if property does not have a value, and -EOVERFLOW if the
634a3b85363SThomas Abraham  * property data isn't large enough.
635a3b85363SThomas Abraham  *
636a3b85363SThomas Abraham  * The out_value is modified only if a valid u32 value can be decoded.
637a3b85363SThomas Abraham  */
638aac285c6SJamie Iles int of_property_read_u32_array(const struct device_node *np,
639aac285c6SJamie Iles 			       const char *propname, u32 *out_values,
640aac285c6SJamie Iles 			       size_t sz)
641a3b85363SThomas Abraham {
642a3b85363SThomas Abraham 	struct property *prop = of_find_property(np, propname, NULL);
6430e373639SRob Herring 	const __be32 *val;
644a3b85363SThomas Abraham 
645a3b85363SThomas Abraham 	if (!prop)
646a3b85363SThomas Abraham 		return -EINVAL;
647a3b85363SThomas Abraham 	if (!prop->value)
648a3b85363SThomas Abraham 		return -ENODATA;
6490e373639SRob Herring 	if ((sz * sizeof(*out_values)) > prop->length)
650a3b85363SThomas Abraham 		return -EOVERFLOW;
6510e373639SRob Herring 
6520e373639SRob Herring 	val = prop->value;
6530e373639SRob Herring 	while (sz--)
6540e373639SRob Herring 		*out_values++ = be32_to_cpup(val++);
655a3b85363SThomas Abraham 	return 0;
656a3b85363SThomas Abraham }
6570e373639SRob Herring EXPORT_SYMBOL_GPL(of_property_read_u32_array);
658a3b85363SThomas Abraham 
659a3b85363SThomas Abraham /**
6604cd7f7a3SJamie Iles  * of_property_read_u64 - Find and read a 64 bit integer from a property
6614cd7f7a3SJamie Iles  * @np:		device node from which the property value is to be read.
6624cd7f7a3SJamie Iles  * @propname:	name of the property to be searched.
6634cd7f7a3SJamie Iles  * @out_value:	pointer to return value, modified only if return value is 0.
6644cd7f7a3SJamie Iles  *
6654cd7f7a3SJamie Iles  * Search for a property in a device node and read a 64-bit value from
6664cd7f7a3SJamie Iles  * it. Returns 0 on success, -EINVAL if the property does not exist,
6674cd7f7a3SJamie Iles  * -ENODATA if property does not have a value, and -EOVERFLOW if the
6684cd7f7a3SJamie Iles  * property data isn't large enough.
6694cd7f7a3SJamie Iles  *
6704cd7f7a3SJamie Iles  * The out_value is modified only if a valid u64 value can be decoded.
6714cd7f7a3SJamie Iles  */
6724cd7f7a3SJamie Iles int of_property_read_u64(const struct device_node *np, const char *propname,
6734cd7f7a3SJamie Iles 			 u64 *out_value)
6744cd7f7a3SJamie Iles {
6754cd7f7a3SJamie Iles 	struct property *prop = of_find_property(np, propname, NULL);
6764cd7f7a3SJamie Iles 
6774cd7f7a3SJamie Iles 	if (!prop)
6784cd7f7a3SJamie Iles 		return -EINVAL;
6794cd7f7a3SJamie Iles 	if (!prop->value)
6804cd7f7a3SJamie Iles 		return -ENODATA;
6814cd7f7a3SJamie Iles 	if (sizeof(*out_value) > prop->length)
6824cd7f7a3SJamie Iles 		return -EOVERFLOW;
6834cd7f7a3SJamie Iles 	*out_value = of_read_number(prop->value, 2);
6844cd7f7a3SJamie Iles 	return 0;
6854cd7f7a3SJamie Iles }
6864cd7f7a3SJamie Iles EXPORT_SYMBOL_GPL(of_property_read_u64);
6874cd7f7a3SJamie Iles 
6884cd7f7a3SJamie Iles /**
689a3b85363SThomas Abraham  * of_property_read_string - Find and read a string from a property
690a3b85363SThomas Abraham  * @np:		device node from which the property value is to be read.
691a3b85363SThomas Abraham  * @propname:	name of the property to be searched.
692a3b85363SThomas Abraham  * @out_string:	pointer to null terminated return string, modified only if
693a3b85363SThomas Abraham  *		return value is 0.
694a3b85363SThomas Abraham  *
695a3b85363SThomas Abraham  * Search for a property in a device tree node and retrieve a null
696a3b85363SThomas Abraham  * terminated string value (pointer to data, not a copy). Returns 0 on
697a3b85363SThomas Abraham  * success, -EINVAL if the property does not exist, -ENODATA if property
698a3b85363SThomas Abraham  * does not have a value, and -EILSEQ if the string is not null-terminated
699a3b85363SThomas Abraham  * within the length of the property data.
700a3b85363SThomas Abraham  *
701a3b85363SThomas Abraham  * The out_string pointer is modified only if a valid string can be decoded.
702a3b85363SThomas Abraham  */
703aac285c6SJamie Iles int of_property_read_string(struct device_node *np, const char *propname,
704f09bc831SShawn Guo 				const char **out_string)
705a3b85363SThomas Abraham {
706a3b85363SThomas Abraham 	struct property *prop = of_find_property(np, propname, NULL);
707a3b85363SThomas Abraham 	if (!prop)
708a3b85363SThomas Abraham 		return -EINVAL;
709a3b85363SThomas Abraham 	if (!prop->value)
710a3b85363SThomas Abraham 		return -ENODATA;
711a3b85363SThomas Abraham 	if (strnlen(prop->value, prop->length) >= prop->length)
712a3b85363SThomas Abraham 		return -EILSEQ;
713a3b85363SThomas Abraham 	*out_string = prop->value;
714a3b85363SThomas Abraham 	return 0;
715a3b85363SThomas Abraham }
716a3b85363SThomas Abraham EXPORT_SYMBOL_GPL(of_property_read_string);
717a3b85363SThomas Abraham 
718a3b85363SThomas Abraham /**
719739649c5SGrant Likely  * of_parse_phandle - Resolve a phandle property to a device_node pointer
720739649c5SGrant Likely  * @np: Pointer to device node holding phandle property
721739649c5SGrant Likely  * @phandle_name: Name of property holding a phandle value
722739649c5SGrant Likely  * @index: For properties holding a table of phandles, this is the index into
723739649c5SGrant Likely  *         the table
724739649c5SGrant Likely  *
725739649c5SGrant Likely  * Returns the device_node pointer with refcount incremented.  Use
726739649c5SGrant Likely  * of_node_put() on it when done.
727739649c5SGrant Likely  */
728739649c5SGrant Likely struct device_node *
729739649c5SGrant Likely of_parse_phandle(struct device_node *np, const char *phandle_name, int index)
730739649c5SGrant Likely {
7319a6b2e58SGrant Likely 	const __be32 *phandle;
732739649c5SGrant Likely 	int size;
733739649c5SGrant Likely 
734739649c5SGrant Likely 	phandle = of_get_property(np, phandle_name, &size);
735739649c5SGrant Likely 	if ((!phandle) || (size < sizeof(*phandle) * (index + 1)))
736739649c5SGrant Likely 		return NULL;
737739649c5SGrant Likely 
7389a6b2e58SGrant Likely 	return of_find_node_by_phandle(be32_to_cpup(phandle + index));
739739649c5SGrant Likely }
740739649c5SGrant Likely EXPORT_SYMBOL(of_parse_phandle);
741739649c5SGrant Likely 
742739649c5SGrant Likely /**
74364b60e09SAnton Vorontsov  * of_parse_phandles_with_args - Find a node pointed by phandle in a list
74464b60e09SAnton Vorontsov  * @np:		pointer to a device tree node containing a list
74564b60e09SAnton Vorontsov  * @list_name:	property name that contains a list
74664b60e09SAnton Vorontsov  * @cells_name:	property name that specifies phandles' arguments count
74764b60e09SAnton Vorontsov  * @index:	index of a phandle to parse out
7487736a3dbSAnton Vorontsov  * @out_node:	optional pointer to device_node struct pointer (will be filled)
7497736a3dbSAnton Vorontsov  * @out_args:	optional pointer to arguments pointer (will be filled)
75064b60e09SAnton Vorontsov  *
75164b60e09SAnton Vorontsov  * This function is useful to parse lists of phandles and their arguments.
75264b60e09SAnton Vorontsov  * Returns 0 on success and fills out_node and out_args, on error returns
75364b60e09SAnton Vorontsov  * appropriate errno value.
75464b60e09SAnton Vorontsov  *
75564b60e09SAnton Vorontsov  * Example:
75664b60e09SAnton Vorontsov  *
75764b60e09SAnton Vorontsov  * phandle1: node1 {
75864b60e09SAnton Vorontsov  * 	#list-cells = <2>;
75964b60e09SAnton Vorontsov  * }
76064b60e09SAnton Vorontsov  *
76164b60e09SAnton Vorontsov  * phandle2: node2 {
76264b60e09SAnton Vorontsov  * 	#list-cells = <1>;
76364b60e09SAnton Vorontsov  * }
76464b60e09SAnton Vorontsov  *
76564b60e09SAnton Vorontsov  * node3 {
76664b60e09SAnton Vorontsov  * 	list = <&phandle1 1 2 &phandle2 3>;
76764b60e09SAnton Vorontsov  * }
76864b60e09SAnton Vorontsov  *
76964b60e09SAnton Vorontsov  * To get a device_node of the `node2' node you may call this:
77064b60e09SAnton Vorontsov  * of_parse_phandles_with_args(node3, "list", "#list-cells", 2, &node2, &args);
77164b60e09SAnton Vorontsov  */
77264b60e09SAnton Vorontsov int of_parse_phandles_with_args(struct device_node *np, const char *list_name,
77364b60e09SAnton Vorontsov 				const char *cells_name, int index,
77464b60e09SAnton Vorontsov 				struct device_node **out_node,
77564b60e09SAnton Vorontsov 				const void **out_args)
77664b60e09SAnton Vorontsov {
77764b60e09SAnton Vorontsov 	int ret = -EINVAL;
77833714881SJeremy Kerr 	const __be32 *list;
77933714881SJeremy Kerr 	const __be32 *list_end;
78064b60e09SAnton Vorontsov 	int size;
78164b60e09SAnton Vorontsov 	int cur_index = 0;
78264b60e09SAnton Vorontsov 	struct device_node *node = NULL;
7837736a3dbSAnton Vorontsov 	const void *args = NULL;
78464b60e09SAnton Vorontsov 
78564b60e09SAnton Vorontsov 	list = of_get_property(np, list_name, &size);
78664b60e09SAnton Vorontsov 	if (!list) {
78764b60e09SAnton Vorontsov 		ret = -ENOENT;
78864b60e09SAnton Vorontsov 		goto err0;
78964b60e09SAnton Vorontsov 	}
79064b60e09SAnton Vorontsov 	list_end = list + size / sizeof(*list);
79164b60e09SAnton Vorontsov 
79264b60e09SAnton Vorontsov 	while (list < list_end) {
79333714881SJeremy Kerr 		const __be32 *cells;
7949a6b2e58SGrant Likely 		phandle phandle;
79564b60e09SAnton Vorontsov 
7969a6b2e58SGrant Likely 		phandle = be32_to_cpup(list++);
797c1bb7c6dSAnton Vorontsov 		args = list;
79864b60e09SAnton Vorontsov 
79964b60e09SAnton Vorontsov 		/* one cell hole in the list = <>; */
8009a6b2e58SGrant Likely 		if (!phandle)
80164b60e09SAnton Vorontsov 			goto next;
80264b60e09SAnton Vorontsov 
8039a6b2e58SGrant Likely 		node = of_find_node_by_phandle(phandle);
80464b60e09SAnton Vorontsov 		if (!node) {
80564b60e09SAnton Vorontsov 			pr_debug("%s: could not find phandle\n",
80664b60e09SAnton Vorontsov 				 np->full_name);
80764b60e09SAnton Vorontsov 			goto err0;
80864b60e09SAnton Vorontsov 		}
80964b60e09SAnton Vorontsov 
81064b60e09SAnton Vorontsov 		cells = of_get_property(node, cells_name, &size);
81164b60e09SAnton Vorontsov 		if (!cells || size != sizeof(*cells)) {
81264b60e09SAnton Vorontsov 			pr_debug("%s: could not get %s for %s\n",
81364b60e09SAnton Vorontsov 				 np->full_name, cells_name, node->full_name);
81464b60e09SAnton Vorontsov 			goto err1;
81564b60e09SAnton Vorontsov 		}
81664b60e09SAnton Vorontsov 
81733714881SJeremy Kerr 		list += be32_to_cpup(cells);
81864b60e09SAnton Vorontsov 		if (list > list_end) {
81964b60e09SAnton Vorontsov 			pr_debug("%s: insufficient arguments length\n",
82064b60e09SAnton Vorontsov 				 np->full_name);
82164b60e09SAnton Vorontsov 			goto err1;
82264b60e09SAnton Vorontsov 		}
82364b60e09SAnton Vorontsov next:
82464b60e09SAnton Vorontsov 		if (cur_index == index)
82564b60e09SAnton Vorontsov 			break;
82664b60e09SAnton Vorontsov 
82764b60e09SAnton Vorontsov 		of_node_put(node);
82864b60e09SAnton Vorontsov 		node = NULL;
8297736a3dbSAnton Vorontsov 		args = NULL;
83064b60e09SAnton Vorontsov 		cur_index++;
83164b60e09SAnton Vorontsov 	}
83264b60e09SAnton Vorontsov 
83364b60e09SAnton Vorontsov 	if (!node) {
8347736a3dbSAnton Vorontsov 		/*
8357736a3dbSAnton Vorontsov 		 * args w/o node indicates that the loop above has stopped at
8367736a3dbSAnton Vorontsov 		 * the 'hole' cell. Report this differently.
8377736a3dbSAnton Vorontsov 		 */
8387736a3dbSAnton Vorontsov 		if (args)
8397736a3dbSAnton Vorontsov 			ret = -EEXIST;
8407736a3dbSAnton Vorontsov 		else
84164b60e09SAnton Vorontsov 			ret = -ENOENT;
84264b60e09SAnton Vorontsov 		goto err0;
84364b60e09SAnton Vorontsov 	}
84464b60e09SAnton Vorontsov 
8457736a3dbSAnton Vorontsov 	if (out_node)
84664b60e09SAnton Vorontsov 		*out_node = node;
8477736a3dbSAnton Vorontsov 	if (out_args)
84864b60e09SAnton Vorontsov 		*out_args = args;
84964b60e09SAnton Vorontsov 
85064b60e09SAnton Vorontsov 	return 0;
85164b60e09SAnton Vorontsov err1:
85264b60e09SAnton Vorontsov 	of_node_put(node);
85364b60e09SAnton Vorontsov err0:
85464b60e09SAnton Vorontsov 	pr_debug("%s failed with status %d\n", __func__, ret);
85564b60e09SAnton Vorontsov 	return ret;
85664b60e09SAnton Vorontsov }
85764b60e09SAnton Vorontsov EXPORT_SYMBOL(of_parse_phandles_with_args);
85802af11b0SGrant Likely 
85902af11b0SGrant Likely /**
86002af11b0SGrant Likely  * prom_add_property - Add a property to a node
86102af11b0SGrant Likely  */
86202af11b0SGrant Likely int prom_add_property(struct device_node *np, struct property *prop)
86302af11b0SGrant Likely {
86402af11b0SGrant Likely 	struct property **next;
86502af11b0SGrant Likely 	unsigned long flags;
86602af11b0SGrant Likely 
86702af11b0SGrant Likely 	prop->next = NULL;
86802af11b0SGrant Likely 	write_lock_irqsave(&devtree_lock, flags);
86902af11b0SGrant Likely 	next = &np->properties;
87002af11b0SGrant Likely 	while (*next) {
87102af11b0SGrant Likely 		if (strcmp(prop->name, (*next)->name) == 0) {
87202af11b0SGrant Likely 			/* duplicate ! don't insert it */
87302af11b0SGrant Likely 			write_unlock_irqrestore(&devtree_lock, flags);
87402af11b0SGrant Likely 			return -1;
87502af11b0SGrant Likely 		}
87602af11b0SGrant Likely 		next = &(*next)->next;
87702af11b0SGrant Likely 	}
87802af11b0SGrant Likely 	*next = prop;
87902af11b0SGrant Likely 	write_unlock_irqrestore(&devtree_lock, flags);
88002af11b0SGrant Likely 
88102af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE
88202af11b0SGrant Likely 	/* try to add to proc as well if it was initialized */
88302af11b0SGrant Likely 	if (np->pde)
88402af11b0SGrant Likely 		proc_device_tree_add_prop(np->pde, prop);
88502af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */
88602af11b0SGrant Likely 
88702af11b0SGrant Likely 	return 0;
88802af11b0SGrant Likely }
88902af11b0SGrant Likely 
89002af11b0SGrant Likely /**
89102af11b0SGrant Likely  * prom_remove_property - Remove a property from a node.
89202af11b0SGrant Likely  *
89302af11b0SGrant Likely  * Note that we don't actually remove it, since we have given out
89402af11b0SGrant Likely  * who-knows-how-many pointers to the data using get-property.
89502af11b0SGrant Likely  * Instead we just move the property to the "dead properties"
89602af11b0SGrant Likely  * list, so it won't be found any more.
89702af11b0SGrant Likely  */
89802af11b0SGrant Likely int prom_remove_property(struct device_node *np, struct property *prop)
89902af11b0SGrant Likely {
90002af11b0SGrant Likely 	struct property **next;
90102af11b0SGrant Likely 	unsigned long flags;
90202af11b0SGrant Likely 	int found = 0;
90302af11b0SGrant Likely 
90402af11b0SGrant Likely 	write_lock_irqsave(&devtree_lock, flags);
90502af11b0SGrant Likely 	next = &np->properties;
90602af11b0SGrant Likely 	while (*next) {
90702af11b0SGrant Likely 		if (*next == prop) {
90802af11b0SGrant Likely 			/* found the node */
90902af11b0SGrant Likely 			*next = prop->next;
91002af11b0SGrant Likely 			prop->next = np->deadprops;
91102af11b0SGrant Likely 			np->deadprops = prop;
91202af11b0SGrant Likely 			found = 1;
91302af11b0SGrant Likely 			break;
91402af11b0SGrant Likely 		}
91502af11b0SGrant Likely 		next = &(*next)->next;
91602af11b0SGrant Likely 	}
91702af11b0SGrant Likely 	write_unlock_irqrestore(&devtree_lock, flags);
91802af11b0SGrant Likely 
91902af11b0SGrant Likely 	if (!found)
92002af11b0SGrant Likely 		return -ENODEV;
92102af11b0SGrant Likely 
92202af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE
92302af11b0SGrant Likely 	/* try to remove the proc node as well */
92402af11b0SGrant Likely 	if (np->pde)
92502af11b0SGrant Likely 		proc_device_tree_remove_prop(np->pde, prop);
92602af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */
92702af11b0SGrant Likely 
92802af11b0SGrant Likely 	return 0;
92902af11b0SGrant Likely }
93002af11b0SGrant Likely 
93102af11b0SGrant Likely /*
93202af11b0SGrant Likely  * prom_update_property - Update a property in a node.
93302af11b0SGrant Likely  *
93402af11b0SGrant Likely  * Note that we don't actually remove it, since we have given out
93502af11b0SGrant Likely  * who-knows-how-many pointers to the data using get-property.
93602af11b0SGrant Likely  * Instead we just move the property to the "dead properties" list,
93702af11b0SGrant Likely  * and add the new property to the property list
93802af11b0SGrant Likely  */
93902af11b0SGrant Likely int prom_update_property(struct device_node *np,
94002af11b0SGrant Likely 			 struct property *newprop,
94102af11b0SGrant Likely 			 struct property *oldprop)
94202af11b0SGrant Likely {
94302af11b0SGrant Likely 	struct property **next;
94402af11b0SGrant Likely 	unsigned long flags;
94502af11b0SGrant Likely 	int found = 0;
94602af11b0SGrant Likely 
94702af11b0SGrant Likely 	write_lock_irqsave(&devtree_lock, flags);
94802af11b0SGrant Likely 	next = &np->properties;
94902af11b0SGrant Likely 	while (*next) {
95002af11b0SGrant Likely 		if (*next == oldprop) {
95102af11b0SGrant Likely 			/* found the node */
95202af11b0SGrant Likely 			newprop->next = oldprop->next;
95302af11b0SGrant Likely 			*next = newprop;
95402af11b0SGrant Likely 			oldprop->next = np->deadprops;
95502af11b0SGrant Likely 			np->deadprops = oldprop;
95602af11b0SGrant Likely 			found = 1;
95702af11b0SGrant Likely 			break;
95802af11b0SGrant Likely 		}
95902af11b0SGrant Likely 		next = &(*next)->next;
96002af11b0SGrant Likely 	}
96102af11b0SGrant Likely 	write_unlock_irqrestore(&devtree_lock, flags);
96202af11b0SGrant Likely 
96302af11b0SGrant Likely 	if (!found)
96402af11b0SGrant Likely 		return -ENODEV;
96502af11b0SGrant Likely 
96602af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE
96702af11b0SGrant Likely 	/* try to add to proc as well if it was initialized */
96802af11b0SGrant Likely 	if (np->pde)
96902af11b0SGrant Likely 		proc_device_tree_update_prop(np->pde, newprop, oldprop);
97002af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */
97102af11b0SGrant Likely 
97202af11b0SGrant Likely 	return 0;
97302af11b0SGrant Likely }
974fcdeb7feSGrant Likely 
975fcdeb7feSGrant Likely #if defined(CONFIG_OF_DYNAMIC)
976fcdeb7feSGrant Likely /*
977fcdeb7feSGrant Likely  * Support for dynamic device trees.
978fcdeb7feSGrant Likely  *
979fcdeb7feSGrant Likely  * On some platforms, the device tree can be manipulated at runtime.
980fcdeb7feSGrant Likely  * The routines in this section support adding, removing and changing
981fcdeb7feSGrant Likely  * device tree nodes.
982fcdeb7feSGrant Likely  */
983fcdeb7feSGrant Likely 
984fcdeb7feSGrant Likely /**
985fcdeb7feSGrant Likely  * of_attach_node - Plug a device node into the tree and global list.
986fcdeb7feSGrant Likely  */
987fcdeb7feSGrant Likely void of_attach_node(struct device_node *np)
988fcdeb7feSGrant Likely {
989fcdeb7feSGrant Likely 	unsigned long flags;
990fcdeb7feSGrant Likely 
991fcdeb7feSGrant Likely 	write_lock_irqsave(&devtree_lock, flags);
992fcdeb7feSGrant Likely 	np->sibling = np->parent->child;
993fcdeb7feSGrant Likely 	np->allnext = allnodes;
994fcdeb7feSGrant Likely 	np->parent->child = np;
995fcdeb7feSGrant Likely 	allnodes = np;
996fcdeb7feSGrant Likely 	write_unlock_irqrestore(&devtree_lock, flags);
997fcdeb7feSGrant Likely }
998fcdeb7feSGrant Likely 
999fcdeb7feSGrant Likely /**
1000fcdeb7feSGrant Likely  * of_detach_node - "Unplug" a node from the device tree.
1001fcdeb7feSGrant Likely  *
1002fcdeb7feSGrant Likely  * The caller must hold a reference to the node.  The memory associated with
1003fcdeb7feSGrant Likely  * the node is not freed until its refcount goes to zero.
1004fcdeb7feSGrant Likely  */
1005fcdeb7feSGrant Likely void of_detach_node(struct device_node *np)
1006fcdeb7feSGrant Likely {
1007fcdeb7feSGrant Likely 	struct device_node *parent;
1008fcdeb7feSGrant Likely 	unsigned long flags;
1009fcdeb7feSGrant Likely 
1010fcdeb7feSGrant Likely 	write_lock_irqsave(&devtree_lock, flags);
1011fcdeb7feSGrant Likely 
1012fcdeb7feSGrant Likely 	parent = np->parent;
1013fcdeb7feSGrant Likely 	if (!parent)
1014fcdeb7feSGrant Likely 		goto out_unlock;
1015fcdeb7feSGrant Likely 
1016fcdeb7feSGrant Likely 	if (allnodes == np)
1017fcdeb7feSGrant Likely 		allnodes = np->allnext;
1018fcdeb7feSGrant Likely 	else {
1019fcdeb7feSGrant Likely 		struct device_node *prev;
1020fcdeb7feSGrant Likely 		for (prev = allnodes;
1021fcdeb7feSGrant Likely 		     prev->allnext != np;
1022fcdeb7feSGrant Likely 		     prev = prev->allnext)
1023fcdeb7feSGrant Likely 			;
1024fcdeb7feSGrant Likely 		prev->allnext = np->allnext;
1025fcdeb7feSGrant Likely 	}
1026fcdeb7feSGrant Likely 
1027fcdeb7feSGrant Likely 	if (parent->child == np)
1028fcdeb7feSGrant Likely 		parent->child = np->sibling;
1029fcdeb7feSGrant Likely 	else {
1030fcdeb7feSGrant Likely 		struct device_node *prevsib;
1031fcdeb7feSGrant Likely 		for (prevsib = np->parent->child;
1032fcdeb7feSGrant Likely 		     prevsib->sibling != np;
1033fcdeb7feSGrant Likely 		     prevsib = prevsib->sibling)
1034fcdeb7feSGrant Likely 			;
1035fcdeb7feSGrant Likely 		prevsib->sibling = np->sibling;
1036fcdeb7feSGrant Likely 	}
1037fcdeb7feSGrant Likely 
1038fcdeb7feSGrant Likely 	of_node_set_flag(np, OF_DETACHED);
1039fcdeb7feSGrant Likely 
1040fcdeb7feSGrant Likely out_unlock:
1041fcdeb7feSGrant Likely 	write_unlock_irqrestore(&devtree_lock, flags);
1042fcdeb7feSGrant Likely }
1043fcdeb7feSGrant Likely #endif /* defined(CONFIG_OF_DYNAMIC) */
1044fcdeb7feSGrant Likely 
1045611cad72SShawn Guo static void of_alias_add(struct alias_prop *ap, struct device_node *np,
1046611cad72SShawn Guo 			 int id, const char *stem, int stem_len)
1047611cad72SShawn Guo {
1048611cad72SShawn Guo 	ap->np = np;
1049611cad72SShawn Guo 	ap->id = id;
1050611cad72SShawn Guo 	strncpy(ap->stem, stem, stem_len);
1051611cad72SShawn Guo 	ap->stem[stem_len] = 0;
1052611cad72SShawn Guo 	list_add_tail(&ap->link, &aliases_lookup);
1053611cad72SShawn Guo 	pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
1054611cad72SShawn Guo 		 ap->alias, ap->stem, ap->id, np ? np->full_name : NULL);
1055611cad72SShawn Guo }
1056611cad72SShawn Guo 
1057611cad72SShawn Guo /**
1058611cad72SShawn Guo  * of_alias_scan - Scan all properties of 'aliases' node
1059611cad72SShawn Guo  *
1060611cad72SShawn Guo  * The function scans all the properties of 'aliases' node and populate
1061611cad72SShawn Guo  * the the global lookup table with the properties.  It returns the
1062611cad72SShawn Guo  * number of alias_prop found, or error code in error case.
1063611cad72SShawn Guo  *
1064611cad72SShawn Guo  * @dt_alloc:	An allocator that provides a virtual address to memory
1065611cad72SShawn Guo  *		for the resulting tree
1066611cad72SShawn Guo  */
1067611cad72SShawn Guo void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
1068611cad72SShawn Guo {
1069611cad72SShawn Guo 	struct property *pp;
1070611cad72SShawn Guo 
1071611cad72SShawn Guo 	of_chosen = of_find_node_by_path("/chosen");
1072611cad72SShawn Guo 	if (of_chosen == NULL)
1073611cad72SShawn Guo 		of_chosen = of_find_node_by_path("/chosen@0");
1074611cad72SShawn Guo 	of_aliases = of_find_node_by_path("/aliases");
1075611cad72SShawn Guo 	if (!of_aliases)
1076611cad72SShawn Guo 		return;
1077611cad72SShawn Guo 
1078611cad72SShawn Guo 	for_each_property(pp, of_aliases->properties) {
1079611cad72SShawn Guo 		const char *start = pp->name;
1080611cad72SShawn Guo 		const char *end = start + strlen(start);
1081611cad72SShawn Guo 		struct device_node *np;
1082611cad72SShawn Guo 		struct alias_prop *ap;
1083611cad72SShawn Guo 		int id, len;
1084611cad72SShawn Guo 
1085611cad72SShawn Guo 		/* Skip those we do not want to proceed */
1086611cad72SShawn Guo 		if (!strcmp(pp->name, "name") ||
1087611cad72SShawn Guo 		    !strcmp(pp->name, "phandle") ||
1088611cad72SShawn Guo 		    !strcmp(pp->name, "linux,phandle"))
1089611cad72SShawn Guo 			continue;
1090611cad72SShawn Guo 
1091611cad72SShawn Guo 		np = of_find_node_by_path(pp->value);
1092611cad72SShawn Guo 		if (!np)
1093611cad72SShawn Guo 			continue;
1094611cad72SShawn Guo 
1095611cad72SShawn Guo 		/* walk the alias backwards to extract the id and work out
1096611cad72SShawn Guo 		 * the 'stem' string */
1097611cad72SShawn Guo 		while (isdigit(*(end-1)) && end > start)
1098611cad72SShawn Guo 			end--;
1099611cad72SShawn Guo 		len = end - start;
1100611cad72SShawn Guo 
1101611cad72SShawn Guo 		if (kstrtoint(end, 10, &id) < 0)
1102611cad72SShawn Guo 			continue;
1103611cad72SShawn Guo 
1104611cad72SShawn Guo 		/* Allocate an alias_prop with enough space for the stem */
1105611cad72SShawn Guo 		ap = dt_alloc(sizeof(*ap) + len + 1, 4);
1106611cad72SShawn Guo 		if (!ap)
1107611cad72SShawn Guo 			continue;
1108611cad72SShawn Guo 		ap->alias = start;
1109611cad72SShawn Guo 		of_alias_add(ap, np, id, start, len);
1110611cad72SShawn Guo 	}
1111611cad72SShawn Guo }
1112611cad72SShawn Guo 
1113611cad72SShawn Guo /**
1114611cad72SShawn Guo  * of_alias_get_id - Get alias id for the given device_node
1115611cad72SShawn Guo  * @np:		Pointer to the given device_node
1116611cad72SShawn Guo  * @stem:	Alias stem of the given device_node
1117611cad72SShawn Guo  *
1118611cad72SShawn Guo  * The function travels the lookup table to get alias id for the given
1119611cad72SShawn Guo  * device_node and alias stem.  It returns the alias id if find it.
1120611cad72SShawn Guo  */
1121611cad72SShawn Guo int of_alias_get_id(struct device_node *np, const char *stem)
1122611cad72SShawn Guo {
1123611cad72SShawn Guo 	struct alias_prop *app;
1124611cad72SShawn Guo 	int id = -ENODEV;
1125611cad72SShawn Guo 
1126611cad72SShawn Guo 	mutex_lock(&of_aliases_mutex);
1127611cad72SShawn Guo 	list_for_each_entry(app, &aliases_lookup, link) {
1128611cad72SShawn Guo 		if (strcmp(app->stem, stem) != 0)
1129611cad72SShawn Guo 			continue;
1130611cad72SShawn Guo 
1131611cad72SShawn Guo 		if (np == app->np) {
1132611cad72SShawn Guo 			id = app->id;
1133611cad72SShawn Guo 			break;
1134611cad72SShawn Guo 		}
1135611cad72SShawn Guo 	}
1136611cad72SShawn Guo 	mutex_unlock(&of_aliases_mutex);
1137611cad72SShawn Guo 
1138611cad72SShawn Guo 	return id;
1139611cad72SShawn Guo }
1140611cad72SShawn Guo EXPORT_SYMBOL_GPL(of_alias_get_id);
1141