1
0
Fork 0

Merge branches 'pci/demodularize-hosts' and 'pci/host-request-windows' into next

* pci/demodularize-hosts:
  PCI: xgene: Make explicitly non-modular
  PCI: thunder-pem: Make explicitly non-modular
  PCI: thunder-ecam: Make explicitly non-modular
  PCI: tegra: Make explicitly non-modular
  PCI: rcar-gen2: Make explicitly non-modular
  PCI: rcar: Make explicitly non-modular
  PCI: mvebu: Make explicitly non-modular
  PCI: layerscape: Make explicitly non-modular
  PCI: keystone: Make explicitly non-modular
  PCI: hisi: Make explicitly non-modular
  PCI: generic: Make explicitly non-modular
  PCI: designware-plat: Make it explicitly non-modular
  PCI: artpec6: Make explicitly non-modular
  PCI: armada8k: Make explicitly non-modular
  PCI: artpec: Add PCI_MSI_IRQ_DOMAIN dependency
  PCI: artpec: Add Axis ARTPEC-6 PCIe controller driver
  PCI: Add DT binding for Axis ARTPEC-6 PCIe controller
  PCI: generic: Select IRQ_DOMAIN

* pci/host-request-windows:
  PCI: versatile: Simplify host bridge window iteration
  PCI: versatile: Request host bridge window resources with core function
  PCI: tegra: Request host bridge window resources with core function
  PCI: tegra: Remove top-level resource from hierarchy
  PCI: rcar: Simplify host bridge window iteration
  PCI: rcar: Request host bridge window resources with core function
  PCI: rcar Gen2: Request host bridge window resources
  PCI: rcar: Drop gen2 dummy I/O port region
  ARM: Make PCI I/O space optional
  PCI: mvebu: Request host bridge window resources with core function
  PCI: generic: Simplify host bridge window iteration
  PCI: generic: Request host bridge window resources with core function
  PCI: altera: Simplify host bridge window iteration
  PCI: altera: Request host bridge window resources with core function
  PCI: xilinx-nwl: Use dev_printk() when possible
  PCI: xilinx-nwl: Request host bridge window resources
  PCI: xilinx-nwl: Free bridge resource list on failure
  PCI: xilinx: Request host bridge window resources
  PCI: xilinx: Free bridge resource list on failure
  PCI: xgene: Request host bridge window resources
  PCI: xgene: Free bridge resource list on failure
  PCI: iproc: Request host bridge window resources
  PCI: designware: Simplify host bridge window iteration
  PCI: designware: Request host bridge window resources
  PCI: designware: Free bridge resource list on failure
  PCI: Add devm_request_pci_bus_resources()
hifive-unleashed-5.1
Bjorn Helgaas 2016-08-01 12:23:57 -05:00
commit 79dd993461
29 changed files with 556 additions and 270 deletions

View File

@ -0,0 +1,46 @@
* Axis ARTPEC-6 PCIe interface
This PCIe host controller is based on the Synopsys DesignWare PCIe IP
and thus inherits all the common properties defined in designware-pcie.txt.
Required properties:
- compatible: "axis,artpec6-pcie", "snps,dw-pcie"
- reg: base addresses and lengths of the PCIe controller (DBI),
the phy controller, and configuration address space.
- reg-names: Must include the following entries:
- "dbi"
- "phy"
- "config"
- interrupts: A list of interrupt outputs of the controller. Must contain an
entry for each entry in the interrupt-names property.
- interrupt-names: Must include the following entries:
- "msi": The interrupt that is asserted when an MSI is received
- axis,syscon-pcie: A phandle pointing to the ARTPEC-6 system controller,
used to enable and control the Synopsys IP.
Example:
pcie@f8050000 {
compatible = "axis,artpec6-pcie", "snps,dw-pcie";
reg = <0xf8050000 0x2000
0xf8040000 0x1000
0xc0000000 0x1000>;
reg-names = "dbi", "phy", "config";
#address-cells = <3>;
#size-cells = <2>;
device_type = "pci";
/* downstream I/O */
ranges = <0x81000000 0 0x00010000 0xc0010000 0 0x00010000
/* non-prefetchable memory */
0x82000000 0 0xc0020000 0xc0020000 0 0x1ffe0000>;
num-lanes = <2>;
interrupts = <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "msi";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &intc GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 2 &intc GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 3 &intc GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 4 &intc GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>;
axis,syscon-pcie = <&syscon>;
};

View File

