Merge tag 'pci-v6.9-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 14 Mar 2024 17:58:27 +0000 (10:58 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 14 Mar 2024 17:58:27 +0000 (10:58 -0700)
Pull PCI updates from Bjorn Helgaas:
 "Enumeration:

   - Consolidate interrupt related code in irq.c (Ilpo Järvinen)

   - Reduce kernel size by replacing sysfs resource macros with
     functions (Ilpo Järvinen)

   - Reduce kernel size by compiling sysfs support only when
     CONFIG_SYSFS=y (Lukas Wunner)

   - Avoid using Extended Tags on 3ware-9650SE Root Port to work around
     an apparent hardware defect (Jörg Wedekind)

  Resource management:

   - Fix an MMIO mapping leak in pci_iounmap() (Philipp Stanner)

   - Move pci_iomap.c and other PCI-specific devres code to drivers/pci
     (Philipp Stanner)

   - Consolidate PCI devres code in devres.c (Philipp Stanner)

  Power management:

   - Avoid D3cold on Asus B1400 PCI-NVMe bridge, where firmware doesn't
     know how to return correctly to D0, and remove previous quirk that
     wasn't as specific (Daniel Drake)

   - Allow runtime PM when the driver enables it but doesn't need any
     runtime PM callbacks (Raag Jadav)

   - Drain runtime-idle callbacks before driver removal to avoid races
     between .remove() and .runtime_idle(), which caused intermittent
     page faults when the rtsx .runtime_idle() accessed registers that
     its .remove() had already unmapped (Rafael J. Wysocki)

  Virtualization:

   - Avoid Secondary Bus Reset on LSI FW643 so it can be assigned to VMs
     with VFIO, e.g., for professional audio software on many Apple
     machines, at the cost of leaking state between VMs (Edmund Raile)

  Error handling:

   - Print all logged TLP Prefixes, not just the first, after AER or DPC
     errors (Ilpo Järvinen)

   - Quirk the DPC PIO log size for Intel Raptor Lake Root Ports, which
     still don't advertise a legal size (Paul Menzel)

   - Ignore expected DPC Surprise Down errors on hot removal (Smita
     Koralahalli)

   - Block runtime suspend while handling AER errors to avoid races that
     prevent the device form being resumed from D3hot (Stanislaw
     Gruszka)

  Peer-to-peer DMA:

   - Use atomic XA allocation in RCU read section (Christophe JAILLET)

  ASPM:

   - Collect bits of ASPM-related code that we need even without
     CONFIG_PCIEASPM into aspm.c (David E. Box)

   - Save/restore L1 PM Substates config for suspend/resume (David E.
     Box)

   - Update save_save when ASPM config is changed, so a .slot_reset()
     during error recovery restores the changed config, not the
     .probe()-time config (Vidya Sagar)

  Endpoint framework:

   - Refactor and improve pci_epf_alloc_space() API (Niklas Cassel)

   - Clean up endpoint BAR descriptions (Niklas Cassel)

   - Fix ntb_register_device() name leak in error path (Yang Yingliang)

   - Return actual error code for pci_vntb_probe() failure (Yang
     Yingliang)

  Broadcom STB PCIe controller driver:

   - Fix MDIO write polling, which previously never waited for
     completion (Jonathan Bell)

  Cadence PCIe endpoint driver:

   - Clear the ARI "Next Function Number" of last function (Jasko-EXT
     Wojciech)

  Freescale i.MX6 PCIe controller driver:

   - Simplify by replacing switch statements with function pointers for
     different hardware variants (Frank Li)

   - Simplify by using clk_bulk*() API (Frank Li)

   - Remove redundant DT clock and reg/reg-name details (Frank Li)

   - Add i.MX95 DT and driver support for both Root Complex and Endpoint
     mode (Frank Li)

  Microsoft Hyper-V host bridge driver:

   - Reduce memory usage by limiting ring buffer size to 16KB instead of
     4 pages (Michael Kelley)

  Qualcomm PCIe controller driver:

   - Add X1E80100 DT and driver support (Abel Vesa)

   - Add DT 'required-opps' for SoCs that require a minimum performance
     level (Johan Hovold)

   - Make DT 'msi-map-mask' optional, depending on how MSI interrupts
     are mapped (Johan Hovold)

   - Disable ASPM L0s for sc8280xp, sa8540p and sa8295p because the PHY
     configuration isn't tuned correctly for L0s (Johan Hovold)

   - Split dt-binding qcom,pcie.yaml into qcom,pcie-common.yaml and
     separate files for SA8775p, SC7280, SC8180X, SC8280XP, SM8150,
     SM8250, SM8350, SM8450, SM8550 for easier reviewing (Krzysztof
     Kozlowski)

   - Enable BDF to SID translation by disabling bypass mode (Manivannan
     Sadhasivam)

   - Add endpoint MHI support for Snapdragon SA8775P SoC (Mrinmay
     Sarkar)

  Synopsys DesignWare PCIe controller driver:

   - Allocate 64-bit MSI address if no 32-bit address is available (Ajay
     Agarwal)

   - Fix endpoint Resizable BAR to actually advertise the required 1MB
     size (Niklas Cassel)

  MicroSemi Switchtec management driver:

   - Release resources if the .probe() fails (Christophe JAILLET)

  Miscellaneous:

   - Make pcie_port_bus_type const (Ricardo B. Marliere)"

* tag 'pci-v6.9-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/pci/pci: (77 commits)
  PCI/ASPM: Update save_state when configuration changes
  PCI/ASPM: Disable L1 before configuring L1 Substates
  PCI/ASPM: Call pci_save_ltr_state() from pci_save_pcie_state()
  PCI/ASPM: Save L1 PM Substates Capability for suspend/resume
  PCI: hv: Fix ring buffer size calculation
  PCI: dwc: endpoint: Fix advertised resizable BAR size
  PCI: cadence: Clear the ARI Capability Next Function Number of the last function
  PCI: dwc: Strengthen the MSI address allocation logic
  PCI: brcmstb: Fix broken brcm_pcie_mdio_write() polling
  PCI: qcom: Add X1E80100 PCIe support
  dt-bindings: PCI: qcom: Document the X1E80100 PCIe Controller
  PCI: qcom: Enable BDF to SID translation properly
  PCI/AER: Generalize TLP Header Log reading
  PCI/AER: Use explicit register size for PCI_ERR_CAP
  PCI: qcom: Disable ASPM L0s for sc8280xp, sa8540p and sa8295p
  dt-bindings: PCI: qcom: Do not require 'msi-map-mask'
  dt-bindings: PCI: qcom: Allow 'required-opps'
  PCI/AER: Block runtime suspend when handling errors
  PCI/ASPM: Move pci_save_ltr_state() to aspm.c
  PCI/ASPM: Always build aspm.c
  ...

73 files changed:
Documentation/ABI/testing/sysfs-bus-pci-devices-aer_stats
Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-common.yaml
Documentation/devicetree/bindings/pci/fsl,imx6q-pcie-ep.yaml
Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
Documentation/devicetree/bindings/pci/qcom,pcie-common.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/pci/qcom,pcie-sc7280.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/pci/qcom,pcie-sc8180x.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/pci/qcom,pcie-sc8280xp.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/pci/qcom,pcie-sm8150.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/pci/qcom,pcie-sm8250.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/pci/qcom,pcie-sm8350.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/pci/qcom,pcie-sm8450.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/pci/qcom,pcie-sm8550.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/pci/qcom,pcie-x1e80100.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/pci/qcom,pcie.yaml
Documentation/driver-api/device-io.rst
Documentation/driver-api/pci/pci.rst
MAINTAINERS
arch/x86/pci/fixup.c
drivers/acpi/sleep.c
drivers/firmware/efi/cper.c
drivers/ntb/core.c
drivers/pci/Kconfig
drivers/pci/Makefile
drivers/pci/controller/cadence/pcie-cadence-ep.c
drivers/pci/controller/cadence/pcie-cadence.h
drivers/pci/controller/dwc/pci-imx6.c
drivers/pci/controller/dwc/pci-keystone.c
drivers/pci/controller/dwc/pci-layerscape-ep.c
drivers/pci/controller/dwc/pcie-designware-ep.c
drivers/pci/controller/dwc/pcie-designware-host.c
drivers/pci/controller/dwc/pcie-keembay.c
drivers/pci/controller/dwc/pcie-qcom.c
drivers/pci/controller/dwc/pcie-rcar-gen4.c
drivers/pci/controller/dwc/pcie-tegra194.c
drivers/pci/controller/dwc/pcie-uniphier-ep.c
drivers/pci/controller/pci-hyperv.c
drivers/pci/controller/pcie-brcmstb.c
drivers/pci/controller/pcie-rcar-ep.c
drivers/pci/devres.c [new file with mode: 0644]
drivers/pci/endpoint/functions/pci-epf-mhi.c
drivers/pci/endpoint/functions/pci-epf-ntb.c
drivers/pci/endpoint/functions/pci-epf-test.c
drivers/pci/endpoint/functions/pci-epf-vntb.c
drivers/pci/endpoint/pci-epc-core.c
drivers/pci/endpoint/pci-epf-core.c
drivers/pci/iomap.c [moved from lib/pci_iomap.c with 99% similarity]
drivers/pci/irq.c
drivers/pci/mmap.c
drivers/pci/p2pdma.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/Makefile
drivers/pci/pcie/aer.c
drivers/pci/pcie/aspm.c
drivers/pci/pcie/dpc.c
drivers/pci/pcie/err.c
drivers/pci/pcie/portdrv.h
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pci/setup-irq.c [deleted file]
drivers/pci/switch/switchtec.c
include/linux/aer.h
include/linux/pci-epc.h
include/linux/pci-epf.h
include/linux/pci.h
include/ras/ras_event.h
lib/Kconfig
lib/Makefile
lib/devres.c

index 860db53037a58fae2faa10fcfc8672c0ed20ace9..d1f67bb81d5d14c28eb518a97ba0ca6413325b3a 100644 (file)
@@ -11,7 +11,7 @@ saw any problems).
 
 What:          /sys/bus/pci/devices/<dev>/aer_dev_correctable
 Date:          July 2018
-KernelVersion: 4.19.0
+KernelVersion: 4.19.0
 Contact:       linux-pci@vger.kernel.org, rajatja@google.com
 Description:   List of correctable errors seen and reported by this
                PCI device using ERR_COR. Note that since multiple errors may
@@ -32,7 +32,7 @@ Description:  List of correctable errors seen and reported by this
 
 What:          /sys/bus/pci/devices/<dev>/aer_dev_fatal
 Date:          July 2018
-KernelVersion: 4.19.0
+KernelVersion: 4.19.0
 Contact:       linux-pci@vger.kernel.org, rajatja@google.com
 Description:   List of uncorrectable fatal errors seen and reported by this
                PCI device using ERR_FATAL. Note that since multiple errors may
@@ -62,7 +62,7 @@ Description:  List of uncorrectable fatal errors seen and reported by this
 
 What:          /sys/bus/pci/devices/<dev>/aer_dev_nonfatal
 Date:          July 2018
-KernelVersion: 4.19.0
+KernelVersion: 4.19.0
 Contact:       linux-pci@vger.kernel.org, rajatja@google.com
 Description:   List of uncorrectable nonfatal errors seen and reported by this
                PCI device using ERR_NONFATAL. Note that since multiple errors
@@ -100,20 +100,20 @@ collectors) that are AER capable. These indicate the number of error messages as
 device, so these counters include them and are thus cumulative of all the error
 messages on the PCI hierarchy originating at that root port.
 
-What:          /sys/bus/pci/devices/<dev>/aer_stats/aer_rootport_total_err_cor
+What:          /sys/bus/pci/devices/<dev>/aer_rootport_total_err_cor
 Date:          July 2018
-KernelVersion: 4.19.0
+KernelVersion: 4.19.0
 Contact:       linux-pci@vger.kernel.org, rajatja@google.com
 Description:   Total number of ERR_COR messages reported to rootport.
 
-What:      /sys/bus/pci/devices/<dev>/aer_stats/aer_rootport_total_err_fatal
+What:          /sys/bus/pci/devices/<dev>/aer_rootport_total_err_fatal
 Date:          July 2018
-KernelVersion: 4.19.0
+KernelVersion: 4.19.0
 Contact:       linux-pci@vger.kernel.org, rajatja@google.com
 Description:   Total number of ERR_FATAL messages reported to rootport.
 
-What:      /sys/bus/pci/devices/<dev>/aer_stats/aer_rootport_total_err_nonfatal
+What:          /sys/bus/pci/devices/<dev>/aer_rootport_total_err_nonfatal
 Date:          July 2018
-KernelVersion: 4.19.0
+KernelVersion: 4.19.0
 Contact:       linux-pci@vger.kernel.org, rajatja@google.com
 Description:   Total number of ERR_NONFATAL messages reported to rootport.
index d91b639ae7ae75d15eb131f8ebaa409cc5658afe..a8b34f58f8f49520e8c7bd6c900ad499c5cbba94 100644 (file)
@@ -150,22 +150,6 @@ allOf:
             - {}
             - 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:
@@ -223,6 +207,7 @@ allOf:
                 - fsl,imx6sx-pcie
                 - fsl,imx6q-pcie
                 - fsl,imx6qp-pcie
+                - fsl,imx95-pcie
                 - fsl,imx6sx-pcie-ep
                 - fsl,imx6q-pcie-ep
                 - fsl,imx6qp-pcie-ep
index ee155ed5f18118164ae05d56cd12a2b934aad187..a06f75df8458ae6bdb18b7e688433bace5462ef4 100644 (file)
@@ -22,14 +22,7 @@ properties:
       - fsl,imx8mm-pcie-ep
       - fsl,imx8mq-pcie-ep
       - fsl,imx8mp-pcie-ep
-
-  reg:
-    minItems: 2
-
-  reg-names:
-    items:
-      - const: dbi
-      - const: addr_space
+      - fsl,imx95-pcie-ep
 
   clocks:
     minItems: 3
@@ -62,11 +55,48 @@ required:
 allOf:
   - $ref: /schemas/pci/snps,dw-pcie-ep.yaml#
   - $ref: /schemas/pci/fsl,imx6q-pcie-common.yaml#
+  - if:
+      properties:
+        compatible:
+          enum:
+            - fsl,imx8mm-pcie-ep
+            - fsl,imx8mq-pcie-ep
+            - fsl,imx8mp-pcie-ep
+    then:
+      properties:
+        reg:
+          minItems: 2
+          maxItems: 2
+        reg-names:
+          items:
+            - const: dbi
+            - const: addr_space
+
+  - if:
+      properties:
+        compatible:
+          enum:
+            - fsl,imx95-pcie-ep
+    then:
+      properties:
+        reg:
+          minItems: 6
+          maxItems: 6
+        reg-names:
+          items:
+            - const: dbi
+            - const: atu
+            - const: dbi2
+            - const: app
+            - const: dma
+            - const: addr_space
+
   - if:
       properties:
         compatible:
           enum:
             - fsl,imx8mq-pcie-ep
+            - fsl,imx95-pcie-ep
     then:
       properties:
         clocks:
index 81bbb8728f0f97a6db584a8d970c3740449f0655..8b8d77b1154b5c69d719a54100b584a0ec199dda 100644 (file)
@@ -29,16 +29,7 @@ properties:
       - fsl,imx8mq-pcie
       - fsl,imx8mm-pcie
       - fsl,imx8mp-pcie
-
-  reg:
-    items:
-      - description: Data Bus Interface (DBI) registers.
-      - description: PCIe configuration space region.
-
-  reg-names:
-    items:
-      - const: dbi
-      - const: config
+      - fsl,imx95-pcie
 
   clocks:
     minItems: 3
@@ -90,6 +81,43 @@ required:
 allOf:
   - $ref: /schemas/pci/snps,dw-pcie.yaml#
   - $ref: /schemas/pci/fsl,imx6q-pcie-common.yaml#
+  - if:
+      properties:
+        compatible:
+          enum:
+            - fsl,imx6q-pcie
+            - fsl,imx6sx-pcie
+            - fsl,imx6qp-pcie
+            - fsl,imx7d-pcie
+            - fsl,imx8mq-pcie
+            - fsl,imx8mm-pcie
+            - fsl,imx8mp-pcie
+    then:
+      properties:
+        reg:
+          maxItems: 2
+        reg-names:
+          items:
+            - const: dbi
+            - const: config
+
+  - if:
+      properties:
+        compatible:
+          enum:
+            - fsl,imx95-pcie
+    then:
+      properties:
+        reg:
+          minItems: 4
+          maxItems: 4
+        reg-names:
+          items:
+            - const: dbi
+            - const: config
+            - const: atu
+            - const: app
+
   - if:
       properties:
         compatible:
@@ -111,6 +139,7 @@ allOf:
         compatible:
           enum:
             - fsl,imx8mq-pcie
