xref: /openbmc/linux/drivers/of/base.c (revision 8832963d)
197e873e5SStephen Rothwell /*
297e873e5SStephen Rothwell  * Procedures for creating, accessing and interpreting the device tree.
397e873e5SStephen Rothwell  *
497e873e5SStephen Rothwell  * Paul Mackerras	August 1996.
597e873e5SStephen Rothwell  * Copyright (C) 1996-2005 Paul Mackerras.
697e873e5SStephen Rothwell  *
797e873e5SStephen Rothwell  *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
897e873e5SStephen Rothwell  *    {engebret|bergner}@us.ibm.com
997e873e5SStephen Rothwell  *
1097e873e5SStephen Rothwell  *  Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net
1197e873e5SStephen Rothwell  *
12e91edcf5SGrant Likely  *  Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and
13e91edcf5SGrant Likely  *  Grant Likely.
1497e873e5SStephen Rothwell  *
1597e873e5SStephen Rothwell  *      This program is free software; you can redistribute it and/or
1697e873e5SStephen Rothwell  *      modify it under the terms of the GNU General Public License
1797e873e5SStephen Rothwell  *      as published by the Free Software Foundation; either version
1897e873e5SStephen Rothwell  *      2 of the License, or (at your option) any later version.
1997e873e5SStephen Rothwell  */
20606ad42aSRob Herring 
21606ad42aSRob Herring #define pr_fmt(fmt)	"OF: " fmt
22606ad42aSRob Herring 
233482f2c5SGrant Likely #include <linux/console.h>
24611cad72SShawn Guo #include <linux/ctype.h>
25183912d3SSudeep KarkadaNagesha #include <linux/cpu.h>
2697e873e5SStephen Rothwell #include <linux/module.h>
2797e873e5SStephen Rothwell #include <linux/of.h>
285fa23530SSudeep Holla #include <linux/of_device.h>
29fd9fdb78SPhilipp Zabel #include <linux/of_graph.h>
30581b605aSStephen Rothwell #include <linux/spinlock.h>
315a0e3ad6STejun Heo #include <linux/slab.h>
3275b57ecfSGrant Likely #include <linux/string.h>
33a9f2f63aSJeremy Kerr #include <linux/proc_fs.h>
34581b605aSStephen Rothwell 
35ced4eec9SStepan Moskovchenko #include "of_private.h"
36611cad72SShawn Guo 
37ced4eec9SStepan Moskovchenko LIST_HEAD(aliases_lookup);
38611cad72SShawn Guo 
395063e25aSGrant Likely struct device_node *of_root;
405063e25aSGrant Likely EXPORT_SYMBOL(of_root);
41fc0bdae4SGrant Likely struct device_node *of_chosen;
42611cad72SShawn Guo struct device_node *of_aliases;
43a752ee56SGrant Likely struct device_node *of_stdout;
447914a7c5SLeif Lindholm static const char *of_stdout_options;
45611cad72SShawn Guo 
468a2b22a2SGrant Likely struct kset *of_kset;
4775b57ecfSGrant Likely 
4875b57ecfSGrant Likely /*
498a2b22a2SGrant Likely  * Used to protect the of_aliases, to hold off addition of nodes to sysfs.
508a2b22a2SGrant Likely  * This mutex must be held whenever modifications are being made to the
518a2b22a2SGrant Likely  * device tree. The of_{attach,detach}_node() and
528a2b22a2SGrant Likely  * of_{add,remove,update}_property() helpers make sure this happens.
5375b57ecfSGrant Likely  */
54c05aba2bSPantelis Antoniou DEFINE_MUTEX(of_mutex);
551ef4d424SStephen Rothwell 
565063e25aSGrant Likely /* use when traversing tree through the child, sibling,
57581b605aSStephen Rothwell  * or parent members of struct device_node.
58581b605aSStephen Rothwell  */
59d6d3c4e6SThomas Gleixner DEFINE_RAW_SPINLOCK(devtree_lock);
6097e873e5SStephen Rothwell 
6197e873e5SStephen Rothwell int of_n_addr_cells(struct device_node *np)
6297e873e5SStephen Rothwell {
638832963dSSergei Shtylyov 	u32 cells;
6497e873e5SStephen Rothwell 
6597e873e5SStephen Rothwell 	do {
6697e873e5SStephen Rothwell 		if (np->parent)
6797e873e5SStephen Rothwell 			np = np->parent;
688832963dSSergei Shtylyov 		if (!of_property_read_u32(np, "#address-cells", &cells))
698832963dSSergei Shtylyov 			return cells;
7097e873e5SStephen Rothwell 	} while (np->parent);
7197e873e5SStephen Rothwell 	/* No #address-cells property for the root node */
7297e873e5SStephen Rothwell 	return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
7397e873e5SStephen Rothwell }
7497e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_addr_cells);
7597e873e5SStephen Rothwell 
7697e873e5SStephen Rothwell int of_n_size_cells(struct device_node *np)
7797e873e5SStephen Rothwell {
788832963dSSergei Shtylyov 	u32 cells;
7997e873e5SStephen Rothwell 
8097e873e5SStephen Rothwell 	do {
8197e873e5SStephen Rothwell 		if (np->parent)
8297e873e5SStephen Rothwell 			np = np->parent;
838832963dSSergei Shtylyov 		if (!of_property_read_u32(np, "#size-cells", &cells))
848832963dSSergei Shtylyov 			return cells;
8597e873e5SStephen Rothwell 	} while (np->parent);
8697e873e5SStephen Rothwell 	/* No #size-cells property for the root node */
8797e873e5SStephen Rothwell 	return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
8897e873e5SStephen Rothwell }
8997e873e5SStephen Rothwell EXPORT_SYMBOL(of_n_size_cells);
9097e873e5SStephen Rothwell 
910c3f061cSRob Herring #ifdef CONFIG_NUMA
920c3f061cSRob Herring int __weak of_node_to_nid(struct device_node *np)
930c3f061cSRob Herring {
94c8fff7bcSKonstantin Khlebnikov 	return NUMA_NO_NODE;
950c3f061cSRob Herring }
960c3f061cSRob Herring #endif
970c3f061cSRob Herring 
986afc0dc3SGrant Likely #ifndef CONFIG_OF_DYNAMIC
9975b57ecfSGrant Likely static void of_node_release(struct kobject *kobj)
10075b57ecfSGrant Likely {
10175b57ecfSGrant Likely 	/* Without CONFIG_OF_DYNAMIC, no nodes gets freed */
10275b57ecfSGrant Likely }
1030f22dd39SGrant Likely #endif /* CONFIG_OF_DYNAMIC */
104923f7e30SGrant Likely 
10575b57ecfSGrant Likely struct kobj_type of_node_ktype = {
10675b57ecfSGrant Likely 	.release = of_node_release,
10775b57ecfSGrant Likely };
10875b57ecfSGrant Likely 
10975b57ecfSGrant Likely static ssize_t of_node_property_read(struct file *filp, struct kobject *kobj,
11075b57ecfSGrant Likely 				struct bin_attribute *bin_attr, char *buf,
11175b57ecfSGrant Likely 				loff_t offset, size_t count)
11275b57ecfSGrant Likely {
11375b57ecfSGrant Likely 	struct property *pp = container_of(bin_attr, struct property, attr);
11475b57ecfSGrant Likely 	return memory_read_from_buffer(buf, count, &offset, pp->value, pp->length);
11575b57ecfSGrant Likely }
11675b57ecfSGrant Likely 
117d9fc8807SFrank Rowand /* always return newly allocated name, caller must free after use */
11875b57ecfSGrant Likely static const char *safe_name(struct kobject *kobj, const char *orig_name)
11975b57ecfSGrant Likely {
12075b57ecfSGrant Likely 	const char *name = orig_name;
12175b57ecfSGrant Likely 	struct kernfs_node *kn;
12275b57ecfSGrant Likely 	int i = 0;
12375b57ecfSGrant Likely 
12475b57ecfSGrant Likely 	/* don't be a hero. After 16 tries give up */
12575b57ecfSGrant Likely 	while (i < 16 && (kn = sysfs_get_dirent(kobj->sd, name))) {
12675b57ecfSGrant Likely 		sysfs_put(kn);
12775b57ecfSGrant Likely 		if (name != orig_name)
12875b57ecfSGrant Likely 			kfree(name);
12975b57ecfSGrant Likely 		name = kasprintf(GFP_KERNEL, "%s#%i", orig_name, ++i);
13075b57ecfSGrant Likely 	}
13175b57ecfSGrant Likely 
132d9fc8807SFrank Rowand 	if (name == orig_name) {
133d9fc8807SFrank Rowand 		name = kstrdup(orig_name, GFP_KERNEL);
134d9fc8807SFrank Rowand 	} else {
135606ad42aSRob Herring 		pr_warn("Duplicate name in %s, renamed to \"%s\"\n",
13675b57ecfSGrant Likely 			kobject_name(kobj), name);
137d9fc8807SFrank Rowand 	}
13875b57ecfSGrant Likely 	return name;
13975b57ecfSGrant Likely }
14075b57ecfSGrant Likely 
1418a2b22a2SGrant Likely int __of_add_property_sysfs(struct device_node *np, struct property *pp)
14275b57ecfSGrant Likely {
14375b57ecfSGrant Likely 	int rc;
14475b57ecfSGrant Likely 
14575b57ecfSGrant Likely 	/* Important: Don't leak passwords */
14675b57ecfSGrant Likely 	bool secure = strncmp(pp->name, "security-", 9) == 0;
14775b57ecfSGrant Likely 
148ef69d740SGaurav Minocha 	if (!IS_ENABLED(CONFIG_SYSFS))
149ef69d740SGaurav Minocha 		return 0;
150ef69d740SGaurav Minocha 
1518a2b22a2SGrant Likely 	if (!of_kset || !of_node_is_attached(np))
1528a2b22a2SGrant Likely 		return 0;
1538a2b22a2SGrant Likely 
15475b57ecfSGrant Likely 	sysfs_bin_attr_init(&pp->attr);
15575b57ecfSGrant Likely 	pp->attr.attr.name = safe_name(&np->kobj, pp->name);
1567ace5f48SFrank Rowand 	pp->attr.attr.mode = secure ? 0400 : 0444;
15775b57ecfSGrant Likely 	pp->attr.size = secure ? 0 : pp->length;
15875b57ecfSGrant Likely 	pp->attr.read = of_node_property_read;
15975b57ecfSGrant Likely 
16075b57ecfSGrant Likely 	rc = sysfs_create_bin_file(&np->kobj, &pp->attr);
1610d638a07SRob Herring 	WARN(rc, "error adding attribute %s to node %pOF\n", pp->name, np);
16275b57ecfSGrant Likely 	return rc;
16375b57ecfSGrant Likely }
16475b57ecfSGrant Likely 
1658a2b22a2SGrant Likely int __of_attach_node_sysfs(struct device_node *np)
16675b57ecfSGrant Likely {
16775b57ecfSGrant Likely 	const char *name;
168d9fc8807SFrank Rowand 	struct kobject *parent;
16975b57ecfSGrant Likely 	struct property *pp;
17075b57ecfSGrant Likely 	int rc;
17175b57ecfSGrant Likely 
172ef69d740SGaurav Minocha 	if (!IS_ENABLED(CONFIG_SYSFS))
173ef69d740SGaurav Minocha 		return 0;
174ef69d740SGaurav Minocha 
1758a2b22a2SGrant Likely 	if (!of_kset)
1768a2b22a2SGrant Likely 		return 0;
1778a2b22a2SGrant Likely 
17875b57ecfSGrant Likely 	np->kobj.kset = of_kset;
17975b57ecfSGrant Likely 	if (!np->parent) {
18075b57ecfSGrant Likely 		/* Nodes without parents are new top level trees */
181d9fc8807SFrank Rowand 		name = safe_name(&of_kset->kobj, "base");
182d9fc8807SFrank Rowand 		parent = NULL;
18375b57ecfSGrant Likely 	} else {
18475b57ecfSGrant Likely 		name = safe_name(&np->parent->kobj, kbasename(np->full_name));
185d9fc8807SFrank Rowand 		parent = &np->parent->kobj;
18675b57ecfSGrant Likely 	}
187d9fc8807SFrank Rowand 	if (!name)
188d9fc8807SFrank Rowand 		return -ENOMEM;
189d9fc8807SFrank Rowand 	rc = kobject_add(&np->kobj, parent, "%s", name);
190d9fc8807SFrank Rowand 	kfree(name);
19175b57ecfSGrant Likely 	if (rc)
19275b57ecfSGrant Likely 		return rc;
19375b57ecfSGrant Likely 
19475b57ecfSGrant Likely 	for_each_property_of_node(np, pp)
19575b57ecfSGrant Likely 		__of_add_property_sysfs(np, pp);
19675b57ecfSGrant Likely 
19775b57ecfSGrant Likely 	return 0;
19875b57ecfSGrant Likely }
19975b57ecfSGrant Likely 
200194ec936SSudeep Holla void __init of_core_init(void)
20175b57ecfSGrant Likely {
20275b57ecfSGrant Likely 	struct device_node *np;
20375b57ecfSGrant Likely 
20475b57ecfSGrant Likely 	/* Create the kset, and register existing nodes */
205c05aba2bSPantelis Antoniou 	mutex_lock(&of_mutex);
20675b57ecfSGrant Likely 	of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);
20775b57ecfSGrant Likely 	if (!of_kset) {
208c05aba2bSPantelis Antoniou 		mutex_unlock(&of_mutex);
209606ad42aSRob Herring 		pr_err("failed to register existing nodes\n");
210194ec936SSudeep Holla 		return;
21175b57ecfSGrant Likely 	}
21275b57ecfSGrant Likely 	for_each_of_allnodes(np)
2138a2b22a2SGrant Likely 		__of_attach_node_sysfs(np);
214c05aba2bSPantelis Antoniou 	mutex_unlock(&of_mutex);
21575b57ecfSGrant Likely 
2168357041aSGrant Likely 	/* Symlink in /proc as required by userspace ABI */
2175063e25aSGrant Likely 	if (of_root)
21875b57ecfSGrant Likely 		proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");
21975b57ecfSGrant Likely }
22075b57ecfSGrant Likely 
22128d0e36bSThomas Gleixner static struct property *__of_find_property(const struct device_node *np,
22228d0e36bSThomas Gleixner 					   const char *name, int *lenp)
223581b605aSStephen Rothwell {
224581b605aSStephen Rothwell 	struct property *pp;
225581b605aSStephen Rothwell 
22664e4566fSTimur Tabi 	if (!np)
22764e4566fSTimur Tabi 		return NULL;
22864e4566fSTimur Tabi 
229a3a7cab1SSachin Kamat 	for (pp = np->properties; pp; pp = pp->next) {
230581b605aSStephen Rothwell 		if (of_prop_cmp(pp->name, name) == 0) {
231a3a7cab1SSachin Kamat 			if (lenp)
232581b605aSStephen Rothwell 				*lenp = pp->length;
233581b605aSStephen Rothwell 			break;
234581b605aSStephen Rothwell 		}
235581b605aSStephen Rothwell 	}
23628d0e36bSThomas Gleixner 
23728d0e36bSThomas Gleixner 	return pp;
23828d0e36bSThomas Gleixner }
23928d0e36bSThomas Gleixner 
24028d0e36bSThomas Gleixner struct property *of_find_property(const struct device_node *np,
24128d0e36bSThomas Gleixner 				  const char *name,
24228d0e36bSThomas Gleixner 				  int *lenp)
24328d0e36bSThomas Gleixner {
24428d0e36bSThomas Gleixner 	struct property *pp;
245d6d3c4e6SThomas Gleixner 	unsigned long flags;
24628d0e36bSThomas Gleixner 
247d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
24828d0e36bSThomas Gleixner 	pp = __of_find_property(np, name, lenp);
249d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
250581b605aSStephen Rothwell 
251581b605aSStephen Rothwell 	return pp;
252581b605aSStephen Rothwell }
253581b605aSStephen Rothwell EXPORT_SYMBOL(of_find_property);
254581b605aSStephen Rothwell 
2555063e25aSGrant Likely struct device_node *__of_find_all_nodes(struct device_node *prev)
2565063e25aSGrant Likely {
2575063e25aSGrant Likely 	struct device_node *np;
2585063e25aSGrant Likely 	if (!prev) {
2595063e25aSGrant Likely 		np = of_root;
2605063e25aSGrant Likely 	} else if (prev->child) {
2615063e25aSGrant Likely 		np = prev->child;
2625063e25aSGrant Likely 	} else {
2635063e25aSGrant Likely 		/* Walk back up looking for a sibling, or the end of the structure */
2645063e25aSGrant Likely 		np = prev;
2655063e25aSGrant Likely 		while (np->parent && !np->sibling)
2665063e25aSGrant Likely 			np = np->parent;
2675063e25aSGrant Likely 		np = np->sibling; /* Might be null at the end of the tree */
2685063e25aSGrant Likely 	}
2695063e25aSGrant Likely 	return np;
2705063e25aSGrant Likely }
2715063e25aSGrant Likely 
272e91edcf5SGrant Likely /**
273e91edcf5SGrant Likely  * of_find_all_nodes - Get next node in global list
274e91edcf5SGrant Likely  * @prev:	Previous node or NULL to start iteration
275e91edcf5SGrant Likely  *		of_node_put() will be called on it
276e91edcf5SGrant Likely  *
277e91edcf5SGrant Likely  * Returns a node pointer with refcount incremented, use
278e91edcf5SGrant Likely  * of_node_put() on it when done.
279e91edcf5SGrant Likely  */
280e91edcf5SGrant Likely struct device_node *of_find_all_nodes(struct device_node *prev)
281e91edcf5SGrant Likely {
282e91edcf5SGrant Likely 	struct device_node *np;
283d25d8694SBenjamin Herrenschmidt 	unsigned long flags;
284e91edcf5SGrant Likely 
285d25d8694SBenjamin Herrenschmidt 	raw_spin_lock_irqsave(&devtree_lock, flags);
2865063e25aSGrant Likely 	np = __of_find_all_nodes(prev);
2875063e25aSGrant Likely 	of_node_get(np);
288e91edcf5SGrant Likely 	of_node_put(prev);
289d25d8694SBenjamin Herrenschmidt 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
290e91edcf5SGrant Likely 	return np;
291e91edcf5SGrant Likely }
292e91edcf5SGrant Likely EXPORT_SYMBOL(of_find_all_nodes);
293e91edcf5SGrant Likely 
29497e873e5SStephen Rothwell /*
29597e873e5SStephen Rothwell  * Find a property with a given name for a given node
29697e873e5SStephen Rothwell  * and return the value.
29797e873e5SStephen Rothwell  */
298a25095d4SGrant Likely const void *__of_get_property(const struct device_node *np,
29928d0e36bSThomas Gleixner 			      const char *name, int *lenp)
30028d0e36bSThomas Gleixner {
30128d0e36bSThomas Gleixner 	struct property *pp = __of_find_property(np, name, lenp);
30228d0e36bSThomas Gleixner 
30328d0e36bSThomas Gleixner 	return pp ? pp->value : NULL;
30428d0e36bSThomas Gleixner }
30528d0e36bSThomas Gleixner 
30628d0e36bSThomas Gleixner /*
30728d0e36bSThomas Gleixner  * Find a property with a given name for a given node
30828d0e36bSThomas Gleixner  * and return the value.
30928d0e36bSThomas Gleixner  */
31097e873e5SStephen Rothwell const void *of_get_property(const struct device_node *np, const char *name,
31197e873e5SStephen Rothwell 			    int *lenp)
31297e873e5SStephen Rothwell {
31397e873e5SStephen Rothwell 	struct property *pp = of_find_property(np, name, lenp);
31497e873e5SStephen Rothwell 
31597e873e5SStephen Rothwell 	return pp ? pp->value : NULL;
31697e873e5SStephen Rothwell }
31797e873e5SStephen Rothwell EXPORT_SYMBOL(of_get_property);
3180081cbc3SStephen Rothwell 
319183912d3SSudeep KarkadaNagesha /*
320183912d3SSudeep KarkadaNagesha  * arch_match_cpu_phys_id - Match the given logical CPU and physical id
321183912d3SSudeep KarkadaNagesha  *
322183912d3SSudeep KarkadaNagesha  * @cpu: logical cpu index of a core/thread
323183912d3SSudeep KarkadaNagesha  * @phys_id: physical identifier of a core/thread
324183912d3SSudeep KarkadaNagesha  *
325183912d3SSudeep KarkadaNagesha  * CPU logical to physical index mapping is architecture specific.
326183912d3SSudeep KarkadaNagesha  * However this __weak function provides a default match of physical
327183912d3SSudeep KarkadaNagesha  * id to logical cpu index. phys_id provided here is usually values read
328183912d3SSudeep KarkadaNagesha  * from the device tree which must match the hardware internal registers.
329183912d3SSudeep KarkadaNagesha  *
330183912d3SSudeep KarkadaNagesha  * Returns true if the physical identifier and the logical cpu index
331183912d3SSudeep KarkadaNagesha  * correspond to the same core/thread, false otherwise.
332183912d3SSudeep KarkadaNagesha  */
333183912d3SSudeep KarkadaNagesha bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id)
334183912d3SSudeep KarkadaNagesha {
335183912d3SSudeep KarkadaNagesha 	return (u32)phys_id == cpu;
336183912d3SSudeep KarkadaNagesha }
337183912d3SSudeep KarkadaNagesha 
338183912d3SSudeep KarkadaNagesha /**
339183912d3SSudeep KarkadaNagesha  * Checks if the given "prop_name" property holds the physical id of the
340183912d3SSudeep KarkadaNagesha  * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not
341183912d3SSudeep KarkadaNagesha  * NULL, local thread number within the core is returned in it.
342183912d3SSudeep KarkadaNagesha  */
343183912d3SSudeep KarkadaNagesha static bool __of_find_n_match_cpu_property(struct device_node *cpun,
344183912d3SSudeep KarkadaNagesha 			const char *prop_name, int cpu, unsigned int *thread)
345183912d3SSudeep KarkadaNagesha {
346183912d3SSudeep KarkadaNagesha 	const __be32 *cell;
347183912d3SSudeep KarkadaNagesha 	int ac, prop_len, tid;
348183912d3SSudeep KarkadaNagesha 	u64 hwid;
349183912d3SSudeep KarkadaNagesha 
350183912d3SSudeep KarkadaNagesha 	ac = of_n_addr_cells(cpun);
351183912d3SSudeep KarkadaNagesha 	cell = of_get_property(cpun, prop_name, &prop_len);
352f3cea45aSGrant Likely 	if (!cell || !ac)
353183912d3SSudeep KarkadaNagesha 		return false;
354f3cea45aSGrant Likely 	prop_len /= sizeof(*cell) * ac;
355183912d3SSudeep KarkadaNagesha 	for (tid = 0; tid < prop_len; tid++) {
356183912d3SSudeep KarkadaNagesha 		hwid = of_read_number(cell, ac);
357183912d3SSudeep KarkadaNagesha 		if (arch_match_cpu_phys_id(cpu, hwid)) {
358183912d3SSudeep KarkadaNagesha 			if (thread)
359183912d3SSudeep KarkadaNagesha 				*thread = tid;
360183912d3SSudeep KarkadaNagesha 			return true;
361183912d3SSudeep KarkadaNagesha 		}
362183912d3SSudeep KarkadaNagesha 		cell += ac;
363183912d3SSudeep KarkadaNagesha 	}
364183912d3SSudeep KarkadaNagesha 	return false;
365183912d3SSudeep KarkadaNagesha }
366183912d3SSudeep KarkadaNagesha 
367d1cb9d1aSDavid Miller /*
368d1cb9d1aSDavid Miller  * arch_find_n_match_cpu_physical_id - See if the given device node is
369d1cb9d1aSDavid Miller  * for the cpu corresponding to logical cpu 'cpu'.  Return true if so,
370d1cb9d1aSDavid Miller  * else false.  If 'thread' is non-NULL, the local thread number within the
371d1cb9d1aSDavid Miller  * core is returned in it.
372d1cb9d1aSDavid Miller  */
373d1cb9d1aSDavid Miller bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun,
374d1cb9d1aSDavid Miller 					      int cpu, unsigned int *thread)
375d1cb9d1aSDavid Miller {
376d1cb9d1aSDavid Miller 	/* Check for non-standard "ibm,ppc-interrupt-server#s" property
377d1cb9d1aSDavid Miller 	 * for thread ids on PowerPC. If it doesn't exist fallback to
378d1cb9d1aSDavid Miller 	 * standard "reg" property.
379d1cb9d1aSDavid Miller 	 */
380d1cb9d1aSDavid Miller 	if (IS_ENABLED(CONFIG_PPC) &&
381d1cb9d1aSDavid Miller 	    __of_find_n_match_cpu_property(cpun,
382d1cb9d1aSDavid Miller 					   "ibm,ppc-interrupt-server#s",
383d1cb9d1aSDavid Miller 					   cpu, thread))
384d1cb9d1aSDavid Miller 		return true;
385d1cb9d1aSDavid Miller 
386510bd068SMasahiro Yamada 	return __of_find_n_match_cpu_property(cpun, "reg", cpu, thread);
387d1cb9d1aSDavid Miller }
388d1cb9d1aSDavid Miller 
389183912d3SSudeep KarkadaNagesha /**
390183912d3SSudeep KarkadaNagesha  * of_get_cpu_node - Get device node associated with the given logical CPU
391183912d3SSudeep KarkadaNagesha  *
392183912d3SSudeep KarkadaNagesha  * @cpu: CPU number(logical index) for which device node is required
393183912d3SSudeep KarkadaNagesha  * @thread: if not NULL, local thread number within the physical core is
394183912d3SSudeep KarkadaNagesha  *          returned
395183912d3SSudeep KarkadaNagesha  *
396183912d3SSudeep KarkadaNagesha  * The main purpose of this function is to retrieve the device node for the
397183912d3SSudeep KarkadaNagesha  * given logical CPU index. It should be used to initialize the of_node in
398183912d3SSudeep KarkadaNagesha  * cpu device. Once of_node in cpu device is populated, all the further
399183912d3SSudeep KarkadaNagesha  * references can use that instead.
400183912d3SSudeep KarkadaNagesha  *
401183912d3SSudeep KarkadaNagesha  * CPU logical to physical index mapping is architecture specific and is built
402183912d3SSudeep KarkadaNagesha  * before booting secondary cores. This function uses arch_match_cpu_phys_id
403183912d3SSudeep KarkadaNagesha  * which can be overridden by architecture specific implementation.
404183912d3SSudeep KarkadaNagesha  *
4051c986e36SMasahiro Yamada  * Returns a node pointer for the logical cpu with refcount incremented, use
4061c986e36SMasahiro Yamada  * of_node_put() on it when done. Returns NULL if not found.
407183912d3SSudeep KarkadaNagesha  */
408183912d3SSudeep KarkadaNagesha struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
409183912d3SSudeep KarkadaNagesha {
410d1cb9d1aSDavid Miller 	struct device_node *cpun;
411183912d3SSudeep KarkadaNagesha 
412d1cb9d1aSDavid Miller 	for_each_node_by_type(cpun, "cpu") {
413d1cb9d1aSDavid Miller 		if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread))
414183912d3SSudeep KarkadaNagesha 			return cpun;
415183912d3SSudeep KarkadaNagesha 	}
416183912d3SSudeep KarkadaNagesha 	return NULL;
417183912d3SSudeep KarkadaNagesha }
418183912d3SSudeep KarkadaNagesha EXPORT_SYMBOL(of_get_cpu_node);
419183912d3SSudeep KarkadaNagesha 
420215a14cfSKevin Hao /**
421215a14cfSKevin Hao  * __of_device_is_compatible() - Check if the node matches given constraints
422215a14cfSKevin Hao  * @device: pointer to node
423215a14cfSKevin Hao  * @compat: required compatible string, NULL or "" for any match
424215a14cfSKevin Hao  * @type: required device_type value, NULL or "" for any match
425215a14cfSKevin Hao  * @name: required node name, NULL or "" for any match
426215a14cfSKevin Hao  *
427215a14cfSKevin Hao  * Checks if the given @compat, @type and @name strings match the
428215a14cfSKevin Hao  * properties of the given @device. A constraints can be skipped by
429215a14cfSKevin Hao  * passing NULL or an empty string as the constraint.
430215a14cfSKevin Hao  *
431215a14cfSKevin Hao  * Returns 0 for no match, and a positive integer on match. The return
432215a14cfSKevin Hao  * value is a relative score with larger values indicating better
433215a14cfSKevin Hao  * matches. The score is weighted for the most specific compatible value
434215a14cfSKevin Hao  * to get the highest score. Matching type is next, followed by matching
435215a14cfSKevin Hao  * name. Practically speaking, this results in the following priority
436215a14cfSKevin Hao  * order for matches:
437215a14cfSKevin Hao  *
438215a14cfSKevin Hao  * 1. specific compatible && type && name
439215a14cfSKevin Hao  * 2. specific compatible && type
440215a14cfSKevin Hao  * 3. specific compatible && name
441215a14cfSKevin Hao  * 4. specific compatible
442215a14cfSKevin Hao  * 5. general compatible && type && name
443215a14cfSKevin Hao  * 6. general compatible && type
444215a14cfSKevin Hao  * 7. general compatible && name
445215a14cfSKevin Hao  * 8. general compatible
446215a14cfSKevin Hao  * 9. type && name
447215a14cfSKevin Hao  * 10. type
448215a14cfSKevin Hao  * 11. name
4490081cbc3SStephen Rothwell  */
45028d0e36bSThomas Gleixner static int __of_device_is_compatible(const struct device_node *device,
451215a14cfSKevin Hao 				     const char *compat, const char *type, const char *name)
4520081cbc3SStephen Rothwell {
453215a14cfSKevin Hao 	struct property *prop;
4540081cbc3SStephen Rothwell 	const char *cp;
455215a14cfSKevin Hao 	int index = 0, score = 0;
4560081cbc3SStephen Rothwell 
457215a14cfSKevin Hao 	/* Compatible match has highest priority */
458215a14cfSKevin Hao 	if (compat && compat[0]) {
459215a14cfSKevin Hao 		prop = __of_find_property(device, "compatible", NULL);
460215a14cfSKevin Hao 		for (cp = of_prop_next_string(prop, NULL); cp;
461215a14cfSKevin Hao 		     cp = of_prop_next_string(prop, cp), index++) {
462215a14cfSKevin Hao 			if (of_compat_cmp(cp, compat, strlen(compat)) == 0) {
463215a14cfSKevin Hao 				score = INT_MAX/2 - (index << 2);
464215a14cfSKevin Hao 				break;
465215a14cfSKevin Hao 			}
466215a14cfSKevin Hao 		}
467215a14cfSKevin Hao 		if (!score)
4680081cbc3SStephen Rothwell 			return 0;
4690081cbc3SStephen Rothwell 	}
4700081cbc3SStephen Rothwell 
471215a14cfSKevin Hao 	/* Matching type is better than matching name */
472215a14cfSKevin Hao 	if (type && type[0]) {
473215a14cfSKevin Hao 		if (!device->type || of_node_cmp(type, device->type))
4740081cbc3SStephen Rothwell 			return 0;
475215a14cfSKevin Hao 		score += 2;
476215a14cfSKevin Hao 	}
477215a14cfSKevin Hao 
478215a14cfSKevin Hao 	/* Matching name is a bit better than not */
479215a14cfSKevin Hao 	if (name && name[0]) {
480215a14cfSKevin Hao 		if (!device->name || of_node_cmp(name, device->name))
481215a14cfSKevin Hao 			return 0;
482215a14cfSKevin Hao 		score++;
483215a14cfSKevin Hao 	}
484215a14cfSKevin Hao 
485215a14cfSKevin Hao 	return score;
4860081cbc3SStephen Rothwell }
48728d0e36bSThomas Gleixner 
48828d0e36bSThomas Gleixner /** Checks if the given "compat" string matches one of the strings in
48928d0e36bSThomas Gleixner  * the device's "compatible" property
49028d0e36bSThomas Gleixner  */
49128d0e36bSThomas Gleixner int of_device_is_compatible(const struct device_node *device,
49228d0e36bSThomas Gleixner 		const char *compat)
49328d0e36bSThomas Gleixner {
494d6d3c4e6SThomas Gleixner 	unsigned long flags;
49528d0e36bSThomas Gleixner 	int res;
49628d0e36bSThomas Gleixner 
497d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
498215a14cfSKevin Hao 	res = __of_device_is_compatible(device, compat, NULL, NULL);
499d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
50028d0e36bSThomas Gleixner 	return res;
50128d0e36bSThomas Gleixner }
5020081cbc3SStephen Rothwell EXPORT_SYMBOL(of_device_is_compatible);
503e679c5f4SStephen Rothwell 
504b9c13fe3SBenjamin Herrenschmidt /** Checks if the device is compatible with any of the entries in
505b9c13fe3SBenjamin Herrenschmidt  *  a NULL terminated array of strings. Returns the best match
506b9c13fe3SBenjamin Herrenschmidt  *  score or 0.
507b9c13fe3SBenjamin Herrenschmidt  */
508b9c13fe3SBenjamin Herrenschmidt int of_device_compatible_match(struct device_node *device,
509b9c13fe3SBenjamin Herrenschmidt 			       const char *const *compat)
510b9c13fe3SBenjamin Herrenschmidt {
511b9c13fe3SBenjamin Herrenschmidt 	unsigned int tmp, score = 0;
512b9c13fe3SBenjamin Herrenschmidt 
513b9c13fe3SBenjamin Herrenschmidt 	if (!compat)
514b9c13fe3SBenjamin Herrenschmidt 		return 0;
515b9c13fe3SBenjamin Herrenschmidt 
516b9c13fe3SBenjamin Herrenschmidt 	while (*compat) {
517b9c13fe3SBenjamin Herrenschmidt 		tmp = of_device_is_compatible(device, *compat);
518b9c13fe3SBenjamin Herrenschmidt 		if (tmp > score)
519b9c13fe3SBenjamin Herrenschmidt 			score = tmp;
520b9c13fe3SBenjamin Herrenschmidt 		compat++;
521b9c13fe3SBenjamin Herrenschmidt 	}
522b9c13fe3SBenjamin Herrenschmidt 
523b9c13fe3SBenjamin Herrenschmidt 	return score;
524b9c13fe3SBenjamin Herrenschmidt }
525b9c13fe3SBenjamin Herrenschmidt 
526e679c5f4SStephen Rothwell /**
52771a157e8SGrant Likely  * of_machine_is_compatible - Test root of device tree for a given compatible value
5281f43cfb9SGrant Likely  * @compat: compatible string to look for in root node's compatible property.
5291f43cfb9SGrant Likely  *
53025c7a1deSKevin Cernekee  * Returns a positive integer if the root node has the given value in its
5311f43cfb9SGrant Likely  * compatible property.
5321f43cfb9SGrant Likely  */
53371a157e8SGrant Likely int of_machine_is_compatible(const char *compat)
5341f43cfb9SGrant Likely {
5351f43cfb9SGrant Likely 	struct device_node *root;
5361f43cfb9SGrant Likely 	int rc = 0;
5371f43cfb9SGrant Likely 
5381f43cfb9SGrant Likely 	root = of_find_node_by_path("/");
5391f43cfb9SGrant Likely 	if (root) {
5401f43cfb9SGrant Likely 		rc = of_device_is_compatible(root, compat);
5411f43cfb9SGrant Likely 		of_node_put(root);
5421f43cfb9SGrant Likely 	}
5431f43cfb9SGrant Likely 	return rc;
5441f43cfb9SGrant Likely }
54571a157e8SGrant Likely EXPORT_SYMBOL(of_machine_is_compatible);
5461f43cfb9SGrant Likely 
5471f43cfb9SGrant Likely /**
548c31a0c05SStephen Warren  *  __of_device_is_available - check if a device is available for use
549834d97d4SJosh Boyer  *
550c31a0c05SStephen Warren  *  @device: Node to check for availability, with locks already held
551834d97d4SJosh Boyer  *
55253a4ab96SKevin Cernekee  *  Returns true if the status property is absent or set to "okay" or "ok",
55353a4ab96SKevin Cernekee  *  false otherwise
554834d97d4SJosh Boyer  */
55553a4ab96SKevin Cernekee static bool __of_device_is_available(const struct device_node *device)
556834d97d4SJosh Boyer {
557834d97d4SJosh Boyer 	const char *status;
558834d97d4SJosh Boyer 	int statlen;
559834d97d4SJosh Boyer 
56042ccd781SXiubo Li 	if (!device)
56153a4ab96SKevin Cernekee 		return false;
56242ccd781SXiubo Li 
563c31a0c05SStephen Warren 	status = __of_get_property(device, "status", &statlen);
564834d97d4SJosh Boyer 	if (status == NULL)
56553a4ab96SKevin Cernekee 		return true;
566834d97d4SJosh Boyer 
567834d97d4SJosh Boyer 	if (statlen > 0) {
568834d97d4SJosh Boyer 		if (!strcmp(status, "okay") || !strcmp(status, "ok"))
56953a4ab96SKevin Cernekee 			return true;
570834d97d4SJosh Boyer 	}
571834d97d4SJosh Boyer 
57253a4ab96SKevin Cernekee 	return false;
573834d97d4SJosh Boyer }
574c31a0c05SStephen Warren 
575c31a0c05SStephen Warren /**
576c31a0c05SStephen Warren  *  of_device_is_available - check if a device is available for use
577c31a0c05SStephen Warren  *
578c31a0c05SStephen Warren  *  @device: Node to check for availability
579c31a0c05SStephen Warren  *
58053a4ab96SKevin Cernekee  *  Returns true if the status property is absent or set to "okay" or "ok",
58153a4ab96SKevin Cernekee  *  false otherwise
582c31a0c05SStephen Warren  */
58353a4ab96SKevin Cernekee bool of_device_is_available(const struct device_node *device)
584c31a0c05SStephen Warren {
585c31a0c05SStephen Warren 	unsigned long flags;
58653a4ab96SKevin Cernekee 	bool res;
587c31a0c05SStephen Warren 
588c31a0c05SStephen Warren 	raw_spin_lock_irqsave(&devtree_lock, flags);
589c31a0c05SStephen Warren 	res = __of_device_is_available(device);
590c31a0c05SStephen Warren 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
591c31a0c05SStephen Warren 	return res;
592c31a0c05SStephen Warren 
593c31a0c05SStephen Warren }
594834d97d4SJosh Boyer EXPORT_SYMBOL(of_device_is_available);
595834d97d4SJosh Boyer 
596834d97d4SJosh Boyer /**
59737786c7fSKevin Cernekee  *  of_device_is_big_endian - check if a device has BE registers
59837786c7fSKevin Cernekee  *
59937786c7fSKevin Cernekee  *  @device: Node to check for endianness
60037786c7fSKevin Cernekee  *
60137786c7fSKevin Cernekee  *  Returns true if the device has a "big-endian" property, or if the kernel
60237786c7fSKevin Cernekee  *  was compiled for BE *and* the device has a "native-endian" property.
60337786c7fSKevin Cernekee  *  Returns false otherwise.
60437786c7fSKevin Cernekee  *
60537786c7fSKevin Cernekee  *  Callers would nominally use ioread32be/iowrite32be if
60637786c7fSKevin Cernekee  *  of_device_is_big_endian() == true, or readl/writel otherwise.
60737786c7fSKevin Cernekee  */
60837786c7fSKevin Cernekee bool of_device_is_big_endian(const struct device_node *device)
60937786c7fSKevin Cernekee {
61037786c7fSKevin Cernekee 	if (of_property_read_bool(device, "big-endian"))
61137786c7fSKevin Cernekee 		return true;
61237786c7fSKevin Cernekee 	if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) &&
61337786c7fSKevin Cernekee 	    of_property_read_bool(device, "native-endian"))
61437786c7fSKevin Cernekee 		return true;
61537786c7fSKevin Cernekee 	return false;
61637786c7fSKevin Cernekee }
61737786c7fSKevin Cernekee EXPORT_SYMBOL(of_device_is_big_endian);
61837786c7fSKevin Cernekee 
61937786c7fSKevin Cernekee /**
620e679c5f4SStephen Rothwell  *	of_get_parent - Get a node's parent if any
621e679c5f4SStephen Rothwell  *	@node:	Node to get parent
622e679c5f4SStephen Rothwell  *
623e679c5f4SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
624e679c5f4SStephen Rothwell  *	of_node_put() on it when done.
625e679c5f4SStephen Rothwell  */
626e679c5f4SStephen Rothwell struct device_node *of_get_parent(const struct device_node *node)
627e679c5f4SStephen Rothwell {
628e679c5f4SStephen Rothwell 	struct device_node *np;
629d6d3c4e6SThomas Gleixner 	unsigned long flags;
630e679c5f4SStephen Rothwell 
631e679c5f4SStephen Rothwell 	if (!node)
632e679c5f4SStephen Rothwell 		return NULL;
633e679c5f4SStephen Rothwell 
634d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
635e679c5f4SStephen Rothwell 	np = of_node_get(node->parent);
636d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
637e679c5f4SStephen Rothwell 	return np;
638e679c5f4SStephen Rothwell }
639e679c5f4SStephen Rothwell EXPORT_SYMBOL(of_get_parent);
640d1cd355aSStephen Rothwell 
641d1cd355aSStephen Rothwell /**
642f4eb0107SMichael Ellerman  *	of_get_next_parent - Iterate to a node's parent
643f4eb0107SMichael Ellerman  *	@node:	Node to get parent of
644f4eb0107SMichael Ellerman  *
645f4eb0107SMichael Ellerman  *	This is like of_get_parent() except that it drops the
646f4eb0107SMichael Ellerman  *	refcount on the passed node, making it suitable for iterating
647f4eb0107SMichael Ellerman  *	through a node's parents.
648f4eb0107SMichael Ellerman  *
649f4eb0107SMichael Ellerman  *	Returns a node pointer with refcount incremented, use
650f4eb0107SMichael Ellerman  *	of_node_put() on it when done.
651f4eb0107SMichael Ellerman  */
652f4eb0107SMichael Ellerman struct device_node *of_get_next_parent(struct device_node *node)
653f4eb0107SMichael Ellerman {
654f4eb0107SMichael Ellerman 	struct device_node *parent;
655d6d3c4e6SThomas Gleixner 	unsigned long flags;
656f4eb0107SMichael Ellerman 
657f4eb0107SMichael Ellerman 	if (!node)
658f4eb0107SMichael Ellerman 		return NULL;
659f4eb0107SMichael Ellerman 
660d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
661f4eb0107SMichael Ellerman 	parent = of_node_get(node->parent);
662f4eb0107SMichael Ellerman 	of_node_put(node);
663d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
664f4eb0107SMichael Ellerman 	return parent;
665f4eb0107SMichael Ellerman }
6666695be68SGuennadi Liakhovetski EXPORT_SYMBOL(of_get_next_parent);
667f4eb0107SMichael Ellerman 
6680d0e02d6SGrant Likely static struct device_node *__of_get_next_child(const struct device_node *node,
6690d0e02d6SGrant Likely 						struct device_node *prev)
6700d0e02d6SGrant Likely {
6710d0e02d6SGrant Likely 	struct device_node *next;
6720d0e02d6SGrant Likely 
67343cb4367SFlorian Fainelli 	if (!node)
67443cb4367SFlorian Fainelli 		return NULL;
67543cb4367SFlorian Fainelli 
6760d0e02d6SGrant Likely 	next = prev ? prev->sibling : node->child;
6770d0e02d6SGrant Likely 	for (; next; next = next->sibling)
6780d0e02d6SGrant Likely 		if (of_node_get(next))
6790d0e02d6SGrant Likely 			break;
6800d0e02d6SGrant Likely 	of_node_put(prev);
6810d0e02d6SGrant Likely 	return next;
6820d0e02d6SGrant Likely }
6830d0e02d6SGrant Likely #define __for_each_child_of_node(parent, child) \
6840d0e02d6SGrant Likely 	for (child = __of_get_next_child(parent, NULL); child != NULL; \
6850d0e02d6SGrant Likely 	     child = __of_get_next_child(parent, child))
6860d0e02d6SGrant Likely 
687f4eb0107SMichael Ellerman /**
688d1cd355aSStephen Rothwell  *	of_get_next_child - Iterate a node childs
689d1cd355aSStephen Rothwell  *	@node:	parent node
690d1cd355aSStephen Rothwell  *	@prev:	previous child of the parent node, or NULL to get first
691d1cd355aSStephen Rothwell  *
69264808273SBaruch Siach  *	Returns a node pointer with refcount incremented, use of_node_put() on
69364808273SBaruch Siach  *	it when done. Returns NULL when prev is the last child. Decrements the
69464808273SBaruch Siach  *	refcount of prev.
695d1cd355aSStephen Rothwell  */
696d1cd355aSStephen Rothwell struct device_node *of_get_next_child(const struct device_node *node,
697d1cd355aSStephen Rothwell 	struct device_node *prev)
698d1cd355aSStephen Rothwell {
699d1cd355aSStephen Rothwell 	struct device_node *next;
700d6d3c4e6SThomas Gleixner 	unsigned long flags;
701d1cd355aSStephen Rothwell 
702d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
7030d0e02d6SGrant Likely 	next = __of_get_next_child(node, prev);
704d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
705d1cd355aSStephen Rothwell 	return next;
706d1cd355aSStephen Rothwell }
707d1cd355aSStephen Rothwell EXPORT_SYMBOL(of_get_next_child);
7081ef4d424SStephen Rothwell 
7091ef4d424SStephen Rothwell /**
7103296193dSTimur Tabi  *	of_get_next_available_child - Find the next available child node
7113296193dSTimur Tabi  *	@node:	parent node
7123296193dSTimur Tabi  *	@prev:	previous child of the parent node, or NULL to get first
7133296193dSTimur Tabi  *
7143296193dSTimur Tabi  *      This function is like of_get_next_child(), except that it
7153296193dSTimur Tabi  *      automatically skips any disabled nodes (i.e. status = "disabled").
7163296193dSTimur Tabi  */
7173296193dSTimur Tabi struct device_node *of_get_next_available_child(const struct device_node *node,
7183296193dSTimur Tabi 	struct device_node *prev)
7193296193dSTimur Tabi {
7203296193dSTimur Tabi 	struct device_node *next;
721d25d8694SBenjamin Herrenschmidt 	unsigned long flags;
7223296193dSTimur Tabi 
72343cb4367SFlorian Fainelli 	if (!node)
72443cb4367SFlorian Fainelli 		return NULL;
72543cb4367SFlorian Fainelli 
726d25d8694SBenjamin Herrenschmidt 	raw_spin_lock_irqsave(&devtree_lock, flags);
7273296193dSTimur Tabi 	next = prev ? prev->sibling : node->child;
7283296193dSTimur Tabi 	for (; next; next = next->sibling) {
729c31a0c05SStephen Warren 		if (!__of_device_is_available(next))
7303296193dSTimur Tabi 			continue;
7313296193dSTimur Tabi 		if (of_node_get(next))
7323296193dSTimur Tabi 			break;
7333296193dSTimur Tabi 	}
7343296193dSTimur Tabi 	of_node_put(prev);
735d25d8694SBenjamin Herrenschmidt 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
7363296193dSTimur Tabi 	return next;
7373296193dSTimur Tabi }
7383296193dSTimur Tabi EXPORT_SYMBOL(of_get_next_available_child);
7393296193dSTimur Tabi 
7403296193dSTimur Tabi /**
7419c19761aSSrinivas Kandagatla  *	of_get_child_by_name - Find the child node by name for a given parent
7429c19761aSSrinivas Kandagatla  *	@node:	parent node
7439c19761aSSrinivas Kandagatla  *	@name:	child name to look for.
7449c19761aSSrinivas Kandagatla  *
7459c19761aSSrinivas Kandagatla  *      This function looks for child node for given matching name
7469c19761aSSrinivas Kandagatla  *
7479c19761aSSrinivas Kandagatla  *	Returns a node pointer if found, with refcount incremented, use
7489c19761aSSrinivas Kandagatla  *	of_node_put() on it when done.
7499c19761aSSrinivas Kandagatla  *	Returns NULL if node is not found.
7509c19761aSSrinivas Kandagatla  */
7519c19761aSSrinivas Kandagatla struct device_node *of_get_child_by_name(const struct device_node *node,
7529c19761aSSrinivas Kandagatla 				const char *name)
7539c19761aSSrinivas Kandagatla {
7549c19761aSSrinivas Kandagatla 	struct device_node *child;
7559c19761aSSrinivas Kandagatla 
7569c19761aSSrinivas Kandagatla 	for_each_child_of_node(node, child)
7579c19761aSSrinivas Kandagatla 		if (child->name && (of_node_cmp(child->name, name) == 0))
7589c19761aSSrinivas Kandagatla 			break;
7599c19761aSSrinivas Kandagatla 	return child;
7609c19761aSSrinivas Kandagatla }
7619c19761aSSrinivas Kandagatla EXPORT_SYMBOL(of_get_child_by_name);
7629c19761aSSrinivas Kandagatla 
763c22e650eSGrant Likely static struct device_node *__of_find_node_by_path(struct device_node *parent,
764c22e650eSGrant Likely 						const char *path)
765c22e650eSGrant Likely {
766c22e650eSGrant Likely 	struct device_node *child;
767106937e8SLeif Lindholm 	int len;
768c22e650eSGrant Likely 
769721a09e9SBrian Norris 	len = strcspn(path, "/:");
770c22e650eSGrant Likely 	if (!len)
771c22e650eSGrant Likely 		return NULL;
772c22e650eSGrant Likely 
773c22e650eSGrant Likely 	__for_each_child_of_node(parent, child) {
77495e6b1faSRob Herring 		const char *name = kbasename(child->full_name);
775c22e650eSGrant Likely 		if (strncmp(path, name, len) == 0 && (strlen(name) == len))
776c22e650eSGrant Likely 			return child;
777c22e650eSGrant Likely 	}
778c22e650eSGrant Likely 	return NULL;
779c22e650eSGrant Likely }
780c22e650eSGrant Likely 
78127497e11SRob Herring struct device_node *__of_find_node_by_full_path(struct device_node *node,
78227497e11SRob Herring 						const char *path)
78327497e11SRob Herring {
78427497e11SRob Herring 	const char *separator = strchr(path, ':');
78527497e11SRob Herring 
78627497e11SRob Herring 	while (node && *path == '/') {
78727497e11SRob Herring 		struct device_node *tmp = node;
78827497e11SRob Herring 
78927497e11SRob Herring 		path++; /* Increment past '/' delimiter */
79027497e11SRob Herring 		node = __of_find_node_by_path(node, path);
79127497e11SRob Herring 		of_node_put(tmp);
79227497e11SRob Herring 		path = strchrnul(path, '/');
79327497e11SRob Herring 		if (separator && separator < path)
79427497e11SRob Herring 			break;
79527497e11SRob Herring 	}
79627497e11SRob Herring 	return node;
79727497e11SRob Herring }
79827497e11SRob Herring 
7999c19761aSSrinivas Kandagatla /**
80075c28c09SLeif Lindholm  *	of_find_node_opts_by_path - Find a node matching a full OF path
801c22e650eSGrant Likely  *	@path: Either the full path to match, or if the path does not
802c22e650eSGrant Likely  *	       start with '/', the name of a property of the /aliases
803c22e650eSGrant Likely  *	       node (an alias).  In the case of an alias, the node
804c22e650eSGrant Likely  *	       matching the alias' value will be returned.
80575c28c09SLeif Lindholm  *	@opts: Address of a pointer into which to store the start of
80675c28c09SLeif Lindholm  *	       an options string appended to the end of the path with
80775c28c09SLeif Lindholm  *	       a ':' separator.
808c22e650eSGrant Likely  *
809c22e650eSGrant Likely  *	Valid paths:
810c22e650eSGrant Likely  *		/foo/bar	Full path
811c22e650eSGrant Likely  *		foo		Valid alias
812c22e650eSGrant Likely  *		foo/bar		Valid alias + relative path
8131ef4d424SStephen Rothwell  *
8141ef4d424SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
8151ef4d424SStephen Rothwell  *	of_node_put() on it when done.
8161ef4d424SStephen Rothwell  */
81775c28c09SLeif Lindholm struct device_node *of_find_node_opts_by_path(const char *path, const char **opts)
8181ef4d424SStephen Rothwell {
819c22e650eSGrant Likely 	struct device_node *np = NULL;
820c22e650eSGrant Likely 	struct property *pp;
821d6d3c4e6SThomas Gleixner 	unsigned long flags;
82275c28c09SLeif Lindholm 	const char *separator = strchr(path, ':');
82375c28c09SLeif Lindholm 
82475c28c09SLeif Lindholm 	if (opts)
82575c28c09SLeif Lindholm 		*opts = separator ? separator + 1 : NULL;
8261ef4d424SStephen Rothwell 
827c22e650eSGrant Likely 	if (strcmp(path, "/") == 0)
8285063e25aSGrant Likely 		return of_node_get(of_root);
829c22e650eSGrant Likely 
830c22e650eSGrant Likely 	/* The path could begin with an alias */
831c22e650eSGrant Likely 	if (*path != '/') {
832106937e8SLeif Lindholm 		int len;
833106937e8SLeif Lindholm 		const char *p = separator;
834106937e8SLeif Lindholm 
835106937e8SLeif Lindholm 		if (!p)
836106937e8SLeif Lindholm 			p = strchrnul(path, '/');
837106937e8SLeif Lindholm 		len = p - path;
838c22e650eSGrant Likely 
839c22e650eSGrant Likely 		/* of_aliases must not be NULL */
840c22e650eSGrant Likely 		if (!of_aliases)
841c22e650eSGrant Likely 			return NULL;
842c22e650eSGrant Likely 
843c22e650eSGrant Likely 		for_each_property_of_node(of_aliases, pp) {
844c22e650eSGrant Likely 			if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) {
845c22e650eSGrant Likely 				np = of_find_node_by_path(pp->value);
8461ef4d424SStephen Rothwell 				break;
8471ef4d424SStephen Rothwell 			}
848c22e650eSGrant Likely 		}
849c22e650eSGrant Likely 		if (!np)
850c22e650eSGrant Likely 			return NULL;
851c22e650eSGrant Likely 		path = p;
852c22e650eSGrant Likely 	}
853c22e650eSGrant Likely 
854c22e650eSGrant Likely 	/* Step down the tree matching path components */
855c22e650eSGrant Likely 	raw_spin_lock_irqsave(&devtree_lock, flags);
856c22e650eSGrant Likely 	if (!np)
8575063e25aSGrant Likely 		np = of_node_get(of_root);
85827497e11SRob Herring 	np = __of_find_node_by_full_path(np, path);
859d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
8601ef4d424SStephen Rothwell 	return np;
8611ef4d424SStephen Rothwell }
86275c28c09SLeif Lindholm EXPORT_SYMBOL(of_find_node_opts_by_path);
8631ef4d424SStephen Rothwell 
8641ef4d424SStephen Rothwell /**
8651ef4d424SStephen Rothwell  *	of_find_node_by_name - Find a node by its "name" property
8661ef4d424SStephen Rothwell  *	@from:	The node to start searching from or NULL, the node
8671ef4d424SStephen Rothwell  *		you pass will not be searched, only the next one
8681ef4d424SStephen Rothwell  *		will; typically, you pass what the previous call
8691ef4d424SStephen Rothwell  *		returned. of_node_put() will be called on it
8701ef4d424SStephen Rothwell  *	@name:	The name string to match against
8711ef4d424SStephen Rothwell  *
8721ef4d424SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
8731ef4d424SStephen Rothwell  *	of_node_put() on it when done.
8741ef4d424SStephen Rothwell  */
8751ef4d424SStephen Rothwell struct device_node *of_find_node_by_name(struct device_node *from,
8761ef4d424SStephen Rothwell 	const char *name)
8771ef4d424SStephen Rothwell {
8781ef4d424SStephen Rothwell 	struct device_node *np;
879d6d3c4e6SThomas Gleixner 	unsigned long flags;
8801ef4d424SStephen Rothwell 
881d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
8825063e25aSGrant Likely 	for_each_of_allnodes_from(from, np)
8831ef4d424SStephen Rothwell 		if (np->name && (of_node_cmp(np->name, name) == 0)
8841ef4d424SStephen Rothwell 		    && of_node_get(np))
8851ef4d424SStephen Rothwell 			break;
8861ef4d424SStephen Rothwell 	of_node_put(from);
887d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
8881ef4d424SStephen Rothwell 	return np;
8891ef4d424SStephen Rothwell }
8901ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_name);
8911ef4d424SStephen Rothwell 
8921ef4d424SStephen Rothwell /**
8931ef4d424SStephen Rothwell  *	of_find_node_by_type - Find a node by its "device_type" property
8941ef4d424SStephen Rothwell  *	@from:	The node to start searching from, or NULL to start searching
8951ef4d424SStephen Rothwell  *		the entire device tree. The node you pass will not be
8961ef4d424SStephen Rothwell  *		searched, only the next one will; typically, you pass
8971ef4d424SStephen Rothwell  *		what the previous call returned. of_node_put() will be
8981ef4d424SStephen Rothwell  *		called on from for you.
8991ef4d424SStephen Rothwell  *	@type:	The type string to match against
9001ef4d424SStephen Rothwell  *
9011ef4d424SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
9021ef4d424SStephen Rothwell  *	of_node_put() on it when done.
9031ef4d424SStephen Rothwell  */
9041ef4d424SStephen Rothwell struct device_node *of_find_node_by_type(struct device_node *from,
9051ef4d424SStephen Rothwell 	const char *type)
9061ef4d424SStephen Rothwell {
9071ef4d424SStephen Rothwell 	struct device_node *np;
908d6d3c4e6SThomas Gleixner 	unsigned long flags;
9091ef4d424SStephen Rothwell 
910d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
9115063e25aSGrant Likely 	for_each_of_allnodes_from(from, np)
9121ef4d424SStephen Rothwell 		if (np->type && (of_node_cmp(np->type, type) == 0)
9131ef4d424SStephen Rothwell 		    && of_node_get(np))
9141ef4d424SStephen Rothwell 			break;
9151ef4d424SStephen Rothwell 	of_node_put(from);
916d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
9171ef4d424SStephen Rothwell 	return np;
9181ef4d424SStephen Rothwell }
9191ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_node_by_type);
9201ef4d424SStephen Rothwell 
9211ef4d424SStephen Rothwell /**
9221ef4d424SStephen Rothwell  *	of_find_compatible_node - Find a node based on type and one of the
9231ef4d424SStephen Rothwell  *                                tokens in its "compatible" property
9241ef4d424SStephen Rothwell  *	@from:		The node to start searching from or NULL, the node
9251ef4d424SStephen Rothwell  *			you pass will not be searched, only the next one
9261ef4d424SStephen Rothwell  *			will; typically, you pass what the previous call
9271ef4d424SStephen Rothwell  *			returned. of_node_put() will be called on it
9281ef4d424SStephen Rothwell  *	@type:		The type string to match "device_type" or NULL to ignore
9291ef4d424SStephen Rothwell  *	@compatible:	The string to match to one of the tokens in the device
9301ef4d424SStephen Rothwell  *			"compatible" list.
9311ef4d424SStephen Rothwell  *
9321ef4d424SStephen Rothwell  *	Returns a node pointer with refcount incremented, use
9331ef4d424SStephen Rothwell  *	of_node_put() on it when done.
9341ef4d424SStephen Rothwell  */
9351ef4d424SStephen Rothwell struct device_node *of_find_compatible_node(struct device_node *from,
9361ef4d424SStephen Rothwell 	const char *type, const char *compatible)
9371ef4d424SStephen Rothwell {
9381ef4d424SStephen Rothwell 	struct device_node *np;
939d6d3c4e6SThomas Gleixner 	unsigned long flags;
9401ef4d424SStephen Rothwell 
941d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
9425063e25aSGrant Likely 	for_each_of_allnodes_from(from, np)
943215a14cfSKevin Hao 		if (__of_device_is_compatible(np, compatible, type, NULL) &&
94428d0e36bSThomas Gleixner 		    of_node_get(np))
9451ef4d424SStephen Rothwell 			break;
9461ef4d424SStephen Rothwell 	of_node_put(from);
947d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
9481ef4d424SStephen Rothwell 	return np;
9491ef4d424SStephen Rothwell }
9501ef4d424SStephen Rothwell EXPORT_SYMBOL(of_find_compatible_node);
951283029d1SGrant Likely 
952283029d1SGrant Likely /**
9531e291b14SMichael Ellerman  *	of_find_node_with_property - Find a node which has a property with
9541e291b14SMichael Ellerman  *                                   the given name.
9551e291b14SMichael Ellerman  *	@from:		The node to start searching from or NULL, the node
9561e291b14SMichael Ellerman  *			you pass will not be searched, only the next one
9571e291b14SMichael Ellerman  *			will; typically, you pass what the previous call
9581e291b14SMichael Ellerman  *			returned. of_node_put() will be called on it
9591e291b14SMichael Ellerman  *	@prop_name:	The name of the property to look for.
9601e291b14SMichael Ellerman  *
9611e291b14SMichael Ellerman  *	Returns a node pointer with refcount incremented, use
9621e291b14SMichael Ellerman  *	of_node_put() on it when done.
9631e291b14SMichael Ellerman  */
9641e291b14SMichael Ellerman struct device_node *of_find_node_with_property(struct device_node *from,
9651e291b14SMichael Ellerman 	const char *prop_name)
9661e291b14SMichael Ellerman {
9671e291b14SMichael Ellerman 	struct device_node *np;
9681e291b14SMichael Ellerman 	struct property *pp;
969d6d3c4e6SThomas Gleixner 	unsigned long flags;
9701e291b14SMichael Ellerman 
971d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
9725063e25aSGrant Likely 	for_each_of_allnodes_from(from, np) {
973a3a7cab1SSachin Kamat 		for (pp = np->properties; pp; pp = pp->next) {
9741e291b14SMichael Ellerman 			if (of_prop_cmp(pp->name, prop_name) == 0) {
9751e291b14SMichael Ellerman 				of_node_get(np);
9761e291b14SMichael Ellerman 				goto out;
9771e291b14SMichael Ellerman 			}
9781e291b14SMichael Ellerman 		}
9791e291b14SMichael Ellerman 	}
9801e291b14SMichael Ellerman out:
9811e291b14SMichael Ellerman 	of_node_put(from);
982d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
9831e291b14SMichael Ellerman 	return np;
9841e291b14SMichael Ellerman }
9851e291b14SMichael Ellerman EXPORT_SYMBOL(of_find_node_with_property);
9861e291b14SMichael Ellerman 
98728d0e36bSThomas Gleixner static
98828d0e36bSThomas Gleixner const struct of_device_id *__of_match_node(const struct of_device_id *matches,
989283029d1SGrant Likely 					   const struct device_node *node)
990283029d1SGrant Likely {
991215a14cfSKevin Hao 	const struct of_device_id *best_match = NULL;
992215a14cfSKevin Hao 	int score, best_score = 0;
993215a14cfSKevin Hao 
994a52f07ecSGrant Likely 	if (!matches)
995a52f07ecSGrant Likely 		return NULL;
996a52f07ecSGrant Likely 
997215a14cfSKevin Hao 	for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) {
998215a14cfSKevin Hao 		score = __of_device_is_compatible(node, matches->compatible,
999215a14cfSKevin Hao 						  matches->type, matches->name);
1000215a14cfSKevin Hao 		if (score > best_score) {
1001215a14cfSKevin Hao 			best_match = matches;
1002215a14cfSKevin Hao 			best_score = score;
1003283029d1SGrant Likely 		}
1004215a14cfSKevin Hao 	}
1005215a14cfSKevin Hao 
1006215a14cfSKevin Hao 	return best_match;
1007283029d1SGrant Likely }
100828d0e36bSThomas Gleixner 
100928d0e36bSThomas Gleixner /**
1010c50949d3SGeert Uytterhoeven  * of_match_node - Tell if a device_node has a matching of_match structure
101128d0e36bSThomas Gleixner  *	@matches:	array of of device match structures to search in
101228d0e36bSThomas Gleixner  *	@node:		the of device structure to match against
101328d0e36bSThomas Gleixner  *
101471c5498eSKevin Hao  *	Low level utility function used by device matching.
101528d0e36bSThomas Gleixner  */
101628d0e36bSThomas Gleixner const struct of_device_id *of_match_node(const struct of_device_id *matches,
101728d0e36bSThomas Gleixner 					 const struct device_node *node)
101828d0e36bSThomas Gleixner {
101928d0e36bSThomas Gleixner 	const struct of_device_id *match;
1020d6d3c4e6SThomas Gleixner 	unsigned long flags;
102128d0e36bSThomas Gleixner 
1022d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
102328d0e36bSThomas Gleixner 	match = __of_match_node(matches, node);
1024d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
102528d0e36bSThomas Gleixner 	return match;
102628d0e36bSThomas Gleixner }
1027283029d1SGrant Likely EXPORT_SYMBOL(of_match_node);
1028283029d1SGrant Likely 
1029283029d1SGrant Likely /**
103050c8af4cSStephen Warren  *	of_find_matching_node_and_match - Find a node based on an of_device_id
103150c8af4cSStephen Warren  *					  match table.
1032283029d1SGrant Likely  *	@from:		The node to start searching from or NULL, the node
1033283029d1SGrant Likely  *			you pass will not be searched, only the next one
1034283029d1SGrant Likely  *			will; typically, you pass what the previous call
1035283029d1SGrant Likely  *			returned. of_node_put() will be called on it
1036283029d1SGrant Likely  *	@matches:	array of of device match structures to search in
103750c8af4cSStephen Warren  *	@match		Updated to point at the matches entry which matched
1038283029d1SGrant Likely  *
1039283029d1SGrant Likely  *	Returns a node pointer with refcount incremented, use
1040283029d1SGrant Likely  *	of_node_put() on it when done.
1041283029d1SGrant Likely  */
104250c8af4cSStephen Warren struct device_node *of_find_matching_node_and_match(struct device_node *from,
104350c8af4cSStephen Warren 					const struct of_device_id *matches,
104450c8af4cSStephen Warren 					const struct of_device_id **match)
1045283029d1SGrant Likely {
1046283029d1SGrant Likely 	struct device_node *np;
1047dc71bcf1SThomas Abraham 	const struct of_device_id *m;
1048d6d3c4e6SThomas Gleixner 	unsigned long flags;
1049283029d1SGrant Likely 
105050c8af4cSStephen Warren 	if (match)
105150c8af4cSStephen Warren 		*match = NULL;
105250c8af4cSStephen Warren 
1053d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
10545063e25aSGrant Likely 	for_each_of_allnodes_from(from, np) {
105528d0e36bSThomas Gleixner 		m = __of_match_node(matches, np);
1056dc71bcf1SThomas Abraham 		if (m && of_node_get(np)) {
105750c8af4cSStephen Warren 			if (match)
1058dc71bcf1SThomas Abraham 				*match = m;
1059283029d1SGrant Likely 			break;
1060283029d1SGrant Likely 		}
106150c8af4cSStephen Warren 	}
1062283029d1SGrant Likely 	of_node_put(from);
1063d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1064283029d1SGrant Likely 	return np;
1065283029d1SGrant Likely }
106680c2022eSGrant Likely EXPORT_SYMBOL(of_find_matching_node_and_match);
10673f07af49SGrant Likely 
10683f07af49SGrant Likely /**
10693f07af49SGrant Likely  * of_modalias_node - Lookup appropriate modalias for a device node
10703f07af49SGrant Likely  * @node:	pointer to a device tree node
10713f07af49SGrant Likely  * @modalias:	Pointer to buffer that modalias value will be copied into
10723f07af49SGrant Likely  * @len:	Length of modalias value
10733f07af49SGrant Likely  *
10742ffe8c5fSGrant Likely  * Based on the value of the compatible property, this routine will attempt
10752ffe8c5fSGrant Likely  * to choose an appropriate modalias value for a particular device tree node.
10762ffe8c5fSGrant Likely  * It does this by stripping the manufacturer prefix (as delimited by a ',')
10772ffe8c5fSGrant Likely  * from the first entry in the compatible list property.
10783f07af49SGrant Likely  *
10792ffe8c5fSGrant Likely  * This routine returns 0 on success, <0 on failure.
10803f07af49SGrant Likely  */
10813f07af49SGrant Likely int of_modalias_node(struct device_node *node, char *modalias, int len)
10823f07af49SGrant Likely {
10832ffe8c5fSGrant Likely 	const char *compatible, *p;
10842ffe8c5fSGrant Likely 	int cplen;
10853f07af49SGrant Likely 
10863f07af49SGrant Likely 	compatible = of_get_property(node, "compatible", &cplen);
10872ffe8c5fSGrant Likely 	if (!compatible || strlen(compatible) > cplen)
10883f07af49SGrant Likely 		return -ENODEV;
10893f07af49SGrant Likely 	p = strchr(compatible, ',');
10902ffe8c5fSGrant Likely 	strlcpy(modalias, p ? p + 1 : compatible, len);
10913f07af49SGrant Likely 	return 0;
10923f07af49SGrant Likely }
10933f07af49SGrant Likely EXPORT_SYMBOL_GPL(of_modalias_node);
10943f07af49SGrant Likely 
109564b60e09SAnton Vorontsov /**
109689751a7cSJeremy Kerr  * of_find_node_by_phandle - Find a node given a phandle
109789751a7cSJeremy Kerr  * @handle:	phandle of the node to find
109889751a7cSJeremy Kerr  *
109989751a7cSJeremy Kerr  * Returns a node pointer with refcount incremented, use
110089751a7cSJeremy Kerr  * of_node_put() on it when done.
110189751a7cSJeremy Kerr  */
110289751a7cSJeremy Kerr struct device_node *of_find_node_by_phandle(phandle handle)
110389751a7cSJeremy Kerr {
110489751a7cSJeremy Kerr 	struct device_node *np;
1105d25d8694SBenjamin Herrenschmidt 	unsigned long flags;
110689751a7cSJeremy Kerr 
1107fc59b447SGrant Likely 	if (!handle)
1108fc59b447SGrant Likely 		return NULL;
1109fc59b447SGrant Likely 
1110d25d8694SBenjamin Herrenschmidt 	raw_spin_lock_irqsave(&devtree_lock, flags);
11115063e25aSGrant Likely 	for_each_of_allnodes(np)
111289751a7cSJeremy Kerr 		if (np->phandle == handle)
111389751a7cSJeremy Kerr 			break;
111489751a7cSJeremy Kerr 	of_node_get(np);
1115d25d8694SBenjamin Herrenschmidt 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
111689751a7cSJeremy Kerr 	return np;
111789751a7cSJeremy Kerr }
111889751a7cSJeremy Kerr EXPORT_SYMBOL(of_find_node_by_phandle);
111989751a7cSJeremy Kerr 
1120624cfca5SGrant Likely void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
1121624cfca5SGrant Likely {
1122624cfca5SGrant Likely 	int i;
11230d638a07SRob Herring 	printk("%s %pOF", msg, args->np);
11244aa66344SMarcin Nowakowski 	for (i = 0; i < args->args_count; i++) {
11254aa66344SMarcin Nowakowski 		const char delim = i ? ',' : ':';
11264aa66344SMarcin Nowakowski 
11274aa66344SMarcin Nowakowski 		pr_cont("%c%08x", delim, args->args[i]);
11284aa66344SMarcin Nowakowski 	}
11294aa66344SMarcin Nowakowski 	pr_cont("\n");
1130624cfca5SGrant Likely }
1131624cfca5SGrant Likely 
113274e1fbb1SJoerg Roedel int of_phandle_iterator_init(struct of_phandle_iterator *it,
113374e1fbb1SJoerg Roedel 		const struct device_node *np,
113474e1fbb1SJoerg Roedel 		const char *list_name,
113574e1fbb1SJoerg Roedel 		const char *cells_name,
113674e1fbb1SJoerg Roedel 		int cell_count)
113774e1fbb1SJoerg Roedel {
113874e1fbb1SJoerg Roedel 	const __be32 *list;
113974e1fbb1SJoerg Roedel 	int size;
114074e1fbb1SJoerg Roedel 
114174e1fbb1SJoerg Roedel 	memset(it, 0, sizeof(*it));
114274e1fbb1SJoerg Roedel 
114374e1fbb1SJoerg Roedel 	list = of_get_property(np, list_name, &size);
114474e1fbb1SJoerg Roedel 	if (!list)
114574e1fbb1SJoerg Roedel 		return -ENOENT;
114674e1fbb1SJoerg Roedel 
114774e1fbb1SJoerg Roedel 	it->cells_name = cells_name;
114874e1fbb1SJoerg Roedel 	it->cell_count = cell_count;
114974e1fbb1SJoerg Roedel 	it->parent = np;
115074e1fbb1SJoerg Roedel 	it->list_end = list + size / sizeof(*list);
115174e1fbb1SJoerg Roedel 	it->phandle_end = list;
115274e1fbb1SJoerg Roedel 	it->cur = list;
115374e1fbb1SJoerg Roedel 
115474e1fbb1SJoerg Roedel 	return 0;
115574e1fbb1SJoerg Roedel }
115600bab23fSKuninori Morimoto EXPORT_SYMBOL_GPL(of_phandle_iterator_init);
115774e1fbb1SJoerg Roedel 
1158cd209b41SJoerg Roedel int of_phandle_iterator_next(struct of_phandle_iterator *it)
1159cd209b41SJoerg Roedel {
1160cd209b41SJoerg Roedel 	uint32_t count = 0;
1161cd209b41SJoerg Roedel 
1162cd209b41SJoerg Roedel 	if (it->node) {
1163cd209b41SJoerg Roedel 		of_node_put(it->node);
1164cd209b41SJoerg Roedel 		it->node = NULL;
1165cd209b41SJoerg Roedel 	}
1166cd209b41SJoerg Roedel 
1167cd209b41SJoerg Roedel 	if (!it->cur || it->phandle_end >= it->list_end)
1168cd209b41SJoerg Roedel 		return -ENOENT;
1169cd209b41SJoerg Roedel 
1170cd209b41SJoerg Roedel 	it->cur = it->phandle_end;
1171cd209b41SJoerg Roedel 
1172cd209b41SJoerg Roedel 	/* If phandle is 0, then it is an empty entry with no arguments. */
1173cd209b41SJoerg Roedel 	it->phandle = be32_to_cpup(it->cur++);
1174cd209b41SJoerg Roedel 
1175cd209b41SJoerg Roedel 	if (it->phandle) {
1176cd209b41SJoerg Roedel 
1177cd209b41SJoerg Roedel 		/*
1178cd209b41SJoerg Roedel 		 * Find the provider node and parse the #*-cells property to
1179cd209b41SJoerg Roedel 		 * determine the argument length.
1180cd209b41SJoerg Roedel 		 */
1181cd209b41SJoerg Roedel 		it->node = of_find_node_by_phandle(it->phandle);
1182cd209b41SJoerg Roedel 
1183cd209b41SJoerg Roedel 		if (it->cells_name) {
1184cd209b41SJoerg Roedel 			if (!it->node) {
11850d638a07SRob Herring 				pr_err("%pOF: could not find phandle\n",
11860d638a07SRob Herring 				       it->parent);
1187cd209b41SJoerg Roedel 				goto err;
1188cd209b41SJoerg Roedel 			}
1189cd209b41SJoerg Roedel 
1190cd209b41SJoerg Roedel 			if (of_property_read_u32(it->node, it->cells_name,
1191cd209b41SJoerg Roedel 						 &count)) {
11920d638a07SRob Herring 				pr_err("%pOF: could not get %s for %pOF\n",
11930d638a07SRob Herring 				       it->parent,
1194cd209b41SJoerg Roedel 				       it->cells_name,
11950d638a07SRob Herring 				       it->node);
1196cd209b41SJoerg Roedel 				goto err;
1197cd209b41SJoerg Roedel 			}
1198cd209b41SJoerg Roedel 		} else {
1199cd209b41SJoerg Roedel 			count = it->cell_count;
1200cd209b41SJoerg Roedel 		}
1201cd209b41SJoerg Roedel 
1202cd209b41SJoerg Roedel 		/*
1203cd209b41SJoerg Roedel 		 * Make sure that the arguments actually fit in the remaining
1204cd209b41SJoerg Roedel 		 * property data length
1205cd209b41SJoerg Roedel 		 */
1206cd209b41SJoerg Roedel 		if (it->cur + count > it->list_end) {
12070d638a07SRob Herring 			pr_err("%pOF: arguments longer than property\n",
12080d638a07SRob Herring 			       it->parent);
1209cd209b41SJoerg Roedel 			goto err;
1210cd209b41SJoerg Roedel 		}
1211cd209b41SJoerg Roedel 	}
1212cd209b41SJoerg Roedel 
1213cd209b41SJoerg Roedel 	it->phandle_end = it->cur + count;
1214cd209b41SJoerg Roedel 	it->cur_count = count;
1215cd209b41SJoerg Roedel 
1216cd209b41SJoerg Roedel 	return 0;
1217cd209b41SJoerg Roedel 
1218cd209b41SJoerg Roedel err:
1219cd209b41SJoerg Roedel 	if (it->node) {
1220cd209b41SJoerg Roedel 		of_node_put(it->node);
1221cd209b41SJoerg Roedel 		it->node = NULL;
1222cd209b41SJoerg Roedel 	}
1223cd209b41SJoerg Roedel 
1224cd209b41SJoerg Roedel 	return -EINVAL;
1225cd209b41SJoerg Roedel }
122600bab23fSKuninori Morimoto EXPORT_SYMBOL_GPL(of_phandle_iterator_next);
1227cd209b41SJoerg Roedel 
1228abdaa77bSJoerg Roedel int of_phandle_iterator_args(struct of_phandle_iterator *it,
1229abdaa77bSJoerg Roedel 			     uint32_t *args,
1230abdaa77bSJoerg Roedel 			     int size)
1231abdaa77bSJoerg Roedel {
1232abdaa77bSJoerg Roedel 	int i, count;
1233abdaa77bSJoerg Roedel 
1234abdaa77bSJoerg Roedel 	count = it->cur_count;
1235abdaa77bSJoerg Roedel 
1236abdaa77bSJoerg Roedel 	if (WARN_ON(size < count))
1237abdaa77bSJoerg Roedel 		count = size;
1238abdaa77bSJoerg Roedel 
1239abdaa77bSJoerg Roedel 	for (i = 0; i < count; i++)
1240abdaa77bSJoerg Roedel 		args[i] = be32_to_cpup(it->cur++);
1241abdaa77bSJoerg Roedel 
1242abdaa77bSJoerg Roedel 	return count;
1243abdaa77bSJoerg Roedel }
1244abdaa77bSJoerg Roedel 
1245bd69f73fSGrant Likely static int __of_parse_phandle_with_args(const struct device_node *np,
1246bd69f73fSGrant Likely 					const char *list_name,
1247035fd948SStephen Warren 					const char *cells_name,
1248035fd948SStephen Warren 					int cell_count, int index,
124915c9a0acSGrant Likely 					struct of_phandle_args *out_args)
125064b60e09SAnton Vorontsov {
125174e1fbb1SJoerg Roedel 	struct of_phandle_iterator it;
125274e1fbb1SJoerg Roedel 	int rc, cur_index = 0;
125315c9a0acSGrant Likely 
125415c9a0acSGrant Likely 	/* Loop over the phandles until all the requested entry is found */
1255f623ce95SJoerg Roedel 	of_for_each_phandle(&it, rc, np, list_name, cells_name, cell_count) {
125615c9a0acSGrant Likely 		/*
1257cd209b41SJoerg Roedel 		 * All of the error cases bail out of the loop, so at
125815c9a0acSGrant Likely 		 * this point, the parsing is successful. If the requested
125915c9a0acSGrant Likely 		 * index matches, then fill the out_args structure and return,
126015c9a0acSGrant Likely 		 * or return -ENOENT for an empty entry.
126115c9a0acSGrant Likely 		 */
126223ce04c0SGrant Likely 		rc = -ENOENT;
126315c9a0acSGrant Likely 		if (cur_index == index) {
126474e1fbb1SJoerg Roedel 			if (!it.phandle)
126523ce04c0SGrant Likely 				goto err;
126615c9a0acSGrant Likely 
126715c9a0acSGrant Likely 			if (out_args) {
1268abdaa77bSJoerg Roedel 				int c;
1269abdaa77bSJoerg Roedel 
1270abdaa77bSJoerg Roedel 				c = of_phandle_iterator_args(&it,
1271abdaa77bSJoerg Roedel 							     out_args->args,
1272abdaa77bSJoerg Roedel 							     MAX_PHANDLE_ARGS);
127374e1fbb1SJoerg Roedel 				out_args->np = it.node;
1274abdaa77bSJoerg Roedel 				out_args->args_count = c;
1275b855f16bSTang Yuantian 			} else {
127674e1fbb1SJoerg Roedel 				of_node_put(it.node);
127715c9a0acSGrant Likely 			}
127823ce04c0SGrant Likely 
127923ce04c0SGrant Likely 			/* Found it! return success */
128015c9a0acSGrant Likely 			return 0;
128115c9a0acSGrant Likely 		}
128264b60e09SAnton Vorontsov 
128364b60e09SAnton Vorontsov 		cur_index++;
128464b60e09SAnton Vorontsov 	}
128564b60e09SAnton Vorontsov 
128623ce04c0SGrant Likely 	/*
128723ce04c0SGrant Likely 	 * Unlock node before returning result; will be one of:
128823ce04c0SGrant Likely 	 * -ENOENT : index is for empty phandle
128923ce04c0SGrant Likely 	 * -EINVAL : parsing error on data
129023ce04c0SGrant Likely 	 */
1291cd209b41SJoerg Roedel 
129223ce04c0SGrant Likely  err:
129374e1fbb1SJoerg Roedel 	of_node_put(it.node);
129423ce04c0SGrant Likely 	return rc;
129564b60e09SAnton Vorontsov }
1296bd69f73fSGrant Likely 
1297eded9dd4SStephen Warren /**
12985fba49e3SStephen Warren  * of_parse_phandle - Resolve a phandle property to a device_node pointer
12995fba49e3SStephen Warren  * @np: Pointer to device node holding phandle property
13005fba49e3SStephen Warren  * @phandle_name: Name of property holding a phandle value
13015fba49e3SStephen Warren  * @index: For properties holding a table of phandles, this is the index into
13025fba49e3SStephen Warren  *         the table
13035fba49e3SStephen Warren  *
13045fba49e3SStephen Warren  * Returns the device_node pointer with refcount incremented.  Use
13055fba49e3SStephen Warren  * of_node_put() on it when done.
13065fba49e3SStephen Warren  */
13075fba49e3SStephen Warren struct device_node *of_parse_phandle(const struct device_node *np,
13085fba49e3SStephen Warren 				     const char *phandle_name, int index)
13095fba49e3SStephen Warren {
131091d9942cSStephen Warren 	struct of_phandle_args args;
13115fba49e3SStephen Warren 
131291d9942cSStephen Warren 	if (index < 0)
13135fba49e3SStephen Warren 		return NULL;
13145fba49e3SStephen Warren 
131591d9942cSStephen Warren 	if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0,
131691d9942cSStephen Warren 					 index, &args))
131791d9942cSStephen Warren 		return NULL;
131891d9942cSStephen Warren 
131991d9942cSStephen Warren 	return args.np;
13205fba49e3SStephen Warren }
13215fba49e3SStephen Warren EXPORT_SYMBOL(of_parse_phandle);
13225fba49e3SStephen Warren 
13235fba49e3SStephen Warren /**
1324eded9dd4SStephen Warren  * of_parse_phandle_with_args() - Find a node pointed by phandle in a list
1325eded9dd4SStephen Warren  * @np:		pointer to a device tree node containing a list
1326eded9dd4SStephen Warren  * @list_name:	property name that contains a list
1327eded9dd4SStephen Warren  * @cells_name:	property name that specifies phandles' arguments count
1328eded9dd4SStephen Warren  * @index:	index of a phandle to parse out
1329eded9dd4SStephen Warren  * @out_args:	optional pointer to output arguments structure (will be filled)
1330eded9dd4SStephen Warren  *
1331eded9dd4SStephen Warren  * This function is useful to parse lists of phandles and their arguments.
1332eded9dd4SStephen Warren  * Returns 0 on success and fills out_args, on error returns appropriate
1333eded9dd4SStephen Warren  * errno value.
1334eded9dd4SStephen Warren  *
1335d94a75c1SGeert Uytterhoeven  * Caller is responsible to call of_node_put() on the returned out_args->np
1336eded9dd4SStephen Warren  * pointer.
1337eded9dd4SStephen Warren  *
1338eded9dd4SStephen Warren  * Example:
1339eded9dd4SStephen Warren  *
1340eded9dd4SStephen Warren  * phandle1: node1 {
1341eded9dd4SStephen Warren  *	#list-cells = <2>;
1342eded9dd4SStephen Warren  * }
1343eded9dd4SStephen Warren  *
1344eded9dd4SStephen Warren  * phandle2: node2 {
1345eded9dd4SStephen Warren  *	#list-cells = <1>;
1346eded9dd4SStephen Warren  * }
1347eded9dd4SStephen Warren  *
1348eded9dd4SStephen Warren  * node3 {
1349eded9dd4SStephen Warren  *	list = <&phandle1 1 2 &phandle2 3>;
1350eded9dd4SStephen Warren  * }
1351eded9dd4SStephen Warren  *
1352eded9dd4SStephen Warren  * To get a device_node of the `node2' node you may call this:
1353eded9dd4SStephen Warren  * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
1354eded9dd4SStephen Warren  */
1355bd69f73fSGrant Likely int of_parse_phandle_with_args(const struct device_node *np, const char *list_name,
1356bd69f73fSGrant Likely 				const char *cells_name, int index,
1357bd69f73fSGrant Likely 				struct of_phandle_args *out_args)
1358bd69f73fSGrant Likely {
1359bd69f73fSGrant Likely 	if (index < 0)
1360bd69f73fSGrant Likely 		return -EINVAL;
1361035fd948SStephen Warren 	return __of_parse_phandle_with_args(np, list_name, cells_name, 0,
1362035fd948SStephen Warren 					    index, out_args);
1363bd69f73fSGrant Likely }
136415c9a0acSGrant Likely EXPORT_SYMBOL(of_parse_phandle_with_args);
136502af11b0SGrant Likely 
1366bd69f73fSGrant Likely /**
1367035fd948SStephen Warren  * of_parse_phandle_with_fixed_args() - Find a node pointed by phandle in a list
1368035fd948SStephen Warren  * @np:		pointer to a device tree node containing a list
1369035fd948SStephen Warren  * @list_name:	property name that contains a list
1370035fd948SStephen Warren  * @cell_count: number of argument cells following the phandle
1371035fd948SStephen Warren  * @index:	index of a phandle to parse out
1372035fd948SStephen Warren  * @out_args:	optional pointer to output arguments structure (will be filled)
1373035fd948SStephen Warren  *
1374035fd948SStephen Warren  * This function is useful to parse lists of phandles and their arguments.
1375035fd948SStephen Warren  * Returns 0 on success and fills out_args, on error returns appropriate
1376035fd948SStephen Warren  * errno value.
1377035fd948SStephen Warren  *
1378d94a75c1SGeert Uytterhoeven  * Caller is responsible to call of_node_put() on the returned out_args->np
1379035fd948SStephen Warren  * pointer.
1380035fd948SStephen Warren  *
1381035fd948SStephen Warren  * Example:
1382035fd948SStephen Warren  *
1383035fd948SStephen Warren  * phandle1: node1 {
1384035fd948SStephen Warren  * }
1385035fd948SStephen Warren  *
1386035fd948SStephen Warren  * phandle2: node2 {
1387035fd948SStephen Warren  * }
1388035fd948SStephen Warren  *
1389035fd948SStephen Warren  * node3 {
1390035fd948SStephen Warren  *	list = <&phandle1 0 2 &phandle2 2 3>;
1391035fd948SStephen Warren  * }
1392035fd948SStephen Warren  *
1393035fd948SStephen Warren  * To get a device_node of the `node2' node you may call this:
1394035fd948SStephen Warren  * of_parse_phandle_with_fixed_args(node3, "list", 2, 1, &args);
1395035fd948SStephen Warren  */
1396035fd948SStephen Warren int of_parse_phandle_with_fixed_args(const struct device_node *np,
1397035fd948SStephen Warren 				const char *list_name, int cell_count,
1398035fd948SStephen Warren 				int index, struct of_phandle_args *out_args)
1399035fd948SStephen Warren {
1400035fd948SStephen Warren 	if (index < 0)
1401035fd948SStephen Warren 		return -EINVAL;
1402035fd948SStephen Warren 	return __of_parse_phandle_with_args(np, list_name, NULL, cell_count,
1403035fd948SStephen Warren 					   index, out_args);
1404035fd948SStephen Warren }
1405035fd948SStephen Warren EXPORT_SYMBOL(of_parse_phandle_with_fixed_args);
1406035fd948SStephen Warren 
1407035fd948SStephen Warren /**
1408bd69f73fSGrant Likely  * of_count_phandle_with_args() - Find the number of phandles references in a property
1409bd69f73fSGrant Likely  * @np:		pointer to a device tree node containing a list
1410bd69f73fSGrant Likely  * @list_name:	property name that contains a list
1411bd69f73fSGrant Likely  * @cells_name:	property name that specifies phandles' arguments count
1412bd69f73fSGrant Likely  *
1413bd69f73fSGrant Likely  * Returns the number of phandle + argument tuples within a property. It
1414bd69f73fSGrant Likely  * is a typical pattern to encode a list of phandle and variable
1415bd69f73fSGrant Likely  * arguments into a single property. The number of arguments is encoded
1416bd69f73fSGrant Likely  * by a property in the phandle-target node. For example, a gpios
1417bd69f73fSGrant Likely  * property would contain a list of GPIO specifies consisting of a
1418bd69f73fSGrant Likely  * phandle and 1 or more arguments. The number of arguments are
1419bd69f73fSGrant Likely  * determined by the #gpio-cells property in the node pointed to by the
1420bd69f73fSGrant Likely  * phandle.
1421bd69f73fSGrant Likely  */
1422bd69f73fSGrant Likely int of_count_phandle_with_args(const struct device_node *np, const char *list_name,
1423bd69f73fSGrant Likely 				const char *cells_name)
1424bd69f73fSGrant Likely {
14252021bd01SJoerg Roedel 	struct of_phandle_iterator it;
14262021bd01SJoerg Roedel 	int rc, cur_index = 0;
14272021bd01SJoerg Roedel 
14282021bd01SJoerg Roedel 	rc = of_phandle_iterator_init(&it, np, list_name, cells_name, 0);
14292021bd01SJoerg Roedel 	if (rc)
14302021bd01SJoerg Roedel 		return rc;
14312021bd01SJoerg Roedel 
14322021bd01SJoerg Roedel 	while ((rc = of_phandle_iterator_next(&it)) == 0)
14332021bd01SJoerg Roedel 		cur_index += 1;
14342021bd01SJoerg Roedel 
14352021bd01SJoerg Roedel 	if (rc != -ENOENT)
14362021bd01SJoerg Roedel 		return rc;
14372021bd01SJoerg Roedel 
14382021bd01SJoerg Roedel 	return cur_index;
1439bd69f73fSGrant Likely }
1440bd69f73fSGrant Likely EXPORT_SYMBOL(of_count_phandle_with_args);
1441bd69f73fSGrant Likely 
144202af11b0SGrant Likely /**
144362664f67SXiubo Li  * __of_add_property - Add a property to a node without lock operations
144462664f67SXiubo Li  */
1445d8c50088SPantelis Antoniou int __of_add_property(struct device_node *np, struct property *prop)
144662664f67SXiubo Li {
144762664f67SXiubo Li 	struct property **next;
144862664f67SXiubo Li 
144962664f67SXiubo Li 	prop->next = NULL;
145062664f67SXiubo Li 	next = &np->properties;
145162664f67SXiubo Li 	while (*next) {
145262664f67SXiubo Li 		if (strcmp(prop->name, (*next)->name) == 0)
145362664f67SXiubo Li 			/* duplicate ! don't insert it */
145462664f67SXiubo Li 			return -EEXIST;
145562664f67SXiubo Li 
145662664f67SXiubo Li 		next = &(*next)->next;
145762664f67SXiubo Li 	}
145862664f67SXiubo Li 	*next = prop;
145962664f67SXiubo Li 
146062664f67SXiubo Li 	return 0;
146162664f67SXiubo Li }
146262664f67SXiubo Li 
146362664f67SXiubo Li /**
146479d1c712SNathan Fontenot  * of_add_property - Add a property to a node
146502af11b0SGrant Likely  */
146679d1c712SNathan Fontenot int of_add_property(struct device_node *np, struct property *prop)
146702af11b0SGrant Likely {
146802af11b0SGrant Likely 	unsigned long flags;
14691cf3d8b3SNathan Fontenot 	int rc;
14701cf3d8b3SNathan Fontenot 
14718a2b22a2SGrant Likely 	mutex_lock(&of_mutex);
147202af11b0SGrant Likely 
1473d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
147462664f67SXiubo Li 	rc = __of_add_property(np, prop);
1475d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
147602af11b0SGrant Likely 
14778a2b22a2SGrant Likely 	if (!rc)
147875b57ecfSGrant Likely 		__of_add_property_sysfs(np, prop);
147902af11b0SGrant Likely 
14808a2b22a2SGrant Likely 	mutex_unlock(&of_mutex);
14818a2b22a2SGrant Likely 
1482259092a3SGrant Likely 	if (!rc)
1483259092a3SGrant Likely 		of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL);
1484259092a3SGrant Likely 
148562664f67SXiubo Li 	return rc;
148602af11b0SGrant Likely }
148702af11b0SGrant Likely 
1488d8c50088SPantelis Antoniou int __of_remove_property(struct device_node *np, struct property *prop)
1489d8c50088SPantelis Antoniou {
1490d8c50088SPantelis Antoniou 	struct property **next;
1491d8c50088SPantelis Antoniou 
1492d8c50088SPantelis Antoniou 	for (next = &np->properties; *next; next = &(*next)->next) {
1493d8c50088SPantelis Antoniou 		if (*next == prop)
1494d8c50088SPantelis Antoniou 			break;
1495d8c50088SPantelis Antoniou 	}
1496d8c50088SPantelis Antoniou 	if (*next == NULL)
1497d8c50088SPantelis Antoniou 		return -ENODEV;
1498d8c50088SPantelis Antoniou 
1499d8c50088SPantelis Antoniou 	/* found the node */
1500d8c50088SPantelis Antoniou 	*next = prop->next;
1501d8c50088SPantelis Antoniou 	prop->next = np->deadprops;
1502d8c50088SPantelis Antoniou 	np->deadprops = prop;
1503d8c50088SPantelis Antoniou 
1504d8c50088SPantelis Antoniou 	return 0;
1505d8c50088SPantelis Antoniou }
1506d8c50088SPantelis Antoniou 
1507d9fc8807SFrank Rowand void __of_sysfs_remove_bin_file(struct device_node *np, struct property *prop)
1508d9fc8807SFrank Rowand {
1509d9fc8807SFrank Rowand 	sysfs_remove_bin_file(&np->kobj, &prop->attr);
1510d9fc8807SFrank Rowand 	kfree(prop->attr.attr.name);
1511d9fc8807SFrank Rowand }
1512d9fc8807SFrank Rowand 
15138a2b22a2SGrant Likely void __of_remove_property_sysfs(struct device_node *np, struct property *prop)
15148a2b22a2SGrant Likely {
1515ef69d740SGaurav Minocha 	if (!IS_ENABLED(CONFIG_SYSFS))
1516ef69d740SGaurav Minocha 		return;
1517ef69d740SGaurav Minocha 
15188a2b22a2SGrant Likely 	/* at early boot, bail here and defer setup to of_init() */
15198a2b22a2SGrant Likely 	if (of_kset && of_node_is_attached(np))
1520d9fc8807SFrank Rowand 		__of_sysfs_remove_bin_file(np, prop);
15218a2b22a2SGrant Likely }
15228a2b22a2SGrant Likely 
152302af11b0SGrant Likely /**
152479d1c712SNathan Fontenot  * of_remove_property - Remove a property from a node.
152502af11b0SGrant Likely  *
152602af11b0SGrant Likely  * Note that we don't actually remove it, since we have given out
152702af11b0SGrant Likely  * who-knows-how-many pointers to the data using get-property.
152802af11b0SGrant Likely  * Instead we just move the property to the "dead properties"
152902af11b0SGrant Likely  * list, so it won't be found any more.
153002af11b0SGrant Likely  */
153179d1c712SNathan Fontenot int of_remove_property(struct device_node *np, struct property *prop)
153202af11b0SGrant Likely {
153302af11b0SGrant Likely 	unsigned long flags;
15341cf3d8b3SNathan Fontenot 	int rc;
15351cf3d8b3SNathan Fontenot 
1536201b3fe5SSuraj Jitindar Singh 	if (!prop)
1537201b3fe5SSuraj Jitindar Singh 		return -ENODEV;
1538201b3fe5SSuraj Jitindar Singh 
15398a2b22a2SGrant Likely 	mutex_lock(&of_mutex);
154002af11b0SGrant Likely 
1541d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
1542d8c50088SPantelis Antoniou 	rc = __of_remove_property(np, prop);
1543d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
154402af11b0SGrant Likely 
15458a2b22a2SGrant Likely 	if (!rc)
15468a2b22a2SGrant Likely 		__of_remove_property_sysfs(np, prop);
154702af11b0SGrant Likely 
15488a2b22a2SGrant Likely 	mutex_unlock(&of_mutex);
15498a2b22a2SGrant Likely 
1550259092a3SGrant Likely 	if (!rc)
1551259092a3SGrant Likely 		of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL);
1552259092a3SGrant Likely 
1553d8c50088SPantelis Antoniou 	return rc;
155402af11b0SGrant Likely }
155502af11b0SGrant Likely 
1556d8c50088SPantelis Antoniou int __of_update_property(struct device_node *np, struct property *newprop,
1557d8c50088SPantelis Antoniou 		struct property **oldpropp)
1558d8c50088SPantelis Antoniou {
1559d8c50088SPantelis Antoniou 	struct property **next, *oldprop;
1560d8c50088SPantelis Antoniou 
1561d8c50088SPantelis Antoniou 	for (next = &np->properties; *next; next = &(*next)->next) {
1562d8c50088SPantelis Antoniou 		if (of_prop_cmp((*next)->name, newprop->name) == 0)
1563d8c50088SPantelis Antoniou 			break;
1564d8c50088SPantelis Antoniou 	}
1565d8c50088SPantelis Antoniou 	*oldpropp = oldprop = *next;
1566d8c50088SPantelis Antoniou 
1567d8c50088SPantelis Antoniou 	if (oldprop) {
1568d8c50088SPantelis Antoniou 		/* replace the node */
1569d8c50088SPantelis Antoniou 		newprop->next = oldprop->next;
1570d8c50088SPantelis Antoniou 		*next = newprop;
1571d8c50088SPantelis Antoniou 		oldprop->next = np->deadprops;
1572d8c50088SPantelis Antoniou 		np->deadprops = oldprop;
1573d8c50088SPantelis Antoniou 	} else {
1574d8c50088SPantelis Antoniou 		/* new node */
1575d8c50088SPantelis Antoniou 		newprop->next = NULL;
1576d8c50088SPantelis Antoniou 		*next = newprop;
1577d8c50088SPantelis Antoniou 	}
1578d8c50088SPantelis Antoniou 
1579d8c50088SPantelis Antoniou 	return 0;
1580d8c50088SPantelis Antoniou }
1581d8c50088SPantelis Antoniou 
15828a2b22a2SGrant Likely void __of_update_property_sysfs(struct device_node *np, struct property *newprop,
15838a2b22a2SGrant Likely 		struct property *oldprop)
15848a2b22a2SGrant Likely {
1585ef69d740SGaurav Minocha 	if (!IS_ENABLED(CONFIG_SYSFS))
1586ef69d740SGaurav Minocha 		return;
1587ef69d740SGaurav Minocha 
15888a2b22a2SGrant Likely 	/* At early boot, bail out and defer setup to of_init() */
158902af11b0SGrant Likely 	if (!of_kset)
15908a2b22a2SGrant Likely 		return;
159102af11b0SGrant Likely 
15928a2b22a2SGrant Likely 	if (oldprop)
1593d9fc8807SFrank Rowand 		__of_sysfs_remove_bin_file(np, oldprop);
15948a2b22a2SGrant Likely 	__of_add_property_sysfs(np, newprop);
159502af11b0SGrant Likely }
159602af11b0SGrant Likely 
159702af11b0SGrant Likely /*
159879d1c712SNathan Fontenot  * of_update_property - Update a property in a node, if the property does
1599475d0094SDong Aisheng  * not exist, add it.
160002af11b0SGrant Likely  *
160102af11b0SGrant Likely  * Note that we don't actually remove it, since we have given out
160202af11b0SGrant Likely  * who-knows-how-many pointers to the data using get-property.
160302af11b0SGrant Likely  * Instead we just move the property to the "dead properties" list,
160402af11b0SGrant Likely  * and add the new property to the property list
160502af11b0SGrant Likely  */
160679d1c712SNathan Fontenot int of_update_property(struct device_node *np, struct property *newprop)
160702af11b0SGrant Likely {
1608d8c50088SPantelis Antoniou 	struct property *oldprop;
160902af11b0SGrant Likely 	unsigned long flags;
1610947fdaadSXiubo Li 	int rc;
16111cf3d8b3SNathan Fontenot 
1612475d0094SDong Aisheng 	if (!newprop->name)
1613475d0094SDong Aisheng 		return -EINVAL;
1614475d0094SDong Aisheng 
16158a2b22a2SGrant Likely 	mutex_lock(&of_mutex);
1616fcdeb7feSGrant Likely 
1617d6d3c4e6SThomas Gleixner 	raw_spin_lock_irqsave(&devtree_lock, flags);
1618d8c50088SPantelis Antoniou 	rc = __of_update_property(np, newprop, &oldprop);
1619d6d3c4e6SThomas Gleixner 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
1620e81b3295SNathan Fontenot 
16218a2b22a2SGrant Likely 	if (!rc)
16228a2b22a2SGrant Likely 		__of_update_property_sysfs(np, newprop, oldprop);
1623fcdeb7feSGrant Likely 
16248a2b22a2SGrant Likely 	mutex_unlock(&of_mutex);
16251cf3d8b3SNathan Fontenot 
1626259092a3SGrant Likely 	if (!rc)
1627259092a3SGrant Likely 		of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop);
1628fcdeb7feSGrant Likely 
16291cf3d8b3SNathan Fontenot 	return rc;
1630e81b3295SNathan Fontenot }
1631e81b3295SNathan Fontenot 
1632611cad72SShawn Guo static void of_alias_add(struct alias_prop *ap, struct device_node *np,
1633611cad72SShawn Guo 			 int id, const char *stem, int stem_len)
1634611cad72SShawn Guo {
1635611cad72SShawn Guo 	ap->np = np;
1636611cad72SShawn Guo 	ap->id = id;
1637611cad72SShawn Guo 	strncpy(ap->stem, stem, stem_len);
1638611cad72SShawn Guo 	ap->stem[stem_len] = 0;
1639611cad72SShawn Guo 	list_add_tail(&ap->link, &aliases_lookup);
16400d638a07SRob Herring 	pr_debug("adding DT alias:%s: stem=%s id=%i node=%pOF\n",
16410d638a07SRob Herring 		 ap->alias, ap->stem, ap->id, np);
1642611cad72SShawn Guo }
1643611cad72SShawn Guo 
1644611cad72SShawn Guo /**
16451821dda4SGeert Uytterhoeven  * of_alias_scan - Scan all properties of the 'aliases' node
1646611cad72SShawn Guo  *
16471821dda4SGeert Uytterhoeven  * The function scans all the properties of the 'aliases' node and populates
16481821dda4SGeert Uytterhoeven  * the global lookup table with the properties.  It returns the
16491821dda4SGeert Uytterhoeven  * number of alias properties found, or an error code in case of failure.
1650611cad72SShawn Guo  *
1651611cad72SShawn Guo  * @dt_alloc:	An allocator that provides a virtual address to memory
16521821dda4SGeert Uytterhoeven  *		for storing the resulting tree
1653611cad72SShawn Guo  */
1654611cad72SShawn Guo void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
1655611cad72SShawn Guo {
1656611cad72SShawn Guo 	struct property *pp;
1657611cad72SShawn Guo 
16587dbe5849SLaurentiu Tudor 	of_aliases = of_find_node_by_path("/aliases");
1659611cad72SShawn Guo 	of_chosen = of_find_node_by_path("/chosen");
1660611cad72SShawn Guo 	if (of_chosen == NULL)
1661611cad72SShawn Guo 		of_chosen = of_find_node_by_path("/chosen@0");
16625c19e952SSascha Hauer 
16635c19e952SSascha Hauer 	if (of_chosen) {
1664a752ee56SGrant Likely 		/* linux,stdout-path and /aliases/stdout are for legacy compatibility */
1665676e1b2fSGrant Likely 		const char *name = of_get_property(of_chosen, "stdout-path", NULL);
1666676e1b2fSGrant Likely 		if (!name)
16675c19e952SSascha Hauer 			name = of_get_property(of_chosen, "linux,stdout-path", NULL);
1668a752ee56SGrant Likely 		if (IS_ENABLED(CONFIG_PPC) && !name)
1669a752ee56SGrant Likely 			name = of_get_property(of_aliases, "stdout", NULL);
1670f64255b5SPeter Hurley 		if (name)
16717914a7c5SLeif Lindholm 			of_stdout = of_find_node_opts_by_path(name, &of_stdout_options);
16725c19e952SSascha Hauer 	}
16735c19e952SSascha Hauer 
1674611cad72SShawn Guo 	if (!of_aliases)
1675611cad72SShawn Guo 		return;
1676611cad72SShawn Guo 
16778af0da93SDong Aisheng 	for_each_property_of_node(of_aliases, pp) {
1678611cad72SShawn Guo 		const char *start = pp->name;
1679611cad72SShawn Guo 		const char *end = start + strlen(start);
1680611cad72SShawn Guo 		struct device_node *np;
1681611cad72SShawn Guo 		struct alias_prop *ap;
1682611cad72SShawn Guo 		int id, len;
1683611cad72SShawn Guo 
1684611cad72SShawn Guo 		/* Skip those we do not want to proceed */
1685611cad72SShawn Guo 		if (!strcmp(pp->name, "name") ||
1686611cad72SShawn Guo 		    !strcmp(pp->name, "phandle") ||
1687611cad72SShawn Guo 		    !strcmp(pp->name, "linux,phandle"))
1688611cad72SShawn Guo 			continue;
1689611cad72SShawn Guo 
1690611cad72SShawn Guo 		np = of_find_node_by_path(pp->value);
1691611cad72SShawn Guo 		if (!np)
1692611cad72SShawn Guo 			continue;
1693611cad72SShawn Guo 
1694611cad72SShawn Guo 		/* walk the alias backwards to extract the id and work out
1695611cad72SShawn Guo 		 * the 'stem' string */
1696611cad72SShawn Guo 		while (isdigit(*(end-1)) && end > start)
1697611cad72SShawn Guo 			end--;
1698611cad72SShawn Guo 		len = end - start;
1699611cad72SShawn Guo 
1700611cad72SShawn Guo 		if (kstrtoint(end, 10, &id) < 0)
1701611cad72SShawn Guo 			continue;
1702611cad72SShawn Guo 
1703611cad72SShawn Guo 		/* Allocate an alias_prop with enough space for the stem */
1704de96ec2aSPaul Burton 		ap = dt_alloc(sizeof(*ap) + len + 1, __alignof__(*ap));
1705611cad72SShawn Guo 		if (!ap)
1706611cad72SShawn Guo 			continue;
17070640332eSGrant Likely 		memset(ap, 0, sizeof(*ap) + len + 1);
1708611cad72SShawn Guo 		ap->alias = start;
1709611cad72SShawn Guo 		of_alias_add(ap, np, id, start, len);
1710611cad72SShawn Guo 	}
1711611cad72SShawn Guo }
1712611cad72SShawn Guo 
1713611cad72SShawn Guo /**
1714611cad72SShawn Guo  * of_alias_get_id - Get alias id for the given device_node
1715611cad72SShawn Guo  * @np:		Pointer to the given device_node
1716611cad72SShawn Guo  * @stem:	Alias stem of the given device_node
1717611cad72SShawn Guo  *
17185a53a07fSGeert Uytterhoeven  * The function travels the lookup table to get the alias id for the given
17195a53a07fSGeert Uytterhoeven  * device_node and alias stem.  It returns the alias id if found.
1720611cad72SShawn Guo  */
1721611cad72SShawn Guo int of_alias_get_id(struct device_node *np, const char *stem)
1722611cad72SShawn Guo {
1723611cad72SShawn Guo 	struct alias_prop *app;
1724611cad72SShawn Guo 	int id = -ENODEV;
1725611cad72SShawn Guo 
1726c05aba2bSPantelis Antoniou 	mutex_lock(&of_mutex);
1727611cad72SShawn Guo 	list_for_each_entry(app, &aliases_lookup, link) {
1728611cad72SShawn Guo 		if (strcmp(app->stem, stem) != 0)
1729611cad72SShawn Guo 			continue;
1730611cad72SShawn Guo 
1731611cad72SShawn Guo 		if (np == app->np) {
1732611cad72SShawn Guo 			id = app->id;
1733611cad72SShawn Guo 			break;
1734611cad72SShawn Guo 		}
1735611cad72SShawn Guo 	}
1736c05aba2bSPantelis Antoniou 	mutex_unlock(&of_mutex);
1737611cad72SShawn Guo 
1738611cad72SShawn Guo 	return id;
1739611cad72SShawn Guo }
1740611cad72SShawn Guo EXPORT_SYMBOL_GPL(of_alias_get_id);
1741c541adc6SStephen Warren 
1742351d224fSWolfram Sang /**
1743351d224fSWolfram Sang  * of_alias_get_highest_id - Get highest alias id for the given stem
1744351d224fSWolfram Sang  * @stem:	Alias stem to be examined
1745351d224fSWolfram Sang  *
1746351d224fSWolfram Sang  * The function travels the lookup table to get the highest alias id for the
1747351d224fSWolfram Sang  * given alias stem.  It returns the alias id if found.
1748351d224fSWolfram Sang  */
1749351d224fSWolfram Sang int of_alias_get_highest_id(const char *stem)
1750351d224fSWolfram Sang {
1751351d224fSWolfram Sang 	struct alias_prop *app;
1752351d224fSWolfram Sang 	int id = -ENODEV;
1753351d224fSWolfram Sang 
1754351d224fSWolfram Sang 	mutex_lock(&of_mutex);
1755351d224fSWolfram Sang 	list_for_each_entry(app, &aliases_lookup, link) {
1756351d224fSWolfram Sang 		if (strcmp(app->stem, stem) != 0)
1757351d224fSWolfram Sang 			continue;
1758351d224fSWolfram Sang 
1759351d224fSWolfram Sang 		if (app->id > id)
1760351d224fSWolfram Sang 			id = app->id;
1761351d224fSWolfram Sang 	}
1762351d224fSWolfram Sang 	mutex_unlock(&of_mutex);
1763351d224fSWolfram Sang 
1764351d224fSWolfram Sang 	return id;
1765351d224fSWolfram Sang }
1766351d224fSWolfram Sang EXPORT_SYMBOL_GPL(of_alias_get_highest_id);
1767351d224fSWolfram Sang 
17685c19e952SSascha Hauer /**
17693482f2c5SGrant Likely  * of_console_check() - Test and setup console for DT setup
17703482f2c5SGrant Likely  * @dn - Pointer to device node
17713482f2c5SGrant Likely  * @name - Name to use for preferred console without index. ex. "ttyS"
17723482f2c5SGrant Likely  * @index - Index to use for preferred console.
17735c19e952SSascha Hauer  *
17743482f2c5SGrant Likely  * Check if the given device node matches the stdout-path property in the
17753482f2c5SGrant Likely  * /chosen node. If it does then register it as the preferred console and return
17763482f2c5SGrant Likely  * TRUE. Otherwise return FALSE.
17775c19e952SSascha Hauer  */
17783482f2c5SGrant Likely bool of_console_check(struct device_node *dn, char *name, int index)
17795c19e952SSascha Hauer {
17803482f2c5SGrant Likely 	if (!dn || dn != of_stdout || console_set_on_cmdline)
17815c19e952SSascha Hauer 		return false;
17827914a7c5SLeif Lindholm 	return !add_preferred_console(name, index,
17837914a7c5SLeif Lindholm 				      kstrdup(of_stdout_options, GFP_KERNEL));
17845c19e952SSascha Hauer }
17853482f2c5SGrant Likely EXPORT_SYMBOL_GPL(of_console_check);
1786a3e31b45SSudeep KarkadaNagesha 
1787a3e31b45SSudeep KarkadaNagesha /**
1788a3e31b45SSudeep KarkadaNagesha  *	of_find_next_cache_node - Find a node's subsidiary cache
1789a3e31b45SSudeep KarkadaNagesha  *	@np:	node of type "cpu" or "cache"
1790a3e31b45SSudeep KarkadaNagesha  *
1791a3e31b45SSudeep KarkadaNagesha  *	Returns a node pointer with refcount incremented, use
1792a3e31b45SSudeep KarkadaNagesha  *	of_node_put() on it when done.  Caller should hold a reference
1793a3e31b45SSudeep KarkadaNagesha  *	to np.
1794a3e31b45SSudeep KarkadaNagesha  */
1795a3e31b45SSudeep KarkadaNagesha struct device_node *of_find_next_cache_node(const struct device_node *np)
1796a3e31b45SSudeep KarkadaNagesha {
179791d96749SRob Herring 	struct device_node *child, *cache_node;
1798a3e31b45SSudeep KarkadaNagesha 
179991d96749SRob Herring 	cache_node = of_parse_phandle(np, "l2-cache", 0);
180091d96749SRob Herring 	if (!cache_node)
180191d96749SRob Herring 		cache_node = of_parse_phandle(np, "next-level-cache", 0);
1802a3e31b45SSudeep KarkadaNagesha 
180391d96749SRob Herring 	if (cache_node)
180491d96749SRob Herring 		return cache_node;
1805a3e31b45SSudeep KarkadaNagesha 
1806a3e31b45SSudeep KarkadaNagesha 	/* OF on pmac has nodes instead of properties named "l2-cache"
1807a3e31b45SSudeep KarkadaNagesha 	 * beneath CPU nodes.
1808a3e31b45SSudeep KarkadaNagesha 	 */
1809a3e31b45SSudeep KarkadaNagesha 	if (!strcmp(np->type, "cpu"))
1810a3e31b45SSudeep KarkadaNagesha 		for_each_child_of_node(np, child)
1811a3e31b45SSudeep KarkadaNagesha 			if (!strcmp(child->type, "cache"))
1812a3e31b45SSudeep KarkadaNagesha 				return child;
1813a3e31b45SSudeep KarkadaNagesha 
1814a3e31b45SSudeep KarkadaNagesha 	return NULL;
1815a3e31b45SSudeep KarkadaNagesha }
1816fd9fdb78SPhilipp Zabel 
1817fd9fdb78SPhilipp Zabel /**
18185fa23530SSudeep Holla  * of_find_last_cache_level - Find the level at which the last cache is
18195fa23530SSudeep Holla  * 		present for the given logical cpu
18205fa23530SSudeep Holla  *
18215fa23530SSudeep Holla  * @cpu: cpu number(logical index) for which the last cache level is needed
18225fa23530SSudeep Holla  *
18235fa23530SSudeep Holla  * Returns the the level at which the last cache is present. It is exactly
18245fa23530SSudeep Holla  * same as  the total number of cache levels for the given logical cpu.
18255fa23530SSudeep Holla  */
18265fa23530SSudeep Holla int of_find_last_cache_level(unsigned int cpu)
18275fa23530SSudeep Holla {
18285fa23530SSudeep Holla 	u32 cache_level = 0;
18295fa23530SSudeep Holla 	struct device_node *prev = NULL, *np = of_cpu_device_node_get(cpu);
18305fa23530SSudeep Holla 
18315fa23530SSudeep Holla 	while (np) {
18325fa23530SSudeep Holla 		prev = np;
18335fa23530SSudeep Holla 		of_node_put(np);
18345fa23530SSudeep Holla 		np = of_find_next_cache_node(np);
18355fa23530SSudeep Holla 	}
18365fa23530SSudeep Holla 
18375fa23530SSudeep Holla 	of_property_read_u32(prev, "cache-level", &cache_level);
18385fa23530SSudeep Holla 
18395fa23530SSudeep Holla 	return cache_level;
18405fa23530SSudeep Holla }
1841