summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clang-format1
-rw-r--r--Documentation/devicetree/bindings/pci/amlogic,axg-pcie.yaml134
-rw-r--r--Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt70
-rw-r--r--Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-common.yaml279
-rw-r--r--Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-ep.yaml85
-rw-r--r--Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml240
-rw-r--r--Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml2
-rw-r--r--Documentation/devicetree/bindings/pci/qcom,pcie.yaml91
-rw-r--r--MAINTAINERS2
-rw-r--r--arch/alpha/kernel/pci.c5
-rw-r--r--arch/arm/kernel/bios32.c16
-rw-r--r--arch/arm/mach-dove/pcie.c10
-rw-r--r--arch/arm/mach-mv78xx0/pcie.c10
-rw-r--r--arch/arm/mach-orion5x/pci.c10
-rw-r--r--arch/mips/pci/ops-bcm63xx.c8
-rw-r--r--arch/mips/pci/pci-legacy.c3
-rw-r--r--arch/powerpc/kernel/pci-common.c21
-rw-r--r--arch/powerpc/platforms/4xx/pci.c8
-rw-r--r--arch/powerpc/platforms/52xx/mpc52xx_pci.c5
-rw-r--r--arch/powerpc/platforms/pseries/pci.c16
-rw-r--r--arch/sh/drivers/pci/pcie-sh7786.c10
-rw-r--r--arch/sparc/kernel/leon_pci.c5
-rw-r--r--arch/sparc/kernel/pci.c10
-rw-r--r--arch/sparc/kernel/pcic.c5
-rw-r--r--arch/x86/pci/fixup.c59
-rw-r--r--drivers/eisa/pci_eisa.c4
-rw-r--r--drivers/firmware/efi/cper-arm.c1
-rw-r--r--drivers/pci/bus.c7
-rw-r--r--drivers/pci/controller/Kconfig423
-rw-r--r--drivers/pci/controller/cadence/Kconfig10
-rw-r--r--drivers/pci/controller/dwc/Kconfig431
-rw-r--r--drivers/pci/controller/dwc/pci-imx6.c7
-rw-r--r--drivers/pci/controller/dwc/pci-layerscape-ep.c1
-rw-r--r--drivers/pci/controller/dwc/pcie-qcom.c1246
-rw-r--r--drivers/pci/controller/mobiveil/Kconfig19
-rw-r--r--drivers/pci/controller/pci-ixp4xx.c10
-rw-r--r--drivers/pci/controller/pci-tegra.c4
-rw-r--r--drivers/pci/controller/pcie-mediatek.c2
-rw-r--r--drivers/pci/controller/pcie-mt7621.c4
-rw-r--r--drivers/pci/controller/pcie-rcar-host.c4
-rw-r--r--drivers/pci/controller/pcie-rcar.h2
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c15
-rw-r--r--drivers/pci/hotplug/rpaphp_core.c4
-rw-r--r--drivers/pci/hotplug/shpchp_sysfs.c8
-rw-r--r--drivers/pci/of.c2
-rw-r--r--drivers/pci/p2pdma.c3
-rw-r--r--drivers/pci/pci-driver.c3
-rw-r--r--drivers/pci/pci.c21
-rw-r--r--drivers/pci/pci.h9
-rw-r--r--drivers/pci/pcie/dpc.c3
-rw-r--r--drivers/pci/pcie/edr.c12
-rw-r--r--drivers/pci/probe.c2
-rw-r--r--drivers/pci/quirks.c13
-rw-r--r--drivers/pci/remove.c5
-rw-r--r--drivers/pci/setup-bus.c37
-rw-r--r--drivers/pci/setup-res.c4
-rw-r--r--drivers/pci/vgaarb.c17
-rw-r--r--drivers/pci/xen-pcifront.c4
-rw-r--r--drivers/pnp/quirks.c29
-rw-r--r--include/linux/pci.h71
60 files changed, 1860 insertions, 1682 deletions
diff --git a/.clang-format b/.clang-format
index d988e9fa9b26..2048b0296d76 100644
--- a/.clang-format
+++ b/.clang-format
@@ -520,6 +520,7 @@ ForEachMacros:
- 'of_property_for_each_string'
- 'of_property_for_each_u32'
- 'pci_bus_for_each_resource'
+ - 'pci_dev_for_each_resource'
- 'pci_doe_for_each_off'
- 'pcl_for_each_chunk'
- 'pcl_for_each_segment'
diff --git a/Documentation/devicetree/bindings/pci/amlogic,axg-pcie.yaml b/Documentation/devicetree/bindings/pci/amlogic,axg-pcie.yaml
new file mode 100644
index 000000000000..a5bd90bc0712
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/amlogic,axg-pcie.yaml
@@ -0,0 +1,134 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/amlogic,axg-pcie.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic Meson AXG DWC PCIe SoC controller
+
+maintainers:
+ - Neil Armstrong <neil.armstrong@linaro.org>
+
+description:
+ Amlogic Meson PCIe host controller is based on the Synopsys DesignWare PCI core.
+
+allOf:
+ - $ref: /schemas/pci/pci-bus.yaml#
+ - $ref: /schemas/pci/snps,dw-pcie-common.yaml#
+
+# We need a select here so we don't match all nodes with 'snps,dw-pcie'
+select:
+ properties:
+ compatible:
+ enum:
+ - amlogic,axg-pcie
+ - amlogic,g12a-pcie
+ required:
+ - compatible
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - amlogic,axg-pcie
+ - amlogic,g12a-pcie
+ - const: snps,dw-pcie
+
+ reg:
+ items:
+ - description: External local bus interface registers
+ - description: Meson designed configuration registers
+ - description: PCIe configuration space
+
+ reg-names:
+ items:
+ - const: elbi
+ - const: cfg
+ - const: config
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: PCIe GEN 100M PLL clock
+ - description: PCIe RC clock gate
+ - description: PCIe PHY clock
+
+ clock-names:
+ items:
+ - const: pclk
+ - const: port
+ - const: general
+
+ phys:
+ maxItems: 1
+
+ phy-names:
+ const: pcie
+
+ resets:
+ items:
+ - description: Port Reset
+ - description: Shared APB reset
+
+ reset-names:
+ items:
+ - const: port
+ - const: apb
+
+ num-lanes:
+ const: 1
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - interrupts
+ - clock
+ - clock-names
+ - "#address-cells"
+ - "#size-cells"
+ - "#interrupt-cells"
+ - interrupt-map
+ - interrupt-map-mask
+ - ranges
+ - bus-range
+ - device_type
+ - num-lanes
+ - phys
+ - phy-names
+ - resets
+ - reset-names
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ pcie: pcie@f9800000 {
+ compatible = "amlogic,axg-pcie", "snps,dw-pcie";
+ reg = <0xf9800000 0x400000>, <0xff646000 0x2000>, <0xf9f00000 0x100000>;
+ reg-names = "elbi", "cfg", "config";
+ interrupts = <GIC_SPI 177 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&pclk>, <&clk_port>, <&clk_phy>;
+ clock-names = "pclk", "port", "general";
+ resets = <&reset_pcie_port>, <&reset_pcie_apb>;
+ reset-names = "port", "apb";
+ phys = <&pcie_phy>;
+ phy-names = "pcie";
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0>;
+ interrupt-map = <0 0 0 0 &gic GIC_SPI 179 IRQ_TYPE_EDGE_RISING>;
+ bus-range = <0x0 0xff>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+ num-lanes = <1>;
+ ranges = <0x82000000 0 0 0xf9c00000 0 0x00300000>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt b/Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt
deleted file mode 100644
index c3a75ac6e59d..000000000000
--- a/Documentation/devicetree/bindings/pci/amlogic,meson-pcie.txt
+++ /dev/null
@@ -1,70 +0,0 @@
-Amlogic Meson AXG DWC PCIE SoC controller
-
-Amlogic Meson PCIe host controller is based on the Synopsys DesignWare PCI core.
-It shares common functions with the PCIe DesignWare core driver and
-inherits common properties defined in
-Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml.
-
-Additional properties are described here:
-
-Required properties:
-- compatible:
- should contain :
- - "amlogic,axg-pcie" for AXG SoC Family
- - "amlogic,g12a-pcie" for G12A SoC Family
- to identify the core.
-- reg:
- should contain the configuration address space.
-- reg-names: Must be
- - "elbi" External local bus interface registers
- - "cfg" Meson specific registers
- - "config" PCIe configuration space
-- reset-gpios: The GPIO to generate PCIe PERST# assert and deassert signal.
-- clocks: Must contain an entry for each entry in clock-names.
-- clock-names: Must include the following entries:
- - "pclk" PCIe GEN 100M PLL clock
- - "port" PCIe_x(A or B) RC clock gate
- - "general" PCIe Phy clock
-- resets: phandle to the reset lines.
-- reset-names: must contain "port" and "apb"
- - "port" Port A or B reset
- - "apb" Share APB reset
-- phys: should contain a phandle to the PCIE phy
-- phy-names: must contain "pcie"
-
-- device_type:
- should be "pci". As specified in snps,dw-pcie.yaml
-
-
-Example configuration:
-
- pcie: pcie@f9800000 {
- compatible = "amlogic,axg-pcie", "snps,dw-pcie";
- reg = <0x0 0xf9800000 0x0 0x400000
- 0x0 0xff646000 0x0 0x2000
- 0x0 0xf9f00000 0x0 0x100000>;
- reg-names = "elbi", "cfg", "config";
- reset-gpios = <&gpio GPIOX_19 GPIO_ACTIVE_HIGH>;
- interrupts = <GIC_SPI 177 IRQ_TYPE_EDGE_RISING>;
- #interrupt-cells = <1>;
- interrupt-map-mask = <0 0 0 0>;
- interrupt-map = <0 0 0 0 &gic GIC_SPI 179 IRQ_TYPE_EDGE_RISING>;
- bus-range = <0x0 0xff>;
- #address-cells = <3>;
- #size-cells = <2>;
- device_type = "pci";
- ranges = <0x82000000 0 0 0x0 0xf9c00000 0 0x00300000>;
-
- clocks = <&clkc CLKID_USB
- &clkc CLKID_PCIE_A
- &clkc CLKID_PCIE_CML_EN0>;
- clock-names = "general",
- "pclk",
- "port";
- resets = <&reset RESET_PCIE_A>,
- <&reset RESET_PCIE_APB>;
- reset-names = "port",
- "apb";
- phys = <&pcie_phy>;
- phy-names = "pcie";
- };
diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-common.yaml b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-common.yaml
new file mode 100644
index 000000000000..9bff8ecb653c
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-common.yaml
@@ -0,0 +1,279 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/fsl,imx6q-pcie-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX6 PCIe RC/EP controller
+
+maintainers:
+ - Lucas Stach <l.stach@pengutronix.de>
+ - Richard Zhu <hongxing.zhu@nxp.com>
+
+description:
+ Generic Freescale i.MX PCIe Root Port and Endpoint controller
+ properties.
+
+properties:
+ clocks:
+ minItems: 3
+ items:
+ - description: PCIe bridge clock.
+ - description: PCIe bus clock.
+ - description: PCIe PHY clock.
+ - description: Additional required clock entry for imx6sx-pcie,
+ imx6sx-pcie-ep, imx8mq-pcie, imx8mq-pcie-ep.
+
+ clock-names:
+ minItems: 3
+ items:
+ - const: pcie
+ - const: pcie_bus
+ - enum: [ pcie_phy, pcie_aux ]
+ - enum: [ pcie_inbound_axi, pcie_aux ]
+
+ num-lanes:
+ const: 1
+
+ fsl,imx7d-pcie-phy:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: A phandle to an fsl,imx7d-pcie-phy node. Additional
+ required properties for imx7d-pcie, imx7d-pcie-ep, imx8mq-pcie,
+ and imx8mq-pcie-ep.
+
+ power-domains:
+ minItems: 1
+ items:
+ - description: The phandle pointing to the DISPLAY domain for
+ imx6sx-pcie, imx6sx-pcie-ep, to PCIE_PHY power domain for
+ imx7d-pcie, imx7d-pcie-ep, imx8mq-pcie and imx8mq-pcie-ep.
+ - description: The phandle pointing to the PCIE_PHY power domains
+ for imx6sx-pcie and imx6sx-pcie-ep.
+
+ power-domain-names:
+ minItems: 1
+ items:
+ - const: pcie
+ - const: pcie_phy
+
+ resets:
+ minItems: 2
+ maxItems: 3
+ description: Phandles to PCIe-related reset lines exposed by SRC
+ IP block. Additional required by imx7d-pcie, imx7d-pcie-ep,
+ imx8mq-pcie, and imx8mq-pcie-ep.
+
+ reset-names:
+ minItems: 2
+ maxItems: 3
+
+ fsl,tx-deemph-gen1:
+ description: Gen1 De-emphasis value (optional required).
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0
+
+ fsl,tx-deemph-gen2-3p5db:
+ description: Gen2 (3.5db) De-emphasis value (optional required).
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 0
+
+ fsl,tx-deemph-gen2-6db:
+ description: Gen2 (6db) De-emphasis value (optional required).
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 20
+
+ fsl,tx-swing-full:
+ description: Gen2 TX SWING FULL value (optional required).
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 127
+
+ fsl,tx-swing-low:
+ description: TX launch amplitude swing_low value (optional required).
+ $ref: /schemas/types.yaml#/definitions/uint32
+ default: 127
+
+ fsl,max-link-speed:
+ description: Specify PCI Gen for link capability (optional required).
+ Note that the IMX6 LVDS clock outputs do not meet gen2 jitter
+ requirements and thus for gen2 capability a gen2 compliant clock
+ generator should be used and configured.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [1, 2, 3, 4]
+ default: 1
+
+ phys:
+ maxItems: 1
+
+ phy-names:
+ const: pcie-phy
+
+ vpcie-supply:
+ description: Should specify the regulator in charge of PCIe port power.
+ The regulator will be enabled when initializing the PCIe host and
+ disabled either as part of the init process or when shutting down
+ the host (optional required).
+
+ vph-supply:
+ description: Should specify the regulator in charge of VPH one of
+ the three PCIe PHY powers. This regulator can be supplied by both
+ 1.8v and 3.3v voltage supplies (optional required).
+
+required:
+ - clocks
+ - clock-names
+ - num-lanes
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx6sx-pcie
+ - fsl,imx6sx-pcie-ep
+ then:
+ properties:
+ clock-names:
+ items:
+ - {}
+ - {}
+ - const: pcie_phy
+ - const: pcie_inbound_axi
+ power-domains:
+ minItems: 2
+ power-domain-names:
+ minItems: 2
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx8mq-pcie
+ - fsl,imx8mq-pcie-ep
+ then:
+ properties:
+ clock-names:
+ items:
+ - {}
+ - {}
+ - const: pcie_phy
+ - const: pcie_aux
+ - if:
+ properties:
+ compatible:
+ not:
+ contains:
+ enum:
+ - fsl,imx6sx-pcie
+ - fsl,imx8mq-pcie
+ - fsl,imx6sx-pcie-ep
+ - fsl,imx8mq-pcie-ep
+ then:
+ properties:
+ clocks:
+ maxItems: 3
+ clock-names:
+ maxItems: 3
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx6q-pcie
+ - fsl,imx6qp-pcie
+ - fsl,imx7d-pcie
+ - fsl,imx6q-pcie-ep
+ - fsl,imx6qp-pcie-ep
+ - fsl,imx7d-pcie-ep
+ then:
+ properties:
+ clock-names:
+ maxItems: 3
+ contains:
+ const: pcie_phy
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx8mm-pcie
+ - fsl,imx8mp-pcie
+ - fsl,imx8mm-pcie-ep
+ - fsl,imx8mp-pcie-ep
+ then:
+ properties:
+ clock-names:
+ maxItems: 3
+ contains:
+ const: pcie_aux
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx6q-pcie
+ - fsl,imx6qp-pcie
+ - fsl,imx6q-pcie-ep
+ - fsl,imx6qp-pcie-ep
+ then:
+ properties:
+ power-domains: false
+ power-domain-names: false
+
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx6sx-pcie
+ - fsl,imx6q-pcie
+ - fsl,imx6qp-pcie
+ - fsl,imx6sx-pcie-ep
+ - fsl,imx6q-pcie-ep
+ - fsl,imx6qp-pcie-ep
+ then:
+ properties:
+ power-domains:
+ maxItems: 1
+ power-domain-names: false
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx6q-pcie
+ - fsl,imx6sx-pcie
+ - fsl,imx6qp-pcie
+ - fsl,imx7d-pcie
+ - fsl,imx8mq-pcie
+ - fsl,imx6q-pcie-ep
+ - fsl,imx6sx-pcie-ep
+ - fsl,imx6qp-pcie-ep
+ - fsl,imx7d-pcie-ep
+ - fsl,imx8mq-pcie-ep
+ then:
+ properties:
+ resets:
+ minItems: 3
+ reset-names:
+ items:
+ - const: pciephy
+ - const: apps
+ - const: turnoff
+ else:
+ properties:
+ resets:
+ maxItems: 2
+ reset-names:
+ items:
+ - const: apps
+ - const: turnoff
+
+additionalProperties: true
+
+...
diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-ep.yaml b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-ep.yaml
new file mode 100644
index 000000000000..f4a328ec1daa
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-ep.yaml
@@ -0,0 +1,85 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/fsl,imx6q-pcie-ep.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX6 PCIe Endpoint controller
+
+maintainers:
+ - Lucas Stach <l.stach@pengutronix.de>
+ - Richard Zhu <hongxing.zhu@nxp.com>
+
+description: |+
+ This PCIe controller is based on the Synopsys DesignWare PCIe IP and
+ thus inherits all the common properties defined in snps,dw-pcie-ep.yaml.
+ The controller instances are dual mode where in they can work either in
+ Root Port mode or Endpoint mode but one at a time.
+
+properties:
+ compatible:
+ enum:
+ - fsl,imx8mm-pcie-ep
+ - fsl,imx8mq-pcie-ep
+ - fsl,imx8mp-pcie-ep
+
+ reg:
+ minItems: 2
+
+ reg-names:
+ items:
+ - const: dbi
+ - const: addr_space
+
+ interrupts:
+ items:
+ - description: builtin eDMA interrupter.
+
+ interrupt-names:
+ items:
+ - const: dma
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - interrupts
+ - interrupt-names
+
+allOf:
+ - $ref: /schemas/pci/snps,dw-pcie-ep.yaml#
+ - $ref: /schemas/pci/fsl,imx6q-pcie-common.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/imx8mp-clock.h>
+ #include <dt-bindings/power/imx8mp-power.h>
+ #include <dt-bindings/reset/imx8mp-reset.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ pcie_ep: pcie-ep@33800000 {
+ compatible = "fsl,imx8mp-pcie-ep";
+ reg = <0x33800000 0x000400000>, <0x18000000 0x08000000>;
+ reg-names = "dbi", "addr_space";
+ clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
+ <&clk IMX8MP_CLK_HSIO_AXI>,
+ <&clk IMX8MP_CLK_PCIE_ROOT>;
+ clock-names = "pcie", "pcie_bus", "pcie_aux";
+ assigned-clocks = <&clk IMX8MP_CLK_PCIE_AUX>;
+ assigned-clock-rates = <10000000>;
+ assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_50M>;
+ num-lanes = <1>;
+ interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>; /* eDMA */
+ interrupt-names = "dma";
+ fsl,max-link-speed = <3>;
+ power-domains = <&hsio_blk_ctrl IMX8MP_HSIOBLK_PD_PCIE>;
+ resets = <&src IMX8MP_RESET_PCIE_CTRL_APPS_EN>,
+ <&src IMX8MP_RESET_PCIE_CTRL_APPS_TURNOFF>;
+ reset-names = "apps", "turnoff";
+ phys = <&pcie_phy>;
+ phy-names = "pcie-phy";
+ num-ib-windows = <4>;
+ num-ob-windows = <4>;
+ };
diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
index f13f87fddb3d..2443641754d3 100644
--- a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
@@ -13,6 +13,11 @@ maintainers:
description: |+
This PCIe host controller is based on the Synopsys DesignWare PCIe IP
and thus inherits all the common properties defined in snps,dw-pcie.yaml.
+ The controller instances are dual mode where in they can work either in
+ Root Port mode or Endpoint mode but one at a time.
+
+ See fsl,imx6q-pcie-ep.yaml for details on the Endpoint mode device tree
+ bindings.
properties:
compatible:
@@ -24,9 +29,6 @@ properties:
- fsl,imx8mq-pcie
- fsl,imx8mm-pcie
- fsl,imx8mp-pcie
- - fsl,imx8mm-pcie-ep
- - fsl,imx8mq-pcie-ep
- - fsl,imx8mp-pcie-ep
reg:
items:
@@ -46,96 +48,6 @@ properties:
items:
- const: msi
- clocks:
- minItems: 3
- items:
- - description: PCIe bridge clock.
- - description: PCIe bus clock.
- - description: PCIe PHY clock.
- - description: Additional required clock entry for imx6sx-pcie,
- imx8mq-pcie.
-
- clock-names:
- minItems: 3
- items:
- - const: pcie
- - const: pcie_bus
- - enum: [ pcie_phy, pcie_aux ]
- - enum: [ pcie_inbound_axi, pcie_aux ]
-
- num-lanes:
- const: 1
-
- fsl,imx7d-pcie-phy:
- $ref: /schemas/types.yaml#/definitions/phandle
- description: A phandle to an fsl,imx7d-pcie-phy node. Additional
- required properties for imx7d-pcie and imx8mq-pcie.
-
- power-domains:
- minItems: 1
- items:
- - description: The phandle pointing to the DISPLAY domain for
- imx6sx-pcie, to PCIE_PHY power domain for imx7d-pcie and
- imx8mq-pcie.
- - description: The phandle pointing to the PCIE_PHY power domains
- for imx6sx-pcie.
-
- power-domain-names:
- minItems: 1
- items:
- - const: pcie
- - const: pcie_phy
-
- resets:
- minItems: 2
- maxItems: 3
- description: Phandles to PCIe-related reset lines exposed by SRC
- IP block. Additional required by imx7d-pcie and imx8mq-pcie.
-
- reset-names:
- minItems: 2
- maxItems: 3
-
- fsl,tx-deemph-gen1:
- description: Gen1 De-emphasis value (optional required).
- $ref: /schemas/types.yaml#/definitions/uint32
- default: 0
-
- fsl,tx-deemph-gen2-3p5db:
- description: Gen2 (3.5db) De-emphasis value (optional required).
- $ref: /schemas/types.yaml#/definitions/uint32
- default: 0
-
- fsl,tx-deemph-gen2-6db:
- description: Gen2 (6db) De-emphasis value (optional required).
- $ref: /schemas/types.yaml#/definitions/uint32
- default: 20
-
- fsl,tx-swing-full:
- description: Gen2 TX SWING FULL value (optional required).
- $ref: /schemas/types.yaml#/definitions/uint32
- default: 127
-
- fsl,tx-swing-low:
- description: TX launch amplitude swing_low value (optional required).
- $ref: /schemas/types.yaml#/definitions/uint32
- default: 127
-
- fsl,max-link-speed:
- description: Specify PCI Gen for link capability (optional required).
- Note that the IMX6 LVDS clock outputs do not meet gen2 jitter
- requirements and thus for gen2 capability a gen2 compliant clock
- generator should be used and configured.
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [1, 2, 3, 4]
- default: 1
-
- phys:
- maxItems: 1
-
- phy-names:
- const: pcie-phy
-
reset-gpio:
description: Should specify the GPIO for controlling the PCI bus device
reset signal. It's not polarity aware and defaults to active-low reset
@@ -147,17 +59,6 @@ properties:
L=operation state) (optional required).
type: boolean
- vpcie-supply:
- description: Should specify the regulator in charge of PCIe port power.
- The regulator will be enabled when initializing the PCIe host and
- disabled either as part of the init process or when shutting down
- the host (optional required).
-
- vph-supply:
- description: Should specify the regulator in charge of VPH one of
- the three PCIe PHY powers. This regulator can be supplied by both
- 1.8v and 3.3v voltage supplies (optional required).
-
required:
- compatible
- reg
@@ -167,144 +68,15 @@ required:
- device_type
- bus-range
- ranges
- - num-lanes
- interrupts
- interrupt-names
- "#interrupt-cells"
- interrupt-map-mask
- interrupt-map
- - clocks
- - clock-names
allOf:
- $ref: /schemas/pci/snps,dw-pcie.yaml#
- - if:
- properties:
- compatible:
- contains:
- const: fsl,imx6sx-pcie
- then:
- properties:
- clock-names:
- items:
- - {}
- - {}
- - const: pcie_phy
- - const: pcie_inbound_axi
- power-domains:
- minItems: 2
- power-domain-names:
- minItems: 2
- - if:
- properties:
- compatible:
- contains:
- const: fsl,imx8mq-pcie
- then:
- properties:
- clock-names:
- items:
- - {}
- - {}
- - const: pcie_phy
- - const: pcie_aux
- - if:
- properties:
- compatible:
- not:
- contains:
- enum:
- - fsl,imx6sx-pcie
- - fsl,imx8mq-pcie
- then:
- properties:
- clocks:
- maxItems: 3
- clock-names:
- maxItems: 3
-
- - if:
- properties:
- compatible:
- contains:
- enum:
- - fsl,imx6q-pcie
- - fsl,imx6qp-pcie
- - fsl,imx7d-pcie
- then:
- properties:
- clock-names:
- maxItems: 3
- contains:
- const: pcie_phy
-
- - if:
- properties:
- compatible:
- contains:
- enum:
- - fsl,imx8mm-pcie
- - fsl,imx8mp-pcie
- then:
- properties:
- clock-names:
- maxItems: 3
- contains:
- const: pcie_aux
- - if:
- properties:
- compatible:
- contains:
- enum:
- - fsl,imx6q-pcie
- - fsl,imx6qp-pcie
- then:
- properties:
- power-domains: false
- power-domain-names: false
-
- - if:
- not:
- properties:
- compatible:
- contains:
- enum:
- - fsl,imx6sx-pcie
- - fsl,imx6q-pcie
- - fsl,imx6qp-pcie
- then:
- properties:
- power-domains:
- maxItems: 1
- power-domain-names: false
-
- - if:
- properties:
- compatible:
- contains:
- enum:
- - fsl,imx6q-pcie
- - fsl,imx6sx-pcie
- - fsl,imx6qp-pcie
- - fsl,imx7d-pcie
- - fsl,imx8mq-pcie
- then:
- properties:
- resets:
- minItems: 3
- reset-names:
- items:
- - const: pciephy
- - const: apps
- - const: turnoff
- else:
- properties:
- resets:
- maxItems: 2
- reset-names:
- items:
- - const: apps
- - const: turnoff
+ - $ref: /schemas/pci/fsl,imx6q-pcie-common.yaml#
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml
index 523b15428752..b3c22ebd156c 100644
--- a/Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml
+++ b/Documentation/devicetree/bindings/pci/qcom,pcie-ep.yaml
@@ -166,7 +166,7 @@ examples:
#include <dt-bindings/clock/qcom,gcc-sdx55.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
- pcie_ep: pcie-ep@40000000 {
+ pcie_ep: pcie-ep@1c00000 {
compatible = "qcom,sdx55-pcie-ep";
reg = <0x01c00000 0x3000>,
<0x40000000 0xf1d>,
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie.yaml
index fb32c43dd12d..81971be4e554 100644
--- a/Documentation/devicetree/bindings/pci/qcom,pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/qcom,pcie.yaml
@@ -8,7 +8,7 @@ title: Qualcomm PCI express root complex
maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
- - Stanimir Varbanov <svarbanov@mm-sol.com>
+ - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
description: |
Qualcomm PCIe root complex controller is based on the Synopsys DesignWare
@@ -33,22 +33,24 @@ properties:
- qcom,pcie-sc8180x
- qcom,pcie-sc8280xp
- qcom,pcie-sdm845
+ - qcom,pcie-sdx55
- qcom,pcie-sm8150
- qcom,pcie-sm8250
- qcom,pcie-sm8350
- qcom,pcie-sm8450-pcie0
- qcom,pcie-sm8450-pcie1
+ - qcom,pcie-sm8550
- items:
- const: qcom,pcie-msm8998
- const: qcom,pcie-msm8996
reg:
minItems: 4
- maxItems: 5
+ maxItems: 6
reg-names:
minItems: 4
- maxItems: 5
+ maxItems: 6
interrupts:
minItems: 1
@@ -58,6 +60,9 @@ properties:
minItems: 1
maxItems: 8
+ iommu-map:
+ maxItems: 2
+
# Common definitions for clocks, clock-names and reset.
# Platform constraints are described later.
clocks:
@@ -120,14 +125,20 @@ required:
- compatible
- reg
- reg-names
- - interrupts
- - interrupt-names
- - "#interrupt-cells"
- interrupt-map-mask
- interrupt-map
- clocks
- clock-names
+anyOf:
+ - required:
+ - interrupts
+ - interrupt-names
+ - "#interrupt-cells"
+ - required:
+ - msi-map
+ - msi-map-mask
+
allOf:
- $ref: /schemas/pci/pci-bus.yaml#
- if:
@@ -185,13 +196,15 @@ allOf:
properties:
reg:
minItems: 4
- maxItems: 4
+ maxItems: 5
reg-names:
+ minItems: 4
items:
- const: parf # Qualcomm specific registers
- const: dbi # DesignWare PCIe registers
- const: elbi # External local bus interface registers
- const: config # PCIe configuration space
+ - const: mhi # MHI registers
- if:
properties:
@@ -201,22 +214,26 @@ allOf:
- qcom,pcie-sc7280
- qcom,pcie-sc8180x
- qcom,pcie-sc8280xp
+ - qcom,pcie-sdx55
- qcom,pcie-sm8250
- qcom,pcie-sm8350
- qcom,pcie-sm8450-pcie0
- qcom,pcie-sm8450-pcie1
+ - qcom,pcie-sm8550
then:
properties:
reg:
minItems: 5
- maxItems: 5
+ maxItems: 6
reg-names:
+ minItems: 5
items:
- const: parf # Qualcomm specific registers
- const: dbi # DesignWare PCIe registers
- const: elbi # External local bus interface registers
- const: atu # ATU address space
- const: config # PCIe configuration space
+ - const: mhi # MHI registers
- if:
properties:
@@ -644,6 +661,37 @@ allOf:
compatible:
contains:
enum:
+ - qcom,pcie-sm8550
+ then:
+ properties:
+ clocks:
+ minItems: 7
+ maxItems: 8
+ clock-names:
+ minItems: 7
+ items:
+ - const: aux # Auxiliary clock
+ - const: cfg # Configuration clock
+ - const: bus_master # Master AXI clock
+ - const: bus_slave # Slave AXI clock
+ - const: slave_q2a # Slave Q2A clock
+ - const: ddrss_sf_tbu # PCIe SF TBU clock
+ - const: noc_aggr # Aggre NoC PCIe AXI clock
+ - const: cnoc_sf_axi # Config NoC PCIe1 AXI clock
+ resets:
+ minItems: 1
+ maxItems: 2
+ reset-names:
+ minItems: 1
+ items:
+ - const: pci # PCIe core reset
+ - const: link_down # PCIe link down reset
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
- qcom,pcie-sa8540p
- qcom,pcie-sc8280xp
then:
@@ -674,6 +722,32 @@ allOf:
compatible:
contains:
enum:
+ - qcom,pcie-sdx55
+ then:
+ properties:
+ clocks:
+ minItems: 7
+ maxItems: 7
+ clock-names:
+ items:
+ - const: pipe # PIPE clock
+ - const: aux # Auxiliary clock
+ - const: cfg # Configuration clock
+ - const: bus_master # Master AXI clock
+ - const: bus_slave # Slave AXI clock
+ - const: slave_q2a # Slave Q2A clock
+ - const: sleep # PCIe Sleep clock
+ resets:
+ maxItems: 1
+ reset-names:
+ items:
+ - const: pci # PCIe core reset
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
- qcom,pcie-sa8540p
- qcom,pcie-sc8280xp
then:
@@ -724,6 +798,7 @@ allOf:
- qcom,pcie-sm8350
- qcom,pcie-sm8450-pcie0
- qcom,pcie-sm8450-pcie1
+ - qcom,pcie-sm8550
then:
oneOf:
- properties:
diff --git a/MAINTAINERS b/MAINTAINERS
index 5e11a9e9c4a0..a9b604a796fc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16035,6 +16035,8 @@ M: Lucas Stach <l.stach@pengutronix.de>
L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
+F: Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-common.yaml
+F: Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-ep.yaml
F: Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
F: drivers/pci/controller/dwc/*imx6*
diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 64fbfb0763b2..4458eb7f44f0 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -288,11 +288,10 @@ pcibios_claim_one_bus(struct pci_bus *b)
struct pci_bus *child_bus;
list_for_each_entry(dev, &b->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) {
if (r->parent || !r->start || !r->flags)
continue;
if (pci_has_flag(PCI_PROBE_ONLY) ||
diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index e7ef2b5bea9c..d334c7fb672b 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -142,15 +142,15 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940F,
*/
static void pci_fixup_dec21285(struct pci_dev *dev)
{
- int i;
-
if (dev->devfn == 0) {
+ struct resource *r;
+
dev->class &= 0xff;
dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- dev->resource[i].start = 0;
- dev->resource[i].end = 0;
- dev->resource[i].flags = 0;
+ pci_dev_for_each_resource(dev, r) {
+ r->start = 0;
+ r->end = 0;
+ r->flags = 0;
}
}
}
@@ -162,13 +162,11 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, pci_fixup_d
static void pci_fixup_ide_bases(struct pci_dev *dev)
{
struct resource *r;
- int i;
if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
return;
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- r = dev->resource + i;
+ pci_dev_for_each_resource(dev, r) {
if ((r->start & ~0x80) == 0x374) {
r->start |= 2;
r->end = r->start;
diff --git a/arch/arm/mach-dove/pcie.c b/arch/arm/mach-dove/pcie.c
index 754ca381f600..3044b7e03890 100644
--- a/arch/arm/mach-dove/pcie.c
+++ b/arch/arm/mach-dove/pcie.c
@@ -142,14 +142,14 @@ static struct pci_ops pcie_ops = {
static void rc_pci_fixup(struct pci_dev *dev)
{
if (dev->bus->parent == NULL && dev->devfn == 0) {
- int i;
+ struct resource *r;
dev->class &= 0xff;
dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- dev->resource[i].start = 0;
- dev->resource[i].end = 0;
- dev->resource[i].flags = 0;
+ pci_dev_for_each_resource(dev, r) {
+ r->start = 0;
+ r->end = 0;
+ r->flags = 0;
}
}
}
diff --git a/arch/arm/mach-mv78xx0/pcie.c b/arch/arm/mach-mv78xx0/pcie.c
index fa68b63941b1..533cb7856943 100644
--- a/arch/arm/mach-mv78xx0/pcie.c
+++ b/arch/arm/mach-mv78xx0/pcie.c
@@ -186,14 +186,14 @@ static struct pci_ops pcie_ops = {
static void rc_pci_fixup(struct pci_dev *dev)
{
if (dev->bus->parent == NULL && dev->devfn == 0) {
- int i;
+ struct resource *r;
dev->class &= 0xff;
dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- dev->resource[i].start = 0;
- dev->resource[i].end = 0;
- dev->resource[i].flags = 0;
+ pci_dev_for_each_resource(dev, r) {
+ r->start = 0;
+ r->end = 0;
+ r->flags = 0;
}
}
}
diff --git a/arch/arm/mach-orion5x/pci.c b/arch/arm/mach-orion5x/pci.c
index 888fdc9099c5..3313bc5a63ea 100644
--- a/arch/arm/mach-orion5x/pci.c
+++ b/arch/arm/mach-orion5x/pci.c
@@ -522,14 +522,14 @@ static int __init pci_setup(struct pci_sys_data *sys)
static void rc_pci_fixup(struct pci_dev *dev)
{
if (dev->bus->parent == NULL && dev->devfn == 0) {
- int i;
+ struct resource *r;
dev->class &= 0xff;
dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- dev->resource[i].start = 0;
- dev->resource[i].end = 0;
- dev->resource[i].flags = 0;
+ pci_dev_for_each_resource(dev, r) {
+ r->start = 0;
+ r->end = 0;
+ r->flags = 0;
}
}
}
diff --git a/arch/mips/pci/ops-bcm63xx.c b/arch/mips/pci/ops-bcm63xx.c
index dc6dc2741272..b0ea023c47c0 100644
--- a/arch/mips/pci/ops-bcm63xx.c
+++ b/arch/mips/pci/ops-bcm63xx.c
@@ -413,18 +413,18 @@ struct pci_ops bcm63xx_cb_ops = {
static void bcm63xx_fixup(struct pci_dev *dev)
{
static int io_window = -1;
- int i, found, new_io_window;
+ int found, new_io_window;
+ struct resource *r;
u32 val;
/* look for any io resource */
found = 0;
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- if (pci_resource_flags(dev, i) & IORESOURCE_IO) {
+ pci_dev_for_each_resource(dev, r) {
+ if (resource_type(r) == IORESOURCE_IO) {
found = 1;
break;
}
}
-
if (!found)
return;
diff --git a/arch/mips/pci/pci-legacy.c b/arch/mips/pci/pci-legacy.c
index 468722c8a5c6..ec2567f8efd8 100644
--- a/arch/mips/pci/pci-legacy.c
+++ b/arch/mips/pci/pci-legacy.c
@@ -249,12 +249,11 @@ static int pcibios_enable_resources(struct pci_dev *dev, int mask)
pci_read_config_word(dev, PCI_COMMAND, &cmd);
old_cmd = cmd;
- for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
+ pci_dev_for_each_resource(dev, r, idx) {
/* Only set up the requested stuff */
if (!(mask & (1<<idx)))
continue;
- r = &dev->resource[idx];
if (!(r->flags & (IORESOURCE_IO | IORESOURCE_MEM)))
continue;
if ((idx == PCI_ROM_RESOURCE) &&
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index d67cf79bf5d0..e88d7c9feeec 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -880,6 +880,7 @@ int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
static void pcibios_fixup_resources(struct pci_dev *dev)
{
struct pci_controller *hose = pci_bus_to_host(dev->bus);
+ struct resource *res;
int i;
if (!hose) {
@@ -891,9 +892,9 @@ static void pcibios_fixup_resources(struct pci_dev *dev)
if (dev->is_virtfn)
return;
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- struct resource *res = dev->resource + i;
+ pci_dev_for_each_resource(dev, res, i) {
struct pci_bus_region reg;
+
if (!res->flags)
continue;
@@ -1452,11 +1453,10 @@ void pcibios_claim_one_bus(struct pci_bus *bus)
struct pci_bus *child_bus;
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) {
if (r->parent || !r->start || !r->flags)
continue;
@@ -1705,19 +1705,20 @@ EXPORT_SYMBOL_GPL(pcibios_scan_phb);
static void fixup_hide_host_resource_fsl(struct pci_dev *dev)
{
- int i, class = dev->class >> 8;
+ int class = dev->class >> 8;
/* When configured as agent, programming interface = 1 */
int prog_if = dev->class & 0xf;
+ struct resource *r;
if ((class == PCI_CLASS_PROCESSOR_POWERPC ||
class == PCI_CLASS_BRIDGE_OTHER) &&
(dev->hdr_type == PCI_HEADER_TYPE_NORMAL) &&
(prog_if == 0) &&
(dev->bus->parent == NULL)) {
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- dev->resource[i].start = 0;
- dev->resource[i].end = 0;
- dev->resource[i].flags = 0;
+ pci_dev_for_each_resource(dev, r) {
+ r->start = 0;
+ r->end = 0;
+ r->flags = 0;
}
}
}
diff --git a/arch/powerpc/platforms/4xx/pci.c b/arch/powerpc/platforms/4xx/pci.c
index ca5dd7a5842a..07dcc2b8007f 100644
--- a/arch/powerpc/platforms/4xx/pci.c
+++ b/arch/powerpc/platforms/4xx/pci.c
@@ -57,7 +57,7 @@ static inline int ppc440spe_revA(void)
static void fixup_ppc4xx_pci_bridge(struct pci_dev *dev)
{
struct pci_controller *hose;
- int i;
+ struct resource *r;
if (dev->devfn != 0 || dev->bus->self != NULL)
return;
@@ -79,9 +79,9 @@ static void fixup_ppc4xx_pci_bridge(struct pci_dev *dev)
/* Hide the PCI host BARs from the kernel as their content doesn't
* fit well in the resource management
*/
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- dev->resource[i].start = dev->resource[i].end = 0;
- dev->resource[i].flags = 0;
+ pci_dev_for_each_resource(dev, r) {
+ r->start = r->end = 0;
+ r->flags = 0;
}
printk(KERN_INFO "PCI: Hiding 4xx host bridge resources %s\n",
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
index 859e2818c43d..0ca4401ba781 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
@@ -327,14 +327,13 @@ mpc52xx_pci_setup(struct pci_controller *hose,
static void
mpc52xx_pci_fixup_resources(struct pci_dev *dev)
{
- int i;
+ struct resource *res;
pr_debug("%s() %.4x:%.4x\n", __func__, dev->vendor, dev->device);
/* We don't rely on boot loader for PCI and resets all
devices */
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- struct resource *res = &dev->resource[i];
+ pci_dev_for_each_resource(dev, res) {
if (res->end > res->start) { /* Only valid resources */
res->end -= res->start;
res->start = 0;
diff --git a/arch/powerpc/platforms/pseries/pci.c b/arch/powerpc/platforms/pseries/pci.c
index 60e0a58928ef..1772ae3d193d 100644
--- a/arch/powerpc/platforms/pseries/pci.c
+++ b/arch/powerpc/platforms/pseries/pci.c
@@ -240,7 +240,7 @@ void __init pSeries_final_fixup(void)
*/
static void fixup_winbond_82c105(struct pci_dev* dev)
{
- int i;
+ struct resource *r;
unsigned int reg;
if (!machine_is(pseries))
@@ -251,14 +251,14 @@ static void fixup_winbond_82c105(struct pci_dev* dev)
/* Enable LEGIRQ to use INTC instead of ISA interrupts */
pci_write_config_dword(dev, 0x40, reg | (1<<11));
- for (i = 0; i < DEVICE_COUNT_RESOURCE; ++i) {
+ pci_dev_for_each_resource(dev, r) {
/* zap the 2nd function of the winbond chip */
- if (dev->resource[i].flags & IORESOURCE_IO
- && dev->bus->number == 0 && dev->devfn == 0x81)
- dev->resource[i].flags &= ~IORESOURCE_IO;
- if (dev->resource[i].start == 0 && dev->resource[i].end) {
- dev->resource[i].flags = 0;
- dev->resource[i].end = 0;
+ if (dev->bus->number == 0 && dev->devfn == 0x81 &&
+ r->flags & IORESOURCE_IO)
+ r->flags &= ~IORESOURCE_IO;
+ if (r->start == 0 && r->end) {
+ r->flags = 0;
+ r->end = 0;
}
}
}
diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c
index b0c2a5238d04..4f5e49f10805 100644
--- a/arch/sh/drivers/pci/pcie-sh7786.c
+++ b/arch/sh/drivers/pci/pcie-sh7786.c
@@ -140,12 +140,12 @@ static void sh7786_pci_fixup(struct pci_dev *dev)
* Prevent enumeration of root complex resources.
*/
if (pci_is_root_bus(dev->bus) && dev->devfn == 0) {
- int i;
+ struct resource *r;
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- dev->resource[i].start = 0;
- dev->resource[i].end = 0;
- dev->resource[i].flags = 0;
+ pci_dev_for_each_resource(dev, r) {
+ r->start = 0;
+ r->end = 0;
+ r->flags = 0;
}
}
}
diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c
index e5e5ff6b9a5c..b6663a3fbae9 100644
--- a/arch/sparc/kernel/leon_pci.c
+++ b/arch/sparc/kernel/leon_pci.c
@@ -62,15 +62,14 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
+ struct resource *res;
u16 cmd, oldcmd;
int i;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
oldcmd = cmd;
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- struct resource *res = &dev->resource[i];
-
+ pci_dev_for_each_resource(dev, res, i) {
/* Only set up the requested stuff */
if (!(mask & (1<<i)))
continue;
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index cb1ef25116e9..a948a49817c7 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -663,11 +663,10 @@ static void pci_claim_bus_resources(struct pci_bus *bus)
struct pci_dev *dev;
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) {
if (r->parent || !r->start || !r->flags)
continue;
@@ -724,15 +723,14 @@ struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm,
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
+ struct resource *res;
u16 cmd, oldcmd;
int i;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
oldcmd = cmd;
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- struct resource *res = &dev->resource[i];
-
+ pci_dev_for_each_resource(dev, res, i) {
/* Only set up the requested stuff */
if (!(mask & (1<<i)))
continue;
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c
index ee4c9a9a171c..25fe0a061732 100644
--- a/arch/sparc/kernel/pcic.c
+++ b/arch/sparc/kernel/pcic.c
@@ -643,15 +643,14 @@ void pcibios_fixup_bus(struct pci_bus *bus)
int pcibios_enable_device(struct pci_dev *dev, int mask)
{
+ struct resource *res;
u16 cmd, oldcmd;
int i;
pci_read_config_word(dev, PCI_COMMAND, &cmd);
oldcmd = cmd;
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- struct resource *res = &dev->resource[i];
-
+ pci_dev_for_each_resource(dev, res, i) {
/* Only set up the requested stuff */
if (!(mask & (1<<i)))
continue;
diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c
index bf5161dcf89e..e3ec02e6ac9f 100644
--- a/arch/x86/pci/fixup.c
+++ b/arch/x86/pci/fixup.c
@@ -845,3 +845,62 @@ static void quirk_clear_strap_no_soft_reset_dev2_f0(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x15b8, quirk_clear_strap_no_soft_reset_dev2_f0);
#endif
+
+/*
+ * When returning from D3cold to D0, firmware on some Google Coral and Reef
+ * family Chromebooks with Intel Apollo Lake SoC clobbers the headers of
+ * both the L1 PM Substates capability and the previous capability for the
+ * "Celeron N3350/Pentium N4200/Atom E3900 Series PCI Express Port B #1".
+ *
+ * Save those values at enumeration-time and restore them at resume.
+ */
+
+static u16 prev_cap, l1ss_cap;
+static u32 prev_header, l1ss_header;
+
+static void chromeos_save_apl_pci_l1ss_capability(struct pci_dev *dev)
+{
+ int pos = PCI_CFG_SPACE_SIZE, prev = 0;
+ u32 header, pheader = 0;
+
+ while (pos) {
+ pci_read_config_dword(dev, pos, &header);
+ if (PCI_EXT_CAP_ID(header) == PCI_EXT_CAP_ID_L1SS) {
+ prev_cap = prev;
+ prev_header = pheader;
+ l1ss_cap = pos;
+ l1ss_header = header;
+ return;
+ }
+
+ prev = pos;
+ pheader = header;
+ pos = PCI_EXT_CAP_NEXT(header);
+ }
+}
+
+static void chromeos_fixup_apl_pci_l1ss_capability(struct pci_dev *dev)
+{
+ u32 header;
+
+ if (!prev_cap || !prev_header || !l1ss_cap || !l1ss_header)
+ return;
+
+ /* Fixup the header of L1SS Capability if missing */
+ pci_read_config_dword(dev, l1ss_cap, &header);
+ if (header != l1ss_header) {
+ pci_write_config_dword(dev, l1ss_cap, l1ss_header);
+ pci_info(dev, "restore L1SS Capability header (was %#010x now %#010x)\n",
+ header, l1ss_header);
+ }
+
+ /* Fixup the link to L1SS Capability if missing */
+ pci_read_config_dword(dev, prev_cap, &header);
+ if (header != prev_header) {
+ pci_write_config_dword(dev, prev_cap, prev_header);
+ pci_info(dev, "restore previous Capability header (was %#010x now %#010x)\n",
+ header, prev_header);
+ }
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x5ad6, chromeos_save_apl_pci_l1ss_capability);
+DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_INTEL, 0x5ad6, chromeos_fixup_apl_pci_l1ss_capability);
diff --git a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c
index 930c2332c3c4..8173e60bb808 100644
--- a/drivers/eisa/pci_eisa.c
+++ b/drivers/eisa/pci_eisa.c
@@ -20,8 +20,8 @@ static struct eisa_root_device pci_eisa_root;
static int __init pci_eisa_init(struct pci_dev *pdev)
{
- int rc, i;
struct resource *res, *bus_res = NULL;
+ int rc;
if ((rc = pci_enable_device (pdev))) {
dev_err(&pdev->dev, "Could not enable device\n");
@@ -38,7 +38,7 @@ static int __init pci_eisa_init(struct pci_dev *pdev)
* eisa_root_register() can only deal with a single io port resource,
* so we use the first valid io port resource.
*/
- pci_bus_for_each_resource(pdev->bus, res, i)
+ pci_bus_for_each_resource(pdev->bus, res)
if (res && (res->flags & IORESOURCE_IO)) {
bus_res = res;
break;
diff --git a/drivers/firmware/efi/cper-arm.c b/drivers/firmware/efi/cper-arm.c
index 36d3b8b9da47..fa9c1c3bf168 100644
--- a/drivers/firmware/efi/cper-arm.c
+++ b/drivers/firmware/efi/cper-arm.c
@@ -12,7 +12,6 @@
#include <linux/dmi.h>
#include <linux/acpi.h>
#include <linux/pci.h>
-#include <linux/aer.h>
#include <linux/printk.h>
#include <linux/bcd.h>
#include <acpi/ghes.h>
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);
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index ac98b9919029..6085a1471de2 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -229,8 +229,7 @@ static void quirk_ad1815_mpu_resources(struct pnp_dev *dev)
static void quirk_system_pci_resources(struct pnp_dev *dev)
{
struct pci_dev *pdev = NULL;
- struct resource *res;
- resource_size_t pnp_start, pnp_end, pci_start, pci_end;
+ struct resource *res, *r;
int i, j;
/*
@@ -243,32 +242,26 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
* so they won't be claimed by the PNP system driver.
*/
for_each_pci_dev(pdev) {
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- unsigned long flags, type;
+ pci_dev_for_each_resource(pdev, r, i) {
+ unsigned long type = resource_type(r);
- flags = pci_resource_flags(pdev, i);
- type = flags & (IORESOURCE_IO | IORESOURCE_MEM);
- if (!type || pci_resource_len(pdev, i) == 0)
+ if (!(type == IORESOURCE_IO || type == IORESOURCE_MEM) ||
+ resource_size(r) == 0)
continue;
- if (flags & IORESOURCE_UNSET)
+ if (r->flags & IORESOURCE_UNSET)
continue;
- pci_start = pci_resource_start(pdev, i);
- pci_end = pci_resource_end(pdev, i);
for (j = 0;
(res = pnp_get_resource(dev, type, j)); j++) {
if (res->start == 0 && res->end == 0)
continue;
- pnp_start = res->start;
- pnp_end = res->end;
-
/*
* If the PNP region doesn't overlap the PCI
* region at all, there's no problem.
*/
- if (pnp_end < pci_start || pnp_start > pci_end)
+ if (!resource_overlaps(res, r))
continue;
/*
@@ -278,8 +271,7 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
* PNP device describes a bridge with PCI
* behind it.
*/
- if (pnp_start <= pci_start &&
- pnp_end >= pci_end)
+ if (res->start <= r->start && res->end >= r->end)
continue;
/*
@@ -288,9 +280,8 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
* driver from requesting its resources.
*/
dev_warn(&dev->dev,
- "disabling %pR because it overlaps "
- "%s BAR %d %pR\n", res,
- pci_name(pdev), i, &pdev->resource[i]);
+ "disabling %pR because it overlaps %s BAR %d %pR\n",
+ res, pci_name(pdev), i, r);
res->flags |= IORESOURCE_DISABLED;
}
}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index a5dda515fcd1..0b57e37d8e77 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1445,10 +1445,44 @@ int devm_request_pci_bus_resources(struct device *dev,
/* Temporary until new and working PCI SBR API in place */
int pci_bridge_secondary_bus_reset(struct pci_dev *dev);
-#define pci_bus_for_each_resource(bus, res, i) \
- for (i = 0; \
- (res = pci_bus_resource_n(bus, i)) || i < PCI_BRIDGE_RESOURCE_NUM; \
- i++)
+#define __pci_bus_for_each_res0(bus, res, ...) \
+ for (unsigned int __b = 0; \
+ (res = pci_bus_resource_n(bus, __b)) || __b < PCI_BRIDGE_RESOURCE_NUM; \
+ __b++)
+
+#define __pci_bus_for_each_res1(bus, res, __b) \
+ for (__b = 0; \
+ (res = pci_bus_resource_n(bus, __b)) || __b < PCI_BRIDGE_RESOURCE_NUM; \
+ __b++)
+
+/**
+ * pci_bus_for_each_resource - iterate over PCI bus resources
+ * @bus: the PCI bus
+ * @res: pointer to the current resource
+ * @...: optional index of the current resource
+ *
+ * Iterate over PCI bus resources. The first part is to go over PCI bus
+ * resource array, which has at most the %PCI_BRIDGE_RESOURCE_NUM entries.
+ * After that continue with the separate list of the additional resources,
+ * if not empty. That's why the Logical OR is being used.
+ *
+ * Possible usage:
+ *
+ * struct pci_bus *bus = ...;
+ * struct resource *res;
+ * unsigned int i;
+ *
+ * // With optional index
+ * pci_bus_for_each_resource(bus, res, i)
+ * pr_info("PCI bus resource[%u]: %pR\n", i, res);
+ *
+ * // Without index
+ * pci_bus_for_each_resource(bus, res)
+ * _do_something_(res);
+ */
+#define pci_bus_for_each_resource(bus, res, ...) \
+ CONCATENATE(__pci_bus_for_each_res, COUNT_ARGS(__VA_ARGS__)) \
+ (bus, res, __VA_ARGS__)
int __must_check pci_bus_alloc_resource(struct pci_bus *bus,
struct resource *res, resource_size_t size,
@@ -1997,14 +2031,27 @@ int pci_iobar_pfn(struct pci_dev *pdev, int bar, struct vm_area_struct *vma);
* These helpers provide future and backwards compatibility
* for accessing popular PCI BAR info
*/
-#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start)
-#define pci_resource_end(dev, bar) ((dev)->resource[(bar)].end)
-#define pci_resource_flags(dev, bar) ((dev)->resource[(bar)].flags)
-#define pci_resource_len(dev,bar) \
- ((pci_resource_end((dev), (bar)) == 0) ? 0 : \
- \
- (pci_resource_end((dev), (bar)) - \
- pci_resource_start((dev), (bar)) + 1))
+#define pci_resource_n(dev, bar) (&(dev)->resource[(bar)])
+#define pci_resource_start(dev, bar) (pci_resource_n(dev, bar)->start)
+#define pci_resource_end(dev, bar) (pci_resource_n(dev, bar)->end)
+#define pci_resource_flags(dev, bar) (pci_resource_n(dev, bar)->flags)
+#define pci_resource_len(dev,bar) \
+ (pci_resource_end((dev), (bar)) ? \
+ resource_size(pci_resource_n((dev), (bar))) : 0)
+
+#define __pci_dev_for_each_res0(dev, res, ...) \
+ for (unsigned int __b = 0; \
+ res = pci_resource_n(dev, __b), __b < PCI_NUM_RESOURCES; \
+ __b++)
+
+#define __pci_dev_for_each_res1(dev, res, __b) \
+ for (__b = 0; \
+ res = pci_resource_n(dev, __b), __b < PCI_NUM_RESOURCES; \
+ __b++)
+
+#define pci_dev_for_each_resource(dev, res, ...) \
+ CONCATENATE(__pci_dev_for_each_res, COUNT_ARGS(__VA_ARGS__)) \
+ (dev, res, __VA_ARGS__)
/*
* Similar to the helpers above, these manipulate per-pci_dev