Commit 44d745fb authored by Bjorn Helgaas's avatar Bjorn Helgaas

Merge branch 'pci/irq-fixups' into next

* pci/irq-fixups:
  arm64: PCI: Drop DT IRQ allocation from pcibios_alloc_irq()
  PCI: xilinx-nwl: Move to struct pci_host_bridge IRQ mapping functions
  PCI: rockchip: Move to struct pci_host_bridge IRQ mapping functions
  PCI: xgene: Move to struct pci_host_bridge IRQ mapping functions
  PCI: altera: Drop pci_fixup_irqs()
  PCI: versatile: Drop pci_fixup_irqs()
  PCI: generic: Drop pci_fixup_irqs()
  PCI: faraday: Drop pci_fixup_irqs()
  PCI: designware: Drop pci_fixup_irqs()
  PCI: iproc: Drop pci_fixup_irqs()
  PCI: rcar: Drop pci_fixup_irqs()
  PCI: xilinx: Drop pci_fixup_irqs()
  PCI: tegra: Drop pci_fixup_irqs()
  ARM/PCI: Remove pci_fixup_irqs() call for bios32 host controllers
  PCI: Add a call to pci_assign_irq() in pci_device_probe()
  OF/PCI: Update of_irq_parse_and_map_pci() comment
  PCI: Add pci_assign_irq() function and have pci_fixup_irqs() use it
  PCI: Add IRQ mapping function pointers to pci_host_bridge struct
  PCI: Build setup-irq.o on all arches
  PCI: Remove pci_scan_root_bus_msi()
  PCI: xilinx-nwl: Convert PCI scan API to pci_scan_root_bus_bridge()
  PCI: rockchip: Convert PCI scan API to pci_scan_root_bus_bridge()
  PCI: generic: Convert PCI scan API to pci_scan_root_bus_bridge()
  PCI: xgene: Convert PCI scan API to pci_scan_root_bus_bridge()
  PCI: xilinx: Convert PCI scan API to pci_scan_root_bus_bridge()
  PCI: altera: Convert PCI scan API to pci_scan_root_bus_bridge()
  PCI: versatile: Convert PCI scan API to pci_scan_root_bus_bridge()
  PCI: iproc: Convert PCI scan API to pci_scan_root_bus_bridge()
  PCI: rcar: Convert PCI scan API to pci_scan_root_bus_bridge()
  PCI: aardvark: Convert PCI scan API to pci_scan_root_bus_bridge()
  PCI: designware: Convert PCI scan API to pci_scan_root_bus_bridge()
  ARM/PCI: Convert PCI scan API to pci_scan_root_bus_bridge()
  PCI: Make pci_register_host_bridge() PCI core internal
  PCI: Add pci_scan_root_bus_bridge() interface
  PCI: tegra: Fix host bridge memory leakage
  PCI: faraday: Fix host bridge memory leakage
  PCI: Add devm_pci_alloc_host_bridge() interface
  PCI: Add pci_free_host_bridge() interface
  PCI: Initialize bridge release function at bridge allocation
  PCI: faraday: Convert IRQ masking to raw PCI config accessors
  PCI: iproc: Convert link check to raw PCI config accessors
  PCI: xilinx-nwl: Remove nwl_pcie_enable_msi() unused bus parameter
