2018-01-26 12:50:27 -06:00
// SPDX-License-Identifier: GPL-2.0
2016-03-11 15:35:55 -06:00
/*
2016-08-22 17:59:48 -04:00
* Generic PCI host driver common code
*
2016-03-11 15:35:55 -06:00
* Copyright ( C ) 2014 ARM Limited
*
* Author : Will Deacon < will . deacon @ arm . com >
*/
# include <linux/kernel.h>
# include <linux/of_address.h>
# include <linux/of_pci.h>
2016-06-10 21:55:09 +02:00
# include <linux/pci-ecam.h>
2016-03-11 15:35:55 -06:00
# include <linux/platform_device.h>
2016-05-11 17:34:46 -05:00
static void gen_pci_unmap_cfg ( void * ptr )
{
pci_ecam_free ( ( struct pci_config_window * ) ptr ) ;
}
static struct pci_config_window * gen_pci_init ( struct device * dev ,
struct list_head * resources , struct pci_ecam_ops * ops )
2016-03-11 15:35:55 -06:00
{
int err ;
2016-05-11 17:34:46 -05:00
struct resource cfgres ;
struct resource * bus_range = NULL ;
struct pci_config_window * cfg ;
2016-03-11 15:35:55 -06:00
2016-05-11 17:34:46 -05:00
/* Parse our PCI ranges and request their resources */
2019-10-30 17:30:57 -05:00
err = pci_parse_request_of_pci_ranges ( dev , resources , NULL , & bus_range ) ;
2016-05-11 17:34:46 -05:00
if ( err )
2018-01-30 21:56:50 +01:00
return ERR_PTR ( err ) ;
2016-05-11 17:34:46 -05:00
err = of_address_to_resource ( dev - > of_node , 0 , & cfgres ) ;
2016-03-11 15:35:55 -06:00
if ( err ) {
dev_err ( dev , " missing \" reg \" property \n " ) ;
2016-05-11 17:34:46 -05:00
goto err_out ;
2016-03-11 15:35:55 -06:00
}
2016-05-11 17:34:46 -05:00
cfg = pci_ecam_create ( dev , & cfgres , bus_range , ops ) ;
if ( IS_ERR ( cfg ) ) {
err = PTR_ERR ( cfg ) ;
goto err_out ;
2016-03-11 15:35:55 -06:00
}
2019-07-08 20:33:54 +08:00
err = devm_add_action_or_reset ( dev , gen_pci_unmap_cfg , cfg ) ;
2016-05-11 17:34:46 -05:00
if ( err ) {
goto err_out ;
}
return cfg ;
err_out :
pci_free_resource_list ( resources ) ;
return ERR_PTR ( err ) ;
2016-03-11 15:35:55 -06:00
}
int pci_host_common_probe ( struct platform_device * pdev ,
2016-05-11 17:34:46 -05:00
struct pci_ecam_ops * ops )
2016-03-11 15:35:55 -06:00
{
struct device * dev = & pdev - > dev ;
2017-06-28 15:14:00 -05:00
struct pci_host_bridge * bridge ;
2016-05-11 17:34:46 -05:00
struct pci_config_window * cfg ;
struct list_head resources ;
2017-06-28 15:14:00 -05:00
int ret ;
bridge = devm_pci_alloc_host_bridge ( dev , 0 ) ;
if ( ! bridge )
return - ENOMEM ;
2016-03-11 15:35:55 -06:00
of_pci_check_probe_only ( ) ;
/* Parse and map our Configuration Space windows */
2016-05-11 17:34:46 -05:00
cfg = gen_pci_init ( dev , & resources , ops ) ;
if ( IS_ERR ( cfg ) )
return PTR_ERR ( cfg ) ;
2016-03-11 15:35:55 -06:00
/* Do not reassign resources if probe only */
if ( ! pci_has_flag ( PCI_PROBE_ONLY ) )
PCI: Remove PCI_REASSIGN_ALL_RSRC use on arm and arm64
On arm, PCI_REASSIGN_ALL_RSRC is used only in pcibios_assign_all_busses(),
which helps decide whether to reconfigure bridge bus numbers. It has
nothing to do with BAR assignments. On arm64 and powerpc,
pcibios_assign_all_busses() tests PCI_REASSIGN_ALL_BUS, which makes more
sense.
Align arm with arm64 and powerpc, so they all use PCI_REASSIGN_ALL_BUS for
pcibios_assign_all_busses().
Remove PCI_REASSIGN_ALL_RSRC from the generic, Tegra, Versatile, and
R-Car drivers. These drivers are used only on arm or arm64, where
PCI_REASSIGN_ALL_RSRC is not used after this change, so removing it
should have no effect.
No functional change intended.
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Reviewed-by: Manikanta Maddireddy <mmaddireddy@nvidia.com>
Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
2017-11-30 11:21:57 -06:00
pci_add_flags ( PCI_REASSIGN_ALL_BUS ) ;
2016-03-11 15:35:55 -06:00
2017-06-28 15:14:00 -05:00
list_splice_init ( & resources , & bridge - > windows ) ;
bridge - > dev . parent = dev ;
bridge - > sysdata = cfg ;
bridge - > busnr = cfg - > busr . start ;
bridge - > ops = & ops - > pci_ops ;
2017-06-28 15:14:09 -05:00
bridge - > map_irq = of_irq_parse_and_map_pci ;
bridge - > swizzle_irq = pci_common_swizzle ;
2017-06-28 15:14:00 -05:00
2018-01-30 21:56:52 +01:00
ret = pci_host_probe ( bridge ) ;
2017-06-28 15:14:00 -05:00
if ( ret < 0 ) {
2018-01-30 21:56:51 +01:00
pci_free_resource_list ( & resources ) ;
2017-06-28 15:14:00 -05:00
return ret ;
2016-03-11 15:35:55 -06:00
}
2018-05-15 11:07:06 +02:00
platform_set_drvdata ( pdev , bridge - > bus ) ;
return 0 ;
}
int pci_host_common_remove ( struct platform_device * pdev )
{
struct pci_bus * bus = platform_get_drvdata ( pdev ) ;
pci_lock_rescan_remove ( ) ;
pci_stop_root_bus ( bus ) ;
pci_remove_root_bus ( bus ) ;
pci_unlock_rescan_remove ( ) ;
2016-03-11 15:35:55 -06:00
return 0 ;
}