@ -8824,6 +8824,15 @@ S: Maintained
F: Documentation/devicetree/bindings/pci/xgene-pci-msi.txt
F: drivers/pci/host/pci-xgene-msi.c
PCIE DRIVER FOR AXIS ARTPEC
M: Niklas Cassel <niklas.cassel@axis.com>
M: Jesper Nilsson <jesper.nilsson@axis.com>
L: linux-arm-kernel@axis.com
L: linux-pci@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/pci/axis,artpec*
F: drivers/pci/host/*artpec*
PCIE DRIVER FOR HISILICON
M: Zhou Wang <wangzhou1@hisilicon.com>
M: Gabriele Paoloni <gabriele.paoloni@huawei.com>

View File

@ -22,6 +22,7 @@ struct hw_pci {
struct msi_controller *msi_ctrl;
struct pci_ops *ops;
int nr_controllers;
unsigned int io_optional:1;
void **private_data;
int (*setup)(int nr, struct pci_sys_data *);
struct pci_bus *(*scan)(int nr, struct pci_sys_data *);

View File

@ -410,7 +410,8 @@ static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
return irq;
}
static int pcibios_init_resources(int busnr, struct pci_sys_data *sys)
static int pcibios_init_resource(int busnr, struct pci_sys_data *sys,
int io_optional)
{
int ret;
struct resource_entry *window;
@ -420,6 +421,14 @@ static int pcibios_init_resources(int busnr, struct pci_sys_data *sys)
&iomem_resource, sys->mem_offset);
}
/*
* If a platform says I/O port support is optional, we don't add
* the default I/O space. The platform is responsible for adding
* any I/O space it needs.
*/
if (io_optional)
return 0;
resource_list_for_each_entry(window, &sys->resources)
if (resource_type(window->res) == IORESOURCE_IO)
return 0;
@ -466,7 +475,7 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
if (ret > 0) {
struct pci_host_bridge *host_bridge;
ret = pcibios_init_resources(nr, sys);
ret = pcibios_init_resource(nr, sys, hw->io_optional);
if (ret) {
kfree(sys);
break;

View File

@ -91,6 +91,35 @@ void pci_bus_remove_resources(struct pci_bus *bus)
}
}
int devm_request_pci_bus_resources(struct device *dev,
struct list_head *resources)
{
struct resource_entry *win;
struct resource *parent, *res;
int err;
resource_list_for_each_entry(win, resources) {
res = win->res;
switch (resource_type(res)) {
case IORESOURCE_IO:
parent = &ioport_resource;
break;
case IORESOURCE_MEM:
parent = &iomem_resource;
break;
default:
continue;
}
err = devm_request_resource(dev, parent, res);
if (err)
return err;
}
return 0;
}
EXPORT_SYMBOL_GPL(devm_request_pci_bus_resources);
static struct pci_bus_region pci_32_bit = {0, 0xffffffffULL};
#ifdef CONFIG_PCI_BUS_ADDR_T_64BIT
static struct pci_bus_region pci_64_bit = {0,
@ -398,4 +427,3 @@ void pci_bus_put(struct pci_bus *bus)
put_device(&bus->dev);
}
EXPORT_SYMBOL(pci_bus_put);

View File

@ -89,6 +89,7 @@ config PCI_HOST_GENERIC
bool "Generic PCI host controller"
depends on (ARM || ARM64) && OF
select PCI_HOST_COMMON
select IRQ_DOMAIN
help
Say Y here if you want to support a simple generic PCI host
controller, such as the one emulated by kvmtool.
@ -254,4 +255,14 @@ config PCIE_ARMADA_8K
Designware hardware and therefore the driver re-uses the
Designware core functions to implement the driver.
config PCIE_ARTPEC6
bool "Axis ARTPEC-6 PCIe controller"
depends on MACH_ARTPEC6
depends on PCI_MSI_IRQ_DOMAIN
select PCIE_DW
select PCIEPORTBUS
help
Say Y here to enable PCIe controller support on Axis ARTPEC-6
SoCs. This PCIe controller uses the DesignWare core.
endmenu

View File

@ -29,3 +29,4 @@ obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o
obj-$(CONFIG_PCI_HOST_THUNDER_ECAM) += pci-thunder-ecam.o
obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o
obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o

View File

@ -35,44 +35,34 @@ static int gen_pci_parse_request_of_pci_ranges(struct device *dev,
if (err)
return err;
err = devm_request_pci_bus_resources(dev, resources);
if (err)
return err;
resource_list_for_each_entry(win, resources) {
struct resource *parent, *res = win->res;
struct resource *res = win->res;
switch (resource_type(res)) {
case IORESOURCE_IO:
parent = &ioport_resource;
err = pci_remap_iospace(res, iobase);
if (err) {
if (err)
dev_warn(dev, "error %d: failed to map resource %pR\n",
err, res);
continue;
}
break;
case IORESOURCE_MEM:
parent = &iomem_resource;
res_valid |= !(res->flags & IORESOURCE_PREFETCH);
break;
case IORESOURCE_BUS:
*bus_range = res;
default:
continue;
break;
}
err = devm_request_resource(dev, parent, res);
if (err)
goto out_release_res;
}
if (!res_valid) {
dev_err(dev, "non-prefetchable memory resource required\n");
err = -EINVAL;
goto out_release_res;
}
if (res_valid)
return 0;
return 0;
out_release_res:
return err;
dev_err(dev, "non-prefetchable memory resource required\n");
return -EINVAL;
}
static void gen_pci_unmap_cfg(void *ptr)

View File

@ -20,7 +20,7 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/of_address.h>
#include <linux/of_pci.h>
#include <linux/pci-ecam.h>
@ -45,8 +45,6 @@ static const struct of_device_id gen_pci_of_match[] = {
{ },
};
MODULE_DEVICE_TABLE(of, gen_pci_of_match);
static int gen_pci_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id;
@ -65,8 +63,4 @@ static struct platform_driver gen_pci_driver = {
},
.probe = gen_pci_probe,
};
module_platform_driver(gen_pci_driver);
MODULE_DESCRIPTION("Generic PCI host driver");
MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(gen_pci_driver);

View File

