diff options
author | Bjorn Helgaas | 2017-02-21 15:12:18 -0600 |
---|---|---|
committer | Bjorn Helgaas | 2017-02-21 15:12:18 -0600 |
commit | 3bb0356bb1b5a2c4434b4a3267df6dd9927ca5bf (patch) | |
tree | a601387ad9c6a3fd66125e4506b560530280ccbd /drivers/pci | |
parent | 4c2ae32d4c6ccd63819f36702f8455a5b08eaca8 (diff) | |
parent | 7a2b3f024b8b724257d82f76690e68c69d797efd (diff) |
Merge branch 'pci/host-designware' into next
* pci/host-designware:
PCI: dwc: Remove dependency of designware on CONFIG_PCI
PCI: dwc: Add CONFIG_PCIE_DW_HOST to enable PCI dwc host
PCI: dwc: Split pcie-designware.c into host and core files
PCI: dwc: designware: Fix style errors in pcie-designware.c
PCI: dwc: designware: Parse "num-lanes" property in dw_pcie_setup_rc()
PCI: dwc: all: Split struct pcie_port into host-only and core structures
PCI: dwc: designware: Get device pointer at the start of dw_pcie_host_init()
PCI: dwc: all: Rename cfg_read/cfg_write to read/write
PCI: dwc: all: Use platform_set_drvdata() to save private data
PCI: dwc: designware: Move register defines to designware header file
PCI: dwc: Use PTR_ERR_OR_ZERO to simplify code
PCI: dra7xx: Group PHY API invocations
PCI: dra7xx: Enable MSI and legacy interrupts simultaneously
PCI: dra7xx: Add support to force RC to work in GEN1 mode
PCI: dra7xx: Simplify probe code with devm_gpiod_get_optional()
PCI: Move DesignWare IP support to new drivers/pci/dwc/ directory
PCI: designware: Check for iATU unroll only on platforms that use ATU
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/Kconfig | 1 | ||||
-rw-r--r-- | drivers/pci/dwc/Kconfig | 132 | ||||
-rw-r--r-- | drivers/pci/dwc/Makefile | 24 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-dra7xx.c (renamed from drivers/pci/host/pci-dra7xx.c) | 247 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-exynos.c (renamed from drivers/pci/host/pci-exynos.c) | 81 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-imx6.c (renamed from drivers/pci/host/pci-imx6.c) | 131 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-keystone-dw.c (renamed from drivers/pci/host/pci-keystone-dw.c) | 87 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-keystone.c (renamed from drivers/pci/host/pci-keystone.c) | 56 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-keystone.h (renamed from drivers/pci/host/pci-keystone.h) | 4 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-layerscape.c (renamed from drivers/pci/host/pci-layerscape.c) | 93 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-armada8k.c (renamed from drivers/pci/host/pcie-armada8k.c) | 87 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-artpec6.c (renamed from drivers/pci/host/pcie-artpec6.c) | 50 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-designware-host.c (renamed from drivers/pci/host/pcie-designware.c) | 445 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-designware-plat.c (renamed from drivers/pci/host/pcie-designware-plat.c) | 29 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-designware.c | 233 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-designware.h | 198 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-hisi.c (renamed from drivers/pci/host/pcie-hisi.c) | 57 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-qcom.c (renamed from drivers/pci/host/pcie-qcom.c) | 87 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-spear13xx.c (renamed from drivers/pci/host/pcie-spear13xx.c) | 85 | ||||
-rw-r--r-- | drivers/pci/host/Kconfig | 113 | ||||
-rw-r--r-- | drivers/pci/host/Makefile | 12 | ||||
-rw-r--r-- | drivers/pci/host/pcie-designware.h | 86 |
22 files changed, 1319 insertions, 1019 deletions
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 6555eb78d91c..df141420c902 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -132,4 +132,5 @@ config PCI_HYPERV PCI devices from a PCI backend to support PCI driver domains. source "drivers/pci/hotplug/Kconfig" +source "drivers/pci/dwc/Kconfig" source "drivers/pci/host/Kconfig" diff --git a/drivers/pci/dwc/Kconfig b/drivers/pci/dwc/Kconfig new file mode 100644 index 000000000000..dfb8a69afc28 --- /dev/null +++ b/drivers/pci/dwc/Kconfig @@ -0,0 +1,132 @@ +menu "DesignWare PCI Core Support" + +config PCIE_DW + bool + +config PCIE_DW_HOST + bool + depends on PCI + depends on PCI_MSI_IRQ_DOMAIN + select PCIE_DW + +config PCI_DRA7XX + bool "TI DRA7xx PCIe controller" + depends on PCI + depends on OF && HAS_IOMEM && TI_PIPE3 + depends on PCI_MSI_IRQ_DOMAIN + select PCIE_DW_HOST + 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 PCIE_DW_PLAT + bool "Platform bus based DesignWare PCIe Controller" + depends on PCI + depends on PCI_MSI_IRQ_DOMAIN + select PCIE_DW_HOST + ---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 PCI_EXYNOS + bool "Samsung Exynos PCIe controller" + depends on PCI + depends on SOC_EXYNOS5440 + depends on PCI_MSI_IRQ_DOMAIN + select PCIEPORTBUS + select PCIE_DW_HOST + +config PCI_IMX6 + bool "Freescale i.MX6 PCIe controller" + depends on PCI + depends on SOC_IMX6Q + depends on PCI_MSI_IRQ_DOMAIN + select PCIEPORTBUS + select PCIE_DW_HOST + +config PCIE_SPEAR13XX + bool "STMicroelectronics SPEAr PCIe controller" + depends on PCI + depends on ARCH_SPEAR13XX + depends on PCI_MSI_IRQ_DOMAIN + select PCIEPORTBUS + select PCIE_DW_HOST + help + Say Y here if you want PCIe support on SPEAr13XX SoCs. + +config PCI_KEYSTONE + bool "TI Keystone PCIe controller" + depends on PCI + depends on ARCH_KEYSTONE + depends on PCI_MSI_IRQ_DOMAIN + select PCIEPORTBUS + select PCIE_DW_HOST + 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 PCI_LAYERSCAPE + bool "Freescale Layerscape PCIe controller" + depends on PCI + depends on OF && (ARM || ARCH_LAYERSCAPE) + depends on PCI_MSI_IRQ_DOMAIN + select MFD_SYSCON + select PCIE_DW_HOST + help + Say Y here if you want PCIe controller support on Layerscape SoCs. + +config PCI_HISI + depends on OF && ARM64 + bool "HiSilicon Hip05 and Hip06 SoCs PCIe controllers" + depends on PCI + depends on PCI_MSI_IRQ_DOMAIN + select PCIEPORTBUS + select PCIE_DW_HOST + 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 PCI + depends on ARCH_QCOM && OF + depends on PCI_MSI_IRQ_DOMAIN + select PCIEPORTBUS + select PCIE_DW_HOST + 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 PCIE_ARMADA_8K + bool "Marvell Armada-8K PCIe controller" + depends on PCI + depends on ARCH_MVEBU + depends on PCI_MSI_IRQ_DOMAIN + select PCIEPORTBUS + select PCIE_DW_HOST + 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 PCI + depends on MACH_ARTPEC6 + depends on PCI_MSI_IRQ_DOMAIN + select PCIEPORTBUS + select PCIE_DW_HOST + help + Say Y here to enable PCIe controller support on Axis ARTPEC-6 + SoCs. This PCIe controller uses the DesignWare core. + +endmenu diff --git a/drivers/pci/dwc/Makefile b/drivers/pci/dwc/Makefile new file mode 100644 index 000000000000..a2df13c28798 --- /dev/null +++ b/drivers/pci/dwc/Makefile @@ -0,0 +1,24 @@ +obj-$(CONFIG_PCIE_DW) += pcie-designware.o +obj-$(CONFIG_PCIE_DW_HOST) += pcie-designware-host.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_PCIE_SPEAR13XX) += pcie-spear13xx.o +obj-$(CONFIG_PCI_KEYSTONE) += pci-keystone-dw.o pci-keystone.o +obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o +obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o +obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o +obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o + +# The following drivers are for devices that use the generic ACPI +# pci_root.c driver but don't support standard ECAM config access. +# They contain MCFG quirks to replace the generic ECAM accessors with +# device-specific ones that are shared with the DT driver. + +# The ACPI driver is generic and should not require driver-specific +# config options to be enabled, so we always build these drivers on +# 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 diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c index 9595fad63f6f..0984baff07e3 100644 --- a/drivers/pci/host/pci-dra7xx.c +++ b/drivers/pci/dwc/pci-dra7xx.c @@ -17,6 +17,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/of_gpio.h> +#include <linux/of_pci.h> #include <linux/pci.h> #include <linux/phy/phy.h> #include <linux/platform_device.h> @@ -63,14 +64,18 @@ #define LINK_UP BIT(16) #define DRA7XX_CPU_TO_BUS_ADDR 0x0FFFFFFF +#define EXP_CAP_ID_OFFSET 0x70 + struct dra7xx_pcie { - struct pcie_port pp; + struct dw_pcie *pci; void __iomem *base; /* DT ti_conf */ int phy_count; /* DT phy-names count */ struct phy **phy; + int link_gen; + struct irq_domain *irq_domain; }; -#define to_dra7xx_pcie(x) container_of((x), struct dra7xx_pcie, pp) +#define to_dra7xx_pcie(x) dev_get_drvdata((x)->dev) static inline u32 dra7xx_pcie_readl(struct dra7xx_pcie *pcie, u32 offset) { @@ -83,9 +88,9 @@ static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset, writel(value, pcie->base + offset); } -static int dra7xx_pcie_link_up(struct pcie_port *pp) +static int dra7xx_pcie_link_up(struct dw_pcie *pci) { - struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp); + struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); u32 reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_PHY_CS); return !!(reg & LINK_UP); @@ -93,20 +98,41 @@ static int dra7xx_pcie_link_up(struct pcie_port *pp) static int dra7xx_pcie_establish_link(struct dra7xx_pcie *dra7xx) { - struct pcie_port *pp = &dra7xx->pp; - struct device *dev = pp->dev; + struct dw_pcie *pci = dra7xx->pci; + struct device *dev = pci->dev; u32 reg; + u32 exp_cap_off = EXP_CAP_ID_OFFSET; - if (dw_pcie_link_up(pp)) { + if (dw_pcie_link_up(pci)) { dev_err(dev, "link is already up\n"); return 0; } + if (dra7xx->link_gen == 1) { + dw_pcie_read(pci->dbi_base + exp_cap_off + PCI_EXP_LNKCAP, + 4, ®); + if ((reg & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) { + reg &= ~((u32)PCI_EXP_LNKCAP_SLS); + reg |= PCI_EXP_LNKCAP_SLS_2_5GB; + dw_pcie_write(pci->dbi_base + exp_cap_off + + PCI_EXP_LNKCAP, 4, reg); + } + + dw_pcie_read(pci->dbi_base + exp_cap_off + PCI_EXP_LNKCTL2, + 2, ®); + if ((reg & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) { + reg &= ~((u32)PCI_EXP_LNKCAP_SLS); + reg |= PCI_EXP_LNKCAP_SLS_2_5GB; + dw_pcie_write(pci->dbi_base + exp_cap_off + + PCI_EXP_LNKCTL2, 2, reg); + } + } + 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); + return dw_pcie_wait_for_link(pci); } static void dra7xx_pcie_enable_interrupts(struct dra7xx_pcie *dra7xx) @@ -117,19 +143,14 @@ static void dra7xx_pcie_enable_interrupts(struct dra7xx_pcie *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); + dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI, + MSI | LEG_EP_INTERRUPTS); } static void dra7xx_pcie_host_init(struct pcie_port *pp) { - struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pp); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); pp->io_base &= DRA7XX_CPU_TO_BUS_ADDR; pp->mem_base &= DRA7XX_CPU_TO_BUS_ADDR; @@ -139,13 +160,11 @@ static void dra7xx_pcie_host_init(struct pcie_port *pp) dw_pcie_setup_rc(pp); dra7xx_pcie_establish_link(dra7xx); - if (IS_ENABLED(CONFIG_PCI_MSI)) - dw_pcie_msi_init(pp); + 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, +static struct dw_pcie_host_ops dra7xx_pcie_host_ops = { .host_init = dra7xx_pcie_host_init, }; @@ -164,7 +183,9 @@ static const struct irq_domain_ops intx_domain_ops = { static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp) { - struct device *dev = pp->dev; + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct device *dev = pci->dev; + struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); struct device_node *node = dev->of_node; struct device_node *pcie_intc_node = of_get_next_child(node, NULL); @@ -173,9 +194,9 @@ static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp) return -ENODEV; } - pp->irq_domain = irq_domain_add_linear(pcie_intc_node, 4, - &intx_domain_ops, pp); - if (!pp->irq_domain) { + dra7xx->irq_domain = irq_domain_add_linear(pcie_intc_node, 4, + &intx_domain_ops, pp); + if (!dra7xx->irq_domain) { dev_err(dev, "Failed to get a INTx IRQ domain\n"); return -ENODEV; } @@ -186,7 +207,8 @@ static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp) static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg) { struct dra7xx_pcie *dra7xx = arg; - struct pcie_port *pp = &dra7xx->pp; + struct dw_pcie *pci = dra7xx->pci; + struct pcie_port *pp = &pci->pp; u32 reg; reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI); @@ -199,7 +221,8 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg) case INTB: case INTC: case INTD: - generic_handle_irq(irq_find_mapping(pp->irq_domain, ffs(reg))); + generic_handle_irq(irq_find_mapping(dra7xx->irq_domain, + ffs(reg))); break; } @@ -212,7 +235,8 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg) static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg) { struct dra7xx_pcie *dra7xx = arg; - struct device *dev = dra7xx->pp.dev; + struct dw_pcie *pci = dra7xx->pci; + struct device *dev = pci->dev; u32 reg; reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN); @@ -267,8 +291,9 @@ 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 dw_pcie *pci = dra7xx->pci; + struct pcie_port *pp = &pci->pp; + struct device *dev = pci->dev; struct resource *res; pp->irq = platform_get_irq(pdev, 1); @@ -285,15 +310,13 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx, return ret; } - if (!IS_ENABLED(CONFIG_PCI_MSI)) { - ret = dra7xx_pcie_init_irq_domain(pp); - if (ret < 0) - return ret; - } + 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) + pci->dbi_base = devm_ioremap(dev, res->start, resource_size(res)); + if (!pci->dbi_base) return -ENOMEM; ret = dw_pcie_host_init(pp); @@ -305,6 +328,49 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx, return 0; } +static const struct dw_pcie_ops dw_pcie_ops = { + .link_up = dra7xx_pcie_link_up, +}; + +static void dra7xx_pcie_disable_phy(struct dra7xx_pcie *dra7xx) +{ + int phy_count = dra7xx->phy_count; + + while (phy_count--) { + phy_power_off(dra7xx->phy[phy_count]); + phy_exit(dra7xx->phy[phy_count]); + } +} + +static int dra7xx_pcie_enable_phy(struct dra7xx_pcie *dra7xx) +{ + 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; +} + static int __init dra7xx_pcie_probe(struct platform_device *pdev) { u32 reg; @@ -315,21 +381,26 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) struct phy **phy; void __iomem *base; struct resource *res; - struct dra7xx_pcie *dra7xx; + struct dw_pcie *pci; struct pcie_port *pp; + struct dra7xx_pcie *dra7xx; 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; + struct gpio_desc *reset; dra7xx = devm_kzalloc(dev, sizeof(*dra7xx), GFP_KERNEL); if (!dra7xx) return -ENOMEM; - pp = &dra7xx->pp; - pp->dev = dev; + pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); + if (!pci) + return -ENOMEM; + + pci->dev = dev; + pci->ops = &dw_pcie_ops; + + pp = &pci->pp; pp->ops = &dra7xx_pcie_host_ops; irq = platform_get_irq(pdev, 0); @@ -365,22 +436,21 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) 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->pci = pci; dra7xx->phy_count = phy_count; + ret = dra7xx_pcie_enable_phy(dra7xx); + if (ret) { + dev_err(dev, "failed to enable phy\n"); + return ret; + } + + platform_set_drvdata(pdev, dra7xx); + pm_runtime_enable(dev); ret = pm_runtime_get_sync(dev); if (ret < 0) { @@ -388,19 +458,10 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) 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; + reset = devm_gpiod_get_optional(dev, NULL, GPIOD_OUT_HIGH); + if (IS_ERR(reset)) { + ret = PTR_ERR(reset); + dev_err(&pdev->dev, "gpio request failed, ret %d\n", ret); goto err_gpio; } @@ -408,11 +469,14 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) reg &= ~LTSSM_EN; dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg); + dra7xx->link_gen = of_pci_get_max_link_speed(np); + if (dra7xx->link_gen < 0 || dra7xx->link_gen > 2) + dra7xx->link_gen = 2; + ret = dra7xx_add_pcie_port(dra7xx, pdev); if (ret < 0) goto err_gpio; - platform_set_drvdata(pdev, dra7xx); return 0; err_gpio: @@ -420,12 +484,7 @@ err_gpio: err_get_sync: pm_runtime_disable(dev); - -err_phy: - while (--i >= 0) { - phy_power_off(phy[i]); - phy_exit(phy[i]); - } + dra7xx_pcie_disable_phy(dra7xx); return ret; } @@ -434,13 +493,13 @@ err_phy: static int dra7xx_pcie_suspend(struct device *dev) { struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev); - struct pcie_port *pp = &dra7xx->pp; + struct dw_pcie *pci = dra7xx->pci; u32 val; /* clear MSE */ - val = dw_pcie_readl_rc(pp, PCI_COMMAND); + val = dw_pcie_readl_dbi(pci, PCI_COMMAND); val &= ~PCI_COMMAND_MEMORY; - dw_pcie_writel_rc(pp, PCI_COMMAND, val); + dw_pcie_writel_dbi(pci, PCI_COMMAND, val); return 0; } @@ -448,13 +507,13 @@ static int dra7xx_pcie_suspend(struct device *dev) static int dra7xx_pcie_resume(struct device *dev) { struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev); - struct pcie_port *pp = &dra7xx->pp; + struct dw_pcie *pci = dra7xx->pci; u32 val; /* set MSE */ - val = dw_pcie_readl_rc(pp, PCI_COMMAND); + val = dw_pcie_readl_dbi(pci, PCI_COMMAND); val |= PCI_COMMAND_MEMORY; - dw_pcie_writel_rc(pp, PCI_COMMAND, val); + dw_pcie_writel_dbi(pci, PCI_COMMAND, val); return 0; } @@ -462,12 +521,8 @@ static int dra7xx_pcie_resume(struct device *dev) 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]); - } + dra7xx_pcie_disable_phy(dra7xx); return 0; } @@ -475,31 +530,15 @@ static int dra7xx_pcie_suspend_noirq(struct device *dev) 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; - } + ret = dra7xx_pcie_enable_phy(dra7xx); + if (ret) { + dev_err(dev, "failed to enable phy\n"); + return ret; } return 0; - -err_phy: - while (--i >= 0) { - phy_power_off(dra7xx->phy[i]); - phy_exit(dra7xx->phy[i]); - } - - return ret; } #endif diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/dwc/pci-exynos.c index f1c544bb8b68..0295ec96f3d0 100644 --- a/drivers/pci/host/pci-exynos.c +++ b/drivers/pci/dwc/pci-exynos.c @@ -26,10 +26,10 @@ #include "pcie-designware.h" -#define to_exynos_pcie(x) container_of(x, struct exynos_pcie, pp) +#define to_exynos_pcie(x) dev_get_drvdata((x)->dev) struct exynos_pcie { - struct pcie_port pp; + struct dw_pcie *pci; void __iomem *elbi_base; /* DT 0th resource */ void __iomem *phy_base; /* DT 1st resource */ void __iomem *block_base; /* DT 2nd resource */ @@ -297,8 +297,8 @@ static void exynos_pcie_init_phy(struct exynos_pcie *exynos_pcie) static void exynos_pcie_assert_reset(struct exynos_pcie *exynos_pcie) { - struct pcie_port *pp = &exynos_pcie->pp; - struct device *dev = pp->dev; + struct dw_pcie *pci = exynos_pcie->pci; + struct device *dev = pci->dev; if (exynos_pcie->reset_gpio >= 0) devm_gpio_request_one(dev, exynos_pcie->reset_gpio, @@ -307,11 +307,12 @@ static void exynos_pcie_assert_reset(struct exynos_pcie *exynos_pcie) static int exynos_pcie_establish_link(struct exynos_pcie *exynos_pcie) { - struct pcie_port *pp = &exynos_pcie->pp; - struct device *dev = pp->dev; + struct dw_pcie *pci = exynos_pcie->pci; + struct pcie_port *pp = &pci->pp; + struct device *dev = pci->dev; u32 val; - if (dw_pcie_link_up(pp)) { + if (dw_pcie_link_up(pci)) { dev_err(dev, "Link already up\n"); return 0; } @@ -336,7 +337,7 @@ static int exynos_pcie_establish_link(struct exynos_pcie *exynos_pcie) PCIE_APP_LTSSM_ENABLE); /* check if the link is up or not */ - if (!dw_pcie_wait_for_link(pp)) + if (!dw_pcie_wait_for_link(pci)) return 0; while (exynos_phy_readl(exynos_pcie, PCIE_PHY_PLL_LOCKED) == 0) { @@ -376,14 +377,16 @@ static irqreturn_t exynos_pcie_irq_handler(int irq, void *arg) 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; + struct dw_pcie *pci = exynos_pcie->pci; + struct pcie_port *pp = &pci->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; + struct dw_pcie *pci = exynos_pcie->pci; + struct pcie_port *pp = &pci->pp; u32 val; dw_pcie_msi_init(pp); @@ -402,34 +405,35 @@ static void exynos_pcie_enable_interrupts(struct exynos_pcie *exynos_pcie) exynos_pcie_msi_init(exynos_pcie); } -static u32 exynos_pcie_readl_rc(struct pcie_port *pp, u32 reg) +static u32 exynos_pcie_readl_dbi(struct dw_pcie *pci, u32 reg) { - struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); + struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci); u32 val; exynos_pcie_sideband_dbi_r_mode(exynos_pcie, true); - val = readl(pp->dbi_base + reg); + val = readl(pci->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) +static void exynos_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val) { - struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); + struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci); exynos_pcie_sideband_dbi_w_mode(exynos_pcie, true); - writel(val, pp->dbi_base + reg); + writel(val, pci->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); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci); int ret; exynos_pcie_sideband_dbi_r_mode(exynos_pcie, true); - ret = dw_pcie_cfg_read(pp->dbi_base + where, size, val); + ret = dw_pcie_read(pci->dbi_base + where, size, val); exynos_pcie_sideband_dbi_r_mode(exynos_pcie, false); return ret; } @@ -437,18 +441,19 @@ static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, 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); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci); int ret; exynos_pcie_sideband_dbi_w_mode(exynos_pcie, true); - ret = dw_pcie_cfg_write(pp->dbi_base + where, size, val); + ret = dw_pcie_write(pci->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) +static int exynos_pcie_link_up(struct dw_pcie *pci) { - struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); + struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci); u32 val; val = exynos_elb_readl(exynos_pcie, PCIE_ELBI_RDLH_LINKUP); @@ -460,26 +465,25 @@ static int exynos_pcie_link_up(struct pcie_port *pp) static void exynos_pcie_host_init(struct pcie_port *pp) { - struct exynos_pcie *exynos_pcie = to_exynos_pcie(pp); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct exynos_pcie *exynos_pcie = to_exynos_pcie(pci); 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, +static struct dw_pcie_host_ops exynos_pcie_host_ops = { .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; + struct dw_pcie *pci = exynos_pcie->pci; + struct pcie_port *pp = &pci->pp; + struct device *dev = &pdev->dev; int ret; pp->irq = platform_get_irq(pdev, 1); @@ -523,11 +527,17 @@ static int __init exynos_add_pcie_port(struct exynos_pcie *exynos_pcie, return 0; } +static const struct dw_pcie_ops dw_pcie_ops = { + .readl_dbi = exynos_pcie_readl_dbi, + .writel_dbi = exynos_pcie_writel_dbi, + .link_up = exynos_pcie_link_up, +}; + static int __init exynos_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct dw_pcie *pci; struct exynos_pcie *exynos_pcie; - struct pcie_port *pp; struct device_node *np = dev->of_node; struct resource *elbi_base; struct resource *phy_base; @@ -538,8 +548,12 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) if (!exynos_pcie) return -ENOMEM; - pp = &exynos_pcie->pp; - pp->dev = dev; + pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); + if (!pci) + return -ENOMEM; + + pci->dev = dev; + pci->ops = &dw_pcie_ops; exynos_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); @@ -583,11 +597,12 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) goto fail_bus_clk; } + platform_set_drvdata(pdev, exynos_pcie); + 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: diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c index c8cefb078218..70fa380ea077 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/dwc/pci-imx6.c @@ -30,7 +30,7 @@ #include "pcie-designware.h" -#define to_imx6_pcie(x) container_of(x, struct imx6_pcie, pp) +#define to_imx6_pcie(x) dev_get_drvdata((x)->dev) enum imx6_pcie_variants { IMX6Q, @@ -39,7 +39,7 @@ enum imx6_pcie_variants { }; struct imx6_pcie { - struct pcie_port pp; /* pp.dbi_base is DT 0th resource */ + struct dw_pcie *pci; int reset_gpio; bool gpio_active_high; struct clk *pcie_bus; @@ -97,13 +97,13 @@ struct imx6_pcie { static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, int exp_val) { - struct pcie_port *pp = &imx6_pcie->pp; + struct dw_pcie *pci = imx6_pcie->pci; u32 val; u32 max_iterations = 10; u32 wait_counter = 0; do { - val = dw_pcie_readl_rc(pp, PCIE_PHY_STAT); + val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT); val = (val >> PCIE_PHY_STAT_ACK_LOC) & 0x1; wait_counter++; @@ -118,22 +118,22 @@ static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, int exp_val) static int pcie_phy_wait_ack(struct imx6_pcie *imx6_pcie, int addr) { - struct pcie_port *pp = &imx6_pcie->pp; + struct dw_pcie *pci = imx6_pcie->pci; u32 val; int ret; val = addr << PCIE_PHY_CTRL_DATA_LOC; - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, val); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val); val |= (0x1 << PCIE_PHY_CTRL_CAP_ADR_LOC); - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, val); + dw_pcie_writel_dbi(pci, 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); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, val); return pcie_phy_poll_ack(imx6_pcie, 0); } @@ -141,7 +141,7 @@ static int pcie_phy_wait_ack(struct imx6_pcie *imx6_pcie, int addr) /* 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; + struct dw_pcie *pci = imx6_pcie->pci; u32 val, phy_ctl; int ret; @@ -151,24 +151,24 @@ static int pcie_phy_read(struct imx6_pcie *imx6_pcie, int addr, int *data) /* assert Read signal */ phy_ctl = 0x1 << PCIE_PHY_CTRL_RD_LOC; - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, phy_ctl); + dw_pcie_writel_dbi(pci, 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); + val = dw_pcie_readl_dbi(pci, PCIE_PHY_STAT); *data = val & 0xffff; /* deassert Read signal */ - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, 0x00); + dw_pcie_writel_dbi(pci, 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; + struct dw_pcie *pci = imx6_pcie->pci; u32 var; int ret; @@ -179,11 +179,11 @@ static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data) return ret; var = data << PCIE_PHY_CTRL_DATA_LOC; - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var); /* capture data */ var |= (0x1 << PCIE_PHY_CTRL_CAP_DAT_LOC); - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var); ret = pcie_phy_poll_ack(imx6_pcie, 1); if (ret) @@ -191,7 +191,7 @@ static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data) /* deassert cap data */ var = data << PCIE_PHY_CTRL_DATA_LOC; - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var); /* wait for ack de-assertion */ ret = pcie_phy_poll_ack(imx6_pcie, 0); @@ -200,7 +200,7 @@ static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data) /* assert wr signal */ var = 0x1 << PCIE_PHY_CTRL_WR_LOC; - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, var); /* wait for ack */ ret = pcie_phy_poll_ack(imx6_pcie, 1); @@ -209,14 +209,14 @@ static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, int data) /* deassert wr signal */ var = data << PCIE_PHY_CTRL_DATA_LOC; - dw_pcie_writel_rc(pp, PCIE_PHY_CTRL, var); + dw_pcie_writel_dbi(pci, 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); + dw_pcie_writel_dbi(pci, PCIE_PHY_CTRL, 0x0); return 0; } @@ -247,7 +247,7 @@ static int imx6q_pcie_abort_handler(unsigned long addr, static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) { - struct pcie_port *pp = &imx6_pcie->pp; + struct dw_pcie *pci = imx6_pcie->pci; u32 val, gpr1, gpr12; switch (imx6_pcie->variant) { @@ -284,10 +284,10 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) if ((gpr1 & IMX6Q_GPR1_PCIE_REF_CLK_EN) && (gpr12 & IMX6Q_GPR12_PCIE_CTL_2)) { - val = dw_pcie_readl_rc(pp, PCIE_PL_PFLR); + val = dw_pcie_readl_dbi(pci, 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); + dw_pcie_writel_dbi(pci, PCIE_PL_PFLR, val); regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX6Q_GPR12_PCIE_CTL_2, 0 << 10); @@ -303,8 +303,8 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie) static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) { - struct pcie_port *pp = &imx6_pcie->pp; - struct device *dev = pp->dev; + struct dw_pcie *pci = imx6_pcie->pci; + struct device *dev = pci->dev; int ret = 0; switch (imx6_pcie->variant) { @@ -340,8 +340,8 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie) static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie) { - struct pcie_port *pp = &imx6_pcie->pp; - struct device *dev = pp->dev; + struct dw_pcie *pci = imx6_pcie->pci; + struct device *dev = pci->dev; int ret; ret = clk_prepare_enable(imx6_pcie->pcie_phy); @@ -440,28 +440,28 @@ static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie) static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie) { - struct pcie_port *pp = &imx6_pcie->pp; - struct device *dev = pp->dev; + struct dw_pcie *pci = imx6_pcie->pci; + struct device *dev = pci->dev; /* check if the link is up or not */ - if (!dw_pcie_wait_for_link(pp)) + if (!dw_pcie_wait_for_link(pci)) 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)); + dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0), + dw_pcie_readl_dbi(pci, 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; + struct dw_pcie *pci = imx6_pcie->pci; + struct device *dev = pci->dev; u32 tmp; unsigned int retries; for (retries = 0; retries < 200; retries++) { - tmp = dw_pcie_readl_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL); + tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); /* Test if the speed change finished. */ if (!(tmp & PORT_LOGIC_SPEED_CHANGE)) return 0; @@ -475,15 +475,16 @@ static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie) static irqreturn_t imx6_pcie_msi_handler(int irq, void *arg) { struct imx6_pcie *imx6_pcie = arg; - struct pcie_port *pp = &imx6_pcie->pp; + struct dw_pcie *pci = imx6_pcie->pci; + struct pcie_port *pp = &pci->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; + struct dw_pcie *pci = imx6_pcie->pci; + struct device *dev = pci->dev; u32 tmp; int ret; @@ -492,10 +493,10 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) * 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 = dw_pcie_readl_dbi(pci, 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); + dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); /* Start LTSSM. */ regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, @@ -509,10 +510,10 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) if (imx6_pcie->link_gen == 2) { /* Allow Gen2 mode after the link is up. */ - tmp = dw_pcie_readl_rc(pp, PCIE_RC_LCR); + tmp = dw_pcie_readl_dbi(pci, 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); + dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); } else { dev_info(dev, "Link: Gen2 disabled\n"); } @@ -521,9 +522,9 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) * 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 = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); tmp |= PORT_LOGIC_SPEED_CHANGE; - dw_pcie_writel_rc(pp, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); + dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp); ret = imx6_pcie_wait_for_speed_change(imx6_pcie); if (ret) { @@ -538,21 +539,22 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) goto err_reset_phy; } - tmp = dw_pcie_readl_rc(pp, PCIE_RC_LCSR); + tmp = dw_pcie_readl_dbi(pci, 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)); + dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0), + dw_pcie_readl_dbi(pci, 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); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci); imx6_pcie_assert_core_reset(imx6_pcie); imx6_pcie_init_phy(imx6_pcie); @@ -564,22 +566,22 @@ static void imx6_pcie_host_init(struct pcie_port *pp) dw_pcie_msi_init(pp); } -static int imx6_pcie_link_up(struct pcie_port *pp) +static int imx6_pcie_link_up(struct dw_pcie *pci) { - return dw_pcie_readl_rc(pp, PCIE_PHY_DEBUG_R1) & + return dw_pcie_readl_dbi(pci, 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, +static struct dw_pcie_host_ops imx6_pcie_host_ops = { .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; + struct dw_pcie *pci = imx6_pcie->pci; + struct pcie_port *pp = &pci->pp; + struct device *dev = &pdev->dev; int ret; if (IS_ENABLED(CONFIG_PCI_MSI)) { @@ -611,11 +613,15 @@ static int __init imx6_add_pcie_port(struct imx6_pcie *imx6_pcie, return 0; } +static const struct dw_pcie_ops dw_pcie_ops = { + .link_up = imx6_pcie_link_up, +}; + static int __init imx6_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct dw_pcie *pci; struct imx6_pcie *imx6_pcie; - struct pcie_port *pp; struct resource *dbi_base; struct device_node *node = dev->of_node; int ret; @@ -624,8 +630,12 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) if (!imx6_pcie) return -ENOMEM; - pp = &imx6_pcie->pp; - pp->dev = dev; + pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); + if (!pci) + return -ENOMEM; + + pci->dev = dev; + pci->ops = &dw_pcie_ops; imx6_pcie->variant = (enum imx6_pcie_variants)of_device_get_match_data(dev); @@ -635,9 +645,9 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) "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); + pci->dbi_base = devm_ioremap_resource(dev, dbi_base); + if (IS_ERR(pci->dbi_base)) + return PTR_ERR(pci->dbi_base); /* Fetch GPIOs */ imx6_pcie->reset_gpio = of_get_named_gpio(node, "reset-gpio", 0); @@ -719,11 +729,12 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) if (ret) imx6_pcie->link_gen = 1; + platform_set_drvdata(pdev, imx6_pcie); + ret = imx6_add_pcie_port(imx6_pcie, pdev); if (ret < 0) return ret; - platform_set_drvdata(pdev, imx6_pcie); return 0; } diff --git a/drivers/pci/host/pci-keystone-dw.c b/drivers/pci/dwc/pci-keystone-dw.c index 9397c4667106..6b396f6b4615 100644 --- a/drivers/pci/host/pci-keystone-dw.c +++ b/drivers/pci/dwc/pci-keystone-dw.c @@ -72,7 +72,7 @@ /* Config space registers */ #define DEBUG0 0x728 -#define to_keystone_pcie(x) container_of(x, struct keystone_pcie, pp) +#define to_keystone_pcie(x) dev_get_drvdata((x)->dev) static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset, u32 *bit_pos) @@ -83,7 +83,8 @@ static inline void update_reg_offset_bit_pos(u32 offset, u32 *reg_offset, phys_addr_t ks_dw_pcie_get_msi_addr(struct pcie_port *pp) { - struct keystone_pcie *ks_pcie = to_keystone_pcie(pp); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); return ks_pcie->app.start + MSI_IRQ; } @@ -100,8 +101,9 @@ static void ks_dw_app_writel(struct keystone_pcie *ks_pcie, u32 offset, u32 val) 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; + struct dw_pcie *pci = ks_pcie->pci; + struct pcie_port *pp = &pci->pp; + struct device *dev = pci->dev; u32 pending, vector; int src, virq; @@ -128,10 +130,12 @@ static void ks_dw_pcie_msi_irq_ack(struct irq_data *d) struct keystone_pcie *ks_pcie; struct msi_desc *msi; struct pcie_port *pp; + struct dw_pcie *pci; msi = irq_data_get_msi_desc(d); pp = (struct pcie_port *) msi_desc_to_pci_sysdata(msi); - ks_pcie = to_keystone_pcie(pp); + pci = to_dw_pcie_from_pp(pp); + ks_pcie = to_keystone_pcie(pci); offset = d->irq - irq_linear_revmap(pp->irq_domain, 0); update_reg_offset_bit_pos(offset, ®_offset, &bit_pos); @@ -143,7 +147,8 @@ static void ks_dw_pcie_msi_irq_ack(struct irq_data *d) 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); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); update_reg_offset_bit_pos(irq, ®_offset, &bit_pos); ks_dw_app_writel(ks_pcie, MSI0_IRQ_ENABLE_SET + (reg_offset << 4), @@ -153,7 +158,8 @@ 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) { u32 reg_offset, bit_pos; - struct keystone_pcie *ks_pcie = to_keystone_pcie(pp); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); update_reg_offset_bit_pos(irq, ®_offset, &bit_pos); ks_dw_app_writel(ks_pcie, MSI0_IRQ_ENABLE_CLR + (reg_offset << 4), @@ -165,11 +171,13 @@ 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; + struct dw_pcie *pci; 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); + pci = to_dw_pcie_from_pp(pp); + ks_pcie = to_keystone_pcie(pci); offset = d->irq - irq_linear_revmap(pp->irq_domain, 0); /* Mask the end point if PVM implemented */ @@ -186,11 +194,13 @@ 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; + struct dw_pcie *pci; 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); + pci = to_dw_pcie_from_pp(pp); + ks_pcie = to_keystone_pcie(pci); offset = d->irq - irq_linear_revmap(pp->irq_domain, 0); /* Mask the end point if PVM implemented */ @@ -225,8 +235,9 @@ static const struct irq_domain_ops ks_dw_pcie_msi_domain_ops = { 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; + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); + struct device *dev = pci->dev; int i; pp->irq_domain = irq_domain_add_linear(ks_pcie->msi_intc_np, @@ -254,8 +265,8 @@ 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) { - struct pcie_port *pp = &ks_pcie->pp; - struct device *dev = pp->dev; + struct dw_pcie *pci = ks_pcie->pci; + struct device *dev = pci->dev; u32 pending; int virq; @@ -285,7 +296,7 @@ irqreturn_t ks_dw_pcie_handle_error_irq(struct keystone_pcie *ks_pcie) return IRQ_NONE; if (status & ERR_FATAL_IRQ) - dev_err(ks_pcie->pp.dev, "fatal error (status %#010x)\n", + dev_err(ks_pcie->pci->dev, "fatal error (status %#010x)\n", status); /* Ack the IRQ; status bits are RW1C */ @@ -366,15 +377,16 @@ static void ks_dw_pcie_clear_dbi_mode(struct keystone_pcie *ks_pcie) void ks_dw_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie) { - struct pcie_port *pp = &ks_pcie->pp; + struct dw_pcie *pci = ks_pcie->pci; + struct pcie_port *pp = &pci->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); + dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0); + dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0); ks_dw_pcie_clear_dbi_mode(ks_pcie); /* Set outbound translation size per window division */ @@ -415,11 +427,12 @@ 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; + struct dw_pcie *pci = ks_pcie->pci; + struct pcie_port *pp = &pci->pp; u32 regval; if (bus == 0) - return pp->dbi_base; + return pci->dbi_base; regval = (bus << 16) | (device << 8) | function; @@ -438,25 +451,27 @@ static void __iomem *ks_pcie_cfg_setup(struct keystone_pcie *ks_pcie, u8 bus, 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); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); 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); + return dw_pcie_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); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); 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); + return dw_pcie_write(addr + where, size, val); } /** @@ -466,14 +481,15 @@ int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, */ void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp) { - struct keystone_pcie *ks_pcie = to_keystone_pcie(pp); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); /* 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); + dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 1); + dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, SZ_4K - 1); ks_dw_pcie_clear_dbi_mode(ks_pcie); @@ -481,17 +497,17 @@ void ks_dw_pcie_v3_65_scan_bus(struct pcie_port *pp) * 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); + dw_pcie_writel_dbi(pci, 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) +int ks_dw_pcie_link_up(struct dw_pcie *pci) { u32 val; - val = dw_pcie_readl_rc(pp, DEBUG0); + val = dw_pcie_readl_dbi(pci, DEBUG0); return (val & LTSSM_STATE_MASK) == LTSSM_STATE_L0; } @@ -519,22 +535,23 @@ void ks_dw_pcie_initiate_link_train(struct keystone_pcie *ks_pcie) 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 dw_pcie *pci = ks_pcie->pci; + struct pcie_port *pp = &pci->pp; + struct device *dev = pci->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); + pci->dbi_base = devm_ioremap_resource(dev, res); + if (IS_ERR(pci->dbi_base)) + return PTR_ERR(pci->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_cfg0_base = pci->dbi_base + SPACE0_REMOTE_CFG_OFFSET; pp->va_cfg1_base = pp->va_cfg0_base; /* Index 1 is the application reg. space address */ diff --git a/drivers/pci/host/pci-keystone.c b/drivers/pci/dwc/pci-keystone.c index 043c19a05da1..8dc66409182d 100644 --- a/drivers/pci/host/pci-keystone.c +++ b/drivers/pci/dwc/pci-keystone.c @@ -44,7 +44,7 @@ #define PCIE_RC_K2E 0xb009 #define PCIE_RC_K2L 0xb00a -#define to_keystone_pcie(x) container_of(x, struct keystone_pcie, pp) +#define to_keystone_pcie(x) dev_get_drvdata((x)->dev) static void quirk_limit_mrrs(struct pci_dev *dev) { @@ -88,13 +88,14 @@ 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; + struct dw_pcie *pci = ks_pcie->pci; + struct pcie_port *pp = &pci->pp; + struct device *dev = pci->dev; unsigned int retries; dw_pcie_setup_rc(pp); - if (dw_pcie_link_up(pp)) { + if (dw_pcie_link_up(pci)) { dev_err(dev, "Link already up\n"); return 0; } @@ -102,7 +103,7 @@ static int ks_pcie_establish_link(struct keystone_pcie *ks_pcie) /* 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)) + if (!dw_pcie_wait_for_link(pci)) return 0; } @@ -115,8 +116,8 @@ 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 dw_pcie *pci = ks_pcie->pci; + struct device *dev = pci->dev; struct irq_chip *chip = irq_desc_get_chip(desc); dev_dbg(dev, "%s, irq %d\n", __func__, irq); @@ -143,8 +144,8 @@ 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; + struct dw_pcie *pci = ks_pcie->pci; + struct device *dev = pci->dev; u32 irq_offset = irq - ks_pcie->legacy_host_irqs[0]; struct irq_chip *chip = irq_desc_get_chip(desc); @@ -164,7 +165,7 @@ 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 *dev = ks_pcie->pci->dev; struct device_node *np_pcie = dev->of_node, **np_temp; if (!strcmp(controller, "msi-interrupt-controller")) @@ -262,24 +263,25 @@ static int keystone_pcie_fault(unsigned long addr, unsigned int fsr, static void __init ks_pcie_host_init(struct pcie_port *pp) { - struct keystone_pcie *ks_pcie = to_keystone_pcie(pp); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct keystone_pcie *ks_pcie = to_keystone_pcie(pci); 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); + pci->dbi_base + PCI_IO_BASE); /* update the Vendor ID */ - writew(ks_pcie->device_id, pp->dbi_base + PCI_DEVICE_ID); + writew(ks_pcie->device_id, pci->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 = readl(pci->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); + writel(val, pci->dbi_base + PCIE_CAP_BASE + PCI_EXP_DEVCTL); /* * PCIe access errors that result into OCP errors are caught by ARM as @@ -289,10 +291,9 @@ static void __init ks_pcie_host_init(struct pcie_port *pp) "Asynchronous external abort"); } -static struct pcie_host_ops keystone_pcie_host_ops = { +static struct dw_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, @@ -311,8 +312,9 @@ static irqreturn_t pcie_err_irq_handler(int irq, void *priv) 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; + struct dw_pcie *pci = ks_pcie->pci; + struct pcie_port *pp = &pci->pp; + struct device *dev = &pdev->dev; int ret; ret = ks_pcie_get_irq_controller_info(ks_pcie, @@ -365,6 +367,10 @@ static const struct of_device_id ks_pcie_of_match[] = { { }, }; +static const struct dw_pcie_ops dw_pcie_ops = { + .link_up = ks_dw_pcie_link_up, +}; + static int __exit ks_pcie_remove(struct platform_device *pdev) { struct keystone_pcie *ks_pcie = platform_get_drvdata(pdev); @@ -377,8 +383,8 @@ static int __exit ks_pcie_remove(struct platform_device *pdev) static int __init ks_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct dw_pcie *pci; struct keystone_pcie *ks_pcie; - struct pcie_port *pp; struct resource *res; void __iomem *reg_p; struct phy *phy; @@ -388,8 +394,12 @@ static int __init ks_pcie_probe(struct platform_device *pdev) if (!ks_pcie) return -ENOMEM; - pp = &ks_pcie->pp; - pp->dev = dev; + pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); + if (!pci) + return -ENOMEM; + + pci->dev = dev; + pci->ops = &dw_pcie_ops; /* initialize SerDes Phy if present */ phy = devm_phy_get(dev, "pcie-phy"); @@ -422,6 +432,8 @@ static int __init ks_pcie_probe(struct platform_device *pdev) if (ret) return ret; + platform_set_drvdata(pdev, ks_pcie); + ret = ks_add_pcie_port(ks_pcie, pdev); if (ret < 0) goto fail_clk; diff --git a/drivers/pci/host/pci-keystone.h b/drivers/pci/dwc/pci-keystone.h index bc54bafda068..74c5825882df 100644 --- a/drivers/pci/host/pci-keystone.h +++ b/drivers/pci/dwc/pci-keystone.h @@ -17,7 +17,7 @@ #define MAX_LEGACY_HOST_IRQS 4 struct keystone_pcie { - struct pcie_port pp; /* pp.dbi_base is DT 0th res */ + struct dw_pcie *pci; struct clk *clk; /* PCI Device ID */ u32 device_id; @@ -54,10 +54,10 @@ int ks_dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, 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); +int ks_dw_pcie_link_up(struct dw_pcie *pci); diff --git a/drivers/pci/host/pci-layerscape.c b/drivers/pci/dwc/pci-layerscape.c index ea789138531b..f69d2fe6b84c 100644 --- a/drivers/pci/host/pci-layerscape.c +++ b/drivers/pci/dwc/pci-layerscape.c @@ -39,24 +39,26 @@ struct ls_pcie_drvdata { u32 lut_offset; u32 ltssm_shift; u32 lut_dbg; - struct pcie_host_ops *ops; + struct dw_pcie_host_ops *ops; + const struct dw_pcie_ops *dw_pcie_ops; }; struct ls_pcie { - struct pcie_port pp; /* pp.dbi_base is DT regs */ + struct dw_pcie *pci; 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) +#define to_ls_pcie(x) dev_get_drvdata((x)->dev) static bool ls_pcie_is_bridge(struct ls_pcie *pcie) { + struct dw_pcie *pci = pcie->pci; u32 header_type; - header_type = ioread8(pcie->pp.dbi_base + PCI_HEADER_TYPE); + header_type = ioread8(pci->dbi_base + PCI_HEADER_TYPE); header_type &= 0x7f; return header_type == PCI_HEADER_TYPE_BRIDGE; @@ -65,29 +67,34 @@ static bool ls_pcie_is_bridge(struct ls_pcie *pcie) /* 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); + struct dw_pcie *pci = pcie->pci; + + iowrite8(PCI_HEADER_TYPE_BRIDGE, pci->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); + struct dw_pcie *pci = pcie->pci; + + iowrite16(PCI_CLASS_BRIDGE_PCI, pci->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; + struct dw_pcie *pci = pcie->pci; - val = ioread32(pcie->pp.dbi_base + PCIE_STRFMR1); + val = ioread32(pci->dbi_base + PCIE_STRFMR1); val &= 0xDFFFFFFF; - iowrite32(val, pcie->pp.dbi_base + PCIE_STRFMR1); + iowrite32(val, pci->dbi_base + PCIE_STRFMR1); } -static int ls1021_pcie_link_up(struct pcie_port *pp) +static int ls1021_pcie_link_up(struct dw_pcie *pci) { u32 state; - struct ls_pcie *pcie = to_ls_pcie(pp); + struct ls_pcie *pcie = to_ls_pcie(pci); if (!pcie->scfg) return 0; @@ -103,8 +110,9 @@ static int ls1021_pcie_link_up(struct pcie_port *pp) static void ls1021_pcie_host_init(struct pcie_port *pp) { - struct device *dev = pp->dev; - struct ls_pcie *pcie = to_ls_pcie(pp); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct ls_pcie *pcie = to_ls_pcie(pci); + struct device *dev = pci->dev; u32 index[2]; pcie->scfg = syscon_regmap_lookup_by_phandle(dev->of_node, @@ -127,9 +135,9 @@ static void ls1021_pcie_host_init(struct pcie_port *pp) ls_pcie_drop_msg_tlp(pcie); } -static int ls_pcie_link_up(struct pcie_port *pp) +static int ls_pcie_link_up(struct dw_pcie *pci) { - struct ls_pcie *pcie = to_ls_pcie(pp); + struct ls_pcie *pcie = to_ls_pcie(pci); u32 state; state = (ioread32(pcie->lut + pcie->drvdata->lut_dbg) >> @@ -144,19 +152,21 @@ static int ls_pcie_link_up(struct pcie_port *pp) static void ls_pcie_host_init(struct pcie_port *pp) { - struct ls_pcie *pcie = to_ls_pcie(pp); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct ls_pcie *pcie = to_ls_pcie(pci); - iowrite32(1, pcie->pp.dbi_base + PCIE_DBI_RO_WR_EN); + iowrite32(1, pci->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); + iowrite32(0, pci->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 dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct device *dev = pci->dev; struct device_node *np = dev->of_node; struct device_node *msi_node; @@ -175,20 +185,27 @@ static int ls_pcie_msi_host_init(struct pcie_port *pp, return 0; } -static struct pcie_host_ops ls1021_pcie_host_ops = { - .link_up = ls1021_pcie_link_up, +static struct dw_pcie_host_ops ls1021_pcie_host_ops = { .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, +static struct dw_pcie_host_ops ls_pcie_host_ops = { .host_init = ls_pcie_host_init, .msi_host_init = ls_pcie_msi_host_init, }; +static const struct dw_pcie_ops dw_ls1021_pcie_ops = { + .link_up = ls1021_pcie_link_up, +}; + +static const struct dw_pcie_ops dw_ls_pcie_ops = { + .link_up = ls_pcie_link_up, +}; + static struct ls_pcie_drvdata ls1021_drvdata = { .ops = &ls1021_pcie_host_ops, + .dw_pcie_ops = &dw_ls1021_pcie_ops, }; static struct ls_pcie_drvdata ls1043_drvdata = { @@ -196,6 +213,7 @@ static struct ls_pcie_drvdata ls1043_drvdata = { .ltssm_shift = 24, .lut_dbg = 0x7fc, .ops = &ls_pcie_host_ops, + .dw_pcie_ops = &dw_ls_pcie_ops, }; static struct ls_pcie_drvdata ls1046_drvdata = { @@ -203,6 +221,7 @@ static struct ls_pcie_drvdata ls1046_drvdata = { .ltssm_shift = 24, .lut_dbg = 0x407fc, .ops = &ls_pcie_host_ops, + .dw_pcie_ops = &dw_ls_pcie_ops, }; static struct ls_pcie_drvdata ls2080_drvdata = { @@ -210,6 +229,7 @@ static struct ls_pcie_drvdata ls2080_drvdata = { .ltssm_shift = 0, .lut_dbg = 0x7fc, .ops = &ls_pcie_host_ops, + .dw_pcie_ops = &dw_ls_pcie_ops, }; static const struct of_device_id ls_pcie_of_match[] = { @@ -223,10 +243,13 @@ static const struct of_device_id ls_pcie_of_match[] = { static int __init ls_add_pcie_port(struct ls_pcie *pcie) { - struct pcie_port *pp = &pcie->pp; - struct device *dev = pp->dev; + struct dw_pcie *pci = pcie->pci; + struct pcie_port *pp = &pci->pp; + struct device *dev = pci->dev; int ret; + pp->ops = pcie->drvdata->ops; + ret = dw_pcie_host_init(pp); if (ret) { dev_err(dev, "failed to initialize host\n"); @@ -240,8 +263,8 @@ static int __init ls_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; const struct of_device_id *match; + struct dw_pcie *pci; struct ls_pcie *pcie; - struct pcie_port *pp; struct resource *dbi_base; int ret; @@ -253,21 +276,27 @@ static int __init ls_pcie_probe(struct platform_device *pdev) if (!pcie) return -ENOMEM; - pp = &pcie->pp; - pp->dev = dev; + pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); + if (!pci) + return -ENOMEM; + pcie->drvdata = match->data; - pp->ops = pcie->drvdata->ops; + + pci->dev = dev; + pci->ops = pcie->drvdata->dw_pcie_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); + pci->dbi_base = devm_ioremap_resource(dev, dbi_base); + if (IS_ERR(pci->dbi_base)) + return PTR_ERR(pci->dbi_base); - pcie->lut = pcie->pp.dbi_base + pcie->drvdata->lut_offset; + pcie->lut = pci->dbi_base + pcie->drvdata->lut_offset; if (!ls_pcie_is_bridge(pcie)) return -ENODEV; + platform_set_drvdata(pdev, pcie); + ret = ls_add_pcie_port(pcie); if (ret < 0) return ret; diff --git a/drivers/pci/host/pcie-armada8k.c b/drivers/pci/dwc/pcie-armada8k.c index 0ac0f18690f2..66bac6fbfa9f 100644 --- a/drivers/pci/host/pcie-armada8k.c +++ b/drivers/pci/dwc/pcie-armada8k.c @@ -29,7 +29,7 @@ #include "pcie-designware.h" struct armada8k_pcie { - struct pcie_port pp; /* pp.dbi_base is DT ctrl */ + struct dw_pcie *pci; struct clk *clk; }; @@ -67,76 +67,77 @@ struct armada8k_pcie { #define AX_USER_DOMAIN_MASK 0x3 #define AX_USER_DOMAIN_SHIFT 4 -#define to_armada8k_pcie(x) container_of(x, struct armada8k_pcie, pp) +#define to_armada8k_pcie(x) dev_get_drvdata((x)->dev) -static int armada8k_pcie_link_up(struct pcie_port *pp) +static int armada8k_pcie_link_up(struct dw_pcie *pci) { 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); + reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_STATUS_REG); if ((reg & mask) == mask) return 1; - dev_dbg(pp->dev, "No link detected (Global-Status: 0x%08x).\n", reg); + dev_dbg(pci->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; + struct dw_pcie *pci = pcie->pci; u32 reg; - if (!dw_pcie_link_up(pp)) { + if (!dw_pcie_link_up(pci)) { /* Disable LTSSM state machine to enable configuration */ - reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_CONTROL_REG); + reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG); reg &= ~(PCIE_APP_LTSSM_EN); - dw_pcie_writel_rc(pp, PCIE_GLOBAL_CONTROL_REG, reg); + dw_pcie_writel_dbi(pci, PCIE_GLOBAL_CONTROL_REG, reg); } /* Set the device to root complex mode */ - reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_CONTROL_REG); + reg = dw_pcie_readl_dbi(pci, 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); + dw_pcie_writel_dbi(pci, 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); + dw_pcie_writel_dbi(pci, PCIE_ARCACHE_TRC_REG, ARCACHE_DEFAULT_VALUE); + dw_pcie_writel_dbi(pci, PCIE_AWCACHE_TRC_REG, AWCACHE_DEFAULT_VALUE); /* Set the PCIe master AxDomain attributes */ - reg = dw_pcie_readl_rc(pp, PCIE_ARUSER_REG); + reg = dw_pcie_readl_dbi(pci, 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); + dw_pcie_writel_dbi(pci, PCIE_ARUSER_REG, reg); - reg = dw_pcie_readl_rc(pp, PCIE_AWUSER_REG); + reg = dw_pcie_readl_dbi(pci, 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); + dw_pcie_writel_dbi(pci, PCIE_AWUSER_REG, reg); /* Enable INT A-D interrupts */ - reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_INT_MASK1_REG); + reg = dw_pcie_readl_dbi(pci, 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); + dw_pcie_writel_dbi(pci, PCIE_GLOBAL_INT_MASK1_REG, reg); - if (!dw_pcie_link_up(pp)) { + if (!dw_pcie_link_up(pci)) { /* Configuration done. Start LTSSM */ - reg = dw_pcie_readl_rc(pp, PCIE_GLOBAL_CONTROL_REG); + reg = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_CONTROL_REG); reg |= PCIE_APP_LTSSM_EN; - dw_pcie_writel_rc(pp, PCIE_GLOBAL_CONTROL_REG, reg); + dw_pcie_writel_dbi(pci, 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"); + if (dw_pcie_wait_for_link(pci)) + dev_err(pci->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); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct armada8k_pcie *pcie = to_armada8k_pcie(pci); dw_pcie_setup_rc(pp); armada8k_pcie_establish_link(pcie); @@ -145,7 +146,7 @@ static void armada8k_pcie_host_init(struct pcie_port *pp) static irqreturn_t armada8k_pcie_irq_handler(int irq, void *arg) { struct armada8k_pcie *pcie = arg; - struct pcie_port *pp = &pcie->pp; + struct dw_pcie *pci = pcie->pci; u32 val; /* @@ -153,21 +154,21 @@ static irqreturn_t armada8k_pcie_irq_handler(int irq, void *arg) * 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); + val = dw_pcie_readl_dbi(pci, PCIE_GLOBAL_INT_CAUSE1_REG); + dw_pcie_writel_dbi(pci, PCIE_GLOBAL_INT_CAUSE1_REG, val); return IRQ_HANDLED; } -static struct pcie_host_ops armada8k_pcie_host_ops = { - .link_up = armada8k_pcie_link_up, +static struct dw_pcie_host_ops armada8k_pcie_host_ops = { .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 dw_pcie *pci = pcie->pci; + struct pcie_port *pp = &pci->pp; struct device *dev = &pdev->dev; int ret; @@ -196,10 +197,14 @@ static int armada8k_add_pcie_port(struct armada8k_pcie *pcie, return 0; } +static const struct dw_pcie_ops dw_pcie_ops = { + .link_up = armada8k_pcie_link_up, +}; + static int armada8k_pcie_probe(struct platform_device *pdev) { + struct dw_pcie *pci; struct armada8k_pcie *pcie; - struct pcie_port *pp; struct device *dev = &pdev->dev; struct resource *base; int ret; @@ -208,24 +213,30 @@ static int armada8k_pcie_probe(struct platform_device *pdev) if (!pcie) return -ENOMEM; + pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); + if (!pci) + return -ENOMEM; + + pci->dev = dev; + pci->ops = &dw_pcie_ops; + 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)) { + pci->dbi_base = devm_ioremap_resource(dev, base); + if (IS_ERR(pci->dbi_base)) { dev_err(dev, "couldn't remap regs base %p\n", base); - ret = PTR_ERR(pp->dbi_base); + ret = PTR_ERR(pci->dbi_base); goto fail; } + platform_set_drvdata(pdev, pcie); + ret = armada8k_add_pcie_port(pcie, pdev); if (ret) goto fail; diff --git a/drivers/pci/host/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c index 212786b27f1a..59ecc9e66436 100644 --- a/drivers/pci/host/pcie-artpec6.c +++ b/drivers/pci/dwc/pcie-artpec6.c @@ -24,10 +24,10 @@ #include "pcie-designware.h" -#define to_artpec6_pcie(x) container_of(x, struct artpec6_pcie, pp) +#define to_artpec6_pcie(x) dev_get_drvdata((x)->dev) struct artpec6_pcie { - struct pcie_port pp; /* pp.dbi_base is DT dbi */ + struct dw_pcie *pci; struct regmap *regmap; /* DT axis,syscon-pcie */ void __iomem *phy_base; /* DT phy */ }; @@ -80,7 +80,8 @@ static void artpec6_pcie_writel(struct artpec6_pcie *artpec6_pcie, u32 offset, u static int artpec6_pcie_establish_link(struct artpec6_pcie *artpec6_pcie) { - struct pcie_port *pp = &artpec6_pcie->pp; + struct dw_pcie *pci = artpec6_pcie->pci; + struct pcie_port *pp = &pci->pp; u32 val; unsigned int retries; @@ -139,7 +140,7 @@ static int artpec6_pcie_establish_link(struct artpec6_pcie *artpec6_pcie) * 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); + dw_pcie_writel_dbi(pci, MISC_CONTROL_1_OFF, DBI_RO_WR_EN); pp->io_base &= ARTPEC6_CPU_TO_BUS_ADDR; pp->mem_base &= ARTPEC6_CPU_TO_BUS_ADDR; @@ -155,19 +156,20 @@ static int artpec6_pcie_establish_link(struct artpec6_pcie *artpec6_pcie) artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); /* check if the link is up or not */ - if (!dw_pcie_wait_for_link(pp)) + if (!dw_pcie_wait_for_link(pci)) 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)); + dev_dbg(pci->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", + dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0), + dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1)); return -ETIMEDOUT; } static void artpec6_pcie_enable_interrupts(struct artpec6_pcie *artpec6_pcie) { - struct pcie_port *pp = &artpec6_pcie->pp; + struct dw_pcie *pci = artpec6_pcie->pci; + struct pcie_port *pp = &pci->pp; if (IS_ENABLED(CONFIG_PCI_MSI)) dw_pcie_msi_init(pp); @@ -175,20 +177,22 @@ static void artpec6_pcie_enable_interrupts(struct artpec6_pcie *artpec6_pcie) static void artpec6_pcie_host_init(struct pcie_port *pp) { - struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pp); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); artpec6_pcie_establish_link(artpec6_pcie); artpec6_pcie_enable_interrupts(artpec6_pcie); } -static struct pcie_host_ops artpec6_pcie_host_ops = { +static struct dw_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; + struct dw_pcie *pci = artpec6_pcie->pci; + struct pcie_port *pp = &pci->pp; return dw_handle_msi_irq(pp); } @@ -196,8 +200,9 @@ static irqreturn_t artpec6_pcie_msi_handler(int irq, void *arg) 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; + struct dw_pcie *pci = artpec6_pcie->pci; + struct pcie_port *pp = &pci->pp; + struct device *dev = pci->dev; int ret; if (IS_ENABLED(CONFIG_PCI_MSI)) { @@ -232,8 +237,8 @@ static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie, static int artpec6_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct dw_pcie *pci; struct artpec6_pcie *artpec6_pcie; - struct pcie_port *pp; struct resource *dbi_base; struct resource *phy_base; int ret; @@ -242,13 +247,16 @@ static int artpec6_pcie_probe(struct platform_device *pdev) if (!artpec6_pcie) return -ENOMEM; - pp = &artpec6_pcie->pp; - pp->dev = dev; + pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); + if (!pci) + return -ENOMEM; + + pci->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); + pci->dbi_base = devm_ioremap_resource(dev, dbi_base); + if (IS_ERR(pci->dbi_base)) + return PTR_ERR(pci->dbi_base); phy_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy"); artpec6_pcie->phy_base = devm_ioremap_resource(dev, phy_base); @@ -261,6 +269,8 @@ static int artpec6_pcie_probe(struct platform_device *pdev) if (IS_ERR(artpec6_pcie->regmap)) return PTR_ERR(artpec6_pcie->regmap); + platform_set_drvdata(pdev, artpec6_pcie); + ret = artpec6_add_pcie_port(artpec6_pcie, pdev); if (ret < 0) return ret; diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/dwc/pcie-designware-host.c index bed19994c1e9..5ba334938b52 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/dwc/pcie-designware-host.c @@ -11,239 +11,38 @@ * 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) { + struct dw_pcie *pci; + 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); + pci = to_dw_pcie_from_pp(pp); + return dw_pcie_read(pci->dbi_base + where, size, val); } static int dw_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, u32 val) { + struct dw_pcie *pci; + 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"); + pci = to_dw_pcie_from_pp(pp); + return dw_pcie_write(pci->dbi_base + where, size, val); } static struct irq_chip dw_msi_irq_chip = { @@ -263,16 +62,15 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) for (i = 0; i < MAX_MSI_CTRLS; i++) { dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4, - (u32 *)&val); + (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); + i * 32 + pos); + dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + + i * 12, 4, 1 << pos); generic_handle_irq(irq); pos++; } @@ -338,8 +136,9 @@ static void dw_pcie_msi_set_irq(struct pcie_port *pp, int irq) 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); + struct pcie_port *pp; + 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) @@ -401,7 +200,7 @@ static void dw_msi_setup_msg(struct pcie_port *pp, unsigned int irq, u32 pos) } static int dw_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev, - struct msi_desc *desc) + struct msi_desc *desc) { int irq, pos; struct pcie_port *pp = pdev->bus->sysdata; @@ -449,7 +248,7 @@ 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); + struct pcie_port *pp = (struct pcie_port *)msi_desc_to_pci_sysdata(msi); clear_irq_range(pp, irq, 1, data->hwirq); } @@ -460,38 +259,8 @@ static struct msi_controller dw_pcie_msi_chip = { .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_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); @@ -503,21 +272,12 @@ 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 dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct device *dev = pci->dev; + struct device_node *np = dev->of_node; + struct platform_device *pdev = to_platform_device(dev); struct pci_bus *bus, *child; struct resource *cfg_res; int i, ret; @@ -526,19 +286,19 @@ int dw_pcie_host_init(struct pcie_port *pp) 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_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"); + dev_err(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); + ret = devm_request_pci_bus_resources(dev, &res); if (ret) goto error; @@ -548,7 +308,7 @@ int dw_pcie_host_init(struct pcie_port *pp) 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", + dev_warn(dev, "error %d: failed to map resource %pR\n", ret, win->res); resource_list_destroy_entry(win); } else { @@ -566,8 +326,8 @@ int dw_pcie_host_init(struct pcie_port *pp) 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_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; @@ -577,11 +337,11 @@ int dw_pcie_host_init(struct pcie_port *pp) } } - if (!pp->dbi_base) { - pp->dbi_base = devm_ioremap(pp->dev, pp->cfg->start, + if (!pci->dbi_base) { + pci->dbi_base = devm_ioremap(dev, pp->cfg->start, resource_size(pp->cfg)); - if (!pp->dbi_base) { - dev_err(pp->dev, "error with ioremap\n"); + if (!pci->dbi_base) { + dev_err(dev, "error with ioremap\n"); ret = -ENOMEM; goto error; } @@ -590,40 +350,36 @@ int dw_pcie_host_init(struct pcie_port *pp) pp->mem_base = pp->mem->start; if (!pp->va_cfg0_base) { - pp->va_cfg0_base = devm_ioremap(pp->dev, pp->cfg0_base, + pp->va_cfg0_base = devm_ioremap(dev, pp->cfg0_base, pp->cfg0_size); if (!pp->va_cfg0_base) { - dev_err(pp->dev, "error with ioremap in function\n"); + dev_err(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->va_cfg1_base = devm_ioremap(dev, pp->cfg1_base, pp->cfg1_size); if (!pp->va_cfg1_base) { - dev_err(pp->dev, "error with ioremap\n"); + dev_err(dev, "error with ioremap\n"); ret = -ENOMEM; goto error; } } - ret = of_property_read_u32(np, "num-lanes", &pp->lanes); + ret = of_property_read_u32(np, "num-viewport", &pci->num_viewport); if (ret) - pp->lanes = 0; - - ret = of_property_read_u32(np, "num-viewport", &pp->num_viewport); - if (ret) - pp->num_viewport = 2; + pci->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, + pp->irq_domain = irq_domain_add_linear(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"); + dev_err(dev, "irq domain init failed\n"); ret = -ENXIO; goto error; } @@ -642,12 +398,12 @@ int dw_pcie_host_init(struct pcie_port *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, + bus = pci_scan_root_bus_msi(dev, pp->root_bus_nr, &dw_pcie_ops, pp, &res, &dw_pcie_msi_chip); - dw_pcie_msi_chip.dev = pp->dev; + dw_pcie_msi_chip.dev = dev; } else - bus = pci_scan_root_bus(pp->dev, pp->root_bus_nr, &dw_pcie_ops, + bus = pci_scan_root_bus(dev, pp->root_bus_nr, &dw_pcie_ops, pp, &res); if (!bus) { ret = -ENOMEM; @@ -677,12 +433,13 @@ error: } static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, - u32 devfn, int where, int size, u32 *val) + u32 devfn, int where, int size, u32 *val) { int ret, type; u32 busdev, cfg_size; u64 cpu_addr; void __iomem *va_cfg_base; + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); if (pp->ops->rd_other_conf) return pp->ops->rd_other_conf(pp, bus, devfn, where, size, val); @@ -702,12 +459,12 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, va_cfg_base = pp->va_cfg1_base; } - dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1, + dw_pcie_prog_outbound_atu(pci, 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, + ret = dw_pcie_read(va_cfg_base + where, size, val); + if (pci->num_viewport <= 2) + dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1, PCIE_ATU_TYPE_IO, pp->io_base, pp->io_bus_addr, pp->io_size); @@ -715,12 +472,13 @@ static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, } static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, - u32 devfn, int where, int size, u32 val) + u32 devfn, int where, int size, u32 val) { int ret, type; u32 busdev, cfg_size; u64 cpu_addr; void __iomem *va_cfg_base; + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); if (pp->ops->wr_other_conf) return pp->ops->wr_other_conf(pp, bus, devfn, where, size, val); @@ -740,12 +498,12 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, va_cfg_base = pp->va_cfg1_base; } - dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX1, + dw_pcie_prog_outbound_atu(pci, 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, + ret = dw_pcie_write(va_cfg_base + where, size, val); + if (pci->num_viewport <= 2) + dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX1, PCIE_ATU_TYPE_IO, pp->io_base, pp->io_bus_addr, pp->io_size); @@ -755,9 +513,11 @@ static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus, static int dw_pcie_valid_device(struct pcie_port *pp, struct pci_bus *bus, int dev) { + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + /* If there is no link, then there is no device */ if (bus->number != pp->root_bus_nr) { - if (!dw_pcie_link_up(pp)) + if (!dw_pcie_link_up(pci)) return 0; } @@ -769,7 +529,7 @@ static int dw_pcie_valid_device(struct pcie_port *pp, struct pci_bus *bus, } static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, - int size, u32 *val) + int size, u32 *val) { struct pcie_port *pp = bus->sysdata; @@ -785,7 +545,7 @@ static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where, } static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn, - int where, int size, u32 val) + int where, int size, u32 val) { struct pcie_port *pp = bus->sysdata; @@ -803,78 +563,46 @@ static struct pci_ops dw_pcie_ops = { .write = dw_pcie_wr_conf, }; +static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci) +{ + u32 val; + + val = dw_pcie_readl_dbi(pci, PCIE_ATU_VIEWPORT); + if (val == 0xffffffff) + return 1; + + return 0; +} + void dw_pcie_setup_rc(struct pcie_port *pp) { u32 val; + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - /* 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"); - - /* 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); + dw_pcie_setup(pci); /* setup RC BARs */ - dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_0, 0x00000004); - dw_pcie_writel_rc(pp, PCI_BASE_ADDRESS_1, 0x00000000); + dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000004); + dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_1, 0x00000000); /* setup interrupt pins */ - val = dw_pcie_readl_rc(pp, PCI_INTERRUPT_LINE); + val = dw_pcie_readl_dbi(pci, PCI_INTERRUPT_LINE); val &= 0xffff00ff; val |= 0x00000100; - dw_pcie_writel_rc(pp, PCI_INTERRUPT_LINE, val); + dw_pcie_writel_dbi(pci, PCI_INTERRUPT_LINE, val); /* setup bus numbers */ - val = dw_pcie_readl_rc(pp, PCI_PRIMARY_BUS); + val = dw_pcie_readl_dbi(pci, PCI_PRIMARY_BUS); val &= 0xff000000; val |= 0x00010100; - dw_pcie_writel_rc(pp, PCI_PRIMARY_BUS, val); + dw_pcie_writel_dbi(pci, PCI_PRIMARY_BUS, val); /* setup command register */ - val = dw_pcie_readl_rc(pp, PCI_COMMAND); + val = dw_pcie_readl_dbi(pci, 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); + dw_pcie_writel_dbi(pci, PCI_COMMAND, val); /* * If the platform provides ->rd_other_conf, it means the platform @@ -882,11 +610,16 @@ void dw_pcie_setup_rc(struct pcie_port *pp) * we should not program the ATU here. */ if (!pp->ops->rd_other_conf) { - dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0, + /* get iATU unroll support */ + pci->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pci); + dev_dbg(pci->dev, "iATU unroll: %s\n", + pci->iatu_unroll_enabled ? "enabled" : "disabled"); + + dw_pcie_prog_outbound_atu(pci, 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, + if (pci->num_viewport > 2) + dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX2, PCIE_ATU_TYPE_IO, pp->io_base, pp->io_bus_addr, pp->io_size); } diff --git a/drivers/pci/host/pcie-designware-plat.c b/drivers/pci/dwc/pcie-designware-plat.c index 1a02038c4640..65250f63515c 100644 --- a/drivers/pci/host/pcie-designware-plat.c +++ b/drivers/pci/dwc/pcie-designware-plat.c @@ -25,7 +25,7 @@ #include "pcie-designware.h" struct dw_plat_pcie { - struct pcie_port pp; /* pp.dbi_base is DT 0th resource */ + struct dw_pcie *pci; }; static irqreturn_t dw_plat_pcie_msi_irq_handler(int irq, void *arg) @@ -37,21 +37,23 @@ static irqreturn_t dw_plat_pcie_msi_irq_handler(int irq, void *arg) static void dw_plat_pcie_host_init(struct pcie_port *pp) { + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + dw_pcie_setup_rc(pp); - dw_pcie_wait_for_link(pp); + dw_pcie_wait_for_link(pci); if (IS_ENABLED(CONFIG_PCI_MSI)) dw_pcie_msi_init(pp); } -static struct pcie_host_ops dw_plat_pcie_host_ops = { +static struct dw_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; + struct device *dev = &pdev->dev; int ret; pp->irq = platform_get_irq(pdev, 1); @@ -88,7 +90,7 @@ 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 dw_pcie *pci; struct resource *res; /* Resource from DT */ int ret; @@ -96,15 +98,20 @@ static int dw_plat_pcie_probe(struct platform_device *pdev) if (!dw_plat_pcie) return -ENOMEM; - pp = &dw_plat_pcie->pp; - pp->dev = dev; + pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); + if (!pci) + return -ENOMEM; + + pci->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); + pci->dbi_base = devm_ioremap_resource(dev, res); + if (IS_ERR(pci->dbi_base)) + return PTR_ERR(pci->dbi_base); + + platform_set_drvdata(pdev, dw_plat_pcie); - ret = dw_plat_add_pcie_port(pp, pdev); + ret = dw_plat_add_pcie_port(&pci->pp, pdev); if (ret < 0) return ret; diff --git a/drivers/pci/dwc/pcie-designware.c b/drivers/pci/dwc/pcie-designware.c new file mode 100644 index 000000000000..7e1fb7d6643c --- /dev/null +++ b/drivers/pci/dwc/pcie-designware.c @@ -0,0 +1,233 @@ +/* + * 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/delay.h> +#include <linux/of.h> +#include <linux/types.h> + +#include "pcie-designware.h" + +/* 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) + +int dw_pcie_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_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_dbi(struct dw_pcie *pci, u32 reg) +{ + if (pci->ops->readl_dbi) + return pci->ops->readl_dbi(pci, reg); + + return readl(pci->dbi_base + reg); +} + +void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val) +{ + if (pci->ops->writel_dbi) + pci->ops->writel_dbi(pci, reg, val); + else + writel(val, pci->dbi_base + reg); +} + +static u32 dw_pcie_readl_unroll(struct dw_pcie *pci, u32 index, u32 reg) +{ + u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index); + + return dw_pcie_readl_dbi(pci, offset + reg); +} + +static void dw_pcie_writel_unroll(struct dw_pcie *pci, u32 index, u32 reg, + u32 val) +{ + u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index); + + dw_pcie_writel_dbi(pci, offset + reg, val); +} + +void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type, + u64 cpu_addr, u64 pci_addr, u32 size) +{ + u32 retries, val; + + if (pci->iatu_unroll_enabled) { + dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE, + lower_32_bits(cpu_addr)); + dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE, + upper_32_bits(cpu_addr)); + dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_LIMIT, + lower_32_bits(cpu_addr + size - 1)); + dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET, + lower_32_bits(pci_addr)); + dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET, + upper_32_bits(pci_addr)); + dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1, + type); + dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2, + PCIE_ATU_ENABLE); + } else { + dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, + PCIE_ATU_REGION_OUTBOUND | index); + dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_BASE, + lower_32_bits(cpu_addr)); + dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_BASE, + upper_32_bits(cpu_addr)); + dw_pcie_writel_dbi(pci, PCIE_ATU_LIMIT, + lower_32_bits(cpu_addr + size - 1)); + dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET, + lower_32_bits(pci_addr)); + dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET, + upper_32_bits(pci_addr)); + dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type); + dw_pcie_writel_dbi(pci, 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 (pci->iatu_unroll_enabled) + val = dw_pcie_readl_unroll(pci, index, + PCIE_ATU_UNR_REGION_CTRL2); + else + val = dw_pcie_readl_dbi(pci, PCIE_ATU_CR2); + + if (val == PCIE_ATU_ENABLE) + return; + + usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX); + } + dev_err(pci->dev, "iATU is not being enabled\n"); +} + +int dw_pcie_wait_for_link(struct dw_pcie *pci) +{ + int retries; + + /* check if the link is up or not */ + for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) { + if (dw_pcie_link_up(pci)) { + dev_info(pci->dev, "link up\n"); + return 0; + } + usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX); + } + + dev_err(pci->dev, "phy link never came up\n"); + + return -ETIMEDOUT; +} + +int dw_pcie_link_up(struct dw_pcie *pci) +{ + u32 val; + + if (pci->ops->link_up) + return pci->ops->link_up(pci); + + val = readl(pci->dbi_base + PCIE_PHY_DEBUG_R1); + return ((val & PCIE_PHY_DEBUG_R1_LINK_UP) && + (!(val & PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING))); +} + +void dw_pcie_setup(struct dw_pcie *pci) +{ + int ret; + u32 val; + u32 lanes; + struct device *dev = pci->dev; + struct device_node *np = dev->of_node; + + ret = of_property_read_u32(np, "num-lanes", &lanes); + if (ret) + lanes = 0; + + /* set the number of lanes */ + val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL); + val &= ~PORT_LINK_MODE_MASK; + switch (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(pci->dev, "num-lanes %u: invalid value\n", lanes); + return; + } + dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val); + + /* set link width speed control register */ + val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); + val &= ~PORT_LOGIC_LINK_WIDTH_MASK; + switch (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_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val); +} diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h new file mode 100644 index 000000000000..cd3b8713fe50 --- /dev/null +++ b/drivers/pci/dwc/pcie-designware.h @@ -0,0 +1,198 @@ +/* + * 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 + +#include <linux/irq.h> +#include <linux/msi.h> +#include <linux/pci.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)) + +/* + * 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 dw_pcie; + +struct dw_pcie_host_ops { + 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); + 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); +}; + +struct pcie_port { + u8 root_bus_nr; + 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; + struct dw_pcie_host_ops *ops; + int msi_irq; + struct irq_domain *irq_domain; + unsigned long msi_data; + DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS); +}; + +struct dw_pcie_ops { + u32 (*readl_dbi)(struct dw_pcie *pcie, u32 reg); + void (*writel_dbi)(struct dw_pcie *pcie, u32 reg, u32 val); + int (*link_up)(struct dw_pcie *pcie); +}; + +struct dw_pcie { + struct device *dev; + void __iomem *dbi_base; + u32 num_viewport; + u8 iatu_unroll_enabled; + struct pcie_port pp; + const struct dw_pcie_ops *ops; +}; + +#define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp) + +int dw_pcie_read(void __iomem *addr, int size, u32 *val); +int dw_pcie_write(void __iomem *addr, int size, u32 val); + +u32 dw_pcie_readl_dbi(struct dw_pcie *pci, u32 reg); +void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val); +int dw_pcie_link_up(struct dw_pcie *pci); +int dw_pcie_wait_for_link(struct dw_pcie *pci); +void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, + int type, u64 cpu_addr, u64 pci_addr, + u32 size); +void dw_pcie_setup(struct dw_pcie *pci); + +#ifdef CONFIG_PCIE_DW_HOST +irqreturn_t dw_handle_msi_irq(struct pcie_port *pp); +void dw_pcie_msi_init(struct pcie_port *pp); +void dw_pcie_setup_rc(struct pcie_port *pp); +int dw_pcie_host_init(struct pcie_port *pp); +#else +static inline irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) +{ + return IRQ_NONE; +} + +static inline void dw_pcie_msi_init(struct pcie_port *pp) +{ +} + +static inline void dw_pcie_setup_rc(struct pcie_port *pp) +{ +} + +static inline int dw_pcie_host_init(struct pcie_port *pp) +{ + return 0; +} +#endif +#endif /* _PCIE_DESIGNWARE_H */ diff --git a/drivers/pci/host/pcie-hisi.c b/drivers/pci/dwc/pcie-hisi.c index a301a7187b30..386467a4f00f 100644 --- a/drivers/pci/host/pcie-hisi.c +++ b/drivers/pci/dwc/pcie-hisi.c @@ -127,7 +127,7 @@ struct pci_ecam_ops hisi_pcie_ops = { #define PCIE_LTSSM_LINKUP_STATE 0x11 #define PCIE_LTSSM_STATE_MASK 0x3F -#define to_hisi_pcie(x) container_of(x, struct hisi_pcie, pp) +#define to_hisi_pcie(x) dev_get_drvdata((x)->dev) struct hisi_pcie; @@ -136,7 +136,7 @@ struct pcie_soc_ops { }; struct hisi_pcie { - struct pcie_port pp; /* pp.dbi_base is DT rc_dbi */ + struct dw_pcie *pci; struct regmap *subctrl; u32 port_id; struct pcie_soc_ops *soc_ops; @@ -149,10 +149,11 @@ static int hisi_pcie_cfg_read(struct pcie_port *pp, int where, int size, u32 reg; u32 reg_val; void *walker = ®_val; + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); walker += (where & 0x3); reg = where & ~0x3; - reg_val = dw_pcie_readl_rc(pp, reg); + reg_val = dw_pcie_readl_dbi(pci, reg); if (size == 1) *val = *(u8 __force *) walker; @@ -173,19 +174,20 @@ static int hisi_pcie_cfg_write(struct pcie_port *pp, int where, int size, u32 reg_val; u32 reg; void *walker = ®_val; + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); walker += (where & 0x3); reg = where & ~0x3; if (size == 4) - dw_pcie_writel_rc(pp, reg, val); + dw_pcie_writel_dbi(pci, reg, val); else if (size == 2) { - reg_val = dw_pcie_readl_rc(pp, reg); + reg_val = dw_pcie_readl_dbi(pci, reg); *(u16 __force *) walker = val; - dw_pcie_writel_rc(pp, reg, reg_val); + dw_pcie_writel_dbi(pci, reg, reg_val); } else if (size == 1) { - reg_val = dw_pcie_readl_rc(pp, reg); + reg_val = dw_pcie_readl_dbi(pci, reg); *(u8 __force *) walker = val; - dw_pcie_writel_rc(pp, reg, reg_val); + dw_pcie_writel_dbi(pci, reg, reg_val); } else return PCIBIOS_BAD_REGISTER_NUMBER; @@ -204,32 +206,32 @@ static int hisi_pcie_link_up_hip05(struct hisi_pcie *hisi_pcie) static int hisi_pcie_link_up_hip06(struct hisi_pcie *hisi_pcie) { - struct pcie_port *pp = &hisi_pcie->pp; + struct dw_pcie *pci = hisi_pcie->pci; u32 val; - val = dw_pcie_readl_rc(pp, PCIE_SYS_STATE4); + val = dw_pcie_readl_dbi(pci, PCIE_SYS_STATE4); return ((val & PCIE_LTSSM_STATE_MASK) == PCIE_LTSSM_LINKUP_STATE); } -static int hisi_pcie_link_up(struct pcie_port *pp) +static int hisi_pcie_link_up(struct dw_pcie *pci) { - struct hisi_pcie *hisi_pcie = to_hisi_pcie(pp); + struct hisi_pcie *hisi_pcie = to_hisi_pcie(pci); return hisi_pcie->soc_ops->hisi_pcie_link_up(hisi_pcie); } -static struct pcie_host_ops hisi_pcie_host_ops = { +static struct dw_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; + struct dw_pcie *pci = hisi_pcie->pci; + struct pcie_port *pp = &pci->pp; + struct device *dev = &pdev->dev; int ret; u32 port_id; @@ -254,11 +256,15 @@ static int hisi_add_pcie_port(struct hisi_pcie *hisi_pcie, return 0; } +static const struct dw_pcie_ops dw_pcie_ops = { + .link_up = hisi_pcie_link_up, +}; + static int hisi_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct dw_pcie *pci; struct hisi_pcie *hisi_pcie; - struct pcie_port *pp; const struct of_device_id *match; struct resource *reg; struct device_driver *driver; @@ -268,8 +274,13 @@ static int hisi_pcie_probe(struct platform_device *pdev) if (!hisi_pcie) return -ENOMEM; - pp = &hisi_pcie->pp; - pp->dev = dev; + pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); + if (!pci) + return -ENOMEM; + + pci->dev = dev; + pci->ops = &dw_pcie_ops; + driver = dev->driver; match = of_match_device(driver->of_match_table, dev); @@ -283,9 +294,11 @@ static int hisi_pcie_probe(struct platform_device *pdev) } 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); + pci->dbi_base = devm_ioremap_resource(dev, reg); + if (IS_ERR(pci->dbi_base)) + return PTR_ERR(pci->dbi_base); + + platform_set_drvdata(pdev, hisi_pcie); ret = hisi_add_pcie_port(hisi_pcie, pdev); if (ret) diff --git a/drivers/pci/host/pcie-qcom.c b/drivers/pci/dwc/pcie-qcom.c index 734ba0d4a5c8..e36abe0d9d6f 100644 --- a/drivers/pci/host/pcie-qcom.c +++ b/drivers/pci/dwc/pcie-qcom.c @@ -103,7 +103,7 @@ struct qcom_pcie_ops { }; struct qcom_pcie { - struct pcie_port pp; /* pp.dbi_base is DT dbi */ + struct dw_pcie *pci; void __iomem *parf; /* DT parf */ void __iomem *elbi; /* DT elbi */ union qcom_pcie_resources res; @@ -112,7 +112,7 @@ struct qcom_pcie { struct qcom_pcie_ops *ops; }; -#define to_qcom_pcie(x) container_of(x, struct qcom_pcie, pp) +#define to_qcom_pcie(x) dev_get_drvdata((x)->dev) static void qcom_ep_reset_assert(struct qcom_pcie *pcie) { @@ -155,21 +155,23 @@ static void qcom_pcie_v2_ltssm_enable(struct qcom_pcie *pcie) static int qcom_pcie_establish_link(struct qcom_pcie *pcie) { + struct dw_pcie *pci = pcie->pci; - if (dw_pcie_link_up(&pcie->pp)) + if (dw_pcie_link_up(pci)) 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); + return dw_pcie_wait_for_link(pci); } 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; + struct dw_pcie *pci = pcie->pci; + struct device *dev = pci->dev; res->vdda = devm_regulator_get(dev, "vdda"); if (IS_ERR(res->vdda)) @@ -212,16 +214,14 @@ static int qcom_pcie_get_resources_v0(struct qcom_pcie *pcie) 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; + return PTR_ERR_OR_ZERO(res->phy_reset); } 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; + struct dw_pcie *pci = pcie->pci; + struct device *dev = pci->dev; res->vdda = devm_regulator_get(dev, "vdda"); if (IS_ERR(res->vdda)) @@ -244,10 +244,7 @@ static int qcom_pcie_get_resources_v1(struct qcom_pcie *pcie) 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; + return PTR_ERR_OR_ZERO(res->core); } static void qcom_pcie_deinit_v0(struct qcom_pcie *pcie) @@ -270,7 +267,8 @@ static void qcom_pcie_deinit_v0(struct qcom_pcie *pcie) 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; + struct dw_pcie *pci = pcie->pci; + struct device *dev = pci->dev; u32 val; int ret; @@ -392,7 +390,8 @@ static void qcom_pcie_deinit_v1(struct qcom_pcie *pcie) 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; + struct dw_pcie *pci = pcie->pci; + struct device *dev = pci->dev; int ret; ret = reset_control_deassert(res->core); @@ -459,7 +458,8 @@ err_res: 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; + struct dw_pcie *pci = pcie->pci; + struct device *dev = pci->dev; res->aux_clk = devm_clk_get(dev, "aux"); if (IS_ERR(res->aux_clk)) @@ -478,16 +478,14 @@ static int qcom_pcie_get_resources_v2(struct qcom_pcie *pcie) 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; + return PTR_ERR_OR_ZERO(res->pipe_clk); } 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; + struct dw_pcie *pci = pcie->pci; + struct device *dev = pci->dev; u32 val; int ret; @@ -551,7 +549,8 @@ err_cfg_clk: 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; + struct dw_pcie *pci = pcie->pci; + struct device *dev = pci->dev; int ret; ret = clk_prepare_enable(res->pipe_clk); @@ -563,10 +562,9 @@ static int qcom_pcie_post_init_v2(struct qcom_pcie *pcie) return 0; } -static int qcom_pcie_link_up(struct pcie_port *pp) +static int qcom_pcie_link_up(struct dw_pcie *pci) { - struct qcom_pcie *pcie = to_qcom_pcie(pp); - u16 val = readw(pcie->pp.dbi_base + PCIE20_CAP + PCI_EXP_LNKSTA); + u16 val = readw(pci->dbi_base + PCIE20_CAP + PCI_EXP_LNKSTA); return !!(val & PCI_EXP_LNKSTA_DLLLA); } @@ -584,7 +582,8 @@ static void qcom_pcie_deinit_v2(struct qcom_pcie *pcie) static void qcom_pcie_host_init(struct pcie_port *pp) { - struct qcom_pcie *pcie = to_qcom_pcie(pp); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct qcom_pcie *pcie = to_qcom_pcie(pci); int ret; qcom_ep_reset_assert(pcie); @@ -622,19 +621,20 @@ err_deinit: static int qcom_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, u32 *val) { + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + /* 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 = readl(pci->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); + return dw_pcie_read(pci->dbi_base + where, size, val); } -static struct pcie_host_ops qcom_pcie_dw_ops = { - .link_up = qcom_pcie_link_up, +static struct dw_pcie_host_ops qcom_pcie_dw_ops = { .host_init = qcom_pcie_host_init, .rd_own_conf = qcom_pcie_rd_own_conf, }; @@ -661,19 +661,31 @@ static const struct qcom_pcie_ops ops_v2 = { .ltssm_enable = qcom_pcie_v2_ltssm_enable, }; +static const struct dw_pcie_ops dw_pcie_ops = { + .link_up = qcom_pcie_link_up, +}; + 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; + struct dw_pcie *pci; + struct qcom_pcie *pcie; int ret; pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); if (!pcie) return -ENOMEM; - pp = &pcie->pp; + pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); + if (!pci) + return -ENOMEM; + + pci->dev = dev; + pci->ops = &dw_pcie_ops; + pp = &pci->pp; + pcie->ops = (struct qcom_pcie_ops *)of_device_get_match_data(dev); pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_LOW); @@ -686,9 +698,9 @@ static int qcom_pcie_probe(struct platform_device *pdev) 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); + pci->dbi_base = devm_ioremap_resource(dev, res); + if (IS_ERR(pci->dbi_base)) + return PTR_ERR(pci->dbi_base); res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "elbi"); pcie->elbi = devm_ioremap_resource(dev, res); @@ -699,7 +711,6 @@ static int qcom_pcie_probe(struct platform_device *pdev) if (IS_ERR(pcie->phy)) return PTR_ERR(pcie->phy); - pp->dev = dev; ret = pcie->ops->get_resources(pcie); if (ret) return ret; @@ -725,6 +736,8 @@ static int qcom_pcie_probe(struct platform_device *pdev) if (ret) return ret; + platform_set_drvdata(pdev, pcie); + ret = dw_pcie_host_init(pp); if (ret) { dev_err(dev, "cannot initialize host\n"); diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/dwc/pcie-spear13xx.c index dafe8b88d97d..348f9c5e0433 100644 --- a/drivers/pci/host/pcie-spear13xx.c +++ b/drivers/pci/dwc/pcie-spear13xx.c @@ -25,7 +25,7 @@ #include "pcie-designware.h" struct spear13xx_pcie { - struct pcie_port pp; /* DT dbi is pp.dbi_base */ + struct dw_pcie *pci; void __iomem *app_base; struct phy *phy; struct clk *clk; @@ -70,17 +70,18 @@ struct pcie_app_reg { #define EXP_CAP_ID_OFFSET 0x70 -#define to_spear13xx_pcie(x) container_of(x, struct spear13xx_pcie, pp) +#define to_spear13xx_pcie(x) dev_get_drvdata((x)->dev) static int spear13xx_pcie_establish_link(struct spear13xx_pcie *spear13xx_pcie) { - struct pcie_port *pp = &spear13xx_pcie->pp; + struct dw_pcie *pci = spear13xx_pcie->pci; + struct pcie_port *pp = &pci->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"); + if (dw_pcie_link_up(pci)) { + dev_err(pci->dev, "link already up\n"); return 0; } @@ -91,34 +92,34 @@ static int spear13xx_pcie_establish_link(struct spear13xx_pcie *spear13xx_pcie) * 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); + dw_pcie_read(pci->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_write(pci->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); + dw_pcie_write(pci->dbi_base + PCI_VENDOR_ID, 2, 0x104A); + dw_pcie_write(pci->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); + dw_pcie_read(pci->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_write(pci->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); + dw_pcie_read(pci->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); + dw_pcie_write(pci->dbi_base + exp_cap_off + + PCI_EXP_LNKCTL2, 2, val); } } @@ -128,14 +129,15 @@ static int spear13xx_pcie_establish_link(struct spear13xx_pcie *spear13xx_pcie) | ((u32)1 << REG_TRANSLATION_ENABLE), &app_reg->app_ctrl_0); - return dw_pcie_wait_for_link(pp); + return dw_pcie_wait_for_link(pci); } 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; + struct dw_pcie *pci = spear13xx_pcie->pci; + struct pcie_port *pp = &pci->pp; unsigned int status; status = readl(&app_reg->int_sts); @@ -152,7 +154,8 @@ static irqreturn_t spear13xx_pcie_irq_handler(int irq, void *arg) static void spear13xx_pcie_enable_interrupts(struct spear13xx_pcie *spear13xx_pcie) { - struct pcie_port *pp = &spear13xx_pcie->pp; + struct dw_pcie *pci = spear13xx_pcie->pci; + struct pcie_port *pp = &pci->pp; struct pcie_app_reg *app_reg = spear13xx_pcie->app_base; /* Enable MSI interrupt */ @@ -163,9 +166,9 @@ static void spear13xx_pcie_enable_interrupts(struct spear13xx_pcie *spear13xx_pc } } -static int spear13xx_pcie_link_up(struct pcie_port *pp) +static int spear13xx_pcie_link_up(struct dw_pcie *pci) { - struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp); + struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci); struct pcie_app_reg *app_reg = spear13xx_pcie->app_base; if (readl(&app_reg->app_status_1) & XMLH_LINK_UP) @@ -176,22 +179,23 @@ static int spear13xx_pcie_link_up(struct pcie_port *pp) static void spear13xx_pcie_host_init(struct pcie_port *pp) { - struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pp); + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct spear13xx_pcie *spear13xx_pcie = to_spear13xx_pcie(pci); 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, +static struct dw_pcie_host_ops spear13xx_pcie_host_ops = { .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; + struct dw_pcie *pci = spear13xx_pcie->pci; + struct pcie_port *pp = &pci->pp; + struct device *dev = &pdev->dev; int ret; pp->irq = platform_get_irq(pdev, 0); @@ -219,11 +223,15 @@ static int spear13xx_add_pcie_port(struct spear13xx_pcie *spear13xx_pcie, return 0; } +static const struct dw_pcie_ops dw_pcie_ops = { + .link_up = spear13xx_pcie_link_up, +}; + static int spear13xx_pcie_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; + struct dw_pcie *pci; struct spear13xx_pcie *spear13xx_pcie; - struct pcie_port *pp; struct device_node *np = dev->of_node; struct resource *dbi_base; int ret; @@ -232,6 +240,13 @@ static int spear13xx_pcie_probe(struct platform_device *pdev) if (!spear13xx_pcie) return -ENOMEM; + pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); + if (!pci) + return -ENOMEM; + + pci->dev = dev; + pci->ops = &dw_pcie_ops; + spear13xx_pcie->phy = devm_phy_get(dev, "pcie-phy"); if (IS_ERR(spear13xx_pcie->phy)) { ret = PTR_ERR(spear13xx_pcie->phy); @@ -255,26 +270,24 @@ static int spear13xx_pcie_probe(struct platform_device *pdev) 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)) { + pci->dbi_base = devm_ioremap_resource(dev, dbi_base); + if (IS_ERR(pci->dbi_base)) { dev_err(dev, "couldn't remap dbi base %p\n", dbi_base); - ret = PTR_ERR(pp->dbi_base); + ret = PTR_ERR(pci->dbi_base); goto fail_clk; } - spear13xx_pcie->app_base = pp->dbi_base + 0x2000; + spear13xx_pcie->app_base = pci->dbi_base + 0x2000; if (of_property_read_bool(np, "st,pcie-is-gen1")) spear13xx_pcie->is_gen1 = true; + platform_set_drvdata(pdev, spear13xx_pcie); + ret = spear13xx_add_pcie_port(spear13xx_pcie, pdev); if (ret < 0) goto fail_clk; - platform_set_drvdata(pdev, spear13xx_pcie); return 0; fail_clk: 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/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 */ |