2301 lines · 58.8 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0+/* * Procedures for creating, accessing and interpreting the device tree. * * Paul Mackerras	August 1996. * Copyright (C) 1996-2005 Paul Mackerras. * *  Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. *    {engebret|bergner}@us.ibm.com * *  Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net * *  Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and *  Grant Likely. */ #define pr_fmt(fmt)	"OF: " fmt #include <linux/bitmap.h>#include <linux/console.h>#include <linux/ctype.h>#include <linux/cpu.h>#include <linux/module.h>#include <linux/of.h>#include <linux/of_device.h>#include <linux/of_graph.h>#include <linux/spinlock.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/proc_fs.h> #include "of_private.h" LIST_HEAD(aliases_lookup); struct device_node *of_root;EXPORT_SYMBOL(of_root);struct device_node *of_chosen;struct device_node *of_aliases;struct device_node *of_stdout;static const char *of_stdout_options; struct kset *of_kset; /* * Used to protect the of_aliases, to hold off addition of nodes to sysfs. * This mutex must be held whenever modifications are being made to the * device tree. The of_{attach,detach}_node() and * of_{add,remove,update}_property() helpers make sure this happens. */DEFINE_MUTEX(of_mutex); /* use when traversing tree through the child, sibling, * or parent members of struct device_node. */DEFINE_RAW_SPINLOCK(devtree_lock); bool of_node_name_eq(const struct device_node *np, const char *name){	const char *node_name;	size_t len; 	if (!np)		return false; 	node_name = kbasename(np->full_name);	len = strchrnul(node_name, '@') - node_name; 	return (strlen(name) == len) && (strncmp(node_name, name, len) == 0);}EXPORT_SYMBOL(of_node_name_eq); bool of_node_name_prefix(const struct device_node *np, const char *prefix){	if (!np)		return false; 	return strncmp(kbasename(np->full_name), prefix, strlen(prefix)) == 0;}EXPORT_SYMBOL(of_node_name_prefix); static bool __of_node_is_type(const struct device_node *np, const char *type){	const char *match = __of_get_property(np, "device_type", NULL); 	return np && match && type && !strcmp(match, type);} int of_n_addr_cells(struct device_node *np){	u32 cells; 	do {		if (np->parent)			np = np->parent;		if (!of_property_read_u32(np, "#address-cells", &cells))			return cells;	} while (np->parent);	/* No #address-cells property for the root node */	return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;}EXPORT_SYMBOL(of_n_addr_cells); int of_n_size_cells(struct device_node *np){	u32 cells; 	do {		if (np->parent)			np = np->parent;		if (!of_property_read_u32(np, "#size-cells", &cells))			return cells;	} while (np->parent);	/* No #size-cells property for the root node */	return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;}EXPORT_SYMBOL(of_n_size_cells); #ifdef CONFIG_NUMAint __weak of_node_to_nid(struct device_node *np){	return NUMA_NO_NODE;}#endif /* * Assumptions behind phandle_cache implementation: *   - phandle property values are in a contiguous range of 1..n * * If the assumptions do not hold, then *   - the phandle lookup overhead reduction provided by the cache *     will likely be less */ static struct device_node **phandle_cache;static u32 phandle_cache_mask; /* * Caller must hold devtree_lock. */static void __of_free_phandle_cache(void){	u32 cache_entries = phandle_cache_mask + 1;	u32 k; 	if (!phandle_cache)		return; 	for (k = 0; k < cache_entries; k++)		of_node_put(phandle_cache[k]); 	kfree(phandle_cache);	phandle_cache = NULL;} int of_free_phandle_cache(void){	unsigned long flags; 	raw_spin_lock_irqsave(&devtree_lock, flags); 	__of_free_phandle_cache(); 	raw_spin_unlock_irqrestore(&devtree_lock, flags); 	return 0;}#if !defined(CONFIG_MODULES)late_initcall_sync(of_free_phandle_cache);#endif /* * Caller must hold devtree_lock. */void __of_free_phandle_cache_entry(phandle handle){	phandle masked_handle;	struct device_node *np; 	if (!handle)		return; 	masked_handle = handle & phandle_cache_mask; 	if (phandle_cache) {		np = phandle_cache[masked_handle];		if (np && handle == np->phandle) {			of_node_put(np);			phandle_cache[masked_handle] = NULL;		}	}} void of_populate_phandle_cache(void){	unsigned long flags;	u32 cache_entries;	struct device_node *np;	u32 phandles = 0; 	raw_spin_lock_irqsave(&devtree_lock, flags); 	__of_free_phandle_cache(); 	for_each_of_allnodes(np)		if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL)			phandles++; 	if (!phandles)		goto out; 	cache_entries = roundup_pow_of_two(phandles);	phandle_cache_mask = cache_entries - 1; 	phandle_cache = kcalloc(cache_entries, sizeof(*phandle_cache),				GFP_ATOMIC);	if (!phandle_cache)		goto out; 	for_each_of_allnodes(np)		if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL) {			of_node_get(np);			phandle_cache[np->phandle & phandle_cache_mask] = np;		} out:	raw_spin_unlock_irqrestore(&devtree_lock, flags);} void __init of_core_init(void){	struct device_node *np; 	of_populate_phandle_cache(); 	/* Create the kset, and register existing nodes */	mutex_lock(&of_mutex);	of_kset = kset_create_and_add("devicetree", NULL, firmware_kobj);	if (!of_kset) {		mutex_unlock(&of_mutex);		pr_err("failed to register existing nodes\n");		return;	}	for_each_of_allnodes(np)		__of_attach_node_sysfs(np);	mutex_unlock(&of_mutex); 	/* Symlink in /proc as required by userspace ABI */	if (of_root)		proc_symlink("device-tree", NULL, "/sys/firmware/devicetree/base");} static struct property *__of_find_property(const struct device_node *np,					   const char *name, int *lenp){	struct property *pp; 	if (!np)		return NULL; 	for (pp = np->properties; pp; pp = pp->next) {		if (of_prop_cmp(pp->name, name) == 0) {			if (lenp)				*lenp = pp->length;			break;		}	} 	return pp;} struct property *of_find_property(const struct device_node *np,				  const char *name,				  int *lenp){	struct property *pp;	unsigned long flags; 	raw_spin_lock_irqsave(&devtree_lock, flags);	pp = __of_find_property(np, name, lenp);	raw_spin_unlock_irqrestore(&devtree_lock, flags); 	return pp;}EXPORT_SYMBOL(of_find_property); struct device_node *__of_find_all_nodes(struct device_node *prev){	struct device_node *np;	if (!prev) {		np = of_root;	} else if (prev->child) {		np = prev->child;	} else {		/* Walk back up looking for a sibling, or the end of the structure */		np = prev;		while (np->parent && !np->sibling)			np = np->parent;		np = np->sibling; /* Might be null at the end of the tree */	}	return np;} /** * of_find_all_nodes - Get next node in global list * @prev:	Previous node or NULL to start iteration *		of_node_put() will be called on it * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */struct device_node *of_find_all_nodes(struct device_node *prev){	struct device_node *np;	unsigned long flags; 	raw_spin_lock_irqsave(&devtree_lock, flags);	np = __of_find_all_nodes(prev);	of_node_get(np);	of_node_put(prev);	raw_spin_unlock_irqrestore(&devtree_lock, flags);	return np;}EXPORT_SYMBOL(of_find_all_nodes); /* * Find a property with a given name for a given node * and return the value. */const void *__of_get_property(const struct device_node *np,			      const char *name, int *lenp){	struct property *pp = __of_find_property(np, name, lenp); 	return pp ? pp->value : NULL;} /* * Find a property with a given name for a given node * and return the value. */const void *of_get_property(const struct device_node *np, const char *name,			    int *lenp){	struct property *pp = of_find_property(np, name, lenp); 	return pp ? pp->value : NULL;}EXPORT_SYMBOL(of_get_property); /* * arch_match_cpu_phys_id - Match the given logical CPU and physical id * * @cpu: logical cpu index of a core/thread * @phys_id: physical identifier of a core/thread * * CPU logical to physical index mapping is architecture specific. * However this __weak function provides a default match of physical * id to logical cpu index. phys_id provided here is usually values read * from the device tree which must match the hardware internal registers. * * Returns true if the physical identifier and the logical cpu index * correspond to the same core/thread, false otherwise. */bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id){	return (u32)phys_id == cpu;} /** * Checks if the given "prop_name" property holds the physical id of the * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not * NULL, local thread number within the core is returned in it. */static bool __of_find_n_match_cpu_property(struct device_node *cpun,			const char *prop_name, int cpu, unsigned int *thread){	const __be32 *cell;	int ac, prop_len, tid;	u64 hwid; 	ac = of_n_addr_cells(cpun);	cell = of_get_property(cpun, prop_name, &prop_len);	if (!cell && !ac && arch_match_cpu_phys_id(cpu, 0))		return true;	if (!cell || !ac)		return false;	prop_len /= sizeof(*cell) * ac;	for (tid = 0; tid < prop_len; tid++) {		hwid = of_read_number(cell, ac);		if (arch_match_cpu_phys_id(cpu, hwid)) {			if (thread)				*thread = tid;			return true;		}		cell += ac;	}	return false;} /* * arch_find_n_match_cpu_physical_id - See if the given device node is * for the cpu corresponding to logical cpu 'cpu'.  Return true if so, * else false.  If 'thread' is non-NULL, the local thread number within the * core is returned in it. */bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun,					      int cpu, unsigned int *thread){	/* Check for non-standard "ibm,ppc-interrupt-server#s" property	 * for thread ids on PowerPC. If it doesn't exist fallback to	 * standard "reg" property.	 */	if (IS_ENABLED(CONFIG_PPC) &&	    __of_find_n_match_cpu_property(cpun,					   "ibm,ppc-interrupt-server#s",					   cpu, thread))		return true; 	return __of_find_n_match_cpu_property(cpun, "reg", cpu, thread);} /** * of_get_cpu_node - Get device node associated with the given logical CPU * * @cpu: CPU number(logical index) for which device node is required * @thread: if not NULL, local thread number within the physical core is *          returned * * The main purpose of this function is to retrieve the device node for the * given logical CPU index. It should be used to initialize the of_node in * cpu device. Once of_node in cpu device is populated, all the further * references can use that instead. * * CPU logical to physical index mapping is architecture specific and is built * before booting secondary cores. This function uses arch_match_cpu_phys_id * which can be overridden by architecture specific implementation. * * Returns a node pointer for the logical cpu with refcount incremented, use * of_node_put() on it when done. Returns NULL if not found. */struct device_node *of_get_cpu_node(int cpu, unsigned int *thread){	struct device_node *cpun; 	for_each_of_cpu_node(cpun) {		if (arch_find_n_match_cpu_physical_id(cpun, cpu, thread))			return cpun;	}	return NULL;}EXPORT_SYMBOL(of_get_cpu_node); /** * of_cpu_node_to_id: Get the logical CPU number for a given device_node * * @cpu_node: Pointer to the device_node for CPU. * * Returns the logical CPU number of the given CPU device_node. * Returns -ENODEV if the CPU is not found. */int of_cpu_node_to_id(struct device_node *cpu_node){	int cpu;	bool found = false;	struct device_node *np; 	for_each_possible_cpu(cpu) {		np = of_cpu_device_node_get(cpu);		found = (cpu_node == np);		of_node_put(np);		if (found)			return cpu;	} 	return -ENODEV;}EXPORT_SYMBOL(of_cpu_node_to_id); /** * __of_device_is_compatible() - Check if the node matches given constraints * @device: pointer to node * @compat: required compatible string, NULL or "" for any match * @type: required device_type value, NULL or "" for any match * @name: required node name, NULL or "" for any match * * Checks if the given @compat, @type and @name strings match the * properties of the given @device. A constraints can be skipped by * passing NULL or an empty string as the constraint. * * Returns 0 for no match, and a positive integer on match. The return * value is a relative score with larger values indicating better * matches. The score is weighted for the most specific compatible value * to get the highest score. Matching type is next, followed by matching * name. Practically speaking, this results in the following priority * order for matches: * * 1. specific compatible && type && name * 2. specific compatible && type * 3. specific compatible && name

Lines 1–500 of 2301.