@ -17,7 +17,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/msi.h>
#include <linux/of_irq.h>
#include <linux/of.h>
@ -360,7 +360,6 @@ static const struct of_device_id ks_pcie_of_match[] = {
},
{ },
};
MODULE_DEVICE_TABLE(of, ks_pcie_of_match);
static int __exit ks_pcie_remove(struct platform_device *pdev)
{
@ -439,9 +438,4 @@ static struct platform_driver ks_pcie_driver __refdata = {
.of_match_table = of_match_ptr(ks_pcie_of_match),
},
};
module_platform_driver(ks_pcie_driver);
MODULE_AUTHOR("Murali Karicheri <m-karicheri2@ti.com>");
MODULE_DESCRIPTION("Keystone PCIe host controller driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(ks_pcie_driver);

View File

@ -12,7 +12,7 @@
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/of_pci.h>
#include <linux/of_platform.h>
#include <linux/of_irq.h>
@ -211,7 +211,6 @@ static const struct of_device_id ls_pcie_of_match[] = {
{ .compatible = "fsl,ls2085a-pcie", .data = &ls2080_drvdata },
{ },
};
MODULE_DEVICE_TABLE(of, ls_pcie_of_match);
static int __init ls_add_pcie_port(struct pcie_port *pp,
struct platform_device *pdev)
@ -275,9 +274,4 @@ static struct platform_driver ls_pcie_driver = {
.of_match_table = ls_pcie_of_match,
},
};
module_platform_driver_probe(ls_pcie_driver, ls_pcie_probe);
MODULE_AUTHOR("Minghuan Lian <Minghuan.Lian@freescale.com>");
MODULE_DESCRIPTION("Freescale Layerscape PCIe host controller driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver_probe(ls_pcie_driver, ls_pcie_probe);

View File

@ -1,6 +1,8 @@
/*
* PCIe driver for Marvell Armada 370 and Armada XP SoCs
*
* Author: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
@ -11,7 +13,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mbus.h>
#include <linux/msi.h>
#include <linux/slab.h>
@ -839,25 +841,22 @@ static struct pci_ops mvebu_pcie_ops = {
static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
{
struct mvebu_pcie *pcie = sys_to_pcie(sys);
int i;
int err, i;
pcie->mem.name = "PCI MEM";
pcie->realio.name = "PCI I/O";
if (request_resource(&iomem_resource, &pcie->mem))
return 0;
if (resource_size(&pcie->realio) != 0) {
if (request_resource(&ioport_resource, &pcie->realio)) {
release_resource(&pcie->mem);
return 0;
}
if (resource_size(&pcie->realio) != 0)
pci_add_resource_offset(&sys->resources, &pcie->realio,
sys->io_offset);
}
pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
pci_add_resource(&sys->resources, &pcie->busn);
err = devm_request_pci_bus_resources(&pcie->pdev->dev, &sys->resources);
if (err)
return 0;
for (i = 0; i < pcie->nports; i++) {
struct mvebu_pcie_port *port = &pcie->ports[i];
@ -1298,7 +1297,6 @@ static const struct of_device_id mvebu_pcie_of_match_table[] = {
{ .compatible = "marvell,kirkwood-pcie", },
{},
};
MODULE_DEVICE_TABLE(of, mvebu_pcie_of_match_table);
static const struct dev_pm_ops mvebu_pcie_pm_ops = {
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mvebu_pcie_suspend, mvebu_pcie_resume)
@ -1314,8 +1312,4 @@ static struct platform_driver mvebu_pcie_driver = {
},
.probe = mvebu_pcie_probe,
};
module_platform_driver(mvebu_pcie_driver);
MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
MODULE_DESCRIPTION("Marvell EBU PCIe driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(mvebu_pcie_driver);

View File

@ -4,6 +4,8 @@
* Copyright (C) 2013 Renesas Solutions Corp.
* Copyright (C) 2013 Cogent Embedded, Inc.
*
* Author: Valentine Barshak <valentine.barshak@cogentembedded.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
@ -14,7 +16,6 @@
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of_address.h>
#include <linux/of_pci.h>
#include <linux/pci.h>
@ -97,7 +98,6 @@
struct rcar_pci_priv {
struct device *dev;
void __iomem *reg;
struct resource io_res;
struct resource mem_res;
struct resource *cfg_res;
unsigned busnr;
@ -194,6 +194,7 @@ static int rcar_pci_setup(int nr, struct pci_sys_data *sys)
struct rcar_pci_priv *priv = sys->private_data;
void __iomem *reg = priv->reg;
u32 val;
int ret;
pm_runtime_enable(priv->dev);
pm_runtime_get_sync(priv->dev);
@ -273,8 +274,10 @@ static int rcar_pci_setup(int nr, struct pci_sys_data *sys)
rcar_pci_setup_errirq(priv);
/* Add PCI resources */
pci_add_resource(&sys->resources, &priv->io_res);
pci_add_resource(&sys->resources, &priv->mem_res);
ret = devm_request_pci_bus_resources(priv->dev, &sys->resources);
if (ret < 0)
return ret;
/* Setup bus number based on platform device id / of bus-range */
sys->busnr = priv->busnr;
@ -371,14 +374,6 @@ static int rcar_pci_probe(struct platform_device *pdev)
return -ENOMEM;
priv->mem_res = *mem_res;
/*
* The controller does not support/use port I/O,
* so setup a dummy port I/O region here.
*/
priv->io_res.start = priv->mem_res.start;
priv->io_res.end = priv->mem_res.end;
priv->io_res.flags = IORESOURCE_IO;
priv->cfg_res = cfg_res;
priv->irq = platform_get_irq(pdev, 0);
@ -421,6 +416,7 @@ static int rcar_pci_probe(struct platform_device *pdev)
hw_private[0] = priv;
memset(&hw, 0, sizeof(hw));
hw.nr_controllers = ARRAY_SIZE(hw_private);
hw.io_optional = 1;
hw.private_data = hw_private;
hw.map_irq = rcar_pci_map_irq;
hw.ops = &rcar_pci_ops;
@ -437,8 +433,6 @@ static struct of_device_id rcar_pci_of_match[] = {
{ },
};
MODULE_DEVICE_TABLE(of, rcar_pci_of_match);
static struct platform_driver rcar_pci_driver = {
.driver = {
.name = "pci-rcar-gen2",
@ -447,9 +441,4 @@ static struct platform_driver rcar_pci_driver = {
},
.probe = rcar_pci_probe,
};
module_platform_driver(rcar_pci_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Renesas R-Car Gen2 internal PCI");
MODULE_AUTHOR("Valentine Barshak <valentine.barshak@cogentembedded.com>");
builtin_platform_driver(rcar_pci_driver);

View File

@ -9,6 +9,8 @@
*
* Bits taken from arch/arm/mach-dove/pcie.c
*
* Author: Thierry Reding <treding@nvidia.com>
*
* 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
@ -32,7 +34,7 @@
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/msi.h>
#include <linux/of_address.h>
#include <linux/of_pci.h>
@ -274,7 +276,6 @@ struct tegra_pcie {
struct list_head buses;
struct resource *cs;
struct resource all;
struct resource io;
struct resource pio;
struct resource mem;
@ -623,21 +624,11 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
sys->mem_offset = pcie->offset.mem;
sys->io_offset = pcie->offset.io;
err = devm_request_resource(pcie->dev, &pcie->all, &pcie->io);
err = devm_request_resource(pcie->dev, &iomem_resource, &pcie->io);
if (err < 0)
return err;
err = devm_request_resource(pcie->dev, &ioport_resource, &pcie->pio);
if (err < 0)
return err;
err = devm_request_resource(pcie->dev, &pcie->all, &pcie->mem);
if (err < 0)
return err;
err = devm_request_resource(pcie->dev, &pcie->all, &pcie->prefetch);
if (err)
return err;
pci_ioremap_io(pcie->pio.start, pcie->io.start);
pci_add_resource_offset(&sys->resources, &pcie->pio, sys->io_offset);
pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
@ -645,7 +636,9 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys)
sys->mem_offset);
pci_add_resource(&sys->resources, &pcie->busn);
pci_ioremap_io(pcie->pio.start, pcie->io.start);
err = devm_request_pci_bus_resources(pcie->dev, &sys->resources);
if (err < 0)
return err;
return 1;
}
@ -1822,12 +1815,6 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
struct resource res;
int err;
memset(&pcie->all, 0, sizeof(pcie->all));
pcie->all.flags = IORESOURCE_MEM;
pcie->all.name = np->full_name;
pcie->all.start = ~0;
pcie->all.end = 0;
if (of_pci_range_parser_init(&parser, np)) {
dev_err(pcie->dev, "missing \"ranges\" property\n");
return -EINVAL;
@ -1880,18 +1867,8 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
}
break;
}
if (res.start <= pcie->all.start)
pcie->all.start = res.start;
if (res.end >= pcie->all.end)
pcie->all.end = res.end;
}
err = devm_request_resource(pcie->dev, &iomem_resource, &pcie->all);
if (err < 0)
return err;
err = of_pci_parse_bus_range(np, &pcie->busn);
if (err < 0) {
dev_err(pcie->dev, "failed to parse ranges property: %d\n",
@ -2115,7 +2092,6 @@ static const struct of_device_id tegra_pcie_of_match[] = {
{ .compatible = "nvidia,tegra20-pcie", .data = &tegra20_pcie_data },
{ },
};
MODULE_DEVICE_TABLE(of, tegra_pcie_of_match);
static void *tegra_pcie_ports_seq_start(struct seq_file *s, loff_t *pos)
{
@ -2306,8 +2282,4 @@ static struct platform_driver tegra_pcie_driver = {
},
.probe = tegra_pcie_probe,
};
module_platform_driver(tegra_pcie_driver);
MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
MODULE_DESCRIPTION("NVIDIA Tegra PCIe driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(tegra_pcie_driver);

View File

@ -7,7 +7,7 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/of_pci.h>
#include <linux/of.h>
@ -359,7 +359,6 @@ static const struct of_device_id thunder_ecam_of_match[] = {
{ .compatible = "cavium,pci-host-thunder-ecam" },
{ },
};
MODULE_DEVICE_TABLE(of, thunder_ecam_of_match);
static int thunder_ecam_probe(struct platform_device *pdev)
{
@ -373,7 +372,4 @@ static struct platform_driver thunder_ecam_driver = {
},
.probe = thunder_ecam_probe,
};
module_platform_driver(thunder_ecam_driver);
MODULE_DESCRIPTION("Thunder ECAM PCI host driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(thunder_ecam_driver);

View File

@ -15,7 +15,7 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/of_address.h>
#include <linux/of_pci.h>
#include <linux/pci-ecam.h>
@ -346,7 +346,6 @@ static const struct of_device_id thunder_pem_of_match[] = {
{ .compatible = "cavium,pci-host-thunder-pem" },
{ },
};
MODULE_DEVICE_TABLE(of, thunder_pem_of_match);
static int thunder_pem_probe(struct platform_device *pdev)
{
@ -360,7 +359,4 @@ static struct platform_driver thunder_pem_driver = {
},
.probe = thunder_pem_probe,
};
module_platform_driver(thunder_pem_driver);
MODULE_DESCRIPTION("Thunder PEM PCIe host driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(thunder_pem_driver);

View File

@ -80,21 +80,21 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev,
if (err)
return err;
err = devm_request_pci_bus_resources(dev, res);
if (err)
goto out_release_res;
resource_list_for_each_entry(win, res) {
struct resource *parent, *res = win->res;
struct resource *res = win->res;
switch (resource_type(res)) {
case IORESOURCE_IO:
parent = &ioport_resource;
err = pci_remap_iospace(res, iobase);
if (err) {
if (err)
dev_warn(dev, "error %d: failed to map resource %pR\n",
err, res);
continue;
}
break;
case IORESOURCE_MEM:
parent = &iomem_resource;
res_valid |= !(res->flags & IORESOURCE_PREFETCH);
writel(res->start >> 28, PCI_IMAP(mem));
@ -102,23 +102,14 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev,
mem++;
break;
case IORESOURCE_BUS:
default:
continue;
}
err = devm_request_resource(dev, parent, res);
if (err)
goto out_release_res;
}
if (!res_valid) {
dev_err(dev, "non-prefetchable memory resource required\n");
err = -EINVAL;
goto out_release_res;
}
if (res_valid)
return 0;
return 0;
dev_err(dev, "non-prefetchable memory resource required\n");
err = -EINVAL;
out_release_res:
pci_free_resource_list(res);

View File

@ -21,7 +21,7 @@
#include <linux/io.h>
#include <linux/jiffies.h>
#include <linux/memblock.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
@ -540,14 +540,20 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
if (ret)
return ret;
ret = devm_request_pci_bus_resources(&pdev->dev, &res);
if (ret)
goto error;
ret = xgene_pcie_setup(port, &res, iobase);
if (ret)
return ret;
goto error;
bus = pci_create_root_bus(&pdev->dev, 0,
&xgene_pcie_ops, port, &res);
if (!bus)
return -ENOMEM;
if (!bus) {
ret = -ENOMEM;
goto error;
}
pci_scan_child_bus(bus);
pci_assign_unassigned_bus_resources(bus);
@ -555,6 +561,10 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
platform_set_drvdata(pdev, port);
return 0;
error:
pci_free_resource_list(&res);
return ret;
}
static const struct of_device_id xgene_pcie_match_table[] = {
@ -569,8 +579,4 @@ static struct platform_driver xgene_pcie_driver = {
},
.probe = xgene_pcie_probe_bridge,
};
module_platform_driver(xgene_pcie_driver);
MODULE_AUTHOR("Tanmay Inamdar <tinamdar@apm.com>");
MODULE_DESCRIPTION("APM X-Gene PCIe driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(xgene_pcie_driver);

View File

@ -415,11 +415,6 @@ static void altera_pcie_isr(struct irq_desc *desc)
chained_irq_exit(chip, desc);
}
static void altera_pcie_release_of_pci_ranges(struct altera_pcie *pcie)
{
pci_free_resource_list(&pcie->resources);
}
static int altera_pcie_parse_request_of_pci_ranges(struct altera_pcie *pcie)
{
int err, res_valid = 0;
@ -432,33 +427,25 @@ static int altera_pcie_parse_request_of_pci_ranges(struct altera_pcie *pcie)
if (err)
return err;
resource_list_for_each_entry(win, &pcie->resources) {
struct resource *parent, *res = win->res;
switch (resource_type(res)) {
case IORESOURCE_MEM:
parent = &iomem_resource;
res_valid |= !(res->flags & IORESOURCE_PREFETCH);
break;
default:
continue;
}
err = devm_request_resource(dev, parent, res);
if (err)
goto out_release_res;
}
if (!res_valid) {
dev_err(dev, "non-prefetchable memory resource required\n");
err = -EINVAL;
err = devm_request_pci_bus_resources(dev, &pcie->resources);
if (err)
goto out_release_res;
resource_list_for_each_entry(win, &pcie->resources) {
struct resource *res = win->res;
if (resource_type(res) == IORESOURCE_MEM)
res_valid |= !(res->flags & IORESOURCE_PREFETCH);
}
return 0;
if (res_valid)
return 0;
dev_err(dev, "non-prefetchable memory resource required\n");
err = -EINVAL;
out_release_res:
altera_pcie_release_of_pci_ranges(pcie);
pci_free_resource_list(&pcie->resources);
return err;
}

View File

@ -5,6 +5,9 @@
*
* Copyright (C) 2016 Marvell Technology Group Ltd.
*
* Author: Yehuda Yitshak <yehuday@marvell.com>
* Author: Shadi Ammouri <shadi@marvell.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
@ -14,7 +17,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/pci.h>
#include <linux/phy/phy.h>
@ -244,7 +247,6 @@ static const struct of_device_id armada8k_pcie_of_match[] = {
{ .compatible = "marvell,armada8k-pcie", },
{},
};
MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match);
static struct platform_driver armada8k_pcie_driver = {
.probe = armada8k_pcie_probe,
@ -253,10 +255,4 @@ static struct platform_driver armada8k_pcie_driver = {
.of_match_table = of_match_ptr(armada8k_pcie_of_match),
},
};
module_platform_driver(armada8k_pcie_driver);
MODULE_DESCRIPTION("Armada 8k PCIe host controller driver");
MODULE_AUTHOR("Yehuda Yitshak <yehuday@marvell.com>");
MODULE_AUTHOR("Shadi Ammouri <shadi@marvell.com>");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(armada8k_pcie_driver);

View File

@ -0,0 +1,280 @@
/*
* PCIe host controller driver for Axis ARTPEC-6 SoC
*
* Author: Niklas Cassel <niklas.cassel@axis.com>
*
* Based on work done by Phil Edworthy <phil@edworthys.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
#include <linux/resource.h>
#include <linux/signal.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include "pcie-designware.h"
#define to_artpec6_pcie(x) container_of(x, struct artpec6_pcie, pp)
struct artpec6_pcie {
struct pcie_port pp;
struct regmap *regmap;
void __iomem *phy_base;
};
/* PCIe Port Logic registers (memory-mapped) */
#define PL_OFFSET 0x700
#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
#define MISC_CONTROL_1_OFF (PL_OFFSET + 0x1bc)
#define DBI_RO_WR_EN 1
/* ARTPEC-6 specific registers */
#define PCIECFG 0x18
#define PCIECFG_DBG_OEN (1 << 24)
#define PCIECFG_CORE_RESET_REQ (1 << 21)
#define PCIECFG_LTSSM_ENABLE (1 << 20)
#define PCIECFG_CLKREQ_B (1 << 11)
#define PCIECFG_REFCLK_ENABLE (1 << 10)
#define PCIECFG_PLL_ENABLE (1 << 9)
#define PCIECFG_PCLK_ENABLE (1 << 8)
#define PCIECFG_RISRCREN (1 << 4)
#define PCIECFG_MODE_TX_DRV_EN (1 << 3)
#define PCIECFG_CISRREN (1 << 2)
#define PCIECFG_MACRO_ENABLE (1 << 0)
#define NOCCFG 0x40
#define NOCCFG_ENABLE_CLK_PCIE (1 << 4)
#define NOCCFG_POWER_PCIE_IDLEACK (1 << 3)
#define NOCCFG_POWER_PCIE_IDLE (1 << 2)
#define NOCCFG_POWER_PCIE_IDLEREQ (1 << 1)
#define PHY_STATUS 0x118
#define PHY_COSPLLLOCK (1 << 0)
#define ARTPEC6_CPU_TO_BUS_ADDR 0x0fffffff
static int artpec6_pcie_establish_link(struct pcie_port *pp)
{
struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pp);
u32 val;
unsigned int retries;
/* Hold DW core in reset */
regmap_read(artpec6_pcie->regmap, PCIECFG, &val);
val |= PCIECFG_CORE_RESET_REQ;
regmap_write(artpec6_pcie->regmap, PCIECFG, val);
regmap_read(artpec6_pcie->regmap, PCIECFG, &val);
val |= PCIECFG_RISRCREN | /* Receiver term. 50 Ohm */
PCIECFG_MODE_TX_DRV_EN |
PCIECFG_CISRREN | /* Reference clock term. 100 Ohm */
PCIECFG_MACRO_ENABLE;
val |= PCIECFG_REFCLK_ENABLE;
val &= ~PCIECFG_DBG_OEN;
val &= ~PCIECFG_CLKREQ_B;
regmap_write(artpec6_pcie->regmap, PCIECFG, val);
usleep_range(5000, 6000);
regmap_read(artpec6_pcie->regmap, NOCCFG, &val);
val |= NOCCFG_ENABLE_CLK_PCIE;
regmap_write(artpec6_pcie->regmap, NOCCFG, val);
usleep_range(20, 30);
regmap_read(artpec6_pcie->regmap, PCIECFG, &val);
val |= PCIECFG_PCLK_ENABLE | PCIECFG_PLL_ENABLE;
regmap_write(artpec6_pcie->regmap, PCIECFG, val);
usleep_range(6000, 7000);
regmap_read(artpec6_pcie->regmap, NOCCFG, &val);
val &= ~NOCCFG_POWER_PCIE_IDLEREQ;
regmap_write(artpec6_pcie->regmap, NOCCFG, val);
retries = 50;
do {
usleep_range(1000, 2000);
regmap_read(artpec6_pcie->regmap, NOCCFG, &val);
retries--;
} while (retries &&
(val & (NOCCFG_POWER_PCIE_IDLEACK | NOCCFG_POWER_PCIE_IDLE)));
retries = 50;
do {
usleep_range(1000, 2000);
val = readl(artpec6_pcie->phy_base + PHY_STATUS);
retries--;
} while (retries && !(val & PHY_COSPLLLOCK));
/* Take DW core out of reset */
regmap_read(artpec6_pcie->regmap, PCIECFG, &val);
val &= ~PCIECFG_CORE_RESET_REQ;
regmap_write(artpec6_pcie->regmap, PCIECFG, val);
usleep_range(100, 200);
/*
* Enable writing to config regs. This is required as the Synopsys
* driver changes the class code. That register needs DBI write enable.
*/
writel(DBI_RO_WR_EN, pp->dbi_base + MISC_CONTROL_1_OFF);
pp->io_base &= ARTPEC6_CPU_TO_BUS_ADDR;
pp->mem_base &= ARTPEC6_CPU_TO_BUS_ADDR;
pp->cfg0_base &= ARTPEC6_CPU_TO_BUS_ADDR;
pp->cfg1_base &= ARTPEC6_CPU_TO_BUS_ADDR;
/* setup root complex */
dw_pcie_setup_rc(pp);
/* assert LTSSM enable */
regmap_read(artpec6_pcie->regmap, PCIECFG, &val);
val |= PCIECFG_LTSSM_ENABLE;
regmap_write(artpec6_pcie->regmap, PCIECFG, val);
/* check if the link is up or not */
if (!dw_pcie_wait_for_link(pp))
return 0;
dev_dbg(pp->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
readl(pp->dbi_base + PCIE_PHY_DEBUG_R0),
readl(pp->dbi_base + PCIE_PHY_DEBUG_R1));
return -ETIMEDOUT;
}
static void artpec6_pcie_enable_interrupts(struct pcie_port *pp)
{
if (IS_ENABLED(CONFIG_PCI_MSI))
dw_pcie_msi_init(pp);
}
static void artpec6_pcie_host_init(struct pcie_port *pp)
{
artpec6_pcie_establish_link(pp);
artpec6_pcie_enable_interrupts(pp);
}
static int artpec6_pcie_link_up(struct pcie_port *pp)
{
u32 rc;
/*
* Get status from Synopsys IP
* link is debug bit 36, debug register 1 starts at bit 32
*/
rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) & (0x1 << (36 - 32));
if (rc)
return 1;
return 0;
}
static struct pcie_host_ops artpec6_pcie_host_ops = {
.link_up = artpec6_pcie_link_up,
.host_init = artpec6_pcie_host_init,
};
static irqreturn_t artpec6_pcie_msi_handler(int irq, void *arg)
{
struct pcie_port *pp = arg;
return dw_handle_msi_irq(pp);
}
static int __init artpec6_add_pcie_port(struct pcie_port *pp,
struct platform_device *pdev)
{
int ret;
if (IS_ENABLED(CONFIG_PCI_MSI)) {
pp->msi_irq = platform_get_irq_byname(pdev, "msi");
if (pp->msi_irq <= 0) {
dev_err(&pdev->dev, "failed to get MSI irq\n");
return -ENODEV;
}
ret = devm_request_irq(&pdev->dev, pp->msi_irq,
artpec6_pcie_msi_handler,
IRQF_SHARED | IRQF_NO_THREAD,
"artpec6-pcie-msi", pp);
if (ret) {
dev_err(&pdev->dev, "failed to request MSI irq\n");
return ret;
}
}
pp->root_bus_nr = -1;
pp->ops = &artpec6_pcie_host_ops;
ret = dw_pcie_host_init(pp);
if (ret) {
dev_err(&pdev->dev, "failed to initialize host\n");
return ret;
}
return 0;
}
static int artpec6_pcie_probe(struct platform_device *pdev)
{
struct artpec6_pcie *artpec6_pcie;
struct pcie_port *pp;
struct resource *dbi_base;
struct resource *phy_base;
int ret;
artpec6_pcie = devm_kzalloc(&pdev->dev, sizeof(*artpec6_pcie),
GFP_KERNEL);
if (!artpec6_pcie)
return -ENOMEM;
pp = &artpec6_pcie->pp;
pp->dev = &pdev->dev;
dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
pp->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base);
if (IS_ERR(pp->dbi_base))
return PTR_ERR(pp->dbi_base);
phy_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy");
artpec6_pcie->phy_base = devm_ioremap_resource(&pdev->dev, phy_base);
if (IS_ERR(artpec6_pcie->phy_base))
return PTR_ERR(artpec6_pcie->phy_base);
artpec6_pcie->regmap =
syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
"axis,syscon-pcie");
if (IS_ERR(artpec6_pcie->regmap))
return PTR_ERR(artpec6_pcie->regmap);
ret = artpec6_add_pcie_port(pp, pdev);
if (ret < 0)
return ret;
platform_set_drvdata(pdev, artpec6_pcie);
return 0;
}
static const struct of_device_id artpec6_pcie_of_match[] = {
{ .compatible = "axis,artpec6-pcie", },
{},
};
static struct platform_driver artpec6_pcie_driver = {
.probe = artpec6_pcie_probe,
.driver = {
.name = "artpec6-pcie",
.of_match_table = artpec6_pcie_of_match,
},
};
builtin_platform_driver(artpec6_pcie_driver);

