base.c

来自「linux 内核源代码」· C语言 代码 · 共 276 行

C
276
字号
/* * 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. * *      This program is free software; you can redistribute it and/or *      modify it under the terms of the GNU General Public License *      as published by the Free Software Foundation; either version *      2 of the License, or (at your option) any later version. */#include <linux/module.h>#include <linux/of.h>#include <linux/spinlock.h>struct device_node *allnodes;/* use when traversing tree through the allnext, child, sibling, * or parent members of struct device_node. */DEFINE_RWLOCK(devtree_lock);int of_n_addr_cells(struct device_node *np){	const int *ip;	do {		if (np->parent)			np = np->parent;		ip = of_get_property(np, "#address-cells", NULL);		if (ip)			return *ip;	} 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){	const int *ip;	do {		if (np->parent)			np = np->parent;		ip = of_get_property(np, "#size-cells", NULL);		if (ip)			return *ip;	} while (np->parent);	/* No #size-cells property for the root node */	return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;}EXPORT_SYMBOL(of_n_size_cells);struct property *of_find_property(const struct device_node *np,				  const char *name,				  int *lenp){	struct property *pp;	read_lock(&devtree_lock);	for (pp = np->properties; pp != 0; pp = pp->next) {		if (of_prop_cmp(pp->name, name) == 0) {			if (lenp != 0)				*lenp = pp->length;			break;		}	}	read_unlock(&devtree_lock);	return pp;}EXPORT_SYMBOL(of_find_property);/* * 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);/** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */int of_device_is_compatible(const struct device_node *device,		const char *compat){	const char* cp;	int cplen, l;	cp = of_get_property(device, "compatible", &cplen);	if (cp == NULL)		return 0;	while (cplen > 0) {		if (of_compat_cmp(cp, compat, strlen(compat)) == 0)			return 1;		l = strlen(cp) + 1;		cp += l;		cplen -= l;	}	return 0;}EXPORT_SYMBOL(of_device_is_compatible);/** *	of_get_parent - Get a node's parent if any *	@node:	Node to get parent * *	Returns a node pointer with refcount incremented, use *	of_node_put() on it when done. */struct device_node *of_get_parent(const struct device_node *node){	struct device_node *np;	if (!node)		return NULL;	read_lock(&devtree_lock);	np = of_node_get(node->parent);	read_unlock(&devtree_lock);	return np;}EXPORT_SYMBOL(of_get_parent);/** *	of_get_next_child - Iterate a node childs *	@node:	parent node *	@prev:	previous child of the parent node, or NULL to get first * *	Returns a node pointer with refcount incremented, use *	of_node_put() on it when done. */struct device_node *of_get_next_child(const struct device_node *node,	struct device_node *prev){	struct device_node *next;	read_lock(&devtree_lock);	next = prev ? prev->sibling : node->child;	for (; next; next = next->sibling)		if (of_node_get(next))			break;	of_node_put(prev);	read_unlock(&devtree_lock);	return next;}EXPORT_SYMBOL(of_get_next_child);/** *	of_find_node_by_path - Find a node matching a full OF path *	@path:	The full path to match * *	Returns a node pointer with refcount incremented, use *	of_node_put() on it when done. */struct device_node *of_find_node_by_path(const char *path){	struct device_node *np = allnodes;	read_lock(&devtree_lock);	for (; np; np = np->allnext) {		if (np->full_name && (of_node_cmp(np->full_name, path) == 0)		    && of_node_get(np))			break;	}	read_unlock(&devtree_lock);	return np;}EXPORT_SYMBOL(of_find_node_by_path);/** *	of_find_node_by_name - Find a node by its "name" property *	@from:	The node to start searching from or NULL, the node *		you pass will not be searched, only the next one *		will; typically, you pass what the previous call *		returned. of_node_put() will be called on it *	@name:	The name string to match against * *	Returns a node pointer with refcount incremented, use *	of_node_put() on it when done. */struct device_node *of_find_node_by_name(struct device_node *from,	const char *name){	struct device_node *np;	read_lock(&devtree_lock);	np = from ? from->allnext : allnodes;	for (; np; np = np->allnext)		if (np->name && (of_node_cmp(np->name, name) == 0)		    && of_node_get(np))			break;	of_node_put(from);	read_unlock(&devtree_lock);	return np;}EXPORT_SYMBOL(of_find_node_by_name);/** *	of_find_node_by_type - Find a node by its "device_type" property *	@from:	The node to start searching from, or NULL to start searching *		the entire device tree. The node you pass will not be *		searched, only the next one will; typically, you pass *		what the previous call returned. of_node_put() will be *		called on from for you. *	@type:	The type string to match against * *	Returns a node pointer with refcount incremented, use *	of_node_put() on it when done. */struct device_node *of_find_node_by_type(struct device_node *from,	const char *type){	struct device_node *np;	read_lock(&devtree_lock);	np = from ? from->allnext : allnodes;	for (; np; np = np->allnext)		if (np->type && (of_node_cmp(np->type, type) == 0)		    && of_node_get(np))			break;	of_node_put(from);	read_unlock(&devtree_lock);	return np;}EXPORT_SYMBOL(of_find_node_by_type);/** *	of_find_compatible_node - Find a node based on type and one of the *                                tokens in its "compatible" property *	@from:		The node to start searching from or NULL, the node *			you pass will not be searched, only the next one *			will; typically, you pass what the previous call *			returned. of_node_put() will be called on it *	@type:		The type string to match "device_type" or NULL to ignore *	@compatible:	The string to match to one of the tokens in the device *			"compatible" list. * *	Returns a node pointer with refcount incremented, use *	of_node_put() on it when done. */struct device_node *of_find_compatible_node(struct device_node *from,	const char *type, const char *compatible){	struct device_node *np;	read_lock(&devtree_lock);	np = from ? from->allnext : allnodes;	for (; np; np = np->allnext) {		if (type		    && !(np->type && (of_node_cmp(np->type, type) == 0)))			continue;		if (of_device_is_compatible(np, compatible) && of_node_get(np))			break;	}	of_node_put(from);	read_unlock(&devtree_lock);	return np;}EXPORT_SYMBOL(of_find_compatible_node);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?