2011-04-11 05:37:07 +04:00
/*
* PCI < - > OF mapping helpers
*
* Copyright 2011 IBM Corp .
*
* 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 .
*/
2015-07-28 16:46:12 +03:00
# include <linux/irqdomain.h>
2011-04-11 05:37:07 +04:00
# include <linux/kernel.h>
# include <linux/pci.h>
# include <linux/of.h>
2015-09-18 16:07:40 +03:00
# include <linux/of_irq.h>
2011-04-11 05:37:07 +04:00
# include <linux/of_pci.h>
# include "pci.h"
void pci_set_of_node ( struct pci_dev * dev )
{
if ( ! dev - > bus - > dev . of_node )
return ;
dev - > dev . of_node = of_pci_find_child_device ( dev - > bus - > dev . of_node ,
dev - > devfn ) ;
}
void pci_release_of_node ( struct pci_dev * dev )
{
of_node_put ( dev - > dev . of_node ) ;
dev - > dev . of_node = NULL ;
}
void pci_set_bus_of_node ( struct pci_bus * bus )
{
if ( bus - > self = = NULL )
bus - > dev . of_node = pcibios_get_phb_of_node ( bus ) ;
else
bus - > dev . of_node = of_node_get ( bus - > self - > dev . of_node ) ;
}
void pci_release_bus_of_node ( struct pci_bus * bus )
{
of_node_put ( bus - > dev . of_node ) ;
bus - > dev . of_node = NULL ;
}
struct device_node * __weak pcibios_get_phb_of_node ( struct pci_bus * bus )
{
/* This should only be called for PHBs */
if ( WARN_ON ( bus - > self | | bus - > parent ) )
return NULL ;
/* Look for a node pointer in either the intermediary device we
* create above the root bus or it ' s own parent . Normally only
* the later is populated .
*/
if ( bus - > bridge - > of_node )
return of_node_get ( bus - > bridge - > of_node ) ;
2011-08-16 22:24:37 +04:00
if ( bus - > bridge - > parent & & bus - > bridge - > parent - > of_node )
2011-04-11 05:37:07 +04:00
return of_node_get ( bus - > bridge - > parent - > of_node ) ;
return NULL ;
}
2015-07-28 16:46:12 +03:00
struct irq_domain * pci_host_bridge_of_msi_domain ( struct pci_bus * bus )
{
# ifdef CONFIG_IRQ_DOMAIN
struct irq_domain * d ;
if ( ! bus - > dev . of_node )
return NULL ;
/* Start looking for a phandle to an MSI controller. */
2015-09-18 16:07:40 +03:00
d = of_msi_get_domain ( & bus - > dev , bus - > dev . of_node , DOMAIN_BUS_PCI_MSI ) ;
if ( d )
return d ;
2015-07-28 16:46:13 +03:00
/*
* If we don ' t have an msi - parent property , look for a domain
* directly attached to the host bridge .
*/
2015-09-18 16:07:40 +03:00
d = irq_find_matching_host ( bus - > dev . of_node , DOMAIN_BUS_PCI_MSI ) ;
2015-07-28 16:46:12 +03:00
if ( d )
return d ;
2015-09-18 16:07:40 +03:00
return irq_find_host ( bus - > dev . of_node ) ;
2015-07-28 16:46:12 +03:00
# else
return NULL ;
# endif
}