2011-01-24 09:58:55 +05:30
# include <linux/kernel.h>
2011-05-27 17:06:52 -04:00
# include <linux/export.h>
2011-07-23 23:52:48 -06:00
# include <linux/of.h>
2011-01-24 09:58:55 +05:30
# include <linux/of_pci.h>
# include <asm/prom.h>
2011-04-11 11:37:07 +10:00
static inline int __of_pci_pci_compare ( struct device_node * node ,
2013-05-16 17:55:18 +02:00
unsigned int data )
2011-01-24 09:58:55 +05:30
{
2013-05-16 17:55:18 +02:00
int devfn ;
2011-01-24 09:58:55 +05:30
2013-05-16 17:55:18 +02:00
devfn = of_pci_get_devfn ( node ) ;
if ( devfn < 0 )
2011-04-11 11:37:07 +10:00
return 0 ;
2013-05-16 17:55:18 +02:00
return devfn = = data ;
2011-04-11 11:37:07 +10:00
}
2011-01-24 09:58:55 +05:30
2011-04-11 11:37:07 +10:00
struct device_node * of_pci_find_child_device ( struct device_node * parent ,
unsigned int devfn )
{
struct device_node * node , * node2 ;
for_each_child_of_node ( parent , node ) {
if ( __of_pci_pci_compare ( node , devfn ) )
return node ;
/*
* Some OFs create a parent node " multifunc-device " as
* a fake root for all functions of a multi - function
* device we go down them as well .
2011-01-24 09:58:55 +05:30
*/
2011-04-11 11:37:07 +10:00
if ( ! strcmp ( node - > name , " multifunc-device " ) ) {
for_each_child_of_node ( node , node2 ) {
if ( __of_pci_pci_compare ( node2 , devfn ) ) {
of_node_put ( node ) ;
return node2 ;
}
}
}
2011-01-24 09:58:55 +05:30
}
2011-04-11 11:37:07 +10:00
return NULL ;
2011-01-24 09:58:55 +05:30
}
2011-04-11 11:37:07 +10:00
EXPORT_SYMBOL_GPL ( of_pci_find_child_device ) ;
2013-05-16 17:55:18 +02:00
/**
* of_pci_get_devfn ( ) - Get device and function numbers for a device node
* @ np : device node
*
* Parses a standard 5 - cell PCI resource and returns an 8 - bit value that can
* be passed to the PCI_SLOT ( ) and PCI_FUNC ( ) macros to extract the device
* and function numbers respectively . On error a negative error code is
* returned .
*/
int of_pci_get_devfn ( struct device_node * np )
{
unsigned int size ;
const __be32 * reg ;
reg = of_get_property ( np , " reg " , & size ) ;
if ( ! reg | | size < 5 * sizeof ( __be32 ) )
return - EINVAL ;
return ( be32_to_cpup ( reg ) > > 8 ) & 0xff ;
}
EXPORT_SYMBOL_GPL ( of_pci_get_devfn ) ;