+            - fsl,imx95-pcie
     then:
       properties:
         clocks:
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-common.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-common.yaml
new file mode 100644 (file)
index 0000000..0d1b235
--- /dev/null
@@ -0,0 +1,100 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/qcom,pcie-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm PCI Express Root Complex Common Properties
+
+maintainers:
+  - Bjorn Andersson <andersson@kernel.org>
+  - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+properties:
+  reg:
+    minItems: 4
+    maxItems: 6
+
+  reg-names:
+    minItems: 4
+    maxItems: 6
+
+  interrupts:
+    minItems: 1
+    maxItems: 8
+
+  interrupt-names:
+    minItems: 1
+    maxItems: 8
+
+  iommu-map:
+    minItems: 1
+    maxItems: 16
+
+  clocks:
+    minItems: 3
+    maxItems: 13
+
+  clock-names:
+    minItems: 3
+    maxItems: 13
+
+  dma-coherent: true
+
+  interconnects:
+    maxItems: 2
+
+  interconnect-names:
+    items:
+      - const: pcie-mem
+      - const: cpu-pcie
+
+  phys:
+    maxItems: 1
+
+  phy-names:
+    items:
+      - const: pciephy
+
+  power-domains:
+    maxItems: 1
+
+  required-opps:
+    maxItems: 1
+
+  resets:
+    minItems: 1
+    maxItems: 12
+
+  reset-names:
+    minItems: 1
+    maxItems: 12
+
+  perst-gpios:
+    description: GPIO controlled connection to PERST# signal
+    maxItems: 1
+
+  wake-gpios:
+    description: GPIO controlled connection to WAKE# signal
+    maxItems: 1
+
+required:
+  - reg
+  - reg-names
+  - interrupt-map-mask
+  - interrupt-map
+  - clocks
+  - clock-names
+
+anyOf:
+  - required:
+      - interrupts
+      - interrupt-names
+      - "#interrupt-cells"
+  - required:
+      - msi-map
+
+allOf:
+  - $ref: /schemas/pci/pci-bus.yaml#
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-sa8775p.yaml
new file mode 100644 (file)
index 0000000..efde49d
--- /dev/null
@@ -0,0 +1,166 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/qcom,pcie-sa8775p.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SA8775p PCI Express Root Complex
+
+maintainers:
+  - Bjorn Andersson <andersson@kernel.org>
+  - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+description:
+  Qualcomm SA8775p SoC PCIe root complex controller is based on the Synopsys
+  DesignWare PCIe IP.
+
+properties:
+  compatible:
+    const: qcom,pcie-sa8775p
+
+  reg:
+    minItems: 6
+    maxItems: 6
+
+  reg-names:
+    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
+
+  clocks:
+    minItems: 5
+    maxItems: 5
+
+  clock-names:
+    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
+
+  interrupts:
+    minItems: 8
+    maxItems: 8
+
+  interrupt-names:
+    items:
+      - const: msi0
+      - const: msi1
+      - const: msi2
+      - const: msi3
+      - const: msi4
+      - const: msi5
+      - const: msi6
+      - const: msi7
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    items:
+      - const: pci
+
+required:
+  - interconnects
+  - interconnect-names
+
+allOf:
+  - $ref: qcom,pcie-common.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,sa8775p-gcc.h>
+    #include <dt-bindings/clock/qcom,rpmh.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+    #include <dt-bindings/interconnect/qcom,sa8775p-rpmh.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        pcie@1c00000 {
+            compatible = "qcom,pcie-sa8775p";
+            reg = <0x0 0x01c00000 0x0 0x3000>,
+                  <0x0 0x40000000 0x0 0xf20>,
+                  <0x0 0x40000f20 0x0 0xa8>,
+                  <0x0 0x40001000 0x0 0x4000>,
+                  <0x0 0x40100000 0x0 0x100000>,
+                  <0x0 0x01c03000 0x0 0x1000>;
+            reg-names = "parf", "dbi", "elbi", "atu", "config", "mhi";
+            ranges = <0x01000000 0x0 0x00000000 0x0 0x40200000 0x0 0x100000>,
+                     <0x02000000 0x0 0x40300000 0x0 0x40300000 0x0 0x1fd00000>;
+
+            bus-range = <0x00 0xff>;
+            device_type = "pci";
+            linux,pci-domain = <0>;
+            num-lanes = <2>;
+
+            #address-cells = <3>;
+            #size-cells = <2>;
+
+            assigned-clocks = <&gcc GCC_PCIE_0_AUX_CLK>;
+            assigned-clock-rates = <19200000>;
+
+            clocks = <&gcc GCC_PCIE_0_AUX_CLK>,
+                     <&gcc GCC_PCIE_0_CFG_AHB_CLK>,
+                     <&gcc GCC_PCIE_0_MSTR_AXI_CLK>,
+                     <&gcc GCC_PCIE_0_SLV_AXI_CLK>,
+                     <&gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>;
+            clock-names = "aux",
+                          "cfg",
+                          "bus_master",
+                          "bus_slave",
+                          "slave_q2a";
+
+            dma-coherent;
+
+            interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>;
+            interrupt-names = "msi0",
+                              "msi1",
+                              "msi2",
+                              "msi3",
+                              "msi4",
+                              "msi5",
+                              "msi6",
+                              "msi7";
+            #interrupt-cells = <1>;
+            interrupt-map-mask = <0 0 0 0x7>;
+            interrupt-map = <0 0 0 1 &intc GIC_SPI 434 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 0 0 2 &intc GIC_SPI 435 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 0 0 3 &intc GIC_SPI 438 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 0 0 4 &intc GIC_SPI 439 IRQ_TYPE_LEVEL_HIGH>;
+
+            interconnects = <&pcie_anoc MASTER_PCIE_0 0 &mc_virt SLAVE_EBI1 0>,
+                            <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_PCIE_0 0>;
+            interconnect-names = "pcie-mem", "cpu-pcie";
+
+            iommu-map = <0x0 &pcie_smmu 0x0000 0x1>,
+                        <0x100 &pcie_smmu 0x0001 0x1>;
+
+            phys = <&pcie0_phy>;
+            phy-names = "pciephy";
+
+            power-domains = <&gcc PCIE_0_GDSC>;
+
+            resets = <&gcc GCC_PCIE_0_BCR>;
+            reset-names = "pci";
+
+            perst-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>;
+            wake-gpios = <&tlmm 0 GPIO_ACTIVE_HIGH>;
+        };
+    };
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-sc7280.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-sc7280.yaml
new file mode 100644 (file)
index 0000000..634da24
--- /dev/null
@@ -0,0 +1,166 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/qcom,pcie-sc7280.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SC7280 PCI Express Root Complex
+
+maintainers:
+  - Bjorn Andersson <andersson@kernel.org>
+  - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+description:
+  Qualcomm SC7280 SoC PCIe root complex controller is based on the Synopsys
+  DesignWare PCIe IP.
+
+properties:
+  compatible:
+    const: qcom,pcie-sc7280
+
+  reg:
+    minItems: 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
+
+  clocks:
+    minItems: 13
+    maxItems: 13
+
+  clock-names:
+    items:
+      - const: pipe # PIPE clock
+      - const: pipe_mux # PIPE MUX
+      - const: phy_pipe # PIPE output clock
+      - const: ref # REFERENCE 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: tbu # PCIe TBU clock
+      - const: ddrss_sf_tbu # PCIe SF TBU clock
+      - const: aggre0 # Aggre NoC PCIe CENTER SF AXI clock
+      - const: aggre1 # Aggre NoC PCIe1 AXI clock
+
+  interrupts:
+    maxItems: 1
+
+  interrupt-names:
+    items:
+      - const: msi
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    items:
+      - const: pci
+
+  vddpe-3v3-supply:
+    description: PCIe endpoint power supply
+
+allOf:
+  - $ref: qcom,pcie-common.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,gcc-sc7280.h>
+    #include <dt-bindings/clock/qcom,rpmh.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        pcie@1c08000 {
+            compatible = "qcom,pcie-sc7280";
+            reg = <0 0x01c08000 0 0x3000>,
+                  <0 0x40000000 0 0xf1d>,
+                  <0 0x40000f20 0 0xa8>,
+                  <0 0x40001000 0 0x1000>,
+                  <0 0x40100000 0 0x100000>;
+            reg-names = "parf", "dbi", "elbi", "atu", "config";
+            ranges = <0x01000000 0x0 0x00000000 0x0 0x40200000 0x0 0x100000>,
+                     <0x02000000 0x0 0x40300000 0x0 0x40300000 0x0 0x1fd00000>;
+
+            bus-range = <0x00 0xff>;
+            device_type = "pci";
+            linux,pci-domain = <1>;
+            num-lanes = <2>;
+
+            #address-cells = <3>;
+            #size-cells = <2>;
+
+            assigned-clocks = <&gcc GCC_PCIE_1_AUX_CLK>;
+            assigned-clock-rates = <19200000>;
+
+            clocks = <&gcc GCC_PCIE_1_PIPE_CLK>,
+                     <&gcc GCC_PCIE_1_PIPE_CLK_SRC>,
+                     <&pcie1_phy>,
+                     <&rpmhcc RPMH_CXO_CLK>,
+                     <&gcc GCC_PCIE_1_AUX_CLK>,
+                     <&gcc GCC_PCIE_1_CFG_AHB_CLK>,
+                     <&gcc GCC_PCIE_1_MSTR_AXI_CLK>,
+                     <&gcc GCC_PCIE_1_SLV_AXI_CLK>,
+                     <&gcc GCC_PCIE_1_SLV_Q2A_AXI_CLK>,
+                     <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>,
+                     <&gcc GCC_DDRSS_PCIE_SF_CLK>,
+                     <&gcc GCC_AGGRE_NOC_PCIE_CENTER_SF_AXI_CLK>,
+                     <&gcc GCC_AGGRE_NOC_PCIE_1_AXI_CLK>;
+
+            clock-names = "pipe",
+                          "pipe_mux",
+                          "phy_pipe",
+                          "ref",
+                          "aux",
+                          "cfg",
+                          "bus_master",
+                          "bus_slave",
+                          "slave_q2a",
+                          "tbu",
+                          "ddrss_sf_tbu",
+                          "aggre0",
+                          "aggre1";
+
+            dma-coherent;
+
+            interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>;
+            interrupt-names = "msi";
+            #interrupt-cells = <1>;
+            interrupt-map-mask = <0 0 0 0x7>;
+            interrupt-map = <0 0 0 1 &intc 0 0 0 434 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 0 0 2 &intc 0 0 0 435 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 0 0 3 &intc 0 0 0 438 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 0 0 4 &intc 0 0 0 439 IRQ_TYPE_LEVEL_HIGH>;
+
+            iommu-map = <0x0 &apps_smmu 0x1c80 0x1>,
+                        <0x100 &apps_smmu 0x1c81 0x1>;
+
+            phys = <&pcie1_phy>;
+            phy-names = "pciephy";
+
+            pinctrl-names = "default";
+            pinctrl-0 = <&pcie1_clkreq_n>;
+
+            power-domains = <&gcc GCC_PCIE_1_GDSC>;
+
+            resets = <&gcc GCC_PCIE_1_BCR>;
+            reset-names = "pci";
+
+            perst-gpios = <&tlmm 2 GPIO_ACTIVE_LOW>;
+            vddpe-3v3-supply = <&pp3300_ssd>;
+        };
+    };
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-sc8180x.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-sc8180x.yaml
new file mode 100644 (file)
index 0000000..baf1813
--- /dev/null
@@ -0,0 +1,170 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/qcom,pcie-sc8180x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SC8180x PCI Express Root Complex
+
+maintainers:
+  - Bjorn Andersson <andersson@kernel.org>
+  - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+description:
+  Qualcomm SC8180x SoC PCIe root complex controller is based on the Synopsys
+  DesignWare PCIe IP.
+
+properties:
+  compatible:
+    const: qcom,pcie-sc8180x
+
+  reg:
+    minItems: 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
+
+  clocks:
+    minItems: 8
+    maxItems: 8
+
+  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: ref # REFERENCE clock
+      - const: tbu # PCIe TBU clock
+
+  interrupts:
+    minItems: 8
+    maxItems: 8
+
+  interrupt-names:
+    items:
+      - const: msi0
+      - const: msi1
+      - const: msi2
+      - const: msi3
+      - const: msi4
+      - const: msi5
+      - const: msi6
+      - const: msi7
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    items:
+      - const: pci
+
+allOf:
+  - $ref: qcom,pcie-common.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,gcc-sc8180x.h>
+    #include <dt-bindings/interconnect/qcom,sc8180x.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        pcie@1c00000 {
+            compatible = "qcom,pcie-sc8180x";
+            reg = <0 0x01c00000 0 0x3000>,
+                  <0 0x60000000 0 0xf1d>,
+                  <0 0x60000f20 0 0xa8>,
+                  <0 0x60001000 0 0x1000>,
+                  <0 0x60100000 0 0x100000>;
+            reg-names = "parf",
+                        "dbi",
+                        "elbi",
+                        "atu",
+                        "config";
+            ranges = <0x01000000 0x0 0x60200000 0x0 0x60200000 0x0 0x100000>,
+                     <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>;
+
+            bus-range = <0x00 0xff>;
+            device_type = "pci";
+            linux,pci-domain = <0>;
+            num-lanes = <2>;
+
+            #address-cells = <3>;
+            #size-cells = <2>;
+
+            assigned-clocks = <&gcc GCC_PCIE_0_AUX_CLK>;
+            assigned-clock-rates = <19200000>;
+
+            clocks = <&gcc GCC_PCIE_0_PIPE_CLK>,
+                     <&gcc GCC_PCIE_0_AUX_CLK>,
+                     <&gcc GCC_PCIE_0_CFG_AHB_CLK>,
+                     <&gcc GCC_PCIE_0_MSTR_AXI_CLK>,
+                     <&gcc GCC_PCIE_0_SLV_AXI_CLK>,
+                     <&gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>,
+                     <&gcc GCC_PCIE_0_CLKREF_CLK>,
+                     <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>;
+            clock-names = "pipe",
+                          "aux",
+                          "cfg",
+                          "bus_master",
+                          "bus_slave",
+                          "slave_q2a",
+                          "ref",
+                          "tbu";
+
+            dma-coherent;
+
+            interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+            interrupt-names = "msi0",
+                          "msi1",
+                          "msi2",
+                          "msi3",
+                          "msi4",
+                          "msi5",
+                          "msi6",
+                          "msi7";
+            #interrupt-cells = <1>;
+            interrupt-map-mask = <0 0 0 0x7>;
+            interrupt-map = <0 0 0 1 &intc 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+                            <0 0 0 2 &intc 0 150 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+                            <0 0 0 3 &intc 0 151 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+                            <0 0 0 4 &intc 0 152 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+
+            interconnects = <&aggre2_noc MASTER_PCIE 0 &mc_virt SLAVE_EBI_CH0 0>,
+                            <&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_PCIE_0 0>;
+            interconnect-names = "pcie-mem", "cpu-pcie";
+
+            iommu-map = <0x0 &apps_smmu 0x1d80 0x1>,
+                        <0x100 &apps_smmu 0x1d81 0x1>;
+
+            phys = <&pcie0_phy>;
+            phy-names = "pciephy";
+
+            power-domains = <&gcc PCIE_0_GDSC>;
+
+            resets = <&gcc GCC_PCIE_0_BCR>;
+            reset-names = "pci";
+        };
+    };
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-sc8280xp.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-sc8280xp.yaml
new file mode 100644 (file)
index 0000000..25c9f13
--- /dev/null
@@ -0,0 +1,180 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/qcom,pcie-sc8280xp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SC8280XP PCI Express Root Complex
+
+maintainers:
+  - Bjorn Andersson <andersson@kernel.org>
+  - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+description:
+  Qualcomm SC8280XP SoC PCIe root complex controller is based on the Synopsys
+  DesignWare PCIe IP.
+
+properties:
+  compatible:
+    enum:
+      - qcom,pcie-sa8540p
+      - qcom,pcie-sc8280xp
+
+  reg:
+    minItems: 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
+
+  clocks:
+    minItems: 8
+    maxItems: 9
+
+  clock-names:
+    minItems: 8
+    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_4 # NoC aggregate 4 clock
+      - const: noc_aggr_south_sf # NoC aggregate South SF clock
+      - const: cnoc_qx # Configuration NoC QX clock
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    items:
+      - const: pci
+
+  vddpe-3v3-supply:
+    description: A phandle to the PCIe endpoint power supply
+
+required:
+  - interconnects
+  - interconnect-names
+
+allOf:
+  - $ref: qcom,pcie-common.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - qcom,pcie-sc8280xp
+    then:
+      properties:
+        interrupts:
+          minItems: 4
+          maxItems: 4
+        interrupt-names:
+          items:
+            - const: msi0
+            - const: msi1
+            - const: msi2
+            - const: msi3
+    else:
+      properties:
+        interrupts:
+          maxItems: 1
+        interrupt-names:
+          items:
+            - const: msi
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,gcc-sc8280xp.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interconnect/qcom,sc8280xp.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        pcie@1c20000 {
+            compatible = "qcom,pcie-sc8280xp";
+            reg = <0x0 0x01c20000 0x0 0x3000>,
+                  <0x0 0x3c000000 0x0 0xf1d>,
+                  <0x0 0x3c000f20 0x0 0xa8>,
+                  <0x0 0x3c001000 0x0 0x1000>,
+                  <0x0 0x3c100000 0x0 0x100000>,
+                  <0x0 0x01c23000 0x0 0x1000>;
+            reg-names = "parf", "dbi", "elbi", "atu", "config", "mhi";
+            ranges = <0x01000000 0x0 0x00000000 0x0 0x3c200000 0x0 0x100000>,
+                     <0x02000000 0x0 0x3c300000 0x0 0x3c300000 0x0 0x1d00000>;
+
+            bus-range = <0x00 0xff>;
+            device_type = "pci";
+            linux,pci-domain = <2>;
+            num-lanes = <4>;
+
+            #address-cells = <3>;
+            #size-cells = <2>;
+
+            assigned-clocks = <&gcc GCC_PCIE_2A_AUX_CLK>;
+            assigned-clock-rates = <19200000>;
+            clocks = <&gcc GCC_PCIE_2A_AUX_CLK>,
+                     <&gcc GCC_PCIE_2A_CFG_AHB_CLK>,
+                     <&gcc GCC_PCIE_2A_MSTR_AXI_CLK>,
+                     <&gcc GCC_PCIE_2A_SLV_AXI_CLK>,
+                     <&gcc GCC_PCIE_2A_SLV_Q2A_AXI_CLK>,
+                     <&gcc GCC_DDRSS_PCIE_SF_TBU_CLK>,
+                     <&gcc GCC_AGGRE_NOC_PCIE_4_AXI_CLK>,
+                     <&gcc GCC_AGGRE_NOC_PCIE_SOUTH_SF_AXI_CLK>;
+            clock-names = "aux",
+                          "cfg",
+                          "bus_master",
+                          "bus_slave",
+                          "slave_q2a",
+                          "ddrss_sf_tbu",
+                          "noc_aggr_4",
+                          "noc_aggr_south_sf";
+
+            dma-coherent;
+
+            interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 523 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 524 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 525 IRQ_TYPE_LEVEL_HIGH>;
+            interrupt-names = "msi0", "msi1", "msi2", "msi3";
+            #interrupt-cells = <1>;
+            interrupt-map-mask = <0 0 0 0x7>;
+            interrupt-map = <0 0 0 1 &intc 0 0 GIC_SPI 530 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 0 0 2 &intc 0 0 GIC_SPI 531 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 0 0 3 &intc 0 0 GIC_SPI 532 IRQ_TYPE_LEVEL_HIGH>,
+                            <0 0 0 4 &intc 0 0 GIC_SPI 533 IRQ_TYPE_LEVEL_HIGH>;
+
+            interconnects = <&aggre2_noc MASTER_PCIE_2A 0 &mc_virt SLAVE_EBI1 0>,
+                            <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_PCIE_2A 0>;
+            interconnect-names = "pcie-mem", "cpu-pcie";
+
+            phys = <&pcie2a_phy>;
+            phy-names = "pciephy";
+
+            pinctrl-0 = <&pcie2a_default>;
+            pinctrl-names = "default";
+
+            power-domains = <&gcc PCIE_2A_GDSC>;
+
+            resets = <&gcc GCC_PCIE_2A_BCR>;
+            reset-names = "pci";
+
+            perst-gpios = <&tlmm 143 GPIO_ACTIVE_LOW>;
+            wake-gpios = <&tlmm 145 GPIO_ACTIVE_LOW>;
+            vddpe-3v3-supply = <&vreg_nvme>;
+        };
+    };
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-sm8150.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-sm8150.yaml
new file mode 100644 (file)
index 0000000..9d56964
--- /dev/null
@@ -0,0 +1,158 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/qcom,pcie-sm8150.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SM8150 PCI Express Root Complex
+
+maintainers:
+  - Bjorn Andersson <andersson@kernel.org>
+  - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+description:
+  Qualcomm SM8150 SoC PCIe root complex controller is based on the Synopsys
+  DesignWare PCIe IP.
+
+properties:
+  compatible:
+    const: qcom,pcie-sm8150
+
+  reg:
+    minItems: 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
+
+  clocks:
+    minItems: 8
+    maxItems: 8
+
+  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: tbu # PCIe TBU clock
+      - const: ref # REFERENCE clock
+
+  interrupts:
+    minItems: 8
+    maxItems: 8
+
+  interrupt-names:
+    items:
+      - const: msi0
+      - const: msi1
+      - const: msi2
+      - const: msi3
+      - const: msi4
+      - const: msi5
+      - const: msi6
+      - const: msi7
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    items:
+      - const: pci
+
+allOf:
+  - $ref: qcom,pcie-common.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,gcc-sm8150.h>
+    #include <dt-bindings/clock/qcom,rpmh.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interconnect/qcom,sm8150.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+        pcie@1c00000 {
+            compatible = "qcom,pcie-sm8150";
+            reg = <0 0x01c00000 0 0x3000>,
+                  <0 0x60000000 0 0xf1d>,
+                  <0 0x60000f20 0 0xa8>,
+                  <0 0x60001000 0 0x1000>,
+                  <0 0x60100000 0 0x100000>;
+            reg-names = "parf", "dbi", "elbi", "atu", "config";
+            ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>,
+                     <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>;
+
+            bus-range = <0x00 0xff>;
+            device_type = "pci";
+            linux,pci-domain = <0>;
+            num-lanes = <1>;
+
+            #address-cells = <3>;
+            #size-cells = <2>;
+
+            clocks = <&gcc GCC_PCIE_0_PIPE_CLK>,
+                     <&gcc GCC_PCIE_0_AUX_CLK>,
+                     <&gcc GCC_PCIE_0_CFG_AHB_CLK>,
+                     <&gcc GCC_PCIE_0_MSTR_AXI_CLK>,
+                     <&gcc GCC_PCIE_0_SLV_AXI_CLK>,
+                     <&gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>,
+                     <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>,
+                     <&rpmhcc RPMH_CXO_CLK>;
+            clock-names = "pipe",
+                          "aux",
+                          "cfg",
+                          "bus_master",
+                          "bus_slave",
+                          "slave_q2a",
+                          "tbu",
+                          "ref";
+
+            interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+            interrupt-names = "msi0", "msi1", "msi2", "msi3",
+                              "msi4", "msi5", "msi6", "msi7";
+            #interrupt-cells = <1>;
+            interrupt-map-mask = <0 0 0 0x7>;
+            interrupt-map = <0 0 0 1 &intc 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+                            <0 0 0 2 &intc 0 150 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+                            <0 0 0 3 &intc 0 151 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+                            <0 0 0 4 &intc 0 152 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+
+            iommu-map = <0x0 &apps_smmu 0x1d80 0x1>,
+                        <0x100 &apps_smmu 0x1d81 0x1>;
+
+            phys = <&pcie0_phy>;
+            phy-names = "pciephy";
+
+            pinctrl-0 = <&pcie0_default_state>;
+            pinctrl-names = "default";
+
+            power-domains = <&gcc PCIE_0_GDSC>;
+
+            resets = <&gcc GCC_PCIE_0_BCR>;
+            reset-names = "pci";
+
+            perst-gpios = <&tlmm 35 GPIO_ACTIVE_HIGH>;
+            wake-gpios = <&tlmm 37 GPIO_ACTIVE_HIGH>;
+        };
+    };
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-sm8250.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-sm8250.yaml
new file mode 100644 (file)
index 0000000..4d060bc
--- /dev/null
@@ -0,0 +1,173 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/qcom,pcie-sm8250.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SM8250 PCI Express Root Complex
+
+maintainers:
+  - Bjorn Andersson <andersson@kernel.org>
+  - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+description:
+  Qualcomm SM8250 SoC PCIe root complex controller is based on the Synopsys
+  DesignWare PCIe IP.
+
+properties:
+  compatible:
+    const: qcom,pcie-sm8250
+
+  reg:
+    minItems: 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
+
+  clocks:
+    minItems: 8
+    maxItems: 9
+
+  clock-names:
+    # Unfortunately the "optional" ref clock is used in the middle of the list
+    oneOf:
+      - 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: ref # REFERENCE clock
+          - const: tbu # PCIe TBU clock
+          - const: ddrss_sf_tbu # PCIe SF TBU clock
+      - 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: tbu # PCIe TBU clock
+          - const: ddrss_sf_tbu # PCIe SF TBU clock
+
+  interrupts:
+    minItems: 8
+    maxItems: 8
+
+  interrupt-names:
+    items:
+      - const: msi0
+      - const: msi1
+      - const: msi2
+      - const: msi3
+      - const: msi4
+      - const: msi5
+      - const: msi6
+      - const: msi7
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    items:
+      - const: pci
+
+allOf:
+  - $ref: qcom,pcie-common.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,gcc-sm8250.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interconnect/qcom,sm8250.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        pcie@1c00000 {
+            compatible = "qcom,pcie-sm8250";
+            reg = <0 0x01c00000 0 0x3000>,
+                  <0 0x60000000 0 0xf1d>,
+                  <0 0x60000f20 0 0xa8>,
+                  <0 0x60001000 0 0x1000>,
+                  <0 0x60100000 0 0x100000>,
+                  <0 0x01c03000 0 0x1000>;
+            reg-names = "parf", "dbi", "elbi", "atu", "config", "mhi";
+            ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>,
+                     <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>;
+
+            bus-range = <0x00 0xff>;
+            device_type = "pci";
+            linux,pci-domain = <0>;
+            num-lanes = <1>;
+
+            #address-cells = <3>;
+            #size-cells = <2>;
+
+            clocks = <&gcc GCC_PCIE_0_PIPE_CLK>,
+                     <&gcc GCC_PCIE_0_AUX_CLK>,
+                     <&gcc GCC_PCIE_0_CFG_AHB_CLK>,
+                     <&gcc GCC_PCIE_0_MSTR_AXI_CLK>,
+                     <&gcc GCC_PCIE_0_SLV_AXI_CLK>,
+                     <&gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>,
+                     <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>,
+                     <&gcc GCC_DDRSS_PCIE_SF_TBU_CLK>;
+            clock-names = "pipe",
+                          "aux",
+                          "cfg",
+                          "bus_master",
+                          "bus_slave",
+                          "slave_q2a",
+                          "tbu",
+                          "ddrss_sf_tbu";
+
+            dma-coherent;
+
+            interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+            interrupt-names = "msi0", "msi1", "msi2", "msi3",
+                              "msi4", "msi5", "msi6", "msi7";
+            #interrupt-cells = <1>;
+            interrupt-map-mask = <0 0 0 0x7>;
+            interrupt-map = <0 0 0 1 &intc 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+                            <0 0 0 2 &intc 0 150 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+                            <0 0 0 3 &intc 0 151 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+                            <0 0 0 4 &intc 0 152 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+
+            iommu-map = <0x0 &apps_smmu 0x1c00 0x1>,
+                        <0x100 &apps_smmu 0x1c01 0x1>;
+
+            phys = <&pcie0_phy>;
+            phy-names = "pciephy";
+
+            pinctrl-0 = <&pcie0_default_state>;
+            pinctrl-names = "default";
+
+            power-domains = <&gcc PCIE_0_GDSC>;
+
+            resets = <&gcc GCC_PCIE_0_BCR>;
+            reset-names = "pci";
+
+            perst-gpios = <&tlmm 79 GPIO_ACTIVE_LOW>;
+            wake-gpios = <&tlmm 81 GPIO_ACTIVE_HIGH>;
+        };
+    };
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-sm8350.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-sm8350.yaml
new file mode 100644 (file)
index 0000000..9eb6e45
--- /dev/null
@@ -0,0 +1,184 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/qcom,pcie-sm8350.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SM8350 PCI Express Root Complex
+
+maintainers:
+  - Bjorn Andersson <andersson@kernel.org>
+  - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+description:
+  Qualcomm SM8350 SoC PCIe root complex controller is based on the Synopsys
+  DesignWare PCIe IP.
+
+properties:
+  compatible:
+    const: qcom,pcie-sm8350
+
+  reg:
+    minItems: 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
+
+  clocks:
+    minItems: 8
+    maxItems: 9
+
+  clock-names:
+    minItems: 8
+    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: tbu # PCIe TBU clock
+      - const: ddrss_sf_tbu # PCIe SF TBU clock
+      - const: aggre1 # Aggre NoC PCIe1 AXI clock
+      - const: aggre0 # Aggre NoC PCIe0 AXI clock
+
+  interrupts:
+    minItems: 8
+    maxItems: 8
+
+  interrupt-names:
+    items:
+      - const: msi0
+      - const: msi1
+      - const: msi2
+      - const: msi3
+      - const: msi4
+      - const: msi5
+      - const: msi6
+      - const: msi7
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    items:
+      - const: pci
+
+oneOf:
+  - properties:
+      interrupts:
+        maxItems: 1
+      interrupt-names:
+        items:
+          - const: msi
+
+  - properties:
+      interrupts:
+        minItems: 8
+      interrupt-names:
+        items:
+          - const: msi0
+          - const: msi1
+          - const: msi2
+          - const: msi3
+          - const: msi4
+          - const: msi5
+          - const: msi6
+          - const: msi7
+
+allOf:
+  - $ref: qcom,pcie-common.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,gcc-sm8350.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interconnect/qcom,sm8350.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        pcie@1c00000 {
+            compatible = "qcom,pcie-sm8350";
+            reg = <0 0x01c00000 0 0x3000>,
+                  <0 0x60000000 0 0xf1d>,
+                  <0 0x60000f20 0 0xa8>,
+                  <0 0x60001000 0 0x1000>,
+                  <0 0x60100000 0 0x100000>;
+            reg-names = "parf", "dbi", "elbi", "atu", "config";
+            ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>,
+                     <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>;
+
+            bus-range = <0x00 0xff>;
+            device_type = "pci";
+            linux,pci-domain = <0>;
+            num-lanes = <1>;
+
+            #address-cells = <3>;
+            #size-cells = <2>;
+
+            clocks = <&gcc GCC_PCIE_0_AUX_CLK>,
+                     <&gcc GCC_PCIE_0_CFG_AHB_CLK>,
+                     <&gcc GCC_PCIE_0_MSTR_AXI_CLK>,
+                     <&gcc GCC_PCIE_0_SLV_AXI_CLK>,
+                     <&gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>,
+                     <&gcc GCC_AGGRE_NOC_PCIE_TBU_CLK>,
+                     <&gcc GCC_DDRSS_PCIE_SF_TBU_CLK>,
+                     <&gcc GCC_AGGRE_NOC_PCIE_1_AXI_CLK>,
+                     <&gcc GCC_AGGRE_NOC_PCIE_0_AXI_CLK>;
+            clock-names = "aux",
+                          "cfg",
+                          "bus_master",
+                          "bus_slave",
+                          "slave_q2a",
+                          "tbu",
+                          "ddrss_sf_tbu",
+                          "aggre1",
+                          "aggre0";
+
+            interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+            interrupt-names = "msi0", "msi1", "msi2", "msi3",
+                              "msi4", "msi5", "msi6", "msi7";
+            #interrupt-cells = <1>;
+            interrupt-map-mask = <0 0 0 0x7>;
+            interrupt-map = <0 0 0 1 &intc 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+                            <0 0 0 2 &intc 0 150 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+                            <0 0 0 3 &intc 0 151 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+                            <0 0 0 4 &intc 0 152 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+
+            iommu-map = <0x0 &apps_smmu 0x1c00 0x1>,
+                        <0x100 &apps_smmu 0x1c01 0x1>;
+
+            phys = <&pcie0_phy>;
+            phy-names = "pciephy";
+
+            pinctrl-0 = <&pcie0_default_state>;
+            pinctrl-names = "default";
+
+            power-domains = <&gcc PCIE_0_GDSC>;
+
+            resets = <&gcc GCC_PCIE_0_BCR>;
+            reset-names = "pci";
+
+            perst-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
+            wake-gpios = <&tlmm 96 GPIO_ACTIVE_HIGH>;
+        };
+    };
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-sm8450.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-sm8450.yaml
new file mode 100644 (file)
index 0000000..1496d69
--- /dev/null
@@ -0,0 +1,178 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/qcom,pcie-sm8450.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SM8450 PCI Express Root Complex
+
+maintainers:
+  - Bjorn Andersson <andersson@kernel.org>
+  - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+description:
+  Qualcomm SM8450 SoC PCIe root complex controller is based on the Synopsys
+  DesignWare PCIe IP.
+
+properties:
+  compatible:
+    enum:
+      - qcom,pcie-sm8450-pcie0
+      - qcom,pcie-sm8450-pcie1
+
+  reg:
+    minItems: 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
+
+  clocks:
+    minItems: 11
+    maxItems: 12
+
+  clock-names:
+    minItems: 11
+    items:
+      - const: pipe # PIPE clock
+      - const: pipe_mux # PIPE MUX
+      - const: phy_pipe # PIPE output clock
+      - const: ref # REFERENCE 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: ddrss_sf_tbu # PCIe SF TBU clock
+      - enum: [aggre0, aggre1] # Aggre NoC PCIe0/1 AXI clock
+      - const: aggre1 # Aggre NoC PCIe1 AXI clock
+
+  interrupts:
+    minItems: 8
+    maxItems: 8
+
+  interrupt-names:
+    items:
+      - const: msi0
+      - const: msi1
+      - const: msi2
+      - const: msi3
+      - const: msi4
+      - const: msi5
+      - const: msi6
+      - const: msi7
+
+  resets:
+    maxItems: 1
+
+  reset-names:
+    items:
+      - const: pci
+
+allOf:
+  - $ref: qcom,pcie-common.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,gcc-sm8450.h>
+    #include <dt-bindings/clock/qcom,rpmh.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interconnect/qcom,sm8450.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        pcie@1c00000 {
+            compatible = "qcom,pcie-sm8450-pcie0";
+            reg = <0 0x01c00000 0 0x3000>,
+                  <0 0x60000000 0 0xf1d>,
+                  <0 0x60000f20 0 0xa8>,
+                  <0 0x60001000 0 0x1000>,
+                  <0 0x60100000 0 0x100000>;
+            reg-names = "parf", "dbi", "elbi", "atu", "config";
+            ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>,
+                     <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>;
+
+            bus-range = <0x00 0xff>;
+            device_type = "pci";
+            linux,pci-domain = <0>;
+            max-link-speed = <2>;
+            num-lanes = <1>;
+
+            #address-cells = <3>;
+            #size-cells = <2>;
+
+            clocks = <&gcc GCC_PCIE_0_PIPE_CLK>,
+                     <&gcc GCC_PCIE_0_PIPE_CLK_SRC>,
+                     <&pcie0_phy>,
+                     <&rpmhcc RPMH_CXO_CLK>,
+                     <&gcc GCC_PCIE_0_AUX_CLK>,
+                     <&gcc GCC_PCIE_0_CFG_AHB_CLK>,
+                     <&gcc GCC_PCIE_0_MSTR_AXI_CLK>,
+                     <&gcc GCC_PCIE_0_SLV_AXI_CLK>,
+                     <&gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>,
+                     <&gcc GCC_DDRSS_PCIE_SF_TBU_CLK>,
+                     <&gcc GCC_AGGRE_NOC_PCIE_0_AXI_CLK>,
+                     <&gcc GCC_AGGRE_NOC_PCIE_1_AXI_CLK>;
+            clock-names = "pipe",
+                          "pipe_mux",
+                          "phy_pipe",
+                          "ref",
+                          "aux",
+                          "cfg",
+                          "bus_master",
+                          "bus_slave",
+                          "slave_q2a",
+                          "ddrss_sf_tbu",
+                          "aggre0",
+                          "aggre1";
+
+            interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+            interrupt-names = "msi0", "msi1", "msi2", "msi3",
+                              "msi4", "msi5", "msi6", "msi7";
+            #interrupt-cells = <1>;
+            interrupt-map-mask = <0 0 0 0x7>;
+            interrupt-map = <0 0 0 1 &intc 0 0 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+                            <0 0 0 2 &intc 0 0 0 150 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+                            <0 0 0 3 &intc 0 0 0 151 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+                            <0 0 0 4 &intc 0 0 0 152 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+            msi-map = <0x0 &gic_its 0x5981 0x1>,
+                      <0x100 &gic_its 0x5980 0x1>;
+            msi-map-mask = <0xff00>;
+
+            iommu-map = <0x0 &apps_smmu 0x1c00 0x1>,
+                        <0x100 &apps_smmu 0x1c01 0x1>;
+
+            phys = <&pcie0_phy>;
+            phy-names = "pciephy";
+
+            pinctrl-0 = <&pcie0_default_state>;
+            pinctrl-names = "default";
+
+            power-domains = <&gcc PCIE_0_GDSC>;
+
+            resets = <&gcc GCC_PCIE_0_BCR>;
+            reset-names = "pci";
+
+            perst-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
+            wake-gpios = <&tlmm 96 GPIO_ACTIVE_HIGH>;
+        };
+    };
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-sm8550.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-sm8550.yaml
new file mode 100644 (file)
index 0000000..24cb386
--- /dev/null
@@ -0,0 +1,171 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/qcom,pcie-sm8550.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SM8550 PCI Express Root Complex
+
+maintainers:
+  - Bjorn Andersson <andersson@kernel.org>
+  - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+description:
+  Qualcomm SM8550 SoC (and compatible) PCIe root complex controller is based on
+  the Synopsys DesignWare PCIe IP.
+
+properties:
+  compatible:
+    oneOf:
+      - const: qcom,pcie-sm8550
+      - items:
+          - enum:
+              - qcom,pcie-sm8650
+          - const: qcom,pcie-sm8550
+
+  reg:
+    minItems: 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
+
+  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
+
+  interrupts:
+    minItems: 8
+    maxItems: 8
+
+  interrupt-names:
+    items:
+      - const: msi0
+      - const: msi1
+      - const: msi2
+      - const: msi3
+      - const: msi4
+      - const: msi5
+      - const: msi6
+      - const: msi7
+
+  resets:
+    minItems: 1
+    maxItems: 2
+
+  reset-names:
+    minItems: 1
+    items:
+      - const: pci # PCIe core reset
+      - const: link_down # PCIe link down reset
+
+allOf:
+  - $ref: qcom,pcie-common.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,sm8550-gcc.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interconnect/qcom,sm8550-rpmh.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        pcie@1c00000 {
+            compatible = "qcom,pcie-sm8550";
+            reg = <0 0x01c00000 0 0x3000>,
+                  <0 0x60000000 0 0xf1d>,
+                  <0 0x60000f20 0 0xa8>,
+                  <0 0x60001000 0 0x1000>,
+                  <0 0x60100000 0 0x100000>;
+            reg-names = "parf", "dbi", "elbi", "atu", "config";
+            ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>,
+                     <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>;
+
+            bus-range = <0x00 0xff>;
+            device_type = "pci";
+            linux,pci-domain = <0>;
+            num-lanes = <2>;
+
+            #address-cells = <3>;
+            #size-cells = <2>;
+
+            clocks = <&gcc GCC_PCIE_0_AUX_CLK>,
+                     <&gcc GCC_PCIE_0_CFG_AHB_CLK>,
+                     <&gcc GCC_PCIE_0_MSTR_AXI_CLK>,
+                     <&gcc GCC_PCIE_0_SLV_AXI_CLK>,
+                     <&gcc GCC_PCIE_0_SLV_Q2A_AXI_CLK>,
+                     <&gcc GCC_DDRSS_PCIE_SF_QTB_CLK>,
+                     <&gcc GCC_AGGRE_NOC_PCIE_AXI_CLK>;
+            clock-names = "aux",
+                          "cfg",
+                          "bus_master",
+                          "bus_slave",
+                          "slave_q2a",
+                          "ddrss_sf_tbu",
+                          "noc_aggr";
+
+            dma-coherent;
+
+            interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+            interrupt-names = "msi0", "msi1", "msi2", "msi3",
+                              "msi4", "msi5", "msi6", "msi7";
+            #interrupt-cells = <1>;
+            interrupt-map-mask = <0 0 0 0x7>;
+            interrupt-map = <0 0 0 1 &intc 0 0 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+                            <0 0 0 2 &intc 0 0 0 150 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+                            <0 0 0 3 &intc 0 0 0 151 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+                            <0 0 0 4 &intc 0 0 0 152 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+
+            interconnects = <&pcie_noc MASTER_PCIE_0 0 &mc_virt SLAVE_EBI1 0>,
+                            <&gem_noc MASTER_APPSS_PROC 0 &cnoc_main SLAVE_PCIE_0 0>;
+            interconnect-names = "pcie-mem", "cpu-pcie";
+
+            iommu-map = <0x0 &apps_smmu 0x1400 0x1>,
+                        <0x100 &apps_smmu 0x1401 0x1>;
+
+            phys = <&pcie0_phy>;
+            phy-names = "pciephy";
+
+            pinctrl-0 = <&pcie0_default_state>;
+            pinctrl-names = "default";
+
+            power-domains = <&gcc PCIE_0_GDSC>;
+
+            resets = <&gcc GCC_PCIE_0_BCR>;
+            reset-names = "pci";
+
+            perst-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
+            wake-gpios = <&tlmm 96 GPIO_ACTIVE_HIGH>;
+        };
+    };
diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie-x1e80100.yaml b/Documentation/devicetree/bindings/pci/qcom,pcie-x1e80100.yaml
new file mode 100644 (file)
index 0000000..1074310
--- /dev/null
@@ -0,0 +1,165 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/qcom,pcie-x1e80100.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm X1E80100 PCI Express Root Complex
+
+maintainers:
+  - Bjorn Andersson <andersson@kernel.org>
+  - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+description:
+  Qualcomm X1E80100 SoC (and compatible) PCIe root complex controller is based on
+  the Synopsys DesignWare PCIe IP.
+
+properties:
+  compatible:
+    const: qcom,pcie-x1e80100
+
+  reg:
+    minItems: 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
+
+  clocks:
+    minItems: 7
+    maxItems: 7
+
+  clock-names:
+    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: noc_aggr # Aggre NoC PCIe AXI clock
+      - const: cnoc_sf_axi # Config NoC PCIe1 AXI clock
+
+  interrupts:
+    minItems: 8
+    maxItems: 8
+
+  interrupt-names:
+    items:
+      - const: msi0
+      - const: msi1
+      - const: msi2
+      - const: msi3
+      - const: msi4
+      - const: msi5
+      - const: msi6
+      - const: msi7
+
+  resets:
+    minItems: 1
+    maxItems: 2
+
+  reset-names:
+    minItems: 1
+    items:
+      - const: pci # PCIe core reset
+      - const: link_down # PCIe link down reset
+
+allOf:
+  - $ref: qcom,pcie-common.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/qcom,x1e80100-gcc.h>
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interconnect/qcom,x1e80100-rpmh.h>
+    #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+    soc {
+        #address-cells = <2>;
+        #size-cells = <2>;
+
+        pcie@1c08000 {
+            compatible = "qcom,pcie-x1e80100";
+            reg = <0 0x01c08000 0 0x3000>,
+                  <0 0x7c000000 0 0xf1d>,
+                  <0 0x7c000f40 0 0xa8>,
+                  <0 0x7c001000 0 0x1000>,
+                  <0 0x7c100000 0 0x100000>,
+                  <0 0x01c0b000 0 0x1000>;
+            reg-names = "parf", "dbi", "elbi", "atu", "config", "mhi";
+            ranges = <0x01000000 0x0 0x00000000 0x0 0x60200000 0x0 0x100000>,
+                     <0x02000000 0x0 0x60300000 0x0 0x60300000 0x0 0x3d00000>;
+
+            bus-range = <0x00 0xff>;
+            device_type = "pci";
+            linux,pci-domain = <0>;
+            num-lanes = <2>;
+
+            #address-cells = <3>;
+            #size-cells = <2>;
+
+            clocks = <&gcc GCC_PCIE_4_AUX_CLK>,
+                     <&gcc GCC_PCIE_4_CFG_AHB_CLK>,
+                     <&gcc GCC_PCIE_4_MSTR_AXI_CLK>,
+                     <&gcc GCC_PCIE_4_SLV_AXI_CLK>,
+                     <&gcc GCC_PCIE_4_SLV_Q2A_AXI_CLK>,
+                     <&gcc GCC_CFG_NOC_PCIE_ANOC_NORTH_AHB_CLK>,
+                     <&gcc GCC_CNOC_PCIE_NORTH_SF_AXI_CLK>;
+            clock-names = "aux",
+                          "cfg",
+                          "bus_master",
+                          "bus_slave",
+                          "slave_q2a",
+                          "noc_aggr",
+                          "cnoc_sf_axi";
+
+            dma-coherent;
+
+            interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+                         <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+            interrupt-names = "msi0", "msi1", "msi2", "msi3",
+                              "msi4", "msi5", "msi6", "msi7";
+            #interrupt-cells = <1>;
+            interrupt-map-mask = <0 0 0 0x7>;
+            interrupt-map = <0 0 0 1 &intc 0 0 0 149 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
+                            <0 0 0 2 &intc 0 0 0 150 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
+                            <0 0 0 3 &intc 0 0 0 151 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
+                            <0 0 0 4 &intc 0 0 0 152 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
+
+            interconnects = <&pcie_noc MASTER_PCIE_4 0 &mc_virt SLAVE_EBI1 0>,
+                            <&gem_noc MASTER_APPSS_PROC 0 &cnoc_main SLAVE_PCIE_4 0>;
+            interconnect-names = "pcie-mem", "cpu-pcie";
+
+            iommu-map = <0x0 &apps_smmu 0x1400 0x1>,
+                        <0x100 &apps_smmu 0x1401 0x1>;
+
+            phys = <&pcie4_phy>;
+            phy-names = "pciephy";
+
+            pinctrl-0 = <&pcie0_default_state>;
+            pinctrl-names = "default";
+
+            power-domains = <&gcc GCC_PCIE_4_GDSC>;
+
+            resets = <&gcc GCC_PCIE_4_BCR>;
+            reset-names = "pci";
+
+            perst-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
+            wake-gpios = <&tlmm 96 GPIO_ACTIVE_HIGH>;
+        };
+    };
index a93ab3b540666427adb21a2f1631f3a315a0a0c6..cf9a6910b542f0b9529cdcedb6740a820b397f91 100644 (file)
@@ -28,23 +28,8 @@ properties:
           - qcom,pcie-ipq8074-gen3
           - qcom,pcie-msm8996
           - qcom,pcie-qcs404
