xref: /openbmc/linux/drivers/of/base.c (revision b64d09a4)
1af6074fcSRob Herring // SPDX-License-Identifier: GPL-2.0+
297e873e5SStephen Rothwell /*
397e873e5SStephen Rothwell  * Procedures for creating, accessing and interpreting the device tree.
497e873e5SStephen Rothwell  *
597e873e5SStephen Rothwell  * Paul Mackerras	August 1996.
697e873e5SStephen Rothwell  * Copyright (C) 1996-2005 Paul Mackerras.
797e873e5SStephen Rothwell  *
897e873e5SStephen Rothwell  *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
997e873e5SStephen Rothwell  *    {engebret|bergner}@us.ibm.com
1097e873e5SStephen Rothwell  *
1197e873e5SStephen Rothwell  *  Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net
1297e873e5SStephen Rothwell  *
13e91edcf5SGrant Likely  *  Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and
14e91edcf5SGrant Likely  *  Grant Likely.
1597e873e5SStephen Rothwell  */
16606ad42aSRob Herring 
17606ad42aSRob Herring #define pr_fmt(fmt)	"OF: " fmt
18606ad42aSRob Herring 
193482f2c5SGrant Likely #include <linux/console.h>
20611cad72SShawn Guo #include <linux/ctype.h>
21183912d3SSudeep KarkadaNagesha #include <linux/cpu.h>
2297e873e5SStephen Rothwell #include <linux/module.h>
2397e873e5SStephen Rothwell #include <linux/of.h>
245fa23530SSudeep Holla #include <linux/of_device.h>
25fd9fdb78SPhilipp Zabel #include <linux/of_graph.h>
26581b605aSStephen Rothwell #include <linux/spinlock.h>
275a0e3ad6STejun Heo #include <linux/slab.h>
2875b57ecfSGrant Likely #include <linux/string.h>
29a9f2f63aSJeremy Kerr #include <linux/proc_fs.h>
30581b605aSStephen Rothwell 
31ced4eec9SStepan Moskovchenko #include "of_private.h"
32611cad72SShawn Guo 
33ced4eec9SStepan Moskovchenko LIST_HEAD(aliases_lookup);
34611cad72SShawn Guo 
355063e25aSGrant Likely struct device_node *of_root;
365063e25aSGrant Likely EXPORT_SYMBOL(of_root);
37fc0bdae4SGrant Likely struct device_node *of_chosen;
38ec7cc3f7SArnd Bergmann EXPORT_SYMBOL(of_chosen);
39611cad72SShawn Guo struct device_node *of_aliases;
40a752ee56SGrant Likely struct device_node *of_stdout;
417914a7c5SLeif Lindholm static const char *of_stdout_options;
42611cad72SShawn Guo 
438a2b22a2SGrant Likely struct kset *of_kset;
4475b57ecfSGrant Likely 
4575b57ecfSGrant Likely /*
468a2b22a2SGrant Likely  * Used to protect the of_aliases, to hold off addition of nodes to sysfs.
478a2b22a2SGrant Likely  * This mutex must be held whenever modifications are being made to the
488a2b22a2SGrant Likely  * device tree. The of_{attach,detach}_node() and
498a2b22a2SGrant Likely  * of_{add,remove,update}_property() helpers make sure this happens.
5075b57ecfSGrant Likely  */
51c05aba2bSPantelis Antoniou DEFINE_MUTEX(of_mutex);
521ef4d424SStephen Rothwell 
535063e25aSGrant Likely /* use when traversing tree through the child, sibling,
54581b605aSStephen Rothwell  * or parent members of struct device_node.
55581b605aSStephen Rothwell  */
56d6d3c4e6SThomas Gleixner DEFINE_RAW_SPINLOCK(devtree_lock);
5797e873e5SStephen Rothwell 
of_node_name_eq(const struct device_node * np,const char * name)58f42b0e18SRob Herring bool of_node_name_eq(const struct device_node *np, const char *name)
59f42b0e18SRob Herring {
60f42b0e18SRob Herring 	const char *node_name;
61f42b0e18SRob Herring 	size_t len;
62f42b0e18SRob Herring 
63f42b0e18SRob Herring 	if (!np)
64f42b0e18SRob Herring 		return false;
65f42b0e18SRob Herring 
66f42b0e18SRob Herring 	node_name = kbasename(np->full_name);
67f42b0e18SRob Herring 	len = strchrnul(node_name, '@') - node_name;
68f42b0e18SRob Herring 
69f42b0e18SRob Herring 	return (strlen(name) == len) && (strncmp(node_name, name, len) == 0);
70f42b0e18SRob Herring }
71173ee396SRob Herring EXPORT_SYMBOL(of_node_name_eq);
72f42b0e18SRob Herring 
of_node_name_prefix(const struct device_node * np,const char * prefix)73f42b0e18SRob Herring bool of_node_name_prefix(const struct device_node *np, const char *prefix)
74f42b0e18SRob Herring {
75f42b0e18SRob Herring 	if (!np)
76f42b0e18SRob Herring 		return false;
77f42b0e18SRob Herring 
78f42b0e18SRob Herring 	return strncmp(kbasename(np->full_name), prefix, strlen(prefix)) == 0;
79f42b0e18SRob Herring }
80173ee396SRob Herring EXPORT_SYMBOL(of_node_name_prefix);
81f42b0e18SRob Herring 
__of_node_is_type(const struct device_node * np,const char * type)82e8b1dee2SRob Herring static bool __of_node_is_type(const struct device_node *np, const char *type)
83e8b1dee2SRob Herring {
84e8b1dee2SRob Herring 	const char *match = __of_get_property(np, "device_type", NULL);
85e8b1dee2SRob Herring 
86e8b1dee2SRob Herring 	return np && match && type && !strcmp(match, type);
87e8b1dee2SRob Herring }
88e8b1dee2SRob Herring 
of_bus_n_addr_cells(struct device_node * np)89b68ac8dcSRobin Murphy int of_bus_n_addr_cells(struct device_node *np)
9097e873e5SStephen Rothwell {
918832963dSSergei Shtylyov 	u32 cells;
9297e873e5SStephen Rothwell 
93b68ac8dcSRobin Murphy 	for (; np; np = np->parent)
948832963dSSergei Shtylyov 		if (!of_property_read_u32(np, "#address-cells", &cells))
958832963dSSergei Shtylyov 			return cells;
96b68ac8dcSRobin Murphy 
9797e873e5SStephen Rothwell 	/* No #address-cells property for the root node */
9897e873e5SStephen Rothwell 	return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
9997e873e5SStephen Rothwell }
100b68ac8dcSRobin Murphy 
of_n_addr_cells(struct device_node * np)101b68ac8dcSRobin Murphy int of_n_addr_cells(struct device_node *np)
102b68ac8dcSRobin Murphy {
103b68ac8dcSRobin Murphy 	if (np->parent)
104b68ac8dcSRobin Murphy 		np = np->parent;
105b68ac8dcSRobin Murphy 
106b68ac8dcSRobin Murphy 	return of_bus_n_addr_cells(np);
107b68ac8dcSRobin Murphy }
10897e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_addr_cells);
10997e873e5SStephen Rothwell 
of_bus_n_size_cells(struct device_node * np)110b68ac8dcSRobin Murphy int of_bus_n_size_cells(struct device_node *np)
11197e873e5SStephen Rothwell {
1128832963dSSergei Shtylyov 	u32 cells;
11397e873e5SStephen Rothwell 
114b68ac8dcSRobin Murphy 	for (; np; np = np->parent)
1158832963dSSergei Shtylyov 		if (!of_property_read_u32(np, "#size-cells", &cells))
1168832963dSSergei Shtylyov 			return cells;
117b68ac8dcSRobin Murphy 
11897e873e5SStephen Rothwell 	/* No #size-cells property for the root node */
11997e873e5SStephen Rothwell 	return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
12097e873e5SStephen Rothwell }
121b68ac8dcSRobin Murphy 
of_n_size_cells(struct device_node * np)122b68ac8dcSRobin Murphy int of_n_size_cells(struct device_node *np)
123b68ac8dcSRobin Murphy {
124b68ac8dcSRobin Murphy 	if (np->parent)
125b68ac8dcSRobin Murphy 		np = np->parent;
126b68ac8dcSRobin Murphy 
127b68ac8dcSRobin Murphy 	return of_bus_n_size_cells(np);
128b68ac8dcSRobin Murphy }
12997e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_size_cells);
13097e873e5SStephen Rothwell 
1310c3f061cSRob Herring #ifdef CONFIG_NUMA
of_node_to_nid(struct device_node * np)1320c3f061cSRob Herring int __weak of_node_to_nid(struct device_node *np)
1330c3f061cSRob Herring {
134c8fff7bcSKonstantin Khlebnikov 	return NUMA_NO_NODE;
1350c3f061cSRob Herring }
1360c3f061cSRob Herring #endif
1370c3f061cSRob Herring 
13890dc0d1cSRob Herring #define OF_PHANDLE_CACHE_BITS	7
13990dc0d1cSRob Herring #define OF_PHANDLE_CACHE_SZ	BIT(OF_PHANDLE_CACHE_BITS)
140b8a9ac1aSFrank Rowand 
14190dc0d1cSRob Herring static struct device_node *phandle_cache[OF_PHANDLE_CACHE_SZ];
14290dc0d1cSRob Herring 
of_phandle_cache_hash(phandle handle)14390dc0d1cSRob Herring static u32 of_phandle_cache_hash(phandle handle)
14490dc0d1cSRob Herring {
14590dc0d1cSRob Herring 	return hash_32(handle, OF_PHANDLE_CACHE_BITS);
14690dc0d1cSRob Herring }
147b8a9ac1aSFrank Rowand 
148b8a9ac1aSFrank Rowand /*
149b8a9ac1aSFrank Rowand  * Caller must hold devtree_lock.
150b8a9ac1aSFrank Rowand  */
__of_phandle_cache_inv_entry(phandle handle)15190dc0d1cSRob Herring void __of_phandle_cache_inv_entry(phandle handle)
152b8a9ac1aSFrank Rowand {
15390dc0d1cSRob Herring 	u32 handle_hash;
1545801169aSFrank Rowand 	struct device_node *np;
1555801169aSFrank Rowand 
1565801169aSFrank Rowand 	if (!handle)
1575801169aSFrank Rowand 		return;
1585801169aSFrank Rowand 
15990dc0d1cSRob Herring 	handle_hash = of_phandle_cache_hash(handle);
1605801169aSFrank Rowand 
16190dc0d1cSRob Herring 	np = phandle_cache[handle_hash];
16290dc0d1cSRob Herring 	if (np && handle == np->phandle)
16390dc0d1cSRob Herring 		phandle_cache[handle_hash] = NULL;
1640b3ce78eSFrank Rowand }
1650b3ce78eSFrank Rowand 
of_core_init(void)166194ec936SSudeep Holla void __init of_core_init(void)
16775b57ecfSGrant Likely {
16875b57ecfSGrant Likely 	struct device_node *np;
16975b57ecfSGrant Likely 
17073aca58bSRob Herring 	of_platform_register_reconfig_notifier();
1710b3ce78eSFrank Rowand 
17275b57ecfSGrant Likely 	/* Create the kset, and register existing nodes */
173c05aba2bSPantelis Antoniou 	mutex_lock(&of_mutex);
17475b57ecfSGrant Likely 	of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);
17575b57ecfSGrant Likely 	if (!of_kset) {
176c05aba2bSPantelis Antoniou 		mutex_unlock(&of_mutex);
177606ad42aSRob Herring 		pr_err("failed to register existing nodes\n");
178194ec936SSudeep Holla 		return;
17975b57ecfSGrant Likely 	}
18090dc0d1cSRob Herring 	for_each_of_allnodes(np) {
1818a2b22a2SGrant Likely 		__of_attach_node_sysfs(np);
18290dc0d1cSRob Herring 		if (np->phandle && !phandle_cache[of_phandle_cache_hash(np->phandle)])
18390dc0d1cSRob Herring 			phandle_cache[of_phandle_cache_hash(np->phandle)] = np;
18490dc0d1cSRob Herring 	}
185c05aba2bSPantelis Antoniou 	mutex_unlock(&of_mutex);
18675b57ecfSGrant Likely 
1878357041aSGrant Likely 	/* Symlink in /proc as required by userspace ABI */
1885063e25aSGrant Likely 	if (of_root)
18975b57ecfSGrant Likely 		proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");
19075b57ecfSGrant Likely }
19175b57ecfSGrant Likely 
__of_find_property(const struct device_node * np,const char * name,int * lenp)19228d0e36bSThomas Gleixner static struct property *__of_find_property(const struct device_node *np,
19328d0e36bSThomas Gleixner 					   const char *name, int *lenp)
194581b605aSStephen Rothwell {
195581b605aSStephen Rothwell 	struct property *pp;
196581b605aSStephen Rothwell 
19764e4566fSTimur Tabi 	if (!np)
19864e4566fSTimur Tabi 		return NULL;
19964e4566fSTimur Tabi 
200a3a7cab1SSachin Kamat 	for (pp = np->properties; pp; pp = pp->next) {
201581b605aSStephen Rothwell 		if (of_prop_cmp(pp->name, name) == 0) {
202a3a7cab1SSachin Kamat 			if (lenp)
203581b605aSStephen Rothwell 				*lenp = pp->length;
204581b605aSStephen Rothwell 			break;
205581b605aSStephen Rothwell 		}
206581b605aSStephen Rothwell 	}
20728d0e36bSThomas Gleixner 
20828d0e36bSThomas Gleixner 	return pp;
20928d0e36bSThomas Gleixner }
21028d0e36bSThomas Gleixner 
of_find_property(const struct device_node * np,const char * name,int * lenp)21128d0e36bSThomas Gleixner struct property *of_find_property(const struct device_node *np,
21228d0e36bSThomas Gleixner 				  const char *name,
21328d0e36bSThomas Gleixner 				  int *lenp)
21428d0e36bSThomas Gleixner {
21528d0e36bSThomas Gleixner 	struct property *pp;
216d6d3c4e6SThomas Gleixner 	unsigned long flags;
21728d0e36bSThomas Gleixner 
218d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
21928d0e36bSThomas Gleixner 	pp = __of_find_property(np, name, lenp);
220d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
221581b605aSStephen Rothwell 
222581b605aSStephen Rothwell 	return pp;
223581b605aSStephen Rothwell }
224581b605aSStephen Rothwell EXPORT_SYMBOL(of_find_property);
225581b605aSStephen Rothwell 
__of_find_all_nodes(struct device_node * prev)2265063e25aSGrant Likely struct device_node *__of_find_all_nodes(struct device_node *prev)
2275063e25aSGrant Likely {
2285063e25aSGrant Likely 	struct device_node *np;
2295063e25aSGrant Likely 	if (!prev) {
2305063e25aSGrant Likely 		np = of_root;
2315063e25aSGrant Likely 	} else if (prev->child) {
2325063e25aSGrant Likely 		np = prev->child;
2335063e25aSGrant Likely 	} else {
2345063e25aSGrant Likely 		/* Walk back up looking for a sibling, or the end of the structure */
2355063e25aSGrant Likely 		np = prev;
2365063e25aSGrant Likely 		while (np->parent && !np->sibling)
2375063e25aSGrant Likely 			np = np->parent;
2385063e25aSGrant Likely 		np = np->sibling; /* Might be null at the end of the tree */
2395063e25aSGrant Likely 	}
2405063e25aSGrant Likely 	return np;
2415063e25aSGrant Likely }
2425063e25aSGrant Likely 
243e91edcf5SGrant Likely /**
244e91edcf5SGrant Likely  * of_find_all_nodes - Get next node in global list
245e91edcf5SGrant Likely  * @prev:	Previous node or NULL to start iteration
246e91edcf5SGrant Likely  *		of_node_put() will be called on it
247e91edcf5SGrant Likely  *
2488c8239c2SRob Herring  * Return: A node pointer with refcount incremented, use
249e91edcf5SGrant Likely  * of_node_put() on it when done.
250e91edcf5SGrant Likely  */
of_find_all_nodes(struct device_node * prev)251e91edcf5SGrant Likely struct device_node *of_find_all_nodes(struct device_node *prev)
252e91edcf5SGrant Likely {
253e91edcf5SGrant Likely 	struct device_node *np;
254d25d8694SBenjamin Herrenschmidt 	unsigned long flags;
255e91edcf5SGrant Likely 
256d25d8694SBenjamin Herrenschmidt 	raw_spin_lock_irqsave(&devtree_lock, flags);
2575063e25aSGrant Likely 	np = __of_find_all_nodes(prev);
2585063e25aSGrant Likely 	of_node_get(np);
259e91edcf5SGrant Likely 	of_node_put(prev);
260d25d8694SBenjamin Herrenschmidt 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
261e91edcf5SGrant Likely 	return np;
262e91edcf5SGrant Likely }
263e91edcf5SGrant Likely EXPORT_SYMBOL(of_find_all_nodes);
264e91edcf5SGrant Likely 
26597e873e5SStephen Rothwell /*
26697e873e5SStephen Rothwell  * Find a property with a given name for a given node
26797e873e5SStephen Rothwell  * and return the value.
26897e873e5SStephen Rothwell  */
__of_get_property(const struct device_node * np,const char * name,int * lenp)269a25095d4SGrant Likely const void *__of_get_property(const struct device_node *np,
27028d0e36bSThomas Gleixner 			      const char *name, int *lenp)
27128d0e36bSThomas Gleixner {
27228d0e36bSThomas Gleixner 	struct property *pp = __of_find_property(np, name, lenp);
27328d0e36bSThomas Gleixner 
27428d0e36bSThomas Gleixner 	return pp ? pp->value : NULL;
27528d0e36bSThomas Gleixner }
27628d0e36bSThomas Gleixner 
27728d0e36bSThomas Gleixner /*
27828d0e36bSThomas Gleixner  * Find a property with a given name for a given node
27928d0e36bSThomas Gleixner  * and return the value.
28028d0e36bSThomas Gleixner  */
of_get_property(const struct device_node * np,const char * name,int * lenp)28197e873e5SStephen Rothwell const void *of_get_property(const struct device_node *np, const char *name,
28297e873e5SStephen Rothwell 			    int *lenp)
28397e873e5SStephen Rothwell {
28497e873e5SStephen Rothwell 	struct property *pp = of_find_property(np, name, lenp);
28597e873e5SStephen Rothwell 
28697e873e5SStephen Rothwell 	return pp ? pp->value : NULL;
28797e873e5SStephen Rothwell }
28897e873e5SStephen Rothwell EXPORT_SYMBOL(of_get_property);
2890081cbc3SStephen Rothwell 
290795e92ecSRob Herring /**
291215a14cfSKevin Hao  * __of_device_is_compatible() - Check if the node matches given constraints
292215a14cfSKevin Hao  * @device: pointer to node
293215a14cfSKevin Hao  * @compat: required compatible string, NULL or "" for any match
294215a14cfSKevin Hao  * @type: required device_type value, NULL or "" for any match
295215a14cfSKevin Hao  * @name: required node name, NULL or "" for any match
296215a14cfSKevin Hao  *
297215a14cfSKevin Hao  * Checks if the given @compat, @type and @name strings match the
298215a14cfSKevin Hao  * properties of the given @device. A constraints can be skipped by
299215a14cfSKevin Hao  * passing NULL or an empty string as the constraint.
300215a14cfSKevin Hao  *
301215a14cfSKevin Hao  * Returns 0 for no match, and a positive integer on match. The return
302215a14cfSKevin Hao  * value is a relative score with larger values indicating better
303215a14cfSKevin Hao  * matches. The score is weighted for the most specific compatible value
304215a14cfSKevin Hao  * to get the highest score. Matching type is next, followed by matching
305215a14cfSKevin Hao  * name. Practically speaking, this results in the following priority
306215a14cfSKevin Hao  * order for matches:
307215a14cfSKevin Hao  *
308215a14cfSKevin Hao  * 1. specific compatible && type && name
309215a14cfSKevin Hao  * 2. specific compatible && type
310215a14cfSKevin Hao  * 3. specific compatible && name
311215a14cfSKevin Hao  * 4. specific compatible
312215a14cfSKevin Hao  * 5. general compatible && type && name
313215a14cfSKevin Hao  * 6. general compatible && type
314215a14cfSKevin Hao  * 7. general compatible && name
315215a14cfSKevin Hao  * 8. general compatible
316215a14cfSKevin Hao  * 9. type && name
317215a14cfSKevin Hao  * 10. type
318215a14cfSKevin Hao  * 11. name
3190081cbc3SStephen Rothwell  */
__of_device_is_compatible(const struct device_node * device,const char * compat,const char * type,const char * name)32028d0e36bSThomas Gleixner static int __of_device_is_compatible(const struct device_node *device,
321215a14cfSKevin Hao 				     const char *compat, const char *type, const char *name)
3220081cbc3SStephen Rothwell {
323215a14cfSKevin Hao 	struct property *prop;
3240081cbc3SStephen Rothwell 	const char *cp;
325215a14cfSKevin Hao 	int index = 0, score = 0;
3260081cbc3SStephen Rothwell 
327215a14cfSKevin Hao 	/* Compatible match has highest priority */
328215a14cfSKevin Hao 	if (compat && compat[0]) {
329215a14cfSKevin Hao 		prop = __of_find_property(device, "compatible", NULL);
330215a14cfSKevin Hao 		for (cp = of_prop_next_string(prop, NULL); cp;
331215a14cfSKevin Hao 		     cp = of_prop_next_string(prop, cp), index++) {
332215a14cfSKevin Hao 			if (of_compat_cmp(cp, compat, strlen(compat)) == 0) {
333215a14cfSKevin Hao 				score = INT_MAX/2 - (index << 2);
334215a14cfSKevin Hao 				break;
335215a14cfSKevin Hao 			}
336215a14cfSKevin Hao 		}
337215a14cfSKevin Hao 		if (!score)
3380081cbc3SStephen Rothwell 			return 0;
3390081cbc3SStephen Rothwell 	}
3400081cbc3SStephen Rothwell 
341215a14cfSKevin Hao 	/* Matching type is better than matching name */
342215a14cfSKevin Hao 	if (type && type[0]) {
343e8b1dee2SRob Herring 		if (!__of_node_is_type(device, type))
3440081cbc3SStephen Rothwell 			return 0;
345215a14cfSKevin Hao 		score += 2;
346215a14cfSKevin Hao 	}
347215a14cfSKevin Hao 
348215a14cfSKevin Hao 	/* Matching name is a bit better than not */
349215a14cfSKevin Hao 	if (name && name[0]) {
350b3e46d1aSRob Herring 		if (!of_node_name_eq(device, name))
351215a14cfSKevin Hao 			return 0;
352215a14cfSKevin Hao 		score++;
353215a14cfSKevin Hao 	}
354215a14cfSKevin Hao 
355215a14cfSKevin Hao 	return score;
3560081cbc3SStephen Rothwell }
35728d0e36bSThomas Gleixner 
35828d0e36bSThomas Gleixner /** Checks if the given "compat" string matches one of the strings in
35928d0e36bSThomas Gleixner  * the device's "compatible" property
36028d0e36bSThomas Gleixner  */
of_device_is_compatible(const struct device_node * device,const char * compat)36128d0e36bSThomas Gleixner int of_device_is_compatible(const struct device_node *device,
36228d0e36bSThomas Gleixner 		const char *compat)
36328d0e36bSThomas Gleixner {
364d6d3c4e6SThomas Gleixner 	unsigned long flags;
36528d0e36bSThomas Gleixner 	int res;
36628d0e36bSThomas Gleixner 
367d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
368215a14cfSKevin Hao 	res = __of_device_is_compatible(device, compat, NULL, NULL);
369d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
37028d0e36bSThomas Gleixner 	return res;
37128d0e36bSThomas Gleixner }
3720081cbc3SStephen Rothwell EXPORT_SYMBOL(of_device_is_compatible);
373e679c5f4SStephen Rothwell 
374b9c13fe3SBenjamin Herrenschmidt /** Checks if the device is compatible with any of the entries in
375b9c13fe3SBenjamin Herrenschmidt  *  a NULL terminated array of strings. Returns the best match
376b9c13fe3SBenjamin Herrenschmidt  *  score or 0.
377b9c13fe3SBenjamin Herrenschmidt  */
of_device_compatible_match(const struct device_node * device,const char * const * compat)37888269151SDmitry Torokhov int of_device_compatible_match(const struct device_node *device,
379b9c13fe3SBenjamin Herrenschmidt 			       const char *const *compat)
380b9c13fe3SBenjamin Herrenschmidt {
381b9c13fe3SBenjamin Herrenschmidt 	unsigned int tmp, score = 0;
382b9c13fe3SBenjamin Herrenschmidt 
383b9c13fe3SBenjamin Herrenschmidt 	if (!compat)
384b9c13fe3SBenjamin Herrenschmidt 		return 0;
385b9c13fe3SBenjamin Herrenschmidt 
386b9c13fe3SBenjamin Herrenschmidt 	while (*compat) {
387b9c13fe3SBenjamin Herrenschmidt 		tmp = of_device_is_compatible(device, *compat);
388b9c13fe3SBenjamin Herrenschmidt 		if (tmp > score)
389b9c13fe3SBenjamin Herrenschmidt 			score = tmp;
390b9c13fe3SBenjamin Herrenschmidt 		compat++;
391b9c13fe3SBenjamin Herrenschmidt 	}
392b9c13fe3SBenjamin Herrenschmidt 
393b9c13fe3SBenjamin Herrenschmidt 	return score;
394b9c13fe3SBenjamin Herrenschmidt }
395df55e317SVladimir Oltean EXPORT_SYMBOL_GPL(of_device_compatible_match);
396b9c13fe3SBenjamin Herrenschmidt 
397e679c5f4SStephen Rothwell /**
39871a157e8SGrant Likely  * of_machine_is_compatible - Test root of device tree for a given compatible value
3991f43cfb9SGrant Likely  * @compat: compatible string to look for in root node's compatible property.
4001f43cfb9SGrant Likely  *
4018c8239c2SRob Herring  * Return: A positive integer if the root node has the given value in its
4021f43cfb9SGrant Likely  * compatible property.
4031f43cfb9SGrant Likely  */
of_machine_is_compatible(const char * compat)40471a157e8SGrant Likely int of_machine_is_compatible(const char *compat)
4051f43cfb9SGrant Likely {
4061f43cfb9SGrant Likely 	struct device_node *root;
4071f43cfb9SGrant Likely 	int rc = 0;
4081f43cfb9SGrant Likely 
4091f43cfb9SGrant Likely 	root = of_find_node_by_path("/");
4101f43cfb9SGrant Likely 	if (root) {
4111f43cfb9SGrant Likely 		rc = of_device_is_compatible(root, compat);
4121f43cfb9SGrant Likely 		of_node_put(root);
4131f43cfb9SGrant Likely 	}
4141f43cfb9SGrant Likely 	return rc;
4151f43cfb9SGrant Likely }
41671a157e8SGrant Likely EXPORT_SYMBOL(of_machine_is_compatible);
4171f43cfb9SGrant Likely 
4181f43cfb9SGrant Likely /**
419c31a0c05SStephen Warren  *  __of_device_is_available - check if a device is available for use
420834d97d4SJosh Boyer  *
421c31a0c05SStephen Warren  *  @device: Node to check for availability, with locks already held
422834d97d4SJosh Boyer  *
4238c8239c2SRob Herring  *  Return: True if the status property is absent or set to "okay" or "ok",
42453a4ab96SKevin Cernekee  *  false otherwise
425834d97d4SJosh Boyer  */
__of_device_is_available(const struct device_node * device)42653a4ab96SKevin Cernekee static bool __of_device_is_available(const struct device_node *device)
427834d97d4SJosh Boyer {
428834d97d4SJosh Boyer 	const char *status;
429834d97d4SJosh Boyer 	int statlen;
430834d97d4SJosh Boyer 
43142ccd781SXiubo Li 	if (!device)
43253a4ab96SKevin Cernekee 		return false;
43342ccd781SXiubo Li 
434c31a0c05SStephen Warren 	status = __of_get_property(device, "status", &statlen);
435834d97d4SJosh Boyer 	if (status == NULL)
43653a4ab96SKevin Cernekee 		return true;
437834d97d4SJosh Boyer 
438834d97d4SJosh Boyer 	if (statlen > 0) {
439834d97d4SJosh Boyer 		if (!strcmp(status, "okay") || !strcmp(status, "ok"))
44053a4ab96SKevin Cernekee 			return true;
441834d97d4SJosh Boyer 	}
442834d97d4SJosh Boyer 
44353a4ab96SKevin Cernekee 	return false;
444834d97d4SJosh Boyer }
445c31a0c05SStephen Warren 
446c31a0c05SStephen Warren /**
447c31a0c05SStephen Warren  *  of_device_is_available - check if a device is available for use
448c31a0c05SStephen Warren  *
449c31a0c05SStephen Warren  *  @device: Node to check for availability
450c31a0c05SStephen Warren  *
4518c8239c2SRob Herring  *  Return: True if the status property is absent or set to "okay" or "ok",
45253a4ab96SKevin Cernekee  *  false otherwise
453c31a0c05SStephen Warren  */
of_device_is_available(const struct device_node * device)45453a4ab96SKevin Cernekee bool of_device_is_available(const struct device_node *device)
455c31a0c05SStephen Warren {
456c31a0c05SStephen Warren 	unsigned long flags;
45753a4ab96SKevin Cernekee 	bool res;
458c31a0c05SStephen Warren 
459c31a0c05SStephen Warren 	raw_spin_lock_irqsave(&devtree_lock, flags);
460c31a0c05SStephen Warren 	res = __of_device_is_available(device);
461c31a0c05SStephen Warren 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
462c31a0c05SStephen Warren 	return res;
463c31a0c05SStephen Warren 
464c31a0c05SStephen Warren }
465834d97d4SJosh Boyer EXPORT_SYMBOL(of_device_is_available);
466834d97d4SJosh Boyer 
467834d97d4SJosh Boyer /**
4684fdd0736SMatthias Schiffer  *  __of_device_is_fail - check if a device has status "fail" or "fail-..."
4694fdd0736SMatthias Schiffer  *
4704fdd0736SMatthias Schiffer  *  @device: Node to check status for, with locks already held
4714fdd0736SMatthias Schiffer  *
4724fdd0736SMatthias Schiffer  *  Return: True if the status property is set to "fail" or "fail-..." (for any
4734fdd0736SMatthias Schiffer  *  error code suffix), false otherwise
4744fdd0736SMatthias Schiffer  */
__of_device_is_fail(const struct device_node * device)4754fdd0736SMatthias Schiffer static bool __of_device_is_fail(const struct device_node *device)
4764fdd0736SMatthias Schiffer {
4774fdd0736SMatthias Schiffer 	const char *status;
4784fdd0736SMatthias Schiffer 
4794fdd0736SMatthias Schiffer 	if (!device)
4804fdd0736SMatthias Schiffer 		return false;
4814fdd0736SMatthias Schiffer 
4824fdd0736SMatthias Schiffer 	status = __of_get_property(device, "status", NULL);
4834fdd0736SMatthias Schiffer 	if (status == NULL)
4844fdd0736SMatthias Schiffer 		return false;
4854fdd0736SMatthias Schiffer 
4864fdd0736SMatthias Schiffer 	return !strcmp(status, "fail") || !strncmp(status, "fail-", 5);
4874fdd0736SMatthias Schiffer }
4884fdd0736SMatthias Schiffer 
4894fdd0736SMatthias Schiffer /**
49037786c7fSKevin Cernekee  *  of_device_is_big_endian - check if a device has BE registers
49137786c7fSKevin Cernekee  *
49237786c7fSKevin Cernekee  *  @device: Node to check for endianness
49337786c7fSKevin Cernekee  *
4948c8239c2SRob Herring  *  Return: True if the device has a "big-endian" property, or if the kernel
49537786c7fSKevin Cernekee  *  was compiled for BE *and* the device has a "native-endian" property.
49637786c7fSKevin Cernekee  *  Returns false otherwise.
49737786c7fSKevin Cernekee  *
49837786c7fSKevin Cernekee  *  Callers would nominally use ioread32be/iowrite32be if
49937786c7fSKevin Cernekee  *  of_device_is_big_endian() == true, or readl/writel otherwise.
50037786c7fSKevin Cernekee  */
of_device_is_big_endian(const struct device_node * device)50137786c7fSKevin Cernekee bool of_device_is_big_endian(const struct device_node *device)
50237786c7fSKevin Cernekee {
50337786c7fSKevin Cernekee 	if (of_property_read_bool(device, "big-endian"))
50437786c7fSKevin Cernekee 		return true;
50537786c7fSKevin Cernekee 	if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) &&
50637786c7fSKevin Cernekee 	    of_property_read_bool(device, "native-endian"))
50737786c7fSKevin Cernekee 		return true;
50837786c7fSKevin Cernekee 	return false;
50937786c7fSKevin Cernekee }
51037786c7fSKevin Cernekee EXPORT_SYMBOL(of_device_is_big_endian);
51137786c7fSKevin Cernekee 
51237786c7fSKevin Cernekee /**
513e679c5f4SStephen Rothwell  * of_get_parent - Get a node's parent if any
514e679c5f4SStephen Rothwell  * @node:	Node to get parent
515e679c5f4SStephen Rothwell  *
51662f026f0SRob Herring  * Return: A node pointer with refcount incremented, use
517e679c5f4SStephen Rothwell  * of_node_put() on it when done.
518e679c5f4SStephen Rothwell  */
of_get_parent(const struct device_node * node)519e679c5f4SStephen Rothwell struct device_node *of_get_parent(const struct device_node *node)
520e679c5f4SStephen Rothwell {
521e679c5f4SStephen Rothwell 	struct device_node *np;
522d6d3c4e6SThomas Gleixner 	unsigned long flags;
523e679c5f4SStephen Rothwell 
524e679c5f4SStephen Rothwell 	if (!node)
525e679c5f4SStephen Rothwell 		return NULL;
526e679c5f4SStephen Rothwell 
527d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
528e679c5f4SStephen Rothwell 	np = of_node_get(node->parent);
529d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
530e679c5f4SStephen Rothwell 	return np;
531e679c5f4SStephen Rothwell }
532e679c5f4SStephen Rothwell EXPORT_SYMBOL(of_get_parent);
533d1cd355aSStephen Rothwell 
534d1cd355aSStephen Rothwell /**
535f4eb0107SMichael Ellerman  * of_get_next_parent - Iterate to a node's parent
536f4eb0107SMichael Ellerman  * @node:	Node to get parent of
537f4eb0107SMichael Ellerman  *
538f4eb0107SMichael Ellerman  * This is like of_get_parent() except that it drops the
539f4eb0107SMichael Ellerman  * refcount on the passed node, making it suitable for iterating
540f4eb0107SMichael Ellerman  * through a node's parents.
541f4eb0107SMichael Ellerman  *
54262f026f0SRob Herring  * Return: A node pointer with refcount incremented, use
543f4eb0107SMichael Ellerman  * of_node_put() on it when done.
544f4eb0107SMichael Ellerman  */
of_get_next_parent(struct device_node * node)545f4eb0107SMichael Ellerman struct device_node *of_get_next_parent(struct device_node *node)
546f4eb0107SMichael Ellerman {
547f4eb0107SMichael Ellerman 	struct device_node *parent;
548d6d3c4e6SThomas Gleixner 	unsigned long flags;
549f4eb0107SMichael Ellerman 
550f4eb0107SMichael Ellerman 	if (!node)
551f4eb0107SMichael Ellerman 		return NULL;
552f4eb0107SMichael Ellerman 
553d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
554f4eb0107SMichael Ellerman 	parent = of_node_get(node->parent);
555f4eb0107SMichael Ellerman 	of_node_put(node);
556d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
557f4eb0107SMichael Ellerman 	return parent;
558f4eb0107SMichael Ellerman }
5596695be68SGuennadi Liakhovetski EXPORT_SYMBOL(of_get_next_parent);
560f4eb0107SMichael Ellerman 
__of_get_next_child(const struct device_node * node,struct device_node * prev)5610d0e02d6SGrant Likely static struct device_node *__of_get_next_child(const struct device_node *node,
5620d0e02d6SGrant Likely 						struct device_node *prev)
5630d0e02d6SGrant Likely {
5640d0e02d6SGrant Likely 	struct device_node *next;
5650d0e02d6SGrant Likely 
56643cb4367SFlorian Fainelli 	if (!node)
56743cb4367SFlorian Fainelli 		return NULL;
56843cb4367SFlorian Fainelli 
5690d0e02d6SGrant Likely 	next = prev ? prev->sibling : node->child;
570ace1c4b5S권오훈 	of_node_get(next);
5710d0e02d6SGrant Likely 	of_node_put(prev);
5720d0e02d6SGrant Likely 	return next;
5730d0e02d6SGrant Likely }
5740d0e02d6SGrant Likely #define __for_each_child_of_node(parent, child) \
5750d0e02d6SGrant Likely 	for (child = __of_get_next_child(parent, NULL); child != NULL; \
5760d0e02d6SGrant Likely 	     child = __of_get_next_child(parent, child))
5770d0e02d6SGrant Likely 
578f4eb0107SMichael Ellerman /**
579d1cd355aSStephen Rothwell  * of_get_next_child - Iterate a node childs
580d1cd355aSStephen Rothwell  * @node:	parent node
581d1cd355aSStephen Rothwell  * @prev:	previous child of the parent node, or NULL to get first
582d1cd355aSStephen Rothwell  *
58362f026f0SRob Herring  * Return: A node pointer with refcount incremented, use of_node_put() on
58464808273SBaruch Siach  * it when done. Returns NULL when prev is the last child. Decrements the
58564808273SBaruch Siach  * refcount of prev.
586d1cd355aSStephen Rothwell  */
of_get_next_child(const struct device_node * node,struct device_node * prev)587d1cd355aSStephen Rothwell struct device_node *of_get_next_child(const struct device_node *node,
588d1cd355aSStephen Rothwell 	struct device_node *prev)
589d1cd355aSStephen Rothwell {
590d1cd355aSStephen Rothwell 	struct device_node *next;
591d6d3c4e6SThomas Gleixner 	unsigned long flags;
592d1cd355aSStephen Rothwell 
593d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
5940d0e02d6SGrant Likely 	next = __of_get_next_child(node, prev);
595d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
596d1cd355aSStephen Rothwell 	return next;
597d1cd355aSStephen Rothwell }
598d1cd355aSStephen Rothwell EXPORT_SYMBOL(of_get_next_child);
5991ef4d424SStephen Rothwell 
6001ef4d424SStephen Rothwell /**
6013296193dSTimur Tabi  * of_get_next_available_child - Find the next available child node
6023296193dSTimur Tabi  * @node:	parent node
6033296193dSTimur Tabi  * @prev:	previous child of the parent node, or NULL to get first
6043296193dSTimur Tabi  *
6053296193dSTimur Tabi  * This function is like of_get_next_child(), except that it
6063296193dSTimur Tabi  * automatically skips any disabled nodes (i.e. status = "disabled").
6073296193dSTimur Tabi  */
of_get_next_available_child(const struct device_node * node,struct device_node * prev)6083296193dSTimur Tabi struct device_node *of_get_next_available_child(const struct device_node *node,
6093296193dSTimur Tabi 	struct device_node *prev)
6103296193dSTimur Tabi {
6113296193dSTimur Tabi 	struct device_node *next;
612d25d8694SBenjamin Herrenschmidt 	unsigned long flags;
6133296193dSTimur Tabi 
61443cb4367SFlorian Fainelli 	if (!node)
61543cb4367SFlorian Fainelli 		return NULL;
61643cb4367SFlorian Fainelli 
617d25d8694SBenjamin Herrenschmidt 	raw_spin_lock_irqsave(&devtree_lock, flags);
6183296193dSTimur Tabi 	next = prev ? prev->sibling : node->child;
6193296193dSTimur Tabi 	for (; next; next = next->sibling) {
620c31a0c05SStephen Warren 		if (!__of_device_is_available(next))
6213296193dSTimur Tabi 			continue;
6223296193dSTimur Tabi 		if (of_node_get(next))
6233296193dSTimur Tabi 			break;
6243296193dSTimur Tabi 	}
6253296193dSTimur Tabi 	of_node_put(prev);
626d25d8694SBenjamin Herrenschmidt 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
6273296193dSTimur Tabi 	return next;
6283296193dSTimur Tabi }
6293296193dSTimur Tabi EXPORT_SYMBOL(of_get_next_available_child);
6303296193dSTimur Tabi 
6313296193dSTimur Tabi /**
632f1f207e4SRob Herring  * of_get_next_cpu_node - Iterate on cpu nodes
633f1f207e4SRob Herring  * @prev:	previous child of the /cpus node, or NULL to get first
634f1f207e4SRob Herring  *
6354fdd0736SMatthias Schiffer  * Unusable CPUs (those with the status property set to "fail" or "fail-...")
6364fdd0736SMatthias Schiffer  * will be skipped.
6374fdd0736SMatthias Schiffer  *
63862f026f0SRob Herring  * Return: A cpu node pointer with refcount incremented, use of_node_put()
639f1f207e4SRob Herring  * on it when done. Returns NULL when prev is the last child. Decrements
640f1f207e4SRob Herring  * the refcount of prev.
641f1f207e4SRob Herring  */
of_get_next_cpu_node(struct device_node * prev)642f1f207e4SRob Herring struct device_node *of_get_next_cpu_node(struct device_node *prev)
643f1f207e4SRob Herring {
644f1f207e4SRob Herring 	struct device_node *next = NULL;
645f1f207e4SRob Herring 	unsigned long flags;
646f1f207e4SRob Herring 	struct device_node *node;
647f1f207e4SRob Herring 
648f1f207e4SRob Herring 	if (!prev)
649f1f207e4SRob Herring 		node = of_find_node_by_path("/cpus");
650f1f207e4SRob Herring 
651f1f207e4SRob Herring 	raw_spin_lock_irqsave(&devtree_lock, flags);
652f1f207e4SRob Herring 	if (prev)
653f1f207e4SRob Herring 		next = prev->sibling;
654f1f207e4SRob Herring 	else if (node) {
655f1f207e4SRob Herring 		next = node->child;
656f1f207e4SRob Herring 		of_node_put(node);
657f1f207e4SRob Herring 	}
658f1f207e4SRob Herring 	for (; next; next = next->sibling) {
6594fdd0736SMatthias Schiffer 		if (__of_device_is_fail(next))
6604fdd0736SMatthias Schiffer 			continue;
661f1f207e4SRob Herring 		if (!(of_node_name_eq(next, "cpu") ||
662e8b1dee2SRob Herring 		      __of_node_is_type(next, "cpu")))
663f1f207e4SRob Herring 			continue;
664f1f207e4SRob Herring 		if (of_node_get(next))
665f1f207e4SRob Herring 			break;
666f1f207e4SRob Herring 	}
667f1f207e4SRob Herring 	of_node_put(prev);
668f1f207e4SRob Herring 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
669f1f207e4SRob Herring 	return next;
670f1f207e4SRob Herring }
671f1f207e4SRob Herring EXPORT_SYMBOL(of_get_next_cpu_node);
672f1f207e4SRob Herring 
673f1f207e4SRob Herring /**
67436156f92SJohan Hovold  * of_get_compatible_child - Find compatible child node
67536156f92SJohan Hovold  * @parent:	parent node
67636156f92SJohan Hovold  * @compatible:	compatible string
67736156f92SJohan Hovold  *
67836156f92SJohan Hovold  * Lookup child node whose compatible property contains the given compatible
67936156f92SJohan Hovold  * string.
68036156f92SJohan Hovold  *
6818c8239c2SRob Herring  * Return: a node pointer with refcount incremented, use of_node_put() on it
68236156f92SJohan Hovold  * when done; or NULL if not found.
68336156f92SJohan Hovold  */
of_get_compatible_child(const struct device_node * parent,const char * compatible)68436156f92SJohan Hovold struct device_node *of_get_compatible_child(const struct device_node *parent,
68536156f92SJohan Hovold 				const char *compatible)
68636156f92SJohan Hovold {
68736156f92SJohan Hovold 	struct device_node *child;
68836156f92SJohan Hovold 
68936156f92SJohan Hovold 	for_each_child_of_node(parent, child) {
69036156f92SJohan Hovold 		if (of_device_is_compatible(child, compatible))
69136156f92SJohan Hovold 			break;
69236156f92SJohan Hovold 	}
69336156f92SJohan Hovold 
69436156f92SJohan Hovold 	return child;
69536156f92SJohan Hovold }
69636156f92SJohan Hovold EXPORT_SYMBOL(of_get_compatible_child);
69736156f92SJohan Hovold 
69836156f92SJohan Hovold /**
6999c19761aSSrinivas Kandagatla  * of_get_child_by_name - Find the child node by name for a given parent
7009c19761aSSrinivas Kandagatla  * @node:	parent node
7019c19761aSSrinivas Kandagatla  * @name:	child name to look for.
7029c19761aSSrinivas Kandagatla  *
7039c19761aSSrinivas Kandagatla  * This function looks for child node for given matching name
7049c19761aSSrinivas Kandagatla  *
70562f026f0SRob Herring  * Return: A node pointer if found, with refcount incremented, use
7069c19761aSSrinivas Kandagatla  * of_node_put() on it when done.
7079c19761aSSrinivas Kandagatla  * Returns NULL if node is not found.
7089c19761aSSrinivas Kandagatla  */
of_get_child_by_name(const struct device_node * node,const char * name)7099c19761aSSrinivas Kandagatla struct device_node *of_get_child_by_name(const struct device_node *node,
7109c19761aSSrinivas Kandagatla 				const char *name)
7119c19761aSSrinivas Kandagatla {
7129c19761aSSrinivas Kandagatla 	struct device_node *child;
7139c19761aSSrinivas Kandagatla 
7149c19761aSSrinivas Kandagatla 	for_each_child_of_node(node, child)
715b3e46d1aSRob Herring 		if (of_node_name_eq(child, name))
7169c19761aSSrinivas Kandagatla 			break;
7179c19761aSSrinivas Kandagatla 	return child;
7189c19761aSSrinivas Kandagatla }
7199c19761aSSrinivas Kandagatla EXPORT_SYMBOL(of_get_child_by_name);
7209c19761aSSrinivas Kandagatla 
__of_find_node_by_path(struct device_node * parent,const char * path)721e0a58f3eSFrank Rowand struct device_node *__of_find_node_by_path(struct device_node *parent,
722c22e650eSGrant Likely 						const char *path)
723c22e650eSGrant Likely {
724c22e650eSGrant Likely 	struct device_node *child;
725106937e8SLeif Lindholm 	int len;
726c22e650eSGrant Likely 
727721a09e9SBrian Norris 	len = strcspn(path, "/:");
728c22e650eSGrant Likely 	if (!len)
729c22e650eSGrant Likely 		return NULL;
730c22e650eSGrant Likely 
731c22e650eSGrant Likely 	__for_each_child_of_node(parent, child) {
73295e6b1faSRob Herring 		const char *name = kbasename(child->full_name);
733c22e650eSGrant Likely 		if (strncmp(path, name, len) == 0 && (strlen(name) == len))
734c22e650eSGrant Likely 			return child;
735c22e650eSGrant Likely 	}
736c22e650eSGrant Likely 	return NULL;
737c22e650eSGrant Likely }
738c22e650eSGrant Likely 
__of_find_node_by_full_path(struct device_node * node,const char * path)73927497e11SRob Herring struct device_node *__of_find_node_by_full_path(struct device_node *node,
74027497e11SRob Herring 						const char *path)
74127497e11SRob Herring {
74227497e11SRob Herring 	const char *separator = strchr(path, ':');
74327497e11SRob Herring 
74427497e11SRob Herring 	while (node && *path == '/') {
74527497e11SRob Herring 		struct device_node *tmp = node;
74627497e11SRob Herring 
74727497e11SRob Herring 		path++; /* Increment past '/' delimiter */
74827497e11SRob Herring 		node = __of_find_node_by_path(node, path);
74927497e11SRob Herring 		of_node_put(tmp);
75027497e11SRob Herring 		path = strchrnul(path, '/');
75127497e11SRob Herring 		if (separator && separator < path)
75227497e11SRob Herring 			break;
75327497e11SRob Herring 	}
75427497e11SRob Herring 	return node;
75527497e11SRob Herring }
75627497e11SRob Herring 
7579c19761aSSrinivas Kandagatla /**
75875c28c09SLeif Lindholm  * of_find_node_opts_by_path - Find a node matching a full OF path
759c22e650eSGrant Likely  * @path: Either the full path to match, or if the path does not
760c22e650eSGrant Likely  *       start with '/', the name of a property of the /aliases
761c22e650eSGrant Likely  *       node (an alias).  In the case of an alias, the node
762c22e650eSGrant Likely  *       matching the alias' value will be returned.
76375c28c09SLeif Lindholm  * @opts: Address of a pointer into which to store the start of
76475c28c09SLeif Lindholm  *       an options string appended to the end of the path with
76575c28c09SLeif Lindholm  *       a ':' separator.
766c22e650eSGrant Likely  *
767c22e650eSGrant Likely  * Valid paths:
76862f026f0SRob Herring  *  * /foo/bar	Full path
76962f026f0SRob Herring  *  * foo	Valid alias
77062f026f0SRob Herring  *  * foo/bar	Valid alias + relative path
7711ef4d424SStephen Rothwell  *
77262f026f0SRob Herring  * Return: A node pointer with refcount incremented, use
7731ef4d424SStephen Rothwell  * of_node_put() on it when done.
7741ef4d424SStephen Rothwell  */
of_find_node_opts_by_path(const char * path,const char ** opts)77575c28c09SLeif Lindholm struct device_node *of_find_node_opts_by_path(const char *path, const char **opts)
7761ef4d424SStephen Rothwell {
777c22e650eSGrant Likely 	struct device_node *np = NULL;
778c22e650eSGrant Likely 	struct property *pp;
779d6d3c4e6SThomas Gleixner 	unsigned long flags;
78075c28c09SLeif Lindholm 	const char *separator = strchr(path, ':');
78175c28c09SLeif Lindholm 
78275c28c09SLeif Lindholm 	if (opts)
78375c28c09SLeif Lindholm 		*opts = separator ? separator + 1 : NULL;
7841ef4d424SStephen Rothwell 
785c22e650eSGrant Likely 	if (strcmp(path, "/") == 0)
7865063e25aSGrant Likely 		return of_node_get(of_root);
787c22e650eSGrant Likely 
788c22e650eSGrant Likely 	/* The path could begin with an alias */
789c22e650eSGrant Likely 	if (*path != '/') {
790106937e8SLeif Lindholm 		int len;
791106937e8SLeif Lindholm 		const char *p = separator;
792106937e8SLeif Lindholm 
793106937e8SLeif Lindholm 		if (!p)
794106937e8SLeif Lindholm 			p = strchrnul(path, '/');
795106937e8SLeif Lindholm 		len = p - path;
796c22e650eSGrant Likely 
797c22e650eSGrant Likely 		/* of_aliases must not be NULL */
798c22e650eSGrant Likely 		if (!of_aliases)
799c22e650eSGrant Likely 			return NULL;
800c22e650eSGrant Likely 
801c22e650eSGrant Likely 		for_each_property_of_node(of_aliases, pp) {
802c22e650eSGrant Likely 			if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) {
803c22e650eSGrant Likely 				np = of_find_node_by_path(pp->value);
8041ef4d424SStephen Rothwell 				break;
8051ef4d424SStephen Rothwell 			}
806c22e650eSGrant Likely 		}
807c22e650eSGrant Likely 		if (!np)
808c22e650eSGrant Likely 			return NULL;
809c22e650eSGrant Likely 		path = p;
810c22e650eSGrant Likely 	}
811c22e650eSGrant Likely 
812c22e650eSGrant Likely 	/* Step down the tree matching path components */
813c22e650eSGrant Likely 	raw_spin_lock_irqsave(&devtree_lock, flags);
814c22e650eSGrant Likely 	if (!np)
8155063e25aSGrant Likely 		np = of_node_get(of_root);
81627497e11SRob Herring 	np = __of_find_node_by_full_path(np, path);
817d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
8181ef4d424SStephen Rothwell 	return np;
8191ef4d424SStephen Rothwell }
82075c28c09SLeif Lindholm EXPORT_SYMBOL(of_find_node_opts_by_path);
8211ef4d424SStephen Rothwell 
8221ef4d424SStephen Rothwell /**
8231ef4d424SStephen Rothwell  * of_find_node_by_name - Find a node by its "name" property
82402a876b5SStephen Boyd  * @from:	The node to start searching from or NULL; the node
8251ef4d424SStephen Rothwell  *		you pass will not be searched, only the next one
82602a876b5SStephen Boyd  *		will. Typically, you pass what the previous call
82702a876b5SStephen Boyd  *		returned. of_node_put() will be called on @from.
8281ef4d424SStephen Rothwell  * @name:	The name string to match against
8291ef4d424SStephen Rothwell  *
83062f026f0SRob Herring  * Return: A node pointer with refcount incremented, use
8311ef4d424SStephen Rothwell  * of_node_put() on it when done.
8321ef4d424SStephen Rothwell  */
of_find_node_by_name(struct device_node * from,const char * name)8331ef4d424SStephen Rothwell struct device_node *of_find_node_by_name(struct device_node *from,
8341ef4d424SStephen Rothwell 	const char *name)
8351ef4d424SStephen Rothwell {
8361ef4d424SStephen Rothwell 	struct device_node *np;
837d6d3c4e6SThomas Gleixner 	unsigned long flags;
8381ef4d424SStephen Rothwell 
839d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
8405063e25aSGrant Likely 	for_each_of_allnodes_from(from, np)
841b3e46d1aSRob Herring 		if (of_node_name_eq(np, name) && of_node_get(np))
8421ef4d424SStephen Rothwell 			break;
8431ef4d424SStephen Rothwell 	of_node_put(from);
844d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
8451ef4d424SStephen Rothwell 	return np;
8461ef4d424SStephen Rothwell }
8471ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_name);
8481ef4d424SStephen Rothwell 
8491ef4d424SStephen Rothwell /**
8501ef4d424SStephen Rothwell  * of_find_node_by_type - Find a node by its "device_type" property
8511ef4d424SStephen Rothwell  * @from:	The node to start searching from, or NULL to start searching
8521ef4d424SStephen Rothwell  *		the entire device tree. The node you pass will not be
8531ef4d424SStephen Rothwell  *		searched, only the next one will; typically, you pass
8541ef4d424SStephen Rothwell  *		what the previous call returned. of_node_put() will be
8551ef4d424SStephen Rothwell  *		called on from for you.
8561ef4d424SStephen Rothwell  * @type:	The type string to match against
8571ef4d424SStephen Rothwell  *
85862f026f0SRob Herring  * Return: A node pointer with refcount incremented, use
8591ef4d424SStephen Rothwell  * of_node_put() on it when done.
8601ef4d424SStephen Rothwell  */
of_find_node_by_type(struct device_node * from,const char * type)8611ef4d424SStephen Rothwell struct device_node *of_find_node_by_type(struct device_node *from,
8621ef4d424SStephen Rothwell 	const char *type)
8631ef4d424SStephen Rothwell {
8641ef4d424SStephen Rothwell 	struct device_node *np;
865d6d3c4e6SThomas Gleixner 	unsigned long flags;
8661ef4d424SStephen Rothwell 
867d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
8685063e25aSGrant Likely 	for_each_of_allnodes_from(from, np)
869e8b1dee2SRob Herring 		if (__of_node_is_type(np, type) && of_node_get(np))
8701ef4d424SStephen Rothwell 			break;
8711ef4d424SStephen Rothwell 	of_node_put(from);
872d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
8731ef4d424SStephen Rothwell 	return np;
8741ef4d424SStephen Rothwell }
8751ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_type);
8761ef4d424SStephen Rothwell 
8771ef4d424SStephen Rothwell /**
8781ef4d424SStephen Rothwell  * of_find_compatible_node - Find a node based on type and one of the
8791ef4d424SStephen Rothwell  *                                tokens in its "compatible" property
8801ef4d424SStephen Rothwell  * @from:	The node to start searching from or NULL, the node
8811ef4d424SStephen Rothwell  *		you pass will not be searched, only the next one
8821ef4d424SStephen Rothwell  *		will; typically, you pass what the previous call
8831ef4d424SStephen Rothwell  *		returned. of_node_put() will be called on it
8841ef4d424SStephen Rothwell  * @type:	The type string to match "device_type" or NULL to ignore
8851ef4d424SStephen Rothwell  * @compatible:	The string to match to one of the tokens in the device
8861ef4d424SStephen Rothwell  *		"compatible" list.
8871ef4d424SStephen Rothwell  *
88862f026f0SRob Herring  * Return: A node pointer with refcount incremented, use
8891ef4d424SStephen Rothwell  * of_node_put() on it when done.
8901ef4d424SStephen Rothwell  */
of_find_compatible_node(struct device_node * from,const char * type,const char * compatible)8911ef4d424SStephen Rothwell struct device_node *of_find_compatible_node(struct device_node *from,
8921ef4d424SStephen Rothwell 	const char *type, const char *compatible)
8931ef4d424SStephen Rothwell {
8941ef4d424SStephen Rothwell 	struct device_node *np;
895d6d3c4e6SThomas Gleixner 	unsigned long flags;
8961ef4d424SStephen Rothwell 
897d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
8985063e25aSGrant Likely 	for_each_of_allnodes_from(from, np)
899215a14cfSKevin Hao 		if (__of_device_is_compatible(np, compatible, type, NULL) &&
90028d0e36bSThomas Gleixner 		    of_node_get(np))
9011ef4d424SStephen Rothwell 			break;
9021ef4d424SStephen Rothwell 	of_node_put(from);
903d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
9041ef4d424SStephen Rothwell 	return np;
9051ef4d424SStephen Rothwell }
9061ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_compatible_node);
907283029d1SGrant Likely 
908283029d1SGrant Likely /**
9091e291b14SMichael Ellerman  * of_find_node_with_property - Find a node which has a property with
9101e291b14SMichael Ellerman  *                              the given name.
9111e291b14SMichael Ellerman  * @from:	The node to start searching from or NULL, the node
9121e291b14SMichael Ellerman  *		you pass will not be searched, only the next one
9131e291b14SMichael Ellerman  *		will; typically, you pass what the previous call
9141e291b14SMichael Ellerman  *		returned. of_node_put() will be called on it
9151e291b14SMichael Ellerman  * @prop_name:	The name of the property to look for.
9161e291b14SMichael Ellerman  *
91762f026f0SRob Herring  * Return: A node pointer with refcount incremented, use
9181e291b14SMichael Ellerman  * of_node_put() on it when done.
9191e291b14SMichael Ellerman  */
of_find_node_with_property(struct device_node * from,const char * prop_name)9201e291b14SMichael Ellerman struct device_node *of_find_node_with_property(struct device_node *from,
9211e291b14SMichael Ellerman 	const char *prop_name)
9221e291b14SMichael Ellerman {
9231e291b14SMichael Ellerman 	struct device_node *np;
9241e291b14SMichael Ellerman 	struct property *pp;
925d6d3c4e6SThomas Gleixner 	unsigned long flags;
9261e291b14SMichael Ellerman 
927d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
9285063e25aSGrant Likely 	for_each_of_allnodes_from(from, np) {
929a3a7cab1SSachin Kamat 		for (pp = np->properties; pp; pp = pp->next) {
9301e291b14SMichael Ellerman 			if (of_prop_cmp(pp->name, prop_name) == 0) {
9311e291b14SMichael Ellerman 				of_node_get(np);
9321e291b14SMichael Ellerman 				goto out;
9331e291b14SMichael Ellerman 			}
9341e291b14SMichael Ellerman 		}
9351e291b14SMichael Ellerman 	}
9361e291b14SMichael Ellerman out:
9371e291b14SMichael Ellerman 	of_node_put(from);
938d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
9391e291b14SMichael Ellerman 	return np;
9401e291b14SMichael Ellerman }
9411e291b14SMichael Ellerman EXPORT_SYMBOL(of_find_node_with_property);
9421e291b14SMichael Ellerman 
94328d0e36bSThomas Gleixner static
__of_match_node(const struct of_device_id * matches,const struct device_node * node)94428d0e36bSThomas Gleixner const struct of_device_id *__of_match_node(const struct of_device_id *matches,
945283029d1SGrant Likely 					   const struct device_node *node)
946283029d1SGrant Likely {
947215a14cfSKevin Hao 	const struct of_device_id *best_match = NULL;
948215a14cfSKevin Hao 	int score, best_score = 0;
949215a14cfSKevin Hao 
950a52f07ecSGrant Likely 	if (!matches)
951a52f07ecSGrant Likely 		return NULL;
952a52f07ecSGrant Likely 
953215a14cfSKevin Hao 	for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) {
954215a14cfSKevin Hao 		score = __of_device_is_compatible(node, matches->compatible,
955215a14cfSKevin Hao 						  matches->type, matches->name);
956215a14cfSKevin Hao 		if (score > best_score) {
957215a14cfSKevin Hao 			best_match = matches;
958215a14cfSKevin Hao 			best_score = score;
959283029d1SGrant Likely 		}
960215a14cfSKevin Hao 	}
961215a14cfSKevin Hao 
962215a14cfSKevin Hao 	return best_match;
963283029d1SGrant Likely }
96428d0e36bSThomas Gleixner 
96528d0e36bSThomas Gleixner /**
966c50949d3SGeert Uytterhoeven  * of_match_node - Tell if a device_node has a matching of_match structure
96728d0e36bSThomas Gleixner  * @matches:	array of of device match structures to search in
96828d0e36bSThomas Gleixner  * @node:	the of device structure to match against
96928d0e36bSThomas Gleixner  *
97071c5498eSKevin Hao  * Low level utility function used by device matching.
97128d0e36bSThomas Gleixner  */
of_match_node(const struct of_device_id * matches,const struct device_node * node)97228d0e36bSThomas Gleixner const struct of_device_id *of_match_node(const struct of_device_id *matches,
97328d0e36bSThomas Gleixner 					 const struct device_node *node)
97428d0e36bSThomas Gleixner {
97528d0e36bSThomas Gleixner 	const struct of_device_id *match;
976d6d3c4e6SThomas Gleixner 	unsigned long flags;
97728d0e36bSThomas Gleixner 
978d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
97928d0e36bSThomas Gleixner 	match = __of_match_node(matches, node);
980d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
98128d0e36bSThomas Gleixner 	return match;
98228d0e36bSThomas Gleixner }
983283029d1SGrant Likely EXPORT_SYMBOL(of_match_node);
984283029d1SGrant Likely 
985283029d1SGrant Likely /**
98650c8af4cSStephen Warren  * of_find_matching_node_and_match - Find a node based on an of_device_id
98750c8af4cSStephen Warren  *				     match table.
988283029d1SGrant Likely  * @from:	The node to start searching from or NULL, the node
989283029d1SGrant Likely  *		you pass will not be searched, only the next one
990283029d1SGrant Likely  *		will; typically, you pass what the previous call
991283029d1SGrant Likely  *		returned. of_node_put() will be called on it
992283029d1SGrant Likely  * @matches:	array of of device match structures to search in
9933637d49eSLee Jones  * @match:	Updated to point at the matches entry which matched
994283029d1SGrant Likely  *
99562f026f0SRob Herring  * Return: A node pointer with refcount incremented, use
996283029d1SGrant Likely  * of_node_put() on it when done.
997283029d1SGrant Likely  */
of_find_matching_node_and_match(struct device_node * from,const struct of_device_id * matches,const struct of_device_id ** match)99850c8af4cSStephen Warren struct device_node *of_find_matching_node_and_match(struct device_node *from,
99950c8af4cSStephen Warren 					const struct of_device_id *matches,
100050c8af4cSStephen Warren 					const struct of_device_id **match)
1001283029d1SGrant Likely {
1002283029d1SGrant Likely 	struct device_node *np;
1003dc71bcf1SThomas Abraham 	const struct of_device_id *m;
1004d6d3c4e6SThomas Gleixner 	unsigned long flags;
1005283029d1SGrant Likely 
100650c8af4cSStephen Warren 	if (match)
100750c8af4cSStephen Warren 		*match = NULL;
100850c8af4cSStephen Warren 
1009d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
10105063e25aSGrant Likely 	for_each_of_allnodes_from(from, np) {
101128d0e36bSThomas Gleixner 		m = __of_match_node(matches, np);
1012dc71bcf1SThomas Abraham 		if (m && of_node_get(np)) {
101350c8af4cSStephen Warren 			if (match)
1014dc71bcf1SThomas Abraham 				*match = m;
1015283029d1SGrant Likely 			break;
1016283029d1SGrant Likely 		}
101750c8af4cSStephen Warren 	}
1018283029d1SGrant Likely 	of_node_put(from);
1019d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1020283029d1SGrant Likely 	return np;
1021283029d1SGrant Likely }
102280c2022eSGrant Likely EXPORT_SYMBOL(of_find_matching_node_and_match);
10233f07af49SGrant Likely 
10243f07af49SGrant Likely /**
1025673aa1edSMiquel Raynal  * of_alias_from_compatible - Lookup appropriate alias for a device node
1026673aa1edSMiquel Raynal  *			      depending on compatible
10273f07af49SGrant Likely  * @node:	pointer to a device tree node
1028673aa1edSMiquel Raynal  * @alias:	Pointer to buffer that alias value will be copied into
1029673aa1edSMiquel Raynal  * @len:	Length of alias value
10303f07af49SGrant Likely  *
10312ffe8c5fSGrant Likely  * Based on the value of the compatible property, this routine will attempt
1032673aa1edSMiquel Raynal  * to choose an appropriate alias value for a particular device tree node.
10332ffe8c5fSGrant Likely  * It does this by stripping the manufacturer prefix (as delimited by a ',')
10342ffe8c5fSGrant Likely  * from the first entry in the compatible list property.
10353f07af49SGrant Likely  *
1036673aa1edSMiquel Raynal  * Note: The matching on just the "product" side of the compatible is a relic
1037673aa1edSMiquel Raynal  * from I2C and SPI. Please do not add any new user.
1038673aa1edSMiquel Raynal  *
10398c8239c2SRob Herring  * Return: This routine returns 0 on success, <0 on failure.
10403f07af49SGrant Likely  */
of_alias_from_compatible(const struct device_node * node,char * alias,int len)1041673aa1edSMiquel Raynal int of_alias_from_compatible(const struct device_node *node, char *alias, int len)
10423f07af49SGrant Likely {
10432ffe8c5fSGrant Likely 	const char *compatible, *p;
10442ffe8c5fSGrant Likely 	int cplen;
10453f07af49SGrant Likely 
10463f07af49SGrant Likely 	compatible = of_get_property(node, "compatible", &cplen);
10472ffe8c5fSGrant Likely 	if (!compatible || strlen(compatible) > cplen)
10483f07af49SGrant Likely 		return -ENODEV;
10493f07af49SGrant Likely 	p = strchr(compatible, ',');
1050673aa1edSMiquel Raynal 	strscpy(alias, p ? p + 1 : compatible, len);
10513f07af49SGrant Likely 	return 0;
10523f07af49SGrant Likely }
1053673aa1edSMiquel Raynal EXPORT_SYMBOL_GPL(of_alias_from_compatible);
10543f07af49SGrant Likely 
105564b60e09SAnton Vorontsov /**
105689751a7cSJeremy Kerr  * of_find_node_by_phandle - Find a node given a phandle
105789751a7cSJeremy Kerr  * @handle:	phandle of the node to find
105889751a7cSJeremy Kerr  *
10598c8239c2SRob Herring  * Return: A node pointer with refcount incremented, use
106089751a7cSJeremy Kerr  * of_node_put() on it when done.
106189751a7cSJeremy Kerr  */
of_find_node_by_phandle(phandle handle)106289751a7cSJeremy Kerr struct device_node *of_find_node_by_phandle(phandle handle)
106389751a7cSJeremy Kerr {
10640b3ce78eSFrank Rowand 	struct device_node *np = NULL;
1065d25d8694SBenjamin Herrenschmidt 	unsigned long flags;
106690dc0d1cSRob Herring 	u32 handle_hash;
106789751a7cSJeremy Kerr 
1068fc59b447SGrant Likely 	if (!handle)
1069fc59b447SGrant Likely 		return NULL;
1070fc59b447SGrant Likely 
107190dc0d1cSRob Herring 	handle_hash = of_phandle_cache_hash(handle);
107290dc0d1cSRob Herring 
1073d25d8694SBenjamin Herrenschmidt 	raw_spin_lock_irqsave(&devtree_lock, flags);
10740b3ce78eSFrank Rowand 
107590dc0d1cSRob Herring 	if (phandle_cache[handle_hash] &&
107690dc0d1cSRob Herring 	    handle == phandle_cache[handle_hash]->phandle)
107790dc0d1cSRob Herring 		np = phandle_cache[handle_hash];
10780b3ce78eSFrank Rowand 
10790b3ce78eSFrank Rowand 	if (!np) {
10805063e25aSGrant Likely 		for_each_of_allnodes(np)
10815801169aSFrank Rowand 			if (np->phandle == handle &&
10825801169aSFrank Rowand 			    !of_node_check_flag(np, OF_DETACHED)) {
108390dc0d1cSRob Herring 				phandle_cache[handle_hash] = np;
108489751a7cSJeremy Kerr 				break;
10850b3ce78eSFrank Rowand 			}
10860b3ce78eSFrank Rowand 	}
10870b3ce78eSFrank Rowand 
108889751a7cSJeremy Kerr 	of_node_get(np);
1089d25d8694SBenjamin Herrenschmidt 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
109089751a7cSJeremy Kerr 	return np;
109189751a7cSJeremy Kerr }
109289751a7cSJeremy Kerr EXPORT_SYMBOL(of_find_node_by_phandle);
109389751a7cSJeremy Kerr 
of_print_phandle_args(const char * msg,const struct of_phandle_args * args)1094624cfca5SGrant Likely void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
1095624cfca5SGrant Likely {
1096624cfca5SGrant Likely 	int i;
10970d638a07SRob Herring 	printk("%s %pOF", msg, args->np);
10984aa66344SMarcin Nowakowski 	for (i = 0; i < args->args_count; i++) {
10994aa66344SMarcin Nowakowski 		const char delim = i ? ',' : ':';
11004aa66344SMarcin Nowakowski 
11014aa66344SMarcin Nowakowski 		pr_cont("%c%08x", delim, args->args[i]);
11024aa66344SMarcin Nowakowski 	}
11034aa66344SMarcin Nowakowski 	pr_cont("\n");
1104624cfca5SGrant Likely }
1105624cfca5SGrant Likely 
of_phandle_iterator_init(struct of_phandle_iterator * it,const struct device_node * np,const char * list_name,const char * cells_name,int cell_count)110674e1fbb1SJoerg Roedel int of_phandle_iterator_init(struct of_phandle_iterator *it,
110774e1fbb1SJoerg Roedel 		const struct device_node *np,
110874e1fbb1SJoerg Roedel 		const char *list_name,
110974e1fbb1SJoerg Roedel 		const char *cells_name,
111074e1fbb1SJoerg Roedel 		int cell_count)
111174e1fbb1SJoerg Roedel {
111274e1fbb1SJoerg Roedel 	const __be32 *list;
111374e1fbb1SJoerg Roedel 	int size;
111474e1fbb1SJoerg Roedel 
111574e1fbb1SJoerg Roedel 	memset(it, 0, sizeof(*it));
111674e1fbb1SJoerg Roedel 
111759e9fcf8SUwe Kleine-König 	/*
111859e9fcf8SUwe Kleine-König 	 * one of cell_count or cells_name must be provided to determine the
111959e9fcf8SUwe Kleine-König 	 * argument length.
112059e9fcf8SUwe Kleine-König 	 */
112159e9fcf8SUwe Kleine-König 	if (cell_count < 0 && !cells_name)
112259e9fcf8SUwe Kleine-König 		return -EINVAL;
112359e9fcf8SUwe Kleine-König 
112474e1fbb1SJoerg Roedel 	list = of_get_property(np, list_name, &size);
112574e1fbb1SJoerg Roedel 	if (!list)
112674e1fbb1SJoerg Roedel 		return -ENOENT;
112774e1fbb1SJoerg Roedel 
112874e1fbb1SJoerg Roedel 	it->cells_name = cells_name;
112974e1fbb1SJoerg Roedel 	it->cell_count = cell_count;
113074e1fbb1SJoerg Roedel 	it->parent = np;
113174e1fbb1SJoerg Roedel 	it->list_end = list + size / sizeof(*list);
113274e1fbb1SJoerg Roedel 	it->phandle_end = list;
113374e1fbb1SJoerg Roedel 	it->cur = list;
113474e1fbb1SJoerg Roedel 
113574e1fbb1SJoerg Roedel 	return 0;
113674e1fbb1SJoerg Roedel }
113700bab23fSKuninori Morimoto EXPORT_SYMBOL_GPL(of_phandle_iterator_init);
113874e1fbb1SJoerg Roedel 
of_phandle_iterator_next(struct of_phandle_iterator * it)1139cd209b41SJoerg Roedel int of_phandle_iterator_next(struct of_phandle_iterator *it)
1140cd209b41SJoerg Roedel {
1141cd209b41SJoerg Roedel 	uint32_t count = 0;
1142cd209b41SJoerg Roedel 
1143cd209b41SJoerg Roedel 	if (it->node) {
1144cd209b41SJoerg Roedel 		of_node_put(it->node);
1145cd209b41SJoerg Roedel 		it->node = NULL;
1146cd209b41SJoerg Roedel 	}
1147cd209b41SJoerg Roedel 
1148cd209b41SJoerg Roedel 	if (!it->cur || it->phandle_end >= it->list_end)
1149cd209b41SJoerg Roedel 		return -ENOENT;
1150cd209b41SJoerg Roedel 
1151cd209b41SJoerg Roedel 	it->cur = it->phandle_end;
1152cd209b41SJoerg Roedel 
1153cd209b41SJoerg Roedel 	/* If phandle is 0, then it is an empty entry with no arguments. */
1154cd209b41SJoerg Roedel 	it->phandle = be32_to_cpup(it->cur++);
1155cd209b41SJoerg Roedel 
1156cd209b41SJoerg Roedel 	if (it->phandle) {
1157cd209b41SJoerg Roedel 
1158cd209b41SJoerg Roedel 		/*
1159cd209b41SJoerg Roedel 		 * Find the provider node and parse the #*-cells property to
1160cd209b41SJoerg Roedel 		 * determine the argument length.
1161cd209b41SJoerg Roedel 		 */
1162cd209b41SJoerg Roedel 		it->node = of_find_node_by_phandle(it->phandle);
1163cd209b41SJoerg Roedel 
1164cd209b41SJoerg Roedel 		if (it->cells_name) {
1165cd209b41SJoerg Roedel 			if (!it->node) {
116612e17243SEnrico Weigelt, metux IT consult 				pr_err("%pOF: could not find phandle %d\n",
116712e17243SEnrico Weigelt, metux IT consult 				       it->parent, it->phandle);
1168cd209b41SJoerg Roedel 				goto err;
1169cd209b41SJoerg Roedel 			}
1170cd209b41SJoerg Roedel 
1171cd209b41SJoerg Roedel 			if (of_property_read_u32(it->node, it->cells_name,
1172cd209b41SJoerg Roedel 						 &count)) {
1173e42ee610SUwe Kleine-König 				/*
1174e42ee610SUwe Kleine-König 				 * If both cell_count and cells_name is given,
1175e42ee610SUwe Kleine-König 				 * fall back to cell_count in absence
1176e42ee610SUwe Kleine-König 				 * of the cells_name property
1177e42ee610SUwe Kleine-König 				 */
1178e42ee610SUwe Kleine-König 				if (it->cell_count >= 0) {
1179e42ee610SUwe Kleine-König 					count = it->cell_count;
1180e42ee610SUwe Kleine-König 				} else {
11810d638a07SRob Herring 					pr_err("%pOF: could not get %s for %pOF\n",
11820d638a07SRob Herring 					       it->parent,
1183cd209b41SJoerg Roedel 					       it->cells_name,
11840d638a07SRob Herring 					       it->node);
1185cd209b41SJoerg Roedel 					goto err;
1186cd209b41SJoerg Roedel 				}
1187e42ee610SUwe Kleine-König 			}
1188cd209b41SJoerg Roedel 		} else {
1189cd209b41SJoerg Roedel 			count = it->cell_count;
1190cd209b41SJoerg Roedel 		}
1191cd209b41SJoerg Roedel 
1192cd209b41SJoerg Roedel 		/*
1193cd209b41SJoerg Roedel 		 * Make sure that the arguments actually fit in the remaining
1194cd209b41SJoerg Roedel 		 * property data length
1195cd209b41SJoerg Roedel 		 */
1196cd209b41SJoerg Roedel 		if (it->cur + count > it->list_end) {
11975d05b811SBaruch Siach 			if (it->cells_name)
119894a4950aSBaruch Siach 				pr_err("%pOF: %s = %d found %td\n",
1199af3be70aSFlorian Fainelli 					it->parent, it->cells_name,
120094a4950aSBaruch Siach 					count, it->list_end - it->cur);
12015d05b811SBaruch Siach 			else
12025d05b811SBaruch Siach 				pr_err("%pOF: phandle %s needs %d, found %td\n",
12035d05b811SBaruch Siach 					it->parent, of_node_full_name(it->node),
12045d05b811SBaruch Siach 					count, it->list_end - it->cur);
1205cd209b41SJoerg Roedel 			goto err;
1206cd209b41SJoerg Roedel 		}
1207cd209b41SJoerg Roedel 	}
1208cd209b41SJoerg Roedel 
1209cd209b41SJoerg Roedel 	it->phandle_end = it->cur + count;
1210cd209b41SJoerg Roedel 	it->cur_count = count;
1211cd209b41SJoerg Roedel 
1212cd209b41SJoerg Roedel 	return 0;
1213cd209b41SJoerg Roedel 
1214cd209b41SJoerg Roedel err:
1215cd209b41SJoerg Roedel 	if (it->node) {
1216cd209b41SJoerg Roedel 		of_node_put(it->node);
1217cd209b41SJoerg Roedel 		it->node = NULL;
1218cd209b41SJoerg Roedel 	}
1219cd209b41SJoerg Roedel 
1220cd209b41SJoerg Roedel 	return -EINVAL;
1221cd209b41SJoerg Roedel }
122200bab23fSKuninori Morimoto EXPORT_SYMBOL_GPL(of_phandle_iterator_next);
1223cd209b41SJoerg Roedel 
of_phandle_iterator_args(struct of_phandle_iterator * it,uint32_t * args,int size)1224abdaa77bSJoerg Roedel int of_phandle_iterator_args(struct of_phandle_iterator *it,
1225abdaa77bSJoerg Roedel 			     uint32_t *args,
1226abdaa77bSJoerg Roedel 			     int size)
1227abdaa77bSJoerg Roedel {
1228abdaa77bSJoerg Roedel 	int i, count;
1229abdaa77bSJoerg Roedel 
1230abdaa77bSJoerg Roedel 	count = it->cur_count;
1231abdaa77bSJoerg Roedel 
1232abdaa77bSJoerg Roedel 	if (WARN_ON(size < count))
1233abdaa77bSJoerg Roedel 		count = size;
1234abdaa77bSJoerg Roedel 
1235abdaa77bSJoerg Roedel 	for (i = 0; i < count; i++)
1236abdaa77bSJoerg Roedel 		args[i] = be32_to_cpup(it->cur++);
1237abdaa77bSJoerg Roedel 
1238abdaa77bSJoerg Roedel 	return count;
1239abdaa77bSJoerg Roedel }
1240abdaa77bSJoerg Roedel 
__of_parse_phandle_with_args(const struct device_node * np,const char * list_name,const char * cells_name,int cell_count,int index,struct of_phandle_args * out_args)124166a8f7f0SMichael Walle int __of_parse_phandle_with_args(const struct device_node *np,
1242bd69f73fSGrant Likely 				 const char *list_name,
1243035fd948SStephen Warren 				 const char *cells_name,
1244035fd948SStephen Warren 				 int cell_count, int index,
124515c9a0acSGrant Likely 				 struct of_phandle_args *out_args)
124664b60e09SAnton Vorontsov {
124774e1fbb1SJoerg Roedel 	struct of_phandle_iterator it;
124874e1fbb1SJoerg Roedel 	int rc, cur_index = 0;
124915c9a0acSGrant Likely 
125066a8f7f0SMichael Walle 	if (index < 0)
125166a8f7f0SMichael Walle 		return -EINVAL;
125266a8f7f0SMichael Walle 
125315c9a0acSGrant Likely 	/* Loop over the phandles until all the requested entry is found */
1254f623ce95SJoerg Roedel 	of_for_each_phandle(&it, rc, np, list_name, cells_name, cell_count) {
125515c9a0acSGrant Likely 		/*
1256cd209b41SJoerg Roedel 		 * All of the error cases bail out of the loop, so at
125715c9a0acSGrant Likely 		 * this point, the parsing is successful. If the requested
125815c9a0acSGrant Likely 		 * index matches, then fill the out_args structure and return,
125915c9a0acSGrant Likely 		 * or return -ENOENT for an empty entry.
126015c9a0acSGrant Likely 		 */
126123ce04c0SGrant Likely 		rc = -ENOENT;
126215c9a0acSGrant Likely 		if (cur_index == index) {
126374e1fbb1SJoerg Roedel 			if (!it.phandle)
126423ce04c0SGrant Likely 				goto err;
126515c9a0acSGrant Likely 
126615c9a0acSGrant Likely 			if (out_args) {
1267abdaa77bSJoerg Roedel 				int c;
1268abdaa77bSJoerg Roedel 
1269abdaa77bSJoerg Roedel 				c = of_phandle_iterator_args(&it,
1270abdaa77bSJoerg Roedel 							     out_args->args,
1271abdaa77bSJoerg Roedel 							     MAX_PHANDLE_ARGS);
127274e1fbb1SJoerg Roedel 				out_args->np = it.node;
1273abdaa77bSJoerg Roedel 				out_args->args_count = c;
1274b855f16bSTang Yuantian 			} else {
127574e1fbb1SJoerg Roedel 				of_node_put(it.node);
127615c9a0acSGrant Likely 			}
127723ce04c0SGrant Likely 
127823ce04c0SGrant Likely 			/* Found it! return success */
127915c9a0acSGrant Likely 			return 0;
128015c9a0acSGrant Likely 		}
128164b60e09SAnton Vorontsov 
128264b60e09SAnton Vorontsov 		cur_index++;
128364b60e09SAnton Vorontsov 	}
128464b60e09SAnton Vorontsov 
128523ce04c0SGrant Likely 	/*
128623ce04c0SGrant Likely 	 * Unlock node before returning result; will be one of:
128723ce04c0SGrant Likely 	 * -ENOENT : index is for empty phandle
128823ce04c0SGrant Likely 	 * -EINVAL : parsing error on data
128923ce04c0SGrant Likely 	 */
1290cd209b41SJoerg Roedel 
129123ce04c0SGrant Likely  err:
129274e1fbb1SJoerg Roedel 	of_node_put(it.node);
129323ce04c0SGrant Likely 	return rc;
129464b60e09SAnton Vorontsov }
129566a8f7f0SMichael Walle EXPORT_SYMBOL(__of_parse_phandle_with_args);
129602af11b0SGrant Likely 
1297bd69f73fSGrant Likely /**
1298bd6f2fd5SStephen Boyd  * of_parse_phandle_with_args_map() - Find a node pointed by phandle in a list and remap it
1299bd6f2fd5SStephen Boyd  * @np:		pointer to a device tree node containing a list
1300bd6f2fd5SStephen Boyd  * @list_name:	property name that contains a list
1301bd6f2fd5SStephen Boyd  * @stem_name:	stem of property names that specify phandles' arguments count
1302bd6f2fd5SStephen Boyd  * @index:	index of a phandle to parse out
1303bd6f2fd5SStephen Boyd  * @out_args:	optional pointer to output arguments structure (will be filled)
1304bd6f2fd5SStephen Boyd  *
1305bd6f2fd5SStephen Boyd  * This function is useful to parse lists of phandles and their arguments.
1306bd6f2fd5SStephen Boyd  * Returns 0 on success and fills out_args, on error returns appropriate errno
1307bd6f2fd5SStephen Boyd  * value. The difference between this function and of_parse_phandle_with_args()
1308bd6f2fd5SStephen Boyd  * is that this API remaps a phandle if the node the phandle points to has
1309bd6f2fd5SStephen Boyd  * a <@stem_name>-map property.
1310bd6f2fd5SStephen Boyd  *
1311bd6f2fd5SStephen Boyd  * Caller is responsible to call of_node_put() on the returned out_args->np
1312bd6f2fd5SStephen Boyd  * pointer.
1313bd6f2fd5SStephen Boyd  *
131462f026f0SRob Herring  * Example::
1315bd6f2fd5SStephen Boyd  *
1316bd6f2fd5SStephen Boyd  *  phandle1: node1 {
1317bd6f2fd5SStephen Boyd  *  	#list-cells = <2>;
131862f026f0SRob Herring  *  };
1319bd6f2fd5SStephen Boyd  *
1320bd6f2fd5SStephen Boyd  *  phandle2: node2 {
1321bd6f2fd5SStephen Boyd  *  	#list-cells = <1>;
132262f026f0SRob Herring  *  };
1323bd6f2fd5SStephen Boyd  *
1324bd6f2fd5SStephen Boyd  *  phandle3: node3 {
1325bd6f2fd5SStephen Boyd  *  	#list-cells = <1>;
1326bd6f2fd5SStephen Boyd  *  	list-map = <0 &phandle2 3>,
1327bd6f2fd5SStephen Boyd  *  		   <1 &phandle2 2>,
1328bd6f2fd5SStephen Boyd  *  		   <2 &phandle1 5 1>;
1329bd6f2fd5SStephen Boyd  *  	list-map-mask = <0x3>;
1330bd6f2fd5SStephen Boyd  *  };
1331bd6f2fd5SStephen Boyd  *
1332bd6f2fd5SStephen Boyd  *  node4 {
1333bd6f2fd5SStephen Boyd  *  	list = <&phandle1 1 2 &phandle3 0>;
133462f026f0SRob Herring  *  };
1335bd6f2fd5SStephen Boyd  *
133662f026f0SRob Herring  * To get a device_node of the ``node2`` node you may call this:
1337bd6f2fd5SStephen Boyd  * of_parse_phandle_with_args(node4, "list", "list", 1, &args);
1338bd6f2fd5SStephen Boyd  */
of_parse_phandle_with_args_map(const struct device_node * np,const char * list_name,const char * stem_name,int index,struct of_phandle_args * out_args)1339bd6f2fd5SStephen Boyd int of_parse_phandle_with_args_map(const struct device_node *np,
1340bd6f2fd5SStephen Boyd 				   const char *list_name,
1341bd6f2fd5SStephen Boyd 				   const char *stem_name,
1342bd6f2fd5SStephen Boyd 				   int index, struct of_phandle_args *out_args)
1343bd6f2fd5SStephen Boyd {
1344bd6f2fd5SStephen Boyd 	char *cells_name, *map_name = NULL, *mask_name = NULL;
1345bd6f2fd5SStephen Boyd 	char *pass_name = NULL;
1346bd6f2fd5SStephen Boyd 	struct device_node *cur, *new = NULL;
1347bd6f2fd5SStephen Boyd 	const __be32 *map, *mask, *pass;
1348bd6f2fd5SStephen Boyd 	static const __be32 dummy_mask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 };
1349bd6f2fd5SStephen Boyd 	static const __be32 dummy_pass[] = { [0 ... MAX_PHANDLE_ARGS] = 0 };
1350bd6f2fd5SStephen Boyd 	__be32 initial_match_array[MAX_PHANDLE_ARGS];
1351bd6f2fd5SStephen Boyd 	const __be32 *match_array = initial_match_array;
1352bd6f2fd5SStephen Boyd 	int i, ret, map_len, match;
1353bd6f2fd5SStephen Boyd 	u32 list_size, new_size;
1354bd6f2fd5SStephen Boyd 
1355bd6f2fd5SStephen Boyd 	if (index < 0)
1356bd6f2fd5SStephen Boyd 		return -EINVAL;
1357bd6f2fd5SStephen Boyd 
1358bd6f2fd5SStephen Boyd 	cells_name = kasprintf(GFP_KERNEL, "#%s-cells", stem_name);
1359bd6f2fd5SStephen Boyd 	if (!cells_name)
1360bd6f2fd5SStephen Boyd 		return -ENOMEM;
1361bd6f2fd5SStephen Boyd 
1362bd6f2fd5SStephen Boyd 	ret = -ENOMEM;
1363bd6f2fd5SStephen Boyd 	map_name = kasprintf(GFP_KERNEL, "%s-map", stem_name);
1364bd6f2fd5SStephen Boyd 	if (!map_name)
1365bd6f2fd5SStephen Boyd 		goto free;
1366bd6f2fd5SStephen Boyd 
1367bd6f2fd5SStephen Boyd 	mask_name = kasprintf(GFP_KERNEL, "%s-map-mask", stem_name);
1368bd6f2fd5SStephen Boyd 	if (!mask_name)
1369bd6f2fd5SStephen Boyd 		goto free;
1370bd6f2fd5SStephen Boyd 
1371bd6f2fd5SStephen Boyd 	pass_name = kasprintf(GFP_KERNEL, "%s-map-pass-thru", stem_name);
1372bd6f2fd5SStephen Boyd 	if (!pass_name)
1373bd6f2fd5SStephen Boyd 		goto free;
1374bd6f2fd5SStephen Boyd 
1375e42ee610SUwe Kleine-König 	ret = __of_parse_phandle_with_args(np, list_name, cells_name, -1, index,
1376bd6f2fd5SStephen Boyd 					   out_args);
1377bd6f2fd5SStephen Boyd 	if (ret)
1378bd6f2fd5SStephen Boyd 		goto free;
1379bd6f2fd5SStephen Boyd 
1380bd6f2fd5SStephen Boyd 	/* Get the #<list>-cells property */
1381bd6f2fd5SStephen Boyd 	cur = out_args->np;
1382bd6f2fd5SStephen Boyd 	ret = of_property_read_u32(cur, cells_name, &list_size);
1383bd6f2fd5SStephen Boyd 	if (ret < 0)
1384bd6f2fd5SStephen Boyd 		goto put;
1385bd6f2fd5SStephen Boyd 
1386bd6f2fd5SStephen Boyd 	/* Precalculate the match array - this simplifies match loop */
1387bd6f2fd5SStephen Boyd 	for (i = 0; i < list_size; i++)
1388bd6f2fd5SStephen Boyd 		initial_match_array[i] = cpu_to_be32(out_args->args[i]);
1389bd6f2fd5SStephen Boyd 
1390bd6f2fd5SStephen Boyd 	ret = -EINVAL;
1391bd6f2fd5SStephen Boyd 	while (cur) {
1392bd6f2fd5SStephen Boyd 		/* Get the <list>-map property */
1393bd6f2fd5SStephen Boyd 		map = of_get_property(cur, map_name, &map_len);
1394bd6f2fd5SStephen Boyd 		if (!map) {
1395bd6f2fd5SStephen Boyd 			ret = 0;
1396bd6f2fd5SStephen Boyd 			goto free;
1397bd6f2fd5SStephen Boyd 		}
1398bd6f2fd5SStephen Boyd 		map_len /= sizeof(u32);
1399bd6f2fd5SStephen Boyd 
1400bd6f2fd5SStephen Boyd 		/* Get the <list>-map-mask property (optional) */
1401bd6f2fd5SStephen Boyd 		mask = of_get_property(cur, mask_name, NULL);
1402bd6f2fd5SStephen Boyd 		if (!mask)
1403bd6f2fd5SStephen Boyd 			mask = dummy_mask;
1404bd6f2fd5SStephen Boyd 		/* Iterate through <list>-map property */
1405bd6f2fd5SStephen Boyd 		match = 0;
1406bd6f2fd5SStephen Boyd 		while (map_len > (list_size + 1) && !match) {
1407bd6f2fd5SStephen Boyd 			/* Compare specifiers */
1408bd6f2fd5SStephen Boyd 			match = 1;
1409bd6f2fd5SStephen Boyd 			for (i = 0; i < list_size; i++, map_len--)
1410bd6f2fd5SStephen Boyd 				match &= !((match_array[i] ^ *map++) & mask[i]);
1411bd6f2fd5SStephen Boyd 
1412bd6f2fd5SStephen Boyd 			of_node_put(new);
1413bd6f2fd5SStephen Boyd 			new = of_find_node_by_phandle(be32_to_cpup(map));
1414bd6f2fd5SStephen Boyd 			map++;
1415bd6f2fd5SStephen Boyd 			map_len--;
1416bd6f2fd5SStephen Boyd 
1417bd6f2fd5SStephen Boyd 			/* Check if not found */
1418bd6f2fd5SStephen Boyd 			if (!new)
1419bd6f2fd5SStephen Boyd 				goto put;
1420bd6f2fd5SStephen Boyd 
1421bd6f2fd5SStephen Boyd 			if (!of_device_is_available(new))
1422bd6f2fd5SStephen Boyd 				match = 0;
1423bd6f2fd5SStephen Boyd 
1424bd6f2fd5SStephen Boyd 			ret = of_property_read_u32(new, cells_name, &new_size);
1425bd6f2fd5SStephen Boyd 			if (ret)
1426bd6f2fd5SStephen Boyd 				goto put;
1427bd6f2fd5SStephen Boyd 
1428bd6f2fd5SStephen Boyd 			/* Check for malformed properties */
1429bd6f2fd5SStephen Boyd 			if (WARN_ON(new_size > MAX_PHANDLE_ARGS))
1430bd6f2fd5SStephen Boyd 				goto put;
1431bd6f2fd5SStephen Boyd 			if (map_len < new_size)
1432bd6f2fd5SStephen Boyd 				goto put;
1433bd6f2fd5SStephen Boyd 
1434bd6f2fd5SStephen Boyd 			/* Move forward by new node's #<list>-cells amount */
1435bd6f2fd5SStephen Boyd 			map += new_size;
1436bd6f2fd5SStephen Boyd 			map_len -= new_size;
1437bd6f2fd5SStephen Boyd 		}
1438bd6f2fd5SStephen Boyd 		if (!match)
1439bd6f2fd5SStephen Boyd 			goto put;
1440bd6f2fd5SStephen Boyd 
1441bd6f2fd5SStephen Boyd 		/* Get the <list>-map-pass-thru property (optional) */
1442bd6f2fd5SStephen Boyd 		pass = of_get_property(cur, pass_name, NULL);
1443bd6f2fd5SStephen Boyd 		if (!pass)
1444bd6f2fd5SStephen Boyd 			pass = dummy_pass;
1445bd6f2fd5SStephen Boyd 
1446bd6f2fd5SStephen Boyd 		/*
1447bd6f2fd5SStephen Boyd 		 * Successfully parsed a <list>-map translation; copy new
1448bd6f2fd5SStephen Boyd 		 * specifier into the out_args structure, keeping the
1449bd6f2fd5SStephen Boyd 		 * bits specified in <list>-map-pass-thru.
1450bd6f2fd5SStephen Boyd 		 */
1451bd6f2fd5SStephen Boyd 		match_array = map - new_size;
1452bd6f2fd5SStephen Boyd 		for (i = 0; i < new_size; i++) {
1453bd6f2fd5SStephen Boyd 			__be32 val = *(map - new_size + i);
1454bd6f2fd5SStephen Boyd 
1455bd6f2fd5SStephen Boyd 			if (i < list_size) {
1456bd6f2fd5SStephen Boyd 				val &= ~pass[i];
1457bd6f2fd5SStephen Boyd 				val |= cpu_to_be32(out_args->args[i]) & pass[i];
1458bd6f2fd5SStephen Boyd 			}
1459bd6f2fd5SStephen Boyd 
1460bd6f2fd5SStephen Boyd 			out_args->args[i] = be32_to_cpu(val);
1461bd6f2fd5SStephen Boyd 		}
1462bd6f2fd5SStephen Boyd 		out_args->args_count = list_size = new_size;
1463bd6f2fd5SStephen Boyd 		/* Iterate again with new provider */
1464bd6f2fd5SStephen Boyd 		out_args->np = new;
1465bd6f2fd5SStephen Boyd 		of_node_put(cur);
1466bd6f2fd5SStephen Boyd 		cur = new;
1467*b64d09a4SChristian A. Ehrhardt 		new = NULL;
1468bd6f2fd5SStephen Boyd 	}
1469bd6f2fd5SStephen Boyd put:
1470bd6f2fd5SStephen Boyd 	of_node_put(cur);
1471bd6f2fd5SStephen Boyd 	of_node_put(new);
1472bd6f2fd5SStephen Boyd free:
1473bd6f2fd5SStephen Boyd 	kfree(mask_name);
1474bd6f2fd5SStephen Boyd 	kfree(map_name);
1475bd6f2fd5SStephen Boyd 	kfree(cells_name);
1476bd6f2fd5SStephen Boyd 	kfree(pass_name);
1477bd6f2fd5SStephen Boyd 
1478bd6f2fd5SStephen Boyd 	return ret;
1479bd6f2fd5SStephen Boyd }
1480bd6f2fd5SStephen Boyd EXPORT_SYMBOL(of_parse_phandle_with_args_map);
1481bd6f2fd5SStephen Boyd 
1482bd6f2fd5SStephen Boyd /**
1483bd69f73fSGrant Likely  * of_count_phandle_with_args() - Find the number of phandles references in a property
1484bd69f73fSGrant Likely  * @np:		pointer to a device tree node containing a list
1485bd69f73fSGrant Likely  * @list_name:	property name that contains a list
1486bd69f73fSGrant Likely  * @cells_name:	property name that specifies phandles' arguments count
1487bd69f73fSGrant Likely  *
14888c8239c2SRob Herring  * Return: The number of phandle + argument tuples within a property. It
1489bd69f73fSGrant Likely  * is a typical pattern to encode a list of phandle and variable
1490bd69f73fSGrant Likely  * arguments into a single property. The number of arguments is encoded
1491bd69f73fSGrant Likely  * by a property in the phandle-target node. For example, a gpios
1492bd69f73fSGrant Likely  * property would contain a list of GPIO specifies consisting of a
1493bd69f73fSGrant Likely  * phandle and 1 or more arguments. The number of arguments are
1494bd69f73fSGrant Likely  * determined by the #gpio-cells property in the node pointed to by the
1495bd69f73fSGrant Likely  * phandle.
1496bd69f73fSGrant Likely  */
of_count_phandle_with_args(const struct device_node * np,const char * list_name,const char * cells_name)1497bd69f73fSGrant Likely int of_count_phandle_with_args(const struct device_node *np, const char *list_name,
1498bd69f73fSGrant Likely 				const char *cells_name)
1499bd69f73fSGrant Likely {
15002021bd01SJoerg Roedel 	struct of_phandle_iterator it;
15012021bd01SJoerg Roedel 	int rc, cur_index = 0;
15022021bd01SJoerg Roedel 
150359e9fcf8SUwe Kleine-König 	/*
150459e9fcf8SUwe Kleine-König 	 * If cells_name is NULL we assume a cell count of 0. This makes
150559e9fcf8SUwe Kleine-König 	 * counting the phandles trivial as each 32bit word in the list is a
150659e9fcf8SUwe Kleine-König 	 * phandle and no arguments are to consider. So we don't iterate through
150759e9fcf8SUwe Kleine-König 	 * the list but just use the length to determine the phandle count.
150859e9fcf8SUwe Kleine-König 	 */
150959e9fcf8SUwe Kleine-König 	if (!cells_name) {
151059e9fcf8SUwe Kleine-König 		const __be32 *list;
151159e9fcf8SUwe Kleine-König 		int size;
151259e9fcf8SUwe Kleine-König 
151359e9fcf8SUwe Kleine-König 		list = of_get_property(np, list_name, &size);
151459e9fcf8SUwe Kleine-König 		if (!list)
151559e9fcf8SUwe Kleine-König 			return -ENOENT;
151659e9fcf8SUwe Kleine-König 
151759e9fcf8SUwe Kleine-König 		return size / sizeof(*list);
151859e9fcf8SUwe Kleine-König 	}
151959e9fcf8SUwe Kleine-König 
1520e42ee610SUwe Kleine-König 	rc = of_phandle_iterator_init(&it, np, list_name, cells_name, -1);
15212021bd01SJoerg Roedel 	if (rc)
15222021bd01SJoerg Roedel 		return rc;
15232021bd01SJoerg Roedel 
15242021bd01SJoerg Roedel 	while ((rc = of_phandle_iterator_next(&it)) == 0)
15252021bd01SJoerg Roedel 		cur_index += 1;
15262021bd01SJoerg Roedel 
15272021bd01SJoerg Roedel 	if (rc != -ENOENT)
15282021bd01SJoerg Roedel 		return rc;
15292021bd01SJoerg Roedel 
15302021bd01SJoerg Roedel 	return cur_index;
1531bd69f73fSGrant Likely }
1532bd69f73fSGrant Likely EXPORT_SYMBOL(of_count_phandle_with_args);
1533bd69f73fSGrant Likely 
__of_remove_property_from_list(struct property ** list,struct property * prop)15346701c2c7SRob Herring static struct property *__of_remove_property_from_list(struct property **list, struct property *prop)
15356701c2c7SRob Herring {
15366701c2c7SRob Herring 	struct property **next;
15376701c2c7SRob Herring 
15386701c2c7SRob Herring 	for (next = list; *next; next = &(*next)->next) {
15396701c2c7SRob Herring 		if (*next == prop) {
15406701c2c7SRob Herring 			*next = prop->next;
15416701c2c7SRob Herring 			prop->next = NULL;
15426701c2c7SRob Herring 			return prop;
15436701c2c7SRob Herring 		}
15446701c2c7SRob Herring 	}
15456701c2c7SRob Herring 	return NULL;
15466701c2c7SRob Herring }
15476701c2c7SRob Herring 
154802af11b0SGrant Likely /**
154962664f67SXiubo Li  * __of_add_property - Add a property to a node without lock operations
15503637d49eSLee Jones  * @np:		Caller's Device Node
155131e46db0SLee Jones  * @prop:	Property to add
155262664f67SXiubo Li  */
__of_add_property(struct device_node * np,struct property * prop)1553d8c50088SPantelis Antoniou int __of_add_property(struct device_node *np, struct property *prop)
155462664f67SXiubo Li {
1555fab610beSRob Herring 	int rc = 0;
1556fab610beSRob Herring 	unsigned long flags;
155762664f67SXiubo Li 	struct property **next;
155862664f67SXiubo Li 
1559fab610beSRob Herring 	raw_spin_lock_irqsave(&devtree_lock, flags);
1560fab610beSRob Herring 
15616701c2c7SRob Herring 	__of_remove_property_from_list(&np->deadprops, prop);
15626701c2c7SRob Herring 
156362664f67SXiubo Li 	prop->next = NULL;
156462664f67SXiubo Li 	next = &np->properties;
156562664f67SXiubo Li 	while (*next) {
1566fab610beSRob Herring 		if (strcmp(prop->name, (*next)->name) == 0) {
156762664f67SXiubo Li 			/* duplicate ! don't insert it */
1568fab610beSRob Herring 			rc = -EEXIST;
1569fab610beSRob Herring 			goto out_unlock;
1570fab610beSRob Herring 		}
157162664f67SXiubo Li 		next = &(*next)->next;
157262664f67SXiubo Li 	}
157362664f67SXiubo Li 	*next = prop;
157462664f67SXiubo Li 
1575fab610beSRob Herring out_unlock:
1576fab610beSRob Herring 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1577fab610beSRob Herring 	if (rc)
1578fab610beSRob Herring 		return rc;
1579fab610beSRob Herring 
1580fab610beSRob Herring 	__of_add_property_sysfs(np, prop);
158162664f67SXiubo Li 	return 0;
158262664f67SXiubo Li }
158362664f67SXiubo Li 
158462664f67SXiubo Li /**
158579d1c712SNathan Fontenot  * of_add_property - Add a property to a node
15863637d49eSLee Jones  * @np:		Caller's Device Node
158731e46db0SLee Jones  * @prop:	Property to add
158802af11b0SGrant Likely  */
of_add_property(struct device_node * np,struct property * prop)158979d1c712SNathan Fontenot int of_add_property(struct device_node *np, struct property *prop)
159002af11b0SGrant Likely {
15911cf3d8b3SNathan Fontenot 	int rc;
15921cf3d8b3SNathan Fontenot 
15938a2b22a2SGrant Likely 	mutex_lock(&of_mutex);
159462664f67SXiubo Li 	rc = __of_add_property(np, prop);
15958a2b22a2SGrant Likely 	mutex_unlock(&of_mutex);
15968a2b22a2SGrant Likely 
1597259092a3SGrant Likely 	if (!rc)
1598259092a3SGrant Likely 		of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL);
1599259092a3SGrant Likely 
160062664f67SXiubo Li 	return rc;
160102af11b0SGrant Likely }
1602fe794e39SWesley Cheng EXPORT_SYMBOL_GPL(of_add_property);
160302af11b0SGrant Likely 
__of_remove_property(struct device_node * np,struct property * prop)1604d8c50088SPantelis Antoniou int __of_remove_property(struct device_node *np, struct property *prop)
1605d8c50088SPantelis Antoniou {
1606fab610beSRob Herring 	unsigned long flags;
1607fab610beSRob Herring 	int rc = -ENODEV;
1608fab610beSRob Herring 
1609fab610beSRob Herring 	raw_spin_lock_irqsave(&devtree_lock, flags);
1610fab610beSRob Herring 
16116701c2c7SRob Herring 	if (__of_remove_property_from_list(&np->properties, prop)) {
16126701c2c7SRob Herring 		/* Found the property, add it to deadprops list */
1613d8c50088SPantelis Antoniou 		prop->next = np->deadprops;
1614d8c50088SPantelis Antoniou 		np->deadprops = prop;
1615fab610beSRob Herring 		rc = 0;
1616d8c50088SPantelis Antoniou 	}
1617d8c50088SPantelis Antoniou 
1618fab610beSRob Herring 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1619fab610beSRob Herring 	if (rc)
1620fab610beSRob Herring 		return rc;
1621fab610beSRob Herring 
1622fab610beSRob Herring 	__of_remove_property_sysfs(np, prop);
1623fab610beSRob Herring 	return 0;
16246701c2c7SRob Herring }
16256701c2c7SRob Herring 
162602af11b0SGrant Likely /**
162779d1c712SNathan Fontenot  * of_remove_property - Remove a property from a node.
16283637d49eSLee Jones  * @np:		Caller's Device Node
162931e46db0SLee Jones  * @prop:	Property to remove
163002af11b0SGrant Likely  *
163102af11b0SGrant Likely  * Note that we don't actually remove it, since we have given out
163202af11b0SGrant Likely  * who-knows-how-many pointers to the data using get-property.
163302af11b0SGrant Likely  * Instead we just move the property to the "dead properties"
163402af11b0SGrant Likely  * list, so it won't be found any more.
163502af11b0SGrant Likely  */
of_remove_property(struct device_node * np,struct property * prop)163679d1c712SNathan Fontenot int of_remove_property(struct device_node *np, struct property *prop)
163702af11b0SGrant Likely {
16381cf3d8b3SNathan Fontenot 	int rc;
16391cf3d8b3SNathan Fontenot 
1640201b3fe5SSuraj Jitindar Singh 	if (!prop)
1641201b3fe5SSuraj Jitindar Singh 		return -ENODEV;
1642201b3fe5SSuraj Jitindar Singh 
16438a2b22a2SGrant Likely 	mutex_lock(&of_mutex);
1644d8c50088SPantelis Antoniou 	rc = __of_remove_property(np, prop);
16458a2b22a2SGrant Likely 	mutex_unlock(&of_mutex);
16468a2b22a2SGrant Likely 
1647259092a3SGrant Likely 	if (!rc)
1648259092a3SGrant Likely 		of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL);
1649259092a3SGrant Likely 
1650d8c50088SPantelis Antoniou 	return rc;
165102af11b0SGrant Likely }
16520f7c5317SFlorian Fainelli EXPORT_SYMBOL_GPL(of_remove_property);
165302af11b0SGrant Likely 
__of_update_property(struct device_node * np,struct property * newprop,struct property ** oldpropp)1654d8c50088SPantelis Antoniou int __of_update_property(struct device_node *np, struct property *newprop,
1655d8c50088SPantelis Antoniou 		struct property **oldpropp)
1656d8c50088SPantelis Antoniou {
1657d8c50088SPantelis Antoniou 	struct property **next, *oldprop;
1658fab610beSRob Herring 	unsigned long flags;
1659fab610beSRob Herring 
1660fab610beSRob Herring 	raw_spin_lock_irqsave(&devtree_lock, flags);
1661d8c50088SPantelis Antoniou 
16626701c2c7SRob Herring 	__of_remove_property_from_list(&np->deadprops, newprop);
16636701c2c7SRob Herring 
1664d8c50088SPantelis Antoniou 	for (next = &np->properties; *next; next = &(*next)->next) {
1665d8c50088SPantelis Antoniou 		if (of_prop_cmp((*next)->name, newprop->name) == 0)
1666d8c50088SPantelis Antoniou 			break;
1667d8c50088SPantelis Antoniou 	}
1668d8c50088SPantelis Antoniou 	*oldpropp = oldprop = *next;
1669d8c50088SPantelis Antoniou 
1670d8c50088SPantelis Antoniou 	if (oldprop) {
1671d8c50088SPantelis Antoniou 		/* replace the node */
1672d8c50088SPantelis Antoniou 		newprop->next = oldprop->next;
1673d8c50088SPantelis Antoniou 		*next = newprop;
1674d8c50088SPantelis Antoniou 		oldprop->next = np->deadprops;
1675d8c50088SPantelis Antoniou 		np->deadprops = oldprop;
1676d8c50088SPantelis Antoniou 	} else {
1677d8c50088SPantelis Antoniou 		/* new node */
1678d8c50088SPantelis Antoniou 		newprop->next = NULL;
1679d8c50088SPantelis Antoniou 		*next = newprop;
1680d8c50088SPantelis Antoniou 	}
1681d8c50088SPantelis Antoniou 
1682fab610beSRob Herring 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1683fab610beSRob Herring 
1684fab610beSRob Herring 	__of_update_property_sysfs(np, newprop, oldprop);
1685fab610beSRob Herring 
1686d8c50088SPantelis Antoniou 	return 0;
1687d8c50088SPantelis Antoniou }
1688d8c50088SPantelis Antoniou 
168902af11b0SGrant Likely /*
169079d1c712SNathan Fontenot  * of_update_property - Update a property in a node, if the property does
1691475d0094SDong Aisheng  * not exist, add it.
169202af11b0SGrant Likely  *
169302af11b0SGrant Likely  * Note that we don't actually remove it, since we have given out
169402af11b0SGrant Likely  * who-knows-how-many pointers to the data using get-property.
169502af11b0SGrant Likely  * Instead we just move the property to the "dead properties" list,
169602af11b0SGrant Likely  * and add the new property to the property list
169702af11b0SGrant Likely  */
of_update_property(struct device_node * np,struct property * newprop)169879d1c712SNathan Fontenot int of_update_property(struct device_node *np, struct property *newprop)
169902af11b0SGrant Likely {
1700d8c50088SPantelis Antoniou 	struct property *oldprop;
1701947fdaadSXiubo Li 	int rc;
17021cf3d8b3SNathan Fontenot 
1703475d0094SDong Aisheng 	if (!newprop->name)
1704475d0094SDong Aisheng 		return -EINVAL;
1705475d0094SDong Aisheng 
17068a2b22a2SGrant Likely 	mutex_lock(&of_mutex);
1707d8c50088SPantelis Antoniou 	rc = __of_update_property(np, newprop, &oldprop);
17088a2b22a2SGrant Likely 	mutex_unlock(&of_mutex);
17091cf3d8b3SNathan Fontenot 
1710259092a3SGrant Likely 	if (!rc)
1711259092a3SGrant Likely 		of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop);
1712fcdeb7feSGrant Likely 
17131cf3d8b3SNathan Fontenot 	return rc;
1714e81b3295SNathan Fontenot }
1715e81b3295SNathan Fontenot 
of_alias_add(struct alias_prop * ap,struct device_node * np,int id,const char * stem,int stem_len)1716611cad72SShawn Guo static void of_alias_add(struct alias_prop *ap, struct device_node *np,
1717611cad72SShawn Guo 			 int id, const char *stem, int stem_len)
1718611cad72SShawn Guo {
1719611cad72SShawn Guo 	ap->np = np;
1720611cad72SShawn Guo 	ap->id = id;
1721a98bf9dfSXu Panda 	strscpy(ap->stem, stem, stem_len + 1);
1722611cad72SShawn Guo 	list_add_tail(&ap->link, &aliases_lookup);
17230d638a07SRob Herring 	pr_debug("adding DT alias:%s: stem=%s id=%i node=%pOF\n",
17240d638a07SRob Herring 		 ap->alias, ap->stem, ap->id, np);
1725611cad72SShawn Guo }
1726611cad72SShawn Guo 
1727611cad72SShawn Guo /**
17281821dda4SGeert Uytterhoeven  * of_alias_scan - Scan all properties of the 'aliases' node
172962f026f0SRob Herring  * @dt_alloc:	An allocator that provides a virtual address to memory
173062f026f0SRob Herring  *		for storing the resulting tree
1731611cad72SShawn Guo  *
17321821dda4SGeert Uytterhoeven  * The function scans all the properties of the 'aliases' node and populates
17331821dda4SGeert Uytterhoeven  * the global lookup table with the properties.  It returns the
17341821dda4SGeert Uytterhoeven  * number of alias properties found, or an error code in case of failure.
1735611cad72SShawn Guo  */
of_alias_scan(void * (* dt_alloc)(u64 size,u64 align))1736611cad72SShawn Guo void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
1737611cad72SShawn Guo {
1738611cad72SShawn Guo 	struct property *pp;
1739611cad72SShawn Guo 
17407dbe5849SLaurentiu Tudor 	of_aliases = of_find_node_by_path("/aliases");
1741611cad72SShawn Guo 	of_chosen = of_find_node_by_path("/chosen");
1742611cad72SShawn Guo 	if (of_chosen == NULL)
1743611cad72SShawn Guo 		of_chosen = of_find_node_by_path("/chosen@0");
17445c19e952SSascha Hauer 
17455c19e952SSascha Hauer 	if (of_chosen) {
1746a752ee56SGrant Likely 		/* linux,stdout-path and /aliases/stdout are for legacy compatibility */
1747b0d9d92fSSergei Shtylyov 		const char *name = NULL;
1748b0d9d92fSSergei Shtylyov 
1749b0d9d92fSSergei Shtylyov 		if (of_property_read_string(of_chosen, "stdout-path", &name))
1750b0d9d92fSSergei Shtylyov 			of_property_read_string(of_chosen, "linux,stdout-path",
1751b0d9d92fSSergei Shtylyov 						&name);
1752a752ee56SGrant Likely 		if (IS_ENABLED(CONFIG_PPC) && !name)
1753b0d9d92fSSergei Shtylyov 			of_property_read_string(of_aliases, "stdout", &name);
1754f64255b5SPeter Hurley 		if (name)
17557914a7c5SLeif Lindholm 			of_stdout = of_find_node_opts_by_path(name, &of_stdout_options);
1756a244ec36SSaravana Kannan 		if (of_stdout)
1757a244ec36SSaravana Kannan 			of_stdout->fwnode.flags |= FWNODE_FLAG_BEST_EFFORT;
17585c19e952SSascha Hauer 	}
17595c19e952SSascha Hauer 
1760611cad72SShawn Guo 	if (!of_aliases)
1761611cad72SShawn Guo 		return;
1762611cad72SShawn Guo 
17638af0da93SDong Aisheng 	for_each_property_of_node(of_aliases, pp) {
1764611cad72SShawn Guo 		const char *start = pp->name;
1765611cad72SShawn Guo 		const char *end = start + strlen(start);
1766611cad72SShawn Guo 		struct device_node *np;
1767611cad72SShawn Guo 		struct alias_prop *ap;
1768611cad72SShawn Guo 		int id, len;
1769611cad72SShawn Guo 
1770611cad72SShawn Guo 		/* Skip those we do not want to proceed */
1771611cad72SShawn Guo 		if (!strcmp(pp->name, "name") ||
1772611cad72SShawn Guo 		    !strcmp(pp->name, "phandle") ||
1773611cad72SShawn Guo 		    !strcmp(pp->name, "linux,phandle"))
1774611cad72SShawn Guo 			continue;
1775611cad72SShawn Guo 
1776611cad72SShawn Guo 		np = of_find_node_by_path(pp->value);
1777611cad72SShawn Guo 		if (!np)
1778611cad72SShawn Guo 			continue;
1779611cad72SShawn Guo 
1780611cad72SShawn Guo 		/* walk the alias backwards to extract the id and work out
1781611cad72SShawn Guo 		 * the 'stem' string */
1782611cad72SShawn Guo 		while (isdigit(*(end-1)) && end > start)
1783611cad72SShawn Guo 			end--;
1784611cad72SShawn Guo 		len = end - start;
1785611cad72SShawn Guo 
1786611cad72SShawn Guo 		if (kstrtoint(end, 10, &id) < 0)
1787611cad72SShawn Guo 			continue;
1788611cad72SShawn Guo 
1789611cad72SShawn Guo 		/* Allocate an alias_prop with enough space for the stem */
1790de96ec2aSPaul Burton 		ap = dt_alloc(sizeof(*ap) + len + 1, __alignof__(*ap));
1791611cad72SShawn Guo 		if (!ap)
1792611cad72SShawn Guo 			continue;
17930640332eSGrant Likely 		memset(ap, 0, sizeof(*ap) + len + 1);
1794611cad72SShawn Guo 		ap->alias = start;
1795611cad72SShawn Guo 		of_alias_add(ap, np, id, start, len);
1796611cad72SShawn Guo 	}
1797611cad72SShawn Guo }
1798611cad72SShawn Guo 
1799611cad72SShawn Guo /**
1800611cad72SShawn Guo  * of_alias_get_id - Get alias id for the given device_node
1801611cad72SShawn Guo  * @np:		Pointer to the given device_node
1802611cad72SShawn Guo  * @stem:	Alias stem of the given device_node
1803611cad72SShawn Guo  *
18045a53a07fSGeert Uytterhoeven  * The function travels the lookup table to get the alias id for the given
18058c8239c2SRob Herring  * device_node and alias stem.
18068c8239c2SRob Herring  *
18078c8239c2SRob Herring  * Return: The alias id if found.
1808611cad72SShawn Guo  */
of_alias_get_id(struct device_node * np,const char * stem)1809611cad72SShawn Guo int of_alias_get_id(struct device_node *np, const char *stem)
1810611cad72SShawn Guo {
1811611cad72SShawn Guo 	struct alias_prop *app;
1812611cad72SShawn Guo 	int id = -ENODEV;
1813611cad72SShawn Guo 
1814c05aba2bSPantelis Antoniou 	mutex_lock(&of_mutex);
1815611cad72SShawn Guo 	list_for_each_entry(app, &aliases_lookup, link) {
1816611cad72SShawn Guo 		if (strcmp(app->stem, stem) != 0)
1817611cad72SShawn Guo 			continue;
1818611cad72SShawn Guo 
1819611cad72SShawn Guo 		if (np == app->np) {
1820611cad72SShawn Guo 			id = app->id;
1821611cad72SShawn Guo 			break;
1822611cad72SShawn Guo 		}
1823611cad72SShawn Guo 	}
1824c05aba2bSPantelis Antoniou 	mutex_unlock(&of_mutex);
1825611cad72SShawn Guo 
1826611cad72SShawn Guo 	return id;
1827611cad72SShawn Guo }
1828611cad72SShawn Guo EXPORT_SYMBOL_GPL(of_alias_get_id);
1829c541adc6SStephen Warren 
1830351d224fSWolfram Sang /**
1831351d224fSWolfram Sang  * of_alias_get_highest_id - Get highest alias id for the given stem
1832351d224fSWolfram Sang  * @stem:	Alias stem to be examined
1833351d224fSWolfram Sang  *
1834351d224fSWolfram Sang  * The function travels the lookup table to get the highest alias id for the
1835351d224fSWolfram Sang  * given alias stem.  It returns the alias id if found.
1836351d224fSWolfram Sang  */
of_alias_get_highest_id(const char * stem)1837351d224fSWolfram Sang int of_alias_get_highest_id(const char *stem)
1838351d224fSWolfram Sang {
1839351d224fSWolfram Sang 	struct alias_prop *app;
1840351d224fSWolfram Sang 	int id = -ENODEV;
1841351d224fSWolfram Sang 
1842351d224fSWolfram Sang 	mutex_lock(&of_mutex);
1843351d224fSWolfram Sang 	list_for_each_entry(app, &aliases_lookup, link) {
1844351d224fSWolfram Sang 		if (strcmp(app->stem, stem) != 0)
1845351d224fSWolfram Sang 			continue;
1846351d224fSWolfram Sang 
1847351d224fSWolfram Sang 		if (app->id > id)
1848351d224fSWolfram Sang 			id = app->id;
1849351d224fSWolfram Sang 	}
1850351d224fSWolfram Sang 	mutex_unlock(&of_mutex);
1851351d224fSWolfram Sang 
1852351d224fSWolfram Sang 	return id;
1853351d224fSWolfram Sang }
1854351d224fSWolfram Sang EXPORT_SYMBOL_GPL(of_alias_get_highest_id);
1855351d224fSWolfram Sang 
18565c19e952SSascha Hauer /**
18573482f2c5SGrant Likely  * of_console_check() - Test and setup console for DT setup
18583637d49eSLee Jones  * @dn: Pointer to device node
18593637d49eSLee Jones  * @name: Name to use for preferred console without index. ex. "ttyS"
18603637d49eSLee Jones  * @index: Index to use for preferred console.
18615c19e952SSascha Hauer  *
18623482f2c5SGrant Likely  * Check if the given device node matches the stdout-path property in the
18638c8239c2SRob Herring  * /chosen node. If it does then register it as the preferred console.
18648c8239c2SRob Herring  *
18658c8239c2SRob Herring  * Return: TRUE if console successfully setup. Otherwise return FALSE.
18665c19e952SSascha Hauer  */
of_console_check(struct device_node * dn,char * name,int index)18673482f2c5SGrant Likely bool of_console_check(struct device_node *dn, char *name, int index)
18685c19e952SSascha Hauer {
18693482f2c5SGrant Likely 	if (!dn || dn != of_stdout || console_set_on_cmdline)
18705c19e952SSascha Hauer 		return false;
1871db179e0dSSergey Senozhatsky 
1872db179e0dSSergey Senozhatsky 	/*
1873db179e0dSSergey Senozhatsky 	 * XXX: cast `options' to char pointer to suppress complication
1874db179e0dSSergey Senozhatsky 	 * warnings: printk, UART and console drivers expect char pointer.
1875db179e0dSSergey Senozhatsky 	 */
1876db179e0dSSergey Senozhatsky 	return !add_preferred_console(name, index, (char *)of_stdout_options);
18775c19e952SSascha Hauer }
18783482f2c5SGrant Likely EXPORT_SYMBOL_GPL(of_console_check);
1879a3e31b45SSudeep KarkadaNagesha 
1880a3e31b45SSudeep KarkadaNagesha /**
1881a3e31b45SSudeep KarkadaNagesha  * of_find_next_cache_node - Find a node's subsidiary cache
1882a3e31b45SSudeep KarkadaNagesha  * @np:	node of type "cpu" or "cache"
1883a3e31b45SSudeep KarkadaNagesha  *
188462f026f0SRob Herring  * Return: A node pointer with refcount incremented, use
1885a3e31b45SSudeep KarkadaNagesha  * of_node_put() on it when done.  Caller should hold a reference
1886a3e31b45SSudeep KarkadaNagesha  * to np.
1887a3e31b45SSudeep KarkadaNagesha  */
of_find_next_cache_node(const struct device_node * np)1888a3e31b45SSudeep KarkadaNagesha struct device_node *of_find_next_cache_node(const struct device_node *np)
1889a3e31b45SSudeep KarkadaNagesha {
189091d96749SRob Herring 	struct device_node *child, *cache_node;
1891a3e31b45SSudeep KarkadaNagesha 
189291d96749SRob Herring 	cache_node = of_parse_phandle(np, "l2-cache", 0);
189391d96749SRob Herring 	if (!cache_node)
189491d96749SRob Herring 		cache_node = of_parse_phandle(np, "next-level-cache", 0);
1895a3e31b45SSudeep KarkadaNagesha 
189691d96749SRob Herring 	if (cache_node)
189791d96749SRob Herring 		return cache_node;
1898a3e31b45SSudeep KarkadaNagesha 
1899a3e31b45SSudeep KarkadaNagesha 	/* OF on pmac has nodes instead of properties named "l2-cache"
1900a3e31b45SSudeep KarkadaNagesha 	 * beneath CPU nodes.
1901a3e31b45SSudeep KarkadaNagesha 	 */
1902e8b1dee2SRob Herring 	if (IS_ENABLED(CONFIG_PPC_PMAC) && of_node_is_type(np, "cpu"))
1903a3e31b45SSudeep KarkadaNagesha 		for_each_child_of_node(np, child)
1904e8b1dee2SRob Herring 			if (of_node_is_type(child, "cache"))
1905a3e31b45SSudeep KarkadaNagesha 				return child;
1906a3e31b45SSudeep KarkadaNagesha 
1907a3e31b45SSudeep KarkadaNagesha 	return NULL;
1908a3e31b45SSudeep KarkadaNagesha }
1909fd9fdb78SPhilipp Zabel 
1910fd9fdb78SPhilipp Zabel /**
19115fa23530SSudeep Holla  * of_find_last_cache_level - Find the level at which the last cache is
19125fa23530SSudeep Holla  * 		present for the given logical cpu
19135fa23530SSudeep Holla  *
19145fa23530SSudeep Holla  * @cpu: cpu number(logical index) for which the last cache level is needed
19155fa23530SSudeep Holla  *
19163a5230a8SDeming Wang  * Return: The level at which the last cache is present. It is exactly
19175fa23530SSudeep Holla  * same as  the total number of cache levels for the given logical cpu.
19185fa23530SSudeep Holla  */
of_find_last_cache_level(unsigned int cpu)19195fa23530SSudeep Holla int of_find_last_cache_level(unsigned int cpu)
19205fa23530SSudeep Holla {
19215fa23530SSudeep Holla 	u32 cache_level = 0;
19225fa23530SSudeep Holla 	struct device_node *prev = NULL, *np = of_cpu_device_node_get(cpu);
19235fa23530SSudeep Holla 
19245fa23530SSudeep Holla 	while (np) {
19257a7f5857SPierre Gondois 		of_node_put(prev);
19265fa23530SSudeep Holla 		prev = np;
19275fa23530SSudeep Holla 		np = of_find_next_cache_node(np);
19285fa23530SSudeep Holla 	}
19295fa23530SSudeep Holla 
19305fa23530SSudeep Holla 	of_property_read_u32(prev, "cache-level", &cache_level);
19317a7f5857SPierre Gondois 	of_node_put(prev);
19325fa23530SSudeep Holla 
19335fa23530SSudeep Holla 	return cache_level;
19345fa23530SSudeep Holla }
19352a6db719SNipun Gupta 
19362a6db719SNipun Gupta /**
1937746a71d0SLorenzo Pieralisi  * of_map_id - Translate an ID through a downstream mapping.
19382a6db719SNipun Gupta  * @np: root complex device node.
1939746a71d0SLorenzo Pieralisi  * @id: device ID to map.
19402a6db719SNipun Gupta  * @map_name: property name of the map to use.
19412a6db719SNipun Gupta  * @map_mask_name: optional property name of the mask to use.
19422a6db719SNipun Gupta  * @target: optional pointer to a target device node.
19432a6db719SNipun Gupta  * @id_out: optional pointer to receive the translated ID.
19442a6db719SNipun Gupta  *
1945746a71d0SLorenzo Pieralisi  * Given a device ID, look up the appropriate implementation-defined
19462a6db719SNipun Gupta  * platform ID and/or the target device which receives transactions on that
19472a6db719SNipun Gupta  * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or
19482a6db719SNipun Gupta  * @id_out may be NULL if only the other is required. If @target points to
19492a6db719SNipun Gupta  * a non-NULL device node pointer, only entries targeting that node will be
19502a6db719SNipun Gupta  * matched; if it points to a NULL value, it will receive the device node of
19512a6db719SNipun Gupta  * the first matching target phandle, with a reference held.
19522a6db719SNipun Gupta  *
19532a6db719SNipun Gupta  * Return: 0 on success or a standard error code on failure.
19542a6db719SNipun Gupta  */
of_map_id(struct device_node * np,u32 id,const char * map_name,const char * map_mask_name,struct device_node ** target,u32 * id_out)1955746a71d0SLorenzo Pieralisi int of_map_id(struct device_node *np, u32 id,
19562a6db719SNipun Gupta 	       const char *map_name, const char *map_mask_name,
19572a6db719SNipun Gupta 	       struct device_node **target, u32 *id_out)
19582a6db719SNipun Gupta {
1959746a71d0SLorenzo Pieralisi 	u32 map_mask, masked_id;
19602a6db719SNipun Gupta 	int map_len;
19612a6db719SNipun Gupta 	const __be32 *map = NULL;
19622a6db719SNipun Gupta 
19632a6db719SNipun Gupta 	if (!np || !map_name || (!target && !id_out))
19642a6db719SNipun Gupta 		return -EINVAL;
19652a6db719SNipun Gupta 
19662a6db719SNipun Gupta 	map = of_get_property(np, map_name, &map_len);
19672a6db719SNipun Gupta 	if (!map) {
19682a6db719SNipun Gupta 		if (target)
19692a6db719SNipun Gupta 			return -ENODEV;
19702a6db719SNipun Gupta 		/* Otherwise, no map implies no translation */
1971746a71d0SLorenzo Pieralisi 		*id_out = id;
19722a6db719SNipun Gupta 		return 0;
19732a6db719SNipun Gupta 	}
19742a6db719SNipun Gupta 
19752a6db719SNipun Gupta 	if (!map_len || map_len % (4 * sizeof(*map))) {
19762a6db719SNipun Gupta 		pr_err("%pOF: Error: Bad %s length: %d\n", np,
19772a6db719SNipun Gupta 			map_name, map_len);
19782a6db719SNipun Gupta 		return -EINVAL;
19792a6db719SNipun Gupta 	}
19802a6db719SNipun Gupta 
19812a6db719SNipun Gupta 	/* The default is to select all bits. */
19822a6db719SNipun Gupta 	map_mask = 0xffffffff;
19832a6db719SNipun Gupta 
19842a6db719SNipun Gupta 	/*
19852a6db719SNipun Gupta 	 * Can be overridden by "{iommu,msi}-map-mask" property.
19862a6db719SNipun Gupta 	 * If of_property_read_u32() fails, the default is used.
19872a6db719SNipun Gupta 	 */
19882a6db719SNipun Gupta 	if (map_mask_name)
19892a6db719SNipun Gupta 		of_property_read_u32(np, map_mask_name, &map_mask);
19902a6db719SNipun Gupta 
1991746a71d0SLorenzo Pieralisi 	masked_id = map_mask & id;
19922a6db719SNipun Gupta 	for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) {
19932a6db719SNipun Gupta 		struct device_node *phandle_node;
1994746a71d0SLorenzo Pieralisi 		u32 id_base = be32_to_cpup(map + 0);
19952a6db719SNipun Gupta 		u32 phandle = be32_to_cpup(map + 1);
19962a6db719SNipun Gupta 		u32 out_base = be32_to_cpup(map + 2);
1997746a71d0SLorenzo Pieralisi 		u32 id_len = be32_to_cpup(map + 3);
19982a6db719SNipun Gupta 
1999746a71d0SLorenzo Pieralisi 		if (id_base & ~map_mask) {
2000746a71d0SLorenzo Pieralisi 			pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores id-base (0x%x)\n",
20012a6db719SNipun Gupta 				np, map_name, map_name,
2002746a71d0SLorenzo Pieralisi 				map_mask, id_base);
20032a6db719SNipun Gupta 			return -EFAULT;
20042a6db719SNipun Gupta 		}
20052a6db719SNipun Gupta 
2006746a71d0SLorenzo Pieralisi 		if (masked_id < id_base || masked_id >= id_base + id_len)
20072a6db719SNipun Gupta 			continue;
20082a6db719SNipun Gupta 
20092a6db719SNipun Gupta 		phandle_node = of_find_node_by_phandle(phandle);
20102a6db719SNipun Gupta 		if (!phandle_node)
20112a6db719SNipun Gupta 			return -ENODEV;
20122a6db719SNipun Gupta 
20132a6db719SNipun Gupta 		if (target) {
20142a6db719SNipun Gupta 			if (*target)
20152a6db719SNipun Gupta 				of_node_put(phandle_node);
20162a6db719SNipun Gupta 			else
20172a6db719SNipun Gupta 				*target = phandle_node;
20182a6db719SNipun Gupta 
20192a6db719SNipun Gupta 			if (*target != phandle_node)
20202a6db719SNipun Gupta 				continue;
20212a6db719SNipun Gupta 		}
20222a6db719SNipun Gupta 
20232a6db719SNipun Gupta 		if (id_out)
2024746a71d0SLorenzo Pieralisi 			*id_out = masked_id - id_base + out_base;
20252a6db719SNipun Gupta 
2026746a71d0SLorenzo Pieralisi 		pr_debug("%pOF: %s, using mask %08x, id-base: %08x, out-base: %08x, length: %08x, id: %08x -> %08x\n",
2027746a71d0SLorenzo Pieralisi 			np, map_name, map_mask, id_base, out_base,
2028746a71d0SLorenzo Pieralisi 			id_len, id, masked_id - id_base + out_base);
20292a6db719SNipun Gupta 		return 0;
20302a6db719SNipun Gupta 	}
20312a6db719SNipun Gupta 
2032746a71d0SLorenzo Pieralisi 	pr_info("%pOF: no %s translation for id 0x%x on %pOF\n", np, map_name,
2033746a71d0SLorenzo Pieralisi 		id, target && *target ? *target : NULL);
2034fb709b5eSJean-Philippe Brucker 
2035fb709b5eSJean-Philippe Brucker 	/* Bypasses translation */
2036fb709b5eSJean-Philippe Brucker 	if (id_out)
2037746a71d0SLorenzo Pieralisi 		*id_out = id;
2038fb709b5eSJean-Philippe Brucker 	return 0;
20392a6db719SNipun Gupta }
2040746a71d0SLorenzo Pieralisi EXPORT_SYMBOL_GPL(of_map_id);
2041