diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-04-27 20:45:30 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-04-27 20:45:30 +0300 |
commit | 34b62f186db9614e55d021f8c58d22fc44c57911 (patch) | |
tree | dc79b254531aaa4b338067b6de86c534cb2fe0f7 /drivers/pci | |
parent | cb6fe2ceb667eb78f252d473b03deb23999ab1cf (diff) | |
parent | 09a8e5f01dfb30667a8f05e35c1cc073cb4fd134 (diff) | |
download | linux-34b62f186db9614e55d021f8c58d22fc44c57911.tar.xz |
Merge tag 'pci-v6.4-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci
Pull pci updates from Bjorn Helgaas:
"Resource management:
- Add pci_dev_for_each_resource() and pci_bus_for_each_resource()
iterators
PCIe native device hotplug:
- Fix AB-BA deadlock between reset_lock and device_lock
Power management:
- Wait longer for devices to become ready after resume (as we do for
reset) to accommodate Intel Titan Ridge xHCI devices
- Extend D3hot delay for NVIDIA HDA controllers to avoid
unrecoverable devices after a bus reset
Error handling:
- Clear PCIe Device Status after EDR since generic error recovery now
only clears it when AER is native
ASPM:
- Work around Chromebook firmware defect that clobbers Capability
list (including ASPM L1 PM Substates Cap) when returning from
D3cold to D0
Freescale i.MX6 PCIe controller driver:
- Install imprecise external abort handler only when DT indicates
PCIe support
Freescale Layerscape PCIe controller driver:
- Add ls1028a endpoint mode support
Qualcomm PCIe controller driver:
- Add SM8550 DT binding and driver support
- Add SDX55 DT binding and driver support
- Use bulk APIs for clocks of IP 1.0.0, 2.3.2, 2.3.3
- Use bulk APIs for reset of IP 2.1.0, 2.3.3, 2.4.0
- Add DT "mhi" register region for supported SoCs
- Expose link transition counts via debugfs to help debug low power
issues
- Support system suspend and resume; reduce interconnect bandwidth
and turn off clock and PHY if there are no active devices
- Enable async probe by default to reduce boot time
Miscellaneous:
- Sort controller Kconfig entries by vendor"
* tag 'pci-v6.4-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci: (56 commits)
PCI: xilinx: Drop obsolete dependency on COMPILE_TEST
PCI: mobiveil: Sort Kconfig entries by vendor
PCI: dwc: Sort Kconfig entries by vendor
PCI: Sort controller Kconfig entries by vendor
PCI: Use consistent controller Kconfig menu entry language
PCI: xilinx-nwl: Add 'Xilinx' to Kconfig prompt
PCI: hv: Add 'Microsoft' to Kconfig prompt
PCI: meson: Add 'Amlogic' to Kconfig prompt
PCI: Use of_property_present() for testing DT property presence
PCI/PM: Extend D3hot delay for NVIDIA HDA controllers
dt-bindings: PCI: qcom: Document msi-map and msi-map-mask properties
PCI: qcom: Add SM8550 PCIe support
dt-bindings: PCI: qcom: Add SM8550 compatible
PCI: qcom: Add support for SDX55 SoC
dt-bindings: PCI: qcom-ep: Fix the unit address used in example
dt-bindings: PCI: qcom: Add SDX55 SoC
dt-bindings: PCI: qcom: Update maintainers entry
PCI: qcom: Enable async probe by default
PCI: qcom: Add support for system suspend and resume
PCI/PM: Drop pci_bridge_wait_for_secondary_bus() timeout parameter
...
Diffstat (limited to 'drivers/pci')
31 files changed, 1072 insertions, 1260 deletions
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index 549c4bd5caec..5bc81cc0a2de 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -182,13 +182,13 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res, void *alignf_data, struct pci_bus_region *region) { - int i, ret; struct resource *r, avail; resource_size_t max; + int ret; type_mask |= IORESOURCE_TYPE_BITS; - pci_bus_for_each_resource(bus, r, i) { + pci_bus_for_each_resource(bus, r) { resource_size_t min_used = min; if (!r) @@ -289,9 +289,8 @@ bool pci_bus_clip_resource(struct pci_dev *dev, int idx) struct resource *res = &dev->resource[idx]; struct resource orig_res = *res; struct resource *r; - int i; - pci_bus_for_each_resource(bus, r, i) { + pci_bus_for_each_resource(bus, r) { resource_size_t start, end; if (!r) diff --git a/drivers/pci/controller/Kconfig b/drivers/pci/controller/Kconfig index 42654035654a..8d49bad7f847 100644 --- a/drivers/pci/controller/Kconfig +++ b/drivers/pci/controller/Kconfig @@ -3,19 +3,6 @@ menu "PCI controller drivers" depends on PCI -config PCI_MVEBU - tristate "Marvell EBU PCIe controller" - depends on ARCH_MVEBU || ARCH_DOVE || COMPILE_TEST - depends on MVEBU_MBUS - depends on ARM - depends on OF - depends on BROKEN - select PCI_BRIDGE_EMUL - help - Add support for Marvell EBU PCIe controller. This PCIe controller - is used on 32-bit Marvell ARM SoCs: Dove, Kirkwood, Armada 370, - Armada XP, Armada 375, Armada 38x and Armada 39x. - config PCI_AARDVARK tristate "Aardvark PCIe controller" depends on (ARCH_MVEBU && ARM64) || COMPILE_TEST @@ -27,120 +14,54 @@ config PCI_AARDVARK controller is part of the South Bridge of the Marvel Armada 3700 SoC. -config PCIE_XILINX_NWL - bool "NWL PCIe Core" - depends on ARCH_ZYNQMP || COMPILE_TEST - depends on PCI_MSI - help - Say 'Y' here if you want kernel support for Xilinx - NWL PCIe controller. The controller can act as Root Port - or End Point. The current option selection will only - support root port enabling. - -config PCI_FTPCI100 - bool "Faraday Technology FTPCI100 PCI controller" - depends on OF - default ARCH_GEMINI - -config PCI_IXP4XX - bool "Intel IXP4xx PCI controller" - depends on ARM && OF - depends on ARCH_IXP4XX || COMPILE_TEST - default ARCH_IXP4XX - help - Say Y here if you want support for the PCI host controller found - in the Intel IXP4xx XScale-based network processor SoC. - -config PCI_TEGRA - bool "NVIDIA Tegra PCIe controller" - depends on ARCH_TEGRA || COMPILE_TEST - depends on PCI_MSI - help - Say Y here if you want support for the PCIe host controller found - on NVIDIA Tegra SoCs. - -config PCI_RCAR_GEN2 - bool "Renesas R-Car Gen2 Internal PCI controller" - depends on ARCH_RENESAS || COMPILE_TEST - depends on ARM +config PCIE_ALTERA + tristate "Altera PCIe controller" + depends on ARM || NIOS2 || ARM64 || COMPILE_TEST help - Say Y here if you want internal PCI support on R-Car Gen2 SoC. - There are 3 internal PCI controllers available with a single - built-in EHCI/OHCI host controller present on each one. + Say Y here if you want to enable PCIe controller support on Altera + FPGA. -config PCIE_RCAR_HOST - bool "Renesas R-Car PCIe host controller" - depends on ARCH_RENESAS || COMPILE_TEST +config PCIE_ALTERA_MSI + tristate "Altera PCIe MSI feature" + depends on PCIE_ALTERA depends on PCI_MSI help - Say Y here if you want PCIe controller support on R-Car SoCs in host - mode. - -config PCIE_RCAR_EP - bool "Renesas R-Car PCIe endpoint controller" - depends on ARCH_RENESAS || COMPILE_TEST - depends on PCI_ENDPOINT - help - Say Y here if you want PCIe controller support on R-Car SoCs in - endpoint mode. + Say Y here if you want PCIe MSI support for the Altera FPGA. + This MSI driver supports Altera MSI to GIC controller IP. -config PCI_HOST_COMMON - tristate - select PCI_ECAM +config PCIE_APPLE_MSI_DOORBELL_ADDR + hex + default 0xfffff000 + depends on PCIE_APPLE -config PCI_HOST_GENERIC - tristate "Generic PCI host controller" +config PCIE_APPLE + tristate "Apple PCIe controller" + depends on ARCH_APPLE || COMPILE_TEST depends on OF - select PCI_HOST_COMMON - select IRQ_DOMAIN - help - Say Y here if you want to support a simple generic PCI host - controller, such as the one emulated by kvmtool. - -config PCIE_XILINX - bool "Xilinx AXI PCIe host bridge support" - depends on OF || COMPILE_TEST depends on PCI_MSI - help - Say 'Y' here if you want kernel to support the Xilinx AXI PCIe - Host Bridge driver. - -config PCIE_XILINX_CPM - bool "Xilinx Versal CPM host bridge support" - depends on ARCH_ZYNQMP || COMPILE_TEST select PCI_HOST_COMMON help - Say 'Y' here if you want kernel support for the - Xilinx Versal CPM host bridge. - -config PCI_XGENE - bool "X-Gene PCIe controller" - depends on ARM64 || COMPILE_TEST - depends on OF || (ACPI && PCI_QUIRKS) - help - Say Y here if you want internal PCI support on APM X-Gene SoC. - There are 5 internal PCIe ports available. Each port is GEN3 capable - and have varied lanes from x1 to x8. - -config PCI_XGENE_MSI - bool "X-Gene v1 PCIe MSI feature" - depends on PCI_XGENE - depends on PCI_MSI - default y - help - Say Y here if you want PCIe MSI support for the APM X-Gene v1 SoC. - This MSI driver supports 5 PCIe ports on the APM X-Gene v1 SoC. + Say Y here if you want to enable PCIe controller support on Apple + system-on-chips, like the Apple M1. This is required for the USB + type-A ports, Ethernet, Wi-Fi, and Bluetooth. -config PCI_V3_SEMI - bool "V3 Semiconductor PCI controller" - depends on OF - depends on ARM || COMPILE_TEST - default ARCH_INTEGRATOR_AP + If unsure, say Y if you have an Apple Silicon system. config PCI_VERSATILE bool "ARM Versatile PB PCI controller" depends on ARCH_VERSATILE || COMPILE_TEST +config PCIE_BRCMSTB + tristate "Broadcom Brcmstb PCIe controller" + depends on ARCH_BRCMSTB || ARCH_BCM2835 || ARCH_BCMBCA || \ + BMIPS_GENERIC || COMPILE_TEST + depends on OF + depends on PCI_MSI + default ARCH_BRCMSTB || BMIPS_GENERIC + help + Say Y here to enable PCIe host controller support for + Broadcom STB based SoCs, like the Raspberry Pi 4. + config PCIE_IPROC tristate help @@ -159,7 +80,7 @@ config PCIE_IPROC_PLATFORM through the generic platform bus interface config PCIE_IPROC_BCMA - tristate "Broadcom iProc PCIe BCMA bus driver" + tristate "Broadcom iProc BCMA PCIe controller" depends on ARM && (ARCH_BCM_IPROC || COMPILE_TEST) select PCIE_IPROC select BCMA @@ -177,21 +98,6 @@ config PCIE_IPROC_MSI Say Y here if you want to enable MSI support for Broadcom's iProc PCIe controller -config PCIE_ALTERA - tristate "Altera PCIe controller" - depends on ARM || NIOS2 || ARM64 || COMPILE_TEST - help - Say Y here if you want to enable PCIe controller support on Altera - FPGA. - -config PCIE_ALTERA_MSI - tristate "Altera PCIe MSI feature" - depends on PCIE_ALTERA - depends on PCI_MSI - help - Say Y here if you want PCIe MSI support for the Altera FPGA. - This MSI driver supports Altera MSI to GIC controller IP. - config PCI_HOST_THUNDER_PEM bool "Cavium Thunder PCIe controller to off-chip devices" depends on ARM64 || COMPILE_TEST @@ -208,33 +114,77 @@ config PCI_HOST_THUNDER_ECAM help Say Y here if you want ECAM support for CN88XX-Pass-1.x Cavium Thunder SoCs. -config PCIE_ROCKCHIP - bool - depends on PCI +config PCI_FTPCI100 + bool "Faraday Technology FTPCI100 PCI controller" + depends on OF + default ARCH_GEMINI -config PCIE_ROCKCHIP_HOST - tristate "Rockchip PCIe host controller" - depends on ARCH_ROCKCHIP || COMPILE_TEST +config PCI_HOST_COMMON + tristate + select PCI_ECAM + +config PCI_HOST_GENERIC + tristate "Generic PCI host controller" depends on OF - depends on PCI_MSI - select MFD_SYSCON - select PCIE_ROCKCHIP + select PCI_HOST_COMMON + select IRQ_DOMAIN help - Say Y here if you want internal PCI support on Rockchip SoC. - There is 1 internal PCIe port available to support GEN2 with - 4 slots. + Say Y here if you want to support a simple generic PCI host + controller, such as the one emulated by kvmtool. -config PCIE_ROCKCHIP_EP - bool "Rockchip PCIe endpoint controller" - depends on ARCH_ROCKCHIP || COMPILE_TEST +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 + +config PCI_IXP4XX + bool "Intel IXP4xx PCI controller" + depends on ARM && OF + depends on ARCH_IXP4XX || COMPILE_TEST + default ARCH_IXP4XX + help + Say Y here if you want support for the PCI host controller found + in the Intel IXP4xx XScale-based network processor SoC. + +config VMD + depends on PCI_MSI && X86_64 && !UML + tristate "Intel Volume Management Device Driver" + help + Adds support for the Intel Volume Management Device (VMD). VMD is a + secondary PCI host bridge that allows PCI Express root ports, + and devices attached to them, to be removed from the default + PCI domain and placed within the VMD domain. This provides + more bus resources than are otherwise possible with a + single domain. If you know your system provides one of these and + has devices attached to it, say Y; if you are not sure, say N. + + To compile this driver as a module, choose M here: the + module will be called vmd. + +config PCI_LOONGSON + bool "LOONGSON PCIe controller" + depends on MACH_LOONGSON64 || COMPILE_TEST + depends on OF || ACPI + depends on PCI_QUIRKS + default MACH_LOONGSON64 + help + Say Y here if you want to enable PCI controller support on + Loongson systems. + +config PCI_MVEBU + tristate "Marvell EBU PCIe controller" + depends on ARCH_MVEBU || ARCH_DOVE || COMPILE_TEST + depends on MVEBU_MBUS + depends on ARM depends on OF - depends on PCI_ENDPOINT - select MFD_SYSCON - select PCIE_ROCKCHIP + depends on BROKEN + select PCI_BRIDGE_EMUL help - Say Y here if you want to support Rockchip PCIe controller in - endpoint mode on Rockchip SoC. There is 1 internal PCIe port - available to support GEN2 with 4 slots. + Add support for Marvell EBU PCIe controller. This PCIe controller + is used on 32-bit Marvell ARM SoCs: Dove, Kirkwood, Armada 370, + Armada XP, Armada 375, Armada 38x and Armada 39x. config PCIE_MEDIATEK tristate "MediaTek PCIe controller" @@ -258,91 +208,142 @@ config PCIE_MEDIATEK_GEN3 Say Y here if you want to enable Gen3 PCIe controller support on MediaTek SoCs. -config VMD - depends on PCI_MSI && X86_64 && !UML - tristate "Intel Volume Management Device Driver" +config PCIE_MT7621 + tristate "MediaTek MT7621 PCIe controller" + depends on SOC_MT7621 || COMPILE_TEST + select PHY_MT7621_PCI + default SOC_MT7621 help - Adds support for the Intel Volume Management Device (VMD). VMD is a - secondary PCI host bridge that allows PCI Express root ports, - and devices attached to them, to be removed from the default - PCI domain and placed within the VMD domain. This provides - more bus resources than are otherwise possible with a - single domain. If you know your system provides one of these and - has devices attached to it, say Y; if you are not sure, say N. - - To compile this driver as a module, choose M here: the - module will be called vmd. + This selects a driver for the MediaTek MT7621 PCIe Controller. -config PCIE_BRCMSTB - tristate "Broadcom Brcmstb PCIe host controller" - depends on ARCH_BRCMSTB || ARCH_BCM2835 || ARCH_BCMBCA || \ - BMIPS_GENERIC || COMPILE_TEST - depends on OF - depends on PCI_MSI - default ARCH_BRCMSTB || BMIPS_GENERIC +config PCIE_MICROCHIP_HOST + bool "Microchip AXI PCIe controller" + depends on PCI_MSI && OF + select PCI_HOST_COMMON help - Say Y here to enable PCIe host controller support for - Broadcom STB based SoCs, like the Raspberry Pi 4. + Say Y here if you want kernel to support the Microchip AXI PCIe + Host Bridge driver. config PCI_HYPERV_INTERFACE - tristate "Hyper-V PCI Interface" + tristate "Microsoft Hyper-V PCI Interface" depends on ((X86 && X86_64) || ARM64) && HYPERV && PCI_MSI help - The Hyper-V PCI Interface is a helper driver allows other drivers to - have a common interface with the Hyper-V PCI frontend driver. + The Hyper-V PCI Interface is a helper driver that allows other + drivers to have a common interface with the Hyper-V PCI frontend + driver. -config PCI_LOONGSON - bool "LOONGSON PCI Controller" - depends on MACH_LOONGSON64 || COMPILE_TEST - depends on OF || ACPI - depends on PCI_QUIRKS - default MACH_LOONGSON64 +config PCI_TEGRA + bool "NVIDIA Tegra PCIe controller" + depends on ARCH_TEGRA || COMPILE_TEST + depends on PCI_MSI help - Say Y here if you want to enable PCI controller support on - Loongson systems. + Say Y here if you want support for the PCIe host controller found + on NVIDIA Tegra SoCs. -config PCIE_MICROCHIP_HOST - bool "Microchip AXI PCIe host bridge support" - depends on PCI_MSI && OF - select PCI_HOST_COMMON +config PCIE_RCAR_HOST + bool "Renesas R-Car PCIe controller (host mode)" + depends on ARCH_RENESAS || COMPILE_TEST + depends on PCI_MSI help - Say Y here if you want kernel to support the Microchip AXI PCIe - Host Bridge driver. + Say Y here if you want PCIe controller support on R-Car SoCs in host + mode. -config PCIE_HISI_ERR - depends on ACPI_APEI_GHES && (ARM64 || COMPILE_TEST) - bool "HiSilicon HIP PCIe controller error handling driver" +config PCIE_RCAR_EP + bool "Renesas R-Car PCIe controller (endpoint mode)" + depends on ARCH_RENESAS || COMPILE_TEST + depends on PCI_ENDPOINT help - Say Y here if you want error handling support - for the PCIe controller's errors on HiSilicon HIP SoCs + Say Y here if you want PCIe controller support on R-Car SoCs in + endpoint mode. -config PCIE_APPLE_MSI_DOORBELL_ADDR - hex - default 0xfffff000 - depends on PCIE_APPLE +config PCI_RCAR_GEN2 + bool "Renesas R-Car Gen2 Internal PCI controller" + depends on ARCH_RENESAS || COMPILE_TEST + depends on ARM + help + Say Y here if you want internal PCI support on R-Car Gen2 SoC. + There are 3 internal PCI controllers available with a single + built-in EHCI/OHCI host controller present on each one. -config PCIE_APPLE - tristate "Apple PCIe controller" - depends on ARCH_APPLE || COMPILE_TEST +config PCIE_ROCKCHIP + bool + depends on PCI + +config PCIE_ROCKCHIP_HOST + tristate "Rockchip PCIe controller (host mode)" + depends on ARCH_ROCKCHIP || COMPILE_TEST depends on OF depends on PCI_MSI - select PCI_HOST_COMMON + select MFD_SYSCON + select PCIE_ROCKCHIP help - Say Y here if you want to enable PCIe controller support on Apple - system-on-chips, like the Apple M1. This is required for the USB - type-A ports, Ethernet, Wi-Fi, and Bluetooth. + Say Y here if you want internal PCI support on Rockchip SoC. + There is 1 internal PCIe port available to support GEN2 with + 4 slots. - If unsure, say Y if you have an Apple Silicon system. +config PCIE_ROCKCHIP_EP + bool "Rockchip PCIe controller (endpoint mode)" + depends on ARCH_ROCKCHIP || COMPILE_TEST + depends on OF + depends on PCI_ENDPOINT + select MFD_SYSCON + select PCIE_ROCKCHIP + help + Say Y here if you want to support Rockchip PCIe controller in + endpoint mode on Rockchip SoC. There is 1 internal PCIe port + available to support GEN2 with 4 slots. -config PCIE_MT7621 - tristate "MediaTek MT7621 PCIe Controller" - depends on SOC_MT7621 || COMPILE_TEST - select PHY_MT7621_PCI - default SOC_MT7621 +config PCI_V3_SEMI + bool "V3 Semiconductor PCI controller" + depends on OF + depends on ARM || COMPILE_TEST + default ARCH_INTEGRATOR_AP + +config PCI_XGENE + bool "X-Gene PCIe controller" + depends on ARM64 || COMPILE_TEST + depends on OF || (ACPI && PCI_QUIRKS) help - This selects a driver for the MediaTek MT7621 PCIe Controller. + Say Y here if you want internal PCI support on APM X-Gene SoC. + There are 5 internal PCIe ports available. Each port is GEN3 capable + and have varied lanes from x1 to x8. + +config PCI_XGENE_MSI + bool "X-Gene v1 PCIe MSI feature" + depends on PCI_XGENE + depends on PCI_MSI + default y + help + Say Y here if you want PCIe MSI support for the APM X-Gene v1 SoC. + This MSI driver supports 5 PCIe ports on the APM X-Gene v1 SoC. + +config PCIE_XILINX + bool "Xilinx AXI PCIe controller" + depends on OF + depends on PCI_MSI + help + Say 'Y' here if you want kernel to support the Xilinx AXI PCIe + Host Bridge driver. + +config PCIE_XILINX_NWL + bool "Xilinx NWL PCIe controller" + depends on ARCH_ZYNQMP || COMPILE_TEST + depends on PCI_MSI + help + Say 'Y' here if you want kernel support for Xilinx + NWL PCIe controller. The controller can act as Root Port + or End Point. The current option selection will only + support root port enabling. + +config PCIE_XILINX_CPM + bool "Xilinx Versal CPM PCI controller" + depends on ARCH_ZYNQMP || COMPILE_TEST + select PCI_HOST_COMMON + help + Say 'Y' here if you want kernel support for the + Xilinx Versal CPM host bridge. +source "drivers/pci/controller/cadence/Kconfig" source "drivers/pci/controller/dwc/Kconfig" source "drivers/pci/controller/mobiveil/Kconfig" -source "drivers/pci/controller/cadence/Kconfig" endmenu diff --git a/drivers/pci/controller/cadence/Kconfig b/drivers/pci/controller/cadence/Kconfig index 5d30564190e1..291d12711363 100644 --- a/drivers/pci/controller/cadence/Kconfig +++ b/drivers/pci/controller/cadence/Kconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -menu "Cadence PCIe controllers support" +menu "Cadence-based PCIe controllers" depends on PCI config PCIE_CADENCE @@ -22,7 +22,7 @@ config PCIE_CADENCE_PLAT bool config PCIE_CADENCE_PLAT_HOST - bool "Cadence PCIe platform host controller" + bool "Cadence platform PCIe controller (host mode)" depends on OF select PCIE_CADENCE_HOST select PCIE_CADENCE_PLAT @@ -32,7 +32,7 @@ config PCIE_CADENCE_PLAT_HOST vendors SoCs. config PCIE_CADENCE_PLAT_EP - bool "Cadence PCIe platform endpoint controller" + bool "Cadence platform PCIe controller (endpoint mode)" depends on OF depends on PCI_ENDPOINT select PCIE_CADENCE_EP @@ -46,7 +46,7 @@ config PCI_J721E bool config PCI_J721E_HOST - bool "TI J721E PCIe platform host controller" + bool "TI J721E PCIe controller (host mode)" depends on OF select PCIE_CADENCE_HOST select PCI_J721E @@ -56,7 +56,7 @@ config PCI_J721E_HOST core. config PCI_J721E_EP - bool "TI J721E PCIe platform endpoint controller" + bool "TI J721E PCIe controller (endpoint mode)" depends on OF depends on PCI_ENDPOINT select PCIE_CADENCE_EP diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig index 434f6a4f4041..ab96da43e0c2 100644 --- a/drivers/pci/controller/dwc/Kconfig +++ b/drivers/pci/controller/dwc/Kconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -menu "DesignWare PCI Core Support" +menu "DesignWare-based PCIe controllers" depends on PCI config PCIE_DW @@ -14,88 +14,67 @@ config PCIE_DW_EP bool select PCIE_DW -config PCI_DRA7XX - tristate - -config PCI_DRA7XX_HOST - tristate "TI DRA7xx PCIe controller Host Mode" - depends on SOC_DRA7XX || COMPILE_TEST - depends on OF && HAS_IOMEM && TI_PIPE3 +config PCIE_AL + bool "Amazon Annapurna Labs PCIe controller" + depends on OF && (ARM64 || COMPILE_TEST) depends on PCI_MSI select PCIE_DW_HOST - select PCI_DRA7XX - default y if SOC_DRA7XX + select PCI_ECAM help - Enables support for the PCIe controller in the DRA7xx SoC to work in - host mode. There are two instances of PCIe controller in DRA7xx. - This controller can work either as EP or RC. In order to enable - host-specific features PCI_DRA7XX_HOST must be selected and in order - to enable device-specific features PCI_DRA7XX_EP must be selected. - This uses the DesignWare core. + Say Y here to enable support of the Amazon's Annapurna Labs PCIe + controller IP on Amazon SoCs. The PCIe controller uses the DesignWare + core plus Annapurna Labs proprietary hardware wrappers. This is + required only for DT-based platforms. ACPI platforms with the + Annapurna Labs PCIe controller don't need to enable this. -config PCI_DRA7XX_EP - tristate "TI DRA7xx PCIe controller Endpoint Mode" - depends on SOC_DRA7XX || COMPILE_TEST - depends on OF && HAS_IOMEM && TI_PIPE3 - depends on PCI_ENDPOINT - select PCIE_DW_EP - select PCI_DRA7XX +config PCI_MESON + tristate "Amlogic Meson PCIe controller" + default m if ARCH_MESON + depends on PCI_MSI + select PCIE_DW_HOST help - Enables support for the PCIe controller in the DRA7xx SoC to work in - endpoint mode. There are two instances of PCIe controller in DRA7xx. - This controller can work either as EP or RC. In order to enable - host-specific features PCI_DRA7XX_HOST must be selected and in order - to enable device-specific features PCI_DRA7XX_EP must be selected. - This uses the DesignWare core. + Say Y here if you want to enable PCI controller support on Amlogic + SoCs. The PCI controller on Amlogic is based on DesignWare hardware + and therefore the driver re-uses the DesignWare core functions to + implement the driver. -config PCIE_DW_PLAT +config PCIE_ARTPEC6 bool -config PCIE_DW_PLAT_HOST - bool "Platform bus based DesignWare PCIe Controller - Host mode" +config PCIE_ARTPEC6_HOST + bool "Axis ARTPEC-6 PCIe controller (host mode)" + depends on MACH_ARTPEC6 || COMPILE_TEST depends on PCI_MSI select PCIE_DW_HOST - select PCIE_DW_PLAT + select PCIE_ARTPEC6 help - Enables support for the PCIe controller in the Designware IP to - work in host mode. There are two instances of PCIe controller in - Designware IP. - This controller can work either as EP or RC. In order to enable - host-specific features PCIE_DW_PLAT_HOST must be selected and in - order to enable device-specific features PCI_DW_PLAT_EP must be - selected. + Enables support for the PCIe controller in the ARTPEC-6 SoC to work in + host mode. This uses the DesignWare core. -config PCIE_DW_PLAT_EP - bool "Platform bus based DesignWare PCIe Controller - Endpoint mode" - depends on PCI && PCI_MSI +config PCIE_ARTPEC6_EP + bool "Axis ARTPEC-6 PCIe controller (endpoint mode)" + depends on MACH_ARTPEC6 || COMPILE_TEST depends on PCI_ENDPOINT select PCIE_DW_EP - select PCIE_DW_PLAT + select PCIE_ARTPEC6 help - Enables support for the PCIe controller in the Designware IP to - work in endpoint mode. There are two instances of PCIe controller - in Designware IP. - This controller can work either as EP or RC. In order to enable - host-specific features PCIE_DW_PLAT_HOST must be selected and in - order to enable device-specific features PCI_DW_PLAT_EP must be - selected. + Enables support for the PCIe controller in the ARTPEC-6 SoC to work in + endpoint mode. This uses the DesignWare core. -config PCI_EXYNOS - tristate "Samsung Exynos PCIe controller" - depends on ARCH_EXYNOS || COMPILE_TEST +config PCIE_BT1 + tristate "Baikal-T1 PCIe controller" + depends on MIPS_BAIKAL_T1 || COMPILE_TEST depends on PCI_MSI select PCIE_DW_HOST help - Enables support for the PCIe controller in the Samsung Exynos SoCs - to work in host mode. The PCI controller is based on the DesignWare - hardware and therefore the driver re-uses the DesignWare core - functions to implement the driver. + Enables support for the PCIe controller in the Baikal-T1 SoC to work + in host mode. It's based on the Synopsys DWC PCIe v4.60a IP-core. config PCI_IMX6 bool config PCI_IMX6_HOST - bool "Freescale i.MX6/7/8 PCIe controller host mode" + bool "Freescale i.MX6/7/8 PCIe controller (host mode)" depends on ARCH_MXC || COMPILE_TEST depends on PCI_MSI select PCIE_DW_HOST @@ -107,7 +86,7 @@ config PCI_IMX6_HOST DesignWare core functions to implement the driver. config PCI_IMX6_EP - bool "Freescale i.MX6/7/8 PCIe controller endpoint mode" + bool "Freescale i.MX6/7/8 PCIe controller (endpoint mode)" depends on ARCH_MXC || COMPILE_TEST depends on PCI_ENDPOINT select PCIE_DW_EP @@ -118,43 +97,8 @@ config PCI_IMX6_EP on DesignWare hardware and therefore the driver re-uses the DesignWare core functions to implement the driver. -config PCIE_SPEAR13XX - bool "STMicroelectronics SPEAr PCIe controller" - depends on ARCH_SPEAR13XX || COMPILE_TEST - depends on PCI_MSI - select PCIE_DW_HOST - help - Say Y here if you want PCIe support on SPEAr13XX SoCs. - -config PCI_KEYSTONE - bool - -config PCI_KEYSTONE_HOST - bool "PCI Keystone Host Mode" - depends on ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST - depends on PCI_MSI - select PCIE_DW_HOST - select PCI_KEYSTONE - help - Enables support for the PCIe controller in the Keystone SoC to - work in host mode. The PCI controller on Keystone is based on - DesignWare hardware and therefore the driver re-uses the - DesignWare core functions to implement the driver. - -config PCI_KEYSTONE_EP - bool "PCI Keystone Endpoint Mode" - depends on ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST - depends on PCI_ENDPOINT - select PCIE_DW_EP - select PCI_KEYSTONE - help - Enables support for the PCIe controller in the Keystone SoC to - work in endpoint mode. The PCI controller on Keystone is based - on DesignWare hardware and therefore the driver re-uses the - DesignWare core functions to implement the driver. - config PCI_LAYERSCAPE - bool "Freescale Layerscape PCIe controller - Host mode" + bool "Freescale Layerscape PCIe controller (host mode)" depends on OF && (ARM || ARCH_LAYERSCAPE || COMPILE_TEST) depends on PCI_MSI select PCIE_DW_HOST @@ -167,7 +111,7 @@ config PCI_LAYERSCAPE controller works in RC mode. config PCI_LAYERSCAPE_EP - bool "Freescale Layerscape PCIe controller - Endpoint mode" + bool "Freescale Layerscape PCIe controller (endpoint mode)" depends on OF && (ARM || ARCH_LAYERSCAPE || COMPILE_TEST) depends on PCI_ENDPOINT select PCIE_DW_EP @@ -180,7 +124,7 @@ config PCI_LAYERSCAPE_EP config PCI_HISI depends on OF && (ARM64 || COMPILE_TEST) - bool "HiSilicon Hip05 and Hip06 SoCs PCIe controllers" + bool "HiSilicon Hip05 and Hip06 SoCs PCIe controller" depends on PCI_MSI select PCIE_DW_HOST select PCI_HOST_COMMON @@ -188,83 +132,26 @@ config PCI_HISI Say Y here if you want PCIe controller support on HiSilicon Hip05 and Hip06 SoCs -config PCIE_QCOM - bool "Qualcomm PCIe controller" - depends on OF && (ARCH_QCOM || COMPILE_TEST) - depends on PCI_MSI - select PCIE_DW_HOST - select CRC8 - help - Say Y here to enable PCIe controller support on Qualcomm SoCs. The - PCIe controller uses the DesignWare core plus Qualcomm-specific - hardware wrappers. - -config PCIE_QCOM_EP - tristate "Qualcomm PCIe controller - Endpoint mode" - depends on OF && (ARCH_QCOM || COMPILE_TEST) - depends on PCI_ENDPOINT - select PCIE_DW_EP - help - Say Y here to enable support for the PCIe controllers on Qualcomm SoCs - to work in endpoint mode. The PCIe controller uses the DesignWare core - plus Qualcomm-specific hardware wrappers. - -config PCIE_ARMADA_8K - bool "Marvell Armada-8K PCIe controller" - depends on ARCH_MVEBU || COMPILE_TEST - depends on PCI_MSI - select PCIE_DW_HOST - help - Say Y here if you want to enable PCIe controller support on - Armada-8K SoCs. The PCIe controller on Armada-8K is based on - DesignWare hardware and therefore the driver re-uses the - DesignWare core functions to implement the driver. - -config PCIE_ARTPEC6 - bool - -config PCIE_ARTPEC6_HOST - bool "Axis ARTPEC-6 PCIe controller Host Mode" - depends on MACH_ARTPEC6 || COMPILE_TEST +config PCIE_KIRIN + depends on OF && (ARM64 || COMPILE_TEST) + tristate "HiSilicon Kirin PCIe controller" depends on PCI_MSI select PCIE_DW_HOST - select PCIE_ARTPEC6 - help - Enables support for the PCIe controller in the ARTPEC-6 SoC to work in - host mode. This uses the DesignWare core. - -config PCIE_ARTPEC6_EP - bool "Axis ARTPEC-6 PCIe controller Endpoint Mode" - depends on MACH_ARTPEC6 || COMPILE_TEST - depends on PCI_ENDPOINT - select PCIE_DW_EP - select PCIE_ARTPEC6 + select REGMAP_MMIO help - Enables support for the PCIe controller in the ARTPEC-6 SoC to work in - endpoint mode. This uses the DesignWare core. + Say Y here if you want PCIe controller support + on HiSilicon Kirin series SoCs. -config PCIE_BT1 - tristate "Baikal-T1 PCIe controller" - depends on MIPS_BAIKAL_T1 || COMPILE_TEST +config PCIE_HISI_STB + bool "HiSilicon STB PCIe controller" + depends on ARCH_HISI || COMPILE_TEST depends on PCI_MSI select PCIE_DW_HOST help - Enables support for the PCIe controller in the Baikal-T1 SoC to work - in host mode. It's based on the Synopsys DWC PCIe v4.60a IP-core. - -config PCIE_ROCKCHIP_DW_HOST - bool "Rockchip DesignWare PCIe controller" - select PCIE_DW - select PCIE_DW_HOST - depends on PCI_MSI - depends on ARCH_ROCKCHIP || COMPILE_TEST - depends on OF - help - Enables support for the DesignWare PCIe controller in the - Rockchip SoC except RK3399. + Say Y here if you want PCIe controller support on HiSilicon STB SoCs config PCIE_INTEL_GW - bool "Intel Gateway PCIe host controller support" + bool "Intel Gateway PCIe controller " depends on OF && (X86 || COMPILE_TEST) depends on PCI_MSI select PCIE_DW_HOST @@ -278,7 +165,7 @@ config PCIE_KEEMBAY bool config PCIE_KEEMBAY_HOST - bool "Intel Keem Bay PCIe controller - Host mode" + bool "Intel Keem Bay PCIe controller (host mode)" depends on ARCH_KEEMBAY || COMPILE_TEST depends on PCI_MSI select PCIE_DW_HOST @@ -290,7 +177,7 @@ config PCIE_KEEMBAY_HOST DesignWare core functions. config PCIE_KEEMBAY_EP - bool "Intel Keem Bay PCIe controller - Endpoint mode" + bool "Intel Keem Bay PCIe controller (endpoint mode)" depends on ARCH_KEEMBAY || COMPILE_TEST depends on PCI_MSI depends on PCI_ENDPOINT @@ -302,39 +189,22 @@ config PCIE_KEEMBAY_EP The PCIe controller is based on DesignWare Hardware and uses DesignWare core functions. -config PCIE_KIRIN - depends on OF && (ARM64 || COMPILE_TEST) - tristate "HiSilicon Kirin series SoCs PCIe controllers" - depends on PCI_MSI - select PCIE_DW_HOST - help - Say Y here if you want PCIe controller support - on HiSilicon Kirin series SoCs. - -config PCIE_HISI_STB - bool "HiSilicon STB SoCs PCIe controllers" - depends on ARCH_HISI || COMPILE_TEST - depends on PCI_MSI - select PCIE_DW_HOST - help - Say Y here if you want PCIe controller support on HiSilicon STB SoCs - -config PCI_MESON - tristate "MESON PCIe controller" - default m if ARCH_MESON +config PCIE_ARMADA_8K + bool "Marvell Armada-8K PCIe controller" + depends on ARCH_MVEBU || COMPILE_TEST depends on PCI_MSI select PCIE_DW_HOST help - Say Y here if you want to enable PCI controller support on Amlogic - SoCs. The PCI controller on Amlogic is based on DesignWare hardware - and therefore the driver re-uses the DesignWare core functions to - implement the driver. + Say Y here if you want to enable PCIe controller support on + Armada-8K SoCs. The PCIe controller on Armada-8K is based on + DesignWare hardware and therefore the driver re-uses the + DesignWare core functions to implement the driver. config PCIE_TEGRA194 tristate config PCIE_TEGRA194_HOST - tristate "NVIDIA Tegra194 (and later) PCIe controller - Host Mode" + tristate "NVIDIA Tegra194 (and later) PCIe controller (host mode)" depends on ARCH_TEGRA_194_SOC || COMPILE_TEST depends on PCI_MSI select PCIE_DW_HOST @@ -349,7 +219,7 @@ config PCIE_TEGRA194_HOST selected. This uses the DesignWare core. config PCIE_TEGRA194_EP - tristate "NVIDIA Tegra194 (and later) PCIe controller - Endpoint Mode" + tristate "NVIDIA Tegra194 (and later) PCIe controller (endpoint mode)" depends on ARCH_TEGRA_194_SOC || COMPILE_TEST depends on PCI_ENDPOINT select PCIE_DW_EP @@ -363,17 +233,92 @@ config PCIE_TEGRA194_EP in order to enable device-specific features PCIE_TEGRA194_EP must be selected. This uses the DesignWare core. -config PCIE_VISCONTI_HOST - bool "Toshiba Visconti PCIe controllers" - depends on ARCH_VISCONTI || COMPILE_TEST +config PCIE_DW_PLAT + bool + +config PCIE_DW_PLAT_HOST + bool "Platform bus based DesignWare PCIe controller (host mode)" depends on PCI_MSI select PCIE_DW_HOST + select PCIE_DW_PLAT help - Say Y here if you want PCIe controller support on Toshiba Visconti SoC. - This driver supports TMPV7708 SoC. + Enables support for the PCIe controller in the Designware IP to + work in host mode. There are two instances of PCIe controller in + Designware IP. + This controller can work either as EP or RC. In order to enable + host-specific features PCIE_DW_PLAT_HOST must be selected and in + order to enable device-specific features PCI_DW_PLAT_EP must be + selected. + +config PCIE_DW_PLAT_EP + bool "Platform bus based DesignWare PCIe controller (endpoint mode)" + depends on PCI && PCI_MSI + depends on PCI_ENDPOINT + select PCIE_DW_EP + select PCIE_DW_PLAT + help + Enables support for the PCIe controller in the Designware IP to + work in endpoint mode. There are two instances of PCIe controller + in Designware IP. + This controller can work either as EP or RC. In order to enable + host-specific features PCIE_DW_PLAT_HOST must be selected and in + order to enable device-specific features PCI_DW_PLAT_EP must be + selected. + +config PCIE_QCOM + bool "Qualcomm PCIe controller (host mode)" + depends on OF && (ARCH_QCOM || COMPILE_TEST) + depends on PCI_MSI + select PCIE_DW_HOST + select CRC8 + help + Say Y here to enable PCIe controller support on Qualcomm SoCs. The + PCIe controller uses the DesignWare core plus Qualcomm-specific + hardware wrappers. + +config PCIE_QCOM_EP + tristate "Qualcomm PCIe controller (endpoint mode)" + depends on OF && (ARCH_QCOM || COMPILE_TEST) + depends on PCI_ENDPOINT + select PCIE_DW_EP + help + Say Y here to enable support for the PCIe controllers on Qualcomm SoCs + to work in endpoint mode. The PCIe controller uses the DesignWare core + plus Qualcomm-specific hardware wrappers. + +config PCIE_ROCKCHIP_DW_HOST + bool "Rockchip DesignWare PCIe controller" + select PCIE_DW + select PCIE_DW_HOST + depends on PCI_MSI + depends on ARCH_ROCKCHIP || COMPILE_TEST + depends on OF + help + Enables support for the DesignWare PCIe controller in the + Rockchip SoC except RK3399. + +config PCI_EXYNOS + tristate "Samsung Exynos PCIe controller" + depends on ARCH_EXYNOS || COMPILE_TEST + depends on PCI_MSI + select PCIE_DW_HOST + help + Enables support for the PCIe controller in the Samsung Exynos SoCs + to work in host mode. The PCI controller is based on the DesignWare + hardware and therefore the driver re-uses the DesignWare core + functions to implement the driver. + +config PCIE_FU740 + bool "SiFive FU740 PCIe controller" + depends on PCI_MSI + depends on SOC_SIFIVE || COMPILE_TEST + select PCIE_DW_HOST + help + Say Y here if you want PCIe controller support for the SiFive + FU740. config PCIE_UNIPHIER - bool "Socionext UniPhier PCIe host controllers" + bool "Socionext UniPhier PCIe controller (host mode)" depends on ARCH_UNIPHIER || COMPILE_TEST depends on OF && HAS_IOMEM depends on PCI_MSI @@ -383,7 +328,7 @@ config PCIE_UNIPHIER This driver supports LD20 and PXs3 SoCs. config PCIE_UNIPHIER_EP - bool "Socionext UniPhier PCIe endpoint controllers" + bool "Socionext UniPhier PCIe controller (endpoint mode)" depends on ARCH_UNIPHIER || COMPILE_TEST depends on OF && HAS_IOMEM depends on PCI_ENDPOINT @@ -392,26 +337,82 @@ config PCIE_UNIPHIER_EP Say Y here if you want PCIe endpoint controller support on UniPhier SoCs. This driver supports Pro5 SoC. -config PCIE_AL - bool "Amazon Annapurna Labs PCIe controller" - depends on OF && (ARM64 || COMPILE_TEST) +config PCIE_SPEAR13XX + bool "STMicroelectronics SPEAr PCIe controller" + depends on ARCH_SPEAR13XX || COMPILE_TEST depends on PCI_MSI select PCIE_DW_HOST - select PCI_ECAM help - Say Y here to enable support of the Amazon's Annapurna Labs PCIe - controller IP on Amazon SoCs. The PCIe controller uses the DesignWare - core plus Annapurna Labs proprietary hardware wrappers. This is - required only for DT-based platforms. ACPI platforms with the - Annapurna Labs PCIe controller don't need to enable this. + Say Y here if you want PCIe support on SPEAr13XX SoCs. -config PCIE_FU740 - bool "SiFive FU740 PCIe host controller" +config PCI_DRA7XX + tristate + +config PCI_DRA7XX_HOST + tristate "TI DRA7xx PCIe controller (host mode)" + depends on SOC_DRA7XX || COMPILE_TEST + depends on OF && HAS_IOMEM && TI_PIPE3 depends on PCI_MSI - depends on SOC_SIFIVE || COMPILE_TEST select PCIE_DW_HOST + select PCI_DRA7XX + default y if SOC_DRA7XX help - Say Y here if you want PCIe controller support for the SiFive - FU740. + Enables support for the PCIe controller in the DRA7xx SoC to work in + host mode. There are two instances of PCIe controller in DRA7xx. + This controller can work either as EP or RC. In order to enable + host-specific features PCI_DRA7XX_HOST must be selected and in order + to enable device-specific features PCI_DRA7XX_EP must be selected. + This uses the DesignWare core. + +config PCI_DRA7XX_EP + tristate "TI DRA7xx PCIe controller (endpoint mode)" + depends on SOC_DRA7XX || COMPILE_TEST + depends on OF && HAS_IOMEM && TI_PIPE3 + depends on PCI_ENDPOINT + select PCIE_DW_EP + select PCI_DRA7XX + help + Enables support for the PCIe controller in the DRA7xx SoC to work in + endpoint mode. There are two instances of PCIe controller in DRA7xx. + This controller can work either as EP or RC. In order to enable + host-specific features PCI_DRA7XX_HOST must be selected and in order + to enable device-specific features PCI_DRA7XX_EP must be selected. + This uses the DesignWare core. + +config PCI_KEYSTONE + bool + +config PCI_KEYSTONE_HOST + bool "TI Keystone PCIe controller (host mode)" + depends on ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST + depends on PCI_MSI + select PCIE_DW_HOST + select PCI_KEYSTONE + help + Enables support for the PCIe controller in the Keystone SoC to + work in host mode. The PCI controller on Keystone is based on + DesignWare hardware and therefore the driver re-uses the + DesignWare core functions to implement the driver. + +config PCI_KEYSTONE_EP + bool "TI Keystone PCIe controller (endpoint mode)" + depends on ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST + depends on PCI_ENDPOINT + select PCIE_DW_EP + select PCI_KEYSTONE + help + Enables support for the PCIe controller in the Keystone SoC to + work in endpoint mode. The PCI controller on Keystone is based + on DesignWare hardware and therefore the driver re-uses the + DesignWare core functions to implement the driver. + +config PCIE_VISCONTI_HOST + bool "Toshiba Visconti PCIe controller" + depends on ARCH_VISCONTI || COMPILE_TEST + depends on PCI_MSI + select PCIE_DW_HOST + help + Say Y here if you want PCIe controller support on Toshiba Visconti SoC. + This driver supports TMPV7708 SoC. endmenu diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 55a0405b921d..52906f999f2b 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -1566,6 +1566,13 @@ DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_SYNOPSYS, 0xabcd, static int __init imx6_pcie_init(void) { #ifdef CONFIG_ARM + struct device_node *np; + + np = of_find_matching_node(NULL, imx6_pcie_of_match); + if (!np) + return -ENODEV; + of_node_put(np); + /* * Since probe() can be deferred we need to make sure that * hook_fault_code is not called after __init memory is freed diff --git a/drivers/pci/controller/dwc/pci-layerscape-ep.c b/drivers/pci/controller/dwc/pci-layerscape-ep.c index ad99707b3b99..c640db60edc6 100644 --- a/drivers/pci/controller/dwc/pci-layerscape-ep.c +++ b/drivers/pci/controller/dwc/pci-layerscape-ep.c @@ -110,6 +110,7 @@ static const struct ls_pcie_ep_drvdata lx2_ep_drvdata = { }; static const struct of_device_id ls_pcie_ep_of_match[] = { + { .compatible = "fsl,ls1028a-pcie-ep", .data = &ls1_ep_drvdata }, { .compatible = "fsl,ls1046a-pcie-ep", .data = &ls1_ep_drvdata }, { .compatible = "fsl,ls1088a-pcie-ep", .data = &ls2_ep_drvdata }, { .compatible = "fsl,ls2088a-pcie-ep", .data = &ls2_ep_drvdata }, diff --git a/drivers/pci/controller/dwc/pcie-qcom.c b/drivers/pci/controller/dwc/pcie-qcom.c index a232b04af048..4ab30892f6ef 100644 --- a/drivers/pci/controller/dwc/pcie-qcom.c +++ b/drivers/pci/controller/dwc/pcie-qcom.c @@ -10,6 +10,7 @@ #include <linux/clk.h> #include <linux/crc8.h> +#include <linux/debugfs.h> #include <linux/delay.h> #include <linux/gpio/consumer.h> #include <linux/interconnect.h> @@ -33,7 +34,44 @@ #include "../../pci.h" #include "pcie-designware.h" -#define PCIE20_PARF_SYS_CTRL 0x00 +/* PARF registers */ +#define PARF_SYS_CTRL 0x00 +#define PARF_PM_CTRL 0x20 +#define PARF_PCS_DEEMPH 0x34 +#define PARF_PCS_SWING 0x38 +#define PARF_PHY_CTRL 0x40 +#define PARF_PHY_REFCLK 0x4c +#define PARF_CONFIG_BITS 0x50 +#define PARF_DBI_BASE_ADDR 0x168 +#define PARF_SLV_ADDR_SPACE_SIZE_2_3_3 0x16c /* Register offset specific to IP ver 2.3.3 */ +#define PARF_MHI_CLOCK_RESET_CTRL 0x174 +#define PARF_AXI_MSTR_WR_ADDR_HALT 0x178 +#define PARF_AXI_MSTR_WR_ADDR_HALT_V2 0x1a8 +#define PARF_Q2A_FLUSH 0x1ac +#define PARF_LTSSM 0x1b0 +#define PARF_SID_OFFSET 0x234 +#define PARF_BDF_TRANSLATE_CFG 0x24c +#define PARF_SLV_ADDR_SPACE_SIZE 0x358 +#define PARF_DEVICE_TYPE 0x1000 +#define PARF_BDF_TO_SID_TABLE_N 0x2000 + +/* ELBI registers */ +#define ELBI_SYS_CTRL 0x04 + +/* DBI registers */ +#define AXI_MSTR_RESP_COMP_CTRL0 0x818 +#define AXI_MSTR_RESP_COMP_CTRL1 0x81c +#define MISC_CONTROL_1_REG 0x8bc + +/* MHI registers */ +#define PARF_DEBUG_CNT_PM_LINKST_IN_L2 0xc04 +#define PARF_DEBUG_CNT_PM_LINKST_IN_L1 0xc0c +#define PARF_DEBUG_CNT_PM_LINKST_IN_L0S 0xc10 +#define PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L1 0xc84 +#define PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L2 0xc88 + +/* PARF_SYS_CTRL register fields */ +#define MAC_PHY_POWERDOWN_IN_P2_D_MUX_EN BIT(29) #define MST_WAKEUP_EN BIT(13) #define SLV_WAKEUP_EN BIT(12) #define MSTR_ACLK_CGC_DIS BIT(10) @@ -43,45 +81,63 @@ #define L23_CLK_RMV_DIS BIT(2) #define L1_CLK_RMV_DIS BIT(1) -#define PCIE20_PARF_PM_CTRL 0x20 +/* PARF_PM_CTRL register fields */ #define REQ_NOT_ENTR_L1 BIT(5) -#define PCIE20_PARF_PHY_CTRL 0x40 +/* PARF_PCS_DEEMPH register fields */ +#define PCS_DEEMPH_TX_DEEMPH_GEN1(x) FIELD_PREP(GENMASK(21, 16), x) +#define PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(x) FIELD_PREP(GENMASK(13, 8), x) +#define PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(x) FIELD_PREP(GENMASK(5, 0), x) + +/* PARF_PCS_SWING register fields */ +#define PCS_SWING_TX_SWING_FULL(x) FIELD_PREP(GENMASK(14, 8), x) +#define PCS_SWING_TX_SWING_LOW(x) FIELD_PREP(GENMASK(6, 0), x) + +/* PARF_PHY_CTRL register fields */ #define PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK GENMASK(20, 16) -#define PHY_CTRL_PHY_TX0_TERM_OFFSET(x) ((x) << 16) +#define PHY_CTRL_PHY_TX0_TERM_OFFSET(x) FIELD_PREP(PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK, x) +#define PHY_TEST_PWR_DOWN BIT(0) -#define PCIE20_PARF_PHY_REFCLK 0x4C +/* PARF_PHY_REFCLK register fields */ #define PHY_REFCLK_SSP_EN BIT(16) #define PHY_REFCLK_USE_PAD BIT(12) -#define PCIE20_PARF_DBI_BASE_ADDR 0x168 -#define PCIE20_PARF_SLV_ADDR_SPACE_SIZE 0x16C -#define PCIE20_PARF_MHI_CLOCK_RESET_CTRL 0x174 +/* PARF_CONFIG_BITS register fields */ +#define PHY_RX0_EQ(x) FIELD_PREP(GENMASK(26, 24), x) + +/* PARF_SLV_ADDR_SPACE_SIZE register value */ +#define SLV_ADDR_SPACE_SZ 0x10000000 + +/* PARF_MHI_CLOCK_RESET_CTRL register fields */ #define AHB_CLK_EN BIT(0) #define MSTR_AXI_CLK_EN BIT(1) #define BYPASS BIT(4) -#define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT 0x178 -#define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2 0x1A8 -#define PCIE20_PARF_LTSSM 0x1B0 -#define PCIE20_PARF_SID_OFFSET 0x234 -#define PCIE20_PARF_BDF_TRANSLATE_CFG 0x24C -#define PCIE20_PARF_DEVICE_TYPE 0x1000 -#define PCIE20_PARF_BDF_TO_SID_TABLE_N 0x2000 +/* PARF_AXI_MSTR_WR_ADDR_HALT register fields */ +#define EN BIT(31) + +/* PARF_LTSSM register fields */ +#define LTSSM_EN BIT(8) -#define PCIE20_ELBI_SYS_CTRL 0x04 -#define PCIE20_ELBI_SYS_CTRL_LT_ENABLE BIT(0) +/* PARF_DEVICE_TYPE register fields */ +#define DEVICE_TYPE_RC 0x4 + +/* ELBI_SYS_CTRL register fields */ +#define ELBI_SYS_CTRL_LT_ENABLE BIT(0) -#define PCIE20_AXI_MSTR_RESP_COMP_CTRL0 0x818 +/* AXI_MSTR_RESP_COMP_CTRL0 register fields */ #define CFG_REMOTE_RD_REQ_BRIDGE_SIZE_2K 0x4 #define CFG_REMOTE_RD_REQ_BRIDGE_SIZE_4K 0x5 -#define PCIE20_AXI_MSTR_RESP_COMP_CTRL1 0x81c + +/* AXI_MSTR_RESP_COMP_CTRL1 register fields */ #define CFG_BRIDGE_SB_INIT BIT(0) -#define PCIE_CAP_SLOT_POWER_LIMIT_VAL FIELD_PREP(PCI_EXP_SLTCAP_SPLV, \ - 250) -#define PCIE_CAP_SLOT_POWER_LIMIT_SCALE FIELD_PREP(PCI_EXP_SLTCAP_SPLS, \ - 1) +/* MISC_CONTROL_1_REG register fields */ +#define DBI_RO_WR_EN 1 + +/* PCI_EXP_SLTCAP register fields */ +#define PCIE_CAP_SLOT_POWER_LIMIT_VAL FIELD_PREP(PCI_EXP_SLTCAP_SPLV, 250) +#define PCIE_CAP_SLOT_POWER_LIMIT_SCALE FIELD_PREP(PCI_EXP_SLTCAP_SPLS, 1) #define PCIE_CAP_SLOT_VAL (PCI_EXP_SLTCAP_ABP | \ PCI_EXP_SLTCAP_PCP | \ PCI_EXP_SLTCAP_MRLSP | \ @@ -93,103 +149,62 @@ PCIE_CAP_SLOT_POWER_LIMIT_VAL | \ PCIE_CAP_SLOT_POWER_LIMIT_SCALE) -#define PCIE20_PARF_Q2A_FLUSH 0x1AC - -#define PCIE20_MISC_CONTROL_1_REG 0x8BC -#define DBI_RO_WR_EN 1 - #define PERST_DELAY_US 1000 -/* PARF registers */ -#define PCIE20_PARF_PCS_DEEMPH 0x34 -#define PCS_DEEMPH_TX_DEEMPH_GEN1(x) ((x) << 16) -#define PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(x) ((x) << 8) -#define PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(x) ((x) << 0) -#define PCIE20_PARF_PCS_SWING 0x38 -#define PCS_SWING_TX_SWING_FULL(x) ((x) << 8) -#define PCS_SWING_TX_SWING_LOW(x) ((x) << 0) +#define QCOM_PCIE_CRC8_POLYNOMIAL (BIT(2) | BIT(1) | BIT(0)) -#define PCIE20_PARF_CONFIG_BITS 0x50 -#define PHY_RX0_EQ(x) ((x) << 24) - -#define PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE 0x358 -#define SLV_ADDR_SPACE_SZ 0x10000000 - -#define PCIE20_LNK_CONTROL2_LINK_STATUS2 0xa0 - -#define DEVICE_TYPE_RC 0x4 - -#define QCOM_PCIE_2_1_0_MAX_SUPPLY 3 -#define QCOM_PCIE_2_1_0_MAX_CLOCKS 5 - -#define QCOM_PCIE_CRC8_POLYNOMIAL (BIT(2) | BIT(1) | BIT(0)) +#define QCOM_PCIE_1_0_0_MAX_CLOCKS 4 +struct qcom_pcie_resources_1_0_0 { + struct clk_bulk_data clks[QCOM_PCIE_1_0_0_MAX_CLOCKS]; + struct reset_control *core; + struct regulator *vdda; +}; +#define QCOM_PCIE_2_1_0_MAX_CLOCKS 5 +#define QCOM_PCIE_2_1_0_MAX_RESETS 6 +#define QCOM_PCIE_2_1_0_MAX_SUPPLY 3 struct qcom_pcie_resources_2_1_0 { struct clk_bulk_data clks[QCOM_PCIE_2_1_0_MAX_CLOCKS]; - struct reset_control *pci_reset; - struct reset_control *axi_reset; - struct reset_control *ahb_reset; - struct reset_control *por_reset; - struct reset_control *phy_reset; - struct reset_control *ext_reset; + struct reset_control_bulk_data resets[QCOM_PCIE_2_1_0_MAX_RESETS]; + int num_resets; struct regulator_bulk_data supplies[QCOM_PCIE_2_1_0_MAX_SUPPLY]; }; -struct qcom_pcie_resources_1_0_0 { - struct clk *iface; - struct clk *aux; - struct clk *master_bus; - struct clk *slave_bus; - struct reset_control *core; - struct regulator *vdda; -}; - -#define QCOM_PCIE_2_3_2_MAX_SUPPLY 2 +#define QCOM_PCIE_2_3_2_MAX_CLOCKS 4 +#define QCOM_PCIE_2_3_2_MAX_SUPPLY 2 struct qcom_pcie_resources_2_3_2 { - struct clk *aux_clk; - struct clk *master_clk; - struct clk *slave_clk; - struct clk *cfg_clk; + struct clk_bulk_data clks[QCOM_PCIE_2_3_2_MAX_CLOCKS]; struct regulator_bulk_data supplies[QCOM_PCIE_2_3_2_MAX_SUPPLY]; }; -#define QCOM_PCIE_2_4_0_MAX_CLOCKS 4 +#define QCOM_PCIE_2_3_3_MAX_CLOCKS 5 +#define QCOM_PCIE_2_3_3_MAX_RESETS 7 +struct qcom_pcie_resources_2_3_3 { + struct clk_bulk_data clks[QCOM_PCIE_2_3_3_MAX_CLOCKS]; + struct reset_control_bulk_data rst[QCOM_PCIE_2_3_3_MAX_RESETS]; +}; + +#define QCOM_PCIE_2_4_0_MAX_CLOCKS 4 +#define QCOM_PCIE_2_4_0_MAX_RESETS 12 struct qcom_pcie_resources_2_4_0 { struct clk_bulk_data clks[QCOM_PCIE_2_4_0_MAX_CLOCKS]; int num_clks; - struct reset_control *axi_m_reset; - struct reset_control *axi_s_reset; - struct reset_control *pipe_reset; - struct reset_control *axi_m_vmid_reset; - struct reset_control *axi_s_xpu_reset; - struct reset_control *parf_reset; - struct reset_control *phy_reset; - struct reset_control *axi_m_sticky_reset; - struct reset_control *pipe_sticky_reset; - struct reset_control *pwr_reset; - struct reset_control *ahb_reset; - struct reset_control *phy_ahb_reset; -}; - -struct qcom_pcie_resources_2_3_3 { - struct clk *iface; - struct clk *axi_m_clk; - struct clk *axi_s_clk; - struct clk *ahb_clk; - struct clk *aux_clk; - struct reset_control *rst[7]; + struct reset_control_bulk_data resets[QCOM_PCIE_2_4_0_MAX_RESETS]; + int num_resets; }; -/* 6 clocks typically, 7 for sm8250 */ +#define QCOM_PCIE_2_7_0_MAX_CLOCKS 15 +#define QCOM_PCIE_2_7_0_MAX_SUPPLIES 2 struct qcom_pcie_resources_2_7_0 { - struct clk_bulk_data clks[12]; + struct clk_bulk_data clks[QCOM_PCIE_2_7_0_MAX_CLOCKS]; int num_clks; - struct regulator_bulk_data supplies[2]; - struct reset_control *pci_reset; + struct regulator_bulk_data supplies[QCOM_PCIE_2_7_0_MAX_SUPPLIES]; + struct reset_control *rst; }; +#define QCOM_PCIE_2_9_0_MAX_CLOCKS 5 struct qcom_pcie_resources_2_9_0 { - struct clk_bulk_data clks[5]; + struct clk_bulk_data clks[QCOM_PCIE_2_9_0_MAX_CLOCKS]; struct reset_control *rst; }; @@ -222,11 +237,14 @@ struct qcom_pcie { struct dw_pcie *pci; void __iomem *parf; /* DT parf */ void __iomem *elbi; /* DT elbi */ + void __iomem *mhi; union qcom_pcie_resources res; struct phy *phy; struct gpio_desc *reset; struct icc_path *icc_mem; const struct qcom_pcie_cfg *cfg; + struct dentry *debugfs; + bool suspended; }; #define to_qcom_pcie(x) dev_get_drvdata((x)->dev) @@ -261,9 +279,9 @@ static void qcom_pcie_2_1_0_ltssm_enable(struct qcom_pcie *pcie) u32 val; /* enable link training */ - val = readl(pcie->elbi + PCIE20_ELBI_SYS_CTRL); - val |= PCIE20_ELBI_SYS_CTRL_LT_ENABLE; - writel(val, pcie->elbi + PCIE20_ELBI_SYS_CTRL); + val = readl(pcie->elbi + ELBI_SYS_CTRL); + val |= ELBI_SYS_CTRL_LT_ENABLE; + writel(val, pcie->elbi + ELBI_SYS_CTRL); } static int qcom_pcie_get_resources_2_1_0(struct qcom_pcie *pcie) @@ -271,6 +289,7 @@ static int qcom_pcie_get_resources_2_1_0(struct qcom_pcie *pcie) struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0; struct dw_pcie *pci = pcie->pci; struct device *dev = pci->dev; + bool is_apq = of_device_is_compatible(dev->of_node, "qcom,pcie-apq8064"); int ret; res->supplies[0].supply = "vdda"; @@ -297,28 +316,20 @@ static int qcom_pcie_get_resources_2_1_0(struct qcom_pcie *pcie) if (ret < 0) return ret; - res->pci_reset = devm_reset_control_get_exclusive(dev, "pci"); - if (IS_ERR(res->pci_reset)) - return PTR_ERR(res->pci_reset); - - res->axi_reset = devm_reset_control_get_exclusive(dev, "axi"); - if (IS_ERR(res->axi_reset)) - return PTR_ERR(res->axi_reset); - - res->ahb_reset = devm_reset_control_get_exclusive(dev, "ahb"); - if (IS_ERR(res->ahb_reset)) - return PTR_ERR(res->ahb_reset); + res->resets[0].id = "pci"; + res->resets[1].id = "axi"; + res->resets[2].id = "ahb"; + res->resets[3].id = "por"; + res->resets[4].id = "phy"; + res->resets[5].id = "ext"; - res->por_reset = devm_reset_control_get_exclusive(dev, "por"); - if (IS_ERR(res->por_reset)) - return PTR_ERR(res->por_reset); - - res->ext_reset = devm_reset_control_get_optional_exclusive(dev, "ext"); - if (IS_ERR(res->ext_reset)) - return PTR_ERR(res->ext_reset); + /* ext is optional on APQ8016 */ + res->num_resets = is_apq ? 5 : 6; + ret = devm_reset_control_bulk_get_exclusive(dev, res->num_resets, res->resets); + if (ret < 0) + return ret; - res->phy_reset = devm_reset_control_get_exclusive(dev, "phy"); - return PTR_ERR_OR_ZERO(res->phy_reset); + return 0; } static void qcom_pcie_deinit_2_1_0(struct qcom_pcie *pcie) @@ -326,14 +337,9 @@ static void qcom_pcie_deinit_2_1_0(struct qcom_pcie *pcie) struct qcom_pcie_resources_2_1_0 *res = &pcie->res.v2_1_0; clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks); - reset_control_assert(res->pci_reset); - reset_control_assert(res->axi_reset); - reset_control_assert(res->ahb_reset); - reset_control_assert(res->por_reset); - reset_control_assert(res->ext_reset); - reset_control_assert(res->phy_reset); + reset_control_bulk_assert(res->num_resets, res->resets); - writel(1, pcie->parf + PCIE20_PARF_PHY_CTRL); + writel(1, pcie->parf + PARF_PHY_CTRL); regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); } @@ -346,12 +352,11 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) int ret; /* reset the PCIe interface as uboot can leave it undefined state */ - reset_control_assert(res->pci_reset); - reset_control_assert(res->axi_reset); - reset_control_assert(res->ahb_reset); - reset_control_assert(res->por_reset); - reset_control_assert(res->ext_reset); - reset_control_assert(res->phy_reset); + ret = reset_control_bulk_assert(res->num_resets, res->resets); + if (ret < 0) { + dev_err(dev, "cannot assert resets\n"); + return ret; + } ret = regulator_bulk_enable(ARRAY_SIZE(res->supplies), res->supplies); if (ret < 0) { @@ -359,58 +364,14 @@ static int qcom_pcie_init_2_1_0(struct qcom_pcie *pcie) return ret; } - ret = reset_control_deassert(res->ahb_reset); - if (ret) { - dev_err(dev, "cannot deassert ahb reset\n"); - goto err_deassert_ahb; - } - - ret = reset_control_deassert(res->ext_reset); - if (ret) { - dev_err(dev, "cannot deassert ext reset\n"); - goto err_deassert_ext; - } - - ret = reset_control_deassert(res->phy_reset); - if (ret) { - dev_err(dev, "cannot deassert phy reset\n"); - goto err_deassert_phy; - } - - ret = reset_control_deassert(res->pci_reset); - if (ret) { - dev_err(dev, "cannot deassert pci reset\n"); - goto err_deassert_pci; - } - - ret = reset_control_deassert(res->por_reset); - if (ret) { - dev_err(dev, "cannot deassert por reset\n"); - goto err_deassert_por; - } - - ret = reset_control_deassert(res->axi_reset); - if (ret) { - dev_err(dev, "cannot deassert axi reset\n"); - goto err_deassert_axi; + ret = reset_control_bulk_deassert(res->num_resets, res->resets); + if (ret < 0) { + dev_err(dev, "cannot deassert resets\n"); + regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); + return ret; } return 0; - -err_deassert_axi: - reset_control_assert(res->por_reset); -err_deassert_por: - reset_control_assert(res->pci_reset); -err_deassert_pci: - reset_control_assert(res->phy_reset); -err_deassert_phy: - reset_control_assert(res->ext_reset); -err_deassert_ext: - reset_control_assert(res->ahb_reset); -err_deassert_ahb: - regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); - - return ret; } static int qcom_pcie_post_init_2_1_0(struct qcom_pcie *pcie) @@ -423,9 +384,9 @@ static int qcom_pcie_post_init_2_1_0(struct qcom_pcie *pcie) int ret; /* enable PCIe clocks and resets */ - val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); - val &= ~BIT(0); - writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); + val = readl(pcie->parf + PARF_PHY_CTRL); + val &= ~PHY_TEST_PWR_DOWN; + writel(val, pcie->parf + PARF_PHY_CTRL); ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks); if (ret) @@ -436,37 +397,37 @@ static int qcom_pcie_post_init_2_1_0(struct qcom_pcie *pcie) writel(PCS_DEEMPH_TX_DEEMPH_GEN1(24) | PCS_DEEMPH_TX_DEEMPH_GEN2_3_5DB(24) | PCS_DEEMPH_TX_DEEMPH_GEN2_6DB(34), - pcie->parf + PCIE20_PARF_PCS_DEEMPH); + pcie->parf + PARF_PCS_DEEMPH); writel(PCS_SWING_TX_SWING_FULL(120) | PCS_SWING_TX_SWING_LOW(120), - pcie->parf + PCIE20_PARF_PCS_SWING); - writel(PHY_RX0_EQ(4), pcie->parf + PCIE20_PARF_CONFIG_BITS); + pcie->parf + PARF_PCS_SWING); + writel(PHY_RX0_EQ(4), pcie->parf + PARF_CONFIG_BITS); } if (of_device_is_compatible(node, "qcom,pcie-ipq8064")) { /* set TX termination offset */ - val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); + val = readl(pcie->parf + PARF_PHY_CTRL); val &= ~PHY_CTRL_PHY_TX0_TERM_OFFSET_MASK; val |= PHY_CTRL_PHY_TX0_TERM_OFFSET(7); - writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); + writel(val, pcie->parf + PARF_PHY_CTRL); } /* enable external reference clock */ - val = readl(pcie->parf + PCIE20_PARF_PHY_REFCLK); + val = readl(pcie->parf + PARF_PHY_REFCLK); /* USE_PAD is required only for ipq806x */ if (!of_device_is_compatible(node, "qcom,pcie-apq8064")) val &= ~PHY_REFCLK_USE_PAD; val |= PHY_REFCLK_SSP_EN; - writel(val, pcie->parf + PCIE20_PARF_PHY_REFCLK); + writel(val, pcie->parf + PARF_PHY_REFCLK); /* wait for clock acquisition */ usleep_range(1000, 1500); /* Set the Max TLP size to 2K, instead of using default of 4K */ writel(CFG_REMOTE_RD_REQ_BRIDGE_SIZE_2K, - pci->dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL0); + pci->dbi_base + AXI_MSTR_RESP_COMP_CTRL0); writel(CFG_BRIDGE_SB_INIT, - pci->dbi_base + PCIE20_AXI_MSTR_RESP_COMP_CTRL1); + pci->dbi_base + AXI_MSTR_RESP_COMP_CTRL1); return 0; } @@ -476,26 +437,20 @@ static int qcom_pcie_get_resources_1_0_0(struct qcom_pcie *pcie) struct qcom_pcie_resources_1_0_0 *res = &pcie->res.v1_0_0; struct dw_pcie *pci = pcie->pci; struct device *dev = pci->dev; + int ret; res->vdda = devm_regulator_get(dev, "vdda"); if (IS_ERR(res->vdda)) return PTR_ERR(res->vdda); - res->iface = devm_clk_get(dev, "iface"); - if (IS_ERR(res->iface)) - return PTR_ERR(res->iface); - - res->aux = devm_clk_get(dev, "aux"); - if (IS_ERR(res->aux)) - return PTR_ERR(res->aux); - - res->master_bus = devm_clk_get(dev, "master_bus"); - if (IS_ERR(res->master_bus)) - return PTR_ERR(res->master_bus); + res->clks[0].id = "iface"; + res->clks[1].id = "aux"; + res->clks[2].id = "master_bus"; + res->clks[3].id = "slave_bus"; - res->slave_bus = devm_clk_get(dev, "slave_bus"); - if (IS_ERR(res->slave_bus)) - return PTR_ERR(res->slave_bus); + ret = devm_clk_bulk_get(dev, ARRAY_SIZE(res->clks), res->clks); + if (ret < 0) + return ret; res->core = devm_reset_control_get_exclusive(dev, "core"); return PTR_ERR_OR_ZERO(res->core); @@ -506,10 +461,7 @@ static void qcom_pcie_deinit_1_0_0(struct qcom_pcie *pcie) struct qcom_pcie_resources_1_0_0 *res = &pcie->res.v1_0_0; reset_control_assert(res->core); - clk_disable_unprepare(res->slave_bus); - clk_disable_unprepare(res->master_bus); - clk_disable_unprepare(res->iface); - clk_disable_unprepare(res->aux); + clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks); regulator_disable(res->vdda); } @@ -526,46 +478,23 @@ static int qcom_pcie_init_1_0_0(struct qcom_pcie *pcie) return ret; } - ret = clk_prepare_enable(res->aux); - if (ret) { - dev_err(dev, "cannot prepare/enable aux clock\n"); - goto err_res; - } - - ret = clk_prepare_enable(res->iface); - if (ret) { - dev_err(dev, "cannot prepare/enable iface clock\n"); - goto err_aux; - } - - ret = clk_prepare_enable(res->master_bus); - if (ret) { - dev_err(dev, "cannot prepare/enable master_bus clock\n"); - goto err_iface; - } - - ret = clk_prepare_enable(res->slave_bus); + ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks); if (ret) { - dev_err(dev, "cannot prepare/enable slave_bus clock\n"); - goto err_master; + dev_err(dev, "cannot prepare/enable clocks\n"); + goto err_assert_reset; } ret = regulator_enable(res->vdda); if (ret) { dev_err(dev, "cannot enable vdda regulator\n"); - goto err_slave; + goto err_disable_clks; } return 0; -err_slave: - clk_disable_unprepare(res->slave_bus); -err_master: - clk_disable_unprepare(res->master_bus); -err_iface: - clk_disable_unprepare(res->iface); -err_aux: - clk_disable_unprepare(res->aux); -err_res: + +err_disable_clks: + clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks); +err_assert_reset: reset_control_assert(res->core); return ret; @@ -574,13 +503,13 @@ err_res: static int qcom_pcie_post_init_1_0_0(struct qcom_pcie *pcie) { /* change DBI base address */ - writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR); + writel(0, pcie->parf + PARF_DBI_BASE_ADDR); if (IS_ENABLED(CONFIG_PCI_MSI)) { - u32 val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT); + u32 val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT); - val |= BIT(31); - writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT); + val |= EN; + writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT); } return 0; @@ -591,9 +520,9 @@ static void qcom_pcie_2_3_2_ltssm_enable(struct qcom_pcie *pcie) u32 val; /* enable link training */ - val = readl(pcie->parf + PCIE20_PARF_LTSSM); - val |= BIT(8); - writel(val, pcie->parf + PCIE20_PARF_LTSSM); + val = readl(pcie->parf + PARF_LTSSM); + val |= LTSSM_EN; + writel(val, pcie->parf + PARF_LTSSM); } static int qcom_pcie_get_resources_2_3_2(struct qcom_pcie *pcie) @@ -610,21 +539,14 @@ static int qcom_pcie_get_resources_2_3_2(struct qcom_pcie *pcie) if (ret) return ret; - res->aux_clk = devm_clk_get(dev, "aux"); - if (IS_ERR(res->aux_clk)) - return PTR_ERR(res->aux_clk); - - res->cfg_clk = devm_clk_get(dev, "cfg"); - if (IS_ERR(res->cfg_clk)) - return PTR_ERR(res->cfg_clk); - - res->master_clk = devm_clk_get(dev, "bus_master"); - if (IS_ERR(res->master_clk)) - return PTR_ERR(res->master_clk); + res->clks[0].id = "aux"; + res->clks[1].id = "cfg"; + res->clks[2].id = "bus_master"; + res->clks[3].id = "bus_slave"; - res->slave_clk = devm_clk_get(dev, "bus_slave"); - if (IS_ERR(res->slave_clk)) - return PTR_ERR(res->slave_clk); + ret = devm_clk_bulk_get(dev, ARRAY_SIZE(res->clks), res->clks); + if (ret < 0) + return ret; return 0; } @@ -633,11 +555,7 @@ static void qcom_pcie_deinit_2_3_2(struct qcom_pcie *pcie) { struct qcom_pcie_resources_2_3_2 *res = &pcie->res.v2_3_2; - clk_disable_unprepare(res->slave_clk); - clk_disable_unprepare(res->master_clk); - clk_disable_unprepare(res->cfg_clk); - clk_disable_unprepare(res->aux_clk); - + clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks); regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); } @@ -654,43 +572,14 @@ static int qcom_pcie_init_2_3_2(struct qcom_pcie *pcie) return ret; } - ret = clk_prepare_enable(res->aux_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable aux clock\n"); - goto err_aux_clk; - } - - ret = clk_prepare_enable(res->cfg_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable cfg clock\n"); - goto err_cfg_clk; - } - - ret = clk_prepare_enable(res->master_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable master clock\n"); - goto err_master_clk; - } - - ret = clk_prepare_enable(res->slave_clk); + ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks); if (ret) { - dev_err(dev, "cannot prepare/enable slave clock\n"); - goto err_slave_clk; + dev_err(dev, "cannot prepare/enable clocks\n"); + regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); + return ret; } return 0; - -err_slave_clk: - clk_disable_unprepare(res->master_clk); -err_master_clk: - clk_disable_unprepare(res->cfg_clk); -err_cfg_clk: - clk_disable_unprepare(res->aux_clk); - -err_aux_clk: - regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); - - return ret; } static int qcom_pcie_post_init_2_3_2(struct qcom_pcie *pcie) @@ -698,25 +587,25 @@ static int qcom_pcie_post_init_2_3_2(struct qcom_pcie *pcie) u32 val; /* enable PCIe clocks and resets */ - val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); - val &= ~BIT(0); - writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); + val = readl(pcie->parf + PARF_PHY_CTRL); + val &= ~PHY_TEST_PWR_DOWN; + writel(val, pcie->parf + PARF_PHY_CTRL); /* change DBI base address */ - writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR); + writel(0, pcie->parf + PARF_DBI_BASE_ADDR); /* MAC PHY_POWERDOWN MUX DISABLE */ - val = readl(pcie->parf + PCIE20_PARF_SYS_CTRL); - val &= ~BIT(29); - writel(val, pcie->parf + PCIE20_PARF_SYS_CTRL); + val = readl(pcie->parf + PARF_SYS_CTRL); + val &= ~MAC_PHY_POWERDOWN_IN_P2_D_MUX_EN; + writel(val, pcie->parf + PARF_SYS_CTRL); - val = readl(pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL); - val |= BIT(4); - writel(val, pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL); + val = readl(pcie->parf + PARF_MHI_CLOCK_RESET_CTRL); + val |= BYPASS; + writel(val, pcie->parf + PARF_MHI_CLOCK_RESET_CTRL); - val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2); - val |= BIT(31); - writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2); + val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + val |= EN; + writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); return 0; } @@ -741,65 +630,24 @@ static int qcom_pcie_get_resources_2_4_0(struct qcom_pcie *pcie) if (ret < 0) return ret; - res->axi_m_reset = devm_reset_control_get_exclusive(dev, "axi_m"); - if (IS_ERR(res->axi_m_reset)) - return PTR_ERR(res->axi_m_reset); - - res->axi_s_reset = devm_reset_control_get_exclusive(dev, "axi_s"); - if (IS_ERR(res->axi_s_reset)) - return PTR_ERR(res->axi_s_reset); - - if (is_ipq) { - /* - * These resources relates to the PHY or are secure clocks, but - * are controlled here for IPQ4019 - */ - res->pipe_reset = devm_reset_control_get_exclusive(dev, "pipe"); - if (IS_ERR(res->pipe_reset)) - return PTR_ERR(res->pipe_reset); - - res->axi_m_vmid_reset = devm_reset_control_get_exclusive(dev, - "axi_m_vmid"); - if (IS_ERR(res->axi_m_vmid_reset)) - return PTR_ERR(res->axi_m_vmid_reset); - - res->axi_s_xpu_reset = devm_reset_control_get_exclusive(dev, - "axi_s_xpu"); - if (IS_ERR(res->axi_s_xpu_reset)) - return PTR_ERR(res->axi_s_xpu_reset); - - res->parf_reset = devm_reset_control_get_exclusive(dev, "parf"); - if (IS_ERR(res->parf_reset)) - return PTR_ERR(res->parf_reset); - - res->phy_reset = devm_reset_control_get_exclusive(dev, "phy"); - if (IS_ERR(res->phy_reset)) - return PTR_ERR(res->phy_reset); - } - - res->axi_m_sticky_reset = devm_reset_control_get_exclusive(dev, - "axi_m_sticky"); - if (IS_ERR(res->axi_m_sticky_reset)) - return PTR_ERR(res->axi_m_sticky_reset); - - res->pipe_sticky_reset = devm_reset_control_get_exclusive(dev, - "pipe_sticky"); - if (IS_ERR(res->pipe_sticky_reset)) - return PTR_ERR(res->pipe_sticky_reset); - - res->pwr_reset = devm_reset_control_get_exclusive(dev, "pwr"); - if (IS_ERR(res->pwr_reset)) - return PTR_ERR(res->pwr_reset); - - res->ahb_reset = devm_reset_control_get_exclusive(dev, "ahb"); - if (IS_ERR(res->ahb_reset)) - return PTR_ERR(res->ahb_reset); - - if (is_ipq) { - res->phy_ahb_reset = devm_reset_control_get_exclusive(dev, "phy_ahb"); - if (IS_ERR(res->phy_ahb_reset)) - return PTR_ERR(res->phy_ahb_reset); - } + res->resets[0].id = "axi_m"; + res->resets[1].id = "axi_s"; + res->resets[2].id = "axi_m_sticky"; + res->resets[3].id = "pipe_sticky"; + res->resets[4].id = "pwr"; + res->resets[5].id = "ahb"; + res->resets[6].id = "pipe"; + res->resets[7].id = "axi_m_vmid"; + res->resets[8].id = "axi_s_xpu"; + res->resets[9].id = "parf"; + res->resets[10].id = "phy"; + res->resets[11].id = "phy_ahb"; + + res->num_resets = is_ipq ? 12 : 6; + + ret = devm_reset_control_bulk_get_exclusive(dev, res->num_resets, res->resets); + if (ret < 0) + return ret; return 0; } @@ -808,15 +656,7 @@ static void qcom_pcie_deinit_2_4_0(struct qcom_pcie *pcie) { struct qcom_pcie_resources_2_4_0 *res = &pcie->res.v2_4_0; - reset_control_assert(res->axi_m_reset); - reset_control_assert(res->axi_s_reset); - reset_control_assert(res->pipe_reset); - reset_control_assert(res->pipe_sticky_reset); - reset_control_assert(res->phy_reset); - reset_control_assert(res->phy_ahb_reset); - reset_control_assert(res->axi_m_sticky_reset); - reset_control_assert(res->pwr_reset); - reset_control_assert(res->ahb_reset); + reset_control_bulk_assert(res->num_resets, res->resets); clk_bulk_disable_unprepare(res->num_clks, res->clks); } @@ -827,149 +667,29 @@ static int qcom_pcie_init_2_4_0(struct qcom_pcie *pcie) struct device *dev = pci->dev; int ret; - ret = reset_control_assert(res->axi_m_reset); - if (ret) { - dev_err(dev, "cannot assert axi master reset\n"); - return ret; - } - - ret = reset_control_assert(res->axi_s_reset); - if (ret) { - dev_err(dev, "cannot assert axi slave reset\n"); - return ret; - } - - usleep_range(10000, 12000); - - ret = reset_control_assert(res->pipe_reset); - if (ret) { - dev_err(dev, "cannot assert pipe reset\n"); - return ret; - } - - ret = reset_control_assert(res->pipe_sticky_reset); - if (ret) { - dev_err(dev, "cannot assert pipe sticky reset\n"); - return ret; - } - - ret = reset_control_assert(res->phy_reset); - if (ret) { - dev_err(dev, "cannot assert phy reset\n"); - return ret; - } - - ret = reset_control_assert(res->phy_ahb_reset); - if (ret) { - dev_err(dev, "cannot assert phy ahb reset\n"); + ret = reset_control_bulk_assert(res->num_resets, res->resets); + if (ret < 0) { + dev_err(dev, "cannot assert resets\n"); return ret; } usleep_range(10000, 12000); - ret = reset_control_assert(res->axi_m_sticky_reset); - if (ret) { - dev_err(dev, "cannot assert axi master sticky reset\n"); - return ret; - } - - ret = reset_control_assert(res->pwr_reset); - if (ret) { - dev_err(dev, "cannot assert power reset\n"); - return ret; - } - - ret = reset_control_assert(res->ahb_reset); - if (ret) { - dev_err(dev, "cannot assert ahb reset\n"); + ret = reset_control_bulk_deassert(res->num_resets, res->resets); + if (ret < 0) { + dev_err(dev, "cannot deassert resets\n"); return ret; } usleep_range(10000, 12000); - ret = reset_control_deassert(res->phy_ahb_reset); + ret = clk_bulk_prepare_enable(res->num_clks, res->clks); if (ret) { - dev_err(dev, "cannot deassert phy ahb reset\n"); + reset_control_bulk_assert(res->num_resets, res->resets); return ret; } - ret = reset_control_deassert(res->phy_reset); - if (ret) { - dev_err(dev, "cannot deassert phy reset\n"); - goto err_rst_phy; - } - - ret = reset_control_deassert(res->pipe_reset); - if (ret) { - dev_err(dev, "cannot deassert pipe reset\n"); - goto err_rst_pipe; - } - - ret = reset_control_deassert(res->pipe_sticky_reset); - if (ret) { - dev_err(dev, "cannot deassert pipe sticky reset\n"); - goto err_rst_pipe_sticky; - } - - usleep_range(10000, 12000); - - ret = reset_control_deassert(res->axi_m_reset); - if (ret) { - dev_err(dev, "cannot deassert axi master reset\n"); - goto err_rst_axi_m; - } - - ret = reset_control_deassert(res->axi_m_sticky_reset); - if (ret) { - dev_err(dev, "cannot deassert axi master sticky reset\n"); - goto err_rst_axi_m_sticky; - } - - ret = reset_control_deassert(res->axi_s_reset); - if (ret) { - dev_err(dev, "cannot deassert axi slave reset\n"); - goto err_rst_axi_s; - } - - ret = reset_control_deassert(res->pwr_reset); - if (ret) { - dev_err(dev, "cannot deassert power reset\n"); - goto err_rst_pwr; - } - - ret = reset_control_deassert(res->ahb_reset); - if (ret) { - dev_err(dev, "cannot deassert ahb reset\n"); - goto err_rst_ahb; - } - - usleep_range(10000, 12000); - - ret = clk_bulk_prepare_enable(res->num_clks, res->clks); - if (ret) - goto err_clks; - return 0; - -err_clks: - reset_control_assert(res->ahb_reset); -err_rst_ahb: - reset_control_assert(res->pwr_reset); -err_rst_pwr: - reset_control_assert(res->axi_s_reset); -err_rst_axi_s: - reset_control_assert(res->axi_m_sticky_reset); -err_rst_axi_m_sticky: - reset_control_assert(res->axi_m_reset); -err_rst_axi_m: - reset_control_assert(res->pipe_sticky_reset); -err_rst_pipe_sticky: - reset_control_assert(res->pipe_reset); -err_rst_pipe: - reset_control_assert(res->phy_reset); -err_rst_phy: - reset_control_assert(res->phy_ahb_reset); - return ret; } static int qcom_pcie_post_init_2_4_0(struct qcom_pcie *pcie) @@ -977,25 +697,25 @@ static int qcom_pcie_post_init_2_4_0(struct qcom_pcie *pcie) u32 val; /* enable PCIe clocks and resets */ - val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); - val &= ~BIT(0); - writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); + val = readl(pcie->parf + PARF_PHY_CTRL); + val &= ~PHY_TEST_PWR_DOWN; + writel(val, pcie->parf + PARF_PHY_CTRL); /* change DBI base address */ - writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR); + writel(0, pcie->parf + PARF_DBI_BASE_ADDR); /* MAC PHY_POWERDOWN MUX DISABLE */ - val = readl(pcie->parf + PCIE20_PARF_SYS_CTRL); - val &= ~BIT(29); - writel(val, pcie->parf + PCIE20_PARF_SYS_CTRL); + val = readl(pcie->parf + PARF_SYS_CTRL); + val &= ~MAC_PHY_POWERDOWN_IN_P2_D_MUX_EN; + writel(val, pcie->parf + PARF_SYS_CTRL); - val = readl(pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL); - val |= BIT(4); - writel(val, pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL); + val = readl(pcie->parf + PARF_MHI_CLOCK_RESET_CTRL); + val |= BYPASS; + writel(val, pcie->parf + PARF_MHI_CLOCK_RESET_CTRL); - val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2); - val |= BIT(31); - writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT_V2); + val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + val |= EN; + writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); return 0; } @@ -1005,36 +725,29 @@ static int qcom_pcie_get_resources_2_3_3(struct qcom_pcie *pcie) struct qcom_pcie_resources_2_3_3 *res = &pcie->res.v2_3_3; struct dw_pcie *pci = pcie->pci; struct device *dev = pci->dev; - int i; - const char *rst_names[] = { "axi_m", "axi_s", "pipe", - "axi_m_sticky", "sticky", - "ahb", "sleep", }; - - res->iface = devm_clk_get(dev, "iface"); - if (IS_ERR(res->iface)) - return PTR_ERR(res->iface); - - res->axi_m_clk = devm_clk_get(dev, "axi_m"); - if (IS_ERR(res->axi_m_clk)) - return PTR_ERR(res->axi_m_clk); - - res->axi_s_clk = devm_clk_get(dev, "axi_s"); - if (IS_ERR(res->axi_s_clk)) - return PTR_ERR(res->axi_s_clk); - - res->ahb_clk = devm_clk_get(dev, "ahb"); - if (IS_ERR(res->ahb_clk)) - return PTR_ERR(res->ahb_clk); - - res->aux_clk = devm_clk_get(dev, "aux"); - if (IS_ERR(res->aux_clk)) - return PTR_ERR(res->aux_clk); - - for (i = 0; i < ARRAY_SIZE(rst_names); i++) { - res->rst[i] = devm_reset_control_get(dev, rst_names[i]); - if (IS_ERR(res->rst[i])) - return PTR_ERR(res->rst[i]); - } + int ret; + + res->clks[0].id = "iface"; + res->clks[1].id = "axi_m"; + res->clks[2].id = "axi_s"; + res->clks[3].id = "ahb"; + res->clks[4].id = "aux"; + + ret = devm_clk_bulk_get(dev, ARRAY_SIZE(res->clks), res->clks); + if (ret < 0) + return ret; + + res->rst[0].id = "axi_m"; + res->rst[1].id = "axi_s"; + res->rst[2].id = "pipe"; + res->rst[3].id = "axi_m_sticky"; + res->rst[4].id = "sticky"; + res->rst[5].id = "ahb"; + res->rst[6].id = "sleep"; + + ret = devm_reset_control_bulk_get_exclusive(dev, ARRAY_SIZE(res->rst), res->rst); + if (ret < 0) + return ret; return 0; } @@ -1043,11 +756,7 @@ static void qcom_pcie_deinit_2_3_3(struct qcom_pcie *pcie) { struct qcom_pcie_resources_2_3_3 *res = &pcie->res.v2_3_3; - clk_disable_unprepare(res->iface); - clk_disable_unprepare(res->axi_m_clk); - clk_disable_unprepare(res->axi_s_clk); - clk_disable_unprepare(res->ahb_clk); - clk_disable_unprepare(res->aux_clk); + clk_bulk_disable_unprepare(ARRAY_SIZE(res->clks), res->clks); } static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie) @@ -1055,25 +764,20 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie) struct qcom_pcie_resources_2_3_3 *res = &pcie->res.v2_3_3; struct dw_pcie *pci = pcie->pci; struct device *dev = pci->dev; - int i, ret; + int ret; - for (i = 0; i < ARRAY_SIZE(res->rst); i++) { - ret = reset_control_assert(res->rst[i]); - if (ret) { - dev_err(dev, "reset #%d assert failed (%d)\n", i, ret); - return ret; - } + ret = reset_control_bulk_assert(ARRAY_SIZE(res->rst), res->rst); + if (ret < 0) { + dev_err(dev, "cannot assert resets\n"); + return ret; } usleep_range(2000, 2500); - for (i = 0; i < ARRAY_SIZE(res->rst); i++) { - ret = reset_control_deassert(res->rst[i]); - if (ret) { - dev_err(dev, "reset #%d deassert failed (%d)\n", i, - ret); - return ret; - } + ret = reset_control_bulk_deassert(ARRAY_SIZE(res->rst), res->rst); + if (ret < 0) { + dev_err(dev, "cannot deassert resets\n"); + return ret; } /* @@ -1082,53 +786,20 @@ static int qcom_pcie_init_2_3_3(struct qcom_pcie *pcie) */ usleep_range(2000, 2500); - ret = clk_prepare_enable(res->iface); - if (ret) { - dev_err(dev, "cannot prepare/enable core clock\n"); - goto err_clk_iface; - } - - ret = clk_prepare_enable(res->axi_m_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable core clock\n"); - goto err_clk_axi_m; - } - - ret = clk_prepare_enable(res->axi_s_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable axi slave clock\n"); - goto err_clk_axi_s; - } - - ret = clk_prepare_enable(res->ahb_clk); - if (ret) { - dev_err(dev, "cannot prepare/enable ahb clock\n"); - goto err_clk_ahb; - } - - ret = clk_prepare_enable(res->aux_clk); + ret = clk_bulk_prepare_enable(ARRAY_SIZE(res->clks), res->clks); if (ret) { - dev_err(dev, "cannot prepare/enable aux clock\n"); - goto err_clk_aux; + dev_err(dev, "cannot prepare/enable clocks\n"); + goto err_assert_resets; } return 0; -err_clk_aux: - clk_disable_unprepare(res->ahb_clk); -err_clk_ahb: - clk_disable_unprepare(res->axi_s_clk); -err_clk_axi_s: - clk_disable_unprepare(res->axi_m_clk); -err_clk_axi_m: - clk_disable_unprepare(res->iface); -err_clk_iface: +err_assert_resets: /* * Not checking for failure, will anyway return * the original failure in 'ret'. */ - for (i = 0; i < ARRAY_SIZE(res->rst); i++) - reset_control_assert(res->rst[i]); + reset_control_bulk_assert(ARRAY_SIZE(res->rst), res->rst); return ret; } @@ -1140,22 +811,22 @@ static int qcom_pcie_post_init_2_3_3(struct qcom_pcie *pcie) u32 val; writel(SLV_ADDR_SPACE_SZ, - pcie->parf + PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE); + pcie->parf + PARF_SLV_ADDR_SPACE_SIZE_2_3_3); - val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); - val &= ~BIT(0); - writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); + val = readl(pcie->parf + PARF_PHY_CTRL); + val &= ~PHY_TEST_PWR_DOWN; + writel(val, pcie->parf + PARF_PHY_CTRL); - writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR); + writel(0, pcie->parf + PARF_DBI_BASE_ADDR); writel(MST_WAKEUP_EN | SLV_WAKEUP_EN | MSTR_ACLK_CGC_DIS | SLV_ACLK_CGC_DIS | CORE_CLK_CGC_DIS | AUX_PWR_DET | L23_CLK_RMV_DIS | L1_CLK_RMV_DIS, - pcie->parf + PCIE20_PARF_SYS_CTRL); - writel(0, pcie->parf + PCIE20_PARF_Q2A_FLUSH); + pcie->parf + PARF_SYS_CTRL); + writel(0, pcie->parf + PARF_Q2A_FLUSH); writel(PCI_COMMAND_MASTER, pci->dbi_base + PCI_COMMAND); - writel(DBI_RO_WR_EN, pci->dbi_base + PCIE20_MISC_CONTROL_1_REG); + writel(DBI_RO_WR_EN, pci->dbi_base + MISC_CONTROL_1_REG); writel(PCIE_CAP_SLOT_VAL, pci->dbi_base + offset + PCI_EXP_SLTCAP); val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP); @@ -1177,9 +848,9 @@ static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie) unsigned int idx; int ret; - res->pci_reset = devm_reset_control_get_exclusive(dev, "pci"); - if (IS_ERR(res->pci_reset)) - return PTR_ERR(res->pci_reset); + res->rst = devm_reset_control_array_get_exclusive(dev); + if (IS_ERR(res->rst)) + return PTR_ERR(res->rst); res->supplies[0].supply = "vdda"; res->supplies[1].supply = "vddpe-3v3"; @@ -1205,9 +876,12 @@ static int qcom_pcie_get_resources_2_7_0(struct qcom_pcie *pcie) res->clks[idx++].id = "ddrss_sf_tbu"; res->clks[idx++].id = "aggre0"; res->clks[idx++].id = "aggre1"; + res->clks[idx++].id = "noc_aggr"; res->clks[idx++].id = "noc_aggr_4"; res->clks[idx++].id = "noc_aggr_south_sf"; res->clks[idx++].id = "cnoc_qx"; + res->clks[idx++].id = "sleep"; + res->clks[idx++].id = "cnoc_sf_axi"; num_opt_clks = idx - num_clks; res->num_clks = idx; @@ -1237,17 +911,17 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie) if (ret < 0) goto err_disable_regulators; - ret = reset_control_assert(res->pci_reset); - if (ret < 0) { - dev_err(dev, "cannot assert pci reset\n"); + ret = reset_control_assert(res->rst); + if (ret) { + dev_err(dev, "reset assert failed (%d)\n", ret); goto err_disable_clocks; } usleep_range(1000, 1500); - ret = reset_control_deassert(res->pci_reset); - if (ret < 0) { - dev_err(dev, "cannot deassert pci reset\n"); + ret = reset_control_deassert(res->rst); + if (ret) { + dev_err(dev, "reset deassert failed (%d)\n", ret); goto err_disable_clocks; } @@ -1255,35 +929,33 @@ static int qcom_pcie_init_2_7_0(struct qcom_pcie *pcie) usleep_range(1000, 1500); /* configure PCIe to RC mode */ - writel(DEVICE_TYPE_RC, pcie->parf + PCIE20_PARF_DEVICE_TYPE); + writel(DEVICE_TYPE_RC, pcie->parf + PARF_DEVICE_TYPE); /* enable PCIe clocks and resets */ - val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); - val &= ~BIT(0); - writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); + val = readl(pcie->parf + PARF_PHY_CTRL); + val &= ~PHY_TEST_PWR_DOWN; + writel(val, pcie->parf + PARF_PHY_CTRL); /* change DBI base address */ - writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR); + writel(0, pcie->parf + PARF_DBI_BASE_ADDR); /* MAC PHY_POWERDOWN MUX DISABLE */ - val = readl(pcie->parf + PCIE20_PARF_SYS_CTRL); - val &= ~BIT(29); - writel(val, pcie->parf + PCIE20_PARF_SYS_CTRL); + val = readl(pcie->parf + PARF_SYS_CTRL); + val &= ~MAC_PHY_POWERDOWN_IN_P2_D_MUX_EN; + writel(val, pcie->parf + PARF_SYS_CTRL); - val = readl(pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL); - val |= BIT(4); - writel(val, pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL); + val = readl(pcie->parf + PARF_MHI_CLOCK_RESET_CTRL); + val |= BYPASS; + writel(val, pcie->parf + PARF_MHI_CLOCK_RESET_CTRL); /* Enable L1 and L1SS */ - val = readl(pcie->parf + PCIE20_PARF_PM_CTRL); + val = readl(pcie->parf + PARF_PM_CTRL); val &= ~REQ_NOT_ENTR_L1; - writel(val, pcie->parf + PCIE20_PARF_PM_CTRL); + writel(val, pcie->parf + PARF_PM_CTRL); - if (IS_ENABLED(CONFIG_PCI_MSI)) { - val = readl(pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT); - val |= BIT(31); - writel(val, pcie->parf + PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT); - } + val = readl(pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); + val |= EN; + writel(val, pcie->parf + PARF_AXI_MSTR_WR_ADDR_HALT_V2); return 0; err_disable_clocks: @@ -1303,6 +975,76 @@ static void qcom_pcie_deinit_2_7_0(struct qcom_pcie *pcie) regulator_bulk_disable(ARRAY_SIZE(res->supplies), res->supplies); } +static int qcom_pcie_config_sid_1_9_0(struct qcom_pcie *pcie) +{ + /* iommu map structure */ + struct { + u32 bdf; + u32 phandle; + u32 smmu_sid; + u32 smmu_sid_len; + } *map; + void __iomem *bdf_to_sid_base = pcie->parf + PARF_BDF_TO_SID_TABLE_N; + struct device *dev = pcie->pci->dev; + u8 qcom_pcie_crc8_table[CRC8_TABLE_SIZE]; + int i, nr_map, size = 0; + u32 smmu_sid_base; + + of_get_property(dev->of_node, "iommu-map", &size); + if (!size) + return 0; + + map = kzalloc(size, GFP_KERNEL); + if (!map) + return -ENOMEM; + + of_property_read_u32_array(dev->of_node, "iommu-map", (u32 *)map, + size / sizeof(u32)); + + nr_map = size / (sizeof(*map)); + + crc8_populate_msb(qcom_pcie_crc8_table, QCOM_PCIE_CRC8_POLYNOMIAL); + + /* Registers need to be zero out first */ + memset_io(bdf_to_sid_base, 0, CRC8_TABLE_SIZE * sizeof(u32)); + + /* Extract the SMMU SID base from the first entry of iommu-map */ + smmu_sid_base = map[0].smmu_sid; + + /* Look for an available entry to hold the mapping */ + for (i = 0; i < nr_map; i++) { + __be16 bdf_be = cpu_to_be16(map[i].bdf); + u32 val; + u8 hash; + + hash = crc8(qcom_pcie_crc8_table, (u8 *)&bdf_be, sizeof(bdf_be), 0); + + val = readl(bdf_to_sid_base + hash * sizeof(u32)); + + /* If the register is already populated, look for next available entry */ + while (val) { + u8 current_hash = hash++; + u8 next_mask = 0xff; + + /* If NEXT field is NULL then update it with next hash */ + if (!(val & next_mask)) { + val |= (u32)hash; + writel(val, bdf_to_sid_base + current_hash * sizeof(u32)); + } + + val = readl(bdf_to_sid_base + hash * sizeof(u32)); + } + + /* BDF [31:16] | SID [15:8] | NEXT [7:0] */ + val = map[i].bdf << 16 | (map[i].smmu_sid - smmu_sid_base) << 8 | 0; + writel(val, bdf_to_sid_base + hash * sizeof(u32)); + } + + kfree(map); + + return 0; +} + static int qcom_pcie_get_resources_2_9_0(struct qcom_pcie *pcie) { struct qcom_pcie_resources_2_9_0 *res = &pcie->res.v2_9_0; @@ -1371,17 +1113,17 @@ static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie) int i; writel(SLV_ADDR_SPACE_SZ, - pcie->parf + PCIE20_v3_PARF_SLV_ADDR_SPACE_SIZE); + pcie->parf + PARF_SLV_ADDR_SPACE_SIZE); - val = readl(pcie->parf + PCIE20_PARF_PHY_CTRL); - val &= ~BIT(0); - writel(val, pcie->parf + PCIE20_PARF_PHY_CTRL); + val = readl(pcie->parf + PARF_PHY_CTRL); + val &= ~PHY_TEST_PWR_DOWN; + writel(val, pcie->parf + PARF_PHY_CTRL); - writel(0, pcie->parf + PCIE20_PARF_DBI_BASE_ADDR); + writel(0, pcie->parf + PARF_DBI_BASE_ADDR); - writel(DEVICE_TYPE_RC, pcie->parf + PCIE20_PARF_DEVICE_TYPE); + writel(DEVICE_TYPE_RC, pcie->parf + PARF_DEVICE_TYPE); writel(BYPASS | MSTR_AXI_CLK_EN | AHB_CLK_EN, - pcie->parf + PCIE20_PARF_MHI_CLOCK_RESET_CTRL); + pcie->parf + PARF_MHI_CLOCK_RESET_CTRL); writel(GEN3_RELATED_OFF_RXEQ_RGRDLESS_RXTS | GEN3_RELATED_OFF_GEN3_ZRXDC_NONCOMPL, pci->dbi_base + GEN3_RELATED_OFF); @@ -1389,9 +1131,9 @@ static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie) writel(MST_WAKEUP_EN | SLV_WAKEUP_EN | MSTR_ACLK_CGC_DIS | SLV_ACLK_CGC_DIS | CORE_CLK_CGC_DIS | AUX_PWR_DET | L23_CLK_RMV_DIS | L1_CLK_RMV_DIS, - pcie->parf + PCIE20_PARF_SYS_CTRL); + pcie->parf + PARF_SYS_CTRL); - writel(0, pcie->parf + PCIE20_PARF_Q2A_FLUSH); + writel(0, pcie->parf + PARF_Q2A_FLUSH); dw_pcie_dbi_ro_wr_en(pci); writel(PCIE_CAP_SLOT_VAL, pci->dbi_base + offset + PCI_EXP_SLTCAP); @@ -1404,7 +1146,7 @@ static int qcom_pcie_post_init_2_9_0(struct qcom_pcie *pcie) PCI_EXP_DEVCTL2); for (i = 0; i < 256; i++) - writel(0, pcie->parf + PCIE20_PARF_BDF_TO_SID_TABLE_N + (4 * i)); + writel(0, pcie->parf + PARF_BDF_TO_SID_TABLE_N + (4 * i)); return 0; } @@ -1417,77 +1159,6 @@ static int qcom_pcie_link_up(struct dw_pcie *pci) return !!(val & PCI_EXP_LNKSTA_DLLLA); } -static int qcom_pcie_config_sid_sm8250(struct qcom_pcie *pcie) -{ - /* iommu map structure */ - struct { - u32 bdf; - u32 phandle; - u32 smmu_sid; - u32 smmu_sid_len; - } *map; - void __iomem *bdf_to_sid_base = pcie->parf + PCIE20_PARF_BDF_TO_SID_TABLE_N; - struct device *dev = pcie->pci->dev; - u8 qcom_pcie_crc8_table[CRC8_TABLE_SIZE]; - int i, nr_map, size = 0; - u32 smmu_sid_base; - - of_get_property(dev->of_node, "iommu-map", &size); - if (!size) - return 0; - - map = kzalloc(size, GFP_KERNEL); - if (!map) - return -ENOMEM; - - of_property_read_u32_array(dev->of_node, - "iommu-map", (u32 *)map, size / sizeof(u32)); - - nr_map = size / (sizeof(*map)); - - crc8_populate_msb(qcom_pcie_crc8_table, QCOM_PCIE_CRC8_POLYNOMIAL); - - /* Registers need to be zero out first */ - memset_io(bdf_to_sid_base, 0, CRC8_TABLE_SIZE * sizeof(u32)); - - /* Extract the SMMU SID base from the first entry of iommu-map */ - smmu_sid_base = map[0].smmu_sid; - - /* Look for an available entry to hold the mapping */ - for (i = 0; i < nr_map; i++) { - __be16 bdf_be = cpu_to_be16(map[i].bdf); - u32 val; - u8 hash; - - hash = crc8(qcom_pcie_crc8_table, (u8 *)&bdf_be, sizeof(bdf_be), - 0); - - val = readl(bdf_to_sid_base + hash * sizeof(u32)); - - /* If the register is already populated, look for next available entry */ - while (val) { - u8 current_hash = hash++; - u8 next_mask = 0xff; - - /* If NEXT field is NULL then update it with next hash */ - if (!(val & next_mask)) { - val |= (u32)hash; - writel(val, bdf_to_sid_base + current_hash * sizeof(u32)); - } - - val = readl(bdf_to_sid_base + hash * sizeof(u32)); - } - - /* BDF [31:16] | SID [15:8] | NEXT [7:0] */ - val = map[i].bdf << 16 | (map[i].smmu_sid - smmu_sid_base) << 8 | 0; - writel(val, bdf_to_sid_base + hash * sizeof(u32)); - } - - kfree(map); - - return 0; -} - static int qcom_pcie_host_init(struct dw_pcie_rp *pp) { struct dw_pcie *pci = to_dw_pcie_from_pp(pp); @@ -1608,7 +1279,7 @@ static const struct qcom_pcie_ops ops_1_9_0 = { .init = qcom_pcie_init_2_7_0, .deinit = qcom_pcie_deinit_2_7_0, .ltssm_enable = qcom_pcie_2_3_2_ltssm_enable, - .config_sid = qcom_pcie_config_sid_sm8250, + .config_sid = qcom_pcie_config_sid_1_9_0, }; /* Qcom IP rev.: 2.9.0 Synopsys IP rev.: 5.00a */ @@ -1725,13 +1396,51 @@ static void qcom_pcie_icc_update(struct qcom_pcie *pcie) } } +static int qcom_pcie_link_transition_count(struct seq_file *s, void *data) +{ + struct qcom_pcie *pcie = (struct qcom_pcie *)dev_get_drvdata(s->private); + + seq_printf(s, "L0s transition count: %u\n", + readl_relaxed(pcie->mhi + PARF_DEBUG_CNT_PM_LINKST_IN_L0S)); + + seq_printf(s, "L1 transition count: %u\n", + readl_relaxed(pcie->mhi + PARF_DEBUG_CNT_PM_LINKST_IN_L1)); + + seq_printf(s, "L1.1 transition count: %u\n", + readl_relaxed(pcie->mhi + PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L1)); + + seq_printf(s, "L1.2 transition count: %u\n", + readl_relaxed(pcie->mhi + PARF_DEBUG_CNT_AUX_CLK_IN_L1SUB_L2)); + + seq_printf(s, "L2 transition count: %u\n", + readl_relaxed(pcie->mhi + PARF_DEBUG_CNT_PM_LINKST_IN_L2)); + + return 0; +} + +static void qcom_pcie_init_debugfs(struct qcom_pcie *pcie) +{ + struct dw_pcie *pci = pcie->pci; + struct device *dev = pci->dev; + char *name; + + name = devm_kasprintf(dev, GFP_KERNEL, "%pOFP", dev->of_node); + if (!name) + return; + + pcie->debugfs = debugfs_create_dir(name, NULL); + debugfs_create_devm_seqfile(dev, "link_transition_count", pcie->debugfs, + qcom_pcie_link_transition_count); +} + static int qcom_pcie_probe(struct platform_device *pdev) { + const struct qcom_pcie_cfg *pcie_cfg; struct device *dev = &pdev->dev; + struct qcom_pcie *pcie; struct dw_pcie_rp *pp; + struct resource *res; struct dw_pcie *pci; - struct qcom_pcie *pcie; - const struct qcom_pcie_cfg *pcie_cfg; int ret; pcie_cfg = of_device_get_match_data(dev); @@ -1779,6 +1488,16 @@ static int qcom_pcie_probe(struct platform_device *pdev) goto err_pm_runtime_put; } + /* MHI region is optional */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mhi"); + if (res) { + pcie->mhi = devm_ioremap_resource(dev, res); + if (IS_ERR(pcie->mhi)) { + ret = PTR_ERR(pcie->mhi); + goto err_pm_runtime_put; + } + } + pcie->phy = devm_phy_optional_get(dev, "pciephy"); if (IS_ERR(pcie->phy)) { ret = PTR_ERR(pcie->phy); @@ -1809,6 +1528,9 @@ static int qcom_pcie_probe(struct platform_device *pdev) qcom_pcie_icc_update(pcie); + if (pcie->mhi) + qcom_pcie_init_debugfs(pcie); + return 0; err_phy_exit: @@ -1820,6 +1542,62 @@ err_pm_runtime_put: return ret; } +static int qcom_pcie_suspend_noirq(struct device *dev) +{ + struct qcom_pcie *pcie = dev_get_drvdata(dev); + int ret; + + /* + * Set minimum bandwidth required to keep data path functional during + * suspend. + */ + ret = icc_set_bw(pcie->icc_mem, 0, kBps_to_icc(1)); + if (ret) { + dev_err(dev, "Failed to set interconnect bandwidth: %d\n", ret); + return ret; + } + + /* + * Turn OFF the resources only for controllers without active PCIe + * devices. For controllers with active devices, the resources are kept + * ON and the link is expected to be in L0/L1 (sub)states. + * + * Turning OFF the resources for controllers with active PCIe devices + * will trigger access violation during the end of the suspend cycle, + * as kernel tries to access the PCIe devices config space for masking + * MSIs. + * + * Also, it is not desirable to put the link into L2/L3 state as that + * implies VDD supply will be removed and the devices may go into + * powerdown state. This will affect the lifetime of the storage devices + * like NVMe. + */ + if (!dw_pcie_link_up(pcie->pci)) { + qcom_pcie_host_deinit(&pcie->pci->pp); + pcie->suspended = true; + } + + return 0; +} + +static int qcom_pcie_resume_noirq(struct device *dev) +{ + struct qcom_pcie *pcie = dev_get_drvdata(dev); + int ret; + + if (pcie->suspended) { + ret = qcom_pcie_host_init(&pcie->pci->pp); + if (ret) + return ret; + + pcie->suspended = false; + } + + qcom_pcie_icc_update(pcie); + + return 0; +} + static const struct of_device_id qcom_pcie_match[] = { { .compatible = "qcom,pcie-apq8064", .data = &cfg_2_1_0 }, { .compatible = "qcom,pcie-apq8084", .data = &cfg_1_0_0 }, @@ -1836,11 +1614,13 @@ static const struct of_device_id qcom_pcie_match[] = { { .compatible = "qcom,pcie-sc8180x", .data = &cfg_1_9_0 }, { .compatible = "qcom,pcie-sc8280xp", .data = &cfg_1_9_0 }, { .compatible = "qcom,pcie-sdm845", .data = &cfg_2_7_0 }, + { .compatible = "qcom,pcie-sdx55", .data = &cfg_1_9_0 }, { .compatible = "qcom,pcie-sm8150", .data = &cfg_1_9_0 }, { .compatible = "qcom,pcie-sm8250", .data = &cfg_1_9_0 }, { .compatible = "qcom,pcie-sm8350", .data = &cfg_1_9_0 }, { .compatible = "qcom,pcie-sm8450-pcie0", .data = &cfg_1_9_0 }, { .compatible = "qcom,pcie-sm8450-pcie1", .data = &cfg_1_9_0 }, + { .compatible = "qcom,pcie-sm8550", .data = &cfg_1_9_0 }, { } }; @@ -1856,12 +1636,18 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x0302, qcom_fixup_class); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x1000, qcom_fixup_class); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_QCOM, 0x1001, qcom_fixup_class); +static const struct dev_pm_ops qcom_pcie_pm_ops = { + NOIRQ_SYSTEM_SLEEP_PM_OPS(qcom_pcie_suspend_noirq, qcom_pcie_resume_noirq) +}; + static struct platform_driver qcom_pcie_driver = { .probe = qcom_pcie_probe, .driver = { .name = "qcom-pcie", .suppress_bind_attrs = true, .of_match_table = qcom_pcie_match, + .pm = &qcom_pcie_pm_ops, + .probe_type = PROBE_PREFER_ASYNCHRONOUS, }, }; builtin_platform_driver(qcom_pcie_driver); diff --git a/drivers/pci/controller/mobiveil/Kconfig b/drivers/pci/controller/mobiveil/Kconfig index 1d7a07ba9ccd..58ce034f701a 100644 --- a/drivers/pci/controller/mobiveil/Kconfig +++ b/drivers/pci/controller/mobiveil/Kconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -menu "Mobiveil PCIe Core Support" +menu "Mobiveil-based PCIe controllers" depends on PCI config PCIE_MOBIVEIL @@ -11,6 +11,15 @@ config PCIE_MOBIVEIL_HOST depends on PCI_MSI select PCIE_MOBIVEIL +config PCIE_LAYERSCAPE_GEN4 + bool "Freescale Layerscape Gen4 PCIe controller" + depends on ARCH_LAYERSCAPE || COMPILE_TEST + depends on PCI_MSI + select PCIE_MOBIVEIL_HOST + help + Say Y here if you want PCIe Gen4 controller support on + Layerscape SoCs. + config PCIE_MOBIVEIL_PLAT bool "Mobiveil AXI PCIe controller" depends on ARCH_ZYNQMP || COMPILE_TEST @@ -22,12 +31,4 @@ config PCIE_MOBIVEIL_PLAT Soft IP. It has up to 8 outbound and inbound windows for address translation and it is a PCIe Gen4 IP. -config PCIE_LAYERSCAPE_GEN4 - bool "Freescale Layerscape PCIe Gen4 controller" - depends on ARCH_LAYERSCAPE || COMPILE_TEST - depends on PCI_MSI - select PCIE_MOBIVEIL_HOST - help - Say Y here if you want PCIe Gen4 controller support on - Layerscape SoCs. endmenu diff --git a/drivers/pci/controller/pci-ixp4xx.c b/drivers/pci/controller/pci-ixp4xx.c index 654ac4a82beb..e44252db6085 100644 --- a/drivers/pci/controller/pci-ixp4xx.c +++ b/drivers/pci/controller/pci-ixp4xx.c @@ -26,6 +26,7 @@ #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/bits.h> +#include "../pci.h" /* Register offsets */ #define IXP4XX_PCI_NP_AD 0x00 @@ -188,12 +189,13 @@ static u32 ixp4xx_config_addr(u8 bus_num, u16 devfn, int where) /* Root bus is always 0 in this hardware */ if (bus_num == 0) { /* type 0 */ - return BIT(32-PCI_SLOT(devfn)) | ((PCI_FUNC(devfn)) << 8) | - (where & ~3); + return (PCI_CONF1_ADDRESS(0, 0, PCI_FUNC(devfn), where) & + ~PCI_CONF1_ENABLE) | BIT(32-PCI_SLOT(devfn)); } else { /* type 1 */ - return (bus_num << 16) | ((PCI_SLOT(devfn)) << 11) | - ((PCI_FUNC(devfn)) << 8) | (where & ~3) | 1; + return (PCI_CONF1_ADDRESS(bus_num, PCI_SLOT(devfn), + PCI_FUNC(devfn), where) & + ~PCI_CONF1_ENABLE) | 1; } } diff --git a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c index 74c109f14ff0..79630885b9c8 100644 --- a/drivers/pci/controller/pci-tegra.c +++ b/drivers/pci/controller/pci-tegra.c @@ -1375,7 +1375,7 @@ static int tegra_pcie_phys_get(struct tegra_pcie *pcie) struct tegra_pcie_port *port; int err; - if (!soc->has_gen2 || of_find_property(np, "phys", NULL) != NULL) + if (!soc->has_gen2 || of_property_present(np, "phys")) return tegra_pcie_phys_get_legacy(pcie); list_for_each_entry(port, &pcie->ports, list) { @@ -1944,7 +1944,7 @@ static bool of_regulator_bulk_available(struct device_node *np, for (i = 0; i < num_supplies; i++) { snprintf(property, 32, "%s-supply", supplies[i].supply); - if (of_find_property(np, property, NULL) == NULL) + if (!of_property_present(np, property)) return false; } diff --git a/drivers/pci/controller/pcie-mediatek.c b/drivers/pci/controller/pcie-mediatek.c index ae5ad05ddc1d..31de7a29192c 100644 --- a/drivers/pci/controller/pcie-mediatek.c +++ b/drivers/pci/controller/pcie-mediatek.c @@ -643,7 +643,7 @@ static int mtk_pcie_setup_irq(struct mtk_pcie_port *port, return err; } - if (of_find_property(dev->of_node, "interrupt-names", NULL)) + if (of_property_present(dev->of_node, "interrupt-names")) port->irq = platform_get_irq_byname(pdev, "pcie_irq"); else port->irq = platform_get_irq(pdev, port->slot); diff --git a/drivers/pci/controller/pcie-mt7621.c b/drivers/pci/controller/pcie-mt7621.c index 63a5f4463a9f..a445ec314375 100644 --- a/drivers/pci/controller/pcie-mt7621.c +++ b/drivers/pci/controller/pcie-mt7621.c @@ -378,8 +378,8 @@ static int mt7621_pcie_init_ports(struct mt7621_pcie *pcie) u32 slot = port->slot; if (!mt7621_pcie_port_is_linkup(port)) { - dev_err(dev, "pcie%d no card, disable it (RST & CLK)\n", - slot); + dev_info(dev, "pcie%d no card, disable it (RST & CLK)\n", + slot); mt7621_control_assert(port); port->enabled = false; num_disabled++; diff --git a/drivers/pci/controller/pcie-rcar-host.c b/drivers/pci/controller/pcie-rcar-host.c index e4faf90feaf5..e80e56b2a842 100644 --- a/drivers/pci/controller/pcie-rcar-host.c +++ b/drivers/pci/controller/pcie-rcar-host.c @@ -219,9 +219,9 @@ static int rcar_pcie_config_access(struct rcar_pcie_host *host, /* Enable the configuration access */ if (pci_is_root_bus(bus->parent)) - rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR); + rcar_pci_write_reg(pcie, PCIECCTLR_CCIE | TYPE0, PCIECCTLR); else - rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR); + rcar_pci_write_reg(pcie, PCIECCTLR_CCIE | TYPE1, PCIECCTLR); /* Check for errors */ if (rcar_pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST) diff --git a/drivers/pci/controller/pcie-rcar.h b/drivers/pci/controller/pcie-rcar.h index 9bb125db85c6..6799f81392fc 100644 --- a/drivers/pci/controller/pcie-rcar.h +++ b/drivers/pci/controller/pcie-rcar.h @@ -11,7 +11,7 @@ #define PCIECAR 0x000010 #define PCIECCTLR 0x000018 -#define CONFIG_SEND_ENABLE BIT(31) +#define PCIECCTLR_CCIE BIT(31) #define TYPE0 (0 << 8) #define TYPE1 BIT(8) #define PCIECDR 0x000020 diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c index d17f3bf36f70..ad12515a4a12 100644 --- a/drivers/pci/hotplug/pciehp_pci.c +++ b/drivers/pci/hotplug/pciehp_pci.c @@ -63,7 +63,14 @@ int pciehp_configure_device(struct controller *ctrl) pci_assign_unassigned_bridge_resources(bridge); pcie_bus_configure_settings(parent); + + /* + * Release reset_lock during driver binding + * to avoid AB-BA deadlock with device_lock. + */ + up_read(&ctrl->reset_lock); pci_bus_add_devices(parent); + down_read_nested(&ctrl->reset_lock, ctrl->depth); out: pci_unlock_rescan_remove(); @@ -104,7 +111,15 @@ void pciehp_unconfigure_device(struct controller *ctrl, bool presence) list_for_each_entry_safe_reverse(dev, temp, &parent->devices, bus_list) { pci_dev_get(dev); + + /* + * Release reset_lock during driver unbinding + * to avoid AB-BA deadlock with device_lock. + */ + up_read(&ctrl->reset_lock); pci_stop_and_remove_bus_device(dev); + down_read_nested(&ctrl->reset_lock, ctrl->depth); + /* * Ensure that no new Requests will be generated from * the device. diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c index 491986197c47..2316de0fd198 100644 --- a/drivers/pci/hotplug/rpaphp_core.c +++ b/drivers/pci/hotplug/rpaphp_core.c @@ -278,7 +278,7 @@ int rpaphp_check_drc_props(struct device_node *dn, char *drc_name, return -EINVAL; } - if (of_find_property(dn->parent, "ibm,drc-info", NULL)) + if (of_property_present(dn->parent, "ibm,drc-info")) return rpaphp_check_drc_props_v2(dn, drc_name, drc_type, be32_to_cpu(*my_index)); else @@ -440,7 +440,7 @@ int rpaphp_add_slot(struct device_node *dn) if (!of_node_name_eq(dn, "pci")) return 0; - if (of_find_property(dn, "ibm,drc-info", NULL)) + if (of_property_present(dn, "ibm,drc-info")) return rpaphp_drc_info_add_slot(dn); else return rpaphp_drc_add_slot(dn); diff --git a/drivers/pci/hotplug/shpchp_sysfs.c b/drivers/pci/hotplug/shpchp_sysfs.c index 64beed7a26be..01d47a42da04 100644 --- a/drivers/pci/hotplug/shpchp_sysfs.c +++ b/drivers/pci/hotplug/shpchp_sysfs.c @@ -24,16 +24,16 @@ static ssize_t show_ctrl(struct device *dev, struct device_attribute *attr, char *buf) { struct pci_dev *pdev; - int index, busnr; struct resource *res; struct pci_bus *bus; size_t len = 0; + int busnr; pdev = to_pci_dev(dev); bus = pdev->subordinate; len += sysfs_emit_at(buf, len, "Free resources: memory\n"); - pci_bus_for_each_resource(bus, res, index) { + pci_bus_for_each_resource(bus, res) { if (res && (res->flags & IORESOURCE_MEM) && !(res->flags & IORESOURCE_PREFETCH)) { len += sysfs_emit_at(buf, len, @@ -43,7 +43,7 @@ static ssize_t show_ctrl(struct device *dev, struct device_attribute *attr, char } } len += sysfs_emit_at(buf, len, "Free resources: prefetchable memory\n"); - pci_bus_for_each_resource(bus, res, index) { + pci_bus_for_each_resource(bus, res) { if (res && (res->flags & IORESOURCE_MEM) && (res->flags & IORESOURCE_PREFETCH)) { len += sysfs_emit_at(buf, len, @@ -53,7 +53,7 @@ static ssize_t show_ctrl(struct device *dev, struct device_attribute *attr, char } } len += sysfs_emit_at(buf, len, "Free resources: IO\n"); - pci_bus_for_each_resource(bus, res, index) { + pci_bus_for_each_resource(bus, res) { if (res && (res->flags & IORESOURCE_IO)) { len += sysfs_emit_at(buf, len, "start = %8.8llx, length = %8.8llx\n", diff --git a/drivers/pci/of.c b/drivers/pci/of.c index 4c2ef2e28fb5..2c25f4fa0225 100644 --- a/drivers/pci/of.c +++ b/drivers/pci/of.c @@ -465,7 +465,7 @@ static int of_irq_parse_pci(const struct pci_dev *pdev, struct of_phandle_args * return -ENODEV; /* Local interrupt-map in the device node? Use it! */ - if (of_get_property(dn, "interrupt-map", NULL)) { + if (of_property_present(dn, "interrupt-map")) { pin = pci_swizzle_interrupt_pin(pdev, pin); ppnode = dn; } diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c index 9e8205572830..6cd98ffca198 100644 --- a/drivers/pci/p2pdma.c +++ b/drivers/pci/p2pdma.c @@ -746,8 +746,7 @@ EXPORT_SYMBOL_GPL(pci_has_p2pmem); /** * pci_p2pmem_find_many - find a peer-to-peer DMA memory device compatible with - * the specified list of clients and shortest distance (as determined - * by pci_p2pmem_dma()) + * the specified list of clients and shortest distance * @clients: array of devices to check (NULL-terminated) * @num_clients: number of client devices in the list * diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 57ddcc59af30..ae9baf801681 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -572,7 +572,8 @@ static void pci_pm_default_resume_early(struct pci_dev *pci_dev) static void pci_pm_bridge_power_up_actions(struct pci_dev *pci_dev) { - pci_bridge_wait_for_secondary_bus(pci_dev, "resume", PCI_RESET_WAIT); + pci_bridge_wait_for_secondary_bus(pci_dev, "resume"); + /* * When powering on a bridge from D3cold, the whole hierarchy may be * powered on into D0uninitialized state, resume them to give them a diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 7a67611dc5f4..199024beaee9 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -64,6 +64,14 @@ struct pci_pme_device { #define PME_TIMEOUT 1000 /* How long between PME checks */ +/* + * Devices may extend the 1 sec period through Request Retry Status + * completions (PCIe r6.0 sec 2.3.1). The spec does not provide an upper + * limit, but 60 sec ought to be enough for any device to become + * responsive. + */ +#define PCIE_RESET_READY_POLL_MS 60000 /* msec */ + static void pci_dev_d3_sleep(struct pci_dev *dev) { unsigned int delay_ms = max(dev->d3hot_delay, pci_pm_d3hot_delay); @@ -779,9 +787,8 @@ struct resource *pci_find_parent_resource(const struct pci_dev *dev, { const struct pci_bus *bus = dev->bus; struct resource *r; - int i; - pci_bus_for_each_resource(bus, r, i) { + pci_bus_for_each_resource(bus, r) { if (!r) continue; if (resource_contains(r, res)) { @@ -4939,7 +4946,6 @@ static int pci_bus_max_d3cold_delay(const struct pci_bus *bus) * pci_bridge_wait_for_secondary_bus - Wait for secondary bus to be accessible * @dev: PCI bridge * @reset_type: reset type in human-readable form - * @timeout: maximum time to wait for devices on secondary bus (milliseconds) * * Handle necessary delays before access to the devices on the secondary * side of the bridge are permitted after D3cold to D0 transition @@ -4952,8 +4958,7 @@ static int pci_bus_max_d3cold_delay(const struct pci_bus *bus) * Return 0 on success or -ENOTTY if the first device on the secondary bus * failed to become accessible. */ -int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type, - int timeout) +int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type) { struct pci_dev *child; int delay; @@ -5031,7 +5036,8 @@ int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type, } } - return pci_dev_wait(child, reset_type, timeout - delay); + return pci_dev_wait(child, reset_type, + PCIE_RESET_READY_POLL_MS - delay); } void pci_reset_secondary_bus(struct pci_dev *dev) @@ -5068,8 +5074,7 @@ int pci_bridge_secondary_bus_reset(struct pci_dev *dev) { pcibios_reset_secondary_bus(dev); - return pci_bridge_wait_for_secondary_bus(dev, "bus reset", - PCIE_RESET_READY_POLL_MS); + return pci_bridge_wait_for_secondary_bus(dev, "bus reset"); } EXPORT_SYMBOL_GPL(pci_bridge_secondary_bus_reset); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 2b48a0aa8008..67005a0ee381 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -70,12 +70,6 @@ struct pci_cap_saved_state *pci_find_saved_ext_cap(struct pci_dev *dev, * Reset (PCIe r6.0 sec 5.8). */ #define PCI_RESET_WAIT 1000 /* msec */ -/* - * Devices may extend the 1 sec period through Request Retry Status completions - * (PCIe r6.0 sec 2.3.1). The spec does not provide an upper limit, but 60 sec - * ought to be enough for any device to become responsive. - */ -#define PCIE_RESET_READY_POLL_MS 60000 /* msec */ void pci_update_current_state(struct pci_dev *dev, pci_power_t state); void pci_refresh_power_state(struct pci_dev *dev); @@ -100,8 +94,7 @@ void pci_msix_init(struct pci_dev *dev); bool pci_bridge_d3_possible(struct pci_dev *dev); void pci_bridge_d3_update(struct pci_dev *dev); void pci_bridge_reconfigure_ltr(struct pci_dev *dev); -int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type, - int timeout); +int pci_bridge_wait_for_secondary_bus(struct pci_dev *dev, char *reset_type); static inline void pci_wakeup_event(struct pci_dev *dev) { diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index a5d7c69b764e..3ceed8e3de41 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c @@ -170,8 +170,7 @@ pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, PCI_EXP_DPC_STATUS_TRIGGER); - if (pci_bridge_wait_for_secondary_bus(pdev, "DPC", - PCIE_RESET_READY_POLL_MS)) { + if (pci_bridge_wait_for_secondary_bus(pdev, "DPC")) { clear_bit(PCI_DPC_RECOVERED, &pdev->priv_flags); ret = PCI_ERS_RESULT_DISCONNECT; } else { diff --git a/drivers/pci/pcie/edr.c b/drivers/pci/pcie/edr.c index a6b9b479b97a..5f4914d313a1 100644 --- a/drivers/pci/pcie/edr.c +++ b/drivers/pci/pcie/edr.c @@ -151,9 +151,18 @@ static void edr_handle_event(acpi_handle handle, u32 event, void *data) if (event != ACPI_NOTIFY_DISCONNECT_RECOVER) return; + /* + * pdev is a Root Port or Downstream Port that is still present and + * has triggered a containment event, e.g., DPC, so its child + * devices have been disconnected (ACPI r6.5, sec 5.6.6). + */ pci_info(pdev, "EDR event received\n"); - /* Locate the port which issued EDR event */ + /* + * Locate the port that experienced the containment event. pdev + * may be that port or a parent of it (PCI Firmware r3.3, sec + * 4.6.13). + */ edev = acpi_dpc_port_get(pdev); if (!edev) { pci_err(pdev, "Firmware failed to locate DPC port\n"); @@ -193,6 +202,7 @@ send_ost: */ if (estate == PCI_ERS_RESULT_RECOVERED) { pci_dbg(edev, "DPC port successfully recovered\n"); + pcie_clear_device_status(edev); acpi_send_edr_status(pdev, edev, EDR_OST_SUCCESS); } else { pci_dbg(edev, "DPC port recovery failed\n"); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index f96fa83f2627..9123bafab451 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -533,7 +533,7 @@ void pci_read_bridge_bases(struct pci_bus *child) pci_read_bridge_mmio_pref(child); if (dev->transparent) { - pci_bus_for_each_resource(child->parent, res, i) { + pci_bus_for_each_resource(child->parent, res) { if (res && res->flags) { pci_bus_add_resource(child, res, PCI_SUBTRACTIVE_DECODE); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 44cab813bf95..f4e2a88729fd 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1940,6 +1940,19 @@ static void quirk_radeon_pm(struct pci_dev *dev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x6741, quirk_radeon_pm); /* + * NVIDIA Ampere-based HDA controllers can wedge the whole device if a bus + * reset is performed too soon after transition to D0, extend d3hot_delay + * to previous effective default for all NVIDIA HDA controllers. + */ +static void quirk_nvidia_hda_pm(struct pci_dev *dev) +{ + quirk_d3hot_delay(dev, 20); +} +DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, + PCI_CLASS_MULTIMEDIA_HD_AUDIO, 8, + quirk_nvidia_hda_pm); + +/* * Ryzen5/7 XHCI controllers fail upon resume from runtime suspend or s2idle. * https://bugzilla.kernel.org/show_bug.cgi?id=205587 * diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index 22d39e12b236..30a787d45d2e 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -5,10 +5,9 @@ static void pci_free_resources(struct pci_dev *dev) { - int i; + struct resource *res; - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *res = dev->resource + i; + pci_dev_for_each_resource(dev, res) { if (res->parent) release_resource(res); } diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index c690572b10ce..fdeb121e9175 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -124,20 +124,17 @@ static resource_size_t get_res_add_align(struct list_head *head, return dev_res ? dev_res->min_align : 0; } - /* Sort resources by alignment */ static void pdev_sort_resources(struct pci_dev *dev, struct list_head *head) { + struct resource *r; int i; - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *r; + pci_dev_for_each_resource(dev, r, i) { struct pci_dev_resource *dev_res, *tmp; resource_size_t r_align; struct list_head *n; - r = &dev->resource[i]; - if (r->flags & IORESOURCE_PCI_FIXED) continue; @@ -773,9 +770,8 @@ static struct resource *find_bus_resource_of_type(struct pci_bus *bus, unsigned long type) { struct resource *r, *r_assigned = NULL; - int i; - pci_bus_for_each_resource(bus, r, i) { + pci_bus_for_each_resource(bus, r) { if (r == &ioport_resource || r == &iomem_resource) continue; if (r && (r->flags & type_mask) == type && !r->parent) @@ -895,10 +891,9 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, min_align = window_alignment(bus, IORESOURCE_IO); list_for_each_entry(dev, &bus->devices, bus_list) { - int i; + struct resource *r; - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *r = &dev->resource[i]; + pci_dev_for_each_resource(dev, r) { unsigned long r_size; if (r->parent || !(r->flags & IORESOURCE_IO)) @@ -1014,10 +1009,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, size = 0; list_for_each_entry(dev, &bus->devices, bus_list) { + struct resource *r; int i; - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *r = &dev->resource[i]; + pci_dev_for_each_resource(dev, r, i) { resource_size_t r_size; if (r->parent || (r->flags & IORESOURCE_PCI_FIXED) || @@ -1208,7 +1203,7 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head) additional_mmio_pref_size = 0; struct resource *pref; struct pci_host_bridge *host; - int hdr_type, i, ret; + int hdr_type, ret; list_for_each_entry(dev, &bus->devices, bus_list) { struct pci_bus *b = dev->subordinate; @@ -1232,7 +1227,7 @@ void __pci_bus_size_bridges(struct pci_bus *bus, struct list_head *realloc_head) host = to_pci_host_bridge(bus->bridge); if (!host->size_windows) return; - pci_bus_for_each_resource(bus, pref, i) + pci_bus_for_each_resource(bus, pref) if (pref && (pref->flags & IORESOURCE_PREFETCH)) break; hdr_type = -1; /* Intentionally invalid - not a PCI device. */ @@ -1337,12 +1332,11 @@ EXPORT_SYMBOL(pci_bus_size_bridges); static void assign_fixed_resource_on_bus(struct pci_bus *b, struct resource *r) { - int i; struct resource *parent_r; unsigned long mask = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH; - pci_bus_for_each_resource(b, parent_r, i) { + pci_bus_for_each_resource(b, parent_r) { if (!parent_r) continue; @@ -1358,11 +1352,10 @@ static void assign_fixed_resource_on_bus(struct pci_bus *b, struct resource *r) */ static void pdev_assign_fixed_resources(struct pci_dev *dev) { - int i; + struct resource *r; - for (i = 0; i < PCI_NUM_RESOURCES; i++) { + pci_dev_for_each_resource(dev, r) { struct pci_bus *b; - struct resource *r = &dev->resource[i]; if (r->parent || !(r->flags & IORESOURCE_PCI_FIXED) || !(r->flags & (IORESOURCE_IO | IORESOURCE_MEM))) @@ -1795,11 +1788,9 @@ static void remove_dev_resources(struct pci_dev *dev, struct resource *io, struct resource *mmio, struct resource *mmio_pref) { - int i; - - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource *res = &dev->resource[i]; + struct resource *res; + pci_dev_for_each_resource(dev, res) { if (resource_type(res) == IORESOURCE_IO) { remove_dev_resource(io, dev, res); } else if (resource_type(res) == IORESOURCE_MEM) { diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index b492e67c3d87..967f9a758923 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -484,12 +484,10 @@ int pci_enable_resources(struct pci_dev *dev, int mask) pci_read_config_word(dev, PCI_COMMAND, &cmd); old_cmd = cmd; - for (i = 0; i < PCI_NUM_RESOURCES; i++) { + pci_dev_for_each_resource(dev, r, i) { if (!(mask & (1 << i))) continue; - r = &dev->resource[i]; - if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM))) continue; if ((i == PCI_ROM_RESOURCE) && diff --git a/drivers/pci/vgaarb.c b/drivers/pci/vgaarb.c index f80b6ec88dc3..5a696078b382 100644 --- a/drivers/pci/vgaarb.c +++ b/drivers/pci/vgaarb.c @@ -548,10 +548,8 @@ static bool vga_is_firmware_default(struct pci_dev *pdev) #if defined(CONFIG_X86) || defined(CONFIG_IA64) u64 base = screen_info.lfb_base; u64 size = screen_info.lfb_size; + struct resource *r; u64 limit; - resource_size_t start, end; - unsigned long flags; - int i; /* Select the device owning the boot framebuffer if there is one */ @@ -561,19 +559,14 @@ static bool vga_is_firmware_default(struct pci_dev *pdev) limit = base + size; /* Does firmware framebuffer belong to us? */ - for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { - flags = pci_resource_flags(pdev, i); - - if ((flags & IORESOURCE_MEM) == 0) + pci_dev_for_each_resource(pdev, r) { + if (resource_type(r) != IORESOURCE_MEM) continue; - start = pci_resource_start(pdev, i); - end = pci_resource_end(pdev, i); - - if (!start || !end) + if (!r->start || !r->end) continue; - if (base < start || limit >= end) + if (base < r->start || limit >= r->end) continue; return true; diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index fcd029ca2eb1..83c0ab50676d 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c @@ -390,9 +390,7 @@ static int pcifront_claim_resource(struct pci_dev *dev, void *data) int i; struct resource *r; - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - r = &dev->resource[i]; - + pci_dev_for_each_resource(dev, r, i) { if (!r->parent && r->start && r->flags) { dev_info(&pdev->xdev->dev, "claiming resource %s/%d\n", pci_name(dev), i); |