-          - qcom,pcie-sa8540p
-          - qcom,pcie-sa8775p
-          - qcom,pcie-sc7280
-          - 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:
-          - enum:
-              - qcom,pcie-sm8650
-          - const: qcom,pcie-sm8550
       - items:
           - const: qcom,pcie-msm8998
           - const: qcom,pcie-msm8996
@@ -106,9 +91,6 @@ properties:
   vdda_refclk-supply:
     description: A phandle to the core analog power supply for IC which generates reference clock
 
-  vddpe-3v3-supply:
-    description: A phandle to the PCIe endpoint power supply
-
   phys:
     maxItems: 1
 
@@ -123,6 +105,9 @@ properties:
     description: GPIO controlled connection to PERST# signal
     maxItems: 1
 
+  required-opps:
+    maxItems: 1
+
   wake-gpios:
     description: GPIO controlled connection to WAKE# signal
     maxItems: 1
@@ -143,7 +128,6 @@ anyOf:
       - "#interrupt-cells"
   - required:
       - msi-map
-      - msi-map-mask
 
 allOf:
   - $ref: /schemas/pci/pci-bus.yaml#
@@ -217,16 +201,7 @@ allOf:
         compatible:
           contains:
             enum:
-              - qcom,pcie-sa8775p
-              - 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:
@@ -451,65 +426,6 @@ allOf:
             - const: pwr # PWR reset
             - const: ahb # AHB reset
 
-  - if:
-      properties:
-        compatible:
-          contains:
-            enum:
-              - qcom,pcie-sc7280
-    then:
-      properties:
-        clocks:
-          minItems: 13
-          maxItems: 13
-        clock-names:
-          items:
-            - const: pipe # PIPE clock
-            - const: pipe_mux # PIPE MUX
-            - const: phy_pipe # PIPE output clock
-            - const: ref # REFERENCE 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: tbu # PCIe TBU clock
-            - const: ddrss_sf_tbu # PCIe SF TBU clock
-            - const: aggre0 # Aggre NoC PCIe CENTER SF AXI clock
-            - const: aggre1 # Aggre NoC PCIe1 AXI clock
-        resets:
-          maxItems: 1
-        reset-names:
-          items:
-            - const: pci # PCIe core reset
-
-  - if:
-      properties:
-        compatible:
-          contains:
-            enum:
-              - qcom,pcie-sc8180x
-    then:
-      properties:
-        clocks:
-          minItems: 8
-          maxItems: 8
-        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: ref # REFERENCE clock
-            - const: tbu # PCIe TBU clock
-        resets:
-          maxItems: 1
-        reset-names:
-          items:
-            - const: pci # PCIe core reset
-
   - if:
       properties:
         compatible:
@@ -553,229 +469,6 @@ allOf:
           items:
             - const: pci # PCIe core reset
 
-  - if:
-      properties:
-        compatible:
-          contains:
-            enum:
-              - qcom,pcie-sm8150
-    then:
-      properties:
-        clocks:
-          minItems: 8
-          maxItems: 8
-        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: tbu # PCIe TBU clock
-            - const: ref # REFERENCE clock
-        resets:
-          maxItems: 1
-        reset-names:
-          items:
-            - const: pci # PCIe core reset
-
-  - if:
-      properties:
-        compatible:
-          contains:
-            enum:
-              - qcom,pcie-sm8250
-    then:
-      oneOf:
-          # Unfortunately the "optional" ref clock is used in the middle of the list
-        - properties:
-            clocks:
-              minItems: 9
-              maxItems: 9
-            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: ref # REFERENCE clock
-                - const: tbu # PCIe TBU clock
-                - const: ddrss_sf_tbu # PCIe SF TBU clock
-        - properties:
-            clocks:
-              minItems: 8
-              maxItems: 8
-            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: tbu # PCIe TBU clock
-                - const: ddrss_sf_tbu # PCIe SF TBU clock
-      properties:
-        resets:
-          maxItems: 1
-        reset-names:
-          items:
-            - const: pci # PCIe core reset
-
-  - if:
-      properties:
-        compatible:
-          contains:
-            enum:
-              - qcom,pcie-sm8350
-    then:
-      properties:
-        clocks:
-          minItems: 8
-          maxItems: 9
-        clock-names:
-          minItems: 8
-          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: tbu # PCIe TBU clock
-            - const: ddrss_sf_tbu # PCIe SF TBU clock
-            - const: aggre1 # Aggre NoC PCIe1 AXI clock
-            - const: aggre0 # Aggre NoC PCIe0 AXI clock
-        resets:
-          maxItems: 1
-        reset-names:
-          items:
-            - const: pci # PCIe core reset
-
-  - if:
-      properties:
-        compatible:
-          contains:
-            enum:
-              - qcom,pcie-sm8450-pcie0
-    then:
-      properties:
-        clocks:
-          minItems: 12
-          maxItems: 12
-        clock-names:
-          items:
-            - const: pipe # PIPE clock
-            - const: pipe_mux # PIPE MUX
-            - const: phy_pipe # PIPE output clock
-            - const: ref # REFERENCE 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: ddrss_sf_tbu # PCIe SF TBU clock
-            - const: aggre0 # Aggre NoC PCIe0 AXI clock
-            - const: aggre1 # Aggre NoC PCIe1 AXI clock
-        resets:
-          maxItems: 1
-        reset-names:
-          items:
-            - const: pci # PCIe core reset
-
-  - if:
-      properties:
-        compatible:
-          contains:
-            enum:
-              - qcom,pcie-sm8450-pcie1
-    then:
-      properties:
-        clocks:
-          minItems: 11
-          maxItems: 11
-        clock-names:
-          items:
-            - const: pipe # PIPE clock
-            - const: pipe_mux # PIPE MUX
-            - const: phy_pipe # PIPE output clock
-            - const: ref # REFERENCE 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: ddrss_sf_tbu # PCIe SF TBU clock
-            - const: aggre1 # Aggre NoC PCIe1 AXI clock
-        resets:
-          maxItems: 1
-        reset-names:
-          items:
-            - const: pci # PCIe core reset
-
-  - if:
-      properties:
-        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:
-      properties:
-        clocks:
-          minItems: 8
-          maxItems: 9
-        clock-names:
-          minItems: 8
-          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_4 # NoC aggregate 4 clock
-            - const: noc_aggr_south_sf # NoC aggregate South SF clock
-            - const: cnoc_qx # Configuration NoC QX clock
-        resets:
-          maxItems: 1
-        reset-names:
-          items:
-            - const: pci # PCIe core reset
-
   - if:
       properties:
         compatible:
@@ -802,43 +495,6 @@ allOf:
           items:
             - const: pci # PCIe core reset
 
-  - if:
-      properties:
-        compatible:
-          contains:
-            enum:
-              - qcom,pcie-sa8775p
-    then:
-      properties:
-        clocks:
-          minItems: 5
-          maxItems: 5
-        clock-names:
-          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
-        resets:
-          maxItems: 1
-        reset-names:
-          items:
-            - const: pci # PCIe core reset
-
-  - if:
-      properties:
-        compatible:
-          contains:
-            enum:
-              - qcom,pcie-sa8540p
-              - qcom,pcie-sa8775p
-              - qcom,pcie-sc8280xp
-    then:
-      required:
-        - interconnects
-        - interconnect-names
-
   - if:
       not:
         properties:
@@ -874,16 +530,7 @@ allOf:
           contains:
             enum:
               - qcom,pcie-msm8996
-              - qcom,pcie-sa8775p
-              - qcom,pcie-sc7280
-              - qcom,pcie-sc8180x
               - qcom,pcie-sdm845
-              - qcom,pcie-sm8150
-              - qcom,pcie-sm8250
-              - qcom,pcie-sm8350
-              - qcom,pcie-sm8450-pcie0
-              - qcom,pcie-sm8450-pcie1
-              - qcom,pcie-sm8550
     then:
       oneOf:
         - properties:
@@ -906,24 +553,6 @@ allOf:
                 - const: msi6
                 - const: msi7
 
-  - if:
-      properties:
-        compatible:
-          contains:
-            enum:
-              - qcom,pcie-sc8280xp
-    then:
-      properties:
-        interrupts:
-          minItems: 4
-          maxItems: 4
-        interrupt-names:
-          items:
-            - const: msi0
-            - const: msi1
-            - const: msi2
-            - const: msi3
-
   - if:
       properties:
         compatible:
@@ -938,7 +567,6 @@ allOf:
               - qcom,pcie-ipq8074
               - qcom,pcie-ipq8074-gen3
               - qcom,pcie-qcs404
-              - qcom,pcie-sa8540p
     then:
       properties:
         interrupts:
index d55384b106bd4ef7e4c41b77ea58624dbda88688..5c7e8194bef92bcb5c3c807852a3b21b04337728 100644 (file)
@@ -517,6 +517,3 @@ Public Functions Provided
 
 .. kernel-doc:: arch/x86/include/asm/io.h
    :internal:
-
-.. kernel-doc:: lib/pci_iomap.c
-   :export:
index 4843cfad4f60bb43a189fbe0da135b9241c4bff3..aa40b1cc243b84d0485499e977c33dce056053ab 100644 (file)
@@ -4,6 +4,12 @@ PCI Support Library
 .. kernel-doc:: drivers/pci/pci.c
    :export:
 
+.. kernel-doc:: drivers/pci/iomap.c
+   :export:
+
+.. kernel-doc:: drivers/pci/devres.c
+   :export:
+
 .. kernel-doc:: drivers/pci/pci-driver.c
    :export:
 
index 5194176c7c98ad3c6038a8a212bed232b45f0588..4bce9cfedfbada937e55257f3198cd15742c86f6 100644 (file)
@@ -17018,7 +17018,6 @@ F:      include/asm-generic/pci*
 F:     include/linux/of_pci.h
 F:     include/linux/pci*
 F:     include/uapi/linux/pci*
-F:     lib/pci*
 
 PCIE DRIVER FOR AMAZON ANNAPURNA LABS
 M:     Jonathan Chocron <jonnyc@amazon.com>
index f347c20247d307752ab8260b94654aa988816de1..b33afb240601b006d5fd27b5245fed16354f3f71 100644 (file)
@@ -907,6 +907,54 @@ static void chromeos_fixup_apl_pci_l1ss_capability(struct pci_dev *dev)
 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);
 
+/*
+ * Disable D3cold on Asus B1400 PCI-NVMe bridge
+ *
+ * On this platform with VMD off, the NVMe device cannot successfully power
+ * back on from D3cold. This appears to be an untested transition by the
+ * vendor: Windows leaves the NVMe and parent bridge in D0 during suspend.
+ *
+ * We disable D3cold on the parent bridge for simplicity, and the fact that
+ * both parent bridge and NVMe device share the same power resource.
+ *
+ * This is only needed on BIOS versions before 308; the newer versions flip
+ * StorageD3Enable from 1 to 0.
+ */
+static const struct dmi_system_id asus_nvme_broken_d3cold_table[] = {
+       {
+               .matches = {
+                               DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                               DMI_MATCH(DMI_BIOS_VERSION, "B1400CEAE.304"),
+               },
+       },
+       {
+               .matches = {
+                               DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                               DMI_MATCH(DMI_BIOS_VERSION, "B1400CEAE.305"),
+               },
+       },
+       {
+               .matches = {
+                               DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                               DMI_MATCH(DMI_BIOS_VERSION, "B1400CEAE.306"),
+               },
+       },
+       {
+               .matches = {
+                               DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                               DMI_MATCH(DMI_BIOS_VERSION, "B1400CEAE.307"),
+               },
+       },
+       {}
+};
+
+static void asus_disable_nvme_d3cold(struct pci_dev *pdev)
+{
+       if (dmi_check_system(asus_nvme_broken_d3cold_table) > 0)
+               pci_d3cold_disable(pdev);
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x9a09, asus_disable_nvme_d3cold);
+
 #ifdef CONFIG_SUSPEND
 /*
  * Root Ports on some AMD SoCs advertise PME_Support for D3hot and D3cold, but
index 808484d11209761d93e10a6e4937a3e4a75d34b2..728acfeb774d8327bc24108c2401bc46920c8d0c 100644 (file)
@@ -385,18 +385,6 @@ static const struct dmi_system_id acpisleep_dmi_table[] __initconst = {
                DMI_MATCH(DMI_PRODUCT_NAME, "20GGA00L00"),
                },
        },
-       /*
-        * ASUS B1400CEAE hangs on resume from suspend (see
-        * https://bugzilla.kernel.org/show_bug.cgi?id=215742).
-        */
-       {
-       .callback = init_default_s3,
-       .ident = "ASUS B1400CEAE",
-       .matches = {
-               DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
-               DMI_MATCH(DMI_PRODUCT_NAME, "ASUS EXPERTBOOK B1400CEAE"),
-               },
-       },
        {},
 };
 
index 9b3884ff81e699f2308a3cf618e774ad9a67e6a3..7d2cdd9e222740964b488cbc0fd33c559677c652 100644 (file)
@@ -445,8 +445,8 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
                printk("%saer_uncor_severity: 0x%08x\n",
                       pfx, aer->uncor_severity);
                printk("%sTLP Header: %08x %08x %08x %08x\n", pfx,
-                      aer->header_log.dw0, aer->header_log.dw1,
-                      aer->header_log.dw2, aer->header_log.dw3);
+                      aer->header_log.dw[0], aer->header_log.dw[1],
+                      aer->header_log.dw[2], aer->header_log.dw[3]);
        }
 }
 
index 27dd93deff6e561bea171f4695dbd8b975df6c0c..d702bee7808266e3ee04fd49a2c157a3413bc9b2 100644 (file)
@@ -100,6 +100,8 @@ EXPORT_SYMBOL(ntb_unregister_client);
 
 int ntb_register_device(struct ntb_dev *ntb)
 {
+       int ret;
+
        if (!ntb)
                return -EINVAL;
        if (!ntb->pdev)
@@ -120,7 +122,11 @@ int ntb_register_device(struct ntb_dev *ntb)
        ntb->ctx_ops = NULL;
        spin_lock_init(&ntb->ctx_lock);
 
-       return device_register(&ntb->dev);
+       ret = device_register(&ntb->dev);
+       if (ret)
+               put_device(&ntb->dev);
+
+       return ret;
 }
 EXPORT_SYMBOL(ntb_register_device);
 
index 74147262625bc2f899928feeaf643ea5f9f7fcd7..d35001589d88f85a56541d20b6ba4dd7088d2138 100644 (file)
@@ -13,6 +13,11 @@ config FORCE_PCI
        select HAVE_PCI
        select PCI
 
+# select this to provide a generic PCI iomap,
+# without PCI itself having to be defined
+config GENERIC_PCI_IOMAP
+       bool
+
 menuconfig PCI
        bool "PCI support"
        depends on HAVE_PCI
index cc8b4e01e29de5439c1671896d5dd53f77a3b9c4..1753020368909e1f8e770ef171ff7d7c1bf40437 100644 (file)
@@ -4,16 +4,17 @@
 
 obj-$(CONFIG_PCI)              += access.o bus.o probe.o host-bridge.o \
                                   remove.o pci.o pci-driver.o search.o \
-                                  pci-sysfs.o rom.o setup-res.o irq.o vpd.o \
-                                  setup-bus.o vc.o mmap.o setup-irq.o
+                                  rom.o setup-res.o irq.o vpd.o \
+                                  setup-bus.o vc.o mmap.o devres.o
 
 obj-$(CONFIG_PCI)              += msi/
 obj-$(CONFIG_PCI)              += pcie/
 
 ifdef CONFIG_PCI
 obj-$(CONFIG_PROC_FS)          += proc.o
-obj-$(CONFIG_SYSFS)            += slot.o
+obj-$(CONFIG_SYSFS)            += pci-sysfs.o slot.o
 obj-$(CONFIG_ACPI)             += pci-acpi.o
+obj-$(CONFIG_GENERIC_PCI_IOMAP) += iomap.o
 endif
 
 obj-$(CONFIG_OF)               += of.o
index 2d0a8d78bffb525f45e7939561f5427e82e6062e..81c50dc64da96f4c7182e9fc3b19a22d6d04ea0d 100644 (file)
@@ -565,7 +565,8 @@ static int cdns_pcie_ep_start(struct pci_epc *epc)
        struct cdns_pcie *pcie = &ep->pcie;
        struct device *dev = pcie->dev;
        int max_epfs = sizeof(epc->function_num_map) * 8;
-       int ret, value, epf;
+       int ret, epf, last_fn;
+       u32 reg, value;
 
        /*
         * BIT(0) is hardwired to 1, hence function 0 is always enabled
@@ -573,6 +574,17 @@ static int cdns_pcie_ep_start(struct pci_epc *epc)
         */
        cdns_pcie_writel(pcie, CDNS_PCIE_LM_EP_FUNC_CFG, epc->function_num_map);
 
+       /*
+        * Next function field in ARI_CAP_AND_CTR register for last function
+        * should be 0.
+        * Clearing Next Function Number field for the last function used.
+        */
+       last_fn = find_last_bit(&epc->function_num_map, BITS_PER_LONG);
+       reg     = CDNS_PCIE_CORE_PF_I_ARI_CAP_AND_CTRL(last_fn);
+       value  = cdns_pcie_readl(pcie, reg);
+       value &= ~CDNS_PCIE_ARI_CAP_NFN_MASK;
+       cdns_pcie_writel(pcie, reg, value);
+
        if (ep->quirk_disable_flr) {
                for (epf = 0; epf < max_epfs; epf++) {
                        if (!(epc->function_num_map & BIT(epf)))
index 03b96798f858cbad49485cb83016aeef95866d1a..7a66a2f815dcea38c78b1f172f54d7cdd5deb5ad 100644 (file)
 #define CDNS_PCIE_EP_FUNC_DEV_CAP_OFFSET       0xc0
 #define CDNS_PCIE_EP_FUNC_SRIOV_CAP_OFFSET     0x200
 
+/*
+ * Endpoint PF Registers
+ */
+#define CDNS_PCIE_CORE_PF_I_ARI_CAP_AND_CTRL(fn)       (0x144 + (fn) * 0x1000)
+#define CDNS_PCIE_ARI_CAP_NFN_MASK                     GENMASK(15, 8)
+
 /*
  * Root Port Registers (PCI configuration space for the root port function)
  */
index dc2c036ab28cb64a2174a73b367cfe5016534123..99a60270b26cdf16f28c3b0ceb61d8c19b68ff30 100644 (file)
 #define IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE    GENMASK(11, 8)
 #define IMX8MQ_PCIE2_BASE_ADDR                 0x33c00000
 
+#define IMX95_PCIE_PHY_GEN_CTRL                        0x0
+#define IMX95_PCIE_REF_USE_PAD                 BIT(17)
+
+#define IMX95_PCIE_SS_RW_REG_0                 0xf0
+#define IMX95_PCIE_REF_CLKEN                   BIT(23)
+#define IMX95_PCIE_PHY_CR_PARA_SEL             BIT(9)
+
+#define IMX95_PE0_GEN_CTRL_1                   0x1050
+#define IMX95_PCIE_DEVICE_TYPE                 GENMASK(3, 0)
+
+#define IMX95_PE0_GEN_CTRL_3                   0x1058
+#define IMX95_PCIE_LTSSM_EN                    BIT(0)
+
 #define to_imx6_pcie(x)        dev_get_drvdata((x)->dev)
 
 enum imx6_pcie_variants {
@@ -52,14 +65,29 @@ enum imx6_pcie_variants {
        IMX8MQ,
        IMX8MM,
        IMX8MP,
+       IMX95,
        IMX8MQ_EP,
        IMX8MM_EP,
        IMX8MP_EP,
+       IMX95_EP,
 };
 
 #define IMX6_PCIE_FLAG_IMX6_PHY                        BIT(0)
 #define IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE       BIT(1)
 #define IMX6_PCIE_FLAG_SUPPORTS_SUSPEND                BIT(2)
+#define IMX6_PCIE_FLAG_HAS_PHYDRV                      BIT(3)
+#define IMX6_PCIE_FLAG_HAS_APP_RESET           BIT(4)
+#define IMX6_PCIE_FLAG_HAS_PHY_RESET           BIT(5)
+#define IMX6_PCIE_FLAG_HAS_SERDES              BIT(6)
+#define IMX6_PCIE_FLAG_SUPPORT_64BIT           BIT(7)
+
+#define imx6_check_flag(pci, val)     (pci->drvdata->flags & val)
+
+#define IMX6_PCIE_MAX_CLKS       6
+
+#define IMX6_PCIE_MAX_INSTANCES                        2
+
+struct imx6_pcie;
 
 struct imx6_pcie_drvdata {
        enum imx6_pcie_variants variant;
@@ -67,6 +95,14 @@ struct imx6_pcie_drvdata {
        u32 flags;
        int dbi_length;
        const char *gpr;
+       const char * const *clk_names;
+       const u32 clks_cnt;
+       const u32 ltssm_off;
+       const u32 ltssm_mask;
+       const u32 mode_off[IMX6_PCIE_MAX_INSTANCES];
+       const u32 mode_mask[IMX6_PCIE_MAX_INSTANCES];
+       const struct pci_epc_features *epc_features;
+       int (*init_phy)(struct imx6_pcie *pcie);
 };
 
 struct imx6_pcie {
@@ -74,11 +110,7 @@ struct imx6_pcie {
        int                     reset_gpio;
        bool                    gpio_active_high;
        bool                    link_is_up;
-       struct clk              *pcie_bus;
-       struct clk              *pcie_phy;
-       struct clk              *pcie_inbound_axi;
-       struct clk              *pcie;
-       struct clk              *pcie_aux;
+       struct clk_bulk_data    clks[IMX6_PCIE_MAX_CLKS];
        struct regmap           *iomuxc_gpr;
        u16                     msi_ctrl;
        u32                     controller_id;
@@ -165,34 +197,44 @@ static unsigned int imx6_pcie_grp_offset(const struct imx6_pcie *imx6_pcie)
        return imx6_pcie->controller_id == 1 ? IOMUXC_GPR16 : IOMUXC_GPR14;
 }
 
+static int imx95_pcie_init_phy(struct imx6_pcie *imx6_pcie)
+{
+       regmap_update_bits(imx6_pcie->iomuxc_gpr,
+                       IMX95_PCIE_SS_RW_REG_0,
+                       IMX95_PCIE_PHY_CR_PARA_SEL,
+                       IMX95_PCIE_PHY_CR_PARA_SEL);
+
+       regmap_update_bits(imx6_pcie->iomuxc_gpr,
+                          IMX95_PCIE_PHY_GEN_CTRL,
+                          IMX95_PCIE_REF_USE_PAD, 0);
+       regmap_update_bits(imx6_pcie->iomuxc_gpr,
+                          IMX95_PCIE_SS_RW_REG_0,
+                          IMX95_PCIE_REF_CLKEN,
+                          IMX95_PCIE_REF_CLKEN);
+
+       return 0;
+}
+
 static void imx6_pcie_configure_type(struct imx6_pcie *imx6_pcie)
 {
-       unsigned int mask, val, mode;
+       const struct imx6_pcie_drvdata *drvdata = imx6_pcie->drvdata;
+       unsigned int mask, val, mode, id;
 
-       if (imx6_pcie->drvdata->mode == DW_PCIE_EP_TYPE)
+       if (drvdata->mode == DW_PCIE_EP_TYPE)
                mode = PCI_EXP_TYPE_ENDPOINT;
        else
                mode = PCI_EXP_TYPE_ROOT_PORT;
 
-       switch (imx6_pcie->drvdata->variant) {
-       case IMX8MQ:
-       case IMX8MQ_EP:
-               if (imx6_pcie->controller_id == 1) {
-                       mask = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE;
-                       val  = FIELD_PREP(IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE,
-                                         mode);
-               } else {
-                       mask = IMX6Q_GPR12_DEVICE_TYPE;
-                       val  = FIELD_PREP(IMX6Q_GPR12_DEVICE_TYPE, mode);
-               }
-               break;
-       default:
-               mask = IMX6Q_GPR12_DEVICE_TYPE;
-               val  = FIELD_PREP(IMX6Q_GPR12_DEVICE_TYPE, mode);
-               break;
-       }
+       id = imx6_pcie->controller_id;
+
+       /* If mode_mask[id] is zero, means each controller have its individual gpr */
+       if (!drvdata->mode_mask[id])
+               id = 0;
+
+       mask = drvdata->mode_mask[id];
+       val = mode << (ffs(mask) - 1);
 
-       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, mask, val);
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, drvdata->mode_off[id], mask, val);
 }
 
 static int pcie_phy_poll_ack(struct imx6_pcie *imx6_pcie, bool exp_val)
@@ -320,76 +362,66 @@ static int pcie_phy_write(struct imx6_pcie *imx6_pcie, int addr, u16 data)
        return 0;
 }
 
-static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
+static int imx8mq_pcie_init_phy(struct imx6_pcie *imx6_pcie)
 {
-       switch (imx6_pcie->drvdata->variant) {
-       case IMX8MM:
-       case IMX8MM_EP:
-       case IMX8MP:
-       case IMX8MP_EP:
-               /*
-                * The PHY initialization had been done in the PHY
-                * driver, break here directly.
-                */
-               break;
-       case IMX8MQ:
-       case IMX8MQ_EP:
-               /*
-                * TODO: Currently this code assumes external
-                * oscillator is being used
-                */
+       /* TODO: Currently this code assumes external oscillator is being used */
+       regmap_update_bits(imx6_pcie->iomuxc_gpr,
+                          imx6_pcie_grp_offset(imx6_pcie),
+                          IMX8MQ_GPR_PCIE_REF_USE_PAD,
+                          IMX8MQ_GPR_PCIE_REF_USE_PAD);
+       /*
+        * Regarding the datasheet, the PCIE_VPH is suggested to be 1.8V. If the PCIE_VPH is
+        * supplied by 3.3V, the VREG_BYPASS should be cleared to zero.
+        */
+       if (imx6_pcie->vph && regulator_get_voltage(imx6_pcie->vph) > 3000000)
                regmap_update_bits(imx6_pcie->iomuxc_gpr,
                                   imx6_pcie_grp_offset(imx6_pcie),
-                                  IMX8MQ_GPR_PCIE_REF_USE_PAD,
-                                  IMX8MQ_GPR_PCIE_REF_USE_PAD);
-               /*
-                * Regarding the datasheet, the PCIE_VPH is suggested
-                * to be 1.8V. If the PCIE_VPH is supplied by 3.3V, the
-                * VREG_BYPASS should be cleared to zero.
-                */
-               if (imx6_pcie->vph &&
-                   regulator_get_voltage(imx6_pcie->vph) > 3000000)
-                       regmap_update_bits(imx6_pcie->iomuxc_gpr,
-                                          imx6_pcie_grp_offset(imx6_pcie),
-                                          IMX8MQ_GPR_PCIE_VREG_BYPASS,
-                                          0);
-               break;
-       case IMX7D:
-               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
-                                  IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, 0);
-               break;
-       case IMX6SX:
-               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
-                                  IMX6SX_GPR12_PCIE_RX_EQ_MASK,
-                                  IMX6SX_GPR12_PCIE_RX_EQ_2);
-               fallthrough;
-       default:
-               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+                                  IMX8MQ_GPR_PCIE_VREG_BYPASS,
+                                  0);
+
+       return 0;
+}
+
+static int imx7d_pcie_init_phy(struct imx6_pcie *imx6_pcie)
+{
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, 0);
+
+       return 0;
+}
+
+static int imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
+{
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
                                   IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
 
-               /* configure constant input signal to the pcie ctrl and phy */
-               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
-                                  IMX6Q_GPR12_LOS_LEVEL, 9 << 4);
-
-               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                                  IMX6Q_GPR8_TX_DEEMPH_GEN1,
-                                  imx6_pcie->tx_deemph_gen1 << 0);
-               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                                  IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB,
-                                  imx6_pcie->tx_deemph_gen2_3p5db << 6);
-               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                                  IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB,
-                                  imx6_pcie->tx_deemph_gen2_6db << 12);
-               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                                  IMX6Q_GPR8_TX_SWING_FULL,
-                                  imx6_pcie->tx_swing_full << 18);
-               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                                  IMX6Q_GPR8_TX_SWING_LOW,
-                                  imx6_pcie->tx_swing_low << 25);
-               break;
-       }
+       /* configure constant input signal to the pcie ctrl and phy */
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+                          IMX6Q_GPR12_LOS_LEVEL, 9 << 4);
+
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+                          IMX6Q_GPR8_TX_DEEMPH_GEN1,
+                          imx6_pcie->tx_deemph_gen1 << 0);
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+                          IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB,
+                          imx6_pcie->tx_deemph_gen2_3p5db << 6);
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+                          IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB,
+                          imx6_pcie->tx_deemph_gen2_6db << 12);
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+                          IMX6Q_GPR8_TX_SWING_FULL,
+                          imx6_pcie->tx_swing_full << 18);
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+                          IMX6Q_GPR8_TX_SWING_LOW,
+                          imx6_pcie->tx_swing_low << 25);
+       return 0;
+}
 
-       imx6_pcie_configure_type(imx6_pcie);
+static int imx6sx_pcie_init_phy(struct imx6_pcie *imx6_pcie)
+{
+       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+                          IMX6SX_GPR12_PCIE_RX_EQ_MASK, IMX6SX_GPR12_PCIE_RX_EQ_2);
+
+       return imx6_pcie_init_phy(imx6_pcie);
 }
 
 static void imx7d_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie)
