aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/host
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/host')
-rw-r--r--drivers/pci/host/Kconfig113
-rw-r--r--drivers/pci/host/Makefile12
-rw-r--r--drivers/pci/host/pci-dra7xx.c525
-rw-r--r--drivers/pci/host/pci-exynos.c629
-rw-r--r--drivers/pci/host/pci-host-common.c2
-rw-r--r--drivers/pci/host/pci-hyperv.c20
-rw-r--r--drivers/pci/host/pci-imx6.c757
-rw-r--r--drivers/pci/host/pci-keystone-dw.c560
-rw-r--r--drivers/pci/host/pci-keystone.c444
-rw-r--r--drivers/pci/host/pci-keystone.h63
-rw-r--r--drivers/pci/host/pci-layerscape.c284
-rw-r--r--drivers/pci/host/pci-mvebu.c103
-rw-r--r--drivers/pci/host/pci-thunder-pem.c25
-rw-r--r--drivers/pci/host/pci-versatile.c4
-rw-r--r--drivers/pci/host/pci-xgene.c11
-rw-r--r--drivers/pci/host/pcie-altera.c2
-rw-r--r--drivers/pci/host/pcie-armada8k.c254
-rw-r--r--drivers/pci/host/pcie-artpec6.c283
-rw-r--r--drivers/pci/host/pcie-designware-plat.c126
-rw-r--r--drivers/pci/host/pcie-designware.c902
-rw-r--r--drivers/pci/host/pcie-designware.h86
-rw-r--r--drivers/pci/host/pcie-hisi.c326
-rw-r--r--drivers/pci/host/pcie-iproc-platform.c7
-rw-r--r--drivers/pci/host/pcie-iproc.c5
-rw-r--r--drivers/pci/host/pcie-qcom.c753
-rw-r--r--drivers/pci/host/pcie-rcar.c9
-rw-r--r--drivers/pci/host/pcie-rockchip.c175
-rw-r--r--drivers/pci/host/pcie-spear13xx.c299
-rw-r--r--drivers/pci/host/pcie-xilinx-nwl.c14
-rw-r--r--drivers/pci/host/pcie-xilinx.c4
-rw-r--r--drivers/pci/host/vmd.c2
31 files changed, 257 insertions, 6542 deletions
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index 898d2c48239c..f7c1d4d5c665 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -1,16 +1,6 @@
menu "PCI host controller drivers"
depends on PCI
-config PCI_DRA7XX
- bool "TI DRA7xx PCIe controller"
- depends on OF && HAS_IOMEM && TI_PIPE3
- depends on PCI_MSI_IRQ_DOMAIN
- select PCIE_DW
- help
- Enables support for the PCIe controller in the DRA7xx SoC. There
- are two instances of PCIe controller in DRA7xx. This controller can
- act both as EP and RC. This reuses the Designware core.
-
config PCI_MVEBU
bool "Marvell EBU PCIe controller"
depends on ARCH_MVEBU || ARCH_DOVE
@@ -37,36 +27,6 @@ config PCIE_XILINX_NWL
or End Point. The current option selection will only
support root port enabling.
-config PCIE_DW_PLAT
- bool "Platform bus based DesignWare PCIe Controller"
- depends on PCI_MSI_IRQ_DOMAIN
- select PCIE_DW
- ---help---
- This selects the DesignWare PCIe controller support. Select this if
- you have a PCIe controller on Platform bus.
-
- If you have a controller with this interface, say Y or M here.
-
- If unsure, say N.
-
-config PCIE_DW
- bool
- depends on PCI_MSI_IRQ_DOMAIN
-
-config PCI_EXYNOS
- bool "Samsung Exynos PCIe controller"
- depends on SOC_EXYNOS5440
- depends on PCI_MSI_IRQ_DOMAIN
- select PCIEPORTBUS
- select PCIE_DW
-
-config PCI_IMX6
- bool "Freescale i.MX6 PCIe controller"
- depends on SOC_IMX6Q
- depends on PCI_MSI_IRQ_DOMAIN
- select PCIEPORTBUS
- select PCIE_DW
-
config PCI_TEGRA
bool "NVIDIA Tegra PCIe controller"
depends on ARCH_TEGRA
@@ -103,27 +63,6 @@ config PCI_HOST_GENERIC
Say Y here if you want to support a simple generic PCI host
controller, such as the one emulated by kvmtool.
-config PCIE_SPEAR13XX
- bool "STMicroelectronics SPEAr PCIe controller"
- depends on ARCH_SPEAR13XX
- depends on PCI_MSI_IRQ_DOMAIN
- select PCIEPORTBUS
- select PCIE_DW
- help
- Say Y here if you want PCIe support on SPEAr13XX SoCs.
-
-config PCI_KEYSTONE
- bool "TI Keystone PCIe controller"
- depends on ARCH_KEYSTONE
- depends on PCI_MSI_IRQ_DOMAIN
- select PCIE_DW
- select PCIEPORTBUS
- help
- Say Y here if you want to enable PCI controller support on Keystone
- SoCs. The PCI controller on Keystone is based on Designware hardware
- and therefore the driver re-uses the Designware core functions to
- implement the driver.
-
config PCIE_XILINX
bool "Xilinx AXI PCIe host bridge support"
depends on ARCH_ZYNQ || MICROBLAZE
@@ -150,15 +89,6 @@ config PCI_XGENE_MSI
Say Y here if you want PCIe MSI support for the APM X-Gene v1 SoC.
This MSI driver supports 5 PCIe ports on the APM X-Gene v1 SoC.
-config PCI_LAYERSCAPE
- bool "Freescale Layerscape PCIe controller"
- depends on OF && (ARM || ARCH_LAYERSCAPE)
- depends on PCI_MSI_IRQ_DOMAIN
- select PCIE_DW
- select MFD_SYSCON
- help
- Say Y here if you want PCIe controller support on Layerscape SoCs.
-
config PCI_VERSATILE
bool "ARM Versatile PB PCI controller"
depends on ARCH_VERSATILE
@@ -217,27 +147,6 @@ config PCIE_ALTERA_MSI
Say Y here if you want PCIe MSI support for the Altera FPGA.
This MSI driver supports Altera MSI to GIC controller IP.
-config PCI_HISI
- depends on OF && ARM64
- bool "HiSilicon Hip05 and Hip06 SoCs PCIe controllers"
- depends on PCI_MSI_IRQ_DOMAIN
- select PCIEPORTBUS
- select PCIE_DW
- help
- Say Y here if you want PCIe controller support on HiSilicon
- Hip05 and Hip06 SoCs
-
-config PCIE_QCOM
- bool "Qualcomm PCIe controller"
- depends on ARCH_QCOM && OF
- depends on PCI_MSI_IRQ_DOMAIN
- select PCIE_DW
- select PCIEPORTBUS
- help
- Say Y here to enable PCIe controller support on Qualcomm SoCs. The
- PCIe controller uses the Designware core plus Qualcomm-specific
- hardware wrappers.
-
config PCI_HOST_THUNDER_PEM
bool "Cavium Thunder PCIe controller to off-chip devices"
depends on ARM64
@@ -254,28 +163,6 @@ config PCI_HOST_THUNDER_ECAM
help
Say Y here if you want ECAM support for CN88XX-Pass-1.x Cavium Thunder SoCs.
-config PCIE_ARMADA_8K
- bool "Marvell Armada-8K PCIe controller"
- depends on ARCH_MVEBU
- depends on PCI_MSI_IRQ_DOMAIN
- select PCIE_DW
- select PCIEPORTBUS
- help
- Say Y here if you want to enable PCIe controller support on
- Armada-8K SoCs. The PCIe controller on Armada-8K is based on
- 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.
-
config PCIE_ROCKCHIP
bool "Rockchip PCIe controller"
depends on ARCH_ROCKCHIP || COMPILE_TEST
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index bfe3179ae74c..4d3686676cc3 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -1,8 +1,3 @@
-obj-$(CONFIG_PCIE_DW) += pcie-designware.o
-obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o
-obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
-obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
-obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o
obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
@@ -11,12 +6,9 @@ obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o
obj-$(CONFIG_PCIE_RCAR) += pcie-rcar.o
obj-$(CONFIG_PCI_HOST_COMMON) += pci-host-common.o
obj-$(CONFIG_PCI_HOST_GENERIC) += pci-host-generic.o
-obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
-obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o
obj-$(CONFIG_PCIE_XILINX) += pcie-xilinx.o
obj-$(CONFIG_PCIE_XILINX_NWL) += pcie-xilinx-nwl.o
obj-$(CONFIG_PCI_XGENE_MSI) += pci-xgene-msi.o
-obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o
obj-$(CONFIG_PCI_VERSATILE) += pci-versatile.o
obj-$(CONFIG_PCIE_IPROC) += pcie-iproc.o
obj-$(CONFIG_PCIE_IPROC_MSI) += pcie-iproc-msi.o
@@ -24,9 +16,6 @@ obj-$(CONFIG_PCIE_IPROC_PLATFORM) += pcie-iproc-platform.o
obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o
obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o
obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
-obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o
-obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
-obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o
obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o
obj-$(CONFIG_VMD) += vmd.o
@@ -40,7 +29,6 @@ obj-$(CONFIG_VMD) += vmd.o
# ARM64 and use internal ifdefs to only build the pieces we need
# depending on whether ACPI, the DT driver, or both are enabled.
-obj-$(CONFIG_ARM64) += pcie-hisi.o
obj-$(CONFIG_ARM64) += pci-thunder-ecam.o
obj-$(CONFIG_ARM64) += pci-thunder-pem.o
obj-$(CONFIG_ARM64) += pci-xgene.o
diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
deleted file mode 100644
index 9595fad63f6f..000000000000
--- a/drivers/pci/host/pci-dra7xx.c
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- * pcie-dra7xx - PCIe controller driver for TI DRA7xx SoCs
- *
- * Copyright (C) 2013-2014 Texas Instruments Incorporated - http://www.ti.com
- *
- * Authors: Kishon Vijay Abraham I <kishon@ti.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.
- */
-
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/of_gpio.h>
-#include <linux/pci.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/resource.h>
-#include <linux/types.h>
-
-#include "pcie-designware.h"
-
-/* PCIe controller wrapper DRA7XX configuration registers */
-
-#define PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN 0x0024
-#define PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MAIN 0x0028
-#define ERR_SYS BIT(0)
-#define ERR_FATAL BIT(1)
-#define ERR_NONFATAL BIT(2)
-#define ERR_COR BIT(3)
-#define ERR_AXI BIT(4)
-#define ERR_ECRC BIT(5)
-#define PME_TURN_OFF BIT(8)
-#define PME_TO_ACK BIT(9)
-#define PM_PME BIT(10)
-#define LINK_REQ_RST BIT(11)
-#define LINK_UP_EVT BIT(12)
-#define CFG_BME_EVT BIT(13)
-#define CFG_MSE_EVT BIT(14)
-#define INTERRUPTS (ERR_SYS | ERR_FATAL | ERR_NONFATAL | ERR_COR | ERR_AXI | \
- ERR_ECRC | PME_TURN_OFF | PME_TO_ACK | PM_PME | \
- LINK_REQ_RST | LINK_UP_EVT | CFG_BME_EVT | CFG_MSE_EVT)
-
-#define PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI 0x0034
-#define PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI 0x0038
-#define INTA BIT(0)
-#define INTB BIT(1)
-#define INTC BIT(2)
-#define INTD BIT(3)
-#define MSI BIT(4)
-#define LEG_EP_INTERRUPTS (INTA | INTB | INTC | INTD)
-
-#define PCIECTRL_DRA7XX_CONF_DEVICE_CMD 0x0104
-#define LTSSM_EN 0x1
-
-#define PCIECTRL_DRA7XX_CONF_PHY_CS 0x010C
-#define LINK_UP BIT(16)
-#define DRA7XX_CPU_TO_BUS_ADDR 0x0FFFFFFF
-
-struct dra7xx_pcie {
- struct pcie_port pp;
- void __iomem *base; /* DT ti_conf */
- int phy_count; /* DT phy-names count */
- struct phy **phy;
-};
-
-#define to_dra7xx_pcie(x) container_of((x), struct dra7xx_pcie, pp)
-
-static inline u32 dra7xx_pcie_readl(struct dra7xx_pcie *pcie, u32 offset)
-{
- return readl(pcie->base + offset);
-}
-
-static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset,
- u32 value)
-{
- writel(value, pcie->base + offset);
-}
-
-static int dra7xx_pcie_link_up(struct pcie_port *pp)
-{
- struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
- u32 reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_PHY_CS);
-
- return !!(reg & LINK_UP);
-}
-
-static int dra7xx_pcie_establish_link(struct dra7xx_pcie *dra7xx)
-{
- struct pcie_port *pp = &dra7xx->pp;
- struct device *dev = pp->dev;
- u32 reg;
-
- if (dw_pcie_link_up(pp)) {
- dev_err(dev, "link is already up\n");
- return 0;
- }
-
- reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD);
- reg |= LTSSM_EN;
- dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg);
-
- return dw_pcie_wait_for_link(pp);
-}
-
-static void dra7xx_pcie_enable_interrupts(struct dra7xx_pcie *dra7xx)
-{
- dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN,
- ~INTERRUPTS);
- dra7xx_pcie_writel(dra7xx,
- PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MAIN, INTERRUPTS);
- dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI,
- ~LEG_EP_INTERRUPTS & ~MSI);
-
- if (IS_ENABLED(CONFIG_PCI_MSI))
- dra7xx_pcie_writel(dra7xx,
- PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI, MSI);
- else
- dra7xx_pcie_writel(dra7xx,
- PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI,
- LEG_EP_INTERRUPTS);
-}
-
-static void dra7xx_pcie_host_init(struct pcie_port *pp)
-{
- struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp);
-
- pp->io_base &= DRA7XX_CPU_TO_BUS_ADDR;
- pp->mem_base &= DRA7XX_CPU_TO_BUS_ADDR;
- pp->cfg0_base &= DRA7XX_CPU_TO_BUS_ADDR;
- pp->cfg1_base &= DRA7XX_CPU_TO_BUS_ADDR;
-
- dw_pcie_setup_rc(pp);
-
- dra7xx_pcie_establish_link(dra7xx);
- if (IS_ENABLED(CONFIG_PCI_MSI))
- dw_pcie_msi_init(pp);
- dra7xx_pcie_enable_interrupts(dra7xx);
-}
-
-static struct pcie_host_ops dra7xx_pcie_host_ops = {
- .link_up = dra7xx_pcie_link_up,
- .host_init = dra7xx_pcie_host_init,
-};
-
-static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
- irq_set_chip_data(irq, domain->host_data);
-
- return 0;
-}
-
-static const struct irq_domain_ops intx_domain_ops = {
- .map = dra7xx_pcie_intx_map,
-};
-
-static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp)
-{
- struct device *dev = pp->dev;
- struct device_node *node = dev->of_node;
- struct device_node *pcie_intc_node = of_get_next_child(node, NULL);
-
- if (!pcie_intc_node) {
- dev_err(dev, "No PCIe Intc node found\n");
- return -ENODEV;
- }
-
- pp->irq_domain = irq_domain_add_linear(pcie_intc_node, 4,
- &intx_domain_ops, pp);
- if (!pp->irq_domain) {
- dev_err(dev, "Failed to get a INTx IRQ domain\n");
- return -ENODEV;
- }
-
- return 0;
-}
-
-static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg)
-{
- struct dra7xx_pcie *dra7xx = arg;
- struct pcie_port *pp = &dra7xx->pp;
- u32 reg;
-
- reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI);
-
- switch (reg) {
- case MSI:
- dw_handle_msi_irq(pp);
- break;
- case INTA:
- case INTB:
- case INTC:
- case INTD:
- generic_handle_irq(irq_find_mapping(pp->irq_domain, ffs(reg)));
- break;
- }
-
- dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI, reg);
-
- return IRQ_HANDLED;
-}
-
-
-static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg)
-{
- struct dra7xx_pcie *dra7xx = arg;
- struct device *dev = dra7xx->pp.dev;
- u32 reg;
-
- reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN);
-
- if (reg & ERR_SYS)
- dev_dbg(dev, "System Error\n");
-
- if (reg & ERR_FATAL)
- dev_dbg(dev, "Fatal Error\n");
-
- if (reg & ERR_NONFATAL)
- dev_dbg(dev, "Non Fatal Error\n");
-
- if (reg & ERR_COR)
- dev_dbg(dev, "Correctable Error\n");
-
- if (reg & ERR_AXI)
- dev_dbg(dev, "AXI tag lookup fatal Error\n");
-
- if (reg & ERR_ECRC)
- dev_dbg(dev, "ECRC Error\n");
-
- if (reg & PME_TURN_OFF)
- dev_dbg(dev,
- "Power Management Event Turn-Off message received\n");
-
- if (reg & PME_TO_ACK)
- dev_dbg(dev,
- "Power Management Turn-Off Ack message received\n");
-
- if (reg & PM_PME)
- dev_dbg(dev, "PM Power Management Event message received\n");
-
- if (reg & LINK_REQ_RST)
- dev_dbg(dev, "Link Request Reset\n");
-
- if (reg & LINK_UP_EVT)
- dev_dbg(dev, "Link-up state change\n");
-
- if (reg & CFG_BME_EVT)
- dev_dbg(dev, "CFG 'Bus Master Enable' change\n");
-
- if (reg & CFG_MSE_EVT)
- dev_dbg(dev, "CFG 'Memory Space Enable' change\n");
-
- dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN, reg);
-
- return IRQ_HANDLED;
-}
-
-static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
- struct platform_device *pdev)
-{
- int ret;
- struct pcie_port *pp = &dra7xx->pp;
- struct device *dev = pp->dev;
- struct resource *res;
-
- pp->irq = platform_get_irq(pdev, 1);
- if (pp->irq < 0) {
- dev_err(dev, "missing IRQ resource\n");
- return -EINVAL;
- }
-
- ret = devm_request_irq(dev, pp->irq, dra7xx_pcie_msi_irq_handler,
- IRQF_SHARED | IRQF_NO_THREAD,
- "dra7-pcie-msi", dra7xx);
- if (ret) {
- dev_err(dev, "failed to request irq\n");
- return ret;
- }
-
- if (!IS_ENABLED(CONFIG_PCI_MSI)) {
- ret = dra7xx_pcie_init_irq_domain(pp);
- if (ret < 0)
- return ret;
- }
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbics");
- pp->dbi_base = devm_ioremap(dev, res->start, resource_size(res));
- if (!pp->dbi_base)
- return -ENOMEM;
-
- ret = dw_pcie_host_init(pp);
- if (ret) {
- dev_err(dev, "failed to initialize host\n");
- return ret;
- }
-
- return 0;
-}
-
-static int __init dra7xx_pcie_probe(struct platform_device *pdev)
-{
- u32 reg;
- int ret;
- int irq;
- int i;
- int phy_count;
- struct phy **phy;
- void __iomem *base;
- struct resource *res;
- struct dra7xx_pcie *dra7xx;
- struct pcie_port *pp;
- struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
- char name[10];
- int gpio_sel;
- enum of_gpio_flags flags;
- unsigned long gpio_flags;
-
- dra7xx = devm_kzalloc(dev, sizeof(*dra7xx), GFP_KERNEL);
- if (!dra7xx)
- return -ENOMEM;
-
- pp = &dra7xx->pp;
- pp->dev = dev;
- pp->ops = &dra7xx_pcie_host_ops;
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- dev_err(dev, "missing IRQ resource\n");
- return -EINVAL;
- }
-
- ret = devm_request_irq(dev, irq, dra7xx_pcie_irq_handler,
- IRQF_SHARED, "dra7xx-pcie-main", dra7xx);
- if (ret) {
- dev_err(dev, "failed to request irq\n");
- return ret;
- }
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ti_conf");
- base = devm_ioremap_nocache(dev, res->start, resource_size(res));
- if (!base)
- return -ENOMEM;
-
- phy_count = of_property_count_strings(np, "phy-names");
- if (phy_count < 0) {
- dev_err(dev, "unable to find the strings\n");
- return phy_count;
- }
-
- phy = devm_kzalloc(dev, sizeof(*phy) * phy_count, GFP_KERNEL);
- if (!phy)
- return -ENOMEM;
-
- for (i = 0; i < phy_count; i++) {
- snprintf(name, sizeof(name), "pcie-phy%d", i);
- phy[i] = devm_phy_get(dev, name);
- if (IS_ERR(phy[i]))
- return PTR_ERR(phy[i]);
-
- ret = phy_init(phy[i]);
- if (ret < 0)
- goto err_phy;
-
- ret = phy_power_on(phy[i]);
- if (ret < 0) {
- phy_exit(phy[i]);
- goto err_phy;
- }
- }
-
- dra7xx->base = base;
- dra7xx->phy = phy;
- dra7xx->phy_count = phy_count;
-
- pm_runtime_enable(dev);
- ret = pm_runtime_get_sync(dev);
- if (ret < 0) {
- dev_err(dev, "pm_runtime_get_sync failed\n");
- goto err_get_sync;
- }
-
- gpio_sel = of_get_gpio_flags(dev->of_node, 0, &flags);
- if (gpio_is_valid(gpio_sel)) {
- gpio_flags = (flags & OF_GPIO_ACTIVE_LOW) ?
- GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
- ret = devm_gpio_request_one(dev, gpio_sel, gpio_flags,
- "pcie_reset");
- if (ret) {
- dev_err(dev, "gpio%d request failed, ret %d\n",
- gpio_sel, ret);
- goto err_gpio;
- }
- } else if (gpio_sel == -EPROBE_DEFER) {
- ret = -EPROBE_DEFER;
- goto err_gpio;
- }
-
- reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD);
- reg &= ~LTSSM_EN;
- dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg);
-
- ret = dra7xx_add_pcie_port(dra7xx, pdev);
- if (ret < 0)
- goto err_gpio;
-
- platform_set_drvdata(pdev, dra7xx);
- return 0;
-
-err_gpio:
- pm_runtime_put(dev);
-
-err_get_sync:
- pm_runtime_disable(dev);
-
-err_phy:
- while (--i >= 0) {
- phy_power_off(phy[i]);
- phy_exit(phy[i]);
- }
-
- return ret;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int dra7xx_pcie_suspend(struct device *dev)
-{
- struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
- struct pcie_port *pp = &dra7xx->pp;
- u32 val;
-
- /* clear MSE */
- val = dw_pcie_readl_rc(pp, PCI_COMMAND);
- val &= ~PCI_COMMAND_MEMORY;
- dw_pcie_writel_rc(pp, PCI_COMMAND, val);
-
- return 0;
-}
-
-static int dra7xx_pcie_resume(struct device *dev)
-{
- struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
- struct pcie_port *pp = &dra7xx->pp;
- u32 val;
-
- /* set MSE */
- val = dw_pcie_readl_rc(pp, PCI_COMMAND);
- val |= PCI_COMMAND_MEMORY;
- dw_pcie_writel_rc(pp, PCI_COMMAND, val);
-
- return 0;
-}
-
-static int dra7xx_pcie_suspend_noirq(struct device *dev)
-{
- struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
- int count = dra7xx->phy_count;
-
- while (count--) {
- phy_power_off(dra7xx->phy[count]);
- phy_exit(dra7xx->phy[count]);
- }
-
- return 0;
-}
-
-static int dra7xx_pcie_resume_noirq(struct device *dev)
-{
- struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev);
- int phy_count = dra7xx->phy_count;
- int ret;
- int i;
-
- for (i = 0; i < phy_count; i++) {
- ret = phy_init(dra7xx->phy[i]);
- if (ret < 0)
- goto err_phy;
-
- ret = phy_power_on(dra7xx->phy[i]);
- if (ret < 0) {
- phy_exit(dra7xx->phy[i]);
- goto err_phy;
- }
- }
-
- return 0;
-
-err_phy:
- while (--i >= 0) {
- phy_power_off(dra7xx->phy[i]);
- phy_exit(dra7xx->phy[i]);
- }
-
- return ret;
-}
-#endif
-
-static const struct dev_pm_ops dra7xx_pcie_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend, dra7xx_pcie_resume)
- SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(dra7xx_pcie_suspend_noirq,
- dra7xx_pcie_resume_noirq)
-};
-
-static const struct of_device_id of_dra7xx_pcie_match[] = {
- { .compatible = "ti,dra7-pcie", },
- {},
-};
-
-static struct platform_driver dra7xx_pcie_driver = {
- .driver = {
- .name = "dra7-pcie",
- .of_match_table = of_dra7xx_pcie_match,
- .suppress_bind_attrs = true,
- .pm = &dra7xx_pcie_pm_ops,
- },
-};
-builtin_platform_driver_probe(dra7xx_pcie_driver, dra7xx_pcie_probe);
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
deleted file mode 100644
index f1c544bb8b68..000000000000
--- a/drivers/pci/host/pci-exynos.c
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
- * PCIe host controller driver for Samsung EXYNOS SoCs
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Author: Jingoo Han <jg1.han@samsung.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.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/of_gpio.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/resource.h>
-#include <linux/signal.h>
-#include <linux/types.h>
-
-#include "pcie-designware.h"
-
-#define to_exynos_pcie(x) container_of(x, struct exynos_pcie, pp)
-
-struct exynos_pcie {
- struct pcie_port pp;
- void __iomem *elbi_base; /* DT 0th resource */
- void __iomem *phy_base; /* DT 1st resource */
- void __iomem *block_base; /* DT 2nd resource */
- int reset_gpio;
- struct clk *clk;
- struct clk *bus_clk;
-};
-
-/* PCIe ELBI registers */
-#define PCIE_IRQ_PULSE 0x000
-#define IRQ_INTA_ASSERT (0x1 << 0)
-#define IRQ_INTB_ASSERT (0x1 << 2)
-#define IRQ_INTC_ASSERT (0x1 << 4)
-#define IRQ_INTD_ASSERT (0x1 << 6)
-#define PCIE_IRQ_LEVEL 0x004
-#define PCIE_IRQ_SPECIAL 0x008
-#define PCIE_IRQ_EN_PULSE 0x00c
-#define PCIE_IRQ_EN_LEVEL 0x010
-#define IRQ_MSI_ENABLE (0x1 << 2)
-#define PCIE_IRQ_EN_SPECIAL 0x014
-#define PCIE_PWR_RESET 0x018
-#define PCIE_CORE_RESET 0x01c
-#define PCIE_CORE_RESET_ENABLE (0x1 << 0)
-#define PCIE_STICKY_RESET 0x020
-#define PCIE_NONSTICKY_RESET 0x024
-#define PCIE_APP_INIT_RESET 0x028
-#define PCIE_APP_LTSSM_ENABLE 0x02c
-#define PCIE_ELBI_RDLH_LINKUP 0x064
-#define PCIE_ELBI_LTSSM_ENABLE 0x1
-#define PCIE_ELBI_SLV_AWMISC 0x11c
-#define PCIE_ELBI_SLV_ARMISC 0x120
-#define PCIE_ELBI_SLV_DBI_ENABLE (0x1 << 21)
-
-/* PCIe Purple registers */
-#define PCIE_PHY_GLOBAL_RESET 0x000
-#define PCIE_PHY_COMMON_RESET 0x004
-#define PCIE_PHY_CMN_REG 0x008
-#define PCIE_PHY_MAC_RESET 0x00c
-#define PCIE_PHY_PLL_LOCKED 0x010
-#define PCIE_PHY_TRSVREG_RESET 0x020
-#define PCIE_PHY_TRSV_RESET 0x024
-
-/* PCIe PHY registers */
-#define PCIE_PHY_IMPEDANCE 0x004
-#define PCIE_PHY_PLL_DIV_0 0x008
-#define PCIE_PHY_PLL_BIAS 0x00c
-#define PCIE_PHY_DCC_FEEDBACK 0x014
-#define PCIE_PHY_PLL_DIV_1 0x05c
-#define PCIE_PHY_COMMON_POWER 0x064
-#define PCIE_PHY_COMMON_PD_CMN (0x1 << 3)
-#define PCIE_PHY_TRSV0_EMP_LVL 0x084
-#define PCIE_PHY_TRSV0_DRV_LVL 0x088
-#define PCIE_PHY_TRSV0_RXCDR 0x0ac
-#define PCIE_PHY_TRSV0_POWER 0x0c4
-#define PCIE_PHY_TRSV0_PD_TSV (0x1 << 7)
-#define PCIE_PHY_TRSV0_LVCC 0x0dc
-#define PCIE_PHY_TRSV1_EMP_LVL 0x144
-#define PCIE_PHY_TRSV1_RXCDR 0x16c
-#define PCIE_PHY_TRSV1_POWER 0x184
-#define PCIE_PHY_TRSV1_PD_TSV (0x1 << 7)
-#define PCIE_PHY_TRSV1_LVCC 0x19c
-#define PCIE_PHY_TRSV2_EMP_LVL 0x204
-#define PCIE_PHY_TRSV2_RXCDR 0x22c
-#define PCIE_PHY_TRSV2_POWER 0x244
-#define PCIE_PHY_TRSV2_PD_TSV (0x1 << 7)
-#define PCIE_PHY_TRSV2_LVCC 0x25c
-#define PCIE_PHY_TRSV3_EMP_LVL 0x2c4
-#define PCIE_PHY_TRSV3_RXCDR 0x2ec
-#define PCIE_PHY_TRSV3_POWER 0x304
-#define PCIE_PHY_TRSV3_PD_TSV (0x1 << 7)
-#define PCIE_PHY_TRSV3_LVCC 0x31c
-
-static void exynos_elb_writel(struct exynos_pcie *exynos_pcie, u32 val, u32 reg)
-{
- writel(val, exynos_pcie->elbi_base + reg);
-}
-
-static u32 exynos_elb_readl(struct exynos_pcie *exynos_pcie, u32 reg)
-{
- return readl(exynos_pcie->elbi_base + reg);
-}
-
-static void exynos_phy_writel(struct exynos_pcie *exynos_pcie, u32 val, u32 reg)
-{
- writel(val, exynos_pcie->phy_base + reg);
-}
-
-static u32 exynos_phy_readl(struct exynos_pcie *exynos_pcie, u32 reg)
-{
- return readl(exynos_pcie->phy_base + reg);
-}
-
-static void exynos_blk_writel(struct exynos_pcie *exynos_pcie, u32 val, u32 reg)
-{
- writel(val, exynos_pcie->block_base + reg);
-}
-
-static u32 exynos_blk_readl(struct exynos_pcie *exynos_pcie, u32 reg)
-{
- return readl(exynos_pcie->block_base + reg);
-}
-
-static void exynos_pcie_sideband_dbi_w_mode(struct exynos_pcie *exynos_pcie,
- bool on)
-{
- u32 val;
-
- if (on) {
- val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_AWMISC);
- val |= PCIE_ELBI_SLV_DBI_ENABLE;
- exynos_elb_writel(exynos_pcie, val, PCIE_ELBI_SLV_AWMISC);
- } else {
- val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_AWMISC);
- val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
- exynos_elb_writel(exynos_pcie, val, PCIE_ELBI_SLV_AWMISC);
- }
-}
-
-static void exynos_pcie_sideband_dbi_r_mode(struct exynos_pcie *exynos_pcie,
- bool on)
-{
- u32 val;
-
- if (on) {
- val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_ARMISC);
- val |= PCIE_ELBI_SLV_DBI_ENABLE;
- exynos_elb_writel(exynos_pcie, val, PCIE_ELBI_SLV_ARMISC);
- } else {
- val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_SLV_ARMISC);
- val &= ~PCIE_ELBI_SLV_DBI_ENABLE;
- exynos_elb_writel(exynos_pcie, val, PCIE_ELBI_SLV_ARMISC);
- }
-}
-
-static void exynos_pcie_assert_core_reset(struct exynos_pcie *exynos_pcie)
-{
- u32 val;
-
- val = exynos_elb_readl(exynos_pcie, PCIE_CORE_RESET);
- val &= ~PCIE_CORE_RESET_ENABLE;
- exynos_elb_writel(exynos_pcie, val, PCIE_CORE_RESET);
- exynos_elb_writel(exynos_pcie, 0, PCIE_PWR_RESET);
- exynos_elb_writel(exynos_pcie, 0, PCIE_STICKY_RESET);
- exynos_elb_writel(exynos_pcie, 0, PCIE_NONSTICKY_RESET);
-}
-
-static void exynos_pcie_deassert_core_reset(struct exynos_pcie *exynos_pcie)
-{
- u32 val;
-
- val = exynos_elb_readl(exynos_pcie, PCIE_CORE_RESET);
- val |= PCIE_CORE_RESET_ENABLE;
-
- exynos_elb_writel(exynos_pcie, val, PCIE_CORE_RESET);
- exynos_elb_writel(exynos_pcie, 1, PCIE_STICKY_RESET);
- exynos_elb_writel(exynos_pcie, 1, PCIE_NONSTICKY_RESET);
- exynos_elb_writel(exynos_pcie, 1, PCIE_APP_INIT_RESET);
- exynos_elb_writel(exynos_pcie, 0, PCIE_APP_INIT_RESET);
- exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_MAC_RESET);
-}
-
-static void exynos_pcie_assert_phy_reset(struct exynos_pcie *exynos_pcie)
-{
- exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_MAC_RESET);
- exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_GLOBAL_RESET);
-}
-
-static void exynos_pcie_deassert_phy_reset(struct exynos_pcie *exynos_pcie)
-{
- exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_GLOBAL_RESET);
- exynos_elb_writel(exynos_pcie, 1, PCIE_PWR_RESET);
- exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_COMMON_RESET);
- exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_CMN_REG);
- exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSVREG_RESET);
- exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_TRSV_RESET);
-}
-
-static void exynos_pcie_power_on_phy(struct exynos_pcie *exynos_pcie)
-{
- u32 val;
-
- val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER);
- val &= ~PCIE_PHY_COMMON_PD_CMN;
- exynos_phy_writel(exynos_pcie, val, PCIE_PHY_COMMON_POWER);
-
- val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV0_POWER);
- val &= ~PCIE_PHY_TRSV0_PD_TSV;
- exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV0_POWER);
-
- val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV1_POWER);
- val &= ~PCIE_PHY_TRSV1_PD_TSV;
- exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV1_POWER);
-
- val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV2_POWER);
- val &= ~PCIE_PHY_TRSV2_PD_TSV;
- exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV2_POWER);
-
- val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV3_POWER);
- val &= ~PCIE_PHY_TRSV3_PD_TSV;
- exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER);
-}
-
-static void exynos_pcie_power_off_phy(struct exynos_pcie *exynos_pcie)
-{
- u32 val;
-
- val = exynos_phy_readl(exynos_pcie, PCIE_PHY_COMMON_POWER);
- val |= PCIE_PHY_COMMON_PD_CMN;
- exynos_phy_writel(exynos_pcie, val, PCIE_PHY_COMMON_POWER);
-
- val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV0_POWER);
- val |= PCIE_PHY_TRSV0_PD_TSV;
- exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV0_POWER);
-
- val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV1_POWER);
- val |= PCIE_PHY_TRSV1_PD_TSV;
- exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV1_POWER);
-
- val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV2_POWER);
- val |= PCIE_PHY_TRSV2_PD_TSV;
- exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV2_POWER);
-
- val = exynos_phy_readl(exynos_pcie, PCIE_PHY_TRSV3_POWER);
- val |= PCIE_PHY_TRSV3_PD_TSV;
- exynos_phy_writel(exynos_pcie, val, PCIE_PHY_TRSV3_POWER);
-}
-
-static void exynos_pcie_init_phy(struct exynos_pcie *exynos_pcie)
-{
- /* DCC feedback control off */
- exynos_phy_writel(exynos_pcie, 0x29, PCIE_PHY_DCC_FEEDBACK);
-
- /* set TX/RX impedance */
- exynos_phy_writel(exynos_pcie, 0xd5, PCIE_PHY_IMPEDANCE);
-
- /* set 50Mhz PHY clock */
- exynos_phy_writel(exynos_pcie, 0x14, PCIE_PHY_PLL_DIV_0);
- exynos_phy_writel(exynos_pcie, 0x12, PCIE_PHY_PLL_DIV_1);
-
- /* set TX Differential output for lane 0 */
- exynos_phy_writel(exynos_pcie, 0x7f, PCIE_PHY_TRSV0_DRV_LVL);
-
- /* set TX Pre-emphasis Level Control for lane 0 to minimum */
- exynos_phy_writel(exynos_pcie, 0x0, PCIE_PHY_TRSV0_EMP_LVL);
-
- /* set RX clock and data recovery bandwidth */
- exynos_phy_writel(exynos_pcie, 0xe7, PCIE_PHY_PLL_BIAS);
- exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV0_RXCDR);
- exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV1_RXCDR);
- exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV2_RXCDR);
- exynos_phy_writel(exynos_pcie, 0x82, PCIE_PHY_TRSV3_RXCDR);
-
- /* change TX Pre-emphasis Level Control for lanes */
- exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV0_EMP_LVL);
- exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV1_EMP_LVL);
- exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV2_EMP_LVL);
- exynos_phy_writel(exynos_pcie, 0x39, PCIE_PHY_TRSV3_EMP_LVL);
-
- /* set LVCC */
- exynos_phy_writel(exynos_pcie, 0x20, PCIE_PHY_TRSV0_LVCC);
- exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV1_LVCC);
- exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV2_LVCC);
- exynos_phy_writel(exynos_pcie, 0xa0, PCIE_PHY_TRSV3_LVCC);
-}
-
-static void exynos_pcie_assert_reset(struct exynos_pcie *exynos_pcie)
-{
- struct pcie_port *pp = &exynos_pcie->pp;
- struct device *dev = pp->dev;
-
- if (exynos_pcie->reset_gpio >= 0)
- devm_gpio_request_one(dev, exynos_pcie->reset_gpio,
- GPIOF_OUT_INIT_HIGH, "RESET");
-}
-
-static int exynos_pcie_establish_link(struct exynos_pcie *exynos_pcie)
-{
- struct pcie_port *pp = &exynos_pcie->pp;
- struct device *dev = pp->dev;
- u32 val;
-
- if (dw_pcie_link_up(pp)) {
- dev_err(dev, "Link already up\n");
- return 0;
- }
-
- exynos_pcie_assert_core_reset(exynos_pcie);
- exynos_pcie_assert_phy_reset(exynos_pcie);
- exynos_pcie_deassert_phy_reset(exynos_pcie);
- exynos_pcie_power_on_phy(exynos_pcie);
- exynos_pcie_init_phy(exynos_pcie);
-
- /* pulse for common reset */
- exynos_blk_writel(exynos_pcie, 1, PCIE_PHY_COMMON_RESET);
- udelay(500);
- exynos_blk_writel(exynos_pcie, 0, PCIE_PHY_COMMON_RESET);
-
- exynos_pcie_deassert_core_reset(exynos_pcie);
- dw_pcie_setup_rc(pp);
- exynos_pcie_assert_reset(exynos_pcie);
-
- /* assert LTSSM enable */
- exynos_elb_writel(exynos_pcie, PCIE_ELBI_LTSSM_ENABLE,
- PCIE_APP_LTSSM_ENABLE);
-
- /* check if the link is up or not */
- if (!dw_pcie_wait_for_link(pp))
- return 0;
-
- while (exynos_phy_readl(exynos_pcie, PCIE_PHY_PLL_LOCKED) == 0) {
- val = exynos_blk_readl(exynos_pcie, PCIE_PHY_PLL_LOCKED);
- dev_info(dev, "PLL Locked: 0x%x\n", val);
- }
- exynos_pcie_power_off_phy(exynos_pcie);
- return -ETIMEDOUT;
-}
-
-static void exynos_pcie_clear_irq_pulse(struct exynos_pcie *exynos_pcie)
-{
- u32 val;
-
- val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_PULSE);
- exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_PULSE);
-}
-
-static void exynos_pcie_enable_irq_pulse(struct exynos_pcie *exynos_pcie)
-{
- u32 val;
-
- /* enable INTX interrupt */
- val = IRQ_INTA_ASSERT | IRQ_INTB_ASSERT |
- IRQ_INTC_ASSERT | IRQ_INTD_ASSERT;
- exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_PULSE);
-}
-
-static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg)
-{
- struct exynos_pcie *exynos_pcie = arg;
-
- exynos_pcie_clear_irq_pulse(exynos_pcie);
- return IRQ_HANDLED;
-}
-
-static irqreturn_t exynos_pcie_msi_irq_handler(int irq, void *arg)
-{
- struct exynos_pcie *exynos_pcie = arg;
- struct pcie_port *pp = &exynos_pcie->pp;
-
- return dw_handle_msi_irq(pp);
-}
-
-static void exynos_pcie_msi_init(struct exynos_pcie *exynos_pcie)
-{
- struct pcie_port *pp = &exynos_pcie->pp;
- u32 val;
-
- dw_pcie_msi_init(pp);
-
- /* enable MSI interrupt */
- val = exynos_elb_readl(exynos_pcie, PCIE_IRQ_EN_LEVEL);
- val |= IRQ_MSI_ENABLE;
- exynos_elb_writel(exynos_pcie, val, PCIE_IRQ_EN_LEVEL);
-}
-
-static void exynos_pcie_enable_interrupts(struct exynos_pcie *exynos_pcie)
-{
- exynos_pcie_enable_irq_pulse(exynos_pcie);
-
- if (IS_ENABLED(CONFIG_PCI_MSI))
- exynos_pcie_msi_init(exynos_pcie);
-}
-
-static u32 exynos_pcie_readl_rc(struct pcie_port *pp, u32 reg)
-{
- struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
- u32 val;
-
- exynos_pcie_sideband_dbi_r_mode(exynos_pcie, true);
- val = readl(pp->dbi_base + reg);
- exynos_pcie_sideband_dbi_r_mode(exynos_pcie, false);
- return val;
-}
-
-static void exynos_pcie_writel_rc(struct pcie_port *pp, u32 reg, u32 val)
-{
- struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
-
- exynos_pcie_sideband_dbi_w_mode(exynos_pcie, true);
- writel(val, pp->dbi_base + reg);
- exynos_pcie_sideband_dbi_w_mode(exynos_pcie, false);
-}
-
-static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
- u32 *val)
-{
- struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
- int ret;
-
- exynos_pcie_sideband_dbi_r_mode(exynos_pcie, true);
- ret = dw_pcie_cfg_read(pp->dbi_base + where, size, val);
- exynos_pcie_sideband_dbi_r_mode(exynos_pcie, false);
- return ret;
-}
-
-static int exynos_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
- u32 val)
-{
- struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
- int ret;
-
- exynos_pcie_sideband_dbi_w_mode(exynos_pcie, true);
- ret = dw_pcie_cfg_write(pp->dbi_base + where, size, val);
- exynos_pcie_sideband_dbi_w_mode(exynos_pcie, false);
- return ret;
-}
-
-static int exynos_pcie_link_up(struct pcie_port *pp)
-{
- struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
- u32 val;
-
- val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_RDLH_LINKUP);
- if (val == PCIE_ELBI_LTSSM_ENABLE)
- return 1;
-
- return 0;
-}
-
-static void exynos_pcie_host_init(struct pcie_port *pp)
-{
- struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp);
-
- exynos_pcie_establish_link(exynos_pcie);
- exynos_pcie_enable_interrupts(exynos_pcie);
-}
-
-static struct pcie_host_ops exynos_pcie_host_ops = {
- .readl_rc = exynos_pcie_readl_rc,
- .writel_rc = exynos_pcie_writel_rc,
- .rd_own_conf = exynos_pcie_rd_own_conf,
- .wr_own_conf = exynos_pcie_wr_own_conf,
- .link_up = exynos_pcie_link_up,
- .host_init = exynos_pcie_host_init,
-};
-
-static int __init exynos_add_pcie_port(struct exynos_pcie *exynos_pcie,
- struct platform_device *pdev)
-{
- struct pcie_port *pp = &exynos_pcie->pp;
- struct device *dev = pp->dev;
- int ret;
-
- pp->irq = platform_get_irq(pdev, 1);
- if (!pp->irq) {
- dev_err(dev, "failed to get irq\n");
- return -ENODEV;
- }
- ret = devm_request_irq(dev, pp->irq, exynos_pcie_irq_handler,
- IRQF_SHARED, "exynos-pcie", exynos_pcie);
- if (ret) {
- dev_err(dev, "failed to request irq\n");
- return ret;
- }
-
- if (IS_ENABLED(CONFIG_PCI_MSI)) {
- pp->msi_irq = platform_get_irq(pdev, 0);
- if (!pp->msi_irq) {
- dev_err(dev, "failed to get msi irq\n");
- return -ENODEV;
- }
-
- ret = devm_request_irq(dev, pp->msi_irq,
- exynos_pcie_msi_irq_handler,
- IRQF_SHARED | IRQF_NO_THREAD,
- "exynos-pcie", exynos_pcie);
- if (ret) {
- dev_err(dev, "failed to request msi irq\n");
- return ret;
- }
- }
-
- pp->root_bus_nr = -1;
- pp->ops = &exynos_pcie_host_ops;
-
- ret = dw_pcie_host_init(pp);
- if (ret) {
- dev_err(dev, "failed to initialize host\n");
- return ret;
- }
-
- return 0;
-}
-
-static int __init exynos_pcie_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct exynos_pcie *exynos_pcie;
- struct pcie_port *pp;
- struct device_node *np = dev->of_node;
- struct resource *elbi_base;
- struct resource *phy_base;
- struct resource *block_base;
- int ret;
-
- exynos_pcie = devm_kzalloc(dev, sizeof(*exynos_pcie), GFP_KERNEL);
- if (!exynos_pcie)
- return -ENOMEM;
-
- pp = &exynos_pcie->pp;
- pp->dev = dev;
-
- exynos_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0);
-
- exynos_pcie->clk = devm_clk_get(dev, "pcie");
- if (IS_ERR(exynos_pcie->clk)) {
- dev_err(dev, "Failed to get pcie rc clock\n");
- return PTR_ERR(exynos_pcie->clk);
- }
- ret = clk_prepare_enable(exynos_pcie->clk);
- if (ret)
- return ret;
-
- exynos_pcie->bus_clk = devm_clk_get(dev, "pcie_bus");
- if (IS_ERR(exynos_pcie->bus_clk)) {
- dev_err(dev, "Failed to get pcie bus clock\n");
- ret = PTR_ERR(exynos_pcie->bus_clk);
- goto fail_clk;
- }
- ret = clk_prepare_enable(exynos_pcie->bus_clk);
- if (ret)
- goto fail_clk;
-
- elbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- exynos_pcie->elbi_base = devm_ioremap_resource(dev, elbi_base);
- if (IS_ERR(exynos_pcie->elbi_base)) {
- ret = PTR_ERR(exynos_pcie->elbi_base);
- goto fail_bus_clk;
- }
-
- phy_base = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- exynos_pcie->phy_base = devm_ioremap_resource(dev, phy_base);
- if (IS_ERR(exynos_pcie->phy_base)) {
- ret = PTR_ERR(exynos_pcie->phy_base);
- goto fail_bus_clk;
- }
-
- block_base = platform_get_resource(pdev, IORESOURCE_MEM, 2);
- exynos_pcie->block_base = devm_ioremap_resource(dev, block_base);
- if (IS_ERR(exynos_pcie->block_base)) {
- ret = PTR_ERR(exynos_pcie->block_base);
- goto fail_bus_clk;
- }
-
- ret = exynos_add_pcie_port(exynos_pcie, pdev);
- if (ret < 0)
- goto fail_bus_clk;
-
- platform_set_drvdata(pdev, exynos_pcie);
- return 0;
-
-fail_bus_clk:
- clk_disable_unprepare(exynos_pcie->bus_clk);
-fail_clk:
- clk_disable_unprepare(exynos_pcie->clk);
- return ret;
-}
-
-static int __exit exynos_pcie_remove(struct platform_device *pdev)
-{
- struct exynos_pcie *exynos_pcie = platform_get_drvdata(pdev);
-
- clk_disable_unprepare(exynos_pcie->bus_clk);
- clk_disable_unprepare(exynos_pcie->clk);
-
- return 0;
-}
-
-static const struct of_device_id exynos_pcie_of_match[] = {
- { .compatible = "samsung,exynos5440-pcie", },
- {},
-};
-
-static struct platform_driver exynos_pcie_driver = {
- .remove = __exit_p(exynos_pcie_remove),
- .driver = {
- .name = "exynos-pcie",
- .of_match_table = exynos_pcie_of_match,
- },
-};
-
-/* Exynos PCIe driver does not allow module unload */
-
-static int __init exynos_pcie_init(void)
-{
- return platform_driver_probe(&exynos_pcie_driver, exynos_pcie_probe);
-}
-subsys_initcall(exynos_pcie_init);
diff --git a/drivers/pci/host/pci-host-common.c b/drivers/pci/host/pci-host-common.c
index e3c48b5deb93..e9a53bae1c25 100644
--- a/drivers/pci/host/pci-host-common.c
+++ b/drivers/pci/host/pci-host-common.c
@@ -145,7 +145,9 @@ int pci_host_common_probe(struct platform_device *pdev,
return -ENODEV;
}
+#ifdef CONFIG_ARM
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+#endif
/*
* We insert PCI resources into the iomem_resource and
diff --git a/drivers/pci/host/pci-hyperv.c b/drivers/pci/host/pci-hyperv.c
index 3efcc7bdc5fb..ada98569b78e 100644
--- a/drivers/pci/host/pci-hyperv.c
+++ b/drivers/pci/host/pci-hyperv.c
@@ -130,7 +130,8 @@ union pci_version {
*/
union win_slot_encoding {
struct {
- u32 func:8;
+ u32 dev:5;
+ u32 func:3;
u32 reserved:24;
} bits;
u32 slot;
@@ -485,7 +486,8 @@ static u32 devfn_to_wslot(int devfn)
union win_slot_encoding wslot;
wslot.slot = 0;
- wslot.bits.func = PCI_SLOT(devfn) | (PCI_FUNC(devfn) << 5);
+ wslot.bits.dev = PCI_SLOT(devfn);
+ wslot.bits.func = PCI_FUNC(devfn);
return wslot.slot;
}
@@ -503,7 +505,7 @@ static int wslot_to_devfn(u32 wslot)
union win_slot_encoding slot_no;
slot_no.slot = wslot;
- return PCI_DEVFN(0, slot_no.bits.func);
+ return PCI_DEVFN(slot_no.bits.dev, slot_no.bits.func);
}
/*
@@ -1315,6 +1317,18 @@ static struct hv_pci_dev *new_pcichild_device(struct hv_pcibus_device *hbus,
get_pcichild(hpdev, hv_pcidev_ref_initial);
get_pcichild(hpdev, hv_pcidev_ref_childlist);
spin_lock_irqsave(&hbus->device_list_lock, flags);
+
+ /*
+ * When a device is being added to the bus, we set the PCI domain
+ * number to be the device serial number, which is non-zero and
+ * unique on the same VM. The serial numbers start with 1, and
+ * increase by 1 for each device. So device names including this
+ * can have shorter names than based on the bus instance UUID.
+ * Only the first device serial number is used for domain, so the
+ * domain number will not change after the first device is added.
+ */
+ if (list_empty(&hbus->children))
+ hbus->sysdata.domain = desc->ser;
list_add_tail(&hpdev->list_entry, &hbus->children);
spin_unlock_irqrestore(&hbus->device_list_lock, flags);
return hpdev;
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
deleted file mode 100644
index c8cefb078218..000000000000
--- a/drivers/pci/host/pci-imx6.c
+++ /dev/null
@@ -1,757 +0,0 @@
-/*
- * PCIe host controller driver for Freescale i.MX6 SoCs
- *
- * Copyright (C) 2013 Kosagi
- * http://www.kosagi.com
- *
- * Author: Sean Cross <xobs@kosagi.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.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/kernel.h>
-#include <linux/mfd/syscon.h>
-#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
-#include <linux/module.h>
-#include <linux/of_gpio.h>
-#include <linux/of_device.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/regmap.h>
-#include <linux/resource.h>
-#include <linux/signal.h>
-#include <linux/types.h>
-#include <linux/interrupt.h>
-
-#include "pcie-designware.h"
-
-#define to_imx6_pcie(x) container_of(x, struct imx6_pcie, pp)
-
-enum imx6_pcie_variants {
- IMX6Q,
- IMX6SX,
- IMX6QP,
-};
-
-struct imx6_pcie {
- struct pcie_port pp; /* pp.dbi_base is DT 0th resource */
- int reset_gpio;
- bool gpio_active_high;
- struct clk *pcie_bus;
- struct clk *pcie_phy;
- struct clk *pcie_inbound_axi;
- struct clk *pcie;
- struct regmap *iomuxc_gpr;
- enum imx6_pcie_variants variant;
- u32 tx_deemph_gen1;
- u32 tx_deemph_gen2_3p5db;
- u32 tx_deemph_gen2_6db;
- u32 tx_swing_full;
- u32 tx_swing_low;
- int link_gen;
-};
-
-/* PCIe Root Complex registers (memory-mapped) */
-#define PCIE_RC_LCR 0x7c
-#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1 0x1
-#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2 0x2
-#define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK 0xf
-
-#define PCIE_RC_LCSR 0x80
-
-/* PCIe Port Logic registers (memory-mapped) */
-#define PL_OFFSET 0x700
-#define PCIE_PL_PFLR (PL_OFFSET + 0x08)
-#define PCIE_PL_PFLR_LINK_STATE_MASK (0x3f << 16)
-#define PCIE_PL_PFLR_FORCE_LINK (1 << 15)
-#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
-#define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
-#define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING (1 << 29)
-#define PCIE_PHY_DEBUG_R1_XMLH_LINK_UP (1 << 4)
-
-#define PCIE_PHY_CTRL (PL_OFFSET + 0x114)
-#define PCIE_PHY_CTRL_DATA_LOC 0
-#define PCIE_PHY_CTRL_CAP_ADR_LOC 16
-#define PCIE_PHY_CTRL_CAP_DAT_LOC 17
-#define PCIE_PHY_CTRL_WR_LOC 18
-#define PCIE_PHY_CTRL_RD_LOC 19
-
-#define PCIE_PHY_STAT (PL_OFFSET + 0x110)
-#define PCIE_PHY_STAT_ACK_LOC 16
-
-#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
-#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
-
-/* PHY registers (not memory-mapped) */
-#define PCIE_PHY_RX_ASIC_OUT 0x100D
-#define PCIE_PHY_RX_ASIC_OUT_VALID (1 << 0)
-
-#define PHY_RX_OVRD_IN_LO 0x1005
-#define PHY_RX_OVRD_IN_LO_RX_DATA_EN (1 << 5)
-#define PHY_RX_OVRD_IN_LO_RX_PLL_EN (1 << 3)
-
-static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, int exp_val)
-{
- struct pcie_port *pp = &imx6_pcie->pp;
- u32 val;
- u32 max_iterations = 10;
- u32 wait_counter = 0;
-
- do {
- val = dw_pcie_readl_rc(pp, PCIE_PHY_STAT);
- val = (val >> PCIE_PHY_STAT_ACK_LOC) & 0x1;
- wait_counter++;
-
- if (val == exp_val)
- return 0;
-
- udelay(1);
- } while (wait_counter < max_iterations);
-
- return -ETIMEDOUT;
-}
-
-static int pcie_phy_wait_ack(struct imx6_pcie *imx6_pcie, int addr)
-{
- struct pcie_port *pp = &imx6_pcie->pp;
- u32 val;
- int ret;
-
- val = addr << PCIE_PHY_CTRL_DATA_LOC;
- dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, val);
-
- val |= (0x1 << PCIE_PHY_CTRL_CAP_ADR_LOC);
- dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, val);
-
- ret = pcie_phy_poll_ack(imx6_pcie, 1);
- if (ret)
- return ret;
-
- val = addr << PCIE_PHY_CTRL_DATA_LOC;
- dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, val);
-
- return pcie_phy_poll_ack(imx6_pcie, 0);
-}
-
-/* Read from the 16-bit PCIe PHY control registers (not memory-mapped) */
-static int pcie_phy_read(struct imx6_pcie *imx6_pcie, int addr, int *data)
-{
- struct pcie_port *pp = &imx6_pcie->pp;
- u32 val, phy_ctl;
- int ret;
-
- ret = pcie_phy_wait_ack(imx6_pcie, addr);
- if (ret)
- return ret;
-
- /* assert Read signal */
- phy_ctl = 0x1 << PCIE_PHY_CTRL_RD_LOC;
- dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, phy_ctl);
-
- ret = pcie_phy_poll_ack(imx6_pcie, 1);
- if (ret)
- return ret;
-
- val = dw_pcie_readl_rc(pp, PCIE_PHY_STAT);
- *data = val & 0xffff;
-
- /* deassert Read signal */
- dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, 0x00);
-
- return pcie_phy_poll_ack(imx6_pcie, 0);
-}
-
-static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data)
-{
- struct pcie_port *pp = &imx6_pcie->pp;
- u32 var;
- int ret;
-
- /* write addr */
- /* cap addr */
- ret = pcie_phy_wait_ack(imx6_pcie, addr);
- if (ret)
- return ret;
-
- var = data << PCIE_PHY_CTRL_DATA_LOC;
- dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var);
-
- /* capture data */
- var |= (0x1 << PCIE_PHY_CTRL_CAP_DAT_LOC);
- dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var);
-
- ret = pcie_phy_poll_ack(imx6_pcie, 1);
- if (ret)
- return ret;
-
- /* deassert cap data */
- var = data << PCIE_PHY_CTRL_DATA_LOC;
- dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var);
-
- /* wait for ack de-assertion */
- ret = pcie_phy_poll_ack(imx6_pcie, 0);
- if (ret)
- return ret;
-
- /* assert wr signal */
- var = 0x1 << PCIE_PHY_CTRL_WR_LOC;
- dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var);
-
- /* wait for ack */
- ret = pcie_phy_poll_ack(imx6_pcie, 1);
- if (ret)
- return ret;
-
- /* deassert wr signal */
- var = data << PCIE_PHY_CTRL_DATA_LOC;
- dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var);
-
- /* wait for ack de-assertion */
- ret = pcie_phy_poll_ack(imx6_pcie, 0);
- if (ret)
- return ret;
-
- dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, 0x0);
-
- return 0;
-}
-
-static void imx6_pcie_reset_phy(struct imx6_pcie *imx6_pcie)
-{
- u32 tmp;
-
- pcie_phy_read(imx6_pcie, PHY_RX_OVRD_IN_LO, &tmp);
- tmp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN |
- PHY_RX_OVRD_IN_LO_RX_PLL_EN);
- pcie_phy_write(imx6_pcie, PHY_RX_OVRD_IN_LO, tmp);
-
- usleep_range(2000, 3000);
-
- pcie_phy_read(imx6_pcie, PHY_RX_OVRD_IN_LO, &tmp);
- tmp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN |
- PHY_RX_OVRD_IN_LO_RX_PLL_EN);
- pcie_phy_write(imx6_pcie, PHY_RX_OVRD_IN_LO, tmp);
-}
-
-/* Added for PCI abort handling */
-static int imx6q_pcie_abort_handler(unsigned long addr,
- unsigned int fsr, struct pt_regs *regs)
-{
- return 0;
-}
-
-static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
-{
- struct pcie_port *pp = &imx6_pcie->pp;
- u32 val, gpr1, gpr12;
-
- switch (imx6_pcie->variant) {
- case IMX6SX:
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6SX_GPR12_PCIE_TEST_POWERDOWN,
- IMX6SX_GPR12_PCIE_TEST_POWERDOWN);
- /* Force PCIe PHY reset */
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
- IMX6SX_GPR5_PCIE_BTNRST_RESET,
- IMX6SX_GPR5_PCIE_BTNRST_RESET);
- break;
- case IMX6QP:
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- IMX6Q_GPR1_PCIE_SW_RST,
- IMX6Q_GPR1_PCIE_SW_RST);
- break;
- case IMX6Q:
- /*
- * If the bootloader already enabled the link we need some
- * special handling to get the core back into a state where
- * it is safe to touch it for configuration. As there is
- * no dedicated reset signal wired up for MX6QDL, we need
- * to manually force LTSSM into "detect" state before
- * completely disabling LTSSM, which is a prerequisite for
- * core configuration.
- *
- * If both LTSSM_ENABLE and REF_SSP_ENABLE are active we
- * have a strong indication that the bootloader activated
- * the link.
- */
- regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, &gpr1);
- regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, &gpr12);
-
- if ((gpr1 & IMX6Q_GPR1_PCIE_REF_CLK_EN) &&
- (gpr12 & IMX6Q_GPR12_PCIE_CTL_2)) {
- val = dw_pcie_readl_rc(pp, PCIE_PL_PFLR);
- val &= ~PCIE_PL_PFLR_LINK_STATE_MASK;
- val |= PCIE_PL_PFLR_FORCE_LINK;
- dw_pcie_writel_rc(pp, PCIE_PL_PFLR, val);
-
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
- }
-
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
- break;
- }
-}
-
-static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
-{
- struct pcie_port *pp = &imx6_pcie->pp;
- struct device *dev = pp->dev;
- int ret = 0;
-
- switch (imx6_pcie->variant) {
- case IMX6SX:
- ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi);
- if (ret) {
- dev_err(dev, "unable to enable pcie_axi clock\n");
- break;
- }
-
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6SX_GPR12_PCIE_TEST_POWERDOWN, 0);
- break;
- case IMX6QP: /* FALLTHROUGH */
- case IMX6Q:
- /* power up core phy and enable ref clock */
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- IMX6Q_GPR1_PCIE_TEST_PD, 0 << 18);
- /*
- * the async reset input need ref clock to sync internally,
- * when the ref clock comes after reset, internal synced
- * reset time is too short, cannot meet the requirement.
- * add one ~10us delay here.
- */
- udelay(10);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
- break;
- }
-
- return ret;
-}
-
-static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
-{
- struct pcie_port *pp = &imx6_pcie->pp;
- struct device *dev = pp->dev;
- int ret;
-
- ret = clk_prepare_enable(imx6_pcie->pcie_phy);
- if (ret) {
- dev_err(dev, "unable to enable pcie_phy clock\n");
- return;
- }
-
- ret = clk_prepare_enable(imx6_pcie->pcie_bus);
- if (ret) {
- dev_err(dev, "unable to enable pcie_bus clock\n");
- goto err_pcie_bus;
- }
-
- ret = clk_prepare_enable(imx6_pcie->pcie);
- if (ret) {
- dev_err(dev, "unable to enable pcie clock\n");
- goto err_pcie;
- }
-
- ret = imx6_pcie_enable_ref_clk(imx6_pcie);
- if (ret) {
- dev_err(dev, "unable to enable pcie ref clock\n");
- goto err_ref_clk;
- }
-
- /* allow the clocks to stabilize */
- usleep_range(200, 500);
-
- /* Some boards don't have PCIe reset GPIO. */
- if (gpio_is_valid(imx6_pcie->reset_gpio)) {
- gpio_set_value_cansleep(imx6_pcie->reset_gpio,
- imx6_pcie->gpio_active_high);
- msleep(100);
- gpio_set_value_cansleep(imx6_pcie->reset_gpio,
- !imx6_pcie->gpio_active_high);
- }
-
- switch (imx6_pcie->variant) {
- case IMX6SX:
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
- IMX6SX_GPR5_PCIE_BTNRST_RESET, 0);
- break;
- case IMX6QP:
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
- IMX6Q_GPR1_PCIE_SW_RST, 0);
-
- usleep_range(200, 500);
- break;
- case IMX6Q: /* Nothing to do */
- break;
- }
-
- return;
-
-err_ref_clk:
- clk_disable_unprepare(imx6_pcie->pcie);
-err_pcie:
- clk_disable_unprepare(imx6_pcie->pcie_bus);
-err_pcie_bus:
- clk_disable_unprepare(imx6_pcie->pcie_phy);
-}
-
-static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
-{
- if (imx6_pcie->variant == IMX6SX)
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6SX_GPR12_PCIE_RX_EQ_MASK,
- IMX6SX_GPR12_PCIE_RX_EQ_2);
-
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
-
- /* configure constant input signal to the pcie ctrl and phy */
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6Q_GPR12_LOS_LEVEL, 9 << 4);
-
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
- IMX6Q_GPR8_TX_DEEMPH_GEN1,
- imx6_pcie->tx_deemph_gen1 << 0);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
- IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB,
- imx6_pcie->tx_deemph_gen2_3p5db << 6);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
- IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB,
- imx6_pcie->tx_deemph_gen2_6db << 12);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
- IMX6Q_GPR8_TX_SWING_FULL,
- imx6_pcie->tx_swing_full << 18);
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
- IMX6Q_GPR8_TX_SWING_LOW,
- imx6_pcie->tx_swing_low << 25);
-}
-
-static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie)
-{
- struct pcie_port *pp = &imx6_pcie->pp;
- struct device *dev = pp->dev;
-
- /* check if the link is up or not */
- if (!dw_pcie_wait_for_link(pp))
- return 0;
-
- dev_dbg(dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n",
- dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R0),
- dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R1));
- return -ETIMEDOUT;
-}
-
-static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie)
-{
- struct pcie_port *pp = &imx6_pcie->pp;
- struct device *dev = pp->dev;
- u32 tmp;
- unsigned int retries;
-
- for (retries = 0; retries < 200; retries++) {
- tmp = dw_pcie_readl_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL);
- /* Test if the speed change finished. */
- if (!(tmp & PORT_LOGIC_SPEED_CHANGE))
- return 0;
- usleep_range(100, 1000);
- }
-
- dev_err(dev, "Speed change timeout\n");
- return -EINVAL;
-}
-
-static irqreturn_t imx6_pcie_msi_handler(int irq, void *arg)
-{
- struct imx6_pcie *imx6_pcie = arg;
- struct pcie_port *pp = &imx6_pcie->pp;
-
- return dw_handle_msi_irq(pp);
-}
-
-static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
-{
- struct pcie_port *pp = &imx6_pcie->pp;
- struct device *dev = pp->dev;
- u32 tmp;
- int ret;
-
- /*
- * Force Gen1 operation when starting the link. In case the link is
- * started in Gen2 mode, there is a possibility the devices on the
- * bus will not be detected at all. This happens with PCIe switches.
- */
- tmp = dw_pcie_readl_rc(pp, PCIE_RC_LCR);
- tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
- tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1;
- dw_pcie_writel_rc(pp, PCIE_RC_LCR, tmp);
-
- /* Start LTSSM. */
- regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
- IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
-
- ret = imx6_pcie_wait_for_link(imx6_pcie);
- if (ret) {
- dev_info(dev, "Link never came up\n");
- goto err_reset_phy;
- }
-
- if (imx6_pcie->link_gen == 2) {
- /* Allow Gen2 mode after the link is up. */
- tmp = dw_pcie_readl_rc(pp, PCIE_RC_LCR);
- tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
- tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2;
- dw_pcie_writel_rc(pp, PCIE_RC_LCR, tmp);
- } else {
- dev_info(dev, "Link: Gen2 disabled\n");
- }
-
- /*
- * Start Directed Speed Change so the best possible speed both link
- * partners support can be negotiated.
- */
- tmp = dw_pcie_readl_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL);
- tmp |= PORT_LOGIC_SPEED_CHANGE;
- dw_pcie_writel_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp);
-
- ret = imx6_pcie_wait_for_speed_change(imx6_pcie);
- if (ret) {
- dev_err(dev, "Failed to bring link up!\n");
- goto err_reset_phy;
- }
-
- /* Make sure link training is finished as well! */
- ret = imx6_pcie_wait_for_link(imx6_pcie);
- if (ret) {
- dev_err(dev, "Failed to bring link up!\n");
- goto err_reset_phy;
- }
-
- tmp = dw_pcie_readl_rc(pp, PCIE_RC_LCSR);
- dev_info(dev, "Link up, Gen%i\n", (tmp >> 16) & 0xf);
- return 0;
-
-err_reset_phy:
- dev_dbg(dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n",
- dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R0),
- dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R1));
- imx6_pcie_reset_phy(imx6_pcie);
- return ret;
-}
-
-static void imx6_pcie_host_init(struct pcie_port *pp)
-{
- struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
-
- imx6_pcie_assert_core_reset(imx6_pcie);
- imx6_pcie_init_phy(imx6_pcie);
- imx6_pcie_deassert_core_reset(imx6_pcie);
- dw_pcie_setup_rc(pp);
- imx6_pcie_establish_link(imx6_pcie);
-
- if (IS_ENABLED(CONFIG_PCI_MSI))
- dw_pcie_msi_init(pp);
-}
-
-static int imx6_pcie_link_up(struct pcie_port *pp)
-{
- return dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R1) &
- PCIE_PHY_DEBUG_R1_XMLH_LINK_UP;
-}
-
-static struct pcie_host_ops imx6_pcie_host_ops = {
- .link_up = imx6_pcie_link_up,
- .host_init = imx6_pcie_host_init,
-};
-
-static int __init imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,
- struct platform_device *pdev)
-{
- struct pcie_port *pp = &imx6_pcie->pp;
- struct device *dev = pp->dev;
- int ret;
-
- if (IS_ENABLED(CONFIG_PCI_MSI)) {
- pp->msi_irq = platform_get_irq_byname(pdev, "msi");
- if (pp->msi_irq <= 0) {
- dev_err(dev, "failed to get MSI irq\n");
- return -ENODEV;
- }
-
- ret = devm_request_irq(dev, pp->msi_irq,
- imx6_pcie_msi_handler,
- IRQF_SHARED | IRQF_NO_THREAD,
- "mx6-pcie-msi", imx6_pcie);
- if (ret) {
- dev_err(dev, "failed to request MSI irq\n");
- return ret;
- }
- }
-
- pp->root_bus_nr = -1;
- pp->ops = &imx6_pcie_host_ops;
-
- ret = dw_pcie_host_init(pp);
- if (ret) {
- dev_err(dev, "failed to initialize host\n");
- return ret;
- }
-
- return 0;
-}
-
-static int __init imx6_pcie_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct imx6_pcie *imx6_pcie;
- struct pcie_port *pp;
- struct resource *dbi_base;
- struct device_node *node = dev->of_node;
- int ret;
-
- imx6_pcie = devm_kzalloc(dev, sizeof(*imx6_pcie), GFP_KERNEL);
- if (!imx6_pcie)
- return -ENOMEM;
-
- pp = &imx6_pcie->pp;
- pp->dev = dev;
-
- imx6_pcie->variant =
- (enum imx6_pcie_variants)of_device_get_match_data(dev);
-
- /* Added for PCI abort handling */
- hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
- "imprecise external abort");
-
- dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- pp->dbi_base = devm_ioremap_resource(dev, dbi_base);
- if (IS_ERR(pp->dbi_base))
- return PTR_ERR(pp->dbi_base);
-
- /* Fetch GPIOs */
- imx6_pcie->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0);
- imx6_pcie->gpio_active_high = of_property_read_bool(node,
- "reset-gpio-active-high");
- if (gpio_is_valid(imx6_pcie->reset_gpio)) {
- ret = devm_gpio_request_one(dev, imx6_pcie->reset_gpio,
- imx6_pcie->gpio_active_high ?
- GPIOF_OUT_INIT_HIGH :
- GPIOF_OUT_INIT_LOW,
- "PCIe reset");
- if (ret) {
- dev_err(dev, "unable to get reset gpio\n");
- return ret;
- }
- }
-
- /* Fetch clocks */
- imx6_pcie->pcie_phy = devm_clk_get(dev, "pcie_phy");
- if (IS_ERR(imx6_pcie->pcie_phy)) {
- dev_err(dev, "pcie_phy clock source missing or invalid\n");
- return PTR_ERR(imx6_pcie->pcie_phy);
- }
-
- imx6_pcie->pcie_bus = devm_clk_get(dev, "pcie_bus");
- if (IS_ERR(imx6_pcie->pcie_bus)) {
- dev_err(dev, "pcie_bus clock source missing or invalid\n");
- return PTR_ERR(imx6_pcie->pcie_bus);
- }
-
- imx6_pcie->pcie = devm_clk_get(dev, "pcie");
- if (IS_ERR(imx6_pcie->pcie)) {
- dev_err(dev, "pcie clock source missing or invalid\n");
- return PTR_ERR(imx6_pcie->pcie);
- }
-
- if (imx6_pcie->variant == IMX6SX) {
- imx6_pcie->pcie_inbound_axi = devm_clk_get(dev,
- "pcie_inbound_axi");
- if (IS_ERR(imx6_pcie->pcie_inbound_axi)) {
- dev_err(dev,
- "pcie_incbound_axi clock missing or invalid\n");
- return PTR_ERR(imx6_pcie->pcie_inbound_axi);
- }
- }
-
- /* Grab GPR config register range */
- imx6_pcie->iomuxc_gpr =
- syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
- if (IS_ERR(imx6_pcie->iomuxc_gpr)) {
- dev_err(dev, "unable to find iomuxc registers\n");
- return PTR_ERR(imx6_pcie->iomuxc_gpr);
- }
-
- /* Grab PCIe PHY Tx Settings */
- if (of_property_read_u32(node, "fsl,tx-deemph-gen1",
- &imx6_pcie->tx_deemph_gen1))
- imx6_pcie->tx_deemph_gen1 = 0;
-
- if (of_property_read_u32(node, "fsl,tx-deemph-gen2-3p5db",
- &imx6_pcie->tx_deemph_gen2_3p5db))
- imx6_pcie->tx_deemph_gen2_3p5db = 0;
-
- if (of_property_read_u32(node, "fsl,tx-deemph-gen2-6db",
- &imx6_pcie->tx_deemph_gen2_6db))
- imx6_pcie->tx_deemph_gen2_6db = 20;
-
- if (of_property_read_u32(node, "fsl,tx-swing-full",
- &imx6_pcie->tx_swing_full))
- imx6_pcie->tx_swing_full = 127;
-
- if (of_property_read_u32(node, "fsl,tx-swing-low",
- &imx6_pcie->tx_swing_low))
- imx6_pcie->tx_swing_low = 127;
-
- /* Limit link speed */
- ret = of_property_read_u32(node, "fsl,max-link-speed",
- &imx6_pcie->link_gen);
- if (ret)
- imx6_pcie->link_gen = 1;
-
- ret = imx6_add_pcie_port(imx6_pcie, pdev);
- if (ret < 0)
- return ret;
-
- platform_set_drvdata(pdev, imx6_pcie);
- return 0;
-}
-
-static void imx6_pcie_shutdown(struct platform_device *pdev)
-{
- struct imx6_pcie *imx6_pcie = platform_get_drvdata(pdev);
-
- /* bring down link, so bootloader gets clean state in case of reboot */
- imx6_pcie_assert_core_reset(imx6_pcie);
-}
-
-static const struct of_device_id imx6_pcie_of_match[] = {
- { .compatible = "fsl,imx6q-pcie", .data = (void *)IMX6Q, },
- { .compatible = "fsl,imx6sx-pcie", .data = (void *)IMX6SX, },
- { .compatible = "fsl,imx6qp-pcie", .data = (void *)IMX6QP, },
- {},
-};
-
-static struct platform_driver imx6_pcie_driver = {
- .driver = {
- .name = "imx6q-pcie",
- .of_match_table = imx6_pcie_of_match,
- },
- .shutdown = imx6_pcie_shutdown,
-};
-
-static int __init imx6_pcie_init(void)
-{
- return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe);
-}
-device_initcall(imx6_pcie_init);
diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/host/pci-keystone-dw.c
deleted file mode 100644
index 9397c4667106..000000000000
--- a/drivers/pci/host/pci-keystone-dw.c
+++ /dev/null
@@ -1,560 +0,0 @@
-/*
- * Designware application register space functions for Keystone PCI controller
- *
- * Copyright (C) 2013-2014 Texas Instruments., Ltd.
- * http://www.ti.com
- *
- * Author: Murali Karicheri <m-karicheri2@ti.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.
- */
-
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/irqreturn.h>
-#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_pci.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-
-#include "pcie-designware.h"
-#include "pci-keystone.h"
-
-/* Application register defines */
-#define LTSSM_EN_VAL 1
-#define LTSSM_STATE_MASK 0x1f
-#define LTSSM_STATE_L0 0x11
-#define DBI_CS2_EN_VAL 0x20
-#define OB_XLAT_EN_VAL 2
-
-/* Application registers */
-#define CMD_STATUS 0x004
-#define CFG_SETUP 0x008
-#define OB_SIZE 0x030
-#define CFG_PCIM_WIN_SZ_IDX 3
-#define CFG_PCIM_WIN_CNT 32
-#define SPACE0_REMOTE_CFG_OFFSET 0x1000
-#define OB_OFFSET_INDEX(n) (0x200 + (8 * n))
-#define OB_OFFSET_HI(n) (0x204 + (8 * n))
-
-/* IRQ register defines */
-#define IRQ_EOI 0x050
-#define IRQ_STATUS 0x184
-#define IRQ_ENABLE_SET 0x188
-#define IRQ_ENABLE_CLR 0x18c
-
-#define MSI_IRQ 0x054
-#define MSI0_IRQ_STATUS 0x104
-#define MSI0_IRQ_ENABLE_SET 0x108
-#define MSI0_IRQ_ENABLE_CLR 0x10c
-#define IRQ_STATUS 0x184
-#define MSI_IRQ_OFFSET 4
-
-/* Error IRQ bits */
-#define ERR_AER BIT(5) /* ECRC error */
-#define ERR_AXI BIT(4) /* AXI tag lookup fatal error */
-#define ERR_CORR BIT(3) /* Correctable error */
-#define ERR_NONFATAL BIT(2) /* Non-fatal error */
-#define ERR_FATAL BIT(1) /* Fatal error */
-#define ERR_SYS BIT(0) /* System (fatal, non-fatal, or correctable) */
-#define ERR_IRQ_ALL (ERR_AER | ERR_AXI | ERR_CORR | \
- ERR_NONFATAL | ERR_FATAL | ERR_SYS)
-#define ERR_FATAL_IRQ (ERR_FATAL | ERR_AXI)
-#define ERR_IRQ_STATUS_RAW 0x1c0
-#define ERR_IRQ_STATUS 0x1c4
-#define ERR_IRQ_ENABLE_SET 0x1c8
-#define ERR_IRQ_ENABLE_CLR 0x1cc
-
-/* Config space registers */
-#define DEBUG0 0x728
-
-#define to_keystone_pcie(x) container_of(x, struct keystone_pcie, pp)
-
-static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset,
- u32 *bit_pos)
-{
- *reg_offset = offset % 8;
- *bit_pos = offset >> 3;
-}
-
-phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp)
-{
- struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
-
- return ks_pcie->app.start + MSI_IRQ;
-}
-
-static u32 ks_dw_app_readl(struct keystone_pcie *ks_pcie, u32 offset)
-{
- return readl(ks_pcie->va_app_base + offset);
-}
-
-static void ks_dw_app_writel(struct keystone_pcie *ks_pcie, u32 offset, u32 val)
-{
- writel(val, ks_pcie->va_app_base + offset);
-}
-
-void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset)
-{
- struct pcie_port *pp = &ks_pcie->pp;
- struct device *dev = pp->dev;
- u32 pending, vector;
- int src, virq;
-
- pending = ks_dw_app_readl(ks_pcie, MSI0_IRQ_STATUS + (offset << 4));
-
- /*
- * MSI0 status bit 0-3 shows vectors 0, 8, 16, 24, MSI1 status bit
- * shows 1, 9, 17, 25 and so forth
- */
- for (src = 0; src < 4; src++) {
- if (BIT(src) & pending) {
- vector = offset + (src << 3);
- virq = irq_linear_revmap(pp->irq_domain, vector);
- dev_dbg(dev, "irq: bit %d, vector %d, virq %d\n",
- src, vector, virq);
- generic_handle_irq(virq);
- }
- }
-}
-
-static void ks_dw_pcie_msi_irq_ack(struct irq_data *d)
-{
- u32 offset, reg_offset, bit_pos;
- struct keystone_pcie *ks_pcie;
- struct msi_desc *msi;
- struct pcie_port *pp;
-
- msi = irq_data_get_msi_desc(d);
- pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
- ks_pcie = to_keystone_pcie(pp);
- offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
- update_reg_offset_bit_pos(offset, &reg_offset, &bit_pos);
-
- ks_dw_app_writel(ks_pcie, MSI0_IRQ_STATUS + (reg_offset << 4),
- BIT(bit_pos));
- ks_dw_app_writel(ks_pcie, IRQ_EOI, reg_offset + MSI_IRQ_OFFSET);
-}
-
-void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
-{
- u32 reg_offset, bit_pos;
- struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
-
- update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);
- ks_dw_app_writel(ks_pcie, MSI0_IRQ_ENABLE_SET + (reg_offset << 4),
- BIT(bit_pos));
-}
-
-void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
-{
- u32 reg_offset, bit_pos;
- struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
-
- update_reg_offset_bit_pos(irq, &reg_offset, &bit_pos);
- ks_dw_app_writel(ks_pcie, MSI0_IRQ_ENABLE_CLR + (reg_offset << 4),
- BIT(bit_pos));
-}
-
-static void ks_dw_pcie_msi_irq_mask(struct irq_data *d)
-{
- struct keystone_pcie *ks_pcie;
- struct msi_desc *msi;
- struct pcie_port *pp;
- u32 offset;
-
- msi = irq_data_get_msi_desc(d);
- pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
- ks_pcie = to_keystone_pcie(pp);
- offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
-
- /* Mask the end point if PVM implemented */
- if (IS_ENABLED(CONFIG_PCI_MSI)) {
- if (msi->msi_attrib.maskbit)
- pci_msi_mask_irq(d);
- }
-
- ks_dw_pcie_msi_clear_irq(pp, offset);
-}
-
-static void ks_dw_pcie_msi_irq_unmask(struct irq_data *d)
-{
- struct keystone_pcie *ks_pcie;
- struct msi_desc *msi;
- struct pcie_port *pp;
- u32 offset;
-
- msi = irq_data_get_msi_desc(d);
- pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
- ks_pcie = to_keystone_pcie(pp);
- offset = d->irq - irq_linear_revmap(pp->irq_domain, 0);
-
- /* Mask the end point if PVM implemented */
- if (IS_ENABLED(CONFIG_PCI_MSI)) {
- if (msi->msi_attrib.maskbit)
- pci_msi_unmask_irq(d);
- }
-
- ks_dw_pcie_msi_set_irq(pp, offset);
-}
-
-static struct irq_chip ks_dw_pcie_msi_irq_chip = {
- .name = "Keystone-PCIe-MSI-IRQ",
- .irq_ack = ks_dw_pcie_msi_irq_ack,
- .irq_mask = ks_dw_pcie_msi_irq_mask,
- .irq_unmask = ks_dw_pcie_msi_irq_unmask,
-};
-
-static int ks_dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- irq_set_chip_and_handler(irq, &ks_dw_pcie_msi_irq_chip,
- handle_level_irq);
- irq_set_chip_data(irq, domain->host_data);
-
- return 0;
-}
-
-static const struct irq_domain_ops ks_dw_pcie_msi_domain_ops = {
- .map = ks_dw_pcie_msi_map,
-};
-
-int ks_dw_pcie_msi_host_init(struct pcie_port *pp, struct msi_controller *chip)
-{
- struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
- struct device *dev = pp->dev;
- int i;
-
- pp->irq_domain = irq_domain_add_linear(ks_pcie->msi_intc_np,
- MAX_MSI_IRQS,
- &ks_dw_pcie_msi_domain_ops,
- chip);
- if (!pp->irq_domain) {
- dev_err(dev, "irq domain init failed\n");
- return -ENXIO;
- }
-
- for (i = 0; i < MAX_MSI_IRQS; i++)
- irq_create_mapping(pp->irq_domain, i);
-
- return 0;
-}
-
-void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie)
-{
- int i;
-
- for (i = 0; i < MAX_LEGACY_IRQS; i++)
- ks_dw_app_writel(ks_pcie, IRQ_ENABLE_SET + (i << 4), 0x1);
-}
-
-void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, int offset)
-{
- struct pcie_port *pp = &ks_pcie->pp;
- struct device *dev = pp->dev;
- u32 pending;
- int virq;
-
- pending = ks_dw_app_readl(ks_pcie, IRQ_STATUS + (offset << 4));
-
- if (BIT(0) & pending) {
- virq = irq_linear_revmap(ks_pcie->legacy_irq_domain, offset);
- dev_dbg(dev, ": irq: irq_offset %d, virq %d\n", offset, virq);
- generic_handle_irq(virq);
- }
-
- /* EOI the INTx interrupt */
- ks_dw_app_writel(ks_pcie, IRQ_EOI, offset);
-}
-
-void ks_dw_pcie_enable_error_irq(struct keystone_pcie *ks_pcie)
-{
- ks_dw_app_writel(ks_pcie, ERR_IRQ_ENABLE_SET, ERR_IRQ_ALL);
-}
-
-irqreturn_t ks_dw_pcie_handle_error_irq(struct keystone_pcie *ks_pcie)
-{
- u32 status;
-
- status = ks_dw_app_readl(ks_pcie, ERR_IRQ_STATUS_RAW) & ERR_IRQ_ALL;
- if (!status)
- return IRQ_NONE;
-
- if (status & ERR_FATAL_IRQ)
- dev_err(ks_pcie->pp.dev, "fatal error (status %#010x)\n",
- status);
-
- /* Ack the IRQ; status bits are RW1C */
- ks_dw_app_writel(ks_pcie, ERR_IRQ_STATUS, status);
- return IRQ_HANDLED;
-}
-
-static void ks_dw_pcie_ack_legacy_irq(struct irq_data *d)
-{
-}
-
-static void ks_dw_pcie_mask_legacy_irq(struct irq_data *d)
-{
-}
-
-static void ks_dw_pcie_unmask_legacy_irq(struct irq_data *d)
-{
-}
-
-static struct irq_chip ks_dw_pcie_legacy_irq_chip = {
- .name = "Keystone-PCI-Legacy-IRQ",
- .irq_ack = ks_dw_pcie_ack_legacy_irq,
- .irq_mask = ks_dw_pcie_mask_legacy_irq,
- .irq_unmask = ks_dw_pcie_unmask_legacy_irq,
-};
-
-static int ks_dw_pcie_init_legacy_irq_map(struct irq_domain *d,
- unsigned int irq, irq_hw_number_t hw_irq)
-{
- irq_set_chip_and_handler(irq, &ks_dw_pcie_legacy_irq_chip,
- handle_level_irq);
- irq_set_chip_data(irq, d->host_data);
-
- return 0;
-}
-
-static const struct irq_domain_ops ks_dw_pcie_legacy_irq_domain_ops = {
- .map = ks_dw_pcie_init_legacy_irq_map,
- .xlate = irq_domain_xlate_onetwocell,
-};
-
-/**
- * ks_dw_pcie_set_dbi_mode() - Set DBI mode to access overlaid BAR mask
- * registers
- *
- * Since modification of dbi_cs2 involves different clock domain, read the
- * status back to ensure the transition is complete.
- */
-static void ks_dw_pcie_set_dbi_mode(struct keystone_pcie *ks_pcie)
-{
- u32 val;
-
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- ks_dw_app_writel(ks_pcie, CMD_STATUS, DBI_CS2_EN_VAL | val);
-
- do {
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- } while (!(val & DBI_CS2_EN_VAL));
-}
-
-/**
- * ks_dw_pcie_clear_dbi_mode() - Disable DBI mode
- *
- * Since modification of dbi_cs2 involves different clock domain, read the
- * status back to ensure the transition is complete.
- */
-static void ks_dw_pcie_clear_dbi_mode(struct keystone_pcie *ks_pcie)
-{
- u32 val;
-
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- ks_dw_app_writel(ks_pcie, CMD_STATUS, ~DBI_CS2_EN_VAL & val);
-
- do {
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- } while (val & DBI_CS2_EN_VAL);
-}
-
-void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie)
-{
- struct pcie_port *pp = &ks_pcie->pp;
- u32 start = pp->mem->start, end = pp->mem->end;
- int i, tr_size;
- u32 val;
-
- /* Disable BARs for inbound access */
- ks_dw_pcie_set_dbi_mode(ks_pcie);
- dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_0, 0);
- dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_1, 0);
- ks_dw_pcie_clear_dbi_mode(ks_pcie);
-
- /* Set outbound translation size per window division */
- ks_dw_app_writel(ks_pcie, OB_SIZE, CFG_PCIM_WIN_SZ_IDX & 0x7);
-
- tr_size = (1 << (CFG_PCIM_WIN_SZ_IDX & 0x7)) * SZ_1M;
-
- /* Using Direct 1:1 mapping of RC <-> PCI memory space */
- for (i = 0; (i < CFG_PCIM_WIN_CNT) && (start < end); i++) {
- ks_dw_app_writel(ks_pcie, OB_OFFSET_INDEX(i), start | 1);
- ks_dw_app_writel(ks_pcie, OB_OFFSET_HI(i), 0);
- start += tr_size;
- }
-
- /* Enable OB translation */
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- ks_dw_app_writel(ks_pcie, CMD_STATUS, OB_XLAT_EN_VAL | val);
-}
-
-/**
- * ks_pcie_cfg_setup() - Set up configuration space address for a device
- *
- * @ks_pcie: ptr to keystone_pcie structure
- * @bus: Bus number the device is residing on
- * @devfn: device, function number info
- *
- * Forms and returns the address of configuration space mapped in PCIESS
- * address space 0. Also configures CFG_SETUP for remote configuration space
- * access.
- *
- * The address space has two regions to access configuration - local and remote.
- * We access local region for bus 0 (as RC is attached on bus 0) and remote
- * region for others with TYPE 1 access when bus > 1. As for device on bus = 1,
- * we will do TYPE 0 access as it will be on our secondary bus (logical).
- * CFG_SETUP is needed only for remote configuration access.
- */
-static void __iomem *ks_pcie_cfg_setup(struct keystone_pcie *ks_pcie, u8 bus,
- unsigned int devfn)
-{
- u8 device = PCI_SLOT(devfn), function = PCI_FUNC(devfn);
- struct pcie_port *pp = &ks_pcie->pp;
- u32 regval;
-
- if (bus == 0)
- return pp->dbi_base;
-
- regval = (bus << 16) | (device << 8) | function;
-
- /*
- * Since Bus#1 will be a virtual bus, we need to have TYPE0
- * access only.
- * TYPE 1
- */
- if (bus != 1)
- regval |= BIT(24);
-
- ks_dw_app_writel(ks_pcie, CFG_SETUP, regval);
- return pp->va_cfg0_base;
-}
-
-int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
- unsigned int devfn, int where, int size, u32 *val)
-{
- struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
- u8 bus_num = bus->number;
- void __iomem *addr;
-
- addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
-
- return dw_pcie_cfg_read(addr + where, size, val);
-}
-
-int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
- unsigned int devfn, int where, int size, u32 val)
-{
- struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
- u8 bus_num = bus->number;
- void __iomem *addr;
-
- addr = ks_pcie_cfg_setup(ks_pcie, bus_num, devfn);
-
- return dw_pcie_cfg_write(addr + where, size, val);
-}
-
-/**
- * ks_dw_pcie_v3_65_scan_bus() - keystone scan_bus post initialization
- *
- * This sets BAR0 to enable inbound access for MSI_IRQ register
- */
-void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp)
-{
- struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
-
- /* Configure and set up BAR0 */
- ks_dw_pcie_set_dbi_mode(ks_pcie);
-
- /* Enable BAR0 */
- dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_0, 1);
- dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_0, SZ_4K - 1);
-
- ks_dw_pcie_clear_dbi_mode(ks_pcie);
-
- /*
- * For BAR0, just setting bus address for inbound writes (MSI) should
- * be sufficient. Use physical address to avoid any conflicts.
- */
- dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_0, ks_pcie->app.start);
-}
-
-/**
- * ks_dw_pcie_link_up() - Check if link up
- */
-int ks_dw_pcie_link_up(struct pcie_port *pp)
-{
- u32 val;
-
- val = dw_pcie_readl_rc(pp, DEBUG0);
- return (val & LTSSM_STATE_MASK) == LTSSM_STATE_L0;
-}
-
-void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie)
-{
- u32 val;
-
- /* Disable Link training */
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- val &= ~LTSSM_EN_VAL;
- ks_dw_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
-
- /* Initiate Link Training */
- val = ks_dw_app_readl(ks_pcie, CMD_STATUS);
- ks_dw_app_writel(ks_pcie, CMD_STATUS, LTSSM_EN_VAL | val);
-}
-
-/**
- * ks_dw_pcie_host_init() - initialize host for v3_65 dw hardware
- *
- * Ioremap the register resources, initialize legacy irq domain
- * and call dw_pcie_v3_65_host_init() API to initialize the Keystone
- * PCI host controller.
- */
-int __init ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
- struct device_node *msi_intc_np)
-{
- struct pcie_port *pp = &ks_pcie->pp;
- struct device *dev = pp->dev;
- struct platform_device *pdev = to_platform_device(dev);
- struct resource *res;
-
- /* Index 0 is the config reg. space address */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- pp->dbi_base = devm_ioremap_resource(dev, res);
- if (IS_ERR(pp->dbi_base))
- return PTR_ERR(pp->dbi_base);
-
- /*
- * We set these same and is used in pcie rd/wr_other_conf
- * functions
- */
- pp->va_cfg0_base = pp->dbi_base + SPACE0_REMOTE_CFG_OFFSET;
- pp->va_cfg1_base = pp->va_cfg0_base;
-
- /* Index 1 is the application reg. space address */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- ks_pcie->va_app_base = devm_ioremap_resource(dev, res);
- if (IS_ERR(ks_pcie->va_app_base))
- return PTR_ERR(ks_pcie->va_app_base);
-
- ks_pcie->app = *res;
-
- /* Create legacy IRQ domain */
- ks_pcie->legacy_irq_domain =
- irq_domain_add_linear(ks_pcie->legacy_intc_np,
- MAX_LEGACY_IRQS,
- &ks_dw_pcie_legacy_irq_domain_ops,
- NULL);
- if (!ks_pcie->legacy_irq_domain) {
- dev_err(dev, "Failed to add irq domain for legacy irqs\n");
- return -EINVAL;
- }
-
- return dw_pcie_host_init(pp);
-}
diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/host/pci-keystone.c
deleted file mode 100644
index 043c19a05da1..000000000000
--- a/drivers/pci/host/pci-keystone.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- * PCIe host controller driver for Texas Instruments Keystone SoCs
- *
- * Copyright (C) 2013-2014 Texas Instruments., Ltd.
- * http://www.ti.com
- *
- * Author: Murali Karicheri <m-karicheri2@ti.com>
- * Implementation based on pci-exynos.c and pcie-designware.c
- *
- * 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/irqchip/chained_irq.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/irqdomain.h>
-#include <linux/init.h>
-#include <linux/msi.h>
-#include <linux/of_irq.h>
-#include <linux/of.h>
-#include <linux/of_pci.h>
-#include <linux/platform_device.h>
-#include <linux/phy/phy.h>
-#include <linux/resource.h>
-#include <linux/signal.h>
-
-#include "pcie-designware.h"
-#include "pci-keystone.h"
-
-#define DRIVER_NAME "keystone-pcie"
-
-/* driver specific constants */
-#define MAX_MSI_HOST_IRQS 8
-#define MAX_LEGACY_HOST_IRQS 4
-
-/* DEV_STAT_CTRL */
-#define PCIE_CAP_BASE 0x70
-
-/* PCIE controller device IDs */
-#define PCIE_RC_K2HK 0xb008
-#define PCIE_RC_K2E 0xb009
-#define PCIE_RC_K2L 0xb00a
-
-#define to_keystone_pcie(x) container_of(x, struct keystone_pcie, pp)
-
-static void quirk_limit_mrrs(struct pci_dev *dev)
-{
- struct pci_bus *bus = dev->bus;
- struct pci_dev *bridge = bus->self;
- static const struct pci_device_id rc_pci_devids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_TI, PCIE_RC_K2HK),
- .class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
- { PCI_DEVICE(PCI_VENDOR_ID_TI, PCIE_RC_K2E),
- .class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
- { PCI_DEVICE(PCI_VENDOR_ID_TI, PCIE_RC_K2L),
- .class = PCI_CLASS_BRIDGE_PCI << 8, .class_mask = ~0, },
- { 0, },
- };
-
- if (pci_is_root_bus(bus))
- return;
-
- /* look for the host bridge */
- while (!pci_is_root_bus(bus)) {
- bridge = bus->self;
- bus = bus->parent;
- }
-
- if (bridge) {
- /*
- * Keystone PCI controller has a h/w limitation of
- * 256 bytes maximum read request size. It can't handle
- * anything higher than this. So force this limit on
- * all downstream devices.
- */
- if (pci_match_id(rc_pci_devids, bridge)) {
- if (pcie_get_readrq(dev) > 256) {
- dev_info(&dev->dev, "limiting MRRS to 256\n");
- pcie_set_readrq(dev, 256);
- }
- }
- }
-}
-DECLARE_PCI_FIXUP_ENABLE(PCI_ANY_ID, PCI_ANY_ID, quirk_limit_mrrs);
-
-static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie)
-{
- struct pcie_port *pp = &ks_pcie->pp;
- struct device *dev = pp->dev;
- unsigned int retries;
-
- dw_pcie_setup_rc(pp);
-
- if (dw_pcie_link_up(pp)) {
- dev_err(dev, "Link already up\n");
- return 0;
- }
-
- /* check if the link is up or not */
- for (retries = 0; retries < 5; retries++) {
- ks_dw_pcie_initiate_link_train(ks_pcie);
- if (!dw_pcie_wait_for_link(pp))
- return 0;
- }
-
- dev_err(dev, "phy link never came up\n");
- return -ETIMEDOUT;
-}
-
-static void ks_pcie_msi_irq_handler(struct irq_desc *desc)
-{
- unsigned int irq = irq_desc_get_irq(desc);
- struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
- u32 offset = irq - ks_pcie->msi_host_irqs[0];
- struct pcie_port *pp = &ks_pcie->pp;
- struct device *dev = pp->dev;
- struct irq_chip *chip = irq_desc_get_chip(desc);
-
- dev_dbg(dev, "%s, irq %d\n", __func__, irq);
-
- /*
- * The chained irq handler installation would have replaced normal
- * interrupt driver handler so we need to take care of mask/unmask and
- * ack operation.
- */
- chained_irq_enter(chip, desc);
- ks_dw_pcie_handle_msi_irq(ks_pcie, offset);
- chained_irq_exit(chip, desc);
-}
-
-/**
- * ks_pcie_legacy_irq_handler() - Handle legacy interrupt
- * @irq: IRQ line for legacy interrupts
- * @desc: Pointer to irq descriptor
- *
- * Traverse through pending legacy interrupts and invoke handler for each. Also
- * takes care of interrupt controller level mask/ack operation.
- */
-static void ks_pcie_legacy_irq_handler(struct irq_desc *desc)
-{
- unsigned int irq = irq_desc_get_irq(desc);
- struct keystone_pcie *ks_pcie = irq_desc_get_handler_data(desc);
- struct pcie_port *pp = &ks_pcie->pp;
- struct device *dev = pp->dev;
- u32 irq_offset = irq - ks_pcie->legacy_host_irqs[0];
- struct irq_chip *chip = irq_desc_get_chip(desc);
-
- dev_dbg(dev, ": Handling legacy irq %d\n", irq);
-
- /*
- * The chained irq handler installation would have replaced normal
- * interrupt driver handler so we need to take care of mask/unmask and
- * ack operation.
- */
- chained_irq_enter(chip, desc);
- ks_dw_pcie_handle_legacy_irq(ks_pcie, irq_offset);
- chained_irq_exit(chip, desc);
-}
-
-static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie,
- char *controller, int *num_irqs)
-{
- int temp, max_host_irqs, legacy = 1, *host_irqs;
- struct device *dev = ks_pcie->pp.dev;
- struct device_node *np_pcie = dev->of_node, **np_temp;
-
- if (!strcmp(controller, "msi-interrupt-controller"))
- legacy = 0;
-
- if (legacy) {
- np_temp = &ks_pcie->legacy_intc_np;
- max_host_irqs = MAX_LEGACY_HOST_IRQS;
- host_irqs = &ks_pcie->legacy_host_irqs[0];
- } else {
- np_temp = &ks_pcie->msi_intc_np;
- max_host_irqs = MAX_MSI_HOST_IRQS;
- host_irqs = &ks_pcie->msi_host_irqs[0];
- }
-
- /* interrupt controller is in a child node */
- *np_temp = of_find_node_by_name(np_pcie, controller);
- if (!(*np_temp)) {
- dev_err(dev, "Node for %s is absent\n", controller);
- return -EINVAL;
- }
-
- temp = of_irq_count(*np_temp);
- if (!temp) {
- dev_err(dev, "No IRQ entries in %s\n", controller);
- return -EINVAL;
- }
-
- if (temp > max_host_irqs)
- dev_warn(dev, "Too many %s interrupts defined %u\n",
- (legacy ? "legacy" : "MSI"), temp);
-
- /*
- * support upto max_host_irqs. In dt from index 0 to 3 (legacy) or 0 to
- * 7 (MSI)
- */
- for (temp = 0; temp < max_host_irqs; temp++) {
- host_irqs[temp] = irq_of_parse_and_map(*np_temp, temp);
- if (!host_irqs[temp])
- break;
- }
-
- if (temp) {
- *num_irqs = temp;
- return 0;
- }
-
- return -EINVAL;
-}
-
-static void ks_pcie_setup_interrupts(struct keystone_pcie *ks_pcie)
-{
- int i;
-
- /* Legacy IRQ */
- for (i = 0; i < ks_pcie->num_legacy_host_irqs; i++) {
- irq_set_chained_handler_and_data(ks_pcie->legacy_host_irqs[i],
- ks_pcie_legacy_irq_handler,
- ks_pcie);
- }
- ks_dw_pcie_enable_legacy_irqs(ks_pcie);
-
- /* MSI IRQ */
- if (IS_ENABLED(CONFIG_PCI_MSI)) {
- for (i = 0; i < ks_pcie->num_msi_host_irqs; i++) {
- irq_set_chained_handler_and_data(ks_pcie->msi_host_irqs[i],
- ks_pcie_msi_irq_handler,
- ks_pcie);
- }
- }
-
- if (ks_pcie->error_irq > 0)
- ks_dw_pcie_enable_error_irq(ks_pcie);
-}
-
-/*
- * When a PCI device does not exist during config cycles, keystone host gets a
- * bus error instead of returning 0xffffffff. This handler always returns 0
- * for this kind of faults.
- */
-static int keystone_pcie_fault(unsigned long addr, unsigned int fsr,
- struct pt_regs *regs)
-{
- unsigned long instr = *(unsigned long *) instruction_pointer(regs);
-
- if ((instr & 0x0e100090) == 0x00100090) {
- int reg = (instr >> 12) & 15;
-
- regs->uregs[reg] = -1;
- regs->ARM_pc += 4;
- }
-
- return 0;
-}
-
-static void __init ks_pcie_host_init(struct pcie_port *pp)
-{
- struct keystone_pcie *ks_pcie = to_keystone_pcie(pp);
- u32 val;
-
- ks_pcie_establish_link(ks_pcie);
- ks_dw_pcie_setup_rc_app_regs(ks_pcie);
- ks_pcie_setup_interrupts(ks_pcie);
- writew(PCI_IO_RANGE_TYPE_32 | (PCI_IO_RANGE_TYPE_32 << 8),
- pp->dbi_base + PCI_IO_BASE);
-
- /* update the Vendor ID */
- writew(ks_pcie->device_id, pp->dbi_base + PCI_DEVICE_ID);
-
- /* update the DEV_STAT_CTRL to publish right mrrs */
- val = readl(pp->dbi_base + PCIE_CAP_BASE + PCI_EXP_DEVCTL);
- val &= ~PCI_EXP_DEVCTL_READRQ;
- /* set the mrrs to 256 bytes */
- val |= BIT(12);
- writel(val, pp->dbi_base + PCIE_CAP_BASE + PCI_EXP_DEVCTL);
-
- /*
- * PCIe access errors that result into OCP errors are caught by ARM as
- * "External aborts"
- */
- hook_fault_code(17, keystone_pcie_fault, SIGBUS, 0,
- "Asynchronous external abort");
-}
-
-static struct pcie_host_ops keystone_pcie_host_ops = {
- .rd_other_conf = ks_dw_pcie_rd_other_conf,
- .wr_other_conf = ks_dw_pcie_wr_other_conf,
- .link_up = ks_dw_pcie_link_up,
- .host_init = ks_pcie_host_init,
- .msi_set_irq = ks_dw_pcie_msi_set_irq,
- .msi_clear_irq = ks_dw_pcie_msi_clear_irq,
- .get_msi_addr = ks_dw_pcie_get_msi_addr,
- .msi_host_init = ks_dw_pcie_msi_host_init,
- .scan_bus = ks_dw_pcie_v3_65_scan_bus,
-};
-
-static irqreturn_t pcie_err_irq_handler(int irq, void *priv)
-{
- struct keystone_pcie *ks_pcie = priv;
-
- return ks_dw_pcie_handle_error_irq(ks_pcie);
-}
-
-static int __init ks_add_pcie_port(struct keystone_pcie *ks_pcie,
- struct platform_device *pdev)
-{
- struct pcie_port *pp = &ks_pcie->pp;
- struct device *dev = pp->dev;
- int ret;
-
- ret = ks_pcie_get_irq_controller_info(ks_pcie,
- "legacy-interrupt-controller",
- &ks_pcie->num_legacy_host_irqs);
- if (ret)
- return ret;
-
- if (IS_ENABLED(CONFIG_PCI_MSI)) {
- ret = ks_pcie_get_irq_controller_info(ks_pcie,
- "msi-interrupt-controller",
- &ks_pcie->num_msi_host_irqs);
- if (ret)
- return ret;
- }
-
- /*
- * Index 0 is the platform interrupt for error interrupt
- * from RC. This is optional.
- */
- ks_pcie->error_irq = irq_of_parse_and_map(ks_pcie->np, 0);
- if (ks_pcie->error_irq <= 0)
- dev_info(dev, "no error IRQ defined\n");
- else {
- ret = request_irq(ks_pcie->error_irq, pcie_err_irq_handler,
- IRQF_SHARED, "pcie-error-irq", ks_pcie);
- if (ret < 0) {
- dev_err(dev, "failed to request error IRQ %d\n",
- ks_pcie->error_irq);
- return ret;
- }
- }
-
- pp->root_bus_nr = -1;
- pp->ops = &keystone_pcie_host_ops;
- ret = ks_dw_pcie_host_init(ks_pcie, ks_pcie->msi_intc_np);
- if (ret) {
- dev_err(dev, "failed to initialize host\n");
- return ret;
- }
-
- return 0;
-}
-
-static const struct of_device_id ks_pcie_of_match[] = {
- {
- .type = "pci",
- .compatible = "ti,keystone-pcie",
- },
- { },
-};
-
-static int __exit ks_pcie_remove(struct platform_device *pdev)
-{
- struct keystone_pcie *ks_pcie = platform_get_drvdata(pdev);
-
- clk_disable_unprepare(ks_pcie->clk);
-
- return 0;
-}
-
-static int __init ks_pcie_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct keystone_pcie *ks_pcie;
- struct pcie_port *pp;
- struct resource *res;
- void __iomem *reg_p;
- struct phy *phy;
- int ret;
-
- ks_pcie = devm_kzalloc(dev, sizeof(*ks_pcie), GFP_KERNEL);
- if (!ks_pcie)
- return -ENOMEM;
-
- pp = &ks_pcie->pp;
- pp->dev = dev;
-
- /* initialize SerDes Phy if present */
- phy = devm_phy_get(dev, "pcie-phy");
- if (PTR_ERR_OR_ZERO(phy) == -EPROBE_DEFER)
- return PTR_ERR(phy);
-
- if (!IS_ERR_OR_NULL(phy)) {
- ret = phy_init(phy);
- if (ret < 0)
- return ret;
- }
-
- /* index 2 is to read PCI DEVICE_ID */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
- reg_p = devm_ioremap_resource(dev, res);
- if (IS_ERR(reg_p))
- return PTR_ERR(reg_p);
- ks_pcie->device_id = readl(reg_p) >> 16;
- devm_iounmap(dev, reg_p);
- devm_release_mem_region(dev, res->start, resource_size(res));
-
- ks_pcie->np = dev->of_node;
- platform_set_drvdata(pdev, ks_pcie);
- ks_pcie->clk = devm_clk_get(dev, "pcie");
- if (IS_ERR(ks_pcie->clk)) {
- dev_err(dev, "Failed to get pcie rc clock\n");
- return PTR_ERR(ks_pcie->clk);
- }
- ret = clk_prepare_enable(ks_pcie->clk);
- if (ret)
- return ret;
-
- ret = ks_add_pcie_port(ks_pcie, pdev);
- if (ret < 0)
- goto fail_clk;
-
- return 0;
-fail_clk:
- clk_disable_unprepare(ks_pcie->clk);
-
- return ret;
-}
-
-static struct platform_driver ks_pcie_driver __refdata = {
- .probe = ks_pcie_probe,
- .remove = __exit_p(ks_pcie_remove),
- .driver = {
- .name = "keystone-pcie",
- .of_match_table = of_match_ptr(ks_pcie_of_match),
- },
-};
-builtin_platform_driver(ks_pcie_driver);
diff --git a/drivers/pci/host/pci-keystone.h b/drivers/pci/host/pci-keystone.h
deleted file mode 100644
index bc54bafda068..000000000000
--- a/drivers/pci/host/pci-keystone.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Keystone PCI Controller's common includes
- *
- * Copyright (C) 2013-2014 Texas Instruments., Ltd.
- * http://www.ti.com
- *
- * Author: Murali Karicheri <m-karicheri2@ti.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.
- */
-
-#define MAX_LEGACY_IRQS 4
-#define MAX_MSI_HOST_IRQS 8
-#define MAX_LEGACY_HOST_IRQS 4
-
-struct keystone_pcie {
- struct pcie_port pp; /* pp.dbi_base is DT 0th res */
- struct clk *clk;
- /* PCI Device ID */
- u32 device_id;
- int num_legacy_host_irqs;
- int legacy_host_irqs[MAX_LEGACY_HOST_IRQS];
- struct device_node *legacy_intc_np;
-
- int num_msi_host_irqs;
- int msi_host_irqs[MAX_MSI_HOST_IRQS];
- struct device_node *msi_intc_np;
- struct irq_domain *legacy_irq_domain;
- struct device_node *np;
-
- int error_irq;
-
- /* Application register space */
- void __iomem *va_app_base; /* DT 1st resource */
- struct resource app;
-};
-
-/* Keystone DW specific MSI controller APIs/definitions */
-void ks_dw_pcie_handle_msi_irq(struct keystone_pcie *ks_pcie, int offset);
-phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp);
-
-/* Keystone specific PCI controller APIs */
-void ks_dw_pcie_enable_legacy_irqs(struct keystone_pcie *ks_pcie);
-void ks_dw_pcie_handle_legacy_irq(struct keystone_pcie *ks_pcie, int offset);
-void ks_dw_pcie_enable_error_irq(struct keystone_pcie *ks_pcie);
-irqreturn_t ks_dw_pcie_handle_error_irq(struct keystone_pcie *ks_pcie);
-int ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
- struct device_node *msi_intc_np);
-int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
- unsigned int devfn, int where, int size, u32 val);
-int ks_dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
- unsigned int devfn, int where, int size, u32 *val);
-void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie);
-int ks_dw_pcie_link_up(struct pcie_port *pp);
-void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie);
-void ks_dw_pcie_msi_set_irq(struct pcie_port *pp, int irq);
-void ks_dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq);
-void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp);
-int ks_dw_pcie_msi_host_init(struct pcie_port *pp,
- struct msi_controller *chip);
diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/host/pci-layerscape.c
deleted file mode 100644
index ea789138531b..000000000000
--- a/drivers/pci/host/pci-layerscape.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * PCIe host controller driver for Freescale Layerscape SoCs
- *
- * Copyright (C) 2014 Freescale Semiconductor.
- *
- * Author: Minghuan Lian <Minghuan.Lian@freescale.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.
- */
-
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/of_pci.h>
-#include <linux/of_platform.h>
-#include <linux/of_irq.h>
-#include <linux/of_address.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/resource.h>
-#include <linux/mfd/syscon.h>
-#include <linux/regmap.h>
-
-#include "pcie-designware.h"
-
-/* PEX1/2 Misc Ports Status Register */
-#define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4)
-#define LTSSM_STATE_SHIFT 20
-#define LTSSM_STATE_MASK 0x3f
-#define LTSSM_PCIE_L0 0x11 /* L0 state */
-
-/* PEX Internal Configuration Registers */
-#define PCIE_STRFMR1 0x71c /* Symbol Timer & Filter Mask Register1 */
-#define PCIE_DBI_RO_WR_EN 0x8bc /* DBI Read-Only Write Enable Register */
-
-struct ls_pcie_drvdata {
- u32 lut_offset;
- u32 ltssm_shift;
- u32 lut_dbg;
- struct pcie_host_ops *ops;
-};
-
-struct ls_pcie {
- struct pcie_port pp; /* pp.dbi_base is DT regs */
- void __iomem *lut;
- struct regmap *scfg;
- const struct ls_pcie_drvdata *drvdata;
- int index;
-};
-
-#define to_ls_pcie(x) container_of(x, struct ls_pcie, pp)
-
-static bool ls_pcie_is_bridge(struct ls_pcie *pcie)
-{
- u32 header_type;
-
- header_type = ioread8(pcie->pp.dbi_base + PCI_HEADER_TYPE);
- header_type &= 0x7f;
-
- return header_type == PCI_HEADER_TYPE_BRIDGE;
-}
-
-/* Clear multi-function bit */
-static void ls_pcie_clear_multifunction(struct ls_pcie *pcie)
-{
- iowrite8(PCI_HEADER_TYPE_BRIDGE, pcie->pp.dbi_base + PCI_HEADER_TYPE);
-}
-
-/* Fix class value */
-static void ls_pcie_fix_class(struct ls_pcie *pcie)
-{
- iowrite16(PCI_CLASS_BRIDGE_PCI, pcie->pp.dbi_base + PCI_CLASS_DEVICE);
-}
-
-/* Drop MSG TLP except for Vendor MSG */
-static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie)
-{
- u32 val;
-
- val = ioread32(pcie->pp.dbi_base + PCIE_STRFMR1);
- val &= 0xDFFFFFFF;
- iowrite32(val, pcie->pp.dbi_base + PCIE_STRFMR1);
-}
-
-static int ls1021_pcie_link_up(struct pcie_port *pp)
-{
- u32 state;
- struct ls_pcie *pcie = to_ls_pcie(pp);
-
- if (!pcie->scfg)
- return 0;
-
- regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), &state);
- state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK;
-
- if (state < LTSSM_PCIE_L0)
- return 0;
-
- return 1;
-}
-
-static void ls1021_pcie_host_init(struct pcie_port *pp)
-{
- struct device *dev = pp->dev;
- struct ls_pcie *pcie = to_ls_pcie(pp);
- u32 index[2];
-
- pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node,
- "fsl,pcie-scfg");
- if (IS_ERR(pcie->scfg)) {
- dev_err(dev, "No syscfg phandle specified\n");
- pcie->scfg = NULL;
- return;
- }
-
- if (of_property_read_u32_array(dev->of_node,
- "fsl,pcie-scfg", index, 2)) {
- pcie->scfg = NULL;
- return;
- }
- pcie->index = index[1];
-
- dw_pcie_setup_rc(pp);
-
- ls_pcie_drop_msg_tlp(pcie);
-}
-
-static int ls_pcie_link_up(struct pcie_port *pp)
-{
- struct ls_pcie *pcie = to_ls_pcie(pp);
- u32 state;
-
- state = (ioread32(pcie->lut + pcie->drvdata->lut_dbg) >>
- pcie->drvdata->ltssm_shift) &
- LTSSM_STATE_MASK;
-
- if (state < LTSSM_PCIE_L0)
- return 0;
-
- return 1;
-}
-
-static void ls_pcie_host_init(struct pcie_port *pp)
-{
- struct ls_pcie *pcie = to_ls_pcie(pp);
-
- iowrite32(1, pcie->pp.dbi_base + PCIE_DBI_RO_WR_EN);
- ls_pcie_fix_class(pcie);
- ls_pcie_clear_multifunction(pcie);
- ls_pcie_drop_msg_tlp(pcie);
- iowrite32(0, pcie->pp.dbi_base + PCIE_DBI_RO_WR_EN);
-}
-
-static int ls_pcie_msi_host_init(struct pcie_port *pp,
- struct msi_controller *chip)
-{
- struct device *dev = pp->dev;
- struct device_node *np = dev->of_node;
- struct device_node *msi_node;
-
- /*
- * The MSI domain is set by the generic of_msi_configure(). This
- * .msi_host_init() function keeps us from doing the default MSI
- * domain setup in dw_pcie_host_init() and also enforces the
- * requirement that "msi-parent" exists.
- */
- msi_node = of_parse_phandle(np, "msi-parent", 0);
- if (!msi_node) {
- dev_err(dev, "failed to find msi-parent\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static struct pcie_host_ops ls1021_pcie_host_ops = {
- .link_up = ls1021_pcie_link_up,
- .host_init = ls1021_pcie_host_init,
- .msi_host_init = ls_pcie_msi_host_init,
-};
-
-static struct pcie_host_ops ls_pcie_host_ops = {
- .link_up = ls_pcie_link_up,
- .host_init = ls_pcie_host_init,
- .msi_host_init = ls_pcie_msi_host_init,
-};
-
-static struct ls_pcie_drvdata ls1021_drvdata = {
- .ops = &ls1021_pcie_host_ops,
-};
-
-static struct ls_pcie_drvdata ls1043_drvdata = {
- .lut_offset = 0x10000,
- .ltssm_shift = 24,
- .lut_dbg = 0x7fc,
- .ops = &ls_pcie_host_ops,
-};
-
-static struct ls_pcie_drvdata ls1046_drvdata = {
- .lut_offset = 0x80000,
- .ltssm_shift = 24,
- .lut_dbg = 0x407fc,
- .ops = &ls_pcie_host_ops,
-};
-
-static struct ls_pcie_drvdata ls2080_drvdata = {
- .lut_offset = 0x80000,
- .ltssm_shift = 0,
- .lut_dbg = 0x7fc,
- .ops = &ls_pcie_host_ops,
-};
-
-static const struct of_device_id ls_pcie_of_match[] = {
- { .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata },
- { .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata },
- { .compatible = "fsl,ls1046a-pcie", .data = &ls1046_drvdata },
- { .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata },
- { .compatible = "fsl,ls2085a-pcie", .data = &ls2080_drvdata },
- { },
-};
-
-static int __init ls_add_pcie_port(struct ls_pcie *pcie)
-{
- struct pcie_port *pp = &pcie->pp;
- struct device *dev = pp->dev;
- int ret;
-
- ret = dw_pcie_host_init(pp);
- if (ret) {
- dev_err(dev, "failed to initialize host\n");
- return ret;
- }
-
- return 0;
-}
-
-static int __init ls_pcie_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- const struct of_device_id *match;
- struct ls_pcie *pcie;
- struct pcie_port *pp;
- struct resource *dbi_base;
- int ret;
-
- match = of_match_device(ls_pcie_of_match, dev);
- if (!match)
- return -ENODEV;
-
- pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
- if (!pcie)
- return -ENOMEM;
-
- pp = &pcie->pp;
- pp->dev = dev;
- pcie->drvdata = match->data;
- pp->ops = pcie->drvdata->ops;
-
- dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
- pcie->pp.dbi_base = devm_ioremap_resource(dev, dbi_base);
- if (IS_ERR(pcie->pp.dbi_base))
- return PTR_ERR(pcie->pp.dbi_base);
-
- pcie->lut = pcie->pp.dbi_base + pcie->drvdata->lut_offset;
-
- if (!ls_pcie_is_bridge(pcie))
- return -ENODEV;
-
- ret = ls_add_pcie_port(pcie);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static struct platform_driver ls_pcie_driver = {
- .driver = {
- .name = "layerscape-pcie",
- .of_match_table = ls_pcie_of_match,
- },
-};
-builtin_platform_driver_probe(ls_pcie_driver, ls_pcie_probe);
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 45a89d969700..cd7d51988738 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -133,6 +133,12 @@ struct mvebu_pcie {
int nports;
};
+struct mvebu_pcie_window {
+ phys_addr_t base;
+ phys_addr_t remap;
+ size_t size;
+};
+
/* Structure representing one PCIe interface */
struct mvebu_pcie_port {
char *name;
@@ -150,10 +156,8 @@ struct mvebu_pcie_port {
struct mvebu_sw_pci_bridge bridge;
struct device_node *dn;
struct mvebu_pcie *pcie;
- phys_addr_t memwin_base;
- size_t memwin_size;
- phys_addr_t iowin_base;
- size_t iowin_size;
+ struct mvebu_pcie_window memwin;
+ struct mvebu_pcie_window iowin;
u32 saved_pcie_stat;
};
@@ -379,23 +383,45 @@ static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port,
}
}
+static void mvebu_pcie_set_window(struct mvebu_pcie_port *port,
+ unsigned int target, unsigned int attribute,
+ const struct mvebu_pcie_window *desired,
+ struct mvebu_pcie_window *cur)
+{
+ if (desired->base == cur->base && desired->remap == cur->remap &&
+ desired->size == cur->size)
+ return;
+
+ if (cur->size != 0) {
+ mvebu_pcie_del_windows(port, cur->base, cur->size);
+ cur->size = 0;
+ cur->base = 0;
+
+ /*
+ * If something tries to change the window while it is enabled
+ * the change will not be done atomically. That would be
+ * difficult to do in the general case.
+ */
+ }
+
+ if (desired->size == 0)
+ return;
+
+ mvebu_pcie_add_windows(port, target, attribute, desired->base,
+ desired->size, desired->remap);
+ *cur = *desired;
+}
+
static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
{
- phys_addr_t iobase;
+ struct mvebu_pcie_window desired = {};
/* Are the new iobase/iolimit values invalid? */
if (port->bridge.iolimit < port->bridge.iobase ||
port->bridge.iolimitupper < port->bridge.iobaseupper ||
!(port->bridge.command & PCI_COMMAND_IO)) {
-
- /* If a window was configured, remove it */
- if (port->iowin_base) {
- mvebu_pcie_del_windows(port, port->iowin_base,
- port->iowin_size);
- port->iowin_base = 0;
- port->iowin_size = 0;
- }
-
+ mvebu_pcie_set_window(port, port->io_target, port->io_attr,
+ &desired, &port->iowin);
return;
}
@@ -412,32 +438,27 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port)
* specifications. iobase is the bus address, port->iowin_base
* is the CPU address.
*/
- iobase = ((port->bridge.iobase & 0xF0) << 8) |
- (port->bridge.iobaseupper << 16);
- port->iowin_base = port->pcie->io.start + iobase;
- port->iowin_size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) |
- (port->bridge.iolimitupper << 16)) -
- iobase) + 1;
-
- mvebu_pcie_add_windows(port, port->io_target, port->io_attr,
- port->iowin_base, port->iowin_size,
- iobase);
+ desired.remap = ((port->bridge.iobase & 0xF0) << 8) |
+ (port->bridge.iobaseupper << 16);
+ desired.base = port->pcie->io.start + desired.remap;
+ desired.size = ((0xFFF | ((port->bridge.iolimit & 0xF0) << 8) |
+ (port->bridge.iolimitupper << 16)) -
+ desired.remap) +
+ 1;
+
+ mvebu_pcie_set_window(port, port->io_target, port->io_attr, &desired,
+ &port->iowin);
}
static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
{
+ struct mvebu_pcie_window desired = {.remap = MVEBU_MBUS_NO_REMAP};
+
/* Are the new membase/memlimit values invalid? */
if (port->bridge.memlimit < port->bridge.membase ||
!(port->bridge.command & PCI_COMMAND_MEMORY)) {
-
- /* If a window was configured, remove it */
- if (port->memwin_base) {
- mvebu_pcie_del_windows(port, port->memwin_base,
- port->memwin_size);
- port->memwin_base = 0;
- port->memwin_size = 0;
- }
-
+ mvebu_pcie_set_window(port, port->mem_target, port->mem_attr,
+ &desired, &port->memwin);
return;
}
@@ -447,14 +468,12 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port)
* window to setup, according to the PCI-to-PCI bridge
* specifications.
*/
- port->memwin_base = ((port->bridge.membase & 0xFFF0) << 16);
- port->memwin_size =
- (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) -
- port->memwin_base + 1;
-
- mvebu_pcie_add_windows(port, port->mem_target, port->mem_attr,
- port->memwin_base, port->memwin_size,
- MVEBU_MBUS_NO_REMAP);
+ desired.base = ((port->bridge.membase & 0xFFF0) << 16);
+ desired.size = (((port->bridge.memlimit & 0xFFF0) << 16) | 0xFFFFF) -
+ desired.base + 1;
+
+ mvebu_pcie_set_window(port, port->mem_target, port->mem_attr, &desired,
+ &port->memwin);
}
/*
@@ -1162,7 +1181,7 @@ static int mvebu_pcie_powerup(struct mvebu_pcie_port *port)
return ret;
if (port->reset_gpio) {
- u32 reset_udelay = 20000;
+ u32 reset_udelay = PCI_PM_D3COLD_WAIT * 1000;
of_property_read_u32(port->dn, "reset-delay-us",
&reset_udelay);
diff --git a/drivers/pci/host/pci-thunder-pem.c b/drivers/pci/host/pci-thunder-pem.c
index af722eb0ca75..52b5bdccf5f0 100644
--- a/drivers/pci/host/pci-thunder-pem.c
+++ b/drivers/pci/host/pci-thunder-pem.c
@@ -36,7 +36,7 @@ struct thunder_pem_pci {
static int thunder_pem_bridge_read(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
- u64 read_val;
+ u64 read_val, tmp_val;
struct pci_config_window *cfg = bus->sysdata;
struct thunder_pem_pci *pem_pci = (struct thunder_pem_pci *)cfg->priv;
@@ -65,13 +65,28 @@ static int thunder_pem_bridge_read(struct pci_bus *bus, unsigned int devfn,
read_val |= 0x00007000; /* Skip MSI CAP */
break;
case 0x70: /* Express Cap */
- /* PME interrupt on vector 2*/
- read_val |= (2u << 25);
+ /*
+ * Change PME interrupt to vector 2 on T88 where it
+ * reads as 0, else leave it alone.
+ */
+ if (!(read_val & (0x1f << 25)))
+ read_val |= (2u << 25);
break;
case 0xb0: /* MSI-X Cap */
- /* TableSize=4, Next Cap is EA */
+ /* TableSize=2 or 4, Next Cap is EA */
read_val &= 0xc00000ff;
- read_val |= 0x0003bc00;
+ /*
+ * If Express Cap(0x70) raw PME vector reads as 0 we are on
+ * T88 and TableSize is reported as 4, else TableSize
+ * is 2.
+ */
+ writeq(0x70, pem_pci->pem_reg_base + PEM_CFG_RD);
+ tmp_val = readq(pem_pci->pem_reg_base + PEM_CFG_RD);
+ tmp_val >>= 32;
+ if (!(tmp_val & (0x1f << 25)))
+ read_val |= 0x0003bc00;
+ else
+ read_val |= 0x0001bc00;
break;
case 0xb4:
/* Table offset=0, BIR=0 */
diff --git a/drivers/pci/host/pci-versatile.c b/drivers/pci/host/pci-versatile.c
index b7dc07002f13..5ebee7d37ff5 100644
--- a/drivers/pci/host/pci-versatile.c
+++ b/drivers/pci/host/pci-versatile.c
@@ -124,7 +124,7 @@ static int versatile_pci_probe(struct platform_device *pdev)
int ret, i, myslot = -1;
u32 val;
void __iomem *local_pci_cfg_base;
- struct pci_bus *bus;
+ struct pci_bus *bus, *child;
LIST_HEAD(pci_res);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -204,6 +204,8 @@ static int versatile_pci_probe(struct platform_device *pdev)
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
pci_assign_unassigned_bus_resources(bus);
+ list_for_each_entry(child, &bus->children, node)
+ pcie_bus_configure_settings(child);
pci_bus_add_devices(bus);
return 0;
diff --git a/drivers/pci/host/pci-xgene.c b/drivers/pci/host/pci-xgene.c
index 7c3b54b9eb17..1a6108788f6f 100644
--- a/drivers/pci/host/pci-xgene.c
+++ b/drivers/pci/host/pci-xgene.c
@@ -246,14 +246,11 @@ static int xgene_pcie_ecam_init(struct pci_config_window *cfg, u32 ipversion)
ret = xgene_get_csr_resource(adev, &csr);
if (ret) {
dev_err(dev, "can't get CSR resource\n");
- kfree(port);
return ret;
}
port->csr_base = devm_ioremap_resource(dev, &csr);
- if (IS_ERR(port->csr_base)) {
- kfree(port);
- return -ENOMEM;
- }
+ if (IS_ERR(port->csr_base))
+ return PTR_ERR(port->csr_base);
port->cfg_base = cfg->win;
port->version = ipversion;
@@ -638,7 +635,7 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
struct device_node *dn = dev->of_node;
struct xgene_pcie_port *port;
resource_size_t iobase = 0;
- struct pci_bus *bus;
+ struct pci_bus *bus, *child;
int ret;
LIST_HEAD(res);
@@ -681,6 +678,8 @@ static int xgene_pcie_probe_bridge(struct platform_device *pdev)
pci_scan_child_bus(bus);
pci_assign_unassigned_bus_resources(bus);
+ list_for_each_entry(child, &bus->children, node)
+ pcie_bus_configure_settings(child);
pci_bus_add_devices(bus);
return 0;
diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c
index 0c1540225ca3..5043b5f00ed8 100644
--- a/drivers/pci/host/pcie-altera.c
+++ b/drivers/pci/host/pcie-altera.c
@@ -65,7 +65,7 @@
(((TLP_REQ_ID(pcie->root_bus_nr, RP_DEVFN)) << 16) | (tag << 8) | (be))
#define TLP_CFG_DW2(bus, devfn, offset) \
(((bus) << 24) | ((devfn) << 16) | (offset))
-#define TLP_COMP_STATUS(s) (((s) >> 12) & 7)
+#define TLP_COMP_STATUS(s) (((s) >> 13) & 7)
#define TLP_HDR_SIZE 3
#define TLP_LOOP 500
diff --git a/drivers/pci/host/pcie-armada8k.c b/drivers/pci/host/pcie-armada8k.c
deleted file mode 100644
index 0ac0f18690f2..000000000000
--- a/drivers/pci/host/pcie-armada8k.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * PCIe host controller driver for Marvell Armada-8K SoCs
- *
- * Armada-8K PCIe Glue Layer Source Code
- *
- * 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.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/of.h>
-#include <linux/pci.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/resource.h>
-#include <linux/of_pci.h>
-#include <linux/of_irq.h>
-
-#include "pcie-designware.h"
-
-struct armada8k_pcie {
- struct pcie_port pp; /* pp.dbi_base is DT ctrl */
- struct clk *clk;
-};
-
-#define PCIE_VENDOR_REGS_OFFSET 0x8000
-
-#define PCIE_GLOBAL_CONTROL_REG (PCIE_VENDOR_REGS_OFFSET + 0x0)
-#define PCIE_APP_LTSSM_EN BIT(2)
-#define PCIE_DEVICE_TYPE_SHIFT 4
-#define PCIE_DEVICE_TYPE_MASK 0xF
-#define PCIE_DEVICE_TYPE_RC 0x4 /* Root complex */
-
-#define PCIE_GLOBAL_STATUS_REG (PCIE_VENDOR_REGS_OFFSET + 0x8)
-#define PCIE_GLB_STS_RDLH_LINK_UP BIT(1)
-#define PCIE_GLB_STS_PHY_LINK_UP BIT(9)
-
-#define PCIE_GLOBAL_INT_CAUSE1_REG (PCIE_VENDOR_REGS_OFFSET + 0x1C)
-#define PCIE_GLOBAL_INT_MASK1_REG (PCIE_VENDOR_REGS_OFFSET + 0x20)
-#define PCIE_INT_A_ASSERT_MASK BIT(9)
-#define PCIE_INT_B_ASSERT_MASK BIT(10)
-#define PCIE_INT_C_ASSERT_MASK BIT(11)
-#define PCIE_INT_D_ASSERT_MASK BIT(12)
-
-#define PCIE_ARCACHE_TRC_REG (PCIE_VENDOR_REGS_OFFSET + 0x50)
-#define PCIE_AWCACHE_TRC_REG (PCIE_VENDOR_REGS_OFFSET + 0x54)
-#define PCIE_ARUSER_REG (PCIE_VENDOR_REGS_OFFSET + 0x5C)
-#define PCIE_AWUSER_REG (PCIE_VENDOR_REGS_OFFSET + 0x60)
-/*
- * AR/AW Cache defauls: Normal memory, Write-Back, Read / Write
- * allocate
- */
-#define ARCACHE_DEFAULT_VALUE 0x3511
-#define AWCACHE_DEFAULT_VALUE 0x5311
-
-#define DOMAIN_OUTER_SHAREABLE 0x2
-#define AX_USER_DOMAIN_MASK 0x3
-#define AX_USER_DOMAIN_SHIFT 4
-
-#define to_armada8k_pcie(x) container_of(x, struct armada8k_pcie, pp)
-
-static int armada8k_pcie_link_up(struct pcie_port *pp)
-{
- u32 reg;
- u32 mask = PCIE_GLB_STS_RDLH_LINK_UP | PCIE_GLB_STS_PHY_LINK_UP;
-
- reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_STATUS_REG);
-
- if ((reg & mask) == mask)
- return 1;
-
- dev_dbg(pp->dev, "No link detected (Global-Status: 0x%08x).\n", reg);
- return 0;
-}
-
-static void armada8k_pcie_establish_link(struct armada8k_pcie *pcie)
-{
- struct pcie_port *pp = &pcie->pp;
- u32 reg;
-
- if (!dw_pcie_link_up(pp)) {
- /* Disable LTSSM state machine to enable configuration */
- reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_CONTROL_REG);
- reg &= ~(PCIE_APP_LTSSM_EN);
- dw_pcie_writel_rc(pp, PCIE_GLOBAL_CONTROL_REG, reg);
- }
-
- /* Set the device to root complex mode */
- reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_CONTROL_REG);
- reg &= ~(PCIE_DEVICE_TYPE_MASK << PCIE_DEVICE_TYPE_SHIFT);
- reg |= PCIE_DEVICE_TYPE_RC << PCIE_DEVICE_TYPE_SHIFT;
- dw_pcie_writel_rc(pp, PCIE_GLOBAL_CONTROL_REG, reg);
-
- /* Set the PCIe master AxCache attributes */
- dw_pcie_writel_rc(pp, PCIE_ARCACHE_TRC_REG, ARCACHE_DEFAULT_VALUE);
- dw_pcie_writel_rc(pp, PCIE_AWCACHE_TRC_REG, AWCACHE_DEFAULT_VALUE);
-
- /* Set the PCIe master AxDomain attributes */
- reg = dw_pcie_readl_rc(pp, PCIE_ARUSER_REG);
- reg &= ~(AX_USER_DOMAIN_MASK << AX_USER_DOMAIN_SHIFT);
- reg |= DOMAIN_OUTER_SHAREABLE << AX_USER_DOMAIN_SHIFT;
- dw_pcie_writel_rc(pp, PCIE_ARUSER_REG, reg);
-
- reg = dw_pcie_readl_rc(pp, PCIE_AWUSER_REG);
- reg &= ~(AX_USER_DOMAIN_MASK << AX_USER_DOMAIN_SHIFT);
- reg |= DOMAIN_OUTER_SHAREABLE << AX_USER_DOMAIN_SHIFT;
- dw_pcie_writel_rc(pp, PCIE_AWUSER_REG, reg);
-
- /* Enable INT A-D interrupts */
- reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_INT_MASK1_REG);
- reg |= PCIE_INT_A_ASSERT_MASK | PCIE_INT_B_ASSERT_MASK |
- PCIE_INT_C_ASSERT_MASK | PCIE_INT_D_ASSERT_MASK;
- dw_pcie_writel_rc(pp, PCIE_GLOBAL_INT_MASK1_REG, reg);
-
- if (!dw_pcie_link_up(pp)) {
- /* Configuration done. Start LTSSM */
- reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_CONTROL_REG);
- reg |= PCIE_APP_LTSSM_EN;
- dw_pcie_writel_rc(pp, PCIE_GLOBAL_CONTROL_REG, reg);
- }
-
- /* Wait until the link becomes active again */
- if (dw_pcie_wait_for_link(pp))
- dev_err(pp->dev, "Link not up after reconfiguration\n");
-}
-
-static void armada8k_pcie_host_init(struct pcie_port *pp)
-{
- struct armada8k_pcie *pcie = to_armada8k_pcie(pp);
-
- dw_pcie_setup_rc(pp);
- armada8k_pcie_establish_link(pcie);
-}
-
-static irqreturn_t armada8k_pcie_irq_handler(int irq, void *arg)
-{
- struct armada8k_pcie *pcie = arg;
- struct pcie_port *pp = &pcie->pp;
- u32 val;
-
- /*
- * Interrupts are directly handled by the device driver of the
- * PCI device. However, they are also latched into the PCIe
- * controller, so we simply discard them.
- */
- val = dw_pcie_readl_rc(pp, PCIE_GLOBAL_INT_CAUSE1_REG);
- dw_pcie_writel_rc(pp, PCIE_GLOBAL_INT_CAUSE1_REG, val);
-
- return IRQ_HANDLED;
-}
-
-static struct pcie_host_ops armada8k_pcie_host_ops = {
- .link_up = armada8k_pcie_link_up,
- .host_init = armada8k_pcie_host_init,
-};
-
-static int armada8k_add_pcie_port(struct armada8k_pcie *pcie,
- struct platform_device *pdev)
-{
- struct pcie_port *pp = &pcie->pp;
- struct device *dev = &pdev->dev;
- int ret;
-
- pp->root_bus_nr = -1;
- pp->ops = &armada8k_pcie_host_ops;
-
- pp->irq = platform_get_irq(pdev, 0);
- if (!pp->irq) {
- dev_err(dev, "failed to get irq for port\n");
- return -ENODEV;
- }
-
- ret = devm_request_irq(dev, pp->irq, armada8k_pcie_irq_handler,
- IRQF_SHARED, "armada8k-pcie", pcie);
- if (ret) {
- dev_err(dev, "failed to request irq %d\n", pp->irq);
- return ret;
- }
-
- ret = dw_pcie_host_init(pp);
- if (ret) {
- dev_err(dev, "failed to initialize host: %d\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-static int armada8k_pcie_probe(struct platform_device *pdev)
-{
- struct armada8k_pcie *pcie;
- struct pcie_port *pp;
- struct device *dev = &pdev->dev;
- struct resource *base;
- int ret;
-
- pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
- if (!pcie)
- return -ENOMEM;
-
- pcie->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(pcie->clk))
- return PTR_ERR(pcie->clk);
-
- clk_prepare_enable(pcie->clk);
-
- pp = &pcie->pp;
- pp->dev = dev;
-
- /* Get the dw-pcie unit configuration/control registers base. */
- base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl");
- pp->dbi_base = devm_ioremap_resource(dev, base);
- if (IS_ERR(pp->dbi_base)) {
- dev_err(dev, "couldn't remap regs base %p\n", base);
- ret = PTR_ERR(pp->dbi_base);
- goto fail;
- }
-
- ret = armada8k_add_pcie_port(pcie, pdev);
- if (ret)
- goto fail;
-
- return 0;
-
-fail:
- if (!IS_ERR(pcie->clk))
- clk_disable_unprepare(pcie->clk);
-
- return ret;
-}
-
-static const struct of_device_id armada8k_pcie_of_match[] = {
- { .compatible = "marvell,armada8k-pcie", },
- {},
-};
-
-static struct platform_driver armada8k_pcie_driver = {
- .probe = armada8k_pcie_probe,
- .driver = {
- .name = "armada8k-pcie",
- .of_match_table = of_match_ptr(armada8k_pcie_of_match),
- },
-};
-builtin_platform_driver(armada8k_pcie_driver);
diff --git a/drivers/pci/host/pcie-artpec6.c b/drivers/pci/host/pcie-artpec6.c
deleted file mode 100644
index 212786b27f1a..000000000000
--- a/drivers/pci/host/pcie-artpec6.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * 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; /* pp.dbi_base is DT dbi */
- struct regmap *regmap; /* DT axis,syscon-pcie */
- void __iomem *phy_base; /* DT phy */
-};
-
-/* 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 u32 artpec6_pcie_readl(struct artpec6_pcie *artpec6_pcie, u32 offset)
-{
- u32 val;
-
- regmap_read(artpec6_pcie->regmap, offset, &val);
- return val;
-}
-
-static void artpec6_pcie_writel(struct artpec6_pcie *artpec6_pcie, u32 offset, u32 val)
-{
- regmap_write(artpec6_pcie->regmap, offset, val);
-}
-
-static int artpec6_pcie_establish_link(struct artpec6_pcie *artpec6_pcie)
-{
- struct pcie_port *pp = &artpec6_pcie->pp;
- u32 val;
- unsigned int retries;
-
- /* Hold DW core in reset */
- val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
- val |= PCIECFG_CORE_RESET_REQ;
- artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
-
- val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
- 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;
- artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
- usleep_range(5000, 6000);
-
- val = artpec6_pcie_readl(artpec6_pcie, NOCCFG);
- val |= NOCCFG_ENABLE_CLK_PCIE;
- artpec6_pcie_writel(artpec6_pcie, NOCCFG, val);
- usleep_range(20, 30);
-
- val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
- val |= PCIECFG_PCLK_ENABLE | PCIECFG_PLL_ENABLE;
- artpec6_pcie_writel(artpec6_pcie, PCIECFG, val);
- usleep_range(6000, 7000);
-
- val = artpec6_pcie_readl(artpec6_pcie, NOCCFG);
- val &= ~NOCCFG_POWER_PCIE_IDLEREQ;
- artpec6_pcie_writel(artpec6_pcie, NOCCFG, val);
-
- retries = 50;
- do {
- usleep_range(1000, 2000);
- val = artpec6_pcie_readl(artpec6_pcie, NOCCFG);
- 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 */
- val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
- val &= ~PCIECFG_CORE_RESET_REQ;
- artpec6_pcie_writel(artpec6_pcie, 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.
- */
- dw_pcie_writel_rc(pp, MISC_CONTROL_1_OFF, DBI_RO_WR_EN);
-
- 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 */
- val = artpec6_pcie_readl(artpec6_pcie, PCIECFG);
- val |= PCIECFG_LTSSM_ENABLE;
- artpec6_pcie_writel(artpec6_pcie, 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",
- dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R0),
- dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R1));
-
- return -ETIMEDOUT;
-}
-
-static void artpec6_pcie_enable_interrupts(struct artpec6_pcie *artpec6_pcie)
-{
- struct pcie_port *pp = &artpec6_pcie->pp;
-
- if (IS_ENABLED(CONFIG_PCI_MSI))
- dw_pcie_msi_init(pp);
-}
-
-static void artpec6_pcie_host_init(struct pcie_port *pp)
-{
- struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pp);
-
- artpec6_pcie_establish_link(artpec6_pcie);
- artpec6_pcie_enable_interrupts(artpec6_pcie);
-}
-
-static struct pcie_host_ops artpec6_pcie_host_ops = {
- .host_init = artpec6_pcie_host_init,
-};
-
-static irqreturn_t artpec6_pcie_msi_handler(int irq, void *arg)
-{
- struct artpec6_pcie *artpec6_pcie = arg;
- struct pcie_port *pp = &artpec6_pcie->pp;
-
- return dw_handle_msi_irq(pp);
-}
-
-static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie,
- struct platform_device *pdev)
-{
- struct pcie_port *pp = &artpec6_pcie->pp;
- struct device *dev = pp->dev;
- int ret;
-
- if (IS_ENABLED(CONFIG_PCI_MSI)) {
- pp->msi_irq = platform_get_irq_byname(pdev, "msi");
- if (pp->msi_irq <= 0) {
- dev_err(dev, "failed to get MSI irq\n");
- return -ENODEV;
- }
-
- ret = devm_request_irq(dev, pp->msi_irq,
- artpec6_pcie_msi_handler,
- IRQF_SHARED | IRQF_NO_THREAD,
- "artpec6-pcie-msi", artpec6_pcie);
- if (ret) {
- dev_err(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(dev, "failed to initialize host\n");
- return ret;
- }
-
- return 0;
-}
-
-static int artpec6_pcie_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct artpec6_pcie *artpec6_pcie;
- struct pcie_port *pp;
- struct resource *dbi_base;
- struct resource *phy_base;
- int ret;
-
- artpec6_pcie = devm_kzalloc(dev, sizeof(*artpec6_pcie), GFP_KERNEL);
- if (!artpec6_pcie)
- return -ENOMEM;
-
- pp = &artpec6_pcie->pp;
- pp->dev = dev;
-
- dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
- pp->dbi_base = devm_ioremap_resource(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(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(dev->of_node,
- "axis,syscon-pcie");
- if (IS_ERR(artpec6_pcie->regmap))
- return PTR_ERR(artpec6_pcie->regmap);
-
- ret = artpec6_add_pcie_port(artpec6_pcie, pdev);
- if (ret < 0)
- return ret;
-
- 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);
diff --git a/drivers/pci/host/pcie-designware-plat.c b/drivers/pci/host/pcie-designware-plat.c
deleted file mode 100644
index 1a02038c4640..000000000000
--- a/drivers/pci/host/pcie-designware-plat.c
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * PCIe RC driver for Synopsys DesignWare Core
- *
- * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
- *
- * Authors: Joao Pinto <Joao.Pinto@synopsys.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.
- */
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/of_gpio.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/resource.h>
-#include <linux/signal.h>
-#include <linux/types.h>
-
-#include "pcie-designware.h"
-
-struct dw_plat_pcie {
- struct pcie_port pp; /* pp.dbi_base is DT 0th resource */
-};
-
-static irqreturn_t dw_plat_pcie_msi_irq_handler(int irq, void *arg)
-{
- struct pcie_port *pp = arg;
-
- return dw_handle_msi_irq(pp);
-}
-
-static void dw_plat_pcie_host_init(struct pcie_port *pp)
-{
- dw_pcie_setup_rc(pp);
- dw_pcie_wait_for_link(pp);
-
- if (IS_ENABLED(CONFIG_PCI_MSI))
- dw_pcie_msi_init(pp);
-}
-
-static struct pcie_host_ops dw_plat_pcie_host_ops = {
- .host_init = dw_plat_pcie_host_init,
-};
-
-static int dw_plat_add_pcie_port(struct pcie_port *pp,
- struct platform_device *pdev)
-{
- struct device *dev = pp->dev;
- int ret;
-
- pp->irq = platform_get_irq(pdev, 1);
- if (pp->irq < 0)
- return pp->irq;
-
- if (IS_ENABLED(CONFIG_PCI_MSI)) {
- pp->msi_irq = platform_get_irq(pdev, 0);
- if (pp->msi_irq < 0)
- return pp->msi_irq;
-
- ret = devm_request_irq(dev, pp->msi_irq,
- dw_plat_pcie_msi_irq_handler,
- IRQF_SHARED, "dw-plat-pcie-msi", pp);
- if (ret) {
- dev_err(dev, "failed to request MSI IRQ\n");
- return ret;
- }
- }
-
- pp->root_bus_nr = -1;
- pp->ops = &dw_plat_pcie_host_ops;
-
- ret = dw_pcie_host_init(pp);
- if (ret) {
- dev_err(dev, "failed to initialize host\n");
- return ret;
- }
-
- return 0;
-}
-
-static int dw_plat_pcie_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct dw_plat_pcie *dw_plat_pcie;
- struct pcie_port *pp;
- struct resource *res; /* Resource from DT */
- int ret;
-
- dw_plat_pcie = devm_kzalloc(dev, sizeof(*dw_plat_pcie), GFP_KERNEL);
- if (!dw_plat_pcie)
- return -ENOMEM;
-
- pp = &dw_plat_pcie->pp;
- pp->dev = dev;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- pp->dbi_base = devm_ioremap_resource(dev, res);
- if (IS_ERR(pp->dbi_base))
- return PTR_ERR(pp->dbi_base);
-
- ret = dw_plat_add_pcie_port(pp, pdev);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static const struct of_device_id dw_plat_pcie_of_match[] = {
- { .compatible = "snps,dw-pcie", },
- {},
-};
-
-static struct platform_driver dw_plat_pcie_driver = {
- .driver = {
- .name = "dw-pcie",
- .of_match_table = dw_plat_pcie_of_match,
- },
- .probe = dw_plat_pcie_probe,
-};
-builtin_platform_driver(dw_plat_pcie_driver);
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
deleted file mode 100644
index af8f6e92e885..000000000000
--- a/drivers/pci/host/pcie-designware.c
+++ /dev/null
@@ -1,902 +0,0 @@
-/*
- * Synopsys Designware PCIe host controller driver
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Author: Jingoo Han <jg1.han@samsung.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.
- */
-
-#include <linux/irq.h>
-#include <linux/irqdomain.h>
-#include <linux/kernel.h>
-#include <linux/msi.h>
-#include <linux/of_address.h>
-#include <linux/of_pci.h>
-#include <linux/pci.h>
-#include <linux/pci_regs.h>
-#include <linux/platform_device.h>
-#include <linux/types.h>
-#include <linux/delay.h>
-
-#include "pcie-designware.h"
-
-/* Parameters for the waiting for link up routine */
-#define LINK_WAIT_MAX_RETRIES 10
-#define LINK_WAIT_USLEEP_MIN 90000
-#define LINK_WAIT_USLEEP_MAX 100000
-
-/* Parameters for the waiting for iATU enabled routine */
-#define LINK_WAIT_MAX_IATU_RETRIES 5
-#define LINK_WAIT_IATU_MIN 9000
-#define LINK_WAIT_IATU_MAX 10000
-
-/* Synopsys-specific PCIe configuration registers */
-#define PCIE_PORT_LINK_CONTROL 0x710
-#define PORT_LINK_MODE_MASK (0x3f << 16)
-#define PORT_LINK_MODE_1_LANES (0x1 << 16)
-#define PORT_LINK_MODE_2_LANES (0x3 << 16)
-#define PORT_LINK_MODE_4_LANES (0x7 << 16)
-#define PORT_LINK_MODE_8_LANES (0xf << 16)
-
-#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
-#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
-#define PORT_LOGIC_LINK_WIDTH_MASK (0x1f << 8)
-#define PORT_LOGIC_LINK_WIDTH_1_LANES (0x1 << 8)
-#define PORT_LOGIC_LINK_WIDTH_2_LANES (0x2 << 8)
-#define PORT_LOGIC_LINK_WIDTH_4_LANES (0x4 << 8)
-#define PORT_LOGIC_LINK_WIDTH_8_LANES (0x8 << 8)
-
-#define PCIE_MSI_ADDR_LO 0x820
-#define PCIE_MSI_ADDR_HI 0x824
-#define PCIE_MSI_INTR0_ENABLE 0x828
-#define PCIE_MSI_INTR0_MASK 0x82C
-#define PCIE_MSI_INTR0_STATUS 0x830
-
-#define PCIE_ATU_VIEWPORT 0x900
-#define PCIE_ATU_REGION_INBOUND (0x1 << 31)
-#define PCIE_ATU_REGION_OUTBOUND (0x0 << 31)
-#define PCIE_ATU_REGION_INDEX2 (0x2 << 0)
-#define PCIE_ATU_REGION_INDEX1 (0x1 << 0)
-#define PCIE_ATU_REGION_INDEX0 (0x0 << 0)
-#define PCIE_ATU_CR1 0x904
-#define PCIE_ATU_TYPE_MEM (0x0 << 0)
-#define PCIE_ATU_TYPE_IO (0x2 << 0)
-#define PCIE_ATU_TYPE_CFG0 (0x4 << 0)
-#define PCIE_ATU_TYPE_CFG1 (0x5 << 0)
-#define PCIE_ATU_CR2 0x908
-#define PCIE_ATU_ENABLE (0x1 << 31)
-#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30)
-#define PCIE_ATU_LOWER_BASE 0x90C
-#define PCIE_ATU_UPPER_BASE 0x910
-#define PCIE_ATU_LIMIT 0x914
-#define PCIE_ATU_LOWER_TARGET 0x918
-#define PCIE_ATU_BUS(x) (((x) & 0xff) << 24)
-#define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19)
-#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
-#define PCIE_ATU_UPPER_TARGET 0x91C
-
-/*
- * iATU Unroll-specific register definitions
- * From 4.80 core version the address translation will be made by unroll
- */
-#define PCIE_ATU_UNR_REGION_CTRL1 0x00
-#define PCIE_ATU_UNR_REGION_CTRL2 0x04
-#define PCIE_ATU_UNR_LOWER_BASE 0x08
-#define PCIE_ATU_UNR_UPPER_BASE 0x0C
-#define PCIE_ATU_UNR_LIMIT 0x10
-#define PCIE_ATU_UNR_LOWER_TARGET 0x14
-#define PCIE_ATU_UNR_UPPER_TARGET 0x18
-
-/* Register address builder */
-#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) ((0x3 << 20) | (region << 9))
-
-/* PCIe Port Logic registers */
-#define PLR_OFFSET 0x700
-#define PCIE_PHY_DEBUG_R1 (PLR_OFFSET + 0x2c)
-#define PCIE_PHY_DEBUG_R1_LINK_UP (0x1 << 4)
-#define PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING (0x1 << 29)
-
-static struct pci_ops dw_pcie_ops;
-
-int dw_pcie_cfg_read(void __iomem *addr, int size, u32 *val)
-{
- if ((uintptr_t)addr & (size - 1)) {
- *val = 0;
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- if (size == 4)
- *val = readl(addr);
- else if (size == 2)
- *val = readw(addr);
- else if (size == 1)
- *val = readb(addr);
- else {
- *val = 0;
- return PCIBIOS_BAD_REGISTER_NUMBER;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-int dw_pcie_cfg_write(void __iomem *addr, int size, u32 val)
-{
- if ((uintptr_t)addr & (size - 1))
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- if (size == 4)
- writel(val, addr);
- else if (size == 2)
- writew(val, addr);
- else if (size == 1)
- writeb(val, addr);
- else
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-u32 dw_pcie_readl_rc(struct pcie_port *pp, u32 reg)
-{
- if (pp->ops->readl_rc)
- return pp->ops->readl_rc(pp, reg);
-
- return readl(pp->dbi_base + reg);
-}
-
-void dw_pcie_writel_rc(struct pcie_port *pp, u32 reg, u32 val)
-{
- if (pp->ops->writel_rc)
- pp->ops->writel_rc(pp, reg, val);
- else
- writel(val, pp->dbi_base + reg);
-}
-
-static u32 dw_pcie_readl_unroll(struct pcie_port *pp, u32 index, u32 reg)
-{
- u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
-
- return dw_pcie_readl_rc(pp, offset + reg);
-}
-
-static void dw_pcie_writel_unroll(struct pcie_port *pp, u32 index, u32 reg,
- u32 val)
-{
- u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
-
- dw_pcie_writel_rc(pp, offset + reg, val);
-}
-
-static int dw_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
- u32 *val)
-{
- if (pp->ops->rd_own_conf)
- return pp->ops->rd_own_conf(pp, where, size, val);
-
- return dw_pcie_cfg_read(pp->dbi_base + where, size, val);
-}
-
-static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
- u32 val)
-{
- if (pp->ops->wr_own_conf)
- return pp->ops->wr_own_conf(pp, where, size, val);
-
- return dw_pcie_cfg_write(pp->dbi_base + where, size, val);
-}
-
-static void dw_pcie_prog_outbound_atu(struct pcie_port *pp, int index,
- int type, u64 cpu_addr, u64 pci_addr, u32 size)
-{
- u32 retries, val;
-
- if (pp->iatu_unroll_enabled) {
- dw_pcie_writel_unroll(pp, index, PCIE_ATU_UNR_LOWER_BASE,
- lower_32_bits(cpu_addr));
- dw_pcie_writel_unroll(pp, index, PCIE_ATU_UNR_UPPER_BASE,
- upper_32_bits(cpu_addr));
- dw_pcie_writel_unroll(pp, index, PCIE_ATU_UNR_LIMIT,
- lower_32_bits(cpu_addr + size - 1));
- dw_pcie_writel_unroll(pp, index, PCIE_ATU_UNR_LOWER_TARGET,
- lower_32_bits(pci_addr));
- dw_pcie_writel_unroll(pp, index, PCIE_ATU_UNR_UPPER_TARGET,
- upper_32_bits(pci_addr));
- dw_pcie_writel_unroll(pp, index, PCIE_ATU_UNR_REGION_CTRL1,
- type);
- dw_pcie_writel_unroll(pp, index, PCIE_ATU_UNR_REGION_CTRL2,
- PCIE_ATU_ENABLE);
- } else {
- dw_pcie_writel_rc(pp, PCIE_ATU_VIEWPORT,
- PCIE_ATU_REGION_OUTBOUND | index);
- dw_pcie_writel_rc(pp, PCIE_ATU_LOWER_BASE,
- lower_32_bits(cpu_addr));
- dw_pcie_writel_rc(pp, PCIE_ATU_UPPER_BASE,
- upper_32_bits(cpu_addr));
- dw_pcie_writel_rc(pp, PCIE_ATU_LIMIT,
- lower_32_bits(cpu_addr + size - 1));
- dw_pcie_writel_rc(pp, PCIE_ATU_LOWER_TARGET,
- lower_32_bits(pci_addr));
- dw_pcie_writel_rc(pp, PCIE_ATU_UPPER_TARGET,
- upper_32_bits(pci_addr));
- dw_pcie_writel_rc(pp, PCIE_ATU_CR1, type);
- dw_pcie_writel_rc(pp, PCIE_ATU_CR2, PCIE_ATU_ENABLE);
- }
-
- /*
- * Make sure ATU enable takes effect before any subsequent config
- * and I/O accesses.
- */
- for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
- if (pp->iatu_unroll_enabled)
- val = dw_pcie_readl_unroll(pp, index,
- PCIE_ATU_UNR_REGION_CTRL2);
- else
- val = dw_pcie_readl_rc(pp, PCIE_ATU_CR2);
-
- if (val == PCIE_ATU_ENABLE)
- return;
-
- usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
- }
- dev_err(pp->dev, "iATU is not being enabled\n");
-}
-
-static struct irq_chip dw_msi_irq_chip = {
- .name = "PCI-MSI",
- .irq_enable = pci_msi_unmask_irq,
- .irq_disable = pci_msi_mask_irq,
- .irq_mask = pci_msi_mask_irq,
- .irq_unmask = pci_msi_unmask_irq,
-};
-
-/* MSI int handler */
-irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
-{
- unsigned long val;
- int i, pos, irq;
- irqreturn_t ret = IRQ_NONE;
-
- for (i = 0; i < MAX_MSI_CTRLS; i++) {
- dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4,
- (u32 *)&val);
- if (val) {
- ret = IRQ_HANDLED;
- pos = 0;
- while ((pos = find_next_bit(&val, 32, pos)) != 32) {
- irq = irq_find_mapping(pp->irq_domain,
- i * 32 + pos);
- dw_pcie_wr_own_conf(pp,
- PCIE_MSI_INTR0_STATUS + i * 12,
- 4, 1 << pos);
- generic_handle_irq(irq);
- pos++;
- }
- }
- }
-
- return ret;
-}
-
-void dw_pcie_msi_init(struct pcie_port *pp)
-{
- u64 msi_target;
-
- pp->msi_data = __get_free_pages(GFP_KERNEL, 0);
- msi_target = virt_to_phys((void *)pp->msi_data);
-
- /* program the msi_data */
- dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4,
- (u32)(msi_target & 0xffffffff));
- dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4,
- (u32)(msi_target >> 32 & 0xffffffff));
-}
-
-static void dw_pcie_msi_clear_irq(struct pcie_port *pp, int irq)
-{
- unsigned int res, bit, val;
-
- res = (irq / 32) * 12;
- bit = irq % 32;
- dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
- val &= ~(1 << bit);
- dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
-}
-
-static void clear_irq_range(struct pcie_port *pp, unsigned int irq_base,
- unsigned int nvec, unsigned int pos)
-{
- unsigned int i;
-
- for (i = 0; i < nvec; i++) {
- irq_set_msi_desc_off(irq_base, i, NULL);
- /* Disable corresponding interrupt on MSI controller */
- if (pp->ops->msi_clear_irq)
- pp->ops->msi_clear_irq(pp, pos + i);
- else
- dw_pcie_msi_clear_irq(pp, pos + i);
- }
-
- bitmap_release_region(pp->msi_irq_in_use, pos, order_base_2(nvec));
-}
-
-static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq)
-{
- unsigned int res, bit, val;
-
- res = (irq / 32) * 12;
- bit = irq % 32;
- dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
- val |= 1 << bit;
- dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
-}
-
-static int assign_irq(int no_irqs, struct msi_desc *desc, int *pos)
-{
- int irq, pos0, i;
- struct pcie_port *pp = (struct pcie_port *) msi_desc_to_pci_sysdata(desc);
-
- pos0 = bitmap_find_free_region(pp->msi_irq_in_use, MAX_MSI_IRQS,
- order_base_2(no_irqs));
- if (pos0 < 0)
- goto no_valid_irq;
-
- irq = irq_find_mapping(pp->irq_domain, pos0);
- if (!irq)
- goto no_valid_irq;
-
- /*
- * irq_create_mapping (called from dw_pcie_host_init) pre-allocates
- * descs so there is no need to allocate descs here. We can therefore
- * assume that if irq_find_mapping above returns non-zero, then the
- * descs are also successfully allocated.
- */
-
- for (i = 0; i < no_irqs; i++) {
- if (irq_set_msi_desc_off(irq, i, desc) != 0) {
- clear_irq_range(pp, irq, i, pos0);
- goto no_valid_irq;
- }
- /*Enable corresponding interrupt in MSI interrupt controller */
- if (pp->ops->msi_set_irq)
- pp->ops->msi_set_irq(pp, pos0 + i);
- else
- dw_pcie_msi_set_irq(pp, pos0 + i);
- }
-
- *pos = pos0;
- desc->nvec_used = no_irqs;
- desc->msi_attrib.multiple = order_base_2(no_irqs);
-
- return irq;
-
-no_valid_irq:
- *pos = pos0;
- return -ENOSPC;
-}
-
-static void dw_msi_setup_msg(struct pcie_port *pp, unsigned int irq, u32 pos)
-{
- struct msi_msg msg;
- u64 msi_target;
-
- if (pp->ops->get_msi_addr)
- msi_target = pp->ops->get_msi_addr(pp);
- else
- msi_target = virt_to_phys((void *)pp->msi_data);
-
- msg.address_lo = (u32)(msi_target & 0xffffffff);
- msg.address_hi = (u32)(msi_target >> 32 & 0xffffffff);
-
- if (pp->ops->get_msi_data)
- msg.data = pp->ops->get_msi_data(pp, pos);
- else
- msg.data = pos;
-
- pci_write_msi_msg(irq, &msg);
-}
-
-static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev,
- struct msi_desc *desc)
-{
- int irq, pos;
- struct pcie_port *pp = pdev->bus->sysdata;
-
- if (desc->msi_attrib.is_msix)
- return -EINVAL;
-
- irq = assign_irq(1, desc, &pos);
- if (irq < 0)
- return irq;
-
- dw_msi_setup_msg(pp, irq, pos);
-
- return 0;
-}
-
-static int dw_msi_setup_irqs(struct msi_controller *chip, struct pci_dev *pdev,
- int nvec, int type)
-{
-#ifdef CONFIG_PCI_MSI
- int irq, pos;
- struct msi_desc *desc;
- struct pcie_port *pp = pdev->bus->sysdata;
-
- /* MSI-X interrupts are not supported */
- if (type == PCI_CAP_ID_MSIX)
- return -EINVAL;
-
- WARN_ON(!list_is_singular(&pdev->dev.msi_list));
- desc = list_entry(pdev->dev.msi_list.next, struct msi_desc, list);
-
- irq = assign_irq(nvec, desc, &pos);
- if (irq < 0)
- return irq;
-
- dw_msi_setup_msg(pp, irq, pos);
-
- return 0;
-#else
- return -EINVAL;
-#endif
-}
-
-static void dw_msi_teardown_irq(struct msi_controller *chip, unsigned int irq)
-{
- struct irq_data *data = irq_get_irq_data(irq);
- struct msi_desc *msi = irq_data_get_msi_desc(data);
- struct pcie_port *pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi);
-
- clear_irq_range(pp, irq, 1, data->hwirq);
-}
-
-static struct msi_controller dw_pcie_msi_chip = {
- .setup_irq = dw_msi_setup_irq,
- .setup_irqs = dw_msi_setup_irqs,
- .teardown_irq = dw_msi_teardown_irq,
-};
-
-int dw_pcie_wait_for_link(struct pcie_port *pp)
-{
- int retries;
-
- /* check if the link is up or not */
- for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {
- if (dw_pcie_link_up(pp)) {
- dev_info(pp->dev, "link up\n");
- return 0;
- }
- usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);
- }
-
- dev_err(pp->dev, "phy link never came up\n");
-
- return -ETIMEDOUT;
-}
-
-int dw_pcie_link_up(struct pcie_port *pp)
-{
- u32 val;
-
- if (pp->ops->link_up)
- return pp->ops->link_up(pp);
-
- val = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
- return ((val & PCIE_PHY_DEBUG_R1_LINK_UP) &&
- (!(val & PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING)));
-}
-
-static int dw_pcie_msi_map(struct irq_domain *domain, unsigned int irq,
- irq_hw_number_t hwirq)
-{
- irq_set_chip_and_handler(irq, &dw_msi_irq_chip, handle_simple_irq);
- irq_set_chip_data(irq, domain->host_data);
-
- return 0;
-}
-
-static const struct irq_domain_ops msi_domain_ops = {
- .map = dw_pcie_msi_map,
-};
-
-static u8 dw_pcie_iatu_unroll_enabled(struct pcie_port *pp)
-{
- u32 val;
-
- val = dw_pcie_readl_rc(pp, PCIE_ATU_VIEWPORT);
- if (val == 0xffffffff)
- return 1;
-
- return 0;
-}
-
-int dw_pcie_host_init(struct pcie_port *pp)
-{
- struct device_node *np = pp->dev->of_node;
- struct platform_device *pdev = to_platform_device(pp->dev);
- struct pci_bus *bus, *child;
- struct resource *cfg_res;
- int i, ret;
- LIST_HEAD(res);
- struct resource_entry *win, *tmp;
-
- cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
- if (cfg_res) {
- pp->cfg0_size = resource_size(cfg_res)/2;
- pp->cfg1_size = resource_size(cfg_res)/2;
- pp->cfg0_base = cfg_res->start;
- pp->cfg1_base = cfg_res->start + pp->cfg0_size;
- } else if (!pp->va_cfg0_base) {
- dev_err(pp->dev, "missing *config* reg space\n");
- }
-
- ret = of_pci_get_host_bridge_resources(np, 0, 0xff, &res, &pp->io_base);
- 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_safe(win, tmp, &res) {
- switch (resource_type(win->res)) {
- case IORESOURCE_IO:
- ret = pci_remap_iospace(win->res, pp->io_base);
- if (ret) {
- dev_warn(pp->dev, "error %d: failed to map resource %pR\n",
- ret, win->res);
- resource_list_destroy_entry(win);
- } else {
- pp->io = win->res;
- pp->io->name = "I/O";
- pp->io_size = resource_size(pp->io);
- pp->io_bus_addr = pp->io->start - win->offset;
- }
- break;
- case IORESOURCE_MEM:
- pp->mem = win->res;
- pp->mem->name = "MEM";
- pp->mem_size = resource_size(pp->mem);
- pp->mem_bus_addr = pp->mem->start - win->offset;
- break;
- case 0:
- pp->cfg = win->res;
- pp->cfg0_size = resource_size(pp->cfg)/2;
- pp->cfg1_size = resource_size(pp->cfg)/2;
- pp->cfg0_base = pp->cfg->start;
- pp->cfg1_base = pp->cfg->start + pp->cfg0_size;
- break;
- case IORESOURCE_BUS:
- pp->busn = win->res;
- break;
- }
- }
-
- if (!pp->dbi_base) {
- pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start,
- resource_size(pp->cfg));
- if (!pp->dbi_base) {
- dev_err(pp->dev, "error with ioremap\n");
- ret = -ENOMEM;
- goto error;
- }
- }
-
- pp->mem_base = pp->mem->start;
-
- if (!pp->va_cfg0_base) {
- pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base,
- pp->cfg0_size);
- if (!pp->va_cfg0_base) {
- dev_err(pp->dev, "error with ioremap in function\n");
- ret = -ENOMEM;
- goto error;
- }
- }
-
- if (!pp->va_cfg1_base) {
- pp->va_cfg1_base = devm_ioremap(pp->dev, pp->cfg1_base,
- pp->cfg1_size);
- if (!pp->va_cfg1_base) {
- dev_err(pp->dev, "error with ioremap\n");
- ret = -ENOMEM;
- goto error;
- }
- }
-
- ret = of_property_read_u32(np, "num-lanes", &pp->lanes);
- if (ret)
- pp->lanes = 0;
-
- ret = of_property_read_u32(np, "num-viewport", &pp->num_viewport);
- if (ret)
- pp->num_viewport = 2;
-
- if (IS_ENABLED(CONFIG_PCI_MSI)) {
- if (!pp->ops->msi_host_init) {
- pp->irq_domain = irq_domain_add_linear(pp->dev->of_node,
- MAX_MSI_IRQS, &msi_domain_ops,
- &dw_pcie_msi_chip);
- if (!pp->irq_domain) {
- dev_err(pp->dev, "irq domain init failed\n");
- ret = -ENXIO;
- goto error;
- }
-
- for (i = 0; i < MAX_MSI_IRQS; i++)
- irq_create_mapping(pp->irq_domain, i);
- } else {
- ret = pp->ops->msi_host_init(pp, &dw_pcie_msi_chip);
- if (ret < 0)
- goto error;
- }
- }
-
- if (pp->ops->host_init)
- pp->ops->host_init(pp);
-
- pp->root_bus_nr = pp->busn->start;
- if (IS_ENABLED(CONFIG_PCI_MSI)) {
- bus = pci_scan_root_bus_msi(pp->dev, pp->root_bus_nr,
- &dw_pcie_ops, pp, &res,
- &dw_pcie_msi_chip);
- dw_pcie_msi_chip.dev = pp->dev;
- } else
- bus = pci_scan_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops,
- pp, &res);
- if (!bus) {
- ret = -ENOMEM;
- goto error;
- }
-
- if (pp->ops->scan_bus)
- pp->ops->scan_bus(pp);
-
-#ifdef CONFIG_ARM
- /* support old dtbs that incorrectly describe IRQs */
- pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
-#endif
-
- pci_bus_size_bridges(bus);
- pci_bus_assign_resources(bus);
-
- list_for_each_entry(child, &bus->children, node)
- pcie_bus_configure_settings(child);
-
- 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,
- u32 devfn, int where, int size, u32 *val)
-{
- int ret, type;
- u32 busdev, cfg_size;
- u64 cpu_addr;
- void __iomem *va_cfg_base;
-
- if (pp->ops->rd_other_conf)
- return pp->ops->rd_other_conf(pp, bus, devfn, where, size, val);
-
- busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
- PCIE_ATU_FUNC(PCI_FUNC(devfn));
-
- if (bus->parent->number == pp->root_bus_nr) {
- type = PCIE_ATU_TYPE_CFG0;
- cpu_addr = pp->cfg0_base;
- cfg_size = pp->cfg0_size;
- va_cfg_base = pp->va_cfg0_base;
- } else {
- type = PCIE_ATU_TYPE_CFG1;
- cpu_addr = pp->cfg1_base;
- cfg_size = pp->cfg1_size;
- va_cfg_base = pp->va_cfg1_base;
- }
-
- dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
- type, cpu_addr,
- busdev, cfg_size);
- ret = dw_pcie_cfg_read(va_cfg_base + where, size, val);
- if (pp->num_viewport <= 2)
- dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
- PCIE_ATU_TYPE_IO, pp->io_base,
- pp->io_bus_addr, pp->io_size);
-
- return ret;
-}
-
-static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
- u32 devfn, int where, int size, u32 val)
-{
- int ret, type;
- u32 busdev, cfg_size;
- u64 cpu_addr;
- void __iomem *va_cfg_base;
-
- if (pp->ops->wr_other_conf)
- return pp->ops->wr_other_conf(pp, bus, devfn, where, size, val);
-
- busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
- PCIE_ATU_FUNC(PCI_FUNC(devfn));
-
- if (bus->parent->number == pp->root_bus_nr) {
- type = PCIE_ATU_TYPE_CFG0;
- cpu_addr = pp->cfg0_base;
- cfg_size = pp->cfg0_size;
- va_cfg_base = pp->va_cfg0_base;
- } else {
- type = PCIE_ATU_TYPE_CFG1;
- cpu_addr = pp->cfg1_base;
- cfg_size = pp->cfg1_size;
- va_cfg_base = pp->va_cfg1_base;
- }
-
- dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
- type, cpu_addr,
- busdev, cfg_size);
- ret = dw_pcie_cfg_write(va_cfg_base + where, size, val);
- if (pp->num_viewport <= 2)
- dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1,
- PCIE_ATU_TYPE_IO, pp->io_base,
- pp->io_bus_addr, pp->io_size);
-
- return ret;
-}
-
-static int dw_pcie_valid_device(struct pcie_port *pp, struct pci_bus *bus,
- int dev)
-{
- /* If there is no link, then there is no device */
- if (bus->number != pp->root_bus_nr) {
- if (!dw_pcie_link_up(pp))
- return 0;
- }
-
- /* access only one slot on each root port */
- if (bus->number == pp->root_bus_nr && dev > 0)
- return 0;
-
- return 1;
-}
-
-static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
- int size, u32 *val)
-{
- struct pcie_port *pp = bus->sysdata;
-
- if (!dw_pcie_valid_device(pp, bus, PCI_SLOT(devfn))) {
- *val = 0xffffffff;
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
-
- if (bus->number == pp->root_bus_nr)
- return dw_pcie_rd_own_conf(pp, where, size, val);
-
- return dw_pcie_rd_other_conf(pp, bus, devfn, where, size, val);
-}
-
-static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
- int where, int size, u32 val)
-{
- struct pcie_port *pp = bus->sysdata;
-
- if (!dw_pcie_valid_device(pp, bus, PCI_SLOT(devfn)))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- if (bus->number == pp->root_bus_nr)
- return dw_pcie_wr_own_conf(pp, where, size, val);
-
- return dw_pcie_wr_other_conf(pp, bus, devfn, where, size, val);
-}
-
-static struct pci_ops dw_pcie_ops = {
- .read = dw_pcie_rd_conf,
- .write = dw_pcie_wr_conf,
-};
-
-void dw_pcie_setup_rc(struct pcie_port *pp)
-{
- u32 val;
-
- /* set the number of lanes */
- val = dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL);
- val &= ~PORT_LINK_MODE_MASK;
- switch (pp->lanes) {
- case 1:
- val |= PORT_LINK_MODE_1_LANES;
- break;
- case 2:
- val |= PORT_LINK_MODE_2_LANES;
- break;
- case 4:
- val |= PORT_LINK_MODE_4_LANES;
- break;
- case 8:
- val |= PORT_LINK_MODE_8_LANES;
- break;
- default:
- dev_err(pp->dev, "num-lanes %u: invalid value\n", pp->lanes);
- return;
- }
- dw_pcie_writel_rc(pp, PCIE_PORT_LINK_CONTROL, val);
-
- /* set link width speed control register */
- val = dw_pcie_readl_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL);
- val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
- switch (pp->lanes) {
- case 1:
- val |= PORT_LOGIC_LINK_WIDTH_1_LANES;
- break;
- case 2:
- val |= PORT_LOGIC_LINK_WIDTH_2_LANES;
- break;
- case 4:
- val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
- break;
- case 8:
- val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
- break;
- }
- dw_pcie_writel_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
-
- /* setup RC BARs */
- dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_0, 0x00000004);
- dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_1, 0x00000000);
-
- /* setup interrupt pins */
- val = dw_pcie_readl_rc(pp, PCI_INTERRUPT_LINE);
- val &= 0xffff00ff;
- val |= 0x00000100;
- dw_pcie_writel_rc(pp, PCI_INTERRUPT_LINE, val);
-
- /* setup bus numbers */
- val = dw_pcie_readl_rc(pp, PCI_PRIMARY_BUS);
- val &= 0xff000000;
- val |= 0x00010100;
- dw_pcie_writel_rc(pp, PCI_PRIMARY_BUS, val);
-
- /* setup command register */
- val = dw_pcie_readl_rc(pp, PCI_COMMAND);
- val &= 0xffff0000;
- val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
- PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
- dw_pcie_writel_rc(pp, PCI_COMMAND, val);
-
- /*
- * If the platform provides ->rd_other_conf, it means the platform
- * uses its own address translation component rather than ATU, so
- * we should not program the ATU here.
- */
- if (!pp->ops->rd_other_conf) {
- /* get iATU unroll support */
- pp->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pp);
- dev_dbg(pp->dev, "iATU unroll: %s\n",
- pp->iatu_unroll_enabled ? "enabled" : "disabled");
-
- dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
- PCIE_ATU_TYPE_MEM, pp->mem_base,
- pp->mem_bus_addr, pp->mem_size);
- if (pp->num_viewport > 2)
- dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX2,
- PCIE_ATU_TYPE_IO, pp->io_base,
- pp->io_bus_addr, pp->io_size);
- }
-
- dw_pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
-
- /* program correct class for RC */
- dw_pcie_wr_own_conf(pp, PCI_CLASS_DEVICE, 2, PCI_CLASS_BRIDGE_PCI);
-
- dw_pcie_rd_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, &val);
- val |= PORT_LOGIC_SPEED_CHANGE;
- dw_pcie_wr_own_conf(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, 4, val);
-}
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
deleted file mode 100644
index a567ea288ee2..000000000000
--- a/drivers/pci/host/pcie-designware.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Synopsys Designware PCIe host controller driver
- *
- * Copyright (C) 2013 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Author: Jingoo Han <jg1.han@samsung.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.
- */
-
-#ifndef _PCIE_DESIGNWARE_H
-#define _PCIE_DESIGNWARE_H
-
-/*
- * Maximum number of MSI IRQs can be 256 per controller. But keep
- * it 32 as of now. Probably we will never need more than 32. If needed,
- * then increment it in multiple of 32.
- */
-#define MAX_MSI_IRQS 32
-#define MAX_MSI_CTRLS (MAX_MSI_IRQS / 32)
-
-struct pcie_port {
- struct device *dev;
- u8 root_bus_nr;
- void __iomem *dbi_base;
- u64 cfg0_base;
- void __iomem *va_cfg0_base;
- u32 cfg0_size;
- u64 cfg1_base;
- void __iomem *va_cfg1_base;
- u32 cfg1_size;
- resource_size_t io_base;
- phys_addr_t io_bus_addr;
- u32 io_size;
- u64 mem_base;
- phys_addr_t mem_bus_addr;
- u32 mem_size;
- struct resource *cfg;
- struct resource *io;
- struct resource *mem;
- struct resource *busn;
- int irq;
- u32 lanes;
- u32 num_viewport;
- struct pcie_host_ops *ops;
- int msi_irq;
- struct irq_domain *irq_domain;
- unsigned long msi_data;
- u8 iatu_unroll_enabled;
- DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
-};
-
-struct pcie_host_ops {
- u32 (*readl_rc)(struct pcie_port *pp, u32 reg);
- void (*writel_rc)(struct pcie_port *pp, u32 reg, u32 val);
- int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val);
- int (*wr_own_conf)(struct pcie_port *pp, int where, int size, u32 val);
- int (*rd_other_conf)(struct pcie_port *pp, struct pci_bus *bus,
- unsigned int devfn, int where, int size, u32 *val);
- int (*wr_other_conf)(struct pcie_port *pp, struct pci_bus *bus,
- unsigned int devfn, int where, int size, u32 val);
- int (*link_up)(struct pcie_port *pp);
- void (*host_init)(struct pcie_port *pp);
- void (*msi_set_irq)(struct pcie_port *pp, int irq);
- void (*msi_clear_irq)(struct pcie_port *pp, int irq);
- phys_addr_t (*get_msi_addr)(struct pcie_port *pp);
- u32 (*get_msi_data)(struct pcie_port *pp, int pos);
- void (*scan_bus)(struct pcie_port *pp);
- int (*msi_host_init)(struct pcie_port *pp, struct msi_controller *chip);
-};
-
-u32 dw_pcie_readl_rc(struct pcie_port *pp, u32 reg);
-void dw_pcie_writel_rc(struct pcie_port *pp, u32 reg, u32 val);
-int dw_pcie_cfg_read(void __iomem *addr, int size, u32 *val);
-int dw_pcie_cfg_write(void __iomem *addr, int size, u32 val);
-irqreturn_t dw_handle_msi_irq(struct pcie_port *pp);
-void dw_pcie_msi_init(struct pcie_port *pp);
-int dw_pcie_wait_for_link(struct pcie_port *pp);
-int dw_pcie_link_up(struct pcie_port *pp);
-void dw_pcie_setup_rc(struct pcie_port *pp);
-int dw_pcie_host_init(struct pcie_port *pp);
-
-#endif /* _PCIE_DESIGNWARE_H */
diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/host/pcie-hisi.c
deleted file mode 100644
index a301a7187b30..000000000000
--- a/drivers/pci/host/pcie-hisi.c
+++ /dev/null
@@ -1,326 +0,0 @@
-/*
- * PCIe host controller driver for HiSilicon SoCs
- *
- * Copyright (C) 2015 HiSilicon Co., Ltd. http://www.hisilicon.com
- *
- * Authors: Zhou Wang <wangzhou1@hisilicon.com>
- * Dacai Zhu <zhudacai@hisilicon.com>
- * Gabriele Paoloni <gabriele.paoloni@huawei.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.
- */
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/mfd/syscon.h>
-#include <linux/of_address.h>
-#include <linux/of_pci.h>
-#include <linux/platform_device.h>
-#include <linux/of_device.h>
-#include <linux/pci.h>
-#include <linux/pci-acpi.h>
-#include <linux/pci-ecam.h>
-#include <linux/regmap.h>
-#include "../pci.h"
-
-#if defined(CONFIG_ACPI) && defined(CONFIG_PCI_QUIRKS)
-
-static int hisi_pcie_acpi_rd_conf(struct pci_bus *bus, u32 devfn, int where,
- int size, u32 *val)
-{
- struct pci_config_window *cfg = bus->sysdata;
- int dev = PCI_SLOT(devfn);
-
- if (bus->number == cfg->busr.start) {
- /* access only one slot on each root port */
- if (dev > 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
- else
- return pci_generic_config_read32(bus, devfn, where,
- size, val);
- }
-
- return pci_generic_config_read(bus, devfn, where, size, val);
-}
-
-static int hisi_pcie_acpi_wr_conf(struct pci_bus *bus, u32 devfn,
- int where, int size, u32 val)
-{
- struct pci_config_window *cfg = bus->sysdata;
- int dev = PCI_SLOT(devfn);
-
- if (bus->number == cfg->busr.start) {
- /* access only one slot on each root port */
- if (dev > 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
- else
- return pci_generic_config_write32(bus, devfn, where,
- size, val);
- }
-
- return pci_generic_config_write(bus, devfn, where, size, val);
-}
-
-static void __iomem *hisi_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
- int where)
-{
- struct pci_config_window *cfg = bus->sysdata;
- void __iomem *reg_base = cfg->priv;
-
- if (bus->number == cfg->busr.start)
- return reg_base + where;
- else
- return pci_ecam_map_bus(bus, devfn, where);
-}
-
-static int hisi_pcie_init(struct pci_config_window *cfg)
-{
- struct device *dev = cfg->parent;
- struct acpi_device *adev = to_acpi_device(dev);
- struct acpi_pci_root *root = acpi_driver_data(adev);
- struct resource *res;
- void __iomem *reg_base;
- int ret;
-
- /*
- * Retrieve RC base and size from a HISI0081 device with _UID
- * matching our segment.
- */
- res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
- if (!res)
- return -ENOMEM;
-
- ret = acpi_get_rc_resources(dev, "HISI0081", root->segment, res);
- if (ret) {
- dev_err(dev, "can't get rc base address\n");
- return -ENOMEM;
- }
-
- reg_base = devm_ioremap(dev, res->start, resource_size(res));
- if (!reg_base)
- return -ENOMEM;
-
- cfg->priv = reg_base;
- return 0;
-}
-
-struct pci_ecam_ops hisi_pcie_ops = {
- .bus_shift = 20,
- .init = hisi_pcie_init,
- .pci_ops = {
- .map_bus = hisi_pcie_map_bus,
- .read = hisi_pcie_acpi_rd_conf,
- .write = hisi_pcie_acpi_wr_conf,
- }
-};
-
-#endif
-
-#ifdef CONFIG_PCI_HISI
-
-#include "pcie-designware.h"
-
-#define PCIE_SUBCTRL_SYS_STATE4_REG 0x6818
-#define PCIE_HIP06_CTRL_OFF 0x1000
-#define PCIE_SYS_STATE4 (PCIE_HIP06_CTRL_OFF + 0x31c)
-#define PCIE_LTSSM_LINKUP_STATE 0x11
-#define PCIE_LTSSM_STATE_MASK 0x3F
-
-#define to_hisi_pcie(x) container_of(x, struct hisi_pcie, pp)
-
-struct hisi_pcie;
-
-struct pcie_soc_ops {
- int (*hisi_pcie_link_up)(struct hisi_pcie *hisi_pcie);
-};
-
-struct hisi_pcie {
- struct pcie_port pp; /* pp.dbi_base is DT rc_dbi */
- struct regmap *subctrl;
- u32 port_id;
- struct pcie_soc_ops *soc_ops;
-};
-
-/* HipXX PCIe host only supports 32-bit config access */
-static int hisi_pcie_cfg_read(struct pcie_port *pp, int where, int size,
- u32 *val)
-{
- u32 reg;
- u32 reg_val;
- void *walker = &reg_val;
-
- walker += (where & 0x3);
- reg = where & ~0x3;
- reg_val = dw_pcie_readl_rc(pp, reg);
-
- if (size == 1)
- *val = *(u8 __force *) walker;
- else if (size == 2)
- *val = *(u16 __force *) walker;
- else if (size == 4)
- *val = reg_val;
- else
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-/* HipXX PCIe host only supports 32-bit config access */
-static int hisi_pcie_cfg_write(struct pcie_port *pp, int where, int size,
- u32 val)
-{
- u32 reg_val;
- u32 reg;
- void *walker = &reg_val;
-
- walker += (where & 0x3);
- reg = where & ~0x3;
- if (size == 4)
- dw_pcie_writel_rc(pp, reg, val);
- else if (size == 2) {
- reg_val = dw_pcie_readl_rc(pp, reg);
- *(u16 __force *) walker = val;
- dw_pcie_writel_rc(pp, reg, reg_val);
- } else if (size == 1) {
- reg_val = dw_pcie_readl_rc(pp, reg);
- *(u8 __force *) walker = val;
- dw_pcie_writel_rc(pp, reg, reg_val);
- } else
- return PCIBIOS_BAD_REGISTER_NUMBER;
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int hisi_pcie_link_up_hip05(struct hisi_pcie *hisi_pcie)
-{
- u32 val;
-
- regmap_read(hisi_pcie->subctrl, PCIE_SUBCTRL_SYS_STATE4_REG +
- 0x100 * hisi_pcie->port_id, &val);
-
- return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE);
-}
-
-static int hisi_pcie_link_up_hip06(struct hisi_pcie *hisi_pcie)
-{
- struct pcie_port *pp = &hisi_pcie->pp;
- u32 val;
-
- val = dw_pcie_readl_rc(pp, PCIE_SYS_STATE4);
-
- return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE);
-}
-
-static int hisi_pcie_link_up(struct pcie_port *pp)
-{
- struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp);
-
- return hisi_pcie->soc_ops->hisi_pcie_link_up(hisi_pcie);
-}
-
-static struct pcie_host_ops hisi_pcie_host_ops = {
- .rd_own_conf = hisi_pcie_cfg_read,
- .wr_own_conf = hisi_pcie_cfg_write,
- .link_up = hisi_pcie_link_up,
-};
-
-static int hisi_add_pcie_port(struct hisi_pcie *hisi_pcie,
- struct platform_device *pdev)
-{
- struct pcie_port *pp = &hisi_pcie->pp;
- struct device *dev = pp->dev;
- int ret;
- u32 port_id;
-
- if (of_property_read_u32(dev->of_node, "port-id", &port_id)) {
- dev_err(dev, "failed to read port-id\n");
- return -EINVAL;
- }
- if (port_id > 3) {
- dev_err(dev, "Invalid port-id: %d\n", port_id);
- return -EINVAL;
- }
- hisi_pcie->port_id = port_id;
-
- pp->ops = &hisi_pcie_host_ops;
-
- ret = dw_pcie_host_init(pp);
- if (ret) {
- dev_err(dev, "failed to initialize host\n");
- return ret;
- }
-
- return 0;
-}
-
-static int hisi_pcie_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct hisi_pcie *hisi_pcie;
- struct pcie_port *pp;
- const struct of_device_id *match;
- struct resource *reg;
- struct device_driver *driver;
- int ret;
-
- hisi_pcie = devm_kzalloc(dev, sizeof(*hisi_pcie), GFP_KERNEL);
- if (!hisi_pcie)
- return -ENOMEM;
-
- pp = &hisi_pcie->pp;
- pp->dev = dev;
- driver = dev->driver;
-
- match = of_match_device(driver->of_match_table, dev);
- hisi_pcie->soc_ops = (struct pcie_soc_ops *) match->data;
-
- hisi_pcie->subctrl =
- syscon_regmap_lookup_by_compatible("hisilicon,pcie-sas-subctrl");
- if (IS_ERR(hisi_pcie->subctrl)) {
- dev_err(dev, "cannot get subctrl base\n");
- return PTR_ERR(hisi_pcie->subctrl);
- }
-
- reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbi");
- pp->dbi_base = devm_ioremap_resource(dev, reg);
- if (IS_ERR(pp->dbi_base))
- return PTR_ERR(pp->dbi_base);
-
- ret = hisi_add_pcie_port(hisi_pcie, pdev);
- if (ret)
- return ret;
-
- return 0;
-}
-
-static struct pcie_soc_ops hip05_ops = {
- &hisi_pcie_link_up_hip05
-};
-
-static struct pcie_soc_ops hip06_ops = {
- &hisi_pcie_link_up_hip06
-};
-
-static const struct of_device_id hisi_pcie_of_match[] = {
- {
- .compatible = "hisilicon,hip05-pcie",
- .data = (void *) &hip05_ops,
- },
- {
- .compatible = "hisilicon,hip06-pcie",
- .data = (void *) &hip06_ops,
- },
- {},
-};
-
-static struct platform_driver hisi_pcie_driver = {
- .probe = hisi_pcie_probe,
- .driver = {
- .name = "hisi-pcie",
- .of_match_table = hisi_pcie_of_match,
- },
-};
-builtin_platform_driver(hisi_pcie_driver);
-
-#endif
diff --git a/drivers/pci/host/pcie-iproc-platform.c b/drivers/pci/host/pcie-iproc-platform.c
index 22d814a78a78..f4909bb0b2ad 100644
--- a/drivers/pci/host/pcie-iproc-platform.c
+++ b/drivers/pci/host/pcie-iproc-platform.c
@@ -47,7 +47,6 @@ MODULE_DEVICE_TABLE(of, iproc_pcie_of_match_table);
static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- const struct of_device_id *of_id;
struct iproc_pcie *pcie;
struct device_node *np = dev->of_node;
struct resource reg;
@@ -55,16 +54,12 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
LIST_HEAD(res);
int ret;
- of_id = of_match_device(iproc_pcie_of_match_table, dev);
- if (!of_id)
- return -EINVAL;
-
pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
if (!pcie)
return -ENOMEM;
pcie->dev = dev;
- pcie->type = (enum iproc_pcie_type)of_id->data;
+ pcie->type = (enum iproc_pcie_type) of_device_get_match_data(dev);
ret = of_address_to_resource(np, 0, &reg);
if (ret < 0) {
diff --git a/drivers/pci/host/pcie-iproc.c b/drivers/pci/host/pcie-iproc.c
index 3ebc025499b9..0f39bd2a04cb 100644
--- a/drivers/pci/host/pcie-iproc.c
+++ b/drivers/pci/host/pcie-iproc.c
@@ -1205,7 +1205,7 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
struct device *dev;
int ret;
void *sysdata;
- struct pci_bus *bus;
+ struct pci_bus *bus, *child;
dev = pcie->dev;
@@ -1278,6 +1278,9 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
if (pcie->map_irq)
pci_fixup_irqs(pci_common_swizzle, pcie->map_irq);
+ list_for_each_entry(child, &bus->children, node)
+ pcie_bus_configure_settings(child);
+
pci_bus_add_devices(bus);
return 0;
diff --git a/drivers/pci/host/pcie-qcom.c b/drivers/pci/host/pcie-qcom.c
deleted file mode 100644
index 734ba0d4a5c8..000000000000
--- a/drivers/pci/host/pcie-qcom.c
+++ /dev/null
@@ -1,753 +0,0 @@
-/*
- * Qualcomm PCIe root complex driver
- *
- * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
- * Copyright 2015 Linaro Limited.
- *
- * Author: Stanimir Varbanov <svarbanov@mm-sol.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 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
-#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/phy/phy.h>
-#include <linux/regulator/consumer.h>
-#include <linux/reset.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-
-#include "pcie-designware.h"
-
-#define PCIE20_PARF_SYS_CTRL 0x00
-#define PCIE20_PARF_PHY_CTRL 0x40
-#define PCIE20_PARF_PHY_REFCLK 0x4C
-#define PCIE20_PARF_DBI_BASE_ADDR 0x168
-#define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x16C
-#define PCIE20_PARF_MHI_CLOCK_RESET_CTRL 0x174
-#define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT 0x178
-#define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2 0x1A8
-#define PCIE20_PARF_LTSSM 0x1B0
-#define PCIE20_PARF_SID_OFFSET 0x234
-#define PCIE20_PARF_BDF_TRANSLATE_CFG 0x24C
-
-#define PCIE20_ELBI_SYS_CTRL 0x04
-#define PCIE20_ELBI_SYS_CTRL_LT_ENABLE BIT(0)
-
-#define PCIE20_CAP 0x70
-
-#define PERST_DELAY_US 1000
-
-struct qcom_pcie_resources_v0 {
- struct clk *iface_clk;
- struct clk *core_clk;
- struct clk *phy_clk;
- struct reset_control *pci_reset;
- struct reset_control *axi_reset;
- struct reset_control *ahb_reset;
- struct reset_control *por_reset;
- struct reset_control *phy_reset;
- struct regulator *vdda;
- struct regulator *vdda_phy;
- struct regulator *vdda_refclk;
-};
-
-struct qcom_pcie_resources_v1 {
- struct clk *iface;
- struct clk *aux;
- struct clk *master_bus;
- struct clk *slave_bus;
- struct reset_control *core;
- struct regulator *vdda;
-};
-
-struct qcom_pcie_resources_v2 {
- struct clk *aux_clk;
- struct clk *master_clk;
- struct clk *slave_clk;
- struct clk *cfg_clk;
- struct clk *pipe_clk;
-};
-
-union qcom_pcie_resources {
- struct qcom_pcie_resources_v0 v0;
- struct qcom_pcie_resources_v1 v1;
- struct qcom_pcie_resources_v2 v2;
-};
-
-struct qcom_pcie;
-
-struct qcom_pcie_ops {
- int (*get_resources)(struct qcom_pcie *pcie);
- int (*init)(struct qcom_pcie *pcie);
- int (*post_init)(struct qcom_pcie *pcie);
- void (*deinit)(struct qcom_pcie *pcie);
- void (*ltssm_enable)(struct qcom_pcie *pcie);
-};
-
-struct qcom_pcie {
- struct pcie_port pp; /* pp.dbi_base is DT dbi */
- void __iomem *parf; /* DT parf */
- void __iomem *elbi; /* DT elbi */
- union qcom_pcie_resources res;
- struct phy *phy;
- struct gpio_desc *reset;
- struct qcom_pcie_ops *ops;
-};
-
-#define to_qcom_pcie(x) container_of(x, struct qcom_pcie, pp)
-
-static void qcom_ep_reset_assert(struct qcom_pcie *pcie)
-{
- gpiod_set_value(pcie->reset, 1);
- usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500);
-}
-
-static void qcom_ep_reset_deassert(struct qcom_pcie *pcie)
-{
- gpiod_set_value(pcie->reset, 0);
- usleep_range(PERST_DELAY_US, PERST_DELAY_US + 500);
-}
-
-static irqreturn_t qcom_pcie_msi_irq_handler(int irq, void *arg)
-{
- struct pcie_port *pp = arg;
-
- return dw_handle_msi_irq(pp);
-}
-
-static void qcom_pcie_v0_v1_ltssm_enable(struct qcom_pcie *pcie)
-{
- u32 val;
-
- /* enable link training */
- val = readl(pcie->elbi + PCIE20_ELBI_SYS_CTRL);
- val |= PCIE20_ELBI_SYS_CTRL_LT_ENABLE;
- writel(val, pcie->elbi + PCIE20_ELBI_SYS_CTRL);
-}
-
-static void qcom_pcie_v2_ltssm_enable(struct qcom_pcie *pcie)
-{
- u32 val;
-
- /* enable link training */
- val = readl(pcie->parf + PCIE20_PARF_LTSSM);
- val |= BIT(8);
- writel(val, pcie->parf + PCIE20_PARF_LTSSM);
-}
-
-static int qcom_pcie_establish_link(struct qcom_pcie *pcie)
-{
-
- if (dw_pcie_link_up(&pcie->pp))
- return 0;
-
- /* Enable Link Training state machine */
- if (pcie->ops->ltssm_enable)
- pcie->ops->ltssm_enable(pcie);
-
- return dw_pcie_wait_for_link(&pcie->pp);
-}
-
-static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie)
-{
- struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
- struct device *dev = pcie->pp.dev;
-
- res->vdda = devm_regulator_get(dev, "vdda");
- if (IS_ERR(res->vdda))
- return PTR_ERR(res->vdda);
-
- res->vdda_phy = devm_regulator_get(dev, "vdda_phy");
- if (IS_ERR(res->vdda_phy))
- return PTR_ERR(res->vdda_phy);
-
- res->vdda_refclk = devm_regulator_get(dev, "vdda_refclk");
- if (IS_ERR(res->vdda_refclk))
- return PTR_ERR(res->vdda_refclk);
-
- res->iface_clk = devm_clk_get(dev, "iface");
- if (IS_ERR(res->iface_clk))
- return PTR_ERR(res->iface_clk);
-
- res->core_clk = devm_clk_get(dev, "core");
- if (IS_ERR(res->core_clk))
- return PTR_ERR(res->core_clk);
-
- res->phy_clk = devm_clk_get(dev, "phy");
- if (IS_ERR(res->phy_clk))
- return PTR_ERR(res->phy_clk);
-
- res->pci_reset = devm_reset_control_get(dev, "pci");
- if (IS_ERR(res->pci_reset))
- return PTR_ERR(res->pci_reset);
-
- res->axi_reset = devm_reset_control_get(dev, "axi");
- if (IS_ERR(res->axi_reset))
- return PTR_ERR(res->axi_reset);
-
- res->ahb_reset = devm_reset_control_get(dev, "ahb");
- if (IS_ERR(res->ahb_reset))
- return PTR_ERR(res->ahb_reset);
-
- res->por_reset = devm_reset_control_get(dev, "por");
- if (IS_ERR(res->por_reset))
- return PTR_ERR(res->por_reset);
-
- res->phy_reset = devm_reset_control_get(dev, "phy");
- if (IS_ERR(res->phy_reset))
- return PTR_ERR(res->phy_reset);
-
- return 0;
-}
-
-static int qcom_pcie_get_resources_v1(struct qcom_pcie *pcie)
-{
- struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
- struct device *dev = pcie->pp.dev;
-
- res->vdda = devm_regulator_get(dev, "vdda");
- if (IS_ERR(res->vdda))
- return PTR_ERR(res->vdda);
-
- res->iface = devm_clk_get(dev, "iface");
- if (IS_ERR(res->iface))
- return PTR_ERR(res->iface);
-
- res->aux = devm_clk_get(dev, "aux");
- if (IS_ERR(res->aux))
- return PTR_ERR(res->aux);
-
- res->master_bus = devm_clk_get(dev, "master_bus");
- if (IS_ERR(res->master_bus))
- return PTR_ERR(res->master_bus);
-
- res->slave_bus = devm_clk_get(dev, "slave_bus");
- if (IS_ERR(res->slave_bus))
- return PTR_ERR(res->slave_bus);
-
- res->core = devm_reset_control_get(dev, "core");
- if (IS_ERR(res->core))
- return PTR_ERR(res->core);
-
- return 0;
-}
-
-static void qcom_pcie_deinit_v0(struct qcom_pcie *pcie)
-{
- struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
-
- reset_control_assert(res->pci_reset);
- reset_control_assert(res->axi_reset);
- reset_control_assert(res->ahb_reset);
- reset_control_assert(res->por_reset);
- reset_control_assert(res->pci_reset);
- clk_disable_unprepare(res->iface_clk);
- clk_disable_unprepare(res->core_clk);
- clk_disable_unprepare(res->phy_clk);
- regulator_disable(res->vdda);
- regulator_disable(res->vdda_phy);
- regulator_disable(res->vdda_refclk);
-}
-
-static int qcom_pcie_init_v0(struct qcom_pcie *pcie)
-{
- struct qcom_pcie_resources_v0 *res = &pcie->res.v0;
- struct device *dev = pcie->pp.dev;
- u32 val;
- int ret;
-
- ret = regulator_enable(res->vdda);
- if (ret) {
- dev_err(dev, "cannot enable vdda regulator\n");
- return ret;
- }
-
- ret = regulator_enable(res->vdda_refclk);
- if (ret) {
- dev_err(dev, "cannot enable vdda_refclk regulator\n");
- goto err_refclk;
- }
-
- ret = regulator_enable(res->vdda_phy);
- if (ret) {
- dev_err(dev, "cannot enable vdda_phy regulator\n");
- goto err_vdda_phy;
- }
-
- ret = reset_control_assert(res->ahb_reset);
- if (ret) {
- dev_err(dev, "cannot assert ahb reset\n");
- goto err_assert_ahb;
- }
-
- ret = clk_prepare_enable(res->iface_clk);
- if (ret) {
- dev_err(dev, "cannot prepare/enable iface clock\n");
- goto err_assert_ahb;
- }
-
- ret = clk_prepare_enable(res->phy_clk);
- if (ret) {
- dev_err(dev, "cannot prepare/enable phy clock\n");
- goto err_clk_phy;
- }
-
- ret = clk_prepare_enable(res->core_clk);
- if (ret) {
- dev_err(dev, "cannot prepare/enable core clock\n");
- goto err_clk_core;
- }
-
- ret = reset_control_deassert(res->ahb_reset);
- if (ret) {
- dev_err(dev, "cannot deassert ahb reset\n");
- goto err_deassert_ahb;
- }
-
- /* enable PCIe clocks and resets */
- val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
- val &= ~BIT(0);
- writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
-
- /* enable external reference clock */
- val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK);
- val |= BIT(16);
- writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK);
-
- ret = reset_control_deassert(res->phy_reset);
- if (ret) {
- dev_err(dev, "cannot deassert phy reset\n");
- return ret;
- }
-
- ret = reset_control_deassert(res->pci_reset);
- if (ret) {
- dev_err(dev, "cannot deassert pci reset\n");
- return ret;
- }
-
- ret = reset_control_deassert(res->por_reset);
- if (ret) {
- dev_err(dev, "cannot deassert por reset\n");
- return ret;
- }
-
- ret = reset_control_deassert(res->axi_reset);
- if (ret) {
- dev_err(dev, "cannot deassert axi reset\n");
- return ret;
- }
-
- /* wait for clock acquisition */
- usleep_range(1000, 1500);
-
- return 0;
-
-err_deassert_ahb:
- clk_disable_unprepare(res->core_clk);
-err_clk_core:
- clk_disable_unprepare(res->phy_clk);
-err_clk_phy:
- clk_disable_unprepare(res->iface_clk);
-err_assert_ahb:
- regulator_disable(res->vdda_phy);
-err_vdda_phy:
- regulator_disable(res->vdda_refclk);
-err_refclk:
- regulator_disable(res->vdda);
-
- return ret;
-}
-
-static void qcom_pcie_deinit_v1(struct qcom_pcie *pcie)
-{
- struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
-
- reset_control_assert(res->core);
- clk_disable_unprepare(res->slave_bus);
- clk_disable_unprepare(res->master_bus);
- clk_disable_unprepare(res->iface);
- clk_disable_unprepare(res->aux);
- regulator_disable(res->vdda);
-}
-
-static int qcom_pcie_init_v1(struct qcom_pcie *pcie)
-{
- struct qcom_pcie_resources_v1 *res = &pcie->res.v1;
- struct device *dev = pcie->pp.dev;
- int ret;
-
- ret = reset_control_deassert(res->core);
- if (ret) {
- dev_err(dev, "cannot deassert core reset\n");
- return ret;
- }
-
- ret = clk_prepare_enable(res->aux);
- if (ret) {
- dev_err(dev, "cannot prepare/enable aux clock\n");
- goto err_res;
- }
-
- ret = clk_prepare_enable(res->iface);
- if (ret) {
- dev_err(dev, "cannot prepare/enable iface clock\n");
- goto err_aux;
- }
-
- ret = clk_prepare_enable(res->master_bus);
- if (ret) {
- dev_err(dev, "cannot prepare/enable master_bus clock\n");
- goto err_iface;
- }
-
- ret = clk_prepare_enable(res->slave_bus);
- if (ret) {
- dev_err(dev, "cannot prepare/enable slave_bus clock\n");
- goto err_master;
- }
-
- ret = regulator_enable(res->vdda);
- if (ret) {
- dev_err(dev, "cannot enable vdda regulator\n");
- goto err_slave;
- }
-
- /* change DBI base address */
- writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
-
- if (IS_ENABLED(CONFIG_PCI_MSI)) {
- u32 val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT);
-
- val |= BIT(31);
- writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT);
- }
-
- return 0;
-err_slave:
- clk_disable_unprepare(res->slave_bus);
-err_master:
- clk_disable_unprepare(res->master_bus);
-err_iface:
- clk_disable_unprepare(res->iface);
-err_aux:
- clk_disable_unprepare(res->aux);
-err_res:
- reset_control_assert(res->core);
-
- return ret;
-}
-
-static int qcom_pcie_get_resources_v2(struct qcom_pcie *pcie)
-{
- struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
- struct device *dev = pcie->pp.dev;
-
- res->aux_clk = devm_clk_get(dev, "aux");
- if (IS_ERR(res->aux_clk))
- return PTR_ERR(res->aux_clk);
-
- res->cfg_clk = devm_clk_get(dev, "cfg");
- if (IS_ERR(res->cfg_clk))
- return PTR_ERR(res->cfg_clk);
-
- res->master_clk = devm_clk_get(dev, "bus_master");
- if (IS_ERR(res->master_clk))
- return PTR_ERR(res->master_clk);
-
- res->slave_clk = devm_clk_get(dev, "bus_slave");
- if (IS_ERR(res->slave_clk))
- return PTR_ERR(res->slave_clk);
-
- res->pipe_clk = devm_clk_get(dev, "pipe");
- if (IS_ERR(res->pipe_clk))
- return PTR_ERR(res->pipe_clk);
-
- return 0;
-}
-
-static int qcom_pcie_init_v2(struct qcom_pcie *pcie)
-{
- struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
- struct device *dev = pcie->pp.dev;
- u32 val;
- int ret;
-
- ret = clk_prepare_enable(res->aux_clk);
- if (ret) {
- dev_err(dev, "cannot prepare/enable aux clock\n");
- return ret;
- }
-
- ret = clk_prepare_enable(res->cfg_clk);
- if (ret) {
- dev_err(dev, "cannot prepare/enable cfg clock\n");
- goto err_cfg_clk;
- }
-
- ret = clk_prepare_enable(res->master_clk);
- if (ret) {
- dev_err(dev, "cannot prepare/enable master clock\n");
- goto err_master_clk;
- }
-
- ret = clk_prepare_enable(res->slave_clk);
- if (ret) {
- dev_err(dev, "cannot prepare/enable slave clock\n");
- goto err_slave_clk;
- }
-
- /* enable PCIe clocks and resets */
- val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL);
- val &= ~BIT(0);
- writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL);
-
- /* change DBI base address */
- writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR);
-
- /* MAC PHY_POWERDOWN MUX DISABLE */
- val = readl(pcie->parf + PCIE20_PARF_SYS_CTRL);
- val &= ~BIT(29);
- writel(val, pcie->parf + PCIE20_PARF_SYS_CTRL);
-
- val = readl(pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
- val |= BIT(4);
- writel(val, pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL);
-
- val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2);
- val |= BIT(31);
- writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2);
-
- return 0;
-
-err_slave_clk:
- clk_disable_unprepare(res->master_clk);
-err_master_clk:
- clk_disable_unprepare(res->cfg_clk);
-err_cfg_clk:
- clk_disable_unprepare(res->aux_clk);
-
- return ret;
-}
-
-static int qcom_pcie_post_init_v2(struct qcom_pcie *pcie)
-{
- struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
- struct device *dev = pcie->pp.dev;
- int ret;
-
- ret = clk_prepare_enable(res->pipe_clk);
- if (ret) {
- dev_err(dev, "cannot prepare/enable pipe clock\n");
- return ret;
- }
-
- return 0;
-}
-
-static int qcom_pcie_link_up(struct pcie_port *pp)
-{
- struct qcom_pcie *pcie = to_qcom_pcie(pp);
- u16 val = readw(pcie->pp.dbi_base + PCIE20_CAP + PCI_EXP_LNKSTA);
-
- return !!(val & PCI_EXP_LNKSTA_DLLLA);
-}
-
-static void qcom_pcie_deinit_v2(struct qcom_pcie *pcie)
-{
- struct qcom_pcie_resources_v2 *res = &pcie->res.v2;
-
- clk_disable_unprepare(res->pipe_clk);
- clk_disable_unprepare(res->slave_clk);
- clk_disable_unprepare(res->master_clk);
- clk_disable_unprepare(res->cfg_clk);
- clk_disable_unprepare(res->aux_clk);
-}
-
-static void qcom_pcie_host_init(struct pcie_port *pp)
-{
- struct qcom_pcie *pcie = to_qcom_pcie(pp);
- int ret;
-
- qcom_ep_reset_assert(pcie);
-
- ret = pcie->ops->init(pcie);
- if (ret)
- goto err_deinit;
-
- ret = phy_power_on(pcie->phy);
- if (ret)
- goto err_deinit;
-
- if (pcie->ops->post_init)
- pcie->ops->post_init(pcie);
-
- dw_pcie_setup_rc(pp);
-
- if (IS_ENABLED(CONFIG_PCI_MSI))
- dw_pcie_msi_init(pp);
-
- qcom_ep_reset_deassert(pcie);
-
- ret = qcom_pcie_establish_link(pcie);
- if (ret)
- goto err;
-
- return;
-err:
- qcom_ep_reset_assert(pcie);
- phy_power_off(pcie->phy);
-err_deinit:
- pcie->ops->deinit(pcie);
-}
-
-static int qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
- u32 *val)
-{
- /* the device class is not reported correctly from the register */
- if (where == PCI_CLASS_REVISION && size == 4) {
- *val = readl(pp->dbi_base + PCI_CLASS_REVISION);
- *val &= 0xff; /* keep revision id */
- *val |= PCI_CLASS_BRIDGE_PCI << 16;
- return PCIBIOS_SUCCESSFUL;
- }
-
- return dw_pcie_cfg_read(pp->dbi_base + where, size, val);
-}
-
-static struct pcie_host_ops qcom_pcie_dw_ops = {
- .link_up = qcom_pcie_link_up,
- .host_init = qcom_pcie_host_init,
- .rd_own_conf = qcom_pcie_rd_own_conf,
-};
-
-static const struct qcom_pcie_ops ops_v0 = {
- .get_resources = qcom_pcie_get_resources_v0,
- .init = qcom_pcie_init_v0,
- .deinit = qcom_pcie_deinit_v0,
- .ltssm_enable = qcom_pcie_v0_v1_ltssm_enable,
-};
-
-static const struct qcom_pcie_ops ops_v1 = {
- .get_resources = qcom_pcie_get_resources_v1,
- .init = qcom_pcie_init_v1,
- .deinit = qcom_pcie_deinit_v1,
- .ltssm_enable = qcom_pcie_v0_v1_ltssm_enable,
-};
-
-static const struct qcom_pcie_ops ops_v2 = {
- .get_resources = qcom_pcie_get_resources_v2,
- .init = qcom_pcie_init_v2,
- .post_init = qcom_pcie_post_init_v2,
- .deinit = qcom_pcie_deinit_v2,
- .ltssm_enable = qcom_pcie_v2_ltssm_enable,
-};
-
-static int qcom_pcie_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct resource *res;
- struct qcom_pcie *pcie;
- struct pcie_port *pp;
- int ret;
-
- pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
- if (!pcie)
- return -ENOMEM;
-
- pp = &pcie->pp;
- pcie->ops = (struct qcom_pcie_ops *)of_device_get_match_data(dev);
-
- pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_LOW);
- if (IS_ERR(pcie->reset))
- return PTR_ERR(pcie->reset);
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "parf");
- pcie->parf = devm_ioremap_resource(dev, res);
- if (IS_ERR(pcie->parf))
- return PTR_ERR(pcie->parf);
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
- pp->dbi_base = devm_ioremap_resource(dev, res);
- if (IS_ERR(pp->dbi_base))
- return PTR_ERR(pp->dbi_base);
-
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi");
- pcie->elbi = devm_ioremap_resource(dev, res);
- if (IS_ERR(pcie->elbi))
- return PTR_ERR(pcie->elbi);
-
- pcie->phy = devm_phy_optional_get(dev, "pciephy");
- if (IS_ERR(pcie->phy))
- return PTR_ERR(pcie->phy);
-
- pp->dev = dev;
- ret = pcie->ops->get_resources(pcie);
- if (ret)
- return ret;
-
- pp->root_bus_nr = -1;
- pp->ops = &qcom_pcie_dw_ops;
-
- if (IS_ENABLED(CONFIG_PCI_MSI)) {
- pp->msi_irq = platform_get_irq_byname(pdev, "msi");
- if (pp->msi_irq < 0)
- return pp->msi_irq;
-
- ret = devm_request_irq(dev, pp->msi_irq,
- qcom_pcie_msi_irq_handler,
- IRQF_SHARED, "qcom-pcie-msi", pp);
- if (ret) {
- dev_err(dev, "cannot request msi irq\n");
- return ret;
- }
- }
-
- ret = phy_init(pcie->phy);
- if (ret)
- return ret;
-
- ret = dw_pcie_host_init(pp);
- if (ret) {
- dev_err(dev, "cannot initialize host\n");
- return ret;
- }
-
- return 0;
-}
-
-static const struct of_device_id qcom_pcie_match[] = {
- { .compatible = "qcom,pcie-ipq8064", .data = &ops_v0 },
- { .compatible = "qcom,pcie-apq8064", .data = &ops_v0 },
- { .compatible = "qcom,pcie-apq8084", .data = &ops_v1 },
- { .compatible = "qcom,pcie-msm8996", .data = &ops_v2 },
- { }
-};
-
-static struct platform_driver qcom_pcie_driver = {
- .probe = qcom_pcie_probe,
- .driver = {
- .name = "qcom-pcie",
- .suppress_bind_attrs = true,
- .of_match_table = qcom_pcie_match,
- },
-};
-builtin_platform_driver(qcom_pcie_driver);
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index aca85be101f8..cb07c45c1858 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -1125,7 +1125,6 @@ static int rcar_pcie_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct rcar_pcie *pcie;
unsigned int data;
- const struct of_device_id *of_id;
int err;
int (*hw_init_fn)(struct rcar_pcie *);
@@ -1149,11 +1148,6 @@ static int rcar_pcie_probe(struct platform_device *pdev)
if (err)
return err;
- of_id = of_match_device(rcar_pcie_of_match, dev);
- if (!of_id || !of_id->data)
- return -EINVAL;
- hw_init_fn = of_id->data;
-
pm_runtime_enable(dev);
err = pm_runtime_get_sync(dev);
if (err < 0) {
@@ -1162,10 +1156,11 @@ static int rcar_pcie_probe(struct platform_device *pdev)
}
/* Failure to get a link might just be that no cards are inserted */
+ hw_init_fn = of_device_get_match_data(dev);
err = hw_init_fn(pcie);
if (err) {
dev_info(dev, "PCIe link down\n");
- err = 0;
+ err = -ENODEV;
goto err_pm_put;
}
diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c
index f2dca7bb0b39..26ddd3535272 100644
--- a/drivers/pci/host/pcie-rockchip.c
+++ b/drivers/pci/host/pcie-rockchip.c
@@ -20,6 +20,7 @@
#include <linux/gpio/consumer.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/iopoll.h>
#include <linux/irq.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdomain.h>
@@ -55,6 +56,10 @@
#define PCIE_CLIENT_MODE_RC HIWORD_UPDATE_BIT(0x0040)
#define PCIE_CLIENT_GEN_SEL_1 HIWORD_UPDATE(0x0080, 0)
#define PCIE_CLIENT_GEN_SEL_2 HIWORD_UPDATE_BIT(0x0080)
+#define PCIE_CLIENT_DEBUG_OUT_0 (PCIE_CLIENT_BASE + 0x3c)
+#define PCIE_CLIENT_DEBUG_LTSSM_MASK GENMASK(5, 0)
+#define PCIE_CLIENT_DEBUG_LTSSM_L1 0x18
+#define PCIE_CLIENT_DEBUG_LTSSM_L2 0x19
#define PCIE_CLIENT_BASIC_STATUS1 (PCIE_CLIENT_BASE + 0x48)
#define PCIE_CLIENT_LINK_STATUS_UP 0x00300000
#define PCIE_CLIENT_LINK_STATUS_MASK 0x00300000
@@ -120,6 +125,7 @@
#define PCIE_CORE_INT_CT BIT(11)
#define PCIE_CORE_INT_UTC BIT(18)
#define PCIE_CORE_INT_MMVC BIT(19)
+#define PCIE_CORE_CONFIG_VENDOR (PCIE_CORE_CTRL_MGMT_BASE + 0x44)
#define PCIE_CORE_INT_MASK (PCIE_CORE_CTRL_MGMT_BASE + 0x210)
#define PCIE_RC_BAR_CONF (PCIE_CORE_CTRL_MGMT_BASE + 0x300)
@@ -133,13 +139,14 @@
PCIE_CORE_INT_MMVC)
#define PCIE_RC_CONFIG_BASE 0xa00000
-#define PCIE_RC_CONFIG_VENDOR (PCIE_RC_CONFIG_BASE + 0x00)
#define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08)
#define PCIE_RC_CONFIG_SCC_SHIFT 16
#define PCIE_RC_CONFIG_DCR (PCIE_RC_CONFIG_BASE + 0xc4)
#define PCIE_RC_CONFIG_DCR_CSPL_SHIFT 18
#define PCIE_RC_CONFIG_DCR_CSPL_LIMIT 0xff
#define PCIE_RC_CONFIG_DCR_CPLS_SHIFT 26
+#define PCIE_RC_CONFIG_LINK_CAP (PCIE_RC_CONFIG_BASE + 0xcc)
+#define PCIE_RC_CONFIG_LINK_CAP_L0S BIT(10)
#define PCIE_RC_CONFIG_LCS (PCIE_RC_CONFIG_BASE + 0xd0)
#define PCIE_RC_CONFIG_L1_SUBSTATE_CTRL2 (PCIE_RC_CONFIG_BASE + 0x90c)
#define PCIE_RC_CONFIG_THP_CAP (PCIE_RC_CONFIG_BASE + 0x274)
@@ -167,9 +174,11 @@
#define IB_ROOT_PORT_REG_SIZE_SHIFT 3
#define AXI_WRAPPER_IO_WRITE 0x6
#define AXI_WRAPPER_MEM_WRITE 0x2
+#define AXI_WRAPPER_NOR_MSG 0xc
#define MAX_AXI_IB_ROOTPORT_REGION_NUM 3
#define MIN_AXI_ADDR_BITS_PASSED 8
+#define PCIE_RC_SEND_PME_OFF 0x11960
#define ROCKCHIP_VENDOR_ID 0x1d87
#define PCIE_ECAM_BUS(x) (((x) & 0xff) << 20)
#define PCIE_ECAM_DEV(x) (((x) & 0x1f) << 15)
@@ -178,6 +187,12 @@
#define PCIE_ECAM_ADDR(bus, dev, func, reg) \
(PCIE_ECAM_BUS(bus) | PCIE_ECAM_DEV(dev) | \
PCIE_ECAM_FUNC(func) | PCIE_ECAM_REG(reg))
+#define PCIE_LINK_IS_L2(x) \
+ (((x) & PCIE_CLIENT_DEBUG_LTSSM_MASK) == PCIE_CLIENT_DEBUG_LTSSM_L2)
+#define PCIE_LINK_UP(x) \
+ (((x) & PCIE_CLIENT_LINK_STATUS_MASK) == PCIE_CLIENT_LINK_STATUS_UP)
+#define PCIE_LINK_IS_GEN2(x) \
+ (((x) & PCIE_CORE_PL_CONF_SPEED_MASK) == PCIE_CORE_PL_CONF_SPEED_5G)
#define RC_REGION_0_ADDR_TRANS_H 0x00000000
#define RC_REGION_0_ADDR_TRANS_L 0x00000000
@@ -211,7 +226,9 @@ struct rockchip_pcie {
u32 io_size;
int offset;
phys_addr_t io_bus_addr;
+ void __iomem *msg_region;
u32 mem_size;
+ phys_addr_t msg_bus_addr;
phys_addr_t mem_bus_addr;
};
@@ -449,7 +466,6 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
struct device *dev = rockchip->dev;
int err;
u32 status;
- unsigned long timeout;
gpiod_set_value(rockchip->ep_gpio, 0);
@@ -590,23 +606,12 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
gpiod_set_value(rockchip->ep_gpio, 1);
/* 500ms timeout value should be enough for Gen1/2 training */
- timeout = jiffies + msecs_to_jiffies(500);
-
- for (;;) {
- status = rockchip_pcie_read(rockchip,
- PCIE_CLIENT_BASIC_STATUS1);
- if ((status & PCIE_CLIENT_LINK_STATUS_MASK) ==
- PCIE_CLIENT_LINK_STATUS_UP) {
- dev_dbg(dev, "PCIe link training gen1 pass!\n");
- break;
- }
-
- if (time_after(jiffies, timeout)) {
- dev_err(dev, "PCIe link training gen1 timeout!\n");
- return -ETIMEDOUT;
- }
-
- msleep(20);
+ err = readl_poll_timeout(rockchip->apb_base + PCIE_CLIENT_BASIC_STATUS1,
+ status, PCIE_LINK_UP(status), 20,
+ 500 * USEC_PER_MSEC);
+ if (err) {
+ dev_err(dev, "PCIe link training gen1 timeout!\n");
+ return -ETIMEDOUT;
}
if (rockchip->link_gen == 2) {
@@ -618,22 +623,11 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
status |= PCI_EXP_LNKCTL_RL;
rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
- timeout = jiffies + msecs_to_jiffies(500);
- for (;;) {
- status = rockchip_pcie_read(rockchip, PCIE_CORE_CTRL);
- if ((status & PCIE_CORE_PL_CONF_SPEED_MASK) ==
- PCIE_CORE_PL_CONF_SPEED_5G) {
- dev_dbg(dev, "PCIe link training gen2 pass!\n");
- break;
- }
-
- if (time_after(jiffies, timeout)) {
- dev_dbg(dev, "PCIe link training gen2 timeout, fall back to gen1!\n");
- break;
- }
-
- msleep(20);
- }
+ err = readl_poll_timeout(rockchip->apb_base + PCIE_CORE_CTRL,
+ status, PCIE_LINK_IS_GEN2(status), 20,
+ 500 * USEC_PER_MSEC);
+ if (err)
+ dev_dbg(dev, "PCIe link training gen2 timeout, fall back to gen1!\n");
}
/* Check the final link width from negotiated lane counter from MGMT */
@@ -643,7 +637,7 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
dev_dbg(dev, "current link width is x%d\n", status);
rockchip_pcie_write(rockchip, ROCKCHIP_VENDOR_ID,
- PCIE_RC_CONFIG_VENDOR);
+ PCIE_CORE_CONFIG_VENDOR);
rockchip_pcie_write(rockchip,
PCI_CLASS_BRIDGE_PCI << PCIE_RC_CONFIG_SCC_SHIFT,
PCIE_RC_CONFIG_RID_CCR);
@@ -653,6 +647,13 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
status &= ~PCIE_RC_CONFIG_THP_CAP_NEXT_MASK;
rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_THP_CAP);
+ /* Clear L0s from RC's link cap */
+ if (of_property_read_bool(dev->of_node, "aspm-no-l0s")) {
+ status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LINK_CAP);
+ status &= ~PCIE_RC_CONFIG_LINK_CAP_L0S;
+ rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LINK_CAP);
+ }
+
rockchip_pcie_write(rockchip, 0x0, PCIE_RC_BAR_CONF);
rockchip_pcie_write(rockchip,
@@ -1186,6 +1187,85 @@ static int rockchip_cfg_atu(struct rockchip_pcie *rockchip)
}
}
+ /* assign message regions */
+ rockchip_pcie_prog_ob_atu(rockchip, reg_no + 1 + offset,
+ AXI_WRAPPER_NOR_MSG,
+ 20 - 1, 0, 0);
+
+ rockchip->msg_bus_addr = rockchip->mem_bus_addr +
+ ((reg_no + offset) << 20);
+ return err;
+}
+
+static int rockchip_pcie_wait_l2(struct rockchip_pcie *rockchip)
+{
+ u32 value;
+ int err;
+
+ /* send PME_TURN_OFF message */
+ writel(0x0, rockchip->msg_region + PCIE_RC_SEND_PME_OFF);
+
+ /* read LTSSM and wait for falling into L2 link state */
+ err = readl_poll_timeout(rockchip->apb_base + PCIE_CLIENT_DEBUG_OUT_0,
+ value, PCIE_LINK_IS_L2(value), 20,
+ jiffies_to_usecs(5 * HZ));
+ if (err) {
+ dev_err(rockchip->dev, "PCIe link enter L2 timeout!\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int __maybe_unused rockchip_pcie_suspend_noirq(struct device *dev)
+{
+ struct rockchip_pcie *rockchip = dev_get_drvdata(dev);
+ int ret;
+
+ /* disable core and cli int since we don't need to ack PME_ACK */
+ rockchip_pcie_write(rockchip, (PCIE_CLIENT_INT_CLI << 16) |
+ PCIE_CLIENT_INT_CLI, PCIE_CLIENT_INT_MASK);
+ rockchip_pcie_write(rockchip, (u32)PCIE_CORE_INT, PCIE_CORE_INT_MASK);
+
+ ret = rockchip_pcie_wait_l2(rockchip);
+ if (ret) {
+ rockchip_pcie_enable_interrupts(rockchip);
+ return ret;
+ }
+
+ phy_power_off(rockchip->phy);
+ phy_exit(rockchip->phy);
+
+ clk_disable_unprepare(rockchip->clk_pcie_pm);
+ clk_disable_unprepare(rockchip->hclk_pcie);
+ clk_disable_unprepare(rockchip->aclk_perf_pcie);
+ clk_disable_unprepare(rockchip->aclk_pcie);
+
+ return ret;
+}
+
+static int __maybe_unused rockchip_pcie_resume_noirq(struct device *dev)
+{
+ struct rockchip_pcie *rockchip = dev_get_drvdata(dev);
+ int err;
+
+ clk_prepare_enable(rockchip->clk_pcie_pm);
+ clk_prepare_enable(rockchip->hclk_pcie);
+ clk_prepare_enable(rockchip->aclk_perf_pcie);
+ clk_prepare_enable(rockchip->aclk_pcie);
+
+ err = rockchip_pcie_init_port(rockchip);
+ if (err)
+ return err;
+
+ err = rockchip_cfg_atu(rockchip);
+ if (err)
+ return err;
+
+ /* Need this to enter L1 again */
+ rockchip_pcie_update_txcredit_mui(rockchip);
+ rockchip_pcie_enable_interrupts(rockchip);
+
return 0;
}
@@ -1209,6 +1289,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
if (!rockchip)
return -ENOMEM;
+ platform_set_drvdata(pdev, rockchip);
rockchip->dev = dev;
err = rockchip_pcie_parse_dt(rockchip);
@@ -1262,7 +1343,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
err = devm_request_pci_bus_resources(dev, &res);
if (err)
- goto err_vpcie;
+ goto err_free_res;
/* Get the I/O and memory ranges from DT */
resource_list_for_each_entry(win, &res) {
@@ -1295,11 +1376,19 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
err = rockchip_cfg_atu(rockchip);
if (err)
- goto err_vpcie;
+ goto err_free_res;
+
+ rockchip->msg_region = devm_ioremap(rockchip->dev,
+ rockchip->msg_bus_addr, SZ_1M);
+ if (!rockchip->msg_region) {
+ err = -ENOMEM;
+ goto err_free_res;
+ }
+
bus = pci_scan_root_bus(&pdev->dev, 0, &rockchip_pcie_ops, rockchip, &res);
if (!bus) {
err = -ENOMEM;
- goto err_vpcie;
+ goto err_free_res;
}
pci_bus_size_bridges(bus);
@@ -1310,6 +1399,8 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
pci_bus_add_devices(bus);
return err;
+err_free_res:
+ pci_free_resource_list(&res);
err_vpcie:
if (!IS_ERR(rockchip->vpcie3v3))
regulator_disable(rockchip->vpcie3v3);
@@ -1329,6 +1420,11 @@ err_aclk_pcie:
return err;
}
+static const struct dev_pm_ops rockchip_pcie_pm_ops = {
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(rockchip_pcie_suspend_noirq,
+ rockchip_pcie_resume_noirq)
+};
+
static const struct of_device_id rockchip_pcie_of_match[] = {
{ .compatible = "rockchip,rk3399-pcie", },
{}
@@ -1338,6 +1434,7 @@ static struct platform_driver rockchip_pcie_driver = {
.driver = {
.name = "rockchip-pcie",
.of_match_table = rockchip_pcie_of_match,
+ .pm = &rockchip_pcie_pm_ops,
},
.probe = rockchip_pcie_probe,
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
deleted file mode 100644
index dafe8b88d97d..000000000000
--- a/drivers/pci/host/pcie-spear13xx.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * PCIe host controller driver for ST Microelectronics SPEAr13xx SoCs
- *
- * SPEAr13xx PCIe Glue Layer Source Code
- *
- * Copyright (C) 2010-2014 ST Microelectronics
- * Pratyush Anand <pratyush.anand@gmail.com>
- * Mohit Kumar <mohit.kumar.dhaka@gmail.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.
- */
-
-#include <linux/clk.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/of.h>
-#include <linux/pci.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/resource.h>
-
-#include "pcie-designware.h"
-
-struct spear13xx_pcie {
- struct pcie_port pp; /* DT dbi is pp.dbi_base */
- void __iomem *app_base;
- struct phy *phy;
- struct clk *clk;
- bool is_gen1;
-};
-
-struct pcie_app_reg {
- u32 app_ctrl_0; /* cr0 */
- u32 app_ctrl_1; /* cr1 */
- u32 app_status_0; /* cr2 */
- u32 app_status_1; /* cr3 */
- u32 msg_status; /* cr4 */
- u32 msg_payload; /* cr5 */
- u32 int_sts; /* cr6 */
- u32 int_clr; /* cr7 */
- u32 int_mask; /* cr8 */
- u32 mst_bmisc; /* cr9 */
- u32 phy_ctrl; /* cr10 */
- u32 phy_status; /* cr11 */
- u32 cxpl_debug_info_0; /* cr12 */
- u32 cxpl_debug_info_1; /* cr13 */
- u32 ven_msg_ctrl_0; /* cr14 */
- u32 ven_msg_ctrl_1; /* cr15 */
- u32 ven_msg_data_0; /* cr16 */
- u32 ven_msg_data_1; /* cr17 */
- u32 ven_msi_0; /* cr18 */
- u32 ven_msi_1; /* cr19 */
- u32 mst_rmisc; /* cr20 */
-};
-
-/* CR0 ID */
-#define APP_LTSSM_ENABLE_ID 3
-#define DEVICE_TYPE_RC (4 << 25)
-#define MISCTRL_EN_ID 30
-#define REG_TRANSLATION_ENABLE 31
-
-/* CR3 ID */
-#define XMLH_LINK_UP (1 << 6)
-
-/* CR6 */
-#define MSI_CTRL_INT (1 << 26)
-
-#define EXP_CAP_ID_OFFSET 0x70
-
-#define to_spear13xx_pcie(x) container_of(x, struct spear13xx_pcie, pp)
-
-static int spear13xx_pcie_establish_link(struct spear13xx_pcie *spear13xx_pcie)
-{
- struct pcie_port *pp = &spear13xx_pcie->pp;
- struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
- u32 val;
- u32 exp_cap_off = EXP_CAP_ID_OFFSET;
-
- if (dw_pcie_link_up(pp)) {
- dev_err(pp->dev, "link already up\n");
- return 0;
- }
-
- dw_pcie_setup_rc(pp);
-
- /*
- * this controller support only 128 bytes read size, however its
- * default value in capability register is 512 bytes. So force
- * it to 128 here.
- */
- dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_DEVCTL, 2, &val);
- val &= ~PCI_EXP_DEVCTL_READRQ;
- dw_pcie_cfg_write(pp->dbi_base + exp_cap_off + PCI_EXP_DEVCTL, 2, val);
-
- dw_pcie_cfg_write(pp->dbi_base + PCI_VENDOR_ID, 2, 0x104A);
- dw_pcie_cfg_write(pp->dbi_base + PCI_DEVICE_ID, 2, 0xCD80);
-
- /*
- * if is_gen1 is set then handle it, so that some buggy card
- * also works
- */
- if (spear13xx_pcie->is_gen1) {
- dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_LNKCAP,
- 4, &val);
- if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) {
- val &= ~((u32)PCI_EXP_LNKCAP_SLS);
- val |= PCI_EXP_LNKCAP_SLS_2_5GB;
- dw_pcie_cfg_write(pp->dbi_base + exp_cap_off +
- PCI_EXP_LNKCAP, 4, val);
- }
-
- dw_pcie_cfg_read(pp->dbi_base + exp_cap_off + PCI_EXP_LNKCTL2,
- 2, &val);
- if ((val & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) {
- val &= ~((u32)PCI_EXP_LNKCAP_SLS);
- val |= PCI_EXP_LNKCAP_SLS_2_5GB;
- dw_pcie_cfg_write(pp->dbi_base + exp_cap_off +
- PCI_EXP_LNKCTL2, 2, val);
- }
- }
-
- /* enable ltssm */
- writel(DEVICE_TYPE_RC | (1 << MISCTRL_EN_ID)
- | (1 << APP_LTSSM_ENABLE_ID)
- | ((u32)1 << REG_TRANSLATION_ENABLE),
- &app_reg->app_ctrl_0);
-
- return dw_pcie_wait_for_link(pp);
-}
-
-static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg)
-{
- struct spear13xx_pcie *spear13xx_pcie = arg;
- struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
- struct pcie_port *pp = &spear13xx_pcie->pp;
- unsigned int status;
-
- status = readl(&app_reg->int_sts);
-
- if (status & MSI_CTRL_INT) {
- BUG_ON(!IS_ENABLED(CONFIG_PCI_MSI));
- dw_handle_msi_irq(pp);
- }
-
- writel(status, &app_reg->int_clr);
-
- return IRQ_HANDLED;
-}
-
-static void spear13xx_pcie_enable_interrupts(struct spear13xx_pcie *spear13xx_pcie)
-{
- struct pcie_port *pp = &spear13xx_pcie->pp;
- struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
-
- /* Enable MSI interrupt */
- if (IS_ENABLED(CONFIG_PCI_MSI)) {
- dw_pcie_msi_init(pp);
- writel(readl(&app_reg->int_mask) |
- MSI_CTRL_INT, &app_reg->int_mask);
- }
-}
-
-static int spear13xx_pcie_link_up(struct pcie_port *pp)
-{
- struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
- struct pcie_app_reg *app_reg = spear13xx_pcie->app_base;
-
- if (readl(&app_reg->app_status_1) & XMLH_LINK_UP)
- return 1;
-
- return 0;
-}
-
-static void spear13xx_pcie_host_init(struct pcie_port *pp)
-{
- struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp);
-
- spear13xx_pcie_establish_link(spear13xx_pcie);
- spear13xx_pcie_enable_interrupts(spear13xx_pcie);
-}
-
-static struct pcie_host_ops spear13xx_pcie_host_ops = {
- .link_up = spear13xx_pcie_link_up,
- .host_init = spear13xx_pcie_host_init,
-};
-
-static int spear13xx_add_pcie_port(struct spear13xx_pcie *spear13xx_pcie,
- struct platform_device *pdev)
-{
- struct pcie_port *pp = &spear13xx_pcie->pp;
- struct device *dev = pp->dev;
- int ret;
-
- pp->irq = platform_get_irq(pdev, 0);
- if (!pp->irq) {
- dev_err(dev, "failed to get irq\n");
- return -ENODEV;
- }
- ret = devm_request_irq(dev, pp->irq, spear13xx_pcie_irq_handler,
- IRQF_SHARED | IRQF_NO_THREAD,
- "spear1340-pcie", spear13xx_pcie);
- if (ret) {
- dev_err(dev, "failed to request irq %d\n", pp->irq);
- return ret;
- }
-
- pp->root_bus_nr = -1;
- pp->ops = &spear13xx_pcie_host_ops;
-
- ret = dw_pcie_host_init(pp);
- if (ret) {
- dev_err(dev, "failed to initialize host\n");
- return ret;
- }
-
- return 0;
-}
-
-static int spear13xx_pcie_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct spear13xx_pcie *spear13xx_pcie;
- struct pcie_port *pp;
- struct device_node *np = dev->of_node;
- struct resource *dbi_base;
- int ret;
-
- spear13xx_pcie = devm_kzalloc(dev, sizeof(*spear13xx_pcie), GFP_KERNEL);
- if (!spear13xx_pcie)
- return -ENOMEM;
-
- spear13xx_pcie->phy = devm_phy_get(dev, "pcie-phy");
- if (IS_ERR(spear13xx_pcie->phy)) {
- ret = PTR_ERR(spear13xx_pcie->phy);
- if (ret == -EPROBE_DEFER)
- dev_info(dev, "probe deferred\n");
- else
- dev_err(dev, "couldn't get pcie-phy\n");
- return ret;
- }
-
- phy_init(spear13xx_pcie->phy);
-
- spear13xx_pcie->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(spear13xx_pcie->clk)) {
- dev_err(dev, "couldn't get clk for pcie\n");
- return PTR_ERR(spear13xx_pcie->clk);
- }
- ret = clk_prepare_enable(spear13xx_pcie->clk);
- if (ret) {
- dev_err(dev, "couldn't enable clk for pcie\n");
- return ret;
- }
-
- pp = &spear13xx_pcie->pp;
- pp->dev = dev;
-
- dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
- pp->dbi_base = devm_ioremap_resource(dev, dbi_base);
- if (IS_ERR(pp->dbi_base)) {
- dev_err(dev, "couldn't remap dbi base %p\n", dbi_base);
- ret = PTR_ERR(pp->dbi_base);
- goto fail_clk;
- }
- spear13xx_pcie->app_base = pp->dbi_base + 0x2000;
-
- if (of_property_read_bool(np, "st,pcie-is-gen1"))
- spear13xx_pcie->is_gen1 = true;
-
- ret = spear13xx_add_pcie_port(spear13xx_pcie, pdev);
- if (ret < 0)
- goto fail_clk;
-
- platform_set_drvdata(pdev, spear13xx_pcie);
- return 0;
-
-fail_clk:
- clk_disable_unprepare(spear13xx_pcie->clk);
-
- return ret;
-}
-
-static const struct of_device_id spear13xx_pcie_of_match[] = {
- { .compatible = "st,spear1340-pcie", },
- {},
-};
-
-static struct platform_driver spear13xx_pcie_driver = {
- .probe = spear13xx_pcie_probe,
- .driver = {
- .name = "spear-pcie",
- .of_match_table = of_match_ptr(spear13xx_pcie_of_match),
- },
-};
-
-builtin_platform_driver(spear13xx_pcie_driver);
diff --git a/drivers/pci/host/pcie-xilinx-nwl.c b/drivers/pci/host/pcie-xilinx-nwl.c
index 43eaa4afab94..4c3e0ab35496 100644
--- a/drivers/pci/host/pcie-xilinx-nwl.c
+++ b/drivers/pci/host/pcie-xilinx-nwl.c
@@ -62,21 +62,9 @@
#define CFG_ENABLE_PM_MSG_FWD BIT(1)
#define CFG_ENABLE_INT_MSG_FWD BIT(2)
#define CFG_ENABLE_ERR_MSG_FWD BIT(3)
-#define CFG_ENABLE_SLT_MSG_FWD BIT(5)
-#define CFG_ENABLE_VEN_MSG_FWD BIT(7)
-#define CFG_ENABLE_OTH_MSG_FWD BIT(13)
-#define CFG_ENABLE_VEN_MSG_EN BIT(14)
-#define CFG_ENABLE_VEN_MSG_VEN_INV BIT(15)
-#define CFG_ENABLE_VEN_MSG_VEN_ID GENMASK(31, 16)
#define CFG_ENABLE_MSG_FILTER_MASK (CFG_ENABLE_PM_MSG_FWD | \
CFG_ENABLE_INT_MSG_FWD | \
- CFG_ENABLE_ERR_MSG_FWD | \
- CFG_ENABLE_SLT_MSG_FWD | \
- CFG_ENABLE_VEN_MSG_FWD | \
- CFG_ENABLE_OTH_MSG_FWD | \
- CFG_ENABLE_VEN_MSG_EN | \
- CFG_ENABLE_VEN_MSG_VEN_INV | \
- CFG_ENABLE_VEN_MSG_VEN_ID)
+ CFG_ENABLE_ERR_MSG_FWD)
/* Misc interrupt status mask bits */
#define MSGF_MISC_SR_RXMSG_AVAIL BIT(0)
diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/host/pcie-xilinx.c
index c8616fadccf1..7f030f5d750b 100644
--- a/drivers/pci/host/pcie-xilinx.c
+++ b/drivers/pci/host/pcie-xilinx.c
@@ -632,7 +632,7 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct xilinx_pcie_port *port;
- struct pci_bus *bus;
+ struct pci_bus *bus, *child;
int err;
resource_size_t iobase = 0;
LIST_HEAD(res);
@@ -686,6 +686,8 @@ static int xilinx_pcie_probe(struct platform_device *pdev)
#ifndef CONFIG_MICROBLAZE
pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
#endif
+ list_for_each_entry(child, &bus->children, node)
+ pcie_bus_configure_settings(child);
pci_bus_add_devices(bus);
return 0;
diff --git a/drivers/pci/host/vmd.c b/drivers/pci/host/vmd.c
index 18ef1a93c10a..e27ad2a3bd33 100644
--- a/drivers/pci/host/vmd.c
+++ b/drivers/pci/host/vmd.c
@@ -282,7 +282,7 @@ static struct device *to_vmd_dev(struct device *dev)
return &vmd->dev->dev;
}
-static struct dma_map_ops *vmd_dma_ops(struct device *dev)
+static const struct dma_map_ops *vmd_dma_ops(struct device *dev)
{
return get_dma_ops(to_vmd_dev(dev));
}