diff options
Diffstat (limited to 'drivers/pci/host/pci-host-generic.c')
| -rw-r--r-- | drivers/pci/host/pci-host-generic.c | 52 | 
1 files changed, 33 insertions, 19 deletions
diff --git a/drivers/pci/host/pci-host-generic.c b/drivers/pci/host/pci-host-generic.c index ba46e581db99..265dd25169bf 100644 --- a/drivers/pci/host/pci-host-generic.c +++ b/drivers/pci/host/pci-host-generic.c @@ -38,7 +38,16 @@ struct gen_pci_cfg_windows {  	const struct gen_pci_cfg_bus_ops	*ops;  }; +/* + * ARM pcibios functions expect the ARM struct pci_sys_data as the PCI + * sysdata.  Add pci_sys_data as the first element in struct gen_pci so + * that when we use a gen_pci pointer as sysdata, it is also a pointer to + * a struct pci_sys_data. + */  struct gen_pci { +#ifdef CONFIG_ARM +	struct pci_sys_data			sys; +#endif  	struct pci_host_bridge			host;  	struct gen_pci_cfg_windows		cfg;  	struct list_head			resources; @@ -48,8 +57,7 @@ static void __iomem *gen_pci_map_cfg_bus_cam(struct pci_bus *bus,  					     unsigned int devfn,  					     int where)  { -	struct pci_sys_data *sys = bus->sysdata; -	struct gen_pci *pci = sys->private_data; +	struct gen_pci *pci = bus->sysdata;  	resource_size_t idx = bus->number - pci->cfg.bus_range->start;  	return pci->cfg.win[idx] + ((devfn << 8) | where); @@ -64,8 +72,7 @@ static void __iomem *gen_pci_map_cfg_bus_ecam(struct pci_bus *bus,  					      unsigned int devfn,  					      int where)  { -	struct pci_sys_data *sys = bus->sysdata; -	struct gen_pci *pci = sys->private_data; +	struct gen_pci *pci = bus->sysdata;  	resource_size_t idx = bus->number - pci->cfg.bus_range->start;  	return pci->cfg.win[idx] + ((devfn << 12) | where); @@ -198,13 +205,6 @@ static int gen_pci_parse_map_cfg_windows(struct gen_pci *pci)  	return 0;  } -static int gen_pci_setup(int nr, struct pci_sys_data *sys) -{ -	struct gen_pci *pci = sys->private_data; -	list_splice_init(&pci->resources, &sys->resources); -	return 1; -} -  static int gen_pci_probe(struct platform_device *pdev)  {  	int err; @@ -214,13 +214,7 @@ static int gen_pci_probe(struct platform_device *pdev)  	struct device *dev = &pdev->dev;  	struct device_node *np = dev->of_node;  	struct gen_pci *pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); -	struct hw_pci hw = { -		.nr_controllers	= 1, -		.private_data	= (void **)&pci, -		.setup		= gen_pci_setup, -		.map_irq	= of_irq_parse_and_map_pci, -		.ops		= &gen_pci_ops, -	}; +	struct pci_bus *bus, *child;  	if (!pci)  		return -ENOMEM; @@ -258,7 +252,27 @@ static int gen_pci_probe(struct platform_device *pdev)  		return err;  	} -	pci_common_init_dev(dev, &hw); +	/* Do not reassign resources if probe only */ +	if (!pci_has_flag(PCI_PROBE_ONLY)) +		pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); + +	bus = pci_scan_root_bus(dev, 0, &gen_pci_ops, pci, &pci->resources); +	if (!bus) { +		dev_err(dev, "Scanning rootbus failed"); +		return -ENODEV; +	} + +	pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); + +	if (!pci_has_flag(PCI_PROBE_ONLY)) { +		pci_bus_size_bridges(bus); +		pci_bus_assign_resources(bus); + +		list_for_each_entry(child, &bus->children, node) +			pcie_bus_configure_settings(child); +	} + +	pci_bus_add_devices(bus);  	return 0;  }  |