parents bb02ce95 769b461f
...@@ -342,6 +342,7 @@ PER-CPU MEM ...@@ -342,6 +342,7 @@ PER-CPU MEM
devm_free_percpu() devm_free_percpu()
PCI PCI
devm_pci_alloc_host_bridge() : managed PCI host bridge allocation
devm_pci_remap_cfgspace() : ioremap PCI configuration space devm_pci_remap_cfgspace() : ioremap PCI configuration space
devm_pci_remap_cfg_resource() : ioremap PCI configuration space resource devm_pci_remap_cfg_resource() : ioremap PCI configuration space resource
pcim_enable_device() : after success, all PCI ops become managed pcim_enable_device() : after success, all PCI ops become managed
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
struct pci_sys_data; struct pci_sys_data;
struct pci_ops; struct pci_ops;
struct pci_bus; struct pci_bus;
struct pci_host_bridge;
struct device; struct device;
struct hw_pci { struct hw_pci {
...@@ -25,7 +26,7 @@ struct hw_pci { ...@@ -25,7 +26,7 @@ struct hw_pci {
unsigned int io_optional:1; unsigned int io_optional:1;
void **private_data; void **private_data;
int (*setup)(int nr, struct pci_sys_data *); int (*setup)(int nr, struct pci_sys_data *);
struct pci_bus *(*scan)(int nr, struct pci_sys_data *); int (*scan)(int nr, struct pci_host_bridge *);
void (*preinit)(void); void (*preinit)(void);
void (*postinit)(void); void (*postinit)(void);
u8 (*swizzle)(struct pci_dev *dev, u8 *pin); u8 (*swizzle)(struct pci_dev *dev, u8 *pin);
......
...@@ -458,10 +458,14 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw, ...@@ -458,10 +458,14 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
int nr, busnr; int nr, busnr;
for (nr = busnr = 0; nr < hw->nr_controllers; nr++) { for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL); struct pci_host_bridge *bridge;
if (WARN(!sys, "PCI: unable to allocate sys data!"))
bridge = pci_alloc_host_bridge(sizeof(struct pci_sys_data));
if (WARN(!bridge, "PCI: unable to allocate bridge!"))
break; break;
sys = pci_host_bridge_priv(bridge);
sys->busnr = busnr; sys->busnr = busnr;
sys->swizzle = hw->swizzle; sys->swizzle = hw->swizzle;
sys->map_irq = hw->map_irq; sys->map_irq = hw->map_irq;
...@@ -473,7 +477,6 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw, ...@@ -473,7 +477,6 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
ret = hw->setup(nr, sys); ret = hw->setup(nr, sys);
if (ret > 0) { if (ret > 0) {
struct pci_host_bridge *host_bridge;
ret = pcibios_init_resource(nr, sys, hw->io_optional); ret = pcibios_init_resource(nr, sys, hw->io_optional);
if (ret) { if (ret) {
...@@ -481,26 +484,37 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw, ...@@ -481,26 +484,37 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
break; break;
} }
bridge->map_irq = pcibios_map_irq;
bridge->swizzle_irq = pcibios_swizzle;
if (hw->scan) if (hw->scan)
sys->bus = hw->scan(nr, sys); ret = hw->scan(nr, bridge);
else else {
sys->bus = pci_scan_root_bus_msi(parent, list_splice_init(&sys->resources,
sys->busnr, hw->ops, sys, &bridge->windows);
&sys->resources, hw->msi_ctrl); bridge->dev.parent = parent;
bridge->sysdata = sys;
bridge->busnr = sys->busnr;
bridge->ops = hw->ops;
bridge->msi = hw->msi_ctrl;
bridge->align_resource =
hw->align_resource;
ret = pci_scan_root_bus_bridge(bridge);
}
if (WARN(!sys->bus, "PCI: unable to scan bus!")) { if (WARN(ret < 0, "PCI: unable to scan bus!")) {
kfree(sys); pci_free_host_bridge(bridge);
break; break;
} }
sys->bus = bridge->bus;
busnr = sys->bus->busn_res.end + 1; busnr = sys->bus->busn_res.end + 1;
list_add(&sys->node, head); list_add(&sys->node, head);
host_bridge = pci_find_host_bridge(sys->bus);
host_bridge->align_resource = hw->align_resource;
} else { } else {
kfree(sys); pci_free_host_bridge(bridge);
if (ret < 0) if (ret < 0)
break; break;
} }
...@@ -519,8 +533,6 @@ void pci_common_init_dev(struct device *parent, struct hw_pci *hw) ...@@ -519,8 +533,6 @@ void pci_common_init_dev(struct device *parent, struct hw_pci *hw)
if (hw->postinit) if (hw->postinit)
hw->postinit(); hw->postinit();
pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
list_for_each_entry(sys, &head, node) { list_for_each_entry(sys, &head, node) {
struct pci_bus *bus = sys->bus; struct pci_bus *bus = sys->bus;
......
...@@ -152,16 +152,23 @@ static void rc_pci_fixup(struct pci_dev *dev) ...@@ -152,16 +152,23 @@ static void rc_pci_fixup(struct pci_dev *dev)
} }
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
static struct pci_bus __init * static int __init
dove_pcie_scan_bus(int nr, struct pci_sys_data *sys) dove_pcie_scan_bus(int nr, struct pci_host_bridge *bridge)
{ {
struct pci_sys_data *sys = pci_host_bridge_priv(bridge);
if (nr >= num_pcie_ports) { if (nr >= num_pcie_ports) {
BUG(); BUG();
return NULL; return -EINVAL;
} }
return pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys, list_splice_init(&sys->resources, &bridge->windows);
&sys->resources); bridge->dev.parent = NULL;
bridge->sysdata = sys;
bridge->busnr = sys->busnr;
bridge->ops = &pcie_ops;
return pci_scan_root_bus_bridge(bridge);
} }
static int __init dove_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) static int __init dove_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
......
...@@ -504,10 +504,10 @@ iop13xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs) ...@@ -504,10 +504,10 @@ iop13xx_pci_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
/* Scan an IOP13XX PCI bus. nr selects which ATU we use. /* Scan an IOP13XX PCI bus. nr selects which ATU we use.
*/ */
struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys) int iop13xx_scan_bus(int nr, struct pci_host_bridge *bridge)
{ {
int which_atu; int which_atu, ret;
struct pci_bus *bus = NULL; struct pci_sys_data *sys = pci_host_bridge_priv(bridge);
switch (init_atu) { switch (init_atu) {
case IOP13XX_INIT_ATU_ATUX: case IOP13XX_INIT_ATU_ATUX:
...@@ -525,9 +525,14 @@ struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys) ...@@ -525,9 +525,14 @@ struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys)
if (!which_atu) { if (!which_atu) {
BUG(); BUG();
return NULL; return -ENODEV;
} }
list_splice_init(&sys->resources, &bridge->windows);
bridge->dev.parent = NULL;
bridge->sysdata = sys;
bridge->busnr = sys->busnr;
switch (which_atu) { switch (which_atu) {
case IOP13XX_INIT_ATU_ATUX: case IOP13XX_INIT_ATU_ATUX:
if (time_after_eq(jiffies + msecs_to_jiffies(1000), if (time_after_eq(jiffies + msecs_to_jiffies(1000),
...@@ -535,18 +540,22 @@ struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys) ...@@ -535,18 +540,22 @@ struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *sys)
while(time_before(jiffies, atux_trhfa_timeout)) while(time_before(jiffies, atux_trhfa_timeout))
udelay(100); udelay(100);
bus = pci_bus_atux = pci_scan_root_bus(NULL, sys->busnr, bridge->ops = &iop13xx_atux_ops;
&iop13xx_atux_ops, ret = pci_scan_root_bus_bridge(bridge);
sys, &sys->resources); if (!ret)
pci_bus_atux = bridge->bus;
break; break;
case IOP13XX_INIT_ATU_ATUE: case IOP13XX_INIT_ATU_ATUE:
bus = pci_bus_atue = pci_scan_root_bus(NULL, sys->busnr, bridge->ops = &iop13xx_atue_ops;
&iop13xx_atue_ops, ret = pci_scan_root_bus_bridge(bridge);
sys, &sys->resources); if (!ret)
pci_bus_atue = bridge->bus;
break; break;
default:
ret = -EINVAL;
} }
return bus; return ret;
} }
/* This function is called from iop13xx_pci_init() after assigning valid /* This function is called from iop13xx_pci_init() after assigning valid
......
...@@ -11,9 +11,10 @@ extern size_t iop13xx_atue_mem_size; ...@@ -11,9 +11,10 @@ extern size_t iop13xx_atue_mem_size;
extern size_t iop13xx_atux_mem_size; extern size_t iop13xx_atux_mem_size;
struct pci_sys_data; struct pci_sys_data;
struct pci_host_bridge;
struct hw_pci; struct hw_pci;
int iop13xx_pci_setup(int nr, struct pci_sys_data *sys); int iop13xx_pci_setup(int nr, struct pci_sys_data *sys);
struct pci_bus *iop13xx_scan_bus(int nr, struct pci_sys_data *); int iop13xx_scan_bus(int nr, struct pci_host_bridge *bridge);
void iop13xx_atu_select(struct hw_pci *plat_pci); void iop13xx_atu_select(struct hw_pci *plat_pci);
void iop13xx_pci_init(void); void iop13xx_pci_init(void);
void iop13xx_map_pci_memory(void); void iop13xx_map_pci_memory(void);
......
...@@ -194,16 +194,22 @@ static void rc_pci_fixup(struct pci_dev *dev) ...@@ -194,16 +194,22 @@ static void rc_pci_fixup(struct pci_dev *dev)
} }
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
static struct pci_bus __init * static int __init mv78xx0_pcie_scan_bus(int nr, struct pci_host_bridge *bridge)
mv78xx0_pcie_scan_bus(int nr, struct pci_sys_data *sys)
{ {
struct pci_sys_data *sys = pci_host_bridge_priv(bridge);
if (nr >= num_pcie_ports) { if (nr >= num_pcie_ports) {
BUG(); BUG();
return NULL; return -EINVAL;
} }
return pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys, list_splice_init(&sys->resources, &bridge->windows);
&sys->resources); bridge->dev.parent = NULL;
bridge->sysdata = sys;
bridge->busnr = sys->busnr;
bridge->ops = &pcie_ops;
return pci_scan_root_bus_bridge(bridge);
} }
static int __init mv78xx0_pcie_map_irq(const struct pci_dev *dev, u8 slot, static int __init mv78xx0_pcie_map_irq(const struct pci_dev *dev, u8 slot,
......
...@@ -54,6 +54,7 @@ void orion5x_restart(enum reboot_mode, const char *); ...@@ -54,6 +54,7 @@ void orion5x_restart(enum reboot_mode, const char *);
* PCIe/PCI functions. * PCIe/PCI functions.
*/ */
struct pci_bus; struct pci_bus;
struct pci_host_bridge;
struct pci_sys_data; struct pci_sys_data;
struct pci_dev; struct pci_dev;
...@@ -61,7 +62,7 @@ void orion5x_pcie_id(u32 *dev, u32 *rev); ...@@ -61,7 +62,7 @@ void orion5x_pcie_id(u32 *dev, u32 *rev);
void orion5x_pci_disable(void); void orion5x_pci_disable(void);
void orion5x_pci_set_cardbus_mode(void); void orion5x_pci_set_cardbus_mode(void);
int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys); int orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys);
struct pci_bus *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys); int orion5x_pci_sys_scan_bus(int nr, struct pci_host_bridge *bridge);
int orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin); int orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin);
struct tag; struct tag;
......
...@@ -555,18 +555,27 @@ int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys) ...@@ -555,18 +555,27 @@ int __init orion5x_pci_sys_setup(int nr, struct pci_sys_data *sys)
return 0; return 0;
} }
struct pci_bus __init *orion5x_pci_sys_scan_bus(int nr, struct pci_sys_data *sys) int __init orion5x_pci_sys_scan_bus(int nr, struct pci_host_bridge *bridge)
{ {
if (nr == 0) struct pci_sys_data *sys = pci_host_bridge_priv(bridge);
return pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
&sys->resources);
if (nr == 1 && !orion5x_pci_disabled) list_splice_init(&sys->resources, &bridge->windows);
return pci_scan_root_bus(NULL, sys->busnr, &pci_ops, sys, bridge->dev.parent = NULL;
&sys->resources); bridge->sysdata = sys;
bridge->busnr = sys->busnr;
if (nr == 0) {
bridge->ops = &pcie_ops;
return pci_scan_root_bus_bridge(bridge);
}
if (nr == 1 && !orion5x_pci_disabled) {
bridge->ops = &pci_ops;
return pci_scan_root_bus_bridge(bridge);
}
BUG(); BUG();
return NULL; return -ENODEV;
} }
int __init orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) int __init orion5x_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
......
...@@ -39,20 +39,18 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res, ...@@ -39,20 +39,18 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
return res->start; return res->start;
} }
#ifdef CONFIG_ACPI
/* /*
* Try to assign the IRQ number when probing a new device * Try to assign the IRQ number when probing a new device
*/ */
int pcibios_alloc_irq(struct pci_dev *dev) int pcibios_alloc_irq(struct pci_dev *dev)
{ {
if (acpi_disabled) if (!acpi_disabled)
dev->irq = of_irq_parse_and_map_pci(dev, 0, 0); acpi_pci_irq_enable(dev);
#ifdef CONFIG_ACPI
else
return acpi_pci_irq_enable(dev);
#endif
return 0; return 0;
} }
#endif
/* /*
* raw_pci_read/write - Platform-specific PCI config space access. * raw_pci_read/write - Platform-specific PCI config space access.
......
...@@ -113,7 +113,8 @@ EXPORT_SYMBOL_GPL(of_irq_parse_pci); ...@@ -113,7 +113,8 @@ EXPORT_SYMBOL_GPL(of_irq_parse_pci);
* @pin: PCI irq pin number; passed when used as map_irq callback. Unused * @pin: PCI irq pin number; passed when used as map_irq callback. Unused
* *
* @slot and @pin are unused, but included in the function so that this * @slot and @pin are unused, but included in the function so that this
* function can be used directly as the map_irq callback to pci_fixup_irqs(). * function can be used directly as the map_irq callback to
* pci_assign_irq() and struct pci_host_bridge.map_irq pointer
*/ */
int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin) int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
{ {
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
obj-y += access.o bus.o probe.o host-bridge.o remove.o pci.o \ obj-y += access.o bus.o probe.o host-bridge.o remove.o pci.o \
pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \ pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
irq.o vpd.o setup-bus.o vc.o mmap.o irq.o vpd.o setup-bus.o vc.o mmap.o setup-irq.o
obj-$(CONFIG_PROC_FS) += proc.o obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_SYSFS) += slot.o obj-$(CONFIG_SYSFS) += slot.o
...@@ -28,20 +29,6 @@ obj-$(CONFIG_HT_IRQ) += htirq.o ...@@ -28,20 +29,6 @@ obj-$(CONFIG_HT_IRQ) += htirq.o
obj-$(CONFIG_PCI_ATS) += ats.o obj-$(CONFIG_PCI_ATS) += ats.o
obj-$(CONFIG_PCI_IOV) += iov.o obj-$(CONFIG_PCI_IOV) += iov.o
#
# Some architectures use the generic PCI setup functions
#
obj-$(CONFIG_ALPHA) += setup-irq.o
obj-$(CONFIG_ARC) += setup-irq.o
obj-$(CONFIG_ARM) += setup-irq.o
obj-$(CONFIG_ARM64) += setup-irq.o
obj-$(CONFIG_UNICORE32) += setup-irq.o
obj-$(CONFIG_SUPERH) += setup-irq.o
obj-$(CONFIG_MIPS) += setup-irq.o
obj-$(CONFIG_TILE) += setup-irq.o
obj-$(CONFIG_SPARC_LEON) += setup-irq.o
obj-$(CONFIG_M68K) += setup-irq.o
# #
# ACPI Related PCI FW Functions # ACPI Related PCI FW Functions
# ACPI _DSM provided firmware instance and string name # ACPI _DSM provided firmware instance and string name
......
...@@ -280,9 +280,9 @@ int dw_pcie_host_init(struct pcie_port *pp) ...@@ -280,9 +280,9 @@ int dw_pcie_host_init(struct pcie_port *pp)
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
struct pci_bus *bus, *child; struct pci_bus *bus, *child;
struct pci_host_bridge *bridge;
struct resource *cfg_res; struct resource *cfg_res;
int i, ret; int i, ret;
LIST_HEAD(res);
struct resource_entry *win, *tmp; struct resource_entry *win, *tmp;
cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config"); cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
...@@ -295,16 +295,21 @@ int dw_pcie_host_init(struct pcie_port *pp) ...@@ -295,16 +295,21 @@ int dw_pcie_host_init(struct pcie_port *pp)
dev_err(dev, "missing *config* reg space\n"); dev_err(dev, "missing *config* reg space\n");
} }
ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base); bridge = pci_alloc_host_bridge(0);
if (!bridge)
return -ENOMEM;
ret = of_pci_get_host_bridge_resources(np, 0, 0xff,
&bridge->windows, &pp->io_base);
if (ret) if (ret)
return ret; return ret;
ret = devm_request_pci_bus_resources(dev, &res); ret = devm_request_pci_bus_resources(dev, &bridge->windows);
if (ret) if (ret)
goto error; goto error;
/* Get the I/O and memory ranges from DT */ /* Get the I/O and memory ranges from DT */
resource_list_for_each_entry_safe(win, tmp, &res) { resource_list_for_each_entry_safe(win, tmp, &bridge->windows) {
switch (resource_type(win->res)) { switch (resource_type(win->res)) {
case IORESOURCE_IO: case IORESOURCE_IO:
ret = pci_remap_iospace(win->res, pp->io_base); ret = pci_remap_iospace(win->res, pp->io_base);
...@@ -400,27 +405,27 @@ int dw_pcie_host_init(struct pcie_port *pp) ...@@ -400,27 +405,27 @@ int dw_pcie_host_init(struct pcie_port *pp)
pp->ops->host_init(pp); pp->ops->host_init(pp);
pp->root_bus_nr = pp->busn->start; pp->root_bus_nr = pp->busn->start;
bridge->dev.parent = dev;
bridge->sysdata = pp;
bridge->busnr = pp->root_bus_nr;
bridge->ops = &dw_pcie_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
if (IS_ENABLED(CONFIG_PCI_MSI)) { if (IS_ENABLED(CONFIG_PCI_MSI)) {
bus = pci_scan_root_bus_msi(dev, pp->root_bus_nr, bridge->msi = &dw_pcie_msi_chip;
&dw_pcie_ops, pp, &res,
&dw_pcie_msi_chip);
dw_pcie_msi_chip.dev = dev; dw_pcie_msi_chip.dev = dev;
} else
bus = pci_scan_root_bus(dev, pp->root_bus_nr, &dw_pcie_ops,
pp, &res);
if (!bus) {
ret = -ENOMEM;
goto error;
} }
ret = pci_scan_root_bus_bridge(bridge);
if (ret)
goto error;
bus = bridge->bus;
if (pp->ops->scan_bus) if (pp->ops->scan_bus)
pp->ops->scan_bus(pp); pp->ops->scan_bus(pp);
#ifdef CONFIG_ARM
/* support old dtbs that incorrectly describe IRQs */
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
#endif
pci_bus_size_bridges(bus); pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus); pci_bus_assign_resources(bus);
...@@ -431,7 +436,7 @@ int dw_pcie_host_init(struct pcie_port *pp) ...@@ -431,7 +436,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
return 0; return 0;
error: error:
pci_free_resource_list(&res); pci_free_host_bridge(bridge);
return ret; return ret;
} }
......
...@@ -886,12 +886,14 @@ static int advk_pcie_probe(struct platform_device *pdev) ...@@ -886,12 +886,14 @@ static int advk_pcie_probe(struct platform_device *pdev)
struct advk_pcie *pcie; struct advk_pcie *pcie;
struct resource *res; struct resource *res;
struct pci_bus *bus, *child; struct pci_bus *bus, *child;
struct pci_host_bridge *bridge;
int ret, irq; int ret, irq;
pcie = devm_kzalloc(dev, sizeof(struct advk_pcie), GFP_KERNEL); bridge = devm_pci_alloc_host_bridge(dev, sizeof(struct advk_pcie));
if (!pcie) if (!bridge)
return -ENOMEM; return -ENOMEM;
pcie = pci_host_bridge_priv(bridge);
pcie->pdev = pdev; pcie->pdev = pdev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
...@@ -929,14 +931,21 @@ static int advk_pcie_probe(struct platform_device *pdev) ...@@ -929,14 +931,21 @@ static int advk_pcie_probe(struct platform_device *pdev)
return ret; return ret;
} }
bus = pci_scan_root_bus(dev, 0, &advk_pcie_ops, list_splice_init(&pcie->resources, &bridge->windows);
pcie, &pcie->resources); bridge->dev.parent = dev;
if (!bus) { bridge->sysdata = pcie;
bridge->busnr = 0;
bridge->ops = &advk_pcie_ops;
ret = pci_scan_root_bus_bridge(bridge);
if (ret < 0) {
advk_pcie_remove_msi_irq_domain(pcie); advk_pcie_remove_msi_irq_domain(pcie);
advk_pcie_remove_irq_domain(pcie); advk_pcie_remove_irq_domain(pcie);
return -ENOMEM; return ret;
} }
bus = bridge->bus;
pci_bus_assign_resources(bus); pci_bus_assign_resources(bus);
list_for_each_entry(child, &bus->children, node) list_for_each_entry(child, &bus->children, node)
......
...@@ -178,12 +178,11 @@ static int faraday_res_to_memcfg(resource_size_t mem_base, ...@@ -178,12 +178,11 @@ static int faraday_res_to_memcfg(resource_size_t mem_base,
return 0; return 0;
} }
static int faraday_pci_read_config(struct pci_bus *bus, unsigned int fn, static int faraday_raw_pci_read_config(struct faraday_pci *p, int bus_number,
int config, int size, u32 *value) unsigned int fn, int config, int size,
u32 *value)
{ {
struct faraday_pci *p = bus->sysdata; writel(PCI_CONF_BUS(bus_number) |
writel(PCI_CONF_BUS(bus->number) |
PCI_CONF_DEVICE(PCI_SLOT(fn)) | PCI_CONF_DEVICE(PCI_SLOT(fn)) |
PCI_CONF_FUNCTION(PCI_FUNC(fn)) | PCI_CONF_FUNCTION(PCI_FUNC(fn)) |
PCI_CONF_WHERE(config) | PCI_CONF_WHERE(config) |
...@@ -197,24 +196,28 @@ static int faraday_pci_read_config(struct pci_bus *bus, unsigned int fn, ...@@ -197,24 +196,28 @@ static int faraday_pci_read_config(struct pci_bus *bus, unsigned int fn,
else if (size == 2) else if (size == 2)
*value = (*value >> (8 * (config & 3))) & 0xFFFF; *value = (*value >> (8 * (config & 3))) & 0xFFFF;
return PCIBIOS_SUCCESSFUL;
}
static int faraday_pci_read_config(struct pci_bus *bus, unsigned int fn,
int config, int size, u32 *value)
{
struct faraday_pci *p = bus->sysdata;
dev_dbg(&bus->dev, dev_dbg(&bus->dev,
"[read] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n", "[read] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
PCI_SLOT(fn), PCI_FUNC(fn), config, size, *value); PCI_SLOT(fn), PCI_FUNC(fn), config, size, *value);
return PCIBIOS_SUCCESSFUL; return faraday_raw_pci_read_config(p, bus->number, fn, config, size, value);
} }
static int faraday_pci_write_config(struct pci_bus *bus, unsigned int fn, static int faraday_raw_pci_write_config(struct faraday_pci *p, int bus_number,
int config, int size, u32 value) unsigned int fn, int config, int size,
u32 value)
{ {
struct faraday_pci *p = bus->sysdata;
int ret = PCIBIOS_SUCCESSFUL; int ret = PCIBIOS_SUCCESSFUL;
dev_dbg(&bus->dev, writel(PCI_CONF_BUS(bus_number) |
"[write] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
PCI_SLOT(fn), PCI_FUNC(fn), config, size, value);
writel(PCI_CONF_BUS(bus->number) |
PCI_CONF_DEVICE(PCI_SLOT(fn)) | PCI_CONF_DEVICE(PCI_SLOT(fn)) |
PCI_CONF_FUNCTION(PCI_FUNC(fn)) | PCI_CONF_FUNCTION(PCI_FUNC(fn)) |
PCI_CONF_WHERE(config) | PCI_CONF_WHERE(config) |
...@@ -238,6 +241,19 @@ static int faraday_pci_write_config(struct pci_bus *bus, unsigned int fn, ...@@ -238,6 +241,19 @@ static int faraday_pci_write_config(struct pci_bus *bus, unsigned int fn,
return ret; return ret;
} }
static int faraday_pci_write_config(struct pci_bus *bus, unsigned int fn,
int config, int size, u32 value)
{
struct faraday_pci *p = bus->sysdata;
dev_dbg(&bus->dev,
"[write] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
PCI_SLOT(fn), PCI_FUNC(fn), config, size, value);
return faraday_raw_pci_write_config(p, bus->number, fn, config, size,
value);
}
static struct pci_ops faraday_pci_ops = { static struct pci_ops faraday_pci_ops = {
.read = faraday_pci_read_config, .read = faraday_pci_read_config,
.write = faraday_pci_write_config, .write = faraday_pci_write_config,
...@@ -248,10 +264,10 @@ static void faraday_pci_ack_irq(struct irq_data *d) ...@@ -248,10 +264,10 @@ static void faraday_pci_ack_irq(struct irq_data *d)
struct faraday_pci *p = irq_data_get_irq_chip_data(d); struct faraday_pci *p = irq_data_get_irq_chip_data(d);
unsigned int reg; unsigned int reg;
faraday_pci_read_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, &reg); faraday_raw_pci_read_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, &reg);
reg &= ~(0xF << PCI_CTRL2_INTSTS_SHIFT); reg &= ~(0xF << PCI_CTRL2_INTSTS_SHIFT);
reg |= BIT(irqd_to_hwirq(d) + PCI_CTRL2_INTSTS_SHIFT); reg |= BIT(irqd_to_hwirq(d) + PCI_CTRL2_INTSTS_SHIFT);
faraday_pci_write_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, reg); faraday_raw_pci_write_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, reg);
} }
static void faraday_pci_mask_irq(struct irq_data *d) static void faraday_pci_mask_irq(struct irq_data *d)
...@@ -259,10 +275,10 @@ static void faraday_pci_mask_irq(struct irq_data *d) ...@@ -259,10 +275,10 @@ static void faraday_pci_mask_irq(struct irq_data *d)
struct faraday_pci *p = irq_data_get_irq_chip_data(d); struct faraday_pci *p = irq_data_get_irq_chip_data(d);
unsigned int reg; unsigned int reg;
faraday_pci_read_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, &reg); faraday_raw_pci_read_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, &reg);
reg &= ~((0xF << PCI_CTRL2_INTSTS_SHIFT) reg &= ~((0xF << PCI_CTRL2_INTSTS_SHIFT)
| BIT(irqd_to_hwirq(d) + PCI_CTRL2_INTMASK_SHIFT)); | BIT(irqd_to_hwirq(d) + PCI_CTRL2_INTMASK_SHIFT));
faraday_pci_write_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, reg); faraday_raw_pci_write_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, reg);
} }
static void faraday_pci_unmask_irq(struct irq_data *d) static void faraday_pci_unmask_irq(struct irq_data *d)
...@@ -270,10 +286,10 @@ static void faraday_pci_unmask_irq(struct irq_data *d) ...@@ -270,10 +286,10 @@ static void faraday_pci_unmask_irq(struct irq_data *d)
struct faraday_pci *p = irq_data_get_irq_chip_data(d); struct faraday_pci *p = irq_data_get_irq_chip_data(d);
unsigned int reg; unsigned int reg;
faraday_pci_read_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, &reg); faraday_raw_pci_read_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, &reg);
reg &= ~(0xF << PCI_CTRL2_INTSTS_SHIFT); reg &= ~(0xF << PCI_CTRL2_INTSTS_SHIFT);
reg |= BIT(irqd_to_hwirq(d) + PCI_CTRL2_INTMASK_SHIFT); reg |= BIT(irqd_to_hwirq(d) + PCI_CTRL2_INTMASK_SHIFT);
faraday_pci_write_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, reg); faraday_raw_pci_write_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, reg);
} }
static void faraday_pci_irq_handler(struct irq_desc *desc) static void faraday_pci_irq_handler(struct irq_desc *desc)
...@@ -282,7 +298,7 @@ static void faraday_pci_irq_handler(struct irq_desc *desc) ...@@ -282,7 +298,7 @@ static void faraday_pci_irq_handler(struct irq_desc *desc)
struct irq_chip *irqchip = irq_desc_get_chip(desc); struct irq_chip *irqchip = irq_desc_get_chip(desc);
unsigned int irq_stat, reg, i; unsigned int irq_stat, reg, i;
faraday_pci_read_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, &reg); faraday_raw_pci_read_config(p, 0, 0, FARADAY_PCI_CTRL2, 4, &reg);
irq_stat = reg >> PCI_CTRL2_INTSTS_SHIFT; irq_stat = reg >> PCI_CTRL2_INTSTS_SHIFT;
chained_irq_enter(irqchip, desc); chained_irq_enter(irqchip, desc);
...@@ -403,7 +419,7 @@ static int faraday_pci_parse_map_dma_ranges(struct faraday_pci *p, ...@@ -403,7 +419,7 @@ static int faraday_pci_parse_map_dma_ranges(struct faraday_pci *p,
dev_info(dev, "DMA MEM%d BASE: 0x%016llx -> 0x%016llx config %08x\n", dev_info(dev, "DMA MEM%d BASE: 0x%016llx -> 0x%016llx config %08x\n",
i + 1, range.pci_addr, end, val); i + 1, range.pci_addr, end, val);
if (i <= 2) { if (i <= 2) {
faraday_pci_write_config(p->bus, 0, confreg[i], faraday_raw_pci_write_config(p, 0, 0, confreg[i],
4, val); 4, val);
} else { } else {
dev_err(dev, "ignore extraneous dma-range %d\n", i); dev_err(dev, "ignore extraneous dma-range %d\n", i);
...@@ -432,7 +448,7 @@ static int faraday_pci_probe(struct platform_device *pdev) ...@@ -432,7 +448,7 @@ static int faraday_pci_probe(struct platform_device *pdev)
u32 val; u32 val;
LIST_HEAD(res); LIST_HEAD(res);
host = pci_alloc_host_bridge(sizeof(*p)); host = devm_pci_alloc_host_bridge(dev, sizeof(*p));
if (!host) if (!host)
return -ENOMEM; return -ENOMEM;
...@@ -440,6 +456,8 @@ static int faraday_pci_probe(struct platform_device *pdev) ...@@ -440,6 +456,8 @@ static int faraday_pci_probe(struct platform_device *pdev)
host->ops = &faraday_pci_ops; host->ops = &faraday_pci_ops;
host->busnr = 0; host->busnr = 0;
host->msi = NULL; host->msi = NULL;
host->map_irq = of_irq_parse_and_map_pci;
host->swizzle_irq = pci_common_swizzle;
p = pci_host_bridge_priv(host); p = pci_host_bridge_priv(host);
host->sysdata = p; host->sysdata = p;
p->dev = dev; p->dev = dev;
...@@ -496,17 +514,8 @@ static int faraday_pci_probe(struct platform_device *pdev) ...@@ -496,17 +514,8 @@ static int faraday_pci_probe(struct platform_device *pdev)
val |= PCI_COMMAND_MEMORY; val |= PCI_COMMAND_MEMORY;
val |= PCI_COMMAND_MASTER; val |= PCI_COMMAND_MASTER;
writel(val, p->base + PCI_CTRL); writel(val, p->base + PCI_CTRL);
list_splice_init(&res, &host->windows);
ret = pci_register_host_bridge(host);
if (ret) {
dev_err(dev, "failed to register host: %d\n", ret);
return ret;
}
p->bus = host->bus;
/* Mask and clear all interrupts */ /* Mask and clear all interrupts */
faraday_pci_write_config(p->bus, 0, FARADAY_PCI_CTRL2 + 2, 2, 0xF000); faraday_raw_pci_write_config(p, 0, 0, FARADAY_PCI_CTRL2 + 2, 2, 0xF000);
if (variant->cascaded_irq) { if (variant->cascaded_irq) {
ret = faraday_pci_setup_cascaded_irq(p); ret = faraday_pci_setup_cascaded_irq(p);
if (ret) { if (ret) {
...@@ -519,8 +528,14 @@ static int faraday_pci_probe(struct platform_device *pdev) ...@@ -519,8 +528,14 @@ static int faraday_pci_probe(struct platform_device *pdev)
if (ret) if (ret)
return ret; return ret;
pci_scan_child_bus(p->bus); list_splice_init(&res, &host->windows);
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); ret = pci_scan_root_bus_bridge(host);
if (ret) {
dev_err(dev, "failed to scan host: %d\n", ret);
return ret;
}
p->bus = host->bus;
pci_bus_assign_resources(p->bus); pci_bus_assign_resources(p->bus);
pci_bus_add_devices(p->bus); pci_bus_add_devices(p->bus);
pci_free_resource_list(&res); pci_free_resource_list(&res);
......
...@@ -117,8 +117,14 @@ int pci_host_common_probe(struct platform_device *pdev, ...@@ -117,8 +117,14 @@ int pci_host_common_probe(struct platform_device *pdev,
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node; struct device_node *np = dev->of_node;
struct pci_bus *bus, *child; struct pci_bus *bus, *child;
struct pci_host_bridge *bridge;
struct pci_config_window *cfg; struct pci_config_window *cfg;
struct list_head resources; struct list_head resources;
int ret;
bridge = devm_pci_alloc_host_bridge(dev, 0);
if (!bridge)
return -ENOMEM;
type = of_get_property(np, "device_type", NULL); type = of_get_property(np, "device_type", NULL);
if (!type || strcmp(type, "pci")) { if (!type || strcmp(type, "pci")) {
...@@ -138,16 +144,21 @@ int pci_host_common_probe(struct platform_device *pdev, ...@@ -138,16 +144,21 @@ int pci_host_common_probe(struct platform_device *pdev,
if (!pci_has_flag(PCI_PROBE_ONLY)) if (!pci_has_flag(PCI_PROBE_ONLY))
pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
bus = pci_scan_root_bus(dev, cfg->busr.start, &ops->pci_ops, cfg, list_splice_init(&resources, &bridge->windows);
&resources); bridge->dev.parent = dev;
if (!bus) { bridge->sysdata = cfg;
dev_err(dev, "Scanning rootbus failed"); bridge->busnr = cfg->busr.start;
return -ENODEV; bridge->ops = &ops->pci_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
ret = pci_scan_root_bus_bridge(bridge);
if (ret < 0) {
dev_err(dev, "Scanning root bridge failed");
return ret;
} }
#ifdef CONFIG_ARM bus = bridge->bus;
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
#endif
/* /*
* We insert PCI resources into the iomem_resource and * We insert PCI resources into the iomem_resource and
......
...@@ -2238,7 +2238,7 @@ static int tegra_pcie_probe(struct platform_device *pdev) ...@@ -2238,7 +2238,7 @@ static int tegra_pcie_probe(struct platform_device *pdev)
struct pci_bus *child; struct pci_bus *child;
int err; int err;
host = pci_alloc_host_bridge(sizeof(*pcie)); host = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
if (!host) if (!host)
return -ENOMEM; return -ENOMEM;
...@@ -2284,16 +2284,15 @@ static int tegra_pcie_probe(struct platform_device *pdev) ...@@ -2284,16 +2284,15 @@ static int tegra_pcie_probe(struct platform_device *pdev)
host->busnr = pcie->busn.start; host->busnr = pcie->busn.start;
host->dev.parent = &pdev->dev; host->dev.parent = &pdev->dev;
host->ops = &tegra_pcie_ops; host->ops = &tegra_pcie_ops;
host->map_irq = tegra_pcie_map_irq;
host->swizzle_irq = pci_common_swizzle;
err = pci_register_host_bridge(host); err = pci_scan_root_bus_bridge(host);
if (err < 0) { if (err < 0) {
dev_err(dev, "failed to register host: %d\n", err); dev_err(dev, "failed to register host: %d\n", err);
goto disable_msi; goto disable_msi;
} }
pci_scan_child_bus(host->bus);
pci_fixup_irqs(pci_common_swizzle, tegra_pcie_map_irq);
pci_bus_size_bridges(host->bus); pci_bus_size_bridges(host->bus);
pci_bus_assign_resources(host->bus); pci_bus_assign_resources(host->bus);
......
...@@ -125,8 +125,13 @@ static int versatile_pci_probe(struct platform_device *pdev) ...@@ -125,8 +125,13 @@ static int versatile_pci_probe(struct platform_device *pdev)
u32 val; u32 val;
void __iomem *local_pci_cfg_base; void __iomem *local_pci_cfg_base;
struct pci_bus *bus, *child; struct pci_bus *bus, *child;
struct pci_host_bridge *bridge;
LIST_HEAD(pci_res); LIST_HEAD(pci_res);
bridge = devm_pci_alloc_host_bridge(&pdev->dev, 0);
if (!bridge)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
versatile_pci_base = devm_ioremap_resource(&pdev->dev, res); versatile_pci_base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(versatile_pci_base)) if (IS_ERR(versatile_pci_base))
...@@ -199,11 +204,20 @@ static int versatile_pci_probe(struct platform_device *pdev) ...@@ -199,11 +204,20 @@ static int versatile_pci_probe(struct platform_device *pdev)
pci_add_flags(PCI_ENABLE_PROC_DOMAINS); pci_add_flags(PCI_ENABLE_PROC_DOMAINS);
pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC); pci_add_flags(PCI_REASSIGN_ALL_BUS | PCI_REASSIGN_ALL_RSRC);
bus = pci_scan_root_bus(&pdev->dev, 0, &pci_versatile_ops, NULL, &pci_res); list_splice_init(&pci_res, &bridge->windows);
if (!bus) bridge->dev.parent = &pdev->dev;
return -ENOMEM; bridge->sysdata = NULL;
bridge->busnr = 0;
bridge->ops = &pci_versatile_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
ret = pci_scan_root_bus_bridge(bridge);
if (ret < 0)
return ret;
bus = bridge->bus;
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
pci_assign_unassigned_bus_resources(bus); pci_assign_unassigned_bus_resources(bus);
list_for_each_entry(child, &bus->children, node) list_for_each_entry(child, &bus->children, node)
pcie_bus_configure_settings(child); pcie_bus_configure_settings(child);
......
...@@ -636,13 +636,16 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev) ...@@ -636,13 +636,16 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
struct xgene_pcie_port *port; struct xgene_pcie_port *port;
resource_size_t iobase = 0; resource_size_t iobase = 0;
struct pci_bus *bus, *child; struct pci_bus *bus, *child;
struct pci_host_bridge *bridge;
int ret; int ret;
LIST_HEAD(res); LIST_HEAD(res);
port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); bridge = devm_pci_alloc_host_bridge(dev, sizeof(*port));
if (!port) if (!bridge)
return -ENOMEM; return -ENOMEM;
port = pci_host_bridge_priv(bridge);
port->node = of_node_get(dn); port->node = of_node_get(dn);
port->dev = dev; port->dev = dev;
...@@ -670,11 +673,19 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev) ...@@ -670,11 +673,19 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
if (ret) if (ret)
goto error; goto error;
bus = pci_create_root_bus(dev, 0, &xgene_pcie_ops, port, &res); list_splice_init(&res, &bridge->windows);
if (!bus) { bridge->dev.parent = dev;
ret = -ENOMEM; bridge->sysdata = port;
bridge->busnr = 0;
bridge->ops = &xgene_pcie_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
ret = pci_scan_root_bus_bridge(bridge);
if (ret < 0)
goto error; goto error;
}
bus = bridge->bus;
pci_scan_child_bus(bus); pci_scan_child_bus(bus);
pci_assign_unassigned_bus_resources(bus); pci_assign_unassigned_bus_resources(bus);
......
...@@ -579,12 +579,14 @@ static int altera_pcie_probe(struct platform_device *pdev) ...@@ -579,12 +579,14 @@ static int altera_pcie_probe(struct platform_device *pdev)
struct altera_pcie *pcie; struct altera_pcie *pcie;
struct pci_bus *bus; struct pci_bus *bus;
struct pci_bus *child; struct pci_bus *child;
struct pci_host_bridge *bridge;
int ret; int ret;
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
if (!pcie) if (!bridge)
return -ENOMEM; return -ENOMEM;
pcie = pci_host_bridge_priv(bridge);
pcie->pdev = pdev; pcie->pdev = pdev;
ret = altera_pcie_parse_dt(pcie); ret = altera_pcie_parse_dt(pcie);
...@@ -613,12 +615,20 @@ static int altera_pcie_probe(struct platform_device *pdev) ...@@ -613,12 +615,20 @@ static int altera_pcie_probe(struct platform_device *pdev)
cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE);
altera_pcie_host_init(pcie); altera_pcie_host_init(pcie);
bus = pci_scan_root_bus(dev, pcie->root_bus_nr, &altera_pcie_ops, list_splice_init(&pcie->resources, &bridge->windows);
pcie, &pcie->resources); bridge->dev.parent = dev;
if (!bus) bridge->sysdata = pcie;
return -ENOMEM; bridge->busnr = pcie->root_bus_nr;
bridge->ops = &altera_pcie_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
ret = pci_scan_root_bus_bridge(bridge);
if (ret < 0)
return ret;
bus = bridge->bus;
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
pci_assign_unassigned_bus_resources(bus); pci_assign_unassigned_bus_resources(bus);
/* Configure PCI Express setting. */ /* Configure PCI Express setting. */
......
...@@ -45,12 +45,15 @@ static int iproc_pcie_bcma_probe(struct bcma_device *bdev) ...@@ -45,12 +45,15 @@ static int iproc_pcie_bcma_probe(struct bcma_device *bdev)
struct device *dev = &bdev->dev; struct device *dev = &bdev->dev;
struct iproc_pcie *pcie; struct iproc_pcie *pcie;
LIST_HEAD(resources); LIST_HEAD(resources);
struct pci_host_bridge *bridge;
int ret; int ret;
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
if (!pcie) if (!bridge)
return -ENOMEM; return -ENOMEM;
pcie = pci_host_bridge_priv(bridge);
pcie->dev = dev; pcie->dev = dev;
pcie->type = IPROC_PCIE_PAXB_BCMA; pcie->type = IPROC_PCIE_PAXB_BCMA;
......
...@@ -52,12 +52,15 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev) ...@@ -52,12 +52,15 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
struct resource reg; struct resource reg;
resource_size_t iobase = 0; resource_size_t iobase = 0;
LIST_HEAD(resources); LIST_HEAD(resources);
struct pci_host_bridge *bridge;
int ret; int ret;
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
if (!pcie) if (!bridge)
return -ENOMEM; return -ENOMEM;
pcie = pci_host_bridge_priv(bridge);
pcie->dev = dev; pcie->dev = dev;
pcie->type = (enum iproc_pcie_type) of_device_get_match_data(dev); pcie->type = (enum iproc_pcie_type) of_device_get_match_data(dev);
......
...@@ -452,14 +452,13 @@ static inline void iproc_pcie_apb_err_disable(struct pci_bus *bus, ...@@ -452,14 +452,13 @@ static inline void iproc_pcie_apb_err_disable(struct pci_bus *bus,
* Note access to the configuration registers are protected at the higher layer * Note access to the configuration registers are protected at the higher layer
* by 'pci_lock' in drivers/pci/access.c * by 'pci_lock' in drivers/pci/access.c
*/ */
static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus, static void __iomem *iproc_pcie_map_cfg_bus(struct iproc_pcie *pcie,
int busno,
unsigned int devfn, unsigned int devfn,
int where) int where)
{ {
struct iproc_pcie *pcie = iproc_data(bus);
unsigned slot = PCI_SLOT(devfn); unsigned slot = PCI_SLOT(devfn);
unsigned fn = PCI_FUNC(devfn); unsigned fn = PCI_FUNC(devfn);
unsigned busno = bus->number;
u32 val; u32 val;
u16 offset; u16 offset;
...@@ -499,6 +498,58 @@ static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus, ...@@ -499,6 +498,58 @@ static void __iomem *iproc_pcie_map_cfg_bus(struct pci_bus *bus,
return (pcie->base + offset); return (pcie->base + offset);
} }
static void __iomem *iproc_pcie_bus_map_cfg_bus(struct pci_bus *bus,
unsigned int devfn,
int where)
{
return iproc_pcie_map_cfg_bus(iproc_data(bus), bus->number, devfn,
where);
}
static int iproc_pci_raw_config_read32(struct iproc_pcie *pcie,
unsigned int devfn, int where,
int size, u32 *val)
{
void __iomem *addr;
addr = iproc_pcie_map_cfg_bus(pcie, 0, devfn, where & ~0x3);
if (!addr) {
*val = ~0;
return PCIBIOS_DEVICE_NOT_FOUND;
}
*val = readl(addr);
if (size <= 2)
*val = (*val >> (8 * (where & 3))) & ((1 << (size * 8)) - 1);
return PCIBIOS_SUCCESSFUL;
}
static int iproc_pci_raw_config_write32(struct iproc_pcie *pcie,
unsigned int devfn, int where,
int size, u32 val)
{
void __iomem *addr;
u32 mask, tmp;
addr = iproc_pcie_map_cfg_bus(pcie, 0, devfn, where & ~0x3);
if (!addr)
return PCIBIOS_DEVICE_NOT_FOUND;
if (size == 4) {
writel(val, addr);
return PCIBIOS_SUCCESSFUL;
}
mask = ~(((1 << (size * 8)) - 1) << ((where & 0x3) * 8));
tmp = readl(addr) & mask;
tmp |= val << ((where & 0x3) * 8);
writel(tmp, addr);
return PCIBIOS_SUCCESSFUL;
}
static int iproc_pcie_config_read32(struct pci_bus *bus, unsigned int devfn, static int iproc_pcie_config_read32(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val) int where, int size, u32 *val)
{ {
...@@ -524,7 +575,7 @@ static int iproc_pcie_config_write32(struct pci_bus *bus, unsigned int devfn, ...@@ -524,7 +575,7 @@ static int iproc_pcie_config_write32(struct pci_bus *bus, unsigned int devfn,
} }
static struct pci_ops iproc_pcie_ops = { static struct pci_ops iproc_pcie_ops = {
.map_bus = iproc_pcie_map_cfg_bus, .map_bus = iproc_pcie_bus_map_cfg_bus,
.read = iproc_pcie_config_read32, .read = iproc_pcie_config_read32,
.write = iproc_pcie_config_write32, .write = iproc_pcie_config_write32,
}; };
...@@ -556,12 +607,11 @@ static void iproc_pcie_reset(struct iproc_pcie *pcie) ...@@ -556,12 +607,11 @@ static void iproc_pcie_reset(struct iproc_pcie *pcie)
msleep(100); msleep(100);
} }
static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) static int iproc_pcie_check_link(struct iproc_pcie *pcie)
{ {
struct device *dev = pcie->dev; struct device *dev = pcie->dev;
u8 hdr_type; u32 hdr_type, link_ctrl, link_status, class, val;
u32 link_ctrl, class, val; u16 pos = PCI_EXP_CAP;
u16 pos = PCI_EXP_CAP, link_status;
bool link_is_active = false; bool link_is_active = false;
/* /*
...@@ -578,7 +628,7 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) ...@@ -578,7 +628,7 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
} }
/* make sure we are not in EP mode */ /* make sure we are not in EP mode */
pci_bus_read_config_byte(bus, 0, PCI_HEADER_TYPE, &hdr_type); iproc_pci_raw_config_read32(pcie, 0, PCI_HEADER_TYPE, 1, &hdr_type);
if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) { if ((hdr_type & 0x7f) != PCI_HEADER_TYPE_BRIDGE) {
dev_err(dev, "in EP mode, hdr=%#02x\n", hdr_type); dev_err(dev, "in EP mode, hdr=%#02x\n", hdr_type);
return -EFAULT; return -EFAULT;
...@@ -588,13 +638,16 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) ...@@ -588,13 +638,16 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
#define PCI_BRIDGE_CTRL_REG_OFFSET 0x43c #define PCI_BRIDGE_CTRL_REG_OFFSET 0x43c
#define PCI_CLASS_BRIDGE_MASK 0xffff00 #define PCI_CLASS_BRIDGE_MASK 0xffff00
#define PCI_CLASS_BRIDGE_SHIFT 8 #define PCI_CLASS_BRIDGE_SHIFT 8
pci_bus_read_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, &class); iproc_pci_raw_config_read32(pcie, 0, PCI_BRIDGE_CTRL_REG_OFFSET,
4, &class);
class &= ~PCI_CLASS_BRIDGE_MASK; class &= ~PCI_CLASS_BRIDGE_MASK;
class |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT); class |= (PCI_CLASS_BRIDGE_PCI << PCI_CLASS_BRIDGE_SHIFT);
pci_bus_write_config_dword(bus, 0, PCI_BRIDGE_CTRL_REG_OFFSET, class); iproc_pci_raw_config_write32(pcie, 0, PCI_BRIDGE_CTRL_REG_OFFSET,
4, class);
/* check link status to see if link is active */ /* check link status to see if link is active */
pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, &link_status); iproc_pci_raw_config_read32(pcie, 0, pos + PCI_EXP_LNKSTA,
2, &link_status);
if (link_status & PCI_EXP_LNKSTA_NLW) if (link_status & PCI_EXP_LNKSTA_NLW)
link_is_active = true; link_is_active = true;
...@@ -603,20 +656,21 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus) ...@@ -603,20 +656,21 @@ static int iproc_pcie_check_link(struct iproc_pcie *pcie, struct pci_bus *bus)
#define PCI_TARGET_LINK_SPEED_MASK 0xf #define PCI_TARGET_LINK_SPEED_MASK 0xf
#define PCI_TARGET_LINK_SPEED_GEN2 0x2 #define PCI_TARGET_LINK_SPEED_GEN2 0x2
#define PCI_TARGET_LINK_SPEED_GEN1 0x1 #define PCI_TARGET_LINK_SPEED_GEN1 0x1
pci_bus_read_config_dword(bus, 0, iproc_pci_raw_config_read32(pcie, 0,
pos + PCI_EXP_LNKCTL2, pos + PCI_EXP_LNKCTL2, 4,
&link_ctrl); &link_ctrl);
if ((link_ctrl & PCI_TARGET_LINK_SPEED_MASK) == if ((link_ctrl & PCI_TARGET_LINK_SPEED_MASK) ==
PCI_TARGET_LINK_SPEED_GEN2) { PCI_TARGET_LINK_SPEED_GEN2) {
link_ctrl &= ~PCI_TARGET_LINK_SPEED_MASK; link_ctrl &= ~PCI_TARGET_LINK_SPEED_MASK;
link_ctrl |= PCI_TARGET_LINK_SPEED_GEN1; link_ctrl |= PCI_TARGET_LINK_SPEED_GEN1;
pci_bus_write_config_dword(bus, 0, iproc_pci_raw_config_write32(pcie, 0,
pos + PCI_EXP_LNKCTL2, pos + PCI_EXP_LNKCTL2,
link_ctrl); 4, link_ctrl);
msleep(100); msleep(100);
pci_bus_read_config_word(bus, 0, pos + PCI_EXP_LNKSTA, iproc_pci_raw_config_read32(pcie, 0,
&link_status); pos + PCI_EXP_LNKSTA,
2, &link_status);
if (link_status & PCI_EXP_LNKSTA_NLW) if (link_status & PCI_EXP_LNKSTA_NLW)
link_is_active = true; link_is_active = true;
} }
...@@ -1205,7 +1259,8 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) ...@@ -1205,7 +1259,8 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
struct device *dev; struct device *dev;
int ret; int ret;
void *sysdata; void *sysdata;
struct pci_bus *bus, *child; struct pci_bus *child;
struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
dev = pcie->dev; dev = pcie->dev;
...@@ -1252,18 +1307,10 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) ...@@ -1252,18 +1307,10 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
sysdata = pcie; sysdata = pcie;
#endif #endif
bus = pci_create_root_bus(dev, 0, &iproc_pcie_ops, sysdata, res); ret = iproc_pcie_check_link(pcie);
if (!bus) {
dev_err(dev, "unable to create PCI root bus\n");
ret = -ENOMEM;
goto err_power_off_phy;
}
pcie->root_bus = bus;
ret = iproc_pcie_check_link(pcie, bus);
if (ret) { if (ret) {
dev_err(dev, "no PCIe EP device detected\n"); dev_err(dev, "no PCIe EP device detected\n");
goto err_rm_root_bus; goto err_power_off_phy;
} }
iproc_pcie_enable(pcie); iproc_pcie_enable(pcie);
...@@ -1272,23 +1319,31 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res) ...@@ -1272,23 +1319,31 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
if (iproc_pcie_msi_enable(pcie)) if (iproc_pcie_msi_enable(pcie))
dev_info(dev, "not using iProc MSI\n"); dev_info(dev, "not using iProc MSI\n");
pci_scan_child_bus(bus); list_splice_init(res, &host->windows);
pci_assign_unassigned_bus_resources(bus); host->busnr = 0;
host->dev.parent = dev;
host->ops = &iproc_pcie_ops;
host->sysdata = sysdata;
host->map_irq = pcie->map_irq;
host->swizzle_irq = pci_common_swizzle;
ret = pci_scan_root_bus_bridge(host);
if (ret < 0) {
dev_err(dev, "failed to scan host: %d\n", ret);
goto err_power_off_phy;
}
pci_assign_unassigned_bus_resources(host->bus);
if (pcie->map_irq) pcie->root_bus = host->bus;
pci_fixup_irqs(pci_common_swizzle, pcie->map_irq);
list_for_each_entry(child, &bus->children, node) list_for_each_entry(child, &host->bus->children, node)
pcie_bus_configure_settings(child); pcie_bus_configure_settings(child);
pci_bus_add_devices(bus); pci_bus_add_devices(host->bus);
return 0; return 0;
err_rm_root_bus:
pci_stop_root_bus(bus);
pci_remove_root_bus(bus);
err_power_off_phy: err_power_off_phy:
phy_power_off(pcie->phy); phy_power_off(pcie->phy);
err_exit_phy: err_exit_phy:
......
...@@ -450,29 +450,33 @@ static void rcar_pcie_force_speedup(struct rcar_pcie *pcie) ...@@ -450,29 +450,33 @@ static void rcar_pcie_force_speedup(struct rcar_pcie *pcie)
static int rcar_pcie_enable(struct rcar_pcie *pcie) static int rcar_pcie_enable(struct rcar_pcie *pcie)
{ {
struct device *dev = pcie->dev; struct device *dev = pcie->dev;
struct pci_host_bridge *bridge = pci_host_bridge_from_priv(pcie);
struct pci_bus *bus, *child; struct pci_bus *bus, *child;
LIST_HEAD(res); int ret;
/* Try setting 5 GT/s link speed */ /* Try setting 5 GT/s link speed */
rcar_pcie_force_speedup(pcie); rcar_pcie_force_speedup(pcie);
rcar_pcie_setup(&res, pcie); rcar_pcie_setup(&bridge->windows, pcie);
pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS); pci_add_flags(PCI_REASSIGN_ALL_RSRC | PCI_REASSIGN_ALL_BUS);
bridge->dev.parent = dev;
bridge->sysdata = pcie;
bridge->busnr = pcie->root_bus_nr;
bridge->ops = &rcar_pcie_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
if (IS_ENABLED(CONFIG_PCI_MSI)) if (IS_ENABLED(CONFIG_PCI_MSI))
bus = pci_scan_root_bus_msi(dev, pcie->root_bus_nr, bridge->msi = &pcie->msi.chip;
&rcar_pcie_ops, pcie, &res, &pcie->msi.chip);
else
bus = pci_scan_root_bus(dev, pcie->root_bus_nr,
&rcar_pcie_ops, pcie, &res);
if (!bus) { ret = pci_scan_root_bus_bridge(bridge);
dev_err(dev, "Scanning rootbus failed"); if (ret < 0) {
return -ENODEV; kfree(bridge);
return ret;
} }
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci); bus = bridge->bus;
pci_bus_size_bridges(bus); pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus); pci_bus_assign_resources(bus);
...@@ -1127,11 +1131,14 @@ static int rcar_pcie_probe(struct platform_device *pdev) ...@@ -1127,11 +1131,14 @@ static int rcar_pcie_probe(struct platform_device *pdev)
unsigned int data; unsigned int data;
int err; int err;
int (*hw_init_fn)(struct rcar_pcie *); int (*hw_init_fn)(struct rcar_pcie *);
struct pci_host_bridge *bridge;
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); bridge = pci_alloc_host_bridge(sizeof(*pcie));
if (!pcie) if (!bridge)
return -ENOMEM; return -ENOMEM;
pcie = pci_host_bridge_priv(bridge);
pcie->dev = dev; pcie->dev = dev;
INIT_LIST_HEAD(&pcie->resources); INIT_LIST_HEAD(&pcie->resources);
...@@ -1141,12 +1148,12 @@ static int rcar_pcie_probe(struct platform_device *pdev) ...@@ -1141,12 +1148,12 @@ static int rcar_pcie_probe(struct platform_device *pdev)
err = rcar_pcie_get_resources(pcie); err = rcar_pcie_get_resources(pcie);
if (err < 0) { if (err < 0) {
dev_err(dev, "failed to request resources: %d\n", err); dev_err(dev, "failed to request resources: %d\n", err);
return err; goto err_free_bridge;
} }
err = rcar_pcie_parse_map_dma_ranges(pcie, dev->of_node); err = rcar_pcie_parse_map_dma_ranges(pcie, dev->of_node);
if (err) if (err)
return err; goto err_free_bridge;
pm_runtime_enable(dev); pm_runtime_enable(dev);
err = pm_runtime_get_sync(dev); err = pm_runtime_get_sync(dev);
...@@ -1183,6 +1190,9 @@ static int rcar_pcie_probe(struct platform_device *pdev) ...@@ -1183,6 +1190,9 @@ static int rcar_pcie_probe(struct platform_device *pdev)
return 0; return 0;
err_free_bridge:
pci_free_host_bridge(bridge);
err_pm_put: err_pm_put:
pm_runtime_put(dev); pm_runtime_put(dev);
......
...@@ -1284,6 +1284,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev) ...@@ -1284,6 +1284,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
struct rockchip_pcie *rockchip; struct rockchip_pcie *rockchip;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct pci_bus *bus, *child; struct pci_bus *bus, *child;
struct pci_host_bridge *bridge;
struct resource_entry *win; struct resource_entry *win;
resource_size_t io_base; resource_size_t io_base;
struct resource *mem; struct resource *mem;
...@@ -1295,10 +1296,12 @@ static int rockchip_pcie_probe(struct platform_device *pdev) ...@@ -1295,10 +1296,12 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
if (!dev->of_node) if (!dev->of_node)
return -ENODEV; return -ENODEV;
rockchip = devm_kzalloc(dev, sizeof(*rockchip), GFP_KERNEL); bridge = devm_pci_alloc_host_bridge(dev, sizeof(*rockchip));
if (!rockchip) if (!bridge)
return -ENOMEM; return -ENOMEM;
rockchip = pci_host_bridge_priv(bridge);
platform_set_drvdata(pdev, rockchip); platform_set_drvdata(pdev, rockchip);
rockchip->dev = dev; rockchip->dev = dev;
...@@ -1396,11 +1399,20 @@ static int rockchip_pcie_probe(struct platform_device *pdev) ...@@ -1396,11 +1399,20 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
goto err_free_res; goto err_free_res;
} }
bus = pci_scan_root_bus(&pdev->dev, 0, &rockchip_pcie_ops, rockchip, &res); list_splice_init(&res, &bridge->windows);
if (!bus) { bridge->dev.parent = &pdev->dev;
err = -ENOMEM; bridge->sysdata = rockchip;
bridge->busnr = 0;
bridge->ops = &rockchip_pcie_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
err = pci_scan_root_bus_bridge(bridge);
if (!err)
goto err_free_res; goto err_free_res;
}
bus = bridge->bus;
rockchip->root_bus = bus; rockchip->root_bus = bus;
pci_bus_size_bridges(bus); pci_bus_size_bridges(bus);
......
...@@ -530,7 +530,7 @@ static int nwl_pcie_init_irq_domain(struct nwl_pcie *pcie) ...@@ -530,7 +530,7 @@ static int nwl_pcie_init_irq_domain(struct nwl_pcie *pcie)
return 0; return 0;
} }
static int nwl_pcie_enable_msi(struct nwl_pcie *pcie, struct pci_bus *bus) static int nwl_pcie_enable_msi(struct nwl_pcie *pcie)
{ {
struct device *dev = pcie->dev; struct device *dev = pcie->dev;
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
...@@ -791,13 +791,16 @@ static int nwl_pcie_probe(struct platform_device *pdev) ...@@ -791,13 +791,16 @@ static int nwl_pcie_probe(struct platform_device *pdev)
struct nwl_pcie *pcie; struct nwl_pcie *pcie;
struct pci_bus *bus; struct pci_bus *bus;
struct pci_bus *child; struct pci_bus *child;
struct pci_host_bridge *bridge;
int err; int err;
resource_size_t iobase = 0; resource_size_t iobase = 0;
LIST_HEAD(res); LIST_HEAD(res);
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); bridge = devm_pci_alloc_host_bridge(dev, sizeof(*pcie));
if (!pcie) if (!bridge)
return -ENOMEM; return -ENODEV;
pcie = pci_host_bridge_priv(bridge);
pcie->dev = dev; pcie->dev = dev;
pcie->ecam_value = NWL_ECAM_VALUE_DEFAULT; pcie->ecam_value = NWL_ECAM_VALUE_DEFAULT;
...@@ -830,21 +833,28 @@ static int nwl_pcie_probe(struct platform_device *pdev) ...@@ -830,21 +833,28 @@ static int nwl_pcie_probe(struct platform_device *pdev)
goto error; goto error;
} }
bus = pci_create_root_bus(dev, pcie->root_busno, list_splice_init(&res, &bridge->windows);
&nwl_pcie_ops, pcie, &res); bridge->dev.parent = dev;
if (!bus) { bridge->sysdata = pcie;
err = -ENOMEM; bridge->busnr = pcie->root_busno;
goto error; bridge->ops = &nwl_pcie_ops;
} bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
if (IS_ENABLED(CONFIG_PCI_MSI)) { if (IS_ENABLED(CONFIG_PCI_MSI)) {
err = nwl_pcie_enable_msi(pcie, bus); err = nwl_pcie_enable_msi(pcie);
if (err < 0) { if (err < 0) {
dev_err(dev, "failed to enable MSI support: %d\n", err); dev_err(dev, "failed to enable MSI support: %d\n", err);
goto error; goto error;
} }
} }
pci_scan_child_bus(bus);
err = pci_scan_root_bus_bridge(bridge);
if (err)
goto error;
bus = bridge->bus;
pci_assign_unassigned_bus_resources(bus); pci_assign_unassigned_bus_resources(bus);
list_for_each_entry(child, &bus->children, node) list_for_each_entry(child, &bus->children, node)
pcie_bus_configure_settings(child); pcie_bus_configure_settings(child);
......
...@@ -633,6 +633,7 @@ static int xilinx_pcie_probe(struct platform_device *pdev) ...@@ -633,6 +633,7 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct xilinx_pcie_port *port; struct xilinx_pcie_port *port;
struct pci_bus *bus, *child; struct pci_bus *bus, *child;
struct pci_host_bridge *bridge;
int err; int err;
resource_size_t iobase = 0; resource_size_t iobase = 0;
LIST_HEAD(res); LIST_HEAD(res);
...@@ -640,9 +641,11 @@ static int xilinx_pcie_probe(struct platform_device *pdev) ...@@ -640,9 +641,11 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
if (!dev->of_node) if (!dev->of_node)
return -ENODEV; return -ENODEV;
port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL); bridge = devm_pci_alloc_host_bridge(dev, sizeof(*port));
if (!port) if (!bridge)
return -ENOMEM; return -ENODEV;
port = pci_host_bridge_priv(bridge);
port->dev = dev; port->dev = dev;
...@@ -671,21 +674,26 @@ static int xilinx_pcie_probe(struct platform_device *pdev) ...@@ -671,21 +674,26 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
if (err) if (err)
goto error; goto error;
bus = pci_create_root_bus(dev, 0, &xilinx_pcie_ops, port, &res);
if (!bus) { list_splice_init(&res, &bridge->windows);
err = -ENOMEM; bridge->dev.parent = dev;
goto error; bridge->sysdata = port;
} bridge->busnr = 0;
bridge->ops = &xilinx_pcie_ops;
bridge->map_irq = of_irq_parse_and_map_pci;
bridge->swizzle_irq = pci_common_swizzle;
#ifdef CONFIG_PCI_MSI #ifdef CONFIG_PCI_MSI
xilinx_pcie_msi_chip.dev = dev; xilinx_pcie_msi_chip.dev = dev;
bus->msi = &xilinx_pcie_msi_chip; bridge->msi = &xilinx_pcie_msi_chip;
#endif #endif
pci_scan_child_bus(bus); err = pci_scan_root_bus_bridge(bridge);
if (err < 0)
goto error;
bus = bridge->bus;
pci_assign_unassigned_bus_resources(bus); pci_assign_unassigned_bus_resources(bus);
#ifndef CONFIG_MICROBLAZE
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
#endif
list_for_each_entry(child, &bus->children, node) list_for_each_entry(child, &bus->children, node)
pcie_bus_configure_settings(child); pcie_bus_configure_settings(child);
pci_bus_add_devices(bus); pci_bus_add_devices(bus);
......
...@@ -412,6 +412,8 @@ static int pci_device_probe(struct device *dev) ...@@ -412,6 +412,8 @@ static int pci_device_probe(struct device *dev)
struct pci_dev *pci_dev = to_pci_dev(dev); struct pci_dev *pci_dev = to_pci_dev(dev);
struct pci_driver *drv = to_pci_driver(dev->driver); struct pci_driver *drv = to_pci_driver(dev->driver);
pci_assign_irq(pci_dev);
error = pcibios_alloc_irq(pci_dev); error = pcibios_alloc_irq(pci_dev);
if (error < 0) if (error < 0)
return error; return error;
......
...@@ -510,16 +510,18 @@ static struct pci_bus *pci_alloc_bus(struct pci_bus *parent) ...@@ -510,16 +510,18 @@ static struct pci_bus *pci_alloc_bus(struct pci_bus *parent)
return b; return b;
} }
static void pci_release_host_bridge_dev(struct device *dev) static void devm_pci_release_host_bridge_dev(struct device *dev)
{ {
struct pci_host_bridge *bridge = to_pci_host_bridge(dev); struct pci_host_bridge *bridge = to_pci_host_bridge(dev);
if (bridge->release_fn) if (bridge->release_fn)
bridge->release_fn(bridge); bridge->release_fn(bridge);
}
pci_free_resource_list(&bridge->windows); static void pci_release_host_bridge_dev(struct device *dev)
{
kfree(bridge); devm_pci_release_host_bridge_dev(dev);
pci_free_host_bridge(to_pci_host_bridge(dev));
} }
struct pci_host_bridge *pci_alloc_host_bridge(size_t priv) struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
...@@ -531,11 +533,36 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv) ...@@ -531,11 +533,36 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
return NULL; return NULL;
INIT_LIST_HEAD(&bridge->windows); INIT_LIST_HEAD(&bridge->windows);
bridge->dev.release = pci_release_host_bridge_dev;
return bridge; return bridge;
} }
EXPORT_SYMBOL(pci_alloc_host_bridge); EXPORT_SYMBOL(pci_alloc_host_bridge);
struct pci_host_bridge *devm_pci_alloc_host_bridge(struct device *dev,
size_t priv)
{
struct pci_host_bridge *bridge;
bridge = devm_kzalloc(dev, sizeof(*bridge) + priv, GFP_KERNEL);
if (!bridge)
return NULL;
INIT_LIST_HEAD(&bridge->windows);
bridge->dev.release = devm_pci_release_host_bridge_dev;
return bridge;
}
EXPORT_SYMBOL(devm_pci_alloc_host_bridge);
void pci_free_host_bridge(struct pci_host_bridge *bridge)
{
pci_free_resource_list(&bridge->windows);
kfree(bridge);
}
EXPORT_SYMBOL(pci_free_host_bridge);
static const unsigned char pcix_bus_speed[] = { static const unsigned char pcix_bus_speed[] = {
PCI_SPEED_UNKNOWN, /* 0 */ PCI_SPEED_UNKNOWN, /* 0 */
PCI_SPEED_66MHz_PCIX, /* 1 */ PCI_SPEED_66MHz_PCIX, /* 1 */
...@@ -719,7 +746,7 @@ static void pci_set_bus_msi_domain(struct pci_bus *bus) ...@@ -719,7 +746,7 @@ static void pci_set_bus_msi_domain(struct pci_bus *bus)
dev_set_msi_domain(&bus->dev, d); dev_set_msi_domain(&bus->dev, d);
} }
int pci_register_host_bridge(struct pci_host_bridge *bridge) static int pci_register_host_bridge(struct pci_host_bridge *bridge)
{ {
struct device *parent = bridge->dev.parent; struct device *parent = bridge->dev.parent;
struct resource_entry *window, *n; struct resource_entry *window, *n;
...@@ -834,7 +861,6 @@ int pci_register_host_bridge(struct pci_host_bridge *bridge) ...@@ -834,7 +861,6 @@ int pci_register_host_bridge(struct pci_host_bridge *bridge)
kfree(bus); kfree(bus);
return err; return err;
} }
EXPORT_SYMBOL(pci_register_host_bridge);
static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
struct pci_dev *bridge, int busnr) struct pci_dev *bridge, int busnr)
...@@ -2333,9 +2359,8 @@ void __weak pcibios_remove_bus(struct pci_bus *bus) ...@@ -2333,9 +2359,8 @@ void __weak pcibios_remove_bus(struct pci_bus *bus)
{ {
} }
static struct pci_bus *pci_create_root_bus_msi(struct device *parent, struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
int bus, struct pci_ops *ops, void *sysdata, struct pci_ops *ops, void *sysdata, struct list_head *resources)
struct list_head *resources, struct msi_controller *msi)
{ {
int error; int error;
struct pci_host_bridge *bridge; struct pci_host_bridge *bridge;
...@@ -2345,13 +2370,11 @@ static struct pci_bus *pci_create_root_bus_msi(struct device *parent, ...@@ -2345,13 +2370,11 @@ static struct pci_bus *pci_create_root_bus_msi(struct device *parent,
return NULL; return NULL;
bridge->dev.parent = parent; bridge->dev.parent = parent;
bridge->dev.release = pci_release_host_bridge_dev;
list_splice_init(resources, &bridge->windows); list_splice_init(resources, &bridge->windows);
bridge->sysdata = sysdata; bridge->sysdata = sysdata;
bridge->busnr = bus; bridge->busnr = bus;
bridge->ops = ops; bridge->ops = ops;
bridge->msi = msi;
error = pci_register_host_bridge(bridge); error = pci_register_host_bridge(bridge);
if (error < 0) if (error < 0)
...@@ -2363,13 +2386,6 @@ static struct pci_bus *pci_create_root_bus_msi(struct device *parent, ...@@ -2363,13 +2386,6 @@ static struct pci_bus *pci_create_root_bus_msi(struct device *parent,
kfree(bridge); kfree(bridge);
return NULL; return NULL;
} }
struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata, struct list_head *resources)
{
return pci_create_root_bus_msi(parent, bus, ops, sysdata, resources,
NULL);
}
EXPORT_SYMBOL_GPL(pci_create_root_bus); EXPORT_SYMBOL_GPL(pci_create_root_bus);
int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max) int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
...@@ -2435,24 +2451,28 @@ void pci_bus_release_busn_res(struct pci_bus *b) ...@@ -2435,24 +2451,28 @@ void pci_bus_release_busn_res(struct pci_bus *b)
res, ret ? "can not be" : "is"); res, ret ? "can not be" : "is");
} }
struct pci_bus *pci_scan_root_bus_msi(struct device *parent, int bus, int pci_scan_root_bus_bridge(struct pci_host_bridge *bridge)
struct pci_ops *ops, void *sysdata,
struct list_head *resources, struct msi_controller *msi)
{ {
struct resource_entry *window; struct resource_entry *window;
bool found = false; bool found = false;
struct pci_bus *b; struct pci_bus *b;
int max; int max, bus, ret;
resource_list_for_each_entry(window, resources) if (!bridge)
return -EINVAL;
resource_list_for_each_entry(window, &bridge->windows)
if (window->res->flags & IORESOURCE_BUS) { if (window->res->flags & IORESOURCE_BUS) {
found = true; found = true;
break; break;
} }
b = pci_create_root_bus_msi(parent, bus, ops, sysdata, resources, msi); ret = pci_register_host_bridge(bridge);
if (!b) if (ret < 0)
return NULL; return ret;
b = bridge->bus;
bus = bridge->busnr;
if (!found) { if (!found) {
dev_info(&b->dev, dev_info(&b->dev,
...@@ -2466,14 +2486,41 @@ struct pci_bus *pci_scan_root_bus_msi(struct device *parent, int bus, ...@@ -2466,14 +2486,41 @@ struct pci_bus *pci_scan_root_bus_msi(struct device *parent, int bus,
if (!found) if (!found)
pci_bus_update_busn_res_end(b, max); pci_bus_update_busn_res_end(b, max);
return b; return 0;
} }
EXPORT_SYMBOL(pci_scan_root_bus_bridge);
struct pci_bus *pci_scan_root_bus(struct device *parent, int bus, struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata, struct list_head *resources) struct pci_ops *ops, void *sysdata, struct list_head *resources)
{ {
return pci_scan_root_bus_msi(parent, bus, ops, sysdata, resources, struct resource_entry *window;
NULL); bool found = false;
struct pci_bus *b;
int max;
resource_list_for_each_entry(window, resources)
if (window->res->flags & IORESOURCE_BUS) {
found = true;
break;
}
b = pci_create_root_bus(parent, bus, ops, sysdata, resources);
if (!b)
return NULL;
if (!found) {
dev_info(&b->dev,
"No busn resource found for root bus, will use [bus %02x-ff]\n",
bus);
pci_bus_insert_busn_res(b, bus, 255);
}
max = pci_scan_child_bus(b);
if (!found)
pci_bus_update_busn_res_end(b, max);
return b;
} }
EXPORT_SYMBOL(pci_scan_root_bus); EXPORT_SYMBOL(pci_scan_root_bus);
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/cache.h> #include <linux/cache.h>
#include "pci.h"
void __weak pcibios_update_irq(struct pci_dev *dev, int irq) void __weak pcibios_update_irq(struct pci_dev *dev, int irq)
{ {
...@@ -22,12 +23,17 @@ void __weak pcibios_update_irq(struct pci_dev *dev, int irq) ...@@ -22,12 +23,17 @@ void __weak pcibios_update_irq(struct pci_dev *dev, int irq)
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
} }
static void pdev_fixup_irq(struct pci_dev *dev, void pci_assign_irq(struct pci_dev *dev)
u8 (*swizzle)(struct pci_dev *, u8 *),
int (*map_irq)(const struct pci_dev *, u8, u8))
{ {
u8 pin, slot; u8 pin;
u8 slot = -1;
int irq = 0; int irq = 0;
struct pci_host_bridge *hbrg = pci_find_host_bridge(dev->bus);
if (!(hbrg->map_irq)) {
dev_dbg(&dev->dev, "runtime IRQ mapping not provided by arch\n");
return;
}
/* If this device is not on the primary bus, we need to figure out /* If this device is not on the primary bus, we need to figure out
which interrupt pin it will come in on. We know which slot it which interrupt pin it will come in on. We know which slot it
...@@ -40,17 +46,22 @@ static void pdev_fixup_irq(struct pci_dev *dev, ...@@ -40,17 +46,22 @@ static void pdev_fixup_irq(struct pci_dev *dev,
if (pin > 4) if (pin > 4)
pin = 1; pin = 1;
if (pin != 0) { if (pin) {
/* Follow the chain of bridges, swizzling as we go. */ /* Follow the chain of bridges, swizzling as we go. */
slot = (*swizzle)(dev, &pin); if (hbrg->swizzle_irq)
slot = (*(hbrg->swizzle_irq))(dev, &pin);
irq = (*map_irq)(dev, slot, pin); /*
* If a swizzling function is not used map_irq must
* ignore slot
*/
irq = (*(hbrg->map_irq))(dev, slot, pin);
if (irq == -1) if (irq == -1)
irq = 0; irq = 0;
} }
dev->irq = irq; dev->irq = irq;
dev_dbg(&dev->dev, "fixup irq: got %d\n", dev->irq); dev_dbg(&dev->dev, "assign IRQ: got %d\n", dev->irq);
/* Always tell the device, so the driver knows what is /* Always tell the device, so the driver knows what is
the real IRQ to use; the device does not use it. */ the real IRQ to use; the device does not use it. */
...@@ -60,9 +71,23 @@ static void pdev_fixup_irq(struct pci_dev *dev, ...@@ -60,9 +71,23 @@ static void pdev_fixup_irq(struct pci_dev *dev,
void pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *), void pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
int (*map_irq)(const struct pci_dev *, u8, u8)) int (*map_irq)(const struct pci_dev *, u8, u8))
{ {
/*
* Implement pci_fixup_irqs() through pci_assign_irq().
* This code should be remove eventually, it is a wrapper
* around pci_assign_irq() interface to keep current
* pci_fixup_irqs() behaviour unchanged on architecture
* code still relying on its interface.
*/
struct pci_dev *dev = NULL; struct pci_dev *dev = NULL;
struct pci_host_bridge *hbrg = NULL;
for_each_pci_dev(dev) for_each_pci_dev(dev) {
pdev_fixup_irq(dev, swizzle, map_irq); hbrg = pci_find_host_bridge(dev->bus);
hbrg->swizzle_irq = swizzle;
hbrg->map_irq = map_irq;
pci_assign_irq(dev);
hbrg->swizzle_irq = NULL;
hbrg->map_irq = NULL;
}
} }
EXPORT_SYMBOL_GPL(pci_fixup_irqs); EXPORT_SYMBOL_GPL(pci_fixup_irqs);
...@@ -445,6 +445,8 @@ struct pci_host_bridge { ...@@ -445,6 +445,8 @@ struct pci_host_bridge {
void *sysdata; void *sysdata;
int busnr; int busnr;
struct list_head windows; /* resource_entry */ struct list_head windows; /* resource_entry */
u8 (*swizzle_irq)(struct pci_dev *, u8 *); /* platform IRQ swizzler */
int (*map_irq)(const struct pci_dev *, u8, u8);
void (*release_fn)(struct pci_host_bridge *); void (*release_fn)(struct pci_host_bridge *);
void *release_data; void *release_data;
struct msi_controller *msi; struct msi_controller *msi;
...@@ -471,7 +473,9 @@ static inline struct pci_host_bridge *pci_host_bridge_from_priv(void *priv) ...@@ -471,7 +473,9 @@ static inline struct pci_host_bridge *pci_host_bridge_from_priv(void *priv)
} }
struct pci_host_bridge *pci_alloc_host_bridge(size_t priv); struct pci_host_bridge *pci_alloc_host_bridge(size_t priv);
int pci_register_host_bridge(struct pci_host_bridge *bridge); struct pci_host_bridge *devm_pci_alloc_host_bridge(struct device *dev,
size_t priv);
void pci_free_host_bridge(struct pci_host_bridge *bridge);
struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus); struct pci_host_bridge *pci_find_host_bridge(struct pci_bus *bus);
void pci_set_host_bridge_release(struct pci_host_bridge *bridge, void pci_set_host_bridge_release(struct pci_host_bridge *bridge,
...@@ -861,13 +865,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, ...@@ -861,13 +865,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax); int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax); int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
void pci_bus_release_busn_res(struct pci_bus *b); void pci_bus_release_busn_res(struct pci_bus *b);
struct pci_bus *pci_scan_root_bus_msi(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata,
struct list_head *resources,
struct msi_controller *msi);
struct pci_bus *pci_scan_root_bus(struct device *parent, int bus, struct pci_bus *pci_scan_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata, struct pci_ops *ops, void *sysdata,
struct list_head *resources); struct list_head *resources);
int pci_scan_root_bus_bridge(struct pci_host_bridge *bridge);
struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
int busnr); int busnr);
void pcie_update_link_speed(struct pci_bus *bus, u16 link_status); void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
...@@ -1168,6 +1169,7 @@ void pdev_enable_device(struct pci_dev *); ...@@ -1168,6 +1169,7 @@ void pdev_enable_device(struct pci_dev *);
int pci_enable_resources(struct pci_dev *, int mask); int pci_enable_resources(struct pci_dev *, int mask);
void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
int (*)(const struct pci_dev *, u8, u8)); int (*)(const struct pci_dev *, u8, u8));
void pci_assign_irq(struct pci_dev *dev);
struct resource *pci_find_resource(struct pci_dev *dev, struct resource *res); struct resource *pci_find_resource(struct pci_dev *dev, struct resource *res);
#define HAVE_PCI_REQ_REGIONS 2 #define HAVE_PCI_REQ_REGIONS 2
int __must_check pci_request_regions(struct pci_dev *, const char *); int __must_check pci_request_regions(struct pci_dev *, const char *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment