2007-05-02 20:38:57 +04:00
/*
* Copyright ( C ) 2006 Benjamin Herrenschmidt , IBM Corp .
* < benh @ kernel . crashing . org >
* and Arnd Bergmann , IBM Corp .
* Merged from powerpc / kernel / of_platform . c and
* sparc { , 64 } / kernel / of_device . 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/errno.h>
2007-10-18 08:17:42 +04:00
# include <linux/module.h>
2011-06-21 20:59:34 +04:00
# include <linux/amba/bus.h>
2007-05-02 20:38:57 +04:00
# include <linux/device.h>
2010-06-08 17:48:13 +04:00
# include <linux/dma-mapping.h>
2010-06-08 17:48:20 +04:00
# include <linux/slab.h>
2010-06-08 17:48:26 +04:00
# include <linux/of_address.h>
2007-05-02 20:38:57 +04:00
# include <linux/of_device.h>
2010-06-08 17:48:26 +04:00
# include <linux/of_irq.h>
2007-05-02 20:38:57 +04:00
# include <linux/of_platform.h>
2010-06-08 17:48:21 +04:00
# include <linux/platform_device.h>
2011-06-21 20:59:34 +04:00
const struct of_device_id of_default_bus_match_table [ ] = {
{ . compatible = " simple-bus " , } ,
# ifdef CONFIG_ARM_AMBA
{ . compatible = " arm,amba-bus " , } ,
# endif /* CONFIG_ARM_AMBA */
{ } /* Empty terminated list */
} ;
2010-07-23 21:19:35 +04:00
static int of_dev_node_match ( struct device * dev , void * data )
{
return dev - > of_node = = data ;
}
/**
* of_find_device_by_node - Find the platform_device associated with a node
* @ np : Pointer to device tree node
*
* Returns platform_device pointer , or NULL if not found
*/
struct platform_device * of_find_device_by_node ( struct device_node * np )
{
struct device * dev ;
dev = bus_find_device ( & platform_bus_type , NULL , np , of_dev_node_match ) ;
return dev ? to_platform_device ( dev ) : NULL ;
}
EXPORT_SYMBOL ( of_find_device_by_node ) ;
2012-02-25 01:58:34 +04:00
# ifdef CONFIG_OF_ADDRESS
2010-06-08 17:48:13 +04:00
/*
* The following routines scan a subtree and registers a device for
* each applicable node .
*
* Note : sparc doesn ' t use these routines because it has a different
* mechanism for creating devices from device tree nodes .
*/
2010-06-08 17:48:14 +04:00
/**
* of_device_make_bus_id - Use the device node data to assign a unique name
* @ dev : pointer to device structure that is linked to a device tree node
*
2014-05-21 10:40:31 +04:00
* This routine will first try using the translated bus address to
* derive a unique name . If it cannot , then it will prepend names from
* parent nodes until a unique name can be derived .
2010-06-08 17:48:14 +04:00
*/
2010-07-24 01:04:01 +04:00
void of_device_make_bus_id ( struct device * dev )
2010-06-08 17:48:14 +04:00
{
struct device_node * node = dev - > of_node ;
2012-10-09 04:42:11 +04:00
const __be32 * reg ;
2010-06-08 17:48:14 +04:00
u64 addr ;
2014-05-21 10:40:31 +04:00
/* Construct the name, using parent nodes if necessary to ensure uniqueness */
while ( node - > parent ) {
/*
* If the address can be translated , then that is as much
* uniqueness as we need . Make it the first component and return
*/
reg = of_get_property ( node , " reg " , NULL ) ;
if ( reg & & ( addr = of_translate_address ( node , reg ) ) ! = OF_BAD_ADDR ) {
dev_set_name ( dev , dev_name ( dev ) ? " %llx.%s:%s " : " %llx.%s " ,
( unsigned long long ) addr , node - > name ,
dev_name ( dev ) ) ;
2010-06-08 17:48:14 +04:00
return ;
}
2014-05-21 10:40:31 +04:00
/* format arguments only used if dev_name() resolves to NULL */
dev_set_name ( dev , dev_name ( dev ) ? " %s:%s " : " %s " ,
strrchr ( node - > full_name , ' / ' ) + 1 , dev_name ( dev ) ) ;
node = node - > parent ;
}
2010-06-08 17:48:14 +04:00
}
/**
* of_device_alloc - Allocate and initialize an of_device
* @ np : device node to assign to device
* @ bus_id : Name to assign to the device . May be null to use default name .
* @ parent : Parent device .
*/
2010-07-22 23:59:23 +04:00
struct platform_device * of_device_alloc ( struct device_node * np ,
2010-06-08 17:48:14 +04:00
const char * bus_id ,
struct device * parent )
{
2010-07-22 23:59:23 +04:00
struct platform_device * dev ;
2010-10-11 07:35:05 +04:00
int rc , i , num_reg = 0 , num_irq ;
2010-06-08 17:48:15 +04:00
struct resource * res , temp_res ;
2010-10-20 21:45:13 +04:00
dev = platform_device_alloc ( " " , - 1 ) ;
if ( ! dev )
return NULL ;
/* count the io and irq resources */
2014-05-08 00:23:56 +04:00
while ( of_address_to_resource ( np , num_reg , & temp_res ) = = 0 )
num_reg + + ;
2010-10-11 07:35:05 +04:00
num_irq = of_irq_count ( np ) ;
2010-06-08 17:48:15 +04:00
/* Populate the resource table */
if ( num_irq | | num_reg ) {
2010-10-20 21:45:13 +04:00
res = kzalloc ( sizeof ( * res ) * ( num_irq + num_reg ) , GFP_KERNEL ) ;
if ( ! res ) {
platform_device_put ( dev ) ;
return NULL ;
}
2010-06-08 17:48:15 +04:00
dev - > num_resources = num_reg + num_irq ;
dev - > resource = res ;
for ( i = 0 ; i < num_reg ; i + + , res + + ) {
rc = of_address_to_resource ( np , i , res ) ;
WARN_ON ( rc ) ;
}
2014-04-24 02:57:41 +04:00
if ( of_irq_to_resource_table ( np , res , num_irq ) ! = num_irq )
pr_debug ( " not all legacy IRQ resources mapped for %s \n " ,
np - > name ) ;
2010-06-08 17:48:15 +04:00
}
2010-06-08 17:48:14 +04:00
dev - > dev . of_node = of_node_get ( np ) ;
dev - > dev . parent = parent ;
if ( bus_id )
dev_set_name ( & dev - > dev , " %s " , bus_id ) ;
else
of_device_make_bus_id ( & dev - > dev ) ;
return dev ;
}
EXPORT_SYMBOL ( of_device_alloc ) ;
2014-04-24 19:30:04 +04:00
/**
* of_dma_configure - Setup DMA configuration
* @ dev : Device to apply DMA configuration
*
* Try to get devices ' s DMA configuration from DT and update it
* accordingly .
*
* In case if platform code need to use own special DMA configuration , it
* can use Platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE event
* to fix up DMA configuration .
*/
static void of_dma_configure ( struct platform_device * pdev )
{
u64 dma_addr , paddr , size ;
int ret ;
struct device * dev = & pdev - > dev ;
/*
* Set default dma - mask to 32 bit . Drivers are expected to setup
* the correct supported dma_mask .
*/
dev - > coherent_dma_mask = DMA_BIT_MASK ( 32 ) ;
/*
* Set it to coherent_dma_mask by default if the architecture
* code has not set it .
*/
if ( ! dev - > dma_mask )
dev - > dma_mask = & dev - > coherent_dma_mask ;
/*
* if dma - coherent property exist , call arch hook to setup
* dma coherent operations .
*/
if ( of_dma_is_coherent ( dev - > of_node ) ) {
set_arch_dma_coherent_ops ( dev ) ;
dev_dbg ( dev , " device is dma coherent \n " ) ;
}
/*
* if dma - ranges property doesn ' t exist - just return else
* setup the dma offset
*/
ret = of_dma_get_range ( dev - > of_node , & dma_addr , & paddr , & size ) ;
if ( ret < 0 ) {
dev_dbg ( dev , " no dma range information to setup \n " ) ;
return ;
}
/* DMA ranges found. Calculate and set dma_pfn_offset */
dev - > dma_pfn_offset = PFN_DOWN ( paddr - dma_addr ) ;
dev_dbg ( dev , " dma_pfn_offset(%#08lx) \n " , dev - > dma_pfn_offset ) ;
}
2010-06-08 17:48:13 +04:00
/**
2011-06-21 20:59:35 +04:00
* of_platform_device_create_pdata - Alloc , initialize and register an of_device
2010-06-08 17:48:13 +04:00
* @ np : pointer to node to create device for
* @ bus_id : name to assign device
2011-06-21 20:59:35 +04:00
* @ platform_data : pointer to populate platform_data pointer with
2010-06-08 17:48:13 +04:00
* @ parent : Linux device model parent device .
2011-01-04 01:51:11 +03:00
*
* Returns pointer to created platform device , or NULL if a device was not
* registered . Unavailable devices will not get registered .
2010-06-08 17:48:13 +04:00
*/
2013-07-01 23:26:52 +04:00
static struct platform_device * of_platform_device_create_pdata (
2011-06-21 20:59:35 +04:00
struct device_node * np ,
const char * bus_id ,
void * platform_data ,
struct device * parent )
2010-06-08 17:48:13 +04:00
{
2010-07-22 23:59:23 +04:00
struct platform_device * dev ;
2010-06-08 17:48:13 +04:00
2014-05-15 19:55:24 +04:00
if ( ! of_device_is_available ( np ) | |
of_node_test_and_set_flag ( np , OF_POPULATED ) )
2011-01-04 01:51:11 +03:00
return NULL ;
2010-06-08 17:48:13 +04:00
dev = of_device_alloc ( np , bus_id , parent ) ;
if ( ! dev )
2014-05-15 19:55:24 +04:00
goto err_clear_flag ;
2010-06-08 17:48:13 +04:00
2014-04-24 19:30:04 +04:00
of_dma_configure ( dev ) ;
2010-06-08 17:48:21 +04:00
dev - > dev . bus = & platform_bus_type ;
2011-06-21 20:59:35 +04:00
dev - > dev . platform_data = platform_data ;
2010-06-08 17:48:13 +04:00
/* We do not fill the DMA ops for platform devices by default.
* This is currently the responsibility of the platform code
* to do such , possibly using a device notifier
*/
2010-10-20 21:45:13 +04:00
if ( of_device_add ( dev ) ! = 0 ) {
platform_device_put ( dev ) ;
2014-05-15 19:55:24 +04:00
goto err_clear_flag ;
2010-06-08 17:48:13 +04:00
}
return dev ;
2014-05-15 19:55:24 +04:00
err_clear_flag :
of_node_clear_flag ( np , OF_POPULATED ) ;
return NULL ;
2010-06-08 17:48:13 +04:00
}
2011-06-21 20:59:35 +04:00
/**
* of_platform_device_create - Alloc , initialize and register an of_device
* @ np : pointer to node to create device for
* @ bus_id : name to assign device
* @ parent : Linux device model parent device .
*
* Returns pointer to created platform device , or NULL if a device was not
* registered . Unavailable devices will not get registered .
*/
struct platform_device * of_platform_device_create ( struct device_node * np ,
const char * bus_id ,
struct device * parent )
{
return of_platform_device_create_pdata ( np , bus_id , NULL , parent ) ;
}
2010-06-08 17:48:13 +04:00
EXPORT_SYMBOL ( of_platform_device_create ) ;
2011-06-21 20:59:34 +04:00
# ifdef CONFIG_ARM_AMBA
static struct amba_device * of_amba_device_create ( struct device_node * node ,
const char * bus_id ,
void * platform_data ,
struct device * parent )
{
struct amba_device * dev ;
const void * prop ;
int i , ret ;
pr_debug ( " Creating amba device %s \n " , node - > full_name ) ;
2014-05-15 19:55:24 +04:00
if ( ! of_device_is_available ( node ) | |
of_node_test_and_set_flag ( node , OF_POPULATED ) )
2011-06-21 20:59:34 +04:00
return NULL ;
2011-12-18 15:45:17 +04:00
dev = amba_device_alloc ( NULL , 0 , 0 ) ;
2013-08-30 15:17:29 +04:00
if ( ! dev ) {
pr_err ( " %s(): amba_device_alloc() failed for %s \n " ,
__func__ , node - > full_name ) ;
2014-05-15 19:55:24 +04:00
goto err_clear_flag ;
2013-08-30 15:17:29 +04:00
}
2011-06-21 20:59:34 +04:00
/* setup generic device info */
dev - > dev . coherent_dma_mask = ~ 0 ;
dev - > dev . of_node = of_node_get ( node ) ;
dev - > dev . parent = parent ;
dev - > dev . platform_data = platform_data ;
if ( bus_id )
dev_set_name ( & dev - > dev , " %s " , bus_id ) ;
else
of_device_make_bus_id ( & dev - > dev ) ;
/* Allow the HW Peripheral ID to be overridden */
prop = of_get_property ( node , " arm,primecell-periphid " , NULL ) ;
if ( prop )
dev - > periphid = of_read_ulong ( prop , 1 ) ;
/* Decode the IRQs and address ranges */
for ( i = 0 ; i < AMBA_NR_IRQS ; i + + )
dev - > irq [ i ] = irq_of_parse_and_map ( node , i ) ;
ret = of_address_to_resource ( node , 0 , & dev - > res ) ;
2013-08-30 15:17:29 +04:00
if ( ret ) {
pr_err ( " %s(): of_address_to_resource() failed (%d) for %s \n " ,
__func__ , ret , node - > full_name ) ;
2011-06-21 20:59:34 +04:00
goto err_free ;
2013-08-30 15:17:29 +04:00
}
2011-06-21 20:59:34 +04:00
2011-12-18 15:45:17 +04:00
ret = amba_device_add ( dev , & iomem_resource ) ;
2013-08-30 15:17:29 +04:00
if ( ret ) {
pr_err ( " %s(): amba_device_add() failed (%d) for %s \n " ,
__func__ , ret , node - > full_name ) ;
2011-06-21 20:59:34 +04:00
goto err_free ;
2013-08-30 15:17:29 +04:00
}
2011-06-21 20:59:34 +04:00
return dev ;
err_free :
2011-12-18 15:45:17 +04:00
amba_device_put ( dev ) ;
2014-05-15 19:55:24 +04:00
err_clear_flag :
of_node_clear_flag ( node , OF_POPULATED ) ;
2011-06-21 20:59:34 +04:00
return NULL ;
}
# else /* CONFIG_ARM_AMBA */
static struct amba_device * of_amba_device_create ( struct device_node * node ,
const char * bus_id ,
void * platform_data ,
struct device * parent )
{
return NULL ;
}
# endif /* CONFIG_ARM_AMBA */
2011-06-21 20:59:35 +04:00
/**
* of_devname_lookup ( ) - Given a device node , lookup the preferred Linux name
*/
static const struct of_dev_auxdata * of_dev_lookup ( const struct of_dev_auxdata * lookup ,
struct device_node * np )
{
struct resource res ;
2011-11-03 09:07:29 +04:00
if ( ! lookup )
return NULL ;
2011-12-12 20:26:00 +04:00
for ( ; lookup - > compatible ! = NULL ; lookup + + ) {
2011-11-03 09:07:29 +04:00
if ( ! of_device_is_compatible ( np , lookup - > compatible ) )
continue ;
2012-07-05 18:15:36 +04:00
if ( ! of_address_to_resource ( np , 0 , & res ) )
if ( res . start ! = lookup - > phys_addr )
continue ;
2011-11-03 09:07:29 +04:00
pr_debug ( " %s: devname=%s \n " , np - > full_name , lookup - > name ) ;
return lookup ;
2011-06-21 20:59:35 +04:00
}
2011-11-03 09:07:29 +04:00
2011-06-21 20:59:35 +04:00
return NULL ;
}
2010-06-08 17:48:13 +04:00
/**
2011-03-18 19:21:28 +03:00
* of_platform_bus_create ( ) - Create a device for a node and its children .
2010-06-08 17:48:13 +04:00
* @ bus : device node of the bus to instantiate
2011-03-18 19:21:29 +03:00
* @ matches : match table for bus nodes
2011-11-03 09:07:29 +04:00
* @ lookup : auxdata table for matching id and platform_data with device nodes
2011-03-18 19:21:28 +03:00
* @ parent : parent for new device , or NULL for top level .
2011-11-03 09:07:29 +04:00
* @ strict : require compatible property
2011-03-18 19:21:28 +03:00
*
* Creates a platform_device for the provided device_node , and optionally
* recursively create devices for all the child nodes .
2010-06-08 17:48:13 +04:00
*/
2011-03-18 19:21:28 +03:00
static int of_platform_bus_create ( struct device_node * bus ,
2010-06-08 17:48:13 +04:00
const struct of_device_id * matches ,
2011-06-21 20:59:35 +04:00
const struct of_dev_auxdata * lookup ,
2011-06-21 20:59:34 +04:00
struct device * parent , bool strict )
2010-06-08 17:48:13 +04:00
{
2011-06-21 20:59:35 +04:00
const struct of_dev_auxdata * auxdata ;
2010-06-08 17:48:13 +04:00
struct device_node * child ;
2010-07-22 23:59:23 +04:00
struct platform_device * dev ;
2011-06-21 20:59:35 +04:00
const char * bus_id = NULL ;
void * platform_data = NULL ;
2010-06-08 17:48:13 +04:00
int rc = 0 ;
2011-06-21 20:59:34 +04:00
/* Make sure it has a compatible property */
if ( strict & & ( ! of_get_property ( bus , " compatible " , NULL ) ) ) {
pr_debug ( " %s() - skipping %s, no compatible prop \n " ,
__func__ , bus - > full_name ) ;
return 0 ;
}
2011-06-21 20:59:35 +04:00
auxdata = of_dev_lookup ( lookup , bus ) ;
if ( auxdata ) {
bus_id = auxdata - > name ;
platform_data = auxdata - > platform_data ;
}
2011-06-21 20:59:34 +04:00
if ( of_device_is_compatible ( bus , " arm,primecell " ) ) {
2013-08-30 15:17:29 +04:00
/*
* Don ' t return an error here to keep compatibility with older
* device tree files .
*/
2011-06-21 20:59:35 +04:00
of_amba_device_create ( bus , bus_id , platform_data , parent ) ;
2011-06-21 20:59:34 +04:00
return 0 ;
}
2011-06-21 20:59:35 +04:00
dev = of_platform_device_create_pdata ( bus , bus_id , platform_data , parent ) ;
2011-03-18 19:21:28 +03:00
if ( ! dev | | ! of_match_node ( matches , bus ) )
return 0 ;
2010-06-08 17:48:13 +04:00
for_each_child_of_node ( bus , child ) {
pr_debug ( " create child: %s \n " , child - > full_name ) ;
2011-06-21 20:59:35 +04:00
rc = of_platform_bus_create ( child , matches , lookup , & dev - > dev , strict ) ;
2010-06-08 17:48:13 +04:00
if ( rc ) {
of_node_put ( child ) ;
break ;
}
}
2014-06-24 19:13:47 +04:00
of_node_set_flag ( bus , OF_POPULATED_BUS ) ;
2010-06-08 17:48:13 +04:00
return rc ;
}
/**
2011-03-18 19:21:28 +03:00
* of_platform_bus_probe ( ) - Probe the device - tree for platform buses
2010-06-08 17:48:13 +04:00
* @ root : parent of the first level to probe or NULL for the root of the tree
2011-03-18 19:21:29 +03:00
* @ matches : match table for bus nodes
2010-06-08 17:48:13 +04:00
* @ parent : parent to hook devices from , NULL for toplevel
*
* Note that children of the provided root are not instantiated as devices
* unless the specified root itself matches the bus list and is not NULL .
*/
int of_platform_bus_probe ( struct device_node * root ,
const struct of_device_id * matches ,
struct device * parent )
{
struct device_node * child ;
int rc = 0 ;
2011-03-18 19:21:29 +03:00
root = root ? of_node_get ( root ) : of_find_node_by_path ( " / " ) ;
if ( ! root )
2010-06-08 17:48:25 +04:00
return - EINVAL ;
2010-06-08 17:48:13 +04:00
pr_debug ( " of_platform_bus_probe() \n " ) ;
pr_debug ( " starting at: %s \n " , root - > full_name ) ;
2011-03-18 19:21:29 +03:00
/* Do a self check of bus type, if there's a match, create children */
2010-06-08 17:48:13 +04:00
if ( of_match_node ( matches , root ) ) {
2011-06-21 20:59:35 +04:00
rc = of_platform_bus_create ( root , matches , NULL , parent , false ) ;
2011-03-18 19:21:28 +03:00
} else for_each_child_of_node ( root , child ) {
2010-06-08 17:48:13 +04:00
if ( ! of_match_node ( matches , child ) )
continue ;
2011-06-21 20:59:35 +04:00
rc = of_platform_bus_create ( child , matches , NULL , parent , false ) ;
2011-03-18 19:21:28 +03:00
if ( rc )
2010-06-08 17:48:13 +04:00
break ;
}
2011-03-18 19:21:28 +03:00
2010-06-08 17:48:13 +04:00
of_node_put ( root ) ;
return rc ;
}
EXPORT_SYMBOL ( of_platform_bus_probe ) ;
2011-06-21 20:59:34 +04:00
/**
* of_platform_populate ( ) - Populate platform_devices from device tree data
* @ root : parent of the first level to probe or NULL for the root of the tree
* @ matches : match table , NULL to use the default
2012-11-23 20:25:08 +04:00
* @ lookup : auxdata table for matching id and platform_data with device nodes
2011-06-21 20:59:34 +04:00
* @ parent : parent to hook devices from , NULL for toplevel
*
* Similar to of_platform_bus_probe ( ) , this function walks the device tree
* and creates devices from nodes . It differs in that it follows the modern
* convention of requiring all device nodes to have a ' compatible ' property ,
* and it is suitable for creating devices which are children of the root
* node ( of_platform_bus_probe will only create children of the root which
* are selected by the @ matches argument ) .
*
* New board support should be using this function instead of
* of_platform_bus_probe ( ) .
*
* Returns 0 on success , < 0 on failure .
*/
int of_platform_populate ( struct device_node * root ,
const struct of_device_id * matches ,
2011-06-21 20:59:35 +04:00
const struct of_dev_auxdata * lookup ,
2011-06-21 20:59:34 +04:00
struct device * parent )
{
struct device_node * child ;
int rc = 0 ;
root = root ? of_node_get ( root ) : of_find_node_by_path ( " / " ) ;
if ( ! root )
return - EINVAL ;
for_each_child_of_node ( root , child ) {
2011-06-21 20:59:35 +04:00
rc = of_platform_bus_create ( child , matches , lookup , parent , true ) ;
2011-06-21 20:59:34 +04:00
if ( rc )
break ;
}
of_node_put ( root ) ;
return rc ;
}
2012-06-08 03:57:36 +04:00
EXPORT_SYMBOL_GPL ( of_platform_populate ) ;
2014-05-15 19:55:24 +04:00
static int of_platform_device_destroy ( struct device * dev , void * data )
{
/* Do not touch devices not populated from the device tree */
2014-06-24 19:13:47 +04:00
if ( ! dev - > of_node | | ! of_node_check_flag ( dev - > of_node , OF_POPULATED ) )
2014-05-15 19:55:24 +04:00
return 0 ;
2014-06-24 19:13:47 +04:00
/* Recurse for any nodes that were treated as busses */
if ( of_node_check_flag ( dev - > of_node , OF_POPULATED_BUS ) )
device_for_each_child ( dev , NULL , of_platform_device_destroy ) ;
2014-05-15 19:55:24 +04:00
if ( dev - > bus = = & platform_bus_type )
platform_device_unregister ( to_platform_device ( dev ) ) ;
# ifdef CONFIG_ARM_AMBA
else if ( dev - > bus = = & amba_bustype )
amba_device_unregister ( to_amba_device ( dev ) ) ;
# endif
of_node_clear_flag ( dev - > of_node , OF_POPULATED ) ;
2014-06-24 19:13:47 +04:00
of_node_clear_flag ( dev - > of_node , OF_POPULATED_BUS ) ;
2014-05-15 19:55:24 +04:00
return 0 ;
}
/**
* of_platform_depopulate ( ) - Remove devices populated from device tree
2014-06-24 19:13:47 +04:00
* @ parent : device which children will be removed
2014-05-15 19:55:24 +04:00
*
* Complementary to of_platform_populate ( ) , this function removes children
* of the given device ( and , recurrently , their children ) that have been
* created from their respective device tree nodes ( and only those ,
* leaving others - eg . manually created - unharmed ) .
*
* Returns 0 when all children devices have been removed or
* - EBUSY when some children remained .
*/
2014-06-24 19:13:47 +04:00
void of_platform_depopulate ( struct device * parent )
2014-05-15 19:55:24 +04:00
{
2014-06-24 19:13:47 +04:00
device_for_each_child ( parent , NULL , of_platform_device_destroy ) ;
2014-05-15 19:55:24 +04:00
}
EXPORT_SYMBOL_GPL ( of_platform_depopulate ) ;
2012-02-25 01:58:34 +04:00
# endif /* CONFIG_OF_ADDRESS */