2006-11-11 17:24:59 +11:00
/*
* Copyright ( C ) 2006 Benjamin Herrenschmidt , IBM Corp .
* < benh @ kernel . crashing . org >
2006-11-11 17:25:08 +11:00
* and Arnd Bergmann , IBM Corp .
2006-11-11 17:24:59 +11:00
*
* 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 .
*
*/
# undef DEBUG
# include <linux/string.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/module.h>
# include <linux/mod_devicetable.h>
2006-11-11 17:25:08 +11:00
# include <linux/pci.h>
2008-01-09 06:20:40 +11:00
# include <linux/of.h>
2007-09-21 18:08:17 +10:00
# include <linux/of_device.h>
# include <linux/of_platform.h>
2006-11-11 17:24:59 +11:00
# include <asm/errno.h>
2006-11-11 17:25:02 +11:00
# include <asm/topology.h>
2006-11-11 17:25:08 +11:00
# include <asm/pci-bridge.h>
# include <asm/ppc-pci.h>
2006-11-21 14:56:37 +11:00
# include <asm/atomic.h>
2006-11-11 17:25:08 +11:00
# ifdef CONFIG_PPC_OF_PLATFORM_PCI
/* The probing of PCI controllers from of_platform is currently
* 64 bits only , mostly due to gratuitous differences between
* the 32 and 64 bits PCI code on PowerPC and the 32 bits one
* lacking some bits needed here .
*/
2010-07-22 15:52:34 -06:00
static int __devinit of_pci_phb_probe ( struct platform_device * dev ,
2006-11-11 17:25:08 +11:00
const struct of_device_id * match )
{
struct pci_controller * phb ;
/* Check if we can do that ... */
if ( ppc_md . pci_setup_phb = = NULL )
return - ENODEV ;
2010-04-13 16:12:29 -07:00
pr_info ( " Setting up PCI bus %s \n " , dev - > dev . of_node - > full_name ) ;
2006-11-11 17:25:08 +11:00
/* Alloc and setup PHB data structure */
2010-04-13 16:12:29 -07:00
phb = pcibios_alloc_controller ( dev - > dev . of_node ) ;
2006-11-11 17:25:08 +11:00
if ( ! phb )
return - ENODEV ;
/* Setup parent in sysfs */
phb - > parent = & dev - > dev ;
/* Setup the PHB using arch provided callback */
if ( ppc_md . pci_setup_phb ( phb ) ) {
pcibios_free_controller ( phb ) ;
return - ENODEV ;
}
/* Process "ranges" property */
2010-04-13 16:12:29 -07:00
pci_process_bridge_OF_ranges ( phb , dev - > dev . of_node , 0 ) ;
2006-11-11 17:25:08 +11:00
/* Init pci_dn data structures */
pci_devs_phb_init_dynamic ( phb ) ;
/* Register devices with EEH */
# ifdef CONFIG_EEH
2010-04-13 16:12:29 -07:00
if ( dev - > dev . of_node - > child )
eeh_add_device_tree_early ( dev - > dev . of_node ) ;
2006-11-11 17:25:08 +11:00
# endif /* CONFIG_EEH */
/* Scan the bus */
2010-04-13 16:12:29 -07:00
pcibios_scan_phb ( phb , dev - > dev . of_node ) ;
2008-04-24 19:21:10 +10:00
if ( phb - > bus = = NULL )
return - ENXIO ;
2006-11-11 17:25:08 +11:00
/* Claim resources. This might need some rework as well depending
* wether we are doing probe - only or not , like assigning unassigned
* resources etc . . .
*/
pcibios_claim_one_bus ( phb - > bus ) ;
/* Finish EEH setup */
# ifdef CONFIG_EEH
eeh_add_device_tree_late ( phb - > bus ) ;
# endif
/* Add probed PCI devices to the device model */
pci_bus_add_devices ( phb - > bus ) ;
return 0 ;
}
static struct of_device_id of_pci_phb_ids [ ] = {
{ . type = " pci " , } ,
{ . type = " pcix " , } ,
{ . type = " pcie " , } ,
{ . type = " pciex " , } ,
{ . type = " ht " , } ,
{ }
} ;
static struct of_platform_driver of_pci_phb_driver = {
2007-09-21 18:08:17 +10:00
. probe = of_pci_phb_probe ,
. driver = {
. name = " of-pci " ,
2010-04-13 16:13:02 -07:00
. owner = THIS_MODULE ,
. of_match_table = of_pci_phb_ids ,
2007-09-21 18:08:17 +10:00
} ,
2006-11-11 17:25:08 +11:00
} ;
static __init int of_pci_phb_init ( void )
{
return of_register_platform_driver ( & of_pci_phb_driver ) ;
}
device_initcall ( of_pci_phb_init ) ;
# endif /* CONFIG_PPC_OF_PLATFORM_PCI */