diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-22 12:41:00 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-10-22 12:41:00 -0700 |
commit | 00937f36b09e89c74e4a059dbb8acbf4b971d5eb (patch) | |
tree | ff2e5f5fa6736460437f57680405a20124d1e969 /drivers/pci/controller | |
parent | 96485e4462604744d66bf4301557d996d80b85eb (diff) | |
parent | 28e34e751f6c50098d9bcecb30c97634b6126730 (diff) | |
download | linux-00937f36b09e89c74e4a059dbb8acbf4b971d5eb.tar.gz linux-00937f36b09e89c74e4a059dbb8acbf4b971d5eb.tar.bz2 linux-00937f36b09e89c74e4a059dbb8acbf4b971d5eb.zip |
Merge tag 'pci-v5.10-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
Pull PCI updates from Bjorn Helgaas:
"Enumeration:
- Print IRQ number used by PCIe Link Bandwidth Notification (Dongdong
Liu)
- Add schedule point in pci_read_config() to reduce max latency
(Jiang Biao)
- Add Kconfig options for MPS/MRRS strategy (Jim Quinlan)
Resource management:
- Fix pci_iounmap() memory leak when !CONFIG_GENERIC_IOMAP (Lorenzo
Pieralisi)
PCIe native device hotplug:
- Reduce noisiness on hot removal (Lukas Wunner)
Power management:
- Revert "PCI/PM: Apply D2 delay as milliseconds, not microseconds"
that was done on the basis of spec typo (Bjorn Helgaas)
- Rename pci_dev.d3_delay to d3hot_delay to remove D3hot/D3cold
ambiguity (Krzysztof Wilczyński)
- Remove unused pcibios_pm_ops (Vaibhav Gupta)
IOMMU:
- Enable Translation Blocking for external devices to harden against
DMA attacks (Rajat Jain)
Error handling:
- Add an ACPI APEI notifier chain for vendor CPER records to enable
device-specific error handling (Shiju Jose)
ASPM:
- Remove struct aspm_register_info to simplify code (Saheed O.
Bolarinwa)
Amlogic Meson PCIe controller driver:
- Build as module by default (Kevin Hilman)
Ampere Altra PCIe controller driver:
- Add MCFG quirk to work around non-standard ECAM implementation
(Tuan Phan)
Broadcom iProc PCIe controller driver:
- Set affinity mask on MSI interrupts (Mark Tomlinson)
Broadcom STB PCIe controller driver:
- Make PCIE_BRCMSTB depend on ARCH_BRCMSTB (Jim Quinlan)
- Add DT bindings for more Brcmstb chips (Jim Quinlan)
- Add bcm7278 register info (Jim Quinlan)
- Add bcm7278 PERST# support (Jim Quinlan)
- Add suspend and resume pm_ops (Jim Quinlan)
- Add control of rescal reset (Jim Quinlan)
- Set additional internal memory DMA viewport sizes (Jim Quinlan)
- Accommodate MSI for older chips (Jim Quinlan)
- Set bus max burst size by chip type (Jim Quinlan)
- Add support for bcm7211, bcm7216, bcm7445, bcm7278 (Jim Quinlan)
Freescale i.MX6 PCIe controller driver:
- Use dev_err_probe() to reduce redundant messages (Anson Huang)
Freescale Layerscape PCIe controller driver:
- Enforce 4K DMA buffer alignment in endpoint test (Hou Zhiqiang)
- Add DT compatible strings for ls1088a, ls2088a (Xiaowei Bao)
- Add endpoint support for ls1088a, ls2088a (Xiaowei Bao)
- Add endpoint test support for lS1088a (Xiaowei Bao)
- Add MSI-X support for ls1088a (Xiaowei Bao)
HiSilicon HIP PCIe controller driver:
- Handle HIP-specific errors via ACPI APEI (Yicong Yang)
HiSilicon Kirin PCIe controller driver:
- Return -EPROBE_DEFER if the GPIO isn't ready (Bean Huo)
Intel VMD host bridge driver:
- Factor out physical offset, bus offset, IRQ domain, IRQ allocation
(Jon Derrick)
- Use generic PCI PM correctly (Jon Derrick)
Marvell Aardvark PCIe controller driver:
- Fix compilation on s390 (Pali Rohár)
- Implement driver 'remove' function and allow to build it as module
(Pali Rohár)
- Move PCIe reset card code to advk_pcie_train_link() (Pali Rohár)
- Convert mvebu a3700 internal SMCC firmware return codes to errno
(Pali Rohár)
- Fix initialization with old Marvell's Arm Trusted Firmware (Pali
Rohár)
Microsoft Hyper-V host bridge driver:
- Fix hibernation in case interrupts are not re-created (Dexuan Cui)
NVIDIA Tegra PCIe controller driver:
- Stop checking return value of debugfs_create() functions (Greg
Kroah-Hartman)
- Convert to use DEFINE_SEQ_ATTRIBUTE macro (Liu Shixin)
Qualcomm PCIe controller driver:
- Reset PCIe to work around Qsdk U-Boot issue (Ansuel Smith)
Renesas R-Car PCIe controller driver:
- Add DT documentation for r8a774a1, r8a774b1, r8a774e1 endpoints
(Lad Prabhakar)
- Add RZ/G2M, RZ/G2N, RZ/G2H IDs to endpoint test (Lad Prabhakar)
- Add DT support for r8a7742 (Lad Prabhakar)
Socionext UniPhier Pro5 controller driver:
- Add DT descriptions of iATU register (host and endpoint) (Kunihiko
Hayashi)
Synopsys DesignWare PCIe controller driver:
- Add link up check in dw_child_pcie_ops.map_bus() (racy, but seems
unavoidable) (Hou Zhiqiang)
- Fix endpoint Header Type check so multi-function devices work (Hou
Zhiqiang)
- Skip PCIE_MSI_INTR0* programming if MSI is disabled (Jisheng Zhang)
- Stop leaking MSI page in suspend/resume (Jisheng Zhang)
- Add common iATU register support instead of keystone-specific code
(Kunihiko Hayashi)
- Major config space access and other cleanups in dwc core and
drivers that use it (al, exynos, histb, imx6, intel-gw, keystone,
kirin, meson, qcom, tegra) (Rob Herring)
- Add multiple PFs support for endpoint (Xiaowei Bao)
- Add MSI-X doorbell mode in endpoint mode (Xiaowei Bao)
Miscellaneous:
- Use fallthrough pseudo-keyword (Gustavo A. R. Silva)
- Fix "0 used as NULL pointer" warnings (Gustavo Pimentel)
- Fix "cast truncates bits from constant value" warnings (Gustavo
Pimentel)
- Remove redundant zeroing for sg_init_table() (Julia Lawall)
- Use scnprintf(), not snprintf(), in sysfs "show" functions
(Krzysztof Wilczyński)
- Remove unused assignments (Krzysztof Wilczyński)
- Fix "0 used as NULL pointer" warning (Krzysztof Wilczyński)
- Simplify bool comparisons (Krzysztof Wilczyński)
- Use for_each_child_of_node() and for_each_node_by_name() (Qinglang
Miao)
- Simplify return expressions (Qinglang Miao)"
* tag 'pci-v5.10-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci: (147 commits)
PCI: vmd: Update VMD PM to correctly use generic PCI PM
PCI: vmd: Create IRQ allocation helper
PCI: vmd: Create IRQ Domain configuration helper
PCI: vmd: Create bus offset configuration helper
PCI: vmd: Create physical offset helper
PCI: v3-semi: Remove unneeded break
PCI: dwc: Add link up check in dw_child_pcie_ops.map_bus()
PCI/ASPM: Remove struct pcie_link_state.l1ss
PCI/ASPM: Remove struct aspm_register_info.l1ss_cap
PCI/ASPM: Pass L1SS Capabilities value, not struct aspm_register_info
PCI/ASPM: Remove struct aspm_register_info.l1ss_ctl1
PCI/ASPM: Remove struct aspm_register_info.l1ss_ctl2 (unused)
PCI/ASPM: Remove struct aspm_register_info.l1ss_cap_ptr
PCI/ASPM: Remove struct aspm_register_info.latency_encoding
PCI/ASPM: Remove struct aspm_register_info.enabled
PCI/ASPM: Remove struct aspm_register_info.support
PCI/ASPM: Use 'parent' and 'child' for readability
PCI/ASPM: Move LTR path check to where it's used
PCI/ASPM: Move pci_clear_and_set_dword() earlier
PCI: dwc: Fix MSI page leakage in suspend/resume
...
Diffstat (limited to 'drivers/pci/controller')
40 files changed, 1935 insertions, 1426 deletions
diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig index 4a7afbe189f8..64e2f5e379aa 100644 --- a/drivers/pci/controller/Kconfig +++ b/drivers/pci/controller/Kconfig @@ -12,7 +12,7 @@ config PCI_MVEBU select PCI_BRIDGE_EMUL config PCI_AARDVARK - bool "Aardvark PCIe controller" + tristate "Aardvark PCIe controller" depends on (ARCH_MVEBU && ARM64) || COMPILE_TEST depends on OF depends on PCI_MSI_IRQ_DOMAIN @@ -273,9 +273,10 @@ config VMD config PCIE_BRCMSTB tristate "Broadcom Brcmstb PCIe host controller" - depends on ARCH_BCM2835 || COMPILE_TEST + depends on ARCH_BRCMSTB || ARCH_BCM2835 || COMPILE_TEST depends on OF depends on PCI_MSI_IRQ_DOMAIN + default ARCH_BRCMSTB help Say Y here to enable PCIe host controller support for Broadcom STB based SoCs, like the Raspberry Pi 4. @@ -297,6 +298,13 @@ config PCI_LOONGSON Say Y here if you want to enable PCI controller support on Loongson systems. +config PCIE_HISI_ERR + depends on ACPI_APEI_GHES && (ARM64 || COMPILE_TEST) + bool "HiSilicon HIP PCIe controller error handling driver" + help + Say Y here if you want error handling support + for the PCIe controller's errors on HiSilicon HIP SoCs + source "drivers/pci/controller/dwc/Kconfig" source "drivers/pci/controller/mobiveil/Kconfig" source "drivers/pci/controller/cadence/Kconfig" diff --git a/drivers/pci/controller/Makefile b/drivers/pci/controller/Makefile index bcdbf49ab1e4..04c6edc285c5 100644 --- a/drivers/pci/controller/Makefile +++ b/drivers/pci/controller/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o obj-$(CONFIG_VMD) += vmd.o obj-$(CONFIG_PCIE_BRCMSTB) += pcie-brcmstb.o obj-$(CONFIG_PCI_LOONGSON) += pci-loongson.o +obj-$(CONFIG_PCIE_HISI_ERR) += pcie-hisi-error.o # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW obj-y += dwc/ obj-y += mobiveil/ diff --git a/drivers/pci/controller/cadence/pcie-cadence-ep.c b/drivers/pci/controller/cadence/pcie-cadence-ep.c index 254a3e1eff50..84cc58dc8512 100644 --- a/drivers/pci/controller/cadence/pcie-cadence-ep.c +++ b/drivers/pci/controller/cadence/pcie-cadence-ep.c @@ -328,7 +328,6 @@ static int cdns_pcie_ep_send_legacy_irq(struct cdns_pcie_ep *ep, u8 fn, u8 intx) cdns_pcie_ep_assert_intx(ep, fn, intx, true); /* * The mdelay() value was taken from dra7xx_pcie_raise_legacy_irq() - * from drivers/pci/dwc/pci-dra7xx.c */ mdelay(1); cdns_pcie_ep_assert_intx(ep, fn, intx, false); diff --git a/drivers/pci/controller/cadence/pcie-cadence-host.c b/drivers/pci/controller/cadence/pcie-cadence-host.c index 4550e0d469ca..811c1cb2e8de 100644 --- a/drivers/pci/controller/cadence/pcie-cadence-host.c +++ b/drivers/pci/controller/cadence/pcie-cadence-host.c @@ -337,7 +337,7 @@ static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc) struct resource_entry *entry; u64 cpu_addr = cfg_res->start; u32 addr0, addr1, desc1; - int r, err, busnr = 0; + int r, busnr = 0; entry = resource_list_first_type(&bridge->windows, IORESOURCE_BUS); if (entry) @@ -383,11 +383,7 @@ static int cdns_pcie_host_init_address_translation(struct cdns_pcie_rc *rc) r++; } - err = cdns_pcie_host_map_dma_ranges(rc); - if (err) - return err; - - return 0; + return cdns_pcie_host_map_dma_ranges(rc); } static int cdns_pcie_host_init(struct device *dev, diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig index 044a3761c44f..bc049865f8e0 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -237,8 +237,9 @@ config PCIE_HISI_STB Say Y here if you want PCIe controller support on HiSilicon STB SoCs config PCI_MESON - bool "MESON PCIe controller" + tristate "MESON PCIe controller" depends on PCI_MSI_IRQ_DOMAIN + default m if ARCH_MESON select PCIE_DW_HOST help Say Y here if you want to enable PCI controller support on Amlogic diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c index dc387724cf08..6d012d2b1e90 100644 --- a/drivers/pci/controller/dwc/pci-dra7xx.c +++ b/drivers/pci/controller/dwc/pci-dra7xx.c @@ -73,8 +73,6 @@ #define LINK_UP BIT(16) #define DRA7XX_CPU_TO_BUS_ADDR 0x0FFFFFFF -#define EXP_CAP_ID_OFFSET 0x70 - #define PCIECTRL_TI_CONF_INTX_ASSERT 0x0124 #define PCIECTRL_TI_CONF_INTX_DEASSERT 0x0128 @@ -91,7 +89,6 @@ struct dra7xx_pcie { void __iomem *base; /* DT ti_conf */ int phy_count; /* DT phy-names count */ struct phy **phy; - int link_gen; struct irq_domain *irq_domain; enum dw_pcie_device_mode mode; }; @@ -142,33 +139,12 @@ static int dra7xx_pcie_establish_link(struct dw_pcie *pci) struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci); struct device *dev = pci->dev; u32 reg; - u32 exp_cap_off = EXP_CAP_ID_OFFSET; if (dw_pcie_link_up(pci)) { dev_err(dev, "link is already up\n"); return 0; } - if (dra7xx->link_gen == 1) { - dw_pcie_read(pci->dbi_base + exp_cap_off + PCI_EXP_LNKCAP, - 4, ®); - if ((reg & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) { - reg &= ~((u32)PCI_EXP_LNKCAP_SLS); - reg |= PCI_EXP_LNKCAP_SLS_2_5GB; - dw_pcie_write(pci->dbi_base + exp_cap_off + - PCI_EXP_LNKCAP, 4, reg); - } - - dw_pcie_read(pci->dbi_base + exp_cap_off + PCI_EXP_LNKCTL2, - 2, ®); - if ((reg & PCI_EXP_LNKCAP_SLS) != PCI_EXP_LNKCAP_SLS_2_5GB) { - reg &= ~((u32)PCI_EXP_LNKCAP_SLS); - reg |= PCI_EXP_LNKCAP_SLS_2_5GB; - dw_pcie_write(pci->dbi_base + exp_cap_off + - PCI_EXP_LNKCTL2, 2, reg); - } - } - reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD); reg |= LTSSM_EN; dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg); @@ -490,7 +466,9 @@ static struct irq_chip dra7xx_pci_msi_bottom_irq_chip = { static int dra7xx_pcie_msi_host_init(struct pcie_port *pp) { struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct device *dev = pci->dev; u32 ctrl, num_ctrls; + int ret; pp->msi_irq_chip = &dra7xx_pci_msi_bottom_irq_chip; @@ -506,7 +484,21 @@ static int dra7xx_pcie_msi_host_init(struct pcie_port *pp) ~0); } - return dw_pcie_allocate_domains(pp); + ret = dw_pcie_allocate_domains(pp); + if (ret) + return ret; + + pp->msi_data = dma_map_single_attrs(dev, &pp->msi_msg, + sizeof(pp->msi_msg), + DMA_FROM_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + ret = dma_mapping_error(dev, pp->msi_data); + if (ret) { + dev_err(dev, "Failed to map MSI data\n"); + pp->msi_data = 0; + dw_pcie_free_msi(pp); + } + return ret; } static const struct dw_pcie_host_ops dra7xx_pcie_host_ops = { @@ -937,10 +929,6 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev) reg &= ~LTSSM_EN; dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg); - dra7xx->link_gen = of_pci_get_max_link_speed(np); - if (dra7xx->link_gen < 0 || dra7xx->link_gen > 2) - dra7xx->link_gen = 2; - switch (mode) { case DW_PCIE_RC_TYPE: if (!IS_ENABLED(CONFIG_PCI_DRA7XX_HOST)) { diff --git a/drivers/pci/controller/dwc/pci-exynos.c b/drivers/pci/controller/dwc/pci-exynos.c index 8d82c43ae299..242683cde04a 100644 --- a/drivers/pci/controller/dwc/pci-exynos.c +++ b/drivers/pci/controller/dwc/pci-exynos.c @@ -336,32 +336,37 @@ static void exynos_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base, exynos_pcie_sideband_dbi_w_mode(ep, false); } -static int exynos_pcie_rd_own_conf(struct pcie_port *pp, int where, int size, - u32 *val) +static int exynos_pcie_rd_own_conf(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *val) { - struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - struct exynos_pcie *ep = to_exynos_pcie(pci); - int ret; + struct dw_pcie *pci = to_dw_pcie_from_pp(bus->sysdata); - exynos_pcie_sideband_dbi_r_mode(ep, true); - ret = dw_pcie_read(pci->dbi_base + where, size, val); - exynos_pcie_sideband_dbi_r_mode(ep, false); - return ret; + if (PCI_SLOT(devfn)) { + *val = ~0; + return PCIBIOS_DEVICE_NOT_FOUND; + } + + *val = dw_pcie_read_dbi(pci, where, size); + return PCIBIOS_SUCCESSFUL; } -static int exynos_pcie_wr_own_conf(struct pcie_port *pp, int where, int size, - u32 val) +static int exynos_pcie_wr_own_conf(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) { - struct dw_pcie *pci = to_dw_pcie_from_pp(pp); - struct exynos_pcie *ep = to_exynos_pcie(pci); - int ret; + struct dw_pcie *pci = to_dw_pcie_from_pp(bus->sysdata); - exynos_pcie_sideband_dbi_w_mode(ep, true); - ret = dw_pcie_write(pci->dbi_base + where, size, val); - exynos_pcie_sideband_dbi_w_mode(ep, false); - return ret; + if (PCI_SLOT(devfn)) + return PCIBIOS_DEVICE_NOT_FOUND; + + dw_pcie_write_dbi(pci, where, size, val); + return PCIBIOS_SUCCESSFUL; } +static struct pci_ops exynos_pci_ops = { + .read = exynos_pcie_rd_own_conf, + .write = exynos_pcie_wr_own_conf, +}; + static int exynos_pcie_link_up(struct dw_pcie *pci) { struct exynos_pcie *ep = to_exynos_pcie(pci); @@ -379,6 +384,8 @@ static int exynos_pcie_host_init(struct pcie_port *pp) struct dw_pcie *pci = to_dw_pcie_from_pp(pp); struct exynos_pcie *ep = to_exynos_pcie(pci); + pp->bridge->ops = &exynos_pci_ops; + exynos_pcie_establish_link(ep); exynos_pcie_enable_interrupts(ep); @@ -386,8 +393,6 @@ static int exynos_pcie_host_init(struct pcie_port *pp) } static const struct dw_pcie_host_ops exynos_pcie_host_ops = { - .rd_own_conf = exynos_pcie_rd_own_conf, - .wr_own_conf = exynos_pcie_wr_own_conf, .host_init = exynos_pcie_host_init, }; diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 5fef2613b223..5cf1ef12fb9b 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -79,7 +79,6 @@ struct imx6_pcie { u32 tx_deemph_gen2_6db; u32 tx_swing_full; u32 tx_swing_low; - int link_gen; struct regulator *vpcie; void __iomem *phy_base; @@ -94,15 +93,6 @@ struct imx6_pcie { #define PHY_PLL_LOCK_WAIT_USLEEP_MAX 200 #define PHY_PLL_LOCK_WAIT_TIMEOUT (2000 * PHY_PLL_LOCK_WAIT_USLEEP_MAX) -/* PCIe Root Complex registers (memory-mapped) */ -#define PCIE_RC_IMX6_MSI_CAP 0x50 -#define PCIE_RC_LCR 0x7c -#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1 0x1 -#define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2 0x2 -#define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK 0xf - -#define PCIE_RC_LCSR 0x80 - /* PCIe Port Logic registers (memory-mapped) */ #define PL_OFFSET 0x700 @@ -116,8 +106,6 @@ struct imx6_pcie { #define PCIE_PHY_STAT (PL_OFFSET + 0x110) #define PCIE_PHY_STAT_ACK BIT(16) -#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C - /* PHY registers (not memory-mapped) */ #define PCIE_PHY_ATEOVRD 0x10 #define PCIE_PHY_ATEOVRD_EN BIT(2) @@ -761,6 +749,7 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) { struct dw_pcie *pci = imx6_pcie->pci; struct device *dev = pci->dev; + u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP); u32 tmp; int ret; @@ -769,10 +758,10 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) * started in Gen2 mode, there is a possibility the devices on the * bus will not be detected at all. This happens with PCIe switches. */ - tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR); - tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; - tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1; - dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); + tmp = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP); + tmp &= ~PCI_EXP_LNKCAP_SLS; + tmp |= PCI_EXP_LNKCAP_SLS_2_5GB; + dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, tmp); /* Start LTSSM. */ imx6_pcie_ltssm_enable(dev); @@ -781,12 +770,12 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) if (ret) goto err_reset_phy; - if (imx6_pcie->link_gen == 2) { + if (pci->link_gen == 2) { /* Allow Gen2 mode after the link is up. */ - tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCR); - tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; - tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2; - dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp); + tmp = dw_pcie_readl_dbi(pci, offset + PCI_EXP_LNKCAP); + tmp &= ~PCI_EXP_LNKCAP_SLS; + tmp |= PCI_EXP_LNKCAP_SLS_5_0GB; + dw_pcie_writel_dbi(pci, offset + PCI_EXP_LNKCAP, tmp); /* * Start Directed Speed Change so the best possible @@ -824,8 +813,8 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) dev_info(dev, "Link: Gen2 disabled\n"); } - tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCSR); - dev_info(dev, "Link up, Gen%i\n", (tmp >> 16) & 0xf); + tmp = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA); + dev_info(dev, "Link up, Gen%i\n", tmp & PCI_EXP_LNKSTA_CLS); return 0; err_reset_phy: @@ -847,9 +836,7 @@ static int imx6_pcie_host_init(struct pcie_port *pp) imx6_setup_phy_mpll(imx6_pcie); dw_pcie_setup_rc(pp); imx6_pcie_establish_link(imx6_pcie); - - if (IS_ENABLED(CONFIG_PCI_MSI)) - dw_pcie_msi_init(pp); + dw_pcie_msi_init(pp); return 0; } @@ -1073,38 +1060,33 @@ static int imx6_pcie_probe(struct platform_device *pdev) /* Fetch clocks */ imx6_pcie->pcie_phy = devm_clk_get(dev, "pcie_phy"); - if (IS_ERR(imx6_pcie->pcie_phy)) { - dev_err(dev, "pcie_phy clock source missing or invalid\n"); - return PTR_ERR(imx6_pcie->pcie_phy); - } + if (IS_ERR(imx6_pcie->pcie_phy)) + return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_phy), + "pcie_phy clock source missing or invalid\n"); imx6_pcie->pcie_bus = devm_clk_get(dev, "pcie_bus"); - if (IS_ERR(imx6_pcie->pcie_bus)) { - dev_err(dev, "pcie_bus clock source missing or invalid\n"); - return PTR_ERR(imx6_pcie->pcie_bus); - } + if (IS_ERR(imx6_pcie->pcie_bus)) + return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_bus), + "pcie_bus clock source missing or invalid\n"); imx6_pcie->pcie = devm_clk_get(dev, "pcie"); - if (IS_ERR(imx6_pcie->pcie)) { - dev_err(dev, "pcie clock source missing or invalid\n"); - return PTR_ERR(imx6_pcie->pcie); - } + if (IS_ERR(imx6_pcie->pcie)) + return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie), + "pcie clock source missing or invalid\n"); switch (imx6_pcie->drvdata->variant) { case IMX6SX: imx6_pcie->pcie_inbound_axi = devm_clk_get(dev, "pcie_inbound_axi"); - if (IS_ERR(imx6_pcie->pcie_inbound_axi)) { - dev_err(dev, "pcie_inbound_axi clock missing or invalid\n"); - return PTR_ERR(imx6_pcie->pcie_inbound_axi); - } + if (IS_ERR(imx6_pcie->pcie_inbound_axi)) + return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_inbound_axi), + "pcie_inbound_axi clock missing or invalid\n"); break; case IMX8MQ: imx6_pcie->pcie_aux = devm_clk_get(dev, "pcie_aux"); - if (IS_ERR(imx6_pcie->pcie_aux)) { - dev_err(dev, "pcie_aux clock source missing or invalid\n"); - return PTR_ERR(imx6_pcie->pcie_aux); - } + if (IS_ERR(imx6_pcie->pcie_aux)) + return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_aux), + "pcie_aux clock source missing or invalid\n"); fallthrough; case IMX7D: if (dbi_base->start == IMX8MQ_PCIE2_BASE_ADDR) @@ -1165,10 +1147,8 @@ static int imx6_pcie_probe(struct platform_device *pdev) imx6_pcie->tx_swing_low = 127; /* Limit link speed */ - ret = of_property_read_u32(node, "fsl,max-link-speed", - &imx6_pcie->link_gen); - if (ret) - imx6_pcie->link_gen = 1; + pci->link_gen = 1; + ret = of_property_read_u32(node, "fsl,max-link-speed", &pci->link_gen); imx6_pcie->vpcie = devm_regulator_get_optional(&pdev->dev, "vpcie"); if (IS_ERR(imx6_pcie->vpcie)) { @@ -1188,11 +1168,10 @@ static int imx6_pcie_probe(struct platform_device *pdev) return ret; if (pci_msi_enabled()) { - val = dw_pcie_readw_dbi(pci, PCIE_RC_IMX6_MSI_CAP + - PCI_MSI_FLAGS); + u8 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_MSI); + val = dw_pcie_readw_dbi(pci, offset + PCI_MSI_FLAGS); val |= PCI_MSI_FLAGS_ENABLE; - dw_pcie_writew_dbi(pci, PCIE_RC_IMX6_MSI_CAP + PCI_MSI_FLAGS, - val); + dw_pcie_writew_dbi(pci, offset + PCI_MSI_FLAGS, val); } return 0; diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c index c8c9d6a75f17..a222728238ca 100644 --- a/drivers/pci/controller/dwc/pci-keystone.c +++ b/drivers/pci/controller/dwc/pci-keystone.c @@ -96,8 +96,6 @@ #define LEG_EP 0x1 #define RC 0x2 -#define EXP_CAP_ID_OFFSET 0x70 - #define KS_PCIE_SYSCLOCKOUTEN BIT(0) #define AM654_PCIE_DEV_TYPE_MASK 0x3 @@ -123,7 +121,6 @@ struct keystone_pcie { int msi_host_irq; int num_lanes; - u32 num_viewport; struct phy **phy; struct device_link **link; struct device_node *msi_intc_np; @@ -397,13 +394,17 @@ static void ks_pcie_clear_dbi_mode(struct keystone_pcie *ks_pcie) static void ks_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie) { u32 val; - u32 num_viewport = ks_pcie->num_viewport; struct dw_pcie *pci = ks_pcie->pci; struct pcie_port *pp = &pci->pp; - u64 start = pp->mem->start; - u64 end = pp->mem->end; + u32 num_viewport = pci->num_viewport; + u64 start, end; + struct resource *mem; int i; + mem = resource_list_first_type(&pp->bridge->windows, IORESOURCE_MEM)->res; + start = mem->start; + end = mem->end; + /* Disable BARs for inbound access */ ks_pcie_set_dbi_mode(ks_pcie); dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0); @@ -430,10 +431,10 @@ static void ks_pcie_setup_rc_app_regs(struct keystone_pcie *ks_pcie) ks_pcie_app_writel(ks_pcie, CMD_STATUS, val); } -static int ks_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, |