18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Procedures for creating, accessing and interpreting the device tree.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Paul Mackerras	August 1996.
68c2ecf20Sopenharmony_ci * Copyright (C) 1996-2005 Paul Mackerras.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
98c2ecf20Sopenharmony_ci *    {engebret|bergner}@us.ibm.com
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci *  Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci *  Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and
148c2ecf20Sopenharmony_ci *  Grant Likely.
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#define pr_fmt(fmt)	"OF: " fmt
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include <linux/bitmap.h>
208c2ecf20Sopenharmony_ci#include <linux/console.h>
218c2ecf20Sopenharmony_ci#include <linux/ctype.h>
228c2ecf20Sopenharmony_ci#include <linux/cpu.h>
238c2ecf20Sopenharmony_ci#include <linux/module.h>
248c2ecf20Sopenharmony_ci#include <linux/of.h>
258c2ecf20Sopenharmony_ci#include <linux/of_device.h>
268c2ecf20Sopenharmony_ci#include <linux/of_graph.h>
278c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
288c2ecf20Sopenharmony_ci#include <linux/slab.h>
298c2ecf20Sopenharmony_ci#include <linux/string.h>
308c2ecf20Sopenharmony_ci#include <linux/proc_fs.h>
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#include "of_private.h"
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ciLIST_HEAD(aliases_lookup);
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_cistruct device_node *of_root;
378c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_root);
388c2ecf20Sopenharmony_cistruct device_node *of_chosen;
398c2ecf20Sopenharmony_cistruct device_node *of_aliases;
408c2ecf20Sopenharmony_cistruct device_node *of_stdout;
418c2ecf20Sopenharmony_cistatic const char *of_stdout_options;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cistruct kset *of_kset;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci/*
468c2ecf20Sopenharmony_ci * Used to protect the of_aliases, to hold off addition of nodes to sysfs.
478c2ecf20Sopenharmony_ci * This mutex must be held whenever modifications are being made to the
488c2ecf20Sopenharmony_ci * device tree. The of_{attach,detach}_node() and
498c2ecf20Sopenharmony_ci * of_{add,remove,update}_property() helpers make sure this happens.
508c2ecf20Sopenharmony_ci */
518c2ecf20Sopenharmony_ciDEFINE_MUTEX(of_mutex);
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci/* use when traversing tree through the child, sibling,
548c2ecf20Sopenharmony_ci * or parent members of struct device_node.
558c2ecf20Sopenharmony_ci */
568c2ecf20Sopenharmony_ciDEFINE_RAW_SPINLOCK(devtree_lock);
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cibool of_node_name_eq(const struct device_node *np, const char *name)
598c2ecf20Sopenharmony_ci{
608c2ecf20Sopenharmony_ci	const char *node_name;
618c2ecf20Sopenharmony_ci	size_t len;
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	if (!np)
648c2ecf20Sopenharmony_ci		return false;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	node_name = kbasename(np->full_name);
678c2ecf20Sopenharmony_ci	len = strchrnul(node_name, '@') - node_name;
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci	return (strlen(name) == len) && (strncmp(node_name, name, len) == 0);
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_node_name_eq);
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_cibool of_node_name_prefix(const struct device_node *np, const char *prefix)
748c2ecf20Sopenharmony_ci{
758c2ecf20Sopenharmony_ci	if (!np)
768c2ecf20Sopenharmony_ci		return false;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	return strncmp(kbasename(np->full_name), prefix, strlen(prefix)) == 0;
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_node_name_prefix);
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cistatic bool __of_node_is_type(const struct device_node *np, const char *type)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	const char *match = __of_get_property(np, "device_type", NULL);
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	return np && match && type && !strcmp(match, type);
878c2ecf20Sopenharmony_ci}
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ciint of_bus_n_addr_cells(struct device_node *np)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	u32 cells;
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	for (; np; np = np->parent)
948c2ecf20Sopenharmony_ci		if (!of_property_read_u32(np, "#address-cells", &cells))
958c2ecf20Sopenharmony_ci			return cells;
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci	/* No #address-cells property for the root node */
988c2ecf20Sopenharmony_ci	return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
998c2ecf20Sopenharmony_ci}
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ciint of_n_addr_cells(struct device_node *np)
1028c2ecf20Sopenharmony_ci{
1038c2ecf20Sopenharmony_ci	if (np->parent)
1048c2ecf20Sopenharmony_ci		np = np->parent;
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci	return of_bus_n_addr_cells(np);
1078c2ecf20Sopenharmony_ci}
1088c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_n_addr_cells);
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ciint of_bus_n_size_cells(struct device_node *np)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	u32 cells;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	for (; np; np = np->parent)
1158c2ecf20Sopenharmony_ci		if (!of_property_read_u32(np, "#size-cells", &cells))
1168c2ecf20Sopenharmony_ci			return cells;
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	/* No #size-cells property for the root node */
1198c2ecf20Sopenharmony_ci	return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ciint of_n_size_cells(struct device_node *np)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	if (np->parent)
1258c2ecf20Sopenharmony_ci		np = np->parent;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	return of_bus_n_size_cells(np);
1288c2ecf20Sopenharmony_ci}
1298c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_n_size_cells);
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci#ifdef CONFIG_NUMA
1328c2ecf20Sopenharmony_ciint __weak of_node_to_nid(struct device_node *np)
1338c2ecf20Sopenharmony_ci{
1348c2ecf20Sopenharmony_ci	return NUMA_NO_NODE;
1358c2ecf20Sopenharmony_ci}
1368c2ecf20Sopenharmony_ci#endif
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci#define OF_PHANDLE_CACHE_BITS	7
1398c2ecf20Sopenharmony_ci#define OF_PHANDLE_CACHE_SZ	BIT(OF_PHANDLE_CACHE_BITS)
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistatic struct device_node *phandle_cache[OF_PHANDLE_CACHE_SZ];
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_cistatic u32 of_phandle_cache_hash(phandle handle)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	return hash_32(handle, OF_PHANDLE_CACHE_BITS);
1468c2ecf20Sopenharmony_ci}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci/*
1498c2ecf20Sopenharmony_ci * Caller must hold devtree_lock.
1508c2ecf20Sopenharmony_ci */
1518c2ecf20Sopenharmony_civoid __of_phandle_cache_inv_entry(phandle handle)
1528c2ecf20Sopenharmony_ci{
1538c2ecf20Sopenharmony_ci	u32 handle_hash;
1548c2ecf20Sopenharmony_ci	struct device_node *np;
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	if (!handle)
1578c2ecf20Sopenharmony_ci		return;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	handle_hash = of_phandle_cache_hash(handle);
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	np = phandle_cache[handle_hash];
1628c2ecf20Sopenharmony_ci	if (np && handle == np->phandle)
1638c2ecf20Sopenharmony_ci		phandle_cache[handle_hash] = NULL;
1648c2ecf20Sopenharmony_ci}
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_civoid __init of_core_init(void)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	struct device_node *np;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	/* Create the kset, and register existing nodes */
1728c2ecf20Sopenharmony_ci	mutex_lock(&of_mutex);
1738c2ecf20Sopenharmony_ci	of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);
1748c2ecf20Sopenharmony_ci	if (!of_kset) {
1758c2ecf20Sopenharmony_ci		mutex_unlock(&of_mutex);
1768c2ecf20Sopenharmony_ci		pr_err("failed to register existing nodes\n");
1778c2ecf20Sopenharmony_ci		return;
1788c2ecf20Sopenharmony_ci	}
1798c2ecf20Sopenharmony_ci	for_each_of_allnodes(np) {
1808c2ecf20Sopenharmony_ci		__of_attach_node_sysfs(np);
1818c2ecf20Sopenharmony_ci		if (np->phandle && !phandle_cache[of_phandle_cache_hash(np->phandle)])
1828c2ecf20Sopenharmony_ci			phandle_cache[of_phandle_cache_hash(np->phandle)] = np;
1838c2ecf20Sopenharmony_ci	}
1848c2ecf20Sopenharmony_ci	mutex_unlock(&of_mutex);
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	/* Symlink in /proc as required by userspace ABI */
1878c2ecf20Sopenharmony_ci	if (of_root)
1888c2ecf20Sopenharmony_ci		proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cistatic struct property *__of_find_property(const struct device_node *np,
1928c2ecf20Sopenharmony_ci					   const char *name, int *lenp)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	struct property *pp;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	if (!np)
1978c2ecf20Sopenharmony_ci		return NULL;
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	for (pp = np->properties; pp; pp = pp->next) {
2008c2ecf20Sopenharmony_ci		if (of_prop_cmp(pp->name, name) == 0) {
2018c2ecf20Sopenharmony_ci			if (lenp)
2028c2ecf20Sopenharmony_ci				*lenp = pp->length;
2038c2ecf20Sopenharmony_ci			break;
2048c2ecf20Sopenharmony_ci		}
2058c2ecf20Sopenharmony_ci	}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	return pp;
2088c2ecf20Sopenharmony_ci}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_cistruct property *of_find_property(const struct device_node *np,
2118c2ecf20Sopenharmony_ci				  const char *name,
2128c2ecf20Sopenharmony_ci				  int *lenp)
2138c2ecf20Sopenharmony_ci{
2148c2ecf20Sopenharmony_ci	struct property *pp;
2158c2ecf20Sopenharmony_ci	unsigned long flags;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
2188c2ecf20Sopenharmony_ci	pp = __of_find_property(np, name, lenp);
2198c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	return pp;
2228c2ecf20Sopenharmony_ci}
2238c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_find_property);
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_cistruct device_node *__of_find_all_nodes(struct device_node *prev)
2268c2ecf20Sopenharmony_ci{
2278c2ecf20Sopenharmony_ci	struct device_node *np;
2288c2ecf20Sopenharmony_ci	if (!prev) {
2298c2ecf20Sopenharmony_ci		np = of_root;
2308c2ecf20Sopenharmony_ci	} else if (prev->child) {
2318c2ecf20Sopenharmony_ci		np = prev->child;
2328c2ecf20Sopenharmony_ci	} else {
2338c2ecf20Sopenharmony_ci		/* Walk back up looking for a sibling, or the end of the structure */
2348c2ecf20Sopenharmony_ci		np = prev;
2358c2ecf20Sopenharmony_ci		while (np->parent && !np->sibling)
2368c2ecf20Sopenharmony_ci			np = np->parent;
2378c2ecf20Sopenharmony_ci		np = np->sibling; /* Might be null at the end of the tree */
2388c2ecf20Sopenharmony_ci	}
2398c2ecf20Sopenharmony_ci	return np;
2408c2ecf20Sopenharmony_ci}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci/**
2438c2ecf20Sopenharmony_ci * of_find_all_nodes - Get next node in global list
2448c2ecf20Sopenharmony_ci * @prev:	Previous node or NULL to start iteration
2458c2ecf20Sopenharmony_ci *		of_node_put() will be called on it
2468c2ecf20Sopenharmony_ci *
2478c2ecf20Sopenharmony_ci * Return: A node pointer with refcount incremented, use
2488c2ecf20Sopenharmony_ci * of_node_put() on it when done.
2498c2ecf20Sopenharmony_ci */
2508c2ecf20Sopenharmony_cistruct device_node *of_find_all_nodes(struct device_node *prev)
2518c2ecf20Sopenharmony_ci{
2528c2ecf20Sopenharmony_ci	struct device_node *np;
2538c2ecf20Sopenharmony_ci	unsigned long flags;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
2568c2ecf20Sopenharmony_ci	np = __of_find_all_nodes(prev);
2578c2ecf20Sopenharmony_ci	of_node_get(np);
2588c2ecf20Sopenharmony_ci	of_node_put(prev);
2598c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
2608c2ecf20Sopenharmony_ci	return np;
2618c2ecf20Sopenharmony_ci}
2628c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_find_all_nodes);
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ci/*
2658c2ecf20Sopenharmony_ci * Find a property with a given name for a given node
2668c2ecf20Sopenharmony_ci * and return the value.
2678c2ecf20Sopenharmony_ci */
2688c2ecf20Sopenharmony_ciconst void *__of_get_property(const struct device_node *np,
2698c2ecf20Sopenharmony_ci			      const char *name, int *lenp)
2708c2ecf20Sopenharmony_ci{
2718c2ecf20Sopenharmony_ci	struct property *pp = __of_find_property(np, name, lenp);
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	return pp ? pp->value : NULL;
2748c2ecf20Sopenharmony_ci}
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci/*
2778c2ecf20Sopenharmony_ci * Find a property with a given name for a given node
2788c2ecf20Sopenharmony_ci * and return the value.
2798c2ecf20Sopenharmony_ci */
2808c2ecf20Sopenharmony_ciconst void *of_get_property(const struct device_node *np, const char *name,
2818c2ecf20Sopenharmony_ci			    int *lenp)
2828c2ecf20Sopenharmony_ci{
2838c2ecf20Sopenharmony_ci	struct property *pp = of_find_property(np, name, lenp);
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	return pp ? pp->value : NULL;
2868c2ecf20Sopenharmony_ci}
2878c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_get_property);
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci/*
2908c2ecf20Sopenharmony_ci * arch_match_cpu_phys_id - Match the given logical CPU and physical id
2918c2ecf20Sopenharmony_ci *
2928c2ecf20Sopenharmony_ci * @cpu: logical cpu index of a core/thread
2938c2ecf20Sopenharmony_ci * @phys_id: physical identifier of a core/thread
2948c2ecf20Sopenharmony_ci *
2958c2ecf20Sopenharmony_ci * CPU logical to physical index mapping is architecture specific.
2968c2ecf20Sopenharmony_ci * However this __weak function provides a default match of physical
2978c2ecf20Sopenharmony_ci * id to logical cpu index. phys_id provided here is usually values read
2988c2ecf20Sopenharmony_ci * from the device tree which must match the hardware internal registers.
2998c2ecf20Sopenharmony_ci *
3008c2ecf20Sopenharmony_ci * Returns true if the physical identifier and the logical cpu index
3018c2ecf20Sopenharmony_ci * correspond to the same core/thread, false otherwise.
3028c2ecf20Sopenharmony_ci */
3038c2ecf20Sopenharmony_cibool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id)
3048c2ecf20Sopenharmony_ci{
3058c2ecf20Sopenharmony_ci	return (u32)phys_id == cpu;
3068c2ecf20Sopenharmony_ci}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci/*
3098c2ecf20Sopenharmony_ci * Checks if the given "prop_name" property holds the physical id of the
3108c2ecf20Sopenharmony_ci * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not
3118c2ecf20Sopenharmony_ci * NULL, local thread number within the core is returned in it.
3128c2ecf20Sopenharmony_ci */
3138c2ecf20Sopenharmony_cistatic bool __of_find_n_match_cpu_property(struct device_node *cpun,
3148c2ecf20Sopenharmony_ci			const char *prop_name, int cpu, unsigned int *thread)
3158c2ecf20Sopenharmony_ci{
3168c2ecf20Sopenharmony_ci	const __be32 *cell;
3178c2ecf20Sopenharmony_ci	int ac, prop_len, tid;
3188c2ecf20Sopenharmony_ci	u64 hwid;
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci	ac = of_n_addr_cells(cpun);
3218c2ecf20Sopenharmony_ci	cell = of_get_property(cpun, prop_name, &prop_len);
3228c2ecf20Sopenharmony_ci	if (!cell && !ac && arch_match_cpu_phys_id(cpu, 0))
3238c2ecf20Sopenharmony_ci		return true;
3248c2ecf20Sopenharmony_ci	if (!cell || !ac)
3258c2ecf20Sopenharmony_ci		return false;
3268c2ecf20Sopenharmony_ci	prop_len /= sizeof(*cell) * ac;
3278c2ecf20Sopenharmony_ci	for (tid = 0; tid < prop_len; tid++) {
3288c2ecf20Sopenharmony_ci		hwid = of_read_number(cell, ac);
3298c2ecf20Sopenharmony_ci		if (arch_match_cpu_phys_id(cpu, hwid)) {
3308c2ecf20Sopenharmony_ci			if (thread)
3318c2ecf20Sopenharmony_ci				*thread = tid;
3328c2ecf20Sopenharmony_ci			return true;
3338c2ecf20Sopenharmony_ci		}
3348c2ecf20Sopenharmony_ci		cell += ac;
3358c2ecf20Sopenharmony_ci	}
3368c2ecf20Sopenharmony_ci	return false;
3378c2ecf20Sopenharmony_ci}
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci/*
3408c2ecf20Sopenharmony_ci * arch_find_n_match_cpu_physical_id - See if the given device node is
3418c2ecf20Sopenharmony_ci * for the cpu corresponding to logical cpu 'cpu'.  Return true if so,
3428c2ecf20Sopenharmony_ci * else false.  If 'thread' is non-NULL, the local thread number within the
3438c2ecf20Sopenharmony_ci * core is returned in it.
3448c2ecf20Sopenharmony_ci */
3458c2ecf20Sopenharmony_cibool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun,
3468c2ecf20Sopenharmony_ci					      int cpu, unsigned int *thread)
3478c2ecf20Sopenharmony_ci{
3488c2ecf20Sopenharmony_ci	/* Check for non-standard "ibm,ppc-interrupt-server#s" property
3498c2ecf20Sopenharmony_ci	 * for thread ids on PowerPC. If it doesn't exist fallback to
3508c2ecf20Sopenharmony_ci	 * standard "reg" property.
3518c2ecf20Sopenharmony_ci	 */
3528c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_PPC) &&
3538c2ecf20Sopenharmony_ci	    __of_find_n_match_cpu_property(cpun,
3548c2ecf20Sopenharmony_ci					   "ibm,ppc-interrupt-server#s",
3558c2ecf20Sopenharmony_ci					   cpu, thread))
3568c2ecf20Sopenharmony_ci		return true;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	return __of_find_n_match_cpu_property(cpun, "reg", cpu, thread);
3598c2ecf20Sopenharmony_ci}
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_ci/**
3628c2ecf20Sopenharmony_ci * of_get_cpu_node - Get device node associated with the given logical CPU
3638c2ecf20Sopenharmony_ci *
3648c2ecf20Sopenharmony_ci * @cpu: CPU number(logical index) for which device node is required
3658c2ecf20Sopenharmony_ci * @thread: if not NULL, local thread number within the physical core is
3668c2ecf20Sopenharmony_ci *          returned
3678c2ecf20Sopenharmony_ci *
3688c2ecf20Sopenharmony_ci * The main purpose of this function is to retrieve the device node for the
3698c2ecf20Sopenharmony_ci * given logical CPU index. It should be used to initialize the of_node in
3708c2ecf20Sopenharmony_ci * cpu device. Once of_node in cpu device is populated, all the further
3718c2ecf20Sopenharmony_ci * references can use that instead.
3728c2ecf20Sopenharmony_ci *
3738c2ecf20Sopenharmony_ci * CPU logical to physical index mapping is architecture specific and is built
3748c2ecf20Sopenharmony_ci * before booting secondary cores. This function uses arch_match_cpu_phys_id
3758c2ecf20Sopenharmony_ci * which can be overridden by architecture specific implementation.
3768c2ecf20Sopenharmony_ci *
3778c2ecf20Sopenharmony_ci * Return: A node pointer for the logical cpu with refcount incremented, use
3788c2ecf20Sopenharmony_ci * of_node_put() on it when done. Returns NULL if not found.
3798c2ecf20Sopenharmony_ci */
3808c2ecf20Sopenharmony_cistruct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
3818c2ecf20Sopenharmony_ci{
3828c2ecf20Sopenharmony_ci	struct device_node *cpun;
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	for_each_of_cpu_node(cpun) {
3858c2ecf20Sopenharmony_ci		if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread))
3868c2ecf20Sopenharmony_ci			return cpun;
3878c2ecf20Sopenharmony_ci	}
3888c2ecf20Sopenharmony_ci	return NULL;
3898c2ecf20Sopenharmony_ci}
3908c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_get_cpu_node);
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci/**
3938c2ecf20Sopenharmony_ci * of_cpu_node_to_id: Get the logical CPU number for a given device_node
3948c2ecf20Sopenharmony_ci *
3958c2ecf20Sopenharmony_ci * @cpu_node: Pointer to the device_node for CPU.
3968c2ecf20Sopenharmony_ci *
3978c2ecf20Sopenharmony_ci * Return: The logical CPU number of the given CPU device_node or -ENODEV if the
3988c2ecf20Sopenharmony_ci * CPU is not found.
3998c2ecf20Sopenharmony_ci */
4008c2ecf20Sopenharmony_ciint of_cpu_node_to_id(struct device_node *cpu_node)
4018c2ecf20Sopenharmony_ci{
4028c2ecf20Sopenharmony_ci	int cpu;
4038c2ecf20Sopenharmony_ci	bool found = false;
4048c2ecf20Sopenharmony_ci	struct device_node *np;
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	for_each_possible_cpu(cpu) {
4078c2ecf20Sopenharmony_ci		np = of_cpu_device_node_get(cpu);
4088c2ecf20Sopenharmony_ci		found = (cpu_node == np);
4098c2ecf20Sopenharmony_ci		of_node_put(np);
4108c2ecf20Sopenharmony_ci		if (found)
4118c2ecf20Sopenharmony_ci			return cpu;
4128c2ecf20Sopenharmony_ci	}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	return -ENODEV;
4158c2ecf20Sopenharmony_ci}
4168c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_cpu_node_to_id);
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci/**
4198c2ecf20Sopenharmony_ci * of_get_cpu_state_node - Get CPU's idle state node at the given index
4208c2ecf20Sopenharmony_ci *
4218c2ecf20Sopenharmony_ci * @cpu_node: The device node for the CPU
4228c2ecf20Sopenharmony_ci * @index: The index in the list of the idle states
4238c2ecf20Sopenharmony_ci *
4248c2ecf20Sopenharmony_ci * Two generic methods can be used to describe a CPU's idle states, either via
4258c2ecf20Sopenharmony_ci * a flattened description through the "cpu-idle-states" binding or via the
4268c2ecf20Sopenharmony_ci * hierarchical layout, using the "power-domains" and the "domain-idle-states"
4278c2ecf20Sopenharmony_ci * bindings. This function check for both and returns the idle state node for
4288c2ecf20Sopenharmony_ci * the requested index.
4298c2ecf20Sopenharmony_ci *
4308c2ecf20Sopenharmony_ci * Return: An idle state node if found at @index. The refcount is incremented
4318c2ecf20Sopenharmony_ci * for it, so call of_node_put() on it when done. Returns NULL if not found.
4328c2ecf20Sopenharmony_ci */
4338c2ecf20Sopenharmony_cistruct device_node *of_get_cpu_state_node(struct device_node *cpu_node,
4348c2ecf20Sopenharmony_ci					  int index)
4358c2ecf20Sopenharmony_ci{
4368c2ecf20Sopenharmony_ci	struct of_phandle_args args;
4378c2ecf20Sopenharmony_ci	int err;
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	err = of_parse_phandle_with_args(cpu_node, "power-domains",
4408c2ecf20Sopenharmony_ci					"#power-domain-cells", 0, &args);
4418c2ecf20Sopenharmony_ci	if (!err) {
4428c2ecf20Sopenharmony_ci		struct device_node *state_node =
4438c2ecf20Sopenharmony_ci			of_parse_phandle(args.np, "domain-idle-states", index);
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci		of_node_put(args.np);
4468c2ecf20Sopenharmony_ci		if (state_node)
4478c2ecf20Sopenharmony_ci			return state_node;
4488c2ecf20Sopenharmony_ci	}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	return of_parse_phandle(cpu_node, "cpu-idle-states", index);
4518c2ecf20Sopenharmony_ci}
4528c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_get_cpu_state_node);
4538c2ecf20Sopenharmony_ci
4548c2ecf20Sopenharmony_ci/**
4558c2ecf20Sopenharmony_ci * __of_device_is_compatible() - Check if the node matches given constraints
4568c2ecf20Sopenharmony_ci * @device: pointer to node
4578c2ecf20Sopenharmony_ci * @compat: required compatible string, NULL or "" for any match
4588c2ecf20Sopenharmony_ci * @type: required device_type value, NULL or "" for any match
4598c2ecf20Sopenharmony_ci * @name: required node name, NULL or "" for any match
4608c2ecf20Sopenharmony_ci *
4618c2ecf20Sopenharmony_ci * Checks if the given @compat, @type and @name strings match the
4628c2ecf20Sopenharmony_ci * properties of the given @device. A constraints can be skipped by
4638c2ecf20Sopenharmony_ci * passing NULL or an empty string as the constraint.
4648c2ecf20Sopenharmony_ci *
4658c2ecf20Sopenharmony_ci * Returns 0 for no match, and a positive integer on match. The return
4668c2ecf20Sopenharmony_ci * value is a relative score with larger values indicating better
4678c2ecf20Sopenharmony_ci * matches. The score is weighted for the most specific compatible value
4688c2ecf20Sopenharmony_ci * to get the highest score. Matching type is next, followed by matching
4698c2ecf20Sopenharmony_ci * name. Practically speaking, this results in the following priority
4708c2ecf20Sopenharmony_ci * order for matches:
4718c2ecf20Sopenharmony_ci *
4728c2ecf20Sopenharmony_ci * 1. specific compatible && type && name
4738c2ecf20Sopenharmony_ci * 2. specific compatible && type
4748c2ecf20Sopenharmony_ci * 3. specific compatible && name
4758c2ecf20Sopenharmony_ci * 4. specific compatible
4768c2ecf20Sopenharmony_ci * 5. general compatible && type && name
4778c2ecf20Sopenharmony_ci * 6. general compatible && type
4788c2ecf20Sopenharmony_ci * 7. general compatible && name
4798c2ecf20Sopenharmony_ci * 8. general compatible
4808c2ecf20Sopenharmony_ci * 9. type && name
4818c2ecf20Sopenharmony_ci * 10. type
4828c2ecf20Sopenharmony_ci * 11. name
4838c2ecf20Sopenharmony_ci */
4848c2ecf20Sopenharmony_cistatic int __of_device_is_compatible(const struct device_node *device,
4858c2ecf20Sopenharmony_ci				     const char *compat, const char *type, const char *name)
4868c2ecf20Sopenharmony_ci{
4878c2ecf20Sopenharmony_ci	struct property *prop;
4888c2ecf20Sopenharmony_ci	const char *cp;
4898c2ecf20Sopenharmony_ci	int index = 0, score = 0;
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci	/* Compatible match has highest priority */
4928c2ecf20Sopenharmony_ci	if (compat && compat[0]) {
4938c2ecf20Sopenharmony_ci		prop = __of_find_property(device, "compatible", NULL);
4948c2ecf20Sopenharmony_ci		for (cp = of_prop_next_string(prop, NULL); cp;
4958c2ecf20Sopenharmony_ci		     cp = of_prop_next_string(prop, cp), index++) {
4968c2ecf20Sopenharmony_ci			if (of_compat_cmp(cp, compat, strlen(compat)) == 0) {
4978c2ecf20Sopenharmony_ci				score = INT_MAX/2 - (index << 2);
4988c2ecf20Sopenharmony_ci				break;
4998c2ecf20Sopenharmony_ci			}
5008c2ecf20Sopenharmony_ci		}
5018c2ecf20Sopenharmony_ci		if (!score)
5028c2ecf20Sopenharmony_ci			return 0;
5038c2ecf20Sopenharmony_ci	}
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	/* Matching type is better than matching name */
5068c2ecf20Sopenharmony_ci	if (type && type[0]) {
5078c2ecf20Sopenharmony_ci		if (!__of_node_is_type(device, type))
5088c2ecf20Sopenharmony_ci			return 0;
5098c2ecf20Sopenharmony_ci		score += 2;
5108c2ecf20Sopenharmony_ci	}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_ci	/* Matching name is a bit better than not */
5138c2ecf20Sopenharmony_ci	if (name && name[0]) {
5148c2ecf20Sopenharmony_ci		if (!of_node_name_eq(device, name))
5158c2ecf20Sopenharmony_ci			return 0;
5168c2ecf20Sopenharmony_ci		score++;
5178c2ecf20Sopenharmony_ci	}
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	return score;
5208c2ecf20Sopenharmony_ci}
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci/** Checks if the given "compat" string matches one of the strings in
5238c2ecf20Sopenharmony_ci * the device's "compatible" property
5248c2ecf20Sopenharmony_ci */
5258c2ecf20Sopenharmony_ciint of_device_is_compatible(const struct device_node *device,
5268c2ecf20Sopenharmony_ci		const char *compat)
5278c2ecf20Sopenharmony_ci{
5288c2ecf20Sopenharmony_ci	unsigned long flags;
5298c2ecf20Sopenharmony_ci	int res;
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
5328c2ecf20Sopenharmony_ci	res = __of_device_is_compatible(device, compat, NULL, NULL);
5338c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
5348c2ecf20Sopenharmony_ci	return res;
5358c2ecf20Sopenharmony_ci}
5368c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_device_is_compatible);
5378c2ecf20Sopenharmony_ci
5388c2ecf20Sopenharmony_ci/** Checks if the device is compatible with any of the entries in
5398c2ecf20Sopenharmony_ci *  a NULL terminated array of strings. Returns the best match
5408c2ecf20Sopenharmony_ci *  score or 0.
5418c2ecf20Sopenharmony_ci */
5428c2ecf20Sopenharmony_ciint of_device_compatible_match(struct device_node *device,
5438c2ecf20Sopenharmony_ci			       const char *const *compat)
5448c2ecf20Sopenharmony_ci{
5458c2ecf20Sopenharmony_ci	unsigned int tmp, score = 0;
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	if (!compat)
5488c2ecf20Sopenharmony_ci		return 0;
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci	while (*compat) {
5518c2ecf20Sopenharmony_ci		tmp = of_device_is_compatible(device, *compat);
5528c2ecf20Sopenharmony_ci		if (tmp > score)
5538c2ecf20Sopenharmony_ci			score = tmp;
5548c2ecf20Sopenharmony_ci		compat++;
5558c2ecf20Sopenharmony_ci	}
5568c2ecf20Sopenharmony_ci
5578c2ecf20Sopenharmony_ci	return score;
5588c2ecf20Sopenharmony_ci}
5598c2ecf20Sopenharmony_ci
5608c2ecf20Sopenharmony_ci/**
5618c2ecf20Sopenharmony_ci * of_machine_is_compatible - Test root of device tree for a given compatible value
5628c2ecf20Sopenharmony_ci * @compat: compatible string to look for in root node's compatible property.
5638c2ecf20Sopenharmony_ci *
5648c2ecf20Sopenharmony_ci * Return: A positive integer if the root node has the given value in its
5658c2ecf20Sopenharmony_ci * compatible property.
5668c2ecf20Sopenharmony_ci */
5678c2ecf20Sopenharmony_ciint of_machine_is_compatible(const char *compat)
5688c2ecf20Sopenharmony_ci{
5698c2ecf20Sopenharmony_ci	struct device_node *root;
5708c2ecf20Sopenharmony_ci	int rc = 0;
5718c2ecf20Sopenharmony_ci
5728c2ecf20Sopenharmony_ci	root = of_find_node_by_path("/");
5738c2ecf20Sopenharmony_ci	if (root) {
5748c2ecf20Sopenharmony_ci		rc = of_device_is_compatible(root, compat);
5758c2ecf20Sopenharmony_ci		of_node_put(root);
5768c2ecf20Sopenharmony_ci	}
5778c2ecf20Sopenharmony_ci	return rc;
5788c2ecf20Sopenharmony_ci}
5798c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_machine_is_compatible);
5808c2ecf20Sopenharmony_ci
5818c2ecf20Sopenharmony_ci/**
5828c2ecf20Sopenharmony_ci *  __of_device_is_available - check if a device is available for use
5838c2ecf20Sopenharmony_ci *
5848c2ecf20Sopenharmony_ci *  @device: Node to check for availability, with locks already held
5858c2ecf20Sopenharmony_ci *
5868c2ecf20Sopenharmony_ci *  Return: True if the status property is absent or set to "okay" or "ok",
5878c2ecf20Sopenharmony_ci *  false otherwise
5888c2ecf20Sopenharmony_ci */
5898c2ecf20Sopenharmony_cistatic bool __of_device_is_available(const struct device_node *device)
5908c2ecf20Sopenharmony_ci{
5918c2ecf20Sopenharmony_ci	const char *status;
5928c2ecf20Sopenharmony_ci	int statlen;
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci	if (!device)
5958c2ecf20Sopenharmony_ci		return false;
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci	status = __of_get_property(device, "status", &statlen);
5988c2ecf20Sopenharmony_ci	if (status == NULL)
5998c2ecf20Sopenharmony_ci		return true;
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci	if (statlen > 0) {
6028c2ecf20Sopenharmony_ci		if (!strcmp(status, "okay") || !strcmp(status, "ok"))
6038c2ecf20Sopenharmony_ci			return true;
6048c2ecf20Sopenharmony_ci	}
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_ci	return false;
6078c2ecf20Sopenharmony_ci}
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci/**
6108c2ecf20Sopenharmony_ci *  of_device_is_available - check if a device is available for use
6118c2ecf20Sopenharmony_ci *
6128c2ecf20Sopenharmony_ci *  @device: Node to check for availability
6138c2ecf20Sopenharmony_ci *
6148c2ecf20Sopenharmony_ci *  Return: True if the status property is absent or set to "okay" or "ok",
6158c2ecf20Sopenharmony_ci *  false otherwise
6168c2ecf20Sopenharmony_ci */
6178c2ecf20Sopenharmony_cibool of_device_is_available(const struct device_node *device)
6188c2ecf20Sopenharmony_ci{
6198c2ecf20Sopenharmony_ci	unsigned long flags;
6208c2ecf20Sopenharmony_ci	bool res;
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
6238c2ecf20Sopenharmony_ci	res = __of_device_is_available(device);
6248c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
6258c2ecf20Sopenharmony_ci	return res;
6268c2ecf20Sopenharmony_ci
6278c2ecf20Sopenharmony_ci}
6288c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_device_is_available);
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci/**
6318c2ecf20Sopenharmony_ci *  of_device_is_big_endian - check if a device has BE registers
6328c2ecf20Sopenharmony_ci *
6338c2ecf20Sopenharmony_ci *  @device: Node to check for endianness
6348c2ecf20Sopenharmony_ci *
6358c2ecf20Sopenharmony_ci *  Return: True if the device has a "big-endian" property, or if the kernel
6368c2ecf20Sopenharmony_ci *  was compiled for BE *and* the device has a "native-endian" property.
6378c2ecf20Sopenharmony_ci *  Returns false otherwise.
6388c2ecf20Sopenharmony_ci *
6398c2ecf20Sopenharmony_ci *  Callers would nominally use ioread32be/iowrite32be if
6408c2ecf20Sopenharmony_ci *  of_device_is_big_endian() == true, or readl/writel otherwise.
6418c2ecf20Sopenharmony_ci */
6428c2ecf20Sopenharmony_cibool of_device_is_big_endian(const struct device_node *device)
6438c2ecf20Sopenharmony_ci{
6448c2ecf20Sopenharmony_ci	if (of_property_read_bool(device, "big-endian"))
6458c2ecf20Sopenharmony_ci		return true;
6468c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) &&
6478c2ecf20Sopenharmony_ci	    of_property_read_bool(device, "native-endian"))
6488c2ecf20Sopenharmony_ci		return true;
6498c2ecf20Sopenharmony_ci	return false;
6508c2ecf20Sopenharmony_ci}
6518c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_device_is_big_endian);
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci/**
6548c2ecf20Sopenharmony_ci * of_get_parent - Get a node's parent if any
6558c2ecf20Sopenharmony_ci * @node:	Node to get parent
6568c2ecf20Sopenharmony_ci *
6578c2ecf20Sopenharmony_ci * Return: A node pointer with refcount incremented, use
6588c2ecf20Sopenharmony_ci * of_node_put() on it when done.
6598c2ecf20Sopenharmony_ci */
6608c2ecf20Sopenharmony_cistruct device_node *of_get_parent(const struct device_node *node)
6618c2ecf20Sopenharmony_ci{
6628c2ecf20Sopenharmony_ci	struct device_node *np;
6638c2ecf20Sopenharmony_ci	unsigned long flags;
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	if (!node)
6668c2ecf20Sopenharmony_ci		return NULL;
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
6698c2ecf20Sopenharmony_ci	np = of_node_get(node->parent);
6708c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
6718c2ecf20Sopenharmony_ci	return np;
6728c2ecf20Sopenharmony_ci}
6738c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_get_parent);
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ci/**
6768c2ecf20Sopenharmony_ci * of_get_next_parent - Iterate to a node's parent
6778c2ecf20Sopenharmony_ci * @node:	Node to get parent of
6788c2ecf20Sopenharmony_ci *
6798c2ecf20Sopenharmony_ci * This is like of_get_parent() except that it drops the
6808c2ecf20Sopenharmony_ci * refcount on the passed node, making it suitable for iterating
6818c2ecf20Sopenharmony_ci * through a node's parents.
6828c2ecf20Sopenharmony_ci *
6838c2ecf20Sopenharmony_ci * Return: A node pointer with refcount incremented, use
6848c2ecf20Sopenharmony_ci * of_node_put() on it when done.
6858c2ecf20Sopenharmony_ci */
6868c2ecf20Sopenharmony_cistruct device_node *of_get_next_parent(struct device_node *node)
6878c2ecf20Sopenharmony_ci{
6888c2ecf20Sopenharmony_ci	struct device_node *parent;
6898c2ecf20Sopenharmony_ci	unsigned long flags;
6908c2ecf20Sopenharmony_ci
6918c2ecf20Sopenharmony_ci	if (!node)
6928c2ecf20Sopenharmony_ci		return NULL;
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
6958c2ecf20Sopenharmony_ci	parent = of_node_get(node->parent);
6968c2ecf20Sopenharmony_ci	of_node_put(node);
6978c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
6988c2ecf20Sopenharmony_ci	return parent;
6998c2ecf20Sopenharmony_ci}
7008c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_get_next_parent);
7018c2ecf20Sopenharmony_ci
7028c2ecf20Sopenharmony_cistatic struct device_node *__of_get_next_child(const struct device_node *node,
7038c2ecf20Sopenharmony_ci						struct device_node *prev)
7048c2ecf20Sopenharmony_ci{
7058c2ecf20Sopenharmony_ci	struct device_node *next;
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	if (!node)
7088c2ecf20Sopenharmony_ci		return NULL;
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	next = prev ? prev->sibling : node->child;
7118c2ecf20Sopenharmony_ci	for (; next; next = next->sibling)
7128c2ecf20Sopenharmony_ci		if (of_node_get(next))
7138c2ecf20Sopenharmony_ci			break;
7148c2ecf20Sopenharmony_ci	of_node_put(prev);
7158c2ecf20Sopenharmony_ci	return next;
7168c2ecf20Sopenharmony_ci}
7178c2ecf20Sopenharmony_ci#define __for_each_child_of_node(parent, child) \
7188c2ecf20Sopenharmony_ci	for (child = __of_get_next_child(parent, NULL); child != NULL; \
7198c2ecf20Sopenharmony_ci	     child = __of_get_next_child(parent, child))
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_ci/**
7228c2ecf20Sopenharmony_ci * of_get_next_child - Iterate a node childs
7238c2ecf20Sopenharmony_ci * @node:	parent node
7248c2ecf20Sopenharmony_ci * @prev:	previous child of the parent node, or NULL to get first
7258c2ecf20Sopenharmony_ci *
7268c2ecf20Sopenharmony_ci * Return: A node pointer with refcount incremented, use of_node_put() on
7278c2ecf20Sopenharmony_ci * it when done. Returns NULL when prev is the last child. Decrements the
7288c2ecf20Sopenharmony_ci * refcount of prev.
7298c2ecf20Sopenharmony_ci */
7308c2ecf20Sopenharmony_cistruct device_node *of_get_next_child(const struct device_node *node,
7318c2ecf20Sopenharmony_ci	struct device_node *prev)
7328c2ecf20Sopenharmony_ci{
7338c2ecf20Sopenharmony_ci	struct device_node *next;
7348c2ecf20Sopenharmony_ci	unsigned long flags;
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
7378c2ecf20Sopenharmony_ci	next = __of_get_next_child(node, prev);
7388c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
7398c2ecf20Sopenharmony_ci	return next;
7408c2ecf20Sopenharmony_ci}
7418c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_get_next_child);
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci/**
7448c2ecf20Sopenharmony_ci * of_get_next_available_child - Find the next available child node
7458c2ecf20Sopenharmony_ci * @node:	parent node
7468c2ecf20Sopenharmony_ci * @prev:	previous child of the parent node, or NULL to get first
7478c2ecf20Sopenharmony_ci *
7488c2ecf20Sopenharmony_ci * This function is like of_get_next_child(), except that it
7498c2ecf20Sopenharmony_ci * automatically skips any disabled nodes (i.e. status = "disabled").
7508c2ecf20Sopenharmony_ci */
7518c2ecf20Sopenharmony_cistruct device_node *of_get_next_available_child(const struct device_node *node,
7528c2ecf20Sopenharmony_ci	struct device_node *prev)
7538c2ecf20Sopenharmony_ci{
7548c2ecf20Sopenharmony_ci	struct device_node *next;
7558c2ecf20Sopenharmony_ci	unsigned long flags;
7568c2ecf20Sopenharmony_ci
7578c2ecf20Sopenharmony_ci	if (!node)
7588c2ecf20Sopenharmony_ci		return NULL;
7598c2ecf20Sopenharmony_ci
7608c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
7618c2ecf20Sopenharmony_ci	next = prev ? prev->sibling : node->child;
7628c2ecf20Sopenharmony_ci	for (; next; next = next->sibling) {
7638c2ecf20Sopenharmony_ci		if (!__of_device_is_available(next))
7648c2ecf20Sopenharmony_ci			continue;
7658c2ecf20Sopenharmony_ci		if (of_node_get(next))
7668c2ecf20Sopenharmony_ci			break;
7678c2ecf20Sopenharmony_ci	}
7688c2ecf20Sopenharmony_ci	of_node_put(prev);
7698c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
7708c2ecf20Sopenharmony_ci	return next;
7718c2ecf20Sopenharmony_ci}
7728c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_get_next_available_child);
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_ci/**
7758c2ecf20Sopenharmony_ci * of_get_next_cpu_node - Iterate on cpu nodes
7768c2ecf20Sopenharmony_ci * @prev:	previous child of the /cpus node, or NULL to get first
7778c2ecf20Sopenharmony_ci *
7788c2ecf20Sopenharmony_ci * Return: A cpu node pointer with refcount incremented, use of_node_put()
7798c2ecf20Sopenharmony_ci * on it when done. Returns NULL when prev is the last child. Decrements
7808c2ecf20Sopenharmony_ci * the refcount of prev.
7818c2ecf20Sopenharmony_ci */
7828c2ecf20Sopenharmony_cistruct device_node *of_get_next_cpu_node(struct device_node *prev)
7838c2ecf20Sopenharmony_ci{
7848c2ecf20Sopenharmony_ci	struct device_node *next = NULL;
7858c2ecf20Sopenharmony_ci	unsigned long flags;
7868c2ecf20Sopenharmony_ci	struct device_node *node;
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_ci	if (!prev)
7898c2ecf20Sopenharmony_ci		node = of_find_node_by_path("/cpus");
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
7928c2ecf20Sopenharmony_ci	if (prev)
7938c2ecf20Sopenharmony_ci		next = prev->sibling;
7948c2ecf20Sopenharmony_ci	else if (node) {
7958c2ecf20Sopenharmony_ci		next = node->child;
7968c2ecf20Sopenharmony_ci		of_node_put(node);
7978c2ecf20Sopenharmony_ci	}
7988c2ecf20Sopenharmony_ci	for (; next; next = next->sibling) {
7998c2ecf20Sopenharmony_ci		if (!(of_node_name_eq(next, "cpu") ||
8008c2ecf20Sopenharmony_ci		      __of_node_is_type(next, "cpu")))
8018c2ecf20Sopenharmony_ci			continue;
8028c2ecf20Sopenharmony_ci		if (of_node_get(next))
8038c2ecf20Sopenharmony_ci			break;
8048c2ecf20Sopenharmony_ci	}
8058c2ecf20Sopenharmony_ci	of_node_put(prev);
8068c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
8078c2ecf20Sopenharmony_ci	return next;
8088c2ecf20Sopenharmony_ci}
8098c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_get_next_cpu_node);
8108c2ecf20Sopenharmony_ci
8118c2ecf20Sopenharmony_ci/**
8128c2ecf20Sopenharmony_ci * of_get_compatible_child - Find compatible child node
8138c2ecf20Sopenharmony_ci * @parent:	parent node
8148c2ecf20Sopenharmony_ci * @compatible:	compatible string
8158c2ecf20Sopenharmony_ci *
8168c2ecf20Sopenharmony_ci * Lookup child node whose compatible property contains the given compatible
8178c2ecf20Sopenharmony_ci * string.
8188c2ecf20Sopenharmony_ci *
8198c2ecf20Sopenharmony_ci * Return: a node pointer with refcount incremented, use of_node_put() on it
8208c2ecf20Sopenharmony_ci * when done; or NULL if not found.
8218c2ecf20Sopenharmony_ci */
8228c2ecf20Sopenharmony_cistruct device_node *of_get_compatible_child(const struct device_node *parent,
8238c2ecf20Sopenharmony_ci				const char *compatible)
8248c2ecf20Sopenharmony_ci{
8258c2ecf20Sopenharmony_ci	struct device_node *child;
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_ci	for_each_child_of_node(parent, child) {
8288c2ecf20Sopenharmony_ci		if (of_device_is_compatible(child, compatible))
8298c2ecf20Sopenharmony_ci			break;
8308c2ecf20Sopenharmony_ci	}
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_ci	return child;
8338c2ecf20Sopenharmony_ci}
8348c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_get_compatible_child);
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_ci/**
8378c2ecf20Sopenharmony_ci * of_get_child_by_name - Find the child node by name for a given parent
8388c2ecf20Sopenharmony_ci * @node:	parent node
8398c2ecf20Sopenharmony_ci * @name:	child name to look for.
8408c2ecf20Sopenharmony_ci *
8418c2ecf20Sopenharmony_ci * This function looks for child node for given matching name
8428c2ecf20Sopenharmony_ci *
8438c2ecf20Sopenharmony_ci * Return: A node pointer if found, with refcount incremented, use
8448c2ecf20Sopenharmony_ci * of_node_put() on it when done.
8458c2ecf20Sopenharmony_ci * Returns NULL if node is not found.
8468c2ecf20Sopenharmony_ci */
8478c2ecf20Sopenharmony_cistruct device_node *of_get_child_by_name(const struct device_node *node,
8488c2ecf20Sopenharmony_ci				const char *name)
8498c2ecf20Sopenharmony_ci{
8508c2ecf20Sopenharmony_ci	struct device_node *child;
8518c2ecf20Sopenharmony_ci
8528c2ecf20Sopenharmony_ci	for_each_child_of_node(node, child)
8538c2ecf20Sopenharmony_ci		if (of_node_name_eq(child, name))
8548c2ecf20Sopenharmony_ci			break;
8558c2ecf20Sopenharmony_ci	return child;
8568c2ecf20Sopenharmony_ci}
8578c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_get_child_by_name);
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_cistruct device_node *__of_find_node_by_path(struct device_node *parent,
8608c2ecf20Sopenharmony_ci						const char *path)
8618c2ecf20Sopenharmony_ci{
8628c2ecf20Sopenharmony_ci	struct device_node *child;
8638c2ecf20Sopenharmony_ci	int len;
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci	len = strcspn(path, "/:");
8668c2ecf20Sopenharmony_ci	if (!len)
8678c2ecf20Sopenharmony_ci		return NULL;
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	__for_each_child_of_node(parent, child) {
8708c2ecf20Sopenharmony_ci		const char *name = kbasename(child->full_name);
8718c2ecf20Sopenharmony_ci		if (strncmp(path, name, len) == 0 && (strlen(name) == len))
8728c2ecf20Sopenharmony_ci			return child;
8738c2ecf20Sopenharmony_ci	}
8748c2ecf20Sopenharmony_ci	return NULL;
8758c2ecf20Sopenharmony_ci}
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_cistruct device_node *__of_find_node_by_full_path(struct device_node *node,
8788c2ecf20Sopenharmony_ci						const char *path)
8798c2ecf20Sopenharmony_ci{
8808c2ecf20Sopenharmony_ci	const char *separator = strchr(path, ':');
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci	while (node && *path == '/') {
8838c2ecf20Sopenharmony_ci		struct device_node *tmp = node;
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci		path++; /* Increment past '/' delimiter */
8868c2ecf20Sopenharmony_ci		node = __of_find_node_by_path(node, path);
8878c2ecf20Sopenharmony_ci		of_node_put(tmp);
8888c2ecf20Sopenharmony_ci		path = strchrnul(path, '/');
8898c2ecf20Sopenharmony_ci		if (separator && separator < path)
8908c2ecf20Sopenharmony_ci			break;
8918c2ecf20Sopenharmony_ci	}
8928c2ecf20Sopenharmony_ci	return node;
8938c2ecf20Sopenharmony_ci}
8948c2ecf20Sopenharmony_ci
8958c2ecf20Sopenharmony_ci/**
8968c2ecf20Sopenharmony_ci * of_find_node_opts_by_path - Find a node matching a full OF path
8978c2ecf20Sopenharmony_ci * @path: Either the full path to match, or if the path does not
8988c2ecf20Sopenharmony_ci *       start with '/', the name of a property of the /aliases
8998c2ecf20Sopenharmony_ci *       node (an alias).  In the case of an alias, the node
9008c2ecf20Sopenharmony_ci *       matching the alias' value will be returned.
9018c2ecf20Sopenharmony_ci * @opts: Address of a pointer into which to store the start of
9028c2ecf20Sopenharmony_ci *       an options string appended to the end of the path with
9038c2ecf20Sopenharmony_ci *       a ':' separator.
9048c2ecf20Sopenharmony_ci *
9058c2ecf20Sopenharmony_ci * Valid paths:
9068c2ecf20Sopenharmony_ci *  * /foo/bar	Full path
9078c2ecf20Sopenharmony_ci *  * foo	Valid alias
9088c2ecf20Sopenharmony_ci *  * foo/bar	Valid alias + relative path
9098c2ecf20Sopenharmony_ci *
9108c2ecf20Sopenharmony_ci * Return: A node pointer with refcount incremented, use
9118c2ecf20Sopenharmony_ci * of_node_put() on it when done.
9128c2ecf20Sopenharmony_ci */
9138c2ecf20Sopenharmony_cistruct device_node *of_find_node_opts_by_path(const char *path, const char **opts)
9148c2ecf20Sopenharmony_ci{
9158c2ecf20Sopenharmony_ci	struct device_node *np = NULL;
9168c2ecf20Sopenharmony_ci	struct property *pp;
9178c2ecf20Sopenharmony_ci	unsigned long flags;
9188c2ecf20Sopenharmony_ci	const char *separator = strchr(path, ':');
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	if (opts)
9218c2ecf20Sopenharmony_ci		*opts = separator ? separator + 1 : NULL;
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci	if (strcmp(path, "/") == 0)
9248c2ecf20Sopenharmony_ci		return of_node_get(of_root);
9258c2ecf20Sopenharmony_ci
9268c2ecf20Sopenharmony_ci	/* The path could begin with an alias */
9278c2ecf20Sopenharmony_ci	if (*path != '/') {
9288c2ecf20Sopenharmony_ci		int len;
9298c2ecf20Sopenharmony_ci		const char *p = separator;
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci		if (!p)
9328c2ecf20Sopenharmony_ci			p = strchrnul(path, '/');
9338c2ecf20Sopenharmony_ci		len = p - path;
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_ci		/* of_aliases must not be NULL */
9368c2ecf20Sopenharmony_ci		if (!of_aliases)
9378c2ecf20Sopenharmony_ci			return NULL;
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ci		for_each_property_of_node(of_aliases, pp) {
9408c2ecf20Sopenharmony_ci			if (strlen(pp->name) == len && !strncmp(pp->name, path, len)) {
9418c2ecf20Sopenharmony_ci				np = of_find_node_by_path(pp->value);
9428c2ecf20Sopenharmony_ci				break;
9438c2ecf20Sopenharmony_ci			}
9448c2ecf20Sopenharmony_ci		}
9458c2ecf20Sopenharmony_ci		if (!np)
9468c2ecf20Sopenharmony_ci			return NULL;
9478c2ecf20Sopenharmony_ci		path = p;
9488c2ecf20Sopenharmony_ci	}
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_ci	/* Step down the tree matching path components */
9518c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
9528c2ecf20Sopenharmony_ci	if (!np)
9538c2ecf20Sopenharmony_ci		np = of_node_get(of_root);
9548c2ecf20Sopenharmony_ci	np = __of_find_node_by_full_path(np, path);
9558c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
9568c2ecf20Sopenharmony_ci	return np;
9578c2ecf20Sopenharmony_ci}
9588c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_find_node_opts_by_path);
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_ci/**
9618c2ecf20Sopenharmony_ci * of_find_node_by_name - Find a node by its "name" property
9628c2ecf20Sopenharmony_ci * @from:	The node to start searching from or NULL; the node
9638c2ecf20Sopenharmony_ci *		you pass will not be searched, only the next one
9648c2ecf20Sopenharmony_ci *		will. Typically, you pass what the previous call
9658c2ecf20Sopenharmony_ci *		returned. of_node_put() will be called on @from.
9668c2ecf20Sopenharmony_ci * @name:	The name string to match against
9678c2ecf20Sopenharmony_ci *
9688c2ecf20Sopenharmony_ci * Return: A node pointer with refcount incremented, use
9698c2ecf20Sopenharmony_ci * of_node_put() on it when done.
9708c2ecf20Sopenharmony_ci */
9718c2ecf20Sopenharmony_cistruct device_node *of_find_node_by_name(struct device_node *from,
9728c2ecf20Sopenharmony_ci	const char *name)
9738c2ecf20Sopenharmony_ci{
9748c2ecf20Sopenharmony_ci	struct device_node *np;
9758c2ecf20Sopenharmony_ci	unsigned long flags;
9768c2ecf20Sopenharmony_ci
9778c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
9788c2ecf20Sopenharmony_ci	for_each_of_allnodes_from(from, np)
9798c2ecf20Sopenharmony_ci		if (of_node_name_eq(np, name) && of_node_get(np))
9808c2ecf20Sopenharmony_ci			break;
9818c2ecf20Sopenharmony_ci	of_node_put(from);
9828c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
9838c2ecf20Sopenharmony_ci	return np;
9848c2ecf20Sopenharmony_ci}
9858c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_find_node_by_name);
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci/**
9888c2ecf20Sopenharmony_ci * of_find_node_by_type - Find a node by its "device_type" property
9898c2ecf20Sopenharmony_ci * @from:	The node to start searching from, or NULL to start searching
9908c2ecf20Sopenharmony_ci *		the entire device tree. The node you pass will not be
9918c2ecf20Sopenharmony_ci *		searched, only the next one will; typically, you pass
9928c2ecf20Sopenharmony_ci *		what the previous call returned. of_node_put() will be
9938c2ecf20Sopenharmony_ci *		called on from for you.
9948c2ecf20Sopenharmony_ci * @type:	The type string to match against
9958c2ecf20Sopenharmony_ci *
9968c2ecf20Sopenharmony_ci * Return: A node pointer with refcount incremented, use
9978c2ecf20Sopenharmony_ci * of_node_put() on it when done.
9988c2ecf20Sopenharmony_ci */
9998c2ecf20Sopenharmony_cistruct device_node *of_find_node_by_type(struct device_node *from,
10008c2ecf20Sopenharmony_ci	const char *type)
10018c2ecf20Sopenharmony_ci{
10028c2ecf20Sopenharmony_ci	struct device_node *np;
10038c2ecf20Sopenharmony_ci	unsigned long flags;
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
10068c2ecf20Sopenharmony_ci	for_each_of_allnodes_from(from, np)
10078c2ecf20Sopenharmony_ci		if (__of_node_is_type(np, type) && of_node_get(np))
10088c2ecf20Sopenharmony_ci			break;
10098c2ecf20Sopenharmony_ci	of_node_put(from);
10108c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
10118c2ecf20Sopenharmony_ci	return np;
10128c2ecf20Sopenharmony_ci}
10138c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_find_node_by_type);
10148c2ecf20Sopenharmony_ci
10158c2ecf20Sopenharmony_ci/**
10168c2ecf20Sopenharmony_ci * of_find_compatible_node - Find a node based on type and one of the
10178c2ecf20Sopenharmony_ci *                                tokens in its "compatible" property
10188c2ecf20Sopenharmony_ci * @from:	The node to start searching from or NULL, the node
10198c2ecf20Sopenharmony_ci *		you pass will not be searched, only the next one
10208c2ecf20Sopenharmony_ci *		will; typically, you pass what the previous call
10218c2ecf20Sopenharmony_ci *		returned. of_node_put() will be called on it
10228c2ecf20Sopenharmony_ci * @type:	The type string to match "device_type" or NULL to ignore
10238c2ecf20Sopenharmony_ci * @compatible:	The string to match to one of the tokens in the device
10248c2ecf20Sopenharmony_ci *		"compatible" list.
10258c2ecf20Sopenharmony_ci *
10268c2ecf20Sopenharmony_ci * Return: A node pointer with refcount incremented, use
10278c2ecf20Sopenharmony_ci * of_node_put() on it when done.
10288c2ecf20Sopenharmony_ci */
10298c2ecf20Sopenharmony_cistruct device_node *of_find_compatible_node(struct device_node *from,
10308c2ecf20Sopenharmony_ci	const char *type, const char *compatible)
10318c2ecf20Sopenharmony_ci{
10328c2ecf20Sopenharmony_ci	struct device_node *np;
10338c2ecf20Sopenharmony_ci	unsigned long flags;
10348c2ecf20Sopenharmony_ci
10358c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
10368c2ecf20Sopenharmony_ci	for_each_of_allnodes_from(from, np)
10378c2ecf20Sopenharmony_ci		if (__of_device_is_compatible(np, compatible, type, NULL) &&
10388c2ecf20Sopenharmony_ci		    of_node_get(np))
10398c2ecf20Sopenharmony_ci			break;
10408c2ecf20Sopenharmony_ci	of_node_put(from);
10418c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
10428c2ecf20Sopenharmony_ci	return np;
10438c2ecf20Sopenharmony_ci}
10448c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_find_compatible_node);
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci/**
10478c2ecf20Sopenharmony_ci * of_find_node_with_property - Find a node which has a property with
10488c2ecf20Sopenharmony_ci *                              the given name.
10498c2ecf20Sopenharmony_ci * @from:	The node to start searching from or NULL, the node
10508c2ecf20Sopenharmony_ci *		you pass will not be searched, only the next one
10518c2ecf20Sopenharmony_ci *		will; typically, you pass what the previous call
10528c2ecf20Sopenharmony_ci *		returned. of_node_put() will be called on it
10538c2ecf20Sopenharmony_ci * @prop_name:	The name of the property to look for.
10548c2ecf20Sopenharmony_ci *
10558c2ecf20Sopenharmony_ci * Return: A node pointer with refcount incremented, use
10568c2ecf20Sopenharmony_ci * of_node_put() on it when done.
10578c2ecf20Sopenharmony_ci */
10588c2ecf20Sopenharmony_cistruct device_node *of_find_node_with_property(struct device_node *from,
10598c2ecf20Sopenharmony_ci	const char *prop_name)
10608c2ecf20Sopenharmony_ci{
10618c2ecf20Sopenharmony_ci	struct device_node *np;
10628c2ecf20Sopenharmony_ci	struct property *pp;
10638c2ecf20Sopenharmony_ci	unsigned long flags;
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
10668c2ecf20Sopenharmony_ci	for_each_of_allnodes_from(from, np) {
10678c2ecf20Sopenharmony_ci		for (pp = np->properties; pp; pp = pp->next) {
10688c2ecf20Sopenharmony_ci			if (of_prop_cmp(pp->name, prop_name) == 0) {
10698c2ecf20Sopenharmony_ci				of_node_get(np);
10708c2ecf20Sopenharmony_ci				goto out;
10718c2ecf20Sopenharmony_ci			}
10728c2ecf20Sopenharmony_ci		}
10738c2ecf20Sopenharmony_ci	}
10748c2ecf20Sopenharmony_ciout:
10758c2ecf20Sopenharmony_ci	of_node_put(from);
10768c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
10778c2ecf20Sopenharmony_ci	return np;
10788c2ecf20Sopenharmony_ci}
10798c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_find_node_with_property);
10808c2ecf20Sopenharmony_ci
10818c2ecf20Sopenharmony_cistatic
10828c2ecf20Sopenharmony_ciconst struct of_device_id *__of_match_node(const struct of_device_id *matches,
10838c2ecf20Sopenharmony_ci					   const struct device_node *node)
10848c2ecf20Sopenharmony_ci{
10858c2ecf20Sopenharmony_ci	const struct of_device_id *best_match = NULL;
10868c2ecf20Sopenharmony_ci	int score, best_score = 0;
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_ci	if (!matches)
10898c2ecf20Sopenharmony_ci		return NULL;
10908c2ecf20Sopenharmony_ci
10918c2ecf20Sopenharmony_ci	for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) {
10928c2ecf20Sopenharmony_ci		score = __of_device_is_compatible(node, matches->compatible,
10938c2ecf20Sopenharmony_ci						  matches->type, matches->name);
10948c2ecf20Sopenharmony_ci		if (score > best_score) {
10958c2ecf20Sopenharmony_ci			best_match = matches;
10968c2ecf20Sopenharmony_ci			best_score = score;
10978c2ecf20Sopenharmony_ci		}
10988c2ecf20Sopenharmony_ci	}
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_ci	return best_match;
11018c2ecf20Sopenharmony_ci}
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_ci/**
11048c2ecf20Sopenharmony_ci * of_match_node - Tell if a device_node has a matching of_match structure
11058c2ecf20Sopenharmony_ci * @matches:	array of of device match structures to search in
11068c2ecf20Sopenharmony_ci * @node:	the of device structure to match against
11078c2ecf20Sopenharmony_ci *
11088c2ecf20Sopenharmony_ci * Low level utility function used by device matching.
11098c2ecf20Sopenharmony_ci */
11108c2ecf20Sopenharmony_ciconst struct of_device_id *of_match_node(const struct of_device_id *matches,
11118c2ecf20Sopenharmony_ci					 const struct device_node *node)
11128c2ecf20Sopenharmony_ci{
11138c2ecf20Sopenharmony_ci	const struct of_device_id *match;
11148c2ecf20Sopenharmony_ci	unsigned long flags;
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
11178c2ecf20Sopenharmony_ci	match = __of_match_node(matches, node);
11188c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
11198c2ecf20Sopenharmony_ci	return match;
11208c2ecf20Sopenharmony_ci}
11218c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_match_node);
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci/**
11248c2ecf20Sopenharmony_ci * of_find_matching_node_and_match - Find a node based on an of_device_id
11258c2ecf20Sopenharmony_ci *				     match table.
11268c2ecf20Sopenharmony_ci * @from:	The node to start searching from or NULL, the node
11278c2ecf20Sopenharmony_ci *		you pass will not be searched, only the next one
11288c2ecf20Sopenharmony_ci *		will; typically, you pass what the previous call
11298c2ecf20Sopenharmony_ci *		returned. of_node_put() will be called on it
11308c2ecf20Sopenharmony_ci * @matches:	array of of device match structures to search in
11318c2ecf20Sopenharmony_ci * @match:	Updated to point at the matches entry which matched
11328c2ecf20Sopenharmony_ci *
11338c2ecf20Sopenharmony_ci * Return: A node pointer with refcount incremented, use
11348c2ecf20Sopenharmony_ci * of_node_put() on it when done.
11358c2ecf20Sopenharmony_ci */
11368c2ecf20Sopenharmony_cistruct device_node *of_find_matching_node_and_match(struct device_node *from,
11378c2ecf20Sopenharmony_ci					const struct of_device_id *matches,
11388c2ecf20Sopenharmony_ci					const struct of_device_id **match)
11398c2ecf20Sopenharmony_ci{
11408c2ecf20Sopenharmony_ci	struct device_node *np;
11418c2ecf20Sopenharmony_ci	const struct of_device_id *m;
11428c2ecf20Sopenharmony_ci	unsigned long flags;
11438c2ecf20Sopenharmony_ci
11448c2ecf20Sopenharmony_ci	if (match)
11458c2ecf20Sopenharmony_ci		*match = NULL;
11468c2ecf20Sopenharmony_ci
11478c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
11488c2ecf20Sopenharmony_ci	for_each_of_allnodes_from(from, np) {
11498c2ecf20Sopenharmony_ci		m = __of_match_node(matches, np);
11508c2ecf20Sopenharmony_ci		if (m && of_node_get(np)) {
11518c2ecf20Sopenharmony_ci			if (match)
11528c2ecf20Sopenharmony_ci				*match = m;
11538c2ecf20Sopenharmony_ci			break;
11548c2ecf20Sopenharmony_ci		}
11558c2ecf20Sopenharmony_ci	}
11568c2ecf20Sopenharmony_ci	of_node_put(from);
11578c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
11588c2ecf20Sopenharmony_ci	return np;
11598c2ecf20Sopenharmony_ci}
11608c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_find_matching_node_and_match);
11618c2ecf20Sopenharmony_ci
11628c2ecf20Sopenharmony_ci/**
11638c2ecf20Sopenharmony_ci * of_modalias_node - Lookup appropriate modalias for a device node
11648c2ecf20Sopenharmony_ci * @node:	pointer to a device tree node
11658c2ecf20Sopenharmony_ci * @modalias:	Pointer to buffer that modalias value will be copied into
11668c2ecf20Sopenharmony_ci * @len:	Length of modalias value
11678c2ecf20Sopenharmony_ci *
11688c2ecf20Sopenharmony_ci * Based on the value of the compatible property, this routine will attempt
11698c2ecf20Sopenharmony_ci * to choose an appropriate modalias value for a particular device tree node.
11708c2ecf20Sopenharmony_ci * It does this by stripping the manufacturer prefix (as delimited by a ',')
11718c2ecf20Sopenharmony_ci * from the first entry in the compatible list property.
11728c2ecf20Sopenharmony_ci *
11738c2ecf20Sopenharmony_ci * Return: This routine returns 0 on success, <0 on failure.
11748c2ecf20Sopenharmony_ci */
11758c2ecf20Sopenharmony_ciint of_modalias_node(struct device_node *node, char *modalias, int len)
11768c2ecf20Sopenharmony_ci{
11778c2ecf20Sopenharmony_ci	const char *compatible, *p;
11788c2ecf20Sopenharmony_ci	int cplen;
11798c2ecf20Sopenharmony_ci
11808c2ecf20Sopenharmony_ci	compatible = of_get_property(node, "compatible", &cplen);
11818c2ecf20Sopenharmony_ci	if (!compatible || strlen(compatible) > cplen)
11828c2ecf20Sopenharmony_ci		return -ENODEV;
11838c2ecf20Sopenharmony_ci	p = strchr(compatible, ',');
11848c2ecf20Sopenharmony_ci	strlcpy(modalias, p ? p + 1 : compatible, len);
11858c2ecf20Sopenharmony_ci	return 0;
11868c2ecf20Sopenharmony_ci}
11878c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_modalias_node);
11888c2ecf20Sopenharmony_ci
11898c2ecf20Sopenharmony_ci/**
11908c2ecf20Sopenharmony_ci * of_find_node_by_phandle - Find a node given a phandle
11918c2ecf20Sopenharmony_ci * @handle:	phandle of the node to find
11928c2ecf20Sopenharmony_ci *
11938c2ecf20Sopenharmony_ci * Return: A node pointer with refcount incremented, use
11948c2ecf20Sopenharmony_ci * of_node_put() on it when done.
11958c2ecf20Sopenharmony_ci */
11968c2ecf20Sopenharmony_cistruct device_node *of_find_node_by_phandle(phandle handle)
11978c2ecf20Sopenharmony_ci{
11988c2ecf20Sopenharmony_ci	struct device_node *np = NULL;
11998c2ecf20Sopenharmony_ci	unsigned long flags;
12008c2ecf20Sopenharmony_ci	u32 handle_hash;
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_ci	if (!handle)
12038c2ecf20Sopenharmony_ci		return NULL;
12048c2ecf20Sopenharmony_ci
12058c2ecf20Sopenharmony_ci	handle_hash = of_phandle_cache_hash(handle);
12068c2ecf20Sopenharmony_ci
12078c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_ci	if (phandle_cache[handle_hash] &&
12108c2ecf20Sopenharmony_ci	    handle == phandle_cache[handle_hash]->phandle)
12118c2ecf20Sopenharmony_ci		np = phandle_cache[handle_hash];
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_ci	if (!np) {
12148c2ecf20Sopenharmony_ci		for_each_of_allnodes(np)
12158c2ecf20Sopenharmony_ci			if (np->phandle == handle &&
12168c2ecf20Sopenharmony_ci			    !of_node_check_flag(np, OF_DETACHED)) {
12178c2ecf20Sopenharmony_ci				phandle_cache[handle_hash] = np;
12188c2ecf20Sopenharmony_ci				break;
12198c2ecf20Sopenharmony_ci			}
12208c2ecf20Sopenharmony_ci	}
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	of_node_get(np);
12238c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
12248c2ecf20Sopenharmony_ci	return np;
12258c2ecf20Sopenharmony_ci}
12268c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_find_node_by_phandle);
12278c2ecf20Sopenharmony_ci
12288c2ecf20Sopenharmony_civoid of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
12298c2ecf20Sopenharmony_ci{
12308c2ecf20Sopenharmony_ci	int i;
12318c2ecf20Sopenharmony_ci	printk("%s %pOF", msg, args->np);
12328c2ecf20Sopenharmony_ci	for (i = 0; i < args->args_count; i++) {
12338c2ecf20Sopenharmony_ci		const char delim = i ? ',' : ':';
12348c2ecf20Sopenharmony_ci
12358c2ecf20Sopenharmony_ci		pr_cont("%c%08x", delim, args->args[i]);
12368c2ecf20Sopenharmony_ci	}
12378c2ecf20Sopenharmony_ci	pr_cont("\n");
12388c2ecf20Sopenharmony_ci}
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_ciint of_phandle_iterator_init(struct of_phandle_iterator *it,
12418c2ecf20Sopenharmony_ci		const struct device_node *np,
12428c2ecf20Sopenharmony_ci		const char *list_name,
12438c2ecf20Sopenharmony_ci		const char *cells_name,
12448c2ecf20Sopenharmony_ci		int cell_count)
12458c2ecf20Sopenharmony_ci{
12468c2ecf20Sopenharmony_ci	const __be32 *list;
12478c2ecf20Sopenharmony_ci	int size;
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_ci	memset(it, 0, sizeof(*it));
12508c2ecf20Sopenharmony_ci
12518c2ecf20Sopenharmony_ci	/*
12528c2ecf20Sopenharmony_ci	 * one of cell_count or cells_name must be provided to determine the
12538c2ecf20Sopenharmony_ci	 * argument length.
12548c2ecf20Sopenharmony_ci	 */
12558c2ecf20Sopenharmony_ci	if (cell_count < 0 && !cells_name)
12568c2ecf20Sopenharmony_ci		return -EINVAL;
12578c2ecf20Sopenharmony_ci
12588c2ecf20Sopenharmony_ci	list = of_get_property(np, list_name, &size);
12598c2ecf20Sopenharmony_ci	if (!list)
12608c2ecf20Sopenharmony_ci		return -ENOENT;
12618c2ecf20Sopenharmony_ci
12628c2ecf20Sopenharmony_ci	it->cells_name = cells_name;
12638c2ecf20Sopenharmony_ci	it->cell_count = cell_count;
12648c2ecf20Sopenharmony_ci	it->parent = np;
12658c2ecf20Sopenharmony_ci	it->list_end = list + size / sizeof(*list);
12668c2ecf20Sopenharmony_ci	it->phandle_end = list;
12678c2ecf20Sopenharmony_ci	it->cur = list;
12688c2ecf20Sopenharmony_ci
12698c2ecf20Sopenharmony_ci	return 0;
12708c2ecf20Sopenharmony_ci}
12718c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_phandle_iterator_init);
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_ciint of_phandle_iterator_next(struct of_phandle_iterator *it)
12748c2ecf20Sopenharmony_ci{
12758c2ecf20Sopenharmony_ci	uint32_t count = 0;
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ci	if (it->node) {
12788c2ecf20Sopenharmony_ci		of_node_put(it->node);
12798c2ecf20Sopenharmony_ci		it->node = NULL;
12808c2ecf20Sopenharmony_ci	}
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_ci	if (!it->cur || it->phandle_end >= it->list_end)
12838c2ecf20Sopenharmony_ci		return -ENOENT;
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_ci	it->cur = it->phandle_end;
12868c2ecf20Sopenharmony_ci
12878c2ecf20Sopenharmony_ci	/* If phandle is 0, then it is an empty entry with no arguments. */
12888c2ecf20Sopenharmony_ci	it->phandle = be32_to_cpup(it->cur++);
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci	if (it->phandle) {
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_ci		/*
12938c2ecf20Sopenharmony_ci		 * Find the provider node and parse the #*-cells property to
12948c2ecf20Sopenharmony_ci		 * determine the argument length.
12958c2ecf20Sopenharmony_ci		 */
12968c2ecf20Sopenharmony_ci		it->node = of_find_node_by_phandle(it->phandle);
12978c2ecf20Sopenharmony_ci
12988c2ecf20Sopenharmony_ci		if (it->cells_name) {
12998c2ecf20Sopenharmony_ci			if (!it->node) {
13008c2ecf20Sopenharmony_ci				pr_err("%pOF: could not find phandle\n",
13018c2ecf20Sopenharmony_ci				       it->parent);
13028c2ecf20Sopenharmony_ci				goto err;
13038c2ecf20Sopenharmony_ci			}
13048c2ecf20Sopenharmony_ci
13058c2ecf20Sopenharmony_ci			if (of_property_read_u32(it->node, it->cells_name,
13068c2ecf20Sopenharmony_ci						 &count)) {
13078c2ecf20Sopenharmony_ci				/*
13088c2ecf20Sopenharmony_ci				 * If both cell_count and cells_name is given,
13098c2ecf20Sopenharmony_ci				 * fall back to cell_count in absence
13108c2ecf20Sopenharmony_ci				 * of the cells_name property
13118c2ecf20Sopenharmony_ci				 */
13128c2ecf20Sopenharmony_ci				if (it->cell_count >= 0) {
13138c2ecf20Sopenharmony_ci					count = it->cell_count;
13148c2ecf20Sopenharmony_ci				} else {
13158c2ecf20Sopenharmony_ci					pr_err("%pOF: could not get %s for %pOF\n",
13168c2ecf20Sopenharmony_ci					       it->parent,
13178c2ecf20Sopenharmony_ci					       it->cells_name,
13188c2ecf20Sopenharmony_ci					       it->node);
13198c2ecf20Sopenharmony_ci					goto err;
13208c2ecf20Sopenharmony_ci				}
13218c2ecf20Sopenharmony_ci			}
13228c2ecf20Sopenharmony_ci		} else {
13238c2ecf20Sopenharmony_ci			count = it->cell_count;
13248c2ecf20Sopenharmony_ci		}
13258c2ecf20Sopenharmony_ci
13268c2ecf20Sopenharmony_ci		/*
13278c2ecf20Sopenharmony_ci		 * Make sure that the arguments actually fit in the remaining
13288c2ecf20Sopenharmony_ci		 * property data length
13298c2ecf20Sopenharmony_ci		 */
13308c2ecf20Sopenharmony_ci		if (it->cur + count > it->list_end) {
13318c2ecf20Sopenharmony_ci			if (it->cells_name)
13328c2ecf20Sopenharmony_ci				pr_err("%pOF: %s = %d found %td\n",
13338c2ecf20Sopenharmony_ci					it->parent, it->cells_name,
13348c2ecf20Sopenharmony_ci					count, it->list_end - it->cur);
13358c2ecf20Sopenharmony_ci			else
13368c2ecf20Sopenharmony_ci				pr_err("%pOF: phandle %s needs %d, found %td\n",
13378c2ecf20Sopenharmony_ci					it->parent, of_node_full_name(it->node),
13388c2ecf20Sopenharmony_ci					count, it->list_end - it->cur);
13398c2ecf20Sopenharmony_ci			goto err;
13408c2ecf20Sopenharmony_ci		}
13418c2ecf20Sopenharmony_ci	}
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ci	it->phandle_end = it->cur + count;
13448c2ecf20Sopenharmony_ci	it->cur_count = count;
13458c2ecf20Sopenharmony_ci
13468c2ecf20Sopenharmony_ci	return 0;
13478c2ecf20Sopenharmony_ci
13488c2ecf20Sopenharmony_cierr:
13498c2ecf20Sopenharmony_ci	if (it->node) {
13508c2ecf20Sopenharmony_ci		of_node_put(it->node);
13518c2ecf20Sopenharmony_ci		it->node = NULL;
13528c2ecf20Sopenharmony_ci	}
13538c2ecf20Sopenharmony_ci
13548c2ecf20Sopenharmony_ci	return -EINVAL;
13558c2ecf20Sopenharmony_ci}
13568c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_phandle_iterator_next);
13578c2ecf20Sopenharmony_ci
13588c2ecf20Sopenharmony_ciint of_phandle_iterator_args(struct of_phandle_iterator *it,
13598c2ecf20Sopenharmony_ci			     uint32_t *args,
13608c2ecf20Sopenharmony_ci			     int size)
13618c2ecf20Sopenharmony_ci{
13628c2ecf20Sopenharmony_ci	int i, count;
13638c2ecf20Sopenharmony_ci
13648c2ecf20Sopenharmony_ci	count = it->cur_count;
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_ci	if (WARN_ON(size < count))
13678c2ecf20Sopenharmony_ci		count = size;
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_ci	for (i = 0; i < count; i++)
13708c2ecf20Sopenharmony_ci		args[i] = be32_to_cpup(it->cur++);
13718c2ecf20Sopenharmony_ci
13728c2ecf20Sopenharmony_ci	return count;
13738c2ecf20Sopenharmony_ci}
13748c2ecf20Sopenharmony_ci
13758c2ecf20Sopenharmony_cistatic int __of_parse_phandle_with_args(const struct device_node *np,
13768c2ecf20Sopenharmony_ci					const char *list_name,
13778c2ecf20Sopenharmony_ci					const char *cells_name,
13788c2ecf20Sopenharmony_ci					int cell_count, int index,
13798c2ecf20Sopenharmony_ci					struct of_phandle_args *out_args)
13808c2ecf20Sopenharmony_ci{
13818c2ecf20Sopenharmony_ci	struct of_phandle_iterator it;
13828c2ecf20Sopenharmony_ci	int rc, cur_index = 0;
13838c2ecf20Sopenharmony_ci
13848c2ecf20Sopenharmony_ci	/* Loop over the phandles until all the requested entry is found */
13858c2ecf20Sopenharmony_ci	of_for_each_phandle(&it, rc, np, list_name, cells_name, cell_count) {
13868c2ecf20Sopenharmony_ci		/*
13878c2ecf20Sopenharmony_ci		 * All of the error cases bail out of the loop, so at
13888c2ecf20Sopenharmony_ci		 * this point, the parsing is successful. If the requested
13898c2ecf20Sopenharmony_ci		 * index matches, then fill the out_args structure and return,
13908c2ecf20Sopenharmony_ci		 * or return -ENOENT for an empty entry.
13918c2ecf20Sopenharmony_ci		 */
13928c2ecf20Sopenharmony_ci		rc = -ENOENT;
13938c2ecf20Sopenharmony_ci		if (cur_index == index) {
13948c2ecf20Sopenharmony_ci			if (!it.phandle)
13958c2ecf20Sopenharmony_ci				goto err;
13968c2ecf20Sopenharmony_ci
13978c2ecf20Sopenharmony_ci			if (out_args) {
13988c2ecf20Sopenharmony_ci				int c;
13998c2ecf20Sopenharmony_ci
14008c2ecf20Sopenharmony_ci				c = of_phandle_iterator_args(&it,
14018c2ecf20Sopenharmony_ci							     out_args->args,
14028c2ecf20Sopenharmony_ci							     MAX_PHANDLE_ARGS);
14038c2ecf20Sopenharmony_ci				out_args->np = it.node;
14048c2ecf20Sopenharmony_ci				out_args->args_count = c;
14058c2ecf20Sopenharmony_ci			} else {
14068c2ecf20Sopenharmony_ci				of_node_put(it.node);
14078c2ecf20Sopenharmony_ci			}
14088c2ecf20Sopenharmony_ci
14098c2ecf20Sopenharmony_ci			/* Found it! return success */
14108c2ecf20Sopenharmony_ci			return 0;
14118c2ecf20Sopenharmony_ci		}
14128c2ecf20Sopenharmony_ci
14138c2ecf20Sopenharmony_ci		cur_index++;
14148c2ecf20Sopenharmony_ci	}
14158c2ecf20Sopenharmony_ci
14168c2ecf20Sopenharmony_ci	/*
14178c2ecf20Sopenharmony_ci	 * Unlock node before returning result; will be one of:
14188c2ecf20Sopenharmony_ci	 * -ENOENT : index is for empty phandle
14198c2ecf20Sopenharmony_ci	 * -EINVAL : parsing error on data
14208c2ecf20Sopenharmony_ci	 */
14218c2ecf20Sopenharmony_ci
14228c2ecf20Sopenharmony_ci err:
14238c2ecf20Sopenharmony_ci	of_node_put(it.node);
14248c2ecf20Sopenharmony_ci	return rc;
14258c2ecf20Sopenharmony_ci}
14268c2ecf20Sopenharmony_ci
14278c2ecf20Sopenharmony_ci/**
14288c2ecf20Sopenharmony_ci * of_parse_phandle - Resolve a phandle property to a device_node pointer
14298c2ecf20Sopenharmony_ci * @np: Pointer to device node holding phandle property
14308c2ecf20Sopenharmony_ci * @phandle_name: Name of property holding a phandle value
14318c2ecf20Sopenharmony_ci * @index: For properties holding a table of phandles, this is the index into
14328c2ecf20Sopenharmony_ci *         the table
14338c2ecf20Sopenharmony_ci *
14348c2ecf20Sopenharmony_ci * Return: The device_node pointer with refcount incremented.  Use
14358c2ecf20Sopenharmony_ci * of_node_put() on it when done.
14368c2ecf20Sopenharmony_ci */
14378c2ecf20Sopenharmony_cistruct device_node *of_parse_phandle(const struct device_node *np,
14388c2ecf20Sopenharmony_ci				     const char *phandle_name, int index)
14398c2ecf20Sopenharmony_ci{
14408c2ecf20Sopenharmony_ci	struct of_phandle_args args;
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_ci	if (index < 0)
14438c2ecf20Sopenharmony_ci		return NULL;
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_ci	if (__of_parse_phandle_with_args(np, phandle_name, NULL, 0,
14468c2ecf20Sopenharmony_ci					 index, &args))
14478c2ecf20Sopenharmony_ci		return NULL;
14488c2ecf20Sopenharmony_ci
14498c2ecf20Sopenharmony_ci	return args.np;
14508c2ecf20Sopenharmony_ci}
14518c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_parse_phandle);
14528c2ecf20Sopenharmony_ci
14538c2ecf20Sopenharmony_ci/**
14548c2ecf20Sopenharmony_ci * of_parse_phandle_with_args() - Find a node pointed by phandle in a list
14558c2ecf20Sopenharmony_ci * @np:		pointer to a device tree node containing a list
14568c2ecf20Sopenharmony_ci * @list_name:	property name that contains a list
14578c2ecf20Sopenharmony_ci * @cells_name:	property name that specifies phandles' arguments count
14588c2ecf20Sopenharmony_ci * @index:	index of a phandle to parse out
14598c2ecf20Sopenharmony_ci * @out_args:	optional pointer to output arguments structure (will be filled)
14608c2ecf20Sopenharmony_ci *
14618c2ecf20Sopenharmony_ci * This function is useful to parse lists of phandles and their arguments.
14628c2ecf20Sopenharmony_ci * Returns 0 on success and fills out_args, on error returns appropriate
14638c2ecf20Sopenharmony_ci * errno value.
14648c2ecf20Sopenharmony_ci *
14658c2ecf20Sopenharmony_ci * Caller is responsible to call of_node_put() on the returned out_args->np
14668c2ecf20Sopenharmony_ci * pointer.
14678c2ecf20Sopenharmony_ci *
14688c2ecf20Sopenharmony_ci * Example::
14698c2ecf20Sopenharmony_ci *
14708c2ecf20Sopenharmony_ci *  phandle1: node1 {
14718c2ecf20Sopenharmony_ci *	#list-cells = <2>;
14728c2ecf20Sopenharmony_ci *  };
14738c2ecf20Sopenharmony_ci *
14748c2ecf20Sopenharmony_ci *  phandle2: node2 {
14758c2ecf20Sopenharmony_ci *	#list-cells = <1>;
14768c2ecf20Sopenharmony_ci *  };
14778c2ecf20Sopenharmony_ci *
14788c2ecf20Sopenharmony_ci *  node3 {
14798c2ecf20Sopenharmony_ci *	list = <&phandle1 1 2 &phandle2 3>;
14808c2ecf20Sopenharmony_ci *  };
14818c2ecf20Sopenharmony_ci *
14828c2ecf20Sopenharmony_ci * To get a device_node of the ``node2`` node you may call this:
14838c2ecf20Sopenharmony_ci * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
14848c2ecf20Sopenharmony_ci */
14858c2ecf20Sopenharmony_ciint of_parse_phandle_with_args(const struct device_node *np, const char *list_name,
14868c2ecf20Sopenharmony_ci				const char *cells_name, int index,
14878c2ecf20Sopenharmony_ci				struct of_phandle_args *out_args)
14888c2ecf20Sopenharmony_ci{
14898c2ecf20Sopenharmony_ci	int cell_count = -1;
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_ci	if (index < 0)
14928c2ecf20Sopenharmony_ci		return -EINVAL;
14938c2ecf20Sopenharmony_ci
14948c2ecf20Sopenharmony_ci	/* If cells_name is NULL we assume a cell count of 0 */
14958c2ecf20Sopenharmony_ci	if (!cells_name)
14968c2ecf20Sopenharmony_ci		cell_count = 0;
14978c2ecf20Sopenharmony_ci
14988c2ecf20Sopenharmony_ci	return __of_parse_phandle_with_args(np, list_name, cells_name,
14998c2ecf20Sopenharmony_ci					    cell_count, index, out_args);
15008c2ecf20Sopenharmony_ci}
15018c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_parse_phandle_with_args);
15028c2ecf20Sopenharmony_ci
15038c2ecf20Sopenharmony_ci/**
15048c2ecf20Sopenharmony_ci * of_parse_phandle_with_args_map() - Find a node pointed by phandle in a list and remap it
15058c2ecf20Sopenharmony_ci * @np:		pointer to a device tree node containing a list
15068c2ecf20Sopenharmony_ci * @list_name:	property name that contains a list
15078c2ecf20Sopenharmony_ci * @stem_name:	stem of property names that specify phandles' arguments count
15088c2ecf20Sopenharmony_ci * @index:	index of a phandle to parse out
15098c2ecf20Sopenharmony_ci * @out_args:	optional pointer to output arguments structure (will be filled)
15108c2ecf20Sopenharmony_ci *
15118c2ecf20Sopenharmony_ci * This function is useful to parse lists of phandles and their arguments.
15128c2ecf20Sopenharmony_ci * Returns 0 on success and fills out_args, on error returns appropriate errno
15138c2ecf20Sopenharmony_ci * value. The difference between this function and of_parse_phandle_with_args()
15148c2ecf20Sopenharmony_ci * is that this API remaps a phandle if the node the phandle points to has
15158c2ecf20Sopenharmony_ci * a <@stem_name>-map property.
15168c2ecf20Sopenharmony_ci *
15178c2ecf20Sopenharmony_ci * Caller is responsible to call of_node_put() on the returned out_args->np
15188c2ecf20Sopenharmony_ci * pointer.
15198c2ecf20Sopenharmony_ci *
15208c2ecf20Sopenharmony_ci * Example::
15218c2ecf20Sopenharmony_ci *
15228c2ecf20Sopenharmony_ci *  phandle1: node1 {
15238c2ecf20Sopenharmony_ci *  	#list-cells = <2>;
15248c2ecf20Sopenharmony_ci *  };
15258c2ecf20Sopenharmony_ci *
15268c2ecf20Sopenharmony_ci *  phandle2: node2 {
15278c2ecf20Sopenharmony_ci *  	#list-cells = <1>;
15288c2ecf20Sopenharmony_ci *  };
15298c2ecf20Sopenharmony_ci *
15308c2ecf20Sopenharmony_ci *  phandle3: node3 {
15318c2ecf20Sopenharmony_ci *  	#list-cells = <1>;
15328c2ecf20Sopenharmony_ci *  	list-map = <0 &phandle2 3>,
15338c2ecf20Sopenharmony_ci *  		   <1 &phandle2 2>,
15348c2ecf20Sopenharmony_ci *  		   <2 &phandle1 5 1>;
15358c2ecf20Sopenharmony_ci *  	list-map-mask = <0x3>;
15368c2ecf20Sopenharmony_ci *  };
15378c2ecf20Sopenharmony_ci *
15388c2ecf20Sopenharmony_ci *  node4 {
15398c2ecf20Sopenharmony_ci *  	list = <&phandle1 1 2 &phandle3 0>;
15408c2ecf20Sopenharmony_ci *  };
15418c2ecf20Sopenharmony_ci *
15428c2ecf20Sopenharmony_ci * To get a device_node of the ``node2`` node you may call this:
15438c2ecf20Sopenharmony_ci * of_parse_phandle_with_args(node4, "list", "list", 1, &args);
15448c2ecf20Sopenharmony_ci */
15458c2ecf20Sopenharmony_ciint of_parse_phandle_with_args_map(const struct device_node *np,
15468c2ecf20Sopenharmony_ci				   const char *list_name,
15478c2ecf20Sopenharmony_ci				   const char *stem_name,
15488c2ecf20Sopenharmony_ci				   int index, struct of_phandle_args *out_args)
15498c2ecf20Sopenharmony_ci{
15508c2ecf20Sopenharmony_ci	char *cells_name, *map_name = NULL, *mask_name = NULL;
15518c2ecf20Sopenharmony_ci	char *pass_name = NULL;
15528c2ecf20Sopenharmony_ci	struct device_node *cur, *new = NULL;
15538c2ecf20Sopenharmony_ci	const __be32 *map, *mask, *pass;
15548c2ecf20Sopenharmony_ci	static const __be32 dummy_mask[] = { [0 ... MAX_PHANDLE_ARGS] = ~0 };
15558c2ecf20Sopenharmony_ci	static const __be32 dummy_pass[] = { [0 ... MAX_PHANDLE_ARGS] = 0 };
15568c2ecf20Sopenharmony_ci	__be32 initial_match_array[MAX_PHANDLE_ARGS];
15578c2ecf20Sopenharmony_ci	const __be32 *match_array = initial_match_array;
15588c2ecf20Sopenharmony_ci	int i, ret, map_len, match;
15598c2ecf20Sopenharmony_ci	u32 list_size, new_size;
15608c2ecf20Sopenharmony_ci
15618c2ecf20Sopenharmony_ci	if (index < 0)
15628c2ecf20Sopenharmony_ci		return -EINVAL;
15638c2ecf20Sopenharmony_ci
15648c2ecf20Sopenharmony_ci	cells_name = kasprintf(GFP_KERNEL, "#%s-cells", stem_name);
15658c2ecf20Sopenharmony_ci	if (!cells_name)
15668c2ecf20Sopenharmony_ci		return -ENOMEM;
15678c2ecf20Sopenharmony_ci
15688c2ecf20Sopenharmony_ci	ret = -ENOMEM;
15698c2ecf20Sopenharmony_ci	map_name = kasprintf(GFP_KERNEL, "%s-map", stem_name);
15708c2ecf20Sopenharmony_ci	if (!map_name)
15718c2ecf20Sopenharmony_ci		goto free;
15728c2ecf20Sopenharmony_ci
15738c2ecf20Sopenharmony_ci	mask_name = kasprintf(GFP_KERNEL, "%s-map-mask", stem_name);
15748c2ecf20Sopenharmony_ci	if (!mask_name)
15758c2ecf20Sopenharmony_ci		goto free;
15768c2ecf20Sopenharmony_ci
15778c2ecf20Sopenharmony_ci	pass_name = kasprintf(GFP_KERNEL, "%s-map-pass-thru", stem_name);
15788c2ecf20Sopenharmony_ci	if (!pass_name)
15798c2ecf20Sopenharmony_ci		goto free;
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ci	ret = __of_parse_phandle_with_args(np, list_name, cells_name, -1, index,
15828c2ecf20Sopenharmony_ci					   out_args);
15838c2ecf20Sopenharmony_ci	if (ret)
15848c2ecf20Sopenharmony_ci		goto free;
15858c2ecf20Sopenharmony_ci
15868c2ecf20Sopenharmony_ci	/* Get the #<list>-cells property */
15878c2ecf20Sopenharmony_ci	cur = out_args->np;
15888c2ecf20Sopenharmony_ci	ret = of_property_read_u32(cur, cells_name, &list_size);
15898c2ecf20Sopenharmony_ci	if (ret < 0)
15908c2ecf20Sopenharmony_ci		goto put;
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_ci	/* Precalculate the match array - this simplifies match loop */
15938c2ecf20Sopenharmony_ci	for (i = 0; i < list_size; i++)
15948c2ecf20Sopenharmony_ci		initial_match_array[i] = cpu_to_be32(out_args->args[i]);
15958c2ecf20Sopenharmony_ci
15968c2ecf20Sopenharmony_ci	ret = -EINVAL;
15978c2ecf20Sopenharmony_ci	while (cur) {
15988c2ecf20Sopenharmony_ci		/* Get the <list>-map property */
15998c2ecf20Sopenharmony_ci		map = of_get_property(cur, map_name, &map_len);
16008c2ecf20Sopenharmony_ci		if (!map) {
16018c2ecf20Sopenharmony_ci			ret = 0;
16028c2ecf20Sopenharmony_ci			goto free;
16038c2ecf20Sopenharmony_ci		}
16048c2ecf20Sopenharmony_ci		map_len /= sizeof(u32);
16058c2ecf20Sopenharmony_ci
16068c2ecf20Sopenharmony_ci		/* Get the <list>-map-mask property (optional) */
16078c2ecf20Sopenharmony_ci		mask = of_get_property(cur, mask_name, NULL);
16088c2ecf20Sopenharmony_ci		if (!mask)
16098c2ecf20Sopenharmony_ci			mask = dummy_mask;
16108c2ecf20Sopenharmony_ci		/* Iterate through <list>-map property */
16118c2ecf20Sopenharmony_ci		match = 0;
16128c2ecf20Sopenharmony_ci		while (map_len > (list_size + 1) && !match) {
16138c2ecf20Sopenharmony_ci			/* Compare specifiers */
16148c2ecf20Sopenharmony_ci			match = 1;
16158c2ecf20Sopenharmony_ci			for (i = 0; i < list_size; i++, map_len--)
16168c2ecf20Sopenharmony_ci				match &= !((match_array[i] ^ *map++) & mask[i]);
16178c2ecf20Sopenharmony_ci
16188c2ecf20Sopenharmony_ci			of_node_put(new);
16198c2ecf20Sopenharmony_ci			new = of_find_node_by_phandle(be32_to_cpup(map));
16208c2ecf20Sopenharmony_ci			map++;
16218c2ecf20Sopenharmony_ci			map_len--;
16228c2ecf20Sopenharmony_ci
16238c2ecf20Sopenharmony_ci			/* Check if not found */
16248c2ecf20Sopenharmony_ci			if (!new)
16258c2ecf20Sopenharmony_ci				goto put;
16268c2ecf20Sopenharmony_ci
16278c2ecf20Sopenharmony_ci			if (!of_device_is_available(new))
16288c2ecf20Sopenharmony_ci				match = 0;
16298c2ecf20Sopenharmony_ci
16308c2ecf20Sopenharmony_ci			ret = of_property_read_u32(new, cells_name, &new_size);
16318c2ecf20Sopenharmony_ci			if (ret)
16328c2ecf20Sopenharmony_ci				goto put;
16338c2ecf20Sopenharmony_ci
16348c2ecf20Sopenharmony_ci			/* Check for malformed properties */
16358c2ecf20Sopenharmony_ci			if (WARN_ON(new_size > MAX_PHANDLE_ARGS))
16368c2ecf20Sopenharmony_ci				goto put;
16378c2ecf20Sopenharmony_ci			if (map_len < new_size)
16388c2ecf20Sopenharmony_ci				goto put;
16398c2ecf20Sopenharmony_ci
16408c2ecf20Sopenharmony_ci			/* Move forward by new node's #<list>-cells amount */
16418c2ecf20Sopenharmony_ci			map += new_size;
16428c2ecf20Sopenharmony_ci			map_len -= new_size;
16438c2ecf20Sopenharmony_ci		}
16448c2ecf20Sopenharmony_ci		if (!match)
16458c2ecf20Sopenharmony_ci			goto put;
16468c2ecf20Sopenharmony_ci
16478c2ecf20Sopenharmony_ci		/* Get the <list>-map-pass-thru property (optional) */
16488c2ecf20Sopenharmony_ci		pass = of_get_property(cur, pass_name, NULL);
16498c2ecf20Sopenharmony_ci		if (!pass)
16508c2ecf20Sopenharmony_ci			pass = dummy_pass;
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_ci		/*
16538c2ecf20Sopenharmony_ci		 * Successfully parsed a <list>-map translation; copy new
16548c2ecf20Sopenharmony_ci		 * specifier into the out_args structure, keeping the
16558c2ecf20Sopenharmony_ci		 * bits specified in <list>-map-pass-thru.
16568c2ecf20Sopenharmony_ci		 */
16578c2ecf20Sopenharmony_ci		match_array = map - new_size;
16588c2ecf20Sopenharmony_ci		for (i = 0; i < new_size; i++) {
16598c2ecf20Sopenharmony_ci			__be32 val = *(map - new_size + i);
16608c2ecf20Sopenharmony_ci
16618c2ecf20Sopenharmony_ci			if (i < list_size) {
16628c2ecf20Sopenharmony_ci				val &= ~pass[i];
16638c2ecf20Sopenharmony_ci				val |= cpu_to_be32(out_args->args[i]) & pass[i];
16648c2ecf20Sopenharmony_ci			}
16658c2ecf20Sopenharmony_ci
16668c2ecf20Sopenharmony_ci			out_args->args[i] = be32_to_cpu(val);
16678c2ecf20Sopenharmony_ci		}
16688c2ecf20Sopenharmony_ci		out_args->args_count = list_size = new_size;
16698c2ecf20Sopenharmony_ci		/* Iterate again with new provider */
16708c2ecf20Sopenharmony_ci		out_args->np = new;
16718c2ecf20Sopenharmony_ci		of_node_put(cur);
16728c2ecf20Sopenharmony_ci		cur = new;
16738c2ecf20Sopenharmony_ci		new = NULL;
16748c2ecf20Sopenharmony_ci	}
16758c2ecf20Sopenharmony_ciput:
16768c2ecf20Sopenharmony_ci	of_node_put(cur);
16778c2ecf20Sopenharmony_ci	of_node_put(new);
16788c2ecf20Sopenharmony_cifree:
16798c2ecf20Sopenharmony_ci	kfree(mask_name);
16808c2ecf20Sopenharmony_ci	kfree(map_name);
16818c2ecf20Sopenharmony_ci	kfree(cells_name);
16828c2ecf20Sopenharmony_ci	kfree(pass_name);
16838c2ecf20Sopenharmony_ci
16848c2ecf20Sopenharmony_ci	return ret;
16858c2ecf20Sopenharmony_ci}
16868c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_parse_phandle_with_args_map);
16878c2ecf20Sopenharmony_ci
16888c2ecf20Sopenharmony_ci/**
16898c2ecf20Sopenharmony_ci * of_parse_phandle_with_fixed_args() - Find a node pointed by phandle in a list
16908c2ecf20Sopenharmony_ci * @np:		pointer to a device tree node containing a list
16918c2ecf20Sopenharmony_ci * @list_name:	property name that contains a list
16928c2ecf20Sopenharmony_ci * @cell_count: number of argument cells following the phandle
16938c2ecf20Sopenharmony_ci * @index:	index of a phandle to parse out
16948c2ecf20Sopenharmony_ci * @out_args:	optional pointer to output arguments structure (will be filled)
16958c2ecf20Sopenharmony_ci *
16968c2ecf20Sopenharmony_ci * This function is useful to parse lists of phandles and their arguments.
16978c2ecf20Sopenharmony_ci * Returns 0 on success and fills out_args, on error returns appropriate
16988c2ecf20Sopenharmony_ci * errno value.
16998c2ecf20Sopenharmony_ci *
17008c2ecf20Sopenharmony_ci * Caller is responsible to call of_node_put() on the returned out_args->np
17018c2ecf20Sopenharmony_ci * pointer.
17028c2ecf20Sopenharmony_ci *
17038c2ecf20Sopenharmony_ci * Example::
17048c2ecf20Sopenharmony_ci *
17058c2ecf20Sopenharmony_ci *  phandle1: node1 {
17068c2ecf20Sopenharmony_ci *  };
17078c2ecf20Sopenharmony_ci *
17088c2ecf20Sopenharmony_ci *  phandle2: node2 {
17098c2ecf20Sopenharmony_ci *  };
17108c2ecf20Sopenharmony_ci *
17118c2ecf20Sopenharmony_ci *  node3 {
17128c2ecf20Sopenharmony_ci *  	list = <&phandle1 0 2 &phandle2 2 3>;
17138c2ecf20Sopenharmony_ci *  };
17148c2ecf20Sopenharmony_ci *
17158c2ecf20Sopenharmony_ci * To get a device_node of the ``node2`` node you may call this:
17168c2ecf20Sopenharmony_ci * of_parse_phandle_with_fixed_args(node3, "list", 2, 1, &args);
17178c2ecf20Sopenharmony_ci */
17188c2ecf20Sopenharmony_ciint of_parse_phandle_with_fixed_args(const struct device_node *np,
17198c2ecf20Sopenharmony_ci				const char *list_name, int cell_count,
17208c2ecf20Sopenharmony_ci				int index, struct of_phandle_args *out_args)
17218c2ecf20Sopenharmony_ci{
17228c2ecf20Sopenharmony_ci	if (index < 0)
17238c2ecf20Sopenharmony_ci		return -EINVAL;
17248c2ecf20Sopenharmony_ci	return __of_parse_phandle_with_args(np, list_name, NULL, cell_count,
17258c2ecf20Sopenharmony_ci					   index, out_args);
17268c2ecf20Sopenharmony_ci}
17278c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_parse_phandle_with_fixed_args);
17288c2ecf20Sopenharmony_ci
17298c2ecf20Sopenharmony_ci/**
17308c2ecf20Sopenharmony_ci * of_count_phandle_with_args() - Find the number of phandles references in a property
17318c2ecf20Sopenharmony_ci * @np:		pointer to a device tree node containing a list
17328c2ecf20Sopenharmony_ci * @list_name:	property name that contains a list
17338c2ecf20Sopenharmony_ci * @cells_name:	property name that specifies phandles' arguments count
17348c2ecf20Sopenharmony_ci *
17358c2ecf20Sopenharmony_ci * Return: The number of phandle + argument tuples within a property. It
17368c2ecf20Sopenharmony_ci * is a typical pattern to encode a list of phandle and variable
17378c2ecf20Sopenharmony_ci * arguments into a single property. The number of arguments is encoded
17388c2ecf20Sopenharmony_ci * by a property in the phandle-target node. For example, a gpios
17398c2ecf20Sopenharmony_ci * property would contain a list of GPIO specifies consisting of a
17408c2ecf20Sopenharmony_ci * phandle and 1 or more arguments. The number of arguments are
17418c2ecf20Sopenharmony_ci * determined by the #gpio-cells property in the node pointed to by the
17428c2ecf20Sopenharmony_ci * phandle.
17438c2ecf20Sopenharmony_ci */
17448c2ecf20Sopenharmony_ciint of_count_phandle_with_args(const struct device_node *np, const char *list_name,
17458c2ecf20Sopenharmony_ci				const char *cells_name)
17468c2ecf20Sopenharmony_ci{
17478c2ecf20Sopenharmony_ci	struct of_phandle_iterator it;
17488c2ecf20Sopenharmony_ci	int rc, cur_index = 0;
17498c2ecf20Sopenharmony_ci
17508c2ecf20Sopenharmony_ci	/*
17518c2ecf20Sopenharmony_ci	 * If cells_name is NULL we assume a cell count of 0. This makes
17528c2ecf20Sopenharmony_ci	 * counting the phandles trivial as each 32bit word in the list is a
17538c2ecf20Sopenharmony_ci	 * phandle and no arguments are to consider. So we don't iterate through
17548c2ecf20Sopenharmony_ci	 * the list but just use the length to determine the phandle count.
17558c2ecf20Sopenharmony_ci	 */
17568c2ecf20Sopenharmony_ci	if (!cells_name) {
17578c2ecf20Sopenharmony_ci		const __be32 *list;
17588c2ecf20Sopenharmony_ci		int size;
17598c2ecf20Sopenharmony_ci
17608c2ecf20Sopenharmony_ci		list = of_get_property(np, list_name, &size);
17618c2ecf20Sopenharmony_ci		if (!list)
17628c2ecf20Sopenharmony_ci			return -ENOENT;
17638c2ecf20Sopenharmony_ci
17648c2ecf20Sopenharmony_ci		return size / sizeof(*list);
17658c2ecf20Sopenharmony_ci	}
17668c2ecf20Sopenharmony_ci
17678c2ecf20Sopenharmony_ci	rc = of_phandle_iterator_init(&it, np, list_name, cells_name, -1);
17688c2ecf20Sopenharmony_ci	if (rc)
17698c2ecf20Sopenharmony_ci		return rc;
17708c2ecf20Sopenharmony_ci
17718c2ecf20Sopenharmony_ci	while ((rc = of_phandle_iterator_next(&it)) == 0)
17728c2ecf20Sopenharmony_ci		cur_index += 1;
17738c2ecf20Sopenharmony_ci
17748c2ecf20Sopenharmony_ci	if (rc != -ENOENT)
17758c2ecf20Sopenharmony_ci		return rc;
17768c2ecf20Sopenharmony_ci
17778c2ecf20Sopenharmony_ci	return cur_index;
17788c2ecf20Sopenharmony_ci}
17798c2ecf20Sopenharmony_ciEXPORT_SYMBOL(of_count_phandle_with_args);
17808c2ecf20Sopenharmony_ci
17818c2ecf20Sopenharmony_ci/**
17828c2ecf20Sopenharmony_ci * __of_add_property - Add a property to a node without lock operations
17838c2ecf20Sopenharmony_ci * @np:		Caller's Device Node
17848c2ecf20Sopenharmony_ci * @prob:	Property to add
17858c2ecf20Sopenharmony_ci */
17868c2ecf20Sopenharmony_ciint __of_add_property(struct device_node *np, struct property *prop)
17878c2ecf20Sopenharmony_ci{
17888c2ecf20Sopenharmony_ci	struct property **next;
17898c2ecf20Sopenharmony_ci
17908c2ecf20Sopenharmony_ci	prop->next = NULL;
17918c2ecf20Sopenharmony_ci	next = &np->properties;
17928c2ecf20Sopenharmony_ci	while (*next) {
17938c2ecf20Sopenharmony_ci		if (strcmp(prop->name, (*next)->name) == 0)
17948c2ecf20Sopenharmony_ci			/* duplicate ! don't insert it */
17958c2ecf20Sopenharmony_ci			return -EEXIST;
17968c2ecf20Sopenharmony_ci
17978c2ecf20Sopenharmony_ci		next = &(*next)->next;
17988c2ecf20Sopenharmony_ci	}
17998c2ecf20Sopenharmony_ci	*next = prop;
18008c2ecf20Sopenharmony_ci
18018c2ecf20Sopenharmony_ci	return 0;
18028c2ecf20Sopenharmony_ci}
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ci/**
18058c2ecf20Sopenharmony_ci * of_add_property - Add a property to a node
18068c2ecf20Sopenharmony_ci * @np:		Caller's Device Node
18078c2ecf20Sopenharmony_ci * @prob:	Property to add
18088c2ecf20Sopenharmony_ci */
18098c2ecf20Sopenharmony_ciint of_add_property(struct device_node *np, struct property *prop)
18108c2ecf20Sopenharmony_ci{
18118c2ecf20Sopenharmony_ci	unsigned long flags;
18128c2ecf20Sopenharmony_ci	int rc;
18138c2ecf20Sopenharmony_ci
18148c2ecf20Sopenharmony_ci	mutex_lock(&of_mutex);
18158c2ecf20Sopenharmony_ci
18168c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
18178c2ecf20Sopenharmony_ci	rc = __of_add_property(np, prop);
18188c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
18198c2ecf20Sopenharmony_ci
18208c2ecf20Sopenharmony_ci	if (!rc)
18218c2ecf20Sopenharmony_ci		__of_add_property_sysfs(np, prop);
18228c2ecf20Sopenharmony_ci
18238c2ecf20Sopenharmony_ci	mutex_unlock(&of_mutex);
18248c2ecf20Sopenharmony_ci
18258c2ecf20Sopenharmony_ci	if (!rc)
18268c2ecf20Sopenharmony_ci		of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL);
18278c2ecf20Sopenharmony_ci
18288c2ecf20Sopenharmony_ci	return rc;
18298c2ecf20Sopenharmony_ci}
18308c2ecf20Sopenharmony_ci
18318c2ecf20Sopenharmony_ciint __of_remove_property(struct device_node *np, struct property *prop)
18328c2ecf20Sopenharmony_ci{
18338c2ecf20Sopenharmony_ci	struct property **next;
18348c2ecf20Sopenharmony_ci
18358c2ecf20Sopenharmony_ci	for (next = &np->properties; *next; next = &(*next)->next) {
18368c2ecf20Sopenharmony_ci		if (*next == prop)
18378c2ecf20Sopenharmony_ci			break;
18388c2ecf20Sopenharmony_ci	}
18398c2ecf20Sopenharmony_ci	if (*next == NULL)
18408c2ecf20Sopenharmony_ci		return -ENODEV;
18418c2ecf20Sopenharmony_ci
18428c2ecf20Sopenharmony_ci	/* found the node */
18438c2ecf20Sopenharmony_ci	*next = prop->next;
18448c2ecf20Sopenharmony_ci	prop->next = np->deadprops;
18458c2ecf20Sopenharmony_ci	np->deadprops = prop;
18468c2ecf20Sopenharmony_ci
18478c2ecf20Sopenharmony_ci	return 0;
18488c2ecf20Sopenharmony_ci}
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ci/**
18518c2ecf20Sopenharmony_ci * of_remove_property - Remove a property from a node.
18528c2ecf20Sopenharmony_ci * @np:		Caller's Device Node
18538c2ecf20Sopenharmony_ci * @prob:	Property to remove
18548c2ecf20Sopenharmony_ci *
18558c2ecf20Sopenharmony_ci * Note that we don't actually remove it, since we have given out
18568c2ecf20Sopenharmony_ci * who-knows-how-many pointers to the data using get-property.
18578c2ecf20Sopenharmony_ci * Instead we just move the property to the "dead properties"
18588c2ecf20Sopenharmony_ci * list, so it won't be found any more.
18598c2ecf20Sopenharmony_ci */
18608c2ecf20Sopenharmony_ciint of_remove_property(struct device_node *np, struct property *prop)
18618c2ecf20Sopenharmony_ci{
18628c2ecf20Sopenharmony_ci	unsigned long flags;
18638c2ecf20Sopenharmony_ci	int rc;
18648c2ecf20Sopenharmony_ci
18658c2ecf20Sopenharmony_ci	if (!prop)
18668c2ecf20Sopenharmony_ci		return -ENODEV;
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_ci	mutex_lock(&of_mutex);
18698c2ecf20Sopenharmony_ci
18708c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
18718c2ecf20Sopenharmony_ci	rc = __of_remove_property(np, prop);
18728c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
18738c2ecf20Sopenharmony_ci
18748c2ecf20Sopenharmony_ci	if (!rc)
18758c2ecf20Sopenharmony_ci		__of_remove_property_sysfs(np, prop);
18768c2ecf20Sopenharmony_ci
18778c2ecf20Sopenharmony_ci	mutex_unlock(&of_mutex);
18788c2ecf20Sopenharmony_ci
18798c2ecf20Sopenharmony_ci	if (!rc)
18808c2ecf20Sopenharmony_ci		of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL);
18818c2ecf20Sopenharmony_ci
18828c2ecf20Sopenharmony_ci	return rc;
18838c2ecf20Sopenharmony_ci}
18848c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_remove_property);
18858c2ecf20Sopenharmony_ci
18868c2ecf20Sopenharmony_ciint __of_update_property(struct device_node *np, struct property *newprop,
18878c2ecf20Sopenharmony_ci		struct property **oldpropp)
18888c2ecf20Sopenharmony_ci{
18898c2ecf20Sopenharmony_ci	struct property **next, *oldprop;
18908c2ecf20Sopenharmony_ci
18918c2ecf20Sopenharmony_ci	for (next = &np->properties; *next; next = &(*next)->next) {
18928c2ecf20Sopenharmony_ci		if (of_prop_cmp((*next)->name, newprop->name) == 0)
18938c2ecf20Sopenharmony_ci			break;
18948c2ecf20Sopenharmony_ci	}
18958c2ecf20Sopenharmony_ci	*oldpropp = oldprop = *next;
18968c2ecf20Sopenharmony_ci
18978c2ecf20Sopenharmony_ci	if (oldprop) {
18988c2ecf20Sopenharmony_ci		/* replace the node */
18998c2ecf20Sopenharmony_ci		newprop->next = oldprop->next;
19008c2ecf20Sopenharmony_ci		*next = newprop;
19018c2ecf20Sopenharmony_ci		oldprop->next = np->deadprops;
19028c2ecf20Sopenharmony_ci		np->deadprops = oldprop;
19038c2ecf20Sopenharmony_ci	} else {
19048c2ecf20Sopenharmony_ci		/* new node */
19058c2ecf20Sopenharmony_ci		newprop->next = NULL;
19068c2ecf20Sopenharmony_ci		*next = newprop;
19078c2ecf20Sopenharmony_ci	}
19088c2ecf20Sopenharmony_ci
19098c2ecf20Sopenharmony_ci	return 0;
19108c2ecf20Sopenharmony_ci}
19118c2ecf20Sopenharmony_ci
19128c2ecf20Sopenharmony_ci/*
19138c2ecf20Sopenharmony_ci * of_update_property - Update a property in a node, if the property does
19148c2ecf20Sopenharmony_ci * not exist, add it.
19158c2ecf20Sopenharmony_ci *
19168c2ecf20Sopenharmony_ci * Note that we don't actually remove it, since we have given out
19178c2ecf20Sopenharmony_ci * who-knows-how-many pointers to the data using get-property.
19188c2ecf20Sopenharmony_ci * Instead we just move the property to the "dead properties" list,
19198c2ecf20Sopenharmony_ci * and add the new property to the property list
19208c2ecf20Sopenharmony_ci */
19218c2ecf20Sopenharmony_ciint of_update_property(struct device_node *np, struct property *newprop)
19228c2ecf20Sopenharmony_ci{
19238c2ecf20Sopenharmony_ci	struct property *oldprop;
19248c2ecf20Sopenharmony_ci	unsigned long flags;
19258c2ecf20Sopenharmony_ci	int rc;
19268c2ecf20Sopenharmony_ci
19278c2ecf20Sopenharmony_ci	if (!newprop->name)
19288c2ecf20Sopenharmony_ci		return -EINVAL;
19298c2ecf20Sopenharmony_ci
19308c2ecf20Sopenharmony_ci	mutex_lock(&of_mutex);
19318c2ecf20Sopenharmony_ci
19328c2ecf20Sopenharmony_ci	raw_spin_lock_irqsave(&devtree_lock, flags);
19338c2ecf20Sopenharmony_ci	rc = __of_update_property(np, newprop, &oldprop);
19348c2ecf20Sopenharmony_ci	raw_spin_unlock_irqrestore(&devtree_lock, flags);
19358c2ecf20Sopenharmony_ci
19368c2ecf20Sopenharmony_ci	if (!rc)
19378c2ecf20Sopenharmony_ci		__of_update_property_sysfs(np, newprop, oldprop);
19388c2ecf20Sopenharmony_ci
19398c2ecf20Sopenharmony_ci	mutex_unlock(&of_mutex);
19408c2ecf20Sopenharmony_ci
19418c2ecf20Sopenharmony_ci	if (!rc)
19428c2ecf20Sopenharmony_ci		of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop);
19438c2ecf20Sopenharmony_ci
19448c2ecf20Sopenharmony_ci	return rc;
19458c2ecf20Sopenharmony_ci}
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_cistatic void of_alias_add(struct alias_prop *ap, struct device_node *np,
19488c2ecf20Sopenharmony_ci			 int id, const char *stem, int stem_len)
19498c2ecf20Sopenharmony_ci{
19508c2ecf20Sopenharmony_ci	ap->np = np;
19518c2ecf20Sopenharmony_ci	ap->id = id;
19528c2ecf20Sopenharmony_ci	strncpy(ap->stem, stem, stem_len);
19538c2ecf20Sopenharmony_ci	ap->stem[stem_len] = 0;
19548c2ecf20Sopenharmony_ci	list_add_tail(&ap->link, &aliases_lookup);
19558c2ecf20Sopenharmony_ci	pr_debug("adding DT alias:%s: stem=%s id=%i node=%pOF\n",
19568c2ecf20Sopenharmony_ci		 ap->alias, ap->stem, ap->id, np);
19578c2ecf20Sopenharmony_ci}
19588c2ecf20Sopenharmony_ci
19598c2ecf20Sopenharmony_ci/**
19608c2ecf20Sopenharmony_ci * of_alias_scan - Scan all properties of the 'aliases' node
19618c2ecf20Sopenharmony_ci * @dt_alloc:	An allocator that provides a virtual address to memory
19628c2ecf20Sopenharmony_ci *		for storing the resulting tree
19638c2ecf20Sopenharmony_ci *
19648c2ecf20Sopenharmony_ci * The function scans all the properties of the 'aliases' node and populates
19658c2ecf20Sopenharmony_ci * the global lookup table with the properties.  It returns the
19668c2ecf20Sopenharmony_ci * number of alias properties found, or an error code in case of failure.
19678c2ecf20Sopenharmony_ci */
19688c2ecf20Sopenharmony_civoid of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
19698c2ecf20Sopenharmony_ci{
19708c2ecf20Sopenharmony_ci	struct property *pp;
19718c2ecf20Sopenharmony_ci
19728c2ecf20Sopenharmony_ci	of_aliases = of_find_node_by_path("/aliases");
19738c2ecf20Sopenharmony_ci	of_chosen = of_find_node_by_path("/chosen");
19748c2ecf20Sopenharmony_ci	if (of_chosen == NULL)
19758c2ecf20Sopenharmony_ci		of_chosen = of_find_node_by_path("/chosen@0");
19768c2ecf20Sopenharmony_ci
19778c2ecf20Sopenharmony_ci	if (of_chosen) {
19788c2ecf20Sopenharmony_ci		/* linux,stdout-path and /aliases/stdout are for legacy compatibility */
19798c2ecf20Sopenharmony_ci		const char *name = NULL;
19808c2ecf20Sopenharmony_ci
19818c2ecf20Sopenharmony_ci		if (of_property_read_string(of_chosen, "stdout-path", &name))
19828c2ecf20Sopenharmony_ci			of_property_read_string(of_chosen, "linux,stdout-path",
19838c2ecf20Sopenharmony_ci						&name);
19848c2ecf20Sopenharmony_ci		if (IS_ENABLED(CONFIG_PPC) && !name)
19858c2ecf20Sopenharmony_ci			of_property_read_string(of_aliases, "stdout", &name);
19868c2ecf20Sopenharmony_ci		if (name)
19878c2ecf20Sopenharmony_ci			of_stdout = of_find_node_opts_by_path(name, &of_stdout_options);
19888c2ecf20Sopenharmony_ci	}
19898c2ecf20Sopenharmony_ci
19908c2ecf20Sopenharmony_ci	if (!of_aliases)
19918c2ecf20Sopenharmony_ci		return;
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_ci	for_each_property_of_node(of_aliases, pp) {
19948c2ecf20Sopenharmony_ci		const char *start = pp->name;
19958c2ecf20Sopenharmony_ci		const char *end = start + strlen(start);
19968c2ecf20Sopenharmony_ci		struct device_node *np;
19978c2ecf20Sopenharmony_ci		struct alias_prop *ap;
19988c2ecf20Sopenharmony_ci		int id, len;
19998c2ecf20Sopenharmony_ci
20008c2ecf20Sopenharmony_ci		/* Skip those we do not want to proceed */
20018c2ecf20Sopenharmony_ci		if (!strcmp(pp->name, "name") ||
20028c2ecf20Sopenharmony_ci		    !strcmp(pp->name, "phandle") ||
20038c2ecf20Sopenharmony_ci		    !strcmp(pp->name, "linux,phandle"))
20048c2ecf20Sopenharmony_ci			continue;
20058c2ecf20Sopenharmony_ci
20068c2ecf20Sopenharmony_ci		np = of_find_node_by_path(pp->value);
20078c2ecf20Sopenharmony_ci		if (!np)
20088c2ecf20Sopenharmony_ci			continue;
20098c2ecf20Sopenharmony_ci
20108c2ecf20Sopenharmony_ci		/* walk the alias backwards to extract the id and work out
20118c2ecf20Sopenharmony_ci		 * the 'stem' string */
20128c2ecf20Sopenharmony_ci		while (isdigit(*(end-1)) && end > start)
20138c2ecf20Sopenharmony_ci			end--;
20148c2ecf20Sopenharmony_ci		len = end - start;
20158c2ecf20Sopenharmony_ci
20168c2ecf20Sopenharmony_ci		if (kstrtoint(end, 10, &id) < 0)
20178c2ecf20Sopenharmony_ci			continue;
20188c2ecf20Sopenharmony_ci
20198c2ecf20Sopenharmony_ci		/* Allocate an alias_prop with enough space for the stem */
20208c2ecf20Sopenharmony_ci		ap = dt_alloc(sizeof(*ap) + len + 1, __alignof__(*ap));
20218c2ecf20Sopenharmony_ci		if (!ap)
20228c2ecf20Sopenharmony_ci			continue;
20238c2ecf20Sopenharmony_ci		memset(ap, 0, sizeof(*ap) + len + 1);
20248c2ecf20Sopenharmony_ci		ap->alias = start;
20258c2ecf20Sopenharmony_ci		of_alias_add(ap, np, id, start, len);
20268c2ecf20Sopenharmony_ci	}
20278c2ecf20Sopenharmony_ci}
20288c2ecf20Sopenharmony_ci
20298c2ecf20Sopenharmony_ci/**
20308c2ecf20Sopenharmony_ci * of_alias_get_id - Get alias id for the given device_node
20318c2ecf20Sopenharmony_ci * @np:		Pointer to the given device_node
20328c2ecf20Sopenharmony_ci * @stem:	Alias stem of the given device_node
20338c2ecf20Sopenharmony_ci *
20348c2ecf20Sopenharmony_ci * The function travels the lookup table to get the alias id for the given
20358c2ecf20Sopenharmony_ci * device_node and alias stem.
20368c2ecf20Sopenharmony_ci *
20378c2ecf20Sopenharmony_ci * Return: The alias id if found.
20388c2ecf20Sopenharmony_ci */
20398c2ecf20Sopenharmony_ciint of_alias_get_id(struct device_node *np, const char *stem)
20408c2ecf20Sopenharmony_ci{
20418c2ecf20Sopenharmony_ci	struct alias_prop *app;
20428c2ecf20Sopenharmony_ci	int id = -ENODEV;
20438c2ecf20Sopenharmony_ci
20448c2ecf20Sopenharmony_ci	mutex_lock(&of_mutex);
20458c2ecf20Sopenharmony_ci	list_for_each_entry(app, &aliases_lookup, link) {
20468c2ecf20Sopenharmony_ci		if (strcmp(app->stem, stem) != 0)
20478c2ecf20Sopenharmony_ci			continue;
20488c2ecf20Sopenharmony_ci
20498c2ecf20Sopenharmony_ci		if (np == app->np) {
20508c2ecf20Sopenharmony_ci			id = app->id;
20518c2ecf20Sopenharmony_ci			break;
20528c2ecf20Sopenharmony_ci		}
20538c2ecf20Sopenharmony_ci	}
20548c2ecf20Sopenharmony_ci	mutex_unlock(&of_mutex);
20558c2ecf20Sopenharmony_ci
20568c2ecf20Sopenharmony_ci	return id;
20578c2ecf20Sopenharmony_ci}
20588c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_alias_get_id);
20598c2ecf20Sopenharmony_ci
20608c2ecf20Sopenharmony_ci/**
20618c2ecf20Sopenharmony_ci * of_alias_get_alias_list - Get alias list for the given device driver
20628c2ecf20Sopenharmony_ci * @matches:	Array of OF device match structures to search in
20638c2ecf20Sopenharmony_ci * @stem:	Alias stem of the given device_node
20648c2ecf20Sopenharmony_ci * @bitmap:	Bitmap field pointer
20658c2ecf20Sopenharmony_ci * @nbits:	Maximum number of alias IDs which can be recorded in bitmap
20668c2ecf20Sopenharmony_ci *
20678c2ecf20Sopenharmony_ci * The function travels the lookup table to record alias ids for the given
20688c2ecf20Sopenharmony_ci * device match structures and alias stem.
20698c2ecf20Sopenharmony_ci *
20708c2ecf20Sopenharmony_ci * Return:	0 or -ENOSYS when !CONFIG_OF or
20718c2ecf20Sopenharmony_ci *		-EOVERFLOW if alias ID is greater then allocated nbits
20728c2ecf20Sopenharmony_ci */
20738c2ecf20Sopenharmony_ciint of_alias_get_alias_list(const struct of_device_id *matches,
20748c2ecf20Sopenharmony_ci			     const char *stem, unsigned long *bitmap,
20758c2ecf20Sopenharmony_ci			     unsigned int nbits)
20768c2ecf20Sopenharmony_ci{
20778c2ecf20Sopenharmony_ci	struct alias_prop *app;
20788c2ecf20Sopenharmony_ci	int ret = 0;
20798c2ecf20Sopenharmony_ci
20808c2ecf20Sopenharmony_ci	/* Zero bitmap field to make sure that all the time it is clean */
20818c2ecf20Sopenharmony_ci	bitmap_zero(bitmap, nbits);
20828c2ecf20Sopenharmony_ci
20838c2ecf20Sopenharmony_ci	mutex_lock(&of_mutex);
20848c2ecf20Sopenharmony_ci	pr_debug("%s: Looking for stem: %s\n", __func__, stem);
20858c2ecf20Sopenharmony_ci	list_for_each_entry(app, &aliases_lookup, link) {
20868c2ecf20Sopenharmony_ci		pr_debug("%s: stem: %s, id: %d\n",
20878c2ecf20Sopenharmony_ci			 __func__, app->stem, app->id);
20888c2ecf20Sopenharmony_ci
20898c2ecf20Sopenharmony_ci		if (strcmp(app->stem, stem) != 0) {
20908c2ecf20Sopenharmony_ci			pr_debug("%s: stem comparison didn't pass %s\n",
20918c2ecf20Sopenharmony_ci				 __func__, app->stem);
20928c2ecf20Sopenharmony_ci			continue;
20938c2ecf20Sopenharmony_ci		}
20948c2ecf20Sopenharmony_ci
20958c2ecf20Sopenharmony_ci		if (of_match_node(matches, app->np)) {
20968c2ecf20Sopenharmony_ci			pr_debug("%s: Allocated ID %d\n", __func__, app->id);
20978c2ecf20Sopenharmony_ci
20988c2ecf20Sopenharmony_ci			if (app->id >= nbits) {
20998c2ecf20Sopenharmony_ci				pr_warn("%s: ID %d >= than bitmap field %d\n",
21008c2ecf20Sopenharmony_ci					__func__, app->id, nbits);
21018c2ecf20Sopenharmony_ci				ret = -EOVERFLOW;
21028c2ecf20Sopenharmony_ci			} else {
21038c2ecf20Sopenharmony_ci				set_bit(app->id, bitmap);
21048c2ecf20Sopenharmony_ci			}
21058c2ecf20Sopenharmony_ci		}
21068c2ecf20Sopenharmony_ci	}
21078c2ecf20Sopenharmony_ci	mutex_unlock(&of_mutex);
21088c2ecf20Sopenharmony_ci
21098c2ecf20Sopenharmony_ci	return ret;
21108c2ecf20Sopenharmony_ci}
21118c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_alias_get_alias_list);
21128c2ecf20Sopenharmony_ci
21138c2ecf20Sopenharmony_ci/**
21148c2ecf20Sopenharmony_ci * of_alias_get_highest_id - Get highest alias id for the given stem
21158c2ecf20Sopenharmony_ci * @stem:	Alias stem to be examined
21168c2ecf20Sopenharmony_ci *
21178c2ecf20Sopenharmony_ci * The function travels the lookup table to get the highest alias id for the
21188c2ecf20Sopenharmony_ci * given alias stem.  It returns the alias id if found.
21198c2ecf20Sopenharmony_ci */
21208c2ecf20Sopenharmony_ciint of_alias_get_highest_id(const char *stem)
21218c2ecf20Sopenharmony_ci{
21228c2ecf20Sopenharmony_ci	struct alias_prop *app;
21238c2ecf20Sopenharmony_ci	int id = -ENODEV;
21248c2ecf20Sopenharmony_ci
21258c2ecf20Sopenharmony_ci	mutex_lock(&of_mutex);
21268c2ecf20Sopenharmony_ci	list_for_each_entry(app, &aliases_lookup, link) {
21278c2ecf20Sopenharmony_ci		if (strcmp(app->stem, stem) != 0)
21288c2ecf20Sopenharmony_ci			continue;
21298c2ecf20Sopenharmony_ci
21308c2ecf20Sopenharmony_ci		if (app->id > id)
21318c2ecf20Sopenharmony_ci			id = app->id;
21328c2ecf20Sopenharmony_ci	}
21338c2ecf20Sopenharmony_ci	mutex_unlock(&of_mutex);
21348c2ecf20Sopenharmony_ci
21358c2ecf20Sopenharmony_ci	return id;
21368c2ecf20Sopenharmony_ci}
21378c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_alias_get_highest_id);
21388c2ecf20Sopenharmony_ci
21398c2ecf20Sopenharmony_ci/**
21408c2ecf20Sopenharmony_ci * of_console_check() - Test and setup console for DT setup
21418c2ecf20Sopenharmony_ci * @dn: Pointer to device node
21428c2ecf20Sopenharmony_ci * @name: Name to use for preferred console without index. ex. "ttyS"
21438c2ecf20Sopenharmony_ci * @index: Index to use for preferred console.
21448c2ecf20Sopenharmony_ci *
21458c2ecf20Sopenharmony_ci * Check if the given device node matches the stdout-path property in the
21468c2ecf20Sopenharmony_ci * /chosen node. If it does then register it as the preferred console.
21478c2ecf20Sopenharmony_ci *
21488c2ecf20Sopenharmony_ci * Return: TRUE if console successfully setup. Otherwise return FALSE.
21498c2ecf20Sopenharmony_ci */
21508c2ecf20Sopenharmony_cibool of_console_check(struct device_node *dn, char *name, int index)
21518c2ecf20Sopenharmony_ci{
21528c2ecf20Sopenharmony_ci	if (!dn || dn != of_stdout || console_set_on_cmdline)
21538c2ecf20Sopenharmony_ci		return false;
21548c2ecf20Sopenharmony_ci
21558c2ecf20Sopenharmony_ci	/*
21568c2ecf20Sopenharmony_ci	 * XXX: cast `options' to char pointer to suppress complication
21578c2ecf20Sopenharmony_ci	 * warnings: printk, UART and console drivers expect char pointer.
21588c2ecf20Sopenharmony_ci	 */
21598c2ecf20Sopenharmony_ci	return !add_preferred_console(name, index, (char *)of_stdout_options);
21608c2ecf20Sopenharmony_ci}
21618c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_console_check);
21628c2ecf20Sopenharmony_ci
21638c2ecf20Sopenharmony_ci/**
21648c2ecf20Sopenharmony_ci * of_find_next_cache_node - Find a node's subsidiary cache
21658c2ecf20Sopenharmony_ci * @np:	node of type "cpu" or "cache"
21668c2ecf20Sopenharmony_ci *
21678c2ecf20Sopenharmony_ci * Return: A node pointer with refcount incremented, use
21688c2ecf20Sopenharmony_ci * of_node_put() on it when done.  Caller should hold a reference
21698c2ecf20Sopenharmony_ci * to np.
21708c2ecf20Sopenharmony_ci */
21718c2ecf20Sopenharmony_cistruct device_node *of_find_next_cache_node(const struct device_node *np)
21728c2ecf20Sopenharmony_ci{
21738c2ecf20Sopenharmony_ci	struct device_node *child, *cache_node;
21748c2ecf20Sopenharmony_ci
21758c2ecf20Sopenharmony_ci	cache_node = of_parse_phandle(np, "l2-cache", 0);
21768c2ecf20Sopenharmony_ci	if (!cache_node)
21778c2ecf20Sopenharmony_ci		cache_node = of_parse_phandle(np, "next-level-cache", 0);
21788c2ecf20Sopenharmony_ci
21798c2ecf20Sopenharmony_ci	if (cache_node)
21808c2ecf20Sopenharmony_ci		return cache_node;
21818c2ecf20Sopenharmony_ci
21828c2ecf20Sopenharmony_ci	/* OF on pmac has nodes instead of properties named "l2-cache"
21838c2ecf20Sopenharmony_ci	 * beneath CPU nodes.
21848c2ecf20Sopenharmony_ci	 */
21858c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_PPC_PMAC) && of_node_is_type(np, "cpu"))
21868c2ecf20Sopenharmony_ci		for_each_child_of_node(np, child)
21878c2ecf20Sopenharmony_ci			if (of_node_is_type(child, "cache"))
21888c2ecf20Sopenharmony_ci				return child;
21898c2ecf20Sopenharmony_ci
21908c2ecf20Sopenharmony_ci	return NULL;
21918c2ecf20Sopenharmony_ci}
21928c2ecf20Sopenharmony_ci
21938c2ecf20Sopenharmony_ci/**
21948c2ecf20Sopenharmony_ci * of_find_last_cache_level - Find the level at which the last cache is
21958c2ecf20Sopenharmony_ci * 		present for the given logical cpu
21968c2ecf20Sopenharmony_ci *
21978c2ecf20Sopenharmony_ci * @cpu: cpu number(logical index) for which the last cache level is needed
21988c2ecf20Sopenharmony_ci *
21998c2ecf20Sopenharmony_ci * Return: The the level at which the last cache is present. It is exactly
22008c2ecf20Sopenharmony_ci * same as  the total number of cache levels for the given logical cpu.
22018c2ecf20Sopenharmony_ci */
22028c2ecf20Sopenharmony_ciint of_find_last_cache_level(unsigned int cpu)
22038c2ecf20Sopenharmony_ci{
22048c2ecf20Sopenharmony_ci	u32 cache_level = 0;
22058c2ecf20Sopenharmony_ci	struct device_node *prev = NULL, *np = of_cpu_device_node_get(cpu);
22068c2ecf20Sopenharmony_ci
22078c2ecf20Sopenharmony_ci	while (np) {
22088c2ecf20Sopenharmony_ci		prev = np;
22098c2ecf20Sopenharmony_ci		of_node_put(np);
22108c2ecf20Sopenharmony_ci		np = of_find_next_cache_node(np);
22118c2ecf20Sopenharmony_ci	}
22128c2ecf20Sopenharmony_ci
22138c2ecf20Sopenharmony_ci	of_property_read_u32(prev, "cache-level", &cache_level);
22148c2ecf20Sopenharmony_ci
22158c2ecf20Sopenharmony_ci	return cache_level;
22168c2ecf20Sopenharmony_ci}
22178c2ecf20Sopenharmony_ci
22188c2ecf20Sopenharmony_ci/**
22198c2ecf20Sopenharmony_ci * of_map_id - Translate an ID through a downstream mapping.
22208c2ecf20Sopenharmony_ci * @np: root complex device node.
22218c2ecf20Sopenharmony_ci * @id: device ID to map.
22228c2ecf20Sopenharmony_ci * @map_name: property name of the map to use.
22238c2ecf20Sopenharmony_ci * @map_mask_name: optional property name of the mask to use.
22248c2ecf20Sopenharmony_ci * @target: optional pointer to a target device node.
22258c2ecf20Sopenharmony_ci * @id_out: optional pointer to receive the translated ID.
22268c2ecf20Sopenharmony_ci *
22278c2ecf20Sopenharmony_ci * Given a device ID, look up the appropriate implementation-defined
22288c2ecf20Sopenharmony_ci * platform ID and/or the target device which receives transactions on that
22298c2ecf20Sopenharmony_ci * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or
22308c2ecf20Sopenharmony_ci * @id_out may be NULL if only the other is required. If @target points to
22318c2ecf20Sopenharmony_ci * a non-NULL device node pointer, only entries targeting that node will be
22328c2ecf20Sopenharmony_ci * matched; if it points to a NULL value, it will receive the device node of
22338c2ecf20Sopenharmony_ci * the first matching target phandle, with a reference held.
22348c2ecf20Sopenharmony_ci *
22358c2ecf20Sopenharmony_ci * Return: 0 on success or a standard error code on failure.
22368c2ecf20Sopenharmony_ci */
22378c2ecf20Sopenharmony_ciint of_map_id(struct device_node *np, u32 id,
22388c2ecf20Sopenharmony_ci	       const char *map_name, const char *map_mask_name,
22398c2ecf20Sopenharmony_ci	       struct device_node **target, u32 *id_out)
22408c2ecf20Sopenharmony_ci{
22418c2ecf20Sopenharmony_ci	u32 map_mask, masked_id;
22428c2ecf20Sopenharmony_ci	int map_len;
22438c2ecf20Sopenharmony_ci	const __be32 *map = NULL;
22448c2ecf20Sopenharmony_ci
22458c2ecf20Sopenharmony_ci	if (!np || !map_name || (!target && !id_out))
22468c2ecf20Sopenharmony_ci		return -EINVAL;
22478c2ecf20Sopenharmony_ci
22488c2ecf20Sopenharmony_ci	map = of_get_property(np, map_name, &map_len);
22498c2ecf20Sopenharmony_ci	if (!map) {
22508c2ecf20Sopenharmony_ci		if (target)
22518c2ecf20Sopenharmony_ci			return -ENODEV;
22528c2ecf20Sopenharmony_ci		/* Otherwise, no map implies no translation */
22538c2ecf20Sopenharmony_ci		*id_out = id;
22548c2ecf20Sopenharmony_ci		return 0;
22558c2ecf20Sopenharmony_ci	}
22568c2ecf20Sopenharmony_ci
22578c2ecf20Sopenharmony_ci	if (!map_len || map_len % (4 * sizeof(*map))) {
22588c2ecf20Sopenharmony_ci		pr_err("%pOF: Error: Bad %s length: %d\n", np,
22598c2ecf20Sopenharmony_ci			map_name, map_len);
22608c2ecf20Sopenharmony_ci		return -EINVAL;
22618c2ecf20Sopenharmony_ci	}
22628c2ecf20Sopenharmony_ci
22638c2ecf20Sopenharmony_ci	/* The default is to select all bits. */
22648c2ecf20Sopenharmony_ci	map_mask = 0xffffffff;
22658c2ecf20Sopenharmony_ci
22668c2ecf20Sopenharmony_ci	/*
22678c2ecf20Sopenharmony_ci	 * Can be overridden by "{iommu,msi}-map-mask" property.
22688c2ecf20Sopenharmony_ci	 * If of_property_read_u32() fails, the default is used.
22698c2ecf20Sopenharmony_ci	 */
22708c2ecf20Sopenharmony_ci	if (map_mask_name)
22718c2ecf20Sopenharmony_ci		of_property_read_u32(np, map_mask_name, &map_mask);
22728c2ecf20Sopenharmony_ci
22738c2ecf20Sopenharmony_ci	masked_id = map_mask & id;
22748c2ecf20Sopenharmony_ci	for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) {
22758c2ecf20Sopenharmony_ci		struct device_node *phandle_node;
22768c2ecf20Sopenharmony_ci		u32 id_base = be32_to_cpup(map + 0);
22778c2ecf20Sopenharmony_ci		u32 phandle = be32_to_cpup(map + 1);
22788c2ecf20Sopenharmony_ci		u32 out_base = be32_to_cpup(map + 2);
22798c2ecf20Sopenharmony_ci		u32 id_len = be32_to_cpup(map + 3);
22808c2ecf20Sopenharmony_ci
22818c2ecf20Sopenharmony_ci		if (id_base & ~map_mask) {
22828c2ecf20Sopenharmony_ci			pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores id-base (0x%x)\n",
22838c2ecf20Sopenharmony_ci				np, map_name, map_name,
22848c2ecf20Sopenharmony_ci				map_mask, id_base);
22858c2ecf20Sopenharmony_ci			return -EFAULT;
22868c2ecf20Sopenharmony_ci		}
22878c2ecf20Sopenharmony_ci
22888c2ecf20Sopenharmony_ci		if (masked_id < id_base || masked_id >= id_base + id_len)
22898c2ecf20Sopenharmony_ci			continue;
22908c2ecf20Sopenharmony_ci
22918c2ecf20Sopenharmony_ci		phandle_node = of_find_node_by_phandle(phandle);
22928c2ecf20Sopenharmony_ci		if (!phandle_node)
22938c2ecf20Sopenharmony_ci			return -ENODEV;
22948c2ecf20Sopenharmony_ci
22958c2ecf20Sopenharmony_ci		if (target) {
22968c2ecf20Sopenharmony_ci			if (*target)
22978c2ecf20Sopenharmony_ci				of_node_put(phandle_node);
22988c2ecf20Sopenharmony_ci			else
22998c2ecf20Sopenharmony_ci				*target = phandle_node;
23008c2ecf20Sopenharmony_ci
23018c2ecf20Sopenharmony_ci			if (*target != phandle_node)
23028c2ecf20Sopenharmony_ci				continue;
23038c2ecf20Sopenharmony_ci		}
23048c2ecf20Sopenharmony_ci
23058c2ecf20Sopenharmony_ci		if (id_out)
23068c2ecf20Sopenharmony_ci			*id_out = masked_id - id_base + out_base;
23078c2ecf20Sopenharmony_ci
23088c2ecf20Sopenharmony_ci		pr_debug("%pOF: %s, using mask %08x, id-base: %08x, out-base: %08x, length: %08x, id: %08x -> %08x\n",
23098c2ecf20Sopenharmony_ci			np, map_name, map_mask, id_base, out_base,
23108c2ecf20Sopenharmony_ci			id_len, id, masked_id - id_base + out_base);
23118c2ecf20Sopenharmony_ci		return 0;
23128c2ecf20Sopenharmony_ci	}
23138c2ecf20Sopenharmony_ci
23148c2ecf20Sopenharmony_ci	pr_info("%pOF: no %s translation for id 0x%x on %pOF\n", np, map_name,
23158c2ecf20Sopenharmony_ci		id, target && *target ? *target : NULL);
23168c2ecf20Sopenharmony_ci
23178c2ecf20Sopenharmony_ci	/* Bypasses translation */
23188c2ecf20Sopenharmony_ci	if (id_out)
23198c2ecf20Sopenharmony_ci		*id_out = id;
23208c2ecf20Sopenharmony_ci	return 0;
23218c2ecf20Sopenharmony_ci}
23228c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(of_map_id);
2323