View File

@ -14,7 +14,7 @@
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/of_gpio.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
@ -121,7 +121,6 @@ static const struct of_device_id dw_plat_pcie_of_match[] = {
{ .compatible = "snps,dw-pcie", },
{},
};
MODULE_DEVICE_TABLE(of, dw_plat_pcie_of_match);
static struct platform_driver dw_plat_pcie_driver = {
.driver = {
@ -130,9 +129,4 @@ static struct platform_driver dw_plat_pcie_driver = {
},
.probe = dw_plat_pcie_probe,
};
module_platform_driver(dw_plat_pcie_driver);
MODULE_AUTHOR("Joao Pinto <Joao.Pinto@synopsys.com>");
MODULE_DESCRIPTION("Synopsys PCIe host controller glue platform driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(dw_plat_pcie_driver);

View File

@ -452,6 +452,10 @@ int dw_pcie_host_init(struct pcie_port *pp)
if (ret)
return ret;
ret = devm_request_pci_bus_resources(&pdev->dev, &res);
if (ret)
goto error;
/* Get the I/O and memory ranges from DT */
resource_list_for_each_entry(win, &res) {
switch (resource_type(win->res)) {
@ -461,11 +465,9 @@ int dw_pcie_host_init(struct pcie_port *pp)
pp->io_size = resource_size(pp->io);
pp->io_bus_addr = pp->io->start - win->offset;
ret = pci_remap_iospace(pp->io, pp->io_base);
if (ret) {
if (ret)
dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
ret, pp->io);
continue;
}
break;
case IORESOURCE_MEM:
pp->mem = win->res;
@ -483,8 +485,6 @@ int dw_pcie_host_init(struct pcie_port *pp)
case IORESOURCE_BUS:
pp->busn = win->res;
break;
default:
continue;
}
}
@ -493,7 +493,8 @@ int dw_pcie_host_init(struct pcie_port *pp)
resource_size(pp->cfg));
if (!pp->dbi_base) {
dev_err(pp->dev, "error with ioremap\n");
return -ENOMEM;
ret = -ENOMEM;
goto error;
}
}
@ -504,7 +505,8 @@ int dw_pcie_host_init(struct pcie_port *pp)
pp->cfg0_size);
if (!pp->va_cfg0_base) {
dev_err(pp->dev, "error with ioremap in function\n");
return -ENOMEM;
ret = -ENOMEM;
goto error;
}
}
@ -513,7 +515,8 @@ int dw_pcie_host_init(struct pcie_port *pp)
pp->cfg1_size);
if (!pp->va_cfg1_base) {
dev_err(pp->dev, "error with ioremap\n");
return -ENOMEM;
ret = -ENOMEM;
goto error;
}
}
@ -528,7 +531,8 @@ int dw_pcie_host_init(struct pcie_port *pp)
&dw_pcie_msi_chip);
if (!pp->irq_domain) {
dev_err(pp->dev, "irq domain init failed\n");
return -ENXIO;
ret = -ENXIO;
goto error;
}
for (i = 0; i < MAX_MSI_IRQS; i++)
@ -536,7 +540,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
} else {
ret = pp->ops->msi_host_init(pp, &dw_pcie_msi_chip);
if (ret < 0)
return ret;
goto error;
}
}
@ -552,8 +556,10 @@ int dw_pcie_host_init(struct pcie_port *pp)
} else
bus = pci_scan_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
pp, &res);
if (!bus)
return -ENOMEM;
if (!bus) {
ret = -ENOMEM;
goto error;
}
if (pp->ops->scan_bus)
pp->ops->scan_bus(pp);
@ -571,6 +577,10 @@ int dw_pcie_host_init(struct pcie_port *pp)
pci_bus_add_devices(bus);
return 0;
error:
pci_free_resource_list(&res);
return ret;
}
static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,

