xref: /openbmc/linux/drivers/of/base.c (revision bc51b0c2)
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 
910f22dd39SGrant Likely #if defined(CONFIG_OF_DYNAMIC)
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);
1640f22dd39SGrant Likely #endif /* CONFIG_OF_DYNAMIC */
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);
535bc51b0c2SLinus Torvalds 		if (matches->compatible[0])
536bc51b0c2SLinus Torvalds 			match &= of_device_is_compatible(node,
537bc51b0c2SLinus Torvalds 						matches->compatible);
538bc51b0c2SLinus Torvalds 		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 /**
7194fcd15a0SBenoit Cousson  * of_property_read_string_index - Find and read a string from a multiple
7204fcd15a0SBenoit Cousson  * strings property.
7214fcd15a0SBenoit Cousson  * @np:		device node from which the property value is to be read.
7224fcd15a0SBenoit Cousson  * @propname:	name of the property to be searched.
7234fcd15a0SBenoit Cousson  * @index:	index of the string in the list of strings
7244fcd15a0SBenoit Cousson  * @out_string:	pointer to null terminated return string, modified only if
7254fcd15a0SBenoit Cousson  *		return value is 0.
7264fcd15a0SBenoit Cousson  *
7274fcd15a0SBenoit Cousson  * Search for a property in a device tree node and retrieve a null
7284fcd15a0SBenoit Cousson  * terminated string value (pointer to data, not a copy) in the list of strings
7294fcd15a0SBenoit Cousson  * contained in that property.
7304fcd15a0SBenoit Cousson  * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if
7314fcd15a0SBenoit Cousson  * property does not have a value, and -EILSEQ if the string is not
7324fcd15a0SBenoit Cousson  * null-terminated within the length of the property data.
7334fcd15a0SBenoit Cousson  *
7344fcd15a0SBenoit Cousson  * The out_string pointer is modified only if a valid string can be decoded.
7354fcd15a0SBenoit Cousson  */
7364fcd15a0SBenoit Cousson int of_property_read_string_index(struct device_node *np, const char *propname,
7374fcd15a0SBenoit Cousson 				  int index, const char **output)
7384fcd15a0SBenoit Cousson {
7394fcd15a0SBenoit Cousson 	struct property *prop = of_find_property(np, propname, NULL);
7404fcd15a0SBenoit Cousson 	int i = 0;
7414fcd15a0SBenoit Cousson 	size_t l = 0, total = 0;
7424fcd15a0SBenoit Cousson 	const char *p;
7434fcd15a0SBenoit Cousson 
7444fcd15a0SBenoit Cousson 	if (!prop)
7454fcd15a0SBenoit Cousson 		return -EINVAL;
7464fcd15a0SBenoit Cousson 	if (!prop->value)
7474fcd15a0SBenoit Cousson 		return -ENODATA;
7484fcd15a0SBenoit Cousson 	if (strnlen(prop->value, prop->length) >= prop->length)
7494fcd15a0SBenoit Cousson 		return -EILSEQ;
7504fcd15a0SBenoit Cousson 
7514fcd15a0SBenoit Cousson 	p = prop->value;
7524fcd15a0SBenoit Cousson 
7534fcd15a0SBenoit Cousson 	for (i = 0; total < prop->length; total += l, p += l) {
7544fcd15a0SBenoit Cousson 		l = strlen(p) + 1;
75588af7f58SBenoit Cousson 		if (i++ == index) {
7564fcd15a0SBenoit Cousson 			*output = p;
7574fcd15a0SBenoit Cousson 			return 0;
7584fcd15a0SBenoit Cousson 		}
7594fcd15a0SBenoit Cousson 	}
7604fcd15a0SBenoit Cousson 	return -ENODATA;
7614fcd15a0SBenoit Cousson }
7624fcd15a0SBenoit Cousson EXPORT_SYMBOL_GPL(of_property_read_string_index);
7634fcd15a0SBenoit Cousson 
7647aff0fe3SGrant Likely /**
7657aff0fe3SGrant Likely  * of_property_match_string() - Find string in a list and return index
7667aff0fe3SGrant Likely  * @np: pointer to node containing string list property
7677aff0fe3SGrant Likely  * @propname: string list property name
7687aff0fe3SGrant Likely  * @string: pointer to string to search for in string list
7697aff0fe3SGrant Likely  *
7707aff0fe3SGrant Likely  * This function searches a string list property and returns the index
7717aff0fe3SGrant Likely  * of a specific string value.
7727aff0fe3SGrant Likely  */
7737aff0fe3SGrant Likely int of_property_match_string(struct device_node *np, const char *propname,
7747aff0fe3SGrant Likely 			     const char *string)
7757aff0fe3SGrant Likely {
7767aff0fe3SGrant Likely 	struct property *prop = of_find_property(np, propname, NULL);
7777aff0fe3SGrant Likely 	size_t l;
7787aff0fe3SGrant Likely 	int i;
7797aff0fe3SGrant Likely 	const char *p, *end;
7807aff0fe3SGrant Likely 
7817aff0fe3SGrant Likely 	if (!prop)
7827aff0fe3SGrant Likely 		return -EINVAL;
7837aff0fe3SGrant Likely 	if (!prop->value)
7847aff0fe3SGrant Likely 		return -ENODATA;
7857aff0fe3SGrant Likely 
7867aff0fe3SGrant Likely 	p = prop->value;
7877aff0fe3SGrant Likely 	end = p + prop->length;
7887aff0fe3SGrant Likely 
7897aff0fe3SGrant Likely 	for (i = 0; p < end; i++, p += l) {
7907aff0fe3SGrant Likely 		l = strlen(p) + 1;
7917aff0fe3SGrant Likely 		if (p + l > end)
7927aff0fe3SGrant Likely 			return -EILSEQ;
7937aff0fe3SGrant Likely 		pr_debug("comparing %s with %s\n", string, p);
7947aff0fe3SGrant Likely 		if (strcmp(string, p) == 0)
7957aff0fe3SGrant Likely 			return i; /* Found it; return index */
7967aff0fe3SGrant Likely 	}
7977aff0fe3SGrant Likely 	return -ENODATA;
7987aff0fe3SGrant Likely }
7997aff0fe3SGrant Likely EXPORT_SYMBOL_GPL(of_property_match_string);
8004fcd15a0SBenoit Cousson 
8014fcd15a0SBenoit Cousson /**
8024fcd15a0SBenoit Cousson  * of_property_count_strings - Find and return the number of strings from a
8034fcd15a0SBenoit Cousson  * multiple strings property.
8044fcd15a0SBenoit Cousson  * @np:		device node from which the property value is to be read.
8054fcd15a0SBenoit Cousson  * @propname:	name of the property to be searched.
8064fcd15a0SBenoit Cousson  *
8074fcd15a0SBenoit Cousson  * Search for a property in a device tree node and retrieve the number of null
8084fcd15a0SBenoit Cousson  * terminated string contain in it. Returns the number of strings on
8094fcd15a0SBenoit Cousson  * success, -EINVAL if the property does not exist, -ENODATA if property
8104fcd15a0SBenoit Cousson  * does not have a value, and -EILSEQ if the string is not null-terminated
8114fcd15a0SBenoit Cousson  * within the length of the property data.
8124fcd15a0SBenoit Cousson  */
8134fcd15a0SBenoit Cousson int of_property_count_strings(struct device_node *np, const char *propname)
8144fcd15a0SBenoit Cousson {
8154fcd15a0SBenoit Cousson 	struct property *prop = of_find_property(np, propname, NULL);
8164fcd15a0SBenoit Cousson 	int i = 0;
8174fcd15a0SBenoit Cousson 	size_t l = 0, total = 0;
8184fcd15a0SBenoit Cousson 	const char *p;
8194fcd15a0SBenoit Cousson 
8204fcd15a0SBenoit Cousson 	if (!prop)
8214fcd15a0SBenoit Cousson 		return -EINVAL;
8224fcd15a0SBenoit Cousson 	if (!prop->value)
8234fcd15a0SBenoit Cousson 		return -ENODATA;
8244fcd15a0SBenoit Cousson 	if (strnlen(prop->value, prop->length) >= prop->length)
8254fcd15a0SBenoit Cousson 		return -EILSEQ;
8264fcd15a0SBenoit Cousson 
8274fcd15a0SBenoit Cousson 	p = prop->value;
8284fcd15a0SBenoit Cousson 
82988af7f58SBenoit Cousson 	for (i = 0; total < prop->length; total += l, p += l, i++)
8304fcd15a0SBenoit Cousson 		l = strlen(p) + 1;
83188af7f58SBenoit Cousson 
8324fcd15a0SBenoit Cousson 	return i;
8334fcd15a0SBenoit Cousson }
8344fcd15a0SBenoit Cousson EXPORT_SYMBOL_GPL(of_property_count_strings);
8354fcd15a0SBenoit Cousson 
8364fcd15a0SBenoit Cousson /**
837739649c5SGrant Likely  * of_parse_phandle - Resolve a phandle property to a device_node pointer
838739649c5SGrant Likely  * @np: Pointer to device node holding phandle property
839739649c5SGrant Likely  * @phandle_name: Name of property holding a phandle value
840739649c5SGrant Likely  * @index: For properties holding a table of phandles, this is the index into
841739649c5SGrant Likely  *         the table
842739649c5SGrant Likely  *
843739649c5SGrant Likely  * Returns the device_node pointer with refcount incremented.  Use
844739649c5SGrant Likely  * of_node_put() on it when done.
845739649c5SGrant Likely  */
846739649c5SGrant Likely struct device_node *
847739649c5SGrant Likely of_parse_phandle(struct device_node *np, const char *phandle_name, int index)
848739649c5SGrant Likely {
8499a6b2e58SGrant Likely 	const __be32 *phandle;
850739649c5SGrant Likely 	int size;
851739649c5SGrant Likely 
852739649c5SGrant Likely 	phandle = of_get_property(np, phandle_name, &size);
853739649c5SGrant Likely 	if ((!phandle) || (size < sizeof(*phandle) * (index + 1)))
854739649c5SGrant Likely 		return NULL;
855739649c5SGrant Likely 
8569a6b2e58SGrant Likely 	return of_find_node_by_phandle(be32_to_cpup(phandle + index));
857739649c5SGrant Likely }
858739649c5SGrant Likely EXPORT_SYMBOL(of_parse_phandle);
859739649c5SGrant Likely 
860739649c5SGrant Likely /**
86115c9a0acSGrant Likely  * of_parse_phandle_with_args() - Find a node pointed by phandle in a list
86264b60e09SAnton Vorontsov  * @np:		pointer to a device tree node containing a list
86364b60e09SAnton Vorontsov  * @list_name:	property name that contains a list
86464b60e09SAnton Vorontsov  * @cells_name:	property name that specifies phandles' arguments count
86564b60e09SAnton Vorontsov  * @index:	index of a phandle to parse out
86615c9a0acSGrant Likely  * @out_args:	optional pointer to output arguments structure (will be filled)
86764b60e09SAnton Vorontsov  *
86864b60e09SAnton Vorontsov  * This function is useful to parse lists of phandles and their arguments.
86915c9a0acSGrant Likely  * Returns 0 on success and fills out_args, on error returns appropriate
87015c9a0acSGrant Likely  * errno value.
87115c9a0acSGrant Likely  *
87215c9a0acSGrant Likely  * Caller is responsible to call of_node_put() on the returned out_args->node
87315c9a0acSGrant Likely  * pointer.
87464b60e09SAnton Vorontsov  *
87564b60e09SAnton Vorontsov  * Example:
87664b60e09SAnton Vorontsov  *
87764b60e09SAnton Vorontsov  * phandle1: node1 {
87864b60e09SAnton Vorontsov  * 	#list-cells = <2>;
87964b60e09SAnton Vorontsov  * }
88064b60e09SAnton Vorontsov  *
88164b60e09SAnton Vorontsov  * phandle2: node2 {
88264b60e09SAnton Vorontsov  * 	#list-cells = <1>;
88364b60e09SAnton Vorontsov  * }
88464b60e09SAnton Vorontsov  *
88564b60e09SAnton Vorontsov  * node3 {
88664b60e09SAnton Vorontsov  * 	list = <&phandle1 1 2 &phandle2 3>;
88764b60e09SAnton Vorontsov  * }
88864b60e09SAnton Vorontsov  *
88964b60e09SAnton Vorontsov  * To get a device_node of the `node2' node you may call this:
89015c9a0acSGrant Likely  * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
89164b60e09SAnton Vorontsov  */
89215c9a0acSGrant Likely int of_parse_phandle_with_args(struct device_node *np, const char *list_name,
89364b60e09SAnton Vorontsov 				const char *cells_name, int index,
89415c9a0acSGrant Likely 				struct of_phandle_args *out_args)
89564b60e09SAnton Vorontsov {
89615c9a0acSGrant Likely 	const __be32 *list, *list_end;
89715c9a0acSGrant Likely 	int size, cur_index = 0;
89815c9a0acSGrant Likely 	uint32_t count = 0;
89964b60e09SAnton Vorontsov 	struct device_node *node = NULL;
9009a6b2e58SGrant Likely 	phandle phandle;
90164b60e09SAnton Vorontsov 
90215c9a0acSGrant Likely 	/* Retrieve the phandle list property */
90315c9a0acSGrant Likely 	list = of_get_property(np, list_name, &size);
90415c9a0acSGrant Likely 	if (!list)
90515c9a0acSGrant Likely 		return -EINVAL;
90615c9a0acSGrant Likely 	list_end = list + size / sizeof(*list);
90715c9a0acSGrant Likely 
90815c9a0acSGrant Likely 	/* Loop over the phandles until all the requested entry is found */
90915c9a0acSGrant Likely 	while (list < list_end) {
91015c9a0acSGrant Likely 		count = 0;
91115c9a0acSGrant Likely 
91215c9a0acSGrant Likely 		/*
91315c9a0acSGrant Likely 		 * If phandle is 0, then it is an empty entry with no
91415c9a0acSGrant Likely 		 * arguments.  Skip forward to the next entry.
91515c9a0acSGrant Likely 		 */
9169a6b2e58SGrant Likely 		phandle = be32_to_cpup(list++);
91715c9a0acSGrant Likely 		if (phandle) {
91815c9a0acSGrant Likely 			/*
91915c9a0acSGrant Likely 			 * Find the provider node and parse the #*-cells
92015c9a0acSGrant Likely 			 * property to determine the argument length
92115c9a0acSGrant Likely 			 */
9229a6b2e58SGrant Likely 			node = of_find_node_by_phandle(phandle);
92364b60e09SAnton Vorontsov 			if (!node) {
92415c9a0acSGrant Likely 				pr_err("%s: could not find phandle\n",
92564b60e09SAnton Vorontsov 					 np->full_name);
92664b60e09SAnton Vorontsov 				break;
92715c9a0acSGrant Likely 			}
92815c9a0acSGrant Likely 			if (of_property_read_u32(node, cells_name, &count)) {
92915c9a0acSGrant Likely 				pr_err("%s: could not get %s for %s\n",
93015c9a0acSGrant Likely 					 np->full_name, cells_name,
93115c9a0acSGrant Likely 					 node->full_name);
93215c9a0acSGrant Likely 				break;
93315c9a0acSGrant Likely 			}
93415c9a0acSGrant Likely 
93515c9a0acSGrant Likely 			/*
93615c9a0acSGrant Likely 			 * Make sure that the arguments actually fit in the
93715c9a0acSGrant Likely 			 * remaining property data length
93815c9a0acSGrant Likely 			 */
93915c9a0acSGrant Likely 			if (list + count > list_end) {
94015c9a0acSGrant Likely 				pr_err("%s: arguments longer than property\n",
94115c9a0acSGrant Likely 					 np->full_name);
94215c9a0acSGrant Likely 				break;
94315c9a0acSGrant Likely 			}
94415c9a0acSGrant Likely 		}
94515c9a0acSGrant Likely 
94615c9a0acSGrant Likely 		/*
94715c9a0acSGrant Likely 		 * All of the error cases above bail out of the loop, so at
94815c9a0acSGrant Likely 		 * this point, the parsing is successful. If the requested
94915c9a0acSGrant Likely 		 * index matches, then fill the out_args structure and return,
95015c9a0acSGrant Likely 		 * or return -ENOENT for an empty entry.
95115c9a0acSGrant Likely 		 */
95215c9a0acSGrant Likely 		if (cur_index == index) {
95315c9a0acSGrant Likely 			if (!phandle)
95415c9a0acSGrant Likely 				return -ENOENT;
95515c9a0acSGrant Likely 
95615c9a0acSGrant Likely 			if (out_args) {
95715c9a0acSGrant Likely 				int i;
95815c9a0acSGrant Likely 				if (WARN_ON(count > MAX_PHANDLE_ARGS))
95915c9a0acSGrant Likely 					count = MAX_PHANDLE_ARGS;
96015c9a0acSGrant Likely 				out_args->np = node;
96115c9a0acSGrant Likely 				out_args->args_count = count;
96215c9a0acSGrant Likely 				for (i = 0; i < count; i++)
96315c9a0acSGrant Likely 					out_args->args[i] = be32_to_cpup(list++);
96415c9a0acSGrant Likely 			}
96515c9a0acSGrant Likely 			return 0;
96615c9a0acSGrant Likely 		}
96764b60e09SAnton Vorontsov 
96864b60e09SAnton Vorontsov 		of_node_put(node);
96964b60e09SAnton Vorontsov 		node = NULL;
97015c9a0acSGrant Likely 		list += count;
97164b60e09SAnton Vorontsov 		cur_index++;
97264b60e09SAnton Vorontsov 	}
97364b60e09SAnton Vorontsov 
97415c9a0acSGrant Likely 	/* Loop exited without finding a valid entry; return an error */
97515c9a0acSGrant Likely 	if (node)
97664b60e09SAnton Vorontsov 		of_node_put(node);
97715c9a0acSGrant Likely 	return -EINVAL;
97864b60e09SAnton Vorontsov }
97915c9a0acSGrant Likely EXPORT_SYMBOL(of_parse_phandle_with_args);
98002af11b0SGrant Likely 
98102af11b0SGrant Likely /**
98202af11b0SGrant Likely  * prom_add_property - Add a property to a node
98302af11b0SGrant Likely  */
98402af11b0SGrant Likely int prom_add_property(struct device_node *np, struct property *prop)
98502af11b0SGrant Likely {
98602af11b0SGrant Likely 	struct property **next;
98702af11b0SGrant Likely 	unsigned long flags;
98802af11b0SGrant Likely 
98902af11b0SGrant Likely 	prop->next = NULL;
99002af11b0SGrant Likely 	write_lock_irqsave(&devtree_lock, flags);
99102af11b0SGrant Likely 	next = &np->properties;
99202af11b0SGrant Likely 	while (*next) {
99302af11b0SGrant Likely 		if (strcmp(prop->name, (*next)->name) == 0) {
99402af11b0SGrant Likely 			/* duplicate ! don't insert it */
99502af11b0SGrant Likely 			write_unlock_irqrestore(&devtree_lock, flags);
99602af11b0SGrant Likely 			return -1;
99702af11b0SGrant Likely 		}
99802af11b0SGrant Likely 		next = &(*next)->next;
99902af11b0SGrant Likely 	}
100002af11b0SGrant Likely 	*next = prop;
100102af11b0SGrant Likely 	write_unlock_irqrestore(&devtree_lock, flags);
100202af11b0SGrant Likely 
100302af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE
100402af11b0SGrant Likely 	/* try to add to proc as well if it was initialized */
100502af11b0SGrant Likely 	if (np->pde)
100602af11b0SGrant Likely 		proc_device_tree_add_prop(np->pde, prop);
100702af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */
100802af11b0SGrant Likely 
100902af11b0SGrant Likely 	return 0;
101002af11b0SGrant Likely }
101102af11b0SGrant Likely 
101202af11b0SGrant Likely /**
101302af11b0SGrant Likely  * prom_remove_property - Remove a property from a node.
101402af11b0SGrant Likely  *
101502af11b0SGrant Likely  * Note that we don't actually remove it, since we have given out
101602af11b0SGrant Likely  * who-knows-how-many pointers to the data using get-property.
101702af11b0SGrant Likely  * Instead we just move the property to the "dead properties"
101802af11b0SGrant Likely  * list, so it won't be found any more.
101902af11b0SGrant Likely  */
102002af11b0SGrant Likely int prom_remove_property(struct device_node *np, struct property *prop)
102102af11b0SGrant Likely {
102202af11b0SGrant Likely 	struct property **next;
102302af11b0SGrant Likely 	unsigned long flags;
102402af11b0SGrant Likely 	int found = 0;
102502af11b0SGrant Likely 
102602af11b0SGrant Likely 	write_lock_irqsave(&devtree_lock, flags);
102702af11b0SGrant Likely 	next = &np->properties;
102802af11b0SGrant Likely 	while (*next) {
102902af11b0SGrant Likely 		if (*next == prop) {
103002af11b0SGrant Likely 			/* found the node */
103102af11b0SGrant Likely 			*next = prop->next;
103202af11b0SGrant Likely 			prop->next = np->deadprops;
103302af11b0SGrant Likely 			np->deadprops = prop;
103402af11b0SGrant Likely 			found = 1;
103502af11b0SGrant Likely 			break;
103602af11b0SGrant Likely 		}
103702af11b0SGrant Likely 		next = &(*next)->next;
103802af11b0SGrant Likely 	}
103902af11b0SGrant Likely 	write_unlock_irqrestore(&devtree_lock, flags);
104002af11b0SGrant Likely 
104102af11b0SGrant Likely 	if (!found)
104202af11b0SGrant Likely 		return -ENODEV;
104302af11b0SGrant Likely 
104402af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE
104502af11b0SGrant Likely 	/* try to remove the proc node as well */
104602af11b0SGrant Likely 	if (np->pde)
104702af11b0SGrant Likely 		proc_device_tree_remove_prop(np->pde, prop);
104802af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */
104902af11b0SGrant Likely 
105002af11b0SGrant Likely 	return 0;
105102af11b0SGrant Likely }
105202af11b0SGrant Likely 
105302af11b0SGrant Likely /*
105402af11b0SGrant Likely  * prom_update_property - Update a property in a node.
105502af11b0SGrant Likely  *
105602af11b0SGrant Likely  * Note that we don't actually remove it, since we have given out
105702af11b0SGrant Likely  * who-knows-how-many pointers to the data using get-property.
105802af11b0SGrant Likely  * Instead we just move the property to the "dead properties" list,
105902af11b0SGrant Likely  * and add the new property to the property list
106002af11b0SGrant Likely  */
106102af11b0SGrant Likely int prom_update_property(struct device_node *np,
106202af11b0SGrant Likely 			 struct property *newprop,
106302af11b0SGrant Likely 			 struct property *oldprop)
106402af11b0SGrant Likely {
106502af11b0SGrant Likely 	struct property **next;
106602af11b0SGrant Likely 	unsigned long flags;
106702af11b0SGrant Likely 	int found = 0;
106802af11b0SGrant Likely 
106902af11b0SGrant Likely 	write_lock_irqsave(&devtree_lock, flags);
107002af11b0SGrant Likely 	next = &np->properties;
107102af11b0SGrant Likely 	while (*next) {
107202af11b0SGrant Likely 		if (*next == oldprop) {
107302af11b0SGrant Likely 			/* found the node */
107402af11b0SGrant Likely 			newprop->next = oldprop->next;
107502af11b0SGrant Likely 			*next = newprop;
107602af11b0SGrant Likely 			oldprop->next = np->deadprops;
107702af11b0SGrant Likely 			np->deadprops = oldprop;
107802af11b0SGrant Likely 			found = 1;
107902af11b0SGrant Likely 			break;
108002af11b0SGrant Likely 		}
108102af11b0SGrant Likely 		next = &(*next)->next;
108202af11b0SGrant Likely 	}
108302af11b0SGrant Likely 	write_unlock_irqrestore(&devtree_lock, flags);
108402af11b0SGrant Likely 
108502af11b0SGrant Likely 	if (!found)
108602af11b0SGrant Likely 		return -ENODEV;
108702af11b0SGrant Likely 
108802af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE
108902af11b0SGrant Likely 	/* try to add to proc as well if it was initialized */
109002af11b0SGrant Likely 	if (np->pde)
109102af11b0SGrant Likely 		proc_device_tree_update_prop(np->pde, newprop, oldprop);
109202af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */
109302af11b0SGrant Likely 
109402af11b0SGrant Likely 	return 0;
109502af11b0SGrant Likely }
1096fcdeb7feSGrant Likely 
1097fcdeb7feSGrant Likely #if defined(CONFIG_OF_DYNAMIC)
1098fcdeb7feSGrant Likely /*
1099fcdeb7feSGrant Likely  * Support for dynamic device trees.
1100fcdeb7feSGrant Likely  *
1101fcdeb7feSGrant Likely  * On some platforms, the device tree can be manipulated at runtime.
1102fcdeb7feSGrant Likely  * The routines in this section support adding, removing and changing
1103fcdeb7feSGrant Likely  * device tree nodes.
1104fcdeb7feSGrant Likely  */
1105fcdeb7feSGrant Likely 
1106fcdeb7feSGrant Likely /**
1107fcdeb7feSGrant Likely  * of_attach_node - Plug a device node into the tree and global list.
1108fcdeb7feSGrant Likely  */
1109fcdeb7feSGrant Likely void of_attach_node(struct device_node *np)
1110fcdeb7feSGrant Likely {
1111fcdeb7feSGrant Likely 	unsigned long flags;
1112fcdeb7feSGrant Likely 
1113fcdeb7feSGrant Likely 	write_lock_irqsave(&devtree_lock, flags);
1114fcdeb7feSGrant Likely 	np->sibling = np->parent->child;
1115fcdeb7feSGrant Likely 	np->allnext = allnodes;
1116fcdeb7feSGrant Likely 	np->parent->child = np;
1117fcdeb7feSGrant Likely 	allnodes = np;
1118fcdeb7feSGrant Likely 	write_unlock_irqrestore(&devtree_lock, flags);
1119fcdeb7feSGrant Likely }
1120fcdeb7feSGrant Likely 
1121fcdeb7feSGrant Likely /**
1122fcdeb7feSGrant Likely  * of_detach_node - "Unplug" a node from the device tree.
1123fcdeb7feSGrant Likely  *
1124fcdeb7feSGrant Likely  * The caller must hold a reference to the node.  The memory associated with
1125fcdeb7feSGrant Likely  * the node is not freed until its refcount goes to zero.
1126fcdeb7feSGrant Likely  */
1127fcdeb7feSGrant Likely void of_detach_node(struct device_node *np)
1128fcdeb7feSGrant Likely {
1129fcdeb7feSGrant Likely 	struct device_node *parent;
1130fcdeb7feSGrant Likely 	unsigned long flags;
1131fcdeb7feSGrant Likely 
1132fcdeb7feSGrant Likely 	write_lock_irqsave(&devtree_lock, flags);
1133fcdeb7feSGrant Likely 
1134fcdeb7feSGrant Likely 	parent = np->parent;
1135fcdeb7feSGrant Likely 	if (!parent)
1136fcdeb7feSGrant Likely 		goto out_unlock;
1137fcdeb7feSGrant Likely 
1138fcdeb7feSGrant Likely 	if (allnodes == np)
1139fcdeb7feSGrant Likely 		allnodes = np->allnext;
1140fcdeb7feSGrant Likely 	else {
1141fcdeb7feSGrant Likely 		struct device_node *prev;
1142fcdeb7feSGrant Likely 		for (prev = allnodes;
1143fcdeb7feSGrant Likely 		     prev->allnext != np;
1144fcdeb7feSGrant Likely 		     prev = prev->allnext)
1145fcdeb7feSGrant Likely 			;
1146fcdeb7feSGrant Likely 		prev->allnext = np->allnext;
1147fcdeb7feSGrant Likely 	}
1148fcdeb7feSGrant Likely 
1149fcdeb7feSGrant Likely 	if (parent->child == np)
1150fcdeb7feSGrant Likely 		parent->child = np->sibling;
1151fcdeb7feSGrant Likely 	else {
1152fcdeb7feSGrant Likely 		struct device_node *prevsib;
1153fcdeb7feSGrant Likely 		for (prevsib = np->parent->child;
1154fcdeb7feSGrant Likely 		     prevsib->sibling != np;
1155fcdeb7feSGrant Likely 		     prevsib = prevsib->sibling)
1156fcdeb7feSGrant Likely 			;
1157fcdeb7feSGrant Likely 		prevsib->sibling = np->sibling;
1158fcdeb7feSGrant Likely 	}
1159fcdeb7feSGrant Likely 
1160fcdeb7feSGrant Likely 	of_node_set_flag(np, OF_DETACHED);
1161fcdeb7feSGrant Likely 
1162fcdeb7feSGrant Likely out_unlock:
1163fcdeb7feSGrant Likely 	write_unlock_irqrestore(&devtree_lock, flags);
1164fcdeb7feSGrant Likely }
1165fcdeb7feSGrant Likely #endif /* defined(CONFIG_OF_DYNAMIC) */
1166fcdeb7feSGrant Likely 
1167611cad72SShawn Guo static void of_alias_add(struct alias_prop *ap, struct device_node *np,
1168611cad72SShawn Guo 			 int id, const char *stem, int stem_len)
1169611cad72SShawn Guo {
1170611cad72SShawn Guo 	ap->np = np;
1171611cad72SShawn Guo 	ap->id = id;
1172611cad72SShawn Guo 	strncpy(ap->stem, stem, stem_len);
1173611cad72SShawn Guo 	ap->stem[stem_len] = 0;
1174611cad72SShawn Guo 	list_add_tail(&ap->link, &aliases_lookup);
1175611cad72SShawn Guo 	pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
1176611cad72SShawn Guo 		 ap->alias, ap->stem, ap->id, np ? np->full_name : NULL);
1177611cad72SShawn Guo }
1178611cad72SShawn Guo 
1179611cad72SShawn Guo /**
1180611cad72SShawn Guo  * of_alias_scan - Scan all properties of 'aliases' node
1181611cad72SShawn Guo  *
1182611cad72SShawn Guo  * The function scans all the properties of 'aliases' node and populate
1183611cad72SShawn Guo  * the the global lookup table with the properties.  It returns the
1184611cad72SShawn Guo  * number of alias_prop found, or error code in error case.
1185611cad72SShawn Guo  *
1186611cad72SShawn Guo  * @dt_alloc:	An allocator that provides a virtual address to memory
1187611cad72SShawn Guo  *		for the resulting tree
1188611cad72SShawn Guo  */
1189611cad72SShawn Guo void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
1190611cad72SShawn Guo {
1191611cad72SShawn Guo 	struct property *pp;
1192611cad72SShawn Guo 
1193611cad72SShawn Guo 	of_chosen = of_find_node_by_path("/chosen");
1194611cad72SShawn Guo 	if (of_chosen == NULL)
1195611cad72SShawn Guo 		of_chosen = of_find_node_by_path("/chosen@0");
1196611cad72SShawn Guo 	of_aliases = of_find_node_by_path("/aliases");
1197611cad72SShawn Guo 	if (!of_aliases)
1198611cad72SShawn Guo 		return;
1199611cad72SShawn Guo 
12008af0da93SDong Aisheng 	for_each_property_of_node(of_aliases, pp) {
1201611cad72SShawn Guo 		const char *start = pp->name;
1202611cad72SShawn Guo 		const char *end = start + strlen(start);
1203611cad72SShawn Guo 		struct device_node *np;
1204611cad72SShawn Guo 		struct alias_prop *ap;
1205611cad72SShawn Guo 		int id, len;
1206611cad72SShawn Guo 
1207611cad72SShawn Guo 		/* Skip those we do not want to proceed */
1208611cad72SShawn Guo 		if (!strcmp(pp->name, "name") ||
1209611cad72SShawn Guo 		    !strcmp(pp->name, "phandle") ||
1210611cad72SShawn Guo 		    !strcmp(pp->name, "linux,phandle"))
1211611cad72SShawn Guo 			continue;
1212611cad72SShawn Guo 
1213611cad72SShawn Guo 		np = of_find_node_by_path(pp->value);
1214611cad72SShawn Guo 		if (!np)
1215611cad72SShawn Guo 			continue;
1216611cad72SShawn Guo 
1217611cad72SShawn Guo 		/* walk the alias backwards to extract the id and work out
1218611cad72SShawn Guo 		 * the 'stem' string */
1219611cad72SShawn Guo 		while (isdigit(*(end-1)) && end > start)
1220611cad72SShawn Guo 			end--;
1221611cad72SShawn Guo 		len = end - start;
1222611cad72SShawn Guo 
1223611cad72SShawn Guo 		if (kstrtoint(end, 10, &id) < 0)
1224611cad72SShawn Guo 			continue;
1225611cad72SShawn Guo 
1226611cad72SShawn Guo 		/* Allocate an alias_prop with enough space for the stem */
1227611cad72SShawn Guo 		ap = dt_alloc(sizeof(*ap) + len + 1, 4);
1228611cad72SShawn Guo 		if (!ap)
1229611cad72SShawn Guo 			continue;
1230611cad72SShawn Guo 		ap->alias = start;
1231611cad72SShawn Guo 		of_alias_add(ap, np, id, start, len);
1232611cad72SShawn Guo 	}
1233611cad72SShawn Guo }
1234611cad72SShawn Guo 
1235611cad72SShawn Guo /**
1236611cad72SShawn Guo  * of_alias_get_id - Get alias id for the given device_node
1237611cad72SShawn Guo  * @np:		Pointer to the given device_node
1238611cad72SShawn Guo  * @stem:	Alias stem of the given device_node
1239611cad72SShawn Guo  *
1240611cad72SShawn Guo  * The function travels the lookup table to get alias id for the given
1241611cad72SShawn Guo  * device_node and alias stem.  It returns the alias id if find it.
1242611cad72SShawn Guo  */
1243611cad72SShawn Guo int of_alias_get_id(struct device_node *np, const char *stem)
1244611cad72SShawn Guo {
1245611cad72SShawn Guo 	struct alias_prop *app;
1246611cad72SShawn Guo 	int id = -ENODEV;
1247611cad72SShawn Guo 
1248611cad72SShawn Guo 	mutex_lock(&of_aliases_mutex);
1249611cad72SShawn Guo 	list_for_each_entry(app, &aliases_lookup, link) {
1250611cad72SShawn Guo 		if (strcmp(app->stem, stem) != 0)
1251611cad72SShawn Guo 			continue;
1252611cad72SShawn Guo 
1253611cad72SShawn Guo 		if (np == app->np) {
1254611cad72SShawn Guo 			id = app->id;
1255611cad72SShawn Guo 			break;
1256611cad72SShawn Guo 		}
1257611cad72SShawn Guo 	}
1258611cad72SShawn Guo 	mutex_unlock(&of_aliases_mutex);
1259611cad72SShawn Guo 
1260611cad72SShawn Guo 	return id;
1261611cad72SShawn Guo }
1262611cad72SShawn Guo EXPORT_SYMBOL_GPL(of_alias_get_id);
1263c541adc6SStephen Warren 
1264c541adc6SStephen Warren const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
1265c541adc6SStephen Warren 			       u32 *pu)
1266c541adc6SStephen Warren {
1267c541adc6SStephen Warren 	const void *curv = cur;
1268c541adc6SStephen Warren 
1269c541adc6SStephen Warren 	if (!prop)
1270c541adc6SStephen Warren 		return NULL;
1271c541adc6SStephen Warren 
1272c541adc6SStephen Warren 	if (!cur) {
1273c541adc6SStephen Warren 		curv = prop->value;
1274c541adc6SStephen Warren 		goto out_val;
1275c541adc6SStephen Warren 	}
1276c541adc6SStephen Warren 
1277c541adc6SStephen Warren 	curv += sizeof(*cur);
1278c541adc6SStephen Warren 	if (curv >= prop->value + prop->length)
1279c541adc6SStephen Warren 		return NULL;
1280c541adc6SStephen Warren 
1281c541adc6SStephen Warren out_val:
1282c541adc6SStephen Warren 	*pu = be32_to_cpup(curv);
1283c541adc6SStephen Warren 	return curv;
1284c541adc6SStephen Warren }
1285c541adc6SStephen Warren EXPORT_SYMBOL_GPL(of_prop_next_u32);
1286c541adc6SStephen Warren 
1287c541adc6SStephen Warren const char *of_prop_next_string(struct property *prop, const char *cur)
1288c541adc6SStephen Warren {
1289c541adc6SStephen Warren 	const void *curv = cur;
1290c541adc6SStephen Warren 
1291c541adc6SStephen Warren 	if (!prop)
1292c541adc6SStephen Warren 		return NULL;
1293c541adc6SStephen Warren 
1294c541adc6SStephen Warren 	if (!cur)
1295c541adc6SStephen Warren 		return prop->value;
1296c541adc6SStephen Warren 
1297c541adc6SStephen Warren 	curv += strlen(cur) + 1;
1298c541adc6SStephen Warren 	if (curv >= prop->value + prop->length)
1299c541adc6SStephen Warren 		return NULL;
1300c541adc6SStephen Warren 
1301c541adc6SStephen Warren 	return curv;
1302c541adc6SStephen Warren }
1303c541adc6SStephen Warren EXPORT_SYMBOL_GPL(of_prop_next_string);
1304