xref: /openbmc/linux/drivers/of/base.c (revision eded9dd4)
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 
27ced4eec9SStepan Moskovchenko #include "of_private.h"
28611cad72SShawn Guo 
29ced4eec9SStepan Moskovchenko LIST_HEAD(aliases_lookup);
30611cad72SShawn Guo 
31465aac6dSRandy Dunlap struct device_node *of_allnodes;
32465aac6dSRandy Dunlap EXPORT_SYMBOL(of_allnodes);
33fc0bdae4SGrant Likely struct device_node *of_chosen;
34611cad72SShawn Guo struct device_node *of_aliases;
35611cad72SShawn Guo 
36ced4eec9SStepan Moskovchenko DEFINE_MUTEX(of_aliases_mutex);
371ef4d424SStephen Rothwell 
38581b605aSStephen Rothwell /* use when traversing tree through the allnext, child, sibling,
39581b605aSStephen Rothwell  * or parent members of struct device_node.
40581b605aSStephen Rothwell  */
41d6d3c4e6SThomas Gleixner DEFINE_RAW_SPINLOCK(devtree_lock);
4297e873e5SStephen Rothwell 
4397e873e5SStephen Rothwell int of_n_addr_cells(struct device_node *np)
4497e873e5SStephen Rothwell {
45a9fadeefSJeremy Kerr 	const __be32 *ip;
4697e873e5SStephen Rothwell 
4797e873e5SStephen Rothwell 	do {
4897e873e5SStephen Rothwell 		if (np->parent)
4997e873e5SStephen Rothwell 			np = np->parent;
5097e873e5SStephen Rothwell 		ip = of_get_property(np, "#address-cells", NULL);
5197e873e5SStephen Rothwell 		if (ip)
5233714881SJeremy Kerr 			return be32_to_cpup(ip);
5397e873e5SStephen Rothwell 	} while (np->parent);
5497e873e5SStephen Rothwell 	/* No #address-cells property for the root node */
5597e873e5SStephen Rothwell 	return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
5697e873e5SStephen Rothwell }
5797e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_addr_cells);
5897e873e5SStephen Rothwell 
5997e873e5SStephen Rothwell int of_n_size_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, "#size-cells", NULL);
6797e873e5SStephen Rothwell 		if (ip)
6833714881SJeremy Kerr 			return be32_to_cpup(ip);
6997e873e5SStephen Rothwell 	} while (np->parent);
7097e873e5SStephen Rothwell 	/* No #size-cells property for the root node */
7197e873e5SStephen Rothwell 	return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
7297e873e5SStephen Rothwell }
7397e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_size_cells);
7497e873e5SStephen Rothwell 
750f22dd39SGrant Likely #if defined(CONFIG_OF_DYNAMIC)
76923f7e30SGrant Likely /**
77923f7e30SGrant Likely  *	of_node_get - Increment refcount of a node
78923f7e30SGrant Likely  *	@node:	Node to inc refcount, NULL is supported to
79923f7e30SGrant Likely  *		simplify writing of callers
80923f7e30SGrant Likely  *
81923f7e30SGrant Likely  *	Returns node.
82923f7e30SGrant Likely  */
83923f7e30SGrant Likely struct device_node *of_node_get(struct device_node *node)
84923f7e30SGrant Likely {
85923f7e30SGrant Likely 	if (node)
86923f7e30SGrant Likely 		kref_get(&node->kref);
87923f7e30SGrant Likely 	return node;
88923f7e30SGrant Likely }
89923f7e30SGrant Likely EXPORT_SYMBOL(of_node_get);
90923f7e30SGrant Likely 
91923f7e30SGrant Likely static inline struct device_node *kref_to_device_node(struct kref *kref)
92923f7e30SGrant Likely {
93923f7e30SGrant Likely 	return container_of(kref, struct device_node, kref);
94923f7e30SGrant Likely }
95923f7e30SGrant Likely 
96923f7e30SGrant Likely /**
97923f7e30SGrant Likely  *	of_node_release - release a dynamically allocated node
98923f7e30SGrant Likely  *	@kref:  kref element of the node to be released
99923f7e30SGrant Likely  *
100923f7e30SGrant Likely  *	In of_node_put() this function is passed to kref_put()
101923f7e30SGrant Likely  *	as the destructor.
102923f7e30SGrant Likely  */
103923f7e30SGrant Likely static void of_node_release(struct kref *kref)
104923f7e30SGrant Likely {
105923f7e30SGrant Likely 	struct device_node *node = kref_to_device_node(kref);
106923f7e30SGrant Likely 	struct property *prop = node->properties;
107923f7e30SGrant Likely 
108923f7e30SGrant Likely 	/* We should never be releasing nodes that haven't been detached. */
109923f7e30SGrant Likely 	if (!of_node_check_flag(node, OF_DETACHED)) {
110923f7e30SGrant Likely 		pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name);
111923f7e30SGrant Likely 		dump_stack();
112923f7e30SGrant Likely 		kref_init(&node->kref);
113923f7e30SGrant Likely 		return;
114923f7e30SGrant Likely 	}
115923f7e30SGrant Likely 
116923f7e30SGrant Likely 	if (!of_node_check_flag(node, OF_DYNAMIC))
117923f7e30SGrant Likely 		return;
118923f7e30SGrant Likely 
119923f7e30SGrant Likely 	while (prop) {
120923f7e30SGrant Likely 		struct property *next = prop->next;
121923f7e30SGrant Likely 		kfree(prop->name);
122923f7e30SGrant Likely 		kfree(prop->value);
123923f7e30SGrant Likely 		kfree(prop);
124923f7e30SGrant Likely 		prop = next;
125923f7e30SGrant Likely 
126923f7e30SGrant Likely 		if (!prop) {
127923f7e30SGrant Likely 			prop = node->deadprops;
128923f7e30SGrant Likely 			node->deadprops = NULL;
129923f7e30SGrant Likely 		}
130923f7e30SGrant Likely 	}
131923f7e30SGrant Likely 	kfree(node->full_name);
132923f7e30SGrant Likely 	kfree(node->data);
133923f7e30SGrant Likely 	kfree(node);
134923f7e30SGrant Likely }
135923f7e30SGrant Likely 
136923f7e30SGrant Likely /**
137923f7e30SGrant Likely  *	of_node_put - Decrement refcount of a node
138923f7e30SGrant Likely  *	@node:	Node to dec refcount, NULL is supported to
139923f7e30SGrant Likely  *		simplify writing of callers
140923f7e30SGrant Likely  *
141923f7e30SGrant Likely  */
142923f7e30SGrant Likely void of_node_put(struct device_node *node)
143923f7e30SGrant Likely {
144923f7e30SGrant Likely 	if (node)
145923f7e30SGrant Likely 		kref_put(&node->kref, of_node_release);
146923f7e30SGrant Likely }
147923f7e30SGrant Likely EXPORT_SYMBOL(of_node_put);
1480f22dd39SGrant Likely #endif /* CONFIG_OF_DYNAMIC */
149923f7e30SGrant Likely 
15028d0e36bSThomas Gleixner static struct property *__of_find_property(const struct device_node *np,
15128d0e36bSThomas Gleixner 					   const char *name, int *lenp)
152581b605aSStephen Rothwell {
153581b605aSStephen Rothwell 	struct property *pp;
154581b605aSStephen Rothwell 
15564e4566fSTimur Tabi 	if (!np)
15664e4566fSTimur Tabi 		return NULL;
15764e4566fSTimur Tabi 
158a3a7cab1SSachin Kamat 	for (pp = np->properties; pp; pp = pp->next) {
159581b605aSStephen Rothwell 		if (of_prop_cmp(pp->name, name) == 0) {
160a3a7cab1SSachin Kamat 			if (lenp)
161581b605aSStephen Rothwell 				*lenp = pp->length;
162581b605aSStephen Rothwell 			break;
163581b605aSStephen Rothwell 		}
164581b605aSStephen Rothwell 	}
16528d0e36bSThomas Gleixner 
16628d0e36bSThomas Gleixner 	return pp;
16728d0e36bSThomas Gleixner }
16828d0e36bSThomas Gleixner 
16928d0e36bSThomas Gleixner struct property *of_find_property(const struct device_node *np,
17028d0e36bSThomas Gleixner 				  const char *name,
17128d0e36bSThomas Gleixner 				  int *lenp)
17228d0e36bSThomas Gleixner {
17328d0e36bSThomas Gleixner 	struct property *pp;
174d6d3c4e6SThomas Gleixner 	unsigned long flags;
17528d0e36bSThomas Gleixner 
176d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
17728d0e36bSThomas Gleixner 	pp = __of_find_property(np, name, lenp);
178d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
179581b605aSStephen Rothwell 
180581b605aSStephen Rothwell 	return pp;
181581b605aSStephen Rothwell }
182581b605aSStephen Rothwell EXPORT_SYMBOL(of_find_property);
183581b605aSStephen Rothwell 
184e91edcf5SGrant Likely /**
185e91edcf5SGrant Likely  * of_find_all_nodes - Get next node in global list
186e91edcf5SGrant Likely  * @prev:	Previous node or NULL to start iteration
187e91edcf5SGrant Likely  *		of_node_put() will be called on it
188e91edcf5SGrant Likely  *
189e91edcf5SGrant Likely  * Returns a node pointer with refcount incremented, use
190e91edcf5SGrant Likely  * of_node_put() on it when done.
191e91edcf5SGrant Likely  */
192e91edcf5SGrant Likely struct device_node *of_find_all_nodes(struct device_node *prev)
193e91edcf5SGrant Likely {
194e91edcf5SGrant Likely 	struct device_node *np;
195d25d8694SBenjamin Herrenschmidt 	unsigned long flags;
196e91edcf5SGrant Likely 
197d25d8694SBenjamin Herrenschmidt 	raw_spin_lock_irqsave(&devtree_lock, flags);
198465aac6dSRandy Dunlap 	np = prev ? prev->allnext : of_allnodes;
199e91edcf5SGrant Likely 	for (; np != NULL; np = np->allnext)
200e91edcf5SGrant Likely 		if (of_node_get(np))
201e91edcf5SGrant Likely 			break;
202e91edcf5SGrant Likely 	of_node_put(prev);
203d25d8694SBenjamin Herrenschmidt 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
204e91edcf5SGrant Likely 	return np;
205e91edcf5SGrant Likely }
206e91edcf5SGrant Likely EXPORT_SYMBOL(of_find_all_nodes);
207e91edcf5SGrant Likely 
20897e873e5SStephen Rothwell /*
20997e873e5SStephen Rothwell  * Find a property with a given name for a given node
21097e873e5SStephen Rothwell  * and return the value.
21197e873e5SStephen Rothwell  */
21228d0e36bSThomas Gleixner static const void *__of_get_property(const struct device_node *np,
21328d0e36bSThomas Gleixner 				     const char *name, int *lenp)
21428d0e36bSThomas Gleixner {
21528d0e36bSThomas Gleixner 	struct property *pp = __of_find_property(np, name, lenp);
21628d0e36bSThomas Gleixner 
21728d0e36bSThomas Gleixner 	return pp ? pp->value : NULL;
21828d0e36bSThomas Gleixner }
21928d0e36bSThomas Gleixner 
22028d0e36bSThomas Gleixner /*
22128d0e36bSThomas Gleixner  * Find a property with a given name for a given node
22228d0e36bSThomas Gleixner  * and return the value.
22328d0e36bSThomas Gleixner  */
22497e873e5SStephen Rothwell const void *of_get_property(const struct device_node *np, const char *name,
22597e873e5SStephen Rothwell 			    int *lenp)
22697e873e5SStephen Rothwell {
22797e873e5SStephen Rothwell 	struct property *pp = of_find_property(np, name, lenp);
22897e873e5SStephen Rothwell 
22997e873e5SStephen Rothwell 	return pp ? pp->value : NULL;
23097e873e5SStephen Rothwell }
23197e873e5SStephen Rothwell EXPORT_SYMBOL(of_get_property);
2320081cbc3SStephen Rothwell 
2330081cbc3SStephen Rothwell /** Checks if the given "compat" string matches one of the strings in
2340081cbc3SStephen Rothwell  * the device's "compatible" property
2350081cbc3SStephen Rothwell  */
23628d0e36bSThomas Gleixner static int __of_device_is_compatible(const struct device_node *device,
2370081cbc3SStephen Rothwell 				     const char *compat)
2380081cbc3SStephen Rothwell {
2390081cbc3SStephen Rothwell 	const char* cp;
2400081cbc3SStephen Rothwell 	int cplen, l;
2410081cbc3SStephen Rothwell 
24228d0e36bSThomas Gleixner 	cp = __of_get_property(device, "compatible", &cplen);
2430081cbc3SStephen Rothwell 	if (cp == NULL)
2440081cbc3SStephen Rothwell 		return 0;
2450081cbc3SStephen Rothwell 	while (cplen > 0) {
2460081cbc3SStephen Rothwell 		if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
2470081cbc3SStephen Rothwell 			return 1;
2480081cbc3SStephen Rothwell 		l = strlen(cp) + 1;
2490081cbc3SStephen Rothwell 		cp += l;
2500081cbc3SStephen Rothwell 		cplen -= l;
2510081cbc3SStephen Rothwell 	}
2520081cbc3SStephen Rothwell 
2530081cbc3SStephen Rothwell 	return 0;
2540081cbc3SStephen Rothwell }
25528d0e36bSThomas Gleixner 
25628d0e36bSThomas Gleixner /** Checks if the given "compat" string matches one of the strings in
25728d0e36bSThomas Gleixner  * the device's "compatible" property
25828d0e36bSThomas Gleixner  */
25928d0e36bSThomas Gleixner int of_device_is_compatible(const struct device_node *device,
26028d0e36bSThomas Gleixner 		const char *compat)
26128d0e36bSThomas Gleixner {
262d6d3c4e6SThomas Gleixner 	unsigned long flags;
26328d0e36bSThomas Gleixner 	int res;
26428d0e36bSThomas Gleixner 
265d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
26628d0e36bSThomas Gleixner 	res = __of_device_is_compatible(device, compat);
267d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
26828d0e36bSThomas Gleixner 	return res;
26928d0e36bSThomas Gleixner }
2700081cbc3SStephen Rothwell EXPORT_SYMBOL(of_device_is_compatible);
271e679c5f4SStephen Rothwell 
272e679c5f4SStephen Rothwell /**
27371a157e8SGrant Likely  * of_machine_is_compatible - Test root of device tree for a given compatible value
2741f43cfb9SGrant Likely  * @compat: compatible string to look for in root node's compatible property.
2751f43cfb9SGrant Likely  *
2761f43cfb9SGrant Likely  * Returns true if the root node has the given value in its
2771f43cfb9SGrant Likely  * compatible property.
2781f43cfb9SGrant Likely  */
27971a157e8SGrant Likely int of_machine_is_compatible(const char *compat)
2801f43cfb9SGrant Likely {
2811f43cfb9SGrant Likely 	struct device_node *root;
2821f43cfb9SGrant Likely 	int rc = 0;
2831f43cfb9SGrant Likely 
2841f43cfb9SGrant Likely 	root = of_find_node_by_path("/");
2851f43cfb9SGrant Likely 	if (root) {
2861f43cfb9SGrant Likely 		rc = of_device_is_compatible(root, compat);
2871f43cfb9SGrant Likely 		of_node_put(root);
2881f43cfb9SGrant Likely 	}
2891f43cfb9SGrant Likely 	return rc;
2901f43cfb9SGrant Likely }
29171a157e8SGrant Likely EXPORT_SYMBOL(of_machine_is_compatible);
2921f43cfb9SGrant Likely 
2931f43cfb9SGrant Likely /**
294c31a0c05SStephen Warren  *  __of_device_is_available - check if a device is available for use
295834d97d4SJosh Boyer  *
296c31a0c05SStephen Warren  *  @device: Node to check for availability, with locks already held
297834d97d4SJosh Boyer  *
298834d97d4SJosh Boyer  *  Returns 1 if the status property is absent or set to "okay" or "ok",
299834d97d4SJosh Boyer  *  0 otherwise
300834d97d4SJosh Boyer  */
301c31a0c05SStephen Warren static int __of_device_is_available(const struct device_node *device)
302834d97d4SJosh Boyer {
303834d97d4SJosh Boyer 	const char *status;
304834d97d4SJosh Boyer 	int statlen;
305834d97d4SJosh Boyer 
306c31a0c05SStephen Warren 	status = __of_get_property(device, "status", &statlen);
307834d97d4SJosh Boyer 	if (status == NULL)
308834d97d4SJosh Boyer 		return 1;
309834d97d4SJosh Boyer 
310834d97d4SJosh Boyer 	if (statlen > 0) {
311834d97d4SJosh Boyer 		if (!strcmp(status, "okay") || !strcmp(status, "ok"))
312834d97d4SJosh Boyer 			return 1;
313834d97d4SJosh Boyer 	}
314834d97d4SJosh Boyer 
315834d97d4SJosh Boyer 	return 0;
316834d97d4SJosh Boyer }
317c31a0c05SStephen Warren 
318c31a0c05SStephen Warren /**
319c31a0c05SStephen Warren  *  of_device_is_available - check if a device is available for use
320c31a0c05SStephen Warren  *
321c31a0c05SStephen Warren  *  @device: Node to check for availability
322c31a0c05SStephen Warren  *
323c31a0c05SStephen Warren  *  Returns 1 if the status property is absent or set to "okay" or "ok",
324c31a0c05SStephen Warren  *  0 otherwise
325c31a0c05SStephen Warren  */
326c31a0c05SStephen Warren int of_device_is_available(const struct device_node *device)
327c31a0c05SStephen Warren {
328c31a0c05SStephen Warren 	unsigned long flags;
329c31a0c05SStephen Warren 	int res;
330c31a0c05SStephen Warren 
331c31a0c05SStephen Warren 	raw_spin_lock_irqsave(&devtree_lock, flags);
332c31a0c05SStephen Warren 	res = __of_device_is_available(device);
333c31a0c05SStephen Warren 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
334c31a0c05SStephen Warren 	return res;
335c31a0c05SStephen Warren 
336c31a0c05SStephen Warren }
337834d97d4SJosh Boyer EXPORT_SYMBOL(of_device_is_available);
338834d97d4SJosh Boyer 
339834d97d4SJosh Boyer /**
340e679c5f4SStephen Rothwell  *	of_get_parent - Get a node's parent if any
341e679c5f4SStephen Rothwell  *	@node:	Node to get parent
342e679c5f4SStephen Rothwell  *
343e679c5f4SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
344e679c5f4SStephen Rothwell  *	of_node_put() on it when done.
345e679c5f4SStephen Rothwell  */
346e679c5f4SStephen Rothwell struct device_node *of_get_parent(const struct device_node *node)
347e679c5f4SStephen Rothwell {
348e679c5f4SStephen Rothwell 	struct device_node *np;
349d6d3c4e6SThomas Gleixner 	unsigned long flags;
350e679c5f4SStephen Rothwell 
351e679c5f4SStephen Rothwell 	if (!node)
352e679c5f4SStephen Rothwell 		return NULL;
353e679c5f4SStephen Rothwell 
354d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
355e679c5f4SStephen Rothwell 	np = of_node_get(node->parent);
356d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
357e679c5f4SStephen Rothwell 	return np;
358e679c5f4SStephen Rothwell }
359e679c5f4SStephen Rothwell EXPORT_SYMBOL(of_get_parent);
360d1cd355aSStephen Rothwell 
361d1cd355aSStephen Rothwell /**
362f4eb0107SMichael Ellerman  *	of_get_next_parent - Iterate to a node's parent
363f4eb0107SMichael Ellerman  *	@node:	Node to get parent of
364f4eb0107SMichael Ellerman  *
365f4eb0107SMichael Ellerman  * 	This is like of_get_parent() except that it drops the
366f4eb0107SMichael Ellerman  * 	refcount on the passed node, making it suitable for iterating
367f4eb0107SMichael Ellerman  * 	through a node's parents.
368f4eb0107SMichael Ellerman  *
369f4eb0107SMichael Ellerman  *	Returns a node pointer with refcount incremented, use
370f4eb0107SMichael Ellerman  *	of_node_put() on it when done.
371f4eb0107SMichael Ellerman  */
372f4eb0107SMichael Ellerman struct device_node *of_get_next_parent(struct device_node *node)
373f4eb0107SMichael Ellerman {
374f4eb0107SMichael Ellerman 	struct device_node *parent;
375d6d3c4e6SThomas Gleixner 	unsigned long flags;
376f4eb0107SMichael Ellerman 
377f4eb0107SMichael Ellerman 	if (!node)
378f4eb0107SMichael Ellerman 		return NULL;
379f4eb0107SMichael Ellerman 
380d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
381f4eb0107SMichael Ellerman 	parent = of_node_get(node->parent);
382f4eb0107SMichael Ellerman 	of_node_put(node);
383d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
384f4eb0107SMichael Ellerman 	return parent;
385f4eb0107SMichael Ellerman }
3866695be68SGuennadi Liakhovetski EXPORT_SYMBOL(of_get_next_parent);
387f4eb0107SMichael Ellerman 
388f4eb0107SMichael Ellerman /**
389d1cd355aSStephen Rothwell  *	of_get_next_child - Iterate a node childs
390d1cd355aSStephen Rothwell  *	@node:	parent node
391d1cd355aSStephen Rothwell  *	@prev:	previous child of the parent node, or NULL to get first
392d1cd355aSStephen Rothwell  *
393d1cd355aSStephen Rothwell  *	Returns a node pointer with refcount incremented, use
394d1cd355aSStephen Rothwell  *	of_node_put() on it when done.
395d1cd355aSStephen Rothwell  */
396d1cd355aSStephen Rothwell struct device_node *of_get_next_child(const struct device_node *node,
397d1cd355aSStephen Rothwell 	struct device_node *prev)
398d1cd355aSStephen Rothwell {
399d1cd355aSStephen Rothwell 	struct device_node *next;
400d6d3c4e6SThomas Gleixner 	unsigned long flags;
401d1cd355aSStephen Rothwell 
402d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
403d1cd355aSStephen Rothwell 	next = prev ? prev->sibling : node->child;
404d1cd355aSStephen Rothwell 	for (; next; next = next->sibling)
405d1cd355aSStephen Rothwell 		if (of_node_get(next))
406d1cd355aSStephen Rothwell 			break;
407d1cd355aSStephen Rothwell 	of_node_put(prev);
408d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
409d1cd355aSStephen Rothwell 	return next;
410d1cd355aSStephen Rothwell }
411d1cd355aSStephen Rothwell EXPORT_SYMBOL(of_get_next_child);
4121ef4d424SStephen Rothwell 
4131ef4d424SStephen Rothwell /**
4143296193dSTimur Tabi  *	of_get_next_available_child - Find the next available child node
4153296193dSTimur Tabi  *	@node:	parent node
4163296193dSTimur Tabi  *	@prev:	previous child of the parent node, or NULL to get first
4173296193dSTimur Tabi  *
4183296193dSTimur Tabi  *      This function is like of_get_next_child(), except that it
4193296193dSTimur Tabi  *      automatically skips any disabled nodes (i.e. status = "disabled").
4203296193dSTimur Tabi  */
4213296193dSTimur Tabi struct device_node *of_get_next_available_child(const struct device_node *node,
4223296193dSTimur Tabi 	struct device_node *prev)
4233296193dSTimur Tabi {
4243296193dSTimur Tabi 	struct device_node *next;
425d25d8694SBenjamin Herrenschmidt 	unsigned long flags;
4263296193dSTimur Tabi 
427d25d8694SBenjamin Herrenschmidt 	raw_spin_lock_irqsave(&devtree_lock, flags);
4283296193dSTimur Tabi 	next = prev ? prev->sibling : node->child;
4293296193dSTimur Tabi 	for (; next; next = next->sibling) {
430c31a0c05SStephen Warren 		if (!__of_device_is_available(next))
4313296193dSTimur Tabi 			continue;
4323296193dSTimur Tabi 		if (of_node_get(next))
4333296193dSTimur Tabi 			break;
4343296193dSTimur Tabi 	}
4353296193dSTimur Tabi 	of_node_put(prev);
436d25d8694SBenjamin Herrenschmidt 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
4373296193dSTimur Tabi 	return next;
4383296193dSTimur Tabi }
4393296193dSTimur Tabi EXPORT_SYMBOL(of_get_next_available_child);
4403296193dSTimur Tabi 
4413296193dSTimur Tabi /**
4429c19761aSSrinivas Kandagatla  *	of_get_child_by_name - Find the child node by name for a given parent
4439c19761aSSrinivas Kandagatla  *	@node:	parent node
4449c19761aSSrinivas Kandagatla  *	@name:	child name to look for.
4459c19761aSSrinivas Kandagatla  *
4469c19761aSSrinivas Kandagatla  *      This function looks for child node for given matching name
4479c19761aSSrinivas Kandagatla  *
4489c19761aSSrinivas Kandagatla  *	Returns a node pointer if found, with refcount incremented, use
4499c19761aSSrinivas Kandagatla  *	of_node_put() on it when done.
4509c19761aSSrinivas Kandagatla  *	Returns NULL if node is not found.
4519c19761aSSrinivas Kandagatla  */
4529c19761aSSrinivas Kandagatla struct device_node *of_get_child_by_name(const struct device_node *node,
4539c19761aSSrinivas Kandagatla 				const char *name)
4549c19761aSSrinivas Kandagatla {
4559c19761aSSrinivas Kandagatla 	struct device_node *child;
4569c19761aSSrinivas Kandagatla 
4579c19761aSSrinivas Kandagatla 	for_each_child_of_node(node, child)
4589c19761aSSrinivas Kandagatla 		if (child->name && (of_node_cmp(child->name, name) == 0))
4599c19761aSSrinivas Kandagatla 			break;
4609c19761aSSrinivas Kandagatla 	return child;
4619c19761aSSrinivas Kandagatla }
4629c19761aSSrinivas Kandagatla EXPORT_SYMBOL(of_get_child_by_name);
4639c19761aSSrinivas Kandagatla 
4649c19761aSSrinivas Kandagatla /**
4651ef4d424SStephen Rothwell  *	of_find_node_by_path - Find a node matching a full OF path
4661ef4d424SStephen Rothwell  *	@path:	The full path to match
4671ef4d424SStephen Rothwell  *
4681ef4d424SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
4691ef4d424SStephen Rothwell  *	of_node_put() on it when done.
4701ef4d424SStephen Rothwell  */
4711ef4d424SStephen Rothwell struct device_node *of_find_node_by_path(const char *path)
4721ef4d424SStephen Rothwell {
473465aac6dSRandy Dunlap 	struct device_node *np = of_allnodes;
474d6d3c4e6SThomas Gleixner 	unsigned long flags;
4751ef4d424SStephen Rothwell 
476d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
4771ef4d424SStephen Rothwell 	for (; np; np = np->allnext) {
4781ef4d424SStephen Rothwell 		if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
4791ef4d424SStephen Rothwell 		    && of_node_get(np))
4801ef4d424SStephen Rothwell 			break;
4811ef4d424SStephen Rothwell 	}
482d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
4831ef4d424SStephen Rothwell 	return np;
4841ef4d424SStephen Rothwell }
4851ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_path);
4861ef4d424SStephen Rothwell 
4871ef4d424SStephen Rothwell /**
4881ef4d424SStephen Rothwell  *	of_find_node_by_name - Find a node by its "name" property
4891ef4d424SStephen Rothwell  *	@from:	The node to start searching from or NULL, the node
4901ef4d424SStephen Rothwell  *		you pass will not be searched, only the next one
4911ef4d424SStephen Rothwell  *		will; typically, you pass what the previous call
4921ef4d424SStephen Rothwell  *		returned. of_node_put() will be called on it
4931ef4d424SStephen Rothwell  *	@name:	The name string to match against
4941ef4d424SStephen Rothwell  *
4951ef4d424SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
4961ef4d424SStephen Rothwell  *	of_node_put() on it when done.
4971ef4d424SStephen Rothwell  */
4981ef4d424SStephen Rothwell struct device_node *of_find_node_by_name(struct device_node *from,
4991ef4d424SStephen Rothwell 	const char *name)
5001ef4d424SStephen Rothwell {
5011ef4d424SStephen Rothwell 	struct device_node *np;
502d6d3c4e6SThomas Gleixner 	unsigned long flags;
5031ef4d424SStephen Rothwell 
504d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
505465aac6dSRandy Dunlap 	np = from ? from->allnext : of_allnodes;
5061ef4d424SStephen Rothwell 	for (; np; np = np->allnext)
5071ef4d424SStephen Rothwell 		if (np->name && (of_node_cmp(np->name, name) == 0)
5081ef4d424SStephen Rothwell 		    && of_node_get(np))
5091ef4d424SStephen Rothwell 			break;
5101ef4d424SStephen Rothwell 	of_node_put(from);
511d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
5121ef4d424SStephen Rothwell 	return np;
5131ef4d424SStephen Rothwell }
5141ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_name);
5151ef4d424SStephen Rothwell 
5161ef4d424SStephen Rothwell /**
5171ef4d424SStephen Rothwell  *	of_find_node_by_type - Find a node by its "device_type" property
5181ef4d424SStephen Rothwell  *	@from:	The node to start searching from, or NULL to start searching
5191ef4d424SStephen Rothwell  *		the entire device tree. The node you pass will not be
5201ef4d424SStephen Rothwell  *		searched, only the next one will; typically, you pass
5211ef4d424SStephen Rothwell  *		what the previous call returned. of_node_put() will be
5221ef4d424SStephen Rothwell  *		called on from for you.
5231ef4d424SStephen Rothwell  *	@type:	The type string to match against
5241ef4d424SStephen Rothwell  *
5251ef4d424SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
5261ef4d424SStephen Rothwell  *	of_node_put() on it when done.
5271ef4d424SStephen Rothwell  */
5281ef4d424SStephen Rothwell struct device_node *of_find_node_by_type(struct device_node *from,
5291ef4d424SStephen Rothwell 	const char *type)
5301ef4d424SStephen Rothwell {
5311ef4d424SStephen Rothwell 	struct device_node *np;
532d6d3c4e6SThomas Gleixner 	unsigned long flags;
5331ef4d424SStephen Rothwell 
534d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
535465aac6dSRandy Dunlap 	np = from ? from->allnext : of_allnodes;
5361ef4d424SStephen Rothwell 	for (; np; np = np->allnext)
5371ef4d424SStephen Rothwell 		if (np->type && (of_node_cmp(np->type, type) == 0)
5381ef4d424SStephen Rothwell 		    && of_node_get(np))
5391ef4d424SStephen Rothwell 			break;
5401ef4d424SStephen Rothwell 	of_node_put(from);
541d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
5421ef4d424SStephen Rothwell 	return np;
5431ef4d424SStephen Rothwell }
5441ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_type);
5451ef4d424SStephen Rothwell 
5461ef4d424SStephen Rothwell /**
5471ef4d424SStephen Rothwell  *	of_find_compatible_node - Find a node based on type and one of the
5481ef4d424SStephen Rothwell  *                                tokens in its "compatible" property
5491ef4d424SStephen Rothwell  *	@from:		The node to start searching from or NULL, the node
5501ef4d424SStephen Rothwell  *			you pass will not be searched, only the next one
5511ef4d424SStephen Rothwell  *			will; typically, you pass what the previous call
5521ef4d424SStephen Rothwell  *			returned. of_node_put() will be called on it
5531ef4d424SStephen Rothwell  *	@type:		The type string to match "device_type" or NULL to ignore
5541ef4d424SStephen Rothwell  *	@compatible:	The string to match to one of the tokens in the device
5551ef4d424SStephen Rothwell  *			"compatible" list.
5561ef4d424SStephen Rothwell  *
5571ef4d424SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
5581ef4d424SStephen Rothwell  *	of_node_put() on it when done.
5591ef4d424SStephen Rothwell  */
5601ef4d424SStephen Rothwell struct device_node *of_find_compatible_node(struct device_node *from,
5611ef4d424SStephen Rothwell 	const char *type, const char *compatible)
5621ef4d424SStephen Rothwell {
5631ef4d424SStephen Rothwell 	struct device_node *np;
564d6d3c4e6SThomas Gleixner 	unsigned long flags;
5651ef4d424SStephen Rothwell 
566d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
567465aac6dSRandy Dunlap 	np = from ? from->allnext : of_allnodes;
5681ef4d424SStephen Rothwell 	for (; np; np = np->allnext) {
5691ef4d424SStephen Rothwell 		if (type
5701ef4d424SStephen Rothwell 		    && !(np->type && (of_node_cmp(np->type, type) == 0)))
5711ef4d424SStephen Rothwell 			continue;
57228d0e36bSThomas Gleixner 		if (__of_device_is_compatible(np, compatible) &&
57328d0e36bSThomas Gleixner 		    of_node_get(np))
5741ef4d424SStephen Rothwell 			break;
5751ef4d424SStephen Rothwell 	}
5761ef4d424SStephen Rothwell 	of_node_put(from);
577d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
5781ef4d424SStephen Rothwell 	return np;
5791ef4d424SStephen Rothwell }
5801ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_compatible_node);
581283029d1SGrant Likely 
582283029d1SGrant Likely /**
5831e291b14SMichael Ellerman  *	of_find_node_with_property - Find a node which has a property with
5841e291b14SMichael Ellerman  *                                   the given name.
5851e291b14SMichael Ellerman  *	@from:		The node to start searching from or NULL, the node
5861e291b14SMichael Ellerman  *			you pass will not be searched, only the next one
5871e291b14SMichael Ellerman  *			will; typically, you pass what the previous call
5881e291b14SMichael Ellerman  *			returned. of_node_put() will be called on it
5891e291b14SMichael Ellerman  *	@prop_name:	The name of the property to look for.
5901e291b14SMichael Ellerman  *
5911e291b14SMichael Ellerman  *	Returns a node pointer with refcount incremented, use
5921e291b14SMichael Ellerman  *	of_node_put() on it when done.
5931e291b14SMichael Ellerman  */
5941e291b14SMichael Ellerman struct device_node *of_find_node_with_property(struct device_node *from,
5951e291b14SMichael Ellerman 	const char *prop_name)
5961e291b14SMichael Ellerman {
5971e291b14SMichael Ellerman 	struct device_node *np;
5981e291b14SMichael Ellerman 	struct property *pp;
599d6d3c4e6SThomas Gleixner 	unsigned long flags;
6001e291b14SMichael Ellerman 
601d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
602465aac6dSRandy Dunlap 	np = from ? from->allnext : of_allnodes;
6031e291b14SMichael Ellerman 	for (; np; np = np->allnext) {
604a3a7cab1SSachin Kamat 		for (pp = np->properties; pp; pp = pp->next) {
6051e291b14SMichael Ellerman 			if (of_prop_cmp(pp->name, prop_name) == 0) {
6061e291b14SMichael Ellerman 				of_node_get(np);
6071e291b14SMichael Ellerman 				goto out;
6081e291b14SMichael Ellerman 			}
6091e291b14SMichael Ellerman 		}
6101e291b14SMichael Ellerman 	}
6111e291b14SMichael Ellerman out:
6121e291b14SMichael Ellerman 	of_node_put(from);
613d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
6141e291b14SMichael Ellerman 	return np;
6151e291b14SMichael Ellerman }
6161e291b14SMichael Ellerman EXPORT_SYMBOL(of_find_node_with_property);
6171e291b14SMichael Ellerman 
61828d0e36bSThomas Gleixner static
61928d0e36bSThomas Gleixner const struct of_device_id *__of_match_node(const struct of_device_id *matches,
620283029d1SGrant Likely 					   const struct device_node *node)
621283029d1SGrant Likely {
622a52f07ecSGrant Likely 	if (!matches)
623a52f07ecSGrant Likely 		return NULL;
624a52f07ecSGrant Likely 
625283029d1SGrant Likely 	while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
626283029d1SGrant Likely 		int match = 1;
627283029d1SGrant Likely 		if (matches->name[0])
628283029d1SGrant Likely 			match &= node->name
629283029d1SGrant Likely 				&& !strcmp(matches->name, node->name);
630283029d1SGrant Likely 		if (matches->type[0])
631283029d1SGrant Likely 			match &= node->type
632283029d1SGrant Likely 				&& !strcmp(matches->type, node->type);
633bc51b0c2SLinus Torvalds 		if (matches->compatible[0])
63428d0e36bSThomas Gleixner 			match &= __of_device_is_compatible(node,
635bc51b0c2SLinus Torvalds 							   matches->compatible);
636bc51b0c2SLinus Torvalds 		if (match)
637283029d1SGrant Likely 			return matches;
638283029d1SGrant Likely 		matches++;
639283029d1SGrant Likely 	}
640283029d1SGrant Likely 	return NULL;
641283029d1SGrant Likely }
64228d0e36bSThomas Gleixner 
64328d0e36bSThomas Gleixner /**
64428d0e36bSThomas Gleixner  * of_match_node - Tell if an device_node has a matching of_match structure
64528d0e36bSThomas Gleixner  *	@matches:	array of of device match structures to search in
64628d0e36bSThomas Gleixner  *	@node:		the of device structure to match against
64728d0e36bSThomas Gleixner  *
64828d0e36bSThomas Gleixner  *	Low level utility function used by device matching.
64928d0e36bSThomas Gleixner  */
65028d0e36bSThomas Gleixner const struct of_device_id *of_match_node(const struct of_device_id *matches,
65128d0e36bSThomas Gleixner 					 const struct device_node *node)
65228d0e36bSThomas Gleixner {
65328d0e36bSThomas Gleixner 	const struct of_device_id *match;
654d6d3c4e6SThomas Gleixner 	unsigned long flags;
65528d0e36bSThomas Gleixner 
656d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
65728d0e36bSThomas Gleixner 	match = __of_match_node(matches, node);
658d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
65928d0e36bSThomas Gleixner 	return match;
66028d0e36bSThomas Gleixner }
661283029d1SGrant Likely EXPORT_SYMBOL(of_match_node);
662283029d1SGrant Likely 
663283029d1SGrant Likely /**
66450c8af4cSStephen Warren  *	of_find_matching_node_and_match - Find a node based on an of_device_id
66550c8af4cSStephen Warren  *					  match table.
666283029d1SGrant Likely  *	@from:		The node to start searching from or NULL, the node
667283029d1SGrant Likely  *			you pass will not be searched, only the next one
668283029d1SGrant Likely  *			will; typically, you pass what the previous call
669283029d1SGrant Likely  *			returned. of_node_put() will be called on it
670283029d1SGrant Likely  *	@matches:	array of of device match structures to search in
67150c8af4cSStephen Warren  *	@match		Updated to point at the matches entry which matched
672283029d1SGrant Likely  *
673283029d1SGrant Likely  *	Returns a node pointer with refcount incremented, use
674283029d1SGrant Likely  *	of_node_put() on it when done.
675283029d1SGrant Likely  */
67650c8af4cSStephen Warren struct device_node *of_find_matching_node_and_match(struct device_node *from,
67750c8af4cSStephen Warren 					const struct of_device_id *matches,
67850c8af4cSStephen Warren 					const struct of_device_id **match)
679283029d1SGrant Likely {
680283029d1SGrant Likely 	struct device_node *np;
681dc71bcf1SThomas Abraham 	const struct of_device_id *m;
682d6d3c4e6SThomas Gleixner 	unsigned long flags;
683283029d1SGrant Likely 
68450c8af4cSStephen Warren 	if (match)
68550c8af4cSStephen Warren 		*match = NULL;
68650c8af4cSStephen Warren 
687d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
688465aac6dSRandy Dunlap 	np = from ? from->allnext : of_allnodes;
689283029d1SGrant Likely 	for (; np; np = np->allnext) {
69028d0e36bSThomas Gleixner 		m = __of_match_node(matches, np);
691dc71bcf1SThomas Abraham 		if (m && of_node_get(np)) {
69250c8af4cSStephen Warren 			if (match)
693dc71bcf1SThomas Abraham 				*match = m;
694283029d1SGrant Likely 			break;
695283029d1SGrant Likely 		}
69650c8af4cSStephen Warren 	}
697283029d1SGrant Likely 	of_node_put(from);
698d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
699283029d1SGrant Likely 	return np;
700283029d1SGrant Likely }
70180c2022eSGrant Likely EXPORT_SYMBOL(of_find_matching_node_and_match);
7023f07af49SGrant Likely 
7033f07af49SGrant Likely /**
7043f07af49SGrant Likely  * of_modalias_node - Lookup appropriate modalias for a device node
7053f07af49SGrant Likely  * @node:	pointer to a device tree node
7063f07af49SGrant Likely  * @modalias:	Pointer to buffer that modalias value will be copied into
7073f07af49SGrant Likely  * @len:	Length of modalias value
7083f07af49SGrant Likely  *
7092ffe8c5fSGrant Likely  * Based on the value of the compatible property, this routine will attempt
7102ffe8c5fSGrant Likely  * to choose an appropriate modalias value for a particular device tree node.
7112ffe8c5fSGrant Likely  * It does this by stripping the manufacturer prefix (as delimited by a ',')
7122ffe8c5fSGrant Likely  * from the first entry in the compatible list property.
7133f07af49SGrant Likely  *
7142ffe8c5fSGrant Likely  * This routine returns 0 on success, <0 on failure.
7153f07af49SGrant Likely  */
7163f07af49SGrant Likely int of_modalias_node(struct device_node *node, char *modalias, int len)
7173f07af49SGrant Likely {
7182ffe8c5fSGrant Likely 	const char *compatible, *p;
7192ffe8c5fSGrant Likely 	int cplen;
7203f07af49SGrant Likely 
7213f07af49SGrant Likely 	compatible = of_get_property(node, "compatible", &cplen);
7222ffe8c5fSGrant Likely 	if (!compatible || strlen(compatible) > cplen)
7233f07af49SGrant Likely 		return -ENODEV;
7243f07af49SGrant Likely 	p = strchr(compatible, ',');
7252ffe8c5fSGrant Likely 	strlcpy(modalias, p ? p + 1 : compatible, len);
7263f07af49SGrant Likely 	return 0;
7273f07af49SGrant Likely }
7283f07af49SGrant Likely EXPORT_SYMBOL_GPL(of_modalias_node);
7293f07af49SGrant Likely 
73064b60e09SAnton Vorontsov /**
73189751a7cSJeremy Kerr  * of_find_node_by_phandle - Find a node given a phandle
73289751a7cSJeremy Kerr  * @handle:	phandle of the node to find
73389751a7cSJeremy Kerr  *
73489751a7cSJeremy Kerr  * Returns a node pointer with refcount incremented, use
73589751a7cSJeremy Kerr  * of_node_put() on it when done.
73689751a7cSJeremy Kerr  */
73789751a7cSJeremy Kerr struct device_node *of_find_node_by_phandle(phandle handle)
73889751a7cSJeremy Kerr {
73989751a7cSJeremy Kerr 	struct device_node *np;
740d25d8694SBenjamin Herrenschmidt 	unsigned long flags;
74189751a7cSJeremy Kerr 
742d25d8694SBenjamin Herrenschmidt 	raw_spin_lock_irqsave(&devtree_lock, flags);
743465aac6dSRandy Dunlap 	for (np = of_allnodes; np; np = np->allnext)
74489751a7cSJeremy Kerr 		if (np->phandle == handle)
74589751a7cSJeremy Kerr 			break;
74689751a7cSJeremy Kerr 	of_node_get(np);
747d25d8694SBenjamin Herrenschmidt 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
74889751a7cSJeremy Kerr 	return np;
74989751a7cSJeremy Kerr }
75089751a7cSJeremy Kerr EXPORT_SYMBOL(of_find_node_by_phandle);
75189751a7cSJeremy Kerr 
75289751a7cSJeremy Kerr /**
753daeec1f0STony Prisk  * of_find_property_value_of_size
754daeec1f0STony Prisk  *
755daeec1f0STony Prisk  * @np:		device node from which the property value is to be read.
756daeec1f0STony Prisk  * @propname:	name of the property to be searched.
757daeec1f0STony Prisk  * @len:	requested length of property value
758daeec1f0STony Prisk  *
759daeec1f0STony Prisk  * Search for a property in a device node and valid the requested size.
760daeec1f0STony Prisk  * Returns the property value on success, -EINVAL if the property does not
761daeec1f0STony Prisk  *  exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
762daeec1f0STony Prisk  * property data isn't large enough.
763daeec1f0STony Prisk  *
764daeec1f0STony Prisk  */
765daeec1f0STony Prisk static void *of_find_property_value_of_size(const struct device_node *np,
766daeec1f0STony Prisk 			const char *propname, u32 len)
767daeec1f0STony Prisk {
768daeec1f0STony Prisk 	struct property *prop = of_find_property(np, propname, NULL);
769daeec1f0STony Prisk 
770daeec1f0STony Prisk 	if (!prop)
771daeec1f0STony Prisk 		return ERR_PTR(-EINVAL);
772daeec1f0STony Prisk 	if (!prop->value)
773daeec1f0STony Prisk 		return ERR_PTR(-ENODATA);
774daeec1f0STony Prisk 	if (len > prop->length)
775daeec1f0STony Prisk 		return ERR_PTR(-EOVERFLOW);
776daeec1f0STony Prisk 
777daeec1f0STony Prisk 	return prop->value;
778daeec1f0STony Prisk }
779daeec1f0STony Prisk 
780daeec1f0STony Prisk /**
7813daf3726STony Prisk  * of_property_read_u32_index - Find and read a u32 from a multi-value property.
7823daf3726STony Prisk  *
7833daf3726STony Prisk  * @np:		device node from which the property value is to be read.
7843daf3726STony Prisk  * @propname:	name of the property to be searched.
7853daf3726STony Prisk  * @index:	index of the u32 in the list of values
7863daf3726STony Prisk  * @out_value:	pointer to return value, modified only if no error.
7873daf3726STony Prisk  *
7883daf3726STony Prisk  * Search for a property in a device node and read nth 32-bit value from
7893daf3726STony Prisk  * it. Returns 0 on success, -EINVAL if the property does not exist,
7903daf3726STony Prisk  * -ENODATA if property does not have a value, and -EOVERFLOW if the
7913daf3726STony Prisk  * property data isn't large enough.
7923daf3726STony Prisk  *
7933daf3726STony Prisk  * The out_value is modified only if a valid u32 value can be decoded.
7943daf3726STony Prisk  */
7953daf3726STony Prisk int of_property_read_u32_index(const struct device_node *np,
7963daf3726STony Prisk 				       const char *propname,
7973daf3726STony Prisk 				       u32 index, u32 *out_value)
7983daf3726STony Prisk {
799daeec1f0STony Prisk 	const u32 *val = of_find_property_value_of_size(np, propname,
800daeec1f0STony Prisk 					((index + 1) * sizeof(*out_value)));
8013daf3726STony Prisk 
802daeec1f0STony Prisk 	if (IS_ERR(val))
803daeec1f0STony Prisk 		return PTR_ERR(val);
8043daf3726STony Prisk 
805daeec1f0STony Prisk 	*out_value = be32_to_cpup(((__be32 *)val) + index);
8063daf3726STony Prisk 	return 0;
8073daf3726STony Prisk }
8083daf3726STony Prisk EXPORT_SYMBOL_GPL(of_property_read_u32_index);
8093daf3726STony Prisk 
8103daf3726STony Prisk /**
811be193249SViresh Kumar  * of_property_read_u8_array - Find and read an array of u8 from a property.
812be193249SViresh Kumar  *
813be193249SViresh Kumar  * @np:		device node from which the property value is to be read.
814be193249SViresh Kumar  * @propname:	name of the property to be searched.
815792efb84SLad, Prabhakar  * @out_values:	pointer to return value, modified only if return value is 0.
816be193249SViresh Kumar  * @sz:		number of array elements to read
817be193249SViresh Kumar  *
818be193249SViresh Kumar  * Search for a property in a device node and read 8-bit value(s) from
819be193249SViresh Kumar  * it. Returns 0 on success, -EINVAL if the property does not exist,
820be193249SViresh Kumar  * -ENODATA if property does not have a value, and -EOVERFLOW if the
821be193249SViresh Kumar  * property data isn't large enough.
822be193249SViresh Kumar  *
823be193249SViresh Kumar  * dts entry of array should be like:
824be193249SViresh Kumar  *	property = /bits/ 8 <0x50 0x60 0x70>;
825be193249SViresh Kumar  *
826792efb84SLad, Prabhakar  * The out_values is modified only if a valid u8 value can be decoded.
827be193249SViresh Kumar  */
828be193249SViresh Kumar int of_property_read_u8_array(const struct device_node *np,
829be193249SViresh Kumar 			const char *propname, u8 *out_values, size_t sz)
830be193249SViresh Kumar {
831daeec1f0STony Prisk 	const u8 *val = of_find_property_value_of_size(np, propname,
832daeec1f0STony Prisk 						(sz * sizeof(*out_values)));
833be193249SViresh Kumar 
834daeec1f0STony Prisk 	if (IS_ERR(val))
835daeec1f0STony Prisk 		return PTR_ERR(val);
836be193249SViresh Kumar 
837be193249SViresh Kumar 	while (sz--)
838be193249SViresh Kumar 		*out_values++ = *val++;
839be193249SViresh Kumar 	return 0;
840be193249SViresh Kumar }
841be193249SViresh Kumar EXPORT_SYMBOL_GPL(of_property_read_u8_array);
842be193249SViresh Kumar 
843be193249SViresh Kumar /**
844be193249SViresh Kumar  * of_property_read_u16_array - Find and read an array of u16 from a property.
845be193249SViresh Kumar  *
846be193249SViresh Kumar  * @np:		device node from which the property value is to be read.
847be193249SViresh Kumar  * @propname:	name of the property to be searched.
848792efb84SLad, Prabhakar  * @out_values:	pointer to return value, modified only if return value is 0.
849be193249SViresh Kumar  * @sz:		number of array elements to read
850be193249SViresh Kumar  *
851be193249SViresh Kumar  * Search for a property in a device node and read 16-bit value(s) from
852be193249SViresh Kumar  * it. Returns 0 on success, -EINVAL if the property does not exist,
853be193249SViresh Kumar  * -ENODATA if property does not have a value, and -EOVERFLOW if the
854be193249SViresh Kumar  * property data isn't large enough.
855be193249SViresh Kumar  *
856be193249SViresh Kumar  * dts entry of array should be like:
857be193249SViresh Kumar  *	property = /bits/ 16 <0x5000 0x6000 0x7000>;
858be193249SViresh Kumar  *
859792efb84SLad, Prabhakar  * The out_values is modified only if a valid u16 value can be decoded.
860be193249SViresh Kumar  */
861be193249SViresh Kumar int of_property_read_u16_array(const struct device_node *np,
862be193249SViresh Kumar 			const char *propname, u16 *out_values, size_t sz)
863be193249SViresh Kumar {
864daeec1f0STony Prisk 	const __be16 *val = of_find_property_value_of_size(np, propname,
865daeec1f0STony Prisk 						(sz * sizeof(*out_values)));
866be193249SViresh Kumar 
867daeec1f0STony Prisk 	if (IS_ERR(val))
868daeec1f0STony Prisk 		return PTR_ERR(val);
869be193249SViresh Kumar 
870be193249SViresh Kumar 	while (sz--)
871be193249SViresh Kumar 		*out_values++ = be16_to_cpup(val++);
872be193249SViresh Kumar 	return 0;
873be193249SViresh Kumar }
874be193249SViresh Kumar EXPORT_SYMBOL_GPL(of_property_read_u16_array);
875be193249SViresh Kumar 
876be193249SViresh Kumar /**
8770e373639SRob Herring  * of_property_read_u32_array - Find and read an array of 32 bit integers
8780e373639SRob Herring  * from a property.
8790e373639SRob Herring  *
880a3b85363SThomas Abraham  * @np:		device node from which the property value is to be read.
881a3b85363SThomas Abraham  * @propname:	name of the property to be searched.
882792efb84SLad, Prabhakar  * @out_values:	pointer to return value, modified only if return value is 0.
883be193249SViresh Kumar  * @sz:		number of array elements to read
884a3b85363SThomas Abraham  *
8850e373639SRob Herring  * Search for a property in a device node and read 32-bit value(s) from
886a3b85363SThomas Abraham  * it. Returns 0 on success, -EINVAL if the property does not exist,
887a3b85363SThomas Abraham  * -ENODATA if property does not have a value, and -EOVERFLOW if the
888a3b85363SThomas Abraham  * property data isn't large enough.
889a3b85363SThomas Abraham  *
890792efb84SLad, Prabhakar  * The out_values is modified only if a valid u32 value can be decoded.
891a3b85363SThomas Abraham  */
892aac285c6SJamie Iles int of_property_read_u32_array(const struct device_node *np,
893aac285c6SJamie Iles 			       const char *propname, u32 *out_values,
894aac285c6SJamie Iles 			       size_t sz)
895a3b85363SThomas Abraham {
896daeec1f0STony Prisk 	const __be32 *val = of_find_property_value_of_size(np, propname,
897daeec1f0STony Prisk 						(sz * sizeof(*out_values)));
898a3b85363SThomas Abraham 
899daeec1f0STony Prisk 	if (IS_ERR(val))
900daeec1f0STony Prisk 		return PTR_ERR(val);
9010e373639SRob Herring 
9020e373639SRob Herring 	while (sz--)
9030e373639SRob Herring 		*out_values++ = be32_to_cpup(val++);
904a3b85363SThomas Abraham 	return 0;
905a3b85363SThomas Abraham }
9060e373639SRob Herring EXPORT_SYMBOL_GPL(of_property_read_u32_array);
907a3b85363SThomas Abraham 
908a3b85363SThomas Abraham /**
9094cd7f7a3SJamie Iles  * of_property_read_u64 - Find and read a 64 bit integer from a property
9104cd7f7a3SJamie Iles  * @np:		device node from which the property value is to be read.
9114cd7f7a3SJamie Iles  * @propname:	name of the property to be searched.
9124cd7f7a3SJamie Iles  * @out_value:	pointer to return value, modified only if return value is 0.
9134cd7f7a3SJamie Iles  *
9144cd7f7a3SJamie Iles  * Search for a property in a device node and read a 64-bit value from
9154cd7f7a3SJamie Iles  * it. Returns 0 on success, -EINVAL if the property does not exist,
9164cd7f7a3SJamie Iles  * -ENODATA if property does not have a value, and -EOVERFLOW if the
9174cd7f7a3SJamie Iles  * property data isn't large enough.
9184cd7f7a3SJamie Iles  *
9194cd7f7a3SJamie Iles  * The out_value is modified only if a valid u64 value can be decoded.
9204cd7f7a3SJamie Iles  */
9214cd7f7a3SJamie Iles int of_property_read_u64(const struct device_node *np, const char *propname,
9224cd7f7a3SJamie Iles 			 u64 *out_value)
9234cd7f7a3SJamie Iles {
924daeec1f0STony Prisk 	const __be32 *val = of_find_property_value_of_size(np, propname,
925daeec1f0STony Prisk 						sizeof(*out_value));
9264cd7f7a3SJamie Iles 
927daeec1f0STony Prisk 	if (IS_ERR(val))
928daeec1f0STony Prisk 		return PTR_ERR(val);
929daeec1f0STony Prisk 
930daeec1f0STony Prisk 	*out_value = of_read_number(val, 2);
9314cd7f7a3SJamie Iles 	return 0;
9324cd7f7a3SJamie Iles }
9334cd7f7a3SJamie Iles EXPORT_SYMBOL_GPL(of_property_read_u64);
9344cd7f7a3SJamie Iles 
9354cd7f7a3SJamie Iles /**
936a3b85363SThomas Abraham  * of_property_read_string - Find and read a string from a property
937a3b85363SThomas Abraham  * @np:		device node from which the property value is to be read.
938a3b85363SThomas Abraham  * @propname:	name of the property to be searched.
939a3b85363SThomas Abraham  * @out_string:	pointer to null terminated return string, modified only if
940a3b85363SThomas Abraham  *		return value is 0.
941a3b85363SThomas Abraham  *
942a3b85363SThomas Abraham  * Search for a property in a device tree node and retrieve a null
943a3b85363SThomas Abraham  * terminated string value (pointer to data, not a copy). Returns 0 on
944a3b85363SThomas Abraham  * success, -EINVAL if the property does not exist, -ENODATA if property
945a3b85363SThomas Abraham  * does not have a value, and -EILSEQ if the string is not null-terminated
946a3b85363SThomas Abraham  * within the length of the property data.
947a3b85363SThomas Abraham  *
948a3b85363SThomas Abraham  * The out_string pointer is modified only if a valid string can be decoded.
949a3b85363SThomas Abraham  */
950aac285c6SJamie Iles int of_property_read_string(struct device_node *np, const char *propname,
951f09bc831SShawn Guo 				const char **out_string)
952a3b85363SThomas Abraham {
953a3b85363SThomas Abraham 	struct property *prop = of_find_property(np, propname, NULL);
954a3b85363SThomas Abraham 	if (!prop)
955a3b85363SThomas Abraham 		return -EINVAL;
956a3b85363SThomas Abraham 	if (!prop->value)
957a3b85363SThomas Abraham 		return -ENODATA;
958a3b85363SThomas Abraham 	if (strnlen(prop->value, prop->length) >= prop->length)
959a3b85363SThomas Abraham 		return -EILSEQ;
960a3b85363SThomas Abraham 	*out_string = prop->value;
961a3b85363SThomas Abraham 	return 0;
962a3b85363SThomas Abraham }
963a3b85363SThomas Abraham EXPORT_SYMBOL_GPL(of_property_read_string);
964a3b85363SThomas Abraham 
965a3b85363SThomas Abraham /**
9664fcd15a0SBenoit Cousson  * of_property_read_string_index - Find and read a string from a multiple
9674fcd15a0SBenoit Cousson  * strings property.
9684fcd15a0SBenoit Cousson  * @np:		device node from which the property value is to be read.
9694fcd15a0SBenoit Cousson  * @propname:	name of the property to be searched.
9704fcd15a0SBenoit Cousson  * @index:	index of the string in the list of strings
9714fcd15a0SBenoit Cousson  * @out_string:	pointer to null terminated return string, modified only if
9724fcd15a0SBenoit Cousson  *		return value is 0.
9734fcd15a0SBenoit Cousson  *
9744fcd15a0SBenoit Cousson  * Search for a property in a device tree node and retrieve a null
9754fcd15a0SBenoit Cousson  * terminated string value (pointer to data, not a copy) in the list of strings
9764fcd15a0SBenoit Cousson  * contained in that property.
9774fcd15a0SBenoit Cousson  * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if
9784fcd15a0SBenoit Cousson  * property does not have a value, and -EILSEQ if the string is not
9794fcd15a0SBenoit Cousson  * null-terminated within the length of the property data.
9804fcd15a0SBenoit Cousson  *
9814fcd15a0SBenoit Cousson  * The out_string pointer is modified only if a valid string can be decoded.
9824fcd15a0SBenoit Cousson  */
9834fcd15a0SBenoit Cousson int of_property_read_string_index(struct device_node *np, const char *propname,
9844fcd15a0SBenoit Cousson 				  int index, const char **output)
9854fcd15a0SBenoit Cousson {
9864fcd15a0SBenoit Cousson 	struct property *prop = of_find_property(np, propname, NULL);
9874fcd15a0SBenoit Cousson 	int i = 0;
9884fcd15a0SBenoit Cousson 	size_t l = 0, total = 0;
9894fcd15a0SBenoit Cousson 	const char *p;
9904fcd15a0SBenoit Cousson 
9914fcd15a0SBenoit Cousson 	if (!prop)
9924fcd15a0SBenoit Cousson 		return -EINVAL;
9934fcd15a0SBenoit Cousson 	if (!prop->value)
9944fcd15a0SBenoit Cousson 		return -ENODATA;
9954fcd15a0SBenoit Cousson 	if (strnlen(prop->value, prop->length) >= prop->length)
9964fcd15a0SBenoit Cousson 		return -EILSEQ;
9974fcd15a0SBenoit Cousson 
9984fcd15a0SBenoit Cousson 	p = prop->value;
9994fcd15a0SBenoit Cousson 
10004fcd15a0SBenoit Cousson 	for (i = 0; total < prop->length; total += l, p += l) {
10014fcd15a0SBenoit Cousson 		l = strlen(p) + 1;
100288af7f58SBenoit Cousson 		if (i++ == index) {
10034fcd15a0SBenoit Cousson 			*output = p;
10044fcd15a0SBenoit Cousson 			return 0;
10054fcd15a0SBenoit Cousson 		}
10064fcd15a0SBenoit Cousson 	}
10074fcd15a0SBenoit Cousson 	return -ENODATA;
10084fcd15a0SBenoit Cousson }
10094fcd15a0SBenoit Cousson EXPORT_SYMBOL_GPL(of_property_read_string_index);
10104fcd15a0SBenoit Cousson 
10117aff0fe3SGrant Likely /**
10127aff0fe3SGrant Likely  * of_property_match_string() - Find string in a list and return index
10137aff0fe3SGrant Likely  * @np: pointer to node containing string list property
10147aff0fe3SGrant Likely  * @propname: string list property name
10157aff0fe3SGrant Likely  * @string: pointer to string to search for in string list
10167aff0fe3SGrant Likely  *
10177aff0fe3SGrant Likely  * This function searches a string list property and returns the index
10187aff0fe3SGrant Likely  * of a specific string value.
10197aff0fe3SGrant Likely  */
10207aff0fe3SGrant Likely int of_property_match_string(struct device_node *np, const char *propname,
10217aff0fe3SGrant Likely 			     const char *string)
10227aff0fe3SGrant Likely {
10237aff0fe3SGrant Likely 	struct property *prop = of_find_property(np, propname, NULL);
10247aff0fe3SGrant Likely 	size_t l;
10257aff0fe3SGrant Likely 	int i;
10267aff0fe3SGrant Likely 	const char *p, *end;
10277aff0fe3SGrant Likely 
10287aff0fe3SGrant Likely 	if (!prop)
10297aff0fe3SGrant Likely 		return -EINVAL;
10307aff0fe3SGrant Likely 	if (!prop->value)
10317aff0fe3SGrant Likely 		return -ENODATA;
10327aff0fe3SGrant Likely 
10337aff0fe3SGrant Likely 	p = prop->value;
10347aff0fe3SGrant Likely 	end = p + prop->length;
10357aff0fe3SGrant Likely 
10367aff0fe3SGrant Likely 	for (i = 0; p < end; i++, p += l) {
10377aff0fe3SGrant Likely 		l = strlen(p) + 1;
10387aff0fe3SGrant Likely 		if (p + l > end)
10397aff0fe3SGrant Likely 			return -EILSEQ;
10407aff0fe3SGrant Likely 		pr_debug("comparing %s with %s\n", string, p);
10417aff0fe3SGrant Likely 		if (strcmp(string, p) == 0)
10427aff0fe3SGrant Likely 			return i; /* Found it; return index */
10437aff0fe3SGrant Likely 	}
10447aff0fe3SGrant Likely 	return -ENODATA;
10457aff0fe3SGrant Likely }
10467aff0fe3SGrant Likely EXPORT_SYMBOL_GPL(of_property_match_string);
10474fcd15a0SBenoit Cousson 
10484fcd15a0SBenoit Cousson /**
10494fcd15a0SBenoit Cousson  * of_property_count_strings - Find and return the number of strings from a
10504fcd15a0SBenoit Cousson  * multiple strings property.
10514fcd15a0SBenoit Cousson  * @np:		device node from which the property value is to be read.
10524fcd15a0SBenoit Cousson  * @propname:	name of the property to be searched.
10534fcd15a0SBenoit Cousson  *
10544fcd15a0SBenoit Cousson  * Search for a property in a device tree node and retrieve the number of null
10554fcd15a0SBenoit Cousson  * terminated string contain in it. Returns the number of strings on
10564fcd15a0SBenoit Cousson  * success, -EINVAL if the property does not exist, -ENODATA if property
10574fcd15a0SBenoit Cousson  * does not have a value, and -EILSEQ if the string is not null-terminated
10584fcd15a0SBenoit Cousson  * within the length of the property data.
10594fcd15a0SBenoit Cousson  */
10604fcd15a0SBenoit Cousson int of_property_count_strings(struct device_node *np, const char *propname)
10614fcd15a0SBenoit Cousson {
10624fcd15a0SBenoit Cousson 	struct property *prop = of_find_property(np, propname, NULL);
10634fcd15a0SBenoit Cousson 	int i = 0;
10644fcd15a0SBenoit Cousson 	size_t l = 0, total = 0;
10654fcd15a0SBenoit Cousson 	const char *p;
10664fcd15a0SBenoit Cousson 
10674fcd15a0SBenoit Cousson 	if (!prop)
10684fcd15a0SBenoit Cousson 		return -EINVAL;
10694fcd15a0SBenoit Cousson 	if (!prop->value)
10704fcd15a0SBenoit Cousson 		return -ENODATA;
10714fcd15a0SBenoit Cousson 	if (strnlen(prop->value, prop->length) >= prop->length)
10724fcd15a0SBenoit Cousson 		return -EILSEQ;
10734fcd15a0SBenoit Cousson 
10744fcd15a0SBenoit Cousson 	p = prop->value;
10754fcd15a0SBenoit Cousson 
107688af7f58SBenoit Cousson 	for (i = 0; total < prop->length; total += l, p += l, i++)
10774fcd15a0SBenoit Cousson 		l = strlen(p) + 1;
107888af7f58SBenoit Cousson 
10794fcd15a0SBenoit Cousson 	return i;
10804fcd15a0SBenoit Cousson }
10814fcd15a0SBenoit Cousson EXPORT_SYMBOL_GPL(of_property_count_strings);
10824fcd15a0SBenoit Cousson 
10834fcd15a0SBenoit Cousson /**
1084739649c5SGrant Likely  * of_parse_phandle - Resolve a phandle property to a device_node pointer
1085739649c5SGrant Likely  * @np: Pointer to device node holding phandle property
1086739649c5SGrant Likely  * @phandle_name: Name of property holding a phandle value
1087739649c5SGrant Likely  * @index: For properties holding a table of phandles, this is the index into
1088739649c5SGrant Likely  *         the table
1089739649c5SGrant Likely  *
1090739649c5SGrant Likely  * Returns the device_node pointer with refcount incremented.  Use
1091739649c5SGrant Likely  * of_node_put() on it when done.
1092739649c5SGrant Likely  */
1093b8fbdc42SSteffen Trumtrar struct device_node *of_parse_phandle(const struct device_node *np,
1094b8fbdc42SSteffen Trumtrar 				     const char *phandle_name, int index)
1095739649c5SGrant Likely {
10969a6b2e58SGrant Likely 	const __be32 *phandle;
1097739649c5SGrant Likely 	int size;
1098739649c5SGrant Likely 
1099739649c5SGrant Likely 	phandle = of_get_property(np, phandle_name, &size);
1100739649c5SGrant Likely 	if ((!phandle) || (size < sizeof(*phandle) * (index + 1)))
1101739649c5SGrant Likely 		return NULL;
1102739649c5SGrant Likely 
11039a6b2e58SGrant Likely 	return of_find_node_by_phandle(be32_to_cpup(phandle + index));
1104739649c5SGrant Likely }
1105739649c5SGrant Likely EXPORT_SYMBOL(of_parse_phandle);
1106739649c5SGrant Likely 
1107bd69f73fSGrant Likely static int __of_parse_phandle_with_args(const struct device_node *np,
1108bd69f73fSGrant Likely 					const char *list_name,
110964b60e09SAnton Vorontsov 					const char *cells_name, int index,
111015c9a0acSGrant Likely 					struct of_phandle_args *out_args)
111164b60e09SAnton Vorontsov {
111215c9a0acSGrant Likely 	const __be32 *list, *list_end;
111323ce04c0SGrant Likely 	int rc = 0, size, cur_index = 0;
111415c9a0acSGrant Likely 	uint32_t count = 0;
111564b60e09SAnton Vorontsov 	struct device_node *node = NULL;
11169a6b2e58SGrant Likely 	phandle phandle;
111764b60e09SAnton Vorontsov 
111815c9a0acSGrant Likely 	/* Retrieve the phandle list property */
111915c9a0acSGrant Likely 	list = of_get_property(np, list_name, &size);
112015c9a0acSGrant Likely 	if (!list)
11211af4c7f1SAlexandre Courbot 		return -ENOENT;
112215c9a0acSGrant Likely 	list_end = list + size / sizeof(*list);
112315c9a0acSGrant Likely 
112415c9a0acSGrant Likely 	/* Loop over the phandles until all the requested entry is found */
112515c9a0acSGrant Likely 	while (list < list_end) {
112623ce04c0SGrant Likely 		rc = -EINVAL;
112715c9a0acSGrant Likely 		count = 0;
112815c9a0acSGrant Likely 
112915c9a0acSGrant Likely 		/*
113015c9a0acSGrant Likely 		 * If phandle is 0, then it is an empty entry with no
113115c9a0acSGrant Likely 		 * arguments.  Skip forward to the next entry.
113215c9a0acSGrant Likely 		 */
11339a6b2e58SGrant Likely 		phandle = be32_to_cpup(list++);
113415c9a0acSGrant Likely 		if (phandle) {
113515c9a0acSGrant Likely 			/*
113615c9a0acSGrant Likely 			 * Find the provider node and parse the #*-cells
113715c9a0acSGrant Likely 			 * property to determine the argument length
113815c9a0acSGrant Likely 			 */
11399a6b2e58SGrant Likely 			node = of_find_node_by_phandle(phandle);
114064b60e09SAnton Vorontsov 			if (!node) {
114115c9a0acSGrant Likely 				pr_err("%s: could not find phandle\n",
114264b60e09SAnton Vorontsov 					 np->full_name);
114323ce04c0SGrant Likely 				goto err;
114415c9a0acSGrant Likely 			}
114515c9a0acSGrant Likely 			if (of_property_read_u32(node, cells_name, &count)) {
114615c9a0acSGrant Likely 				pr_err("%s: could not get %s for %s\n",
114715c9a0acSGrant Likely 					 np->full_name, cells_name,
114815c9a0acSGrant Likely 					 node->full_name);
114923ce04c0SGrant Likely 				goto err;
115015c9a0acSGrant Likely 			}
115115c9a0acSGrant Likely 
115215c9a0acSGrant Likely 			/*
115315c9a0acSGrant Likely 			 * Make sure that the arguments actually fit in the
115415c9a0acSGrant Likely 			 * remaining property data length
115515c9a0acSGrant Likely 			 */
115615c9a0acSGrant Likely 			if (list + count > list_end) {
115715c9a0acSGrant Likely 				pr_err("%s: arguments longer than property\n",
115815c9a0acSGrant Likely 					 np->full_name);
115923ce04c0SGrant Likely 				goto err;
116015c9a0acSGrant Likely 			}
116115c9a0acSGrant Likely 		}
116215c9a0acSGrant Likely 
116315c9a0acSGrant Likely 		/*
116415c9a0acSGrant Likely 		 * All of the error cases above bail out of the loop, so at
116515c9a0acSGrant Likely 		 * this point, the parsing is successful. If the requested
116615c9a0acSGrant Likely 		 * index matches, then fill the out_args structure and return,
116715c9a0acSGrant Likely 		 * or return -ENOENT for an empty entry.
116815c9a0acSGrant Likely 		 */
116923ce04c0SGrant Likely 		rc = -ENOENT;
117015c9a0acSGrant Likely 		if (cur_index == index) {
117115c9a0acSGrant Likely 			if (!phandle)
117223ce04c0SGrant Likely 				goto err;
117315c9a0acSGrant Likely 
117415c9a0acSGrant Likely 			if (out_args) {
117515c9a0acSGrant Likely 				int i;
117615c9a0acSGrant Likely 				if (WARN_ON(count > MAX_PHANDLE_ARGS))
117715c9a0acSGrant Likely 					count = MAX_PHANDLE_ARGS;
117815c9a0acSGrant Likely 				out_args->np = node;
117915c9a0acSGrant Likely 				out_args->args_count = count;
118015c9a0acSGrant Likely 				for (i = 0; i < count; i++)
118115c9a0acSGrant Likely 					out_args->args[i] = be32_to_cpup(list++);
1182b855f16bSTang Yuantian 			} else {
1183b855f16bSTang Yuantian 				of_node_put(node);
118415c9a0acSGrant Likely 			}
118523ce04c0SGrant Likely 
118623ce04c0SGrant Likely 			/* Found it! return success */
118715c9a0acSGrant Likely 			return 0;
118815c9a0acSGrant Likely 		}
118964b60e09SAnton Vorontsov 
119064b60e09SAnton Vorontsov 		of_node_put(node);
119164b60e09SAnton Vorontsov 		node = NULL;
119215c9a0acSGrant Likely 		list += count;
119364b60e09SAnton Vorontsov 		cur_index++;
119464b60e09SAnton Vorontsov 	}
119564b60e09SAnton Vorontsov 
119623ce04c0SGrant Likely 	/*
119723ce04c0SGrant Likely 	 * Unlock node before returning result; will be one of:
119823ce04c0SGrant Likely 	 * -ENOENT : index is for empty phandle
119923ce04c0SGrant Likely 	 * -EINVAL : parsing error on data
1200bd69f73fSGrant Likely 	 * [1..n]  : Number of phandle (count mode; when index = -1)
120123ce04c0SGrant Likely 	 */
1202bd69f73fSGrant Likely 	rc = index < 0 ? cur_index : -ENOENT;
120323ce04c0SGrant Likely  err:
120415c9a0acSGrant Likely 	if (node)
120564b60e09SAnton Vorontsov 		of_node_put(node);
120623ce04c0SGrant Likely 	return rc;
120764b60e09SAnton Vorontsov }
1208bd69f73fSGrant Likely 
1209eded9dd4SStephen Warren /**
1210eded9dd4SStephen Warren  * of_parse_phandle_with_args() - Find a node pointed by phandle in a list
1211eded9dd4SStephen Warren  * @np:		pointer to a device tree node containing a list
1212eded9dd4SStephen Warren  * @list_name:	property name that contains a list
1213eded9dd4SStephen Warren  * @cells_name:	property name that specifies phandles' arguments count
1214eded9dd4SStephen Warren  * @index:	index of a phandle to parse out
1215eded9dd4SStephen Warren  * @out_args:	optional pointer to output arguments structure (will be filled)
1216eded9dd4SStephen Warren  *
1217eded9dd4SStephen Warren  * This function is useful to parse lists of phandles and their arguments.
1218eded9dd4SStephen Warren  * Returns 0 on success and fills out_args, on error returns appropriate
1219eded9dd4SStephen Warren  * errno value.
1220eded9dd4SStephen Warren  *
1221eded9dd4SStephen Warren  * Caller is responsible to call of_node_put() on the returned out_args->node
1222eded9dd4SStephen Warren  * pointer.
1223eded9dd4SStephen Warren  *
1224eded9dd4SStephen Warren  * Example:
1225eded9dd4SStephen Warren  *
1226eded9dd4SStephen Warren  * phandle1: node1 {
1227eded9dd4SStephen Warren  * 	#list-cells = <2>;
1228eded9dd4SStephen Warren  * }
1229eded9dd4SStephen Warren  *
1230eded9dd4SStephen Warren  * phandle2: node2 {
1231eded9dd4SStephen Warren  * 	#list-cells = <1>;
1232eded9dd4SStephen Warren  * }
1233eded9dd4SStephen Warren  *
1234eded9dd4SStephen Warren  * node3 {
1235eded9dd4SStephen Warren  * 	list = <&phandle1 1 2 &phandle2 3>;
1236eded9dd4SStephen Warren  * }
1237eded9dd4SStephen Warren  *
1238eded9dd4SStephen Warren  * To get a device_node of the `node2' node you may call this:
1239eded9dd4SStephen Warren  * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
1240eded9dd4SStephen Warren  */
1241bd69f73fSGrant Likely int of_parse_phandle_with_args(const struct device_node *np, const char *list_name,
1242bd69f73fSGrant Likely 				const char *cells_name, int index,
1243bd69f73fSGrant Likely 				struct of_phandle_args *out_args)
1244bd69f73fSGrant Likely {
1245bd69f73fSGrant Likely 	if (index < 0)
1246bd69f73fSGrant Likely 		return -EINVAL;
1247bd69f73fSGrant Likely 	return __of_parse_phandle_with_args(np, list_name, cells_name, index, out_args);
1248bd69f73fSGrant Likely }
124915c9a0acSGrant Likely EXPORT_SYMBOL(of_parse_phandle_with_args);
125002af11b0SGrant Likely 
1251bd69f73fSGrant Likely /**
1252bd69f73fSGrant Likely  * of_count_phandle_with_args() - Find the number of phandles references in a property
1253bd69f73fSGrant Likely  * @np:		pointer to a device tree node containing a list
1254bd69f73fSGrant Likely  * @list_name:	property name that contains a list
1255bd69f73fSGrant Likely  * @cells_name:	property name that specifies phandles' arguments count
1256bd69f73fSGrant Likely  *
1257bd69f73fSGrant Likely  * Returns the number of phandle + argument tuples within a property. It
1258bd69f73fSGrant Likely  * is a typical pattern to encode a list of phandle and variable
1259bd69f73fSGrant Likely  * arguments into a single property. The number of arguments is encoded
1260bd69f73fSGrant Likely  * by a property in the phandle-target node. For example, a gpios
1261bd69f73fSGrant Likely  * property would contain a list of GPIO specifies consisting of a
1262bd69f73fSGrant Likely  * phandle and 1 or more arguments. The number of arguments are
1263bd69f73fSGrant Likely  * determined by the #gpio-cells property in the node pointed to by the
1264bd69f73fSGrant Likely  * phandle.
1265bd69f73fSGrant Likely  */
1266bd69f73fSGrant Likely int of_count_phandle_with_args(const struct device_node *np, const char *list_name,
1267bd69f73fSGrant Likely 				const char *cells_name)
1268bd69f73fSGrant Likely {
1269bd69f73fSGrant Likely 	return __of_parse_phandle_with_args(np, list_name, cells_name, -1, NULL);
1270bd69f73fSGrant Likely }
1271bd69f73fSGrant Likely EXPORT_SYMBOL(of_count_phandle_with_args);
1272bd69f73fSGrant Likely 
12731cf3d8b3SNathan Fontenot #if defined(CONFIG_OF_DYNAMIC)
12741cf3d8b3SNathan Fontenot static int of_property_notify(int action, struct device_node *np,
12751cf3d8b3SNathan Fontenot 			      struct property *prop)
12761cf3d8b3SNathan Fontenot {
12771cf3d8b3SNathan Fontenot 	struct of_prop_reconfig pr;
12781cf3d8b3SNathan Fontenot 
12791cf3d8b3SNathan Fontenot 	pr.dn = np;
12801cf3d8b3SNathan Fontenot 	pr.prop = prop;
12811cf3d8b3SNathan Fontenot 	return of_reconfig_notify(action, &pr);
12821cf3d8b3SNathan Fontenot }
12831cf3d8b3SNathan Fontenot #else
12841cf3d8b3SNathan Fontenot static int of_property_notify(int action, struct device_node *np,
12851cf3d8b3SNathan Fontenot 			      struct property *prop)
12861cf3d8b3SNathan Fontenot {
12871cf3d8b3SNathan Fontenot 	return 0;
12881cf3d8b3SNathan Fontenot }
12891cf3d8b3SNathan Fontenot #endif
12901cf3d8b3SNathan Fontenot 
129102af11b0SGrant Likely /**
129279d1c712SNathan Fontenot  * of_add_property - Add a property to a node
129302af11b0SGrant Likely  */
129479d1c712SNathan Fontenot int of_add_property(struct device_node *np, struct property *prop)
129502af11b0SGrant Likely {
129602af11b0SGrant Likely 	struct property **next;
129702af11b0SGrant Likely 	unsigned long flags;
12981cf3d8b3SNathan Fontenot 	int rc;
12991cf3d8b3SNathan Fontenot 
13001cf3d8b3SNathan Fontenot 	rc = of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop);
13011cf3d8b3SNathan Fontenot 	if (rc)
13021cf3d8b3SNathan Fontenot 		return rc;
130302af11b0SGrant Likely 
130402af11b0SGrant Likely 	prop->next = NULL;
1305d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
130602af11b0SGrant Likely 	next = &np->properties;
130702af11b0SGrant Likely 	while (*next) {
130802af11b0SGrant Likely 		if (strcmp(prop->name, (*next)->name) == 0) {
130902af11b0SGrant Likely 			/* duplicate ! don't insert it */
1310d6d3c4e6SThomas Gleixner 			raw_spin_unlock_irqrestore(&devtree_lock, flags);
131102af11b0SGrant Likely 			return -1;
131202af11b0SGrant Likely 		}
131302af11b0SGrant Likely 		next = &(*next)->next;
131402af11b0SGrant Likely 	}
131502af11b0SGrant Likely 	*next = prop;
1316d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
131702af11b0SGrant Likely 
131802af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE
131902af11b0SGrant Likely 	/* try to add to proc as well if it was initialized */
132002af11b0SGrant Likely 	if (np->pde)
132102af11b0SGrant Likely 		proc_device_tree_add_prop(np->pde, prop);
132202af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */
132302af11b0SGrant Likely 
132402af11b0SGrant Likely 	return 0;
132502af11b0SGrant Likely }
132602af11b0SGrant Likely 
132702af11b0SGrant Likely /**
132879d1c712SNathan Fontenot  * of_remove_property - Remove a property from a node.
132902af11b0SGrant Likely  *
133002af11b0SGrant Likely  * Note that we don't actually remove it, since we have given out
133102af11b0SGrant Likely  * who-knows-how-many pointers to the data using get-property.
133202af11b0SGrant Likely  * Instead we just move the property to the "dead properties"
133302af11b0SGrant Likely  * list, so it won't be found any more.
133402af11b0SGrant Likely  */
133579d1c712SNathan Fontenot int of_remove_property(struct device_node *np, struct property *prop)
133602af11b0SGrant Likely {
133702af11b0SGrant Likely 	struct property **next;
133802af11b0SGrant Likely 	unsigned long flags;
133902af11b0SGrant Likely 	int found = 0;
13401cf3d8b3SNathan Fontenot 	int rc;
13411cf3d8b3SNathan Fontenot 
13421cf3d8b3SNathan Fontenot 	rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop);
13431cf3d8b3SNathan Fontenot 	if (rc)
13441cf3d8b3SNathan Fontenot 		return rc;
134502af11b0SGrant Likely 
1346d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
134702af11b0SGrant Likely 	next = &np->properties;
134802af11b0SGrant Likely 	while (*next) {
134902af11b0SGrant Likely 		if (*next == prop) {
135002af11b0SGrant Likely 			/* found the node */
135102af11b0SGrant Likely 			*next = prop->next;
135202af11b0SGrant Likely 			prop->next = np->deadprops;
135302af11b0SGrant Likely 			np->deadprops = prop;
135402af11b0SGrant Likely 			found = 1;
135502af11b0SGrant Likely 			break;
135602af11b0SGrant Likely 		}
135702af11b0SGrant Likely 		next = &(*next)->next;
135802af11b0SGrant Likely 	}
1359d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
136002af11b0SGrant Likely 
136102af11b0SGrant Likely 	if (!found)
136202af11b0SGrant Likely 		return -ENODEV;
136302af11b0SGrant Likely 
136402af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE
136502af11b0SGrant Likely 	/* try to remove the proc node as well */
136602af11b0SGrant Likely 	if (np->pde)
136702af11b0SGrant Likely 		proc_device_tree_remove_prop(np->pde, prop);
136802af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */
136902af11b0SGrant Likely 
137002af11b0SGrant Likely 	return 0;
137102af11b0SGrant Likely }
137202af11b0SGrant Likely 
137302af11b0SGrant Likely /*
137479d1c712SNathan Fontenot  * of_update_property - Update a property in a node, if the property does
1375475d0094SDong Aisheng  * not exist, add it.
137602af11b0SGrant Likely  *
137702af11b0SGrant Likely  * Note that we don't actually remove it, since we have given out
137802af11b0SGrant Likely  * who-knows-how-many pointers to the data using get-property.
137902af11b0SGrant Likely  * Instead we just move the property to the "dead properties" list,
138002af11b0SGrant Likely  * and add the new property to the property list
138102af11b0SGrant Likely  */
138279d1c712SNathan Fontenot int of_update_property(struct device_node *np, struct property *newprop)
138302af11b0SGrant Likely {
1384475d0094SDong Aisheng 	struct property **next, *oldprop;
138502af11b0SGrant Likely 	unsigned long flags;
13861cf3d8b3SNathan Fontenot 	int rc, found = 0;
13871cf3d8b3SNathan Fontenot 
13881cf3d8b3SNathan Fontenot 	rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
13891cf3d8b3SNathan Fontenot 	if (rc)
13901cf3d8b3SNathan Fontenot 		return rc;
139102af11b0SGrant Likely 
1392475d0094SDong Aisheng 	if (!newprop->name)
1393475d0094SDong Aisheng 		return -EINVAL;
1394475d0094SDong Aisheng 
1395475d0094SDong Aisheng 	oldprop = of_find_property(np, newprop->name, NULL);
1396475d0094SDong Aisheng 	if (!oldprop)
139779d1c712SNathan Fontenot 		return of_add_property(np, newprop);
1398475d0094SDong Aisheng 
1399d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
140002af11b0SGrant Likely 	next = &np->properties;
140102af11b0SGrant Likely 	while (*next) {
140202af11b0SGrant Likely 		if (*next == oldprop) {
140302af11b0SGrant Likely 			/* found the node */
140402af11b0SGrant Likely 			newprop->next = oldprop->next;
140502af11b0SGrant Likely 			*next = newprop;
140602af11b0SGrant Likely 			oldprop->next = np->deadprops;
140702af11b0SGrant Likely 			np->deadprops = oldprop;
140802af11b0SGrant Likely 			found = 1;
140902af11b0SGrant Likely 			break;
141002af11b0SGrant Likely 		}
141102af11b0SGrant Likely 		next = &(*next)->next;
141202af11b0SGrant Likely 	}
1413d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
141402af11b0SGrant Likely 
141502af11b0SGrant Likely 	if (!found)
141602af11b0SGrant Likely 		return -ENODEV;
141702af11b0SGrant Likely 
141802af11b0SGrant Likely #ifdef CONFIG_PROC_DEVICETREE
141902af11b0SGrant Likely 	/* try to add to proc as well if it was initialized */
142002af11b0SGrant Likely 	if (np->pde)
142102af11b0SGrant Likely 		proc_device_tree_update_prop(np->pde, newprop, oldprop);
142202af11b0SGrant Likely #endif /* CONFIG_PROC_DEVICETREE */
142302af11b0SGrant Likely 
142402af11b0SGrant Likely 	return 0;
142502af11b0SGrant Likely }
1426fcdeb7feSGrant Likely 
1427fcdeb7feSGrant Likely #if defined(CONFIG_OF_DYNAMIC)
1428fcdeb7feSGrant Likely /*
1429fcdeb7feSGrant Likely  * Support for dynamic device trees.
1430fcdeb7feSGrant Likely  *
1431fcdeb7feSGrant Likely  * On some platforms, the device tree can be manipulated at runtime.
1432fcdeb7feSGrant Likely  * The routines in this section support adding, removing and changing
1433fcdeb7feSGrant Likely  * device tree nodes.
1434fcdeb7feSGrant Likely  */
1435fcdeb7feSGrant Likely 
14361cf3d8b3SNathan Fontenot static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
14371cf3d8b3SNathan Fontenot 
14381cf3d8b3SNathan Fontenot int of_reconfig_notifier_register(struct notifier_block *nb)
14391cf3d8b3SNathan Fontenot {
14401cf3d8b3SNathan Fontenot 	return blocking_notifier_chain_register(&of_reconfig_chain, nb);
14411cf3d8b3SNathan Fontenot }
14421a9bd454SNathan Fontenot EXPORT_SYMBOL_GPL(of_reconfig_notifier_register);
14431cf3d8b3SNathan Fontenot 
14441cf3d8b3SNathan Fontenot int of_reconfig_notifier_unregister(struct notifier_block *nb)
14451cf3d8b3SNathan Fontenot {
14461cf3d8b3SNathan Fontenot 	return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
14471cf3d8b3SNathan Fontenot }
14481a9bd454SNathan Fontenot EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister);
14491cf3d8b3SNathan Fontenot 
14501cf3d8b3SNathan Fontenot int of_reconfig_notify(unsigned long action, void *p)
14511cf3d8b3SNathan Fontenot {
14521cf3d8b3SNathan Fontenot 	int rc;
14531cf3d8b3SNathan Fontenot 
14541cf3d8b3SNathan Fontenot 	rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
14551cf3d8b3SNathan Fontenot 	return notifier_to_errno(rc);
14561cf3d8b3SNathan Fontenot }
14571cf3d8b3SNathan Fontenot 
1458e81b3295SNathan Fontenot #ifdef CONFIG_PROC_DEVICETREE
1459e81b3295SNathan Fontenot static void of_add_proc_dt_entry(struct device_node *dn)
1460e81b3295SNathan Fontenot {
1461e81b3295SNathan Fontenot 	struct proc_dir_entry *ent;
1462e81b3295SNathan Fontenot 
1463e81b3295SNathan Fontenot 	ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde);
1464e81b3295SNathan Fontenot 	if (ent)
1465e81b3295SNathan Fontenot 		proc_device_tree_add_node(dn, ent);
1466e81b3295SNathan Fontenot }
1467e81b3295SNathan Fontenot #else
1468e81b3295SNathan Fontenot static void of_add_proc_dt_entry(struct device_node *dn)
1469e81b3295SNathan Fontenot {
1470e81b3295SNathan Fontenot 	return;
1471e81b3295SNathan Fontenot }
1472e81b3295SNathan Fontenot #endif
1473e81b3295SNathan Fontenot 
1474fcdeb7feSGrant Likely /**
1475fcdeb7feSGrant Likely  * of_attach_node - Plug a device node into the tree and global list.
1476fcdeb7feSGrant Likely  */
14771cf3d8b3SNathan Fontenot int of_attach_node(struct device_node *np)
1478fcdeb7feSGrant Likely {
1479fcdeb7feSGrant Likely 	unsigned long flags;
14801cf3d8b3SNathan Fontenot 	int rc;
14811cf3d8b3SNathan Fontenot 
14821cf3d8b3SNathan Fontenot 	rc = of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np);
14831cf3d8b3SNathan Fontenot 	if (rc)
14841cf3d8b3SNathan Fontenot 		return rc;
1485fcdeb7feSGrant Likely 
1486d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
1487fcdeb7feSGrant Likely 	np->sibling = np->parent->child;
1488465aac6dSRandy Dunlap 	np->allnext = of_allnodes;
1489fcdeb7feSGrant Likely 	np->parent->child = np;
1490465aac6dSRandy Dunlap 	of_allnodes = np;
1491d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1492e81b3295SNathan Fontenot 
1493e81b3295SNathan Fontenot 	of_add_proc_dt_entry(np);
14941cf3d8b3SNathan Fontenot 	return 0;
1495fcdeb7feSGrant Likely }
1496fcdeb7feSGrant Likely 
1497e81b3295SNathan Fontenot #ifdef CONFIG_PROC_DEVICETREE
1498e81b3295SNathan Fontenot static void of_remove_proc_dt_entry(struct device_node *dn)
1499e81b3295SNathan Fontenot {
1500a8ca16eaSDavid Howells 	proc_remove(dn->pde);
1501e81b3295SNathan Fontenot }
1502e81b3295SNathan Fontenot #else
1503e81b3295SNathan Fontenot static void of_remove_proc_dt_entry(struct device_node *dn)
1504e81b3295SNathan Fontenot {
1505e81b3295SNathan Fontenot 	return;
1506e81b3295SNathan Fontenot }
1507e81b3295SNathan Fontenot #endif
1508e81b3295SNathan Fontenot 
1509fcdeb7feSGrant Likely /**
1510fcdeb7feSGrant Likely  * of_detach_node - "Unplug" a node from the device tree.
1511fcdeb7feSGrant Likely  *
1512fcdeb7feSGrant Likely  * The caller must hold a reference to the node.  The memory associated with
1513fcdeb7feSGrant Likely  * the node is not freed until its refcount goes to zero.
1514fcdeb7feSGrant Likely  */
15151cf3d8b3SNathan Fontenot int of_detach_node(struct device_node *np)
1516fcdeb7feSGrant Likely {
1517fcdeb7feSGrant Likely 	struct device_node *parent;
1518fcdeb7feSGrant Likely 	unsigned long flags;
15191cf3d8b3SNathan Fontenot 	int rc = 0;
15201cf3d8b3SNathan Fontenot 
15211cf3d8b3SNathan Fontenot 	rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
15221cf3d8b3SNathan Fontenot 	if (rc)
15231cf3d8b3SNathan Fontenot 		return rc;
1524fcdeb7feSGrant Likely 
1525d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
1526fcdeb7feSGrant Likely 
1527e81b3295SNathan Fontenot 	if (of_node_check_flag(np, OF_DETACHED)) {
1528e81b3295SNathan Fontenot 		/* someone already detached it */
1529d6d3c4e6SThomas Gleixner 		raw_spin_unlock_irqrestore(&devtree_lock, flags);
15301cf3d8b3SNathan Fontenot 		return rc;
1531e81b3295SNathan Fontenot 	}
1532e81b3295SNathan Fontenot 
1533fcdeb7feSGrant Likely 	parent = np->parent;
1534e81b3295SNathan Fontenot 	if (!parent) {
1535d6d3c4e6SThomas Gleixner 		raw_spin_unlock_irqrestore(&devtree_lock, flags);
15361cf3d8b3SNathan Fontenot 		return rc;
1537e81b3295SNathan Fontenot 	}
1538fcdeb7feSGrant Likely 
1539465aac6dSRandy Dunlap 	if (of_allnodes == np)
1540465aac6dSRandy Dunlap 		of_allnodes = np->allnext;
1541fcdeb7feSGrant Likely 	else {
1542fcdeb7feSGrant Likely 		struct device_node *prev;
1543465aac6dSRandy Dunlap 		for (prev = of_allnodes;
1544fcdeb7feSGrant Likely 		     prev->allnext != np;
1545fcdeb7feSGrant Likely 		     prev = prev->allnext)
1546fcdeb7feSGrant Likely 			;
1547fcdeb7feSGrant Likely 		prev->allnext = np->allnext;
1548fcdeb7feSGrant Likely 	}
1549fcdeb7feSGrant Likely 
1550fcdeb7feSGrant Likely 	if (parent->child == np)
1551fcdeb7feSGrant Likely 		parent->child = np->sibling;
1552fcdeb7feSGrant Likely 	else {
1553fcdeb7feSGrant Likely 		struct device_node *prevsib;
1554fcdeb7feSGrant Likely 		for (prevsib = np->parent->child;
1555fcdeb7feSGrant Likely 		     prevsib->sibling != np;
1556fcdeb7feSGrant Likely 		     prevsib = prevsib->sibling)
1557fcdeb7feSGrant Likely 			;
1558fcdeb7feSGrant Likely 		prevsib->sibling = np->sibling;
1559fcdeb7feSGrant Likely 	}
1560fcdeb7feSGrant Likely 
1561fcdeb7feSGrant Likely 	of_node_set_flag(np, OF_DETACHED);
1562d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1563e81b3295SNathan Fontenot 
1564e81b3295SNathan Fontenot 	of_remove_proc_dt_entry(np);
15651cf3d8b3SNathan Fontenot 	return rc;
1566fcdeb7feSGrant Likely }
1567fcdeb7feSGrant Likely #endif /* defined(CONFIG_OF_DYNAMIC) */
1568fcdeb7feSGrant Likely 
1569611cad72SShawn Guo static void of_alias_add(struct alias_prop *ap, struct device_node *np,
1570611cad72SShawn Guo 			 int id, const char *stem, int stem_len)
1571611cad72SShawn Guo {
1572611cad72SShawn Guo 	ap->np = np;
1573611cad72SShawn Guo 	ap->id = id;
1574611cad72SShawn Guo 	strncpy(ap->stem, stem, stem_len);
1575611cad72SShawn Guo 	ap->stem[stem_len] = 0;
1576611cad72SShawn Guo 	list_add_tail(&ap->link, &aliases_lookup);
1577611cad72SShawn Guo 	pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
157874a7f084SGrant Likely 		 ap->alias, ap->stem, ap->id, of_node_full_name(np));
1579611cad72SShawn Guo }
1580611cad72SShawn Guo 
1581611cad72SShawn Guo /**
1582611cad72SShawn Guo  * of_alias_scan - Scan all properties of 'aliases' node
1583611cad72SShawn Guo  *
1584611cad72SShawn Guo  * The function scans all the properties of 'aliases' node and populate
1585611cad72SShawn Guo  * the the global lookup table with the properties.  It returns the
1586611cad72SShawn Guo  * number of alias_prop found, or error code in error case.
1587611cad72SShawn Guo  *
1588611cad72SShawn Guo  * @dt_alloc:	An allocator that provides a virtual address to memory
1589611cad72SShawn Guo  *		for the resulting tree
1590611cad72SShawn Guo  */
1591611cad72SShawn Guo void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
1592611cad72SShawn Guo {
1593611cad72SShawn Guo 	struct property *pp;
1594611cad72SShawn Guo 
1595611cad72SShawn Guo 	of_chosen = of_find_node_by_path("/chosen");
1596611cad72SShawn Guo 	if (of_chosen == NULL)
1597611cad72SShawn Guo 		of_chosen = of_find_node_by_path("/chosen@0");
1598611cad72SShawn Guo 	of_aliases = of_find_node_by_path("/aliases");
1599611cad72SShawn Guo 	if (!of_aliases)
1600611cad72SShawn Guo 		return;
1601611cad72SShawn Guo 
16028af0da93SDong Aisheng 	for_each_property_of_node(of_aliases, pp) {
1603611cad72SShawn Guo 		const char *start = pp->name;
1604611cad72SShawn Guo 		const char *end = start + strlen(start);
1605611cad72SShawn Guo 		struct device_node *np;
1606611cad72SShawn Guo 		struct alias_prop *ap;
1607611cad72SShawn Guo 		int id, len;
1608611cad72SShawn Guo 
1609611cad72SShawn Guo 		/* Skip those we do not want to proceed */
1610611cad72SShawn Guo 		if (!strcmp(pp->name, "name") ||
1611611cad72SShawn Guo 		    !strcmp(pp->name, "phandle") ||
1612611cad72SShawn Guo 		    !strcmp(pp->name, "linux,phandle"))
1613611cad72SShawn Guo 			continue;
1614611cad72SShawn Guo 
1615611cad72SShawn Guo 		np = of_find_node_by_path(pp->value);
1616611cad72SShawn Guo 		if (!np)
1617611cad72SShawn Guo 			continue;
1618611cad72SShawn Guo 
1619611cad72SShawn Guo 		/* walk the alias backwards to extract the id and work out
1620611cad72SShawn Guo 		 * the 'stem' string */
1621611cad72SShawn Guo 		while (isdigit(*(end-1)) && end > start)
1622611cad72SShawn Guo 			end--;
1623611cad72SShawn Guo 		len = end - start;
1624611cad72SShawn Guo 
1625611cad72SShawn Guo 		if (kstrtoint(end, 10, &id) < 0)
1626611cad72SShawn Guo 			continue;
1627611cad72SShawn Guo 
1628611cad72SShawn Guo 		/* Allocate an alias_prop with enough space for the stem */
1629611cad72SShawn Guo 		ap = dt_alloc(sizeof(*ap) + len + 1, 4);
1630611cad72SShawn Guo 		if (!ap)
1631611cad72SShawn Guo 			continue;
16320640332eSGrant Likely 		memset(ap, 0, sizeof(*ap) + len + 1);
1633611cad72SShawn Guo 		ap->alias = start;
1634611cad72SShawn Guo 		of_alias_add(ap, np, id, start, len);
1635611cad72SShawn Guo 	}
1636611cad72SShawn Guo }
1637611cad72SShawn Guo 
1638611cad72SShawn Guo /**
1639611cad72SShawn Guo  * of_alias_get_id - Get alias id for the given device_node
1640611cad72SShawn Guo  * @np:		Pointer to the given device_node
1641611cad72SShawn Guo  * @stem:	Alias stem of the given device_node
1642611cad72SShawn Guo  *
1643611cad72SShawn Guo  * The function travels the lookup table to get alias id for the given
1644611cad72SShawn Guo  * device_node and alias stem.  It returns the alias id if find it.
1645611cad72SShawn Guo  */
1646611cad72SShawn Guo int of_alias_get_id(struct device_node *np, const char *stem)
1647611cad72SShawn Guo {
1648611cad72SShawn Guo 	struct alias_prop *app;
1649611cad72SShawn Guo 	int id = -ENODEV;
1650611cad72SShawn Guo 
1651611cad72SShawn Guo 	mutex_lock(&of_aliases_mutex);
1652611cad72SShawn Guo 	list_for_each_entry(app, &aliases_lookup, link) {
1653611cad72SShawn Guo 		if (strcmp(app->stem, stem) != 0)
1654611cad72SShawn Guo 			continue;
1655611cad72SShawn Guo 
1656611cad72SShawn Guo 		if (np == app->np) {
1657611cad72SShawn Guo 			id = app->id;
1658611cad72SShawn Guo 			break;
1659611cad72SShawn Guo 		}
1660611cad72SShawn Guo 	}
1661611cad72SShawn Guo 	mutex_unlock(&of_aliases_mutex);
1662611cad72SShawn Guo 
1663611cad72SShawn Guo 	return id;
1664611cad72SShawn Guo }
1665611cad72SShawn Guo EXPORT_SYMBOL_GPL(of_alias_get_id);
1666c541adc6SStephen Warren 
1667c541adc6SStephen Warren const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
1668c541adc6SStephen Warren 			       u32 *pu)
1669c541adc6SStephen Warren {
1670c541adc6SStephen Warren 	const void *curv = cur;
1671c541adc6SStephen Warren 
1672c541adc6SStephen Warren 	if (!prop)
1673c541adc6SStephen Warren 		return NULL;
1674c541adc6SStephen Warren 
1675c541adc6SStephen Warren 	if (!cur) {
1676c541adc6SStephen Warren 		curv = prop->value;
1677c541adc6SStephen Warren 		goto out_val;
1678c541adc6SStephen Warren 	}
1679c541adc6SStephen Warren 
1680c541adc6SStephen Warren 	curv += sizeof(*cur);
1681c541adc6SStephen Warren 	if (curv >= prop->value + prop->length)
1682c541adc6SStephen Warren 		return NULL;
1683c541adc6SStephen Warren 
1684c541adc6SStephen Warren out_val:
1685c541adc6SStephen Warren 	*pu = be32_to_cpup(curv);
1686c541adc6SStephen Warren 	return curv;
1687c541adc6SStephen Warren }
1688c541adc6SStephen Warren EXPORT_SYMBOL_GPL(of_prop_next_u32);
1689c541adc6SStephen Warren 
1690c541adc6SStephen Warren const char *of_prop_next_string(struct property *prop, const char *cur)
1691c541adc6SStephen Warren {
1692c541adc6SStephen Warren 	const void *curv = cur;
1693c541adc6SStephen Warren 
1694c541adc6SStephen Warren 	if (!prop)
1695c541adc6SStephen Warren 		return NULL;
1696c541adc6SStephen Warren 
1697c541adc6SStephen Warren 	if (!cur)
1698c541adc6SStephen Warren 		return prop->value;
1699c541adc6SStephen Warren 
1700c541adc6SStephen Warren 	curv += strlen(cur) + 1;
1701c541adc6SStephen Warren 	if (curv >= prop->value + prop->length)
1702c541adc6SStephen Warren 		return NULL;
1703c541adc6SStephen Warren 
1704c541adc6SStephen Warren 	return curv;
1705c541adc6SStephen Warren }
1706c541adc6SStephen Warren EXPORT_SYMBOL_GPL(of_prop_next_string);
1707