mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-14 21:01:29 +00:00
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()
This commit is contained in:
commit
79dd993461
46
Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt
Normal file
46
Documentation/devicetree/bindings/pci/axis,artpec6-pcie.txt
Normal 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>;
|
||||
};
|
@ -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>
|
||||
|
@ -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 *);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
280
drivers/pci/host/pcie-artpec6.c
Normal file
280
drivers/pci/host/pcie-artpec6.c
Normal 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);
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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; \
|
||||
|
Loading…
Reference in New Issue
Block a user