@@ -407,13 +439,18 @@ static void imx7d_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie)
 
 static int imx6_setup_phy_mpll(struct imx6_pcie *imx6_pcie)
 {
-       unsigned long phy_rate = clk_get_rate(imx6_pcie->pcie_phy);
+       unsigned long phy_rate = 0;
        int mult, div;
        u16 val;
+       int i;
 
        if (!(imx6_pcie->drvdata->flags & IMX6_PCIE_FLAG_IMX6_PHY))
                return 0;
 
+       for (i = 0; i < imx6_pcie->drvdata->clks_cnt; i++)
+               if (strncmp(imx6_pcie->clks[i].id, "pcie_phy", 8) == 0)
+                       phy_rate = clk_get_rate(imx6_pcie->clks[i].clk);
+
        switch (phy_rate) {
        case 125000000:
                /*
@@ -550,19 +587,11 @@ static int imx6_pcie_attach_pd(struct device *dev)
 
 static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
 {
-       struct dw_pcie *pci = imx6_pcie->pci;
-       struct device *dev = pci->dev;
        unsigned int offset;
        int ret = 0;
 
        switch (imx6_pcie->drvdata->variant) {
        case IMX6SX:
-               ret = clk_prepare_enable(imx6_pcie->pcie_inbound_axi);
-               if (ret) {
-                       dev_err(dev, "unable to enable pcie_axi clock\n");
-                       break;
-               }
-
                regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
                                   IMX6SX_GPR12_PCIE_TEST_POWERDOWN, 0);
                break;
@@ -582,6 +611,8 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
                                   IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
                break;
        case IMX7D:
+       case IMX95:
+       case IMX95_EP:
                break;
        case IMX8MM:
        case IMX8MM_EP:
@@ -589,12 +620,6 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
        case IMX8MQ_EP:
        case IMX8MP:
        case IMX8MP_EP:
-               ret = clk_prepare_enable(imx6_pcie->pcie_aux);
-               if (ret) {
-                       dev_err(dev, "unable to enable pcie_aux clock\n");
-                       break;
-               }
-
                offset = imx6_pcie_grp_offset(imx6_pcie);
                /*
                 * Set the over ride low and enabled
@@ -615,9 +640,6 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
 static void imx6_pcie_disable_ref_clk(struct imx6_pcie *imx6_pcie)
 {
        switch (imx6_pcie->drvdata->variant) {
-       case IMX6SX:
-               clk_disable_unprepare(imx6_pcie->pcie_inbound_axi);
-               break;
        case IMX6QP:
        case IMX6Q:
                regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
@@ -631,14 +653,6 @@ static void imx6_pcie_disable_ref_clk(struct imx6_pcie *imx6_pcie)
                                   IMX7D_GPR12_PCIE_PHY_REFCLK_SEL,
                                   IMX7D_GPR12_PCIE_PHY_REFCLK_SEL);
                break;
-       case IMX8MM:
-       case IMX8MM_EP:
-       case IMX8MQ:
-       case IMX8MQ_EP:
-       case IMX8MP:
-       case IMX8MP_EP:
-               clk_disable_unprepare(imx6_pcie->pcie_aux);
-               break;
        default:
                break;
        }
@@ -650,23 +664,9 @@ static int imx6_pcie_clk_enable(struct imx6_pcie *imx6_pcie)
        struct device *dev = pci->dev;
        int ret;
 
-       ret = clk_prepare_enable(imx6_pcie->pcie_phy);
-       if (ret) {
-               dev_err(dev, "unable to enable pcie_phy clock\n");
+       ret = clk_bulk_prepare_enable(imx6_pcie->drvdata->clks_cnt, imx6_pcie->clks);
+       if (ret)
                return ret;
-       }
-
-       ret = clk_prepare_enable(imx6_pcie->pcie_bus);
-       if (ret) {
-               dev_err(dev, "unable to enable pcie_bus clock\n");
-               goto err_pcie_bus;
-       }
-
-       ret = clk_prepare_enable(imx6_pcie->pcie);
-       if (ret) {
-               dev_err(dev, "unable to enable pcie clock\n");
-               goto err_pcie;
-       }
 
        ret = imx6_pcie_enable_ref_clk(imx6_pcie);
        if (ret) {
@@ -679,11 +679,7 @@ static int imx6_pcie_clk_enable(struct imx6_pcie *imx6_pcie)
        return 0;
 
 err_ref_clk:
-       clk_disable_unprepare(imx6_pcie->pcie);
-err_pcie:
-       clk_disable_unprepare(imx6_pcie->pcie_bus);
-err_pcie_bus:
-       clk_disable_unprepare(imx6_pcie->pcie_phy);
+       clk_bulk_disable_unprepare(imx6_pcie->drvdata->clks_cnt, imx6_pcie->clks);
 
        return ret;
 }
@@ -691,25 +687,15 @@ err_pcie_bus:
 static void imx6_pcie_clk_disable(struct imx6_pcie *imx6_pcie)
 {
        imx6_pcie_disable_ref_clk(imx6_pcie);
-       clk_disable_unprepare(imx6_pcie->pcie);
-       clk_disable_unprepare(imx6_pcie->pcie_bus);
-       clk_disable_unprepare(imx6_pcie->pcie_phy);
+       clk_bulk_disable_unprepare(imx6_pcie->drvdata->clks_cnt, imx6_pcie->clks);
 }
 
 static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
 {
+       reset_control_assert(imx6_pcie->pciephy_reset);
+       reset_control_assert(imx6_pcie->apps_reset);
+
        switch (imx6_pcie->drvdata->variant) {
-       case IMX7D:
-       case IMX8MQ:
-       case IMX8MQ_EP:
-               reset_control_assert(imx6_pcie->pciephy_reset);
-               fallthrough;
-       case IMX8MM:
-       case IMX8MM_EP:
-       case IMX8MP:
-       case IMX8MP_EP:
-               reset_control_assert(imx6_pcie->apps_reset);
-               break;
        case IMX6SX:
                regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
                                   IMX6SX_GPR12_PCIE_TEST_POWERDOWN,
@@ -730,6 +716,8 @@ static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
                regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
                                   IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16);
                break;
+       default:
+               break;
        }
 
        /* Some boards don't have PCIe reset GPIO. */
@@ -743,14 +731,10 @@ static int imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
        struct dw_pcie *pci = imx6_pcie->pci;
        struct device *dev = pci->dev;
 
+       reset_control_deassert(imx6_pcie->pciephy_reset);
+
        switch (imx6_pcie->drvdata->variant) {
-       case IMX8MQ:
-       case IMX8MQ_EP:
-               reset_control_deassert(imx6_pcie->pciephy_reset);
-               break;
        case IMX7D:
-               reset_control_deassert(imx6_pcie->pciephy_reset);
-
                /* Workaround for ERR010728, failure of PCI-e PLL VCO to
                 * oscillate, especially when cold.  This turns off "Duty-cycle
                 * Corrector" and other mysterious undocumented things.
@@ -782,11 +766,7 @@ static int imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
 
                usleep_range(200, 500);
                break;
-       case IMX6Q:             /* Nothing to do */
-       case IMX8MM:
-       case IMX8MM_EP:
-       case IMX8MP:
-       case IMX8MP_EP:
+       default:
                break;
        }
 
@@ -824,48 +804,25 @@ static int imx6_pcie_wait_for_speed_change(struct imx6_pcie *imx6_pcie)
 static void imx6_pcie_ltssm_enable(struct device *dev)
 {
        struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
+       const struct imx6_pcie_drvdata *drvdata = imx6_pcie->drvdata;
 
-       switch (imx6_pcie->drvdata->variant) {
-       case IMX6Q:
-       case IMX6SX:
-       case IMX6QP:
-               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
-                                  IMX6Q_GPR12_PCIE_CTL_2,
-                                  IMX6Q_GPR12_PCIE_CTL_2);
-               break;
-       case IMX7D:
-       case IMX8MQ:
-       case IMX8MQ_EP:
-       case IMX8MM:
-       case IMX8MM_EP:
-       case IMX8MP:
-       case IMX8MP_EP:
-               reset_control_deassert(imx6_pcie->apps_reset);
-               break;
-       }
+       if (drvdata->ltssm_mask)
+               regmap_update_bits(imx6_pcie->iomuxc_gpr, drvdata->ltssm_off, drvdata->ltssm_mask,
+                                  drvdata->ltssm_mask);
+
+       reset_control_deassert(imx6_pcie->apps_reset);
 }
 
 static void imx6_pcie_ltssm_disable(struct device *dev)
 {
        struct imx6_pcie *imx6_pcie = dev_get_drvdata(dev);
+       const struct imx6_pcie_drvdata *drvdata = imx6_pcie->drvdata;
 
-       switch (imx6_pcie->drvdata->variant) {
-       case IMX6Q:
-       case IMX6SX:
-       case IMX6QP:
-               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
-                                  IMX6Q_GPR12_PCIE_CTL_2, 0);
-               break;
-       case IMX7D:
-       case IMX8MQ:
-       case IMX8MQ_EP:
-       case IMX8MM:
-       case IMX8MM_EP:
-       case IMX8MP:
-       case IMX8MP_EP:
-               reset_control_assert(imx6_pcie->apps_reset);
-               break;
-       }
+       if (drvdata->ltssm_mask)
+               regmap_update_bits(imx6_pcie->iomuxc_gpr, drvdata->ltssm_off,
+                                  drvdata->ltssm_mask, 0);
+
+       reset_control_assert(imx6_pcie->apps_reset);
 }
 
 static int imx6_pcie_start_link(struct dw_pcie *pci)
@@ -977,7 +934,11 @@ static int imx6_pcie_host_init(struct dw_pcie_rp *pp)
        }
 
        imx6_pcie_assert_core_reset(imx6_pcie);
-       imx6_pcie_init_phy(imx6_pcie);
+
+       if (imx6_pcie->drvdata->init_phy)
+               imx6_pcie->drvdata->init_phy(imx6_pcie);
+
+       imx6_pcie_configure_type(imx6_pcie);
 
        ret = imx6_pcie_clk_enable(imx6_pcie);
        if (ret) {
@@ -1081,14 +1042,35 @@ static const struct pci_epc_features imx8m_pcie_epc_features = {
        .linkup_notifier = false,
        .msi_capable = true,
        .msix_capable = false,
-       .reserved_bar = 1 << BAR_1 | 1 << BAR_3,
+       .bar[BAR_1] = { .type = BAR_RESERVED, },
+       .bar[BAR_3] = { .type = BAR_RESERVED, },
        .align = SZ_64K,
 };
 
+/*
+ * BAR#        | Default BAR enable    | Default BAR Type      | Default BAR Size      | BAR Sizing Scheme
+ * ================================================================================================
+ * BAR0        | Enable                | 64-bit                | 1 MB                  | Programmable Size
+ * BAR1        | Disable               | 32-bit                | 64 KB                 | Fixed Size
+ *        BAR1 should be disabled if BAR0 is 64bit.
+ * BAR2        | Enable                | 32-bit                | 1 MB                  | Programmable Size
+ * BAR3        | Enable                | 32-bit                | 64 KB                 | Programmable Size
+ * BAR4        | Enable                | 32-bit                | 1M                    | Programmable Size
+ * BAR5        | Enable                | 32-bit                | 64 KB                 | Programmable Size
+ */
+static const struct pci_epc_features imx95_pcie_epc_features = {
+       .msi_capable = true,
+       .bar[BAR_1] = { .type = BAR_FIXED, .fixed_size = SZ_64K, },
+       .align = SZ_4K,
+};
+
 static const struct pci_epc_features*
 imx6_pcie_ep_get_features(struct dw_pcie_ep *ep)
 {
-       return &imx8m_pcie_epc_features;
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       struct imx6_pcie *imx6_pcie = to_imx6_pcie(pci);
+
+       return imx6_pcie->drvdata->epc_features;
 }
 
 static const struct dw_pcie_ep_ops pcie_ep_ops = {
@@ -1103,7 +1085,6 @@ static int imx6_add_pcie_ep(struct imx6_pcie *imx6_pcie,
        int ret;
        unsigned int pcie_dbi2_offset;
        struct dw_pcie_ep *ep;
-       struct resource *res;
        struct dw_pcie *pci = imx6_pcie->pci;
        struct dw_pcie_rp *pp = &pci->pp;
        struct device *dev = pci->dev;
@@ -1122,14 +1103,20 @@ static int imx6_add_pcie_ep(struct imx6_pcie *imx6_pcie,
                pcie_dbi2_offset = SZ_4K;
                break;
        }
+
        pci->dbi_base2 = pci->dbi_base + pcie_dbi2_offset;
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space");
-       if (!res)
-               return -EINVAL;
 
-       ep->phys_base = res->start;
-       ep->addr_size = resource_size(res);
-       ep->page_size = SZ_64K;
+       /*
+        * FIXME: Ideally, dbi2 base address should come from DT. But since only IMX95 is defining
+        * "dbi2" in DT, "dbi_base2" is set to NULL here for that platform alone so that the DWC
+        * core code can fetch that from DT. But once all platform DTs were fixed, this and the
+        * above "dbi_base2" setting should be removed.
+        */
+       if (device_property_match_string(dev, "reg-names", "dbi2") >= 0)
+               pci->dbi_base2 = NULL;
+
+       if (imx6_check_flag(imx6_pcie, IMX6_PCIE_FLAG_SUPPORT_64BIT))
+               dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64));
 
        ret = dw_pcie_ep_init(ep);
        if (ret) {
@@ -1251,6 +1238,7 @@ static int imx6_pcie_probe(struct platform_device *pdev)
        struct device_node *node = dev->of_node;
        int ret;
        u16 val;
+       int i;
 
        imx6_pcie = devm_kzalloc(dev, sizeof(*imx6_pcie), GFP_KERNEL);
        if (!imx6_pcie)
@@ -1304,81 +1292,48 @@ static int imx6_pcie_probe(struct platform_device *pdev)
                return imx6_pcie->reset_gpio;
        }
 
-       /* Fetch clocks */
-       imx6_pcie->pcie_bus = devm_clk_get(dev, "pcie_bus");
-       if (IS_ERR(imx6_pcie->pcie_bus))
-               return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_bus),
-                                    "pcie_bus clock source missing or invalid\n");
+       if (imx6_pcie->drvdata->clks_cnt >= IMX6_PCIE_MAX_CLKS)
+               return dev_err_probe(dev, -ENOMEM, "clks_cnt is too big\n");
 
-       imx6_pcie->pcie = devm_clk_get(dev, "pcie");
-       if (IS_ERR(imx6_pcie->pcie))
-               return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie),
-                                    "pcie clock source missing or invalid\n");
+       for (i = 0; i < imx6_pcie->drvdata->clks_cnt; i++)
+               imx6_pcie->clks[i].id = imx6_pcie->drvdata->clk_names[i];
 
-       switch (imx6_pcie->drvdata->variant) {
-       case IMX6SX:
-               imx6_pcie->pcie_inbound_axi = devm_clk_get(dev,
-                                                          "pcie_inbound_axi");
-               if (IS_ERR(imx6_pcie->pcie_inbound_axi))
-                       return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_inbound_axi),
-                                            "pcie_inbound_axi clock missing or invalid\n");
-               break;
-       case IMX8MQ:
-       case IMX8MQ_EP:
-               imx6_pcie->pcie_aux = devm_clk_get(dev, "pcie_aux");
-               if (IS_ERR(imx6_pcie->pcie_aux))
-                       return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_aux),
-                                            "pcie_aux clock source missing or invalid\n");
-               fallthrough;
-       case IMX7D:
-               if (dbi_base->start == IMX8MQ_PCIE2_BASE_ADDR)
-                       imx6_pcie->controller_id = 1;
+       /* Fetch clocks */
+       ret = devm_clk_bulk_get(dev, imx6_pcie->drvdata->clks_cnt, imx6_pcie->clks);
+       if (ret)
+               return ret;
 
-               imx6_pcie->pciephy_reset = devm_reset_control_get_exclusive(dev,
-                                                                           "pciephy");
-               if (IS_ERR(imx6_pcie->pciephy_reset)) {
-                       dev_err(dev, "Failed to get PCIEPHY reset control\n");
-                       return PTR_ERR(imx6_pcie->pciephy_reset);
-               }
+       if (imx6_check_flag(imx6_pcie, IMX6_PCIE_FLAG_HAS_PHYDRV)) {
+               imx6_pcie->phy = devm_phy_get(dev, "pcie-phy");
+               if (IS_ERR(imx6_pcie->phy))
+                       return dev_err_probe(dev, PTR_ERR(imx6_pcie->phy),
+                                            "failed to get pcie phy\n");
+       }
 
-               imx6_pcie->apps_reset = devm_reset_control_get_exclusive(dev,
-                                                                        "apps");
-               if (IS_ERR(imx6_pcie->apps_reset)) {
-                       dev_err(dev, "Failed to get PCIE APPS reset control\n");
-                       return PTR_ERR(imx6_pcie->apps_reset);
-               }
-               break;
-       case IMX8MM:
-       case IMX8MM_EP:
-       case IMX8MP:
-       case IMX8MP_EP:
-               imx6_pcie->pcie_aux = devm_clk_get(dev, "pcie_aux");
-               if (IS_ERR(imx6_pcie->pcie_aux))
-                       return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_aux),
-                                            "pcie_aux clock source missing or invalid\n");
-               imx6_pcie->apps_reset = devm_reset_control_get_exclusive(dev,
-                                                                        "apps");
+       if (imx6_check_flag(imx6_pcie, IMX6_PCIE_FLAG_HAS_APP_RESET)) {
+               imx6_pcie->apps_reset = devm_reset_control_get_exclusive(dev, "apps");
                if (IS_ERR(imx6_pcie->apps_reset))
                        return dev_err_probe(dev, PTR_ERR(imx6_pcie->apps_reset),
                                             "failed to get pcie apps reset control\n");
+       }
 
-               imx6_pcie->phy = devm_phy_get(dev, "pcie-phy");
-               if (IS_ERR(imx6_pcie->phy))
-                       return dev_err_probe(dev, PTR_ERR(imx6_pcie->phy),
-                                            "failed to get pcie phy\n");
+       if (imx6_check_flag(imx6_pcie, IMX6_PCIE_FLAG_HAS_PHY_RESET)) {
+               imx6_pcie->pciephy_reset = devm_reset_control_get_exclusive(dev, "pciephy");
+               if (IS_ERR(imx6_pcie->pciephy_reset))
+                       return dev_err_probe(dev, PTR_ERR(imx6_pcie->pciephy_reset),
+                                            "Failed to get PCIEPHY reset control\n");
+       }
 
+       switch (imx6_pcie->drvdata->variant) {
+       case IMX8MQ:
+       case IMX8MQ_EP:
+       case IMX7D:
+               if (dbi_base->start == IMX8MQ_PCIE2_BASE_ADDR)
+                       imx6_pcie->controller_id = 1;
                break;
        default:
                break;
        }
-       /* Don't fetch the pcie_phy clock, if it has abstract PHY driver */
-       if (imx6_pcie->phy == NULL) {
-               imx6_pcie->pcie_phy = devm_clk_get(dev, "pcie_phy");
-               if (IS_ERR(imx6_pcie->pcie_phy))
-                       return dev_err_probe(dev, PTR_ERR(imx6_pcie->pcie_phy),
-                                            "pcie_phy clock source missing or invalid\n");
-       }
-
 
        /* Grab turnoff reset */
        imx6_pcie->turnoff_reset = devm_reset_control_get_optional_exclusive(dev, "turnoff");
@@ -1387,12 +1342,32 @@ static int imx6_pcie_probe(struct platform_device *pdev)
                return PTR_ERR(imx6_pcie->turnoff_reset);
        }
 
+       if (imx6_pcie->drvdata->gpr) {
        /* Grab GPR config register range */
-       imx6_pcie->iomuxc_gpr =
-                syscon_regmap_lookup_by_compatible(imx6_pcie->drvdata->gpr);
-       if (IS_ERR(imx6_pcie->iomuxc_gpr)) {
-               dev_err(dev, "unable to find iomuxc registers\n");
-               return PTR_ERR(imx6_pcie->iomuxc_gpr);
+               imx6_pcie->iomuxc_gpr =
+                        syscon_regmap_lookup_by_compatible(imx6_pcie->drvdata->gpr);
+               if (IS_ERR(imx6_pcie->iomuxc_gpr))
+                       return dev_err_probe(dev, PTR_ERR(imx6_pcie->iomuxc_gpr),
+                                            "unable to find iomuxc registers\n");
+       }
+
+       if (imx6_check_flag(imx6_pcie, IMX6_PCIE_FLAG_HAS_SERDES)) {
+               void __iomem *off = devm_platform_ioremap_resource_byname(pdev, "app");
+
+               if (IS_ERR(off))
+                       return dev_err_probe(dev, PTR_ERR(off),
+                                            "unable to find serdes registers\n");
+
+               static const struct regmap_config regmap_config = {
+                       .reg_bits = 32,
+                       .val_bits = 32,
+                       .reg_stride = 4,
+               };
+
+               imx6_pcie->iomuxc_gpr = devm_regmap_init_mmio(dev, off, &regmap_config);
+               if (IS_ERR(imx6_pcie->iomuxc_gpr))
+                       return dev_err_probe(dev, PTR_ERR(imx6_pcie->iomuxc_gpr),
+                                            "unable to find iomuxc registers\n");
        }
 
        /* Grab PCIe PHY Tx Settings */
@@ -1469,6 +1444,11 @@ static void imx6_pcie_shutdown(struct platform_device *pdev)
        imx6_pcie_assert_core_reset(imx6_pcie);
 }
 
