diff options
Diffstat (limited to 'drivers/pci/dwc')
-rw-r--r-- | drivers/pci/dwc/Kconfig | 70 | ||||
-rw-r--r-- | drivers/pci/dwc/Makefile | 6 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-dra7xx.c | 47 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-exynos.c | 227 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-imx6.c | 5 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-keystone-dw.c | 6 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-keystone.c | 10 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-keystone.h | 6 | ||||
-rw-r--r-- | drivers/pci/dwc/pci-layerscape.c | 5 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-armada8k.c | 5 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-artpec6.c | 475 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-designware-ep.c | 140 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-designware-host.c | 20 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-designware-plat.c | 5 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-designware.c | 7 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-designware.h | 41 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-hisi.c | 5 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-histb.c | 5 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-kirin.c | 5 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-qcom.c | 14 | ||||
-rw-r--r-- | drivers/pci/dwc/pcie-spear13xx.c | 5 |
21 files changed, 654 insertions, 455 deletions
diff --git a/drivers/pci/dwc/Kconfig b/drivers/pci/dwc/Kconfig index 113e09440f85..0f666b1ce289 100644 --- a/drivers/pci/dwc/Kconfig +++ b/drivers/pci/dwc/Kconfig | |||
@@ -1,3 +1,5 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | ||
2 | |||
1 | menu "DesignWare PCI Core Support" | 3 | menu "DesignWare PCI Core Support" |
2 | 4 | ||
3 | config PCIE_DW | 5 | config PCIE_DW |
@@ -15,39 +17,38 @@ config PCIE_DW_EP | |||
15 | select PCIE_DW | 17 | select PCIE_DW |
16 | 18 | ||
17 | config PCI_DRA7XX | 19 | config PCI_DRA7XX |
18 | bool "TI DRA7xx PCIe controller" | 20 | bool |
19 | depends on SOC_DRA7XX || COMPILE_TEST | ||
20 | depends on (PCI && PCI_MSI_IRQ_DOMAIN) || PCI_ENDPOINT | ||
21 | depends on OF && HAS_IOMEM && TI_PIPE3 | ||
22 | help | ||
23 | Enables support for the PCIe controller in the DRA7xx SoC. There | ||
24 | are two instances of PCIe controller in DRA7xx. This controller can | ||
25 | work either as EP or RC. In order to enable host-specific features | ||
26 | PCI_DRA7XX_HOST must be selected and in order to enable device- | ||
27 | specific features PCI_DRA7XX_EP must be selected. This uses | ||
28 | the DesignWare core. | ||
29 | |||
30 | if PCI_DRA7XX | ||
31 | 21 | ||
32 | config PCI_DRA7XX_HOST | 22 | config PCI_DRA7XX_HOST |
33 | bool "PCI DRA7xx Host Mode" | 23 | bool "TI DRA7xx PCIe controller Host Mode" |
34 | depends on PCI | 24 | depends on SOC_DRA7XX || COMPILE_TEST |
35 | depends on PCI_MSI_IRQ_DOMAIN | 25 | depends on PCI && PCI_MSI_IRQ_DOMAIN |
26 | depends on OF && HAS_IOMEM && TI_PIPE3 | ||
36 | select PCIE_DW_HOST | 27 | select PCIE_DW_HOST |
28 | select PCI_DRA7XX | ||
37 | default y | 29 | default y |
38 | help | 30 | help |
39 | Enables support for the PCIe controller in the DRA7xx SoC to work in | 31 | Enables support for the PCIe controller in the DRA7xx SoC to work in |
40 | host mode. | 32 | host mode. There are two instances of PCIe controller in DRA7xx. |
33 | This controller can work either as EP or RC. In order to enable | ||
34 | host-specific features PCI_DRA7XX_HOST must be selected and in order | ||
35 | to enable device-specific features PCI_DRA7XX_EP must be selected. | ||
36 | This uses the DesignWare core. | ||
41 | 37 | ||
42 | config PCI_DRA7XX_EP | 38 | config PCI_DRA7XX_EP |
43 | bool "PCI DRA7xx Endpoint Mode" | 39 | bool "TI DRA7xx PCIe controller Endpoint Mode" |
40 | depends on SOC_DRA7XX || COMPILE_TEST | ||
44 | depends on PCI_ENDPOINT | 41 | depends on PCI_ENDPOINT |
42 | depends on OF && HAS_IOMEM && TI_PIPE3 | ||
45 | select PCIE_DW_EP | 43 | select PCIE_DW_EP |
44 | select PCI_DRA7XX | ||
46 | help | 45 | help |
47 | Enables support for the PCIe controller in the DRA7xx SoC to work in | 46 | Enables support for the PCIe controller in the DRA7xx SoC to work in |
48 | endpoint mode. | 47 | endpoint mode. There are two instances of PCIe controller in DRA7xx. |
49 | 48 | This controller can work either as EP or RC. In order to enable | |
50 | endif | 49 | host-specific features PCI_DRA7XX_HOST must be selected and in order |
50 | to enable device-specific features PCI_DRA7XX_EP must be selected. | ||
51 | This uses the DesignWare core. | ||
51 | 52 | ||
52 | config PCIE_DW_PLAT | 53 | config PCIE_DW_PLAT |
53 | bool "Platform bus based DesignWare PCIe Controller" | 54 | bool "Platform bus based DesignWare PCIe Controller" |
@@ -149,15 +150,28 @@ config PCIE_ARMADA_8K | |||
149 | DesignWare core functions to implement the driver. | 150 | DesignWare core functions to implement the driver. |
150 | 151 | ||
151 | config PCIE_ARTPEC6 | 152 | config PCIE_ARTPEC6 |
152 | bool "Axis ARTPEC-6 PCIe controller" | 153 | bool |
153 | depends on PCI | 154 | |
155 | config PCIE_ARTPEC6_HOST | ||
156 | bool "Axis ARTPEC-6 PCIe controller Host Mode" | ||
154 | depends on MACH_ARTPEC6 | 157 | depends on MACH_ARTPEC6 |
155 | depends on PCI_MSI_IRQ_DOMAIN | 158 | depends on PCI && PCI_MSI_IRQ_DOMAIN |
156 | select PCIEPORTBUS | 159 | select PCIEPORTBUS |
157 | select PCIE_DW_HOST | 160 | select PCIE_DW_HOST |
161 | select PCIE_ARTPEC6 | ||
162 | help | ||
163 | Enables support for the PCIe controller in the ARTPEC-6 SoC to work in | ||
164 | host mode. This uses the DesignWare core. | ||
165 | |||
166 | config PCIE_ARTPEC6_EP | ||
167 | bool "Axis ARTPEC-6 PCIe controller Endpoint Mode" | ||
168 | depends on MACH_ARTPEC6 | ||
169 | depends on PCI_ENDPOINT | ||
170 | select PCIE_DW_EP | ||
171 | select PCIE_ARTPEC6 | ||
158 | help | 172 | help |
159 | Say Y here to enable PCIe controller support on Axis ARTPEC-6 | 173 | Enables support for the PCIe controller in the ARTPEC-6 SoC to work in |
160 | SoCs. This PCIe controller uses the DesignWare core. | 174 | endpoint mode. This uses the DesignWare core. |
161 | 175 | ||
162 | config PCIE_KIRIN | 176 | config PCIE_KIRIN |
163 | depends on OF && ARM64 | 177 | depends on OF && ARM64 |
diff --git a/drivers/pci/dwc/Makefile b/drivers/pci/dwc/Makefile index 41ba499c96ee..5d2ce72c7a52 100644 --- a/drivers/pci/dwc/Makefile +++ b/drivers/pci/dwc/Makefile | |||
@@ -3,9 +3,7 @@ obj-$(CONFIG_PCIE_DW) += pcie-designware.o | |||
3 | obj-$(CONFIG_PCIE_DW_HOST) += pcie-designware-host.o | 3 | obj-$(CONFIG_PCIE_DW_HOST) += pcie-designware-host.o |
4 | obj-$(CONFIG_PCIE_DW_EP) += pcie-designware-ep.o | 4 | obj-$(CONFIG_PCIE_DW_EP) += pcie-designware-ep.o |
5 | obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o | 5 | obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o |
6 | ifneq ($(filter y,$(CONFIG_PCI_DRA7XX_HOST) $(CONFIG_PCI_DRA7XX_EP)),) | 6 | obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o |
7 | obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o | ||
8 | endif | ||
9 | obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o | 7 | obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o |
10 | obj-$(CONFIG_PCI_IMX6) += pci-imx6.o | 8 | obj-$(CONFIG_PCI_IMX6) += pci-imx6.o |
11 | obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o | 9 | obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o |
@@ -27,4 +25,6 @@ obj-$(CONFIG_PCIE_HISI_STB) += pcie-histb.o | |||
27 | # ARM64 and use internal ifdefs to only build the pieces we need | 25 | # ARM64 and use internal ifdefs to only build the pieces we need |
28 | # depending on whether ACPI, the DT driver, or both are enabled. | 26 | # depending on whether ACPI, the DT driver, or both are enabled. |
29 | 27 | ||
28 | ifdef CONFIG_PCI | ||
30 | obj-$(CONFIG_ARM64) += pcie-hisi.o | 29 | obj-$(CONFIG_ARM64) += pcie-hisi.o |
30 | endif | ||
diff --git a/drivers/pci/dwc/pci-dra7xx.c b/drivers/pci/dwc/pci-dra7xx.c index e77a4ceed74c..ed8558d638e5 100644 --- a/drivers/pci/dwc/pci-dra7xx.c +++ b/drivers/pci/dwc/pci-dra7xx.c | |||
@@ -1,13 +1,10 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * pcie-dra7xx - PCIe controller driver for TI DRA7xx SoCs | 3 | * pcie-dra7xx - PCIe controller driver for TI DRA7xx SoCs |
3 | * | 4 | * |
4 | * Copyright (C) 2013-2014 Texas Instruments Incorporated - http://www.ti.com | 5 | * Copyright (C) 2013-2014 Texas Instruments Incorporated - http://www.ti.com |
5 | * | 6 | * |
6 | * Authors: Kishon Vijay Abraham I <kishon@ti.com> | 7 | * Authors: Kishon Vijay Abraham I <kishon@ti.com> |
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | 8 | */ |
12 | 9 | ||
13 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
@@ -110,7 +107,7 @@ static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset, | |||
110 | writel(value, pcie->base + offset); | 107 | writel(value, pcie->base + offset); |
111 | } | 108 | } |
112 | 109 | ||
113 | static u64 dra7xx_pcie_cpu_addr_fixup(u64 pci_addr) | 110 | static u64 dra7xx_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 pci_addr) |
114 | { | 111 | { |
115 | return pci_addr & DRA7XX_CPU_TO_BUS_ADDR; | 112 | return pci_addr & DRA7XX_CPU_TO_BUS_ADDR; |
116 | } | 113 | } |
@@ -226,6 +223,7 @@ static int dra7xx_pcie_intx_map(struct irq_domain *domain, unsigned int irq, | |||
226 | 223 | ||
227 | static const struct irq_domain_ops intx_domain_ops = { | 224 | static const struct irq_domain_ops intx_domain_ops = { |
228 | .map = dra7xx_pcie_intx_map, | 225 | .map = dra7xx_pcie_intx_map, |
226 | .xlate = pci_irqd_intx_xlate, | ||
229 | }; | 227 | }; |
230 | 228 | ||
231 | static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp) | 229 | static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp) |
@@ -256,7 +254,8 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg) | |||
256 | struct dra7xx_pcie *dra7xx = arg; | 254 | struct dra7xx_pcie *dra7xx = arg; |
257 | struct dw_pcie *pci = dra7xx->pci; | 255 | struct dw_pcie *pci = dra7xx->pci; |
258 | struct pcie_port *pp = &pci->pp; | 256 | struct pcie_port *pp = &pci->pp; |
259 | u32 reg; | 257 | unsigned long reg; |
258 | u32 virq, bit; | ||
260 | 259 | ||
261 | reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI); | 260 | reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI); |
262 | 261 | ||
@@ -268,8 +267,11 @@ static irqreturn_t dra7xx_pcie_msi_irq_handler(int irq, void *arg) | |||
268 | case INTB: | 267 | case INTB: |
269 | case INTC: | 268 | case INTC: |
270 | case INTD: | 269 | case INTD: |
271 | generic_handle_irq(irq_find_mapping(dra7xx->irq_domain, | 270 | for_each_set_bit(bit, ®, PCI_NUM_INTX) { |
272 | ffs(reg))); | 271 | virq = irq_find_mapping(dra7xx->irq_domain, bit); |
272 | if (virq) | ||
273 | generic_handle_irq(virq); | ||
274 | } | ||
273 | break; | 275 | break; |
274 | } | 276 | } |
275 | 277 | ||
@@ -337,15 +339,6 @@ static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg) | |||
337 | return IRQ_HANDLED; | 339 | return IRQ_HANDLED; |
338 | } | 340 | } |
339 | 341 | ||
340 | static void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar) | ||
341 | { | ||
342 | u32 reg; | ||
343 | |||
344 | reg = PCI_BASE_ADDRESS_0 + (4 * bar); | ||
345 | dw_pcie_writel_dbi2(pci, reg, 0x0); | ||
346 | dw_pcie_writel_dbi(pci, reg, 0x0); | ||
347 | } | ||
348 | |||
349 | static void dra7xx_pcie_ep_init(struct dw_pcie_ep *ep) | 342 | static void dra7xx_pcie_ep_init(struct dw_pcie_ep *ep) |
350 | { | 343 | { |
351 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); | 344 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); |
@@ -375,7 +368,7 @@ static void dra7xx_pcie_raise_msi_irq(struct dra7xx_pcie *dra7xx, | |||
375 | dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_MSI_XMT, reg); | 368 | dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_MSI_XMT, reg); |
376 | } | 369 | } |
377 | 370 | ||
378 | static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep, | 371 | static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, |
379 | enum pci_epc_irq_type type, u8 interrupt_num) | 372 | enum pci_epc_irq_type type, u8 interrupt_num) |
380 | { | 373 | { |
381 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); | 374 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); |
@@ -470,6 +463,8 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx, | |||
470 | if (!pci->dbi_base) | 463 | if (!pci->dbi_base) |
471 | return -ENOMEM; | 464 | return -ENOMEM; |
472 | 465 | ||
466 | pp->ops = &dra7xx_pcie_host_ops; | ||
467 | |||
473 | ret = dw_pcie_host_init(pp); | 468 | ret = dw_pcie_host_init(pp); |
474 | if (ret) { | 469 | if (ret) { |
475 | dev_err(dev, "failed to initialize host\n"); | 470 | dev_err(dev, "failed to initialize host\n"); |
@@ -599,7 +594,6 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) | |||
599 | void __iomem *base; | 594 | void __iomem *base; |
600 | struct resource *res; | 595 | struct resource *res; |
601 | struct dw_pcie *pci; | 596 | struct dw_pcie *pci; |
602 | struct pcie_port *pp; | ||
603 | struct dra7xx_pcie *dra7xx; | 597 | struct dra7xx_pcie *dra7xx; |
604 | struct device *dev = &pdev->dev; | 598 | struct device *dev = &pdev->dev; |
605 | struct device_node *np = dev->of_node; | 599 | struct device_node *np = dev->of_node; |
@@ -627,9 +621,6 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) | |||
627 | pci->dev = dev; | 621 | pci->dev = dev; |
628 | pci->ops = &dw_pcie_ops; | 622 | pci->ops = &dw_pcie_ops; |
629 | 623 | ||
630 | pp = &pci->pp; | ||
631 | pp->ops = &dra7xx_pcie_host_ops; | ||
632 | |||
633 | irq = platform_get_irq(pdev, 0); | 624 | irq = platform_get_irq(pdev, 0); |
634 | if (irq < 0) { | 625 | if (irq < 0) { |
635 | dev_err(dev, "missing IRQ resource: %d\n", irq); | 626 | dev_err(dev, "missing IRQ resource: %d\n", irq); |
@@ -705,6 +696,11 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) | |||
705 | 696 | ||
706 | switch (mode) { | 697 | switch (mode) { |
707 | case DW_PCIE_RC_TYPE: | 698 | case DW_PCIE_RC_TYPE: |
699 | if (!IS_ENABLED(CONFIG_PCI_DRA7XX_HOST)) { | ||
700 | ret = -ENODEV; | ||
701 | goto err_gpio; | ||
702 | } | ||
703 | |||
708 | dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_DEVICE_TYPE, | 704 | dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_DEVICE_TYPE, |
709 | DEVICE_TYPE_RC); | 705 | DEVICE_TYPE_RC); |
710 | ret = dra7xx_add_pcie_port(dra7xx, pdev); | 706 | ret = dra7xx_add_pcie_port(dra7xx, pdev); |
@@ -712,6 +708,11 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) | |||
712 | goto err_gpio; | 708 | goto err_gpio; |
713 | break; | 709 | break; |
714 | case DW_PCIE_EP_TYPE: | 710 | case DW_PCIE_EP_TYPE: |
711 | if (!IS_ENABLED(CONFIG_PCI_DRA7XX_EP)) { | ||
712 | ret = -ENODEV; | ||
713 | goto err_gpio; | ||
714 | } | ||
715 | |||
715 | dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_DEVICE_TYPE, | 716 | dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_DEVICE_TYPE, |
716 | DEVICE_TYPE_EP); | 717 | DEVICE_TYPE_EP); |
717 | 718 | ||
@@ -810,7 +811,7 @@ static int dra7xx_pcie_resume_noirq(struct device *dev) | |||
810 | } | 811 | } |
811 | #endif | 812 | #endif |
812 | 813 | ||
813 | void dra7xx_pcie_shutdown(struct platform_device *pdev) | 814 | static void dra7xx_pcie_shutdown(struct platform_device *pdev) |
814 | { | 815 | { |
815 | struct device *dev = &pdev->dev; | 816 | struct device *dev = &pdev->dev; |
816 | struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev); | 817 | struct dra7xx_pcie *dra7xx = dev_get_drvdata(dev); |
diff --git a/drivers/pci/dwc/pci-exynos.c b/drivers/pci/dwc/pci-exynos.c index 5596fdedbb94..ca6278113936 100644 --- a/drivers/pci/dwc/pci-exynos.c +++ b/drivers/pci/dwc/pci-exynos.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * PCIe host controller driver for Samsung EXYNOS SoCs | 3 | * PCIe host controller driver for Samsung EXYNOS SoCs |
3 | * | 4 | * |
@@ -5,10 +6,6 @@ | |||
5 | * http://www.samsung.com | 6 | * http://www.samsung.com |
6 | * | 7 | * |
7 | * Author: Jingoo Han <jg1.han@samsung.com> | 8 | * Author: Jingoo Han <jg1.han@samsung.com> |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | 9 | */ |
13 | 10 | ||
14 | #include <linux/clk.h> | 11 | #include <linux/clk.h> |
@@ -55,49 +52,8 @@ | |||
55 | #define PCIE_ELBI_SLV_ARMISC 0x120 | 52 | #define PCIE_ELBI_SLV_ARMISC 0x120 |
56 | #define PCIE_ELBI_SLV_DBI_ENABLE BIT(21) | 53 | #define PCIE_ELBI_SLV_DBI_ENABLE BIT(21) |
57 | 54 | ||
58 | /* PCIe Purple registers */ | ||
59 | #define PCIE_PHY_GLOBAL_RESET 0x000 | ||
60 | #define PCIE_PHY_COMMON_RESET 0x004 | ||
61 | #define PCIE_PHY_CMN_REG 0x008 | ||
62 | #define PCIE_PHY_MAC_RESET 0x00c | ||
63 | #define PCIE_PHY_PLL_LOCKED 0x010 | ||
64 | #define PCIE_PHY_TRSVREG_RESET 0x020 | ||
65 | #define PCIE_PHY_TRSV_RESET 0x024 | ||
66 | |||
67 | /* PCIe PHY registers */ | ||
68 | #define PCIE_PHY_IMPEDANCE 0x004 | ||
69 | #define PCIE_PHY_PLL_DIV_0 0x008 | ||
70 | #define PCIE_PHY_PLL_BIAS 0x00c | ||
71 | #define PCIE_PHY_DCC_FEEDBACK 0x014 | ||
72 | #define PCIE_PHY_PLL_DIV_1 0x05c | ||
73 | #define PCIE_PHY_COMMON_POWER 0x064 | ||
74 | #define PCIE_PHY_COMMON_PD_CMN BIT(3) | ||
75 | #define PCIE_PHY_TRSV0_EMP_LVL 0x084 | ||
76 | #define PCIE_PHY_TRSV0_DRV_LVL 0x088 | ||
77 | #define PCIE_PHY_TRSV0_RXCDR 0x0ac | ||
78 | #define PCIE_PHY_TRSV0_POWER 0x0c4 | ||
79 | #define PCIE_PHY_TRSV0_PD_TSV BIT(7) | ||
80 | #define PCIE_PHY_TRSV0_LVCC 0x0dc | ||
81 | #define PCIE_PHY_TRSV1_EMP_LVL 0x144 | ||
82 | #define PCIE_PHY_TRSV1_RXCDR 0x16c | ||
83 | #define PCIE_PHY_TRSV1_POWER 0x184 | ||
84 | #define PCIE_PHY_TRSV1_PD_TSV BIT(7) | ||
85 | #define PCIE_PHY_TRSV1_LVCC 0x19c | ||
86 | #define PCIE_PHY_TRSV2_EMP_LVL 0x204 | ||
87 | #define PCIE_PHY_TRSV2_RXCDR 0x22c | ||
88 | #define PCIE_PHY_TRSV2_POWER 0x244 | ||
89 | #define PCIE_PHY_TRSV2_PD_TSV BIT(7) | ||
90 | #define PCIE_PHY_TRSV2_LVCC 0x25c | ||
91 | #define PCIE_PHY_TRSV3_EMP_LVL 0x2c4 | ||
92 | #define PCIE_PHY_TRSV3_RXCDR 0x2ec | ||
93 | #define PCIE_PHY_TRSV3_POWER 0x304 | ||
94 | #define PCIE_PHY_TRSV3_PD_TSV BIT(7) | ||
95 | #define PCIE_PHY_TRSV3_LVCC 0x31c | ||
96 | |||
97 | struct exynos_pcie_mem_res { | 55 | struct exynos_pcie_mem_res { |
98 | void __iomem *elbi_base; /* DT 0th resource: PCIe CTRL */ | 56 | void __iomem *elbi_base; /* DT 0th resource: PCIe CTRL */ |
99 | void __iomem *phy_base; /* DT 1st resource: PHY CTRL */ | ||
100 | void __iomem *block_base; /* DT 2nd resource: PHY ADDITIONAL CTRL */ | ||
101 | }; | 57 | }; |
102 | 58 | ||
103 | struct exynos_pcie_clk_res { | 59 | struct exynos_pcie_clk_res { |
@@ -112,8 +68,6 @@ struct exynos_pcie { | |||
112 | const struct exynos_pcie_ops *ops; | 68 | const struct exynos_pcie_ops *ops; |
113 | int reset_gpio; | 69 | int reset_gpio; |
114 | 70 | ||
115 | /* For Generic PHY Framework */ | ||
116 | bool using_phy; | ||
117 | struct phy *phy; | 71 | struct phy *phy; |
118 | }; | 72 | }; |
119 | 73 | ||
@@ -141,20 +95,6 @@ static int exynos5440_pcie_get_mem_resources(struct platform_device *pdev, | |||
141 | if (IS_ERR(ep->mem_res->elbi_base)) | 95 | if (IS_ERR(ep->mem_res->elbi_base)) |
142 | return PTR_ERR(ep->mem_res->elbi_base); | 96 | return PTR_ERR(ep->mem_res->elbi_base); |
143 | 97 | ||
144 | /* If using the PHY framework, doesn't need to get other resource */ | ||
145 | if (ep->using_phy) | ||
146 | return 0; | ||
147 | |||
148 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
149 | ep->mem_res->phy_base = devm_ioremap_resource(dev, res); | ||
150 | if (IS_ERR(ep->mem_res->phy_base)) | ||
151 | return PTR_ERR(ep->mem_res->phy_base); | ||
152 | |||
153 | res = platform_get_resource(pdev, IORESOURCE_MEM, 2); | ||
154 | ep->mem_res->block_base = devm_ioremap_resource(dev, res); | ||
155 | if (IS_ERR(ep->mem_res->block_base)) | ||
156 | return PTR_ERR(ep->mem_res->block_base); | ||
157 | |||
158 | return 0; | 98 | return 0; |
159 | } | 99 | } |
160 | 100 | ||
@@ -279,111 +219,6 @@ static void exynos_pcie_deassert_core_reset(struct exynos_pcie *ep) | |||
279 | exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_NONSTICKY_RESET); | 219 | exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_NONSTICKY_RESET); |
280 | exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_APP_INIT_RESET); | 220 | exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_APP_INIT_RESET); |
281 | exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_APP_INIT_RESET); | 221 | exynos_pcie_writel(ep->mem_res->elbi_base, 0, PCIE_APP_INIT_RESET); |
282 | exynos_pcie_writel(ep->mem_res->block_base, 1, PCIE_PHY_MAC_RESET); | ||
283 | } | ||
284 | |||
285 | static void exynos_pcie_assert_phy_reset(struct exynos_pcie *ep) | ||
286 | { | ||
287 | exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_MAC_RESET); | ||
288 | exynos_pcie_writel(ep->mem_res->block_base, 1, PCIE_PHY_GLOBAL_RESET); | ||
289 | } | ||
290 | |||
291 | static void exynos_pcie_deassert_phy_reset(struct exynos_pcie *ep) | ||
292 | { | ||
293 | exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_GLOBAL_RESET); | ||
294 | exynos_pcie_writel(ep->mem_res->elbi_base, 1, PCIE_PWR_RESET); | ||
295 | exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_COMMON_RESET); | ||
296 | exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_CMN_REG); | ||
297 | exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_TRSVREG_RESET); | ||
298 | exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_TRSV_RESET); | ||
299 | } | ||
300 | |||
301 | static void exynos_pcie_power_on_phy(struct exynos_pcie *ep) | ||
302 | { | ||
303 | u32 val; | ||
304 | |||
305 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_COMMON_POWER); | ||
306 | val &= ~PCIE_PHY_COMMON_PD_CMN; | ||
307 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_COMMON_POWER); | ||
308 | |||
309 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV0_POWER); | ||
310 | val &= ~PCIE_PHY_TRSV0_PD_TSV; | ||
311 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV0_POWER); | ||
312 | |||
313 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV1_POWER); | ||
314 | val &= ~PCIE_PHY_TRSV1_PD_TSV; | ||
315 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV1_POWER); | ||
316 | |||
317 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV2_POWER); | ||
318 | val &= ~PCIE_PHY_TRSV2_PD_TSV; | ||
319 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV2_POWER); | ||
320 | |||
321 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV3_POWER); | ||
322 | val &= ~PCIE_PHY_TRSV3_PD_TSV; | ||
323 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV3_POWER); | ||
324 | } | ||
325 | |||
326 | static void exynos_pcie_power_off_phy(struct exynos_pcie *ep) | ||
327 | { | ||
328 | u32 val; | ||
329 | |||
330 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_COMMON_POWER); | ||
331 | val |= PCIE_PHY_COMMON_PD_CMN; | ||
332 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_COMMON_POWER); | ||
333 | |||
334 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV0_POWER); | ||
335 | val |= PCIE_PHY_TRSV0_PD_TSV; | ||
336 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV0_POWER); | ||
337 | |||
338 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV1_POWER); | ||
339 | val |= PCIE_PHY_TRSV1_PD_TSV; | ||
340 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV1_POWER); | ||
341 | |||
342 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV2_POWER); | ||
343 | val |= PCIE_PHY_TRSV2_PD_TSV; | ||
344 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV2_POWER); | ||
345 | |||
346 | val = exynos_pcie_readl(ep->mem_res->phy_base, PCIE_PHY_TRSV3_POWER); | ||
347 | val |= PCIE_PHY_TRSV3_PD_TSV; | ||
348 | exynos_pcie_writel(ep->mem_res->phy_base, val, PCIE_PHY_TRSV3_POWER); | ||
349 | } | ||
350 | |||
351 | static void exynos_pcie_init_phy(struct exynos_pcie *ep) | ||
352 | { | ||
353 | /* DCC feedback control off */ | ||
354 | exynos_pcie_writel(ep->mem_res->phy_base, 0x29, PCIE_PHY_DCC_FEEDBACK); | ||
355 | |||
356 | /* set TX/RX impedance */ | ||
357 | exynos_pcie_writel(ep->mem_res->phy_base, 0xd5, PCIE_PHY_IMPEDANCE); | ||
358 | |||
359 | /* set 50Mhz PHY clock */ | ||
360 | exynos_pcie_writel(ep->mem_res->phy_base, 0x14, PCIE_PHY_PLL_DIV_0); | ||
361 | exynos_pcie_writel(ep->mem_res->phy_base, 0x12, PCIE_PHY_PLL_DIV_1); | ||
362 | |||
363 | /* set TX Differential output for lane 0 */ | ||
364 | exynos_pcie_writel(ep->mem_res->phy_base, 0x7f, PCIE_PHY_TRSV0_DRV_LVL); | ||
365 | |||
366 | /* set TX Pre-emphasis Level Control for lane 0 to minimum */ | ||
367 | exynos_pcie_writel(ep->mem_res->phy_base, 0x0, PCIE_PHY_TRSV0_EMP_LVL); | ||
368 | |||
369 | /* set RX clock and data recovery bandwidth */ | ||
370 | exynos_pcie_writel(ep->mem_res->phy_base, 0xe7, PCIE_PHY_PLL_BIAS); | ||
371 | exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV0_RXCDR); | ||
372 | exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV1_RXCDR); | ||
373 | exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV2_RXCDR); | ||
374 | exynos_pcie_writel(ep->mem_res->phy_base, 0x82, PCIE_PHY_TRSV3_RXCDR); | ||
375 | |||
376 | /* change TX Pre-emphasis Level Control for lanes */ | ||
377 | exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV0_EMP_LVL); | ||
378 | exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV1_EMP_LVL); | ||
379 | exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV2_EMP_LVL); | ||
380 | exynos_pcie_writel(ep->mem_res->phy_base, 0x39, PCIE_PHY_TRSV3_EMP_LVL); | ||
381 | |||
382 | /* set LVCC */ | ||
383 | exynos_pcie_writel(ep->mem_res->phy_base, 0x20, PCIE_PHY_TRSV0_LVCC); | ||
384 | exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV1_LVCC); | ||
385 | exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV2_LVCC); | ||
386 | exynos_pcie_writel(ep->mem_res->phy_base, 0xa0, PCIE_PHY_TRSV3_LVCC); | ||
387 | } | 222 | } |
388 | 223 | ||
389 | static void exynos_pcie_assert_reset(struct exynos_pcie *ep) | 224 | static void exynos_pcie_assert_reset(struct exynos_pcie *ep) |
@@ -401,7 +236,6 @@ static int exynos_pcie_establish_link(struct exynos_pcie *ep) | |||
401 | struct dw_pcie *pci = ep->pci; | 236 | struct dw_pcie *pci = ep->pci; |
402 | struct pcie_port *pp = &pci->pp; | 237 | struct pcie_port *pp = &pci->pp; |
403 | struct device *dev = pci->dev; | 238 | struct device *dev = pci->dev; |
404 | u32 val; | ||
405 | 239 | ||
406 | if (dw_pcie_link_up(pci)) { | 240 | if (dw_pcie_link_up(pci)) { |
407 | dev_err(dev, "Link already up\n"); | 241 | dev_err(dev, "Link already up\n"); |
@@ -410,32 +244,13 @@ static int exynos_pcie_establish_link(struct exynos_pcie *ep) | |||
410 | 244 | ||
411 | exynos_pcie_assert_core_reset(ep); | 245 | exynos_pcie_assert_core_reset(ep); |
412 | 246 | ||
413 | if (ep->using_phy) { | 247 | phy_reset(ep->phy); |
414 | phy_reset(ep->phy); | ||
415 | |||
416 | exynos_pcie_writel(ep->mem_res->elbi_base, 1, | ||
417 | PCIE_PWR_RESET); | ||
418 | |||
419 | phy_power_on(ep->phy); | ||
420 | phy_init(ep->phy); | ||
421 | } else { | ||
422 | exynos_pcie_assert_phy_reset(ep); | ||
423 | exynos_pcie_deassert_phy_reset(ep); | ||
424 | exynos_pcie_power_on_phy(ep); | ||
425 | exynos_pcie_init_phy(ep); | ||
426 | |||
427 | /* pulse for common reset */ | ||
428 | exynos_pcie_writel(ep->mem_res->block_base, 1, | ||
429 | PCIE_PHY_COMMON_RESET); | ||
430 | udelay(500); | ||
431 | exynos_pcie_writel(ep->mem_res->block_base, 0, | ||
432 | PCIE_PHY_COMMON_RESET); | ||
433 | } | ||
434 | 248 | ||
435 | /* pulse for common reset */ | 249 | exynos_pcie_writel(ep->mem_res->elbi_base, 1, |
436 | exynos_pcie_writel(ep->mem_res->block_base, 1, PCIE_PHY_COMMON_RESET); | 250 | PCIE_PWR_RESET); |
437 | udelay(500); | 251 | |
438 | exynos_pcie_writel(ep->mem_res->block_base, 0, PCIE_PHY_COMMON_RESET); | 252 | phy_power_on(ep->phy); |
253 | phy_init(ep->phy); | ||
439 | 254 | ||
440 | exynos_pcie_deassert_core_reset(ep); | 255 | exynos_pcie_deassert_core_reset(ep); |
441 | dw_pcie_setup_rc(pp); | 256 | dw_pcie_setup_rc(pp); |
@@ -449,18 +264,7 @@ static int exynos_pcie_establish_link(struct exynos_pcie *ep) | |||
449 | if (!dw_pcie_wait_for_link(pci)) | 264 | if (!dw_pcie_wait_for_link(pci)) |
450 | return 0; | 265 | return 0; |
451 | 266 | ||
452 | if (ep->using_phy) { | 267 | phy_power_off(ep->phy); |
453 | phy_power_off(ep->phy); | ||
454 | return -ETIMEDOUT; | ||
455 | } | ||
456 | |||
457 | while (exynos_pcie_readl(ep->mem_res->phy_base, | ||
458 | PCIE_PHY_PLL_LOCKED) == 0) { | ||
459 | val = exynos_pcie_readl(ep->mem_res->block_base, | ||
460 | PCIE_PHY_PLL_LOCKED); | ||
461 | dev_info(dev, "PLL Locked: 0x%x\n", val); | ||
462 | } | ||
463 | exynos_pcie_power_off_phy(ep); | ||
464 | return -ETIMEDOUT; | 268 | return -ETIMEDOUT; |
465 | } | 269 | } |
466 | 270 | ||
@@ -678,16 +482,13 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) | |||
678 | 482 | ||
679 | ep->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); | 483 | ep->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); |
680 | 484 | ||
681 | /* Assume that controller doesn't use the PHY framework */ | ||
682 | ep->using_phy = false; | ||
683 | |||
684 | ep->phy = devm_of_phy_get(dev, np, NULL); | 485 | ep->phy = devm_of_phy_get(dev, np, NULL); |
685 | if (IS_ERR(ep->phy)) { | 486 | if (IS_ERR(ep->phy)) { |
686 | if (PTR_ERR(ep->phy) == -EPROBE_DEFER) | 487 | if (PTR_ERR(ep->phy) == -EPROBE_DEFER) |
687 | return PTR_ERR(ep->phy); | 488 | return PTR_ERR(ep->phy); |
688 | dev_warn(dev, "Use the 'phy' property. Current DT of pci-exynos was deprecated!!\n"); | 489 | |
689 | } else | 490 | ep->phy = NULL; |
690 | ep->using_phy = true; | 491 | } |
691 | 492 | ||
692 | if (ep->ops && ep->ops->get_mem_resources) { | 493 | if (ep->ops && ep->ops->get_mem_resources) { |
693 | ret = ep->ops->get_mem_resources(pdev, ep); | 494 | ret = ep->ops->get_mem_resources(pdev, ep); |
@@ -695,7 +496,8 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) | |||
695 | return ret; | 496 | return ret; |
696 | } | 497 | } |
697 | 498 | ||
698 | if (ep->ops && ep->ops->get_clk_resources) { | 499 | if (ep->ops && ep->ops->get_clk_resources && |
500 | ep->ops->init_clk_resources) { | ||
699 | ret = ep->ops->get_clk_resources(ep); | 501 | ret = ep->ops->get_clk_resources(ep); |
700 | if (ret) | 502 | if (ret) |
701 | return ret; | 503 | return ret; |
@@ -713,8 +515,7 @@ static int __init exynos_pcie_probe(struct platform_device *pdev) | |||
713 | return 0; | 515 | return 0; |
714 | 516 | ||
715 | fail_probe: | 517 | fail_probe: |
716 | if (ep->using_phy) | 518 | phy_exit(ep->phy); |
717 | phy_exit(ep->phy); | ||
718 | 519 | ||
719 | if (ep->ops && ep->ops->deinit_clk_resources) | 520 | if (ep->ops && ep->ops->deinit_clk_resources) |
720 | ep->ops->deinit_clk_resources(ep); | 521 | ep->ops->deinit_clk_resources(ep); |
diff --git a/drivers/pci/dwc/pci-imx6.c b/drivers/pci/dwc/pci-imx6.c index b73483534a5b..4fddbd08b089 100644 --- a/drivers/pci/dwc/pci-imx6.c +++ b/drivers/pci/dwc/pci-imx6.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * PCIe host controller driver for Freescale i.MX6 SoCs | 3 | * PCIe host controller driver for Freescale i.MX6 SoCs |
3 | * | 4 | * |
@@ -5,10 +6,6 @@ | |||
5 | * http://www.kosagi.com | 6 | * http://www.kosagi.com |
6 | * | 7 | * |
7 | * Author: Sean Cross <xobs@kosagi.com> | 8 | * Author: Sean Cross <xobs@kosagi.com> |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | 9 | */ |
13 | 10 | ||
14 | #include <linux/clk.h> | 11 | #include <linux/clk.h> |
diff --git a/drivers/pci/dwc/pci-keystone-dw.c b/drivers/pci/dwc/pci-keystone-dw.c index 2fb20b887d2a..99a0e7076221 100644 --- a/drivers/pci/dwc/pci-keystone-dw.c +++ b/drivers/pci/dwc/pci-keystone-dw.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * DesignWare application register space functions for Keystone PCI controller | 3 | * DesignWare application register space functions for Keystone PCI controller |
3 | * | 4 | * |
@@ -5,11 +6,6 @@ | |||
5 | * http://www.ti.com | 6 | * http://www.ti.com |
6 | * | 7 | * |
7 | * Author: Murali Karicheri <m-karicheri2@ti.com> | 8 | * Author: Murali Karicheri <m-karicheri2@ti.com> |
8 | * | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | 9 | */ |
14 | 10 | ||
15 | #include <linux/irq.h> | 11 | #include <linux/irq.h> |
diff --git a/drivers/pci/dwc/pci-keystone.c b/drivers/pci/dwc/pci-keystone.c index 5bee3af47588..d4f8ab90c018 100644 --- a/drivers/pci/dwc/pci-keystone.c +++ b/drivers/pci/dwc/pci-keystone.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * PCIe host controller driver for Texas Instruments Keystone SoCs | 3 | * PCIe host controller driver for Texas Instruments Keystone SoCs |
3 | * | 4 | * |
@@ -6,10 +7,6 @@ | |||
6 | * | 7 | * |
7 | * Author: Murali Karicheri <m-karicheri2@ti.com> | 8 | * Author: Murali Karicheri <m-karicheri2@ti.com> |
8 | * Implementation based on pci-exynos.c and pcie-designware.c | 9 | * Implementation based on pci-exynos.c and pcie-designware.c |
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | 10 | */ |
14 | 11 | ||
15 | #include <linux/irqchip/chained_irq.h> | 12 | #include <linux/irqchip/chained_irq.h> |
@@ -178,7 +175,7 @@ static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie, | |||
178 | } | 175 | } |
179 | 176 | ||
180 | /* interrupt controller is in a child node */ | 177 | /* interrupt controller is in a child node */ |
181 | *np_temp = of_find_node_by_name(np_pcie, controller); | 178 | *np_temp = of_get_child_by_name(np_pcie, controller); |
182 | if (!(*np_temp)) { | 179 | if (!(*np_temp)) { |
183 | dev_err(dev, "Node for %s is absent\n", controller); | 180 | dev_err(dev, "Node for %s is absent\n", controller); |
184 | return -EINVAL; | 181 | return -EINVAL; |
@@ -187,6 +184,7 @@ static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie, | |||
187 | temp = of_irq_count(*np_temp); | 184 | temp = of_irq_count(*np_temp); |
188 | if (!temp) { | 185 | if (!temp) { |
189 | dev_err(dev, "No IRQ entries in %s\n", controller); | 186 | dev_err(dev, "No IRQ entries in %s\n", controller); |
187 | of_node_put(*np_temp); | ||
190 | return -EINVAL; | 188 | return -EINVAL; |
191 | } | 189 | } |
192 | 190 | ||
@@ -204,6 +202,8 @@ static int ks_pcie_get_irq_controller_info(struct keystone_pcie *ks_pcie, | |||
204 | break; | 202 | break; |
205 | } | 203 | } |
206 | 204 | ||
205 | of_node_put(*np_temp); | ||
206 | |||
207 | if (temp) { | 207 | if (temp) { |
208 | *num_irqs = temp; | 208 | *num_irqs = temp; |
209 | return 0; | 209 | return 0; |
diff --git a/drivers/pci/dwc/pci-keystone.h b/drivers/pci/dwc/pci-keystone.h index 30b7bc2ac380..1dd1f3ef98e7 100644 --- a/drivers/pci/dwc/pci-keystone.h +++ b/drivers/pci/dwc/pci-keystone.h | |||
@@ -1,3 +1,4 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Keystone PCI Controller's common includes | 3 | * Keystone PCI Controller's common includes |
3 | * | 4 | * |
@@ -5,11 +6,6 @@ | |||
5 | * http://www.ti.com | 6 | * http://www.ti.com |
6 | * | 7 | * |
7 | * Author: Murali Karicheri <m-karicheri2@ti.com> | 8 | * Author: Murali Karicheri <m-karicheri2@ti.com> |
8 | * | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | 9 | */ |
14 | 10 | ||
15 | #define MAX_MSI_HOST_IRQS 8 | 11 | #define MAX_MSI_HOST_IRQS 8 |
diff --git a/drivers/pci/dwc/pci-layerscape.c b/drivers/pci/dwc/pci-layerscape.c index 8f34c2fdc600..a7b4159631ae 100644 --- a/drivers/pci/dwc/pci-layerscape.c +++ b/drivers/pci/dwc/pci-layerscape.c | |||
@@ -1,13 +1,10 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * PCIe host controller driver for Freescale Layerscape SoCs | 3 | * PCIe host controller driver for Freescale Layerscape SoCs |
3 | * | 4 | * |
4 | * Copyright (C) 2014 Freescale Semiconductor. | 5 | * Copyright (C) 2014 Freescale Semiconductor. |
5 | * | 6 | * |
6 | * Author: Minghuan Lian <Minghuan.Lian@freescale.com> | 7 | * Author: Minghuan Lian <Minghuan.Lian@freescale.com> |
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | 8 | */ |
12 | 9 | ||
13 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
diff --git a/drivers/pci/dwc/pcie-armada8k.c b/drivers/pci/dwc/pcie-armada8k.c index 370d057c0046..b587352f8b9f 100644 --- a/drivers/pci/dwc/pcie-armada8k.c +++ b/drivers/pci/dwc/pcie-armada8k.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * PCIe host controller driver for Marvell Armada-8K SoCs | 3 | * PCIe host controller driver for Marvell Armada-8K SoCs |
3 | * | 4 | * |
@@ -7,10 +8,6 @@ | |||
7 | * | 8 | * |
8 | * Author: Yehuda Yitshak <yehuday@marvell.com> | 9 | * Author: Yehuda Yitshak <yehuday@marvell.com> |
9 | * Author: Shadi Ammouri <shadi@marvell.com> | 10 | * Author: Shadi Ammouri <shadi@marvell.com> |
10 | * | ||
11 | * This file is licensed under the terms of the GNU General Public | ||
12 | * License version 2. This program is licensed "as is" without any | ||
13 | * warranty of any kind, whether express or implied. | ||
14 | */ | 11 | */ |
15 | 12 | ||
16 | #include <linux/clk.h> | 13 | #include <linux/clk.h> |
diff --git a/drivers/pci/dwc/pcie-artpec6.c b/drivers/pci/dwc/pcie-artpec6.c index 6653619db6a1..93b3df9ed1b5 100644 --- a/drivers/pci/dwc/pcie-artpec6.c +++ b/drivers/pci/dwc/pcie-artpec6.c | |||
@@ -1,18 +1,16 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * PCIe host controller driver for Axis ARTPEC-6 SoC | 3 | * PCIe host controller driver for Axis ARTPEC-6 SoC |
3 | * | 4 | * |
4 | * Author: Niklas Cassel <niklas.cassel@axis.com> | 5 | * Author: Niklas Cassel <niklas.cassel@axis.com> |
5 | * | 6 | * |
6 | * Based on work done by Phil Edworthy <phil@edworthys.org> | 7 | * Based on work done by Phil Edworthy <phil@edworthys.org> |
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | 8 | */ |
12 | 9 | ||
13 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
14 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
15 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/of_device.h> | ||
16 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
17 | #include <linux/platform_device.h> | 15 | #include <linux/platform_device.h> |
18 | #include <linux/resource.h> | 16 | #include <linux/resource.h> |
@@ -26,44 +24,72 @@ | |||
26 | 24 | ||
27 | #define to_artpec6_pcie(x) dev_get_drvdata((x)->dev) | 25 | #define to_artpec6_pcie(x) dev_get_drvdata((x)->dev) |
28 | 26 | ||
27 | enum artpec_pcie_variants { | ||
28 | ARTPEC6, | ||
29 | ARTPEC7, | ||
30 | }; | ||
31 | |||
29 | struct artpec6_pcie { | 32 | struct artpec6_pcie { |
30 | struct dw_pcie *pci; | 33 | struct dw_pcie *pci; |
31 | struct regmap *regmap; /* DT axis,syscon-pcie */ | 34 | struct regmap *regmap; /* DT axis,syscon-pcie */ |
32 | void __iomem *phy_base; /* DT phy */ | 35 | void __iomem *phy_base; /* DT phy */ |
36 | enum artpec_pcie_variants variant; | ||
37 | enum dw_pcie_device_mode mode; | ||
33 | }; | 38 | }; |
34 | 39 | ||
40 | struct artpec_pcie_of_data { | ||
41 | enum artpec_pcie_variants variant; | ||
42 | enum dw_pcie_device_mode mode; | ||
43 | }; | ||
44 | |||
45 | static const struct of_device_id artpec6_pcie_of_match[]; | ||
46 | |||
35 | /* PCIe Port Logic registers (memory-mapped) */ | 47 | /* PCIe Port Logic registers (memory-mapped) */ |
36 | #define PL_OFFSET 0x700 | 48 | #define PL_OFFSET 0x700 |
37 | #define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28) | ||
38 | #define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c) | ||
39 | 49 | ||
40 | #define MISC_CONTROL_1_OFF (PL_OFFSET + 0x1bc) | 50 | #define ACK_F_ASPM_CTRL_OFF (PL_OFFSET + 0xc) |
41 | #define DBI_RO_WR_EN 1 | 51 | #define ACK_N_FTS_MASK GENMASK(15, 8) |
52 | #define ACK_N_FTS(x) (((x) << 8) & ACK_N_FTS_MASK) | ||
53 | |||
54 | #define FAST_TRAINING_SEQ_MASK GENMASK(7, 0) | ||
55 | #define FAST_TRAINING_SEQ(x) (((x) << 0) & FAST_TRAINING_SEQ_MASK) | ||
42 | 56 | ||
43 | /* ARTPEC-6 specific registers */ | 57 | /* ARTPEC-6 specific registers */ |
44 | #define PCIECFG 0x18 | 58 | #define PCIECFG 0x18 |
45 | #define PCIECFG_DBG_OEN (1 << 24) | 59 | #define PCIECFG_DBG_OEN BIT(24) |
46 | #define PCIECFG_CORE_RESET_REQ (1 << 21) | 60 | #define PCIECFG_CORE_RESET_REQ BIT(21) |
47 | #define PCIECFG_LTSSM_ENABLE (1 << 20) | 61 | #define PCIECFG_LTSSM_ENABLE BIT(20) |
48 | #define PCIECFG_CLKREQ_B (1 << 11) | 62 | #define PCIECFG_DEVICE_TYPE_MASK GENMASK(19, 16) |
49 | #define PCIECFG_REFCLK_ENABLE (1 << 10) | 63 | #define PCIECFG_CLKREQ_B BIT(11) |
50 | #define PCIECFG_PLL_ENABLE (1 << 9) | 64 | #define PCIECFG_REFCLK_ENABLE BIT(10) |
51 | #define PCIECFG_PCLK_ENABLE (1 << 8) | 65 | #define PCIECFG_PLL_ENABLE BIT(9) |
52 | #define PCIECFG_RISRCREN (1 << 4) | 66 | #define PCIECFG_PCLK_ENABLE BIT(8) |
53 | #define PCIECFG_MODE_TX_DRV_EN (1 << 3) | 67 | #define PCIECFG_RISRCREN BIT(4) |
54 | #define PCIECFG_CISRREN (1 << 2) | 68 | #define PCIECFG_MODE_TX_DRV_EN BIT(3) |
55 | #define PCIECFG_MACRO_ENABLE (1 << 0) | 69 | #define PCIECFG_CISRREN BIT(2) |
70 | #define PCIECFG_MACRO_ENABLE BIT(0) | ||
71 | /* ARTPEC-7 specific fields */ | ||
72 | #define PCIECFG_REFCLKSEL BIT(23) | ||
73 | #define PCIECFG_NOC_RESET BIT(3) | ||
74 | |||
75 | #define PCIESTAT 0x1c | ||
76 | /* ARTPEC-7 specific fields */ | ||
77 | #define PCIESTAT_EXTREFCLK BIT(3) | ||
56 | 78 | ||
57 | #define NOCCFG 0x40 | 79 | #define NOCCFG 0x40 |
58 | #define NOCCFG_ENABLE_CLK_PCIE (1 << 4) | 80 | #define NOCCFG_ENABLE_CLK_PCIE BIT(4) |
59 | #define NOCCFG_POWER_PCIE_IDLEACK (1 << 3) | 81 | #define NOCCFG_POWER_PCIE_IDLEACK BIT(3) |
60 | #define NOCCFG_POWER_PCIE_IDLE (1 << 2) | 82 | #define NOCCFG_POWER_PCIE_IDLE BIT(2) |
61 | #define NOCCFG_POWER_PCIE_IDLEREQ (1 << 1) | 83 | #define NOCCFG_POWER_PCIE_IDLEREQ BIT(1) |
62 | 84 | ||
63 | #define PHY_STATUS 0x118 | 85 | #define PHY_STATUS 0x118 |
64 | #define PHY_COSPLLLOCK (1 << 0) | 86 | #define PHY_COSPLLLOCK BIT(0) |
87 | |||
88 | #define PHY_TX_ASIC_OUT 0x4040 | ||
89 | #define PHY_TX_ASIC_OUT_TX_ACK BIT(0) | ||
65 | 90 | ||
66 | #define ARTPEC6_CPU_TO_BUS_ADDR 0x0fffffff | 91 | #define PHY_RX_ASIC_OUT 0x405c |
92 | #define PHY_RX_ASIC_OUT_ACK BIT(0) | ||
67 | 93 | ||
68 | static u32 artpec6_pcie_readl(struct artpec6_pcie *artpec6_pcie, u32 offset) | 94 | static u32 artpec6_pcie_readl(struct artpec6_pcie *artpec6_pcie, u32 offset) |
69 | { | 95 | { |
@@ -78,22 +104,123 @@ static void artpec6_pcie_writel(struct artpec6_pcie *artpec6_pcie, u32 offset, u | |||
78 | regmap_write(artpec6_pcie->regmap, offset, val); | 104 | regmap_write(artpec6_pcie->regmap, offset, val); |
79 | } | 105 | } |
80 | 106 | ||
81 | static u64 artpec6_pcie_cpu_addr_fixup(u64 pci_addr) | 107 | static u64 artpec6_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 pci_addr) |
82 | { | 108 | { |
83 | return pci_addr & ARTPEC6_CPU_TO_BUS_ADDR; | 109 | struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); |
110 | struct pcie_port *pp = &pci->pp; | ||
111 | struct dw_pcie_ep *ep = &pci->ep; | ||
112 | |||
113 | switch (artpec6_pcie->mode) { | ||
114 | case DW_PCIE_RC_TYPE: | ||
115 | return pci_addr - pp->cfg0_base; | ||
116 | case DW_PCIE_EP_TYPE: | ||
117 | return pci_addr - ep->phys_base; | ||
118 | default: | ||
119 | dev_err(pci->dev, "UNKNOWN device type\n"); | ||
120 | } | ||
121 | return pci_addr; | ||
84 | } | 122 | } |
85 | 123 | ||
86 | static int artpec6_pcie_establish_link(struct artpec6_pcie *artpec6_pcie) | 124 | static int artpec6_pcie_establish_link(struct dw_pcie *pci) |
87 | { | 125 | { |
88 | struct dw_pcie *pci = artpec6_pcie->pci; | 126 | struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); |
89 | struct pcie_port *pp = &pci->pp; | 127 | u32 val; |
128 | |||
129 | val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); | ||
130 | val |= PCIECFG_LTSSM_ENABLE; | ||
131 | artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static void artpec6_pcie_stop_link(struct dw_pcie *pci) | ||
137 | { | ||
138 | struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); | ||
90 | u32 val; | 139 | u32 val; |
91 | unsigned int retries; | ||
92 | 140 | ||
93 | /* Hold DW core in reset */ | ||
94 | val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); | 141 | val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); |
95 | val |= PCIECFG_CORE_RESET_REQ; | 142 | val &= ~PCIECFG_LTSSM_ENABLE; |
96 | artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); | 143 | artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); |
144 | } | ||
145 | |||
146 | static const struct dw_pcie_ops dw_pcie_ops = { | ||
147 | .cpu_addr_fixup = artpec6_pcie_cpu_addr_fixup, | ||
148 | .start_link = artpec6_pcie_establish_link, | ||
149 | .stop_link = artpec6_pcie_stop_link, | ||
150 | }; | ||
151 | |||
152 | static void artpec6_pcie_wait_for_phy_a6(struct artpec6_pcie *artpec6_pcie) | ||
153 | { | ||
154 | struct dw_pcie *pci = artpec6_pcie->pci; | ||
155 | struct device *dev = pci->dev; | ||
156 | u32 val; | ||
157 | unsigned int retries; | ||
158 | |||
159 | retries = 50; | ||
160 | do { | ||
161 | usleep_range(1000, 2000); | ||
162 | val = artpec6_pcie_readl(artpec6_pcie, NOCCFG); | ||
163 | retries--; | ||
164 | } while (retries && | ||
165 | (val & (NOCCFG_POWER_PCIE_IDLEACK | NOCCFG_POWER_PCIE_IDLE))); | ||
166 | if (!retries) | ||
167 | dev_err(dev, "PCIe clock manager did not leave idle state\n"); | ||
168 | |||
169 | retries = 50; | ||
170 | do { | ||
171 | usleep_range(1000, 2000); | ||
172 | val = readl(artpec6_pcie->phy_base + PHY_STATUS); | ||
173 | retries--; | ||
174 | } while (retries && !(val & PHY_COSPLLLOCK)); | ||
175 | if (!retries) | ||
176 | dev_err(dev, "PHY PLL did not lock\n"); | ||
177 | } | ||
178 | |||
179 | static void artpec6_pcie_wait_for_phy_a7(struct artpec6_pcie *artpec6_pcie) | ||
180 | { | ||
181 | struct dw_pcie *pci = artpec6_pcie->pci; | ||
182 | struct device *dev = pci->dev; | ||
183 | u32 val; | ||
184 | u16 phy_status_tx, phy_status_rx; | ||
185 | unsigned int retries; | ||
186 | |||
187 | retries = 50; | ||
188 | do { | ||
189 | usleep_range(1000, 2000); | ||
190 | val = artpec6_pcie_readl(artpec6_pcie, NOCCFG); | ||
191 | retries--; | ||
192 | } while (retries && | ||
193 | (val & (NOCCFG_POWER_PCIE_IDLEACK | NOCCFG_POWER_PCIE_IDLE))); | ||
194 | if (!retries) | ||
195 | dev_err(dev, "PCIe clock manager did not leave idle state\n"); | ||
196 | |||
197 | retries = 50; | ||
198 | do { | ||
199 | usleep_range(1000, 2000); | ||
200 | phy_status_tx = readw(artpec6_pcie->phy_base + PHY_TX_ASIC_OUT); | ||
201 | phy_status_rx = readw(artpec6_pcie->phy_base + PHY_RX_ASIC_OUT); | ||
202 | retries--; | ||
203 | } while (retries && ((phy_status_tx & PHY_TX_ASIC_OUT_TX_ACK) || | ||
204 | (phy_status_rx & PHY_RX_ASIC_OUT_ACK))); | ||
205 | if (!retries) | ||
206 | dev_err(dev, "PHY did not enter Pn state\n"); | ||
207 | } | ||
208 | |||
209 | static void artpec6_pcie_wait_for_phy(struct artpec6_pcie *artpec6_pcie) | ||
210 | { | ||
211 | switch (artpec6_pcie->variant) { | ||
212 | case ARTPEC6: | ||
213 | artpec6_pcie_wait_for_phy_a6(artpec6_pcie); | ||
214 | break; | ||
215 | case ARTPEC7: | ||
216 | artpec6_pcie_wait_for_phy_a7(artpec6_pcie); | ||
217 | break; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | static void artpec6_pcie_init_phy_a6(struct artpec6_pcie *artpec6_pcie) | ||
222 | { | ||
223 | u32 val; | ||
97 | 224 | ||
98 | val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); | 225 | val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); |
99 | val |= PCIECFG_RISRCREN | /* Receiver term. 50 Ohm */ | 226 | val |= PCIECFG_RISRCREN | /* Receiver term. 50 Ohm */ |
@@ -119,45 +246,110 @@ static int artpec6_pcie_establish_link(struct artpec6_pcie *artpec6_pcie) | |||
119 | val = artpec6_pcie_readl(artpec6_pcie, NOCCFG); | 246 | val = artpec6_pcie_readl(artpec6_pcie, NOCCFG); |
120 | val &= ~NOCCFG_POWER_PCIE_IDLEREQ; | 247 | val &= ~NOCCFG_POWER_PCIE_IDLEREQ; |
121 | artpec6_pcie_writel(artpec6_pcie, NOCCFG, val); | 248 | artpec6_pcie_writel(artpec6_pcie, NOCCFG, val); |
249 | } | ||
122 | 250 | ||
123 | retries = 50; | 251 | static void artpec6_pcie_init_phy_a7(struct artpec6_pcie *artpec6_pcie) |
124 | do { | 252 | { |
125 | usleep_range(1000, 2000); | 253 | struct dw_pcie *pci = artpec6_pcie->pci; |
126 | val = artpec6_pcie_readl(artpec6_pcie, NOCCFG); | 254 | u32 val; |
127 | retries--; | 255 | bool extrefclk; |
128 | } while (retries && | ||
129 | (val & (NOCCFG_POWER_PCIE_IDLEACK | NOCCFG_POWER_PCIE_IDLE))); | ||
130 | 256 | ||
131 | retries = 50; | 257 | /* Check if external reference clock is connected */ |
132 | do { | 258 | val = artpec6_pcie_readl(artpec6_pcie, PCIESTAT); |
133 | usleep_range(1000, 2000); | 259 | extrefclk = !!(val & PCIESTAT_EXTREFCLK); |
134 | val = readl(artpec6_pcie->phy_base + PHY_STATUS); | 260 | dev_dbg(pci->dev, "Using reference clock: %s\n", |
135 | retries--; | 261 | extrefclk ? "external" : "internal"); |
136 | } while (retries && !(val & PHY_COSPLLLOCK)); | ||
137 | 262 | ||
138 | /* Take DW core out of reset */ | ||
139 | val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); | 263 | val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); |
140 | val &= ~PCIECFG_CORE_RESET_REQ; | 264 | val |= PCIECFG_RISRCREN | /* Receiver term. 50 Ohm */ |
265 | PCIECFG_PCLK_ENABLE; | ||
266 | if (extrefclk) | ||
267 | val |= PCIECFG_REFCLKSEL; | ||
268 | else | ||
269 | val &= ~PCIECFG_REFCLKSEL; | ||
141 | artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); | 270 | artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); |
142 | usleep_range(100, 200); | 271 | usleep_range(10, 20); |
143 | 272 | ||
144 | /* setup root complex */ | 273 | val = artpec6_pcie_readl(artpec6_pcie, NOCCFG); |
145 | dw_pcie_setup_rc(pp); | 274 | val |= NOCCFG_ENABLE_CLK_PCIE; |
275 | artpec6_pcie_writel(artpec6_pcie, NOCCFG, val); | ||
276 | usleep_range(20, 30); | ||
277 | |||
278 | val = artpec6_pcie_readl(artpec6_pcie, NOCCFG); | ||
279 | val &= ~NOCCFG_POWER_PCIE_IDLEREQ; | ||
280 | artpec6_pcie_writel(artpec6_pcie, NOCCFG, val); | ||
281 | } | ||
282 | |||
283 | static void artpec6_pcie_init_phy(struct artpec6_pcie *artpec6_pcie) | ||
284 | { | ||
285 | switch (artpec6_pcie->variant) { | ||
286 | case ARTPEC6: | ||
287 | artpec6_pcie_init_phy_a6(artpec6_pcie); | ||
288 | break; | ||
289 | case ARTPEC7: | ||
290 | artpec6_pcie_init_phy_a7(artpec6_pcie); | ||
291 | break; | ||
292 | } | ||
293 | } | ||
294 | |||
295 | static void artpec6_pcie_set_nfts(struct artpec6_pcie *artpec6_pcie) | ||
296 | { | ||
297 | struct dw_pcie *pci = artpec6_pcie->pci; | ||
298 | u32 val; | ||
299 | |||
300 | if (artpec6_pcie->variant != ARTPEC7) | ||
301 | return; | ||
302 | |||
303 | /* | ||
304 | * Increase the N_FTS (Number of Fast Training Sequences) | ||
305 | * to be transmitted when transitioning from L0s to L0. | ||
306 | */ | ||
307 | val = dw_pcie_readl_dbi(pci, ACK_F_ASPM_CTRL_OFF); | ||
308 | val &= ~ACK_N_FTS_MASK; | ||
309 | val |= ACK_N_FTS(180); | ||
310 | dw_pcie_writel_dbi(pci, ACK_F_ASPM_CTRL_OFF, val); | ||
311 | |||
312 | /* | ||
313 | * Set the Number of Fast Training Sequences that the core | ||
314 | * advertises as its N_FTS during Gen2 or Gen3 link training. | ||
315 | */ | ||
316 | val = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL); | ||
317 | val &= ~FAST_TRAINING_SEQ_MASK; | ||
318 | val |= FAST_TRAINING_SEQ(180); | ||
319 | dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val); | ||
320 | } | ||
321 | |||
322 | static void artpec6_pcie_assert_core_reset(struct artpec6_pcie *artpec6_pcie) | ||
323 | { | ||
324 | u32 val; | ||
146 | 325 | ||
147 | /* assert LTSSM enable */ | ||
148 | val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); | 326 | val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); |
149 | val |= PCIECFG_LTSSM_ENABLE; | 327 | switch (artpec6_pcie->variant) { |
328 | case ARTPEC6: | ||
329 | val |= PCIECFG_CORE_RESET_REQ; | ||
330 | break; | ||
331 | case ARTPEC7: | ||
332 | val &= ~PCIECFG_NOC_RESET; | ||
333 | break; | ||
334 | } | ||
150 | artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); | 335 | artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); |
336 | } | ||
151 | 337 | ||
152 | /* check if the link is up or not */ | 338 | static void artpec6_pcie_deassert_core_reset(struct artpec6_pcie *artpec6_pcie) |
153 | if (!dw_pcie_wait_for_link(pci)) | 339 | { |
154 | return 0; | 340 | u32 val; |
155 | |||
156 | dev_dbg(pci->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", | ||
157 | dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0), | ||
158 | dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1)); | ||
159 | 341 | ||
160 | return -ETIMEDOUT; | 342 | val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); |
343 | switch (artpec6_pcie->variant) { | ||
344 | case ARTPEC6: | ||
345 | val &= ~PCIECFG_CORE_RESET_REQ; | ||
346 | break; | ||
347 | case ARTPEC7: | ||
348 | val |= PCIECFG_NOC_RESET; | ||
349 | break; | ||
350 | } | ||
351 | artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); | ||
352 | usleep_range(100, 200); | ||
161 | } | 353 | } |
162 | 354 | ||
163 | static void artpec6_pcie_enable_interrupts(struct artpec6_pcie *artpec6_pcie) | 355 | static void artpec6_pcie_enable_interrupts(struct artpec6_pcie *artpec6_pcie) |
@@ -174,7 +366,14 @@ static int artpec6_pcie_host_init(struct pcie_port *pp) | |||
174 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | 366 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); |
175 | struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); | 367 | struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); |
176 | 368 | ||
177 | artpec6_pcie_establish_link(artpec6_pcie); | 369 | artpec6_pcie_assert_core_reset(artpec6_pcie); |
370 | artpec6_pcie_init_phy(artpec6_pcie); | ||
371 | artpec6_pcie_deassert_core_reset(artpec6_pcie); | ||
372 | artpec6_pcie_wait_for_phy(artpec6_pcie); | ||
373 | artpec6_pcie_set_nfts(artpec6_pcie); | ||
374 | dw_pcie_setup_rc(pp); | ||
375 | artpec6_pcie_establish_link(pci); | ||
376 | dw_pcie_wait_for_link(pci); | ||
178 | artpec6_pcie_enable_interrupts(artpec6_pcie); | 377 | artpec6_pcie_enable_interrupts(artpec6_pcie); |
179 | 378 | ||
180 | return 0; | 379 | return 0; |
@@ -230,10 +429,78 @@ static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie, | |||
230 | return 0; | 429 | return 0; |
231 | } | 430 | } |
232 | 431 | ||
233 | static const struct dw_pcie_ops dw_pcie_ops = { | 432 | static void artpec6_pcie_ep_init(struct dw_pcie_ep *ep) |
234 | .cpu_addr_fixup = artpec6_pcie_cpu_addr_fixup, | 433 | { |
434 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); | ||
435 | struct artpec6_pcie *artpec6_pcie = to_artpec6_pcie(pci); | ||
436 | enum pci_barno bar; | ||
437 | |||
438 | artpec6_pcie_assert_core_reset(artpec6_pcie); | ||
439 | artpec6_pcie_init_phy(artpec6_pcie); | ||
440 | artpec6_pcie_deassert_core_reset(artpec6_pcie); | ||
441 | artpec6_pcie_wait_for_phy(artpec6_pcie); | ||
442 | artpec6_pcie_set_nfts(artpec6_pcie); | ||
443 | |||
444 | for (bar = BAR_0; bar <= BAR_5; bar++) | ||
445 | dw_pcie_ep_reset_bar(pci, bar); | ||
446 | } | ||
447 | |||
448 | static int artpec6_pcie_raise_irq(struct dw_pcie_ep *ep, u8 func_no, | ||
449 | enum pci_epc_irq_type type, u8 interrupt_num) | ||
450 | { | ||
451 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); | ||
452 | |||
453 | switch (type) { | ||
454 | case PCI_EPC_IRQ_LEGACY: | ||
455 | dev_err(pci->dev, "EP cannot trigger legacy IRQs\n"); | ||
456 | return -EINVAL; | ||
457 | case PCI_EPC_IRQ_MSI: | ||
458 | return dw_pcie_ep_raise_msi_irq(ep, func_no, interrupt_num); | ||
459 | default: | ||
460 | dev_err(pci->dev, "UNKNOWN IRQ type\n"); | ||
461 | } | ||
462 | |||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | static struct dw_pcie_ep_ops pcie_ep_ops = { | ||
467 | .ep_init = artpec6_pcie_ep_init, | ||
468 | .raise_irq = artpec6_pcie_raise_irq, | ||
235 | }; | 469 | }; |
236 | 470 | ||
471 | static int artpec6_add_pcie_ep(struct artpec6_pcie *artpec6_pcie, | ||
472 | struct platform_device *pdev) | ||
473 | { | ||
474 | int ret; | ||
475 | struct dw_pcie_ep *ep; | ||
476 | struct resource *res; | ||
477 | struct device *dev = &pdev->dev; | ||
478 | struct dw_pcie *pci = artpec6_pcie->pci; | ||
479 | |||
480 | ep = &pci->ep; | ||
481 | ep->ops = &pcie_ep_ops; | ||
482 | |||
483 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi2"); | ||
484 | pci->dbi_base2 = devm_ioremap(dev, res->start, resource_size(res)); | ||
485 | if (!pci->dbi_base2) | ||
486 | return -ENOMEM; | ||
487 | |||
488 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space"); | ||
489 | if (!res) | ||
490 | return -EINVAL; | ||
491 | |||
492 | ep->phys_base = res->start; | ||
493 | ep->addr_size = resource_size(res); | ||
494 | |||
495 | ret = dw_pcie_ep_init(ep); | ||
496 | if (ret) { | ||
497 | dev_err(dev, "failed to initialize endpoint\n"); | ||
498 | return ret; | ||
499 | } | ||
500 | |||
501 | return 0; | ||
502 | } | ||
503 | |||
237 | static int artpec6_pcie_probe(struct platform_device *pdev) | 504 | static int artpec6_pcie_probe(struct platform_device *pdev) |
238 | { | 505 | { |
239 | struct device *dev = &pdev->dev; | 506 | struct device *dev = &pdev->dev; |
@@ -242,6 +509,18 @@ static int artpec6_pcie_probe(struct platform_device *pdev) | |||
242 | struct resource *dbi_base; | 509 | struct resource *dbi_base; |
243 | struct resource *phy_base; | 510 | struct resource *phy_base; |
244 | int ret; | 511 | int ret; |
512 | const struct of_device_id *match; | ||
513 | const struct artpec_pcie_of_data *data; | ||
514 | enum artpec_pcie_variants variant; | ||
515 | enum dw_pcie_device_mode mode; | ||
516 | |||
517 | match = of_match_device(artpec6_pcie_of_match, dev); | ||
518 | if (!match) | ||
519 | return -EINVAL; | ||
520 | |||
521 | data = (struct artpec_pcie_of_data *)match->data; | ||
522 | variant = (enum artpec_pcie_variants)data->variant; | ||
523 | mode = (enum dw_pcie_device_mode)data->mode; | ||
245 | 524 | ||
246 | artpec6_pcie = devm_kzalloc(dev, sizeof(*artpec6_pcie), GFP_KERNEL); | 525 | artpec6_pcie = devm_kzalloc(dev, sizeof(*artpec6_pcie), GFP_KERNEL); |
247 | if (!artpec6_pcie) | 526 | if (!artpec6_pcie) |
@@ -255,6 +534,8 @@ static int artpec6_pcie_probe(struct platform_device *pdev) | |||
255 | pci->ops = &dw_pcie_ops; | 534 | pci->ops = &dw_pcie_ops; |
256 | 535 | ||
257 | artpec6_pcie->pci = pci; | 536 | artpec6_pcie->pci = pci; |
537 | artpec6_pcie->variant = variant; | ||
538 | artpec6_pcie->mode = mode; | ||
258 | 539 | ||
259 | dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); | 540 | dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi"); |
260 | pci->dbi_base = devm_ioremap_resource(dev, dbi_base); | 541 | pci->dbi_base = devm_ioremap_resource(dev, dbi_base); |
@@ -274,15 +555,73 @@ static int artpec6_pcie_probe(struct platform_device *pdev) | |||
274 | 555 | ||
275 | platform_set_drvdata(pdev, artpec6_pcie); | 556 | platform_set_drvdata(pdev, artpec6_pcie); |
276 | 557 | ||
277 | ret = artpec6_add_pcie_port(artpec6_pcie, pdev); | 558 | switch (artpec6_pcie->mode) { |
278 | if (ret < 0) | 559 | case DW_PCIE_RC_TYPE: |
279 | return ret; | 560 | if (!IS_ENABLED(CONFIG_PCIE_ARTPEC6_HOST)) |
561 | return -ENODEV; | ||
562 | |||
563 | ret = artpec6_add_pcie_port(artpec6_pcie, pdev); | ||
564 | if (ret < 0) | ||
565 | return ret; | ||
566 | break; | ||
567 | case DW_PCIE_EP_TYPE: { | ||
568 | u32 val; | ||
569 | |||
570 | if (!IS_ENABLED(CONFIG_PCIE_ARTPEC6_EP)) | ||
571 | return -ENODEV; | ||
572 | |||
573 | val = artpec6_pcie_readl(artpec6_pcie, PCIECFG); | ||
574 | val &= ~PCIECFG_DEVICE_TYPE_MASK; | ||
575 | artpec6_pcie_writel(artpec6_pcie, PCIECFG, val); | ||
576 | ret = artpec6_add_pcie_ep(artpec6_pcie, pdev); | ||
577 | if (ret < 0) | ||
578 | return ret; | ||
579 | break; | ||
580 | } | ||
581 | default: | ||
582 | dev_err(dev, "INVALID device type %d\n", artpec6_pcie->mode); | ||
583 | } | ||
280 | 584 | ||
281 | return 0; | 585 | return 0; |
282 | } | 586 | } |
283 | 587 | ||
588 | static const struct artpec_pcie_of_data artpec6_pcie_rc_of_data = { | ||
589 | .variant = ARTPEC6, | ||
590 | .mode = DW_PCIE_RC_TYPE, | ||
591 | }; | ||
592 | |||
593 | static const struct artpec_pcie_of_data artpec6_pcie_ep_of_data = { | ||
594 | .variant = ARTPEC6, | ||
595 | .mode = DW_PCIE_EP_TYPE, | ||
596 | }; | ||
597 | |||
598 | static const struct artpec_pcie_of_data artpec7_pcie_rc_of_data = { | ||
599 | .variant = ARTPEC7, | ||
600 | .mode = DW_PCIE_RC_TYPE, | ||
601 | }; | ||
602 | |||
603 | static const struct artpec_pcie_of_data artpec7_pcie_ep_of_data = { | ||
604 | .variant = ARTPEC7, | ||
605 | .mode = DW_PCIE_EP_TYPE, | ||
606 | }; | ||
607 | |||
284 | static const struct of_device_id artpec6_pcie_of_match[] = { | 608 | static const struct of_device_id artpec6_pcie_of_match[] = { |
285 | { .compatible = "axis,artpec6-pcie", }, | 609 | { |
610 | .compatible = "axis,artpec6-pcie", | ||
611 | .data = &artpec6_pcie_rc_of_data, | ||
612 | }, | ||
613 | { | ||
614 | .compatible = "axis,artpec6-pcie-ep", | ||
615 | .data = &artpec6_pcie_ep_of_data, | ||
616 | }, | ||
617 | { | ||
618 | .compatible = "axis,artpec7-pcie", | ||
619 | .data = &artpec7_pcie_rc_of_data, | ||
620 | }, | ||
621 | { | ||
622 | .compatible = "axis,artpec7-pcie-ep", | ||
623 | .data = &artpec7_pcie_ep_of_data, | ||
624 | }, | ||
286 | {}, | 625 | {}, |
287 | }; | 626 | }; |
288 | 627 | ||
diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie-designware-ep.c index d53d5f168363..3a6feeff5f5b 100644 --- a/drivers/pci/dwc/pcie-designware-ep.c +++ b/drivers/pci/dwc/pcie-designware-ep.c | |||
@@ -1,20 +1,9 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /** | 2 | /** |
2 | * Synopsys DesignWare PCIe Endpoint controller driver | 3 | * Synopsys DesignWare PCIe Endpoint controller driver |
3 | * | 4 | * |
4 | * Copyright (C) 2017 Texas Instruments | 5 | * Copyright (C) 2017 Texas Instruments |
5 | * Author: Kishon Vijay Abraham I <kishon@ti.com> | 6 | * Author: Kishon Vijay Abraham I <kishon@ti.com> |
6 | * | ||
7 | * This program is free software: you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 of | ||
9 | * the License as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | 7 | */ |
19 | 8 | ||
20 | #include <linux/of.h> | 9 | #include <linux/of.h> |
@@ -30,21 +19,24 @@ void dw_pcie_ep_linkup(struct dw_pcie_ep *ep) | |||
30 | pci_epc_linkup(epc); | 19 | pci_epc_linkup(epc); |
31 | } | 20 | } |
32 | 21 | ||
33 | static void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar) | 22 | void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar) |
34 | { | 23 | { |
35 | u32 reg; | 24 | u32 reg; |
36 | 25 | ||
37 | reg = PCI_BASE_ADDRESS_0 + (4 * bar); | 26 | reg = PCI_BASE_ADDRESS_0 + (4 * bar); |
27 | dw_pcie_dbi_ro_wr_en(pci); | ||
38 | dw_pcie_writel_dbi2(pci, reg, 0x0); | 28 | dw_pcie_writel_dbi2(pci, reg, 0x0); |
39 | dw_pcie_writel_dbi(pci, reg, 0x0); | 29 | dw_pcie_writel_dbi(pci, reg, 0x0); |
30 | dw_pcie_dbi_ro_wr_dis(pci); | ||
40 | } | 31 | } |
41 | 32 | ||
42 | static int dw_pcie_ep_write_header(struct pci_epc *epc, | 33 | static int dw_pcie_ep_write_header(struct pci_epc *epc, u8 func_no, |
43 | struct pci_epf_header *hdr) | 34 | struct pci_epf_header *hdr) |
44 | { | 35 | { |
45 | struct dw_pcie_ep *ep = epc_get_drvdata(epc); | 36 | struct dw_pcie_ep *ep = epc_get_drvdata(epc); |
46 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); | 37 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); |
47 | 38 | ||
39 | dw_pcie_dbi_ro_wr_en(pci); | ||
48 | dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, hdr->vendorid); | 40 | dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, hdr->vendorid); |
49 | dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, hdr->deviceid); | 41 | dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, hdr->deviceid); |
50 | dw_pcie_writeb_dbi(pci, PCI_REVISION_ID, hdr->revid); | 42 | dw_pcie_writeb_dbi(pci, PCI_REVISION_ID, hdr->revid); |
@@ -58,6 +50,7 @@ static int dw_pcie_ep_write_header(struct pci_epc *epc, | |||
58 | dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_ID, hdr->subsys_id); | 50 | dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_ID, hdr->subsys_id); |
59 | dw_pcie_writeb_dbi(pci, PCI_INTERRUPT_PIN, | 51 | dw_pcie_writeb_dbi(pci, PCI_INTERRUPT_PIN, |
60 | hdr->interrupt_pin); | 52 | hdr->interrupt_pin); |
53 | dw_pcie_dbi_ro_wr_dis(pci); | ||
61 | 54 | ||
62 | return 0; | 55 | return 0; |
63 | } | 56 | } |
@@ -70,8 +63,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar, | |||
70 | u32 free_win; | 63 | u32 free_win; |
71 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); | 64 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); |
72 | 65 | ||
73 | free_win = find_first_zero_bit(&ep->ib_window_map, | 66 | free_win = find_first_zero_bit(ep->ib_window_map, ep->num_ib_windows); |
74 | sizeof(ep->ib_window_map)); | ||
75 | if (free_win >= ep->num_ib_windows) { | 67 | if (free_win >= ep->num_ib_windows) { |
76 | dev_err(pci->dev, "no free inbound window\n"); | 68 | dev_err(pci->dev, "no free inbound window\n"); |
77 | return -EINVAL; | 69 | return -EINVAL; |
@@ -85,7 +77,7 @@ static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar, | |||
85 | } | 77 | } |
86 | 78 | ||
87 | ep->bar_to_atu[bar] = free_win; | 79 | ep->bar_to_atu[bar] = free_win; |
88 | set_bit(free_win, &ep->ib_window_map); | 80 | set_bit(free_win, ep->ib_window_map); |
89 | 81 | ||
90 | return 0; | 82 | return 0; |
91 | } | 83 | } |
@@ -96,8 +88,7 @@ static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, phys_addr_t phys_addr, | |||
96 | u32 free_win; | 88 | u32 free_win; |
97 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); | 89 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); |
98 | 90 | ||
99 | free_win = find_first_zero_bit(&ep->ob_window_map, | 91 | free_win = find_first_zero_bit(ep->ob_window_map, ep->num_ob_windows); |
100 | sizeof(ep->ob_window_map)); | ||
101 | if (free_win >= ep->num_ob_windows) { | 92 | if (free_win >= ep->num_ob_windows) { |
102 | dev_err(pci->dev, "no free outbound window\n"); | 93 | dev_err(pci->dev, "no free outbound window\n"); |
103 | return -EINVAL; | 94 | return -EINVAL; |
@@ -106,13 +97,14 @@ static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, phys_addr_t phys_addr, | |||
106 | dw_pcie_prog_outbound_atu(pci, free_win, PCIE_ATU_TYPE_MEM, | 97 | dw_pcie_prog_outbound_atu(pci, free_win, PCIE_ATU_TYPE_MEM, |
107 | phys_addr, pci_addr, size); | 98 | phys_addr, pci_addr, size); |
108 | 99 | ||
109 | set_bit(free_win, &ep->ob_window_map); | 100 | set_bit(free_win, ep->ob_window_map); |
110 | ep->outbound_addr[free_win] = phys_addr; | 101 | ep->outbound_addr[free_win] = phys_addr; |
111 | 102 | ||
112 | return 0; | 103 | return 0; |
113 | } | 104 | } |
114 | 105 | ||
115 | static void dw_pcie_ep_clear_bar(struct pci_epc *epc, enum pci_barno bar) | 106 | static void dw_pcie_ep_clear_bar(struct pci_epc *epc, u8 func_no, |
107 | enum pci_barno bar) | ||
116 | { | 108 | { |
117 | struct dw_pcie_ep *ep = epc_get_drvdata(epc); | 109 | struct dw_pcie_ep *ep = epc_get_drvdata(epc); |
118 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); | 110 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); |
@@ -121,10 +113,11 @@ static void dw_pcie_ep_clear_bar(struct pci_epc *epc, enum pci_barno bar) | |||
121 | dw_pcie_ep_reset_bar(pci, bar); | 113 | dw_pcie_ep_reset_bar(pci, bar); |
122 | 114 | ||
123 | dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_INBOUND); | 115 | dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_INBOUND); |
124 | clear_bit(atu_index, &ep->ib_window_map); | 116 | clear_bit(atu_index, ep->ib_window_map); |
125 | } | 117 | } |
126 | 118 | ||
127 | static int dw_pcie_ep_set_bar(struct pci_epc *epc, enum pci_barno bar, | 119 | static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, |
120 | enum pci_barno bar, | ||
128 | dma_addr_t bar_phys, size_t size, int flags) | 121 | dma_addr_t bar_phys, size_t size, int flags) |
129 | { | 122 | { |
130 | int ret; | 123 | int ret; |
@@ -142,8 +135,10 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, enum pci_barno bar, | |||
142 | if (ret) | 135 | if (ret) |
143 | return ret; | 136 | return ret; |
144 | 137 | ||
138 | dw_pcie_dbi_ro_wr_en(pci); | ||
145 | dw_pcie_writel_dbi2(pci, reg, size - 1); | 139 | dw_pcie_writel_dbi2(pci, reg, size - 1); |
146 | dw_pcie_writel_dbi(pci, reg, flags); | 140 | dw_pcie_writel_dbi(pci, reg, flags); |
141 | dw_pcie_dbi_ro_wr_dis(pci); | ||
147 | 142 | ||
148 | return 0; | 143 | return 0; |
149 | } | 144 | } |
@@ -163,7 +158,8 @@ static int dw_pcie_find_index(struct dw_pcie_ep *ep, phys_addr_t addr, | |||
163 | return -EINVAL; | 158 | return -EINVAL; |
164 | } | 159 | } |
165 | 160 | ||
166 | static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, phys_addr_t addr) | 161 | static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, u8 func_no, |
162 | phys_addr_t addr) | ||
167 | { | 163 | { |
168 | int ret; | 164 | int ret; |
169 | u32 atu_index; | 165 | u32 atu_index; |
@@ -175,10 +171,11 @@ static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, phys_addr_t addr) | |||
175 | return; | 171 | return; |
176 | 172 | ||
177 | dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_OUTBOUND); | 173 | dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_OUTBOUND); |
178 | clear_bit(atu_index, &ep->ob_window_map); | 174 | clear_bit(atu_index, ep->ob_window_map); |
179 | } | 175 | } |
180 | 176 | ||
181 | static int dw_pcie_ep_map_addr(struct pci_epc *epc, phys_addr_t addr, | 177 | static int dw_pcie_ep_map_addr(struct pci_epc *epc, u8 func_no, |
178 | phys_addr_t addr, | ||
182 | u64 pci_addr, size_t size) | 179 | u64 pci_addr, size_t size) |
183 | { | 180 | { |
184 | int ret; | 181 | int ret; |
@@ -194,39 +191,37 @@ static int dw_pcie_ep_map_addr(struct pci_epc *epc, phys_addr_t addr, | |||
194 | return 0; | 191 | return 0; |
195 | } | 192 | } |
196 | 193 | ||
197 | static int dw_pcie_ep_get_msi(struct pci_epc *epc) | 194 | static int dw_pcie_ep_get_msi(struct pci_epc *epc, u8 func_no) |
198 | { | 195 | { |
199 | int val; | 196 | int val; |
200 | u32 lower_addr; | ||
201 | u32 upper_addr; | ||
202 | struct dw_pcie_ep *ep = epc_get_drvdata(epc); | 197 | struct dw_pcie_ep *ep = epc_get_drvdata(epc); |
203 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); | 198 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); |
204 | 199 | ||
205 | val = dw_pcie_readb_dbi(pci, MSI_MESSAGE_CONTROL); | 200 | val = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); |
206 | val = (val & MSI_CAP_MME_MASK) >> MSI_CAP_MME_SHIFT; | 201 | if (!(val & MSI_CAP_MSI_EN_MASK)) |
207 | |||
208 | lower_addr = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_L32); | ||
209 | upper_addr = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_U32); | ||
210 | |||
211 | if (!(lower_addr || upper_addr)) | ||
212 | return -EINVAL; | 202 | return -EINVAL; |
213 | 203 | ||
204 | val = (val & MSI_CAP_MME_MASK) >> MSI_CAP_MME_SHIFT; | ||
214 | return val; | 205 | return val; |
215 | } | 206 | } |
216 | 207 | ||
217 | static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 encode_int) | 208 | static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 func_no, u8 encode_int) |
218 | { | 209 | { |
219 | int val; | 210 | int val; |
220 | struct dw_pcie_ep *ep = epc_get_drvdata(epc); | 211 | struct dw_pcie_ep *ep = epc_get_drvdata(epc); |
221 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); | 212 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); |
222 | 213 | ||
223 | val = (encode_int << MSI_CAP_MMC_SHIFT); | 214 | val = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); |
215 | val &= ~MSI_CAP_MMC_MASK; | ||
216 | val |= (encode_int << MSI_CAP_MMC_SHIFT) & MSI_CAP_MMC_MASK; | ||
217 | dw_pcie_dbi_ro_wr_en(pci); | ||
224 | dw_pcie_writew_dbi(pci, MSI_MESSAGE_CONTROL, val); | 218 | dw_pcie_writew_dbi(pci, MSI_MESSAGE_CONTROL, val); |
219 | dw_pcie_dbi_ro_wr_dis(pci); | ||
225 | 220 | ||
226 | return 0; | 221 | return 0; |
227 | } | 222 | } |
228 | 223 | ||
229 | static int dw_pcie_ep_raise_irq(struct pci_epc *epc, | 224 | static int dw_pcie_ep_raise_irq(struct pci_epc *epc, u8 func_no, |
230 | enum pci_epc_irq_type type, u8 interrupt_num) | 225 | enum pci_epc_irq_type type, u8 interrupt_num) |
231 | { | 226 | { |
232 | struct dw_pcie_ep *ep = epc_get_drvdata(epc); | 227 | struct dw_pcie_ep *ep = epc_get_drvdata(epc); |
@@ -234,7 +229,7 @@ static int dw_pcie_ep_raise_irq(struct pci_epc *epc, | |||
234 | if (!ep->ops->raise_irq) | 229 | if (!ep->ops->raise_irq) |
235 | return -EINVAL; | 230 | return -EINVAL; |
236 | 231 | ||
237 | return ep->ops->raise_irq(ep, type, interrupt_num); | 232 | return ep->ops->raise_irq(ep, func_no, type, interrupt_num); |
238 | } | 233 | } |
239 | 234 | ||
240 | static void dw_pcie_ep_stop(struct pci_epc *epc) | 235 | static void dw_pcie_ep_stop(struct pci_epc *epc) |
@@ -272,10 +267,48 @@ static const struct pci_epc_ops epc_ops = { | |||
272 | .stop = dw_pcie_ep_stop, | 267 | .stop = dw_pcie_ep_stop, |
273 | }; | 268 | }; |
274 | 269 | ||
270 | int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, | ||
271 | u8 interrupt_num) | ||
272 | { | ||
273 | struct dw_pcie *pci = to_dw_pcie_from_ep(ep); | ||
274 | struct pci_epc *epc = ep->epc; | ||
275 | u16 msg_ctrl, msg_data; | ||
276 | u32 msg_addr_lower, msg_addr_upper; | ||
277 | u64 msg_addr; | ||
278 | bool has_upper; | ||
279 | int ret; | ||
280 | |||
281 | /* Raise MSI per the PCI Local Bus Specification Revision 3.0, 6.8.1. */ | ||
282 | msg_ctrl = dw_pcie_readw_dbi(pci, MSI_MESSAGE_CONTROL); | ||
283 | has_upper = !!(msg_ctrl & PCI_MSI_FLAGS_64BIT); | ||
284 | msg_addr_lower = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_L32); | ||
285 | if (has_upper) { | ||
286 | msg_addr_upper = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_U32); | ||
287 | msg_data = dw_pcie_readw_dbi(pci, MSI_MESSAGE_DATA_64); | ||
288 | } else { | ||
289 | msg_addr_upper = 0; | ||
290 | msg_data = dw_pcie_readw_dbi(pci, MSI_MESSAGE_DATA_32); | ||
291 | } | ||
292 | msg_addr = ((u64) msg_addr_upper) << 32 | msg_addr_lower; | ||
293 | ret = dw_pcie_ep_map_addr(epc, func_no, ep->msi_mem_phys, msg_addr, | ||
294 | epc->mem->page_size); | ||
295 | if (ret) | ||
296 | return ret; | ||
297 | |||
298 | writel(msg_data | (interrupt_num - 1), ep->msi_mem); | ||
299 | |||
300 | dw_pcie_ep_unmap_addr(epc, func_no, ep->msi_mem_phys); | ||
301 | |||
302 | return 0; | ||
303 | } | ||
304 | |||
275 | void dw_pcie_ep_exit(struct dw_pcie_ep *ep) | 305 | void dw_pcie_ep_exit(struct dw_pcie_ep *ep) |
276 | { | 306 | { |
277 | struct pci_epc *epc = ep->epc; | 307 | struct pci_epc *epc = ep->epc; |
278 | 308 | ||
309 | pci_epc_mem_free_addr(epc, ep->msi_mem_phys, ep->msi_mem, | ||
310 | epc->mem->page_size); | ||
311 | |||
279 | pci_epc_mem_exit(epc); | 312 | pci_epc_mem_exit(epc); |
280 | } | 313 | } |
281 | 314 | ||
@@ -298,12 +331,32 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) | |||
298 | dev_err(dev, "unable to read *num-ib-windows* property\n"); | 331 | dev_err(dev, "unable to read *num-ib-windows* property\n"); |
299 | return ret; | 332 | return ret; |
300 | } | 333 | } |
334 | if (ep->num_ib_windows > MAX_IATU_IN) { | ||
335 | dev_err(dev, "invalid *num-ib-windows*\n"); | ||
336 | return -EINVAL; | ||
337 | } | ||
301 | 338 | ||
302 | ret = of_property_read_u32(np, "num-ob-windows", &ep->num_ob_windows); | 339 | ret = of_property_read_u32(np, "num-ob-windows", &ep->num_ob_windows); |
303 | if (ret < 0) { | 340 | if (ret < 0) { |
304 | dev_err(dev, "unable to read *num-ob-windows* property\n"); | 341 | dev_err(dev, "unable to read *num-ob-windows* property\n"); |
305 | return ret; | 342 | return ret; |
306 | } | 343 | } |
344 | if (ep->num_ob_windows > MAX_IATU_OUT) { | ||
345 | dev_err(dev, "invalid *num-ob-windows*\n"); | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | |||
349 | ep->ib_window_map = devm_kzalloc(dev, sizeof(long) * | ||
350 | BITS_TO_LONGS(ep->num_ib_windows), | ||
351 | GFP_KERNEL); | ||
352 | if (!ep->ib_window_map) | ||
353 | return -ENOMEM; | ||
354 | |||
355 | ep->ob_window_map = devm_kzalloc(dev, sizeof(long) * | ||
356 | BITS_TO_LONGS(ep->num_ob_windows), | ||
357 | GFP_KERNEL); | ||
358 | if (!ep->ob_window_map) | ||
359 | return -ENOMEM; | ||
307 | 360 | ||
308 | addr = devm_kzalloc(dev, sizeof(phys_addr_t) * ep->num_ob_windows, | 361 | addr = devm_kzalloc(dev, sizeof(phys_addr_t) * ep->num_ob_windows, |
309 | GFP_KERNEL); | 362 | GFP_KERNEL); |
@@ -331,6 +384,13 @@ int dw_pcie_ep_init(struct dw_pcie_ep *ep) | |||
331 | return ret; | 384 | return ret; |
332 | } | 385 | } |
333 | 386 | ||
387 | ep->msi_mem = pci_epc_mem_alloc_addr(epc, &ep->msi_mem_phys, | ||
388 | epc->mem->page_size); | ||
389 | if (!ep->msi_mem) { | ||
390 | dev_err(dev, "Failed to reserve memory for MSI\n"); | ||
391 | return -ENOMEM; | ||
392 | } | ||
393 | |||
334 | ep->epc = epc; | 394 | ep->epc = epc; |
335 | epc_set_drvdata(epc, ep); | 395 | epc_set_drvdata(epc, ep); |
336 | dw_pcie_setup(pci); | 396 | dw_pcie_setup(pci); |
diff --git a/drivers/pci/dwc/pcie-designware-host.c b/drivers/pci/dwc/pcie-designware-host.c index 81e2157a7cfb..8de2d5c69b1d 100644 --- a/drivers/pci/dwc/pcie-designware-host.c +++ b/drivers/pci/dwc/pcie-designware-host.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Synopsys DesignWare PCIe host controller driver | 3 | * Synopsys DesignWare PCIe host controller driver |
3 | * | 4 | * |
@@ -5,10 +6,6 @@ | |||
5 | * http://www.samsung.com | 6 | * http://www.samsung.com |
6 | * | 7 | * |
7 | * Author: Jingoo Han <jg1.han@samsung.com> | 8 | * Author: Jingoo Han <jg1.han@samsung.com> |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | 9 | */ |
13 | 10 | ||
14 | #include <linux/irqdomain.h> | 11 | #include <linux/irqdomain.h> |
@@ -83,10 +80,19 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) | |||
83 | 80 | ||
84 | void dw_pcie_msi_init(struct pcie_port *pp) | 81 | void dw_pcie_msi_init(struct pcie_port *pp) |
85 | { | 82 | { |
83 | struct dw_pcie *pci = to_dw_pcie_from_pp(pp); | ||
84 | struct device *dev = pci->dev; | ||
85 | struct page *page; | ||
86 | u64 msi_target; | 86 | u64 msi_target; |
87 | 87 | ||
88 | pp->msi_data = __get_free_pages(GFP_KERNEL, 0); | 88 | page = alloc_page(GFP_KERNEL); |
89 | msi_target = virt_to_phys((void *)pp->msi_data); | 89 | pp->msi_data = dma_map_page(dev, page, 0, PAGE_SIZE, DMA_FROM_DEVICE); |
90 | if (dma_mapping_error(dev, pp->msi_data)) { | ||
91 | dev_err(dev, "failed to map MSI data\n"); | ||
92 | __free_page(page); | ||
93 | return; | ||
94 | } | ||
95 | msi_target = (u64)pp->msi_data; | ||
90 | 96 | ||
91 | /* program the msi_data */ | 97 | /* program the msi_data */ |
92 | dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4, | 98 | dw_pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4, |
@@ -187,7 +193,7 @@ static void dw_msi_setup_msg(struct pcie_port *pp, unsigned int irq, u32 pos) | |||
187 | if (pp->ops->get_msi_addr) | 193 | if (pp->ops->get_msi_addr) |
188 | msi_target = pp->ops->get_msi_addr(pp); | 194 | msi_target = pp->ops->get_msi_addr(pp); |
189 | else | 195 | else |
190 | msi_target = virt_to_phys((void *)pp->msi_data); | 196 | msi_target = (u64)pp->msi_data; |
191 | 197 | ||
192 | msg.address_lo = (u32)(msi_target & 0xffffffff); | 198 | msg.address_lo = (u32)(msi_target & 0xffffffff); |
193 | msg.address_hi = (u32)(msi_target >> 32 & 0xffffffff); | 199 | msg.address_hi = (u32)(msi_target >> 32 & 0xffffffff); |
diff --git a/drivers/pci/dwc/pcie-designware-plat.c b/drivers/pci/dwc/pcie-designware-plat.c index 168e2380f493..ebdf28bcd67d 100644 --- a/drivers/pci/dwc/pcie-designware-plat.c +++ b/drivers/pci/dwc/pcie-designware-plat.c | |||
@@ -1,13 +1,10 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * PCIe RC driver for Synopsys DesignWare Core | 3 | * PCIe RC driver for Synopsys DesignWare Core |
3 | * | 4 | * |
4 | * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com) | 5 | * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com) |
5 | * | 6 | * |
6 | * Authors: Joao Pinto <Joao.Pinto@synopsys.com> | 7 | * Authors: Joao Pinto <Joao.Pinto@synopsys.com> |
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | 8 | */ |
12 | #include <linux/clk.h> | 9 | #include <linux/clk.h> |
13 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
diff --git a/drivers/pci/dwc/pcie-designware.c b/drivers/pci/dwc/pcie-designware.c index 88abdddee2ad..1b7282e5b494 100644 --- a/drivers/pci/dwc/pcie-designware.c +++ b/drivers/pci/dwc/pcie-designware.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Synopsys DesignWare PCIe host controller driver | 3 | * Synopsys DesignWare PCIe host controller driver |
3 | * | 4 | * |
@@ -5,10 +6,6 @@ | |||
5 | * http://www.samsung.com | 6 | * http://www.samsung.com |
6 | * | 7 | * |
7 | * Author: Jingoo Han <jg1.han@samsung.com> | 8 | * Author: Jingoo Han <jg1.han@samsung.com> |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | 9 | */ |
13 | 10 | ||
14 | #include <linux/delay.h> | 11 | #include <linux/delay.h> |
@@ -149,7 +146,7 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type, | |||
149 | u32 retries, val; | 146 | u32 retries, val; |
150 | 147 | ||
151 | if (pci->ops->cpu_addr_fixup) | 148 | if (pci->ops->cpu_addr_fixup) |
152 | cpu_addr = pci->ops->cpu_addr_fixup(cpu_addr); | 149 | cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr); |
153 | 150 | ||
154 | if (pci->iatu_unroll_enabled) { | 151 | if (pci->iatu_unroll_enabled) { |
155 | dw_pcie_prog_outbound_atu_unroll(pci, index, type, cpu_addr, | 152 | dw_pcie_prog_outbound_atu_unroll(pci, index, type, cpu_addr, |
diff --git a/drivers/pci/dwc/pcie-designware.h b/drivers/pci/dwc/pcie-designware.h index e5d9d77b778e..11b13864a406 100644 --- a/drivers/pci/dwc/pcie-designware.h +++ b/drivers/pci/dwc/pcie-designware.h | |||
@@ -1,3 +1,4 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
1 | /* | 2 | /* |
2 | * Synopsys DesignWare PCIe host controller driver | 3 | * Synopsys DesignWare PCIe host controller driver |
3 | * | 4 | * |
@@ -5,15 +6,12 @@ | |||
5 | * http://www.samsung.com | 6 | * http://www.samsung.com |
6 | * | 7 | * |
7 | * Author: Jingoo Han <jg1.han@samsung.com> | 8 | * Author: Jingoo Han <jg1.han@samsung.com> |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | 9 | */ |
13 | 10 | ||
14 | #ifndef _PCIE_DESIGNWARE_H | 11 | #ifndef _PCIE_DESIGNWARE_H |
15 | #define _PCIE_DESIGNWARE_H | 12 | #define _PCIE_DESIGNWARE_H |
16 | 13 | ||
14 | #include <linux/dma-mapping.h> | ||
17 | #include <linux/irq.h> | 15 | #include <linux/irq.h> |
18 | #include <linux/msi.h> | 16 | #include <linux/msi.h> |
19 | #include <linux/pci.h> | 17 | #include <linux/pci.h> |
@@ -100,10 +98,14 @@ | |||
100 | 98 | ||
101 | #define MSI_MESSAGE_CONTROL 0x52 | 99 | #define MSI_MESSAGE_CONTROL 0x52 |
102 | #define MSI_CAP_MMC_SHIFT 1 | 100 | #define MSI_CAP_MMC_SHIFT 1 |
101 | #define MSI_CAP_MMC_MASK (7 << MSI_CAP_MMC_SHIFT) | ||
103 | #define MSI_CAP_MME_SHIFT 4 | 102 | #define MSI_CAP_MME_SHIFT 4 |
103 | #define MSI_CAP_MSI_EN_MASK 0x1 | ||
104 | #define MSI_CAP_MME_MASK (7 << MSI_CAP_MME_SHIFT) | 104 | #define MSI_CAP_MME_MASK (7 << MSI_CAP_MME_SHIFT) |
105 | #define MSI_MESSAGE_ADDR_L32 0x54 | 105 | #define MSI_MESSAGE_ADDR_L32 0x54 |
106 | #define MSI_MESSAGE_ADDR_U32 0x58 | 106 | #define MSI_MESSAGE_ADDR_U32 0x58 |
107 | #define MSI_MESSAGE_DATA_32 0x58 | ||
108 | #define MSI_MESSAGE_DATA_64 0x5C | ||
107 | 109 | ||
108 | /* | 110 | /* |
109 | * Maximum number of MSI IRQs can be 256 per controller. But keep | 111 | * Maximum number of MSI IRQs can be 256 per controller. But keep |
@@ -113,6 +115,10 @@ | |||
113 | #define MAX_MSI_IRQS 32 | 115 | #define MAX_MSI_IRQS 32 |
114 | #define MAX_MSI_CTRLS (MAX_MSI_IRQS / 32) | 116 | #define MAX_MSI_CTRLS (MAX_MSI_IRQS / 32) |
115 | 117 | ||
118 | /* Maximum number of inbound/outbound iATUs */ | ||
119 | #define MAX_IATU_IN 256 | ||
120 | #define MAX_IATU_OUT 256 | ||
121 | |||
116 | struct pcie_port; | 122 | struct pcie_port; |
117 | struct dw_pcie; | 123 | struct dw_pcie; |
118 | struct dw_pcie_ep; | 124 | struct dw_pcie_ep; |
@@ -168,7 +174,7 @@ struct pcie_port { | |||
168 | const struct dw_pcie_host_ops *ops; | 174 | const struct dw_pcie_host_ops *ops; |
169 | int msi_irq; | 175 | int msi_irq; |
170 | struct irq_domain *irq_domain; | 176 | struct irq_domain *irq_domain; |
171 | unsigned long msi_data; | 177 | dma_addr_t msi_data; |
172 | DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS); | 178 | DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS); |
173 | }; | 179 | }; |
174 | 180 | ||
@@ -180,8 +186,8 @@ enum dw_pcie_as_type { | |||
180 | 186 | ||
181 | struct dw_pcie_ep_ops { | 187 | struct dw_pcie_ep_ops { |
182 | void (*ep_init)(struct dw_pcie_ep *ep); | 188 | void (*ep_init)(struct dw_pcie_ep *ep); |
183 | int (*raise_irq)(struct dw_pcie_ep *ep, enum pci_epc_irq_type type, | 189 | int (*raise_irq)(struct dw_pcie_ep *ep, u8 func_no, |
184 | u8 interrupt_num); | 190 | enum pci_epc_irq_type type, u8 interrupt_num); |
185 | }; | 191 | }; |
186 | 192 | ||
187 | struct dw_pcie_ep { | 193 | struct dw_pcie_ep { |
@@ -192,14 +198,16 @@ struct dw_pcie_ep { | |||
192 | size_t page_size; | 198 | size_t page_size; |
193 | u8 bar_to_atu[6]; | 199 | u8 bar_to_atu[6]; |
194 | phys_addr_t *outbound_addr; | 200 | phys_addr_t *outbound_addr; |
195 | unsigned long ib_window_map; | 201 | unsigned long *ib_window_map; |
196 | unsigned long ob_window_map; | 202 | unsigned long *ob_window_map; |
197 | u32 num_ib_windows; | 203 | u32 num_ib_windows; |
198 | u32 num_ob_windows; | 204 | u32 num_ob_windows; |
205 | void __iomem *msi_mem; | ||
206 | phys_addr_t msi_mem_phys; | ||
199 | }; | 207 | }; |
200 | 208 | ||
201 | struct dw_pcie_ops { | 209 | struct dw_pcie_ops { |
202 | u64 (*cpu_addr_fixup)(u64 cpu_addr); | 210 | u64 (*cpu_addr_fixup)(struct dw_pcie *pcie, u64 cpu_addr); |
203 | u32 (*read_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg, | 211 | u32 (*read_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg, |
204 | size_t size); | 212 | size_t size); |
205 | void (*write_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg, | 213 | void (*write_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg, |
@@ -334,6 +342,9 @@ static inline int dw_pcie_host_init(struct pcie_port *pp) | |||
334 | void dw_pcie_ep_linkup(struct dw_pcie_ep *ep); | 342 | void dw_pcie_ep_linkup(struct dw_pcie_ep *ep); |
335 | int dw_pcie_ep_init(struct dw_pcie_ep *ep); | 343 | int dw_pcie_ep_init(struct dw_pcie_ep *ep); |
336 | void dw_pcie_ep_exit(struct dw_pcie_ep *ep); | 344 | void dw_pcie_ep_exit(struct dw_pcie_ep *ep); |
345 | int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, | ||
346 | u8 interrupt_num); | ||
347 | void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar); | ||
337 | #else | 348 | #else |
338 | static inline void dw_pcie_ep_linkup(struct dw_pcie_ep *ep) | 349 | static inline void dw_pcie_ep_linkup(struct dw_pcie_ep *ep) |
339 | { | 350 | { |
@@ -347,5 +358,15 @@ static inline int dw_pcie_ep_init(struct dw_pcie_ep *ep) | |||
347 | static inline void dw_pcie_ep_exit(struct dw_pcie_ep *ep) | 358 | static inline void dw_pcie_ep_exit(struct dw_pcie_ep *ep) |
348 | { | 359 | { |
349 | } | 360 | } |
361 | |||
362 | static inline int dw_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep, u8 func_no, | ||
363 | u8 interrupt_num) | ||
364 | { | ||
365 | return 0; | ||
366 | } | ||
367 | |||
368 | static inline void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar) | ||
369 | { | ||
370 | } | ||
350 | #endif | 371 | #endif |
351 | #endif /* _PCIE_DESIGNWARE_H */ | 372 | #endif /* _PCIE_DESIGNWARE_H */ |
diff --git a/drivers/pci/dwc/pcie-hisi.c b/drivers/pci/dwc/pcie-hisi.c index a20179169e06..2658aaebb993 100644 --- a/drivers/pci/dwc/pcie-hisi.c +++ b/drivers/pci/dwc/pcie-hisi.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * PCIe host controller driver for HiSilicon SoCs | 3 | * PCIe host controller driver for HiSilicon SoCs |
3 | * | 4 | * |
@@ -6,10 +7,6 @@ | |||
6 | * Authors: Zhou Wang <wangzhou1@hisilicon.com> | 7 | * Authors: Zhou Wang <wangzhou1@hisilicon.com> |
7 | * Dacai Zhu <zhudacai@hisilicon.com> | 8 | * Dacai Zhu <zhudacai@hisilicon.com> |
8 | * Gabriele Paoloni <gabriele.paoloni@huawei.com> | 9 | * Gabriele Paoloni <gabriele.paoloni@huawei.com> |
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | 10 | */ |
14 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
15 | #include <linux/init.h> | 12 | #include <linux/init.h> |
diff --git a/drivers/pci/dwc/pcie-histb.c b/drivers/pci/dwc/pcie-histb.c index 33b01b734d7d..70b5c0b108bf 100644 --- a/drivers/pci/dwc/pcie-histb.c +++ b/drivers/pci/dwc/pcie-histb.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * PCIe host controller driver for HiSilicon STB SoCs | 3 | * PCIe host controller driver for HiSilicon STB SoCs |
3 | * | 4 | * |
@@ -5,10 +6,6 @@ | |||
5 | * | 6 | * |
6 | * Authors: Ruqiang Ju <juruqiang@hisilicon.com> | 7 | * Authors: Ruqiang Ju <juruqiang@hisilicon.com> |
7 | * Jianguo Sun <sunjianguo1@huawei.com> | 8 | * Jianguo Sun <sunjianguo1@huawei.com> |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | 9 | */ |
13 | 10 | ||
14 | #include <linux/clk.h> | 11 | #include <linux/clk.h> |
diff --git a/drivers/pci/dwc/pcie-kirin.c b/drivers/pci/dwc/pcie-kirin.c index dc3033cf3c19..13d839bd6160 100644 --- a/drivers/pci/dwc/pcie-kirin.c +++ b/drivers/pci/dwc/pcie-kirin.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * PCIe host controller driver for Kirin Phone SoCs | 3 | * PCIe host controller driver for Kirin Phone SoCs |
3 | * | 4 | * |
@@ -5,10 +6,6 @@ | |||
5 | * http://www.huawei.com | 6 | * http://www.huawei.com |
6 | * | 7 | * |
7 | * Author: Xiaowei Song <songxiaowei@huawei.com> | 8 | * Author: Xiaowei Song <songxiaowei@huawei.com> |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | 9 | */ |
13 | 10 | ||
14 | #include <asm/compiler.h> | 11 | #include <asm/compiler.h> |
diff --git a/drivers/pci/dwc/pcie-qcom.c b/drivers/pci/dwc/pcie-qcom.c index ce7ba5b7552a..6310c66e265c 100644 --- a/drivers/pci/dwc/pcie-qcom.c +++ b/drivers/pci/dwc/pcie-qcom.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * Qualcomm PCIe root complex driver | 3 | * Qualcomm PCIe root complex driver |
3 | * | 4 | * |
@@ -5,15 +6,6 @@ | |||
5 | * Copyright 2015 Linaro Limited. | 6 | * Copyright 2015 Linaro Limited. |
6 | * | 7 | * |
7 | * Author: Stanimir Varbanov <svarbanov@mm-sol.com> | 8 | * Author: Stanimir Varbanov <svarbanov@mm-sol.com> |
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 and | ||
11 | * only version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | */ | 9 | */ |
18 | 10 | ||
19 | #include <linux/clk.h> | 11 | #include <linux/clk.h> |
@@ -171,7 +163,7 @@ struct qcom_pcie { | |||
171 | union qcom_pcie_resources res; | 163 | union qcom_pcie_resources res; |
172 | struct phy *phy; | 164 | struct phy *phy; |
173 | struct gpio_desc *reset; | 165 | struct gpio_desc *reset; |
174 | struct qcom_pcie_ops *ops; | 166 | const struct qcom_pcie_ops *ops; |
175 | }; | 167 | }; |
176 | 168 | ||
177 | #define to_qcom_pcie(x) dev_get_drvdata((x)->dev) | 169 | #define to_qcom_pcie(x) dev_get_drvdata((x)->dev) |
@@ -1234,7 +1226,7 @@ static int qcom_pcie_probe(struct platform_device *pdev) | |||
1234 | 1226 | ||
1235 | pcie->pci = pci; | 1227 | pcie->pci = pci; |
1236 | 1228 | ||
1237 | pcie->ops = (struct qcom_pcie_ops *)of_device_get_match_data(dev); | 1229 | pcie->ops = of_device_get_match_data(dev); |
1238 | 1230 | ||
1239 | pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_LOW); | 1231 | pcie->reset = devm_gpiod_get_optional(dev, "perst", GPIOD_OUT_LOW); |
1240 | if (IS_ERR(pcie->reset)) | 1232 | if (IS_ERR(pcie->reset)) |
diff --git a/drivers/pci/dwc/pcie-spear13xx.c b/drivers/pci/dwc/pcie-spear13xx.c index 709189d23b31..ecb58f7b7566 100644 --- a/drivers/pci/dwc/pcie-spear13xx.c +++ b/drivers/pci/dwc/pcie-spear13xx.c | |||
@@ -1,3 +1,4 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
1 | /* | 2 | /* |
2 | * PCIe host controller driver for ST Microelectronics SPEAr13xx SoCs | 3 | * PCIe host controller driver for ST Microelectronics SPEAr13xx SoCs |
3 | * | 4 | * |
@@ -6,10 +7,6 @@ | |||
6 | * Copyright (C) 2010-2014 ST Microelectronics | 7 | * Copyright (C) 2010-2014 ST Microelectronics |
7 | * Pratyush Anand <pratyush.anand@gmail.com> | 8 | * Pratyush Anand <pratyush.anand@gmail.com> |
8 | * Mohit Kumar <mohit.kumar.dhaka@gmail.com> | 9 | * Mohit Kumar <mohit.kumar.dhaka@gmail.com> |
9 | * | ||
10 | * This file is licensed under the terms of the GNU General Public | ||
11 | * License version 2. This program is licensed "as is" without any | ||
12 | * warranty of any kind, whether express or implied. | ||
13 | */ | 10 | */ |
14 | 11 | ||
15 | #include <linux/clk.h> | 12 | #include <linux/clk.h> |