xref: /kernel/linux/linux-6.6/drivers/of/base.c (revision 62306a36)
162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Procedures for creating, accessing and interpreting the device tree.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Paul Mackerras	August 1996.
662306a36Sopenharmony_ci * Copyright (C) 1996-2005 Paul Mackerras.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
962306a36Sopenharmony_ci *    {engebret|bergner}@us.ibm.com
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci *  Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci *  Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and
1462306a36Sopenharmony_ci *  Grant Likely.
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#define pr_fmt(fmt)	"OF: " fmt
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include <linux/console.h>
2062306a36Sopenharmony_ci#include <linux/ctype.h>
2162306a36Sopenharmony_ci#include <linux/cpu.h>
2262306a36Sopenharmony_ci#include <linux/module.h>
2362306a36Sopenharmony_ci#include <linux/of.h>
2462306a36Sopenharmony_ci#include <linux/of_device.h>
2562306a36Sopenharmony_ci#include <linux/of_graph.h>
2662306a36Sopenharmony_ci#include <linux/spinlock.h>
2762306a36Sopenharmony_ci#include <linux/slab.h>
2862306a36Sopenharmony_ci#include <linux/string.h>
2962306a36Sopenharmony_ci#include <linux/proc_fs.h>
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#include "of_private.h"
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ciLIST_HEAD(aliases_lookup);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistruct device_node *of_root;
3662306a36Sopenharmony_ciEXPORT_SYMBOL(of_root);
3762306a36Sopenharmony_cistruct device_node *of_chosen;
3862306a36Sopenharmony_ciEXPORT_SYMBOL(of_chosen);
3962306a36Sopenharmony_cistruct device_node *of_aliases;
4062306a36Sopenharmony_cistruct device_node *of_stdout;
4162306a36Sopenharmony_cistatic const char *of_stdout_options;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistruct kset *of_kset;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci/*
4662306a36Sopenharmony_ci * Used to protect the of_aliases, to hold off addition of nodes to sysfs.
4762306a36Sopenharmony_ci * This mutex must be held whenever modifications are being made to the
4862306a36Sopenharmony_ci * device tree. The of_{attach,detach}_node() and
4962306a36Sopenharmony_ci * of_{add,remove,update}_property() helpers make sure this happens.
5062306a36Sopenharmony_ci */
5162306a36Sopenharmony_ciDEFINE_MUTEX(of_mutex);
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci/* use when traversing tree through the child, sibling,
5462306a36Sopenharmony_ci * or parent members of struct device_node.
5562306a36Sopenharmony_ci */
5662306a36Sopenharmony_ciDEFINE_RAW_SPINLOCK(devtree_lock);
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cibool of_node_name_eq(const struct device_node *np, const char *name)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	const char *node_name;
6162306a36Sopenharmony_ci	size_t len;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	if (!np)
6462306a36Sopenharmony_ci		return false;
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	node_name = kbasename(np->full_name);
6762306a36Sopenharmony_ci	len = strchrnul(node_name, '@') - node_name;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	return (strlen(name) == len) && (strncmp(node_name, name, len) == 0);
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ciEXPORT_SYMBOL(of_node_name_eq);
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_cibool of_node_name_prefix(const struct device_node *np, const char *prefix)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	if (!np)
7662306a36Sopenharmony_ci		return false;
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	return strncmp(kbasename(np->full_name), prefix, strlen(prefix)) == 0;
7962306a36Sopenharmony_ci}
8062306a36Sopenharmony_ciEXPORT_SYMBOL(of_node_name_prefix);
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic bool __of_node_is_type(const struct device_node *np, const char *type)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	const char *match = __of_get_property(np, "device_type", NULL);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	return np && match && type && !strcmp(match, type);
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ciint of_bus_n_addr_cells(struct device_node *np)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	u32 cells;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	for (; np; np = np->parent)
9462306a36Sopenharmony_ci		if (!of_property_read_u32(np, "#address-cells", &cells))
9562306a36Sopenharmony_ci			return cells;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	/* No #address-cells property for the root node */
9862306a36Sopenharmony_ci	return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ciint of_n_addr_cells(struct device_node *np)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	if (np->parent)
10462306a36Sopenharmony_ci		np = np->parent;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	return of_bus_n_addr_cells(np);
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ciEXPORT_SYMBOL(of_n_addr_cells);
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ciint of_bus_n_size_cells(struct device_node *np)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	u32 cells;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	for (; np; np = np->parent)
11562306a36Sopenharmony_ci		if (!of_property_read_u32(np, "#size-cells", &cells))
11662306a36Sopenharmony_ci			return cells;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	/* No #size-cells property for the root node */
11962306a36Sopenharmony_ci	return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
12062306a36Sopenharmony_ci}
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ciint of_n_size_cells(struct device_node *np)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	if (np->parent)
12562306a36Sopenharmony_ci		np = np->parent;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	return of_bus_n_size_cells(np);
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ciEXPORT_SYMBOL(of_n_size_cells);
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci#ifdef CONFIG_NUMA
13262306a36Sopenharmony_ciint __weak of_node_to_nid(struct device_node *np)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	return NUMA_NO_NODE;
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci#endif
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci#define OF_PHANDLE_CACHE_BITS	7
13962306a36Sopenharmony_ci#define OF_PHANDLE_CACHE_SZ	BIT(OF_PHANDLE_CACHE_BITS)
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic struct device_node *phandle_cache[OF_PHANDLE_CACHE_SZ];
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_cistatic u32 of_phandle_cache_hash(phandle handle)
14462306a36Sopenharmony_ci{
14562306a36Sopenharmony_ci	return hash_32(handle, OF_PHANDLE_CACHE_BITS);
14662306a36Sopenharmony_ci}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci/*
14962306a36Sopenharmony_ci * Caller must hold devtree_lock.
15062306a36Sopenharmony_ci */
15162306a36Sopenharmony_civoid __of_phandle_cache_inv_entry(phandle handle)
15262306a36Sopenharmony_ci{
15362306a36Sopenharmony_ci	u32 handle_hash;
15462306a36Sopenharmony_ci	struct device_node *np;
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	if (!handle)
15762306a36Sopenharmony_ci		return;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	handle_hash = of_phandle_cache_hash(handle);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	np = phandle_cache[handle_hash];
16262306a36Sopenharmony_ci	if (np && handle == np->phandle)
16362306a36Sopenharmony_ci		phandle_cache[handle_hash] = NULL;
16462306a36Sopenharmony_ci}
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_civoid __init of_core_init(void)
16762306a36Sopenharmony_ci{
16862306a36Sopenharmony_ci	struct device_node *np;
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	of_platform_register_reconfig_notifier();
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	/* Create the kset, and register existing nodes */
17362306a36Sopenharmony_ci	mutex_lock(&of_mutex);
17462306a36Sopenharmony_ci	of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);
17562306a36Sopenharmony_ci	if (!of_kset) {
17662306a36Sopenharmony_ci		mutex_unlock(&of_mutex);
17762306a36Sopenharmony_ci		pr_err("failed to register existing nodes\n");
17862306a36Sopenharmony_ci		return;
17962306a36Sopenharmony_ci	}
18062306a36Sopenharmony_ci	for_each_of_allnodes(np) {
18162306a36Sopenharmony_ci		__of_attach_node_sysfs(np);
18262306a36Sopenharmony_ci		if (np->phandle && !phandle_cache[of_phandle_cache_hash(np->phandle)])
18362306a36Sopenharmony_ci			phandle_cache[of_phandle_cache_hash(np->phandle)] = np;
18462306a36Sopenharmony_ci	}
18562306a36Sopenharmony_ci	mutex_unlock(&of_mutex);
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	/* Symlink in /proc as required by userspace ABI */
18862306a36Sopenharmony_ci	if (of_root)
18962306a36Sopenharmony_ci		proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");
19062306a36Sopenharmony_ci}
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_cistatic struct property *__of_find_property(const struct device_node *np,
19362306a36Sopenharmony_ci					   const char *name, int *lenp)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	struct property *pp;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	if (!np)
19862306a36Sopenharmony_ci		return NULL;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	for (pp = np->properties; pp; pp = pp->next) {
20162306a36Sopenharmony_ci		if (of_prop_cmp(pp->name, name) == 0) {
20262306a36Sopenharmony_ci			if (lenp)
20362306a36Sopenharmony_ci				*lenp = pp->length;
20462306a36Sopenharmony_ci			break;
20562306a36Sopenharmony_ci		}
20662306a36Sopenharmony_ci	}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	return pp;
20962306a36Sopenharmony_ci}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_cistruct property *of_find_property(const struct device_node *np,
21262306a36Sopenharmony_ci				  const char *name,
21362306a36Sopenharmony_ci				  int *lenp)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci	struct property *pp;
21662306a36Sopenharmony_ci	unsigned long flags;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
21962306a36Sopenharmony_ci	pp = __of_find_property(np, name, lenp);
22062306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	return pp;
22362306a36Sopenharmony_ci}
22462306a36Sopenharmony_ciEXPORT_SYMBOL(of_find_property);
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_cistruct device_node *__of_find_all_nodes(struct device_node *prev)
22762306a36Sopenharmony_ci{
22862306a36Sopenharmony_ci	struct device_node *np;
22962306a36Sopenharmony_ci	if (!prev) {
23062306a36Sopenharmony_ci		np = of_root;
23162306a36Sopenharmony_ci	} else if (prev->child) {
23262306a36Sopenharmony_ci		np = prev->child;
23362306a36Sopenharmony_ci	} else {
23462306a36Sopenharmony_ci		/* Walk back up looking for a sibling, or the end of the structure */
23562306a36Sopenharmony_ci		np = prev;
23662306a36Sopenharmony_ci		while (np->parent && !np->sibling)
23762306a36Sopenharmony_ci			np = np->parent;
23862306a36Sopenharmony_ci		np = np->sibling; /* Might be null at the end of the tree */
23962306a36Sopenharmony_ci	}
24062306a36Sopenharmony_ci	return np;
24162306a36Sopenharmony_ci}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci/**
24462306a36Sopenharmony_ci * of_find_all_nodes - Get next node in global list
24562306a36Sopenharmony_ci * @prev:	Previous node or NULL to start iteration
24662306a36Sopenharmony_ci *		of_node_put() will be called on it
24762306a36Sopenharmony_ci *
24862306a36Sopenharmony_ci * Return: A node pointer with refcount incremented, use
24962306a36Sopenharmony_ci * of_node_put() on it when done.
25062306a36Sopenharmony_ci */
25162306a36Sopenharmony_cistruct device_node *of_find_all_nodes(struct device_node *prev)
25262306a36Sopenharmony_ci{
25362306a36Sopenharmony_ci	struct device_node *np;
25462306a36Sopenharmony_ci	unsigned long flags;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
25762306a36Sopenharmony_ci	np = __of_find_all_nodes(prev);
25862306a36Sopenharmony_ci	of_node_get(np);
25962306a36Sopenharmony_ci	of_node_put(prev);
26062306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
26162306a36Sopenharmony_ci	return np;
26262306a36Sopenharmony_ci}
26362306a36Sopenharmony_ciEXPORT_SYMBOL(of_find_all_nodes);
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci/*
26662306a36Sopenharmony_ci * Find a property with a given name for a given node
26762306a36Sopenharmony_ci * and return the value.
26862306a36Sopenharmony_ci */
26962306a36Sopenharmony_ciconst void *__of_get_property(const struct device_node *np,
27062306a36Sopenharmony_ci			      const char *name, int *lenp)
27162306a36Sopenharmony_ci{
27262306a36Sopenharmony_ci	struct property *pp = __of_find_property(np, name, lenp);
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	return pp ? pp->value : NULL;
27562306a36Sopenharmony_ci}
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci/*
27862306a36Sopenharmony_ci * Find a property with a given name for a given node
27962306a36Sopenharmony_ci * and return the value.
28062306a36Sopenharmony_ci */
28162306a36Sopenharmony_ciconst void *of_get_property(const struct device_node *np, const char *name,
28262306a36Sopenharmony_ci			    int *lenp)
28362306a36Sopenharmony_ci{
28462306a36Sopenharmony_ci	struct property *pp = of_find_property(np, name, lenp);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	return pp ? pp->value : NULL;
28762306a36Sopenharmony_ci}
28862306a36Sopenharmony_ciEXPORT_SYMBOL(of_get_property);
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci/**
29162306a36Sopenharmony_ci * __of_device_is_compatible() - Check if the node matches given constraints
29262306a36Sopenharmony_ci * @device: pointer to node
29362306a36Sopenharmony_ci * @compat: required compatible string, NULL or "" for any match
29462306a36Sopenharmony_ci * @type: required device_type value, NULL or "" for any match
29562306a36Sopenharmony_ci * @name: required node name, NULL or "" for any match
29662306a36Sopenharmony_ci *
29762306a36Sopenharmony_ci * Checks if the given @compat, @type and @name strings match the
29862306a36Sopenharmony_ci * properties of the given @device. A constraints can be skipped by
29962306a36Sopenharmony_ci * passing NULL or an empty string as the constraint.
30062306a36Sopenharmony_ci *
30162306a36Sopenharmony_ci * Returns 0 for no match, and a positive integer on match. The return
30262306a36Sopenharmony_ci * value is a relative score with larger values indicating better
30362306a36Sopenharmony_ci * matches. The score is weighted for the most specific compatible value
30462306a36Sopenharmony_ci * to get the highest score. Matching type is next, followed by matching
30562306a36Sopenharmony_ci * name. Practically speaking, this results in the following priority
30662306a36Sopenharmony_ci * order for matches:
30762306a36Sopenharmony_ci *
30862306a36Sopenharmony_ci * 1. specific compatible && type && name
30962306a36Sopenharmony_ci * 2. specific compatible && type
31062306a36Sopenharmony_ci * 3. specific compatible && name
31162306a36Sopenharmony_ci * 4. specific compatible
31262306a36Sopenharmony_ci * 5. general compatible && type && name
31362306a36Sopenharmony_ci * 6. general compatible && type
31462306a36Sopenharmony_ci * 7. general compatible && name
31562306a36Sopenharmony_ci * 8. general compatible
31662306a36Sopenharmony_ci * 9. type && name
31762306a36Sopenharmony_ci * 10. type
31862306a36Sopenharmony_ci * 11. name
31962306a36Sopenharmony_ci */
32062306a36Sopenharmony_cistatic int __of_device_is_compatible(const struct device_node *device,
32162306a36Sopenharmony_ci				     const char *compat, const char *type, const char *name)
32262306a36Sopenharmony_ci{
32362306a36Sopenharmony_ci	struct property *prop;
32462306a36Sopenharmony_ci	const char *cp;
32562306a36Sopenharmony_ci	int index = 0, score = 0;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	/* Compatible match has highest priority */
32862306a36Sopenharmony_ci	if (compat && compat[0]) {
32962306a36Sopenharmony_ci		prop = __of_find_property(device, "compatible", NULL);
33062306a36Sopenharmony_ci		for (cp = of_prop_next_string(prop, NULL); cp;
33162306a36Sopenharmony_ci		     cp = of_prop_next_string(prop, cp), index++) {
33262306a36Sopenharmony_ci			if (of_compat_cmp(cp, compat, strlen(compat)) == 0) {
33362306a36Sopenharmony_ci				score = INT_MAX/2 - (index << 2);
33462306a36Sopenharmony_ci				break;
33562306a36Sopenharmony_ci			}
33662306a36Sopenharmony_ci		}
33762306a36Sopenharmony_ci		if (!score)
33862306a36Sopenharmony_ci			return 0;
33962306a36Sopenharmony_ci	}
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	/* Matching type is better than matching name */
34262306a36Sopenharmony_ci	if (type && type[0]) {
34362306a36Sopenharmony_ci		if (!__of_node_is_type(device, type))
34462306a36Sopenharmony_ci			return 0;
34562306a36Sopenharmony_ci		score += 2;
34662306a36Sopenharmony_ci	}
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	/* Matching name is a bit better than not */
34962306a36Sopenharmony_ci	if (name && name[0]) {
35062306a36Sopenharmony_ci		if (!of_node_name_eq(device, name))
35162306a36Sopenharmony_ci			return 0;
35262306a36Sopenharmony_ci		score++;
35362306a36Sopenharmony_ci	}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	return score;
35662306a36Sopenharmony_ci}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci/** Checks if the given "compat" string matches one of the strings in
35962306a36Sopenharmony_ci * the device's "compatible" property
36062306a36Sopenharmony_ci */
36162306a36Sopenharmony_ciint of_device_is_compatible(const struct device_node *device,
36262306a36Sopenharmony_ci		const char *compat)
36362306a36Sopenharmony_ci{
36462306a36Sopenharmony_ci	unsigned long flags;
36562306a36Sopenharmony_ci	int res;
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
36862306a36Sopenharmony_ci	res = __of_device_is_compatible(device, compat, NULL, NULL);
36962306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
37062306a36Sopenharmony_ci	return res;
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ciEXPORT_SYMBOL(of_device_is_compatible);
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci/** Checks if the device is compatible with any of the entries in
37562306a36Sopenharmony_ci *  a NULL terminated array of strings. Returns the best match
37662306a36Sopenharmony_ci *  score or 0.
37762306a36Sopenharmony_ci */
37862306a36Sopenharmony_ciint of_device_compatible_match(const struct device_node *device,
37962306a36Sopenharmony_ci			       const char *const *compat)
38062306a36Sopenharmony_ci{
38162306a36Sopenharmony_ci	unsigned int tmp, score = 0;
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	if (!compat)
38462306a36Sopenharmony_ci		return 0;
38562306a36Sopenharmony_ci
38662306a36Sopenharmony_ci	while (*compat) {
38762306a36Sopenharmony_ci		tmp = of_device_is_compatible(device, *compat);
38862306a36Sopenharmony_ci		if (tmp > score)
38962306a36Sopenharmony_ci			score = tmp;
39062306a36Sopenharmony_ci		compat++;
39162306a36Sopenharmony_ci	}
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	return score;
39462306a36Sopenharmony_ci}
39562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(of_device_compatible_match);
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci/**
39862306a36Sopenharmony_ci * of_machine_is_compatible - Test root of device tree for a given compatible value
39962306a36Sopenharmony_ci * @compat: compatible string to look for in root node's compatible property.
40062306a36Sopenharmony_ci *
40162306a36Sopenharmony_ci * Return: A positive integer if the root node has the given value in its
40262306a36Sopenharmony_ci * compatible property.
40362306a36Sopenharmony_ci */
40462306a36Sopenharmony_ciint of_machine_is_compatible(const char *compat)
40562306a36Sopenharmony_ci{
40662306a36Sopenharmony_ci	struct device_node *root;
40762306a36Sopenharmony_ci	int rc = 0;
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	root = of_find_node_by_path("/");
41062306a36Sopenharmony_ci	if (root) {
41162306a36Sopenharmony_ci		rc = of_device_is_compatible(root, compat);
41262306a36Sopenharmony_ci		of_node_put(root);
41362306a36Sopenharmony_ci	}
41462306a36Sopenharmony_ci	return rc;
41562306a36Sopenharmony_ci}
41662306a36Sopenharmony_ciEXPORT_SYMBOL(of_machine_is_compatible);
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci/**
41962306a36Sopenharmony_ci *  __of_device_is_available - check if a device is available for use
42062306a36Sopenharmony_ci *
42162306a36Sopenharmony_ci *  @device: Node to check for availability, with locks already held
42262306a36Sopenharmony_ci *
42362306a36Sopenharmony_ci *  Return: True if the status property is absent or set to "okay" or "ok",
42462306a36Sopenharmony_ci *  false otherwise
42562306a36Sopenharmony_ci */
42662306a36Sopenharmony_cistatic bool __of_device_is_available(const struct device_node *device)
42762306a36Sopenharmony_ci{
42862306a36Sopenharmony_ci	const char *status;
42962306a36Sopenharmony_ci	int statlen;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	if (!device)
43262306a36Sopenharmony_ci		return false;
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	status = __of_get_property(device, "status", &statlen);
43562306a36Sopenharmony_ci	if (status == NULL)
43662306a36Sopenharmony_ci		return true;
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	if (statlen > 0) {
43962306a36Sopenharmony_ci		if (!strcmp(status, "okay") || !strcmp(status, "ok"))
44062306a36Sopenharmony_ci			return true;
44162306a36Sopenharmony_ci	}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci	return false;
44462306a36Sopenharmony_ci}
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci/**
44762306a36Sopenharmony_ci *  of_device_is_available - check if a device is available for use
44862306a36Sopenharmony_ci *
44962306a36Sopenharmony_ci *  @device: Node to check for availability
45062306a36Sopenharmony_ci *
45162306a36Sopenharmony_ci *  Return: True if the status property is absent or set to "okay" or "ok",
45262306a36Sopenharmony_ci *  false otherwise
45362306a36Sopenharmony_ci */
45462306a36Sopenharmony_cibool of_device_is_available(const struct device_node *device)
45562306a36Sopenharmony_ci{
45662306a36Sopenharmony_ci	unsigned long flags;
45762306a36Sopenharmony_ci	bool res;
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
46062306a36Sopenharmony_ci	res = __of_device_is_available(device);
46162306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
46262306a36Sopenharmony_ci	return res;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci}
46562306a36Sopenharmony_ciEXPORT_SYMBOL(of_device_is_available);
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci/**
46862306a36Sopenharmony_ci *  __of_device_is_fail - check if a device has status "fail" or "fail-..."
46962306a36Sopenharmony_ci *
47062306a36Sopenharmony_ci *  @device: Node to check status for, with locks already held
47162306a36Sopenharmony_ci *
47262306a36Sopenharmony_ci *  Return: True if the status property is set to "fail" or "fail-..." (for any
47362306a36Sopenharmony_ci *  error code suffix), false otherwise
47462306a36Sopenharmony_ci */
47562306a36Sopenharmony_cistatic bool __of_device_is_fail(const struct device_node *device)
47662306a36Sopenharmony_ci{
47762306a36Sopenharmony_ci	const char *status;
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	if (!device)
48062306a36Sopenharmony_ci		return false;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	status = __of_get_property(device, "status", NULL);
48362306a36Sopenharmony_ci	if (status == NULL)
48462306a36Sopenharmony_ci		return false;
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	return !strcmp(status, "fail") || !strncmp(status, "fail-", 5);
48762306a36Sopenharmony_ci}
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci/**
49062306a36Sopenharmony_ci *  of_device_is_big_endian - check if a device has BE registers
49162306a36Sopenharmony_ci *
49262306a36Sopenharmony_ci *  @device: Node to check for endianness
49362306a36Sopenharmony_ci *
49462306a36Sopenharmony_ci *  Return: True if the device has a "big-endian" property, or if the kernel
49562306a36Sopenharmony_ci *  was compiled for BE *and* the device has a "native-endian" property.
49662306a36Sopenharmony_ci *  Returns false otherwise.
49762306a36Sopenharmony_ci *
49862306a36Sopenharmony_ci *  Callers would nominally use ioread32be/iowrite32be if
49962306a36Sopenharmony_ci *  of_device_is_big_endian() == true, or readl/writel otherwise.
50062306a36Sopenharmony_ci */
50162306a36Sopenharmony_cibool of_device_is_big_endian(const struct device_node *device)
50262306a36Sopenharmony_ci{
50362306a36Sopenharmony_ci	if (of_property_read_bool(device, "big-endian"))
50462306a36Sopenharmony_ci		return true;
50562306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) &&
50662306a36Sopenharmony_ci	    of_property_read_bool(device, "native-endian"))
50762306a36Sopenharmony_ci		return true;
50862306a36Sopenharmony_ci	return false;
50962306a36Sopenharmony_ci}
51062306a36Sopenharmony_ciEXPORT_SYMBOL(of_device_is_big_endian);
51162306a36Sopenharmony_ci
51262306a36Sopenharmony_ci/**
51362306a36Sopenharmony_ci * of_get_parent - Get a node's parent if any
51462306a36Sopenharmony_ci * @node:	Node to get parent
51562306a36Sopenharmony_ci *
51662306a36Sopenharmony_ci * Return: A node pointer with refcount incremented, use
51762306a36Sopenharmony_ci * of_node_put() on it when done.
51862306a36Sopenharmony_ci */
51962306a36Sopenharmony_cistruct device_node *of_get_parent(const struct device_node *node)
52062306a36Sopenharmony_ci{
52162306a36Sopenharmony_ci	struct device_node *np;
52262306a36Sopenharmony_ci	unsigned long flags;
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	if (!node)
52562306a36Sopenharmony_ci		return NULL;
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
52862306a36Sopenharmony_ci	np = of_node_get(node->parent);
52962306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
53062306a36Sopenharmony_ci	return np;
53162306a36Sopenharmony_ci}
53262306a36Sopenharmony_ciEXPORT_SYMBOL(of_get_parent);
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci/**
53562306a36Sopenharmony_ci * of_get_next_parent - Iterate to a node's parent
53662306a36Sopenharmony_ci * @node:	Node to get parent of
53762306a36Sopenharmony_ci *
53862306a36Sopenharmony_ci * This is like of_get_parent() except that it drops the
53962306a36Sopenharmony_ci * refcount on the passed node, making it suitable for iterating
54062306a36Sopenharmony_ci * through a node's parents.
54162306a36Sopenharmony_ci *
54262306a36Sopenharmony_ci * Return: A node pointer with refcount incremented, use
54362306a36Sopenharmony_ci * of_node_put() on it when done.
54462306a36Sopenharmony_ci */
54562306a36Sopenharmony_cistruct device_node *of_get_next_parent(struct device_node *node)
54662306a36Sopenharmony_ci{
54762306a36Sopenharmony_ci	struct device_node *parent;
54862306a36Sopenharmony_ci	unsigned long flags;
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	if (!node)
55162306a36Sopenharmony_ci		return NULL;
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
55462306a36Sopenharmony_ci	parent = of_node_get(node->parent);
55562306a36Sopenharmony_ci	of_node_put(node);
55662306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
55762306a36Sopenharmony_ci	return parent;
55862306a36Sopenharmony_ci}
55962306a36Sopenharmony_ciEXPORT_SYMBOL(of_get_next_parent);
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_cistatic struct device_node *__of_get_next_child(const struct device_node *node,
56262306a36Sopenharmony_ci						struct device_node *prev)
56362306a36Sopenharmony_ci{
56462306a36Sopenharmony_ci	struct device_node *next;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	if (!node)
56762306a36Sopenharmony_ci		return NULL;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	next = prev ? prev->sibling : node->child;
57062306a36Sopenharmony_ci	of_node_get(next);
57162306a36Sopenharmony_ci	of_node_put(prev);
57262306a36Sopenharmony_ci	return next;
57362306a36Sopenharmony_ci}
57462306a36Sopenharmony_ci#define __for_each_child_of_node(parent, child) \
57562306a36Sopenharmony_ci	for (child = __of_get_next_child(parent, NULL); child != NULL; \
57662306a36Sopenharmony_ci	     child = __of_get_next_child(parent, child))
57762306a36Sopenharmony_ci
57862306a36Sopenharmony_ci/**
57962306a36Sopenharmony_ci * of_get_next_child - Iterate a node childs
58062306a36Sopenharmony_ci * @node:	parent node
58162306a36Sopenharmony_ci * @prev:	previous child of the parent node, or NULL to get first
58262306a36Sopenharmony_ci *
58362306a36Sopenharmony_ci * Return: A node pointer with refcount incremented, use of_node_put() on
58462306a36Sopenharmony_ci * it when done. Returns NULL when prev is the last child. Decrements the
58562306a36Sopenharmony_ci * refcount of prev.
58662306a36Sopenharmony_ci */
58762306a36Sopenharmony_cistruct device_node *of_get_next_child(const struct device_node *node,
58862306a36Sopenharmony_ci	struct device_node *prev)
58962306a36Sopenharmony_ci{
59062306a36Sopenharmony_ci	struct device_node *next;
59162306a36Sopenharmony_ci	unsigned long flags;
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
59462306a36Sopenharmony_ci	next = __of_get_next_child(node, prev);
59562306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
59662306a36Sopenharmony_ci	return next;
59762306a36Sopenharmony_ci}
59862306a36Sopenharmony_ciEXPORT_SYMBOL(of_get_next_child);
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci/**
60162306a36Sopenharmony_ci * of_get_next_available_child - Find the next available child node
60262306a36Sopenharmony_ci * @node:	parent node
60362306a36Sopenharmony_ci * @prev:	previous child of the parent node, or NULL to get first
60462306a36Sopenharmony_ci *
60562306a36Sopenharmony_ci * This function is like of_get_next_child(), except that it
60662306a36Sopenharmony_ci * automatically skips any disabled nodes (i.e. status = "disabled").
60762306a36Sopenharmony_ci */
60862306a36Sopenharmony_cistruct device_node *of_get_next_available_child(const struct device_node *node,
60962306a36Sopenharmony_ci	struct device_node *prev)
61062306a36Sopenharmony_ci{
61162306a36Sopenharmony_ci	struct device_node *next;
61262306a36Sopenharmony_ci	unsigned long flags;
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	if (!node)
61562306a36Sopenharmony_ci		return NULL;
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
61862306a36Sopenharmony_ci	next = prev ? prev->sibling : node->child;
61962306a36Sopenharmony_ci	for (; next; next = next->sibling) {
62062306a36Sopenharmony_ci		if (!__of_device_is_available(next))
62162306a36Sopenharmony_ci			continue;
62262306a36Sopenharmony_ci		if (of_node_get(next))
62362306a36Sopenharmony_ci			break;
62462306a36Sopenharmony_ci	}
62562306a36Sopenharmony_ci	of_node_put(prev);
62662306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
62762306a36Sopenharmony_ci	return next;
62862306a36Sopenharmony_ci}
62962306a36Sopenharmony_ciEXPORT_SYMBOL(of_get_next_available_child);
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci/**
63262306a36Sopenharmony_ci * of_get_next_cpu_node - Iterate on cpu nodes
63362306a36Sopenharmony_ci * @prev:	previous child of the /cpus node, or NULL to get first
63462306a36Sopenharmony_ci *
63562306a36Sopenharmony_ci * Unusable CPUs (those with the status property set to "fail" or "fail-...")
63662306a36Sopenharmony_ci * will be skipped.
63762306a36Sopenharmony_ci *
63862306a36Sopenharmony_ci * Return: A cpu node pointer with refcount incremented, use of_node_put()
63962306a36Sopenharmony_ci * on it when done. Returns NULL when prev is the last child. Decrements
64062306a36Sopenharmony_ci * the refcount of prev.
64162306a36Sopenharmony_ci */
64262306a36Sopenharmony_cistruct device_node *of_get_next_cpu_node(struct device_node *prev)
64362306a36Sopenharmony_ci{
64462306a36Sopenharmony_ci	struct device_node *next = NULL;
64562306a36Sopenharmony_ci	unsigned long flags;
64662306a36Sopenharmony_ci	struct device_node *node;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	if (!prev)
64962306a36Sopenharmony_ci		node = of_find_node_by_path("/cpus");
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
65262306a36Sopenharmony_ci	if (prev)
65362306a36Sopenharmony_ci		next = prev->sibling;
65462306a36Sopenharmony_ci	else if (node) {
65562306a36Sopenharmony_ci		next = node->child;
65662306a36Sopenharmony_ci		of_node_put(node);
65762306a36Sopenharmony_ci	}
65862306a36Sopenharmony_ci	for (; next; next = next->sibling) {
65962306a36Sopenharmony_ci		if (__of_device_is_fail(next))
66062306a36Sopenharmony_ci			continue;
66162306a36Sopenharmony_ci		if (!(of_node_name_eq(next, "cpu") ||
66262306a36Sopenharmony_ci		      __of_node_is_type(next, "cpu")))
66362306a36Sopenharmony_ci			continue;
66462306a36Sopenharmony_ci		if (of_node_get(next))
66562306a36Sopenharmony_ci			break;
66662306a36Sopenharmony_ci	}
66762306a36Sopenharmony_ci	of_node_put(prev);
66862306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
66962306a36Sopenharmony_ci	return next;
67062306a36Sopenharmony_ci}
67162306a36Sopenharmony_ciEXPORT_SYMBOL(of_get_next_cpu_node);
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci/**
67462306a36Sopenharmony_ci * of_get_compatible_child - Find compatible child node
67562306a36Sopenharmony_ci * @parent:	parent node
67662306a36Sopenharmony_ci * @compatible:	compatible string
67762306a36Sopenharmony_ci *
67862306a36Sopenharmony_ci * Lookup child node whose compatible property contains the given compatible
67962306a36Sopenharmony_ci * string.
68062306a36Sopenharmony_ci *
68162306a36Sopenharmony_ci * Return: a node pointer with refcount incremented, use of_node_put() on it
68262306a36Sopenharmony_ci * when done; or NULL if not found.
68362306a36Sopenharmony_ci */
68462306a36Sopenharmony_cistruct device_node *of_get_compatible_child(const struct device_node *parent,
68562306a36Sopenharmony_ci				const char *compatible)
68662306a36Sopenharmony_ci{
68762306a36Sopenharmony_ci	struct device_node *child;
68862306a36Sopenharmony_ci
68962306a36Sopenharmony_ci	for_each_child_of_node(parent, child) {
69062306a36Sopenharmony_ci		if (of_device_is_compatible(child, compatible))
69162306a36Sopenharmony_ci			break;
69262306a36Sopenharmony_ci	}
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci	return child;
69562306a36Sopenharmony_ci}
69662306a36Sopenharmony_ciEXPORT_SYMBOL(of_get_compatible_child);
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci/**
69962306a36Sopenharmony_ci * of_get_child_by_name - Find the child node by name for a given parent
70062306a36Sopenharmony_ci * @node:	parent node
70162306a36Sopenharmony_ci * @name:	child name to look for.
70262306a36Sopenharmony_ci *
70362306a36Sopenharmony_ci * This function looks for child node for given matching name
70462306a36Sopenharmony_ci *
70562306a36Sopenharmony_ci * Return: A node pointer if found, with refcount incremented, use
70662306a36Sopenharmony_ci * of_node_put() on it when done.
70762306a36Sopenharmony_ci * Returns NULL if node is not found.
70862306a36Sopenharmony_ci */
70962306a36Sopenharmony_cistruct device_node *of_get_child_by_name(const struct device_node *node,
71062306a36Sopenharmony_ci				const char *name)
71162306a36Sopenharmony_ci{
71262306a36Sopenharmony_ci	struct device_node *child;
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ci	for_each_child_of_node(node, child)
71562306a36Sopenharmony_ci		if (of_node_name_eq(child, name))
71662306a36Sopenharmony_ci			break;
71762306a36Sopenharmony_ci	return child;
71862306a36Sopenharmony_ci}
71962306a36Sopenharmony_ciEXPORT_SYMBOL(of_get_child_by_name);
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_cistruct device_node *__of_find_node_by_path(struct device_node *parent,
72262306a36Sopenharmony_ci						const char *path)
72362306a36Sopenharmony_ci{
72462306a36Sopenharmony_ci	struct device_node *child;
72562306a36Sopenharmony_ci	int len;
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci	len = strcspn(path, "/:");
72862306a36Sopenharmony_ci	if (!len)
72962306a36Sopenharmony_ci		return NULL;
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	__for_each_child_of_node(parent, child) {
73262306a36Sopenharmony_ci		const char *name = kbasename(child->full_name);
73362306a36Sopenharmony_ci		if (strncmp(path, name, len) == 0 && (strlen(name) == len))
73462306a36Sopenharmony_ci			return child;
73562306a36Sopenharmony_ci	}
73662306a36Sopenharmony_ci	return NULL;
73762306a36Sopenharmony_ci}
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_cistruct device_node *__of_find_node_by_full_path(struct device_node *node,
74062306a36Sopenharmony_ci						const char *path)
74162306a36Sopenharmony_ci{
74262306a36Sopenharmony_ci	const char *separator = strchr(path, ':');
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci	while (node && *path == '/') {
74562306a36Sopenharmony_ci		struct device_node *tmp = node;
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ci		path++; /* Increment past '/' delimiter */
74862306a36Sopenharmony_ci		node = __of_find_node_by_path(node, path);
74962306a36Sopenharmony_ci		of_node_put(tmp);
75062306a36Sopenharmony_ci		path = strchrnul(path, '/');
75162306a36Sopenharmony_ci		if (separator && separator < path)
75262306a36Sopenharmony_ci			break;
75362306a36Sopenharmony_ci	}
75462306a36Sopenharmony_ci	return node;
75562306a36Sopenharmony_ci}
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci/**
75862306a36Sopenharmony_ci * of_find_node_opts_by_path - Find a node matching a full OF path
75962306a36Sopenharmony_ci * @path: Either the full path to match, or if the path does not
76062306a36Sopenharmony_ci *       start with '/', the name of a property of the /aliases
76162306a36Sopenharmony_ci *       node (an alias).  In the case of an alias, the node
76262306a36Sopenharmony_ci *       matching the alias' value will be returned.
76362306a36Sopenharmony_ci * @opts: Address of a pointer into which to store the start of
76462306a36Sopenharmony_ci *       an options string appended to the end of the path with
76562306a36Sopenharmony_ci *       a ':' separator.
76662306a36Sopenharmony_ci *
76762306a36Sopenharmony_ci * Valid paths:
76862306a36Sopenharmony_ci *  * /foo/bar	Full path
76962306a36Sopenharmony_ci *  * foo	Valid alias
77062306a36Sopenharmony_ci *  * foo/bar	Valid alias + relative path
77162306a36Sopenharmony_ci *
77262306a36Sopenharmony_ci * Return: A node pointer with refcount incremented, use
77362306a36Sopenharmony_ci * of_node_put() on it when done.
77462306a36Sopenharmony_ci */
77562306a36Sopenharmony_cistruct device_node *of_find_node_opts_by_path(const char *path, const char **opts)
77662306a36Sopenharmony_ci{
77762306a36Sopenharmony_ci	struct device_node *np = NULL;
77862306a36Sopenharmony_ci	struct property *pp;
77962306a36Sopenharmony_ci	unsigned long flags;
78062306a36Sopenharmony_ci	const char *separator = strchr(path, ':');
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	if (opts)
78362306a36Sopenharmony_ci		*opts = separator ? separator + 1 : NULL;
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	if (strcmp(path, "/") == 0)
78662306a36Sopenharmony_ci		return of_node_get(of_root);
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	/* The path could begin with an alias */
78962306a36Sopenharmony_ci	if (*path != '/') {
79062306a36Sopenharmony_ci		int len;
79162306a36Sopenharmony_ci		const char *p = separator;
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci		if (!p)
79462306a36Sopenharmony_ci			p = strchrnul(path, '/');
79562306a36Sopenharmony_ci		len = p - path;
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci		/* of_aliases must not be NULL */
79862306a36Sopenharmony_ci		if (!of_aliases)
79962306a36Sopenharmony_ci			return NULL;
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci		for_each_property_of_node(of_aliases, pp) {
80262306a36Sopenharmony_ci			if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) {
80362306a36Sopenharmony_ci				np = of_find_node_by_path(pp->value);
80462306a36Sopenharmony_ci				break;
80562306a36Sopenharmony_ci			}
80662306a36Sopenharmony_ci		}
80762306a36Sopenharmony_ci		if (!np)
80862306a36Sopenharmony_ci			return NULL;
80962306a36Sopenharmony_ci		path = p;
81062306a36Sopenharmony_ci	}
81162306a36Sopenharmony_ci
81262306a36Sopenharmony_ci	/* Step down the tree matching path components */
81362306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
81462306a36Sopenharmony_ci	if (!np)
81562306a36Sopenharmony_ci		np = of_node_get(of_root);
81662306a36Sopenharmony_ci	np = __of_find_node_by_full_path(np, path);
81762306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
81862306a36Sopenharmony_ci	return np;
81962306a36Sopenharmony_ci}
82062306a36Sopenharmony_ciEXPORT_SYMBOL(of_find_node_opts_by_path);
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci/**
82362306a36Sopenharmony_ci * of_find_node_by_name - Find a node by its "name" property
82462306a36Sopenharmony_ci * @from:	The node to start searching from or NULL; the node
82562306a36Sopenharmony_ci *		you pass will not be searched, only the next one
82662306a36Sopenharmony_ci *		will. Typically, you pass what the previous call
82762306a36Sopenharmony_ci *		returned. of_node_put() will be called on @from.
82862306a36Sopenharmony_ci * @name:	The name string to match against
82962306a36Sopenharmony_ci *
83062306a36Sopenharmony_ci * Return: A node pointer with refcount incremented, use
83162306a36Sopenharmony_ci * of_node_put() on it when done.
83262306a36Sopenharmony_ci */
83362306a36Sopenharmony_cistruct device_node *of_find_node_by_name(struct device_node *from,
83462306a36Sopenharmony_ci	const char *name)
83562306a36Sopenharmony_ci{
83662306a36Sopenharmony_ci	struct device_node *np;
83762306a36Sopenharmony_ci	unsigned long flags;
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
84062306a36Sopenharmony_ci	for_each_of_allnodes_from(from, np)
84162306a36Sopenharmony_ci		if (of_node_name_eq(np, name) && of_node_get(np))
84262306a36Sopenharmony_ci			break;
84362306a36Sopenharmony_ci	of_node_put(from);
84462306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
84562306a36Sopenharmony_ci	return np;
84662306a36Sopenharmony_ci}
84762306a36Sopenharmony_ciEXPORT_SYMBOL(of_find_node_by_name);
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci/**
85062306a36Sopenharmony_ci * of_find_node_by_type - Find a node by its "device_type" property
85162306a36Sopenharmony_ci * @from:	The node to start searching from, or NULL to start searching
85262306a36Sopenharmony_ci *		the entire device tree. The node you pass will not be
85362306a36Sopenharmony_ci *		searched, only the next one will; typically, you pass
85462306a36Sopenharmony_ci *		what the previous call returned. of_node_put() will be
85562306a36Sopenharmony_ci *		called on from for you.
85662306a36Sopenharmony_ci * @type:	The type string to match against
85762306a36Sopenharmony_ci *
85862306a36Sopenharmony_ci * Return: A node pointer with refcount incremented, use
85962306a36Sopenharmony_ci * of_node_put() on it when done.
86062306a36Sopenharmony_ci */
86162306a36Sopenharmony_cistruct device_node *of_find_node_by_type(struct device_node *from,
86262306a36Sopenharmony_ci	const char *type)
86362306a36Sopenharmony_ci{
86462306a36Sopenharmony_ci	struct device_node *np;
86562306a36Sopenharmony_ci	unsigned long flags;
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
86862306a36Sopenharmony_ci	for_each_of_allnodes_from(from, np)
86962306a36Sopenharmony_ci		if (__of_node_is_type(np, type) && of_node_get(np))
87062306a36Sopenharmony_ci			break;
87162306a36Sopenharmony_ci	of_node_put(from);
87262306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
87362306a36Sopenharmony_ci	return np;
87462306a36Sopenharmony_ci}
87562306a36Sopenharmony_ciEXPORT_SYMBOL(of_find_node_by_type);
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci/**
87862306a36Sopenharmony_ci * of_find_compatible_node - Find a node based on type and one of the
87962306a36Sopenharmony_ci *                                tokens in its "compatible" property
88062306a36Sopenharmony_ci * @from:	The node to start searching from or NULL, the node
88162306a36Sopenharmony_ci *		you pass will not be searched, only the next one
88262306a36Sopenharmony_ci *		will; typically, you pass what the previous call
88362306a36Sopenharmony_ci *		returned. of_node_put() will be called on it
88462306a36Sopenharmony_ci * @type:	The type string to match "device_type" or NULL to ignore
88562306a36Sopenharmony_ci * @compatible:	The string to match to one of the tokens in the device
88662306a36Sopenharmony_ci *		"compatible" list.
88762306a36Sopenharmony_ci *
88862306a36Sopenharmony_ci * Return: A node pointer with refcount incremented, use
88962306a36Sopenharmony_ci * of_node_put() on it when done.
89062306a36Sopenharmony_ci */
89162306a36Sopenharmony_cistruct device_node *of_find_compatible_node(struct device_node *from,
89262306a36Sopenharmony_ci	const char *type, const char *compatible)
89362306a36Sopenharmony_ci{
89462306a36Sopenharmony_ci	struct device_node *np;
89562306a36Sopenharmony_ci	unsigned long flags;
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
89862306a36Sopenharmony_ci	for_each_of_allnodes_from(from, np)
89962306a36Sopenharmony_ci		if (__of_device_is_compatible(np, compatible, type, NULL) &&
90062306a36Sopenharmony_ci		    of_node_get(np))
90162306a36Sopenharmony_ci			break;
90262306a36Sopenharmony_ci	of_node_put(from);
90362306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
90462306a36Sopenharmony_ci	return np;
90562306a36Sopenharmony_ci}
90662306a36Sopenharmony_ciEXPORT_SYMBOL(of_find_compatible_node);
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_ci/**
90962306a36Sopenharmony_ci * of_find_node_with_property - Find a node which has a property with
91062306a36Sopenharmony_ci *                              the given name.
91162306a36Sopenharmony_ci * @from:	The node to start searching from or NULL, the node
91262306a36Sopenharmony_ci *		you pass will not be searched, only the next one
91362306a36Sopenharmony_ci *		will; typically, you pass what the previous call
91462306a36Sopenharmony_ci *		returned. of_node_put() will be called on it
91562306a36Sopenharmony_ci * @prop_name:	The name of the property to look for.
91662306a36Sopenharmony_ci *
91762306a36Sopenharmony_ci * Return: A node pointer with refcount incremented, use
91862306a36Sopenharmony_ci * of_node_put() on it when done.
91962306a36Sopenharmony_ci */
92062306a36Sopenharmony_cistruct device_node *of_find_node_with_property(struct device_node *from,
92162306a36Sopenharmony_ci	const char *prop_name)
92262306a36Sopenharmony_ci{
92362306a36Sopenharmony_ci	struct device_node *np;
92462306a36Sopenharmony_ci	struct property *pp;
92562306a36Sopenharmony_ci	unsigned long flags;
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
92862306a36Sopenharmony_ci	for_each_of_allnodes_from(from, np) {
92962306a36Sopenharmony_ci		for (pp = np->properties; pp; pp = pp->next) {
93062306a36Sopenharmony_ci			if (of_prop_cmp(pp->name, prop_name) == 0) {
93162306a36Sopenharmony_ci				of_node_get(np);
93262306a36Sopenharmony_ci				goto out;
93362306a36Sopenharmony_ci			}
93462306a36Sopenharmony_ci		}
93562306a36Sopenharmony_ci	}
93662306a36Sopenharmony_ciout:
93762306a36Sopenharmony_ci	of_node_put(from);
93862306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
93962306a36Sopenharmony_ci	return np;
94062306a36Sopenharmony_ci}
94162306a36Sopenharmony_ciEXPORT_SYMBOL(of_find_node_with_property);
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_cistatic
94462306a36Sopenharmony_ciconst struct of_device_id *__of_match_node(const struct of_device_id *matches,
94562306a36Sopenharmony_ci					   const struct device_node *node)
94662306a36Sopenharmony_ci{
94762306a36Sopenharmony_ci	const struct of_device_id *best_match = NULL;
94862306a36Sopenharmony_ci	int score, best_score = 0;
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci	if (!matches)
95162306a36Sopenharmony_ci		return NULL;
95262306a36Sopenharmony_ci
95362306a36Sopenharmony_ci	for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) {
95462306a36Sopenharmony_ci		score = __of_device_is_compatible(node, matches->compatible,
95562306a36Sopenharmony_ci						  matches->type, matches->name);
95662306a36Sopenharmony_ci		if (score > best_score) {
95762306a36Sopenharmony_ci			best_match = matches;
95862306a36Sopenharmony_ci			best_score = score;
95962306a36Sopenharmony_ci		}
96062306a36Sopenharmony_ci	}
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci	return best_match;
96362306a36Sopenharmony_ci}
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci/**
96662306a36Sopenharmony_ci * of_match_node - Tell if a device_node has a matching of_match structure
96762306a36Sopenharmony_ci * @matches:	array of of device match structures to search in
96862306a36Sopenharmony_ci * @node:	the of device structure to match against
96962306a36Sopenharmony_ci *
97062306a36Sopenharmony_ci * Low level utility function used by device matching.
97162306a36Sopenharmony_ci */
97262306a36Sopenharmony_ciconst struct of_device_id *of_match_node(const struct of_device_id *matches,
97362306a36Sopenharmony_ci					 const struct device_node *node)
97462306a36Sopenharmony_ci{
97562306a36Sopenharmony_ci	const struct of_device_id *match;
97662306a36Sopenharmony_ci	unsigned long flags;
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
97962306a36Sopenharmony_ci	match = __of_match_node(matches, node);
98062306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
98162306a36Sopenharmony_ci	return match;
98262306a36Sopenharmony_ci}
98362306a36Sopenharmony_ciEXPORT_SYMBOL(of_match_node);
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci/**
98662306a36Sopenharmony_ci * of_find_matching_node_and_match - Find a node based on an of_device_id
98762306a36Sopenharmony_ci *				     match table.
98862306a36Sopenharmony_ci * @from:	The node to start searching from or NULL, the node
98962306a36Sopenharmony_ci *		you pass will not be searched, only the next one
99062306a36Sopenharmony_ci *		will; typically, you pass what the previous call
99162306a36Sopenharmony_ci *		returned. of_node_put() will be called on it
99262306a36Sopenharmony_ci * @matches:	array of of device match structures to search in
99362306a36Sopenharmony_ci * @match:	Updated to point at the matches entry which matched
99462306a36Sopenharmony_ci *
99562306a36Sopenharmony_ci * Return: A node pointer with refcount incremented, use
99662306a36Sopenharmony_ci * of_node_put() on it when done.
99762306a36Sopenharmony_ci */
99862306a36Sopenharmony_cistruct device_node *of_find_matching_node_and_match(struct device_node *from,
99962306a36Sopenharmony_ci					const struct of_device_id *matches,
100062306a36Sopenharmony_ci					const struct of_device_id **match)
100162306a36Sopenharmony_ci{
100262306a36Sopenharmony_ci	struct device_node *np;
100362306a36Sopenharmony_ci	const struct of_device_id *m;
100462306a36Sopenharmony_ci	unsigned long flags;
100562306a36Sopenharmony_ci
100662306a36Sopenharmony_ci	if (match)
100762306a36Sopenharmony_ci		*match = NULL;
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
101062306a36Sopenharmony_ci	for_each_of_allnodes_from(from, np) {
101162306a36Sopenharmony_ci		m = __of_match_node(matches, np);
101262306a36Sopenharmony_ci		if (m && of_node_get(np)) {
101362306a36Sopenharmony_ci			if (match)
101462306a36Sopenharmony_ci				*match = m;
101562306a36Sopenharmony_ci			break;
101662306a36Sopenharmony_ci		}
101762306a36Sopenharmony_ci	}
101862306a36Sopenharmony_ci	of_node_put(from);
101962306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
102062306a36Sopenharmony_ci	return np;
102162306a36Sopenharmony_ci}
102262306a36Sopenharmony_ciEXPORT_SYMBOL(of_find_matching_node_and_match);
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci/**
102562306a36Sopenharmony_ci * of_alias_from_compatible - Lookup appropriate alias for a device node
102662306a36Sopenharmony_ci *			      depending on compatible
102762306a36Sopenharmony_ci * @node:	pointer to a device tree node
102862306a36Sopenharmony_ci * @alias:	Pointer to buffer that alias value will be copied into
102962306a36Sopenharmony_ci * @len:	Length of alias value
103062306a36Sopenharmony_ci *
103162306a36Sopenharmony_ci * Based on the value of the compatible property, this routine will attempt
103262306a36Sopenharmony_ci * to choose an appropriate alias value for a particular device tree node.
103362306a36Sopenharmony_ci * It does this by stripping the manufacturer prefix (as delimited by a ',')
103462306a36Sopenharmony_ci * from the first entry in the compatible list property.
103562306a36Sopenharmony_ci *
103662306a36Sopenharmony_ci * Note: The matching on just the "product" side of the compatible is a relic
103762306a36Sopenharmony_ci * from I2C and SPI. Please do not add any new user.
103862306a36Sopenharmony_ci *
103962306a36Sopenharmony_ci * Return: This routine returns 0 on success, <0 on failure.
104062306a36Sopenharmony_ci */
104162306a36Sopenharmony_ciint of_alias_from_compatible(const struct device_node *node, char *alias, int len)
104262306a36Sopenharmony_ci{
104362306a36Sopenharmony_ci	const char *compatible, *p;
104462306a36Sopenharmony_ci	int cplen;
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_ci	compatible = of_get_property(node, "compatible", &cplen);
104762306a36Sopenharmony_ci	if (!compatible || strlen(compatible) > cplen)
104862306a36Sopenharmony_ci		return -ENODEV;
104962306a36Sopenharmony_ci	p = strchr(compatible, ',');
105062306a36Sopenharmony_ci	strscpy(alias, p ? p + 1 : compatible, len);
105162306a36Sopenharmony_ci	return 0;
105262306a36Sopenharmony_ci}
105362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(of_alias_from_compatible);
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_ci/**
105662306a36Sopenharmony_ci * of_find_node_by_phandle - Find a node given a phandle
105762306a36Sopenharmony_ci * @handle:	phandle of the node to find
105862306a36Sopenharmony_ci *
105962306a36Sopenharmony_ci * Return: A node pointer with refcount incremented, use
106062306a36Sopenharmony_ci * of_node_put() on it when done.
106162306a36Sopenharmony_ci */
106262306a36Sopenharmony_cistruct device_node *of_find_node_by_phandle(phandle handle)
106362306a36Sopenharmony_ci{
106462306a36Sopenharmony_ci	struct device_node *np = NULL;
106562306a36Sopenharmony_ci	unsigned long flags;
106662306a36Sopenharmony_ci	u32 handle_hash;
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_ci	if (!handle)
106962306a36Sopenharmony_ci		return NULL;
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	handle_hash = of_phandle_cache_hash(handle);
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ci	if (phandle_cache[handle_hash] &&
107662306a36Sopenharmony_ci	    handle == phandle_cache[handle_hash]->phandle)
107762306a36Sopenharmony_ci		np = phandle_cache[handle_hash];
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci	if (!np) {
108062306a36Sopenharmony_ci		for_each_of_allnodes(np)
108162306a36Sopenharmony_ci			if (np->phandle == handle &&
108262306a36Sopenharmony_ci			    !of_node_check_flag(np, OF_DETACHED)) {
108362306a36Sopenharmony_ci				phandle_cache[handle_hash] = np;
108462306a36Sopenharmony_ci				break;
108562306a36Sopenharmony_ci			}
108662306a36Sopenharmony_ci	}
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_ci	of_node_get(np);
108962306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
109062306a36Sopenharmony_ci	return np;
109162306a36Sopenharmony_ci}
109262306a36Sopenharmony_ciEXPORT_SYMBOL(of_find_node_by_phandle);
109362306a36Sopenharmony_ci
109462306a36Sopenharmony_civoid of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
109562306a36Sopenharmony_ci{
109662306a36Sopenharmony_ci	int i;
109762306a36Sopenharmony_ci	printk("%s %pOF", msg, args->np);
109862306a36Sopenharmony_ci	for (i = 0; i < args->args_count; i++) {
109962306a36Sopenharmony_ci		const char delim = i ? ',' : ':';
110062306a36Sopenharmony_ci
110162306a36Sopenharmony_ci		pr_cont("%c%08x", delim, args->args[i]);
110262306a36Sopenharmony_ci	}
110362306a36Sopenharmony_ci	pr_cont("\n");
110462306a36Sopenharmony_ci}
110562306a36Sopenharmony_ci
110662306a36Sopenharmony_ciint of_phandle_iterator_init(struct of_phandle_iterator *it,
110762306a36Sopenharmony_ci		const struct device_node *np,
110862306a36Sopenharmony_ci		const char *list_name,
110962306a36Sopenharmony_ci		const char *cells_name,
111062306a36Sopenharmony_ci		int cell_count)
111162306a36Sopenharmony_ci{
111262306a36Sopenharmony_ci	const __be32 *list;
111362306a36Sopenharmony_ci	int size;
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci	memset(it, 0, sizeof(*it));
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_ci	/*
111862306a36Sopenharmony_ci	 * one of cell_count or cells_name must be provided to determine the
111962306a36Sopenharmony_ci	 * argument length.
112062306a36Sopenharmony_ci	 */
112162306a36Sopenharmony_ci	if (cell_count < 0 && !cells_name)
112262306a36Sopenharmony_ci		return -EINVAL;
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci	list = of_get_property(np, list_name, &size);
112562306a36Sopenharmony_ci	if (!list)
112662306a36Sopenharmony_ci		return -ENOENT;
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	it->cells_name = cells_name;
112962306a36Sopenharmony_ci	it->cell_count = cell_count;
113062306a36Sopenharmony_ci	it->parent = np;
113162306a36Sopenharmony_ci	it->list_end = list + size / sizeof(*list);
113262306a36Sopenharmony_ci	it->phandle_end = list;
113362306a36Sopenharmony_ci	it->cur = list;
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	return 0;
113662306a36Sopenharmony_ci}
113762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(of_phandle_iterator_init);
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_ciint of_phandle_iterator_next(struct of_phandle_iterator *it)
114062306a36Sopenharmony_ci{
114162306a36Sopenharmony_ci	uint32_t count = 0;
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci	if (it->node) {
114462306a36Sopenharmony_ci		of_node_put(it->node);
114562306a36Sopenharmony_ci		it->node = NULL;
114662306a36Sopenharmony_ci	}
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	if (!it->cur || it->phandle_end >= it->list_end)
114962306a36Sopenharmony_ci		return -ENOENT;
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	it->cur = it->phandle_end;
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	/* If phandle is 0, then it is an empty entry with no arguments. */
115462306a36Sopenharmony_ci	it->phandle = be32_to_cpup(it->cur++);
115562306a36Sopenharmony_ci
115662306a36Sopenharmony_ci	if (it->phandle) {
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci		/*
115962306a36Sopenharmony_ci		 * Find the provider node and parse the #*-cells property to
116062306a36Sopenharmony_ci		 * determine the argument length.
116162306a36Sopenharmony_ci		 */
116262306a36Sopenharmony_ci		it->node = of_find_node_by_phandle(it->phandle);
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci		if (it->cells_name) {
116562306a36Sopenharmony_ci			if (!it->node) {
116662306a36Sopenharmony_ci				pr_err("%pOF: could not find phandle %d\n",
116762306a36Sopenharmony_ci				       it->parent, it->phandle);
116862306a36Sopenharmony_ci				goto err;
116962306a36Sopenharmony_ci			}
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_ci			if (of_property_read_u32(it->node, it->cells_name,
117262306a36Sopenharmony_ci						 &count)) {
117362306a36Sopenharmony_ci				/*
117462306a36Sopenharmony_ci				 * If both cell_count and cells_name is given,
117562306a36Sopenharmony_ci				 * fall back to cell_count in absence
117662306a36Sopenharmony_ci				 * of the cells_name property
117762306a36Sopenharmony_ci				 */
117862306a36Sopenharmony_ci				if (it->cell_count >= 0) {
117962306a36Sopenharmony_ci					count = it->cell_count;
118062306a36Sopenharmony_ci				} else {
118162306a36Sopenharmony_ci					pr_err("%pOF: could not get %s for %pOF\n",
118262306a36Sopenharmony_ci					       it->parent,
118362306a36Sopenharmony_ci					       it->cells_name,
118462306a36Sopenharmony_ci					       it->node);
118562306a36Sopenharmony_ci					goto err;
118662306a36Sopenharmony_ci				}
118762306a36Sopenharmony_ci			}
118862306a36Sopenharmony_ci		} else {
118962306a36Sopenharmony_ci			count = it->cell_count;
119062306a36Sopenharmony_ci		}
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_ci		/*
119362306a36Sopenharmony_ci		 * Make sure that the arguments actually fit in the remaining
119462306a36Sopenharmony_ci		 * property data length
119562306a36Sopenharmony_ci		 */
119662306a36Sopenharmony_ci		if (it->cur + count > it->list_end) {
119762306a36Sopenharmony_ci			if (it->cells_name)
119862306a36Sopenharmony_ci				pr_err("%pOF: %s = %d found %td\n",
119962306a36Sopenharmony_ci					it->parent, it->cells_name,
120062306a36Sopenharmony_ci					count, it->list_end - it->cur);
120162306a36Sopenharmony_ci			else
120262306a36Sopenharmony_ci				pr_err("%pOF: phandle %s needs %d, found %td\n",
120362306a36Sopenharmony_ci					it->parent, of_node_full_name(it->node),
120462306a36Sopenharmony_ci					count, it->list_end - it->cur);
120562306a36Sopenharmony_ci			goto err;
120662306a36Sopenharmony_ci		}
120762306a36Sopenharmony_ci	}
120862306a36Sopenharmony_ci
120962306a36Sopenharmony_ci	it->phandle_end = it->cur + count;
121062306a36Sopenharmony_ci	it->cur_count = count;
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci	return 0;
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_cierr:
121562306a36Sopenharmony_ci	if (it->node) {
121662306a36Sopenharmony_ci		of_node_put(it->node);
121762306a36Sopenharmony_ci		it->node = NULL;
121862306a36Sopenharmony_ci	}
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci	return -EINVAL;
122162306a36Sopenharmony_ci}
122262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(of_phandle_iterator_next);
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ciint of_phandle_iterator_args(struct of_phandle_iterator *it,
122562306a36Sopenharmony_ci			     uint32_t *args,
122662306a36Sopenharmony_ci			     int size)
122762306a36Sopenharmony_ci{
122862306a36Sopenharmony_ci	int i, count;
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	count = it->cur_count;
123162306a36Sopenharmony_ci
123262306a36Sopenharmony_ci	if (WARN_ON(size < count))
123362306a36Sopenharmony_ci		count = size;
123462306a36Sopenharmony_ci
123562306a36Sopenharmony_ci	for (i = 0; i < count; i++)
123662306a36Sopenharmony_ci		args[i] = be32_to_cpup(it->cur++);
123762306a36Sopenharmony_ci
123862306a36Sopenharmony_ci	return count;
123962306a36Sopenharmony_ci}
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ciint __of_parse_phandle_with_args(const struct device_node *np,
124262306a36Sopenharmony_ci				 const char *list_name,
124362306a36Sopenharmony_ci				 const char *cells_name,
124462306a36Sopenharmony_ci				 int cell_count, int index,
124562306a36Sopenharmony_ci				 struct of_phandle_args *out_args)
124662306a36Sopenharmony_ci{
124762306a36Sopenharmony_ci	struct of_phandle_iterator it;
124862306a36Sopenharmony_ci	int rc, cur_index = 0;
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci	if (index < 0)
125162306a36Sopenharmony_ci		return -EINVAL;
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_ci	/* Loop over the phandles until all the requested entry is found */
125462306a36Sopenharmony_ci	of_for_each_phandle(&it, rc, np, list_name, cells_name, cell_count) {
125562306a36Sopenharmony_ci		/*
125662306a36Sopenharmony_ci		 * All of the error cases bail out of the loop, so at
125762306a36Sopenharmony_ci		 * this point, the parsing is successful. If the requested
125862306a36Sopenharmony_ci		 * index matches, then fill the out_args structure and return,
125962306a36Sopenharmony_ci		 * or return -ENOENT for an empty entry.
126062306a36Sopenharmony_ci		 */
126162306a36Sopenharmony_ci		rc = -ENOENT;
126262306a36Sopenharmony_ci		if (cur_index == index) {
126362306a36Sopenharmony_ci			if (!it.phandle)
126462306a36Sopenharmony_ci				goto err;
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_ci			if (out_args) {
126762306a36Sopenharmony_ci				int c;
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci				c = of_phandle_iterator_args(&it,
127062306a36Sopenharmony_ci							     out_args->args,
127162306a36Sopenharmony_ci							     MAX_PHANDLE_ARGS);
127262306a36Sopenharmony_ci				out_args->np = it.node;
127362306a36Sopenharmony_ci				out_args->args_count = c;
127462306a36Sopenharmony_ci			} else {
127562306a36Sopenharmony_ci				of_node_put(it.node);
127662306a36Sopenharmony_ci			}
127762306a36Sopenharmony_ci
127862306a36Sopenharmony_ci			/* Found it! return success */
127962306a36Sopenharmony_ci			return 0;
128062306a36Sopenharmony_ci		}
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci		cur_index++;
128362306a36Sopenharmony_ci	}
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci	/*
128662306a36Sopenharmony_ci	 * Unlock node before returning result; will be one of:
128762306a36Sopenharmony_ci	 * -ENOENT : index is for empty phandle
128862306a36Sopenharmony_ci	 * -EINVAL : parsing error on data
128962306a36Sopenharmony_ci	 */
129062306a36Sopenharmony_ci
129162306a36Sopenharmony_ci err:
129262306a36Sopenharmony_ci	of_node_put(it.node);
129362306a36Sopenharmony_ci	return rc;
129462306a36Sopenharmony_ci}
129562306a36Sopenharmony_ciEXPORT_SYMBOL(__of_parse_phandle_with_args);
129662306a36Sopenharmony_ci
129762306a36Sopenharmony_ci/**
129862306a36Sopenharmony_ci * of_parse_phandle_with_args_map() - Find a node pointed by phandle in a list and remap it
129962306a36Sopenharmony_ci * @np:		pointer to a device tree node containing a list
130062306a36Sopenharmony_ci * @list_name:	property name that contains a list
130162306a36Sopenharmony_ci * @stem_name:	stem of property names that specify phandles' arguments count
130262306a36Sopenharmony_ci * @index:	index of a phandle to parse out
130362306a36Sopenharmony_ci * @out_args:	optional pointer to output arguments structure (will be filled)
130462306a36Sopenharmony_ci *
130562306a36Sopenharmony_ci * This function is useful to parse lists of phandles and their arguments.
130662306a36Sopenharmony_ci * Returns 0 on success and fills out_args, on error returns appropriate errno
130762306a36Sopenharmony_ci * value. The difference between this function and of_parse_phandle_with_args()
130862306a36Sopenharmony_ci * is that this API remaps a phandle if the node the phandle points to has
130962306a36Sopenharmony_ci * a <@stem_name>-map property.
131062306a36Sopenharmony_ci *
131162306a36Sopenharmony_ci * Caller is responsible to call of_node_put() on the returned out_args->np
131262306a36Sopenharmony_ci * pointer.
131362306a36Sopenharmony_ci *
131462306a36Sopenharmony_ci * Example::
131562306a36Sopenharmony_ci *
131662306a36Sopenharmony_ci *  phandle1: node1 {
131762306a36Sopenharmony_ci *  	#list-cells = <2>;
131862306a36Sopenharmony_ci *  };
131962306a36Sopenharmony_ci *
132062306a36Sopenharmony_ci *  phandle2: node2 {
132162306a36Sopenharmony_ci *  	#list-cells = <1>;
132262306a36Sopenharmony_ci *  };
132362306a36Sopenharmony_ci *
132462306a36Sopenharmony_ci *  phandle3: node3 {
132562306a36Sopenharmony_ci *  	#list-cells = <1>;
132662306a36Sopenharmony_ci *  	list-map = <0 &phandle2 3>,
132762306a36Sopenharmony_ci *  		   <1 &phandle2 2>,
132862306a36Sopenharmony_ci *  		   <2 &phandle1 5 1>;
132962306a36Sopenharmony_ci *  	list-map-mask = <0x3>;
133062306a36Sopenharmony_ci *  };
133162306a36Sopenharmony_ci *
133262306a36Sopenharmony_ci *  node4 {
133362306a36Sopenharmony_ci *  	list = <&phandle1 1 2 &phandle3 0>;
133462306a36Sopenharmony_ci *  };
133562306a36Sopenharmony_ci *
133662306a36Sopenharmony_ci * To get a device_node of the ``node2`` node you may call this:
133762306a36Sopenharmony_ci * of_parse_phandle_with_args(node4, "list", "list", 1, &args);
133862306a36Sopenharmony_ci */
133962306a36Sopenharmony_ciint of_parse_phandle_with_args_map(const struct device_node *np,
134062306a36Sopenharmony_ci				   const char *list_name,
134162306a36Sopenharmony_ci				   const char *stem_name,
134262306a36Sopenharmony_ci				   int index, struct of_phandle_args *out_args)
134362306a36Sopenharmony_ci{
134462306a36Sopenharmony_ci	char *cells_name, *map_name = NULL, *mask_name = NULL;
134562306a36Sopenharmony_ci	char *pass_name = NULL;
134662306a36Sopenharmony_ci	struct device_node *cur, *new = NULL;
134762306a36Sopenharmony_ci	const __be32 *map, *mask, *pass;
134862306a36Sopenharmony_ci	static const __be32 dummy_mask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 };
134962306a36Sopenharmony_ci	static const __be32 dummy_pass[] = { [0 ... MAX_PHANDLE_ARGS] = 0 };
135062306a36Sopenharmony_ci	__be32 initial_match_array[MAX_PHANDLE_ARGS];
135162306a36Sopenharmony_ci	const __be32 *match_array = initial_match_array;
135262306a36Sopenharmony_ci	int i, ret, map_len, match;
135362306a36Sopenharmony_ci	u32 list_size, new_size;
135462306a36Sopenharmony_ci
135562306a36Sopenharmony_ci	if (index < 0)
135662306a36Sopenharmony_ci		return -EINVAL;
135762306a36Sopenharmony_ci
135862306a36Sopenharmony_ci	cells_name = kasprintf(GFP_KERNEL, "#%s-cells", stem_name);
135962306a36Sopenharmony_ci	if (!cells_name)
136062306a36Sopenharmony_ci		return -ENOMEM;
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_ci	ret = -ENOMEM;
136362306a36Sopenharmony_ci	map_name = kasprintf(GFP_KERNEL, "%s-map", stem_name);
136462306a36Sopenharmony_ci	if (!map_name)
136562306a36Sopenharmony_ci		goto free;
136662306a36Sopenharmony_ci
136762306a36Sopenharmony_ci	mask_name = kasprintf(GFP_KERNEL, "%s-map-mask", stem_name);
136862306a36Sopenharmony_ci	if (!mask_name)
136962306a36Sopenharmony_ci		goto free;
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ci	pass_name = kasprintf(GFP_KERNEL, "%s-map-pass-thru", stem_name);
137262306a36Sopenharmony_ci	if (!pass_name)
137362306a36Sopenharmony_ci		goto free;
137462306a36Sopenharmony_ci
137562306a36Sopenharmony_ci	ret = __of_parse_phandle_with_args(np, list_name, cells_name, -1, index,
137662306a36Sopenharmony_ci					   out_args);
137762306a36Sopenharmony_ci	if (ret)
137862306a36Sopenharmony_ci		goto free;
137962306a36Sopenharmony_ci
138062306a36Sopenharmony_ci	/* Get the #<list>-cells property */
138162306a36Sopenharmony_ci	cur = out_args->np;
138262306a36Sopenharmony_ci	ret = of_property_read_u32(cur, cells_name, &list_size);
138362306a36Sopenharmony_ci	if (ret < 0)
138462306a36Sopenharmony_ci		goto put;
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ci	/* Precalculate the match array - this simplifies match loop */
138762306a36Sopenharmony_ci	for (i = 0; i < list_size; i++)
138862306a36Sopenharmony_ci		initial_match_array[i] = cpu_to_be32(out_args->args[i]);
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_ci	ret = -EINVAL;
139162306a36Sopenharmony_ci	while (cur) {
139262306a36Sopenharmony_ci		/* Get the <list>-map property */
139362306a36Sopenharmony_ci		map = of_get_property(cur, map_name, &map_len);
139462306a36Sopenharmony_ci		if (!map) {
139562306a36Sopenharmony_ci			ret = 0;
139662306a36Sopenharmony_ci			goto free;
139762306a36Sopenharmony_ci		}
139862306a36Sopenharmony_ci		map_len /= sizeof(u32);
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci		/* Get the <list>-map-mask property (optional) */
140162306a36Sopenharmony_ci		mask = of_get_property(cur, mask_name, NULL);
140262306a36Sopenharmony_ci		if (!mask)
140362306a36Sopenharmony_ci			mask = dummy_mask;
140462306a36Sopenharmony_ci		/* Iterate through <list>-map property */
140562306a36Sopenharmony_ci		match = 0;
140662306a36Sopenharmony_ci		while (map_len > (list_size + 1) && !match) {
140762306a36Sopenharmony_ci			/* Compare specifiers */
140862306a36Sopenharmony_ci			match = 1;
140962306a36Sopenharmony_ci			for (i = 0; i < list_size; i++, map_len--)
141062306a36Sopenharmony_ci				match &= !((match_array[i] ^ *map++) & mask[i]);
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_ci			of_node_put(new);
141362306a36Sopenharmony_ci			new = of_find_node_by_phandle(be32_to_cpup(map));
141462306a36Sopenharmony_ci			map++;
141562306a36Sopenharmony_ci			map_len--;
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_ci			/* Check if not found */
141862306a36Sopenharmony_ci			if (!new)
141962306a36Sopenharmony_ci				goto put;
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_ci			if (!of_device_is_available(new))
142262306a36Sopenharmony_ci				match = 0;
142362306a36Sopenharmony_ci
142462306a36Sopenharmony_ci			ret = of_property_read_u32(new, cells_name, &new_size);
142562306a36Sopenharmony_ci			if (ret)
142662306a36Sopenharmony_ci				goto put;
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_ci			/* Check for malformed properties */
142962306a36Sopenharmony_ci			if (WARN_ON(new_size > MAX_PHANDLE_ARGS))
143062306a36Sopenharmony_ci				goto put;
143162306a36Sopenharmony_ci			if (map_len < new_size)
143262306a36Sopenharmony_ci				goto put;
143362306a36Sopenharmony_ci
143462306a36Sopenharmony_ci			/* Move forward by new node's #<list>-cells amount */
143562306a36Sopenharmony_ci			map += new_size;
143662306a36Sopenharmony_ci			map_len -= new_size;
143762306a36Sopenharmony_ci		}
143862306a36Sopenharmony_ci		if (!match)
143962306a36Sopenharmony_ci			goto put;
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci		/* Get the <list>-map-pass-thru property (optional) */
144262306a36Sopenharmony_ci		pass = of_get_property(cur, pass_name, NULL);
144362306a36Sopenharmony_ci		if (!pass)
144462306a36Sopenharmony_ci			pass = dummy_pass;
144562306a36Sopenharmony_ci
144662306a36Sopenharmony_ci		/*
144762306a36Sopenharmony_ci		 * Successfully parsed a <list>-map translation; copy new
144862306a36Sopenharmony_ci		 * specifier into the out_args structure, keeping the
144962306a36Sopenharmony_ci		 * bits specified in <list>-map-pass-thru.
145062306a36Sopenharmony_ci		 */
145162306a36Sopenharmony_ci		match_array = map - new_size;
145262306a36Sopenharmony_ci		for (i = 0; i < new_size; i++) {
145362306a36Sopenharmony_ci			__be32 val = *(map - new_size + i);
145462306a36Sopenharmony_ci
145562306a36Sopenharmony_ci			if (i < list_size) {
145662306a36Sopenharmony_ci				val &= ~pass[i];
145762306a36Sopenharmony_ci				val |= cpu_to_be32(out_args->args[i]) & pass[i];
145862306a36Sopenharmony_ci			}
145962306a36Sopenharmony_ci
146062306a36Sopenharmony_ci			out_args->args[i] = be32_to_cpu(val);
146162306a36Sopenharmony_ci		}
146262306a36Sopenharmony_ci		out_args->args_count = list_size = new_size;
146362306a36Sopenharmony_ci		/* Iterate again with new provider */
146462306a36Sopenharmony_ci		out_args->np = new;
146562306a36Sopenharmony_ci		of_node_put(cur);
146662306a36Sopenharmony_ci		cur = new;
146762306a36Sopenharmony_ci		new = NULL;
146862306a36Sopenharmony_ci	}
146962306a36Sopenharmony_ciput:
147062306a36Sopenharmony_ci	of_node_put(cur);
147162306a36Sopenharmony_ci	of_node_put(new);
147262306a36Sopenharmony_cifree:
147362306a36Sopenharmony_ci	kfree(mask_name);
147462306a36Sopenharmony_ci	kfree(map_name);
147562306a36Sopenharmony_ci	kfree(cells_name);
147662306a36Sopenharmony_ci	kfree(pass_name);
147762306a36Sopenharmony_ci
147862306a36Sopenharmony_ci	return ret;
147962306a36Sopenharmony_ci}
148062306a36Sopenharmony_ciEXPORT_SYMBOL(of_parse_phandle_with_args_map);
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci/**
148362306a36Sopenharmony_ci * of_count_phandle_with_args() - Find the number of phandles references in a property
148462306a36Sopenharmony_ci * @np:		pointer to a device tree node containing a list
148562306a36Sopenharmony_ci * @list_name:	property name that contains a list
148662306a36Sopenharmony_ci * @cells_name:	property name that specifies phandles' arguments count
148762306a36Sopenharmony_ci *
148862306a36Sopenharmony_ci * Return: The number of phandle + argument tuples within a property. It
148962306a36Sopenharmony_ci * is a typical pattern to encode a list of phandle and variable
149062306a36Sopenharmony_ci * arguments into a single property. The number of arguments is encoded
149162306a36Sopenharmony_ci * by a property in the phandle-target node. For example, a gpios
149262306a36Sopenharmony_ci * property would contain a list of GPIO specifies consisting of a
149362306a36Sopenharmony_ci * phandle and 1 or more arguments. The number of arguments are
149462306a36Sopenharmony_ci * determined by the #gpio-cells property in the node pointed to by the
149562306a36Sopenharmony_ci * phandle.
149662306a36Sopenharmony_ci */
149762306a36Sopenharmony_ciint of_count_phandle_with_args(const struct device_node *np, const char *list_name,
149862306a36Sopenharmony_ci				const char *cells_name)
149962306a36Sopenharmony_ci{
150062306a36Sopenharmony_ci	struct of_phandle_iterator it;
150162306a36Sopenharmony_ci	int rc, cur_index = 0;
150262306a36Sopenharmony_ci
150362306a36Sopenharmony_ci	/*
150462306a36Sopenharmony_ci	 * If cells_name is NULL we assume a cell count of 0. This makes
150562306a36Sopenharmony_ci	 * counting the phandles trivial as each 32bit word in the list is a
150662306a36Sopenharmony_ci	 * phandle and no arguments are to consider. So we don't iterate through
150762306a36Sopenharmony_ci	 * the list but just use the length to determine the phandle count.
150862306a36Sopenharmony_ci	 */
150962306a36Sopenharmony_ci	if (!cells_name) {
151062306a36Sopenharmony_ci		const __be32 *list;
151162306a36Sopenharmony_ci		int size;
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci		list = of_get_property(np, list_name, &size);
151462306a36Sopenharmony_ci		if (!list)
151562306a36Sopenharmony_ci			return -ENOENT;
151662306a36Sopenharmony_ci
151762306a36Sopenharmony_ci		return size / sizeof(*list);
151862306a36Sopenharmony_ci	}
151962306a36Sopenharmony_ci
152062306a36Sopenharmony_ci	rc = of_phandle_iterator_init(&it, np, list_name, cells_name, -1);
152162306a36Sopenharmony_ci	if (rc)
152262306a36Sopenharmony_ci		return rc;
152362306a36Sopenharmony_ci
152462306a36Sopenharmony_ci	while ((rc = of_phandle_iterator_next(&it)) == 0)
152562306a36Sopenharmony_ci		cur_index += 1;
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_ci	if (rc != -ENOENT)
152862306a36Sopenharmony_ci		return rc;
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_ci	return cur_index;
153162306a36Sopenharmony_ci}
153262306a36Sopenharmony_ciEXPORT_SYMBOL(of_count_phandle_with_args);
153362306a36Sopenharmony_ci
153462306a36Sopenharmony_cistatic struct property *__of_remove_property_from_list(struct property **list, struct property *prop)
153562306a36Sopenharmony_ci{
153662306a36Sopenharmony_ci	struct property **next;
153762306a36Sopenharmony_ci
153862306a36Sopenharmony_ci	for (next = list; *next; next = &(*next)->next) {
153962306a36Sopenharmony_ci		if (*next == prop) {
154062306a36Sopenharmony_ci			*next = prop->next;
154162306a36Sopenharmony_ci			prop->next = NULL;
154262306a36Sopenharmony_ci			return prop;
154362306a36Sopenharmony_ci		}
154462306a36Sopenharmony_ci	}
154562306a36Sopenharmony_ci	return NULL;
154662306a36Sopenharmony_ci}
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_ci/**
154962306a36Sopenharmony_ci * __of_add_property - Add a property to a node without lock operations
155062306a36Sopenharmony_ci * @np:		Caller's Device Node
155162306a36Sopenharmony_ci * @prop:	Property to add
155262306a36Sopenharmony_ci */
155362306a36Sopenharmony_ciint __of_add_property(struct device_node *np, struct property *prop)
155462306a36Sopenharmony_ci{
155562306a36Sopenharmony_ci	int rc = 0;
155662306a36Sopenharmony_ci	unsigned long flags;
155762306a36Sopenharmony_ci	struct property **next;
155862306a36Sopenharmony_ci
155962306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
156062306a36Sopenharmony_ci
156162306a36Sopenharmony_ci	__of_remove_property_from_list(&np->deadprops, prop);
156262306a36Sopenharmony_ci
156362306a36Sopenharmony_ci	prop->next = NULL;
156462306a36Sopenharmony_ci	next = &np->properties;
156562306a36Sopenharmony_ci	while (*next) {
156662306a36Sopenharmony_ci		if (strcmp(prop->name, (*next)->name) == 0) {
156762306a36Sopenharmony_ci			/* duplicate ! don't insert it */
156862306a36Sopenharmony_ci			rc = -EEXIST;
156962306a36Sopenharmony_ci			goto out_unlock;
157062306a36Sopenharmony_ci		}
157162306a36Sopenharmony_ci		next = &(*next)->next;
157262306a36Sopenharmony_ci	}
157362306a36Sopenharmony_ci	*next = prop;
157462306a36Sopenharmony_ci
157562306a36Sopenharmony_ciout_unlock:
157662306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
157762306a36Sopenharmony_ci	if (rc)
157862306a36Sopenharmony_ci		return rc;
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_ci	__of_add_property_sysfs(np, prop);
158162306a36Sopenharmony_ci	return 0;
158262306a36Sopenharmony_ci}
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_ci/**
158562306a36Sopenharmony_ci * of_add_property - Add a property to a node
158662306a36Sopenharmony_ci * @np:		Caller's Device Node
158762306a36Sopenharmony_ci * @prop:	Property to add
158862306a36Sopenharmony_ci */
158962306a36Sopenharmony_ciint of_add_property(struct device_node *np, struct property *prop)
159062306a36Sopenharmony_ci{
159162306a36Sopenharmony_ci	int rc;
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_ci	mutex_lock(&of_mutex);
159462306a36Sopenharmony_ci	rc = __of_add_property(np, prop);
159562306a36Sopenharmony_ci	mutex_unlock(&of_mutex);
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci	if (!rc)
159862306a36Sopenharmony_ci		of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL);
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_ci	return rc;
160162306a36Sopenharmony_ci}
160262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(of_add_property);
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_ciint __of_remove_property(struct device_node *np, struct property *prop)
160562306a36Sopenharmony_ci{
160662306a36Sopenharmony_ci	unsigned long flags;
160762306a36Sopenharmony_ci	int rc = -ENODEV;
160862306a36Sopenharmony_ci
160962306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
161062306a36Sopenharmony_ci
161162306a36Sopenharmony_ci	if (__of_remove_property_from_list(&np->properties, prop)) {
161262306a36Sopenharmony_ci		/* Found the property, add it to deadprops list */
161362306a36Sopenharmony_ci		prop->next = np->deadprops;
161462306a36Sopenharmony_ci		np->deadprops = prop;
161562306a36Sopenharmony_ci		rc = 0;
161662306a36Sopenharmony_ci	}
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
161962306a36Sopenharmony_ci	if (rc)
162062306a36Sopenharmony_ci		return rc;
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_ci	__of_remove_property_sysfs(np, prop);
162362306a36Sopenharmony_ci	return 0;
162462306a36Sopenharmony_ci}
162562306a36Sopenharmony_ci
162662306a36Sopenharmony_ci/**
162762306a36Sopenharmony_ci * of_remove_property - Remove a property from a node.
162862306a36Sopenharmony_ci * @np:		Caller's Device Node
162962306a36Sopenharmony_ci * @prop:	Property to remove
163062306a36Sopenharmony_ci *
163162306a36Sopenharmony_ci * Note that we don't actually remove it, since we have given out
163262306a36Sopenharmony_ci * who-knows-how-many pointers to the data using get-property.
163362306a36Sopenharmony_ci * Instead we just move the property to the "dead properties"
163462306a36Sopenharmony_ci * list, so it won't be found any more.
163562306a36Sopenharmony_ci */
163662306a36Sopenharmony_ciint of_remove_property(struct device_node *np, struct property *prop)
163762306a36Sopenharmony_ci{
163862306a36Sopenharmony_ci	int rc;
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_ci	if (!prop)
164162306a36Sopenharmony_ci		return -ENODEV;
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci	mutex_lock(&of_mutex);
164462306a36Sopenharmony_ci	rc = __of_remove_property(np, prop);
164562306a36Sopenharmony_ci	mutex_unlock(&of_mutex);
164662306a36Sopenharmony_ci
164762306a36Sopenharmony_ci	if (!rc)
164862306a36Sopenharmony_ci		of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL);
164962306a36Sopenharmony_ci
165062306a36Sopenharmony_ci	return rc;
165162306a36Sopenharmony_ci}
165262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(of_remove_property);
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ciint __of_update_property(struct device_node *np, struct property *newprop,
165562306a36Sopenharmony_ci		struct property **oldpropp)
165662306a36Sopenharmony_ci{
165762306a36Sopenharmony_ci	struct property **next, *oldprop;
165862306a36Sopenharmony_ci	unsigned long flags;
165962306a36Sopenharmony_ci
166062306a36Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_ci	__of_remove_property_from_list(&np->deadprops, newprop);
166362306a36Sopenharmony_ci
166462306a36Sopenharmony_ci	for (next = &np->properties; *next; next = &(*next)->next) {
166562306a36Sopenharmony_ci		if (of_prop_cmp((*next)->name, newprop->name) == 0)
166662306a36Sopenharmony_ci			break;
166762306a36Sopenharmony_ci	}
166862306a36Sopenharmony_ci	*oldpropp = oldprop = *next;
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_ci	if (oldprop) {
167162306a36Sopenharmony_ci		/* replace the node */
167262306a36Sopenharmony_ci		newprop->next = oldprop->next;
167362306a36Sopenharmony_ci		*next = newprop;
167462306a36Sopenharmony_ci		oldprop->next = np->deadprops;
167562306a36Sopenharmony_ci		np->deadprops = oldprop;
167662306a36Sopenharmony_ci	} else {
167762306a36Sopenharmony_ci		/* new node */
167862306a36Sopenharmony_ci		newprop->next = NULL;
167962306a36Sopenharmony_ci		*next = newprop;
168062306a36Sopenharmony_ci	}
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
168362306a36Sopenharmony_ci
168462306a36Sopenharmony_ci	__of_update_property_sysfs(np, newprop, oldprop);
168562306a36Sopenharmony_ci
168662306a36Sopenharmony_ci	return 0;
168762306a36Sopenharmony_ci}
168862306a36Sopenharmony_ci
168962306a36Sopenharmony_ci/*
169062306a36Sopenharmony_ci * of_update_property - Update a property in a node, if the property does
169162306a36Sopenharmony_ci * not exist, add it.
169262306a36Sopenharmony_ci *
169362306a36Sopenharmony_ci * Note that we don't actually remove it, since we have given out
169462306a36Sopenharmony_ci * who-knows-how-many pointers to the data using get-property.
169562306a36Sopenharmony_ci * Instead we just move the property to the "dead properties" list,
169662306a36Sopenharmony_ci * and add the new property to the property list
169762306a36Sopenharmony_ci */
169862306a36Sopenharmony_ciint of_update_property(struct device_node *np, struct property *newprop)
169962306a36Sopenharmony_ci{
170062306a36Sopenharmony_ci	struct property *oldprop;
170162306a36Sopenharmony_ci	int rc;
170262306a36Sopenharmony_ci
170362306a36Sopenharmony_ci	if (!newprop->name)
170462306a36Sopenharmony_ci		return -EINVAL;
170562306a36Sopenharmony_ci
170662306a36Sopenharmony_ci	mutex_lock(&of_mutex);
170762306a36Sopenharmony_ci	rc = __of_update_property(np, newprop, &oldprop);
170862306a36Sopenharmony_ci	mutex_unlock(&of_mutex);
170962306a36Sopenharmony_ci
171062306a36Sopenharmony_ci	if (!rc)
171162306a36Sopenharmony_ci		of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop);
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_ci	return rc;
171462306a36Sopenharmony_ci}
171562306a36Sopenharmony_ci
171662306a36Sopenharmony_cistatic void of_alias_add(struct alias_prop *ap, struct device_node *np,
171762306a36Sopenharmony_ci			 int id, const char *stem, int stem_len)
171862306a36Sopenharmony_ci{
171962306a36Sopenharmony_ci	ap->np = np;
172062306a36Sopenharmony_ci	ap->id = id;
172162306a36Sopenharmony_ci	strscpy(ap->stem, stem, stem_len + 1);
172262306a36Sopenharmony_ci	list_add_tail(&ap->link, &aliases_lookup);
172362306a36Sopenharmony_ci	pr_debug("adding DT alias:%s: stem=%s id=%i node=%pOF\n",
172462306a36Sopenharmony_ci		 ap->alias, ap->stem, ap->id, np);
172562306a36Sopenharmony_ci}
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci/**
172862306a36Sopenharmony_ci * of_alias_scan - Scan all properties of the 'aliases' node
172962306a36Sopenharmony_ci * @dt_alloc:	An allocator that provides a virtual address to memory
173062306a36Sopenharmony_ci *		for storing the resulting tree
173162306a36Sopenharmony_ci *
173262306a36Sopenharmony_ci * The function scans all the properties of the 'aliases' node and populates
173362306a36Sopenharmony_ci * the global lookup table with the properties.  It returns the
173462306a36Sopenharmony_ci * number of alias properties found, or an error code in case of failure.
173562306a36Sopenharmony_ci */
173662306a36Sopenharmony_civoid of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
173762306a36Sopenharmony_ci{
173862306a36Sopenharmony_ci	struct property *pp;
173962306a36Sopenharmony_ci
174062306a36Sopenharmony_ci	of_aliases = of_find_node_by_path("/aliases");
174162306a36Sopenharmony_ci	of_chosen = of_find_node_by_path("/chosen");
174262306a36Sopenharmony_ci	if (of_chosen == NULL)
174362306a36Sopenharmony_ci		of_chosen = of_find_node_by_path("/chosen@0");
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_ci	if (of_chosen) {
174662306a36Sopenharmony_ci		/* linux,stdout-path and /aliases/stdout are for legacy compatibility */
174762306a36Sopenharmony_ci		const char *name = NULL;
174862306a36Sopenharmony_ci
174962306a36Sopenharmony_ci		if (of_property_read_string(of_chosen, "stdout-path", &name))
175062306a36Sopenharmony_ci			of_property_read_string(of_chosen, "linux,stdout-path",
175162306a36Sopenharmony_ci						&name);
175262306a36Sopenharmony_ci		if (IS_ENABLED(CONFIG_PPC) && !name)
175362306a36Sopenharmony_ci			of_property_read_string(of_aliases, "stdout", &name);
175462306a36Sopenharmony_ci		if (name)
175562306a36Sopenharmony_ci			of_stdout = of_find_node_opts_by_path(name, &of_stdout_options);
175662306a36Sopenharmony_ci		if (of_stdout)
175762306a36Sopenharmony_ci			of_stdout->fwnode.flags |= FWNODE_FLAG_BEST_EFFORT;
175862306a36Sopenharmony_ci	}
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_ci	if (!of_aliases)
176162306a36Sopenharmony_ci		return;
176262306a36Sopenharmony_ci
176362306a36Sopenharmony_ci	for_each_property_of_node(of_aliases, pp) {
176462306a36Sopenharmony_ci		const char *start = pp->name;
176562306a36Sopenharmony_ci		const char *end = start + strlen(start);
176662306a36Sopenharmony_ci		struct device_node *np;
176762306a36Sopenharmony_ci		struct alias_prop *ap;
176862306a36Sopenharmony_ci		int id, len;
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_ci		/* Skip those we do not want to proceed */
177162306a36Sopenharmony_ci		if (!strcmp(pp->name, "name") ||
177262306a36Sopenharmony_ci		    !strcmp(pp->name, "phandle") ||
177362306a36Sopenharmony_ci		    !strcmp(pp->name, "linux,phandle"))
177462306a36Sopenharmony_ci			continue;
177562306a36Sopenharmony_ci
177662306a36Sopenharmony_ci		np = of_find_node_by_path(pp->value);
177762306a36Sopenharmony_ci		if (!np)
177862306a36Sopenharmony_ci			continue;
177962306a36Sopenharmony_ci
178062306a36Sopenharmony_ci		/* walk the alias backwards to extract the id and work out
178162306a36Sopenharmony_ci		 * the 'stem' string */
178262306a36Sopenharmony_ci		while (isdigit(*(end-1)) && end > start)
178362306a36Sopenharmony_ci			end--;
178462306a36Sopenharmony_ci		len = end - start;
178562306a36Sopenharmony_ci
178662306a36Sopenharmony_ci		if (kstrtoint(end, 10, &id) < 0)
178762306a36Sopenharmony_ci			continue;
178862306a36Sopenharmony_ci
178962306a36Sopenharmony_ci		/* Allocate an alias_prop with enough space for the stem */
179062306a36Sopenharmony_ci		ap = dt_alloc(sizeof(*ap) + len + 1, __alignof__(*ap));
179162306a36Sopenharmony_ci		if (!ap)
179262306a36Sopenharmony_ci			continue;
179362306a36Sopenharmony_ci		memset(ap, 0, sizeof(*ap) + len + 1);
179462306a36Sopenharmony_ci		ap->alias = start;
179562306a36Sopenharmony_ci		of_alias_add(ap, np, id, start, len);
179662306a36Sopenharmony_ci	}
179762306a36Sopenharmony_ci}
179862306a36Sopenharmony_ci
179962306a36Sopenharmony_ci/**
180062306a36Sopenharmony_ci * of_alias_get_id - Get alias id for the given device_node
180162306a36Sopenharmony_ci * @np:		Pointer to the given device_node
180262306a36Sopenharmony_ci * @stem:	Alias stem of the given device_node
180362306a36Sopenharmony_ci *
180462306a36Sopenharmony_ci * The function travels the lookup table to get the alias id for the given
180562306a36Sopenharmony_ci * device_node and alias stem.
180662306a36Sopenharmony_ci *
180762306a36Sopenharmony_ci * Return: The alias id if found.
180862306a36Sopenharmony_ci */
180962306a36Sopenharmony_ciint of_alias_get_id(struct device_node *np, const char *stem)
181062306a36Sopenharmony_ci{
181162306a36Sopenharmony_ci	struct alias_prop *app;
181262306a36Sopenharmony_ci	int id = -ENODEV;
181362306a36Sopenharmony_ci
181462306a36Sopenharmony_ci	mutex_lock(&of_mutex);
181562306a36Sopenharmony_ci	list_for_each_entry(app, &aliases_lookup, link) {
181662306a36Sopenharmony_ci		if (strcmp(app->stem, stem) != 0)
181762306a36Sopenharmony_ci			continue;
181862306a36Sopenharmony_ci
181962306a36Sopenharmony_ci		if (np == app->np) {
182062306a36Sopenharmony_ci			id = app->id;
182162306a36Sopenharmony_ci			break;
182262306a36Sopenharmony_ci		}
182362306a36Sopenharmony_ci	}
182462306a36Sopenharmony_ci	mutex_unlock(&of_mutex);
182562306a36Sopenharmony_ci
182662306a36Sopenharmony_ci	return id;
182762306a36Sopenharmony_ci}
182862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(of_alias_get_id);
182962306a36Sopenharmony_ci
183062306a36Sopenharmony_ci/**
183162306a36Sopenharmony_ci * of_alias_get_highest_id - Get highest alias id for the given stem
183262306a36Sopenharmony_ci * @stem:	Alias stem to be examined
183362306a36Sopenharmony_ci *
183462306a36Sopenharmony_ci * The function travels the lookup table to get the highest alias id for the
183562306a36Sopenharmony_ci * given alias stem.  It returns the alias id if found.
183662306a36Sopenharmony_ci */
183762306a36Sopenharmony_ciint of_alias_get_highest_id(const char *stem)
183862306a36Sopenharmony_ci{
183962306a36Sopenharmony_ci	struct alias_prop *app;
184062306a36Sopenharmony_ci	int id = -ENODEV;
184162306a36Sopenharmony_ci
184262306a36Sopenharmony_ci	mutex_lock(&of_mutex);
184362306a36Sopenharmony_ci	list_for_each_entry(app, &aliases_lookup, link) {
184462306a36Sopenharmony_ci		if (strcmp(app->stem, stem) != 0)
184562306a36Sopenharmony_ci			continue;
184662306a36Sopenharmony_ci
184762306a36Sopenharmony_ci		if (app->id > id)
184862306a36Sopenharmony_ci			id = app->id;
184962306a36Sopenharmony_ci	}
185062306a36Sopenharmony_ci	mutex_unlock(&of_mutex);
185162306a36Sopenharmony_ci
185262306a36Sopenharmony_ci	return id;
185362306a36Sopenharmony_ci}
185462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(of_alias_get_highest_id);
185562306a36Sopenharmony_ci
185662306a36Sopenharmony_ci/**
185762306a36Sopenharmony_ci * of_console_check() - Test and setup console for DT setup
185862306a36Sopenharmony_ci * @dn: Pointer to device node
185962306a36Sopenharmony_ci * @name: Name to use for preferred console without index. ex. "ttyS"
186062306a36Sopenharmony_ci * @index: Index to use for preferred console.
186162306a36Sopenharmony_ci *
186262306a36Sopenharmony_ci * Check if the given device node matches the stdout-path property in the
186362306a36Sopenharmony_ci * /chosen node. If it does then register it as the preferred console.
186462306a36Sopenharmony_ci *
186562306a36Sopenharmony_ci * Return: TRUE if console successfully setup. Otherwise return FALSE.
186662306a36Sopenharmony_ci */
186762306a36Sopenharmony_cibool of_console_check(struct device_node *dn, char *name, int index)
186862306a36Sopenharmony_ci{
186962306a36Sopenharmony_ci	if (!dn || dn != of_stdout || console_set_on_cmdline)
187062306a36Sopenharmony_ci		return false;
187162306a36Sopenharmony_ci
187262306a36Sopenharmony_ci	/*
187362306a36Sopenharmony_ci	 * XXX: cast `options' to char pointer to suppress complication
187462306a36Sopenharmony_ci	 * warnings: printk, UART and console drivers expect char pointer.
187562306a36Sopenharmony_ci	 */
187662306a36Sopenharmony_ci	return !add_preferred_console(name, index, (char *)of_stdout_options);
187762306a36Sopenharmony_ci}
187862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(of_console_check);
187962306a36Sopenharmony_ci
188062306a36Sopenharmony_ci/**
188162306a36Sopenharmony_ci * of_find_next_cache_node - Find a node's subsidiary cache
188262306a36Sopenharmony_ci * @np:	node of type "cpu" or "cache"
188362306a36Sopenharmony_ci *
188462306a36Sopenharmony_ci * Return: A node pointer with refcount incremented, use
188562306a36Sopenharmony_ci * of_node_put() on it when done.  Caller should hold a reference
188662306a36Sopenharmony_ci * to np.
188762306a36Sopenharmony_ci */
188862306a36Sopenharmony_cistruct device_node *of_find_next_cache_node(const struct device_node *np)
188962306a36Sopenharmony_ci{
189062306a36Sopenharmony_ci	struct device_node *child, *cache_node;
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	cache_node = of_parse_phandle(np, "l2-cache", 0);
189362306a36Sopenharmony_ci	if (!cache_node)
189462306a36Sopenharmony_ci		cache_node = of_parse_phandle(np, "next-level-cache", 0);
189562306a36Sopenharmony_ci
189662306a36Sopenharmony_ci	if (cache_node)
189762306a36Sopenharmony_ci		return cache_node;
189862306a36Sopenharmony_ci
189962306a36Sopenharmony_ci	/* OF on pmac has nodes instead of properties named "l2-cache"
190062306a36Sopenharmony_ci	 * beneath CPU nodes.
190162306a36Sopenharmony_ci	 */
190262306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_PPC_PMAC) && of_node_is_type(np, "cpu"))
190362306a36Sopenharmony_ci		for_each_child_of_node(np, child)
190462306a36Sopenharmony_ci			if (of_node_is_type(child, "cache"))
190562306a36Sopenharmony_ci				return child;
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci	return NULL;
190862306a36Sopenharmony_ci}
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci/**
191162306a36Sopenharmony_ci * of_find_last_cache_level - Find the level at which the last cache is
191262306a36Sopenharmony_ci * 		present for the given logical cpu
191362306a36Sopenharmony_ci *
191462306a36Sopenharmony_ci * @cpu: cpu number(logical index) for which the last cache level is needed
191562306a36Sopenharmony_ci *
191662306a36Sopenharmony_ci * Return: The level at which the last cache is present. It is exactly
191762306a36Sopenharmony_ci * same as  the total number of cache levels for the given logical cpu.
191862306a36Sopenharmony_ci */
191962306a36Sopenharmony_ciint of_find_last_cache_level(unsigned int cpu)
192062306a36Sopenharmony_ci{
192162306a36Sopenharmony_ci	u32 cache_level = 0;
192262306a36Sopenharmony_ci	struct device_node *prev = NULL, *np = of_cpu_device_node_get(cpu);
192362306a36Sopenharmony_ci
192462306a36Sopenharmony_ci	while (np) {
192562306a36Sopenharmony_ci		of_node_put(prev);
192662306a36Sopenharmony_ci		prev = np;
192762306a36Sopenharmony_ci		np = of_find_next_cache_node(np);
192862306a36Sopenharmony_ci	}
192962306a36Sopenharmony_ci
193062306a36Sopenharmony_ci	of_property_read_u32(prev, "cache-level", &cache_level);
193162306a36Sopenharmony_ci	of_node_put(prev);
193262306a36Sopenharmony_ci
193362306a36Sopenharmony_ci	return cache_level;
193462306a36Sopenharmony_ci}
193562306a36Sopenharmony_ci
193662306a36Sopenharmony_ci/**
193762306a36Sopenharmony_ci * of_map_id - Translate an ID through a downstream mapping.
193862306a36Sopenharmony_ci * @np: root complex device node.
193962306a36Sopenharmony_ci * @id: device ID to map.
194062306a36Sopenharmony_ci * @map_name: property name of the map to use.
194162306a36Sopenharmony_ci * @map_mask_name: optional property name of the mask to use.
194262306a36Sopenharmony_ci * @target: optional pointer to a target device node.
194362306a36Sopenharmony_ci * @id_out: optional pointer to receive the translated ID.
194462306a36Sopenharmony_ci *
194562306a36Sopenharmony_ci * Given a device ID, look up the appropriate implementation-defined
194662306a36Sopenharmony_ci * platform ID and/or the target device which receives transactions on that
194762306a36Sopenharmony_ci * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or
194862306a36Sopenharmony_ci * @id_out may be NULL if only the other is required. If @target points to
194962306a36Sopenharmony_ci * a non-NULL device node pointer, only entries targeting that node will be
195062306a36Sopenharmony_ci * matched; if it points to a NULL value, it will receive the device node of
195162306a36Sopenharmony_ci * the first matching target phandle, with a reference held.
195262306a36Sopenharmony_ci *
195362306a36Sopenharmony_ci * Return: 0 on success or a standard error code on failure.
195462306a36Sopenharmony_ci */
195562306a36Sopenharmony_ciint of_map_id(struct device_node *np, u32 id,
195662306a36Sopenharmony_ci	       const char *map_name, const char *map_mask_name,
195762306a36Sopenharmony_ci	       struct device_node **target, u32 *id_out)
195862306a36Sopenharmony_ci{
195962306a36Sopenharmony_ci	u32 map_mask, masked_id;
196062306a36Sopenharmony_ci	int map_len;
196162306a36Sopenharmony_ci	const __be32 *map = NULL;
196262306a36Sopenharmony_ci
196362306a36Sopenharmony_ci	if (!np || !map_name || (!target && !id_out))
196462306a36Sopenharmony_ci		return -EINVAL;
196562306a36Sopenharmony_ci
196662306a36Sopenharmony_ci	map = of_get_property(np, map_name, &map_len);
196762306a36Sopenharmony_ci	if (!map) {
196862306a36Sopenharmony_ci		if (target)
196962306a36Sopenharmony_ci			return -ENODEV;
197062306a36Sopenharmony_ci		/* Otherwise, no map implies no translation */
197162306a36Sopenharmony_ci		*id_out = id;
197262306a36Sopenharmony_ci		return 0;
197362306a36Sopenharmony_ci	}
197462306a36Sopenharmony_ci
197562306a36Sopenharmony_ci	if (!map_len || map_len % (4 * sizeof(*map))) {
197662306a36Sopenharmony_ci		pr_err("%pOF: Error: Bad %s length: %d\n", np,
197762306a36Sopenharmony_ci			map_name, map_len);
197862306a36Sopenharmony_ci		return -EINVAL;
197962306a36Sopenharmony_ci	}
198062306a36Sopenharmony_ci
198162306a36Sopenharmony_ci	/* The default is to select all bits. */
198262306a36Sopenharmony_ci	map_mask = 0xffffffff;
198362306a36Sopenharmony_ci
198462306a36Sopenharmony_ci	/*
198562306a36Sopenharmony_ci	 * Can be overridden by "{iommu,msi}-map-mask" property.
198662306a36Sopenharmony_ci	 * If of_property_read_u32() fails, the default is used.
198762306a36Sopenharmony_ci	 */
198862306a36Sopenharmony_ci	if (map_mask_name)
198962306a36Sopenharmony_ci		of_property_read_u32(np, map_mask_name, &map_mask);
199062306a36Sopenharmony_ci
199162306a36Sopenharmony_ci	masked_id = map_mask & id;
199262306a36Sopenharmony_ci	for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) {
199362306a36Sopenharmony_ci		struct device_node *phandle_node;
199462306a36Sopenharmony_ci		u32 id_base = be32_to_cpup(map + 0);
199562306a36Sopenharmony_ci		u32 phandle = be32_to_cpup(map + 1);
199662306a36Sopenharmony_ci		u32 out_base = be32_to_cpup(map + 2);
199762306a36Sopenharmony_ci		u32 id_len = be32_to_cpup(map + 3);
199862306a36Sopenharmony_ci
199962306a36Sopenharmony_ci		if (id_base & ~map_mask) {
200062306a36Sopenharmony_ci			pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores id-base (0x%x)\n",
200162306a36Sopenharmony_ci				np, map_name, map_name,
200262306a36Sopenharmony_ci				map_mask, id_base);
200362306a36Sopenharmony_ci			return -EFAULT;
200462306a36Sopenharmony_ci		}
200562306a36Sopenharmony_ci
200662306a36Sopenharmony_ci		if (masked_id < id_base || masked_id >= id_base + id_len)
200762306a36Sopenharmony_ci			continue;
200862306a36Sopenharmony_ci
200962306a36Sopenharmony_ci		phandle_node = of_find_node_by_phandle(phandle);
201062306a36Sopenharmony_ci		if (!phandle_node)
201162306a36Sopenharmony_ci			return -ENODEV;
201262306a36Sopenharmony_ci
201362306a36Sopenharmony_ci		if (target) {
201462306a36Sopenharmony_ci			if (*target)
201562306a36Sopenharmony_ci				of_node_put(phandle_node);
201662306a36Sopenharmony_ci			else
201762306a36Sopenharmony_ci				*target = phandle_node;
201862306a36Sopenharmony_ci
201962306a36Sopenharmony_ci			if (*target != phandle_node)
202062306a36Sopenharmony_ci				continue;
202162306a36Sopenharmony_ci		}
202262306a36Sopenharmony_ci
202362306a36Sopenharmony_ci		if (id_out)
202462306a36Sopenharmony_ci			*id_out = masked_id - id_base + out_base;
202562306a36Sopenharmony_ci
202662306a36Sopenharmony_ci		pr_debug("%pOF: %s, using mask %08x, id-base: %08x, out-base: %08x, length: %08x, id: %08x -> %08x\n",
202762306a36Sopenharmony_ci			np, map_name, map_mask, id_base, out_base,
202862306a36Sopenharmony_ci			id_len, id, masked_id - id_base + out_base);
202962306a36Sopenharmony_ci		return 0;
203062306a36Sopenharmony_ci	}
203162306a36Sopenharmony_ci
203262306a36Sopenharmony_ci	pr_info("%pOF: no %s translation for id 0x%x on %pOF\n", np, map_name,
203362306a36Sopenharmony_ci		id, target && *target ? *target : NULL);
203462306a36Sopenharmony_ci
203562306a36Sopenharmony_ci	/* Bypasses translation */
203662306a36Sopenharmony_ci	if (id_out)
203762306a36Sopenharmony_ci		*id_out = id;
203862306a36Sopenharmony_ci	return 0;
203962306a36Sopenharmony_ci}
204062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(of_map_id);
2041