+static const char * const imx6q_clks[] = {"pcie_bus", "pcie", "pcie_phy"};
+static const char * const imx8mm_clks[] = {"pcie_bus", "pcie", "pcie_aux"};
+static const char * const imx8mq_clks[] = {"pcie_bus", "pcie", "pcie_phy", "pcie_aux"};
+static const char * const imx6sx_clks[] = {"pcie_bus", "pcie", "pcie_phy", "pcie_inbound_axi"};
+
 static const struct imx6_pcie_drvdata drvdata[] = {
        [IMX6Q] = {
                .variant = IMX6Q,
@@ -1476,6 +1456,13 @@ static const struct imx6_pcie_drvdata drvdata[] = {
                         IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE,
                .dbi_length = 0x200,
                .gpr = "fsl,imx6q-iomuxc-gpr",
+               .clk_names = imx6q_clks,
+               .clks_cnt = ARRAY_SIZE(imx6q_clks),
+               .ltssm_off = IOMUXC_GPR12,
+               .ltssm_mask = IMX6Q_GPR12_PCIE_CTL_2,
+               .mode_off[0] = IOMUXC_GPR12,
+               .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
+               .init_phy = imx6_pcie_init_phy,
        },
        [IMX6SX] = {
                .variant = IMX6SX,
@@ -1483,6 +1470,13 @@ static const struct imx6_pcie_drvdata drvdata[] = {
                         IMX6_PCIE_FLAG_IMX6_SPEED_CHANGE |
                         IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,
                .gpr = "fsl,imx6q-iomuxc-gpr",
+               .clk_names = imx6sx_clks,
+               .clks_cnt = ARRAY_SIZE(imx6sx_clks),
+               .ltssm_off = IOMUXC_GPR12,
+               .ltssm_mask = IMX6Q_GPR12_PCIE_CTL_2,
+               .mode_off[0] = IOMUXC_GPR12,
+               .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
+               .init_phy = imx6sx_pcie_init_phy,
        },
        [IMX6QP] = {
                .variant = IMX6QP,
@@ -1491,40 +1485,122 @@ static const struct imx6_pcie_drvdata drvdata[] = {
                         IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,
                .dbi_length = 0x200,
                .gpr = "fsl,imx6q-iomuxc-gpr",
+               .clk_names = imx6q_clks,
+               .clks_cnt = ARRAY_SIZE(imx6q_clks),
+               .ltssm_off = IOMUXC_GPR12,
+               .ltssm_mask = IMX6Q_GPR12_PCIE_CTL_2,
+               .mode_off[0] = IOMUXC_GPR12,
+               .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
+               .init_phy = imx6_pcie_init_phy,
        },
        [IMX7D] = {
                .variant = IMX7D,
-               .flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,
+               .flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND |
+                        IMX6_PCIE_FLAG_HAS_APP_RESET |
+                        IMX6_PCIE_FLAG_HAS_PHY_RESET,
                .gpr = "fsl,imx7d-iomuxc-gpr",
+               .clk_names = imx6q_clks,
+               .clks_cnt = ARRAY_SIZE(imx6q_clks),
+               .mode_off[0] = IOMUXC_GPR12,
+               .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
+               .init_phy = imx7d_pcie_init_phy,
        },
        [IMX8MQ] = {
                .variant = IMX8MQ,
+               .flags = IMX6_PCIE_FLAG_HAS_APP_RESET |
+                        IMX6_PCIE_FLAG_HAS_PHY_RESET,
                .gpr = "fsl,imx8mq-iomuxc-gpr",
+               .clk_names = imx8mq_clks,
+               .clks_cnt = ARRAY_SIZE(imx8mq_clks),
+               .mode_off[0] = IOMUXC_GPR12,
+               .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
+               .mode_off[1] = IOMUXC_GPR12,
+               .mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE,
+               .init_phy = imx8mq_pcie_init_phy,
        },
        [IMX8MM] = {
                .variant = IMX8MM,
-               .flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,
+               .flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND |
+                        IMX6_PCIE_FLAG_HAS_PHYDRV |
+                        IMX6_PCIE_FLAG_HAS_APP_RESET,
                .gpr = "fsl,imx8mm-iomuxc-gpr",
+               .clk_names = imx8mm_clks,
+               .clks_cnt = ARRAY_SIZE(imx8mm_clks),
+               .mode_off[0] = IOMUXC_GPR12,
+               .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
        },
        [IMX8MP] = {
                .variant = IMX8MP,
-               .flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND,
+               .flags = IMX6_PCIE_FLAG_SUPPORTS_SUSPEND |
+                        IMX6_PCIE_FLAG_HAS_PHYDRV |
+                        IMX6_PCIE_FLAG_HAS_APP_RESET,
                .gpr = "fsl,imx8mp-iomuxc-gpr",
+               .clk_names = imx8mm_clks,
+               .clks_cnt = ARRAY_SIZE(imx8mm_clks),
+               .mode_off[0] = IOMUXC_GPR12,
+               .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
+       },
+       [IMX95] = {
+               .variant = IMX95,
+               .flags = IMX6_PCIE_FLAG_HAS_SERDES,
+               .clk_names = imx8mq_clks,
+               .clks_cnt = ARRAY_SIZE(imx8mq_clks),
+               .ltssm_off = IMX95_PE0_GEN_CTRL_3,
+               .ltssm_mask = IMX95_PCIE_LTSSM_EN,
+               .mode_off[0]  = IMX95_PE0_GEN_CTRL_1,
+               .mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
+               .init_phy = imx95_pcie_init_phy,
        },
        [IMX8MQ_EP] = {
                .variant = IMX8MQ_EP,
+               .flags = IMX6_PCIE_FLAG_HAS_APP_RESET |
+                        IMX6_PCIE_FLAG_HAS_PHY_RESET,
                .mode = DW_PCIE_EP_TYPE,
                .gpr = "fsl,imx8mq-iomuxc-gpr",
+               .clk_names = imx8mq_clks,
+               .clks_cnt = ARRAY_SIZE(imx8mq_clks),
+               .mode_off[0] = IOMUXC_GPR12,
+               .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
+               .mode_off[1] = IOMUXC_GPR12,
+               .mode_mask[1] = IMX8MQ_GPR12_PCIE2_CTRL_DEVICE_TYPE,
+               .epc_features = &imx8m_pcie_epc_features,
+               .init_phy = imx8mq_pcie_init_phy,
        },
        [IMX8MM_EP] = {
                .variant = IMX8MM_EP,
+               .flags = IMX6_PCIE_FLAG_HAS_PHYDRV,
                .mode = DW_PCIE_EP_TYPE,
                .gpr = "fsl,imx8mm-iomuxc-gpr",
+               .clk_names = imx8mm_clks,
+               .clks_cnt = ARRAY_SIZE(imx8mm_clks),
+               .mode_off[0] = IOMUXC_GPR12,
+               .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
+               .epc_features = &imx8m_pcie_epc_features,
        },
        [IMX8MP_EP] = {
                .variant = IMX8MP_EP,
+               .flags = IMX6_PCIE_FLAG_HAS_PHYDRV,
                .mode = DW_PCIE_EP_TYPE,
                .gpr = "fsl,imx8mp-iomuxc-gpr",
+               .clk_names = imx8mm_clks,
+               .clks_cnt = ARRAY_SIZE(imx8mm_clks),
+               .mode_off[0] = IOMUXC_GPR12,
+               .mode_mask[0] = IMX6Q_GPR12_DEVICE_TYPE,
+               .epc_features = &imx8m_pcie_epc_features,
+       },
+       [IMX95_EP] = {
+               .variant = IMX95_EP,
+               .flags = IMX6_PCIE_FLAG_HAS_SERDES |
+                        IMX6_PCIE_FLAG_SUPPORT_64BIT,
+               .clk_names = imx8mq_clks,
+               .clks_cnt = ARRAY_SIZE(imx8mq_clks),
+               .ltssm_off = IMX95_PE0_GEN_CTRL_3,
+               .ltssm_mask = IMX95_PCIE_LTSSM_EN,
+               .mode_off[0]  = IMX95_PE0_GEN_CTRL_1,
+               .mode_mask[0] = IMX95_PCIE_DEVICE_TYPE,
+               .init_phy = imx95_pcie_init_phy,
+               .epc_features = &imx95_pcie_epc_features,
+               .mode = DW_PCIE_EP_TYPE,
        },
 };
 
@@ -1536,9 +1612,11 @@ static const struct of_device_id imx6_pcie_of_match[] = {
        { .compatible = "fsl,imx8mq-pcie", .data = &drvdata[IMX8MQ], },
        { .compatible = "fsl,imx8mm-pcie", .data = &drvdata[IMX8MM], },
        { .compatible = "fsl,imx8mp-pcie", .data = &drvdata[IMX8MP], },
+       { .compatible = "fsl,imx95-pcie", .data = &drvdata[IMX95], },
        { .compatible = "fsl,imx8mq-pcie-ep", .data = &drvdata[IMX8MQ_EP], },
        { .compatible = "fsl,imx8mm-pcie-ep", .data = &drvdata[IMX8MM_EP], },
        { .compatible = "fsl,imx8mp-pcie-ep", .data = &drvdata[IMX8MP_EP], },
+       { .compatible = "fsl,imx95-pcie-ep", .data = &drvdata[IMX95_EP], },
        {},
 };
 
index c0c62533a3f17688d4bf0ae34def85f77e19e2ba..844de441872429b230c9c5ccf594c38e684f7147 100644 (file)
@@ -924,12 +924,12 @@ static const struct pci_epc_features ks_pcie_am654_epc_features = {
        .linkup_notifier = false,
        .msi_capable = true,
        .msix_capable = true,
-       .reserved_bar = 1 << BAR_0 | 1 << BAR_1,
-       .bar_fixed_64bit = 1 << BAR_0,
-       .bar_fixed_size[2] = SZ_1M,
-       .bar_fixed_size[3] = SZ_64K,
-       .bar_fixed_size[4] = 256,
-       .bar_fixed_size[5] = SZ_1M,
+       .bar[BAR_0] = { .type = BAR_RESERVED, },
+       .bar[BAR_1] = { .type = BAR_RESERVED, },
+       .bar[BAR_2] = { .type = BAR_FIXED, .fixed_size = SZ_1M, },
+       .bar[BAR_3] = { .type = BAR_FIXED, .fixed_size = SZ_64K, },
+       .bar[BAR_4] = { .type = BAR_FIXED, .fixed_size = 256, },
+       .bar[BAR_5] = { .type = BAR_FIXED, .fixed_size = SZ_1M, },
        .align = SZ_1M,
 };
 
index 2e398494e7c0ca625fee3040b096c73c01c85b57..1f6ee1460ec2a390968140ec8bd0001da171c495 100644 (file)
@@ -250,7 +250,10 @@ static int __init ls_pcie_ep_probe(struct platform_device *pdev)
        pci->dev = dev;
        pci->ops = pcie->drvdata->dw_pcie_ops;
 
-       ls_epc->bar_fixed_64bit = (1 << BAR_2) | (1 << BAR_4);
+       ls_epc->bar[BAR_2].only_64bit = true;
+       ls_epc->bar[BAR_3].type = BAR_RESERVED;
+       ls_epc->bar[BAR_4].only_64bit = true;
+       ls_epc->bar[BAR_5].type = BAR_RESERVED;
        ls_epc->linkup_notifier = true;
 
        pcie->pci = pci;
index 9a437cfce073c16996927af40fa0e3816b7c7b32..746a11dcb67f105d31c38d22502e3bc8fb503a66 100644 (file)
@@ -629,8 +629,13 @@ int dw_pcie_ep_init_complete(struct dw_pcie_ep *ep)
                nbars = (reg & PCI_REBAR_CTRL_NBAR_MASK) >>
                        PCI_REBAR_CTRL_NBAR_SHIFT;
 
+               /*
+                * PCIe r6.0, sec 7.8.6.2 require us to support at least one
+                * size in the range from 1 MB to 512 GB. Advertise support
+                * for 1 MB BAR size only.
+                */
                for (i = 0; i < nbars; i++, offset += PCI_REBAR_CTRL)
-                       dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, 0x0);
+                       dw_pcie_writel_dbi(pci, offset + PCI_REBAR_CAP, BIT(4));
        }
 
        /*
index d5fc31f8345f70f587a2052db681f3b023d08b59..d15a5c2d5b48040ab11837f33cc27a117c82fb25 100644 (file)
@@ -328,7 +328,7 @@ static int dw_pcie_msi_host_init(struct dw_pcie_rp *pp)
        struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
        struct device *dev = pci->dev;
        struct platform_device *pdev = to_platform_device(dev);
-       u64 *msi_vaddr;
+       u64 *msi_vaddr = NULL;
        int ret;
        u32 ctrl, num_ctrls;
 
@@ -379,15 +379,20 @@ static int dw_pcie_msi_host_init(struct dw_pcie_rp *pp)
         * memory.
         */
        ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
-       if (ret)
-               dev_warn(dev, "Failed to set DMA mask to 32-bit. Devices with only 32-bit MSI support may not work properly\n");
+       if (!ret)
+               msi_vaddr = dmam_alloc_coherent(dev, sizeof(u64), &pp->msi_data,
+                                               GFP_KERNEL);
 
-       msi_vaddr = dmam_alloc_coherent(dev, sizeof(u64), &pp->msi_data,
-                                       GFP_KERNEL);
        if (!msi_vaddr) {
-               dev_err(dev, "Failed to alloc and map MSI data\n");
-               dw_pcie_free_msi(pp);
-               return -ENOMEM;
+               dev_warn(dev, "Failed to allocate 32-bit MSI address\n");
+               dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
+               msi_vaddr = dmam_alloc_coherent(dev, sizeof(u64), &pp->msi_data,
+                                               GFP_KERNEL);
+               if (!msi_vaddr) {
+                       dev_err(dev, "Failed to allocate MSI address\n");
+                       dw_pcie_free_msi(pp);
+                       return -ENOMEM;
+               }
        }
 
        return 0;
index 208d3b0ba196021aa9e0377c87136f07367594f8..5e8e54f597dd4785dcaf6a1a22ba964c5e03273c 100644 (file)
@@ -312,8 +312,12 @@ static const struct pci_epc_features keembay_pcie_epc_features = {
        .linkup_notifier        = false,
        .msi_capable            = true,
        .msix_capable           = true,
-       .reserved_bar           = BIT(BAR_1) | BIT(BAR_3) | BIT(BAR_5),
-       .bar_fixed_64bit        = BIT(BAR_0) | BIT(BAR_2) | BIT(BAR_4),
+       .bar[BAR_0]             = { .only_64bit = true, },
+       .bar[BAR_1]             = { .type = BAR_RESERVED, },
+       .bar[BAR_2]             = { .only_64bit = true, },
+       .bar[BAR_3]             = { .type = BAR_RESERVED, },
+       .bar[BAR_4]             = { .only_64bit = true, },
+       .bar[BAR_5]             = { .type = BAR_RESERVED, },
        .align                  = SZ_16K,
 };
 
index 2ce2a3bd932bd7e3824b69cc9450135895b7a89e..14772edcf0d34e0dcfcfe04370ddd9d15c024260 100644 (file)
@@ -53,6 +53,7 @@
 #define PARF_SLV_ADDR_SPACE_SIZE               0x358
 #define PARF_DEVICE_TYPE                       0x1000
 #define PARF_BDF_TO_SID_TABLE_N                        0x2000
+#define PARF_BDF_TO_SID_CFG                    0x2c00
 
 /* ELBI registers */
 #define ELBI_SYS_CTRL                          0x04
 /* PARF_DEVICE_TYPE register fields */
 #define DEVICE_TYPE_RC                         0x4
 
+/* PARF_BDF_TO_SID_CFG fields */
+#define BDF_TO_SID_BYPASS                      BIT(0)
+
 /* ELBI_SYS_CTRL register fields */
 #define ELBI_SYS_CTRL_LT_ENABLE                        BIT(0)
 
@@ -229,6 +233,7 @@ struct qcom_pcie_ops {
 
 struct qcom_pcie_cfg {
        const struct qcom_pcie_ops *ops;
+       bool no_l0s;
 };
 
 struct qcom_pcie {
@@ -272,6 +277,26 @@ static int qcom_pcie_start_link(struct dw_pcie *pci)
        return 0;
 }
 
+static void qcom_pcie_clear_aspm_l0s(struct dw_pcie *pci)
+{
+       struct qcom_pcie *pcie = to_qcom_pcie(pci);
+       u16 offset;
+       u32 val;
+
+       if (!pcie->cfg->no_l0s)
+               return;
+
+       offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+
+       dw_pcie_dbi_ro_wr_en(pci);
+
+       val = readl(pci->dbi_base + offset + PCI_EXP_LNKCAP);
+       val &= ~PCI_EXP_LNKCAP_ASPM_L0S;
+       writel(val, pci->dbi_base + offset + PCI_EXP_LNKCAP);
+
+       dw_pcie_dbi_ro_wr_dis(pci);
+}
+
 static void qcom_pcie_clear_hpc(struct dw_pcie *pci)
 {
        u16 offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
@@ -961,6 +986,7 @@ err_disable_regulators:
 
 static int qcom_pcie_post_init_2_7_0(struct qcom_pcie *pcie)
 {
+       qcom_pcie_clear_aspm_l0s(pcie->pci);
        qcom_pcie_clear_hpc(pcie->pci);
 
        return 0;
@@ -1008,11 +1034,17 @@ static int qcom_pcie_config_sid_1_9_0(struct qcom_pcie *pcie)
        u8 qcom_pcie_crc8_table[CRC8_TABLE_SIZE];
        int i, nr_map, size = 0;
        u32 smmu_sid_base;
+       u32 val;
 
        of_get_property(dev->of_node, "iommu-map", &size);
        if (!size)
                return 0;
 
+       /* Enable BDF to SID translation by disabling bypass mode (default) */
+       val = readl(pcie->parf + PARF_BDF_TO_SID_CFG);
+       val &= ~BDF_TO_SID_BYPASS;
+       writel(val, pcie->parf + PARF_BDF_TO_SID_CFG);
+
        map = kzalloc(size, GFP_KERNEL);
        if (!map)
                return -ENOMEM;
@@ -1358,6 +1390,11 @@ static const struct qcom_pcie_cfg cfg_2_9_0 = {
        .ops = &ops_2_9_0,
 };
 
+static const struct qcom_pcie_cfg cfg_sc8280xp = {
+       .ops = &ops_1_9_0,
+       .no_l0s = true,
+};
+
 static const struct dw_pcie_ops dw_pcie_ops = {
        .link_up = qcom_pcie_link_up,
        .start_link = qcom_pcie_start_link,
@@ -1629,11 +1666,11 @@ static const struct of_device_id qcom_pcie_match[] = {
        { .compatible = "qcom,pcie-ipq8074-gen3", .data = &cfg_2_9_0 },
        { .compatible = "qcom,pcie-msm8996", .data = &cfg_2_3_2 },
        { .compatible = "qcom,pcie-qcs404", .data = &cfg_2_4_0 },
-       { .compatible = "qcom,pcie-sa8540p", .data = &cfg_1_9_0 },
+       { .compatible = "qcom,pcie-sa8540p", .data = &cfg_sc8280xp },
        { .compatible = "qcom,pcie-sa8775p", .data = &cfg_1_9_0},
        { .compatible = "qcom,pcie-sc7280", .data = &cfg_1_9_0 },
        { .compatible = "qcom,pcie-sc8180x", .data = &cfg_1_9_0 },
-       { .compatible = "qcom,pcie-sc8280xp", .data = &cfg_1_9_0 },
+       { .compatible = "qcom,pcie-sc8280xp", .data = &cfg_sc8280xp },
        { .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 },
@@ -1642,6 +1679,7 @@ static const struct of_device_id qcom_pcie_match[] = {
        { .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 },
+       { .compatible = "qcom,pcie-x1e80100", .data = &cfg_1_9_0 },
        { }
 };
 
index e9166619b1f9f656a83d60330515e7b20f34d7ca..0be760ed420bdcb6b500acda907e15ae2cefaff3 100644 (file)
@@ -383,7 +383,9 @@ static const struct pci_epc_features rcar_gen4_pcie_epc_features = {
        .linkup_notifier = false,
        .msi_capable = true,
        .msix_capable = false,
-       .reserved_bar = 1 << BAR_1 | 1 << BAR_3 | 1 << BAR_5,
+       .bar[BAR_1] = { .type = BAR_RESERVED, },
+       .bar[BAR_3] = { .type = BAR_RESERVED, },
+       .bar[BAR_5] = { .type = BAR_RESERVED, },
        .align = SZ_1M,
 };
 
index 7afa9e9aabe2165828aff5eaed0dd5033b08fc4c..1f7b662cb8e15b5fecd2b131037274865779ec0f 100644 (file)
@@ -2007,9 +2007,13 @@ static const struct pci_epc_features tegra_pcie_epc_features = {
        .core_init_notifier = true,
        .msi_capable = false,
        .msix_capable = false,
-       .reserved_bar = 1 << BAR_2 | 1 << BAR_3 | 1 << BAR_4 | 1 << BAR_5,
-       .bar_fixed_64bit = 1 << BAR_0,
-       .bar_fixed_size[0] = SZ_1M,
+       .bar[BAR_0] = { .type = BAR_FIXED, .fixed_size = SZ_1M,
+                       .only_64bit = true, },
+       .bar[BAR_1] = { .type = BAR_RESERVED, },
+       .bar[BAR_2] = { .type = BAR_RESERVED, },
+       .bar[BAR_3] = { .type = BAR_RESERVED, },
+       .bar[BAR_4] = { .type = BAR_RESERVED, },
+       .bar[BAR_5] = { .type = BAR_RESERVED, },
 };
 
 static const struct pci_epc_features*
index 3fced0d3e85125067024f948717713278422f6d4..639bc2e12476f5dd92eb60309a2789bfe990b086 100644 (file)
@@ -411,8 +411,12 @@ static const struct uniphier_pcie_ep_soc_data uniphier_pro5_data = {
                .msi_capable = true,
                .msix_capable = false,
                .align = 1 << 16,
-               .bar_fixed_64bit = BIT(BAR_0) | BIT(BAR_2) | BIT(BAR_4),
-               .reserved_bar =  BIT(BAR_4),
+               .bar[BAR_0] = { .only_64bit = true, },
+               .bar[BAR_1] = { .type = BAR_RESERVED, },
+               .bar[BAR_2] = { .only_64bit = true, },
+               .bar[BAR_3] = { .type = BAR_RESERVED, },
+               .bar[BAR_4] = { .type = BAR_RESERVED, },
+               .bar[BAR_5] = { .type = BAR_RESERVED, },
        },
 };
 
@@ -425,7 +429,12 @@ static const struct uniphier_pcie_ep_soc_data uniphier_nx1_data = {
                .msi_capable = true,
                .msix_capable = false,
                .align = 1 << 12,
-               .bar_fixed_64bit = BIT(BAR_0) | BIT(BAR_2) | BIT(BAR_4),
+               .bar[BAR_0] = { .only_64bit = true, },
+               .bar[BAR_1] = { .type = BAR_RESERVED, },
+               .bar[BAR_2] = { .only_64bit = true, },
+               .bar[BAR_3] = { .type = BAR_RESERVED, },
+               .bar[BAR_4] = { .only_64bit = true, },
+               .bar[BAR_5] = { .type = BAR_RESERVED, },
        },
 };
 
index 1eaffff40b8d4dcdee6b8516fcfbe80034a67e72..5992280e8110be900bb9a177296e39b6d8b55662 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/refcount.h>
 #include <linux/irqdomain.h>
 #include <linux/acpi.h>
+#include <linux/sizes.h>
 #include <asm/mshyperv.h>
 
 /*
@@ -465,7 +466,7 @@ struct pci_eject_response {
        u32 status;
 } __packed;
 
-static int pci_ring_size = (4 * PAGE_SIZE);
+static int pci_ring_size = VMBUS_RING_SIZE(SZ_16K);
 
 /*
  * Driver specific state.
index 5b0730c3891b84226896b6865ddb50a5bd377c11..c08683febdd40ac2b023a69e7d684846c6f22e00 100644 (file)
@@ -336,7 +336,7 @@ static int brcm_pcie_mdio_write(void __iomem *base, u8 port,
        readl(base + PCIE_RC_DL_MDIO_ADDR);
        writel(MDIO_DATA_DONE_MASK | wrdata, base + PCIE_RC_DL_MDIO_WR_DATA);
 
-       err = readw_poll_timeout_atomic(base + PCIE_RC_DL_MDIO_WR_DATA, data,
+       err = readl_poll_timeout_atomic(base + PCIE_RC_DL_MDIO_WR_DATA, data,
                                        MDIO_WT_DONE(data), 10, 100);
        return err;
 }
index e6909271def798e5332dfa02b47befdcee5f610d..05967c6c0b426ad4c8269000cbe61c47d7228992 100644 (file)
@@ -440,11 +440,15 @@ static const struct pci_epc_features rcar_pcie_epc_features = {
        .msi_capable = true,
        .msix_capable = false,
        /* use 64-bit BARs so mark BAR[1,3,5] as reserved */
-       .reserved_bar = 1 << BAR_1 | 1 << BAR_3 | 1 << BAR_5,
-       .bar_fixed_64bit = 1 << BAR_0 | 1 << BAR_2 | 1 << BAR_4,
-       .bar_fixed_size[0] = 128,
-       .bar_fixed_size[2] = 256,
-       .bar_fixed_size[4] = 256,
+       .bar[BAR_0] = { .type = BAR_FIXED, .fixed_size = 128,
+                       .only_64bit = true, },
+       .bar[BAR_1] = { .type = BAR_RESERVED, },
+       .bar[BAR_2] = { .type = BAR_FIXED, .fixed_size = 256,
+                       .only_64bit = true, },
+       .bar[BAR_3] = { .type = BAR_RESERVED, },
+       .bar[BAR_4] = { .type = BAR_FIXED, .fixed_size = 256,
+                       .only_64bit = true, },
+       .bar[BAR_5] = { .type = BAR_RESERVED, },
 };
 
 static const struct pci_epc_features*
diff --git a/drivers/pci/devres.c b/drivers/pci/devres.c
new file mode 100644 (file)
index 0000000..2c562b9
--- /dev/null
@@ -0,0 +1,448 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/device.h>
+#include <linux/pci.h>
+#include "pci.h"
+
+/*
+ * PCI iomap devres
+ */
+#define PCIM_IOMAP_MAX PCI_STD_NUM_BARS
+
+struct pcim_iomap_devres {
+       void __iomem *table[PCIM_IOMAP_MAX];
+};
+
+
+static void devm_pci_unmap_iospace(struct device *dev, void *ptr)
+{
+       struct resource **res = ptr;
+
+       pci_unmap_iospace(*res);
+}
+
+/**
+ * devm_pci_remap_iospace - Managed pci_remap_iospace()
+ * @dev: Generic device to remap IO address for
+ * @res: Resource describing the I/O space
+ * @phys_addr: physical address of range to be mapped
+ *
+ * Managed pci_remap_iospace().  Map is automatically unmapped on driver
+ * detach.
+ */
+int devm_pci_remap_iospace(struct device *dev, const struct resource *res,
+                          phys_addr_t phys_addr)
+{
+       const struct resource **ptr;
+       int error;
+
+       ptr = devres_alloc(devm_pci_unmap_iospace, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return -ENOMEM;
+
+       error = pci_remap_iospace(res, phys_addr);
+       if (error) {
+               devres_free(ptr);
+       } else  {
+               *ptr = res;
+               devres_add(dev, ptr);
+       }
+
+       return error;
+}
+EXPORT_SYMBOL(devm_pci_remap_iospace);
+
+/**
+ * devm_pci_remap_cfgspace - Managed pci_remap_cfgspace()
+ * @dev: Generic device to remap IO address for
+ * @offset: Resource address to map
+ * @size: Size of map
+ *
+ * Managed pci_remap_cfgspace().  Map is automatically unmapped on driver
+ * detach.
+ */
+void __iomem *devm_pci_remap_cfgspace(struct device *dev,
+                                     resource_size_t offset,
+                                     resource_size_t size)
+{
+       void __iomem **ptr, *addr;
+
+       ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return NULL;
+
+       addr = pci_remap_cfgspace(offset, size);
+       if (addr) {
+               *ptr = addr;
+               devres_add(dev, ptr);
+       } else
+               devres_free(ptr);
+
+       return addr;
+}
+EXPORT_SYMBOL(devm_pci_remap_cfgspace);
+
+/**
+ * devm_pci_remap_cfg_resource - check, request region and ioremap cfg resource
+ * @dev: generic device to handle the resource for
+ * @res: configuration space resource to be handled
+ *
+ * Checks that a resource is a valid memory region, requests the memory
+ * region and ioremaps with pci_remap_cfgspace() API that ensures the
+ * proper PCI configuration space memory attributes are guaranteed.
+ *
+ * All operations are managed and will be undone on driver detach.
+ *
+ * Returns a pointer to the remapped memory or an ERR_PTR() encoded error code
+ * on failure. Usage example::
+ *
+ *     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ *     base = devm_pci_remap_cfg_resource(&pdev->dev, res);
+ *     if (IS_ERR(base))
+ *             return PTR_ERR(base);
+ */
+void __iomem *devm_pci_remap_cfg_resource(struct device *dev,
+                                         struct resource *res)
+{
+       resource_size_t size;
+       const char *name;
+       void __iomem *dest_ptr;
+
+       BUG_ON(!dev);
+
+       if (!res || resource_type(res) != IORESOURCE_MEM) {
+               dev_err(dev, "invalid resource\n");
+               return IOMEM_ERR_PTR(-EINVAL);
+       }
+
+       size = resource_size(res);
+
+       if (res->name)
+               name = devm_kasprintf(dev, GFP_KERNEL, "%s %s", dev_name(dev),
+                                     res->name);
+       else
+               name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
+       if (!name)
+               return IOMEM_ERR_PTR(-ENOMEM);
+
+       if (!devm_request_mem_region(dev, res->start, size, name)) {
+               dev_err(dev, "can't request region for resource %pR\n", res);
+               return IOMEM_ERR_PTR(-EBUSY);
+       }
+
+       dest_ptr = devm_pci_remap_cfgspace(dev, res->start, size);
+       if (!dest_ptr) {
+               dev_err(dev, "ioremap failed for resource %pR\n", res);
+               devm_release_mem_region(dev, res->start, size);
+               dest_ptr = IOMEM_ERR_PTR(-ENOMEM);
+       }
+
+       return dest_ptr;
+}
+EXPORT_SYMBOL(devm_pci_remap_cfg_resource);
+
+/**
+ * pcim_set_mwi - a device-managed pci_set_mwi()
+ * @dev: the PCI device for which MWI is enabled
+ *
+ * Managed pci_set_mwi().
+ *
+ * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
+ */
+int pcim_set_mwi(struct pci_dev *dev)
+{
+       struct pci_devres *dr;
+
+       dr = find_pci_dr(dev);
+       if (!dr)
+               return -ENOMEM;
+
+       dr->mwi = 1;
+       return pci_set_mwi(dev);
+}
+EXPORT_SYMBOL(pcim_set_mwi);
+
+
+static void pcim_release(struct device *gendev, void *res)
+{
+       struct pci_dev *dev = to_pci_dev(gendev);
+       struct pci_devres *this = res;
+       int i;
+
+       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
+               if (this->region_mask & (1 << i))
+                       pci_release_region(dev, i);
+
+       if (this->mwi)
+               pci_clear_mwi(dev);
+
+       if (this->restore_intx)
+               pci_intx(dev, this->orig_intx);
+
+       if (this->enabled && !this->pinned)
+               pci_disable_device(dev);
+}
+
+/*
+ * TODO: After the last four callers in pci.c are ported, find_pci_dr()
+ * needs to be made static again.
+ */
+struct pci_devres *find_pci_dr(struct pci_dev *pdev)
+{
+       if (pci_is_managed(pdev))
+               return devres_find(&pdev->dev, pcim_release, NULL, NULL);
+       return NULL;
+}
+
+static struct pci_devres *get_pci_dr(struct pci_dev *pdev)
+{
+       struct pci_devres *dr, *new_dr;
+
+       dr = devres_find(&pdev->dev, pcim_release, NULL, NULL);
+       if (dr)
+               return dr;
+
+       new_dr = devres_alloc(pcim_release, sizeof(*new_dr), GFP_KERNEL);
+       if (!new_dr)
+               return NULL;
+       return devres_get(&pdev->dev, new_dr, NULL, NULL);
+}
+
+/**
+ * pcim_enable_device - Managed pci_enable_device()
+ * @pdev: PCI device to be initialized
+ *
+ * Managed pci_enable_device().
+ */
+int pcim_enable_device(struct pci_dev *pdev)
+{
+       struct pci_devres *dr;
+       int rc;
+
+       dr = get_pci_dr(pdev);
+       if (unlikely(!dr))
+               return -ENOMEM;
+       if (dr->enabled)
+               return 0;
+
+       rc = pci_enable_device(pdev);
+       if (!rc) {
+               pdev->is_managed = 1;
+               dr->enabled = 1;
+       }
+       return rc;
+}
+EXPORT_SYMBOL(pcim_enable_device);
+
+/**
+ * pcim_pin_device - Pin managed PCI device
+ * @pdev: PCI device to pin
+ *
+ * Pin managed PCI device @pdev.  Pinned device won't be disabled on
+ * driver detach.  @pdev must have been enabled with
+ * pcim_enable_device().
+ */
+void pcim_pin_device(struct pci_dev *pdev)
+{
+       struct pci_devres *dr;
+
+       dr = find_pci_dr(pdev);
+       WARN_ON(!dr || !dr->enabled);
+       if (dr)
+               dr->pinned = 1;
+}
+EXPORT_SYMBOL(pcim_pin_device);
+
+static void pcim_iomap_release(struct device *gendev, void *res)
+{
+       struct pci_dev *dev = to_pci_dev(gendev);
+       struct pcim_iomap_devres *this = res;
+       int i;
+
+       for (i = 0; i < PCIM_IOMAP_MAX; i++)
+               if (this->table[i])
+                       pci_iounmap(dev, this->table[i]);
+}
+
+/**
+ * pcim_iomap_table - access iomap allocation table
+ * @pdev: PCI device to access iomap table for
+ *
+ * Access iomap allocation table for @dev.  If iomap table doesn't
+ * exist and @pdev is managed, it will be allocated.  All iomaps
+ * recorded in the iomap table are automatically unmapped on driver
+ * detach.
+ *
+ * This function might sleep when the table is first allocated but can
+ * be safely called without context and guaranteed to succeed once
+ * allocated.
+ */
+void __iomem * const *pcim_iomap_table(struct pci_dev *pdev)
+{
+       struct pcim_iomap_devres *dr, *new_dr;
+
+       dr = devres_find(&pdev->dev, pcim_iomap_release, NULL, NULL);
+       if (dr)
+               return dr->table;
+
+       new_dr = devres_alloc_node(pcim_iomap_release, sizeof(*new_dr), GFP_KERNEL,
+                                  dev_to_node(&pdev->dev));
+       if (!new_dr)
+               return NULL;
+       dr = devres_get(&pdev->dev, new_dr, NULL, NULL);
+       return dr->table;
+}
+EXPORT_SYMBOL(pcim_iomap_table);
+
+/**
+ * pcim_iomap - Managed pcim_iomap()
+ * @pdev: PCI device to iomap for
+ * @bar: BAR to iomap
+ * @maxlen: Maximum length of iomap
+ *
+ * Managed pci_iomap().  Map is automatically unmapped on driver
+ * detach.
+ */
+void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
+{
+       void __iomem **tbl;
+
+       BUG_ON(bar >= PCIM_IOMAP_MAX);
+
+       tbl = (void __iomem **)pcim_iomap_table(pdev);
+       if (!tbl || tbl[bar])   /* duplicate mappings not allowed */
+               return NULL;
+
+       tbl[bar] = pci_iomap(pdev, bar, maxlen);
+       return tbl[bar];
+}
+EXPORT_SYMBOL(pcim_iomap);
+
+/**
+ * pcim_iounmap - Managed pci_iounmap()
+ * @pdev: PCI device to iounmap for
+ * @addr: Address to unmap
+ *
+ * Managed pci_iounmap().  @addr must have been mapped using pcim_iomap().
+ */
+void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr)
+{
+       void __iomem **tbl;
+       int i;
+
+       pci_iounmap(pdev, addr);
+
+       tbl = (void __iomem **)pcim_iomap_table(pdev);
+       BUG_ON(!tbl);
+
+       for (i = 0; i < PCIM_IOMAP_MAX; i++)
+               if (tbl[i] == addr) {
+                       tbl[i] = NULL;
+                       return;
+               }
+       WARN_ON(1);
+}
+EXPORT_SYMBOL(pcim_iounmap);
+
+/**
+ * pcim_iomap_regions - Request and iomap PCI BARs
+ * @pdev: PCI device to map IO resources for
+ * @mask: Mask of BARs to request and iomap
+ * @name: Name used when requesting regions
+ *
+ * Request and iomap regions specified by @mask.
+ */
+int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name)
+{
+       void __iomem * const *iomap;
+       int i, rc;
+
+       iomap = pcim_iomap_table(pdev);
+       if (!iomap)
+               return -ENOMEM;
+
+       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+               unsigned long len;
+
+               if (!(mask & (1 << i)))
+                       continue;
+
+               rc = -EINVAL;
+               len = pci_resource_len(pdev, i);
+               if (!len)
+                       goto err_inval;
+
+               rc = pci_request_region(pdev, i, name);
+               if (rc)
+                       goto err_inval;
+
+               rc = -ENOMEM;
+               if (!pcim_iomap(pdev, i, 0))
+                       goto err_region;
+       }
+
+       return 0;
+
+ err_region:
+       pci_release_region(pdev, i);
+ err_inval:
+       while (--i >= 0) {
+               if (!(mask & (1 << i)))
+                       continue;
+               pcim_iounmap(pdev, iomap[i]);
+               pci_release_region(pdev, i);
+       }
+
+       return rc;
+}
+EXPORT_SYMBOL(pcim_iomap_regions);
+
+/**
+ * pcim_iomap_regions_request_all - Request all BARs and iomap specified ones
+ * @pdev: PCI device to map IO resources for
+ * @mask: Mask of BARs to iomap
+ * @name: Name used when requesting regions
+ *
+ * Request all PCI BARs and iomap regions specified by @mask.
+ */
+int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask,
+                                  const char *name)
+{
+       int request_mask = ((1 << 6) - 1) & ~mask;
+       int rc;
+
+       rc = pci_request_selected_regions(pdev, request_mask, name);
+       if (rc)
+               return rc;
+
+       rc = pcim_iomap_regions(pdev, mask, name);
+       if (rc)
+               pci_release_selected_regions(pdev, request_mask);
+       return rc;
+}
+EXPORT_SYMBOL(pcim_iomap_regions_request_all);
+
+/**
+ * pcim_iounmap_regions - Unmap and release PCI BARs
+ * @pdev: PCI device to map IO resources for
+ * @mask: Mask of BARs to unmap and release
+ *
+ * Unmap and release regions specified by @mask.
+ */
+void pcim_iounmap_regions(struct pci_dev *pdev, int mask)
+{
+       void __iomem * const *iomap;
+       int i;
+
+       iomap = pcim_iomap_table(pdev);
+       if (!iomap)
+               return;
+
+       for (i = 0; i < PCIM_IOMAP_MAX; i++) {
+               if (!(mask & (1 << i)))
+                       continue;
+
+               pcim_iounmap(pdev, iomap[i]);
+               pci_release_region(pdev, i);
+       }
+}
+EXPORT_SYMBOL(pcim_iounmap_regions);
index 1c3e4ea76bd2578e47397d0ddbcfa96a8f705574..2c54d80107cf3cb0c8c6a0de5964ea1e6b6c1b67 100644 (file)
@@ -123,6 +123,22 @@ static const struct pci_epf_mhi_ep_info sm8450_info = {
        .flags = MHI_EPF_USE_DMA,
 };
 
+static struct pci_epf_header sa8775p_header = {
+       .vendorid = PCI_VENDOR_ID_QCOM,
+       .deviceid = 0x0306,               /* FIXME: Update deviceid for sa8775p EP */
+       .baseclass_code = PCI_CLASS_OTHERS,
+       .interrupt_pin = PCI_INTERRUPT_INTA,
+};
+
+static const struct pci_epf_mhi_ep_info sa8775p_info = {
+       .config = &mhi_v1_config,
+       .epf_header = &sa8775p_header,
+       .bar_num = BAR_0,
+       .epf_flags = PCI_BASE_ADDRESS_MEM_TYPE_32,
+       .msi_count = 32,
+       .mru = 0x8000,
+};
+
 struct pci_epf_mhi {
        const struct pci_epc_features *epc_features;
        const struct pci_epf_mhi_ep_info *info;
@@ -913,8 +929,9 @@ static int pci_epf_mhi_probe(struct pci_epf *epf,
 }
 
 static const struct pci_epf_device_id pci_epf_mhi_ids[] = {
-       { .name = "sdx55", .driver_data = (kernel_ulong_t)&sdx55_info },
-       { .name = "sm8450", .driver_data = (kernel_ulong_t)&sm8450_info },
+       { .name = "pci_epf_mhi_sa8775p", .driver_data = (kernel_ulong_t)&sa8775p_info },
+       { .name = "pci_epf_mhi_sdx55", .driver_data = (kernel_ulong_t)&sdx55_info },
+       { .name = "pci_epf_mhi_sm8450", .driver_data = (kernel_ulong_t)&sm8450_info },
        {},
 };
 
index 0553946005c4d92990af6ca8ce6962ea51e74772..e01a98e74d211174db3075c20457a3183f37e0a5 100644 (file)
@@ -1012,13 +1012,13 @@ static int epf_ntb_config_spad_bar_alloc(struct epf_ntb *ntb,
 
        epc_features = ntb_epc->epc_features;
        barno = ntb_epc->epf_ntb_bar[BAR_CONFIG];
-       size = epc_features->bar_fixed_size[barno];
+       size = epc_features->bar[barno].fixed_size;
        align = epc_features->align;
 
        peer_ntb_epc = ntb->epc[!type];
        peer_epc_features = peer_ntb_epc->epc_features;
        peer_barno = ntb_epc->epf_ntb_bar[BAR_PEER_SPAD];
-       peer_size = peer_epc_features->bar_fixed_size[peer_barno];
+       peer_size = peer_epc_features->bar[peer_barno].fixed_size;
 
        /* Check if epc_features is populated incorrectly */
        if ((!IS_ALIGNED(size, align)))
@@ -1067,7 +1067,7 @@ static int epf_ntb_config_spad_bar_alloc(struct epf_ntb *ntb,
        else if (size < ctrl_size + spad_size)
                return -EINVAL;
 
-       base = pci_epf_alloc_space(epf, size, barno, align, type);
+       base = pci_epf_alloc_space(epf, size, barno, epc_features, type);
        if (!base) {
                dev_err(dev, "%s intf: Config/Status/SPAD alloc region fail\n",
                        pci_epc_interface_string(type));
index 18c80002d3bd57c1116e04937371eb7077582835..cd4ffb39dcdc6137a3569ac420c90fc09cce7983 100644 (file)
@@ -729,7 +729,7 @@ static int pci_epf_test_set_bar(struct pci_epf *epf)
                 */
                add = (epf_bar->flags & PCI_BASE_ADDRESS_MEM_TYPE_64) ? 2 : 1;
 
-               if (!!(epc_features->reserved_bar & (1 << bar)))
+               if (epc_features->bar[bar].type == BAR_RESERVED)
                        continue;
 
                ret = pci_epc_set_bar(epc, epf->func_no, epf->vfunc_no,
@@ -841,14 +841,8 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
        }
        test_reg_size = test_reg_bar_size + msix_table_size + pba_size;
 
-       if (epc_features->bar_fixed_size[test_reg_bar]) {
-               if (test_reg_size > bar_size[test_reg_bar])
-                       return -ENOMEM;
-               test_reg_size = bar_size[test_reg_bar];
-       }
-
        base = pci_epf_alloc_space(epf, test_reg_size, test_reg_bar,
-                                  epc_features->align, PRIMARY_INTERFACE);
+                                  epc_features, PRIMARY_INTERFACE);
        if (!base) {
                dev_err(dev, "Failed to allocated register space\n");
                return -ENOMEM;
@@ -862,12 +856,11 @@ static int pci_epf_test_alloc_space(struct pci_epf *epf)
                if (bar == test_reg_bar)
                        continue;
 
-               if (!!(epc_features->reserved_bar & (1 << bar)))
+               if (epc_features->bar[bar].type == BAR_RESERVED)
                        continue;
 
                base = pci_epf_alloc_space(epf, bar_size[bar], bar,
-                                          epc_features->align,
-                                          PRIMARY_INTERFACE);
+                                          epc_features, PRIMARY_INTERFACE);
                if (!base)
                        dev_err(dev, "Failed to allocate space for BAR%d\n",
                                bar);
@@ -881,16 +874,12 @@ static void pci_epf_configure_bar(struct pci_epf *epf,
                                  const struct pci_epc_features *epc_features)
 {
        struct pci_epf_bar *epf_bar;
-       bool bar_fixed_64bit;
        int i;
 
        for (i = 0; i < PCI_STD_NUM_BARS; i++) {
                epf_bar = &epf->bar[i];
-               bar_fixed_64bit = !!(epc_features->bar_fixed_64bit & (1 << i));
-               if (bar_fixed_64bit)
+               if (epc_features->bar[i].only_64bit)
                        epf_bar->flags |= PCI_BASE_ADDRESS_MEM_TYPE_64;
-               if (epc_features->bar_fixed_size[i])
-                       bar_size[i] = epc_features->bar_fixed_size[i];
        }
 }
 
index e75a2af77328ea47efb67ea358b4f847d4275687..8e779eecd62d41babe9beca177a01e2fd7ae7f69 100644 (file)
@@ -422,7 +422,7 @@ static int epf_ntb_config_spad_bar_alloc(struct epf_ntb *ntb)
                                                                epf->func_no,
                                                                epf->vfunc_no);
        barno = ntb->epf_ntb_bar[BAR_CONFIG];
-       size = epc_features->bar_fixed_size[barno];
+       size = epc_features->bar[barno].fixed_size;
        align = epc_features->align;
 
        if ((!IS_ALIGNED(size, align)))
@@ -446,7 +446,7 @@ static int epf_ntb_config_spad_bar_alloc(struct epf_ntb *ntb)
        else if (size < ctrl_size + spad_size)
                return -EINVAL;
 
-       base = pci_epf_alloc_space(epf, size, barno, align, 0);
+       base = pci_epf_alloc_space(epf, size, barno, epc_features, 0);
        if (!base) {
                dev_err(dev, "Config/Status/SPAD alloc region fail\n");
                return -ENOMEM;
@@ -527,7 +527,6 @@ static int epf_ntb_configure_interrupt(struct epf_ntb *ntb)
 static int epf_ntb_db_bar_init(struct epf_ntb *ntb)
 {
        const struct pci_epc_features *epc_features;
-       u32 align;
        struct device *dev = &ntb->epf->dev;
        int ret;
        struct pci_epf_bar *epf_bar;
@@ -538,19 +537,9 @@ static int epf_ntb_db_bar_init(struct epf_ntb *ntb)
        epc_features = pci_epc_get_features(ntb->epf->epc,
                                            ntb->epf->func_no,
                                            ntb->epf->vfunc_no);
-       align = epc_features->align;
-
-       if (size < 128)
-               size = 128;
-
-       if (align)
-               size = ALIGN(size, align);
-       else
-               size = roundup_pow_of_two(size);
-
        barno = ntb->epf_ntb_bar[BAR_DB];
 
-       mw_addr = pci_epf_alloc_space(ntb->epf, size, barno, align, 0);
+       mw_addr = pci_epf_alloc_space(ntb->epf, size, barno, epc_features, 0);
        if (!mw_addr) {
                dev_err(dev, "Failed to allocate OB address\n");
                return -ENOMEM;
@@ -1269,21 +1258,17 @@ static int pci_vntb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
        if (ret) {
                dev_err(dev, "Cannot set DMA mask\n");
-               return -EINVAL;
+               return ret;
        }
 
        ret = ntb_register_device(&ndev->ntb);
        if (ret) {
                dev_err(dev, "Failed to register NTB device\n");
-               goto err_register_dev;
+               return ret;
        }
 
        dev_dbg(dev, "PCI Virtual NTB driver loaded\n");
        return 0;
-
-err_register_dev:
-       put_device(&ndev->ntb.dev);
-       return -EINVAL;
 }
 
 static struct pci_device_id pci_vntb_table[] = {
index dcd4e66430c10a9328f05a11f9c28c88b2c5c4bf..da3fc0795b0b620c06c39fe9304eb84857c6c0ca 100644 (file)
@@ -87,7 +87,7 @@ EXPORT_SYMBOL_GPL(pci_epc_get);
  * @epc_features: pci_epc_features structure that holds the reserved bar bitmap
  *
  * Invoke to get the first unreserved BAR that can be used by the endpoint
- * function. For any incorrect value in reserved_bar return '0'.
+ * function.
  */
 enum pci_barno
 pci_epc_get_first_free_bar(const struct pci_epc_features *epc_features)
@@ -102,32 +102,27 @@ EXPORT_SYMBOL_GPL(pci_epc_get_first_free_bar);
  * @bar: the starting BAR number from where unreserved BAR should be searched
  *
  * Invoke to get the next unreserved BAR starting from @bar that can be used
- * for endpoint function. For any incorrect value in reserved_bar return '0'.
+ * for endpoint function.
  */
 enum pci_barno pci_epc_get_next_free_bar(const struct pci_epc_features
                                         *epc_features, enum pci_barno bar)
 {
-       unsigned long free_bar;
+       int i;
 
        if (!epc_features)
                return BAR_0;
 
        /* If 'bar - 1' is a 64-bit BAR, move to the next BAR */
-       if ((epc_features->bar_fixed_64bit << 1) & 1 << bar)
+       if (bar > 0 && epc_features->bar[bar - 1].only_64bit)
                bar++;
 
-       /* Find if the reserved BAR is also a 64-bit BAR */
-       free_bar = epc_features->reserved_bar & epc_features->bar_fixed_64bit;
-
-       /* Set the adjacent bit if the reserved BAR is also a 64-bit BAR */
-       free_bar <<= 1;
-       free_bar |= epc_features->reserved_bar;
-
-       free_bar = find_next_zero_bit(&free_bar, 6, bar);
-       if (free_bar > 5)
-               return NO_BAR;
+       for (i = bar; i < PCI_STD_NUM_BARS; i++) {
+               /* If the BAR is not reserved, return it. */
+               if (epc_features->bar[i].type != BAR_RESERVED)
+                       return i;
+       }
 
-       return free_bar;
+       return NO_BAR;
 }
 EXPORT_SYMBOL_GPL(pci_epc_get_next_free_bar);
 
index 2c32de66793778d3d99932e362339bc1764451ee..0a28a0b0911b1989dc2a265e0115282db00bc8a3 100644 (file)
@@ -17,7 +17,7 @@
 
 static DEFINE_MUTEX(pci_epf_mutex);
 
-static struct bus_type pci_epf_bus_type;
+static const struct bus_type pci_epf_bus_type;
 static const struct device_type pci_epf_type;
 
 /**
@@ -251,14 +251,17 @@ EXPORT_SYMBOL_GPL(pci_epf_free_space);
  * @epf: the EPF device to whom allocate the memory
  * @size: the size of the memory that has to be allocated
  * @bar: the BAR number corresponding to the allocated register space
- * @align: alignment size for the allocation region
+ * @epc_features: the features provided by the EPC specific to this EPF
  * @type: Identifies if the allocation is for primary EPC or secondary EPC
  *
  * Invoke to allocate memory for the PCI EPF register space.
  */
 void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
-                         size_t align, enum pci_epc_interface_type type)
+                         const struct pci_epc_features *epc_features,
+                         enum pci_epc_interface_type type)
 {
+       u64 bar_fixed_size = epc_features->bar[bar].fixed_size;
+       size_t align = epc_features->align;
        struct pci_epf_bar *epf_bar;
        dma_addr_t phys_addr;
        struct pci_epc *epc;
@@ -268,6 +271,15 @@ void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
        if (size < 128)
                size = 128;
 
+       if (epc_features->bar[bar].type == BAR_FIXED && bar_fixed_size) {
+               if (size > bar_fixed_size) {
+                       dev_err(&epf->dev,
+                               "requested BAR size is larger than fixed size\n");
+                       return NULL;
+               }
+               size = bar_fixed_size;
+       }
+
        if (align)
                size = ALIGN(size, align);
        else
@@ -507,7 +519,7 @@ static void pci_epf_device_remove(struct device *dev)
        epf->driver = NULL;
 }
 
-static struct bus_type pci_epf_bus_type = {
+static const struct bus_type pci_epf_bus_type = {
        .name           = "pci-epf",
        .match          = pci_epf_device_match,
        .probe          = pci_epf_device_probe,
similarity index 99%
rename from lib/pci_iomap.c
rename to drivers/pci/iomap.c
index ce39ce9f3526ea2eee7891b62302369b076e8974..c9725428e3874ffd0a7ee6baac1299ba270f5457 100644 (file)
@@ -9,7 +9,6 @@
 
 #include <linux/export.h>
 
-#ifdef CONFIG_PCI
 /**
  * pci_iomap_range - create a virtual mapping cookie for a PCI BAR
  * @dev: PCI device that owns the BAR
@@ -170,11 +169,9 @@ void pci_iounmap(struct pci_dev *dev, void __iomem *p)
 
        if (addr >= start && addr < start + IO_SPACE_LIMIT)
                return;
-       iounmap(p);
 #endif
+       iounmap(p);
 }
 EXPORT_SYMBOL(pci_iounmap);
 
 #endif /* ARCH_WANTS_GENERIC_PCI_IOUNMAP */
-
-#endif /* CONFIG_PCI */
index 0050e8f6814ed655ee06a87252ed468d22963722..4555630be9ecdf3d46b5ea1ebf90fe6861a00212 100644 (file)
@@ -8,9 +8,13 @@
 
 #include <linux/device.h>
 #include <linux/kernel.h>
+#include <linux/errno.h>
 #include <linux/export.h>
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 
+#include "pci.h"
+
 /**
  * pci_request_irq - allocate an interrupt line for a PCI device
  * @dev:       PCI device to operate on
@@ -74,3 +78,203 @@ void pci_free_irq(struct pci_dev *dev, unsigned int nr, void *dev_id)
        kfree(free_irq(pci_irq_vector(dev, nr), dev_id));
 }
 EXPORT_SYMBOL(pci_free_irq);
+
+/**
+ * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge
+ * @dev: the PCI device
+ * @pin: the INTx pin (1=INTA, 2=INTB, 3=INTC, 4=INTD)
+ *
+ * Perform INTx swizzling for a device behind one level of bridge.  This is
+ * required by section 9.1 of the PCI-to-PCI bridge specification for devices
+ * behind bridges on add-in cards.  For devices with ARI enabled, the slot
+ * number is always 0 (see the Implementation Note in section 2.2.8.1 of
+ * the PCI Express Base Specification, Revision 2.1)
+ */
+u8 pci_swizzle_interrupt_pin(const struct pci_dev *dev, u8 pin)
+{
+       int slot;
+
+       if (pci_ari_enabled(dev->bus))
+               slot = 0;
+       else
+               slot = PCI_SLOT(dev->devfn);
+
+       return (((pin - 1) + slot) % 4) + 1;
+}
+
+int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)
+{
+       u8 pin;
+
+       pin = dev->pin;
+       if (!pin)
+               return -1;
+
+       while (!pci_is_root_bus(dev->bus)) {
+               pin = pci_swizzle_interrupt_pin(dev, pin);
+               dev = dev->bus->self;
+       }
+       *bridge = dev;
+       return pin;
+}
+
+/**
+ * pci_common_swizzle - swizzle INTx all the way to root bridge
+ * @dev: the PCI device
+ * @pinp: pointer to the INTx pin value (1=INTA, 2=INTB, 3=INTD, 4=INTD)
+ *
+ * Perform INTx swizzling for a device.  This traverses through all PCI-to-PCI
+ * bridges all the way up to a PCI root bus.
+ */
+u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+       u8 pin = *pinp;
+
+       while (!pci_is_root_bus(dev->bus)) {
+               pin = pci_swizzle_interrupt_pin(dev, pin);
+               dev = dev->bus->self;
+       }
+       *pinp = pin;
+       return PCI_SLOT(dev->devfn);
+}
+EXPORT_SYMBOL_GPL(pci_common_swizzle);
+
+void pci_assign_irq(struct pci_dev *dev)
+{
+       u8 pin;
+       u8 slot = -1;
+       int irq = 0;
+       struct pci_host_bridge *hbrg = pci_find_host_bridge(dev->bus);
+
+       if (!(hbrg->map_irq)) {
+               pci_dbg(dev, "runtime IRQ mapping not provided by arch\n");
+               return;
+       }
+
+       /*
+        * If this device is not on the primary bus, we need to figure out
+        * which interrupt pin it will come in on. We know which slot it
+        * will come in on because that slot is where the bridge is. Each
+        * time the interrupt line passes through a PCI-PCI bridge we must
+        * apply the swizzle function.
+        */
+       pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+       /* Cope with illegal. */
+       if (pin > 4)
+               pin = 1;
+
+       if (pin) {
+               /* Follow the chain of bridges, swizzling as we go. */
+               if (hbrg->swizzle_irq)
+                       slot = (*(hbrg->swizzle_irq))(dev, &pin);
+
+               /*
+                * If a swizzling function is not used, map_irq() must
+                * ignore slot.
+                */
+               irq = (*(hbrg->map_irq))(dev, slot, pin);
+               if (irq == -1)
+                       irq = 0;
+       }
+       dev->irq = irq;
+
+       pci_dbg(dev, "assign IRQ: got %d\n", dev->irq);
+
+       /*
+        * Always tell the device, so the driver knows what is the real IRQ
+        * to use; the device does not use it.
+        */
+       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+static bool pci_check_and_set_intx_mask(struct pci_dev *dev, bool mask)
+{
+       struct pci_bus *bus = dev->bus;
+       bool mask_updated = true;
+       u32 cmd_status_dword;
+       u16 origcmd, newcmd;
+       unsigned long flags;
+       bool irq_pending;
+
+       /*
+        * We do a single dword read to retrieve both command and status.
+        * Document assumptions that make this possible.
+        */
+       BUILD_BUG_ON(PCI_COMMAND % 4);
+       BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS);
+
+       raw_spin_lock_irqsave(&pci_lock, flags);
+
+       bus->ops->read(bus, dev->devfn, PCI_COMMAND, 4, &cmd_status_dword);
+
+       irq_pending = (cmd_status_dword >> 16) & PCI_STATUS_INTERRUPT;
+
+       /*
+        * Check interrupt status register to see whether our device
+        * triggered the interrupt (when masking) or the next IRQ is
+        * already pending (when unmasking).
+        */
+       if (mask != irq_pending) {
+               mask_updated = false;
+               goto done;
+       }
+
+       origcmd = cmd_status_dword;
+       newcmd = origcmd & ~PCI_COMMAND_INTX_DISABLE;
+       if (mask)
+               newcmd |= PCI_COMMAND_INTX_DISABLE;
+       if (newcmd != origcmd)
+               bus->ops->write(bus, dev->devfn, PCI_COMMAND, 2, newcmd);
+
+done:
+       raw_spin_unlock_irqrestore(&pci_lock, flags);
+
+       return mask_updated;
+}
+
+/**
+ * pci_check_and_mask_intx - mask INTx on pending interrupt
+ * @dev: the PCI device to operate on
+ *
+ * Check if the device dev has its INTx line asserted, mask it and return
+ * true in that case. False is returned if no interrupt was pending.
+ */
+bool pci_check_and_mask_intx(struct pci_dev *dev)
+{
+       return pci_check_and_set_intx_mask(dev, true);
+}
+EXPORT_SYMBOL_GPL(pci_check_and_mask_intx);
+
+/**
+ * pci_check_and_unmask_intx - unmask INTx if no interrupt is pending
+ * @dev: the PCI device to operate on
+ *
+ * Check if the device dev has its INTx line asserted, unmask it if not and
+ * return true. False is returned and the mask remains active if there was
+ * still an interrupt pending.
+ */
+bool pci_check_and_unmask_intx(struct pci_dev *dev)
+{
+       return pci_check_and_set_intx_mask(dev, false);
+}
+EXPORT_SYMBOL_GPL(pci_check_and_unmask_intx);
+
+/**
+ * pcibios_penalize_isa_irq - penalize an ISA IRQ
+ * @irq: ISA IRQ to penalize
+ * @active: IRQ active or not
+ *
+ * Permits the platform to provide architecture-specific functionality when
+ * penalizing ISA IRQs. This is the default implementation. Architecture
+ * implementations can override this.
+ */
+void __weak pcibios_penalize_isa_irq(int irq, int active) {}
+
+int __weak pcibios_alloc_irq(struct pci_dev *dev)
+{
+       return 0;
+}
+
+void __weak pcibios_free_irq(struct pci_dev *dev)
+{
+}
index 4504039056d1b54978bcbbdb8fca0360297a7ca6..8da3347a95c47a655dbf0cba643bd4235cd2ba28 100644 (file)
@@ -11,6 +11,8 @@
 #include <linux/mm.h>
 #include <linux/pci.h>
 
+#include "pci.h"
+
 #ifdef ARCH_GENERIC_PCI_MMAP_RESOURCE
 
 static const struct vm_operations_struct pci_phys_vm_ops = {
@@ -50,3 +52,30 @@ int pci_mmap_resource_range(struct pci_dev *pdev, int bar,
 }
 
 #endif
+
+#if (defined(CONFIG_SYSFS) || defined(CONFIG_PROC_FS)) && \
+    (defined(HAVE_PCI_MMAP) || defined(ARCH_GENERIC_PCI_MMAP_RESOURCE))
+
+int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,
+                 enum pci_mmap_api mmap_api)
+{
+       resource_size_t pci_start = 0, pci_end;
+       unsigned long nr, start, size;
+
+       if (pci_resource_len(pdev, resno) == 0)
+               return 0;
+       nr = vma_pages(vma);
+       start = vma->vm_pgoff;
+       size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
+       if (mmap_api == PCI_MMAP_PROCFS) {
+               pci_resource_to_user(pdev, resno, &pdev->resource[resno],
+                                    &pci_start, &pci_end);
+               pci_start >>= PAGE_SHIFT;
+       }
+       if (start >= pci_start && start < pci_start + size &&
+           start + nr <= pci_start + size)
+               return 1;
+       return 0;
+}
+
+#endif
index 0c361561b855c1bde88c43266baa04afb9554622..4f47a13cb500ff5339cde426b6ccb020fcd74ae7 100644 (file)
@@ -661,7 +661,7 @@ done:
        p2pdma = rcu_dereference(provider->p2pdma);
        if (p2pdma)
                xa_store(&p2pdma->map_types, map_types_idx(client),
-                        xa_mk_value(map_type), GFP_KERNEL);
+                        xa_mk_value(map_type), GFP_ATOMIC);
        rcu_read_unlock();
        return map_type;
 }
index 51ec9e7e784f0e3a82134a05b114abe5be90d07c..af2996d0d17ffc0fa2ae730eb09d58243cf79a5b 100644 (file)
@@ -419,15 +419,6 @@ static int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
        return error;
 }
 
-int __weak pcibios_alloc_irq(struct pci_dev *dev)
-{
-       return 0;
-}
-
-void __weak pcibios_free_irq(struct pci_dev *dev)
-{
-}
-
 #ifdef CONFIG_PCI_IOV
 static inline bool pci_device_can_probe(struct pci_dev *pdev)
 {
@@ -473,6 +464,13 @@ static void pci_device_remove(struct device *dev)
 
        if (drv->remove) {
                pm_runtime_get_sync(dev);
+               /*
+                * If the driver provides a .runtime_idle() callback and it has
+                * started to run already, it may continue to run in parallel
+                * with the code below, so wait until all of the runtime PM
+                * activity has completed.
+                */
+               pm_runtime_barrier(dev);
                drv->remove(pci_dev);
                pm_runtime_put_noidle(dev);
        }
@@ -1382,10 +1380,7 @@ static int pci_pm_runtime_idle(struct device *dev)
        if (!pci_dev->driver)
                return 0;
 
-       if (!pm)
-               return -ENOSYS;
-
-       if (pm->runtime_idle)
+       if (pm && pm->runtime_idle)
                return pm->runtime_idle(dev);
 
        return 0;
@@ -1714,7 +1709,7 @@ static int pcie_port_bus_match(struct device *dev, struct device_driver *drv)
        return 1;
 }
 
-struct bus_type pcie_port_bus_type = {
+const struct bus_type pcie_port_bus_type = {
        .name           = "pci_express",
        .match          = pcie_port_bus_match,
 };
index 2321fdfefd7db2682f230cc6267a7bc9b23f75e3..40cfa716392fbd79e075270ca64185ff4c6022c5 100644 (file)
@@ -1022,29 +1022,6 @@ void pci_remove_legacy_files(struct pci_bus *b)
 #endif /* HAVE_PCI_LEGACY */
 
 #if defined(HAVE_PCI_MMAP) || defined(ARCH_GENERIC_PCI_MMAP_RESOURCE)
-
-int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,
-                 enum pci_mmap_api mmap_api)
-{
-       unsigned long nr, start, size;
-       resource_size_t pci_start = 0, pci_end;
-
-       if (pci_resource_len(pdev, resno) == 0)
-               return 0;
-       nr = vma_pages(vma);
-       start = vma->vm_pgoff;
-       size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
-       if (mmap_api == PCI_MMAP_PROCFS) {
-               pci_resource_to_user(pdev, resno, &pdev->resource[resno],
-                                    &pci_start, &pci_end);
-               pci_start >>= PAGE_SHIFT;
-       }
-       if (start >= pci_start && start < pci_start + size &&
-                       start + nr <= pci_start + size)
-               return 1;
-       return 0;
-}
-
 /**
  * pci_mmap_resource - map a PCI resource into user memory space
  * @kobj: kobject for mapping
@@ -1410,79 +1387,89 @@ static const struct attribute_group pci_dev_reset_attr_group = {
        .is_visible = pci_dev_reset_attr_is_visible,
 };
 
+static ssize_t __resource_resize_show(struct device *dev, int n, char *buf)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       ssize_t ret;
+
+       pci_config_pm_runtime_get(pdev);
+
+       ret = sysfs_emit(buf, "%016llx\n",
+                        (u64)pci_rebar_get_possible_sizes(pdev, n));
+
+       pci_config_pm_runtime_put(pdev);
+
+       return ret;
+}
+
+static ssize_t __resource_resize_store(struct device *dev, int n,
+                                      const char *buf, size_t count)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       unsigned long size, flags;
+       int ret, i;
+       u16 cmd;
+
+       if (kstrtoul(buf, 0, &size) < 0)
+               return -EINVAL;
+
+       device_lock(dev);
+       if (dev->driver) {
+               ret = -EBUSY;
+               goto unlock;
+       }
+
+       pci_config_pm_runtime_get(pdev);
+
+       if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {
+               ret = aperture_remove_conflicting_pci_devices(pdev,
+                                               "resourceN_resize");
+               if (ret)
+                       goto pm_put;
+       }
+
+       pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+       pci_write_config_word(pdev, PCI_COMMAND,
+                             cmd & ~PCI_COMMAND_MEMORY);
+
+       flags = pci_resource_flags(pdev, n);
+
+       pci_remove_resource_files(pdev);
+
+       for (i = 0; i < PCI_STD_NUM_BARS; i++) {
+               if (pci_resource_len(pdev, i) &&
+                   pci_resource_flags(pdev, i) == flags)
+                       pci_release_resource(pdev, i);
+       }
+
+       ret = pci_resize_resource(pdev, n, size);
+
+       pci_assign_unassigned_bus_resources(pdev->bus);
+
+       if (pci_create_resource_files(pdev))
+               pci_warn(pdev, "Failed to recreate resource files after BAR resizing\n");
+
+       pci_write_config_word(pdev, PCI_COMMAND, cmd);
+pm_put:
+       pci_config_pm_runtime_put(pdev);
+unlock:
+       device_unlock(dev);
+
+       return ret ? ret : count;
+}
+
 #define pci_dev_resource_resize_attr(n)                                        \
 static ssize_t resource##n##_resize_show(struct device *dev,           \
                                         struct device_attribute *attr, \
-                                        char * buf)                    \
+                                        char *buf)                     \
 {                                                                      \
-       struct pci_dev *pdev = to_pci_dev(dev);                         \
-       ssize_t ret;                                                    \
-                                                                       \
-       pci_config_pm_runtime_get(pdev);                                \
-                                                                       \
-       ret = sysfs_emit(buf, "%016llx\n",                              \
-                        (u64)pci_rebar_get_possible_sizes(pdev, n));   \
-                                                                       \
-       pci_config_pm_runtime_put(pdev);                                \
-                                                                       \
-       return ret;                                                     \
+       return __resource_resize_show(dev, n, buf);                     \
 }                                                                      \
-                                                                       \
 static ssize_t resource##n##_resize_store(struct device *dev,          \
                                          struct device_attribute *attr,\
                                          const char *buf, size_t count)\
 {                                                                      \
-       struct pci_dev *pdev = to_pci_dev(dev);                         \
-       unsigned long size, flags;                                      \
-       int ret, i;                                                     \
-       u16 cmd;                                                        \
-                                                                       \
-       if (kstrtoul(buf, 0, &size) < 0)                                \
-               return -EINVAL;                                         \
-                                                                       \
-       device_lock(dev);                                               \
-       if (dev->driver) {                                              \
-               ret = -EBUSY;                                           \
-               goto unlock;                                            \
-       }                                                               \
-                                                                       \
-       pci_config_pm_runtime_get(pdev);                                \
-                                                                       \
-       if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA) {              \
-               ret = aperture_remove_conflicting_pci_devices(pdev,     \
-                                               "resourceN_resize");    \
-               if (ret)                                                \
-                       goto pm_put;                                    \
-       }                                                               \
-                                                                       \
-       pci_read_config_word(pdev, PCI_COMMAND, &cmd);                  \
-       pci_write_config_word(pdev, PCI_COMMAND,                        \
-                             cmd & ~PCI_COMMAND_MEMORY);               \
-                                                                       \
-       flags = pci_resource_flags(pdev, n);                            \
-                                                                       \
-       pci_remove_resource_files(pdev);                                \
-                                                                       \
-       for (i = 0; i < PCI_STD_NUM_BARS; i++) {                        \
-               if (pci_resource_len(pdev, i) &&                        \
-                   pci_resource_flags(pdev, i) == flags)               \
-                       pci_release_resource(pdev, i);                  \
-       }                                                               \
-                                                                       \
-       ret = pci_resize_resource(pdev, n, size);                       \
-                                                                       \
-       pci_assign_unassigned_bus_resources(pdev->bus);                 \
-                                                                       \
-       if (pci_create_resource_files(pdev))                            \
-               pci_warn(pdev, "Failed to recreate resource files after BAR resizing\n");\
-                                                                       \
-       pci_write_config_word(pdev, PCI_COMMAND, cmd);                  \
-pm_put:                                                                        \
-       pci_config_pm_runtime_put(pdev);                                \
-unlock:                                                                        \
-       device_unlock(dev);                                             \
-                                                                       \
-       return ret ? ret : count;                                       \
+       return __resource_resize_store(dev, n, buf, count);             \
 }                                                                      \
 static DEVICE_ATTR_RW(resource##n##_resize)
 
@@ -1660,7 +1647,7 @@ static const struct attribute_group pcie_dev_attr_group = {
        .is_visible = pcie_dev_attrs_are_visible,
 };
 
-static const struct attribute_group *pci_dev_attr_groups[] = {
+const struct attribute_group *pci_dev_attr_groups[] = {
        &pci_dev_attr_group,
        &pci_dev_hp_attr_group,
 #ifdef CONFIG_PCI_IOV
@@ -1677,7 +1664,3 @@ static const struct attribute_group *pci_dev_attr_groups[] = {
 #endif
        NULL,
 };
-
-const struct device_type pci_dev_type = {
-       .groups = pci_dev_attr_groups,
-};
index 1e33f0e2d945d1ed587fabf322a94292b512d54d..e5f243dd428845a124da6df6419128cdcfee201d 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/log2.h>
 #include <linux/logic_pio.h>
 #include <linux/pm_wakeup.h>
-#include <linux/interrupt.h>
 #include <linux/device.h>
 #include <linux/pm_runtime.h>
 #include <linux/pci_hotplug.h>
@@ -1067,6 +1066,34 @@ disable_acs_redir:
        pci_disable_acs_redir(dev);
 }
 
+/**
+ * pcie_read_tlp_log - read TLP Header Log
+ * @dev: PCIe device
+ * @where: PCI Config offset of TLP Header Log
+ * @tlp_log: TLP Log structure to fill
+ *
+ * Fill @tlp_log from TLP Header Log registers, e.g., AER or DPC.
+ *
+ * Return: 0 on success and filled TLP Log structure, <0 on error.
+ */
+int pcie_read_tlp_log(struct pci_dev *dev, int where,
+                     struct pcie_tlp_log *tlp_log)
+{
+       int i, ret;
+
+       memset(tlp_log, 0, sizeof(*tlp_log));
+
+       for (i = 0; i < 4; i++) {
+               ret = pci_read_config_dword(dev, where + i * 4,
+                                           &tlp_log->dw[i]);
+               if (ret)
+                       return pcibios_err_to_errno(ret);
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(pcie_read_tlp_log);
+
 /**
  * pci_restore_bars - restore a device's BAR values (e.g. after wake-up)
  * @dev: PCI device to have its BARs restored
@@ -1649,25 +1676,10 @@ static int pci_save_pcie_state(struct pci_dev *dev)
        pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &cap[i++]);
        pcie_capability_read_word(dev, PCI_EXP_SLTCTL2, &cap[i++]);
 
-       return 0;
-}
-
-void pci_bridge_reconfigure_ltr(struct pci_dev *dev)
-{
-#ifdef CONFIG_PCIEASPM
-       struct pci_dev *bridge;
-       u32 ctl;
+       pci_save_aspm_l1ss_state(dev);
+       pci_save_ltr_state(dev);
 
-       bridge = pci_upstream_bridge(dev);
-       if (bridge && bridge->ltr_path) {
-               pcie_capability_read_dword(bridge, PCI_EXP_DEVCTL2, &ctl);
-               if (!(ctl & PCI_EXP_DEVCTL2_LTR_EN)) {
-                       pci_dbg(bridge, "re-enabling LTR\n");
-                       pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2,
-                                                PCI_EXP_DEVCTL2_LTR_EN);
-               }
-       }
-#endif
+       return 0;
 }
 
 static void pci_restore_pcie_state(struct pci_dev *dev)
@@ -1676,6 +1688,13 @@ static void pci_restore_pcie_state(struct pci_dev *dev)
        struct pci_cap_saved_state *save_state;
        u16 *cap;
 
+       /*
+        * Restore max latencies (in the LTR capability) before enabling
+        * LTR itself in PCI_EXP_DEVCTL2.
+        */
+       pci_restore_ltr_state(dev);
+       pci_restore_aspm_l1ss_state(dev);
+
        save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
        if (!save_state)
                return;
@@ -1733,46 +1752,6 @@ static void pci_restore_pcix_state(struct pci_dev *dev)
        pci_write_config_word(dev, pos + PCI_X_CMD, cap[i++]);
 }
 
-static void pci_save_ltr_state(struct pci_dev *dev)
-{
-       int ltr;
-       struct pci_cap_saved_state *save_state;
-       u32 *cap;
-
-       if (!pci_is_pcie(dev))
-               return;
-
-       ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
-       if (!ltr)
-               return;
-
-       save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR);
-       if (!save_state) {
-               pci_err(dev, "no suspend buffer for LTR; ASPM issues possible after resume\n");
-               return;
-       }
-
-       /* Some broken devices only support dword access to LTR */
-       cap = &save_state->cap.data[0];
-       pci_read_config_dword(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, cap);
-}
-
-static void pci_restore_ltr_state(struct pci_dev *dev)
-{
-       struct pci_cap_saved_state *save_state;
-       int ltr;
-       u32 *cap;
-
-       save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR);
-       ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
-       if (!save_state || !ltr)
-               return;
-
-       /* Some broken devices only support dword access to LTR */
-       cap = &save_state->cap.data[0];
-       pci_write_config_dword(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, *cap);
-}
-
 /**
  * pci_save_state - save the PCI configuration space of a device before
  *                 suspending
@@ -1797,7 +1776,6 @@ int pci_save_state(struct pci_dev *dev)
        if (i != 0)
                return i;
 
-       pci_save_ltr_state(dev);
        pci_save_dpc_state(dev);
        pci_save_aer_state(dev);
        pci_save_ptm_state(dev);
@@ -1898,12 +1876,6 @@ void pci_restore_state(struct pci_dev *dev)
        if (!dev->state_saved)
                return;
 
-       /*
-        * Restore max latencies (in the LTR capability) before enabling
-        * LTR itself (in the PCIe capability).
-        */
-       pci_restore_ltr_state(dev);
-
        pci_restore_pcie_state(dev);
        pci_restore_pasid_state(dev);
        pci_restore_pri_state(dev);
@@ -2183,107 +2155,6 @@ int pci_enable_device(struct pci_dev *dev)
 }
 EXPORT_SYMBOL(pci_enable_device);
 
-/*
- * Managed PCI resources.  This manages device on/off, INTx/MSI/MSI-X
- * on/off and BAR regions.  pci_dev itself records MSI/MSI-X status, so
- * there's no need to track it separately.  pci_devres is initialized
- * when a device is enabled using managed PCI device enable interface.
- */
-struct pci_devres {
-       unsigned int enabled:1;
-       unsigned int pinned:1;
-       unsigned int orig_intx:1;
-       unsigned int restore_intx:1;
-       unsigned int mwi:1;
-       u32 region_mask;
-};
-
-static void pcim_release(struct device *gendev, void *res)
-{
-       struct pci_dev *dev = to_pci_dev(gendev);
-       struct pci_devres *this = res;
-       int i;
-
-       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
-               if (this->region_mask & (1 << i))
-                       pci_release_region(dev, i);
-
-       if (this->mwi)
-               pci_clear_mwi(dev);
-
-       if (this->restore_intx)
-               pci_intx(dev, this->orig_intx);
-
-       if (this->enabled && !this->pinned)
-               pci_disable_device(dev);
-}
-
-static struct pci_devres *get_pci_dr(struct pci_dev *pdev)
-{
-       struct pci_devres *dr, *new_dr;
-
-       dr = devres_find(&pdev->dev, pcim_release, NULL, NULL);
-       if (dr)
-               return dr;
-
-       new_dr = devres_alloc(pcim_release, sizeof(*new_dr), GFP_KERNEL);
-       if (!new_dr)
-               return NULL;
-       return devres_get(&pdev->dev, new_dr, NULL, NULL);
-}
-
-static struct pci_devres *find_pci_dr(struct pci_dev *pdev)
-{
-       if (pci_is_managed(pdev))
-               return devres_find(&pdev->dev, pcim_release, NULL, NULL);
-       return NULL;
-}
-
-/**
- * pcim_enable_device - Managed pci_enable_device()
- * @pdev: PCI device to be initialized
- *
- * Managed pci_enable_device().
- */
-int pcim_enable_device(struct pci_dev *pdev)
-{
-       struct pci_devres *dr;
-       int rc;
-
-       dr = get_pci_dr(pdev);
-       if (unlikely(!dr))
-               return -ENOMEM;
-       if (dr->enabled)
-               return 0;
-
-       rc = pci_enable_device(pdev);
-       if (!rc) {
-               pdev->is_managed = 1;
-               dr->enabled = 1;
-       }
-       return rc;
-}
-EXPORT_SYMBOL(pcim_enable_device);
-
-/**
- * pcim_pin_device - Pin managed PCI device
- * @pdev: PCI device to pin
- *
- * Pin managed PCI device @pdev.  Pinned device won't be disabled on
- * driver detach.  @pdev must have been enabled with
- * pcim_enable_device().
- */
-void pcim_pin_device(struct pci_dev *pdev)
-{
-       struct pci_devres *dr;
-
-       dr = find_pci_dr(pdev);
-       WARN_ON(!dr || !dr->enabled);
-       if (dr)
-               dr->pinned = 1;
-}
-EXPORT_SYMBOL(pcim_pin_device);
-
 /*
  * pcibios_device_add - provide arch specific hooks when adding device dev
  * @dev: the PCI device being added
@@ -2318,17 +2189,6 @@ void __weak pcibios_release_device(struct pci_dev *dev) {}
  */
 void __weak pcibios_disable_device(struct pci_dev *dev) {}
 
-/**
- * pcibios_penalize_isa_irq - penalize an ISA IRQ
- * @irq: ISA IRQ to penalize
- * @active: IRQ active or not
- *
- * Permits the platform to provide architecture-specific functionality when
- * penalizing ISA IRQs. This is the default implementation. Architecture
- * implementations can override this.
- */
-void __weak pcibios_penalize_isa_irq(int irq, int active) {}
-
 static void do_pci_disable_device(struct pci_dev *dev)
 {
        u16 pci_command;
@@ -3997,66 +3857,6 @@ int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask)
 }
 EXPORT_SYMBOL(pci_enable_atomic_ops_to_root);
 
-/**
- * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge
- * @dev: the PCI device
- * @pin: the INTx pin (1=INTA, 2=INTB, 3=INTC, 4=INTD)
- *
- * Perform INTx swizzling for a device behind one level of bridge.  This is
- * required by section 9.1 of the PCI-to-PCI bridge specification for devices
- * behind bridges on add-in cards.  For devices with ARI enabled, the slot
- * number is always 0 (see the Implementation Note in section 2.2.8.1 of
- * the PCI Express Base Specification, Revision 2.1)
- */
-u8 pci_swizzle_interrupt_pin(const struct pci_dev *dev, u8 pin)
-{
-       int slot;
-
-       if (pci_ari_enabled(dev->bus))
-               slot = 0;
-       else
-               slot = PCI_SLOT(dev->devfn);
-
-       return (((pin - 1) + slot) % 4) + 1;
-}
-
-int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)
-{
-       u8 pin;
-
-       pin = dev->pin;
-       if (!pin)
-               return -1;
-
-       while (!pci_is_root_bus(dev->bus)) {
-               pin = pci_swizzle_interrupt_pin(dev, pin);
-               dev = dev->bus->self;
-       }
-       *bridge = dev;
-       return pin;
-}
-
-/**
- * pci_common_swizzle - swizzle INTx all the way to root bridge
- * @dev: the PCI device
- * @pinp: pointer to the INTx pin value (1=INTA, 2=INTB, 3=INTD, 4=INTD)
- *
- * Perform INTx swizzling for a device.  This traverses through all PCI-to-PCI
- * bridges all the way up to a PCI root bus.
- */
-u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp)
-{
-       u8 pin = *pinp;
-
-       while (!pci_is_root_bus(dev->bus)) {
-               pin = pci_swizzle_interrupt_pin(dev, pin);
-               dev = dev->bus->self;
-       }
-       *pinp = pin;
-       return PCI_SLOT(dev->devfn);
-}
-EXPORT_SYMBOL_GPL(pci_common_swizzle);
-
 /**
  * pci_release_region - Release a PCI bar
  * @pdev: PCI device whose resources were previously reserved by
@@ -4385,133 +4185,6 @@ void pci_unmap_iospace(struct resource *res)
 }
 EXPORT_SYMBOL(pci_unmap_iospace);
 
-static void devm_pci_unmap_iospace(struct device *dev, void *ptr)
-{
-       struct resource **res = ptr;
-
-       pci_unmap_iospace(*res);
-}
-
-/**
- * devm_pci_remap_iospace - Managed pci_remap_iospace()
- * @dev: Generic device to remap IO address for
- * @res: Resource describing the I/O space
- * @phys_addr: physical address of range to be mapped
- *
- * Managed pci_remap_iospace().  Map is automatically unmapped on driver
- * detach.
- */
-int devm_pci_remap_iospace(struct device *dev, const struct resource *res,
-                          phys_addr_t phys_addr)
-{
-       const struct resource **ptr;
-       int error;
-
-       ptr = devres_alloc(devm_pci_unmap_iospace, sizeof(*ptr), GFP_KERNEL);
-       if (!ptr)
-               return -ENOMEM;
-
-       error = pci_remap_iospace(res, phys_addr);
-       if (error) {
-               devres_free(ptr);
-       } else  {
-               *ptr = res;
-               devres_add(dev, ptr);
-       }
-
-       return error;
-}
-EXPORT_SYMBOL(devm_pci_remap_iospace);
-
-/**
- * devm_pci_remap_cfgspace - Managed pci_remap_cfgspace()
- * @dev: Generic device to remap IO address for
- * @offset: Resource address to map
- * @size: Size of map
- *
- * Managed pci_remap_cfgspace().  Map is automatically unmapped on driver
- * detach.
- */
-void __iomem *devm_pci_remap_cfgspace(struct device *dev,
-                                     resource_size_t offset,
-                                     resource_size_t size)
-{
-       void __iomem **ptr, *addr;
-
-       ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
-       if (!ptr)
-               return NULL;
-
-       addr = pci_remap_cfgspace(offset, size);
-       if (addr) {
-               *ptr = addr;
-               devres_add(dev, ptr);
-       } else
-               devres_free(ptr);
-
-       return addr;
-}
-EXPORT_SYMBOL(devm_pci_remap_cfgspace);
-
-/**
- * devm_pci_remap_cfg_resource - check, request region and ioremap cfg resource
- * @dev: generic device to handle the resource for
- * @res: configuration space resource to be handled
- *
- * Checks that a resource is a valid memory region, requests the memory
- * region and ioremaps with pci_remap_cfgspace() API that ensures the
- * proper PCI configuration space memory attributes are guaranteed.
- *
- * All operations are managed and will be undone on driver detach.
- *
- * Returns a pointer to the remapped memory or an ERR_PTR() encoded error code
- * on failure. Usage example::
- *
- *     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- *     base = devm_pci_remap_cfg_resource(&pdev->dev, res);
- *     if (IS_ERR(base))
- *             return PTR_ERR(base);
- */
-void __iomem *devm_pci_remap_cfg_resource(struct device *dev,
-                                         struct resource *res)
-{
-       resource_size_t size;
-       const char *name;
-       void __iomem *dest_ptr;
-
-       BUG_ON(!dev);
-
-       if (!res || resource_type(res) != IORESOURCE_MEM) {
-               dev_err(dev, "invalid resource\n");
-               return IOMEM_ERR_PTR(-EINVAL);
-       }
-
-       size = resource_size(res);
-
-       if (res->name)
-               name = devm_kasprintf(dev, GFP_KERNEL, "%s %s", dev_name(dev),
-                                     res->name);
-       else
-               name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
-       if (!name)
-               return IOMEM_ERR_PTR(-ENOMEM);
-
-       if (!devm_request_mem_region(dev, res->start, size, name)) {
-               dev_err(dev, "can't request region for resource %pR\n", res);
-               return IOMEM_ERR_PTR(-EBUSY);
-       }
-
-       dest_ptr = devm_pci_remap_cfgspace(dev, res->start, size);
-       if (!dest_ptr) {
-               dev_err(dev, "ioremap failed for resource %pR\n", res);
-               devm_release_mem_region(dev, res->start, size);
-               dest_ptr = IOMEM_ERR_PTR(-ENOMEM);
-       }
-
-       return dest_ptr;
-}
-EXPORT_SYMBOL(devm_pci_remap_cfg_resource);
-
 static void __pci_set_master(struct pci_dev *dev, bool enable)
 {
        u16 old_cmd, cmd;
@@ -4661,27 +4334,6 @@ int pci_set_mwi(struct pci_dev *dev)
 }
 EXPORT_SYMBOL(pci_set_mwi);
 
-/**
- * pcim_set_mwi - a device-managed pci_set_mwi()
- * @dev: the PCI device for which MWI is enabled
- *
- * Managed pci_set_mwi().
- *
- * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
- */
-int pcim_set_mwi(struct pci_dev *dev)
-{
-       struct pci_devres *dr;
-
-       dr = find_pci_dr(dev);
-       if (!dr)
-               return -ENOMEM;
-
-       dr->mwi = 1;
-       return pci_set_mwi(dev);
-}
-EXPORT_SYMBOL(pcim_set_mwi);
-
 /**
  * pci_try_set_mwi - enables memory-write-invalidate PCI transaction
  * @dev: the PCI device for which MWI is enabled
@@ -4770,78 +4422,6 @@ void pci_intx(struct pci_dev *pdev, int enable)
 }
 EXPORT_SYMBOL_GPL(pci_intx);
 
-static bool pci_check_and_set_intx_mask(struct pci_dev *dev, bool mask)
-{
-       struct pci_bus *bus = dev->bus;
-       bool mask_updated = true;
-       u32 cmd_status_dword;
-       u16 origcmd, newcmd;
-       unsigned long flags;
-       bool irq_pending;
-
-       /*
-        * We do a single dword read to retrieve both command and status.
-        * Document assumptions that make this possible.
-        */
-       BUILD_BUG_ON(PCI_COMMAND % 4);
-       BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS);
-
-       raw_spin_lock_irqsave(&pci_lock, flags);
-
-       bus->ops->read(bus, dev->devfn, PCI_COMMAND, 4, &cmd_status_dword);
-
-       irq_pending = (cmd_status_dword >> 16) & PCI_STATUS_INTERRUPT;
-
-       /*
-        * Check interrupt status register to see whether our device
-        * triggered the interrupt (when masking) or the next IRQ is
-        * already pending (when unmasking).
-        */
-       if (mask != irq_pending) {
-               mask_updated = false;
-               goto done;
-       }
-
-       origcmd = cmd_status_dword;
-       newcmd = origcmd & ~PCI_COMMAND_INTX_DISABLE;
-       if (mask)
-               newcmd |= PCI_COMMAND_INTX_DISABLE;
-       if (newcmd != origcmd)
-               bus->ops->write(bus, dev->devfn, PCI_COMMAND, 2, newcmd);
-
-done:
-       raw_spin_unlock_irqrestore(&pci_lock, flags);
-
-       return mask_updated;
-}
-
-/**
- * pci_check_and_mask_intx - mask INTx on pending interrupt
- * @dev: the PCI device to operate on
- *
- * Check if the device dev has its INTx line asserted, mask it and return
- * true in that case. False is returned if no interrupt was pending.
- */
-bool pci_check_and_mask_intx(struct pci_dev *dev)
-{
-       return pci_check_and_set_intx_mask(dev, true);
-}
-EXPORT_SYMBOL_GPL(pci_check_and_mask_intx);
-
-/**
- * pci_check_and_unmask_intx - unmask INTx if no interrupt is pending
- * @dev: the PCI device to operate on
- *
- * Check if the device dev has its INTx line asserted, unmask it if not and
- * return true. False is returned and the mask remains active if there was
- * still an interrupt pending.
- */
-bool pci_check_and_unmask_intx(struct pci_dev *dev)
-{
-       return pci_check_and_set_intx_mask(dev, false);
-}
-EXPORT_SYMBOL_GPL(pci_check_and_unmask_intx);
-
 /**
  * pci_wait_for_pending_transaction - wait for pending transaction
  * @dev: the PCI device to operate on
index bfc56f7bee1c9d8c80eba046e90234c394e51d6c..17fed18468474b8ed75694216c742ef55c9079e1 100644 (file)
@@ -31,9 +31,6 @@ bool pcie_cap_has_rtctl(const struct pci_dev *dev);
 
 /* Functions internal to the PCI core code */
 
-int pci_create_sysfs_dev_files(struct pci_dev *pdev);
-void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
-void pci_cleanup_rom(struct pci_dev *dev);
 #ifdef CONFIG_DMI
 extern const struct attribute_group pci_dev_smbios_attr_group;
 #endif
@@ -97,7 +94,6 @@ void pci_msi_init(struct pci_dev *dev);
 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);
 
 static inline void pci_wakeup_event(struct pci_dev *dev)
@@ -152,7 +148,7 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; }
 /* Functions for PCI Hotplug drivers to use */
 int pci_hp_add_bridge(struct pci_dev *dev);
 
-#ifdef HAVE_PCI_LEGACY
+#if defined(CONFIG_SYSFS) && defined(HAVE_PCI_LEGACY)
 void pci_create_legacy_files(struct pci_bus *bus);
 void pci_remove_legacy_files(struct pci_bus *bus);
 #else
@@ -185,10 +181,22 @@ static inline int pci_no_d1d2(struct pci_dev *dev)
        return (dev->no_d1d2 || parent_dstates);
 
 }
+
+#ifdef CONFIG_SYSFS
+int pci_create_sysfs_dev_files(struct pci_dev *pdev);
+void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
 extern const struct attribute_group *pci_dev_groups[];
+extern const struct attribute_group *pci_dev_attr_groups[];
 extern const struct attribute_group *pcibus_groups[];
-extern const struct device_type pci_dev_type;
 extern const struct attribute_group *pci_bus_groups[];
+#else
+static inline int pci_create_sysfs_dev_files(struct pci_dev *pdev) { return 0; }
+static inline void pci_remove_sysfs_dev_files(struct pci_dev *pdev) { }
+#define pci_dev_groups NULL
+#define pci_dev_attr_groups NULL
+#define pcibus_groups NULL
+#define pci_bus_groups NULL
+#endif
 
 extern unsigned long pci_hotplug_io_size;
 extern unsigned long pci_hotplug_mmio_size;
@@ -404,7 +412,7 @@ struct aer_err_info {
 
        unsigned int status;            /* COR/UNCOR Error Status */
        unsigned int mask;              /* COR/UNCOR Error Mask */
-       struct aer_header_log_regs tlp; /* TLP Header */
+       struct pcie_tlp_log tlp;        /* TLP Header */
 };
 
 int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info);
@@ -563,16 +571,28 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
 
 bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
 int pcie_retrain_link(struct pci_dev *pdev, bool use_lt);
+
+/* ASPM-related functionality we need even without CONFIG_PCIEASPM */
+void pci_save_ltr_state(struct pci_dev *dev);
+void pci_restore_ltr_state(struct pci_dev *dev);
+void pci_configure_aspm_l1ss(struct pci_dev *dev);
+void pci_save_aspm_l1ss_state(struct pci_dev *dev);
+void pci_restore_aspm_l1ss_state(struct pci_dev *dev);
+
 #ifdef CONFIG_PCIEASPM
 void pcie_aspm_init_link_state(struct pci_dev *pdev);
 void pcie_aspm_exit_link_state(struct pci_dev *pdev);
 void pcie_aspm_pm_state_change(struct pci_dev *pdev, bool locked);
 void pcie_aspm_powersave_config_link(struct pci_dev *pdev);
+void pci_configure_ltr(struct pci_dev *pdev);
+void pci_bridge_reconfigure_ltr(struct pci_dev *pdev);
 #else
 static inline void pcie_aspm_init_link_state(struct pci_dev *pdev) { }
 static inline void pcie_aspm_exit_link_state(struct pci_dev *pdev) { }
 static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev, bool locked) { }
 static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev) { }
+static inline void pci_configure_ltr(struct pci_dev *pdev) { }
+static inline void pci_bridge_reconfigure_ltr(struct pci_dev *pdev) { }
 #endif
 
 #ifdef CONFIG_PCIE_ECRC
@@ -792,6 +812,27 @@ static inline pci_power_t mid_pci_get_power_state(struct pci_dev *pdev)
 }
 #endif
 
+/*
+ * Managed PCI resources.  This manages device on/off, INTx/MSI/MSI-X
+ * on/off and BAR regions.  pci_dev itself records MSI/MSI-X status, so
+ * there's no need to track it separately.  pci_devres is initialized
+ * when a device is enabled using managed PCI device enable interface.
+ *
+ * TODO: Struct pci_devres and find_pci_dr() only need to be here because
+ * they're used in pci.c.  Port or move these functions to devres.c and
+ * then remove them from here.
+ */
+struct pci_devres {
+       unsigned int enabled:1;
+       unsigned int pinned:1;
+       unsigned int orig_intx:1;
+       unsigned int restore_intx:1;
+       unsigned int mwi:1;
+       u32 region_mask;
+};
+
+struct pci_devres *find_pci_dr(struct pci_dev *pdev);
+
 /*
  * Config Address for PCI Configuration Mechanism #1
  *
index 8de4ed5f98f145065b6c2678f7e09dd184d09a24..6461aa93fe76eccd39c4af08e7e1c9c327e7b77d 100644 (file)
@@ -6,7 +6,7 @@ pcieportdrv-y                   := portdrv.o rcec.o
 
 obj-$(CONFIG_PCIEPORTBUS)      += pcieportdrv.o
 
-obj-$(CONFIG_PCIEASPM)         += aspm.o
+obj-y                          += aspm.o
 obj-$(CONFIG_PCIEAER)          += aer.o err.o
 obj-$(CONFIG_PCIEAER_INJECT)   += aer_inject.o
 obj-$(CONFIG_PCIE_PME)         += pme.o
index 05fc30bb5134d9ae31e681375d843b0f49738c30..ac6293c249766460ddf74ea05a1147651faa21c9 100644 (file)
@@ -664,11 +664,10 @@ static void pci_rootport_aer_stats_incr(struct pci_dev *pdev,
        }
 }
 
-static void __print_tlp_header(struct pci_dev *dev,
-                              struct aer_header_log_regs *t)
+static void __print_tlp_header(struct pci_dev *dev, struct pcie_tlp_log *t)
 {
        pci_err(dev, "  TLP Header: %08x %08x %08x %08x\n",
-               t->dw0, t->dw1, t->dw2, t->dw3);
+               t->dw[0], t->dw[1], t->dw[2], t->dw[3]);
 }
 
 static void __aer_print_error(struct pci_dev *dev,
@@ -1210,7 +1209,7 @@ int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
 {
        int type = pci_pcie_type(dev);
        int aer = dev->aer_cap;
-       int temp;
+       u32 aercc;
 
        /* Must reset in this function */
        info->status = 0;
@@ -1241,19 +1240,12 @@ int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
                        return 0;
 
                /* Get First Error Pointer */
-               pci_read_config_dword(dev, aer + PCI_ERR_CAP, &temp);
-               info->first_error = PCI_ERR_CAP_FEP(temp);
+               pci_read_config_dword(dev, aer + PCI_ERR_CAP, &aercc);
+               info->first_error = PCI_ERR_CAP_FEP(aercc);
 
                if (info->status & AER_LOG_TLP_MASKS) {
                        info->tlp_header_valid = 1;
-                       pci_read_config_dword(dev,
-                               aer + PCI_ERR_HEADER_LOG, &info->tlp.dw0);
-                       pci_read_config_dword(dev,
-                               aer + PCI_ERR_HEADER_LOG + 4, &info->tlp.dw1);
-                       pci_read_config_dword(dev,
-                               aer + PCI_ERR_HEADER_LOG + 8, &info->tlp.dw2);
-                       pci_read_config_dword(dev,
-                               aer + PCI_ERR_HEADER_LOG + 12, &info->tlp.dw3);
+                       pcie_read_tlp_log(dev, aer + PCI_ERR_HEADER_LOG, &info->tlp);
                }
        }
 
index bc0bd86695ec62a2d43428b69eb562f771334bb3..2428d278e015ab99b2989b01a6762806cebb549b 100644 (file)
 
 #include "../pci.h"
 
+void pci_save_ltr_state(struct pci_dev *dev)
+{
+       int ltr;
+       struct pci_cap_saved_state *save_state;
+       u32 *cap;
+
+       if (!pci_is_pcie(dev))
+               return;
+
+       ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
+       if (!ltr)
+               return;
+
+       save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR);
+       if (!save_state) {
+               pci_err(dev, "no suspend buffer for LTR; ASPM issues possible after resume\n");
+               return;
+       }
+
+       /* Some broken devices only support dword access to LTR */
+       cap = &save_state->cap.data[0];
+       pci_read_config_dword(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, cap);
+}
+
+void pci_restore_ltr_state(struct pci_dev *dev)
+{
+       struct pci_cap_saved_state *save_state;
+       int ltr;
+       u32 *cap;
+
+       save_state = pci_find_saved_ext_cap(dev, PCI_EXT_CAP_ID_LTR);
+       ltr = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_LTR);
+       if (!save_state || !ltr)
+               return;
+
+       /* Some broken devices only support dword access to LTR */
+       cap = &save_state->cap.data[0];
+       pci_write_config_dword(dev, ltr + PCI_LTR_MAX_SNOOP_LAT, *cap);
+}
+
+void pci_configure_aspm_l1ss(struct pci_dev *pdev)
+{
+       int rc;
+
+       pdev->l1ss = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_L1SS);
+
+       rc = pci_add_ext_cap_save_buffer(pdev, PCI_EXT_CAP_ID_L1SS,
+                                        2 * sizeof(u32));
+       if (rc)
+               pci_err(pdev, "unable to allocate ASPM L1SS save buffer (%pe)\n",
+                       ERR_PTR(rc));
+}
+
+void pci_save_aspm_l1ss_state(struct pci_dev *pdev)
+{
+       struct pci_cap_saved_state *save_state;
+       u16 l1ss = pdev->l1ss;
+       u32 *cap;
+
+       /*
+        * Save L1 substate configuration. The ASPM L0s/L1 configuration
+        * in PCI_EXP_LNKCTL_ASPMC is saved by pci_save_pcie_state().
+        */
+       if (!l1ss)
+               return;
+
+       save_state = pci_find_saved_ext_cap(pdev, PCI_EXT_CAP_ID_L1SS);
+       if (!save_state)
+               return;
+
+       cap = &save_state->cap.data[0];
+       pci_read_config_dword(pdev, l1ss + PCI_L1SS_CTL2, cap++);
+       pci_read_config_dword(pdev, l1ss + PCI_L1SS_CTL1, cap++);
+}
+
+void pci_restore_aspm_l1ss_state(struct pci_dev *pdev)
+{
+       struct pci_cap_saved_state *pl_save_state, *cl_save_state;
+       struct pci_dev *parent = pdev->bus->self;
+       u32 *cap, pl_ctl1, pl_ctl2, pl_l1_2_enable;
+       u32 cl_ctl1, cl_ctl2, cl_l1_2_enable;
+       u16 clnkctl, plnkctl;
+
+       /*
+        * In case BIOS enabled L1.2 when resuming, we need to disable it first
+        * on the downstream component before the upstream. So, don't attempt to
+        * restore either until we are at the downstream component.
+        */
+       if (pcie_downstream_port(pdev) || !parent)
+               return;
+
+       if (!pdev->l1ss || !parent->l1ss)
+               return;
+
+       cl_save_state = pci_find_saved_ext_cap(pdev, PCI_EXT_CAP_ID_L1SS);
+       pl_save_state = pci_find_saved_ext_cap(parent, PCI_EXT_CAP_ID_L1SS);
+       if (!cl_save_state || !pl_save_state)
+               return;
+
+       cap = &cl_save_state->cap.data[0];
+       cl_ctl2 = *cap++;
+       cl_ctl1 = *cap;
+       cap = &pl_save_state->cap.data[0];
+       pl_ctl2 = *cap++;
+       pl_ctl1 = *cap;
+
+       /* Make sure L0s/L1 are disabled before updating L1SS config */
+       pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &clnkctl);
+       pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &plnkctl);
+       if (FIELD_GET(PCI_EXP_LNKCTL_ASPMC, clnkctl) ||
+           FIELD_GET(PCI_EXP_LNKCTL_ASPMC, plnkctl)) {
+               pcie_capability_write_word(pdev, PCI_EXP_LNKCTL,
+                                          clnkctl & ~PCI_EXP_LNKCTL_ASPMC);
+               pcie_capability_write_word(parent, PCI_EXP_LNKCTL,
+                                          plnkctl & ~PCI_EXP_LNKCTL_ASPMC);
+       }
+
+       /*
+        * Disable L1.2 on this downstream endpoint device first, followed
+        * by the upstream
+        */
+       pci_clear_and_set_config_dword(pdev, pdev->l1ss + PCI_L1SS_CTL1,
+                                      PCI_L1SS_CTL1_L1_2_MASK, 0);
+       pci_clear_and_set_config_dword(parent, parent->l1ss + PCI_L1SS_CTL1,
+                                      PCI_L1SS_CTL1_L1_2_MASK, 0);
+
+       /*
+        * In addition, Common_Mode_Restore_Time and LTR_L1.2_THRESHOLD
+        * in PCI_L1SS_CTL1 must be programmed *before* setting the L1.2
+        * enable bits, even though they're all in PCI_L1SS_CTL1.
+        */
+       pl_l1_2_enable = pl_ctl1 & PCI_L1SS_CTL1_L1_2_MASK;
+       pl_ctl1 &= ~PCI_L1SS_CTL1_L1_2_MASK;
+       cl_l1_2_enable = cl_ctl1 & PCI_L1SS_CTL1_L1_2_MASK;
+       cl_ctl1 &= ~PCI_L1SS_CTL1_L1_2_MASK;
+
+       /* Write back without enables first (above we cleared them in ctl1) */
+       pci_write_config_dword(parent, parent->l1ss + PCI_L1SS_CTL2, pl_ctl2);
+       pci_write_config_dword(pdev, pdev->l1ss + PCI_L1SS_CTL2, cl_ctl2);
+       pci_write_config_dword(parent, parent->l1ss + PCI_L1SS_CTL1, pl_ctl1);
+       pci_write_config_dword(pdev, pdev->l1ss + PCI_L1SS_CTL1, cl_ctl1);
+
+       /* Then write back the enables */
+       if (pl_l1_2_enable || cl_l1_2_enable) {
+               pci_write_config_dword(parent, parent->l1ss + PCI_L1SS_CTL1,
+                                      pl_ctl1 | pl_l1_2_enable);
+               pci_write_config_dword(pdev, pdev->l1ss + PCI_L1SS_CTL1,
+                                      cl_ctl1 | cl_l1_2_enable);
+       }
+
+       /* Restore L0s/L1 if they were enabled */
+       if (FIELD_GET(PCI_EXP_LNKCTL_ASPMC, clnkctl) ||
+           FIELD_GET(PCI_EXP_LNKCTL_ASPMC, plnkctl)) {
+               pcie_capability_write_word(parent, PCI_EXP_LNKCTL, clnkctl);
+               pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, plnkctl);
+       }
+}
+
+#ifdef CONFIG_PCIEASPM
+
 #ifdef MODULE_PARAM_PREFIX
 #undef MODULE_PARAM_PREFIX
 #endif
@@ -141,16 +301,42 @@ static int policy_to_clkpm_state(struct pcie_link_state *link)
        return 0;
 }
 
+static void pci_update_aspm_saved_state(struct pci_dev *dev)
+{
+       struct pci_cap_saved_state *save_state;
+       u16 *cap, lnkctl, aspm_ctl;
+
+       save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
+       if (!save_state)
+               return;
+
+       pcie_capability_read_word(dev, PCI_EXP_LNKCTL, &lnkctl);
+
+       /*
+        * Update ASPM and CLKREQ bits of LNKCTL in save_state. We only
+        * write PCI_EXP_LNKCTL_CCC during enumeration, so it shouldn't
+        * change after being captured in save_state.
+        */
+       aspm_ctl = lnkctl & (PCI_EXP_LNKCTL_ASPMC | PCI_EXP_LNKCTL_CLKREQ_EN);
+       lnkctl &= ~(PCI_EXP_LNKCTL_ASPMC | PCI_EXP_LNKCTL_CLKREQ_EN);
+
+       /* Depends on pci_save_pcie_state(): cap[1] is LNKCTL */
+       cap = (u16 *)&save_state->cap.data[0];
+       cap[1] = lnkctl | aspm_ctl;
+}
+
 static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable)
 {
        struct pci_dev *child;
        struct pci_bus *linkbus = link->pdev->subordinate;
        u32 val = enable ? PCI_EXP_LNKCTL_CLKREQ_EN : 0;
 
-       list_for_each_entry(child, &linkbus->devices, bus_list)
+       list_for_each_entry(child, &linkbus->devices, bus_list) {
                pcie_capability_clear_and_set_word(child, PCI_EXP_LNKCTL,
                                                   PCI_EXP_LNKCTL_CLKREQ_EN,
                                                   val);
+               pci_update_aspm_saved_state(child);
+       }
        link->clkpm_enabled = !!enable;
 }
 
@@ -769,6 +955,12 @@ static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state)
                pcie_config_aspm_dev(parent, upstream);
 
        link->aspm_enabled = state;
+
+       /* Update latest ASPM configuration in saved context */
+       pci_save_aspm_l1ss_state(link->downstream);
+       pci_update_aspm_saved_state(link->downstream);
+       pci_save_aspm_l1ss_state(parent);
+       pci_update_aspm_saved_state(parent);
 }
 
 static void pcie_config_aspm_path(struct pcie_link_state *link)
@@ -938,6 +1130,78 @@ out:
        up_read(&pci_bus_sem);
 }
 
