2006-11-11 09:24:59 +03:00
/*
* Copyright ( C ) 2006 Benjamin Herrenschmidt , IBM Corp .
* < benh @ kernel . crashing . org >
2006-11-11 09:25:08 +03:00
* and Arnd Bergmann , IBM Corp .
2006-11-11 09:24:59 +03: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 09:25:08 +03:00
# include <linux/pci.h>
2008-01-08 22:20:40 +03:00
# include <linux/of.h>
2007-09-21 12:08:17 +04:00
# include <linux/of_device.h>
# include <linux/of_platform.h>
2006-11-11 09:24:59 +03:00
# include <asm/errno.h>
2006-11-11 09:25:02 +03:00
# include <asm/topology.h>
2006-11-11 09:25:08 +03:00
# include <asm/pci-bridge.h>
# include <asm/ppc-pci.h>
2011-07-27 03:09:06 +04:00
# include <linux/atomic.h>
2006-11-21 06:56:37 +03:00
2006-11-11 09:25:08 +03: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 .
*/
2011-02-23 05:59:54 +03:00
static int __devinit of_pci_phb_probe ( struct platform_device * dev )
2006-11-11 09:25:08 +03:00
{
struct pci_controller * phb ;
/* Check if we can do that ... */
if ( ppc_md . pci_setup_phb = = NULL )
return - ENODEV ;
2010-04-14 03:12:29 +04:00
pr_info ( " Setting up PCI bus %s \n " , dev - > dev . of_node - > full_name ) ;
2006-11-11 09:25:08 +03:00
/* Alloc and setup PHB data structure */
2010-04-14 03:12:29 +04:00
phb = pcibios_alloc_controller ( dev - > dev . of_node ) ;
2006-11-11 09:25:08 +03: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-14 03:12:29 +04:00
pci_process_bridge_OF_ranges ( phb , dev - > dev . of_node , 0 ) ;
2006-11-11 09:25:08 +03:00
/* Init pci_dn data structures */
pci_devs_phb_init_dynamic ( phb ) ;
/* Register devices with EEH */
# ifdef CONFIG_EEH
2010-04-14 03:12:29 +04:00
if ( dev - > dev . of_node - > child )
eeh_add_device_tree_early ( dev - > dev . of_node ) ;
2006-11-11 09:25:08 +03:00
# endif /* CONFIG_EEH */
/* Scan the bus */
2011-02-04 21:24:11 +03:00
pcibios_scan_phb ( phb ) ;
2008-04-24 13:21:10 +04:00
if ( phb - > bus = = NULL )
return - ENXIO ;
2006-11-11 09:25:08 +03: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 " , } ,
{ }
} ;
2011-02-23 05:59:54 +03:00
static struct platform_driver of_pci_phb_driver = {
2007-09-21 12:08:17 +04:00
. probe = of_pci_phb_probe ,
. driver = {
. name = " of-pci " ,
2010-04-14 03:13:02 +04:00
. owner = THIS_MODULE ,
. of_match_table = of_pci_phb_ids ,
2007-09-21 12:08:17 +04:00
} ,
2006-11-11 09:25:08 +03:00
} ;
static __init int of_pci_phb_init ( void )
{
2011-02-23 05:59:54 +03:00
return platform_driver_register ( & of_pci_phb_driver ) ;
2006-11-11 09:25:08 +03:00
}
device_initcall ( of_pci_phb_init ) ;
# endif /* CONFIG_PPC_OF_PLATFORM_PCI */