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
commit
79dd993461
|
@ -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>;
|
||||||
|
};
|
|
@ -8824,6 +8824,15 @@ S: Maintained
|
||||||
F: Documentation/devicetree/bindings/pci/xgene-pci-msi.txt
|
F: Documentation/devicetree/bindings/pci/xgene-pci-msi.txt
|
||||||
F: drivers/pci/host/pci-xgene-msi.c
|
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
|
PCIE DRIVER FOR HISILICON
|
||||||
M: Zhou Wang <wangzhou1@hisilicon.com>
|
M: Zhou Wang <wangzhou1@hisilicon.com>
|
||||||
M: Gabriele Paoloni <gabriele.paoloni@huawei.com>
|
M: Gabriele Paoloni <gabriele.paoloni@huawei.com>
|
||||||
|
|
|
@ -22,6 +22,7 @@ struct hw_pci {
|
||||||
struct msi_controller *msi_ctrl;
|
struct msi_controller *msi_ctrl;
|
||||||
struct pci_ops *ops;
|
struct pci_ops *ops;
|
||||||
int nr_controllers;
|
int nr_controllers;
|
||||||
|
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 *);
|
struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
|
||||||
|
|
|
@ -410,7 +410,8 @@ static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
|
||||||
return irq;
|
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;
|
int ret;
|
||||||
struct resource_entry *window;
|
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);
|
&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)
|
resource_list_for_each_entry(window, &sys->resources)
|
||||||
if (resource_type(window->res) == IORESOURCE_IO)
|
if (resource_type(window->res) == IORESOURCE_IO)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -466,7 +475,7 @@ static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
struct pci_host_bridge *host_bridge;
|
struct pci_host_bridge *host_bridge;
|
||||||
|
|
||||||
ret = pcibios_init_resources(nr, sys);
|
ret = pcibios_init_resource(nr, sys, hw->io_optional);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
kfree(sys);
|
kfree(sys);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -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};
|
static struct pci_bus_region pci_32_bit = {0, 0xffffffffULL};
|
||||||
#ifdef CONFIG_PCI_BUS_ADDR_T_64BIT
|
#ifdef CONFIG_PCI_BUS_ADDR_T_64BIT
|
||||||
static struct pci_bus_region pci_64_bit = {0,
|
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);
|
put_device(&bus->dev);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(pci_bus_put);
|
EXPORT_SYMBOL(pci_bus_put);
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,7 @@ config PCI_HOST_GENERIC
|
||||||
bool "Generic PCI host controller"
|
bool "Generic PCI host controller"
|
||||||
depends on (ARM || ARM64) && OF
|
depends on (ARM || ARM64) && OF
|
||||||
select PCI_HOST_COMMON
|
select PCI_HOST_COMMON
|
||||||
|
select IRQ_DOMAIN
|
||||||
help
|
help
|
||||||
Say Y here if you want to support a simple generic PCI host
|
Say Y here if you want to support a simple generic PCI host
|
||||||
controller, such as the one emulated by kvmtool.
|
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 hardware and therefore the driver re-uses the
|
||||||
Designware core functions to implement the driver.
|
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
|
endmenu
|
||||||
|
|
|
@ -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_ECAM) += pci-thunder-ecam.o
|
||||||
obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o
|
obj-$(CONFIG_PCI_HOST_THUNDER_PEM) += pci-thunder-pem.o
|
||||||
obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
|
obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
|
||||||
|
obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o
|
||||||
|
|
|
@ -35,44 +35,34 @@ static int gen_pci_parse_request_of_pci_ranges(struct device *dev,
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
err = devm_request_pci_bus_resources(dev, resources);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
resource_list_for_each_entry(win, resources) {
|
resource_list_for_each_entry(win, resources) {
|
||||||
struct resource *parent, *res = win->res;
|
struct resource *res = win->res;
|
||||||
|
|
||||||
switch (resource_type(res)) {
|
switch (resource_type(res)) {
|
||||||
case IORESOURCE_IO:
|
case IORESOURCE_IO:
|
||||||
parent = &ioport_resource;
|
|
||||||
err = pci_remap_iospace(res, iobase);
|
err = pci_remap_iospace(res, iobase);
|
||||||
if (err) {
|
if (err)
|
||||||
dev_warn(dev, "error %d: failed to map resource %pR\n",
|
dev_warn(dev, "error %d: failed to map resource %pR\n",
|
||||||
err, res);
|
err, res);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case IORESOURCE_MEM:
|
case IORESOURCE_MEM:
|
||||||
parent = &iomem_resource;
|
|
||||||
res_valid |= !(res->flags & IORESOURCE_PREFETCH);
|
res_valid |= !(res->flags & IORESOURCE_PREFETCH);
|
||||||
break;
|
break;
|
||||||
case IORESOURCE_BUS:
|
case IORESOURCE_BUS:
|
||||||
*bus_range = res;
|
*bus_range = res;
|
||||||
default:
|
break;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = devm_request_resource(dev, parent, res);
|
|
||||||
if (err)
|
|
||||||
goto out_release_res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!res_valid) {
|
if (res_valid)
|
||||||
dev_err(dev, "non-prefetchable memory resource required\n");
|
return 0;
|
||||||
err = -EINVAL;
|
|
||||||
goto out_release_res;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
dev_err(dev, "non-prefetchable memory resource required\n");
|
||||||
|
return -EINVAL;
|
||||||
out_release_res:
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_pci_unmap_cfg(void *ptr)
|
static void gen_pci_unmap_cfg(void *ptr)
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/init.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/of_pci.h>
|
#include <linux/of_pci.h>
|
||||||
#include <linux/pci-ecam.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)
|
static int gen_pci_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
const struct of_device_id *of_id;
|
const struct of_device_id *of_id;
|
||||||
|
@ -65,8 +63,4 @@ static struct platform_driver gen_pci_driver = {
|
||||||
},
|
},
|
||||||
.probe = gen_pci_probe,
|
.probe = gen_pci_probe,
|
||||||
};
|
};
|
||||||
module_platform_driver(gen_pci_driver);
|
builtin_platform_driver(gen_pci_driver);
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Generic PCI host driver");
|
|
||||||
MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
|
|
||||||
MODULE_LICENSE("GPL v2");
|
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/irqdomain.h>
|
#include <linux/irqdomain.h>
|
||||||
#include <linux/module.h>
|
#include <linux/init.h>
|
||||||
#include <linux/msi.h>
|
#include <linux/msi.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
#include <linux/of.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)
|
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),
|
.of_match_table = of_match_ptr(ks_pcie_of_match),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
builtin_platform_driver(ks_pcie_driver);
|
||||||
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");
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/module.h>
|
#include <linux/init.h>
|
||||||
#include <linux/of_pci.h>
|
#include <linux/of_pci.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/of_irq.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 },
|
{ .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,
|
static int __init ls_add_pcie_port(struct pcie_port *pp,
|
||||||
struct platform_device *pdev)
|
struct platform_device *pdev)
|
||||||
|
@ -275,9 +274,4 @@ static struct platform_driver ls_pcie_driver = {
|
||||||
.of_match_table = ls_pcie_of_match,
|
.of_match_table = ls_pcie_of_match,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
builtin_platform_driver_probe(ls_pcie_driver, ls_pcie_probe);
|
||||||
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");
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
/*
|
/*
|
||||||
* PCIe driver for Marvell Armada 370 and Armada XP SoCs
|
* 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
|
* This file is licensed under the terms of the GNU General Public
|
||||||
* License version 2. This program is licensed "as is" without any
|
* License version 2. This program is licensed "as is" without any
|
||||||
* warranty of any kind, whether express or implied.
|
* warranty of any kind, whether express or implied.
|
||||||
|
@ -11,7 +13,7 @@
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
#include <linux/module.h>
|
#include <linux/init.h>
|
||||||
#include <linux/mbus.h>
|
#include <linux/mbus.h>
|
||||||
#include <linux/msi.h>
|
#include <linux/msi.h>
|
||||||
#include <linux/slab.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)
|
static int mvebu_pcie_setup(int nr, struct pci_sys_data *sys)
|
||||||
{
|
{
|
||||||
struct mvebu_pcie *pcie = sys_to_pcie(sys);
|
struct mvebu_pcie *pcie = sys_to_pcie(sys);
|
||||||
int i;
|
int err, i;
|
||||||
|
|
||||||
pcie->mem.name = "PCI MEM";
|
pcie->mem.name = "PCI MEM";
|
||||||
pcie->realio.name = "PCI I/O";
|
pcie->realio.name = "PCI I/O";
|
||||||
|
|
||||||
if (request_resource(&iomem_resource, &pcie->mem))
|
if (resource_size(&pcie->realio) != 0)
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (resource_size(&pcie->realio) != 0) {
|
|
||||||
if (request_resource(&ioport_resource, &pcie->realio)) {
|
|
||||||
release_resource(&pcie->mem);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
pci_add_resource_offset(&sys->resources, &pcie->realio,
|
pci_add_resource_offset(&sys->resources, &pcie->realio,
|
||||||
sys->io_offset);
|
sys->io_offset);
|
||||||
}
|
|
||||||
pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
|
pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_offset);
|
||||||
pci_add_resource(&sys->resources, &pcie->busn);
|
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++) {
|
for (i = 0; i < pcie->nports; i++) {
|
||||||
struct mvebu_pcie_port *port = &pcie->ports[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", },
|
{ .compatible = "marvell,kirkwood-pcie", },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, mvebu_pcie_of_match_table);
|
|
||||||
|
|
||||||
static const struct dev_pm_ops mvebu_pcie_pm_ops = {
|
static const struct dev_pm_ops mvebu_pcie_pm_ops = {
|
||||||
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mvebu_pcie_suspend, mvebu_pcie_resume)
|
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,
|
.probe = mvebu_pcie_probe,
|
||||||
};
|
};
|
||||||
module_platform_driver(mvebu_pcie_driver);
|
builtin_platform_driver(mvebu_pcie_driver);
|
||||||
|
|
||||||
MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
|
|
||||||
MODULE_DESCRIPTION("Marvell EBU PCIe driver");
|
|
||||||
MODULE_LICENSE("GPL v2");
|
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
* Copyright (C) 2013 Renesas Solutions Corp.
|
* Copyright (C) 2013 Renesas Solutions Corp.
|
||||||
* Copyright (C) 2013 Cogent Embedded, Inc.
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
|
@ -14,7 +16,6 @@
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/of_pci.h>
|
#include <linux/of_pci.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
|
@ -97,7 +98,6 @@
|
||||||
struct rcar_pci_priv {
|
struct rcar_pci_priv {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
void __iomem *reg;
|
void __iomem *reg;
|
||||||
struct resource io_res;
|
|
||||||
struct resource mem_res;
|
struct resource mem_res;
|
||||||
struct resource *cfg_res;
|
struct resource *cfg_res;
|
||||||
unsigned busnr;
|
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;
|
struct rcar_pci_priv *priv = sys->private_data;
|
||||||
void __iomem *reg = priv->reg;
|
void __iomem *reg = priv->reg;
|
||||||
u32 val;
|
u32 val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
pm_runtime_enable(priv->dev);
|
pm_runtime_enable(priv->dev);
|
||||||
pm_runtime_get_sync(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);
|
rcar_pci_setup_errirq(priv);
|
||||||
|
|
||||||
/* Add PCI resources */
|
/* Add PCI resources */
|
||||||
pci_add_resource(&sys->resources, &priv->io_res);
|
|
||||||
pci_add_resource(&sys->resources, &priv->mem_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 */
|
/* Setup bus number based on platform device id / of bus-range */
|
||||||
sys->busnr = priv->busnr;
|
sys->busnr = priv->busnr;
|
||||||
|
@ -371,14 +374,6 @@ static int rcar_pci_probe(struct platform_device *pdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
priv->mem_res = *mem_res;
|
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->cfg_res = cfg_res;
|
||||||
|
|
||||||
priv->irq = platform_get_irq(pdev, 0);
|
priv->irq = platform_get_irq(pdev, 0);
|
||||||
|
@ -421,6 +416,7 @@ static int rcar_pci_probe(struct platform_device *pdev)
|
||||||
hw_private[0] = priv;
|
hw_private[0] = priv;
|
||||||
memset(&hw, 0, sizeof(hw));
|
memset(&hw, 0, sizeof(hw));
|
||||||
hw.nr_controllers = ARRAY_SIZE(hw_private);
|
hw.nr_controllers = ARRAY_SIZE(hw_private);
|
||||||
|
hw.io_optional = 1;
|
||||||
hw.private_data = hw_private;
|
hw.private_data = hw_private;
|
||||||
hw.map_irq = rcar_pci_map_irq;
|
hw.map_irq = rcar_pci_map_irq;
|
||||||
hw.ops = &rcar_pci_ops;
|
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 = {
|
static struct platform_driver rcar_pci_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "pci-rcar-gen2",
|
.name = "pci-rcar-gen2",
|
||||||
|
@ -447,9 +441,4 @@ static struct platform_driver rcar_pci_driver = {
|
||||||
},
|
},
|
||||||
.probe = rcar_pci_probe,
|
.probe = rcar_pci_probe,
|
||||||
};
|
};
|
||||||
|
builtin_platform_driver(rcar_pci_driver);
|
||||||
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>");
|
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
*
|
*
|
||||||
* Bits taken from arch/arm/mach-dove/pcie.c
|
* 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
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
@ -32,7 +34,7 @@
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/irqdomain.h>
|
#include <linux/irqdomain.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/init.h>
|
||||||
#include <linux/msi.h>
|
#include <linux/msi.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/of_pci.h>
|
#include <linux/of_pci.h>
|
||||||
|
@ -274,7 +276,6 @@ struct tegra_pcie {
|
||||||
struct list_head buses;
|
struct list_head buses;
|
||||||
struct resource *cs;
|
struct resource *cs;
|
||||||
|
|
||||||
struct resource all;
|
|
||||||
struct resource io;
|
struct resource io;
|
||||||
struct resource pio;
|
struct resource pio;
|
||||||
struct resource mem;
|
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->mem_offset = pcie->offset.mem;
|
||||||
sys->io_offset = pcie->offset.io;
|
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)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err = devm_request_resource(pcie->dev, &ioport_resource, &pcie->pio);
|
pci_ioremap_io(pcie->pio.start, pcie->io.start);
|
||||||
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_add_resource_offset(&sys->resources, &pcie->pio, sys->io_offset);
|
pci_add_resource_offset(&sys->resources, &pcie->pio, sys->io_offset);
|
||||||
pci_add_resource_offset(&sys->resources, &pcie->mem, sys->mem_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);
|
sys->mem_offset);
|
||||||
pci_add_resource(&sys->resources, &pcie->busn);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1822,12 +1815,6 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
|
||||||
struct resource res;
|
struct resource res;
|
||||||
int err;
|
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)) {
|
if (of_pci_range_parser_init(&parser, np)) {
|
||||||
dev_err(pcie->dev, "missing \"ranges\" property\n");
|
dev_err(pcie->dev, "missing \"ranges\" property\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -1880,18 +1867,8 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
|
||||||
}
|
}
|
||||||
break;
|
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);
|
err = of_pci_parse_bus_range(np, &pcie->busn);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(pcie->dev, "failed to parse ranges property: %d\n",
|
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 },
|
{ .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)
|
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,
|
.probe = tegra_pcie_probe,
|
||||||
};
|
};
|
||||||
module_platform_driver(tegra_pcie_driver);
|
builtin_platform_driver(tegra_pcie_driver);
|
||||||
|
|
||||||
MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
|
|
||||||
MODULE_DESCRIPTION("NVIDIA Tegra PCIe driver");
|
|
||||||
MODULE_LICENSE("GPL v2");
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/init.h>
|
||||||
#include <linux/ioport.h>
|
#include <linux/ioport.h>
|
||||||
#include <linux/of_pci.h>
|
#include <linux/of_pci.h>
|
||||||
#include <linux/of.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" },
|
{ .compatible = "cavium,pci-host-thunder-ecam" },
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, thunder_ecam_of_match);
|
|
||||||
|
|
||||||
static int thunder_ecam_probe(struct platform_device *pdev)
|
static int thunder_ecam_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
@ -373,7 +372,4 @@ static struct platform_driver thunder_ecam_driver = {
|
||||||
},
|
},
|
||||||
.probe = thunder_ecam_probe,
|
.probe = thunder_ecam_probe,
|
||||||
};
|
};
|
||||||
module_platform_driver(thunder_ecam_driver);
|
builtin_platform_driver(thunder_ecam_driver);
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Thunder ECAM PCI host driver");
|
|
||||||
MODULE_LICENSE("GPL v2");
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/init.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/of_pci.h>
|
#include <linux/of_pci.h>
|
||||||
#include <linux/pci-ecam.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" },
|
{ .compatible = "cavium,pci-host-thunder-pem" },
|
||||||
{ },
|
{ },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, thunder_pem_of_match);
|
|
||||||
|
|
||||||
static int thunder_pem_probe(struct platform_device *pdev)
|
static int thunder_pem_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
|
@ -360,7 +359,4 @@ static struct platform_driver thunder_pem_driver = {
|
||||||
},
|
},
|
||||||
.probe = thunder_pem_probe,
|
.probe = thunder_pem_probe,
|
||||||
};
|
};
|
||||||
module_platform_driver(thunder_pem_driver);
|
builtin_platform_driver(thunder_pem_driver);
|
||||||
|
|
||||||
MODULE_DESCRIPTION("Thunder PEM PCIe host driver");
|
|
||||||
MODULE_LICENSE("GPL v2");
|
|
||||||
|
|
|
@ -80,21 +80,21 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev,
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
err = devm_request_pci_bus_resources(dev, res);
|
||||||
|
if (err)
|
||||||
|
goto out_release_res;
|
||||||
|
|
||||||
resource_list_for_each_entry(win, res) {
|
resource_list_for_each_entry(win, res) {
|
||||||
struct resource *parent, *res = win->res;
|
struct resource *res = win->res;
|
||||||
|
|
||||||
switch (resource_type(res)) {
|
switch (resource_type(res)) {
|
||||||
case IORESOURCE_IO:
|
case IORESOURCE_IO:
|
||||||
parent = &ioport_resource;
|
|
||||||
err = pci_remap_iospace(res, iobase);
|
err = pci_remap_iospace(res, iobase);
|
||||||
if (err) {
|
if (err)
|
||||||
dev_warn(dev, "error %d: failed to map resource %pR\n",
|
dev_warn(dev, "error %d: failed to map resource %pR\n",
|
||||||
err, res);
|
err, res);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case IORESOURCE_MEM:
|
case IORESOURCE_MEM:
|
||||||
parent = &iomem_resource;
|
|
||||||
res_valid |= !(res->flags & IORESOURCE_PREFETCH);
|
res_valid |= !(res->flags & IORESOURCE_PREFETCH);
|
||||||
|
|
||||||
writel(res->start >> 28, PCI_IMAP(mem));
|
writel(res->start >> 28, PCI_IMAP(mem));
|
||||||
|
@ -102,23 +102,14 @@ static int versatile_pci_parse_request_of_pci_ranges(struct device *dev,
|
||||||
mem++;
|
mem++;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case IORESOURCE_BUS:
|
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = devm_request_resource(dev, parent, res);
|
|
||||||
if (err)
|
|
||||||
goto out_release_res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!res_valid) {
|
if (res_valid)
|
||||||
dev_err(dev, "non-prefetchable memory resource required\n");
|
return 0;
|
||||||
err = -EINVAL;
|
|
||||||
goto out_release_res;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
dev_err(dev, "non-prefetchable memory resource required\n");
|
||||||
|
err = -EINVAL;
|
||||||
|
|
||||||
out_release_res:
|
out_release_res:
|
||||||
pci_free_resource_list(res);
|
pci_free_resource_list(res);
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/jiffies.h>
|
#include <linux/jiffies.h>
|
||||||
#include <linux/memblock.h>
|
#include <linux/memblock.h>
|
||||||
#include <linux/module.h>
|
#include <linux/init.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/of_irq.h>
|
#include <linux/of_irq.h>
|
||||||
|
@ -540,14 +540,20 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
ret = devm_request_pci_bus_resources(&pdev->dev, &res);
|
||||||
|
if (ret)
|
||||||
|
goto error;
|
||||||
|
|
||||||
ret = xgene_pcie_setup(port, &res, iobase);
|
ret = xgene_pcie_setup(port, &res, iobase);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
goto error;
|
||||||
|
|
||||||
bus = pci_create_root_bus(&pdev->dev, 0,
|
bus = pci_create_root_bus(&pdev->dev, 0,
|
||||||
&xgene_pcie_ops, port, &res);
|
&xgene_pcie_ops, port, &res);
|
||||||
if (!bus)
|
if (!bus) {
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
pci_scan_child_bus(bus);
|
pci_scan_child_bus(bus);
|
||||||
pci_assign_unassigned_bus_resources(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);
|
platform_set_drvdata(pdev, port);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
pci_free_resource_list(&res);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id xgene_pcie_match_table[] = {
|
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,
|
.probe = xgene_pcie_probe_bridge,
|
||||||
};
|
};
|
||||||
module_platform_driver(xgene_pcie_driver);
|
builtin_platform_driver(xgene_pcie_driver);
|
||||||
|
|
||||||
MODULE_AUTHOR("Tanmay Inamdar <tinamdar@apm.com>");
|
|
||||||
MODULE_DESCRIPTION("APM X-Gene PCIe driver");
|
|
||||||
MODULE_LICENSE("GPL v2");
|
|
||||||
|
|
|
@ -415,11 +415,6 @@ static void altera_pcie_isr(struct irq_desc *desc)
|
||||||
chained_irq_exit(chip, 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)
|
static int altera_pcie_parse_request_of_pci_ranges(struct altera_pcie *pcie)
|
||||||
{
|
{
|
||||||
int err, res_valid = 0;
|
int err, res_valid = 0;
|
||||||
|
@ -432,33 +427,25 @@ static int altera_pcie_parse_request_of_pci_ranges(struct altera_pcie *pcie)
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
resource_list_for_each_entry(win, &pcie->resources) {
|
err = devm_request_pci_bus_resources(dev, &pcie->resources);
|
||||||
struct resource *parent, *res = win->res;
|
if (err)
|
||||||
|
|
||||||
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;
|
|
||||||
goto out_release_res;
|
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:
|
out_release_res:
|
||||||
altera_pcie_release_of_pci_ranges(pcie);
|
pci_free_resource_list(&pcie->resources);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2016 Marvell Technology Group Ltd.
|
* 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
|
* This file is licensed under the terms of the GNU General Public
|
||||||
* License version 2. This program is licensed "as is" without any
|
* License version 2. This program is licensed "as is" without any
|
||||||
* warranty of any kind, whether express or implied.
|
* warranty of any kind, whether express or implied.
|
||||||
|
@ -14,7 +17,7 @@
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/init.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/phy/phy.h>
|
#include <linux/phy/phy.h>
|
||||||
|
@ -244,7 +247,6 @@ static const struct of_device_id armada8k_pcie_of_match[] = {
|
||||||
{ .compatible = "marvell,armada8k-pcie", },
|
{ .compatible = "marvell,armada8k-pcie", },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, armada8k_pcie_of_match);
|
|
||||||
|
|
||||||
static struct platform_driver armada8k_pcie_driver = {
|
static struct platform_driver armada8k_pcie_driver = {
|
||||||
.probe = armada8k_pcie_probe,
|
.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),
|
.of_match_table = of_match_ptr(armada8k_pcie_of_match),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
builtin_platform_driver(armada8k_pcie_driver);
|
||||||
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");
|
|
||||||
|
|
|
@ -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);
|
|
@ -14,7 +14,7 @@
|
||||||
#include <linux/gpio.h>
|
#include <linux/gpio.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/init.h>
|
||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/platform_device.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", },
|
{ .compatible = "snps,dw-pcie", },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, dw_plat_pcie_of_match);
|
|
||||||
|
|
||||||
static struct platform_driver dw_plat_pcie_driver = {
|
static struct platform_driver dw_plat_pcie_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
|
@ -130,9 +129,4 @@ static struct platform_driver dw_plat_pcie_driver = {
|
||||||
},
|
},
|
||||||
.probe = dw_plat_pcie_probe,
|
.probe = dw_plat_pcie_probe,
|
||||||
};
|
};
|
||||||
|
builtin_platform_driver(dw_plat_pcie_driver);
|
||||||
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");
|
|
||||||
|
|
|
@ -452,6 +452,10 @@ int dw_pcie_host_init(struct pcie_port *pp)
|
||||||
if (ret)
|
if (ret)
|
||||||
return 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 */
|
/* Get the I/O and memory ranges from DT */
|
||||||
resource_list_for_each_entry(win, &res) {
|
resource_list_for_each_entry(win, &res) {
|
||||||
switch (resource_type(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_size = resource_size(pp->io);
|
||||||
pp->io_bus_addr = pp->io->start - win->offset;
|
pp->io_bus_addr = pp->io->start - win->offset;
|
||||||
ret = pci_remap_iospace(pp->io, pp->io_base);
|
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",
|
dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
|
||||||
ret, pp->io);
|
ret, pp->io);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case IORESOURCE_MEM:
|
case IORESOURCE_MEM:
|
||||||
pp->mem = win->res;
|
pp->mem = win->res;
|
||||||
|
@ -483,8 +485,6 @@ int dw_pcie_host_init(struct pcie_port *pp)
|
||||||
case IORESOURCE_BUS:
|
case IORESOURCE_BUS:
|
||||||
pp->busn = win->res;
|
pp->busn = win->res;
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,7 +493,8 @@ int dw_pcie_host_init(struct pcie_port *pp)
|
||||||
resource_size(pp->cfg));
|
resource_size(pp->cfg));
|
||||||
if (!pp->dbi_base) {
|
if (!pp->dbi_base) {
|
||||||
dev_err(pp->dev, "error with ioremap\n");
|
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);
|
pp->cfg0_size);
|
||||||
if (!pp->va_cfg0_base) {
|
if (!pp->va_cfg0_base) {
|
||||||
dev_err(pp->dev, "error with ioremap in function\n");
|
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);
|
pp->cfg1_size);
|
||||||
if (!pp->va_cfg1_base) {
|
if (!pp->va_cfg1_base) {
|
||||||
dev_err(pp->dev, "error with ioremap\n");
|
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);
|
&dw_pcie_msi_chip);
|
||||||
if (!pp->irq_domain) {
|
if (!pp->irq_domain) {
|
||||||
dev_err(pp->dev, "irq domain init failed\n");
|
dev_err(pp->dev, "irq domain init failed\n");
|
||||||
return -ENXIO;
|
ret = -ENXIO;
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < MAX_MSI_IRQS; i++)
|
for (i = 0; i < MAX_MSI_IRQS; i++)
|
||||||
|
@ -536,7 +540,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
|
||||||
} else {
|
} else {
|
||||||
ret = pp->ops->msi_host_init(pp, &dw_pcie_msi_chip);
|
ret = pp->ops->msi_host_init(pp, &dw_pcie_msi_chip);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,8 +556,10 @@ int dw_pcie_host_init(struct pcie_port *pp)
|
||||||
} else
|
} else
|
||||||
bus = pci_scan_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
|
bus = pci_scan_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
|
||||||
pp, &res);
|
pp, &res);
|
||||||
if (!bus)
|
if (!bus) {
|
||||||
return -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
if (pp->ops->scan_bus)
|
if (pp->ops->scan_bus)
|
||||||
pp->ops->scan_bus(pp);
|
pp->ops->scan_bus(pp);
|
||||||
|
@ -571,6 +577,10 @@ int dw_pcie_host_init(struct pcie_port *pp)
|
||||||
|
|
||||||
pci_bus_add_devices(bus);
|
pci_bus_add_devices(bus);
|
||||||
return 0;
|
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,
|
static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/module.h>
|
#include <linux/init.h>
|
||||||
#include <linux/mfd/syscon.h>
|
#include <linux/mfd/syscon.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/of_pci.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 = {
|
static struct platform_driver hisi_pcie_driver = {
|
||||||
.probe = hisi_pcie_probe,
|
.probe = hisi_pcie_probe,
|
||||||
.driver = {
|
.driver = {
|
||||||
|
@ -245,10 +242,4 @@ static struct platform_driver hisi_pcie_driver = {
|
||||||
.of_match_table = hisi_pcie_of_match,
|
.of_match_table = hisi_pcie_of_match,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
builtin_platform_driver(hisi_pcie_driver);
|
||||||
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");
|
|
||||||
|
|
|
@ -462,6 +462,10 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
|
||||||
if (!pcie || !pcie->dev || !pcie->base)
|
if (!pcie || !pcie->dev || !pcie->base)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = devm_request_pci_bus_resources(pcie->dev, res);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
ret = phy_init(pcie->phy);
|
ret = phy_init(pcie->phy);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(pcie->dev, "unable to initialize PCIe PHY\n");
|
dev_err(pcie->dev, "unable to initialize PCIe PHY\n");
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
* arch/sh/drivers/pci/ops-sh7786.c
|
* arch/sh/drivers/pci/ops-sh7786.c
|
||||||
* Copyright (C) 2009 - 2011 Paul Mundt
|
* 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
|
* This file is licensed under the terms of the GNU General Public
|
||||||
* License version 2. This program is licensed "as is" without any
|
* License version 2. This program is licensed "as is" without any
|
||||||
* warranty of any kind, whether express or implied.
|
* warranty of any kind, whether express or implied.
|
||||||
|
@ -18,7 +20,7 @@
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/irqdomain.h>
|
#include <linux/irqdomain.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/module.h>
|
#include <linux/init.h>
|
||||||
#include <linux/msi.h>
|
#include <linux/msi.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/of_irq.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 },
|
{ .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)
|
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)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
resource_list_for_each_entry(win, &pci->resources) {
|
err = devm_request_pci_bus_resources(dev, &pci->resources);
|
||||||
struct resource *parent, *res = win->res;
|
if (err)
|
||||||
|
goto out_release_res;
|
||||||
|
|
||||||
switch (resource_type(res)) {
|
resource_list_for_each_entry(win, &pci->resources) {
|
||||||
case IORESOURCE_IO:
|
struct resource *res = win->res;
|
||||||
parent = &ioport_resource;
|
|
||||||
|
if (resource_type(res) == IORESOURCE_IO) {
|
||||||
err = pci_remap_iospace(res, iobase);
|
err = pci_remap_iospace(res, iobase);
|
||||||
if (err) {
|
if (err)
|
||||||
dev_warn(dev, "error %d: failed to map resource %pR\n",
|
dev_warn(dev, "error %d: failed to map resource %pR\n",
|
||||||
err, res);
|
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;
|
return 0;
|
||||||
|
|
||||||
out_release_res:
|
out_release_res:
|
||||||
rcar_pcie_release_of_pci_ranges(pci);
|
pci_free_resource_list(&pci->resources);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1073,8 +1057,4 @@ static struct platform_driver rcar_pcie_driver = {
|
||||||
},
|
},
|
||||||
.probe = rcar_pcie_probe,
|
.probe = rcar_pcie_probe,
|
||||||
};
|
};
|
||||||
module_platform_driver(rcar_pcie_driver);
|
builtin_platform_driver(rcar_pcie_driver);
|
||||||
|
|
||||||
MODULE_AUTHOR("Phil Edworthy <phil.edworthy@renesas.com>");
|
|
||||||
MODULE_DESCRIPTION("Renesas R-Car PCIe driver");
|
|
||||||
MODULE_LICENSE("GPL v2");
|
|
||||||
|
|
|
@ -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);
|
err = of_pci_get_host_bridge_resources(node, 0, 0xff, &res, &iobase);
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_err("Getting bridge resources failed\n");
|
dev_err(pcie->dev, "Getting bridge resources failed\n");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = devm_request_pci_bus_resources(pcie->dev, &res);
|
||||||
|
if (err)
|
||||||
|
goto error;
|
||||||
|
|
||||||
err = nwl_pcie_init_irq_domain(pcie);
|
err = nwl_pcie_init_irq_domain(pcie);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(pcie->dev, "Failed creating IRQ Domain\n");
|
dev_err(pcie->dev, "Failed creating IRQ Domain\n");
|
||||||
return err;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
bus = pci_create_root_bus(&pdev->dev, pcie->root_busno,
|
bus = pci_create_root_bus(&pdev->dev, pcie->root_busno,
|
||||||
&nwl_pcie_ops, pcie, &res);
|
&nwl_pcie_ops, pcie, &res);
|
||||||
if (!bus)
|
if (!bus) {
|
||||||
return -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
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, bus);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(&pdev->dev,
|
dev_err(&pdev->dev,
|
||||||
"failed to enable MSI support: %d\n", err);
|
"failed to enable MSI support: %d\n", err);
|
||||||
return err;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pci_scan_child_bus(bus);
|
pci_scan_child_bus(bus);
|
||||||
|
@ -855,6 +861,10 @@ static int nwl_pcie_probe(struct platform_device *pdev)
|
||||||
pci_bus_add_devices(bus);
|
pci_bus_add_devices(bus);
|
||||||
platform_set_drvdata(pdev, pcie);
|
platform_set_drvdata(pdev, pcie);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
pci_free_resource_list(&res);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int nwl_pcie_remove(struct platform_device *pdev)
|
static int nwl_pcie_remove(struct platform_device *pdev)
|
||||||
|
|
|
@ -660,7 +660,6 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
|
||||||
struct xilinx_pcie_port *port;
|
struct xilinx_pcie_port *port;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct pci_bus *bus;
|
struct pci_bus *bus;
|
||||||
|
|
||||||
int err;
|
int err;
|
||||||
resource_size_t iobase = 0;
|
resource_size_t iobase = 0;
|
||||||
LIST_HEAD(res);
|
LIST_HEAD(res);
|
||||||
|
@ -694,10 +693,17 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
|
||||||
dev_err(dev, "Getting bridge resources failed\n");
|
dev_err(dev, "Getting bridge resources failed\n");
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = devm_request_pci_bus_resources(dev, &res);
|
||||||
|
if (err)
|
||||||
|
goto error;
|
||||||
|
|
||||||
bus = pci_create_root_bus(&pdev->dev, 0,
|
bus = pci_create_root_bus(&pdev->dev, 0,
|
||||||
&xilinx_pcie_ops, port, &res);
|
&xilinx_pcie_ops, port, &res);
|
||||||
if (!bus)
|
if (!bus) {
|
||||||
return -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PCI_MSI
|
#ifdef CONFIG_PCI_MSI
|
||||||
xilinx_pcie_msi_chip.dev = port->dev;
|
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);
|
platform_set_drvdata(pdev, port);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
pci_free_resource_list(&res);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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,
|
void pci_add_resource_offset(struct list_head *resources, struct resource *res,
|
||||||
resource_size_t offset);
|
resource_size_t offset);
|
||||||
void pci_free_resource_list(struct list_head *resources);
|
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);
|
struct resource *pci_bus_resource_n(const struct pci_bus *bus, int n);
|
||||||
void pci_bus_remove_resources(struct pci_bus *bus);
|
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) \
|
#define pci_bus_for_each_resource(bus, res, i) \
|
||||||
for (i = 0; \
|
for (i = 0; \
|
||||||
|
|
Loading…
Reference in New Issue