+void pci_bridge_reconfigure_ltr(struct pci_dev *pdev)
+{
+       struct pci_dev *bridge;
+       u32 ctl;
+
+       bridge = pci_upstream_bridge(pdev);
+       if (bridge && bridge->ltr_path) {
+               pcie_capability_read_dword(bridge, PCI_EXP_DEVCTL2, &ctl);
+               if (!(ctl & PCI_EXP_DEVCTL2_LTR_EN)) {
+                       pci_dbg(bridge, "re-enabling LTR\n");
+                       pcie_capability_set_word(bridge, PCI_EXP_DEVCTL2,
+                                                PCI_EXP_DEVCTL2_LTR_EN);
+               }
+       }
+}
+
+void pci_configure_ltr(struct pci_dev *pdev)
+{
+       struct pci_host_bridge *host = pci_find_host_bridge(pdev->bus);
+       struct pci_dev *bridge;
+       u32 cap, ctl;
+
+       if (!pci_is_pcie(pdev))
+               return;
+
+       pcie_capability_read_dword(pdev, PCI_EXP_DEVCAP2, &cap);
+       if (!(cap & PCI_EXP_DEVCAP2_LTR))
+               return;
+
+       pcie_capability_read_dword(pdev, PCI_EXP_DEVCTL2, &ctl);
+       if (ctl & PCI_EXP_DEVCTL2_LTR_EN) {
+               if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT) {
+                       pdev->ltr_path = 1;
+                       return;
+               }
+
+               bridge = pci_upstream_bridge(pdev);
+               if (bridge && bridge->ltr_path)
+                       pdev->ltr_path = 1;
+
+               return;
+       }
+
+       if (!host->native_ltr)
+               return;
+
+       /*
+        * Software must not enable LTR in an Endpoint unless the Root
+        * Complex and all intermediate Switches indicate support for LTR.
+        * PCIe r4.0, sec 6.18.
+        */
+       if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT) {
+               pcie_capability_set_word(pdev, PCI_EXP_DEVCTL2,
+                                        PCI_EXP_DEVCTL2_LTR_EN);
+               pdev->ltr_path = 1;
+               return;
+       }
+
+       /*
+        * If we're configuring a hot-added device, LTR was likely
+        * disabled in the upstream bridge, so re-enable it before enabling
+        * it in the new device.
+        */
+       bridge = pci_upstream_bridge(pdev);
+       if (bridge && bridge->ltr_path) {
+               pci_bridge_reconfigure_ltr(pdev);
+               pcie_capability_set_word(pdev, PCI_EXP_DEVCTL2,
+                                        PCI_EXP_DEVCTL2_LTR_EN);
+               pdev->ltr_path = 1;
+       }
+}
+
 /* Recheck latencies and update aspm_capable for links under the root */
 static void pcie_update_aspm_capable(struct pcie_link_state *root)
 {
@@ -1447,3 +1711,5 @@ bool pcie_aspm_support_enabled(void)
 {
        return aspm_support_enabled;
 }
+
+#endif /* CONFIG_PCIEASPM */
index 94111e4382413dc57ff10a079e1bdfc50c0e978e..a668820696dc0faee03455933182910409a5c03e 100644 (file)
@@ -190,7 +190,8 @@ out:
 static void dpc_process_rp_pio_error(struct pci_dev *pdev)
 {
        u16 cap = pdev->dpc_cap, dpc_status, first_error;
-       u32 status, mask, sev, syserr, exc, dw0, dw1, dw2, dw3, log, prefix;
+       u32 status, mask, sev, syserr, exc, log, prefix;
+       struct pcie_tlp_log tlp_log;
        int i;
 
        pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_STATUS, &status);
@@ -216,16 +217,9 @@ static void dpc_process_rp_pio_error(struct pci_dev *pdev)
 
        if (pdev->dpc_rp_log_size < 4)
                goto clear_status;
-       pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_HEADER_LOG,
-                             &dw0);
-       pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_HEADER_LOG + 4,
-                             &dw1);
-       pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_HEADER_LOG + 8,
-                             &dw2);
-       pci_read_config_dword(pdev, cap + PCI_EXP_DPC_RP_PIO_HEADER_LOG + 12,
-                             &dw3);
+       pcie_read_tlp_log(pdev, cap + PCI_EXP_DPC_RP_PIO_HEADER_LOG, &tlp_log);
        pci_err(pdev, "TLP Header: %#010x %#010x %#010x %#010x\n",
-               dw0, dw1, dw2, dw3);
+               tlp_log.dw[0], tlp_log.dw[1], tlp_log.dw[2], tlp_log.dw[3]);
 
        if (pdev->dpc_rp_log_size < 5)
                goto clear_status;
@@ -234,7 +228,7 @@ static void dpc_process_rp_pio_error(struct pci_dev *pdev)
 
        for (i = 0; i < pdev->dpc_rp_log_size - 5; i++) {
                pci_read_config_dword(pdev,
-                       cap + PCI_EXP_DPC_RP_PIO_TLPPREFIX_LOG, &prefix);
+                       cap + PCI_EXP_DPC_RP_PIO_TLPPREFIX_LOG + i * 4, &prefix);
                pci_err(pdev, "TLP Prefix Header: dw%d, %#010x\n", i, prefix);
        }
  clear_status:
@@ -303,10 +297,70 @@ void dpc_process_error(struct pci_dev *pdev)
        }
 }
 
+static void pci_clear_surpdn_errors(struct pci_dev *pdev)
+{
+       if (pdev->dpc_rp_extensions)
+               pci_write_config_dword(pdev, pdev->dpc_cap +
+                                      PCI_EXP_DPC_RP_PIO_STATUS, ~0);
+
+       /*
+        * In practice, Surprise Down errors have been observed to also set
+        * error bits in the Status Register as well as the Fatal Error
+        * Detected bit in the Device Status Register.
+        */
+       pci_write_config_word(pdev, PCI_STATUS, 0xffff);
+
+       pcie_capability_write_word(pdev, PCI_EXP_DEVSTA, PCI_EXP_DEVSTA_FED);
+}
+
+static void dpc_handle_surprise_removal(struct pci_dev *pdev)
+{
+       if (!pcie_wait_for_link(pdev, false)) {
+               pci_info(pdev, "Data Link Layer Link Active not cleared in 1000 msec\n");
+               goto out;
+       }
+
+       if (pdev->dpc_rp_extensions && dpc_wait_rp_inactive(pdev))
+               goto out;
+
+       pci_aer_raw_clear_status(pdev);
+       pci_clear_surpdn_errors(pdev);
+
+       pci_write_config_word(pdev, pdev->dpc_cap + PCI_EXP_DPC_STATUS,
+                             PCI_EXP_DPC_STATUS_TRIGGER);
+
+out:
+       clear_bit(PCI_DPC_RECOVERED, &pdev->priv_flags);
+       wake_up_all(&dpc_completed_waitqueue);
+}
+
+static bool dpc_is_surprise_removal(struct pci_dev *pdev)
+{
+       u16 status;
+
+       if (!pdev->is_hotplug_bridge)
+               return false;
+
+       if (pci_read_config_word(pdev, pdev->aer_cap + PCI_ERR_UNCOR_STATUS,
+                                &status))
+               return false;
+
+       return status & PCI_ERR_UNC_SURPDN;
+}
+
 static irqreturn_t dpc_handler(int irq, void *context)
 {
        struct pci_dev *pdev = context;
 
+       /*
+        * According to PCIe r6.0 sec 6.7.6, errors are an expected side effect
+        * of async removal and should be ignored by software.
+        */
+       if (dpc_is_surprise_removal(pdev)) {
+               dpc_handle_surprise_removal(pdev);
+               return IRQ_HANDLED;
+       }
+
        dpc_process_error(pdev);
 
        /* We configure DPC so it only triggers on ERR_FATAL */
index 59c90d04a609afbc6f2c485604e8038fbaecddc2..705893b5f7b09babb7ff2b003dd49d74f408f0fe 100644 (file)
@@ -13,6 +13,7 @@
 #define dev_fmt(fmt) "AER: " fmt
 
 #include <linux/pci.h>
+#include <linux/pm_runtime.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -85,6 +86,18 @@ static int report_error_detected(struct pci_dev *dev,
        return 0;
 }
 
+static int pci_pm_runtime_get_sync(struct pci_dev *pdev, void *data)
+{
+       pm_runtime_get_sync(&pdev->dev);
+       return 0;
+}
+
+static int pci_pm_runtime_put(struct pci_dev *pdev, void *data)
+{
+       pm_runtime_put(&pdev->dev);
+       return 0;
+}
+
 static int report_frozen_detected(struct pci_dev *dev, void *data)
 {
        return report_error_detected(dev, pci_channel_io_frozen, data);
@@ -207,6 +220,8 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
        else
                bridge = pci_upstream_bridge(dev);
 
+       pci_walk_bridge(bridge, pci_pm_runtime_get_sync, NULL);
+
        pci_dbg(bridge, "broadcast error_detected message\n");
        if (state == pci_channel_io_frozen) {
                pci_walk_bridge(bridge, report_frozen_detected, &status);
@@ -251,10 +266,15 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
                pcie_clear_device_status(dev);
                pci_aer_clear_nonfatal_status(dev);
        }
+
+       pci_walk_bridge(bridge, pci_pm_runtime_put, NULL);
+
        pci_info(bridge, "device recovery successful\n");
        return status;
 
 failed:
+       pci_walk_bridge(bridge, pci_pm_runtime_put, NULL);
+
        pci_uevent_ers(bridge, PCI_ERS_RESULT_DISCONNECT);
 
        /* TODO: Should kernel panic here? */
index 1f3803bde7ee16067d4aa801057076268dfe4b51..12c89ea0313b9c4c5aa73744ea6aff9dee844d84 100644 (file)
@@ -96,7 +96,7 @@ struct pcie_port_service_driver {
 int pcie_port_service_register(struct pcie_port_service_driver *new);
 void pcie_port_service_unregister(struct pcie_port_service_driver *new);
 
-extern struct bus_type pcie_port_bus_type;
+extern const struct bus_type pcie_port_bus_type;
 
 struct pci_dev;
 
index b7335be56008f76ce0da493b56b40a35928af756..1325fbae2f28fb10dbbbd6c6ff65ce2cf9193f3d 100644 (file)
@@ -2209,67 +2209,6 @@ static void pci_configure_relaxed_ordering(struct pci_dev *dev)
        }
 }
 
-static void pci_configure_ltr(struct pci_dev *dev)
-{
-#ifdef CONFIG_PCIEASPM
-       struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
-       struct pci_dev *bridge;
-       u32 cap, ctl;
-
-       if (!pci_is_pcie(dev))
-               return;
-
-       /* Read L1 PM substate capabilities */
-       dev->l1ss = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_L1SS);
-
-       pcie_capability_read_dword(dev, PCI_EXP_DEVCAP2, &cap);
-       if (!(cap & PCI_EXP_DEVCAP2_LTR))
-               return;
-
-       pcie_capability_read_dword(dev, PCI_EXP_DEVCTL2, &ctl);
-       if (ctl & PCI_EXP_DEVCTL2_LTR_EN) {
-               if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) {
-                       dev->ltr_path = 1;
-                       return;
-               }
-
-               bridge = pci_upstream_bridge(dev);
-               if (bridge && bridge->ltr_path)
-                       dev->ltr_path = 1;
-
-               return;
-       }
-
-       if (!host->native_ltr)
-               return;
-
-       /*
-        * Software must not enable LTR in an Endpoint unless the Root
-        * Complex and all intermediate Switches indicate support for LTR.
-        * PCIe r4.0, sec 6.18.
-        */
-       if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) {
-               pcie_capability_set_word(dev, PCI_EXP_DEVCTL2,
-                                        PCI_EXP_DEVCTL2_LTR_EN);
-               dev->ltr_path = 1;
-               return;
-       }
-
-       /*
-        * If we're configuring a hot-added device, LTR was likely
-        * disabled in the upstream bridge, so re-enable it before enabling
-        * it in the new device.
-        */
-       bridge = pci_upstream_bridge(dev);
-       if (bridge && bridge->ltr_path) {
-               pci_bridge_reconfigure_ltr(dev);
-               pcie_capability_set_word(dev, PCI_EXP_DEVCTL2,
-                                        PCI_EXP_DEVCTL2_LTR_EN);
-               dev->ltr_path = 1;
-       }
-#endif
-}
-
 static void pci_configure_eetlp_prefix(struct pci_dev *dev)
 {
 #ifdef CONFIG_PCI_PASID
@@ -2320,6 +2259,7 @@ static void pci_configure_device(struct pci_dev *dev)
        pci_configure_extended_tags(dev, NULL);
        pci_configure_relaxed_ordering(dev);
        pci_configure_ltr(dev);
+       pci_configure_aspm_l1ss(dev);
        pci_configure_eetlp_prefix(dev);
        pci_configure_serr(dev);
 
@@ -2357,6 +2297,10 @@ static void pci_release_dev(struct device *dev)
        kfree(pci_dev);
 }
 
+static const struct device_type pci_dev_type = {
+       .groups = pci_dev_attr_groups,
+};
+
 struct pci_dev *pci_alloc_dev(struct pci_bus *bus)
 {
        struct pci_dev *dev;
index d797df6e5f3e917d08dfce4e40f594e322a5782e..bf4833221816d492d4adca02d508d33a74879a92 100644 (file)
@@ -3765,6 +3765,14 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATHEROS, 0x003e, quirk_no_bus_reset);
  */
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CAVIUM, 0xa100, quirk_no_bus_reset);
 
+/*
+ * Apparently the LSI / Agere FW643 can't recover after a Secondary Bus
+ * Reset and requires a power-off or suspend/resume and rescan.  Prevent
+ * use of that reset.
+ */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATT, 0x5900, quirk_no_bus_reset);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATT, 0x5901, quirk_no_bus_reset);
+
 /*
  * Some TI KeyStone C667X devices do not support bus/hot reset.  The PCIESS
  * automatically disables LTSSM when Secondary Bus Reset is received and
@@ -5527,6 +5535,7 @@ static void quirk_no_ext_tags(struct pci_dev *pdev)
 
        pci_walk_bus(bridge->bus, pci_configure_extended_tags, NULL);
 }
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_3WARE, 0x1004, quirk_no_ext_tags);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0132, quirk_no_ext_tags);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0140, quirk_no_ext_tags);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SERVERWORKS, 0x0141, quirk_no_ext_tags);
@@ -6225,6 +6234,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a2b, dpc_log_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a2d, dpc_log_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a2f, dpc_log_size);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a31, dpc_log_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0xa73f, dpc_log_size);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0xa76e, dpc_log_size);
 #endif
 
 /*
diff --git a/drivers/pci/setup-irq.c b/drivers/pci/setup-irq.c
deleted file mode 100644 (file)
index cc7d26b..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Support routines for initializing a PCI subsystem
- *
- * Extruded from code written by
- *      Dave Rusling (david.rusling@reo.mts.dec.com)
- *      David Mosberger (davidm@cs.arizona.edu)
- *     David Miller (davem@redhat.com)
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/cache.h>
-#include "pci.h"
-
-void pci_assign_irq(struct pci_dev *dev)
-{
-       u8 pin;
-       u8 slot = -1;
-       int irq = 0;
-       struct pci_host_bridge *hbrg = pci_find_host_bridge(dev->bus);
-
-       if (!(hbrg->map_irq)) {
-               pci_dbg(dev, "runtime IRQ mapping not provided by arch\n");
-               return;
-       }
-
-       /*
-        * If this device is not on the primary bus, we need to figure out
-        * which interrupt pin it will come in on. We know which slot it
-        * will come in on because that slot is where the bridge is. Each
-        * time the interrupt line passes through a PCI-PCI bridge we must
-        * apply the swizzle function.
-        */
-       pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-       /* Cope with illegal. */
-       if (pin > 4)
-               pin = 1;
-
-       if (pin) {
-               /* Follow the chain of bridges, swizzling as we go. */
-               if (hbrg->swizzle_irq)
-                       slot = (*(hbrg->swizzle_irq))(dev, &pin);
-
-               /*
-                * If a swizzling function is not used, map_irq() must
-                * ignore slot.
-                */
-               irq = (*(hbrg->map_irq))(dev, slot, pin);
-               if (irq == -1)
-                       irq = 0;
-       }
-       dev->irq = irq;
-
-       pci_dbg(dev, "assign IRQ: got %d\n", dev->irq);
-
-       /*
-        * Always tell the device, so the driver knows what is the real IRQ
-        * to use; the device does not use it.
-        */
-       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}
index 1804794d0e686f22febe508c58aa340f03eecd23..5a4adf6c04cf89eb06fb649656bfa3be32407248 100644 (file)
@@ -1672,7 +1672,7 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
        rc = switchtec_init_isr(stdev);
        if (rc) {
                dev_err(&stdev->dev, "failed to init isr.\n");
-               goto err_put;
+               goto err_exit_pci;
        }
 
        iowrite32(SWITCHTEC_EVENT_CLEAR |
@@ -1693,6 +1693,8 @@ static int switchtec_pci_probe(struct pci_dev *pdev,
 
 err_devadd:
        stdev_kill(stdev);
+err_exit_pci:
+       switchtec_exit_pci(stdev);
 err_put:
        ida_free(&switchtec_minor_ida, MINOR(stdev->dev.devt));
        put_device(&stdev->dev);
index ae0fae70d4bd2c15a7109ba89dcfd5974177a930..4b97f38f3fcf22faffb00a2839b306453a453da4 100644 (file)
 
 struct pci_dev;
 
-struct aer_header_log_regs {
-       u32 dw0;
-       u32 dw1;
-       u32 dw2;
-       u32 dw3;
+struct pcie_tlp_log {
+       u32 dw[4];
 };
 
 struct aer_capability_regs {
@@ -33,13 +30,15 @@ struct aer_capability_regs {
        u32 cor_status;
        u32 cor_mask;
        u32 cap_control;
-       struct aer_header_log_regs header_log;
+       struct pcie_tlp_log header_log;
        u32 root_command;
        u32 root_status;
        u16 cor_err_source;
        u16 uncor_err_source;
 };
 
+int pcie_read_tlp_log(struct pci_dev *dev, int where, struct pcie_tlp_log *log);
+
 #if defined(CONFIG_PCIEAER)
 int pci_aer_clear_nonfatal_status(struct pci_dev *dev);
 int pcie_aer_is_native(struct pci_dev *dev);
index 40ea18f5aa029ef5bebc3d4a56ae3e061afa4a28..cc2f70d061c83b551af24c866312147a09cdf820 100644 (file)
@@ -145,6 +145,37 @@ struct pci_epc {
        unsigned long                   function_num_map;
 };
 
+/**
+ * @BAR_PROGRAMMABLE: The BAR mask can be configured by the EPC.
+ * @BAR_FIXED: The BAR mask is fixed by the hardware.
+ * @BAR_RESERVED: The BAR should not be touched by an EPF driver.
+ */
+enum pci_epc_bar_type {
+       BAR_PROGRAMMABLE = 0,
+       BAR_FIXED,
+       BAR_RESERVED,
+};
+
+/**
+ * struct pci_epc_bar_desc - hardware description for a BAR
+ * @type: the type of the BAR
+ * @fixed_size: the fixed size, only applicable if type is BAR_FIXED_MASK.
+ * @only_64bit: if true, an EPF driver is not allowed to choose if this BAR
+ *             should be configured as 32-bit or 64-bit, the EPF driver must
+ *             configure this BAR as 64-bit. Additionally, the BAR succeeding
+ *             this BAR must be set to type BAR_RESERVED.
+ *
+ *             only_64bit should not be set on a BAR of type BAR_RESERVED.
+ *             (If BARx is a 64-bit BAR that an EPF driver is not allowed to
+ *             touch, then both BARx and BARx+1 must be set to type
+ *             BAR_RESERVED.)
+ */
+struct pci_epc_bar_desc {
+       enum pci_epc_bar_type type;
+       u64 fixed_size;
+       bool only_64bit;
+};
+
 /**
  * struct pci_epc_features - features supported by a EPC device per function
  * @linkup_notifier: indicate if the EPC device can notify EPF driver on link up
@@ -152,9 +183,7 @@ struct pci_epc {
  *                     for initialization
  * @msi_capable: indicate if the endpoint function has MSI capability
  * @msix_capable: indicate if the endpoint function has MSI-X capability
- * @reserved_bar: bitmap to indicate reserved BAR unavailable to function driver
- * @bar_fixed_64bit: bitmap to indicate fixed 64bit BARs
- * @bar_fixed_size: Array specifying the size supported by each BAR
+ * @bar: array specifying the hardware description for each BAR
  * @align: alignment size required for BAR buffer allocation
  */
 struct pci_epc_features {
@@ -162,9 +191,7 @@ struct pci_epc_features {
        unsigned int    core_init_notifier : 1;
        unsigned int    msi_capable : 1;
        unsigned int    msix_capable : 1;
-       u8      reserved_bar;
-       u8      bar_fixed_64bit;
-       u64     bar_fixed_size[PCI_STD_NUM_BARS];
+       struct  pci_epc_bar_desc bar[PCI_STD_NUM_BARS];
        size_t  align;
 };
 
index 77b146e0f6727e2e8b9820b90b16584714063044..adee6a1b35db70e50fa2b95bda6a0fb3632e4f75 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/pci.h>
 
 struct pci_epf;
+struct pci_epc_features;
 enum pci_epc_interface_type;
 
 enum pci_barno {
@@ -216,7 +217,8 @@ int __pci_epf_register_driver(struct pci_epf_driver *driver,
                              struct module *owner);
 void pci_epf_unregister_driver(struct pci_epf_driver *driver);
 void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar,
-                         size_t align, enum pci_epc_interface_type type);
+                         const struct pci_epc_features *epc_features,
+                         enum pci_epc_interface_type type);
 void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar,
                        enum pci_epc_interface_type type);
 int pci_epf_bind(struct pci_epf *epf);
index 213109d3c601d11057a5b70c2695121a26d73e4c..16493426a04ff9a2c0009644c8ae993758f34c22 100644 (file)
@@ -390,9 +390,9 @@ struct pci_dev {
        unsigned int    d3hot_delay;    /* D3hot->D0 transition time in ms */
        unsigned int    d3cold_delay;   /* D3cold->D0 transition time in ms */
 
+       u16             l1ss;           /* L1SS Capability pointer */
 #ifdef CONFIG_PCIEASPM
        struct pcie_link_state  *link_state;    /* ASPM link state */
-       u16             l1ss;           /* L1SS Capability pointer */
        unsigned int    ltr_path:1;     /* Latency Tolerance Reporting
                                           supported from root to here */
 #endif
index cbd3ddd7c33d4d12326bafbc3c33c60c6317358e..c011ea236e9b7fe0fd403262214f223334a7adb0 100644 (file)
@@ -300,7 +300,7 @@ TRACE_EVENT(aer_event,
                 const u32 status,
                 const u8 severity,
                 const u8 tlp_header_valid,
-                struct aer_header_log_regs *tlp),
+                struct pcie_tlp_log *tlp),
 
        TP_ARGS(dev_name, status, severity, tlp_header_valid, tlp),
 
@@ -318,10 +318,10 @@ TRACE_EVENT(aer_event,
                __entry->severity       = severity;
                __entry->tlp_header_valid = tlp_header_valid;
                if (tlp_header_valid) {
-                       __entry->tlp_header[0] = tlp->dw0;
-                       __entry->tlp_header[1] = tlp->dw1;
-                       __entry->tlp_header[2] = tlp->dw2;
-                       __entry->tlp_header[3] = tlp->dw3;
+                       __entry->tlp_header[0] = tlp->dw[0];
+                       __entry->tlp_header[1] = tlp->dw[1];
+                       __entry->tlp_header[2] = tlp->dw[2];
+                       __entry->tlp_header[3] = tlp->dw[3];
                }
        ),
 
index 5ddda7c2ed9b3387375fa54ecec6b539f921d951..4557bb8a5256516e95019a5dc683d1e0617749aa 100644 (file)
@@ -70,9 +70,6 @@ source "lib/math/Kconfig"
 config NO_GENERIC_PCI_IOPORT_MAP
        bool
 
-config GENERIC_PCI_IOMAP
-       bool
-
 config GENERIC_IOMAP
        bool
        select GENERIC_PCI_IOMAP
index 363852afa20049e5c21a65a9bb6baf52d84fe28a..ffc6b2341b45a52a8ba1820d5ff9718cfe05a4a1 100644 (file)
@@ -152,7 +152,6 @@ CFLAGS_debug_info.o += $(call cc-option, -femit-struct-debug-detailed=any)
 obj-y += math/ crypto/
 
 obj-$(CONFIG_GENERIC_IOMAP) += iomap.o
-obj-$(CONFIG_GENERIC_PCI_IOMAP) += pci_iomap.o
 obj-$(CONFIG_HAS_IOMEM) += iomap_copy.o devres.o
 obj-$(CONFIG_CHECK_SIGNATURE) += check_signature.o
 obj-$(CONFIG_DEBUG_LOCKING_API_SELFTESTS) += locking-selftest.o
index c44f104b58d58178555525919e9a4059987f49c1..fe0c63caeb6892132ea208529715b71176c9ea26 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <linux/device.h>
 #include <linux/err.h>
-#include <linux/pci.h>
 #include <linux/io.h>
 #include <linux/gfp.h>
 #include <linux/export.h>
@@ -311,212 +311,6 @@ void devm_ioport_unmap(struct device *dev, void __iomem *addr)
 EXPORT_SYMBOL(devm_ioport_unmap);
 #endif /* CONFIG_HAS_IOPORT_MAP */
 
-#ifdef CONFIG_PCI
-/*
- * PCI iomap devres
- */
-#define PCIM_IOMAP_MAX PCI_STD_NUM_BARS
-
-struct pcim_iomap_devres {
-       void __iomem *table[PCIM_IOMAP_MAX];
-};
-
-static void pcim_iomap_release(struct device *gendev, void *res)
-{
-       struct pci_dev *dev = to_pci_dev(gendev);
-       struct pcim_iomap_devres *this = res;
-       int i;
-
-       for (i = 0; i < PCIM_IOMAP_MAX; i++)
-               if (this->table[i])
-                       pci_iounmap(dev, this->table[i]);
-}
-
-/**
- * pcim_iomap_table - access iomap allocation table
- * @pdev: PCI device to access iomap table for
- *
- * Access iomap allocation table for @dev.  If iomap table doesn't
- * exist and @pdev is managed, it will be allocated.  All iomaps
- * recorded in the iomap table are automatically unmapped on driver
- * detach.
- *
- * This function might sleep when the table is first allocated but can
- * be safely called without context and guaranteed to succeed once
- * allocated.
- */
-void __iomem * const *pcim_iomap_table(struct pci_dev *pdev)
-{
-       struct pcim_iomap_devres *dr, *new_dr;
-
-       dr = devres_find(&pdev->dev, pcim_iomap_release, NULL, NULL);
-       if (dr)
-               return dr->table;
-
-       new_dr = devres_alloc_node(pcim_iomap_release, sizeof(*new_dr), GFP_KERNEL,
-                                  dev_to_node(&pdev->dev));
-       if (!new_dr)
-               return NULL;
-       dr = devres_get(&pdev->dev, new_dr, NULL, NULL);
-       return dr->table;
-}
-EXPORT_SYMBOL(pcim_iomap_table);
-
-/**
- * pcim_iomap - Managed pcim_iomap()
- * @pdev: PCI device to iomap for
- * @bar: BAR to iomap
- * @maxlen: Maximum length of iomap
- *
- * Managed pci_iomap().  Map is automatically unmapped on driver
- * detach.
- */
-void __iomem *pcim_iomap(struct pci_dev *pdev, int bar, unsigned long maxlen)
-{
-       void __iomem **tbl;
-
-       BUG_ON(bar >= PCIM_IOMAP_MAX);
-
-       tbl = (void __iomem **)pcim_iomap_table(pdev);
-       if (!tbl || tbl[bar])   /* duplicate mappings not allowed */
-               return NULL;
-
-       tbl[bar] = pci_iomap(pdev, bar, maxlen);
-       return tbl[bar];
-}
-EXPORT_SYMBOL(pcim_iomap);
-
-/**
- * pcim_iounmap - Managed pci_iounmap()
- * @pdev: PCI device to iounmap for
- * @addr: Address to unmap
- *
- * Managed pci_iounmap().  @addr must have been mapped using pcim_iomap().
- */
-void pcim_iounmap(struct pci_dev *pdev, void __iomem *addr)
-{
-       void __iomem **tbl;
-       int i;
-
-       pci_iounmap(pdev, addr);
-
-       tbl = (void __iomem **)pcim_iomap_table(pdev);
-       BUG_ON(!tbl);
-
-       for (i = 0; i < PCIM_IOMAP_MAX; i++)
-               if (tbl[i] == addr) {
-                       tbl[i] = NULL;
-                       return;
-               }
-       WARN_ON(1);
-}
-EXPORT_SYMBOL(pcim_iounmap);
-
-/**
- * pcim_iomap_regions - Request and iomap PCI BARs
- * @pdev: PCI device to map IO resources for
- * @mask: Mask of BARs to request and iomap
- * @name: Name used when requesting regions
- *
- * Request and iomap regions specified by @mask.
- */
-int pcim_iomap_regions(struct pci_dev *pdev, int mask, const char *name)
-{
-       void __iomem * const *iomap;
-       int i, rc;
-
-       iomap = pcim_iomap_table(pdev);
-       if (!iomap)
-               return -ENOMEM;
-
-       for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
-               unsigned long len;
-
-               if (!(mask & (1 << i)))
-                       continue;
-
-               rc = -EINVAL;
-               len = pci_resource_len(pdev, i);
-               if (!len)
-                       goto err_inval;
-
-               rc = pci_request_region(pdev, i, name);
-               if (rc)
-                       goto err_inval;
-
-               rc = -ENOMEM;
-               if (!pcim_iomap(pdev, i, 0))
-                       goto err_region;
-       }
-
-       return 0;
-
- err_region:
-       pci_release_region(pdev, i);
- err_inval:
-       while (--i >= 0) {
-               if (!(mask & (1 << i)))
-                       continue;
-               pcim_iounmap(pdev, iomap[i]);
-               pci_release_region(pdev, i);
-       }
-
-       return rc;
-}
-EXPORT_SYMBOL(pcim_iomap_regions);
-
-/**
- * pcim_iomap_regions_request_all - Request all BARs and iomap specified ones
- * @pdev: PCI device to map IO resources for
- * @mask: Mask of BARs to iomap
- * @name: Name used when requesting regions
- *
- * Request all PCI BARs and iomap regions specified by @mask.
- */
-int pcim_iomap_regions_request_all(struct pci_dev *pdev, int mask,
-                                  const char *name)
-{
-       int request_mask = ((1 << 6) - 1) & ~mask;
-       int rc;
-
-       rc = pci_request_selected_regions(pdev, request_mask, name);
-       if (rc)
-               return rc;
-
-       rc = pcim_iomap_regions(pdev, mask, name);
-       if (rc)
-               pci_release_selected_regions(pdev, request_mask);
-       return rc;
-}
-EXPORT_SYMBOL(pcim_iomap_regions_request_all);
-
-/**
- * pcim_iounmap_regions - Unmap and release PCI BARs
- * @pdev: PCI device to map IO resources for
- * @mask: Mask of BARs to unmap and release
- *
- * Unmap and release regions specified by @mask.
- */
-void pcim_iounmap_regions(struct pci_dev *pdev, int mask)
-{
-       void __iomem * const *iomap;
-       int i;
-
-       iomap = pcim_iomap_table(pdev);
-       if (!iomap)
-               return;
-
-       for (i = 0; i < PCIM_IOMAP_MAX; i++) {
-               if (!(mask & (1 << i)))
-                       continue;
-
-               pcim_iounmap(pdev, iomap[i]);
-               pci_release_region(pdev, i);
-       }
-}
-EXPORT_SYMBOL(pcim_iounmap_regions);
-#endif /* CONFIG_PCI */
-
 static void devm_arch_phys_ac_add_release(struct device *dev, void *res)
 {
        arch_phys_wc_del(*((int *)res));