2007-05-01 10:26:07 +04:00
/*
* Procedures for creating , accessing and interpreting the device tree .
*
* Paul Mackerras August 1996.
* Copyright ( C ) 1996 - 2005 Paul Mackerras .
*
* Adapted for 64 bit 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>
2007-04-24 10:46:53 +04:00
# include <linux/spinlock.h>
/* use when traversing tree through the allnext, child, sibling,
* or parent members of struct device_node .
*/
DEFINE_RWLOCK ( devtree_lock ) ;
2007-05-01 10:26:07 +04:00
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 ) ;
2007-04-24 10:46:53 +04:00
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 ) ;
2007-05-01 10:26:07 +04:00
/*
* 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 ) ;
2007-05-01 10:29:19 +04:00
/** 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 ) ;
2007-04-24 11:16:16 +04:00
/**
* 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 ) ;