View File

@ -12,7 +12,7 @@
* published by the Free Software Foundation.
*/
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mfd/syscon.h>
#include <linux/of_address.h>
#include <linux/of_pci.h>
@ -235,9 +235,6 @@ static const struct of_device_id hisi_pcie_of_match[] = {
{},
};
MODULE_DEVICE_TABLE(of, hisi_pcie_of_match);
static struct platform_driver hisi_pcie_driver = {
.probe = hisi_pcie_probe,
.driver = {
@ -245,10 +242,4 @@ static struct platform_driver hisi_pcie_driver = {
.of_match_table = hisi_pcie_of_match,
},
};
module_platform_driver(hisi_pcie_driver);
MODULE_AUTHOR("Zhou Wang <wangzhou1@hisilicon.com>");
MODULE_AUTHOR("Dacai Zhu <zhudacai@hisilicon.com>");
MODULE_AUTHOR("Gabriele Paoloni <gabriele.paoloni@huawei.com>");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(hisi_pcie_driver);

View File

@ -462,6 +462,10 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
if (!pcie || !pcie->dev || !pcie->base)
return -EINVAL;
ret = devm_request_pci_bus_resources(pcie->dev, res);
if (ret)
return ret;
ret = phy_init(pcie->phy);
if (ret) {
dev_err(pcie->dev, "unable to initialize PCIe PHY\n");

View File

@ -7,6 +7,8 @@
* arch/sh/drivers/pci/ops-sh7786.c
* Copyright (C) 2009 - 2011 Paul Mundt
*
* Author: Phil Edworthy <phil.edworthy@renesas.com>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
@ -18,7 +20,7 @@
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/msi.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
@ -936,12 +938,6 @@ static const struct of_device_id rcar_pcie_of_match[] = {
{ .compatible = "renesas,pcie-r8a7795", .data = rcar_pcie_hw_init },
{},
};
MODULE_DEVICE_TABLE(of, rcar_pcie_of_match);
static void rcar_pcie_release_of_pci_ranges(struct rcar_pcie *pci)
{
pci_free_resource_list(&pci->resources);
}
static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci)
{
@ -955,37 +951,25 @@ static int rcar_pcie_parse_request_of_pci_ranges(struct rcar_pcie *pci)
if (err)
return err;
resource_list_for_each_entry(win, &pci->resources) {
struct resource *parent, *res = win->res;
err = devm_request_pci_bus_resources(dev, &pci->resources);
if (err)
goto out_release_res;
switch (resource_type(res)) {
case IORESOURCE_IO:
parent = &ioport_resource;
resource_list_for_each_entry(win, &pci->resources) {
struct resource *res = win->res;
if (resource_type(res) == IORESOURCE_IO) {
err = pci_remap_iospace(res, iobase);
if (err) {
if (err)
dev_warn(dev, "error %d: failed to map resource %pR\n",
err, res);
continue;
}
break;
case IORESOURCE_MEM:
parent = &iomem_resource;
break;
case IORESOURCE_BUS:
default:
continue;
}
err = devm_request_resource(dev, parent, res);
if (err)
goto out_release_res;
}
return 0;
out_release_res:
rcar_pcie_release_of_pci_ranges(pci);
pci_free_resource_list(&pci->resources);
return err;
}
@ -1073,8 +1057,4 @@ static struct platform_driver rcar_pcie_driver = {
},
.probe = rcar_pcie_probe,
};
module_platform_driver(rcar_pcie_driver);
MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
MODULE_DESCRIPTION("Renesas R-Car PCIe driver");
MODULE_LICENSE("GPL v2");
builtin_platform_driver(rcar_pcie_driver);

View File

@ -825,27 +825,33 @@ static int nwl_pcie_probe(struct platform_device *pdev)
err = of_pci_get_host_bridge_resources(node, 0, 0xff, &res, &iobase);
if (err) {
pr_err("Getting bridge resources failed\n");
dev_err(pcie->dev, "Getting bridge resources failed\n");
return err;
}
err = devm_request_pci_bus_resources(pcie->dev, &res);
if (err)
goto error;
err = nwl_pcie_init_irq_domain(pcie);
if (err) {
dev_err(pcie->dev, "Failed creating IRQ Domain\n");
return err;
goto error;
}
bus = pci_create_root_bus(&pdev->dev, pcie->root_busno,
&nwl_pcie_ops, pcie, &res);
if (!bus)
return -ENOMEM;
if (!bus) {
err = -ENOMEM;
goto error;
}
if (IS_ENABLED(CONFIG_PCI_MSI)) {
err = nwl_pcie_enable_msi(pcie, bus);
if (err < 0) {
dev_err(&pdev->dev,
"failed to enable MSI support: %d\n", err);
return err;
goto error;
}
}
pci_scan_child_bus(bus);
@ -855,6 +861,10 @@ static int nwl_pcie_probe(struct platform_device *pdev)
pci_bus_add_devices(bus);
platform_set_drvdata(pdev, pcie);
return 0;
error:
pci_free_resource_list(&res);
return err;
}
static int nwl_pcie_remove(struct platform_device *pdev)

View File

@ -660,7 +660,6 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
struct xilinx_pcie_port *port;
struct device *dev = &pdev->dev;
struct pci_bus *bus;
int err;
resource_size_t iobase = 0;
LIST_HEAD(res);
@ -694,10 +693,17 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
dev_err(dev, "Getting bridge resources failed\n");
return err;
}
err = devm_request_pci_bus_resources(dev, &res);
if (err)
goto error;
bus = pci_create_root_bus(&pdev->dev, 0,
&xilinx_pcie_ops, port, &res);
if (!bus)
return -ENOMEM;
if (!bus) {
err = -ENOMEM;
goto error;
}
#ifdef CONFIG_PCI_MSI
xilinx_pcie_msi_chip.dev = port->dev;
@ -712,6 +718,10 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, port);
return 0;
error:
pci_free_resource_list(&res);
return err;
}
/**

View File

@ -1151,9 +1151,12 @@ void pci_add_resource(struct list_head *resources, struct resource *res);
void pci_add_resource_offset(struct list_head *resources, struct resource *res,
resource_size_t offset);
void pci_free_resource_list(struct list_head *resources);
void pci_bus_add_resource(struct pci_bus *bus, struct resource *res, unsigned int flags);
void pci_bus_add_resource(struct pci_bus *bus, struct resource *res,
unsigned int flags);
struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n);
void pci_bus_remove_resources(struct pci_bus *bus);
int devm_request_pci_bus_resources(struct device *dev,
struct list_head *resources);
#define pci_bus_for_each_resource(bus, res, i) \
for (i = 0; \